From bd6ea4393c7d2f059fc4decc70f1ec3eb3597268 Mon Sep 17 00:00:00 2001 From: Ivan Grokhotkov Date: Wed, 17 Aug 2016 23:08:22 +0800 Subject: [PATCH] Initial public version --- .gitignore | 14 + .gitmodules | 3 + Kconfig | 63 + LICENSE | 202 + README.buildenv | 265 + README.md | 151 + bin/eclipse_windows_make.sh | 9 + bin/esptool.py | 1800 +++ bin/gen_esp32part.py | 308 + components/bootloader/Makefile.projbuild | 45 + components/bootloader/src/.gitignore | 2 + components/bootloader/src/Makefile | 12 + components/bootloader/src/main/Makefile | 13 + .../bootloader/src/main/bootloader_config.h | 138 + .../bootloader/src/main/bootloader_log.h | 89 + .../bootloader/src/main/bootloader_start.c | 597 + .../bootloader/src/main/eagle.bootloader.ld | 148 + .../bootloader/src/main/flash_encrypt.c | 190 + components/bootloader/src/main/secure_boot.c | 125 + components/bt/Kconfig | 23 + components/esp32/Kconfig | 39 + components/esp32/Makefile | 20 + components/esp32/abi.cpp | 114 + components/esp32/cpu_start.c | 259 + components/esp32/event.c | 306 + components/esp32/heap_alloc_caps.c | 246 + components/esp32/heap_alloc_caps.h | 34 + components/esp32/include/esp_attr.h | 35 + components/esp32/include/esp_err.h | 36 + components/esp32/include/esp_event.h | 107 + components/esp32/include/esp_ssc.h | 119 + components/esp32/include/esp_system.h | 364 + components/esp32/include/esp_types.h | 73 + components/esp32/include/esp_wifi.h | 231 + components/esp32/include/esp_wps.h | 131 + components/esp32/include/rom/aes.h | 48 + components/esp32/include/rom/bigint.h | 53 + components/esp32/include/rom/cache.h | 69 + components/esp32/include/rom/crc.h | 34 + components/esp32/include/rom/efuse.h | 29 + components/esp32/include/rom/ets_sys.h | 329 + components/esp32/include/rom/gpio.h | 142 + components/esp32/include/rom/libc_stubs.h | 89 + components/esp32/include/rom/lldesc.h | 176 + components/esp32/include/rom/md5_hash.h | 36 + components/esp32/include/rom/miniz.h | 777 ++ components/esp32/include/rom/queue.h | 645 + components/esp32/include/rom/rtc.h | 168 + components/esp32/include/rom/secure_boot.h | 41 + components/esp32/include/rom/sha.h | 50 + components/esp32/include/rom/spi_flash.h | 145 + components/esp32/include/rom/ssc.h | 85 + components/esp32/include/rom/tbconsole.h | 27 + components/esp32/include/rom/tjpgd.h | 99 + components/esp32/include/rom/uart.h | 187 + components/esp32/include/rom/wdt.h | 40 + components/esp32/include/soc/bb_reg.h | 102 + components/esp32/include/soc/boot_mode.h | 104 + components/esp32/include/soc/dport_reg.h | 1766 +++ components/esp32/include/soc/efuse_reg.h | 422 + components/esp32/include/soc/gpio_reg.h | 3124 +++++ components/esp32/include/soc/gpio_sd_reg.h | 80 + components/esp32/include/soc/gpio_sig_map.h | 422 + components/esp32/include/soc/i2s_reg.h | 579 + components/esp32/include/soc/io_mux_reg.h | 264 + components/esp32/include/soc/pid.h | 65 + components/esp32/include/soc/rtc_cntl_reg.h | 751 ++ components/esp32/include/soc/rtc_io_reg.h | 723 ++ components/esp32/include/soc/soc.h | 270 + components/esp32/include/soc/spi_register.h | 399 + components/esp32/include/soc/timers_reg.h | 288 + components/esp32/include/soc/uart_register.h | 1399 ++ components/esp32/include/soc/uhci0_reg.h | 350 + components/esp32/include/xtensa/board.h | 28 + components/esp32/include/xtensa/c6x-compat.h | 1758 +++ components/esp32/include/xtensa/cacheasm.h | 962 ++ .../esp32/include/xtensa/cacheattrasm.h | 436 + .../esp32/include/xtensa/config/core-isa.h | 655 + .../esp32/include/xtensa/config/core-matmap.h | 318 + components/esp32/include/xtensa/config/core.h | 1405 +++ components/esp32/include/xtensa/config/defs.h | 38 + .../esp32/include/xtensa/config/specreg.h | 117 + .../esp32/include/xtensa/config/system.h | 274 + .../esp32/include/xtensa/config/tie-asm.h | 323 + components/esp32/include/xtensa/config/tie.h | 182 + components/esp32/include/xtensa/core-macros.h | 456 + components/esp32/include/xtensa/coreasm.h | 939 ++ components/esp32/include/xtensa/corebits.h | 185 + components/esp32/include/xtensa/debugfs.h | 93 + components/esp32/include/xtensa/feedback.h | 45 + components/esp32/include/xtensa/gdbio.h | 80 + components/esp32/include/xtensa/hal.h | 1024 ++ components/esp32/include/xtensa/jtag-xtensa.h | 99 + .../xtensa/lcd-splc780d-4bitmode-board.h | 62 + .../include/xtensa/lcd-splc780d-4bitmode.h | 105 + .../esp32/include/xtensa/lcd-splc780d.h | 151 + components/esp32/include/xtensa/overlay.h | 184 + .../esp32/include/xtensa/overlay_os_asm.h | 140 + components/esp32/include/xtensa/sim.h | 60 + components/esp32/include/xtensa/simboard.h | 71 + .../esp32/include/xtensa/simcall-errno.h | 139 + .../esp32/include/xtensa/simcall-fcntl.h | 21 + components/esp32/include/xtensa/simcall.h | 189 + components/esp32/include/xtensa/specreg.h | 143 + .../esp32/include/xtensa/tie/xt_DFP_assist.h | 96 + components/esp32/include/xtensa/tie/xt_FP.h | 197 + .../esp32/include/xtensa/tie/xt_MAC16.h | 239 + .../esp32/include/xtensa/tie/xt_MUL32.h | 24 + .../esp32/include/xtensa/tie/xt_booleans.h | 69 + .../include/xtensa/tie/xt_coprocessors.h | 48 + components/esp32/include/xtensa/tie/xt_core.h | 395 + .../esp32/include/xtensa/tie/xt_debug.h | 116 + .../esp32/include/xtensa/tie/xt_density.h | 58 + .../esp32/include/xtensa/tie/xt_exceptions.h | 45 + .../include/xtensa/tie/xt_externalregisters.h | 46 + .../include/xtensa/tie/xt_integerdivide.h | 50 + .../esp32/include/xtensa/tie/xt_interrupt.h | 56 + .../esp32/include/xtensa/tie/xt_ioports.h | 66 + components/esp32/include/xtensa/tie/xt_misc.h | 58 + components/esp32/include/xtensa/tie/xt_mmu.h | 62 + components/esp32/include/xtensa/tie/xt_mul.h | 52 + .../esp32/include/xtensa/tie/xt_regwin.h | 64 + .../esp32/include/xtensa/tie/xt_scmpr.h | 22 + components/esp32/include/xtensa/tie/xt_sync.h | 60 + .../esp32/include/xtensa/tie/xt_timer.h | 66 + .../esp32/include/xtensa/tie/xt_trace.h | 44 + components/esp32/include/xtensa/trax-api.h | 93 + .../esp32/include/xtensa/trax-core-config.h | 144 + components/esp32/include/xtensa/trax-proto.h | 91 + components/esp32/include/xtensa/trax-util.h | 63 + components/esp32/include/xtensa/trax.h | 409 + components/esp32/include/xtensa/traxfile.h | 62 + components/esp32/include/xtensa/traxreg.h | 199 + .../esp32/include/xtensa/uart-16550-board.h | 69 + components/esp32/include/xtensa/uart-16550.h | 152 + components/esp32/include/xtensa/udma.h | 276 + components/esp32/include/xtensa/xdm-regs.h | 530 + components/esp32/include/xtensa/xmon.h | 97 + components/esp32/include/xtensa/xmp-library.h | 789 ++ components/esp32/include/xtensa/xos.h | 524 + components/esp32/include/xtensa/xos_common.h | 362 + components/esp32/include/xtensa/xos_cond.h | 145 + components/esp32/include/xtensa/xos_errors.h | 107 + components/esp32/include/xtensa/xos_event.h | 281 + .../esp32/include/xtensa/xos_internal.h | 120 + components/esp32/include/xtensa/xos_msgq.h | 278 + components/esp32/include/xtensa/xos_mutex.h | 205 + components/esp32/include/xtensa/xos_params.h | 276 + .../esp32/include/xtensa/xos_regaccess.h | 201 + .../esp32/include/xtensa/xos_semaphore.h | 190 + .../esp32/include/xtensa/xos_stopwatch.h | 175 + components/esp32/include/xtensa/xos_syslog.h | 330 + components/esp32/include/xtensa/xos_thread.h | 1086 ++ components/esp32/include/xtensa/xos_timer.h | 592 + components/esp32/include/xtensa/xos_types.h | 75 + .../esp32/include/xtensa/xt_perf_consts.h | 283 + components/esp32/include/xtensa/xt_perfmon.h | 183 + .../esp32/include/xtensa/xt_profiling.h | 233 + components/esp32/include/xtensa/xt_reftb.h | 86 + components/esp32/include/xtensa/xtav110.h | 313 + .../include/xtensa/xtav110/xtensa/board.h | 13 + components/esp32/include/xtensa/xtav200.h | 280 + .../include/xtensa/xtav200/xtensa/board.h | 13 + components/esp32/include/xtensa/xtav60.h | 241 + .../include/xtensa/xtav60/xtensa/board.h | 13 + .../xtensa/xtav60/xtensa/lcd-splc780d-board.h | 60 + components/esp32/include/xtensa/xtbsp.h | 269 + .../include/xtensa/xtensa-libdb-macros.h | 161 + .../esp32/include/xtensa/xtensa-versions.h | 347 + components/esp32/include/xtensa/xtensa-xer.h | 149 + components/esp32/include/xtensa/xtkc705.h | 14 + .../include/xtensa/xtkc705/xtensa/board.h | 13 + components/esp32/include/xtensa/xtload-api.h | 77 + components/esp32/include/xtensa/xtml605.h | 338 + .../include/xtensa/xtml605/xtensa/board.h | 13 + .../include/xtensa/xtruntime-core-state.h | 212 + .../esp32/include/xtensa/xtruntime-frames.h | 162 + components/esp32/include/xtensa/xtruntime.h | 221 + components/esp32/include/xtensa/xtutil.h | 61 + .../esp32/ld/eagle.fpga32.rom.addr.v7.ld | 1829 +++ components/esp32/ld/eagle.fpga32.v7.ld | 170 + components/esp32/ld/elf_to_ld.sh | 12 + components/esp32/lib | 1 + components/esp32/libhal.a | Bin 0 -> 462242 bytes components/esp32/spiram.h | 19 + components/esp32/syscalls.c | 256 + components/esp32/wifi.c | 109 + components/esptool_py/Kconfig.projbuild | 49 + components/esptool_py/LICENSE | 339 + components/esptool_py/Makefile.projbuild | 25 + components/freertos/Kconfig | 125 + components/freertos/Makefile | 13 + components/freertos/croutine.c | 390 + components/freertos/event_groups.c | 695 + components/freertos/gdbstub.c | 365 + components/freertos/gdbstub.h | 22 + components/freertos/heap_regions.c | 559 + .../freertos/include/freertos/FreeRTOS.h | 791 ++ .../include/freertos/FreeRTOSConfig.h | 244 + .../freertos/include/freertos/StackMacros.h | 184 + .../freertos/include/freertos/croutine.h | 762 ++ .../include/freertos/deprecated_definitions.h | 321 + .../freertos/include/freertos/event_groups.h | 730 ++ .../freertos/include/freertos/heap_regions.h | 34 + components/freertos/include/freertos/list.h | 453 + .../freertos/include/freertos/mpu_wrappers.h | 157 + .../freertos/include/freertos/portable.h | 203 + .../freertos/include/freertos/portbenchmark.h | 46 + .../freertos/include/freertos/portmacro.h | 290 + .../freertos/include/freertos/porttrace.h | 42 + .../freertos/include/freertos/projdefs.h | 109 + components/freertos/include/freertos/queue.h | 1693 +++ components/freertos/include/freertos/semphr.h | 844 ++ components/freertos/include/freertos/task.h | 2019 +++ components/freertos/include/freertos/timers.h | 1125 ++ .../freertos/include/freertos/xtensa_api.h | 118 + .../freertos/include/freertos/xtensa_config.h | 146 + .../include/freertos/xtensa_context.h | 383 + .../freertos/include/freertos/xtensa_rtos.h | 233 + .../freertos/include/freertos/xtensa_timer.h | 159 + components/freertos/license.txt | 440 + components/freertos/list.c | 233 + components/freertos/panic.c | 211 + components/freertos/port.c | 390 + components/freertos/portasm.S | 662 + components/freertos/queue.c | 2642 ++++ components/freertos/readme_smp.txt | 26 + components/freertos/readme_xtensa.txt | 769 ++ components/freertos/stdint.readme | 27 + components/freertos/tasks.c | 4535 +++++++ components/freertos/timers.c | 909 ++ components/freertos/xtensa_context.S | 645 + components/freertos/xtensa_init.c | 65 + components/freertos/xtensa_intr.c | 138 + components/freertos/xtensa_intr_asm.S | 179 + components/freertos/xtensa_overlay_os_hook.c | 67 + components/freertos/xtensa_vectors.S | 1980 +++ components/freertos/xtensa_vectors.S-new | 1915 +++ components/freertos/xtensa_vectors.S-old | 2064 +++ components/lwip/CHANGELOG | 4044 ++++++ components/lwip/COPYING | 33 + components/lwip/Kconfig | 14 + components/lwip/Makefile | 16 + components/lwip/README | 86 + components/lwip/VERSION | 1 + components/lwip/api/api_lib.c | 979 ++ components/lwip/api/api_msg.c | 1930 +++ components/lwip/api/err.c | 75 + components/lwip/api/netbuf.c | 250 + components/lwip/api/netdb.c | 415 + components/lwip/api/netifapi.c | 206 + components/lwip/api/pppapi.c | 371 + components/lwip/api/sockets.c | 3263 +++++ components/lwip/api/tcpip.c | 569 + components/lwip/apps/dhcpserver.c | 2485 ++++ components/lwip/core/def.c | 108 + components/lwip/core/dns.c | 1500 +++ components/lwip/core/inet_chksum.c | 612 + components/lwip/core/init.c | 378 + components/lwip/core/ip.c | 101 + components/lwip/core/ipv4/autoip.c | 549 + components/lwip/core/ipv4/dhcp.c | 1941 +++ components/lwip/core/ipv4/icmp.c | 391 + components/lwip/core/ipv4/igmp.c | 832 ++ components/lwip/core/ipv4/ip4.c | 1085 ++ components/lwip/core/ipv4/ip4_addr.c | 372 + components/lwip/core/ipv4/ip_frag.c | 902 ++ components/lwip/core/ipv6/README | 1 + components/lwip/core/ipv6/dhcp6.c | 50 + components/lwip/core/ipv6/ethip6.c | 159 + components/lwip/core/ipv6/icmp6.c | 353 + components/lwip/core/ipv6/inet6.c | 53 + components/lwip/core/ipv6/ip6.c | 1104 ++ components/lwip/core/ipv6/ip6_addr.c | 292 + components/lwip/core/ipv6/ip6_frag.c | 778 ++ components/lwip/core/ipv6/mld6.c | 593 + components/lwip/core/ipv6/nd6.c | 1846 +++ components/lwip/core/mem.c | 686 + components/lwip/core/memp.c | 436 + components/lwip/core/netif.c | 1090 ++ components/lwip/core/pbuf.c | 1396 ++ components/lwip/core/raw.c | 483 + components/lwip/core/stats.c | 188 + components/lwip/core/sys.c | 68 + components/lwip/core/tcp.c | 2155 ++++ components/lwip/core/tcp_in.c | 1802 +++ components/lwip/core/tcp_out.c | 1614 +++ components/lwip/core/timers.c | 614 + components/lwip/core/udp.c | 1198 ++ .../lwip/include/lwip/apps/dhcpserver.h | 494 + components/lwip/include/lwip/lwip/api.h | 368 + components/lwip/include/lwip/lwip/arch.h | 233 + components/lwip/include/lwip/lwip/autoip.h | 124 + components/lwip/include/lwip/lwip/debug.h | 117 + components/lwip/include/lwip/lwip/def.h | 132 + components/lwip/include/lwip/lwip/dhcp.h | 298 + components/lwip/include/lwip/lwip/dhcp6.h | 58 + components/lwip/include/lwip/lwip/dns.h | 118 + components/lwip/include/lwip/lwip/err.h | 95 + components/lwip/include/lwip/lwip/ethip6.h | 68 + components/lwip/include/lwip/lwip/icmp.h | 137 + components/lwip/include/lwip/lwip/icmp6.h | 152 + components/lwip/include/lwip/lwip/igmp.h | 108 + components/lwip/include/lwip/lwip/inet.h | 172 + .../lwip/include/lwip/lwip/inet_chksum.h | 106 + components/lwip/include/lwip/lwip/init.h | 72 + components/lwip/include/lwip/lwip/ip.h | 304 + components/lwip/include/lwip/lwip/ip4.h | 161 + components/lwip/include/lwip/lwip/ip4_addr.h | 253 + components/lwip/include/lwip/lwip/ip6.h | 197 + components/lwip/include/lwip/lwip/ip6_addr.h | 301 + components/lwip/include/lwip/lwip/ip6_frag.h | 120 + components/lwip/include/lwip/lwip/ip_addr.h | 291 + components/lwip/include/lwip/lwip/ip_frag.h | 95 + components/lwip/include/lwip/lwip/mem.h | 162 + components/lwip/include/lwip/lwip/memp.h | 133 + components/lwip/include/lwip/lwip/mld6.h | 119 + components/lwip/include/lwip/lwip/nd6.h | 361 + components/lwip/include/lwip/lwip/netbuf.h | 112 + components/lwip/include/lwip/lwip/netdb.h | 142 + components/lwip/include/lwip/lwip/netif.h | 447 + components/lwip/include/lwip/lwip/netifapi.h | 108 + components/lwip/include/lwip/lwip/opt.h | 3015 +++++ components/lwip/include/lwip/lwip/pbuf.h | 231 + components/lwip/include/lwip/lwip/pppapi.h | 148 + .../lwip/include/lwip/lwip/priv/api_msg.h | 260 + .../lwip/include/lwip/lwip/priv/memp_priv.h | 163 + .../lwip/include/lwip/lwip/priv/memp_std.h | 151 + .../lwip/include/lwip/lwip/priv/tcp_priv.h | 545 + .../lwip/include/lwip/lwip/priv/tcpip_priv.h | 163 + components/lwip/include/lwip/lwip/raw.h | 109 + components/lwip/include/lwip/lwip/sio.h | 141 + components/lwip/include/lwip/lwip/snmp.h | 195 + components/lwip/include/lwip/lwip/sockets.h | 624 + components/lwip/include/lwip/lwip/stats.h | 462 + components/lwip/include/lwip/lwip/sys.h | 362 + components/lwip/include/lwip/lwip/tcp.h | 411 + components/lwip/include/lwip/lwip/tcpip.h | 85 + components/lwip/include/lwip/lwip/timers.h | 101 + components/lwip/include/lwip/lwip/udp.h | 194 + components/lwip/include/lwip/netif/etharp.h | 143 + components/lwip/include/lwip/netif/ethernet.h | 171 + components/lwip/include/lwip/netif/lowpan6.h | 84 + .../lwip/include/lwip/netif/lowpan6_opts.h | 65 + components/lwip/include/lwip/netif/ppp/ccp.h | 156 + .../lwip/include/lwip/netif/ppp/chap-md5.h | 36 + .../lwip/include/lwip/netif/ppp/chap-new.h | 192 + .../lwip/include/lwip/netif/ppp/chap_ms.h | 44 + components/lwip/include/lwip/netif/ppp/eap.h | 169 + components/lwip/include/lwip/netif/ppp/ecp.h | 50 + .../lwip/include/lwip/netif/ppp/eui64.h | 94 + components/lwip/include/lwip/netif/ppp/fsm.h | 175 + components/lwip/include/lwip/netif/ppp/ipcp.h | 126 + .../lwip/include/lwip/netif/ppp/ipv6cp.h | 183 + components/lwip/include/lwip/netif/ppp/lcp.h | 169 + .../lwip/include/lwip/netif/ppp/magic.h | 122 + components/lwip/include/lwip/netif/ppp/mppe.h | 177 + .../include/lwip/netif/ppp/polarssl/arc4.h | 81 + .../include/lwip/netif/ppp/polarssl/des.h | 92 + .../include/lwip/netif/ppp/polarssl/md4.h | 97 + .../include/lwip/netif/ppp/polarssl/md5.h | 96 + .../include/lwip/netif/ppp/polarssl/sha1.h | 96 + components/lwip/include/lwip/netif/ppp/ppp.h | 573 + .../lwip/include/lwip/netif/ppp/ppp_impl.h | 632 + .../lwip/include/lwip/netif/ppp/pppcrypt.h | 43 + .../lwip/include/lwip/netif/ppp/pppdebug.h | 80 + .../lwip/include/lwip/netif/ppp/pppoe.h | 179 + .../lwip/include/lwip/netif/ppp/pppol2tp.h | 201 + .../lwip/include/lwip/netif/ppp/pppos.h | 119 + components/lwip/include/lwip/netif/ppp/upap.h | 123 + components/lwip/include/lwip/netif/ppp/vj.h | 161 + components/lwip/include/lwip/netif/slipif.h | 81 + components/lwip/include/lwip/port/arch/cc.h | 77 + components/lwip/include/lwip/port/arch/perf.h | 40 + .../lwip/include/lwip/port/arch/sys_arch.h | 73 + components/lwip/include/lwip/port/lwipopts.h | 526 + .../lwip/include/lwip/port/netif/wlanif.h | 23 + components/lwip/include/lwip/posix/netdb.h | 33 + .../lwip/include/lwip/posix/sys/socket.h | 33 + components/lwip/netif/FILES | 31 + components/lwip/netif/etharp.c | 1385 ++ components/lwip/netif/ethernet.c | 222 + components/lwip/netif/ethernetif.c | 339 + components/lwip/netif/lowpan6.c | 1196 ++ components/lwip/netif/ppp/PPPD_FOLLOWUP | 382 + components/lwip/netif/ppp/auth.c | 2497 ++++ components/lwip/netif/ppp/ccp.c | 1741 +++ components/lwip/netif/ppp/chap-md5.c | 127 + components/lwip/netif/ppp/chap-new.c | 677 + components/lwip/netif/ppp/chap_ms.c | 954 ++ components/lwip/netif/ppp/demand.c | 465 + components/lwip/netif/ppp/eap.c | 2429 ++++ components/lwip/netif/ppp/ecp.c | 191 + components/lwip/netif/ppp/eui64.c | 56 + components/lwip/netif/ppp/fsm.c | 799 ++ components/lwip/netif/ppp/ipcp.c | 2408 ++++ components/lwip/netif/ppp/ipv6cp.c | 1533 +++ components/lwip/netif/ppp/lcp.c | 2786 ++++ components/lwip/netif/ppp/magic.c | 294 + components/lwip/netif/ppp/mppe.c | 418 + components/lwip/netif/ppp/multilink.c | 609 + components/lwip/netif/ppp/polarssl/README | 33 + components/lwip/netif/ppp/polarssl/arc4.c | 101 + components/lwip/netif/ppp/polarssl/des.c | 422 + components/lwip/netif/ppp/polarssl/md4.c | 281 + components/lwip/netif/ppp/polarssl/md5.c | 300 + components/lwip/netif/ppp/polarssl/sha1.c | 335 + components/lwip/netif/ppp/ppp.c | 1600 +++ components/lwip/netif/ppp/pppcrypt.c | 66 + components/lwip/netif/ppp/pppoe.c | 1250 ++ components/lwip/netif/ppp/pppol2tp.c | 1151 ++ components/lwip/netif/ppp/pppos.c | 899 ++ components/lwip/netif/ppp/upap.c | 677 + components/lwip/netif/ppp/utils.c | 961 ++ components/lwip/netif/ppp/vj.c | 670 + components/lwip/netif/slipif.c | 555 + components/lwip/port/freertos/sys_arch.c | 494 + components/lwip/port/netif/wlanif.c | 284 + components/newlib/.gitignore | 2 + components/newlib/.gitmodules | 4 + components/newlib/COPYING.NEWLIB | 953 ++ components/newlib/Makefile | 8 + components/newlib/Makefile.old | 47 + components/newlib/include/_ansi.h | 140 + components/newlib/include/_syslist.h | 40 + components/newlib/include/alloca.h | 21 + components/newlib/include/ar.h | 69 + components/newlib/include/argz.h | 33 + components/newlib/include/assert.h | 50 + components/newlib/include/complex.h | 124 + components/newlib/include/config.h | 28 + components/newlib/include/ctype.h | 113 + components/newlib/include/dirent.h | 15 + components/newlib/include/envlock.h | 15 + components/newlib/include/envz.h | 16 + components/newlib/include/errno.h | 11 + components/newlib/include/fastmath.h | 13 + components/newlib/include/fcntl.h | 1 + components/newlib/include/fenv.h | 88 + components/newlib/include/fnmatch.h | 55 + components/newlib/include/getopt.h | 190 + components/newlib/include/glob.h | 90 + components/newlib/include/grp.h | 95 + components/newlib/include/iconv.h | 63 + components/newlib/include/ieeefp.h | 256 + components/newlib/include/inttypes.h | 319 + components/newlib/include/langinfo.h | 316 + components/newlib/include/libgen.h | 23 + components/newlib/include/limits.h | 146 + components/newlib/include/locale.h | 64 + .../newlib/include/machine/_default_types.h | 56 + components/newlib/include/machine/_types.h | 8 + components/newlib/include/machine/ansi.h | 1 + components/newlib/include/machine/endian.h | 20 + components/newlib/include/machine/fastmath.h | 100 + components/newlib/include/machine/ieeefp.h | 434 + components/newlib/include/machine/malloc.h | 8 + components/newlib/include/machine/param.h | 1 + components/newlib/include/machine/setjmp-dj.h | 43 + components/newlib/include/machine/setjmp.h | 453 + components/newlib/include/machine/stdlib.h | 8 + components/newlib/include/machine/termios.h | 1 + components/newlib/include/machine/time.h | 19 + components/newlib/include/machine/types.h | 30 + components/newlib/include/malloc.h | 169 + components/newlib/include/math.h | 615 + components/newlib/include/newlib.h | 201 + components/newlib/include/paths.h | 9 + components/newlib/include/pthread.h | 431 + components/newlib/include/pwd.h | 87 + components/newlib/include/reent.h | 189 + components/newlib/include/regdef.h | 7 + components/newlib/include/regex.h | 103 + components/newlib/include/sched.h | 97 + components/newlib/include/search.h | 64 + components/newlib/include/setjmp.h | 27 + components/newlib/include/signal.h | 32 + components/newlib/include/spawn.h | 119 + components/newlib/include/stdatomic.h | 413 + components/newlib/include/stdint.h | 511 + components/newlib/include/stdio.h | 727 ++ components/newlib/include/stdio_ext.h | 79 + components/newlib/include/stdlib.h | 297 + components/newlib/include/string.h | 167 + components/newlib/include/strings.h | 35 + .../newlib/include/sys/_default_fcntl.h | 213 + components/newlib/include/sys/_intsup.h | 20 + components/newlib/include/sys/_types.h | 91 + components/newlib/include/sys/cdefs.h | 710 ++ components/newlib/include/sys/config.h | 300 + components/newlib/include/sys/custom_file.h | 2 + components/newlib/include/sys/dir.h | 10 + components/newlib/include/sys/dirent.h | 13 + components/newlib/include/sys/errno.h | 192 + components/newlib/include/sys/fcntl.h | 4 + components/newlib/include/sys/features.h | 235 + components/newlib/include/sys/file.h | 33 + components/newlib/include/sys/iconvnls.h | 77 + components/newlib/include/sys/lock.h | 50 + components/newlib/include/sys/param.h | 28 + components/newlib/include/sys/queue.h | 691 + components/newlib/include/sys/reent.h | 793 ++ components/newlib/include/sys/resource.h | 17 + components/newlib/include/sys/sched.h | 67 + components/newlib/include/sys/signal.h | 357 + components/newlib/include/sys/stat.h | 192 + components/newlib/include/sys/stdio.h | 27 + components/newlib/include/sys/string.h | 2 + components/newlib/include/sys/syslimits.h | 65 + components/newlib/include/sys/time.h | 91 + components/newlib/include/sys/timeb.h | 39 + components/newlib/include/sys/times.h | 31 + components/newlib/include/sys/types.h | 521 + components/newlib/include/sys/unistd.h | 516 + components/newlib/include/sys/utime.h | 22 + components/newlib/include/sys/wait.h | 44 + components/newlib/include/tar.h | 39 + components/newlib/include/termios.h | 7 + components/newlib/include/tgmath.h | 184 + components/newlib/include/time.h | 291 + components/newlib/include/unctrl.h | 46 + components/newlib/include/unistd.h | 13 + components/newlib/include/utime.h | 12 + components/newlib/include/utmp.h | 8 + components/newlib/include/wchar.h | 254 + components/newlib/include/wctype.h | 47 + components/newlib/include/wordexp.h | 53 + .../newlib/include/xtensa/config/core-isa.h | 655 + components/newlib/lib/extracted/romsyms | 639 + components/newlib/lib/fixlibc.sh | 23 + components/newlib/lib/libc-minusrom.a | Bin 0 -> 3675626 bytes components/newlib/lib/libc.a | Bin 0 -> 3699654 bytes components/newlib/lib/libc_rom.a | Bin 0 -> 4870926 bytes components/newlib/lib/libg.a | Bin 0 -> 4921612 bytes components/newlib/lib/libm.a | Bin 0 -> 2227074 bytes components/newlib/libc_discard.list | 159 + components/nvs_flash/.gitignore | 1 + components/nvs_flash/Makefile | 14 + components/nvs_flash/README.rst | 219 + components/nvs_flash/include/nvs.h | 212 + components/nvs_flash/include/nvs_flash.h | 29 + .../nvs_flash/src/compressed_enum_table.hpp | 79 + components/nvs_flash/src/intrusive_list.h | 248 + components/nvs_flash/src/nvs.hpp | 25 + components/nvs_flash/src/nvs_api.cpp | 278 + components/nvs_flash/src/nvs_page.cpp | 689 + components/nvs_flash/src/nvs_page.hpp | 246 + components/nvs_flash/src/nvs_pagemanager.cpp | 137 + components/nvs_flash/src/nvs_pagemanager.hpp | 70 + components/nvs_flash/src/nvs_platform.hpp | 84 + components/nvs_flash/src/nvs_storage.cpp | 195 + components/nvs_flash/src/nvs_storage.hpp | 114 + components/nvs_flash/src/nvs_types.cpp | 42 + components/nvs_flash/src/nvs_types.hpp | 100 + components/nvs_flash/test/Makefile | 40 + components/nvs_flash/test/catch.hpp | 10509 ++++++++++++++++ components/nvs_flash/test/crc.cpp | 38 + components/nvs_flash/test/crc.h | 30 + components/nvs_flash/test/main.cpp | 2 + .../nvs_flash/test/spi_flash_emulation.cpp | 97 + .../nvs_flash/test/spi_flash_emulation.h | 198 + .../test/test_compressed_enum_table.cpp | 56 + .../nvs_flash/test/test_intrusive_list.cpp | 212 + components/nvs_flash/test/test_nvs.cpp | 715 ++ .../test/test_spi_flash_emulation.cpp | 154 + components/partition_table/Kconfig.projbuild | 50 + components/partition_table/Makefile.projbuild | 42 + .../partition_table/partitions_singleapp.csv | 4 + .../partition_table/partitions_two_ota.csv | 7 + .../tests/gen_esp32part_tests.py | 313 + components/spi_flash/Makefile | 3 + components/spi_flash/esp_spi_flash.c | 106 + components/spi_flash/include/esp_spi_flash.h | 69 + components/tcpip_adapter/Makefile | 12 + .../tcpip_adapter/include/tcpip_adapter.h | 100 + components/tcpip_adapter/tcpip_adapter_lwip.c | 450 + docs/COPYRIGHT.rst | 103 + docs/eclipse-setup.rst | 75 + docs/windows-setup.rst | 87 + make/common.mk | 56 + make/component.mk | 111 + make/project.mk | 185 + make/project_config.mk | 63 + tools/gen_esp32part.py | 343 + tools/kconfig/.gitignore | 22 + tools/kconfig/Kconfig | 1 + tools/kconfig/Makefile | 306 + tools/kconfig/POTFILES.in | 12 + tools/kconfig/check.sh | 13 + tools/kconfig/conf.c | 723 ++ tools/kconfig/confdata.c | 1247 ++ tools/kconfig/expr.c | 1206 ++ tools/kconfig/expr.h | 238 + tools/kconfig/gconf.c | 1521 +++ tools/kconfig/gconf.glade | 661 + tools/kconfig/images.c | 326 + tools/kconfig/kconfig-language.txt | 556 + tools/kconfig/kxgettext.c | 235 + tools/kconfig/list.h | 131 + tools/kconfig/lkc.h | 187 + tools/kconfig/lkc_proto.h | 52 + tools/kconfig/lxdialog/.gitignore | 4 + tools/kconfig/lxdialog/BIG.FAT.WARNING | 4 + tools/kconfig/lxdialog/check-lxdialog.sh | 95 + tools/kconfig/lxdialog/checklist.c | 332 + tools/kconfig/lxdialog/dialog.h | 257 + tools/kconfig/lxdialog/inputbox.c | 301 + tools/kconfig/lxdialog/menubox.c | 437 + tools/kconfig/lxdialog/textbox.c | 408 + tools/kconfig/lxdialog/util.c | 713 ++ tools/kconfig/lxdialog/yesno.c | 114 + tools/kconfig/mconf.c | 1047 ++ tools/kconfig/menu.c | 697 + tools/kconfig/merge_config.sh | 170 + tools/kconfig/nconf.c | 1561 +++ tools/kconfig/nconf.gui.c | 656 + tools/kconfig/nconf.h | 96 + tools/kconfig/qconf.cc | 1870 +++ tools/kconfig/qconf.h | 330 + tools/kconfig/streamline_config.pl | 647 + tools/kconfig/symbol.c | 1378 ++ tools/kconfig/util.c | 147 + tools/kconfig/zconf.gperf | 49 + tools/kconfig/zconf.l | 390 + tools/kconfig/zconf.y | 745 ++ tools/tests/gen_esp32part_tests.py | 313 + ...oolchain-linux64-win32-canadian-build.conf | 534 + .../windows/windows_install_prerequisites.sh | 60 + 628 files changed, 224814 insertions(+) create mode 100644 .gitignore create mode 100644 .gitmodules create mode 100644 Kconfig create mode 100644 LICENSE create mode 100644 README.buildenv create mode 100644 README.md create mode 100755 bin/eclipse_windows_make.sh create mode 100755 bin/esptool.py create mode 100755 bin/gen_esp32part.py create mode 100644 components/bootloader/Makefile.projbuild create mode 100644 components/bootloader/src/.gitignore create mode 100644 components/bootloader/src/Makefile create mode 100644 components/bootloader/src/main/Makefile create mode 100644 components/bootloader/src/main/bootloader_config.h create mode 100644 components/bootloader/src/main/bootloader_log.h create mode 100644 components/bootloader/src/main/bootloader_start.c create mode 100644 components/bootloader/src/main/eagle.bootloader.ld create mode 100644 components/bootloader/src/main/flash_encrypt.c create mode 100644 components/bootloader/src/main/secure_boot.c create mode 100644 components/bt/Kconfig create mode 100644 components/esp32/Kconfig create mode 100644 components/esp32/Makefile create mode 100644 components/esp32/abi.cpp create mode 100644 components/esp32/cpu_start.c create mode 100644 components/esp32/event.c create mode 100644 components/esp32/heap_alloc_caps.c create mode 100644 components/esp32/heap_alloc_caps.h create mode 100644 components/esp32/include/esp_attr.h create mode 100644 components/esp32/include/esp_err.h create mode 100755 components/esp32/include/esp_event.h create mode 100644 components/esp32/include/esp_ssc.h create mode 100644 components/esp32/include/esp_system.h create mode 100755 components/esp32/include/esp_types.h create mode 100755 components/esp32/include/esp_wifi.h create mode 100644 components/esp32/include/esp_wps.h create mode 100644 components/esp32/include/rom/aes.h create mode 100644 components/esp32/include/rom/bigint.h create mode 100644 components/esp32/include/rom/cache.h create mode 100644 components/esp32/include/rom/crc.h create mode 100644 components/esp32/include/rom/efuse.h create mode 100644 components/esp32/include/rom/ets_sys.h create mode 100644 components/esp32/include/rom/gpio.h create mode 100644 components/esp32/include/rom/libc_stubs.h create mode 100644 components/esp32/include/rom/lldesc.h create mode 100755 components/esp32/include/rom/md5_hash.h create mode 100644 components/esp32/include/rom/miniz.h create mode 100755 components/esp32/include/rom/queue.h create mode 100644 components/esp32/include/rom/rtc.h create mode 100644 components/esp32/include/rom/secure_boot.h create mode 100644 components/esp32/include/rom/sha.h create mode 100644 components/esp32/include/rom/spi_flash.h create mode 100755 components/esp32/include/rom/ssc.h create mode 100644 components/esp32/include/rom/tbconsole.h create mode 100644 components/esp32/include/rom/tjpgd.h create mode 100755 components/esp32/include/rom/uart.h create mode 100644 components/esp32/include/rom/wdt.h create mode 100755 components/esp32/include/soc/bb_reg.h create mode 100755 components/esp32/include/soc/boot_mode.h create mode 100644 components/esp32/include/soc/dport_reg.h create mode 100644 components/esp32/include/soc/efuse_reg.h create mode 100644 components/esp32/include/soc/gpio_reg.h create mode 100644 components/esp32/include/soc/gpio_sd_reg.h create mode 100644 components/esp32/include/soc/gpio_sig_map.h create mode 100644 components/esp32/include/soc/i2s_reg.h create mode 100644 components/esp32/include/soc/io_mux_reg.h create mode 100644 components/esp32/include/soc/pid.h create mode 100644 components/esp32/include/soc/rtc_cntl_reg.h create mode 100644 components/esp32/include/soc/rtc_io_reg.h create mode 100755 components/esp32/include/soc/soc.h create mode 100755 components/esp32/include/soc/spi_register.h create mode 100644 components/esp32/include/soc/timers_reg.h create mode 100644 components/esp32/include/soc/uart_register.h create mode 100644 components/esp32/include/soc/uhci0_reg.h create mode 100755 components/esp32/include/xtensa/board.h create mode 100755 components/esp32/include/xtensa/c6x-compat.h create mode 100755 components/esp32/include/xtensa/cacheasm.h create mode 100755 components/esp32/include/xtensa/cacheattrasm.h create mode 100644 components/esp32/include/xtensa/config/core-isa.h create mode 100644 components/esp32/include/xtensa/config/core-matmap.h create mode 100644 components/esp32/include/xtensa/config/core.h create mode 100644 components/esp32/include/xtensa/config/defs.h create mode 100644 components/esp32/include/xtensa/config/specreg.h create mode 100644 components/esp32/include/xtensa/config/system.h create mode 100644 components/esp32/include/xtensa/config/tie-asm.h create mode 100644 components/esp32/include/xtensa/config/tie.h create mode 100755 components/esp32/include/xtensa/core-macros.h create mode 100755 components/esp32/include/xtensa/coreasm.h create mode 100755 components/esp32/include/xtensa/corebits.h create mode 100755 components/esp32/include/xtensa/debugfs.h create mode 100755 components/esp32/include/xtensa/feedback.h create mode 100755 components/esp32/include/xtensa/gdbio.h create mode 100755 components/esp32/include/xtensa/hal.h create mode 100755 components/esp32/include/xtensa/jtag-xtensa.h create mode 100755 components/esp32/include/xtensa/lcd-splc780d-4bitmode-board.h create mode 100755 components/esp32/include/xtensa/lcd-splc780d-4bitmode.h create mode 100755 components/esp32/include/xtensa/lcd-splc780d.h create mode 100755 components/esp32/include/xtensa/overlay.h create mode 100755 components/esp32/include/xtensa/overlay_os_asm.h create mode 100755 components/esp32/include/xtensa/sim.h create mode 100755 components/esp32/include/xtensa/simboard.h create mode 100755 components/esp32/include/xtensa/simcall-errno.h create mode 100755 components/esp32/include/xtensa/simcall-fcntl.h create mode 100755 components/esp32/include/xtensa/simcall.h create mode 100755 components/esp32/include/xtensa/specreg.h create mode 100644 components/esp32/include/xtensa/tie/xt_DFP_assist.h create mode 100644 components/esp32/include/xtensa/tie/xt_FP.h create mode 100644 components/esp32/include/xtensa/tie/xt_MAC16.h create mode 100644 components/esp32/include/xtensa/tie/xt_MUL32.h create mode 100644 components/esp32/include/xtensa/tie/xt_booleans.h create mode 100644 components/esp32/include/xtensa/tie/xt_coprocessors.h create mode 100644 components/esp32/include/xtensa/tie/xt_core.h create mode 100644 components/esp32/include/xtensa/tie/xt_debug.h create mode 100644 components/esp32/include/xtensa/tie/xt_density.h create mode 100644 components/esp32/include/xtensa/tie/xt_exceptions.h create mode 100644 components/esp32/include/xtensa/tie/xt_externalregisters.h create mode 100644 components/esp32/include/xtensa/tie/xt_integerdivide.h create mode 100644 components/esp32/include/xtensa/tie/xt_interrupt.h create mode 100644 components/esp32/include/xtensa/tie/xt_ioports.h create mode 100644 components/esp32/include/xtensa/tie/xt_misc.h create mode 100644 components/esp32/include/xtensa/tie/xt_mmu.h create mode 100644 components/esp32/include/xtensa/tie/xt_mul.h create mode 100644 components/esp32/include/xtensa/tie/xt_regwin.h create mode 100644 components/esp32/include/xtensa/tie/xt_scmpr.h create mode 100644 components/esp32/include/xtensa/tie/xt_sync.h create mode 100644 components/esp32/include/xtensa/tie/xt_timer.h create mode 100644 components/esp32/include/xtensa/tie/xt_trace.h create mode 100755 components/esp32/include/xtensa/trax-api.h create mode 100755 components/esp32/include/xtensa/trax-core-config.h create mode 100755 components/esp32/include/xtensa/trax-proto.h create mode 100755 components/esp32/include/xtensa/trax-util.h create mode 100755 components/esp32/include/xtensa/trax.h create mode 100755 components/esp32/include/xtensa/traxfile.h create mode 100755 components/esp32/include/xtensa/traxreg.h create mode 100755 components/esp32/include/xtensa/uart-16550-board.h create mode 100755 components/esp32/include/xtensa/uart-16550.h create mode 100755 components/esp32/include/xtensa/udma.h create mode 100755 components/esp32/include/xtensa/xdm-regs.h create mode 100755 components/esp32/include/xtensa/xmon.h create mode 100755 components/esp32/include/xtensa/xmp-library.h create mode 100755 components/esp32/include/xtensa/xos.h create mode 100755 components/esp32/include/xtensa/xos_common.h create mode 100755 components/esp32/include/xtensa/xos_cond.h create mode 100755 components/esp32/include/xtensa/xos_errors.h create mode 100755 components/esp32/include/xtensa/xos_event.h create mode 100755 components/esp32/include/xtensa/xos_internal.h create mode 100755 components/esp32/include/xtensa/xos_msgq.h create mode 100755 components/esp32/include/xtensa/xos_mutex.h create mode 100755 components/esp32/include/xtensa/xos_params.h create mode 100755 components/esp32/include/xtensa/xos_regaccess.h create mode 100755 components/esp32/include/xtensa/xos_semaphore.h create mode 100755 components/esp32/include/xtensa/xos_stopwatch.h create mode 100755 components/esp32/include/xtensa/xos_syslog.h create mode 100755 components/esp32/include/xtensa/xos_thread.h create mode 100755 components/esp32/include/xtensa/xos_timer.h create mode 100755 components/esp32/include/xtensa/xos_types.h create mode 100755 components/esp32/include/xtensa/xt_perf_consts.h create mode 100755 components/esp32/include/xtensa/xt_perfmon.h create mode 100755 components/esp32/include/xtensa/xt_profiling.h create mode 100755 components/esp32/include/xtensa/xt_reftb.h create mode 100755 components/esp32/include/xtensa/xtav110.h create mode 100755 components/esp32/include/xtensa/xtav110/xtensa/board.h create mode 100755 components/esp32/include/xtensa/xtav200.h create mode 100755 components/esp32/include/xtensa/xtav200/xtensa/board.h create mode 100755 components/esp32/include/xtensa/xtav60.h create mode 100755 components/esp32/include/xtensa/xtav60/xtensa/board.h create mode 100755 components/esp32/include/xtensa/xtav60/xtensa/lcd-splc780d-board.h create mode 100755 components/esp32/include/xtensa/xtbsp.h create mode 100755 components/esp32/include/xtensa/xtensa-libdb-macros.h create mode 100755 components/esp32/include/xtensa/xtensa-versions.h create mode 100755 components/esp32/include/xtensa/xtensa-xer.h create mode 100755 components/esp32/include/xtensa/xtkc705.h create mode 100755 components/esp32/include/xtensa/xtkc705/xtensa/board.h create mode 100755 components/esp32/include/xtensa/xtload-api.h create mode 100755 components/esp32/include/xtensa/xtml605.h create mode 100755 components/esp32/include/xtensa/xtml605/xtensa/board.h create mode 100755 components/esp32/include/xtensa/xtruntime-core-state.h create mode 100755 components/esp32/include/xtensa/xtruntime-frames.h create mode 100755 components/esp32/include/xtensa/xtruntime.h create mode 100755 components/esp32/include/xtensa/xtutil.h create mode 100644 components/esp32/ld/eagle.fpga32.rom.addr.v7.ld create mode 100644 components/esp32/ld/eagle.fpga32.v7.ld create mode 100755 components/esp32/ld/elf_to_ld.sh create mode 160000 components/esp32/lib create mode 100644 components/esp32/libhal.a create mode 100644 components/esp32/spiram.h create mode 100644 components/esp32/syscalls.c create mode 100644 components/esp32/wifi.c create mode 100644 components/esptool_py/Kconfig.projbuild create mode 100644 components/esptool_py/LICENSE create mode 100644 components/esptool_py/Makefile.projbuild create mode 100644 components/freertos/Kconfig create mode 100644 components/freertos/Makefile create mode 100644 components/freertos/croutine.c create mode 100644 components/freertos/event_groups.c create mode 100644 components/freertos/gdbstub.c create mode 100644 components/freertos/gdbstub.h create mode 100644 components/freertos/heap_regions.c create mode 100644 components/freertos/include/freertos/FreeRTOS.h create mode 100644 components/freertos/include/freertos/FreeRTOSConfig.h create mode 100644 components/freertos/include/freertos/StackMacros.h create mode 100644 components/freertos/include/freertos/croutine.h create mode 100644 components/freertos/include/freertos/deprecated_definitions.h create mode 100644 components/freertos/include/freertos/event_groups.h create mode 100644 components/freertos/include/freertos/heap_regions.h create mode 100644 components/freertos/include/freertos/list.h create mode 100644 components/freertos/include/freertos/mpu_wrappers.h create mode 100644 components/freertos/include/freertos/portable.h create mode 100644 components/freertos/include/freertos/portbenchmark.h create mode 100644 components/freertos/include/freertos/portmacro.h create mode 100644 components/freertos/include/freertos/porttrace.h create mode 100644 components/freertos/include/freertos/projdefs.h create mode 100644 components/freertos/include/freertos/queue.h create mode 100644 components/freertos/include/freertos/semphr.h create mode 100644 components/freertos/include/freertos/task.h create mode 100644 components/freertos/include/freertos/timers.h create mode 100644 components/freertos/include/freertos/xtensa_api.h create mode 100644 components/freertos/include/freertos/xtensa_config.h create mode 100644 components/freertos/include/freertos/xtensa_context.h create mode 100644 components/freertos/include/freertos/xtensa_rtos.h create mode 100644 components/freertos/include/freertos/xtensa_timer.h create mode 100644 components/freertos/license.txt create mode 100644 components/freertos/list.c create mode 100644 components/freertos/panic.c create mode 100644 components/freertos/port.c create mode 100644 components/freertos/portasm.S create mode 100644 components/freertos/queue.c create mode 100644 components/freertos/readme_smp.txt create mode 100644 components/freertos/readme_xtensa.txt create mode 100644 components/freertos/stdint.readme create mode 100644 components/freertos/tasks.c create mode 100644 components/freertos/timers.c create mode 100644 components/freertos/xtensa_context.S create mode 100644 components/freertos/xtensa_init.c create mode 100644 components/freertos/xtensa_intr.c create mode 100644 components/freertos/xtensa_intr_asm.S create mode 100644 components/freertos/xtensa_overlay_os_hook.c create mode 100644 components/freertos/xtensa_vectors.S create mode 100644 components/freertos/xtensa_vectors.S-new create mode 100644 components/freertos/xtensa_vectors.S-old create mode 100755 components/lwip/CHANGELOG create mode 100755 components/lwip/COPYING create mode 100644 components/lwip/Kconfig create mode 100755 components/lwip/Makefile create mode 100755 components/lwip/README create mode 100644 components/lwip/VERSION create mode 100755 components/lwip/api/api_lib.c create mode 100755 components/lwip/api/api_msg.c create mode 100755 components/lwip/api/err.c create mode 100755 components/lwip/api/netbuf.c create mode 100755 components/lwip/api/netdb.c create mode 100755 components/lwip/api/netifapi.c create mode 100755 components/lwip/api/pppapi.c create mode 100755 components/lwip/api/sockets.c create mode 100755 components/lwip/api/tcpip.c create mode 100644 components/lwip/apps/dhcpserver.c create mode 100755 components/lwip/core/def.c create mode 100755 components/lwip/core/dns.c create mode 100755 components/lwip/core/inet_chksum.c create mode 100755 components/lwip/core/init.c create mode 100755 components/lwip/core/ip.c create mode 100755 components/lwip/core/ipv4/autoip.c create mode 100755 components/lwip/core/ipv4/dhcp.c create mode 100755 components/lwip/core/ipv4/icmp.c create mode 100755 components/lwip/core/ipv4/igmp.c create mode 100755 components/lwip/core/ipv4/ip4.c create mode 100755 components/lwip/core/ipv4/ip4_addr.c create mode 100755 components/lwip/core/ipv4/ip_frag.c create mode 100755 components/lwip/core/ipv6/README create mode 100755 components/lwip/core/ipv6/dhcp6.c create mode 100755 components/lwip/core/ipv6/ethip6.c create mode 100755 components/lwip/core/ipv6/icmp6.c create mode 100755 components/lwip/core/ipv6/inet6.c create mode 100755 components/lwip/core/ipv6/ip6.c create mode 100755 components/lwip/core/ipv6/ip6_addr.c create mode 100755 components/lwip/core/ipv6/ip6_frag.c create mode 100755 components/lwip/core/ipv6/mld6.c create mode 100755 components/lwip/core/ipv6/nd6.c create mode 100755 components/lwip/core/mem.c create mode 100755 components/lwip/core/memp.c create mode 100755 components/lwip/core/netif.c create mode 100755 components/lwip/core/pbuf.c create mode 100755 components/lwip/core/raw.c create mode 100755 components/lwip/core/stats.c create mode 100755 components/lwip/core/sys.c create mode 100755 components/lwip/core/tcp.c create mode 100755 components/lwip/core/tcp_in.c create mode 100755 components/lwip/core/tcp_out.c create mode 100755 components/lwip/core/timers.c create mode 100755 components/lwip/core/udp.c create mode 100644 components/lwip/include/lwip/apps/dhcpserver.h create mode 100755 components/lwip/include/lwip/lwip/api.h create mode 100755 components/lwip/include/lwip/lwip/arch.h create mode 100755 components/lwip/include/lwip/lwip/autoip.h create mode 100755 components/lwip/include/lwip/lwip/debug.h create mode 100755 components/lwip/include/lwip/lwip/def.h create mode 100755 components/lwip/include/lwip/lwip/dhcp.h create mode 100755 components/lwip/include/lwip/lwip/dhcp6.h create mode 100755 components/lwip/include/lwip/lwip/dns.h create mode 100755 components/lwip/include/lwip/lwip/err.h create mode 100755 components/lwip/include/lwip/lwip/ethip6.h create mode 100755 components/lwip/include/lwip/lwip/icmp.h create mode 100755 components/lwip/include/lwip/lwip/icmp6.h create mode 100755 components/lwip/include/lwip/lwip/igmp.h create mode 100755 components/lwip/include/lwip/lwip/inet.h create mode 100755 components/lwip/include/lwip/lwip/inet_chksum.h create mode 100755 components/lwip/include/lwip/lwip/init.h create mode 100755 components/lwip/include/lwip/lwip/ip.h create mode 100755 components/lwip/include/lwip/lwip/ip4.h create mode 100755 components/lwip/include/lwip/lwip/ip4_addr.h create mode 100755 components/lwip/include/lwip/lwip/ip6.h create mode 100755 components/lwip/include/lwip/lwip/ip6_addr.h create mode 100755 components/lwip/include/lwip/lwip/ip6_frag.h create mode 100755 components/lwip/include/lwip/lwip/ip_addr.h create mode 100755 components/lwip/include/lwip/lwip/ip_frag.h create mode 100755 components/lwip/include/lwip/lwip/mem.h create mode 100755 components/lwip/include/lwip/lwip/memp.h create mode 100755 components/lwip/include/lwip/lwip/mld6.h create mode 100755 components/lwip/include/lwip/lwip/nd6.h create mode 100755 components/lwip/include/lwip/lwip/netbuf.h create mode 100755 components/lwip/include/lwip/lwip/netdb.h create mode 100755 components/lwip/include/lwip/lwip/netif.h create mode 100755 components/lwip/include/lwip/lwip/netifapi.h create mode 100755 components/lwip/include/lwip/lwip/opt.h create mode 100755 components/lwip/include/lwip/lwip/pbuf.h create mode 100755 components/lwip/include/lwip/lwip/pppapi.h create mode 100755 components/lwip/include/lwip/lwip/priv/api_msg.h create mode 100755 components/lwip/include/lwip/lwip/priv/memp_priv.h create mode 100755 components/lwip/include/lwip/lwip/priv/memp_std.h create mode 100755 components/lwip/include/lwip/lwip/priv/tcp_priv.h create mode 100755 components/lwip/include/lwip/lwip/priv/tcpip_priv.h create mode 100755 components/lwip/include/lwip/lwip/raw.h create mode 100755 components/lwip/include/lwip/lwip/sio.h create mode 100755 components/lwip/include/lwip/lwip/snmp.h create mode 100755 components/lwip/include/lwip/lwip/sockets.h create mode 100755 components/lwip/include/lwip/lwip/stats.h create mode 100755 components/lwip/include/lwip/lwip/sys.h create mode 100755 components/lwip/include/lwip/lwip/tcp.h create mode 100755 components/lwip/include/lwip/lwip/tcpip.h create mode 100755 components/lwip/include/lwip/lwip/timers.h create mode 100755 components/lwip/include/lwip/lwip/udp.h create mode 100755 components/lwip/include/lwip/netif/etharp.h create mode 100755 components/lwip/include/lwip/netif/ethernet.h create mode 100755 components/lwip/include/lwip/netif/lowpan6.h create mode 100755 components/lwip/include/lwip/netif/lowpan6_opts.h create mode 100755 components/lwip/include/lwip/netif/ppp/ccp.h create mode 100755 components/lwip/include/lwip/netif/ppp/chap-md5.h create mode 100755 components/lwip/include/lwip/netif/ppp/chap-new.h create mode 100755 components/lwip/include/lwip/netif/ppp/chap_ms.h create mode 100755 components/lwip/include/lwip/netif/ppp/eap.h create mode 100755 components/lwip/include/lwip/netif/ppp/ecp.h create mode 100755 components/lwip/include/lwip/netif/ppp/eui64.h create mode 100755 components/lwip/include/lwip/netif/ppp/fsm.h create mode 100755 components/lwip/include/lwip/netif/ppp/ipcp.h create mode 100755 components/lwip/include/lwip/netif/ppp/ipv6cp.h create mode 100755 components/lwip/include/lwip/netif/ppp/lcp.h create mode 100755 components/lwip/include/lwip/netif/ppp/magic.h create mode 100755 components/lwip/include/lwip/netif/ppp/mppe.h create mode 100755 components/lwip/include/lwip/netif/ppp/polarssl/arc4.h create mode 100755 components/lwip/include/lwip/netif/ppp/polarssl/des.h create mode 100755 components/lwip/include/lwip/netif/ppp/polarssl/md4.h create mode 100755 components/lwip/include/lwip/netif/ppp/polarssl/md5.h create mode 100755 components/lwip/include/lwip/netif/ppp/polarssl/sha1.h create mode 100755 components/lwip/include/lwip/netif/ppp/ppp.h create mode 100755 components/lwip/include/lwip/netif/ppp/ppp_impl.h create mode 100755 components/lwip/include/lwip/netif/ppp/pppcrypt.h create mode 100755 components/lwip/include/lwip/netif/ppp/pppdebug.h create mode 100755 components/lwip/include/lwip/netif/ppp/pppoe.h create mode 100755 components/lwip/include/lwip/netif/ppp/pppol2tp.h create mode 100755 components/lwip/include/lwip/netif/ppp/pppos.h create mode 100755 components/lwip/include/lwip/netif/ppp/upap.h create mode 100755 components/lwip/include/lwip/netif/ppp/vj.h create mode 100755 components/lwip/include/lwip/netif/slipif.h create mode 100644 components/lwip/include/lwip/port/arch/cc.h create mode 100644 components/lwip/include/lwip/port/arch/perf.h create mode 100644 components/lwip/include/lwip/port/arch/sys_arch.h create mode 100755 components/lwip/include/lwip/port/lwipopts.h create mode 100755 components/lwip/include/lwip/port/netif/wlanif.h create mode 100755 components/lwip/include/lwip/posix/netdb.h create mode 100755 components/lwip/include/lwip/posix/sys/socket.h create mode 100755 components/lwip/netif/FILES create mode 100755 components/lwip/netif/etharp.c create mode 100755 components/lwip/netif/ethernet.c create mode 100755 components/lwip/netif/ethernetif.c create mode 100755 components/lwip/netif/lowpan6.c create mode 100755 components/lwip/netif/ppp/PPPD_FOLLOWUP create mode 100755 components/lwip/netif/ppp/auth.c create mode 100755 components/lwip/netif/ppp/ccp.c create mode 100755 components/lwip/netif/ppp/chap-md5.c create mode 100755 components/lwip/netif/ppp/chap-new.c create mode 100755 components/lwip/netif/ppp/chap_ms.c create mode 100755 components/lwip/netif/ppp/demand.c create mode 100755 components/lwip/netif/ppp/eap.c create mode 100755 components/lwip/netif/ppp/ecp.c create mode 100755 components/lwip/netif/ppp/eui64.c create mode 100755 components/lwip/netif/ppp/fsm.c create mode 100755 components/lwip/netif/ppp/ipcp.c create mode 100755 components/lwip/netif/ppp/ipv6cp.c create mode 100755 components/lwip/netif/ppp/lcp.c create mode 100755 components/lwip/netif/ppp/magic.c create mode 100755 components/lwip/netif/ppp/mppe.c create mode 100755 components/lwip/netif/ppp/multilink.c create mode 100755 components/lwip/netif/ppp/polarssl/README create mode 100755 components/lwip/netif/ppp/polarssl/arc4.c create mode 100755 components/lwip/netif/ppp/polarssl/des.c create mode 100755 components/lwip/netif/ppp/polarssl/md4.c create mode 100755 components/lwip/netif/ppp/polarssl/md5.c create mode 100755 components/lwip/netif/ppp/polarssl/sha1.c create mode 100755 components/lwip/netif/ppp/ppp.c create mode 100755 components/lwip/netif/ppp/pppcrypt.c create mode 100755 components/lwip/netif/ppp/pppoe.c create mode 100755 components/lwip/netif/ppp/pppol2tp.c create mode 100755 components/lwip/netif/ppp/pppos.c create mode 100755 components/lwip/netif/ppp/upap.c create mode 100755 components/lwip/netif/ppp/utils.c create mode 100755 components/lwip/netif/ppp/vj.c create mode 100755 components/lwip/netif/slipif.c create mode 100755 components/lwip/port/freertos/sys_arch.c create mode 100755 components/lwip/port/netif/wlanif.c create mode 100644 components/newlib/.gitignore create mode 100644 components/newlib/.gitmodules create mode 100644 components/newlib/COPYING.NEWLIB create mode 100644 components/newlib/Makefile create mode 100644 components/newlib/Makefile.old create mode 100644 components/newlib/include/_ansi.h create mode 100644 components/newlib/include/_syslist.h create mode 100644 components/newlib/include/alloca.h create mode 100644 components/newlib/include/ar.h create mode 100644 components/newlib/include/argz.h create mode 100644 components/newlib/include/assert.h create mode 100644 components/newlib/include/complex.h create mode 100644 components/newlib/include/config.h create mode 100644 components/newlib/include/ctype.h create mode 100644 components/newlib/include/dirent.h create mode 100644 components/newlib/include/envlock.h create mode 100644 components/newlib/include/envz.h create mode 100644 components/newlib/include/errno.h create mode 100644 components/newlib/include/fastmath.h create mode 100644 components/newlib/include/fcntl.h create mode 100644 components/newlib/include/fenv.h create mode 100644 components/newlib/include/fnmatch.h create mode 100644 components/newlib/include/getopt.h create mode 100644 components/newlib/include/glob.h create mode 100644 components/newlib/include/grp.h create mode 100644 components/newlib/include/iconv.h create mode 100644 components/newlib/include/ieeefp.h create mode 100644 components/newlib/include/inttypes.h create mode 100644 components/newlib/include/langinfo.h create mode 100644 components/newlib/include/libgen.h create mode 100644 components/newlib/include/limits.h create mode 100644 components/newlib/include/locale.h create mode 100644 components/newlib/include/machine/_default_types.h create mode 100644 components/newlib/include/machine/_types.h create mode 100644 components/newlib/include/machine/ansi.h create mode 100644 components/newlib/include/machine/endian.h create mode 100644 components/newlib/include/machine/fastmath.h create mode 100644 components/newlib/include/machine/ieeefp.h create mode 100644 components/newlib/include/machine/malloc.h create mode 100644 components/newlib/include/machine/param.h create mode 100644 components/newlib/include/machine/setjmp-dj.h create mode 100644 components/newlib/include/machine/setjmp.h create mode 100644 components/newlib/include/machine/stdlib.h create mode 100644 components/newlib/include/machine/termios.h create mode 100644 components/newlib/include/machine/time.h create mode 100644 components/newlib/include/machine/types.h create mode 100644 components/newlib/include/malloc.h create mode 100644 components/newlib/include/math.h create mode 100644 components/newlib/include/newlib.h create mode 100644 components/newlib/include/paths.h create mode 100644 components/newlib/include/pthread.h create mode 100644 components/newlib/include/pwd.h create mode 100644 components/newlib/include/reent.h create mode 100644 components/newlib/include/regdef.h create mode 100644 components/newlib/include/regex.h create mode 100644 components/newlib/include/sched.h create mode 100644 components/newlib/include/search.h create mode 100644 components/newlib/include/setjmp.h create mode 100644 components/newlib/include/signal.h create mode 100644 components/newlib/include/spawn.h create mode 100644 components/newlib/include/stdatomic.h create mode 100644 components/newlib/include/stdint.h create mode 100644 components/newlib/include/stdio.h create mode 100644 components/newlib/include/stdio_ext.h create mode 100644 components/newlib/include/stdlib.h create mode 100644 components/newlib/include/string.h create mode 100644 components/newlib/include/strings.h create mode 100644 components/newlib/include/sys/_default_fcntl.h create mode 100644 components/newlib/include/sys/_intsup.h create mode 100644 components/newlib/include/sys/_types.h create mode 100644 components/newlib/include/sys/cdefs.h create mode 100644 components/newlib/include/sys/config.h create mode 100644 components/newlib/include/sys/custom_file.h create mode 100644 components/newlib/include/sys/dir.h create mode 100644 components/newlib/include/sys/dirent.h create mode 100644 components/newlib/include/sys/errno.h create mode 100644 components/newlib/include/sys/fcntl.h create mode 100644 components/newlib/include/sys/features.h create mode 100644 components/newlib/include/sys/file.h create mode 100644 components/newlib/include/sys/iconvnls.h create mode 100644 components/newlib/include/sys/lock.h create mode 100644 components/newlib/include/sys/param.h create mode 100644 components/newlib/include/sys/queue.h create mode 100644 components/newlib/include/sys/reent.h create mode 100644 components/newlib/include/sys/resource.h create mode 100644 components/newlib/include/sys/sched.h create mode 100644 components/newlib/include/sys/signal.h create mode 100644 components/newlib/include/sys/stat.h create mode 100644 components/newlib/include/sys/stdio.h create mode 100644 components/newlib/include/sys/string.h create mode 100644 components/newlib/include/sys/syslimits.h create mode 100644 components/newlib/include/sys/time.h create mode 100644 components/newlib/include/sys/timeb.h create mode 100644 components/newlib/include/sys/times.h create mode 100644 components/newlib/include/sys/types.h create mode 100644 components/newlib/include/sys/unistd.h create mode 100644 components/newlib/include/sys/utime.h create mode 100644 components/newlib/include/sys/wait.h create mode 100644 components/newlib/include/tar.h create mode 100644 components/newlib/include/termios.h create mode 100644 components/newlib/include/tgmath.h create mode 100644 components/newlib/include/time.h create mode 100644 components/newlib/include/unctrl.h create mode 100644 components/newlib/include/unistd.h create mode 100644 components/newlib/include/utime.h create mode 100644 components/newlib/include/utmp.h create mode 100644 components/newlib/include/wchar.h create mode 100644 components/newlib/include/wctype.h create mode 100644 components/newlib/include/wordexp.h create mode 100644 components/newlib/include/xtensa/config/core-isa.h create mode 100644 components/newlib/lib/extracted/romsyms create mode 100755 components/newlib/lib/fixlibc.sh create mode 100644 components/newlib/lib/libc-minusrom.a create mode 100644 components/newlib/lib/libc.a create mode 100644 components/newlib/lib/libc_rom.a create mode 100644 components/newlib/lib/libg.a create mode 100644 components/newlib/lib/libm.a create mode 100644 components/newlib/libc_discard.list create mode 100644 components/nvs_flash/.gitignore create mode 100755 components/nvs_flash/Makefile create mode 100644 components/nvs_flash/README.rst create mode 100644 components/nvs_flash/include/nvs.h create mode 100644 components/nvs_flash/include/nvs_flash.h create mode 100644 components/nvs_flash/src/compressed_enum_table.hpp create mode 100644 components/nvs_flash/src/intrusive_list.h create mode 100644 components/nvs_flash/src/nvs.hpp create mode 100644 components/nvs_flash/src/nvs_api.cpp create mode 100644 components/nvs_flash/src/nvs_page.cpp create mode 100644 components/nvs_flash/src/nvs_page.hpp create mode 100644 components/nvs_flash/src/nvs_pagemanager.cpp create mode 100644 components/nvs_flash/src/nvs_pagemanager.hpp create mode 100644 components/nvs_flash/src/nvs_platform.hpp create mode 100644 components/nvs_flash/src/nvs_storage.cpp create mode 100644 components/nvs_flash/src/nvs_storage.hpp create mode 100644 components/nvs_flash/src/nvs_types.cpp create mode 100644 components/nvs_flash/src/nvs_types.hpp create mode 100644 components/nvs_flash/test/Makefile create mode 100644 components/nvs_flash/test/catch.hpp create mode 100644 components/nvs_flash/test/crc.cpp create mode 100644 components/nvs_flash/test/crc.h create mode 100644 components/nvs_flash/test/main.cpp create mode 100644 components/nvs_flash/test/spi_flash_emulation.cpp create mode 100644 components/nvs_flash/test/spi_flash_emulation.h create mode 100644 components/nvs_flash/test/test_compressed_enum_table.cpp create mode 100644 components/nvs_flash/test/test_intrusive_list.cpp create mode 100644 components/nvs_flash/test/test_nvs.cpp create mode 100644 components/nvs_flash/test/test_spi_flash_emulation.cpp create mode 100644 components/partition_table/Kconfig.projbuild create mode 100644 components/partition_table/Makefile.projbuild create mode 100644 components/partition_table/partitions_singleapp.csv create mode 100644 components/partition_table/partitions_two_ota.csv create mode 100755 components/partition_table/tests/gen_esp32part_tests.py create mode 100755 components/spi_flash/Makefile create mode 100644 components/spi_flash/esp_spi_flash.c create mode 100644 components/spi_flash/include/esp_spi_flash.h create mode 100755 components/tcpip_adapter/Makefile create mode 100644 components/tcpip_adapter/include/tcpip_adapter.h create mode 100644 components/tcpip_adapter/tcpip_adapter_lwip.c create mode 100644 docs/COPYRIGHT.rst create mode 100644 docs/eclipse-setup.rst create mode 100644 docs/windows-setup.rst create mode 100644 make/common.mk create mode 100644 make/component.mk create mode 100644 make/project.mk create mode 100644 make/project_config.mk create mode 100755 tools/gen_esp32part.py create mode 100644 tools/kconfig/.gitignore create mode 100644 tools/kconfig/Kconfig create mode 100644 tools/kconfig/Makefile create mode 100644 tools/kconfig/POTFILES.in create mode 100755 tools/kconfig/check.sh create mode 100644 tools/kconfig/conf.c create mode 100644 tools/kconfig/confdata.c create mode 100644 tools/kconfig/expr.c create mode 100644 tools/kconfig/expr.h create mode 100644 tools/kconfig/gconf.c create mode 100644 tools/kconfig/gconf.glade create mode 100644 tools/kconfig/images.c create mode 100644 tools/kconfig/kconfig-language.txt create mode 100644 tools/kconfig/kxgettext.c create mode 100644 tools/kconfig/list.h create mode 100644 tools/kconfig/lkc.h create mode 100644 tools/kconfig/lkc_proto.h create mode 100644 tools/kconfig/lxdialog/.gitignore create mode 100644 tools/kconfig/lxdialog/BIG.FAT.WARNING create mode 100755 tools/kconfig/lxdialog/check-lxdialog.sh create mode 100644 tools/kconfig/lxdialog/checklist.c create mode 100644 tools/kconfig/lxdialog/dialog.h create mode 100644 tools/kconfig/lxdialog/inputbox.c create mode 100644 tools/kconfig/lxdialog/menubox.c create mode 100644 tools/kconfig/lxdialog/textbox.c create mode 100644 tools/kconfig/lxdialog/util.c create mode 100644 tools/kconfig/lxdialog/yesno.c create mode 100644 tools/kconfig/mconf.c create mode 100644 tools/kconfig/menu.c create mode 100755 tools/kconfig/merge_config.sh create mode 100644 tools/kconfig/nconf.c create mode 100644 tools/kconfig/nconf.gui.c create mode 100644 tools/kconfig/nconf.h create mode 100644 tools/kconfig/qconf.cc create mode 100644 tools/kconfig/qconf.h create mode 100755 tools/kconfig/streamline_config.pl create mode 100644 tools/kconfig/symbol.c create mode 100644 tools/kconfig/util.c create mode 100644 tools/kconfig/zconf.gperf create mode 100644 tools/kconfig/zconf.l create mode 100644 tools/kconfig/zconf.y create mode 100755 tools/tests/gen_esp32part_tests.py create mode 100644 tools/windows/ctng-toolchain-linux64-win32-canadian-build.conf create mode 100755 tools/windows/windows_install_prerequisites.sh diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000000..48230f5690 --- /dev/null +++ b/.gitignore @@ -0,0 +1,14 @@ +.config +*.o +*.pyc + +# gtags +GTAGS +GRTAGS +GPATH + +# emacs temp file suffixes +*~ +.#* +\#*# + diff --git a/.gitmodules b/.gitmodules new file mode 100644 index 0000000000..174c4c70b2 --- /dev/null +++ b/.gitmodules @@ -0,0 +1,3 @@ +[submodule "components/esp32/lib"] + path = components/esp32/lib + url = ssh://git@github.com:espressif/esp32-wifi-lib.git diff --git a/Kconfig b/Kconfig new file mode 100644 index 0000000000..f3cfbef101 --- /dev/null +++ b/Kconfig @@ -0,0 +1,63 @@ +# +# For a description of the syntax of this configuration file, +# see kconfig/kconfig-language.txt. +# +mainmenu "Espressif ESP32 SDK Configuration" + + +menu "SDK tool configuration" +config TOOLPREFIX + string "Compiler toolchain path/prefix" + default "xtensa-esp32-elf-" + help + The prefix/path that is used to call the toolchain. The default setting assumes + a crosstool-ng gcc setup that is in your PATH. + +config PYTHON + string "Python 2 interpreter" + default "python" + help + The executable name/path that is used to run python. On some systems Python 2.x + may need to be invoked as python2. + +config MEMMAP_BT + bool "Reserve space for Bluetooth stack" + default "n" + help + The Bluetooth stack uses memory that cannot be used as generic memory anymore. This + reserves the space for that within the memory map of the compiled binary. + +config MEMMAP_SMP + bool "Reserve memory for two cores" + default "y" + help + The ESP32 contains two cores. If you plan to only use one, you can disable this item + to save some memory. (ToDo: Make this automatically depend on unicore support) + +config MEMMAP_TRACEMEM + bool "Use TRAX tracing feature" + default "n" + help + The ESP32 contains a feature which allows you to trace the execution path the processor + has taken through the program. This is stored in a chunk of 32K (16K for single-processor) + of memory that can't be used for general purposes anymore. Disable this if you do not know + what this is. + +config MEMMAP_SPISRAM + bool "Use external SPI SRAM chip as main memory" + default "n" + help + The ESP32 can control an external SPI SRAM chip, adding the memory it contains to the + main memory map. Enable this if you have this hardware and want to use it in the same + way as on-chip RAM. + +endmenu + +source "$COMPONENT_KCONFIGS_PROJBUILD" + +menu "Component config" +source "$COMPONENT_KCONFIGS" +endmenu + + + diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000000..d645695673 --- /dev/null +++ b/LICENSE @@ -0,0 +1,202 @@ + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/README.buildenv b/README.buildenv new file mode 100644 index 0000000000..249268c480 --- /dev/null +++ b/README.buildenv @@ -0,0 +1,265 @@ +The build structure of the Espressif IoT Development Framework explained. + +An ESP-IDF project can be seen as an almagation of a number of components. +For example, for a webserver that shows the current humidity, we would +have: +- The ESP32 base libraries (libc, rom bindings etc) +- The WiFi drivers +- A TCP/IP stack +- The FreeRTOS operating system +- A webserver +- A driver for an humidity sensor +- Main code tying it all together + +ESP-IDF makes these components explicit and configurable. To do that, when a project +is compiled, the build environment will look up all the components in the +SDK directories, the project directories and optionally custom other component +directories. It then allows the user to configure compile-time options using +a friendly text-based menu system to customize the SDK as well as other components +to the requirements of the project. After the components are customized, the +build process will compile everything into an output file, which can then be uploaded +into a board in a way that can also be defined by components. + +A project in this sense is defined as a directory under which all the files required +to build it live, excluding the SDK files and the toolchain. A simple project +tree looks like this: + +- myProject/ - build/ + - components/ - component1/ - Makefile + - Kconfig + - src1.c + - component2/ - Makefile + - Kconfig + - src1.c + - main/ - src1.c + - src2.c + - Makefile + + +As we can see, a project consists of a components/ subdirectory containing its +components as well as one or more directories containing the project-specific +sources; by default a single directory called 'main' is assumed. The project +directory will also have a Makefile where the projects name as well as optionally +other options are defined. After compilation, the project directory will contain +a 'build'-directory containing all of the objects, libraries and other generated +files as well as the final binary. + +Components also have a Makefile containing various definititions influencing +the build process of the component as well as the project it's used in, as +well as a Kconfig file defining the compile-time options that are settable +by means of the menu system. + + +Project makefile variables that can be set by the programmer: +PROJECT_NAME: Mandatory. Name for the project +BUILD_DIR_BASE: Set the directory where all objects/libraries/binaries end up in. + Defaults to $(PROJECT_PATH)/build +COMPONENT_DIRS: Search path for components. Defaults to the component/ directories + in the SDK path and the project path. +COMPONENTS: A list of component names. Defaults to all the component found in the + COMPONENT_DIRS directory +EXTRA_COMPONENT_DIRS: Defaults to unset. Use this to add directories to the default + COMPONENT_DIRS. +SRCDIRS: Directories under the project dir containing project-specific sources. + Defaults to 'main'. These are treated as 'lite' components: they do not have + include directories that are passed to the compilation pass of all components and + they do not have a Kconfig option. + + +Component makefile variables that can be set by the programmer: +COMPONENT_ADD_INCLUDEDIRS: Relative path to include directories to be added to + the entire project +COMPONENT_PRIV_INCLUDEDIRS: Relative path to include directories that are only used + when compiling this specific component +COMPONENT_DEPENDS: Names of any components that need to be compiled before this component. +COMPONENT_ADD_LDFLAGS: Ld flags to add for this project. Defaults to -l$(COMPONENT_NAME). + Add libraries etc in the current directory as $(abspath libwhatever.a) +COMPONENT_EXTRA_INCLUDES: Any extra include paths. These will be prefixed with '-I' and + passed to the compiler; please put absolute paths here. +COMPONENT_SRCDIRS: Relative directories to look in for sources. Defaults to '.', the current + directory (the root of the component) only. Use this to specify any subdirectories. Note + that specifying this overwrites the default action of compiling everything in the + components root dir; to keep this behaviour please also add '.' as a directory in this + list. +COMPONENT_OBJS: Object files to compile. Defaults to the .o variants of all .c and .S files + that are found in COMPONENT_SRCDIRS. +COMPONENT_EXTRA_CLEAN: Files that are generated using rules in the components Makefile + that also need to be cleaned +COMPONENT_BUILDRECIPE: Recipe to build the component. Optional. Defaults to building all + COMPONENT_OBJS and linking them into lib(componentname).a +COMPONENT_CLEANRECIPE: Recipe to clean the component. Optional. Defaults to removing + all built objects and libraries. +COMPONENT_BUILD_DIR: Equals the cwd of the component build, which is the build dir + of the component (where all the .o etc files should be created). + + +These variables are already set early on in the Makefile and the values in it will +be usable in component or project Makefiles: +CC, LD, AR, OBJCOPY: Xtensa gcc tools +HOSTCC, HOSTLD etc: Host gcc tools +LDFLAGS, CFLAGS: Set to usable values as defined in SDK Makefile +PROJECT_NAME: Name of the project, as set in project makefile +PROJECT_PATH: Path to the root of the project folder +COMPONENTS: Name of the components to be included +CONFIG_*: Values set by 'make menuconfig' also have corresponding Makefile variables. + +For components, there also are these defines: +COMPONENT_PATH: Absolute path to the root of the source tree of the component we're + compiling +COMPONENT_LIBRARY: The full path to the static library the components compilation pass + is supposed to generate + + +How this works: +The Make process is always invoked from the project directory by the +user; invoking it anywhere else gives an error. This is what happens if +we build a binary: + +The Makefile first determines how it was included. It determines it was +included as a project file in this case and will continue to figure out +various paths as well as the components available to it. It will also +collect the ldflags and includes that the components specify they need. +It does this by running a dummy Make on the components with a target that +will output these values. + +The Makefile will then create targets to build the lib*.a libraries of +all components and make the elf target depend on this. The targets +invoke Make on the makefiles of the components in a subshell: this way +the components have full freedom to do whatever is necessary to build +the library without influencing other components. By default, the +component includes the utility makefile $(SDK_PATH)/make/component.mk. +This provides default targets and configurations that will work +out-of-the-box for most projects. + +For components that have parts that need to be run when building of the +project is done, you can create a file called Makefile.projbuild in the +component root directory. This file will be included in the main +Makefile. For the menu, there's an equivalent: if you want to include +options not in the 'components' submenu, create a Kconfig.projbuild and +it will be included in the main menu of menuconfig. Take good care when +(re)defining stuff here: because it's included with all the other +.projbuild files, it's possible to overwrite variables or re-declare +targets defined in the SDK makefile/Kconfig and other .projbuild files + + +WRITING COMPONENT MAKEFILES + +A component consists of a directory which doubles as the name for the +component: a component named 'httpd' lives in a directory called 'httpd' +Because components usually live under the project directory (although +they can also reside in an other folder), the path to this may be +something like /home/myuser/projects/myprojects/components/httpd . + +One of the things that most components will have is a Makefile, +containing instructions on how to build the component. Because the +build environment tries to set reasonable defaults that will work most +of the time, a component Makefile can be pretty small. At the absolute +minimum, it will just include the SDK component makefile, which adds +component functionality: + +----8<---- +include $(SDK_PATH)/make/component.mk +---->8---- + +This will take all the .c and .S files in the component root and compile +them into object files, finally linking them into a library. +Subdirectories are ignored; if your project has sources in subdirectories +instead of in the root of the component, you can tell that to the build +system by setting COMPONENT_SRCDIRS: + +----8<---- +COMPONENT_SRCDIRS := src1 src2 +include $(SDK_PATH)/make/component.mk +---->8---- + +This will compile all source files in the src1/ and src2/ subdirectories +instead. + +The standard component.mk logic adds all .S and .c files in the source +directories as sources to be compiled unconditionally. It is possible +to circumvent that logic and hardcode the objects to be compiled by +manually setting the COMPONENT_OBJS variable to the name of the +objects that need to be generated: + +----8<---- +COMPONENT_OBJS := file1.o file2.o thing/filea.o thing/fileb.o anotherthing/main.o +include $(SDK_PATH)/make/component.mk +---->8---- + +This can also be used in order to conditionally compile some files +dependent on the options selected in the Makefile: + +Kconfig: +----8<---- +config FOO_ENABLE_BAR + bool "Enable the BAR feature." + help + This enables the BAR feature of the FOO component. +---->8---- + +Makefile: +----8<---- +COMPONENT_OBJS := foo_a.o foo_b.o $(if $(CONFIG_FOO_ENABLE_BAR),foo_bar.o foo_bar_interface.o) +include $(SDK_PATH)/make/component.mk +---->8---- + +Some components will have a situation where a source file isn't supplied +with the component itself but has to be generated from another file. Say +our component has a header file that consists of the converted binary +data of a BMP file, converted using a hypothetical tool called bmp2h. The +header file is then included in as C source file called graphics_lib.c. + +----8<---- +COMPONENT_EXTRA_CLEAN := logo.h + +graphics_lib.o: logo.h + +logo.h: $(COMPONENT_PATH)/logo.bmp + bmp2h -i $^ -o $@ + +include $(SDK_PATH)/make/component.mk +---->8---- + +In this example, graphics_lib.o and logo.h will be generated in the +current directory (the build directory) while logo.bmp comes with the +component and resides under the component path. Because logo.h is a +generated file, it needs to be cleaned when make clean is called which +why it is added to the COMPONENT_EXTRA_CLEAN variable. + + +This will work just fine, but there's one last cosmetic improvement that +can be done. The SDK make system tries to make the make process somewhat +easier on the eyes by hiding the commands (unless you run make with the +V=1 switch) and this does not do that yet. Here's an improved version +that will output in the same style as the rest of the make process: + +----8<---- +COMPONENT_EXTRA_CLEAN := test_tjpgd_logo.h + +graphics_lib.o: logo.h + +logo.h: $(COMPONENT_PATH)/logo.bmp + $(vecho) BMP2H $@ + $(Q) bmp2h -i $^ -o $@ + +include $(SDK_PATH)/make/component.mk +---->8---- + +Obviously, there are cases where all these recipes are insufficient for a +certain component, for example when the component is basically a wrapper +around another third-party component not originally intended to be +compiled under this build system. In that case, it's possible to forego +the build system entirely by setting COMPONENT_OWNBUILDTARGET and +possibly COMPONENT_OWNCLEANTARGET and defining your own build- and clean +target. The build target can do anything as long as it creates +$(COMPONENT_LIBRARY) for the main file to link into the project binary, +and even that is not necessary: if the COMPONENT_ADD_LDFLAGS variable +is set, the component can instruct the linker to do anything else as well. + + + + + + + + diff --git a/README.md b/README.md new file mode 100644 index 0000000000..42b5ee7e83 --- /dev/null +++ b/README.md @@ -0,0 +1,151 @@ +# Using Espressif IoT Development Framework with the ESP32 + +# Prerequisites + +# Configuring your project + +`make menuconfig` + +# Compiling your project + +`make app` + +# Flashing the Bootloader + +ESP32 has a bootloader in ROM which runs after reset, but ESP-IDF also uses a second stage software bootloader. The ROM bootloader loads the software bootloader, which then loads the firmware app of the ESP32. The software bootloader must be flashed to offset 0x5000 in the flash. + +To build the software bootloader, navigate to your project's top-level directory and run: + +``` shell +make bootloader +``` + +If you've configured the serial port details in `make menuconfig`, then + +``` shell +make bootloader-flash +``` + +... will automatically run esptool.py to flash the image. Otherwise, you can customise the `esptool.py` command that is printed out as part of `make bootloader`. + +You only need to flash the ESP32 bootloader once. + +# The Partition Table + +Once you've compiled your project, the "build" directory will contain a binary file with a name like "my_app.bin". This is an ESP32 image binary that can be loaded by the bootloader. + +A single ESP32's flash can contain multiple apps, as well as many different kinds of data (calibration data, filesystems, parameter storage, etc). For this reason a partition table is flashed to offset 0x4000 in the flash. + +Each entry in the partition table has a name (label), type (app, data, or something else), subtype and the offset in flash where the partition is loaded. + +The simplest way to use the partition table is to `make menuconfig` and choose one of the simple predefined partition tables: + +* "Single factory app, no OTA" +* "Factory app, two OTA definitions" + +In both cases the factory app is flashed at offset 0x10000. If you `make partition_table` then it will print a summary of the partition table. + +Here is the summary printed for the "Single factory app, no OTA" configuration: + +``` +# Espressif ESP32 Partition Table +# Name, Type, SubType, Offset, Size +factory, app, factory, 0x10000, 1M +rfdata, data, rf, 0x110000, 256K +wifidata,data, wifi, 0x150000, 256K +``` + +* At a 0x10000 (64KB) offset in the flash is the app labelled "factory". The bootloader will run this app by default. +* There are also two data regions defined in the partition table for storing RF & Wifi calibration data. + +Here is the summary printed for the "Factory app, two OTA definitions" configuration: + +``` +# Espressif ESP32 Partition Table +# Name, Type, SubType, Offset, Size +factory, app, factory, 0x10000, 1M +ota_0, app, ota_0, 0x110000, 1M +ota_1, app, ota_1, 0x210000, 1M +rfdata, data, rf, 0x310000, 256K +wifidata,data, wifi, 0x350000, 256K +otadata, data, ota, 0x390000, 256K +``` + +* There are now three app partition definitions. +* The type of all three are set as "app", but the subtype varies between the factory app at 0x10000 and the next two "OTA" apps. +* There is also a new "ota data" slot, which holds the data for OTA updates. The bootloader consults this data in order to know which app to execute. If "ota data" is empty, it will execute the factory app. + + +## Creating Custom Tables + +If you choose "Custom partition table CSV" in menuconfig then you can also enter the name of a CSV file (in the project directory) to use for your partition table. The CSV file can describe any number of definitions for the table you need. + +The CSV format is the same format as printed in the summaries shown above. However, not all fields are required in the CSV. For example, here is the "input" CSV for the OTA partition table: + +``` +# Name, Type, SubType, Offset, Size +factory, app, factory, 0x10000, 1M +ota_0, app, ota_0, , 1M +ota_1, app, ota_1, , 1M +rfdata, data, rf, , 256K +wifidata, data, wifi, , 256K +otadata, data, ota, , 256K +``` + +* Whitespace between fields is ignored, and so is any line starting with # (comments). +* Each non-comment line in the CSV file is a partition definition. +* Only the offset for the first partition is supplied. The gen_esp32part.py tool fills in each remaining offset to start after the preceding partition. + +### Name field + +Name field can be any meaningful name. It is not significant to the ESP32. Names longer than 16 characters will be truncated. + +### Type field + +Type field can be specified as app (0) or data (1). Or it can be a number 0-254 (or as hex 0x00-0xFE). Types 0x00-0x3F are reserved for Espressif. If your application needs to store data, please add a custom partition type in the range 0x40-0xFE. + +The bootloader ignores any types other than 0 & 1. + +### Subtype + +When type is "app", the subtype field can be specified as factory (0), ota_0 (0x10) ... ota_15 (0x1F) and test (0x20). Or it can be any number 0-255 (0x00-0xFF). The bootloader will execute the factory app unless there it sees a partition of type data/ota, in which case it reads this partition to determine which OTA image to boot + +When type is "data", the subtype field can be specified as ota (0), rf (1), wifi (2). Or it can be a number 0x00-0xFF. The bootloader ignores all data subtypes except for ota. Other "data" subtypes are reserved for Espressif use. To create custom data partition subtypes then use a custom type value, and choose any subtype 0x00-0xFF. + +### Offset & Size + +Only the first offset field is required (we recommend using 0x10000). Partitions with blank offsets will start after the previous partition. + +App partitions have to be at offsets aligned to 0x10000 (64K). If you leave the offset field blank, the tool will automatically align the partition. If you specify an unaligned offset for an app partition, the tool will return an error. + +Sizes and offsets can be specified as decimal numbers, hex numbers with the prefix 0x, or size multipliers M or K (1024 and 1024*1024 bytes). + +## Generating Binary Partition Table + +The partition table which is flashed to the ESP32 is in a binary format, not CSV. The tool components/partition_table/gen_esp32part.py is used to convert between CSV and binary formats. + +If you configure the partition table CSV name in `make menuconfig` and then `make partition_table`, this conversion is done for you. + +To convert CSV to Binary manually: + +``` shell +python components/partition_table/gen_esp32part.py --verify input_partitions.csv binary_partitions.bin +``` + +To convert binary format back to CSV: + +``` shell +python components/partition_table/gen_esp32part.py --verify binary_partitions.bin input_partitions.csv +``` + +To display the contents of a binary partition table on stdout (this is how the summaries displayed when running `make partition_table` are generated: + +``` shell +python components/partition_table/gen_esp32part.py binary_partitions.bin +``` + +`gen_esp32part.py` takes one optional argument, `--verify`, which will also verify the partition table during conversion (checking for overlapping partitions, unaligned partitions, etc.) + +# Flashing the partition table + +The command `make partition_table-flash` will flash the partition table with esptool.py. However a manual flashing command is printed as part of `make partition_table`. diff --git a/bin/eclipse_windows_make.sh b/bin/eclipse_windows_make.sh new file mode 100755 index 0000000000..115ecac2fa --- /dev/null +++ b/bin/eclipse_windows_make.sh @@ -0,0 +1,9 @@ +#!/bin/bash +# A wrapper for make on Windows with Eclipse +# +# Eclipse's output parser expects to see output of the form C:/dir/dir/file but our Make +# process uses MinGW paths of the form /c/dir/dir/file. So parse these out... +# +# (regexp deliberate only matches after a space character to try and avoid false-positives.) +echo "Running make in $(dirname $0)" +make $@ V=1 | sed -E "s@ /([a-z])/(.+)/@ \1:/\2/@g" | sed -E "s@-I/([a-z])/(.+)/@-I\1:/\2/@g" | sed -E "s@-L/([a-z])/(.+)/@-L\1:/\2/@g" diff --git a/bin/esptool.py b/bin/esptool.py new file mode 100755 index 0000000000..345fb2fd98 --- /dev/null +++ b/bin/esptool.py @@ -0,0 +1,1800 @@ +#!/usr/bin/env python +# NB: Before sending a PR to change the above line to '#!/usr/bin/env python2', please read https://github.com/themadinventor/esptool/issues/21 +# +# ESP8266 ROM Bootloader Utility +# https://github.com/themadinventor/esptool +# +# Copyright (C) 2014-2016 Fredrik Ahlberg, Angus Gratton, other contributors as noted. +# ESP31/32 support Copyright (C) 2016 Angus Gratton, based in part on work Copyright +# (C) 2015-2016 Espressif Systems. +# +# This program is free software; you can redistribute it and/or modify it under +# the terms of the GNU General Public License as published by the Free Software +# Foundation; either version 2 of the License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, but WITHOUT +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS +# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License along with +# this program; if not, write to the Free Software Foundation, Inc., 51 Franklin +# Street, Fifth Floor, Boston, MA 02110-1301 USA. + +import argparse +import hashlib +import inspect +import json +import os +import serial +import struct +import subprocess +import sys +import time +import zlib + +__version__ = "2.0-dev" + + +MAX_UINT32 = 0xffffffff +MAX_UINT24 = 0xffffff + + +class ESPROM(object): + """ Base class providing access to ESP ROM bootloader. Subclasses provide + ESP8266, ESP31 & ESP32 specific functionality. + + Don't instantiate this base class directly, either instantiate a subclass or + call ESPROM.detect_chip() which will interrogate the chip and return the + appropriate subclass instance. + + """ + CHIP_NAME = "Espressif device" + + DEFAULT_PORT = "/dev/ttyUSB0" + + # These are the currently known commands supported by the ROM + ESP_FLASH_BEGIN = 0x02 + ESP_FLASH_DATA = 0x03 + ESP_FLASH_END = 0x04 + ESP_MEM_BEGIN = 0x05 + ESP_MEM_END = 0x06 + ESP_MEM_DATA = 0x07 + ESP_SYNC = 0x08 + ESP_WRITE_REG = 0x09 + ESP_READ_REG = 0x0a + + # Maximum block sized for RAM and Flash writes, respectively. + ESP_RAM_BLOCK = 0x1800 + ESP_FLASH_BLOCK = 0x400 + + # Default baudrate. The ROM auto-bauds, so we can use more or less whatever we want. + ESP_ROM_BAUD = 115200 + + # First byte of the application image + ESP_IMAGE_MAGIC = 0xe9 + + # Initial state for the checksum routine + ESP_CHECKSUM_MAGIC = 0xef + + # Flash sector size, minimum unit of erase. + ESP_FLASH_SECTOR = 0x1000 + + UART_DATA_REG_ADDR = 0x60000078 + + # SPI peripheral "command" bitmasks + SPI_CMD_READ_ID = 0x10000000 + + # Memory addresses + IROM_MAP_START = 0x40200000 + IROM_MAP_END = 0x40300000 + + # The number of bytes in the response that signify command status + STATUS_BYTES_LENGTH = 2 + + def __init__(self, port=DEFAULT_PORT, baud=ESP_ROM_BAUD, do_connect=True): + """Base constructor for ESPROM objects + + Don't call this constructor, either instantiate ESP8266ROM, + ESP31ROM, or ESP32ROM, or use ESPROM.detect_chip(). + + """ + self._port = serial.Serial(port) + self._slip_reader = slip_reader(self._port) + # setting baud rate in a separate step is a workaround for + # CH341 driver on some Linux versions (this opens at 9600 then + # sets), shouldn't matter for other platforms/drivers. See + # https://github.com/themadinventor/esptool/issues/44#issuecomment-107094446 + self._port.baudrate = baud + if do_connect: + self.connect() + + @staticmethod + def detect_chip(port=DEFAULT_PORT, baud=ESP_ROM_BAUD): + """Use serial access to detect the chip type. + + We use the UART's datecode register for this, it's mapped at + the same address on ESP8266 & ESP31/32 so we can use one + memory read and compare to the datecode register for each chip + type. + + """ + detect_port = ESPROM(port, baud, True) + sys.stdout.write('Detecting chip type... ') + date_reg = detect_port.read_reg(ESPROM.UART_DATA_REG_ADDR) + for cls in [ESP8266ROM, ESP31ROM, ESP32ROM]: + if date_reg == cls.DATE_REG_VALUE: + inst = cls(port, baud, False) # don't connect a second time + print '%s' % inst.CHIP_NAME + return inst + print '' + raise FatalError("Unexpected UART datecode value 0x%08x. Failed to autodetect chip type." % date_reg) + + """ Read a SLIP packet from the serial port """ + def read(self): + return self._slip_reader.next() + + """ Write bytes to the serial port while performing SLIP escaping """ + def write(self, packet): + buf = '\xc0' \ + + (packet.replace('\xdb','\xdb\xdd').replace('\xc0','\xdb\xdc')) \ + + '\xc0' + self._port.write(buf) + + """ Calculate checksum of a blob, as it is defined by the ROM """ + @staticmethod + def checksum(data, state=ESP_CHECKSUM_MAGIC): + for b in data: + state ^= ord(b) + return state + + """ Send a request and read the response """ + def command(self, op=None, data=None, chk=0): + if op is not None: + pkt = struct.pack(' self.STATUS_BYTES_LENGTH: + return data[:-self.STATUS_BYTES_LENGTH] + else: # otherwise, just return the 'val' field which comes from the reply header (this is used by read_reg) + return val + + def sync(self): + """ Perform a connection test """ + self.command(ESPROM.ESP_SYNC, '\x07\x07\x12\x20' + 32 * '\x55') + for i in xrange(7): + self.command() + + def connect(self): + """ Try connecting repeatedly until successful, or giving up """ + print 'Connecting...' + + for _ in xrange(4): + # issue reset-to-bootloader: + # RTS = either CH_PD or nRESET (both active low = chip in reset) + # DTR = GPIO0 (active low = boot to flasher) + self._port.setDTR(False) + self._port.setRTS(True) + time.sleep(0.05) + self._port.setDTR(True) + self._port.setRTS(False) + time.sleep(0.05) + self._port.setDTR(False) + + # worst-case latency timer should be 255ms (probably <20ms) + self._port.timeout = 0.3 + last_exception = None + for _ in xrange(4): + try: + self._port.flushInput() + self._slip_reader = slip_reader(self._port) + self._port.flushOutput() + self.sync() + self._port.timeout = 5 + return + except FatalError as e: + last_exception = e + time.sleep(0.05) + raise FatalError('Failed to connect to %s: %s' % (self.CHIP_NAME, last_exception)) + + """ Read memory address in target """ + def read_reg(self, addr): + # we don't call check_command here because read_reg() function is called + # when detecting chip type, and the way we check for success (STATUS_BYTES_LENGTH) is different + # for different chip types (!) + val, data = self.command(ESPROM.ESP_READ_REG, struct.pack('> 24) | ((id1 & MAX_UINT24) << 8) + + def read_mac(self): + """ Read MAC from OTP ROM """ + mac0 = self.read_reg(self.ESP_OTP_MAC0) + mac1 = self.read_reg(self.ESP_OTP_MAC1) + mac3 = self.read_reg(self.ESP_OTP_MAC3) + if (mac3 != 0): + oui = ((mac3 >> 16) & 0xff, (mac3 >> 8) & 0xff, mac3 & 0xff) + elif ((mac1 >> 16) & 0xff) == 0: + oui = (0x18, 0xfe, 0x34) + elif ((mac1 >> 16) & 0xff) == 1: + oui = (0xac, 0xd0, 0x74) + else: + raise FatalError("Unknown OUI") + return oui + ((mac1 >> 8) & 0xff, mac1 & 0xff, (mac0 >> 24) & 0xff) + + def get_erase_size(self, size): + """ Calculate an erase size given a specific size in bytes. + + Provides a workaround for the bootloader erase bug.""" + + sectors_per_block = 16 + sector_size = self.ESP_FLASH_SECTOR + num_sectors = (size + sector_size - 1) / sector_size + start_sector = offset / sector_size + + head_sectors = sectors_per_block - (start_sector % sectors_per_block) + if num_sectors < head_sectors: + head_sectors = num_sectors + + if num_sectors < 2 * head_sectors: + return (num_sectors + 1) / 2 * sector_size + else: + return (num_sectors - head_sectors) * sector_size + +class ESP31ROM(ESPROM): + """ Access class for ESP31 ROM bootloader + """ + CHIP_NAME = "ESP31" + + DATE_REG_VALUE = 0x15052100 + + SPI_CMD_REG_ADDR = 0x60003000 + SPI_W0_REG_ADDR = 0x60003040 + + EFUSE_BASE = 0x6001a000 + + FLASH_SIZES = { + '1MB':0x00, + '2MB':0x10, + '4MB':0x20, + '8MB':0x30, + '16MB':0x40 + } + + def read_efuse(self, n): + """ Read the nth word of the ESP3x EFUSE region. """ + return self.read_reg(self.EFUSE_BASE + (4 * n)) + + def chip_id(self): + word16 = self.read_efuse(16) + word17 = self.read_efuse(17) + return ((word17 & MAX_UINT24) << 24) | (word16 >> 8) & MAX_UINT24 + + def read_mac(self): + """ Read MAC from EFUSE region """ + word16 = self.read_efuse(16) + word17 = self.read_efuse(17) + word18 = self.read_efuse(18) + word19 = self.read_efuse(19) + wifi_mac = (((word17 >> 16) & 0xff), ((word17 >> 8) & 0xff), ((word17 >> 0) & 0xff), + ((word16 >> 24) & 0xff), ((word16 >> 16) & 0xff), ((word16 >> 8) & 0xff)) + bt_mac = (((word19 >> 16) & 0xff), ((word19 >> 8) & 0xff), ((word19 >> 0) & 0xff), + ((word18 >> 24) & 0xff), ((word18 >> 16) & 0xff), ((word18 >> 8) & 0xff)) + return (wifi_mac,bt_mac) + + def get_erase_size(self, size): + return size + +class ESP32ROM(ESP31ROM): + """Access class for ESP32 ROM bootloader + + """ + CHIP_NAME = "ESP32" + + DATE_REG_VALUE = 0x15122500 + + # ESP32-only commands + ESP_SPI_FLASH_SET = 0xb + + ESP_SPI_ATTACH_REQ = 0xD + + ESP_CHANGE_BAUDRATE = 0x0F + ESP_FLASH_DEFL_BEGIN = 0x10 + ESP_FLASH_DEFL_DATA = 0x11 + ESP_FLASH_DEFL_END = 0x12 + + ESP_SPI_FLASH_MD5 = 0x13 + + IROM_MAP_START = 0x400d0000 + IROM_MAP_END = 0x40400000 + DROM_MAP_START = 0x3F400000 + DROM_MAP_END = 0x3F700000 + + # ESP32 uses a 4 byte status reply + STATUS_BYTES_LENGTH = 4 + + def flash_defl_begin(self, size, compsize, offset): + """ Start downloading compressed data to Flash (performs an erase) """ + old_tmo = self._port.timeout + num_blocks = (compsize + self.ESP_FLASH_BLOCK - 1) / self.ESP_FLASH_BLOCK + erase_blocks = (size + self.ESP_FLASH_BLOCK - 1) / self.ESP_FLASH_BLOCK + + erase_size = size + if erase_size > 0 and (offset + erase_size) >= (16 / 8) * 1024 * 1024: + self.flash_spi_param_set() + + self._port.timeout = 20 + t = time.time() + print "Unc size %d comp size %d comp blocks %d" % (size, compsize, num_blocks) + self.check_command("enter compressed flash mode", self.ESP_FLASH_DEFL_BEGIN, + struct.pack(' 16: + raise FatalError('Invalid firmware image magic=%d segments=%d' % (magic, segments)) + return segments + + def load_segment(self, f, is_irom_segment=False): + """ Load the next segment from the image file """ + file_offs = f.tell() + (offset, size) = struct.unpack(' 0x40200000 or offset < 0x3ffe0000 or size > 65536: + print('WARNING: Suspicious segment 0x%x, length %d' % (offset, size)) + segment_data = f.read(size) + if len(segment_data) < size: + raise FatalError('End of file reading segment 0x%x, length %d (actual length %d)' % (offset, size, len(segment_data))) + segment = ImageSegment(offset, segment_data, file_offs) + self.segments.append(segment) + return segment + + def save_segment(self, f, segment, checksum=None): + """ Save the next segment to the image file, return next checksum value if provided """ + f.write(struct.pack(' 0: + if len(irom_segments) != 1: + raise FatalError('Found %d segments that could be irom0. Bad ELF file?' % len(irom_segments)) + return irom_segments[0] + return None + + def get_non_irom_segments(self): + irom_segment = self.get_irom_segment() + return [s for s in self.segments if s != irom_segment] + + +class ESPFirmwareImage(BaseFirmwareImage): + """ 'Version 1' firmware image, segments loaded directly by the ROM bootloader. """ + def __init__(self, load_file=None): + super(ESPFirmwareImage, self).__init__() + self.flash_mode = 0 + self.flash_size_freq = 0 + self.version = 1 + + if load_file is not None: + segments = self.load_common_header(load_file, ESPROM.ESP_IMAGE_MAGIC) + + for _ in xrange(segments): + self.load_segment(load_file) + self.checksum = self.read_checksum(load_file) + + def default_output_name(self, input_file): + """ Derive a default output name from the ELF name. """ + return input_file + '-' + + def save(self, basename): + """ Save a set of V1 images for flashing. Parameter is a base filename. """ + # IROM data goes in its own plain binary file + irom_segment = self.get_irom_segment() + if irom_segment is not None: + with open("%s0x%05x.bin" % (basename, irom_segment.addr), "wb") as f: + f.write(irom_segment.data) + + # everything but IROM goes at 0x00000 in an image file + normal_segments = self.get_non_irom_segments() + with open("%s0x00000.bin" % basename, 'wb') as f: + self.write_common_header(f, normal_segments) + checksum = ESPROM.ESP_CHECKSUM_MAGIC + for segment in self.segments: + checksum = self.save_segment(f, segment, checksum) + self.append_checksum(f, checksum) + + +class OTAFirmwareImage(BaseFirmwareImage): + """ 'Version 2' firmware image, segments loaded by software bootloader stub + (ie Espressif bootloader or rboot) + """ + def __init__(self, load_file=None): + super(OTAFirmwareImage, self).__init__() + self.version = 2 + if load_file is not None: + segments = self.load_common_header(load_file, ESPBOOTLOADER.IMAGE_V2_MAGIC) + if segments != ESPBOOTLOADER.IMAGE_V2_SEGMENT: + # segment count is not really segment count here, but we expect to see '4' + print 'Warning: V2 header has unexpected "segment" count %d (usually 4)' % segments + + # irom segment comes before the second header + # + # the file is saved in the image with a zero load address + # in the header, so we need to calculate a load address + irom_offs = load_file.tell() + irom_segment = self.load_segment(load_file, True) + irom_segment.addr = irom_offs + ESPROM.IROM_MAP_START + + first_flash_mode = self.flash_mode + first_flash_size_freq = self.flash_size_freq + first_entrypoint = self.entrypoint + # load the second header + self.load_common_header(load_file, ESPROM.ESP_IMAGE_MAGIC) + (magic, segments, self.flash_mode, self.flash_size_freq, self.entrypoint) = struct.unpack(' 0: + #print("Calculated pad length %08x to place next header @ %08x" % (pad_len, f.tell()+pad_len)) + null = ImageSegment(0, '\x00' * pad_len, f.tell()) + checksum = self.save_segment(f, null, checksum) + #print("After padding, at file offset %08x" % f.tell()) + padding_segments += 1 + #print "Comparing file offs %x (data @ %x) with segment load addr %x" % (f.tell(), f.tell() + 8, segment.addr) + # verify that after the 8 byte header is added, were are at the correct offset relative to the segment's vaddr + assert (f.tell() + 8) % IROM_ALIGN == segment.addr % IROM_ALIGN + checksum = self.save_segment(f, segment, checksum) + self.append_checksum(f, checksum) + # kinda hacky: go back to the initial header and write the new segment count + # that includes padding segments. Luckily(?) this header is not checksummed + f.seek(1) + f.write(chr(len(self.segments) + padding_segments)) + + +class ELFFile(object): + SEC_TYPE_PROGBITS = 0x01 + SEC_TYPE_STRTAB = 0x03 + + def __init__(self, name): + # Load sections from the ELF file + self.name = name + with open(self.name, 'rb') as f: + self._read_elf_file(f) + + def _read_elf_file(self, f): + # read the ELF file header + LEN_FILE_HEADER = 0x34 + try: + (ident,_type,machine,_version, + self.entrypoint,_phoff,shoff,_flags, + _ehsize, _phentsize,_phnum,_shentsize, + _shnum,shstrndx) = struct.unpack("<16sHHLLLLLHHHHHH", f.read(LEN_FILE_HEADER)) + except struct.error as e: + raise FatalError("Failed to read a valid ELF header from %s: %s" % (self.name, e)) + + if ident[0] != '\x7f' or ident[1:4] != 'ELF': + raise FatalError("%s has invalid ELF magic header" % self.name) + if machine != 0x5e: + raise FatalError("%s does not appear to be an Xtensa ELF file. e_machine=%04x" % (self.name, machine)) + self._read_sections(f, shoff, shstrndx) + + def _read_sections(self, f, section_header_offs, shstrndx): + f.seek(section_header_offs) + section_header = f.read() + LEN_SEC_HEADER = 0x28 + if len(section_header) == 0: + raise FatalError("No section header found at offset %04x in ELF file." % section_header_offs) + if len(section_header) % LEN_SEC_HEADER != 0: + print 'WARNING: Unexpected ELF section header length %04x is not mod-%02x' % (len(section_header),LEN_SEC_HEADER) + + # walk through the section header and extract all sections + section_header_offsets = range(0, len(section_header), LEN_SEC_HEADER) + + def read_section_header(offs): + name_offs,sec_type,_flags,lma,sec_offs,size = struct.unpack_from(" 0: + esp._port.baudrate = baud_rate + # Read the greeting. + p = esp.read() + if p != 'OHAI': + raise FatalError('Failed to connect to the flasher (got %s)' % hexify(p)) + + def flash_write(self, addr, data, show_progress=False): + assert addr % self._esp.ESP_FLASH_SECTOR == 0, 'Address must be sector-aligned' + assert len(data) % self._esp.ESP_FLASH_SECTOR == 0, 'Length must be sector-aligned' + sys.stdout.write('Writing %d @ 0x%x... ' % (len(data), addr)) + sys.stdout.flush() + self._esp.write(struct.pack(' length: + raise FatalError('Read more than expected') + p = self._esp.read() + if len(p) != 16: + raise FatalError('Expected digest, got: %s' % hexify(p)) + expected_digest = hexify(p).upper() + digest = hashlib.md5(data).hexdigest().upper() + print + if digest != expected_digest: + raise FatalError('Digest mismatch: expected %s, got %s' % (expected_digest, digest)) + p = self._esp.read() + if len(p) != 1: + raise FatalError('Expected status, got: %s' % hexify(p)) + status_code = struct.unpack(', ) or a single +# argument. + +def load_ram(esp, args): + image = LoadFirmwareImage(esp, args.filename) + + print 'RAM boot...' + for (offset, size, data) in image.segments: + print 'Downloading %d bytes at %08x...' % (size, offset), + sys.stdout.flush() + esp.mem_begin(size, div_roundup(size, esp.ESP_RAM_BLOCK), esp.ESP_RAM_BLOCK, offset) + + seq = 0 + while len(data) > 0: + esp.mem_block(data[0:esp.ESP_RAM_BLOCK], seq) + data = data[esp.ESP_RAM_BLOCK:] + seq += 1 + print 'done!' + + print 'All segments done, executing at %08x' % image.entrypoint + esp.mem_finish(image.entrypoint) + + +def read_mem(esp, args): + print '0x%08x = 0x%08x' % (args.address, esp.read_reg(args.address)) + + +def write_mem(esp, args): + esp.write_reg(args.address, args.value, args.mask, 0) + print 'Wrote %08x, mask %08x to %08x' % (args.value, args.mask, args.address) + + +def dump_mem(esp, args): + f = file(args.filename, 'wb') + for i in xrange(args.size / 4): + d = esp.read_reg(args.address + (i * 4)) + f.write(struct.pack(' 0: + print '\rWriting at 0x%08x... (%d %%)' % (address + seq * esp.ESP_FLASH_BLOCK, 100 * (seq + 1) / blocks), + sys.stdout.flush() + block = image[0:esp.ESP_FLASH_BLOCK] + if args.compress: + esp.flash_defl_block(block, seq) + else: + # Pad the last block + block = block + '\xff' * (esp.ESP_FLASH_BLOCK - len(block)) + # Fix sflash config data + if address == 0 and seq == 0 and block[0] == '\xe9': + block = block[0:2] + flash_info + block[4:] + header_block = block + esp.flash_block(block, seq) + image = image[esp.ESP_FLASH_BLOCK:] + seq += 1 + written += len(block) + t = time.time() - t + print '\rWrote %d bytes at 0x%08x in %.1f seconds (%.1f kbit/s)...' % (written, address, t, written / t * 8 / 1000) + res = esp.flash_md5sum(address, uncsize) + if res != calcmd5: + print 'File md5: %s' % calcmd5 + print 'Flash md5: %s' % res + raise FatalError("MD5 of file does not match data in flash!") + else: + print 'Hash of data verified.' + print '\nLeaving...' + if args.flash_mode == 'dio': + esp.flash_unlock_dio() + else: + esp.flash_begin(0, 0) + if args.compress: + esp.flash_defl_finish(False) + else: + esp.flash_finish(False) + if args.verify: + print 'Verifying just-written flash...' + verify_flash(esp, args, header_block) + + +def image_info(args): + image = LoadFirmwareImage(args.chip, args.filename) + print('Image version: %d' % image.version) + print('Entry point: %08x' % image.entrypoint) if image.entrypoint != 0 else 'Entry point not set' + print '%d segments' % len(image.segments) + print + checksum = ESPROM.ESP_CHECKSUM_MAGIC + idx = 0 + for seg in image.segments: + idx += 1 + print 'Segment %d: %r' % (idx, seg) + checksum = ESPROM.checksum(seg.data, checksum) + print + print 'Checksum: %02x (%s)' % (image.checksum, 'valid' if image.checksum == checksum else 'invalid!') + + +def make_image(args): + image = ESPFirmwareImage() + if len(args.segfile) == 0: + raise FatalError('No segments specified') + if len(args.segfile) != len(args.segaddr): + raise FatalError('Number of specified files does not match number of specified addresses') + for (seg, addr) in zip(args.segfile, args.segaddr): + data = file(seg, 'rb').read() + image.segments.append(ImageSegment(addr, data)) + image.entrypoint = args.entrypoint + image.save(args.output) + + +def elf2image(args): + e = ELFFile(args.input) + if args.chip == 'auto': # Default to ESP8266 for backwards compatibility + print "Creating image for ESP8266..." + args.chip == 'esp8266' + + if args.chip == 'esp31': + raise FatalError("No elf2image support for ESP31. Use gen_appimage.py from the ESP31 SDK") + elif args.chip == 'esp32': + image = ESP32FirmwareImage() + elif args.version == '1': # ESP8266 + image = ESPFirmwareImage() + else: + image = OTAFirmwareImage() + image.entrypoint = e.entrypoint + image.segments = e.sections # ELFSection is a subclass of ImageSegment + image.flash_mode = {'qio':0, 'qout':1, 'dio':2, 'dout': 3}[args.flash_mode] + image.flash_size_freq = ESP8266ROM.FLASH_SIZES[args.flash_size] + image.flash_size_freq += {'40m':0, '26m':1, '20m':2, '80m': 0xf}[args.flash_freq] + + if args.output is None: + args.output = image.default_output_name(args.input) + image.save(args.output) + + +def read_mac(esp, args): + mac = esp.read_mac() + print 'MAC: %s' % ':'.join(map(lambda x: '%02x' % x, mac)) + + +def chip_id(esp, args): + chipid = esp.chip_id() + print 'Chip ID: 0x%08x' % chipid + + +def erase_flash(esp, args): + print 'Erasing flash (this may take a while)...' + flasher = CesantaFlasher(esp, args.baud) + flasher.flash_erase() + print 'Erase completed successfully.' + + +def run(esp, args): + esp.run() + + +def flash_id(esp, args): + flash_id = esp.flash_id() + print 'Manufacturer: %02x' % (flash_id & 0xff) + print 'Device: %02x%02x' % ((flash_id >> 8) & 0xff, (flash_id >> 16) & 0xff) + + +def read_flash(esp, args): + flasher = CesantaFlasher(esp, args.baud) + t = time.time() + data = flasher.flash_read(args.address, args.size, not args.no_progress) + t = time.time() - t + print ('\rRead %d bytes at 0x%x in %.1f seconds (%.1f kbit/s)...' + % (len(data), args.address, t, len(data) / t * 8 / 1000)) + file(args.filename, 'wb').write(data) + + +def _verify_flash(flasher, args, flash_params=None): + differences = False + for address, argfile in args.addr_filename: + image = argfile.read() + argfile.seek(0) # rewind in case we need it again + if address == 0 and image[0] == '\xe9' and flash_params is not None: + image = image[0:2] + flash_params + image[4:] + image_size = len(image) + print 'Verifying 0x%x (%d) bytes @ 0x%08x in flash against %s...' % (image_size, image_size, address, argfile.name) + # Try digest first, only read if there are differences. + digest, _ = flasher.flash_digest(address, image_size) + digest = hexify(digest).upper() + expected_digest = hashlib.md5(image).hexdigest().upper() + if digest == expected_digest: + print '-- verify OK (digest matched)' + continue + else: + differences = True + if getattr(args, 'diff', 'no') != 'yes': + print '-- verify FAILED (digest mismatch)' + continue + + flash = flasher.flash_read(address, image_size) + assert flash != image + diff = [i for i in xrange(image_size) if flash[i] != image[i]] + print '-- verify FAILED: %d differences, first @ 0x%08x' % (len(diff), address + diff[0]) + for d in diff: + print ' %08x %02x %02x' % (address + d, ord(flash[d]), ord(image[d])) + if differences: + raise FatalError("Verify failed.") + + +def verify_flash(esp, args, flash_params=None): + flasher = CesantaFlasher(esp) + _verify_flash(flasher, args, flash_params) + + +def version(args): + print __version__ + +# +# End of operations functions +# + + +def main(): + parser = argparse.ArgumentParser(description='esptool.py v%s - ESP8266 ROM Bootloader Utility' % __version__, prog='esptool') + + parser.add_argument('--chip', '-c', + help='Target chip type', + choices=['auto', 'esp8266', 'esp31', 'esp32'], + default=os.environ.get('ESPTOOL_CHIP', 'auto')) + + parser.add_argument( + '--port', '-p', + help='Serial port device', + default=os.environ.get('ESPTOOL_PORT', ESPROM.DEFAULT_PORT)) + + parser.add_argument( + '--baud', '-b', + help='Serial port baud rate used when flashing/reading', + type=arg_auto_int, + default=os.environ.get('ESPTOOL_BAUD', ESPROM.ESP_ROM_BAUD)) + + subparsers = parser.add_subparsers( + dest='operation', + help='Run esptool {command} -h for additional help') + + parser_load_ram = subparsers.add_parser( + 'load_ram', + help='Download an image to RAM and execute') + parser_load_ram.add_argument('filename', help='Firmware image') + + parser_dump_mem = subparsers.add_parser( + 'dump_mem', + help='Dump arbitrary memory to disk') + parser_dump_mem.add_argument('address', help='Base address', type=arg_auto_int) + parser_dump_mem.add_argument('size', help='Size of region to dump', type=arg_auto_int) + parser_dump_mem.add_argument('filename', help='Name of binary dump') + + parser_read_mem = subparsers.add_parser( + 'read_mem', + help='Read arbitrary memory location') + parser_read_mem.add_argument('address', help='Address to read', type=arg_auto_int) + + parser_write_mem = subparsers.add_parser( + 'write_mem', + help='Read-modify-write to arbitrary memory location') + parser_write_mem.add_argument('address', help='Address to write', type=arg_auto_int) + parser_write_mem.add_argument('value', help='Value', type=arg_auto_int) + parser_write_mem.add_argument('mask', help='Mask of bits to write', type=arg_auto_int) + + def add_spi_flash_subparsers(parent): + """ Add common parser arguments for SPI flash properties """ + parent.add_argument('--flash_freq', '-ff', help='SPI Flash frequency', + choices=['40m', '26m', '20m', '80m'], + default=os.environ.get('ESPTOOL_FF', '40m')) + parent.add_argument('--flash_mode', '-fm', help='SPI Flash mode', + choices=['qio', 'qout', 'dio', 'dout'], + default=os.environ.get('ESPTOOL_FM', 'qio')) + parent.add_argument('--flash_size', '-fs', help='SPI Flash size in MegaBytes (1MB, 2MB, 4MB, 8MB, 16M)' + ' plus ESP8266-only (256KB, 512KB, 2MB-c1, 4MB-c1, 4MB-2)', + action=FlashSizeAction, + default=os.environ.get('ESPTOOL_FS', '1MB')) + + parser_write_flash = subparsers.add_parser( + 'write_flash', + help='Write a binary blob to flash') + parser_write_flash.add_argument('addr_filename', metavar='
', help='Address followed by binary filename, separated by space', + action=AddrFilenamePairAction) + add_spi_flash_subparsers(parser_write_flash) + parser_write_flash.add_argument('--no-progress', '-p', help='Suppress progress output', action="store_true") + parser_write_flash.add_argument('--verify', help='Verify just-written data (only necessary if very cautious, data is already CRCed', action='store_true') + parser_write_flash.add_argument('--ucIsHspi', '-ih', help='Config SPI PORT/PINS (Espressif internal feature)',default='0') + parser_write_flash.add_argument('--ucIsLegacy', '-il', help='Config SPI LEGACY (Espressif internal feature)',default='0') + parser_write_flash.add_argument('--compress', '-z', help='Compress data in transfer',action="store_true") + + subparsers.add_parser( + 'run', + help='Run application code in flash') + + parser_image_info = subparsers.add_parser( + 'image_info', + help='Dump headers from an application image') + parser_image_info.add_argument('filename', help='Image file to parse') + + parser_make_image = subparsers.add_parser( + 'make_image', + help='Create an application image from binary files') + parser_make_image.add_argument('output', help='Output image file') + parser_make_image.add_argument('--segfile', '-f', action='append', help='Segment input file') + parser_make_image.add_argument('--segaddr', '-a', action='append', help='Segment base address', type=arg_auto_int) + parser_make_image.add_argument('--entrypoint', '-e', help='Address of entry point', type=arg_auto_int, default=0) + + parser_elf2image = subparsers.add_parser( + 'elf2image', + help='Create an application image from ELF file') + parser_elf2image.add_argument('input', help='Input ELF file') + parser_elf2image.add_argument('--output', '-o', help='Output filename prefix (for version 1 image), or filename (for version 2 single image)', type=str) + parser_elf2image.add_argument('--version', '-e', help='Output image version', choices=['1','2'], default='1') + add_spi_flash_subparsers(parser_elf2image) + + subparsers.add_parser( + 'read_mac', + help='Read MAC address from OTP ROM') + + subparsers.add_parser( + 'chip_id', + help='Read Chip ID from OTP ROM') + + subparsers.add_parser( + 'flash_id', + help='Read SPI flash manufacturer and device ID') + + parser_read_flash = subparsers.add_parser( + 'read_flash', + help='Read SPI flash content') + parser_read_flash.add_argument('address', help='Start address', type=arg_auto_int) + parser_read_flash.add_argument('size', help='Size of region to dump', type=arg_auto_int) + parser_read_flash.add_argument('filename', help='Name of binary dump') + parser_read_flash.add_argument('--no-progress', '-p', help='Suppress progress output', action="store_true") + + parser_verify_flash = subparsers.add_parser( + 'verify_flash', + help='Verify a binary blob against flash') + parser_verify_flash.add_argument('addr_filename', help='Address and binary file to verify there, separated by space', + action=AddrFilenamePairAction) + parser_verify_flash.add_argument('--diff', '-d', help='Show differences', + choices=['no', 'yes'], default='no') + + subparsers.add_parser( + 'erase_flash', + help='Perform Chip Erase on SPI flash') + + subparsers.add_parser( + 'version', help='Print esptool version') + + # internal sanity check - every operation matches a module function of the same name + for operation in subparsers.choices.keys(): + assert operation in globals(), "%s should be a module function" % operation + + args = parser.parse_args() + + print 'esptool.py v%s' % __version__ + + # operation function can take 1 arg (args), 2 args (esp, arg) + # or be a member function of the ESPROM class. + + operation_func = globals()[args.operation] + operation_args,_,_,_ = inspect.getargspec(operation_func) + if operation_args[0] == 'esp': # operation function takes an ESPROM connection object + initial_baud = min(ESPROM.ESP_ROM_BAUD, args.baud) # don't sync faster than the default baud rate + chip_constructor_fun = { + 'auto': ESPROM.detect_chip, + 'esp8266': ESP8266ROM, + 'esp31': ESP31ROM, + 'esp32': ESP32ROM, + }[args.chip] + esp = chip_constructor_fun(args.port, initial_baud) + operation_func(esp, args) + else: + operation_func(args) + + +class FlashSizeAction(argparse.Action): + """ Custom flash size parser class to support backwards compatibility with megabit size arguments. + + (At next major relase, remove deprecated sizes and this can become a 'normal' choices= argument again.) + """ + def __init__(self, option_strings, dest, nargs=1, **kwargs): + super(FlashSizeAction, self).__init__(option_strings, dest, nargs, **kwargs) + + def __call__(self, parser, namespace, values, option_string=None): + try: + value = { + '2m': '256KB', + '4m': '512KB', + '8m': '1MB', + '16m': '2MB', + '32m': '4MB', + '16m-c1': '2MB-c1', + '32m-c1': '4MB-c1', + '32m-c2': '4MB-c2' + }[values[0]] + print("WARNING: Flash size arguments in megabits like '%s' are deprecated." % (values[0])) + print("Please use the equivalent size '%s'." % (value)) + print("Megabit arguments may be removed in a future release.") + except KeyError: + values = values[0] + + known_sizes = dict(ESP8266ROM.FLASH_SIZES) + known_sizes.update(ESP32ROM.FLASH_SIZES) + if value not in known_sizes: + raise argparse.ArgumentError(self, '%s is not a known flash size. Known sizes: %s' % (value, ", ".join(known_sizes.keys()))) + setattr(namespace, self.dest, value) + + +class AddrFilenamePairAction(argparse.Action): + """ Custom parser class for the address/filename pairs passed as arguments """ + def __init__(self, option_strings, dest, nargs='+', **kwargs): + super(AddrFilenamePairAction, self).__init__(option_strings, dest, nargs, **kwargs) + + def __call__(self, parser, namespace, values, option_string=None): + # validate pair arguments + pairs = [] + for i in range(0,len(values),2): + try: + address = int(values[i],0) + except ValueError as e: + raise argparse.ArgumentError(self,'Address "%s" must be a number' % values[i]) + try: + argfile = open(values[i + 1], 'rb') + except IOError as e: + raise argparse.ArgumentError(self, e) + except IndexError: + raise argparse.ArgumentError(self,'Must be pairs of an address and the binary filename to write there') + pairs.append((address, argfile)) + setattr(namespace, self.dest, pairs) + +# This is "wrapped" stub_flasher.c, to be loaded using run_stub. +_CESANTA_FLASHER_STUB = """\ +{"code_start": 1074790404, "code": "080000601C000060000000601000006031FCFF71FCFF\ +81FCFFC02000680332D218C020004807404074DCC48608005823C0200098081BA5A9239245005803\ +1B555903582337350129230B446604DFC6F3FF21EEFFC0200069020DF0000000010078480040004A\ +0040B449004012C1F0C921D911E901DD0209312020B4ED033C2C56C2073020B43C3C56420701F5FF\ +C000003C4C569206CD0EEADD860300202C4101F1FFC0000056A204C2DCF0C02DC0CC6CCAE2D1EAFF\ +0606002030F456D3FD86FBFF00002020F501E8FFC00000EC82D0CCC0C02EC0C73DEB2ADC46030020\ +2C4101E1FFC00000DC42C2DCF0C02DC056BCFEC602003C5C8601003C6C4600003C7C08312D0CD811\ +C821E80112C1100DF0000C180000140010400C0000607418000064180000801800008C1800008418\ +0000881800009018000018980040880F0040A80F0040349800404C4A0040740F0040800F0040980F\ +00400099004012C1E091F5FFC961CD0221EFFFE941F9310971D9519011C01A223902E2D1180C0222\ +6E1D21E4FF31E9FF2AF11A332D0F42630001EAFFC00000C030B43C2256A31621E1FF1A2228022030\ +B43C3256B31501ADFFC00000DD023C4256ED1431D6FF4D010C52D90E192E126E0101DDFFC0000021\ +D2FF32A101C020004802303420C0200039022C0201D7FFC00000463300000031CDFF1A333803D023\ +C03199FF27B31ADC7F31CBFF1A3328030198FFC0000056C20E2193FF2ADD060E000031C6FF1A3328\ +030191FFC0000056820DD2DD10460800000021BEFF1A2228029CE231BCFFC020F51A33290331BBFF\ +C02C411A332903C0F0F4222E1D22D204273D9332A3FFC02000280E27B3F721ABFF381E1A2242A400\ +01B5FFC00000381E2D0C42A40001B3FFC0000056120801B2FFC00000C02000280EC2DC0422D2FCC0\ +2000290E01ADFFC00000222E1D22D204226E1D281E22D204E7B204291E860000126E012198FF32A0\ +042A21C54C003198FF222E1D1A33380337B202C6D6FF2C02019FFFC000002191FF318CFF1A223A31\ +019CFFC00000218DFF1C031A22C549000C02060300003C528601003C624600003C72918BFF9A1108\ +71C861D851E841F83112C1200DF00010000068100000581000007010000074100000781000007C10\ +0000801000001C4B0040803C004091FDFF12C1E061F7FFC961E941F9310971D9519011C01A662906\ +21F3FFC2D1101A22390231F2FF0C0F1A33590331EAFFF26C1AED045C2247B3028636002D0C016DFF\ +C0000021E5FF41EAFF2A611A4469040622000021E4FF1A222802F0D2C0D7BE01DD0E31E0FF4D0D1A\ +3328033D0101E2FFC00000561209D03D2010212001DFFFC000004D0D2D0C3D01015DFFC0000041D5\ +FFDAFF1A444804D0648041D2FF1A4462640061D1FF106680622600673F1331D0FF10338028030C43\ +853A002642164613000041CAFF222C1A1A444804202FC047328006F6FF222C1A273F3861C2FF222C\ +1A1A6668066732B921BDFF3D0C1022800148FFC0000021BAFF1C031A2201BFFFC000000C02460300\ +5C3206020000005C424600005C5291B7FF9A110871C861D851E841F83112C1200DF0B0100000C010\ +0000D010000012C1E091FEFFC961D951E9410971F931CD039011C0ED02DD0431A1FF9C1422A06247\ +B302062D0021F4FF1A22490286010021F1FF1A223902219CFF2AF12D0F011FFFC00000461C0022D1\ +10011CFFC0000021E9FFFD0C1A222802C7B20621E6FF1A22F8022D0E3D014D0F0195FFC000008C52\ +22A063C6180000218BFF3D01102280F04F200111FFC00000AC7D22D1103D014D0F010DFFC0000021\ +D6FF32D110102280010EFFC0000021D3FF1C031A220185FFC00000FAEEF0CCC056ACF821CDFF317A\ +FF1A223A310105FFC0000021C9FF1C031A22017CFFC000002D0C91C8FF9A110871C861D851E841F8\ +3112C1200DF0000200600000001040020060FFFFFF0012C1E00C02290131FAFF21FAFF026107C961\ +C02000226300C02000C80320CC10564CFF21F5FFC02000380221F4FF20231029010C432D010163FF\ +C0000008712D0CC86112C1200DF00080FE3F8449004012C1D0C9A109B17CFC22C1110C13C51C0026\ +1202463000220111C24110B68202462B0031F5FF3022A02802A002002D011C03851A0066820A2801\ +32210105A6FF0607003C12C60500000010212032A01085180066A20F2221003811482105B3FF2241\ +10861A004C1206FDFF2D011C03C5160066B20E280138114821583185CFFF06F7FF005C1286F5FF00\ +10212032A01085140066A20D2221003811482105E1FF06EFFF0022A06146EDFF45F0FFC6EBFF0000\ +01D2FFC0000006E9FF000C022241100C1322C110C50F00220111060600000022C1100C13C50E0022\ +011132C2FA303074B6230206C8FF08B1C8A112C1300DF0000000000010404F484149007519031027\ +000000110040A8100040BC0F0040583F0040CC2E00401CE20040D83900408000004021F4FF12C1E0\ +C961C80221F2FF097129010C02D951C91101F4FFC0000001F3FFC00000AC2C22A3E801F2FFC00000\ +21EAFFC031412A233D0C01EFFFC000003D0222A00001EDFFC00000C1E4FF2D0C01E8FFC000002D01\ +32A004450400C5E7FFDD022D0C01E3FFC00000666D1F4B2131DCFF4600004B22C0200048023794F5\ +31D9FFC0200039023DF08601000001DCFFC000000871C861D85112C1200DF000000012C1F0026103\ +01EAFEC00000083112C1100DF000643B004012C1D0E98109B1C9A1D991F97129013911E2A0C001FA\ +FFC00000CD02E792F40C0DE2A0C0F2A0DB860D00000001F4FFC00000204220E71240F7921C226102\ +01EFFFC0000052A0DC482157120952A0DD571205460500004D0C3801DA234242001BDD3811379DC5\ +C6000000000C0DC2A0C001E3FFC00000C792F608B12D0DC8A1D891E881F87112C1300DF00000", "\ +entry": 1074792180, "num_params": 1, "params_start": 1074790400, "data": "FE0510\ +401A0610403B0610405A0610407A061040820610408C0610408C061040", "data_start": 10736\ +43520} +""" + +if __name__ == '__main__': + try: + main() + except FatalError as e: + print '\nA fatal error occurred: %s' % e + sys.exit(2) diff --git a/bin/gen_esp32part.py b/bin/gen_esp32part.py new file mode 100755 index 0000000000..8b5df2b3b5 --- /dev/null +++ b/bin/gen_esp32part.py @@ -0,0 +1,308 @@ +#!/usr/bin/env python +# +# ESP32 partition table generation tool +# +# Converts partition tables to/from CSV and binary formats. +# +# See the sdkng README.md file for details about how to use this tool. +import struct +import argparse +import sys + +__version__ = '1.0' + +quiet = False + +def status(msg): + """ Print status message to stderr """ + if not quiet: + critical(msg) + +def critical(msg): + """ Print critical message to stderr """ + if not quiet: + sys.stderr.write(msg) + sys.stderr.write('\n') + +class PartitionTable(list): + def __init__(self): + super(PartitionTable, self).__init__(self) + + @classmethod + def from_csv(cls, csv_contents): + res = PartitionTable() + lines = csv_contents.split("\n") + for line_no in range(len(lines)): + line = lines[line_no].strip() + if line.startswith("#") or len(line) == 0: + continue + try: + res.append(PartitionDefinition.from_csv(line)) + except InputError as e: + raise InputError("Error at line %d: %s" % (line_no+1, e)) + except Exception: + critical("Unexpected error parsing line %d: %s" % (line_no+1, line)) + raise + + # fix up missing offsets & negative sizes + last_end = 0x5000 # first offset after partition table + for e in res: + if e.offset is None: + pad_to = 0x10000 if e.type == PartitionDefinition.APP_TYPE else 4 + if last_end % pad_to != 0: + last_end += pad_to - (last_end % pad_to) + e.offset = last_end + if e.size < 0: + e.size = -e.size - e.offset + last_end = e.offset + e.size + + return res + + def __getitem__(self, item): + """ Allow partition table access via name as well as by + numeric index. """ + if isinstance(item, str): + for x in self: + if x.name == item: + return x + raise ValueError("No partition entry named '%s'" % item) + else: + return super(PartitionTable, self).__getitem__(item) + + def verify(self): + # verify each partition individually + for p in self: + p.verify() + # check for overlaps + last = None + for p in sorted(self): + if p.offset < 0x5000: + raise InputError("Partition offset 0x%x is below 0x5000" % p.offset) + if last is not None and p.offset < last.offset + last.size: + raise InputError("Partition at 0x%x overlaps 0x%x-0x%x" % (p.offset, last.offset, last.offset+last.size-1)) + last = p + + @classmethod + def from_binary(cls, b): + if len(b) % 32 != 0: + raise InputError("Partition table length must be a multiple of 32 bytes. Got %d bytes." % len(b)) + result = cls() + for o in range(0,len(b),32): + result.append(PartitionDefinition.from_binary(b[o:o+32])) + return result + + def to_binary(self): + return "".join(e.to_binary() for e in self) + + def to_csv(self, simple_formatting=False): + rows = [ "# Espressif ESP32 Partition Table", + "# Name, Type, SubType, Offset, Size" ] + rows += [ x.to_csv(simple_formatting) for x in self ] + return "\n".join(rows) + "\n" + +class PartitionDefinition(object): + APP_TYPE = 0x00 + DATA_TYPE = 0x01 + TYPES = { + "app" : APP_TYPE, + "data" : DATA_TYPE, + } + + SUBTYPES = { + APP_TYPE : { + "factory" : 0x00, + "test" : 0x20, + }, + DATA_TYPE : { + "ota" : 0x00, + "rf" : 0x01, + "wifi" : 0x02, + }, + } + + MAGIC_BYTES = "\xAA\x50" + + ALIGNMENT = { + APP_TYPE : 0x1000, + DATA_TYPE : 0x04, + } + + # add subtypes for the 16 OTA slot values ("ota_XXX, etc.") + for ota_slot in range(16): + SUBTYPES[TYPES["app"]]["ota_%d" % ota_slot] = 0x10 + ota_slot + + def __init__(self): + self.name = "" + self.type = None + self.subtype = None + self.offset = None + self.size = None + + @classmethod + def from_csv(cls, line): + """ Parse a line from the CSV """ + line_w_defaults = line + ",,," # lazy way to support default fields + fields = [ f.strip() for f in line_w_defaults.split(",") ] + + res = PartitionDefinition() + res.name = fields[0] + res.type = res.parse_type(fields[1]) + res.subtype = res.parse_subtype(fields[2]) + res.offset = res.parse_address(fields[3]) + res.size = res.parse_address(fields[4]) + if res.size is None: + raise InputError("Size field can't be empty") + return res + + def __eq__(self, other): + return self.name == other.name and self.type == other.type \ + and self.subtype == other.subtype and self.offset == other.offset \ + and self.size == other.size + + def __repr__(self): + def maybe_hex(x): + return "0x%x" % x if x is not None else "None" + return "PartitionDefinition('%s', 0x%x, 0x%x, %s, %s)" % (self.name, self.type, self.subtype or 0, + maybe_hex(self.offset), maybe_hex(self.size)) + + def __str__(self): + return "Part '%s' %d/%d @ 0x%x size 0x%x" % (self.name, self.type, self.subtype, self.offset or -1, self.size or -1) + + def __cmp__(self, other): + return self.offset - other.offset + + def parse_type(self, strval): + if strval == "": + raise InputError("Field 'type' can't be left empty.") + return parse_int(strval, self.TYPES) + + def parse_subtype(self, strval): + if strval == "": + return 0 # default + return parse_int(strval, self.SUBTYPES.get(self.type, {})) + + def parse_address(self, strval): + if strval == "": + return None # PartitionTable will fill in default + return parse_int(strval) + + def verify(self): + if self.type is None: + raise ValidationError("Type field is not set") + if self.subtype is None: + raise ValidationError("Subtype field is not set") + if self.offset is None: + raise ValidationError("Offset field is not set") + align = self.ALIGNMENT.get(self.type, 4) + if self.offset % align: + raise ValidationError("%s offset 0x%x is not aligned to 0x%x" % (self.name, self.offset, align)) + if self.size is None: + raise ValidationError("Size field is not set") + + STRUCT_FORMAT = "<2sBBLL16sL" + + @classmethod + def from_binary(cls, b): + if len(b) != 32: + raise InputError("Partition definition length must be exactly 32 bytes. Got %d bytes." % len(b)) + res = cls() + (magic, res.type, res.subtype, res.offset, + res.size, res.name, reserved) = struct.unpack(cls.STRUCT_FORMAT, b) + if "\x00" in res.name: # strip null byte padding from name string + res.name = res.name[:res.name.index("\x00")] + if magic != cls.MAGIC_BYTES: + raise InputError("Invalid magic bytes (%r) for partition definition" % magic) + if reserved != 0: + critical("WARNING: Partition definition had unexpected reserved value 0x%08x. Newer binary format?" % reserved) + return res + + def to_binary(self): + return struct.pack(self.STRUCT_FORMAT, + self.MAGIC_BYTES, + self.type, self.subtype, + self.offset, self.size, + self.name, + 0) # reserved + + def to_csv(self, simple_formatting=False): + def addr_format(a, include_sizes): + if not simple_formatting and include_sizes: + for (val, suffix) in [ (0x100000, "M"), (0x400, "K") ]: + if a % val == 0: + return "%d%s" % (a / val, suffix) + return "0x%x" % a + + def lookup_keyword(t, keywords): + for k,v in keywords.items(): + if simple_formatting == False and t == v: + return k + return "%d" % t + + return ",".join([ self.name, + lookup_keyword(self.type, self.TYPES), + lookup_keyword(self.subtype, self.SUBTYPES.get(self.type, {})), + addr_format(self.offset, False), + addr_format(self.size, True) ]) + +class InputError(RuntimeError): + def __init__(self, e): + super(InputError, self).__init__(e) + +def parse_int(v, keywords={}): + """Generic parser for integer fields - int(x,0) with provision for + k/m/K/M suffixes and 'keyword' value lookup. + """ + try: + for letter, multiplier in [ ("k",1024), ("m",1024*1024) ]: + if v.lower().endswith(letter): + return parse_int(v[:-1], keywords) * multiplier + return int(v, 0) + except ValueError: + if len(keywords) == 0: + raise InputError("Invalid field value %s" % v) + try: + return keywords[v.lower()] + except KeyError: + raise InputError("Value '%s' is not valid. Known keywords: %s" % (v, ", ".join(keywords))) + +def main(): + global quiet + parser = argparse.ArgumentParser(description='ESP32 partition table utility') + + parser.add_argument('--verify', '-v', help='Verify partition table fields', default=True, action='store_false') + parser.add_argument('--quiet', '-q', help="Don't print status messages to stderr", action='store_true') + + parser.add_argument('input', help='Path to CSV or binary file to parse. Will use stdin if omitted.', type=argparse.FileType('r'), default=sys.stdin) + parser.add_argument('output', help='Path to output converted binary or CSV file. Will use stdout if omitted, unless the --display argument is also passed (in which case only the summary is printed.)', + nargs='?', + default='-') + + args = parser.parse_args() + + quiet = args.quiet + input = args.input.read() + input_is_binary = input[0:2] == PartitionDefinition.MAGIC_BYTES + if input_is_binary: + status("Parsing binary partition input...") + table = PartitionTable.from_binary(input) + else: + status("Parsing CSV input...") + table = PartitionTable.from_csv(input) + + if args.verify: + status("Verifying table...") + table.verify() + + if input_is_binary: + output = table.to_csv() + else: + output = table.to_binary() + with sys.stdout if args.output == '-' else open(args.output, 'w') as f: + f.write(output) + +if __name__ == '__main__': + try: + main() + except InputError as e: + print(e) + sys.exit(2) diff --git a/components/bootloader/Makefile.projbuild b/components/bootloader/Makefile.projbuild new file mode 100644 index 0000000000..72f0789650 --- /dev/null +++ b/components/bootloader/Makefile.projbuild @@ -0,0 +1,45 @@ +# +# Bootloader component +# +# The bootloader is not a real component that gets linked into the project. +# Instead it is an entire standalone project ( in src/) that gets built in +# the upper projects build directory. This Makefile.projbuild provides the +# glue to build the bootloader project from the original project. It +# basically runs Make in the src/ directory but it needs to zero some variables +# the SDK makefile exports first, to not let them interfere. +# + +BOOTLOADER_COMPONENT_PATH := $(COMPONENT_PATH) +EXTRA_CLEAN_TARGETS+=bootloader-clean +BOOTLOADER_BIN=$(BUILD_DIR_BASE)/bootloader.bin + +.PHONY: bootloader-clean bootloader-flash bootloader + +$(BOOTLOADER_BIN): $(COMPONENT_PATH)/src/sdkconfig + $(Q) PROJECT_PATH= \ + COMPONENT_LDFLAGS= \ + COMPONENT_INCLUDES= \ + LDFLAGS= \ + CFLAGS= \ + BUILD_DIR_BASE=$(BUILD_DIR_BASE)/bootloader \ + make -C $(BOOTLOADER_COMPONENT_PATH)/src MAKEFLAGS= V=$(V) TARGET_BIN_LAYOUT="$(BOOTLOADER_TARGET_BIN_LAYOUT)" + +bootloader-clean: + $(Q) PROJECT_PATH= \ + COMPONENT_LDFLAGS= \ + COMPONENT_INCLUDES= \ + LDFLAGS= \ + CFLAGS= \ + BUILD_DIR_BASE=$(BUILD_DIR_BASE)/bootloader \ + make -C $(BOOTLOADER_COMPONENT_PATH)/src clean MAKEFLAGS= V=$(V) + +bootloader: $(BUILD_DIR_BASE)/bootloader.bin + +# synchronise the project level config to the component's +# config +$(COMPONENT_PATH)/src/sdkconfig: $(PROJECT_PATH)/sdkconfig + $(Q) cp $< $@ + +# bootloader-flash calls flash in the bootloader dummy project +bootloader-flash: $(BOOTLOADER_BIN) + make -C $(BOOTLOADER_COMPONENT_PATH)/src flash MAKEFLAGS= V=$(V) CONFIG_APP_OFFSET=0x1000 diff --git a/components/bootloader/src/.gitignore b/components/bootloader/src/.gitignore new file mode 100644 index 0000000000..278a862ae7 --- /dev/null +++ b/components/bootloader/src/.gitignore @@ -0,0 +1,2 @@ +build +sdkconfig diff --git a/components/bootloader/src/Makefile b/components/bootloader/src/Makefile new file mode 100644 index 0000000000..abf6374015 --- /dev/null +++ b/components/bootloader/src/Makefile @@ -0,0 +1,12 @@ +# +# This is a project Makefile. It is assumed the directory this Makefile resides in is a +# project subdirectory. +# + +PROJECT_NAME := bootloader +COMPONENTS := esptool_py + +#We cannot include the esp32 component directly but we need its includes. This is fixed by +#adding it in the main/Makefile directory. + +include $(SDK_PATH)/make/project.mk diff --git a/components/bootloader/src/main/Makefile b/components/bootloader/src/main/Makefile new file mode 100644 index 0000000000..2f07b6972e --- /dev/null +++ b/components/bootloader/src/main/Makefile @@ -0,0 +1,13 @@ +# +# Main Makefile. This is basically the same as a component makefile. +# +# This Makefile should, at the very least, just include $(SDK_PATH)/make/component.mk. By default, +# this will take the sources in the src/ directory, compile them and link them into +# lib(subdirectory_name).a in the build directory. This behaviour is entirely configurable, +# please read the SDK documents if you need to do this. +# + +COMPONENT_ADD_LDFLAGS := -L $(abspath .) -lmain -T eagle.bootloader.ld -T $(SDK_PATH)/components/esp32/ld/eagle.fpga32.rom.addr.v7.ld +COMPONENT_EXTRA_INCLUDES := $(SDK_PATH)/components/esp32/include + +include $(SDK_PATH)/make/component.mk diff --git a/components/bootloader/src/main/bootloader_config.h b/components/bootloader/src/main/bootloader_config.h new file mode 100644 index 0000000000..7ad97af674 --- /dev/null +++ b/components/bootloader/src/main/bootloader_config.h @@ -0,0 +1,138 @@ +// Copyright 2015-2016 Espressif Systems (Shanghai) PTE LTD +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at + +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +#ifndef __BOOT_CONFIG_H__ +#define __BOOT_CONFIG_H__ + +#include + +#ifdef __cplusplus +extern "C" +{ +#endif +#define BOOT_VERSION "V0.1" +#define SPI_SEC_SIZE 0x1000 +#define MEM_CACHE(offset) (uint8_t *)(0x3f400000 + (offset)) +#define CACHE_READ_32(offset) ((uint32_t *)(0x3f400000 + (offset))) +#define PARTITION_ADD 0x4000 +#define PARTITION_MAGIC 0x50AA +#define IROM_LOW 0x400D0000 +#define IROM_HIGH 0x40400000 +#define DROM_LOW 0x3F400000 +#define DROM_HIGH 0x3F800000 + +/*spi mode,saved in third byte in flash */ +enum { + SPI_MODE_QIO, + SPI_MODE_QOUT, + SPI_MODE_DIO, + SPI_MODE_DOUT, + SPI_MODE_FAST_READ, + SPI_MODE_SLOW_READ +}; +/* spi speed*/ +enum { + SPI_SPEED_40M, + SPI_SPEED_26M, + SPI_SPEED_20M, + SPI_SPEED_80M = 0xF +}; +/*suppport flash size in esp32 */ +enum { + SPI_SIZE_1MB = 0, + SPI_SIZE_2MB, + SPI_SIZE_4MB, + SPI_SIZE_8MB, + SPI_SIZE_16MB, + SPI_SIZE_MAX +}; + + +struct flash_hdr { + char magic; + char blocks; + char spi_mode; /* flag of flash read mode in unpackage and usage in future */ + char spi_speed: 4; /* low bit */ + char spi_size: 4; + unsigned int entry_addr; + uint8_t encrypt_flag; /* encrypt flag */ + uint8_t secury_boot_flag; /* secury boot flag */ + char extra_header[14]; /* ESP32 additional header, unused by second bootloader */ +}; + +/* each header of flash bin block */ +struct block_hdr { + unsigned int load_addr; + unsigned int data_len; +}; + +/* OTA selection structure (two copies in the OTA data partition.) + + Size of 32 bytes is friendly to flash encryption */ +typedef struct { + uint32_t ota_seq; + uint8_t seq_label[24]; + uint32_t crc; /* CRC32 of ota_seq field only */ +} ota_select; + +typedef struct { + uint32_t offset; + uint32_t size; +} partition_pos_t; + +typedef struct { + uint16_t magic; + uint8_t type; /* partition Type */ + uint8_t subtype; /* part_subtype */ + partition_pos_t pos; + uint8_t label[16]; /* label for the partition */ + uint8_t reserved[4]; /* reserved */ +} partition_info_t; + +#define PART_TYPE_APP 0x00 +#define PART_SUBTYPE_FACTORY 0x00 +#define PART_SUBTYPE_OTA_FLAG 0x10 +#define PART_SUBTYPE_OTA_MASK 0x0f +#define PART_SUBTYPE_TEST 0x20 + +#define PART_TYPE_DATA 0x01 +#define PART_SUBTYPE_DATA_OTA 0x00 +#define PART_SUBTYPE_DATA_RF 0x01 +#define PART_SUBTYPE_DATA_WIFI 0x02 + +#define PART_TYPE_END 0xff +#define PART_SUBTYPE_END 0xff + +#define SPI_ERROR_LOG "spi flash error" + +typedef struct { + partition_pos_t ota_info; + partition_pos_t factory; + partition_pos_t test; + partition_pos_t ota[16]; + uint32_t app_count; + uint32_t selected_subtype; +} bootloader_state_t; + +void boot_cache_redirect( uint32_t pos, size_t size ); +uint32_t get_bin_len(uint32_t pos); + +bool flash_encrypt(bootloader_state_t *bs); +bool secure_boot(void); + + +#ifdef __cplusplus +} +#endif + +#endif /* __BOOT_CONFIG_H__ */ diff --git a/components/bootloader/src/main/bootloader_log.h b/components/bootloader/src/main/bootloader_log.h new file mode 100644 index 0000000000..32bc4852e2 --- /dev/null +++ b/components/bootloader/src/main/bootloader_log.h @@ -0,0 +1,89 @@ +// Copyright 2015-2016 Espressif Systems (Shanghai) PTE LTD +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at + +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +#ifndef __BOOT_LOG_H__ +#define __BOOT_LOG_H__ + +#ifdef __cplusplus +extern "C" +{ +#endif + + +#define BOOT_LOG_LEVEL_ERROR (1) +#define BOOT_LOG_LEVEL_WARN (2) +#define BOOT_LOG_LEVEL_INFO (3) +#define BOOT_LOG_LEVEL_NOTICE (4) +#define BOOT_LOG_LEVEL_DEBUG (5) + +#define Black 0;30 +#define Red 0;31 +#define Green 0;32 +#define Brown 0;33 +#define Blue 0;34 +#define Purple 0;35 +#define Cyan 0;36 + +// TODO: move BOOT_LOG_LEVEL into menuconfig +//#define BOOT_LOG_LEVEL BOOT_LOG_LEVEL_ERROR +#define BOOT_LOG_LEVEL BOOT_LOG_LEVEL_NOTICE + +//printf("\033[0;36m[NOTICE][%s][%s][%d]\n" format "\r\n", __FILE__, __FUNCTION__, __LINE__, ##__VA_ARGS__); +#define log_notice(format, ...) \ + do{\ + if(BOOT_LOG_LEVEL >= BOOT_LOG_LEVEL_NOTICE){\ + ets_printf("\033[0;36m" format "\r\n", ##__VA_ARGS__);\ + ets_printf("\033[0m"); \ + }\ + }while(0) + +#define log_info(format, ...) \ + do{\ + if(BOOT_LOG_LEVEL >= BOOT_LOG_LEVEL_INFO){\ + ets_printf("\033[1;36m" format "\r\n", ##__VA_ARGS__);\ + ets_printf("\033[0m"); \ + }\ + }while(0) + +//printf("\033[0;31m[ERROR][%s][%s][%d]\n" format "\r\n", __FILE__, __FUNCTION__, __LINE__, ##__VA_ARGS__); +#define log_error(format, ...) \ + do{\ + if(BOOT_LOG_LEVEL >= BOOT_LOG_LEVEL_ERROR){\ + ets_printf("\033[0;31m[ERROR][%s][%s][%d]\n" format "\r\n", __FILE__, __FUNCTION__, __LINE__, ##__VA_ARGS__);\ + ets_printf("\033[0m"); \ + }\ + }while(0) + +//printf("\033[1;33m[WARN][%s][%s][%d]\n" format "\r\n", __FILE__, __FUNCTION__, __LINE__, ##__VA_ARGS__); +#define log_warn(format, ...) \ + do{\ + if(BOOT_LOG_LEVEL >= BOOT_LOG_LEVEL_WARN){\ + ets_printf("\033[1;33m[WARN][%s][%s][%d]\n" format "\r\n", __FILE__, __FUNCTION__, __LINE__, ##__VA_ARGS__);\ + ets_printf("\033[0m"); \ + }\ + }while(0) + +//printf("\033[1;32m[DEBUG][%s][%s][%d]\n" format "\r\n", __FILE__, __FUNCTION__, __LINE__, ##__VA_ARGS__); +#define log_debug(format, ...) \ + do{\ + if(BOOT_LOG_LEVEL >= BOOT_LOG_LEVEL_DEBUG){\ + ets_printf("\033[1;32m[DEBUG][%s][%s][%d]\n" format "\r\n", __FILE__, __FUNCTION__, __LINE__, ##__VA_ARGS__); \ + ets_printf("\033[0m"); \ + }\ + }while(0) + +#ifdef __cplusplus +} +#endif + +#endif /* __BOOT_LOGGING_H__ */ \ No newline at end of file diff --git a/components/bootloader/src/main/bootloader_start.c b/components/bootloader/src/main/bootloader_start.c new file mode 100644 index 0000000000..5c2a186812 --- /dev/null +++ b/components/bootloader/src/main/bootloader_start.c @@ -0,0 +1,597 @@ +// Copyright 2015-2016 Espressif Systems (Shanghai) PTE LTD +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at + +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +#include +#include +#include + +#include "esp_attr.h" + +#include "rom/cache.h" +#include "rom/ets_sys.h" +#include "rom/spi_flash.h" +#include "rom/crc.h" + +#include "soc/soc.h" +#include "soc/dport_reg.h" +#include "soc/io_mux_reg.h" +#include "soc/efuse_reg.h" +#include "soc/rtc_cntl_reg.h" +#include "soc/timers_reg.h" + +#include "sdkconfig.h" + +#include "bootloader_log.h" +#include "bootloader_config.h" + +extern int _bss_start; +extern int _bss_end; +/* +We arrive here after the bootloader finished loading the program from flash. The hardware is mostly uninitialized, +flash cache is down and the app CPU is in reset. We do have a stack, so we can do the initialization in C. +*/ + +// TODO: make a nice header file for ROM functions instead of adding externs all over the place +extern void Cache_Flush(int); + +void bootloader_main(); +void unpack_load_app(const partition_pos_t *app_node); +void print_flash_info(struct flash_hdr* pfhdr); +void IRAM_ATTR set_cache_and_start_app(uint32_t drom_addr, + uint32_t drom_load_addr, + uint32_t drom_size, + uint32_t irom_addr, + uint32_t irom_load_addr, + uint32_t irom_size, + uint32_t entry_addr); + + +void IRAM_ATTR call_start_cpu0() +{ + //Make page 0 access raise an exception + //Also some other unused pages so we can catch weirdness + //ToDo: this but nicer. + asm volatile (\ + "movi a4,0x00000000\n" \ + "movi a5,0xf\n" \ + "wdtlb a5,a4\n" \ + "witlb a5,a4\n" \ + "movi a4,0x80000000\n" \ + "wdtlb a5,a4\n" \ + "witlb a5,a4\n" \ + "movi a4,0xa0000000\n" \ + "wdtlb a5,a4\n" \ + "witlb a5,a4\n" \ + "movi a4,0xc0000000\n" \ + "wdtlb a5,a4\n" \ + "witlb a5,a4\n" \ + "movi a4,0xe0000000\n" \ + "wdtlb a5,a4\n" \ + "witlb a5,a4\n" \ + "movi a4,0x20000000\n" \ + "movi a5,0x0\n" \ + "wdtlb a5,a4\n" \ + "witlb a5,a4\n" \ + "movi a4,0x40000000\n" \ + "movi a5,0x2\n" \ + "wdtlb a5,a4\n" \ + "witlb a5,a4\n" \ + "isync\n" \ + :::"a4","a5"); + + //Clear bss + memset(&_bss_start, 0, (&_bss_end - &_bss_start) * sizeof(_bss_start)); + + /* completely reset MMU for both CPUs + (in case serial bootloader was running) */ + Cache_Read_Disable(0); + Cache_Read_Disable(1); + Cache_Flush(0); + Cache_Flush(1); + mmu_init(0); + mmu_init(1); + /* (above steps probably unnecessary for most serial bootloader + usage, all that's absolutely needed is that we unmask DROM0 + cache on the following two lines - normal ROM boot exits with + DROM0 cache unmasked, but serial bootloader exits with it + masked. However can't hurt to be thorough and reset + everything.) + */ + REG_CLR_BIT(PRO_CACHE_CTRL1_REG, DPORT_PRO_CACHE_MASK_DROM0); + REG_CLR_BIT(APP_CACHE_CTRL1_REG, DPORT_APP_CACHE_MASK_DROM0); + + bootloader_main(); +} + +/** + * @function : get_bin_len + * @description: get bin's length + * + * @inputs: pos bin locate address in flash + * @return: uint32 length of bin,if bin MAGIC error return 0 + */ + +uint32_t get_bin_len(uint32_t pos) +{ + uint32_t len = 8 + 16; + uint8_t i; + log_debug("pos %d %x\n",pos,*(uint8_t *)pos); + if(0xE9 != *(uint8_t *)pos) { + return 0; + } + for (i = 0; i < *(uint8_t *)(pos + 1); i++) { + len += *(uint32_t *)(pos + len + 4) + 8; + } + if (len % 16 != 0) { + len = (len / 16 + 1) * 16; + } else { + len += 16; + } + log_debug("bin length = %d\n", len); + return len; +} + +/** + * @function : boot_cache_redirect + * @description: Configure several pages in flash map so that `size` bytes + * starting at `pos` are mapped to 0x3f400000. + * This sets up mapping only for PRO CPU. + * + * @inputs: pos address in flash + * size size of the area to map, in bytes + */ +void boot_cache_redirect( uint32_t pos, size_t size ) +{ + uint32_t pos_aligned = pos & 0xffff0000; + uint32_t count = (size + 0xffff) / 0x10000; + Cache_Read_Disable( 0 ); + Cache_Flush( 0 ); + log_debug( "mmu set paddr=%08x count=%d", pos_aligned, count ); + cache_flash_mmu_set( 0, 0, 0x3f400000, pos_aligned, 64, count ); + Cache_Read_Enable( 0 ); +} + +/** + * @function : load_partition_table + * @description: Parse partition table, get useful data such as location of + * OTA info sector, factory app sector, and test app sector. + * + * @inputs: bs bootloader state structure used to save the data + * addr address of partition table in flash + * @return: return true, if the partition table is loaded (and MD5 checksum is valid) + * + */ +bool load_partition_table(bootloader_state_t* bs, uint32_t addr) +{ + partition_info_t partition; + uint32_t end = addr + 0x1000; + int index = 0; + char *partition_usage; + + log_info("Partition Table:"); + log_info("## Label Usage Type ST Offset Length"); + + while (addr < end) { + log_debug("load partition table entry from %x(%08x)", addr, MEM_CACHE(addr)); + memcpy(&partition, MEM_CACHE(addr), sizeof(partition)); + log_debug("type=%x subtype=%x", partition.type, partition.subtype); + partition_usage = "unknown"; + + if (partition.magic == PARTITION_MAGIC) { /* valid partition definition */ + switch(partition.type) { + case PART_TYPE_APP: /* app partition */ + switch(partition.subtype) { + case PART_SUBTYPE_FACTORY: /* factory binary */ + bs->factory = partition.pos; + partition_usage = "factory app"; + break; + case PART_SUBTYPE_TEST: /* test binary */ + bs->test = partition.pos; + partition_usage = "test app"; + break; + default: + /* OTA binary */ + if ((partition.subtype & ~PART_SUBTYPE_OTA_MASK) == PART_SUBTYPE_OTA_FLAG) { + bs->ota[partition.subtype & PART_SUBTYPE_OTA_MASK] = partition.pos; + ++bs->app_count; + partition_usage = "OTA app"; + } + else { + partition_usage = "Unknown app"; + } + break; + } + break; /* PART_TYPE_APP */ + case PART_TYPE_DATA: /* data partition */ + switch(partition.subtype) { + case PART_SUBTYPE_DATA_OTA: /* ota data */ + bs->ota_info = partition.pos; + partition_usage = "OTA data"; + break; + case PART_SUBTYPE_DATA_RF: + partition_usage = "RF data"; + break; + case PART_SUBTYPE_DATA_WIFI: + partition_usage = "WiFi data"; + break; + default: + partition_usage = "Unknown data"; + break; + } + break; /* PARTITION_USAGE_DATA */ + default: /* other partition type */ + break; + } + } + /* invalid partition magic number */ + else { + break; /* todo: validate md5 */ + } + + /* print partition type info */ + log_info("%2d %-16s %-16s %02x %02x %08x %08x", index, partition.label, partition_usage, + partition.type, partition.subtype, + partition.pos.offset, partition.pos.size); + index++; + addr += sizeof(partition); + } + + log_info("End of partition table"); + return true; +} + +static uint32_t ota_select_crc(const ota_select *s) +{ + return crc32_le(UINT32_MAX, (uint8_t*)&s->ota_seq, 4); +} + +static bool ota_select_valid(const ota_select *s) +{ + return s->ota_seq != UINT32_MAX && s->crc == ota_select_crc(s); +} + +/** + * @function : bootloader_main + * @description: entry function of 2nd bootloader + * + * @inputs: void + */ + +void bootloader_main() +{ + //Run start routine. + /*ESP32 2ND bootload start here*/ + + + log_info( "\n" ); + log_info( "**************************************" ); + log_info( "* hello espressif ESP32! *" ); + log_info( "* 2nd boot is running! *" ); + log_info( "* version (%s) *", BOOT_VERSION); + log_info( "**************************************"); + + struct flash_hdr fhdr; + bootloader_state_t bs; + SpiFlashOpResult spiRet1,spiRet2; + ota_select sa,sb; + memset(&bs, 0, sizeof(bs)); + + log_notice( "compile time %s\n", __TIME__ ); + /* close watch dog here */ + REG_CLR_BIT( RTC_WDTCONFIG0, RTC_CNTL_WDT_FLASHBOOT_MOD_EN ); + REG_CLR_BIT( WDTCONFIG0, TIMERS_WDT_FLASHBOOT_MOD_EN ); + SPIUnlock(); + /*register first sector in drom0 page 0 */ + boot_cache_redirect( 0, 0x5000 ); + + memcpy((unsigned int *) &fhdr, MEM_CACHE(0x1000), sizeof(struct flash_hdr) ); + + print_flash_info(&fhdr); + + if (!load_partition_table(&bs, PARTITION_ADD)) { + log_error("load partition table error!"); + return; + } + + partition_pos_t load_part_pos; + + if (bs.ota_info.offset != 0) { // check if partition table has OTA info partition + //log_error("OTA info sector handling is not implemented"); + boot_cache_redirect(bs.ota_info.offset, bs.ota_info.size ); + memcpy(&sa,MEM_CACHE(bs.ota_info.offset & 0x0000ffff),sizeof(sa)); + memcpy(&sb,MEM_CACHE((bs.ota_info.offset + 0x1000)&0x0000ffff) ,sizeof(sb)); + if(sa.ota_seq == 0xFFFFFFFF && sb.ota_seq == 0xFFFFFFFF) { + // init status flash + load_part_pos = bs.ota[0]; + sa.ota_seq = 0x01; + sa.crc = ota_select_crc(&sa); + sb.ota_seq = 0x00; + sb.crc = ota_select_crc(&sb); + + Cache_Read_Disable(0); + spiRet1 = SPIEraseSector(bs.ota_info.offset/0x1000); + spiRet2 = SPIEraseSector(bs.ota_info.offset/0x1000+1); + if (spiRet1 != SPI_FLASH_RESULT_OK || spiRet2 != SPI_FLASH_RESULT_OK ) { + log_error(SPI_ERROR_LOG); + return; + } + spiRet1 = SPIWrite(bs.ota_info.offset,(uint32_t *)&sa,sizeof(ota_select)); + spiRet2 = SPIWrite(bs.ota_info.offset + 0x1000,(uint32_t *)&sb,sizeof(ota_select)); + if (spiRet1 != SPI_FLASH_RESULT_OK || spiRet2 != SPI_FLASH_RESULT_OK ) { + log_error(SPI_ERROR_LOG); + return; + } + Cache_Read_Enable(0); + //TODO:write data in ota info + } else { + if(ota_select_valid(&sa) && ota_select_valid(&sb)) { + load_part_pos = bs.ota[(((sa.ota_seq > sb.ota_seq)?sa.ota_seq:sb.ota_seq) - 1)%bs.app_count]; + }else if(ota_select_valid(&sa)) { + load_part_pos = bs.ota[(sa.ota_seq - 1) % bs.app_count]; + }else if(ota_select_valid(&sb)) { + load_part_pos = bs.ota[(sb.ota_seq - 1) % bs.app_count]; + }else { + log_error("ota data partition info error"); + return; + } + } + } else if (bs.factory.offset != 0) { // otherwise, look for factory app partition + load_part_pos = bs.factory; + } else if (bs.test.offset != 0) { // otherwise, look for test app parition + load_part_pos = bs.test; + } else { // nothing to load, bail out + log_error("nothing to load"); + return; + } + + log_info("Loading app partition at offset %08x", load_part_pos); + if(fhdr.secury_boot_flag == 0x01) { + /* protect the 2nd_boot */ + if(false == secure_boot()){ + log_error("secure boot failed"); + return; + } + } + + if(fhdr.encrypt_flag == 0x01) { + /* encrypt flash */ + if (false == flash_encrypt(&bs)) { + log_error("flash encrypt failed"); + return; + } + } + + // copy sections to RAM, set up caches, and start application + unpack_load_app(&load_part_pos); +} + + +void unpack_load_app(const partition_pos_t* partition) +{ + boot_cache_redirect(partition->offset, partition->size); + + uint32_t pos = 0; + struct flash_hdr image_header; + memcpy(&image_header, MEM_CACHE(pos), sizeof(image_header)); + pos += sizeof(image_header); + + uint32_t drom_addr = 0; + uint32_t drom_load_addr = 0; + uint32_t drom_size = 0; + uint32_t irom_addr = 0; + uint32_t irom_load_addr = 0; + uint32_t irom_size = 0; + + log_debug("bin_header: %u %u %u %u %08x\n", image_header.magic, + image_header.blocks, + image_header.spi_mode, + image_header.spi_size, + (unsigned)image_header.entry_addr); + + for (uint32_t section_index = 0; + section_index < image_header.blocks; + ++section_index) { + struct block_hdr section_header = {0}; + memcpy(§ion_header, MEM_CACHE(pos), sizeof(section_header)); + pos += sizeof(section_header); + + const uint32_t address = section_header.load_addr; + bool load = true; + bool map = false; + if (address == 0x00000000) { // padding, ignore block + load = false; + } + if (address == 0x00000004) { + load = false; // md5 checksum block + // TODO: actually check md5 + } + + if (address >= DROM_LOW && address < DROM_HIGH) { + log_debug("found drom section, map from %08x to %08x\n", pos, + section_header.load_addr); + drom_addr = partition->offset + pos - sizeof(section_header); + drom_load_addr = section_header.load_addr; + drom_size = section_header.data_len + sizeof(section_header); + load = false; + map = true; + } + + if (address >= IROM_LOW && address < IROM_HIGH) { + log_debug("found irom section, map from %08x to %08x\n", pos, + section_header.load_addr); + irom_addr = partition->offset + pos - sizeof(section_header); + irom_load_addr = section_header.load_addr; + irom_size = section_header.data_len + sizeof(section_header); + load = false; + map = true; + } + + log_notice("section %d: paddr=0x%08x vaddr=0x%08x size=0x%05x (%6d) %s", section_index, pos, section_header.load_addr, section_header.data_len, section_header.data_len, (load)?"load":(map)?"map":""); + + if (!load) { + pos += section_header.data_len; + continue; + } + + memcpy((void*) section_header.load_addr, MEM_CACHE(pos), section_header.data_len); + pos += section_header.data_len; + } + + set_cache_and_start_app(drom_addr, + drom_load_addr, + drom_size, + irom_addr, + irom_load_addr, + irom_size, + image_header.entry_addr); +} + +void IRAM_ATTR set_cache_and_start_app( + uint32_t drom_addr, + uint32_t drom_load_addr, + uint32_t drom_size, + uint32_t irom_addr, + uint32_t irom_load_addr, + uint32_t irom_size, + uint32_t entry_addr) +{ + log_debug("configure drom and irom and start\n"); + Cache_Read_Disable( 0 ); + Cache_Read_Disable( 1 ); + Cache_Flush( 0 ); + Cache_Flush( 1 ); + uint32_t drom_page_count = (drom_size + 64*1024 - 1) / (64*1024); // round up to 64k + log_debug( "d mmu set paddr=%08x vaddr=%08x size=%d n=%d \n", drom_addr & 0xffff0000, drom_load_addr & 0xffff0000, drom_size, drom_page_count ); + int rc = cache_flash_mmu_set( 0, 0, drom_load_addr & 0xffff0000, drom_addr & 0xffff0000, 64, drom_page_count ); + log_debug( "rc=%d", rc ); + rc = cache_flash_mmu_set( 1, 0, drom_load_addr & 0xffff0000, drom_addr & 0xffff0000, 64, drom_page_count ); + log_debug( "rc=%d", rc ); + uint32_t irom_page_count = (irom_size + 64*1024 - 1) / (64*1024); // round up to 64k + log_debug( "i mmu set paddr=%08x vaddr=%08x size=%d n=%d\n", irom_addr & 0xffff0000, irom_load_addr & 0xffff0000, irom_size, irom_page_count ); + rc = cache_flash_mmu_set( 0, 0, irom_load_addr & 0xffff0000, irom_addr & 0xffff0000, 64, irom_page_count ); + log_debug( "rc=%d", rc ); + rc = cache_flash_mmu_set( 1, 0, irom_load_addr & 0xffff0000, irom_addr & 0xffff0000, 64, irom_page_count ); + log_debug( "rc=%d", rc ); + REG_CLR_BIT( PRO_CACHE_CTRL1_REG, (DPORT_PRO_CACHE_MASK_IRAM0) | (DPORT_PRO_CACHE_MASK_IRAM1 & 0) | (DPORT_PRO_CACHE_MASK_IROM0 & 0) | DPORT_PRO_CACHE_MASK_DROM0 | DPORT_PRO_CACHE_MASK_DRAM1 ); + REG_CLR_BIT( APP_CACHE_CTRL1_REG, (DPORT_APP_CACHE_MASK_IRAM0) | (DPORT_APP_CACHE_MASK_IRAM1 & 0) | (DPORT_APP_CACHE_MASK_IROM0 & 0) | DPORT_APP_CACHE_MASK_DROM0 | DPORT_APP_CACHE_MASK_DRAM1 ); + Cache_Read_Enable( 0 ); + Cache_Read_Enable( 1 ); + + log_notice("start: 0x%08x\n", entry_addr); + typedef void (*entry_t)(void); + entry_t entry = ((entry_t) entry_addr); + + // TODO: we have used quite a bit of stack at this point. + // use "movsp" instruction to reset stack back to where ROM stack starts. + (*entry)(); +} + + +void print_flash_info(struct flash_hdr* pfhdr) +{ +#if (BOOT_LOG_LEVEL >= BOOT_LOG_LEVEL_NOTICE) + + struct flash_hdr fhdr = *pfhdr; + + log_debug( "[D]: magic %02x\n", fhdr.magic ); + log_debug( "[D]: blocks %02x\n", fhdr.blocks ); + log_debug( "[D]: spi_mode %02x\n", fhdr.spi_mode ); + log_debug( "[D]: spi_speed %02x\n", fhdr.spi_speed ); + log_debug( "[D]: spi_size %02x\n", fhdr.spi_size ); + + const char* str; + switch ( fhdr.spi_speed ) { + case SPI_SPEED_40M: + str = "40MHz"; + break; + + case SPI_SPEED_26M: + str = "26.7MHz"; + break; + + case SPI_SPEED_20M: + str = "20MHz"; + break; + + case SPI_SPEED_80M: + str = "80MHz"; + break; + + default: + str = "20MHz"; + break; + } + log_notice( " SPI Speed : %s", str ); + + + + switch ( fhdr.spi_mode ) { + case SPI_MODE_QIO: + str = "QIO"; + break; + + case SPI_MODE_QOUT: + str = "QOUT"; + break; + + case SPI_MODE_DIO: + str = "DIO"; + break; + + case SPI_MODE_DOUT: + str = "DOUT"; + break; + + case SPI_MODE_FAST_READ: + str = "FAST READ"; + break; + + case SPI_MODE_SLOW_READ: + str = "SLOW READ"; + break; + default: + str = "DIO"; + break; + } + log_notice( " SPI Mode : %s", str ); + + + + switch ( fhdr.spi_size ) { + case SPI_SIZE_1MB: + str = "1MB"; + break; + + case SPI_SIZE_2MB: + str = "2MB"; + break; + + case SPI_SIZE_4MB: + str = "4MB"; + break; + + case SPI_SIZE_8MB: + str = "8MB"; + break; + + case SPI_SIZE_16MB: + str = "16MB"; + break; + + default: + str = "1MB"; + break; + } + log_notice( " SPI Flash Size : %s", str ); +#endif +} diff --git a/components/bootloader/src/main/eagle.bootloader.ld b/components/bootloader/src/main/eagle.bootloader.ld new file mode 100644 index 0000000000..af97bda3ad --- /dev/null +++ b/components/bootloader/src/main/eagle.bootloader.ld @@ -0,0 +1,148 @@ +/* +Linker file used to link the bootloader. + +*WARNING* For now this linker dumps everything into IRAM/DRAM. ToDo: move +some/most stuff to DROM/IROM. + +*/ + + +/* THESE ARE THE VIRTUAL RUNTIME ADDRESSES */ +/* The load addresses are defined later using the AT statements. */ +MEMORY +{ + /* All these values assume the flash cache is on, and have the blocks this uses subtracted from the length + of the various regions. The 'data access port' dram/drom regions map to the same iram/irom regions but + are connected to the data port of the CPU and eg allow bytewise access. */ + dport0_seg (RW) : org = 0x3FF00000, len = 0x10 /* IO */ + iram_seg (RWX) : org = 0x40098000, len = 0x1000 + iram_pool_1_seg (RWX) : org = 0x40078000, len = 0x8000 /* IRAM POOL1, used for APP CPU cache. We can abuse it in bootloader because APP CPU is still held in reset, until we enable APP CPU cache */ + dram_seg (RW) : org = 0x3FFC0000, len = 0x20000 /* Shared RAM, minus rom bss/data/stack.*/ +} + +/* Default entry point: */ +ENTRY(call_start_cpu0); + + +SECTIONS +{ + .iram1.text : + { + _init_start = ABSOLUTE(.); + *(.UserEnter.literal); + *(.UserEnter.text); + . = ALIGN (16); + *(.entry.text) + *(.init.literal) + *(.init) + _init_end = ABSOLUTE(.); + + /* Code marked as runnning out of IRAM */ + _iram_text_start = ABSOLUTE(.); + *(.iram1 .iram1.*) + _iram_text_end = ABSOLUTE(.); + } > iram_seg + + + /* Shared RAM */ + .dram0.bss (NOLOAD) : + { + . = ALIGN (8); + _bss_start = ABSOLUTE(.); + *(.dynsbss) + *(.sbss) + *(.sbss.*) + *(.gnu.linkonce.sb.*) + *(.scommon) + *(.sbss2) + *(.sbss2.*) + *(.gnu.linkonce.sb2.*) + *(.dynbss) + KEEP(*(.bss)) + *(.bss.*) + *(.gnu.linkonce.b.*) + *(COMMON) + . = ALIGN (8); + _bss_end = ABSOLUTE(.); + } >dram_seg + + + .dram0.data : + { + _data_start = ABSOLUTE(.); + KEEP(*(.data)) + KEEP(*(.data.*)) + KEEP(*(.gnu.linkonce.d.*)) + KEEP(*(.data1)) + KEEP(*(.sdata)) + KEEP(*(.sdata.*)) + KEEP(*(.gnu.linkonce.s.*)) + KEEP(*(.sdata2)) + KEEP(*(.sdata2.*)) + KEEP(*(.gnu.linkonce.s2.*)) + KEEP(*(.jcr)) + _data_end = ABSOLUTE(.); + } >dram_seg + + + + + .dram0.rodata : + { + _rodata_start = ABSOLUTE(.); + *(.rodata) + *(.rodata.*) + *(.irom1.text) /* catch stray ICACHE_RODATA_ATTR */ + *(.gnu.linkonce.r.*) + *(.rodata1) + __XT_EXCEPTION_TABLE_ = ABSOLUTE(.); + *(.xt_except_table) + *(.gcc_except_table) + *(.gnu.linkonce.e.*) + *(.gnu.version_r) + *(.eh_frame) + . = (. + 3) & ~ 3; + /* C++ constructor and destructor tables, properly ordered: */ + __init_array_start = ABSOLUTE(.); + KEEP (*crtbegin.o(.ctors)) + KEEP (*(EXCLUDE_FILE (*crtend.o) .ctors)) + KEEP (*(SORT(.ctors.*))) + KEEP (*(.ctors)) + __init_array_end = ABSOLUTE(.); + KEEP (*crtbegin.o(.dtors)) + KEEP (*(EXCLUDE_FILE (*crtend.o) .dtors)) + KEEP (*(SORT(.dtors.*))) + KEEP (*(.dtors)) + /* C++ exception handlers table: */ + __XT_EXCEPTION_DESCS_ = ABSOLUTE(.); + *(.xt_except_desc) + *(.gnu.linkonce.h.*) + __XT_EXCEPTION_DESCS_END__ = ABSOLUTE(.); + *(.xt_except_desc_end) + *(.dynamic) + *(.gnu.version_d) + _rodata_end = ABSOLUTE(.); + /* Literals are also RO data. */ + _lit4_start = ABSOLUTE(.); + *(*.lit4) + *(.lit4.*) + *(.gnu.linkonce.lit4.*) + _lit4_end = ABSOLUTE(.); + . = ALIGN(4); + _heap_start = ABSOLUTE(.); + } >dram_seg + + .iram_pool_1.text : + { + _stext = .; + _text_start = ABSOLUTE(.); + *(.literal .text .literal.* .text.* .stub .gnu.warning .gnu.linkonce.literal.* .gnu.linkonce.t.*.literal .gnu.linkonce.t.*) + *(.irom0.text) /* catch stray ICACHE_RODATA_ATTR */ + *(.fini.literal) + *(.fini) + *(.gnu.version) + _text_end = ABSOLUTE(.); + _etext = .; + } >iram_pool_1_seg + +} diff --git a/components/bootloader/src/main/flash_encrypt.c b/components/bootloader/src/main/flash_encrypt.c new file mode 100644 index 0000000000..d5f105f9cc --- /dev/null +++ b/components/bootloader/src/main/flash_encrypt.c @@ -0,0 +1,190 @@ +// Copyright 2015-2016 Espressif Systems (Shanghai) PTE LTD +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at + +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include + +#include "esp_types.h" +#include "esp_attr.h" + +#include "rom/cache.h" +#include "rom/ets_sys.h" +#include "rom/spi_flash.h" + +#include "soc/dport_reg.h" +#include "soc/io_mux_reg.h" +#include "soc/efuse_reg.h" +#include "soc/rtc_cntl_reg.h" + +#include "sdkconfig.h" + +#include "bootloader_log.h" +#include "bootloader_config.h" + +/** + * @function : bitcount + * @description: caculate bit 1 in flash_crypt_cnt + * if it's even number ,need encrypt flash data,and burn efuse + * + * @inputs: n flash_crypt_cnt + * @return: number of 1 in flash_crypt_cnt + * + */ +int bitcount(int n){ + int count = 0; + while (n > 0) { + count += n & 1; + n >>= 1; + } + return count; + +} +/** + * @function : flash_encrypt_write + * @description: write encrypted data in flash + * + * @inputs: pos address in flash + * len size of data need encrypt + * @return: return true, if the write flash success + * + */ +bool flash_encrypt_write(uint32_t pos, uint32_t len) +{ + SpiFlashOpResult spiRet; + uint32_t buf[1024]; + int i = 0; + Cache_Read_Disable(0); + for (i = 0;i<((len-1)/0x1000 + 1);i++) { + spiRet = SPIRead(pos, buf, SPI_SEC_SIZE); + if (spiRet != SPI_FLASH_RESULT_OK) { + Cache_Read_Enable(0); + log_error(SPI_ERROR_LOG); + return false; + } + spiRet = SPIEraseSector(pos/SPI_SEC_SIZE); + if (spiRet != SPI_FLASH_RESULT_OK) { + Cache_Read_Enable(0); + log_error(SPI_ERROR_LOG); + return false; + } + spiRet = SPI_Encrypt_Write(pos, buf, SPI_SEC_SIZE); + if (spiRet != SPI_FLASH_RESULT_OK) { + Cache_Read_Enable(0); + log_error(SPI_ERROR_LOG); + return false; + } + pos += SPI_SEC_SIZE; + } + Cache_Read_Enable(0); + return true; +} +/** + * @function : flash_encrypt + * @description: encrypt 2nd boot ,partition table ,factory bin ��test bin (if use)��ota bin + * ��OTA info sector. + * + * @inputs: bs bootloader state structure used to save the data + * + * @return: return true, if the encrypt flash success + * + */ +bool flash_encrypt(bootloader_state_t *bs) +{ + uint32_t bin_len = 0; + uint32_t flash_crypt_cnt = REG_GET_FIELD(EFUSE_BLK0_RDATA0, EFUSE_FLASH_CRYPT_CNT); + uint8_t count = bitcount(flash_crypt_cnt); + int i = 0; + log_debug("flash crypt cnt %x, count %d\n", flash_crypt_cnt, count); + + if ((count % 2) == 0) { + boot_cache_redirect( 0, 64*1024); + /* encrypt iv and abstruct */ + if (false == flash_encrypt_write(0,SPI_SEC_SIZE)) { + log_error("encrypt iv and abstruct error"); + return false; + } + + /* encrypt write boot bin*/ + bin_len = get_bin_len((uint32_t)MEM_CACHE(0x1000)); + if(bin_len != 0) { + if (false == flash_encrypt_write(0x1000,bin_len)) { + log_error("encrypt 2nd boot error"); + return false; + } + } else { + log_error("2nd boot len error"); + return false; + } + /* encrypt partition table */ + if (false == flash_encrypt_write(PARTITION_ADD,SPI_SEC_SIZE)) { + log_error("encrypt partition table error"); + return false; + } + + /* encrypt write factory bin */ + if(bs->factory.offset != 0x00) { + log_debug("have factory bin\n"); + boot_cache_redirect(bs->factory.offset,bs->factory.size); + bin_len = get_bin_len((uint32_t)MEM_CACHE(bs->factory.offset&0xffff)); + if(bin_len != 0) { + if (false == flash_encrypt_write(bs->factory.offset,bin_len)) { + log_error("encrypt factory bin error"); + return false; + } + } + } + /* encrypt write test bin */ + if(bs->test.offset != 0x00) { + ets_printf("have test bin\n"); + boot_cache_redirect(bs->test.offset,bs->test.size); + bin_len = get_bin_len((uint32_t)MEM_CACHE(bs->test.offset&0xffff)); + if(bin_len != 0) { + if (false == flash_encrypt_write(bs->test.offset,bin_len)) { + log_error("encrypt test bin error"); + return false; + } + } + } + /* encrypt write ota bin */ + for (i = 0;i<16;i++) { + if(bs->ota[i].offset != 0x00) { + log_debug("have ota[%d] bin\n",i); + boot_cache_redirect(bs->ota[i].offset,bs->ota[i].size); + bin_len = get_bin_len((uint32_t)MEM_CACHE(bs->ota[i].offset&0xffff)); + if(bin_len != 0) { + if (false == flash_encrypt_write(bs->ota[i].offset,bin_len)) { + log_error("encrypt ota bin error"); + return false; + } + } + } + } + /* encrypt write ota info bin */ + if (false == flash_encrypt_write(bs->ota_info.offset,2*SPI_SEC_SIZE)) { + log_error("encrypt ota binfo error"); + return false; + } + REG_SET_FIELD(EFUSE_BLK0_WDATA0, EFUSE_FLASH_CRYPT_CNT, 0x04); + REG_WRITE(EFUSE_CONF, 0x5A5A); /* efuse_pgm_op_ena, force no rd/wr disable */ + REG_WRITE(EFUSE_CMD, 0x02); /* efuse_pgm_cmd */ + while (REG_READ(EFUSE_CMD)); /* wait for efuse_pagm_cmd=0 */ + log_warn("burn flash_crypt_cnt\n"); + REG_WRITE(EFUSE_CONF, 0x5AA5); /* efuse_read_op_ena, release force */ + REG_WRITE(EFUSE_CMD, 0x01); /* efuse_read_cmd */ + while (REG_READ(EFUSE_CMD)); /* wait for efuse_read_cmd=0 */ + return true; + } else { + log_info("flash already encrypted.\n"); + return true; + } +} diff --git a/components/bootloader/src/main/secure_boot.c b/components/bootloader/src/main/secure_boot.c new file mode 100644 index 0000000000..97ddd1a8de --- /dev/null +++ b/components/bootloader/src/main/secure_boot.c @@ -0,0 +1,125 @@ +// Copyright 2015-2016 Espressif Systems (Shanghai) PTE LTD +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at + +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include + +#include "esp_attr.h" +#include "esp_types.h" + +#include "rom/cache.h" +#include "rom/ets_sys.h" +#include "rom/spi_flash.h" +#include "rom/secure_boot.h" + +#include "soc/dport_reg.h" +#include "soc/io_mux_reg.h" +#include "soc/efuse_reg.h" +#include "soc/rtc_cntl_reg.h" + +#include "sdkconfig.h" + +#include "bootloader_log.h" +#include "bootloader_config.h" + +/** + * @function : secure_boot_generate + * @description: generate boot abstruct & iv + * + * @inputs: bool + */ +bool secure_boot_generate(uint32_t bin_len){ + SpiFlashOpResult spiRet; + uint16_t i; + uint32_t buf[32]; + if (bin_len % 128 != 0) { + bin_len = (bin_len / 128 + 1) * 128; + } + ets_secure_boot_start(); + ets_secure_boot_rd_iv(buf); + ets_secure_boot_hash(NULL); + Cache_Read_Disable(0); + /* iv stored in sec 0 */ + spiRet = SPIEraseSector(0); + if (spiRet != SPI_FLASH_RESULT_OK) + { + log_error(SPI_ERROR_LOG); + return false; + } + /* write iv to flash, 0x0000, 128 bytes (1024 bits) */ + spiRet = SPIWrite(0, buf, 128); + if (spiRet != SPI_FLASH_RESULT_OK) + { + log_error(SPI_ERROR_LOG); + return false; + } + log_debug("write iv to flash.\n"); + Cache_Read_Enable(0); + /* read 4K code image from flash, for test */ + for (i = 0; i < bin_len; i+=128) { + ets_secure_boot_hash((uint32_t *)(0x3f400000 + 0x1000 + i)); + } + + ets_secure_boot_obtain(); + ets_secure_boot_rd_abstract(buf); + ets_secure_boot_finish(); + Cache_Read_Disable(0); + /* write abstract to flash, 0x0080, 64 bytes (512 bits) */ + spiRet = SPIWrite(0x80, buf, 64); + if (spiRet != SPI_FLASH_RESULT_OK) { + log_error(SPI_ERROR_LOG); + return false; + } + log_debug("write abstract to flash.\n"); + Cache_Read_Enable(0); + return true; +} + + +/** + * @function : secure_boot + * @description: protect boot code inflash + * + * @inputs: bool + */ +bool secure_boot(void){ + uint32_t bin_len = 0; + if (REG_READ(EFUSE_BLK0_RDATA6) & EFUSE_RD_ABS_DONE_0) + { + log_info("already secure boot !\n"); + return true; + } else { + boot_cache_redirect( 0, 64*1024); + bin_len = get_bin_len((uint32_t)MEM_CACHE(0x1000)); + if (bin_len == 0) { + log_error("boot len is error"); + return false; + } + if (false == secure_boot_generate(bin_len)){ + log_error("secure boot generate failed"); + return false; + } + } + + REG_SET_BIT(EFUSE_BLK0_WDATA6, EFUSE_RD_ABS_DONE_0); + REG_WRITE(EFUSE_CONF, 0x5A5A); /* efuse_pgm_op_ena, force no rd/wr disable */ + REG_WRITE(EFUSE_CMD, 0x02); /* efuse_pgm_cmd */ + while (REG_READ(EFUSE_CMD)); /* wait for efuse_pagm_cmd=0 */ + log_warn("burn abstract_done_0\n"); + REG_WRITE(EFUSE_CONF, 0x5AA5); /* efuse_read_op_ena, release force */ + REG_WRITE(EFUSE_CMD, 0x01); /* efuse_read_cmd */ + while (REG_READ(EFUSE_CMD)); /* wait for efuse_read_cmd=0 */ + log_debug("read EFUSE_BLK0_RDATA6 %x\n", REG_READ(EFUSE_BLK0_RDATA6)); + return true; + +} diff --git a/components/bt/Kconfig b/components/bt/Kconfig new file mode 100644 index 0000000000..90ef1f3eb6 --- /dev/null +++ b/components/bt/Kconfig @@ -0,0 +1,23 @@ +menu "BT config" +visible if MEMMAP_BT + + +config BT_ENABLED + bool "Enable low-level BT stack" + depends on MEMMAP_BT + help + This compiles in the low-level BT stack. + +config BT_BTLE + bool "Enable BTLE" + depends on BT_ENABLED + help + This compiles BTLE support + +config BT_BT + bool "Enable classic BT" + depends on BT_ENABLED + help + This enables classic BT support + +endmenu diff --git a/components/esp32/Kconfig b/components/esp32/Kconfig new file mode 100644 index 0000000000..b257806843 --- /dev/null +++ b/components/esp32/Kconfig @@ -0,0 +1,39 @@ +menu "WiFi config" + +config WIFI_ENABLED + bool "Enable low-level WiFi stack" + default "y" + help + This compiles in the low-level WiFi stack. + +config WIFI_AUTO_STARTUP + bool "Start WiFi with system startup" + default "y" + depends on WIFI_ENABLED + help + By default, WiFi is started with system startup, you can turn off this + feature and start by yourself. + +config WIFI_AUTO_CONNECT + bool "Enable auto connect" + default "y" + depends on WIFI_ENABLED + help + If station is enabled, and station config is set, this will enable WiFi + station auto connect when WiFi startup. + +config WIFI_ENENT_QUEUE_SIZE + int "WiFi event queue size" + default 32 + depends on WIFI_ENABLED + help + Config WiFi event queue size in different application. + +config WIFI_EVENT_TASK_STACK_SIZE + int "WiFi event task stack size" + default 2048 + depends on WIFI_ENABLED + help + Config WiFi event task stack size in different application. + +endmenu diff --git a/components/esp32/Makefile b/components/esp32/Makefile new file mode 100644 index 0000000000..db3772c35d --- /dev/null +++ b/components/esp32/Makefile @@ -0,0 +1,20 @@ +# +# Component Makefile +# +# This Makefile should, at the very least, just include $(SDK_PATH)/make/component.mk. By default, +# this will take the sources in this directory, compile them and link them into +# lib(subdirectory_name).a in the build directory. This behaviour is entirely configurable, +# please read the SDK documents if you need to do this. +# + +LIBS := crypto core net80211 phy rtc pp wpa wps + +COMPONENT_ADD_LDFLAGS := -lesp32 \ + $(abspath libhal.a) \ + -L$(abspath lib) \ + $(addprefix -l,$(LIBS)) \ + -L $(abspath ld) \ + -T eagle.fpga32.v7.ld \ + -T eagle.fpga32.rom.addr.v7.ld + +include $(SDK_PATH)/make/component.mk diff --git a/components/esp32/abi.cpp b/components/esp32/abi.cpp new file mode 100644 index 0000000000..c40dba85e0 --- /dev/null +++ b/components/esp32/abi.cpp @@ -0,0 +1,114 @@ +// Copyright 2015-2016 Espressif Systems (Shanghai) PTE LTD +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at + +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +#include +#include +#include +#include + +// using __cxxabiv1::__guard; + +void *operator new(size_t size) +{ + return malloc(size); +} + +void *operator new[](size_t size) +{ + return malloc(size); +} + +void operator delete(void * ptr) +{ + free(ptr); +} + +void operator delete[](void * ptr) +{ + free(ptr); +} + +extern "C" void __cxa_pure_virtual(void) __attribute__ ((__noreturn__)); +extern "C" void __cxa_deleted_virtual(void) __attribute__ ((__noreturn__)); + +void __cxa_pure_virtual(void) +{ + abort(); +} + +void __cxa_deleted_virtual(void) +{ + abort(); +} + +#if 0 +typedef struct { + uint8_t guard; + uint8_t ps; +} guard_t; + +extern "C" int __cxa_guard_acquire(__guard* pg) +{ + uint8_t ps = xt_rsil(15); + if (reinterpret_cast(pg)->guard) { + xt_wsr_ps(ps); + return 0; + } + reinterpret_cast(pg)->ps = ps; + return 1; +} + +extern "C" void __cxa_guard_release(__guard* pg) +{ + reinterpret_cast(pg)->guard = 1; + xt_wsr_ps(reinterpret_cast(pg)->ps); +} + +extern "C" void __cxa_guard_abort(__guard* pg) +{ + xt_wsr_ps(reinterpret_cast(pg)->ps); +} +#endif + +extern "C" void __cxa_throw_bad_array_new_length() +{ + abort(); +} + +namespace std +{ +void __throw_bad_function_call() +{ + abort(); +} + +void __throw_length_error(char const*) +{ + abort(); +} + +void __throw_bad_alloc() +{ + abort(); +} + +void __throw_logic_error(const char* str) +{ + abort(); +} + +void __throw_out_of_range(const char* str) +{ + abort(); +} +} diff --git a/components/esp32/cpu_start.c b/components/esp32/cpu_start.c new file mode 100644 index 0000000000..d6e8fdd5c5 --- /dev/null +++ b/components/esp32/cpu_start.c @@ -0,0 +1,259 @@ +// Copyright 2015-2016 Espressif Systems (Shanghai) PTE LTD +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at + +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +#include +#include + +#include "esp_attr.h" +#include "esp_err.h" + +#include "rom/ets_sys.h" + +#include "soc/dport_reg.h" +#include "soc/io_mux_reg.h" + +#include "freertos/FreeRTOS.h" +#include "freertos/task.h" +#include "freertos/semphr.h" +#include "freertos/queue.h" +#include "freertos/portmacro.h" + +#include "tcpip_adapter.h" + +#include "heap_alloc_caps.h" +#include "sdkconfig.h" +#include "esp_system.h" +#include "esp_spi_flash.h" +#include "nvs_flash.h" +#include "esp_event.h" + +static void IRAM_ATTR user_start_cpu0(void); +static void IRAM_ATTR call_user_start_cpu1(); +static void IRAM_ATTR user_start_cpu1(void); +void Cache_Read_Enable(); +extern void ets_setup_syscalls(void); + + +extern int __cpu1_entry_point; +extern int _bss_start; +extern int _bss_end; +extern int _init_start; +extern int _init_end; +extern int _iram_romjumptable_start; +extern int _iram_romjumptable_end; +extern int _iram_text_start; +extern int _iram_text_end; + +/* +We arrive here after the bootloader finished loading the program from flash. The hardware is mostly uninitialized, +flash cache is down and the app CPU is in reset. We do have a stack, so we can do the initialization in C. +*/ + +void Uart_Init(int no); +void uartAttach(); +void ets_set_appcpu_boot_addr(uint32_t ent); +int ets_getAppEntry(); + +void IRAM_ATTR call_user_start_cpu0() { + //Kill wdt + REG_CLR_BIT(0x3ff4808c, BIT(10)); //RTCCNTL+8C RTC_WDTCONFIG0 RTC_ + REG_CLR_BIT(0x6001f048, BIT(14)); //DR_REG_BB_BASE+48 + + //Move exception vectors to IRAM + asm volatile (\ + "wsr %0, vecbase\n" \ + ::"r"(&_init_start)); + + uartAttach(); + ets_install_uart_printf(); + + //Make page 0 access raise an exception + //Also some other unused pages so we can catch weirdness + //ToDo: this but nicer. + asm volatile (\ + "movi a4,0x00000000\n" \ + "movi a5,0xf\n" \ + "wdtlb a5,a4\n" \ + "witlb a5,a4\n" \ + "movi a4,0x80000000\n" \ + "wdtlb a5,a4\n" \ + "witlb a5,a4\n" \ + "movi a4,0xa0000000\n" \ + "wdtlb a5,a4\n" \ + "witlb a5,a4\n" \ + "movi a4,0xc0000000\n" \ + "wdtlb a5,a4\n" \ + "witlb a5,a4\n" \ + "movi a4,0xe0000000\n" \ + "wdtlb a5,a4\n" \ + "witlb a5,a4\n" \ + "movi a4,0x20000000\n" \ + "movi a5,0x0\n" \ + "wdtlb a5,a4\n" \ + "witlb a5,a4\n" \ + "movi a4,0x40000000\n" \ + "movi a5,0x2\n" \ + "wdtlb a5,a4\n" \ + "witlb a5,a4\n" \ + "isync\n" \ + :::"a4","a5"); + + memset(&_bss_start, 0, (&_bss_end - &_bss_start) * sizeof(_bss_start)); + + //Initialize heap allocator + heap_alloc_caps_init(); + + ets_printf("Pro cpu up.\n"); +#ifndef CONFIG_FREERTOS_UNICORE + ets_printf("Running app cpu, entry point is %p\n", call_user_start_cpu1); + ets_delay_us(60000); + + SET_PERI_REG_MASK(APPCPU_CTRL_REG_B, DPORT_APPCPU_CLKGATE_EN); + SET_PERI_REG_MASK(APPCPU_CTRL_REG_A, DPORT_APPCPU_RESETTING); + CLEAR_PERI_REG_MASK(APPCPU_CTRL_REG_A, DPORT_APPCPU_RESETTING); + + + for (int i=0; i<20; i++) ets_delay_us(40000); + ets_set_appcpu_boot_addr((uint32_t)call_user_start_cpu1); + + ets_delay_us(10000); + +// while (ets_getAppEntry()==(int)call_user_start_cpu1) ; + //Because of Reasons (tm), the pro cpu cannot use the SPI flash while the app cpu is booting. +// while(((READ_PERI_REG(RTC_STORE7))&BIT(31)) == 0) ; // check APP boot complete flag + ets_delay_us(50000); + ets_delay_us(50000); + ets_printf("\n\nBack to pro cpu.\n"); +#else + CLEAR_PERI_REG_MASK(APPCPU_CTRL_REG_B, DPORT_APPCPU_CLKGATE_EN); +#endif + user_start_cpu0(); +} + + +extern int xPortGetCoreID(); + +extern int _init_start; + +/* +We arrive here because the pro CPU pulled us from reset. IRAM is in place, cache is still disabled, we can execute C code. +*/ +void IRAM_ATTR call_user_start_cpu1() { + //We need to do this ASAP because otherwise the structure to catch the SYSCALL instruction, which + //we abuse to do ROM calls, won't work. + + asm volatile (\ + "wsr %0, vecbase\n" \ + ::"r"(&_init_start)); + + //Enable SPI flash +// PIN_FUNC_SELECT(PERIPHS_IO_MUX_SD_DATA3_U, FUNC_SD_DATA3_SPIWP); // swap PIN SDDATA3 from uart1 to spi, because cache need spi + + ets_printf("App cpu up\n"); + + //Make page 0 access raise an exception + //Also some other unused pages so we can catch weirdness + //ToDo: this but nicer. + asm volatile (\ + "movi a4,0x00000000\n" \ + "movi a5,0xf\n" \ + "wdtlb a5,a4\n" \ + "witlb a5,a4\n" \ + "movi a4,0x80000000\n" \ + "wdtlb a5,a4\n" \ + "witlb a5,a4\n" \ + "movi a4,0xa0000000\n" \ + "wdtlb a5,a4\n" \ + "witlb a5,a4\n" \ + "movi a4,0xc0000000\n" \ + "wdtlb a5,a4\n" \ + "witlb a5,a4\n" \ + "movi a4,0xe0000000\n" \ + "wdtlb a5,a4\n" \ + "witlb a5,a4\n" \ + "movi a4,0x20000000\n" \ + "movi a5,0x0\n" \ + "wdtlb a5,a4\n" \ + "witlb a5,a4\n" \ + "movi a4,0x40000000\n" \ + "movi a5,0x2\n" \ + "wdtlb a5,a4\n" \ + "witlb a5,a4\n" \ + "isync\n" \ + :::"a4","a5"); + + user_start_cpu1(); +} + + + +extern volatile int port_xSchedulerRunning; +extern int xPortStartScheduler(); + +void user_start_cpu1(void) { + ets_printf("App cpu is running!\n"); + //Wait for the freertos initialization is finished on CPU0 + while (port_xSchedulerRunning == 0) ; + ets_printf("Core0 started initializing FreeRTOS. Jumping to scheduler.\n"); + //Okay, start the scheduler! + xPortStartScheduler(); +} + +extern void (*__init_array_start)(void); +extern void (*__init_array_end)(void); + +extern esp_err_t app_main(); +static void do_global_ctors(void) { + void (**p)(void); + for(p = &__init_array_start; p != &__init_array_end; ++p) + (*p)(); +} + + +void user_start_cpu0(void) { + esp_err_t ret; + + ets_setup_syscalls(); + do_global_ctors(); + +#if 1 //workaround + for (uint8_t i = 5; i < 8; i++) { + ets_printf("erase sector %d\n", i); + spi_flash_erase_sector(i); + } +#endif + ets_printf("nvs_flash_init\n"); + ret = nvs_flash_init(5, 3); + if (ESP_OK != ret) { + ets_printf("nvs_flash_init fail, ret=%d\n", ret); + } + + system_init(); + + esp_event_init(NULL); + + // TODO: consider ethernet interface +#if CONFIG_WIFI_ENABLED + tcpip_adapter_init(); +#endif + +#if CONFIG_WIFI_ENABLED && CONFIG_WIFI_AUTO_STARTUP +#include "esp_wifi.h" + esp_wifi_startup(app_main); +#else + app_main(); +#endif + + vTaskStartScheduler(); +} + diff --git a/components/esp32/event.c b/components/esp32/event.c new file mode 100644 index 0000000000..1a920436b6 --- /dev/null +++ b/components/esp32/event.c @@ -0,0 +1,306 @@ +// Copyright 2015-2016 Espressif Systems (Shanghai) PTE LTD +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at + +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +#include +#include + +#include "esp_err.h" +#include "esp_wifi.h" +#include "esp_event.h" + +#include "freertos/FreeRTOS.h" +#include "freertos/task.h" +#include "freertos/queue.h" +#include "freertos/semphr.h" + +#include "tcpip_adapter.h" + +#define ESP32_WORKAROUND 1 + +#if CONFIG_WIFI_ENABLED + +#ifdef ESP32_WORKAROUND + +extern SemaphoreHandle_t stdio_mutex_tx; +#define os_printf(fmt, ...) do {\ + if (!stdio_mutex_tx) {\ + stdio_mutex_tx = xSemaphoreCreateMutex();\ + }\ +\ + xSemaphoreTake(stdio_mutex_tx, portMAX_DELAY);\ + ets_printf(fmt, ##__VA_ARGS__);\ + xSemaphoreGive(stdio_mutex_tx);\ +} while (0) + +#endif + +static xQueueHandle g_event_handler = NULL; +static system_event_cb_t g_event_handler_cb; + +#define WIFI_DEBUG os_printf +#define WIFI_API_CALL_CHECK(info, api_call, ret) \ +do{\ + esp_err_t __err = (api_call);\ + if ((ret) != __err) {\ + WIFI_DEBUG("%s %d %s ret=%d\n", __FUNCTION__, __LINE__, (info), __err);\ + return __err;\ + }\ +} while(0) + +typedef esp_err_t (*system_event_handle_fn_t)(system_event_t *e); +typedef struct { + system_event_id_t event_id; + system_event_handle_fn_t event_handle; +} system_event_handle_t; + + +static esp_err_t system_event_ap_start_handle_default(system_event_t *event); +static esp_err_t system_event_ap_stop_handle_default(system_event_t *event); +static esp_err_t system_event_sta_start_handle_default(system_event_t *event); +static esp_err_t system_event_sta_stop_handle_default(system_event_t *event); +static esp_err_t system_event_sta_connected_handle_default(system_event_t *event); +static esp_err_t system_event_sta_disconnected_handle_default(system_event_t *event); + +static system_event_handle_t g_system_event_handle_table[] = { + {SYSTEM_EVENT_WIFI_READY, NULL}, + {SYSTEM_EVENT_SCAN_DONE, NULL}, + {SYSTEM_EVENT_STA_START, system_event_sta_start_handle_default}, + {SYSTEM_EVENT_STA_STOP, system_event_sta_stop_handle_default}, + {SYSTEM_EVENT_STA_CONNECTED, system_event_sta_connected_handle_default}, + {SYSTEM_EVENT_STA_DISCONNECTED, system_event_sta_disconnected_handle_default}, + {SYSTEM_EVENT_STA_AUTHMODE_CHANGE, NULL}, + {SYSTEM_EVENT_AP_START, system_event_ap_start_handle_default}, + {SYSTEM_EVENT_AP_STOP, system_event_ap_stop_handle_default}, + {SYSTEM_EVENT_AP_STACONNECTED, NULL}, + {SYSTEM_EVENT_AP_STADISCONNECTED, NULL}, + {SYSTEM_EVENT_AP_PROBEREQRECVED, NULL}, + {SYSTEM_EVENT_MAX, NULL}, +}; + +esp_err_t system_event_ap_start_handle_default(system_event_t *event) +{ + struct ip_info ap_ip; + uint8_t ap_mac[6]; + + WIFI_API_CALL_CHECK("esp_wifi_reg_rxcb", esp_wifi_reg_rxcb(WIFI_IF_AP, (wifi_rxcb_t)tcpip_adapter_ap_input), ESP_OK); + WIFI_API_CALL_CHECK("esp_wifi_mac_get", esp_wifi_get_mac(WIFI_IF_AP, ap_mac), ESP_OK); + + tcpip_adapter_get_ip_info(TCPIP_ADAPTER_IF_AP, &ap_ip); + tcpip_adapter_start(TCPIP_ADAPTER_IF_AP, ap_mac, &ap_ip); + + return ESP_OK; +} + +esp_err_t system_event_ap_stop_handle_default(system_event_t *event) +{ + WIFI_API_CALL_CHECK("esp_wifi_reg_rxcb", esp_wifi_reg_rxcb(WIFI_IF_AP, NULL), ESP_OK); + + tcpip_adapter_stop(TCPIP_ADAPTER_IF_AP); + + return ESP_OK; +} + +esp_err_t system_event_sta_start_handle_default(system_event_t *event) +{ + struct ip_info sta_ip; + uint8_t sta_mac[6]; + + WIFI_API_CALL_CHECK("esp_wifi_mac_get", esp_wifi_get_mac(WIFI_IF_STA, sta_mac), ESP_OK); + tcpip_adapter_get_ip_info(TCPIP_ADAPTER_IF_STA, &sta_ip); + tcpip_adapter_start(TCPIP_ADAPTER_IF_STA, sta_mac, &sta_ip); + + return ESP_OK; +} + +esp_err_t system_event_sta_stop_handle_default(system_event_t *event) +{ + tcpip_adapter_stop(TCPIP_ADAPTER_IF_STA); + + return ESP_OK; +} + +esp_err_t system_event_sta_connected_handle_default(system_event_t *event) +{ + WIFI_API_CALL_CHECK("esp_wifi_reg_rxcb", esp_wifi_reg_rxcb(WIFI_IF_STA, (wifi_rxcb_t)tcpip_adapter_sta_input), ESP_OK); + + tcpip_adapter_up(TCPIP_ADAPTER_IF_STA); + tcpip_adapter_dhcpc_start(TCPIP_ADAPTER_IF_STA); + + return ESP_OK; +} + +esp_err_t system_event_sta_disconnected_handle_default(system_event_t *event) +{ + tcpip_adapter_down(TCPIP_ADAPTER_IF_STA); + WIFI_API_CALL_CHECK("esp_wifi_reg_rxcb", esp_wifi_reg_rxcb(WIFI_IF_STA, NULL), ESP_OK); + return ESP_OK; +} + +static esp_err_t esp_wifi_post_event_to_user(system_event_t *event) +{ + if (g_event_handler_cb) { + return (*g_event_handler_cb)(event); + } + + return ESP_OK; +} + +static esp_err_t esp_system_event_debug(system_event_t *event) +{ + system_event_sta_scan_done_t *scan_done; + system_event_sta_connected_t *connected; + system_event_sta_disconnected_t *disconnected; + system_event_sta_authmode_change_t *auth_change; + system_event_ap_staconnected_t *staconnected; + system_event_ap_stadisconnected_t *stadisconnected; + system_event_ap_probe_req_rx_t *ap_probereqrecved; + + if (event == NULL) { + os_printf("Error: event is null!\n"); + return ESP_FAIL; + } + + os_printf("received event: "); + switch (event->event_id) { + case SYSTEM_EVENT_WIFI_READY: + os_printf("SYSTEM_EVENT_WIFI_READY\n"); + break; + case SYSTEM_EVENT_SCAN_DONE: + scan_done = &event->event_info.scan_done; + os_printf("SYSTEM_EVENT_SCAN_DONE\nstatus:%d, number:%d\n", \ + scan_done->status, scan_done->number); + break; + case SYSTEM_EVENT_STA_START: + os_printf("SYSTEM_EVENT_STA_START\n"); + break; + case SYSTEM_EVENT_STA_STOP: + os_printf("SYSTEM_EVENT_STA_STOP\n"); + break; + case SYSTEM_EVENT_STA_CONNECTED: + connected = &event->event_info.connected; + os_printf("SYSTEM_EVENT_STA_CONNECTED\nssid:%s, ssid_len:%d, bssid:%02x:%02x:%02x:%02x:%02x:%02x, channel:%d\n", \ + connected->ssid, connected->ssid_len, connected->bssid[0], connected->bssid[0], connected->bssid[1], \ + connected->bssid[3], connected->bssid[4], connected->bssid[5], connected->channel); + break; + case SYSTEM_EVENT_STA_DISCONNECTED: + disconnected = &event->event_info.disconnected; + os_printf("SYSTEM_EVENT_STA_DISCONNECTED\nssid:%s, ssid_len:%d, bssid:%02x:%02x:%02x:%02x:%02x:%02x, reason:%d\n", \ + disconnected->ssid, disconnected->ssid_len, disconnected->bssid[0], disconnected->bssid[0], disconnected->bssid[1], \ + disconnected->bssid[3], disconnected->bssid[4], disconnected->bssid[5], disconnected->reason); + break; + case SYSTEM_EVENT_STA_AUTHMODE_CHANGE: + auth_change = &event->event_info.auth_change; + os_printf("SYSTEM_EVENT_STA_AUTHMODE_CHNAGE\nold_mode:%d, new_mode:%d\n", auth_change->old_mode, auth_change->new_mode); + break; + case SYSTEM_EVENT_AP_START: + os_printf("SYSTEM_EVENT_AP_START\n"); + break; + case SYSTEM_EVENT_AP_STOP: + os_printf("SYSTEM_EVENT_AP_STOP\n"); + break; + case SYSTEM_EVENT_AP_STACONNECTED: + staconnected = &event->event_info.sta_connected; + os_printf("SYSTEM_EVENT_AP_STACONNECTED\nmac:%02x:%02x:%02x:%02x:%02x:%02x, aid:%d\n", \ + staconnected->mac[0], staconnected->mac[0], staconnected->mac[1], \ + staconnected->mac[3], staconnected->mac[4], staconnected->mac[5], staconnected->aid); + break; + case SYSTEM_EVENT_AP_STADISCONNECTED: + stadisconnected = &event->event_info.sta_disconnected; + os_printf("SYSTEM_EVENT_AP_STADISCONNECTED\nmac:%02x:%02x:%02x:%02x:%02x:%02x, aid:%d\n", \ + stadisconnected->mac[0], stadisconnected->mac[0], stadisconnected->mac[1], \ + stadisconnected->mac[3], stadisconnected->mac[4], stadisconnected->mac[5], stadisconnected->aid); + break; + case SYSTEM_EVENT_AP_PROBEREQRECVED: + ap_probereqrecved = &event->event_info.ap_probereqrecved; + os_printf("SYSTEM_EVENT_AP_PROBEREQRECVED\nrssi:%d, mac:%02x:%02x:%02x:%02x:%02x:%02x\n", \ + ap_probereqrecved->rssi, ap_probereqrecved->mac[0], ap_probereqrecved->mac[0], ap_probereqrecved->mac[1], \ + ap_probereqrecved->mac[3], ap_probereqrecved->mac[4], ap_probereqrecved->mac[5]); + break; + default: + os_printf("Error: no such kind of event!\n"); + break; + } + + return ESP_OK; +} + +static esp_err_t esp_system_event_handler(system_event_t *event) +{ + if (event == NULL) { + os_printf("Error: event is null!\n"); + return ESP_FAIL; + } + + esp_system_event_debug(event); + if ((event->event_id < SYSTEM_EVENT_MAX) && (event->event_id == g_system_event_handle_table[event->event_id].event_id)){ + if (g_system_event_handle_table[event->event_id].event_handle){ + os_printf("enter default callback\n"); + g_system_event_handle_table[event->event_id].event_handle(event); + os_printf("exit default callback\n"); + } + } else { + os_printf("mismatch or invalid event, id=%d\n", event->event_id); + } + + return esp_wifi_post_event_to_user(event); +} + +static void esp_system_event_task(void *pvParameters) +{ + system_event_t evt; + esp_err_t ret; + + while (1) { + if (xQueueReceive(g_event_handler, &evt, portMAX_DELAY) == pdPASS) { + ret = esp_system_event_handler(&evt); + if (ret == ESP_FAIL) + os_printf("esp wifi post event to user fail!\n"); + } + } +} + +system_event_cb_t esp_event_set_cb(system_event_cb_t cb) +{ + system_event_cb_t old_cb = g_event_handler_cb; + g_event_handler_cb = cb; + return old_cb; +} + +esp_err_t esp_event_send(system_event_t *event) +{ + portBASE_TYPE ret; + + ret = xQueueSendToBack((xQueueHandle)g_event_handler, event, 0); + if (pdPASS != ret){ + if (event) ets_printf("e=%d f\n", event->event_id); + else ets_printf("e null\n"); + return ESP_FAIL; + } + + return ESP_OK; +} + +void* esp_event_get_handler(void) +{ + return (void*)g_event_handler; +} + +esp_err_t esp_event_init(system_event_cb_t cb) +{ + g_event_handler_cb = (system_event_cb_t)cb; + g_event_handler = xQueueCreate(CONFIG_WIFI_ENENT_QUEUE_SIZE, sizeof(system_event_t)); + xTaskCreatePinnedToCore(esp_system_event_task, "eventTask", CONFIG_WIFI_EVENT_TASK_STACK_SIZE, NULL, 5, NULL, 0); // TODO: rearrange task priority + return ESP_OK; +} + +#endif diff --git a/components/esp32/heap_alloc_caps.c b/components/esp32/heap_alloc_caps.c new file mode 100644 index 0000000000..3f63c5d8a1 --- /dev/null +++ b/components/esp32/heap_alloc_caps.c @@ -0,0 +1,246 @@ +// Copyright 2015-2016 Espressif Systems (Shanghai) PTE LTD +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at + +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +#include + +#include + +#include "heap_alloc_caps.h" +#include "spiram.h" + +/* +This file, combined with a region allocator that supports tags, solves the problem that the ESP32 has RAM that's +slightly heterogeneous. Some RAM can be byte-accessed, some allows only 32-bit accesses, some can execute memory, +some can be remapped by the MMU to only be accessed by a certain PID etc. In order to allow the most flexible +memory allocation possible, this code makes it possible to request memory that has certain capabilities. The +code will then use its knowledge of how the memory is configured along with a priority scheme to allocate that +memory in the most sane way possible. This should optimize the amount of RAM accessible to the code without +hardwiring addresses. +*/ + + +//Amount of priority slots for the tag descriptors. +#define NO_PRIOS 3 + +/* +Tag descriptors. These describe the capabilities of a bit of memory that's tagged with the index into this table. +Each tag contains NO_PRIOS entries; later entries are only taken if earlier ones can't fulfill the memory request. +*/ +static const uint32_t tagDesc[][NO_PRIOS]={ + { MALLOC_CAP_DMA|MALLOC_CAP_8BIT, MALLOC_CAP_32BIT, 0 }, //Tag 0: Plain ole D-port RAM + { 0, MALLOC_CAP_DMA|MALLOC_CAP_8BIT, MALLOC_CAP_32BIT|MALLOC_CAP_EXEC }, //Tag 1: Plain ole D-port RAM which has an alias on the I-port + { MALLOC_CAP_EXEC|MALLOC_CAP_32BIT, 0, 0 }, //Tag 2: IRAM + { MALLOC_CAP_PID2, 0, MALLOC_CAP_EXEC|MALLOC_CAP_32BIT }, //Tag 3-8: PID 2-7 IRAM + { MALLOC_CAP_PID3, 0, MALLOC_CAP_EXEC|MALLOC_CAP_32BIT }, // + { MALLOC_CAP_PID4, 0, MALLOC_CAP_EXEC|MALLOC_CAP_32BIT }, // + { MALLOC_CAP_PID5, 0, MALLOC_CAP_EXEC|MALLOC_CAP_32BIT }, // + { MALLOC_CAP_PID6, 0, MALLOC_CAP_EXEC|MALLOC_CAP_32BIT }, // + { MALLOC_CAP_PID7, 0, MALLOC_CAP_EXEC|MALLOC_CAP_32BIT }, // + { MALLOC_CAP_PID2, MALLOC_CAP_8BIT, MALLOC_CAP_32BIT }, //Tag 9-14: PID 2-7 DRAM + { MALLOC_CAP_PID3, MALLOC_CAP_8BIT, MALLOC_CAP_32BIT }, // + { MALLOC_CAP_PID4, MALLOC_CAP_8BIT, MALLOC_CAP_32BIT }, // + { MALLOC_CAP_PID5, MALLOC_CAP_8BIT, MALLOC_CAP_32BIT }, // + { MALLOC_CAP_PID6, MALLOC_CAP_8BIT, MALLOC_CAP_32BIT }, // + { MALLOC_CAP_PID7, MALLOC_CAP_8BIT, MALLOC_CAP_32BIT }, // + { MALLOC_CAP_SPISRAM, 0, MALLOC_CAP_DMA|MALLOC_CAP_8BIT|MALLOC_CAP_32BIT}, //Tag 15: SPI SRAM data + { MALLOC_CAP_INVALID, MALLOC_CAP_INVALID, MALLOC_CAP_INVALID } //End +}; + +/* +Region descriptors. These describe all regions of memory available, and tag them according to the +capabilities the hardware has. This array is not marked constant; the initialization code may want to +change the tags of some regions because eg BT is detected, applications are loaded etc. + +The priorities here roughly work like this: +- For a normal malloc (MALLOC_CAP_8BIT), give away the DRAM-only memory first, then pass off any dual-use IRAM regions, + finally eat into the application memory. +- For a malloc where 32-bit-aligned-only access is okay, first allocate IRAM, then DRAM, finally application IRAM. +- Application mallocs (PIDx) will allocate IRAM first, if possible, then DRAM. +- Most other malloc caps only fit in one region anyway. + +These region descriptors are very ESP32 specific, because they describe the memory pools available there. + +Because of requirements in the coalescing code as well as the heap allocator itself, this list should always +be sorted from low to high start address. + +This array is *NOT* const because it gets modified depending on what pools are/aren't available. +*/ +static HeapRegionTagged_t regions[]={ + { (uint8_t *)0x3F800000, 0x20000, 15, 0}, //SPI SRAM, if available +// { (uint8_t *)0x3FFAE000, 0x2000, 0, 0}, //pool 16 <- can be used for BT <- THIS POOL DOESN'T WORK for some reason! Hw seems fine. ToDo: Figure out. + { (uint8_t *)0x3FFB0000, 0x8000, 0, 0}, //pool 15 <- can be used for BT + { (uint8_t *)0x3FFB8000, 0x8000, 0, 0}, //pool 14 + { (uint8_t *)0x3FFC0000, 0x2000, 0, 0}, //pool 10-13, mmu page 0 + { (uint8_t *)0x3FFC2000, 0x2000, 0, 0}, //pool 10-13, mmu page 1 + { (uint8_t *)0x3FFC4000, 0x2000, 0, 0}, //pool 10-13, mmu page 2 + { (uint8_t *)0x3FFC6000, 0x2000, 0, 0}, //pool 10-13, mmu page 3 + { (uint8_t *)0x3FFC8000, 0x2000, 0, 0}, //pool 10-13, mmu page 4 + { (uint8_t *)0x3FFCA000, 0x2000, 0, 0}, //pool 10-13, mmu page 5 + { (uint8_t *)0x3FFCC000, 0x2000, 0, 0}, //pool 10-13, mmu page 6 + { (uint8_t *)0x3FFCE000, 0x2000, 0, 0}, //pool 10-13, mmu page 7 + { (uint8_t *)0x3FFD0000, 0x2000, 0, 0}, //pool 10-13, mmu page 8 + { (uint8_t *)0x3FFD2000, 0x2000, 0, 0}, //pool 10-13, mmu page 9 + { (uint8_t *)0x3FFD4000, 0x2000, 0, 0}, //pool 10-13, mmu page 10 + { (uint8_t *)0x3FFD6000, 0x2000, 0, 0}, //pool 10-13, mmu page 11 + { (uint8_t *)0x3FFD8000, 0x2000, 0, 0}, //pool 10-13, mmu page 12 + { (uint8_t *)0x3FFDA000, 0x2000, 0, 0}, //pool 10-13, mmu page 13 + { (uint8_t *)0x3FFDC000, 0x2000, 0, 0}, //pool 10-13, mmu page 14 + { (uint8_t *)0x3FFDE000, 0x2000, 0, 0}, //pool 10-13, mmu page 15 + { (uint8_t *)0x3FFE0000, 0x4000, 1, 0x400BC000}, //pool 9 blk 1 + { (uint8_t *)0x3FFE4000, 0x4000, 1, 0x400B8000}, //pool 9 blk 0 + { (uint8_t *)0x3FFE8000, 0x8000, 1, 0x400B0000}, //pool 8 <- can be remapped to ROM, used for MAC dump + { (uint8_t *)0x3FFF0000, 0x8000, 1, 0x400A8000}, //pool 7 <- can be used for MAC dump + { (uint8_t *)0x3FFF8000, 0x4000, 1, 0x400A4000}, //pool 6 blk 1 <- can be used as trace memory + { (uint8_t *)0x3FFFC000, 0x4000, 1, 0x400A0000}, //pool 6 blk 0 <- can be used as trace memory + { (uint8_t *)0x40070000, 0x8000, 2, 0}, //pool 0 + { (uint8_t *)0x40078000, 0x8000, 2, 0}, //pool 1 + { (uint8_t *)0x40080000, 0x2000, 2, 0}, //pool 2-5, mmu page 0 + { (uint8_t *)0x40082000, 0x2000, 2, 0}, //pool 2-5, mmu page 1 + { (uint8_t *)0x40084000, 0x2000, 2, 0}, //pool 2-5, mmu page 2 + { (uint8_t *)0x40086000, 0x2000, 2, 0}, //pool 2-5, mmu page 3 + { (uint8_t *)0x40088000, 0x2000, 2, 0}, //pool 2-5, mmu page 4 + { (uint8_t *)0x4008A000, 0x2000, 2, 0}, //pool 2-5, mmu page 5 + { (uint8_t *)0x4008C000, 0x2000, 2, 0}, //pool 2-5, mmu page 6 + { (uint8_t *)0x4008E000, 0x2000, 2, 0}, //pool 2-5, mmu page 7 + { (uint8_t *)0x40090000, 0x2000, 2, 0}, //pool 2-5, mmu page 8 + { (uint8_t *)0x40092000, 0x2000, 2, 0}, //pool 2-5, mmu page 9 + { (uint8_t *)0x40094000, 0x2000, 2, 0}, //pool 2-5, mmu page 10 + { (uint8_t *)0x40096000, 0x2000, 2, 0}, //pool 2-5, mmu page 11 + { (uint8_t *)0x40098000, 0x2000, 2, 0}, //pool 2-5, mmu page 12 + { (uint8_t *)0x4009A000, 0x2000, 2, 0}, //pool 2-5, mmu page 13 + { (uint8_t *)0x4009C000, 0x2000, 2, 0}, //pool 2-5, mmu page 14 + { (uint8_t *)0x4009E000, 0x2000, 2, 0}, //pool 2-5, mmu page 15 + { NULL, 0, 0, 0} //end +}; + + +//Modify regions array to disable the given range of memory. +static void disable_mem_region(void *from, void *to) { + int i; + //Align from and to on word boundaries + from=(void*)((uint32_t)from&~3); + to=(void*)(((uint32_t)to+3)&~3); + for (i=0; regions[i].xSizeInBytes!=0; i++) { + void *regStart=regions[i].pucStartAddress; + void *regEnd=regions[i].pucStartAddress+regions[i].xSizeInBytes; + if (regStart>=from && regEnd<=to) { + //Entire region falls in the range. Disable entirely. + regions[i].xTag=-1; + } else if (regStart>=from && regEnd>to && regStartfrom && regEnd<=to) { + //End of the region falls in the range. Modify length. + regions[i].xSizeInBytes-=(uint8_t *)regEnd-(uint8_t *)from; + } else if (regStartto) { + //Range punches a hole in the region! We do not support this. + ets_printf("%s: region %d: hole punching is not supported!\n", i); + regions[i].xTag=-1; //Just disable memory region. That'll teach them! + } + } +} + + +/* +ToDo: These are very dependent on the linker script, and the logic involving this works only +because we're not using the SPI flash yet! If we enable that, this will break. ToDo: Rewrite by then. +*/ +extern int _init_start, _text_end; +extern int _bss_start, _heap_start; + +/* +Initialize the heap allocator. We pass it a bunch of region descriptors, but we need to modify those first to accommodate for +the data as loaded by the bootloader. +ToDo: The regions are different when stuff like trace memory, BT, ... is used. Modify the regions struct on the fly for this. +Same with loading of apps. Same with using SPI RAM. +*/ +void heap_alloc_caps_init() { + int i; + //Disable the bits of memory where this code is loaded. + disable_mem_region(&_init_start, &_text_end); + disable_mem_region(&_bss_start, &_heap_start); + disable_mem_region((void*)0x3ffae000, (void*)0x3ffb0000); //knock out ROM data region + disable_mem_region((void*)0x3ffe0000, (void*)0x3ffe8000); //knock out ROM data region + disable_mem_region((void*)0x40070000, (void*)0x40078000); //CPU0 cache region + disable_mem_region((void*)0x40078000, (void*)0x40080000); //CPU1 cache region +#if 0 + enable_spi_sram(); +#else + disable_mem_region((void*)0x3f800000, (void*)0x3f820000); //SPI SRAM not installed +#endif + + //The heap allocator will treat every region given to it as separate. In order to get bigger ranges of contiguous memory, + //it's useful to coalesce adjacent regions that have the same tag. + + for (i=1; regions[i].xSizeInBytes!=0; i++) { + if (regions[i].pucStartAddress == (regions[i-1].pucStartAddress + regions[i-1].xSizeInBytes) && + regions[i].xTag == regions[i-1].xTag ) { + regions[i-1].xTag=-1; + regions[i].pucStartAddress=regions[i-1].pucStartAddress; + regions[i].xSizeInBytes+=regions[i-1].xSizeInBytes; + } + } + +#if 1 //Change to 1 to show the regions the heap allocator is initialized with. + ets_printf("Initializing heap allocator:\n"); + for (i=0; regions[i].xSizeInBytes!=0; i++) { + if ( regions[i].xTag != -1 ) ets_printf("Region %02d: %08X len %08X tag %d\n", i, (int)regions[i].pucStartAddress, regions[i].xSizeInBytes, regions[i].xTag); + } +#endif + //Initialize the malloc implementation. + vPortDefineHeapRegionsTagged( regions ); +} + +/* +Standard malloc() implementation. Will return ho-hum byte-accessible data memory. +*/ +void *pvPortMalloc( size_t xWantedSize ) +{ + return pvPortMallocCaps( xWantedSize, MALLOC_CAP_8BIT ); +} + +/* +Routine to allocate a bit of memory with certain capabilities. caps is a bitfield of MALLOC_CAP_* bits. +*/ +void *pvPortMallocCaps( size_t xWantedSize, uint32_t caps ) +{ + int prio; + int tag, j; + void *ret=NULL; + uint32_t remCaps; + for (prio=0; prio + +#ifdef __cplusplus +extern "C" { +#endif + +typedef int32_t esp_err_t; + +/* Definitions for error constants. */ + +#define ESP_OK 0 +#define ESP_FAIL -1 + +#define ESP_ERR_NO_MEM 0x101 + +#ifdef __cplusplus +} +#endif + +#endif /* __ESP_ERR_H__ */ diff --git a/components/esp32/include/esp_event.h b/components/esp32/include/esp_event.h new file mode 100755 index 0000000000..8a34eb5691 --- /dev/null +++ b/components/esp32/include/esp_event.h @@ -0,0 +1,107 @@ +// Copyright 2015-2016 Espressif Systems (Shanghai) PTE LTD +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at + +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#ifndef __ESP_EVENT_H__ +#define __ESP_EVENT_H__ + +#include +#include + +#include "esp_err.h" + +#ifdef __cplusplus +extern "C" { +#endif + +typedef enum { + SYSTEM_EVENT_WIFI_READY = 0, /**< ESP32 wifi ready */ + SYSTEM_EVENT_SCAN_DONE, /**< ESP32 finish scanning AP */ + SYSTEM_EVENT_STA_START, /**< ESP32 station start */ + SYSTEM_EVENT_STA_STOP, /**< ESP32 station start */ + SYSTEM_EVENT_STA_CONNECTED, /**< ESP32 station connected to AP */ + SYSTEM_EVENT_STA_DISCONNECTED, /**< ESP32 station disconnected to AP */ + SYSTEM_EVENT_STA_AUTHMODE_CHANGE, /**< the auth mode of AP connected by ESP32 station changed */ + SYSTEM_EVENT_AP_START, /**< ESP32 softap start */ + SYSTEM_EVENT_AP_STOP, /**< ESP32 softap start */ + SYSTEM_EVENT_AP_STACONNECTED, /**< a station connected to ESP32 soft-AP */ + SYSTEM_EVENT_AP_STADISCONNECTED, /**< a station disconnected to ESP32 soft-AP */ + SYSTEM_EVENT_AP_PROBEREQRECVED, /**< Receive probe request packet in soft-AP interface */ + SYSTEM_EVENT_MAX +} system_event_id_t; + +typedef struct { + uint32_t status; /**< status of scanning APs*/ + uint8_t number; +} system_event_sta_scan_done_t; + +typedef struct { + uint8_t ssid[32]; /**< SSID of connected AP */ + uint8_t ssid_len; /**< SSID length of connected AP */ + uint8_t bssid[6]; /**< BSSID of connected AP*/ + uint8_t channel; /**< channel of connected AP*/ +} system_event_sta_connected_t; + +typedef struct { + uint8_t ssid[32]; /**< SSID of disconnected AP */ + uint8_t ssid_len; /**< SSID length of disconnected AP */ + uint8_t bssid[6]; /**< BSSID of disconnected AP */ + uint8_t reason; /**< reason of disconnection */ +} system_event_sta_disconnected_t; + +typedef struct { + uint8_t old_mode; /**< the old auth mode of AP */ + uint8_t new_mode; /**< the new auth mode of AP */ +} system_event_sta_authmode_change_t; + +typedef struct { + uint8_t mac[6]; /**< MAC address of the station connected to ESP32 soft-AP */ + uint8_t aid; /**< the aid that ESP32 soft-AP gives to the station connected to */ +} system_event_ap_staconnected_t; + +typedef struct { + uint8_t mac[6]; /**< MAC address of the station disconnects to ESP32 soft-AP */ + uint8_t aid; /**< the aid that ESP32 soft-AP gave to the station disconnects to */ +} system_event_ap_stadisconnected_t; + +typedef struct { + int rssi; /**< Received probe request signal strength */ + uint8_t mac[6]; /**< MAC address of the station which send probe request */ +} system_event_ap_probe_req_rx_t; + +typedef union { + system_event_sta_connected_t connected; /**< ESP32 station connected to AP */ + system_event_sta_disconnected_t disconnected; /**< ESP32 station disconnected to AP */ + system_event_sta_scan_done_t scan_done; /**< ESP32 station scan (APs) done */ + system_event_sta_authmode_change_t auth_change; /**< the auth mode of AP ESP32 station connected to changed */ + system_event_ap_staconnected_t sta_connected; /**< a station connected to ESP32 soft-AP */ + system_event_ap_stadisconnected_t sta_disconnected; /**< a station disconnected to ESP32 soft-AP */ + system_event_ap_probe_req_rx_t ap_probereqrecved; /**< ESP32 softAP receive probe request packet */ +} system_event_info_t; + +typedef struct { + system_event_id_t event_id; /**< even ID */ + system_event_info_t event_info; /**< event information */ +} system_event_t; + +typedef esp_err_t (*system_event_cb_t)(system_event_t *event); +system_event_cb_t esp_event_set_cb(system_event_cb_t cb); +esp_err_t esp_event_send(system_event_t * event); +void* esp_event_get_handler(void); +esp_err_t esp_event_init(system_event_cb_t cb); + +#ifdef __cplusplus +} +#endif + +#endif /* __ESP_EVENT_H__ */ diff --git a/components/esp32/include/esp_ssc.h b/components/esp32/include/esp_ssc.h new file mode 100644 index 0000000000..02893ff410 --- /dev/null +++ b/components/esp32/include/esp_ssc.h @@ -0,0 +1,119 @@ +// Copyright 2015-2016 Espressif Systems (Shanghai) PTE LTD +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at + +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#ifndef __ESP_SSC_H__ +#define __ESP_SSC_H__ + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +#define CMD_T_ASYNC 0x01 +#define CMD_T_SYNC 0x02 + +typedef struct cmd_s { + char *cmd_str; + uint8_t flag; + uint8_t id; + void (* cmd_func)(void); + void (* cmd_callback)(void *arg); +} ssc_cmd_t; + +#define MAX_LINE_N 127 + +typedef enum { + SSC_BR_9600 = 9600, + SSC_BR_19200 = 19200, + SSC_BR_38400 = 38400, + SSC_BR_57600 = 57600, + SSC_BR_74880 = 74880, + SSC_BR_115200 = 115200, + SSC_BR_230400 = 230400, + SSC_BR_460800 = 460800, + SSC_BR_921600 = 921600 +} SscBaudRate; + +/** \defgroup SSC_APIs SSC APIs + * @brief SSC APIs + * + * SSC means simple serial command. + * SSC APIs allows users to define their own command, users can refer to spiffs_test/test_main.c. + * + */ + +/** @addtogroup SSC_APIs + * @{ + */ + +/** + * @brief Initial the ssc function. + * + * @attention param is no use, just compatible with ESP8266, default bandrate is 115200 + * + * @param SscBaudRate bandrate : baud rate + * + * @return null + */ +void ssc_attach(SscBaudRate bandrate); + +/** + * @brief Get the length of the simple serial command. + * + * @param null + * + * @return length of the command. + */ +int ssc_param_len(void); + +/** + * @brief Get the simple serial command string. + * + * @param null + * + * @return the command. + */ +char *ssc_param_str(void); + +/** + * @brief Parse the simple serial command (ssc). + * + * @param char *pLine : [input] the ssc string + * @param char *argv[] : [output] parameters of the ssc + * + * @return the number of parameters. + */ +int ssc_parse_param(char *pLine, char *argv[]); + +/** + * @brief Register the user-defined simple serial command (ssc) set. + * + * @param ssc_cmd_t *cmdset : the ssc set + * @param uint8 cmdnum : number of commands + * @param void (* help)(void) : callback of user-guide + * + * @return null + */ +void ssc_register(ssc_cmd_t *cmdset, uint8_t cmdnum, void (* help)(void)); + +/** + * @} + */ + +#ifdef __cplusplus +} +#endif + +#endif /* __ESP_SSC_H__ */ diff --git a/components/esp32/include/esp_system.h b/components/esp32/include/esp_system.h new file mode 100644 index 0000000000..4f140db91f --- /dev/null +++ b/components/esp32/include/esp_system.h @@ -0,0 +1,364 @@ +// Copyright 2015-2016 Espressif Systems (Shanghai) PTE LTD +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at + +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#ifndef __ESP_SYSTEM_H__ +#define __ESP_SYSTEM_H__ + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/** \defgroup System_APIs System APIs + * @brief System APIs + */ + +/** @addtogroup System_APIs + * @{ + */ + +/** + * @brief Get information of the SDK version. + * + * @param null + * + * @return Information of the SDK version. + */ +const char *system_get_sdk_version(void); + +/** + * @brief Reset to default settings. + * + * Reset to default settings of the following APIs : wifi_station_set_auto_connect, + * wifi_set_phy_mode, wifi_softap_set_config related, wifi_station_set_config + * related, and wifi_set_opmode. + * + * @param null + * + * @return null + */ +void system_restore(void); + +/** + * @brief Restart system. + * + * @param null + * + * @return null + */ +void system_restart(void); + +/** + * @brief Set the chip to deep-sleep mode. + * + * The device will automatically wake up after the deep-sleep time set + * by the users. Upon waking up, the device boots up from user_init. + * + * @attention The parameter time_in_us to be "uint64" is for further development. + * Only the low 32 bits of parameter time_in_us are avalable now. + * + * @param uint64 time_in_us : deep-sleep time, only the low 32bits are avalable now. unit: microsecond + * + * @return null + */ +void system_deep_sleep(uint64_t time_in_us); + +/** + * @brief Get system time, unit: microsecond. + * + * @param null + * + * @return System time, unit: microsecond. + */ +uint32_t system_get_time(void); + +/** + * @brief Print the system memory distribution, including data/rodata/bss/heap. + * + * @param null + * + * @return null + */ +void system_print_meminfo(void); + +/** + * @brief Get the size of available heap. + * + * @param null + * + * @return Available heap size. + */ +uint32_t system_get_free_heap_size(void); + +/** + * @brief Get the chip ID. + * + * Example: + *
 
+  *         uint8 chip_id[6];
+  *         system_get_chip_id(chip_id);
+  * 
+ * + * @param uint8 *chip_id : the chip ID + * + * @return true : succeed + * @return false : fail + */ +bool system_get_chip_id(uint8_t *chip_id); + +/** + * @brief Get RTC time, unit: RTC clock cycle. + * + * @param null + * + * @return RTC time. + */ +uint64_t system_get_rtc_time(void); + +/** + * @brief Read user data from the RTC memory. + * + * The user data segment (1024 bytes, as shown below) is used to store user data. + * + * |<---- system data(512 bytes) ---->|<----------- user data(1024 bytes) --------->| + * + * @attention Read and write unit for data stored in the RTC memory is 4 bytes. + * @attention src_addr is the block number (4 bytes per block). So when reading data + * at the beginning of the user data segment, src_addr will be 512/4 = 128, + * n will be data length. + * + * @param uint16 src : source address of rtc memory, src_addr >= 128 + * @param void *dst : data pointer + * @param uint16 n : data length, unit: byte + * + * @return true : succeed + * @return false : fail + */ +bool system_rtc_mem_read(uint16_t src, void *dst, uint16_t n); + +/** + * @brief Write user data to the RTC memory. + * + * During deep-sleep, only RTC is working. So users can store their data + * in RTC memory if it is needed. The user data segment below (1024 bytes) + * is used to store the user data. + * + * |<---- system data(512 bytes) ---->|<----------- user data(1024 bytes) --------->| + * + * @attention Read and write unit for data stored in the RTC memory is 4 bytes. + * @attention src_addr is the block number (4 bytes per block). So when storing data + * at the beginning of the user data segment, src_addr will be 512/4 = 128, + * n will be data length. + * + * @param uint16 src : source address of rtc memory, src_addr >= 128 + * @param void *dst : data pointer + * @param uint16 n : data length, unit: byte + * + * @return true : succeed + * @return false : fail + */ +bool system_rtc_mem_write(uint16_t dst, const void *src, uint16_t n); + +typedef enum { + ADC1_PAD_GPIO36 = 0, + ADC1_PAD_GPIO37, + ADC1_PAD_GPIO38, + ADC1_PAD_GPIO39, + ADC1_PAD_GPIO32, + ADC1_PAD_GPIO33, + ADC1_PAD_GPIO34, + ADC1_PAD_GPIO35 +} adc1_read_pad_t; + +typedef enum { + ADC1_ATTEN_0DB = 0, + ADC1_ATTEN_3DB, + ADC1_ATTEN_6DB, + ADC1_ATTEN_12DB +} adc1_read_atten_t; + +/** + * @brief Read ADC1. + * + * @param adc1_read_pad pad : the corresponding GPIO + * @param adc1_read_atten atten : value of attenuation + * + * @return range of the return value is [0, 4096]. + * - If atten == 0, the range of voltage can be measured is [0, 1] V. + * - If atten == 1, the range of voltage can be measured is [0, 1.4] V. + * - If atten == 2, the range of voltage can be measured is [0, 2] V. + * - If atten == 3, the range of voltage can be measured is [0, 4] V. + */ +uint16_t system_adc1_read(adc1_read_pad_t pad, adc1_read_atten_t atten); + +/** + * @brief Measure the power voltage of VDD3P3 pin 3 and 4, unit : 1/1024 V. + * + * @attention system_get_vdd33 depends on RF, please do not use it if RF is disabled. + * + * @param null + * + * @return Power voltage of VDD33, unit : 1/1024 V + */ +uint16_t system_get_vdd33(void); + +/** + * @brief Write data into flash with protection. + * + * Flash read/write has to be 4-bytes aligned. + * + * Protection of flash read/write : + * use 3 sectors (4KBytes per sector) to save 4KB data with protect, + * sector 0 and sector 1 are data sectors, back up each other, + * save data alternately, sector 2 is flag sector, point out which sector + * is keeping the latest data, sector 0 or sector 1. + * + * @param uint16 start_sec : start sector (sector 0) of the 3 sectors which are + * used for flash read/write protection. + * - For example, in IOT_Demo we can use the 3 sectors (3 * 4KB) starting from flash + * 0x3D000 for flash read/write protection, so the parameter start_sec should be 0x3D + * @param void *param : pointer of the data to be written + * @param uint16 len : data length, should be less than a sector, which is 4 * 1024 + * + * @return true : succeed + * @return false : fail + */ +bool system_param_save_with_protect(uint16_t start_sec, void *param, uint16_t len); + +/** + * @brief Read the data saved into flash with the read/write protection. + * + * Flash read/write has to be 4-bytes aligned. + * + * Read/write protection of flash: + * use 3 sectors (4KB per sector) to save 4KB data with protect, sector + * 0 and sector 1 are data sectors, back up each other, save data alternately, + * sector 2 is flag sector, point out which sector is keeping the latest data, + * sector 0 or sector 1. + * + * @param uint16 start_sec : start sector (sector 0) of the 3 sectors used for + * flash read/write protection. It cannot be sector 1 or sector 2. + * - For example, in IOT_Demo, the 3 sectors (3 * 4KB) starting from flash 0x3D000 + * can be used for flash read/write protection. + * The parameter start_sec is 0x3D, and it cannot be 0x3E or 0x3F. + * @param uint16 offset : offset of data saved in sector + * @param void *param : data pointer + * @param uint16 len : data length, offset + len =< 4 * 1024 + * + * @return true : succeed + * @return false : fail + */ +bool system_param_load(uint16_t start_sec, uint16_t offset, void *param, uint16_t len); + + +/** \defgroup System_boot_APIs Boot APIs + * @brief boot APIs + */ + +/** @addtogroup System_boot_APIs + * @{ + */ + +/** + * @} + */ + +/** \defgroup Hardware_MAC_APIs Hardware MAC APIs + * @brief Hardware MAC address APIs + * + * In WiFi MAC, only ESP32 station MAC is the hardware MAC, ESP32 softAP MAC is a software MAC + * calculated from ESP32 station MAC. + * So users need to call wifi_get_macaddr to query the ESP32 softAP MAC if ESP32 station MAC changed. + * + */ + +/** @addtogroup Hardware_MAC_APIs + * @{ + */ + +typedef enum { + DEFAULT_MAC = 0, /**< Default hardware MAC provided by Espressif Systems */ + USER_MAC, /**< User-define hardware MAC */ +} mac_group_t; + +typedef enum { + WIFI_MAC = 0, /**< Hardware MAC address of ESP32 WiFi */ + BT_MAC, /**< Hardware MAC address of ESP32 bluetooth */ +} mac_type_t; + +/** + * @brief Set user-define hardware MAC address. + * + * @attention Hardware MAC address can only be set ONCE for each ESP32 chip. + * + * @param mac_type type : type of hardware MAC address. + * @param uint8 *mac : user-define hardware MAC address, length: 6 bytes. + * + * @return 0 : succeed to set. + * @return 1 : the hardware MAC has been set once, users can not set it any more. + * @return 2 : fail to set. + * @return 3 : invalid parameter. + */ +int system_efuse_program_user_mac(mac_type_t type, uint8_t *mac); + +/** + * @brief Read hardware MAC address. + * + * @param mac_group group : default MAC or user-defined MAC. + * @param mac_type type : type of hardware MAC address. + * @param uint8 *mac : the hardware MAC address, length: 6 bytes. + * + * @return true : succeed + * @return false : fail + */ +bool system_efuse_read_mac(mac_group_t group, mac_type_t type, uint8_t *mac); + +/** + * @brief Set hardware MAC group, default MAC or user-defined MAC. + * + * @attention This API needs system_restart to take effect. + * + * @param mac_group group : default MAC or user-defined MAC. + * + * @return true : succeed + * @return false : fail + */ +bool system_efuse_set_mac_group(mac_group_t group); + +/** + * @brief Get hardware MAC group, default MAC or user-defined MAC. + * + * @param null + * + * @return mac_group, the hardware MAC group. + */ +mac_group_t system_efuse_get_mac_group(void); + +void system_init(void); + +/** + * @} + */ + + +/** + * @} + */ + +#ifdef __cplusplus +} +#endif + +#endif /* __ESP_SYSTEM_H__ */ diff --git a/components/esp32/include/esp_types.h b/components/esp32/include/esp_types.h new file mode 100755 index 0000000000..c142aee687 --- /dev/null +++ b/components/esp32/include/esp_types.h @@ -0,0 +1,73 @@ +// Copyright 2010-2016 Espressif Systems (Shanghai) PTE LTD +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at + +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#ifndef __ESP_TYPES_H__ +#define __ESP_TYPES_H__ + +#ifdef __GNUC__ +#include +#endif /*__GNUC__*/ +#include +#include +#include + +#define __ATTRIB_PACK __attribute__ ((packed)) +#define __ATTRIB_PRINTF __attribute__ ((format (printf, 1, 2))) +#define __ATTRIB_NORETURN __attribute__ ((noreturn)) +#define __ATTRIB_ALIGN(x) __attribute__ ((aligned((x)))) +#define INLINE __inline__ + +#define LOCAL static + +/* probably should not put STATUS here */ +typedef enum { + OK = 0, + FAIL, + PENDING, + BUSY, + CANCEL, +} STATUS; + +//#define _LITTLE_ENDIAN 1234 +//#define _BYTE_ORDER == _LITTLE_ENDIAN + +#define ASSERT( x ) do { \ + if (!(x)) { \ + printf("%s %u\n", __FILE__, __LINE__); \ + while (1) { \ + asm volatile("nop"); \ + }; \ + } \ +} while (0) + +/* #if __GNUC_PREREQ__(4, 1) */ +#ifndef __GNUC__ +#if 1 +#define __offsetof(type, field) __builtin_offsetof(type, field) +#else +#define __offsetof(type, field) ((size_t)(&((type *)0)->field)) +#endif +#endif /* __GNUC__ */ + + +/* Macros for counting and rounding. */ +#ifndef howmany +#define howmany(x, y) (((x)+((y)-1))/(y)) +#endif + +#define container_of(ptr, type, member) ({ \ + const typeof( ((type *)0)->member ) *__mptr = (ptr); \ + (type *)( (char *)__mptr - __offsetof(type,member) );}) + +#endif /* __ESP_TYPES_H__ */ diff --git a/components/esp32/include/esp_wifi.h b/components/esp32/include/esp_wifi.h new file mode 100755 index 0000000000..bdd125395f --- /dev/null +++ b/components/esp32/include/esp_wifi.h @@ -0,0 +1,231 @@ +// Copyright 2015-2016 Espressif Systems (Shanghai) PTE LTD +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at + +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#ifndef __ESP_WIFI_H__ +#define __ESP_WIFI_H__ + +#include +#include + +#include "esp_err.h" + +#ifdef __cplusplus +extern "C" { +#endif + +typedef enum { + WIFI_MODE_NULL = 0, /**< null mode */ + WIFI_MODE_STA, /**< WiFi station mode */ + WIFI_MODE_AP, /**< WiFi soft-AP mode */ + WIFI_MODE_APSTA, /**< WiFi station + soft-AP mode */ + WIFI_MODE_MAX +} wifi_mode_t; + +typedef enum { + WIFI_IF_STA = 0, /**< ESP32 station interface */ + WIFI_IF_AP, /**< ESP32 soft-AP interface */ + WIFI_IF_MAX +} wifi_interface_t; + +typedef enum { + WIFI_COUNTRY_CN = 0, + WIFI_COUNTRY_JP, + WIFI_COUNTRY_US, + WIFI_COUNTRY_EU, + WIFI_COUNTRY_MAX +} wifi_country_t; + +typedef enum { + WIFI_AUTH_OPEN = 0, /**< authenticate mode : open */ + WIFI_AUTH_WEP, /**< authenticate mode : WEP */ + WIFI_AUTH_WPA_PSK, /**< authenticate mode : WPA_PSK */ + WIFI_AUTH_WPA2_PSK, /**< authenticate mode : WPA2_PSK */ + WIFI_AUTH_WPA_WPA2_PSK, /**< authenticate mode : WPA_WPA2_PSK */ + WIFI_AUTH_MAX +} wifi_auth_mode_t; + +enum { + WIFI_REASON_UNSPECIFIED = 1, + WIFI_REASON_AUTH_EXPIRE = 2, + WIFI_REASON_AUTH_LEAVE = 3, + WIFI_REASON_ASSOC_EXPIRE = 4, + WIFI_REASON_ASSOC_TOOMANY = 5, + WIFI_REASON_NOT_AUTHED = 6, + WIFI_REASON_NOT_ASSOCED = 7, + WIFI_REASON_ASSOC_LEAVE = 8, + WIFI_REASON_ASSOC_NOT_AUTHED = 9, + WIFI_REASON_DISASSOC_PWRCAP_BAD = 10, + WIFI_REASON_DISASSOC_SUPCHAN_BAD = 11, + WIFI_REASON_IE_INVALID = 13, + WIFI_REASON_MIC_FAILURE = 14, + WIFI_REASON_4WAY_HANDSHAKE_TIMEOUT = 15, + WIFI_REASON_GROUP_KEY_UPDATE_TIMEOUT = 16, + WIFI_REASON_IE_IN_4WAY_DIFFERS = 17, + WIFI_REASON_GROUP_CIPHER_INVALID = 18, + WIFI_REASON_PAIRWISE_CIPHER_INVALID = 19, + WIFI_REASON_AKMP_INVALID = 20, + WIFI_REASON_UNSUPP_RSN_IE_VERSION = 21, + WIFI_REASON_INVALID_RSN_IE_CAP = 22, + WIFI_REASON_802_1X_AUTH_FAILED = 23, + WIFI_REASON_CIPHER_SUITE_REJECTED = 24, + + WIFI_REASON_BEACON_TIMEOUT = 200, + WIFI_REASON_NO_AP_FOUND = 201, + WIFI_REASON_AUTH_FAIL = 202, + WIFI_REASON_ASSOC_FAIL = 203, + WIFI_REASON_HANDSHAKE_TIMEOUT = 204, +}; + +typedef enum { + WIFI_SECOND_CHAN_NONE = 0, + WIFI_SECOND_CHAN_ABOVE, + WIFI_SECOND_CHAN_BELOW, +} wifi_second_chan_t; + +typedef esp_err_t (* wifi_startup_cb_t)(void); + +void esp_wifi_startup(wifi_startup_cb_t cb); + +typedef struct { + void *event_q; + uint8_t rx_ba_win; /**< TBC */ + uint8_t tx_ba_win; /**< TBC */ + uint8_t rx_buf_cnt; /**< TBC */ + uint8_t tx_buf_cnt; /**< TBC */ +} wifi_init_config_t; + +esp_err_t esp_wifi_init(wifi_init_config_t *config); + +esp_err_t esp_wifi_deinit(void); + +esp_err_t esp_wifi_set_mode(wifi_mode_t mode); + +esp_err_t esp_wifi_get_mode(wifi_mode_t *mode); + +esp_err_t esp_wifi_start(void); + +esp_err_t esp_wifi_stop(void); + +esp_err_t esp_wifi_connect(void); + +esp_err_t esp_wifi_disconnect(void); + +typedef struct { + char *ssid; /**< SSID of AP */ + uint8_t *bssid; /**< MAC address of AP */ + uint8_t channel; /**< channel, scan the specific channel */ + bool show_hidden; /**< enable to scan AP whose SSID is hidden */ +} wifi_scan_config_t; + +esp_err_t esp_wifi_scan_start(wifi_scan_config_t *conf); + +esp_err_t esp_wifi_scan_stop(void); + +esp_err_t esp_wifi_get_ap_num(uint16_t *number); + +typedef struct { + uint8_t bssid[6]; /**< MAC address of AP */ + uint8_t ssid[32]; /**< SSID of AP */ + uint8_t primary; /**< channel of AP */ + wifi_second_chan_t second; /**< second channel of AP */ + char rssi; /**< single strength of AP */ + wifi_auth_mode_t authmode; /**< authmode of AP */ +}wifi_ap_list_t; + +esp_err_t esp_wifi_get_ap_list(uint16_t *number, wifi_ap_list_t *ap_list); + +typedef enum { + WIFI_PS_NONE, + WIFI_PS_MODEM, + WIFI_PS_LIGHT, + WIFI_PS_MAC, +} wifi_ps_type_t; + +esp_err_t esp_wifi_set_ps(wifi_ps_type_t type); + +esp_err_t esp_wifi_get_ps(wifi_ps_type_t *type); + +#define WIFI_PROTOCOL_11B 1 +#define WIFI_PROTOCOL_11G 2 +#define WIFI_PROTOCOL_11N 4 + +esp_err_t esp_wifi_set_protocol(wifi_interface_t ifx, uint8_t protocol); + +esp_err_t esp_wifi_get_protocol(wifi_interface_t ifx, uint8_t *protocol); + +typedef enum { + WIFI_BW_HT20 = 0, + WIFI_BW_HT40, +} wifi_bandwidth_t; + +esp_err_t esp_wifi_set_bandwidth(wifi_interface_t ifx, wifi_bandwidth_t bw); + +esp_err_t esp_wifi_get_bandwidth(wifi_interface_t ifx, wifi_bandwidth_t *bw); + +esp_err_t esp_wifi_set_channel(uint8_t primary, wifi_second_chan_t second); + +esp_err_t esp_wifi_get_channel(uint8_t *primary, wifi_second_chan_t *second); + +esp_err_t esp_wifi_set_country(wifi_country_t country); + +esp_err_t esp_wifi_get_country(wifi_country_t *country); + +esp_err_t esp_wifi_set_mac(wifi_interface_t ifx, uint8_t mac[6]); + +esp_err_t esp_wifi_get_mac(wifi_interface_t ifx, uint8_t mac[6]); + +typedef void (* wifi_promiscuous_cb_t)(void *buf, uint16_t len); + +wifi_promiscuous_cb_t wifi_set_promiscuous_rx_cb(wifi_promiscuous_cb_t cb); + +esp_err_t esp_wifi_set_promiscuous(uint8_t enable); + +esp_err_t esp_wifi_get_promiscuous(uint8_t *enable); + +typedef struct { + char ssid[32]; /**< SSID of ESP32 soft-AP */ + char password[64]; /**< Password of ESP32 soft-AP */ + uint8_t ssid_len; /**< Length of SSID. If softap_config.ssid_len==0, check the SSID until there is a termination character; otherwise, set the SSID length according to softap_config.ssid_len. */ + uint8_t channel; /**< Channel of ESP32 soft-AP */ + wifi_auth_mode_t authmode; /**< Auth mode of ESP32 soft-AP. Do not support AUTH_WEP in soft-AP mode */ + uint8_t ssid_hidden; /**< Broadcast SSID or not, default 0, broadcast the SSID */ + uint8_t max_connection; /**< Max number of stations allowed to connect in, default 4, max 4 */ + uint16_t beacon_interval; /**< Beacon interval, 100 ~ 60000 ms, default 100 */ +} wifi_ap_config_t; + +typedef struct { + char ssid[32]; /**< SSID of target AP*/ + char password[64]; /**< password of target AP*/ + bool bssid_set; /**< whether set MAC address of target AP or not. Generally, station_config.bssid_set needs to be 0; and it needs to be 1 only when users need to check the MAC address of the AP.*/ + uint8_t bssid[6]; /**< MAC address of target AP*/ +} wifi_sta_config_t; + +typedef union { + wifi_ap_config_t ap; + wifi_sta_config_t sta; +} wifi_config_t; + +esp_err_t esp_wifi_set_config(wifi_interface_t ifx, wifi_config_t *conf); + +esp_err_t esp_wifi_get_config(wifi_interface_t ifx, wifi_config_t *conf); + +typedef esp_err_t (*wifi_rxcb_t)(void *buffer, uint16_t len, void* eb); + +esp_err_t esp_wifi_reg_rxcb(wifi_interface_t ifx, wifi_rxcb_t fn); + +#ifdef __cplusplus +} +#endif + +#endif /* __ESP_WIFI_H__ */ diff --git a/components/esp32/include/esp_wps.h b/components/esp32/include/esp_wps.h new file mode 100644 index 0000000000..b37fe542e0 --- /dev/null +++ b/components/esp32/include/esp_wps.h @@ -0,0 +1,131 @@ +// Copyright 2015-2016 Espressif Systems (Shanghai) PTE LTD +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at + +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#ifndef __ESP_WPS_H__ +#define __ESP_WPS_H__ + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/** \defgroup WiFi_APIs WiFi Related APIs + * @brief WiFi APIs + */ + +/** @addtogroup WiFi_APIs + * @{ + */ + +/** \defgroup WPS_APIs WPS APIs + * @brief ESP32 WPS APIs + * + * WPS can only be used when ESP32 station is enabled. + * + */ + +/** @addtogroup WPS_APIs + * @{ + */ + +typedef enum wps_type { + WPS_TYPE_DISABLE = 0, + WPS_TYPE_PBC, + WPS_TYPE_PIN, + WPS_TYPE_DISPLAY, + WPS_TYPE_MAX, +} WPS_TYPE_t; + +enum wps_cb_status { + WPS_CB_ST_SUCCESS = 0, /**< WPS succeed */ + WPS_CB_ST_FAILED, /**< WPS fail */ + WPS_CB_ST_TIMEOUT, /**< WPS timeout, fail */ + WPS_CB_ST_WEP, /**< WPS failed because that WEP is not supported */ + WPS_CB_ST_SCAN_ERR, /**< can not find the target WPS AP */ +}; + +/** + * @brief Enable Wi-Fi WPS function. + * + * @attention WPS can only be used when ESP32 station is enabled. + * + * @param WPS_TYPE_t wps_type : WPS type, so far only WPS_TYPE_PBC is supported + * + * @return true : succeed + * @return false : fail + */ +bool wifi_wps_enable(WPS_TYPE_t wps_type); + +/** + * @brief Disable Wi-Fi WPS function and release resource it taken. + * + * @param null + * + * @return true : succeed + * @return false : fail + */ +bool wifi_wps_disable(void); + +/** + * @brief WPS starts to work. + * + * @attention WPS can only be used when ESP32 station is enabled. + * + * @param null + * + * @return true : WPS starts to work successfully, but does not mean WPS succeed. + * @return false : fail + */ +bool wifi_wps_start(void); + +/** + * @brief WPS callback. + * + * @param int status : status of WPS, enum wps_cb_status. + * - If parameter status == WPS_CB_ST_SUCCESS in WPS callback, it means WPS got AP's + * information, user can call wifi_wps_disable to disable WPS and release resource, + * then call wifi_station_connect to connect to target AP. + * - Otherwise, it means that WPS fail, user can create a timer to retry WPS by + * wifi_wps_start after a while, or call wifi_wps_disable to disable WPS and release resource. + * + * @return null + */ +typedef void (*wps_st_cb_t)(int status); + +/** + * @brief Set WPS callback. + * + * @attention WPS can only be used when ESP32 station is enabled. + * + * @param wps_st_cb_t cb : callback. + * + * @return true : WPS starts to work successfully, but does not mean WPS succeed. + * @return false : fail + */ +bool wifi_set_wps_cb(wps_st_cb_t cb); + +/** + * @} + */ + +/** + * @} + */ + +#ifdef __cplusplus +} +#endif + +#endif /* __ESP_WPS_H__ */ diff --git a/components/esp32/include/rom/aes.h b/components/esp32/include/rom/aes.h new file mode 100644 index 0000000000..97e6248bca --- /dev/null +++ b/components/esp32/include/rom/aes.h @@ -0,0 +1,48 @@ +// Copyright 2015-2016 Espressif Systems (Shanghai) PTE LTD +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at + +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +#ifndef _ROM_AES_H_ +#define _ROM_AES_H_ + +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +enum AES_BITS { + AES128, + AES192, + AES256 +}; + +void ets_aes_enable(void); + +void ets_aes_disable(void); + +void ets_set_endian(bool key_word_swap, bool key_byte_swap, + bool in_word_swap, bool in_byte_swap, + bool out_word_swap, bool out_byte_swap); + +bool ets_aes_setkey_enc(const uint8_t *key, enum AES_BITS bits); + +bool ets_aes_setkey_dec(const uint8_t *key, enum AES_BITS bits); + +void ets_aes_crypt(const uint8_t input[16], uint8_t output[16]); + +#ifdef __cplusplus +} +#endif + +#endif /* _ROM_AES_H_ */ diff --git a/components/esp32/include/rom/bigint.h b/components/esp32/include/rom/bigint.h new file mode 100644 index 0000000000..461469cacd --- /dev/null +++ b/components/esp32/include/rom/bigint.h @@ -0,0 +1,53 @@ +// Copyright 2015-2016 Espressif Systems (Shanghai) PTE LTD +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at + +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +#ifndef _ROM_BIGINT_H_ +#define _ROM_BIGINT_H_ + +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +void ets_bigint_enable(void); + +void ets_bigint_disable(void); + +void ets_bigint_wait_finish(void); + +bool ets_bigint_mod_power_prepare(uint32_t *x, uint32_t *y, uint32_t *m, + uint32_t m_dash, uint32_t *rb, uint32_t len, bool again); + +bool ets_bigint_mod_power_getz(uint32_t *z, uint32_t len); + +bool ets_bigint_mult_prepare(uint32_t *x, uint32_t *y, uint32_t len); + +bool ets_bigint_mult_getz(uint32_t *z, uint32_t len); + +bool ets_bigint_montgomery_mult_prepare(uint32_t *x, uint32_t *y, uint32_t *m, + uint32_t m_dash, uint32_t len, bool again); + +bool ets_bigint_montgomery_mult_getz(uint32_t *z, uint32_t len); + +bool ets_bigint_mod_mult_prepare(uint32_t *x, uint32_t *y, uint32_t *m, + uint32_t m_dash, uint32_t *rb, uint32_t len, bool again); + +bool ets_bigint_mod_mult_getz(uint32_t *m, uint32_t *z, uint32_t len); + +#ifdef __cplusplus +} +#endif + +#endif /* _ROM_BIGINT_H_ */ diff --git a/components/esp32/include/rom/cache.h b/components/esp32/include/rom/cache.h new file mode 100644 index 0000000000..b9e59448f1 --- /dev/null +++ b/components/esp32/include/rom/cache.h @@ -0,0 +1,69 @@ +// Copyright 2015-2016 Espressif Systems (Shanghai) PTE LTD +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at + +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +#ifndef _ROM_CACHE_H_ +#define _ROM_CACHE_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +//=========================================== +// function : cache_init +// description: initialise cache mmu, mark all entries as invalid. +// conditions: +// Call Cache_Read_Disable() before calling this function. +// inputs: +// cpu_no is CPU number,0(PRO CPU) or 1(APP CPU), +// output: NONE +//=========================================== +void mmu_init(int cpu_no); + +//=========================================== +// function : cache_flash_mmu_set +// description: Configure MMU to cache a flash region. +// conditions: +// Call this function to configure the flash cache before enabling it. +// Check return value to verify MMU was set correctly. +// inputs: +// cpu_no is CPU number,0(PRO CPU) or 1(APP CPU), +// pid is process identifier. Range 0~7 +// vaddr is "virtual" address in CPU address space. Can be IRam0, IRam1, IRom0 and DRom0 memory address. +// Should be aligned by psize +// paddr is "physical" address in flash controller's address space. +// ie for 16M flash the range is 0x000000~0xFFFFFF. Should be aligned by psize +// psize is page size of flash, in kilobytes. Can be 64, 32, 16. +// num is number of pages to be set, valid range 0 ~ (flash size)/(page size) +// output: error status +// 0 : mmu set success +// 1 : vaddr or paddr is not aligned +// 2 : pid error +// 3 : psize error +// 4 : mmu table to be written is out of range +// 5 : vaddr is out of range +//=========================================== +unsigned int cache_flash_mmu_set(int cpu_no, int pid, unsigned int vaddr, unsigned int paddr, int psize, int num); + +unsigned int cache_sram_mmu_set(int cpu_no, int pid,unsigned int vaddr, unsigned int paddr, int psize, int num); + +void Cache_Read_Init(int cpu_no); + +void Cache_Read_Disable(int cpu_no); + +void Cache_Read_Enable(int cpu_no); + +#ifdef __cplusplus +} +#endif + +#endif /* _ROM_CACHE_H_ */ diff --git a/components/esp32/include/rom/crc.h b/components/esp32/include/rom/crc.h new file mode 100644 index 0000000000..be763d7dc5 --- /dev/null +++ b/components/esp32/include/rom/crc.h @@ -0,0 +1,34 @@ +// Copyright 2015-2016 Espressif Systems (Shanghai) PTE LTD +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at + +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +#ifndef ROM_CRC_H +#define ROM_CRC_H + +#ifdef __cplusplus +extern "C" { +#endif + +/* Standard CRC8/16/32 algorithms. */ +uint32_t crc32_le(uint32_t crc, uint8_t const * buf, uint32_t len); +uint32_t crc32_be(uint32_t crc, uint8_t const * buf, uint32_t len); +uint16_t crc16_le(uint16_t crc, uint8_t const * buf, uint32_t len); +uint16_t crc16_be(uint16_t crc, uint8_t const * buf, uint32_t len); +uint8_t crc8_le(uint8_t crc, uint8_t const * buf, uint32_t len); +uint8_t crc8_be(uint8_t crc, uint8_t const * buf, uint32_t len); + +#ifdef __cplusplus +} +#endif + + +#endif diff --git a/components/esp32/include/rom/efuse.h b/components/esp32/include/rom/efuse.h new file mode 100644 index 0000000000..6d0252b5e4 --- /dev/null +++ b/components/esp32/include/rom/efuse.h @@ -0,0 +1,29 @@ +// Copyright 2015-2016 Espressif Systems (Shanghai) PTE LTD +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at + +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +#ifndef _ROM_EFUSE_H_ +#define _ROM_EFUSE_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +void ets_efuse_read_op(void); + +void ets_efuse_program_op(void); + +#ifdef __cplusplus +} +#endif + +#endif /* _ROM_EFUSE_H_ */ diff --git a/components/esp32/include/rom/ets_sys.h b/components/esp32/include/rom/ets_sys.h new file mode 100644 index 0000000000..a1c186d97c --- /dev/null +++ b/components/esp32/include/rom/ets_sys.h @@ -0,0 +1,329 @@ +// Copyright 2010-2016 Espressif Systems (Shanghai) PTE LTD +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at + +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#ifndef _ROM_ETS_SYS_H_ +#define _ROM_ETS_SYS_H_ + +#include +#include + +#include "soc/soc.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#define ETS_DEBUG +#define ETS_SERIAL_ENABLED() (1) + +typedef enum { + ETS_OK = 0, + ETS_FAILED = 1 +} ETS_STATUS; + +typedef uint32_t ETSSignal; +typedef uint32_t ETSParam; + +typedef struct ETSEventTag ETSEvent; + +struct ETSEventTag { + ETSSignal sig; + ETSParam par; +}; + +typedef void (*ETSTask)(ETSEvent *e); + +enum ETS_User_Priorities { + /* task priorities... */ + TICK_TASK_A_PRIO = 2, + KBD_TASK_PRIO = 5, + MAX_ETS_USER_PRIO = 16, + + /* ISR priorities... */ + MAX_ETS_USER_ISR_PRIO = 0xFF - 16 +}; + +/* ETS interrupt entry and exit */ +/* actually we don't need the following 2 macros any more since we won't exit + * isr until it is finised, more over, we don't do nest interrupt + */ + +void ets_run(void); + +void ets_task(ETSTask task, uint8_t prio, ETSEvent *queue, uint8_t qlen); + +ETS_STATUS ets_post(uint8_t prio, ETSSignal sig, ETSParam par); + +/* + * now things become complicated, print could be directed to uart and/or SDIO + */ +int ets_printf(const char *fmt, ...); + +/* by default it's UART, just install_uart_printf, set putc1 to NULL to disable */ +void ets_install_putc1(void (*p)(char c)); +void ets_install_uart_printf(void); + +/* no need to install, call directly */ +int ets_uart_printf(const char *fmt, ...); + +/* usually we don't need to call this, unless we want to disable SDIO print */ +void ets_install_putc2(void (*p)(char c)); +/* @prepare_buf: allocate buffer for printf internal writting + * @putc: just set to NULL, let printf write to to buffer, unless if you want more fancy stuff + * @post_printf: will be called every time printf finish write buffer + * + * main idea of external printf is re-directing content to an external buffer. + * e.g. sip module allocates an event buffer in prepare_buf() and send the event to host in post_printf() + * moreover, you can check printf_buf_remain_len in post_printf(), send the event to host till buf is + * about to full. + * + * TBD: Another approach is sending printf parameter to host and let host to decode, which could save some bytes. + */ +void ets_install_external_printf(void (*prepare_buf)(char ** bufptr, uint16_t *buflen, uint32_t *cookie), + void (*putc)(char c), + void (*post_printf)(uint32_t cookie)); + +uint16_t est_get_printf_buf_remain_len(void); +void est_reset_printf_buf_len(void); + +/* external (SDIO) printf only, still need to install*/ +int ets_external_printf(const char *fmt, ...); + + +#define ETS_PRINTF(...) ets_printf(...) + +#define ETS_ASSERT(v) do { \ + if (!(v)) { \ + ets_printf("%s %u \n", __FILE__, __LINE__); \ + while (1) {}; \ + } \ +} while (0); + +/* memory and string support */ +int8_t ets_char2xdigit(char ch); +uint8_t * ets_str2macaddr(uint8_t *macaddr, char *str); +void ets_getc(char *c); +void ets_putc(char c); + +/* timer related */ +typedef uint32_t ETSHandle; +typedef void ETSTimerFunc(void *timer_arg); + +typedef struct _ETSTIMER_ { + struct _ETSTIMER_ *timer_next; + uint32_t timer_expire; + uint32_t timer_period; + ETSTimerFunc *timer_func; + void *timer_arg; +} ETSTimer; + +void ets_timer_init(void); +void ets_timer_arm(ETSTimer *timer, uint32_t tmout, bool repeat); +void ets_timer_disarm(ETSTimer *timer); +void ets_timer_done(ETSTimer *ptimer); +void ets_timer_setfn(ETSTimer *ptimer, ETSTimerFunc *pfunction, void *parg); + +/* watchdog related */ +typedef enum { + WDT_NONE = -1, + WDT_DISABLED = 0, + WDT_CONTROL_RESET = 1, + WDT_CONTROL_INTR = 2, /* usually we use this mode? */ + WDT_CONTROL_EXTERNAL_FEED = 3, + WDT_TESET_OVERFLOW = 4, // intend to make watchdog overflow to test +} WDT_MODE; + +typedef enum{ + WDT_INTERVAL_THREE_SEC = 3, + WDT_INTERVAL_SIX_SEC = 6, + WDT_INTERVAL_TWELVE_SEC = 12, +} WDT_INTERVAL_TIME; + +void ets_wdt_init(void); +WDT_MODE ets_wdt_get_mode(void); +void ets_wdt_enable(WDT_MODE mode, WDT_INTERVAL_TIME feed_interval, + WDT_INTERVAL_TIME expire_interval); +WDT_MODE ets_wdt_disable(void); +void ets_wdt_restore(WDT_MODE old_mode); + +/* interrupt related */ +typedef void (* ets_isr_t)(void *); + +#define ETS_WMAC_SOURCE 0 +#define ETS_SLC_SOURCE 1 +#define ETS_UART_SOURCE 13 +#define ETS_UART1_SOURCE 14 +#define ETS_FRC_TIMER2_SOURCE 43 + +#define ETS_WMAC_INUM 0 +#define ETS_SLC_INUM 1 +#define ETS_SPI_INUM 2 +#define ETS_HSIP_INUM 2 +#define ETS_I2S_INUM 2 +#define ETS_RTC_INUM 3 +#define ETS_FRC_TIMER1_INUM 9 /* use edge*/ +#define ETS_FRC_TIMER2_INUM 10 /* use edge*/ +#define ETS_WDT_INUM 8 /* use edge*/ +#define ETS_GPIO_INUM 4 +#define ETS_UART_INUM 5 +#define ETS_UART1_INUM 5 +#define ETS_MAX_INUM 6 + + +void ets_isr_attach(int i, ets_isr_t func, void *arg); +void ets_isr_mask(uint32_t mask); +void ets_isr_unmask(uint32_t unmask); +void ets_intr_lock(void); +void ets_intr_unlock(void); +void intr_matrix_set(int cpu_no, uint32_t model_num, uint32_t intr_num); + +#define _ETSTR(v) # v +#define _ETS_SET_INTLEVEL(intlevel) ({ unsigned __tmp; \ + __asm__ __volatile__( "rsil %0, " _ETSTR(intlevel) "\n" \ + : "=a" (__tmp) : : "memory" ); \ + }) + +#define ETS_INTR_LOCK() \ + ets_intr_lock() + +#define ETS_INTR_UNLOCK() \ + ets_intr_unlock() + +#define ETS_CCOMPARE_INTR_ATTACH(func, arg) \ + ets_isr_attach(ETS_CCOMPARE_INUM, (func), (void *)(arg)) + +#define ETS_PWM_INTR_ATTACH(func, arg) \ + ets_isr_attach(ETS_PWM_INUM, (func), (void *)(arg)) + +#define ETS_WMAC_INTR_ATTACH(func, arg) \ + ets_isr_attach(ETS_WMAC_INUM, (func), (void *)(arg)) + +#define ETS_FRC_TIMER1_INTR_ATTACH(func, arg) \ + ets_isr_attach(ETS_FRC_TIMER1_INUM, (func), (void *)(arg)) + +#define ETS_FRC_TIMER2_INTR_ATTACH(func, arg) \ + ets_isr_attach(ETS_FRC_TIMER2_INUM, (func), (void *)(arg)) + +#define ETS_GPIO_INTR_ATTACH(func, arg) \ + ets_isr_attach(ETS_GPIO_INUM, (func), (void *)(arg)) + +#define ETS_UART_INTR_ATTACH(func, arg) \ + ets_isr_attach(ETS_UART_INUM, (func), (void *)(arg)) + +#define ETS_WDT_INTR_ATTACH(func, arg) \ + ets_isr_attach(ETS_WDT_INUM, (func), (void *)(arg)) + +#define ETS_RTC_INTR_ATTACH(func, arg) \ + ets_isr_attach(ETS_RTC_INUM, (func), (void *)(arg)) + +#define ETS_SLC_INTR_ATTACH(func, arg) \ + ets_isr_attach(ETS_SLC_INUM, (func), (void *)(arg)) + + +#define ETS_INTR_ENABLE(inum) \ + ets_isr_unmask((1<= '0') && (c <= '9')) + +#define isxdigit(c) (((c >= '0') && (c <= '9')) || \ + ((c >= 'a') && (c <= 'f')) || \ + ((c >= 'A') && (c <= 'F')) ) + +#define isblank(c) ((c == ' ') || (c == '\t')) + +#define isupper(c) ((c >= 'A') && (c <= 'Z')) +#endif + + +#ifndef MAC2STR +#define MAC2STR(a) (a)[0], (a)[1], (a)[2], (a)[3], (a)[4], (a)[5] +#define MACSTR "%02x:%02x:%02x:%02x:%02x:%02x" +#endif + +#define ETS_MEM_BAR() asm volatile ( "" : : : "memory" ) + +#ifdef __cplusplus +} +#endif + +#endif /* _ROM_ETS_SYS_H_ */ diff --git a/components/esp32/include/rom/gpio.h b/components/esp32/include/rom/gpio.h new file mode 100644 index 0000000000..afb8e20184 --- /dev/null +++ b/components/esp32/include/rom/gpio.h @@ -0,0 +1,142 @@ +// Copyright 2010-2016 Espressif Systems (Shanghai) PTE LTD +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at + +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#ifndef _ROM_GPIO_H_ +#define _ROM_GPIO_H_ + +#include +#include + +#include "esp_attr.h" +#include "soc/gpio_reg.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#define GPIO_REG_READ(reg) READ_PERI_REG(reg) +#define GPIO_REG_WRITE(reg, val) WRITE_PERI_REG(reg, val) +#define GPIO_PIN_COUNT 40 +#define GPIO_ID_PIN0 0 +#define GPIO_ID_PIN(n) (GPIO_ID_PIN0+(n)) +#define GPIO_PIN_ADDR(i) (GPIO_PIN0 + i*4) + +#define GPIO_ID_IS_PIN_REGISTER(reg_id) \ + ((reg_id >= GPIO_ID_PIN0) && (reg_id <= GPIO_ID_PIN(GPIO_PIN_COUNT-1))) + +#define GPIO_REGID_TO_PINIDX(reg_id) ((reg_id) - GPIO_ID_PIN0) + +typedef enum{ + GPIO_PIN_INTR_DISABLE = 0, + GPIO_PIN_INTR_POSEDGE = 1, + GPIO_PIN_INTR_NEGEDGE = 2, + GPIO_PIN_INTR_ANYEGDE = 3, + GPIO_PIN_INTR_LOLEVEL = 4, + GPIO_PIN_INTR_HILEVEL = 5 +}GPIO_INT_TYPE; + +#define GREEN_LED_ON() GPIO_OUTPUT_SET(GPIO_ID_PIN(1) , 0) +#define GREEN_LED_OFF() GPIO_OUTPUT_SET(GPIO_ID_PIN(1) , 1) + +#define GPIO_OUTPUT_SET(gpio_no, bit_value) \ + ((gpio_no < 32) ? gpio_output_set(bit_value<>gpio_no)&BIT0) : ((gpio_input_get_high()>>(gpio_no - 32))&BIT0)) + +/* GPIO interrupt handler, registered through gpio_intr_handler_register */ +typedef void (* gpio_intr_handler_fn_t)(uint32_t intr_mask, bool high, void *arg); + + +/* + * Initialize GPIO. This includes reading the GPIO Configuration DataSet + * to initialize "output enables" and pin configurations for each gpio pin. + * Must be called once during startup. + */ +void gpio_init(void) ROMFN_ATTR; + +/* + * Change GPIO pin output by setting, clearing, or disabling pins. + * In general, it is expected that a bit will be set in at most one + * of these masks. If a bit is clear in all masks, the output state + * remains unchanged. + * + * There is no particular ordering guaranteed; so if the order of + * writes is significant, calling code should divide a single call + * into multiple calls. + */ +void gpio_output_set(uint32_t set_mask, + uint32_t clear_mask, + uint32_t enable_mask, + uint32_t disable_mask) ROMFN_ATTR; +void gpio_output_set_high(uint32_t set_mask, + uint32_t clear_mask, + uint32_t enable_mask, + uint32_t disable_mask) ROMFN_ATTR; +/* + * Sample the value of GPIO input pins and returns a bitmask. + */ +uint32_t gpio_input_get(void) ROMFN_ATTR; +uint32_t gpio_input_get_high(void) ROMFN_ATTR; + +/* + * Set the specified GPIO register to the specified value. + * This is a very general and powerful interface that is not + * expected to be used during normal operation. It is intended + * mainly for debug, or for unusual requirements. + */ +void gpio_register_set(uint32_t reg_id, uint32_t value) ROMFN_ATTR; + +/* Get the current value of the specified GPIO register. */ +uint32_t gpio_register_get(uint32_t reg_id) ROMFN_ATTR; + +/* + * Register an application-specific interrupt handler for GPIO pin + * interrupts. Once the interrupt handler is called, it will not + * be called again until after a call to gpio_intr_ack. Any GPIO + * interrupts that occur during the interim are masked. + * + * The application-specific handler is called with a mask of + * pending GPIO interrupts. After processing pin interrupts, the + * application-specific handler may wish to use gpio_intr_pending + * to check for any additional pending interrupts before it returns. + */ +void gpio_intr_handler_register(gpio_intr_handler_fn_t fn, void *arg) ROMFN_ATTR; + +/* Determine which GPIO interrupts are pending. */ +uint32_t gpio_intr_pending(void) ROMFN_ATTR; +uint32_t gpio_intr_pending_high(void) ROMFN_ATTR; + +/* + * Acknowledge GPIO interrupts. + * Intended to be called from the gpio_intr_handler_fn. + */ +void gpio_intr_ack(uint32_t ack_mask) ROMFN_ATTR; +void gpio_intr_ack_high(uint32_t ack_mask) ROMFN_ATTR; + +void gpio_pin_wakeup_enable(uint32_t i, GPIO_INT_TYPE intr_state) ROMFN_ATTR; + +void gpio_pin_wakeup_disable() ROMFN_ATTR; + +//extern void gpio_module_install(struct gpio_api *api); + +void gpio_matrix_in(uint32_t gpio, uint32_t signal_idx, bool inv) ROMFN_ATTR; + +void gpio_matrix_out(uint32_t gpio, uint32_t signal_idx, bool out_inv, bool oen_inv) ROMFN_ATTR; + +#ifdef __cplusplus +} +#endif + +#endif /* _ROM_GPIO_H_ */ diff --git a/components/esp32/include/rom/libc_stubs.h b/components/esp32/include/rom/libc_stubs.h new file mode 100644 index 0000000000..0c1876e585 --- /dev/null +++ b/components/esp32/include/rom/libc_stubs.h @@ -0,0 +1,89 @@ +// Copyright 2015-2016 Espressif Systems (Shanghai) PTE LTD +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at + +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +#ifndef _ROM_LIBC_STUBS_H_ +#define _ROM_LIBC_STUBS_H_ + +#include +#include +#include +#include +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/* +ESP32 ROM code contains implementations of some of C library functions. +Whenever a function in ROM needs to use a syscall, it calls a pointer to the corresponding syscall +implementation defined in the following struct. + +The table itself, by default, is not allocated in RAM. There are two pointers, `syscall_table_ptr_pro` and +`syscall_table_ptr_app`, which can be set to point to the locations of syscall tables of CPU 0 (aka PRO CPU) +and CPU 1 (aka APP CPU). Location of these pointers in .bss segment of ROM code is defined in linker script. + +So, before using any of the C library functions (except for pure functions and memcpy/memset functions), +application must allocate syscall table structure for each CPU being used, and populate it with pointers +to actual implementations of corresponding syscalls. +*/ + +struct syscall_stub_table +{ + struct _reent* (*__getreent)(void); + void* (*_malloc_r)(struct _reent *r, size_t); + void (*_free_r)(struct _reent *r, void*); + void* (*_realloc_r)(struct _reent *r, void*, size_t); + void* (*_calloc_r)(struct _reent *r, size_t, size_t); + void (*_abort)(void); + int (*_system_r)(struct _reent *r, const char*); + int (*_rename_r)(struct _reent *r, const char*, const char*); + clock_t (*_times_r)(struct _reent *r, struct tms *); + int (*_gettimeofday_r) (struct _reent *r, struct timeval *, void *); + void (*_raise_r)(struct _reent *r); + int (*_unlink_r)(struct _reent *r, const char*); + int (*_link_r)(struct _reent *r, const char*, const char*); + int (*_stat_r)(struct _reent *r, const char*, struct stat *); + int (*_fstat_r)(struct _reent *r, int, struct stat *); + void* (*_sbrk_r)(struct _reent *r, ptrdiff_t); + int (*_getpid_r)(struct _reent *r); + int (*_kill_r)(struct _reent *r, int, int); + void (*_exit_r)(struct _reent *r, int); + int (*_close_r)(struct _reent *r, int); + int (*_open_r)(struct _reent *r, const char *, int, int); + int (*_write_r)(struct _reent *r, int, const void *, int); + int (*_lseek_r)(struct _reent *r, int, int, int); + int (*_read_r)(struct _reent *r, int, void *, int); + void (*_lock_init)(_lock_t *lock); + void (*_lock_init_recursive)(_lock_t *lock); + void (*_lock_close)(_lock_t *lock); + void (*_lock_close_recursive)(_lock_t *lock); + void (*_lock_acquire)(_lock_t *lock); + void (*_lock_acquire_recursive)(_lock_t *lock); + int (*_lock_try_acquire)(_lock_t *lock); + int (*_lock_try_acquire_recursive)(_lock_t *lock); + void (*_lock_release)(_lock_t *lock); + void (*_lock_release_recursive)(_lock_t *lock); + int (*_printf_float)(struct _reent *data, void *pdata, FILE * fp, int (*pfunc) (struct _reent *, FILE *, _CONST char *, size_t len), va_list * ap); + int (*_scanf_float) (struct _reent *rptr, void *pdata, FILE *fp, va_list *ap); +}; + +extern struct syscall_stub_table* syscall_table_ptr_pro; +extern struct syscall_stub_table* syscall_table_ptr_app; + +#ifdef __cplusplus +} // extern "C" +#endif + +#endif /* _ROM_LIBC_STUBS_H_ */ diff --git a/components/esp32/include/rom/lldesc.h b/components/esp32/include/rom/lldesc.h new file mode 100644 index 0000000000..d027362a51 --- /dev/null +++ b/components/esp32/include/rom/lldesc.h @@ -0,0 +1,176 @@ +// Copyright 2010-2016 Espressif Systems (Shanghai) PTE LTD +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at + +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#ifndef _ROM_LLDESC_H_ +#define _ROM_LLDESC_H_ + +#include + +#include "queue.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#define LLDESC_TX_MBLK_SIZE 268 /* */ +#define LLDESC_RX_SMBLK_SIZE 64 /* small block size, for small mgmt frame */ +#define LLDESC_RX_MBLK_SIZE 524 /* rx is large sinec we want to contain mgmt frame in one block*/ +#define LLDESC_RX_AMPDU_ENTRY_MBLK_SIZE 64 /* it is a small buffer which is a cycle link*/ +#define LLDESC_RX_AMPDU_LEN_MBLK_SIZE 256 /*for ampdu entry*/ +#ifdef ESP_MAC_5 +#define LLDESC_TX_MBLK_NUM 116 /* 64K / 256 */ +#define LLDESC_RX_MBLK_NUM 82 /* 64K / 512 MAX 172*/ +#define LLDESC_RX_AMPDU_ENTRY_MBLK_NUM 4 +#define LLDESC_RX_AMPDU_LEN_MLBK_NUM 12 +#else +#ifdef SBUF_RXTX +#define LLDESC_TX_MBLK_NUM_MAX (2 * 48) /* 23K / 260 - 8 */ +#define LLDESC_RX_MBLK_NUM_MAX (2 * 48) /* 23K / 524 */ +#define LLDESC_TX_MBLK_NUM_MIN (2 * 16) /* 23K / 260 - 8 */ +#define LLDESC_RX_MBLK_NUM_MIN (2 * 16) /* 23K / 524 */ +#endif +#define LLDESC_TX_MBLK_NUM 10 //(2 * 32) /* 23K / 260 - 8 */ + +#ifdef IEEE80211_RX_AMPDU +#define LLDESC_RX_MBLK_NUM 30 +#else +#define LLDESC_RX_MBLK_NUM 10 +#endif /*IEEE80211_RX_AMPDU*/ + +#define LLDESC_RX_AMPDU_ENTRY_MBLK_NUM 4 +#define LLDESC_RX_AMPDU_LEN_MLBK_NUM 8 +#endif /* !ESP_MAC_5 */ +/* + * SLC2 DMA Desc struct, aka lldesc_t + * + * -------------------------------------------------------------- + * | own | EoF | sub_sof | 5'b0 | length [11:0] | size [11:0] | + * -------------------------------------------------------------- + * | buf_ptr [31:0] | + * -------------------------------------------------------------- + * | next_desc_ptr [31:0] | + * -------------------------------------------------------------- + */ + +/* this bitfield is start from the LSB!!! */ +typedef struct lldesc_s { + volatile uint32_t size :12, + length:12, + offset: 5, /* h/w reserved 5bit, s/w use it as offset in buffer */ + sosf : 1, /* start of sub-frame */ + eof : 1, /* end of frame */ + owner : 1; /* hw or sw */ + volatile uint8_t *buf; /* point to buffer data */ + union{ + volatile uint32_t empty; + STAILQ_ENTRY(lldesc_s) qe; /* pointing to the next desc */ + }; +} lldesc_t; + +typedef struct tx_ampdu_entry_s{ + uint32_t sub_len :12, + dili_num : 7, + : 1, + null_byte: 2, + data : 1, + enc : 1, + seq : 8; +} tx_ampdu_entry_t; + +typedef struct lldesc_chain_s { + lldesc_t *head; + lldesc_t *tail; +} lldesc_chain_t; + +#ifdef SBUF_RXTX +enum sbuf_mask_s { + SBUF_MOVE_NO = 0, + SBUF_MOVE_TX2RX, + SBUF_MOVE_RX2TX, +} ; + +#define SBUF_MOVE_STEP 8 +#endif +#define LLDESC_SIZE sizeof(struct lldesc_s) + +/* SLC Descriptor */ +#define LLDESC_OWNER_MASK 0x80000000 +#define LLDESC_OWNER_SHIFT 31 +#define LLDESC_SW_OWNED 0 +#define LLDESC_HW_OWNED 1 + +#define LLDESC_EOF_MASK 0x40000000 +#define LLDESC_EOF_SHIFT 30 + +#define LLDESC_SOSF_MASK 0x20000000 +#define LLDESC_SOSF_SHIFT 29 + +#define LLDESC_LENGTH_MASK 0x00fff000 +#define LLDESC_LENGTH_SHIFT 12 + +#define LLDESC_SIZE_MASK 0x00000fff +#define LLDESC_SIZE_SHIFT 0 + +#define LLDESC_ADDR_MASK 0x000fffff + +void lldesc_build_chain(uint8_t *descptr, uint32_t desclen, uint8_t * mblkptr, uint32_t buflen, uint32_t blksz, uint8_t owner, + lldesc_t **head, +#ifdef TO_HOST_RESTART + lldesc_t ** one_before_tail, +#endif + lldesc_t **tail); + +lldesc_t *lldesc_num2link(lldesc_t * head, uint16_t nblks); + +lldesc_t *lldesc_set_owner(lldesc_t * head, uint16_t nblks, uint8_t owner); + +static inline uint32_t lldesc_get_chain_length(lldesc_t *head) +{ + lldesc_t *ds = head; + uint32_t len = 0; + + while (ds) { + len += ds->length; + ds = STAILQ_NEXT(ds, qe); + } + + return len; +} + +static inline void lldesc_config(lldesc_t *ds, uint8_t owner, uint8_t eof, uint8_t sosf, uint16_t len) +{ + ds->owner = owner; + ds->eof = eof; + ds->sosf = sosf; + ds->length = len; +} + +#define LLDESC_CONFIG(_desc, _owner, _eof, _sosf, _len) do { \ + (_desc)->owner = (_owner); \ + (_desc)->eof = (_eof); \ + (_desc)->sosf = (_sosf); \ + (_desc)->length = (_len); \ +} while(0) + +#define LLDESC_FROM_HOST_CLEANUP(ds) LLDESC_CONFIG((ds), LLDESC_HW_OWNED, 0, 0, 0) + +#define LLDESC_MAC_RX_CLEANUP(ds) LLDESC_CONFIG((ds), LLDESC_HW_OWNED, 0, 0, (ds)->size) + +#define LLDESC_TO_HOST_CLEANUP(ds) LLDESC_CONFIG((ds), LLDESC_HW_OWNED, 0, 0, 0) + +#ifdef __cplusplus +} +#endif + +#endif /* _ROM_LLDESC_H_ */ diff --git a/components/esp32/include/rom/md5_hash.h b/components/esp32/include/rom/md5_hash.h new file mode 100755 index 0000000000..612ee59925 --- /dev/null +++ b/components/esp32/include/rom/md5_hash.h @@ -0,0 +1,36 @@ +/* + * MD5 internal definitions + * Copyright (c) 2003-2005, Jouni Malinen + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * Alternatively, this software may be distributed under the terms of BSD + * license. + * + * See README and COPYING for more details. + */ + +#ifndef _ROM_MD5_HASH_H_ +#define _ROM_MD5_HASH_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +struct MD5Context { + uint32 buf[4]; + uint32 bits[2]; + uint8 in[64]; +}; + +void MD5Init(struct MD5Context *context); +void MD5Update(struct MD5Context *context, unsigned char const *buf, unsigned len); +void MD5Final(unsigned char digest[16], struct MD5Context *context); + +#ifdef __cplusplus +} +#endif + +#endif /* _ROM_MD5_HASH_H_ */ diff --git a/components/esp32/include/rom/miniz.h b/components/esp32/include/rom/miniz.h new file mode 100644 index 0000000000..ed79beb2cb --- /dev/null +++ b/components/esp32/include/rom/miniz.h @@ -0,0 +1,777 @@ +#ifndef MINIZ_HEADER_INCLUDED +#define MINIZ_HEADER_INCLUDED + +#include + +// Defines to completely disable specific portions of miniz.c: +// If all macros here are defined the only functionality remaining will be CRC-32, adler-32, tinfl, and tdefl. + +// Define MINIZ_NO_STDIO to disable all usage and any functions which rely on stdio for file I/O. +#define MINIZ_NO_STDIO + +// If MINIZ_NO_TIME is specified then the ZIP archive functions will not be able to get the current time, or +// get/set file times, and the C run-time funcs that get/set times won't be called. +// The current downside is the times written to your archives will be from 1979. +#define MINIZ_NO_TIME + +// Define MINIZ_NO_ARCHIVE_APIS to disable all ZIP archive API's. +#define MINIZ_NO_ARCHIVE_APIS + +// Define MINIZ_NO_ARCHIVE_APIS to disable all writing related ZIP archive API's. +#define MINIZ_NO_ARCHIVE_WRITING_APIS + +// Define MINIZ_NO_ZLIB_APIS to remove all ZLIB-style compression/decompression API's. +#define MINIZ_NO_ZLIB_APIS + +// Define MINIZ_NO_ZLIB_COMPATIBLE_NAME to disable zlib names, to prevent conflicts against stock zlib. +#define MINIZ_NO_ZLIB_COMPATIBLE_NAMES + +// Define MINIZ_NO_MALLOC to disable all calls to malloc, free, and realloc. +// Note if MINIZ_NO_MALLOC is defined then the user must always provide custom user alloc/free/realloc +// callbacks to the zlib and archive API's, and a few stand-alone helper API's which don't provide custom user +// functions (such as tdefl_compress_mem_to_heap() and tinfl_decompress_mem_to_heap()) won't work. +#define MINIZ_NO_MALLOC + +#if defined(__TINYC__) && (defined(__linux) || defined(__linux__)) + // TODO: Work around "error: include file 'sys\utime.h' when compiling with tcc on Linux + #define MINIZ_NO_TIME +#endif + +#if !defined(MINIZ_NO_TIME) && !defined(MINIZ_NO_ARCHIVE_APIS) + #include +#endif + +//Hardcoded options for Xtensa - JD +#define MINIZ_X86_OR_X64_CPU 0 +#define MINIZ_LITTLE_ENDIAN 1 +#define MINIZ_USE_UNALIGNED_LOADS_AND_STORES 0 +#define MINIZ_HAS_64BIT_REGISTERS 0 +#define TINFL_USE_64BIT_BITBUF 0 + + +#if defined(_M_IX86) || defined(_M_X64) || defined(__i386__) || defined(__i386) || defined(__i486__) || defined(__i486) || defined(i386) || defined(__ia64__) || defined(__x86_64__) +// MINIZ_X86_OR_X64_CPU is only used to help set the below macros. +#define MINIZ_X86_OR_X64_CPU 1 +#endif + +#if (__BYTE_ORDER__==__ORDER_LITTLE_ENDIAN__) || MINIZ_X86_OR_X64_CPU +// Set MINIZ_LITTLE_ENDIAN to 1 if the processor is little endian. +#define MINIZ_LITTLE_ENDIAN 1 +#endif + +#if MINIZ_X86_OR_X64_CPU +// Set MINIZ_USE_UNALIGNED_LOADS_AND_STORES to 1 on CPU's that permit efficient integer loads and stores from unaligned addresses. +#define MINIZ_USE_UNALIGNED_LOADS_AND_STORES 1 +#endif + +#if defined(_M_X64) || defined(_WIN64) || defined(__MINGW64__) || defined(_LP64) || defined(__LP64__) || defined(__ia64__) || defined(__x86_64__) +// Set MINIZ_HAS_64BIT_REGISTERS to 1 if operations on 64-bit integers are reasonably fast (and don't involve compiler generated calls to helper functions). +#define MINIZ_HAS_64BIT_REGISTERS 1 +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +// ------------------- zlib-style API Definitions. + +// For more compatibility with zlib, miniz.c uses unsigned long for some parameters/struct members. Beware: mz_ulong can be either 32 or 64-bits! +typedef unsigned long mz_ulong; + +// mz_free() internally uses the MZ_FREE() macro (which by default calls free() unless you've modified the MZ_MALLOC macro) to release a block allocated from the heap. +void mz_free(void *p); + +#define MZ_ADLER32_INIT (1) +// mz_adler32() returns the initial adler-32 value to use when called with ptr==NULL. +mz_ulong mz_adler32(mz_ulong adler, const unsigned char *ptr, size_t buf_len); + +#define MZ_CRC32_INIT (0) +// mz_crc32() returns the initial CRC-32 value to use when called with ptr==NULL. +mz_ulong mz_crc32(mz_ulong crc, const unsigned char *ptr, size_t buf_len); + +// Compression strategies. +enum { MZ_DEFAULT_STRATEGY = 0, MZ_FILTERED = 1, MZ_HUFFMAN_ONLY = 2, MZ_RLE = 3, MZ_FIXED = 4 }; + +// Method +#define MZ_DEFLATED 8 + +#ifndef MINIZ_NO_ZLIB_APIS + +// Heap allocation callbacks. +// Note that mz_alloc_func parameter types purpsosely differ from zlib's: items/size is size_t, not unsigned long. +typedef void *(*mz_alloc_func)(void *opaque, size_t items, size_t size); +typedef void (*mz_free_func)(void *opaque, void *address); +typedef void *(*mz_realloc_func)(void *opaque, void *address, size_t items, size_t size); + +#define MZ_VERSION "9.1.15" +#define MZ_VERNUM 0x91F0 +#define MZ_VER_MAJOR 9 +#define MZ_VER_MINOR 1 +#define MZ_VER_REVISION 15 +#define MZ_VER_SUBREVISION 0 + +// Flush values. For typical usage you only need MZ_NO_FLUSH and MZ_FINISH. The other values are for advanced use (refer to the zlib docs). +enum { MZ_NO_FLUSH = 0, MZ_PARTIAL_FLUSH = 1, MZ_SYNC_FLUSH = 2, MZ_FULL_FLUSH = 3, MZ_FINISH = 4, MZ_BLOCK = 5 }; + +// Return status codes. MZ_PARAM_ERROR is non-standard. +enum { MZ_OK = 0, MZ_STREAM_END = 1, MZ_NEED_DICT = 2, MZ_ERRNO = -1, MZ_STREAM_ERROR = -2, MZ_DATA_ERROR = -3, MZ_MEM_ERROR = -4, MZ_BUF_ERROR = -5, MZ_VERSION_ERROR = -6, MZ_PARAM_ERROR = -10000 }; + +// Compression levels: 0-9 are the standard zlib-style levels, 10 is best possible compression (not zlib compatible, and may be very slow), MZ_DEFAULT_COMPRESSION=MZ_DEFAULT_LEVEL. +enum { MZ_NO_COMPRESSION = 0, MZ_BEST_SPEED = 1, MZ_BEST_COMPRESSION = 9, MZ_UBER_COMPRESSION = 10, MZ_DEFAULT_LEVEL = 6, MZ_DEFAULT_COMPRESSION = -1 }; + +// Window bits +#define MZ_DEFAULT_WINDOW_BITS 15 + +struct mz_internal_state; + +// Compression/decompression stream struct. +typedef struct mz_stream_s +{ + const unsigned char *next_in; // pointer to next byte to read + unsigned int avail_in; // number of bytes available at next_in + mz_ulong total_in; // total number of bytes consumed so far + + unsigned char *next_out; // pointer to next byte to write + unsigned int avail_out; // number of bytes that can be written to next_out + mz_ulong total_out; // total number of bytes produced so far + + char *msg; // error msg (unused) + struct mz_internal_state *state; // internal state, allocated by zalloc/zfree + + mz_alloc_func zalloc; // optional heap allocation function (defaults to malloc) + mz_free_func zfree; // optional heap free function (defaults to free) + void *opaque; // heap alloc function user pointer + + int data_type; // data_type (unused) + mz_ulong adler; // adler32 of the source or uncompressed data + mz_ulong reserved; // not used +} mz_stream; + +typedef mz_stream *mz_streamp; + +// Returns the version string of miniz.c. +const char *mz_version(void); + +// mz_deflateInit() initializes a compressor with default options: +// Parameters: +// pStream must point to an initialized mz_stream struct. +// level must be between [MZ_NO_COMPRESSION, MZ_BEST_COMPRESSION]. +// level 1 enables a specially optimized compression function that's been optimized purely for performance, not ratio. +// (This special func. is currently only enabled when MINIZ_USE_UNALIGNED_LOADS_AND_STORES and MINIZ_LITTLE_ENDIAN are defined.) +// Return values: +// MZ_OK on success. +// MZ_STREAM_ERROR if the stream is bogus. +// MZ_PARAM_ERROR if the input parameters are bogus. +// MZ_MEM_ERROR on out of memory. +int mz_deflateInit(mz_streamp pStream, int level); + +// mz_deflateInit2() is like mz_deflate(), except with more control: +// Additional parameters: +// method must be MZ_DEFLATED +// window_bits must be MZ_DEFAULT_WINDOW_BITS (to wrap the deflate stream with zlib header/adler-32 footer) or -MZ_DEFAULT_WINDOW_BITS (raw deflate/no header or footer) +// mem_level must be between [1, 9] (it's checked but ignored by miniz.c) +int mz_deflateInit2(mz_streamp pStream, int level, int method, int window_bits, int mem_level, int strategy); + +// Quickly resets a compressor without having to reallocate anything. Same as calling mz_deflateEnd() followed by mz_deflateInit()/mz_deflateInit2(). +int mz_deflateReset(mz_streamp pStream); + +// mz_deflate() compresses the input to output, consuming as much of the input and producing as much output as possible. +// Parameters: +// pStream is the stream to read from and write to. You must initialize/update the next_in, avail_in, next_out, and avail_out members. +// flush may be MZ_NO_FLUSH, MZ_PARTIAL_FLUSH/MZ_SYNC_FLUSH, MZ_FULL_FLUSH, or MZ_FINISH. +// Return values: +// MZ_OK on success (when flushing, or if more input is needed but not available, and/or there's more output to be written but the output buffer is full). +// MZ_STREAM_END if all input has been consumed and all output bytes have been written. Don't call mz_deflate() on the stream anymore. +// MZ_STREAM_ERROR if the stream is bogus. +// MZ_PARAM_ERROR if one of the parameters is invalid. +// MZ_BUF_ERROR if no forward progress is possible because the input and/or output buffers are empty. (Fill up the input buffer or free up some output space and try again.) +int mz_deflate(mz_streamp pStream, int flush); + +// mz_deflateEnd() deinitializes a compressor: +// Return values: +// MZ_OK on success. +// MZ_STREAM_ERROR if the stream is bogus. +int mz_deflateEnd(mz_streamp pStream); + +// mz_deflateBound() returns a (very) conservative upper bound on the amount of data that could be generated by deflate(), assuming flush is set to only MZ_NO_FLUSH or MZ_FINISH. +mz_ulong mz_deflateBound(mz_streamp pStream, mz_ulong source_len); + +// Single-call compression functions mz_compress() and mz_compress2(): +// Returns MZ_OK on success, or one of the error codes from mz_deflate() on failure. +int mz_compress(unsigned char *pDest, mz_ulong *pDest_len, const unsigned char *pSource, mz_ulong source_len); +int mz_compress2(unsigned char *pDest, mz_ulong *pDest_len, const unsigned char *pSource, mz_ulong source_len, int level); + +// mz_compressBound() returns a (very) conservative upper bound on the amount of data that could be generated by calling mz_compress(). +mz_ulong mz_compressBound(mz_ulong source_len); + +// Initializes a decompressor. +int mz_inflateInit(mz_streamp pStream); + +// mz_inflateInit2() is like mz_inflateInit() with an additional option that controls the window size and whether or not the stream has been wrapped with a zlib header/footer: +// window_bits must be MZ_DEFAULT_WINDOW_BITS (to parse zlib header/footer) or -MZ_DEFAULT_WINDOW_BITS (raw deflate). +int mz_inflateInit2(mz_streamp pStream, int window_bits); + +// Decompresses the input stream to the output, consuming only as much of the input as needed, and writing as much to the output as possible. +// Parameters: +// pStream is the stream to read from and write to. You must initialize/update the next_in, avail_in, next_out, and avail_out members. +// flush may be MZ_NO_FLUSH, MZ_SYNC_FLUSH, or MZ_FINISH. +// On the first call, if flush is MZ_FINISH it's assumed the input and output buffers are both sized large enough to decompress the entire stream in a single call (this is slightly faster). +// MZ_FINISH implies that there are no more source bytes available beside what's already in the input buffer, and that the output buffer is large enough to hold the rest of the decompressed data. +// Return values: +// MZ_OK on success. Either more input is needed but not available, and/or there's more output to be written but the output buffer is full. +// MZ_STREAM_END if all needed input has been consumed and all output bytes have been written. For zlib streams, the adler-32 of the decompressed data has also been verified. +// MZ_STREAM_ERROR if the stream is bogus. +// MZ_DATA_ERROR if the deflate stream is invalid. +// MZ_PARAM_ERROR if one of the parameters is invalid. +// MZ_BUF_ERROR if no forward progress is possible because the input buffer is empty but the inflater needs more input to continue, or if the output buffer is not large enough. Call mz_inflate() again +// with more input data, or with more room in the output buffer (except when using single call decompression, described above). +int mz_inflate(mz_streamp pStream, int flush); + +// Deinitializes a decompressor. +int mz_inflateEnd(mz_streamp pStream); + +// Single-call decompression. +// Returns MZ_OK on success, or one of the error codes from mz_inflate() on failure. +int mz_uncompress(unsigned char *pDest, mz_ulong *pDest_len, const unsigned char *pSource, mz_ulong source_len); + +// Returns a string description of the specified error code, or NULL if the error code is invalid. +const char *mz_error(int err); + +// Redefine zlib-compatible names to miniz equivalents, so miniz.c can be used as a drop-in replacement for the subset of zlib that miniz.c supports. +// Define MINIZ_NO_ZLIB_COMPATIBLE_NAMES to disable zlib-compatibility if you use zlib in the same project. +#ifndef MINIZ_NO_ZLIB_COMPATIBLE_NAMES + typedef unsigned char Byte; + typedef unsigned int uInt; + typedef mz_ulong uLong; + typedef Byte Bytef; + typedef uInt uIntf; + typedef char charf; + typedef int intf; + typedef void *voidpf; + typedef uLong uLongf; + typedef void *voidp; + typedef void *const voidpc; + #define Z_NULL 0 + #define Z_NO_FLUSH MZ_NO_FLUSH + #define Z_PARTIAL_FLUSH MZ_PARTIAL_FLUSH + #define Z_SYNC_FLUSH MZ_SYNC_FLUSH + #define Z_FULL_FLUSH MZ_FULL_FLUSH + #define Z_FINISH MZ_FINISH + #define Z_BLOCK MZ_BLOCK + #define Z_OK MZ_OK + #define Z_STREAM_END MZ_STREAM_END + #define Z_NEED_DICT MZ_NEED_DICT + #define Z_ERRNO MZ_ERRNO + #define Z_STREAM_ERROR MZ_STREAM_ERROR + #define Z_DATA_ERROR MZ_DATA_ERROR + #define Z_MEM_ERROR MZ_MEM_ERROR + #define Z_BUF_ERROR MZ_BUF_ERROR + #define Z_VERSION_ERROR MZ_VERSION_ERROR + #define Z_PARAM_ERROR MZ_PARAM_ERROR + #define Z_NO_COMPRESSION MZ_NO_COMPRESSION + #define Z_BEST_SPEED MZ_BEST_SPEED + #define Z_BEST_COMPRESSION MZ_BEST_COMPRESSION + #define Z_DEFAULT_COMPRESSION MZ_DEFAULT_COMPRESSION + #define Z_DEFAULT_STRATEGY MZ_DEFAULT_STRATEGY + #define Z_FILTERED MZ_FILTERED + #define Z_HUFFMAN_ONLY MZ_HUFFMAN_ONLY + #define Z_RLE MZ_RLE + #define Z_FIXED MZ_FIXED + #define Z_DEFLATED MZ_DEFLATED + #define Z_DEFAULT_WINDOW_BITS MZ_DEFAULT_WINDOW_BITS + #define alloc_func mz_alloc_func + #define free_func mz_free_func + #define internal_state mz_internal_state + #define z_stream mz_stream + #define deflateInit mz_deflateInit + #define deflateInit2 mz_deflateInit2 + #define deflateReset mz_deflateReset + #define deflate mz_deflate + #define deflateEnd mz_deflateEnd + #define deflateBound mz_deflateBound + #define compress mz_compress + #define compress2 mz_compress2 + #define compressBound mz_compressBound + #define inflateInit mz_inflateInit + #define inflateInit2 mz_inflateInit2 + #define inflate mz_inflate + #define inflateEnd mz_inflateEnd + #define uncompress mz_uncompress + #define crc32 mz_crc32 + #define adler32 mz_adler32 + #define MAX_WBITS 15 + #define MAX_MEM_LEVEL 9 + #define zError mz_error + #define ZLIB_VERSION MZ_VERSION + #define ZLIB_VERNUM MZ_VERNUM + #define ZLIB_VER_MAJOR MZ_VER_MAJOR + #define ZLIB_VER_MINOR MZ_VER_MINOR + #define ZLIB_VER_REVISION MZ_VER_REVISION + #define ZLIB_VER_SUBREVISION MZ_VER_SUBREVISION + #define zlibVersion mz_version + #define zlib_version mz_version() +#endif // #ifndef MINIZ_NO_ZLIB_COMPATIBLE_NAMES + +#endif // MINIZ_NO_ZLIB_APIS + +// ------------------- Types and macros + +typedef unsigned char mz_uint8; +typedef signed short mz_int16; +typedef unsigned short mz_uint16; +typedef unsigned int mz_uint32; +typedef unsigned int mz_uint; +typedef long long mz_int64; +typedef unsigned long long mz_uint64; +typedef int mz_bool; + +#define MZ_FALSE (0) +#define MZ_TRUE (1) + +// An attempt to work around MSVC's spammy "warning C4127: conditional expression is constant" message. +#ifdef _MSC_VER + #define MZ_MACRO_END while (0, 0) +#else + #define MZ_MACRO_END while (0) +#endif + +// ------------------- ZIP archive reading/writing + +#ifndef MINIZ_NO_ARCHIVE_APIS + +enum +{ + MZ_ZIP_MAX_IO_BUF_SIZE = 64*1024, + MZ_ZIP_MAX_ARCHIVE_FILENAME_SIZE = 260, + MZ_ZIP_MAX_ARCHIVE_FILE_COMMENT_SIZE = 256 +}; + +typedef struct +{ + mz_uint32 m_file_index; + mz_uint32 m_central_dir_ofs; + mz_uint16 m_version_made_by; + mz_uint16 m_version_needed; + mz_uint16 m_bit_flag; + mz_uint16 m_method; +#ifndef MINIZ_NO_TIME + time_t m_time; +#endif + mz_uint32 m_crc32; + mz_uint64 m_comp_size; + mz_uint64 m_uncomp_size; + mz_uint16 m_internal_attr; + mz_uint32 m_external_attr; + mz_uint64 m_local_header_ofs; + mz_uint32 m_comment_size; + char m_filename[MZ_ZIP_MAX_ARCHIVE_FILENAME_SIZE]; + char m_comment[MZ_ZIP_MAX_ARCHIVE_FILE_COMMENT_SIZE]; +} mz_zip_archive_file_stat; + +typedef size_t (*mz_file_read_func)(void *pOpaque, mz_uint64 file_ofs, void *pBuf, size_t n); +typedef size_t (*mz_file_write_func)(void *pOpaque, mz_uint64 file_ofs, const void *pBuf, size_t n); + +struct mz_zip_internal_state_tag; +typedef struct mz_zip_internal_state_tag mz_zip_internal_state; + +typedef enum +{ + MZ_ZIP_MODE_INVALID = 0, + MZ_ZIP_MODE_READING = 1, + MZ_ZIP_MODE_WRITING = 2, + MZ_ZIP_MODE_WRITING_HAS_BEEN_FINALIZED = 3 +} mz_zip_mode; + +typedef struct mz_zip_archive_tag +{ + mz_uint64 m_archive_size; + mz_uint64 m_central_directory_file_ofs; + mz_uint m_total_files; + mz_zip_mode m_zip_mode; + + mz_uint m_file_offset_alignment; + + mz_alloc_func m_pAlloc; + mz_free_func m_pFree; + mz_realloc_func m_pRealloc; + void *m_pAlloc_opaque; + + mz_file_read_func m_pRead; + mz_file_write_func m_pWrite; + void *m_pIO_opaque; + + mz_zip_internal_state *m_pState; + +} mz_zip_archive; + +typedef enum +{ + MZ_ZIP_FLAG_CASE_SENSITIVE = 0x0100, + MZ_ZIP_FLAG_IGNORE_PATH = 0x0200, + MZ_ZIP_FLAG_COMPRESSED_DATA = 0x0400, + MZ_ZIP_FLAG_DO_NOT_SORT_CENTRAL_DIRECTORY = 0x0800 +} mz_zip_flags; + +// ZIP archive reading + +// Inits a ZIP archive reader. +// These functions read and validate the archive's central directory. +mz_bool mz_zip_reader_init(mz_zip_archive *pZip, mz_uint64 size, mz_uint32 flags); +mz_bool mz_zip_reader_init_mem(mz_zip_archive *pZip, const void *pMem, size_t size, mz_uint32 flags); + +#ifndef MINIZ_NO_STDIO +mz_bool mz_zip_reader_init_file(mz_zip_archive *pZip, const char *pFilename, mz_uint32 flags); +#endif + +// Returns the total number of files in the archive. +mz_uint mz_zip_reader_get_num_files(mz_zip_archive *pZip); + +// Returns detailed information about an archive file entry. +mz_bool mz_zip_reader_file_stat(mz_zip_archive *pZip, mz_uint file_index, mz_zip_archive_file_stat *pStat); + +// Determines if an archive file entry is a directory entry. +mz_bool mz_zip_reader_is_file_a_directory(mz_zip_archive *pZip, mz_uint file_index); +mz_bool mz_zip_reader_is_file_encrypted(mz_zip_archive *pZip, mz_uint file_index); + +// Retrieves the filename of an archive file entry. +// Returns the number of bytes written to pFilename, or if filename_buf_size is 0 this function returns the number of bytes needed to fully store the filename. +mz_uint mz_zip_reader_get_filename(mz_zip_archive *pZip, mz_uint file_index, char *pFilename, mz_uint filename_buf_size); + +// Attempts to locates a file in the archive's central directory. +// Valid flags: MZ_ZIP_FLAG_CASE_SENSITIVE, MZ_ZIP_FLAG_IGNORE_PATH +// Returns -1 if the file cannot be found. +int mz_zip_reader_locate_file(mz_zip_archive *pZip, const char *pName, const char *pComment, mz_uint flags); + +// Extracts a archive file to a memory buffer using no memory allocation. +mz_bool mz_zip_reader_extract_to_mem_no_alloc(mz_zip_archive *pZip, mz_uint file_index, void *pBuf, size_t buf_size, mz_uint flags, void *pUser_read_buf, size_t user_read_buf_size); +mz_bool mz_zip_reader_extract_file_to_mem_no_alloc(mz_zip_archive *pZip, const char *pFilename, void *pBuf, size_t buf_size, mz_uint flags, void *pUser_read_buf, size_t user_read_buf_size); + +// Extracts a archive file to a memory buffer. +mz_bool mz_zip_reader_extract_to_mem(mz_zip_archive *pZip, mz_uint file_index, void *pBuf, size_t buf_size, mz_uint flags); +mz_bool mz_zip_reader_extract_file_to_mem(mz_zip_archive *pZip, const char *pFilename, void *pBuf, size_t buf_size, mz_uint flags); + +// Extracts a archive file to a dynamically allocated heap buffer. +void *mz_zip_reader_extract_to_heap(mz_zip_archive *pZip, mz_uint file_index, size_t *pSize, mz_uint flags); +void *mz_zip_reader_extract_file_to_heap(mz_zip_archive *pZip, const char *pFilename, size_t *pSize, mz_uint flags); + +// Extracts a archive file using a callback function to output the file's data. +mz_bool mz_zip_reader_extract_to_callback(mz_zip_archive *pZip, mz_uint file_index, mz_file_write_func pCallback, void *pOpaque, mz_uint flags); +mz_bool mz_zip_reader_extract_file_to_callback(mz_zip_archive *pZip, const char *pFilename, mz_file_write_func pCallback, void *pOpaque, mz_uint flags); + +#ifndef MINIZ_NO_STDIO +// Extracts a archive file to a disk file and sets its last accessed and modified times. +// This function only extracts files, not archive directory records. +mz_bool mz_zip_reader_extract_to_file(mz_zip_archive *pZip, mz_uint file_index, const char *pDst_filename, mz_uint flags); +mz_bool mz_zip_reader_extract_file_to_file(mz_zip_archive *pZip, const char *pArchive_filename, const char *pDst_filename, mz_uint flags); +#endif + +// Ends archive reading, freeing all allocations, and closing the input archive file if mz_zip_reader_init_file() was used. +mz_bool mz_zip_reader_end(mz_zip_archive *pZip); + +// ZIP archive writing + +#ifndef MINIZ_NO_ARCHIVE_WRITING_APIS + +// Inits a ZIP archive writer. +mz_bool mz_zip_writer_init(mz_zip_archive *pZip, mz_uint64 existing_size); +mz_bool mz_zip_writer_init_heap(mz_zip_archive *pZip, size_t size_to_reserve_at_beginning, size_t initial_allocation_size); + +#ifndef MINIZ_NO_STDIO +mz_bool mz_zip_writer_init_file(mz_zip_archive *pZip, const char *pFilename, mz_uint64 size_to_reserve_at_beginning); +#endif + +// Converts a ZIP archive reader object into a writer object, to allow efficient in-place file appends to occur on an existing archive. +// For archives opened using mz_zip_reader_init_file, pFilename must be the archive's filename so it can be reopened for writing. If the file can't be reopened, mz_zip_reader_end() will be called. +// For archives opened using mz_zip_reader_init_mem, the memory block must be growable using the realloc callback (which defaults to realloc unless you've overridden it). +// Finally, for archives opened using mz_zip_reader_init, the mz_zip_archive's user provided m_pWrite function cannot be NULL. +// Note: In-place archive modification is not recommended unless you know what you're doing, because if execution stops or something goes wrong before +// the archive is finalized the file's central directory will be hosed. +mz_bool mz_zip_writer_init_from_reader(mz_zip_archive *pZip, const char *pFilename); + +// Adds the contents of a memory buffer to an archive. These functions record the current local time into the archive. +// To add a directory entry, call this method with an archive name ending in a forwardslash with empty buffer. +// level_and_flags - compression level (0-10, see MZ_BEST_SPEED, MZ_BEST_COMPRESSION, etc.) logically OR'd with zero or more mz_zip_flags, or just set to MZ_DEFAULT_COMPRESSION. +mz_bool mz_zip_writer_add_mem(mz_zip_archive *pZip, const char *pArchive_name, const void *pBuf, size_t buf_size, mz_uint level_and_flags); +mz_bool mz_zip_writer_add_mem_ex(mz_zip_archive *pZip, const char *pArchive_name, const void *pBuf, size_t buf_size, const void *pComment, mz_uint16 comment_size, mz_uint level_and_flags, mz_uint64 uncomp_size, mz_uint32 uncomp_crc32); + +#ifndef MINIZ_NO_STDIO +// Adds the contents of a disk file to an archive. This function also records the disk file's modified time into the archive. +// level_and_flags - compression level (0-10, see MZ_BEST_SPEED, MZ_BEST_COMPRESSION, etc.) logically OR'd with zero or more mz_zip_flags, or just set to MZ_DEFAULT_COMPRESSION. +mz_bool mz_zip_writer_add_file(mz_zip_archive *pZip, const char *pArchive_name, const char *pSrc_filename, const void *pComment, mz_uint16 comment_size, mz_uint level_and_flags); +#endif + +// Adds a file to an archive by fully cloning the data from another archive. +// This function fully clones the source file's compressed data (no recompression), along with its full filename, extra data, and comment fields. +mz_bool mz_zip_writer_add_from_zip_reader(mz_zip_archive *pZip, mz_zip_archive *pSource_zip, mz_uint file_index); + +// Finalizes the archive by writing the central directory records followed by the end of central directory record. +// After an archive is finalized, the only valid call on the mz_zip_archive struct is mz_zip_writer_end(). +// An archive must be manually finalized by calling this function for it to be valid. +mz_bool mz_zip_writer_finalize_archive(mz_zip_archive *pZip); +mz_bool mz_zip_writer_finalize_heap_archive(mz_zip_archive *pZip, void **pBuf, size_t *pSize); + +// Ends archive writing, freeing all allocations, and closing the output file if mz_zip_writer_init_file() was used. +// Note for the archive to be valid, it must have been finalized before ending. +mz_bool mz_zip_writer_end(mz_zip_archive *pZip); + +// Misc. high-level helper functions: + +// mz_zip_add_mem_to_archive_file_in_place() efficiently (but not atomically) appends a memory blob to a ZIP archive. +// level_and_flags - compression level (0-10, see MZ_BEST_SPEED, MZ_BEST_COMPRESSION, etc.) logically OR'd with zero or more mz_zip_flags, or just set to MZ_DEFAULT_COMPRESSION. +mz_bool mz_zip_add_mem_to_archive_file_in_place(const char *pZip_filename, const char *pArchive_name, const void *pBuf, size_t buf_size, const void *pComment, mz_uint16 comment_size, mz_uint level_and_flags); + +// Reads a single file from an archive into a heap block. +// Returns NULL on failure. +void *mz_zip_extract_archive_file_to_heap(const char *pZip_filename, const char *pArchive_name, size_t *pSize, mz_uint zip_flags); + +#endif // #ifndef MINIZ_NO_ARCHIVE_WRITING_APIS + +#endif // #ifndef MINIZ_NO_ARCHIVE_APIS + +// ------------------- Low-level Decompression API Definitions + +// Decompression flags used by tinfl_decompress(). +// TINFL_FLAG_PARSE_ZLIB_HEADER: If set, the input has a valid zlib header and ends with an adler32 checksum (it's a valid zlib stream). Otherwise, the input is a raw deflate stream. +// TINFL_FLAG_HAS_MORE_INPUT: If set, there are more input bytes available beyond the end of the supplied input buffer. If clear, the input buffer contains all remaining input. +// TINFL_FLAG_USING_NON_WRAPPING_OUTPUT_BUF: If set, the output buffer is large enough to hold the entire decompressed stream. If clear, the output buffer is at least the size of the dictionary (typically 32KB). +// TINFL_FLAG_COMPUTE_ADLER32: Force adler-32 checksum computation of the decompressed bytes. +enum +{ + TINFL_FLAG_PARSE_ZLIB_HEADER = 1, + TINFL_FLAG_HAS_MORE_INPUT = 2, + TINFL_FLAG_USING_NON_WRAPPING_OUTPUT_BUF = 4, + TINFL_FLAG_COMPUTE_ADLER32 = 8 +}; + +// High level decompression functions: +// tinfl_decompress_mem_to_heap() decompresses a block in memory to a heap block allocated via malloc(). +// On entry: +// pSrc_buf, src_buf_len: Pointer and size of the Deflate or zlib source data to decompress. +// On return: +// Function returns a pointer to the decompressed data, or NULL on failure. +// *pOut_len will be set to the decompressed data's size, which could be larger than src_buf_len on uncompressible data. +// The caller must call mz_free() on the returned block when it's no longer needed. +void *tinfl_decompress_mem_to_heap(const void *pSrc_buf, size_t src_buf_len, size_t *pOut_len, int flags); + +// tinfl_decompress_mem_to_mem() decompresses a block in memory to another block in memory. +// Returns TINFL_DECOMPRESS_MEM_TO_MEM_FAILED on failure, or the number of bytes written on success. +#define TINFL_DECOMPRESS_MEM_TO_MEM_FAILED ((size_t)(-1)) +size_t tinfl_decompress_mem_to_mem(void *pOut_buf, size_t out_buf_len, const void *pSrc_buf, size_t src_buf_len, int flags); + +// tinfl_decompress_mem_to_callback() decompresses a block in memory to an internal 32KB buffer, and a user provided callback function will be called to flush the buffer. +// Returns 1 on success or 0 on failure. +typedef int (*tinfl_put_buf_func_ptr)(const void* pBuf, int len, void *pUser); +int tinfl_decompress_mem_to_callback(const void *pIn_buf, size_t *pIn_buf_size, tinfl_put_buf_func_ptr pPut_buf_func, void *pPut_buf_user, int flags); + +struct tinfl_decompressor_tag; typedef struct tinfl_decompressor_tag tinfl_decompressor; + +// Max size of LZ dictionary. +#define TINFL_LZ_DICT_SIZE 32768 + +// Return status. +typedef enum +{ + TINFL_STATUS_BAD_PARAM = -3, + TINFL_STATUS_ADLER32_MISMATCH = -2, + TINFL_STATUS_FAILED = -1, + TINFL_STATUS_DONE = 0, + TINFL_STATUS_NEEDS_MORE_INPUT = 1, + TINFL_STATUS_HAS_MORE_OUTPUT = 2 +} tinfl_status; + +// Initializes the decompressor to its initial state. +#define tinfl_init(r) do { (r)->m_state = 0; } MZ_MACRO_END +#define tinfl_get_adler32(r) (r)->m_check_adler32 + +// Main low-level decompressor coroutine function. This is the only function actually needed for decompression. All the other functions are just high-level helpers for improved usability. +// This is a universal API, i.e. it can be used as a building block to build any desired higher level decompression API. In the limit case, it can be called once per every byte input or output. +tinfl_status tinfl_decompress(tinfl_decompressor *r, const mz_uint8 *pIn_buf_next, size_t *pIn_buf_size, mz_uint8 *pOut_buf_start, mz_uint8 *pOut_buf_next, size_t *pOut_buf_size, const mz_uint32 decomp_flags); + +// Internal/private bits follow. +enum +{ + TINFL_MAX_HUFF_TABLES = 3, TINFL_MAX_HUFF_SYMBOLS_0 = 288, TINFL_MAX_HUFF_SYMBOLS_1 = 32, TINFL_MAX_HUFF_SYMBOLS_2 = 19, + TINFL_FAST_LOOKUP_BITS = 10, TINFL_FAST_LOOKUP_SIZE = 1 << TINFL_FAST_LOOKUP_BITS +}; + +typedef struct +{ + mz_uint8 m_code_size[TINFL_MAX_HUFF_SYMBOLS_0]; + mz_int16 m_look_up[TINFL_FAST_LOOKUP_SIZE], m_tree[TINFL_MAX_HUFF_SYMBOLS_0 * 2]; +} tinfl_huff_table; + +#if MINIZ_HAS_64BIT_REGISTERS + #define TINFL_USE_64BIT_BITBUF 1 +#endif + +#if TINFL_USE_64BIT_BITBUF + typedef mz_uint64 tinfl_bit_buf_t; + #define TINFL_BITBUF_SIZE (64) +#else + typedef mz_uint32 tinfl_bit_buf_t; + #define TINFL_BITBUF_SIZE (32) +#endif + +struct tinfl_decompressor_tag +{ + mz_uint32 m_state, m_num_bits, m_zhdr0, m_zhdr1, m_z_adler32, m_final, m_type, m_check_adler32, m_dist, m_counter, m_num_extra, m_table_sizes[TINFL_MAX_HUFF_TABLES]; + tinfl_bit_buf_t m_bit_buf; + size_t m_dist_from_out_buf_start; + tinfl_huff_table m_tables[TINFL_MAX_HUFF_TABLES]; + mz_uint8 m_raw_header[4], m_len_codes[TINFL_MAX_HUFF_SYMBOLS_0 + TINFL_MAX_HUFF_SYMBOLS_1 + 137]; +}; + +// ------------------- Low-level Compression API Definitions + +// Set TDEFL_LESS_MEMORY to 1 to use less memory (compression will be slightly slower, and raw/dynamic blocks will be output more frequently). +#define TDEFL_LESS_MEMORY 1 + +// tdefl_init() compression flags logically OR'd together (low 12 bits contain the max. number of probes per dictionary search): +// TDEFL_DEFAULT_MAX_PROBES: The compressor defaults to 128 dictionary probes per dictionary search. 0=Huffman only, 1=Huffman+LZ (fastest/crap compression), 4095=Huffman+LZ (slowest/best compression). +enum +{ + TDEFL_HUFFMAN_ONLY = 0, TDEFL_DEFAULT_MAX_PROBES = 128, TDEFL_MAX_PROBES_MASK = 0xFFF +}; + +// TDEFL_WRITE_ZLIB_HEADER: If set, the compressor outputs a zlib header before the deflate data, and the Adler-32 of the source data at the end. Otherwise, you'll get raw deflate data. +// TDEFL_COMPUTE_ADLER32: Always compute the adler-32 of the input data (even when not writing zlib headers). +// TDEFL_GREEDY_PARSING_FLAG: Set to use faster greedy parsing, instead of more efficient lazy parsing. +// TDEFL_NONDETERMINISTIC_PARSING_FLAG: Enable to decrease the compressor's initialization time to the minimum, but the output may vary from run to run given the same input (depending on the contents of memory). +// TDEFL_RLE_MATCHES: Only look for RLE matches (matches with a distance of 1) +// TDEFL_FILTER_MATCHES: Discards matches <= 5 chars if enabled. +// TDEFL_FORCE_ALL_STATIC_BLOCKS: Disable usage of optimized Huffman tables. +// TDEFL_FORCE_ALL_RAW_BLOCKS: Only use raw (uncompressed) deflate blocks. +// The low 12 bits are reserved to control the max # of hash probes per dictionary lookup (see TDEFL_MAX_PROBES_MASK). +enum +{ + TDEFL_WRITE_ZLIB_HEADER = 0x01000, + TDEFL_COMPUTE_ADLER32 = 0x02000, + TDEFL_GREEDY_PARSING_FLAG = 0x04000, + TDEFL_NONDETERMINISTIC_PARSING_FLAG = 0x08000, + TDEFL_RLE_MATCHES = 0x10000, + TDEFL_FILTER_MATCHES = 0x20000, + TDEFL_FORCE_ALL_STATIC_BLOCKS = 0x40000, + TDEFL_FORCE_ALL_RAW_BLOCKS = 0x80000 +}; + +// High level compression functions: +// tdefl_compress_mem_to_heap() compresses a block in memory to a heap block allocated via malloc(). +// On entry: +// pSrc_buf, src_buf_len: Pointer and size of source block to compress. +// flags: The max match finder probes (default is 128) logically OR'd against the above flags. Higher probes are slower but improve compression. +// On return: +// Function returns a pointer to the compressed data, or NULL on failure. +// *pOut_len will be set to the compressed data's size, which could be larger than src_buf_len on uncompressible data. +// The caller must free() the returned block when it's no longer needed. +void *tdefl_compress_mem_to_heap(const void *pSrc_buf, size_t src_buf_len, size_t *pOut_len, int flags); + +// tdefl_compress_mem_to_mem() compresses a block in memory to another block in memory. +// Returns 0 on failure. +size_t tdefl_compress_mem_to_mem(void *pOut_buf, size_t out_buf_len, const void *pSrc_buf, size_t src_buf_len, int flags); + +// Compresses an image to a compressed PNG file in memory. +// On entry: +// pImage, w, h, and num_chans describe the image to compress. num_chans may be 1, 2, 3, or 4. +// The image pitch in bytes per scanline will be w*num_chans. The leftmost pixel on the top scanline is stored first in memory. +// level may range from [0,10], use MZ_NO_COMPRESSION, MZ_BEST_SPEED, MZ_BEST_COMPRESSION, etc. or a decent default is MZ_DEFAULT_LEVEL +// If flip is true, the image will be flipped on the Y axis (useful for OpenGL apps). +// On return: +// Function returns a pointer to the compressed data, or NULL on failure. +// *pLen_out will be set to the size of the PNG image file. +// The caller must mz_free() the returned heap block (which will typically be larger than *pLen_out) when it's no longer needed. +void *tdefl_write_image_to_png_file_in_memory_ex(const void *pImage, int w, int h, int num_chans, size_t *pLen_out, mz_uint level, mz_bool flip); +void *tdefl_write_image_to_png_file_in_memory(const void *pImage, int w, int h, int num_chans, size_t *pLen_out); + +// Output stream interface. The compressor uses this interface to write compressed data. It'll typically be called TDEFL_OUT_BUF_SIZE at a time. +typedef mz_bool (*tdefl_put_buf_func_ptr)(const void* pBuf, int len, void *pUser); + +// tdefl_compress_mem_to_output() compresses a block to an output stream. The above helpers use this function internally. +mz_bool tdefl_compress_mem_to_output(const void *pBuf, size_t buf_len, tdefl_put_buf_func_ptr pPut_buf_func, void *pPut_buf_user, int flags); + +enum { TDEFL_MAX_HUFF_TABLES = 3, TDEFL_MAX_HUFF_SYMBOLS_0 = 288, TDEFL_MAX_HUFF_SYMBOLS_1 = 32, TDEFL_MAX_HUFF_SYMBOLS_2 = 19, TDEFL_LZ_DICT_SIZE = 32768, TDEFL_LZ_DICT_SIZE_MASK = TDEFL_LZ_DICT_SIZE - 1, TDEFL_MIN_MATCH_LEN = 3, TDEFL_MAX_MATCH_LEN = 258 }; + +// TDEFL_OUT_BUF_SIZE MUST be large enough to hold a single entire compressed output block (using static/fixed Huffman codes). +#if TDEFL_LESS_MEMORY +enum { TDEFL_LZ_CODE_BUF_SIZE = 24 * 1024, TDEFL_OUT_BUF_SIZE = (TDEFL_LZ_CODE_BUF_SIZE * 13 ) / 10, TDEFL_MAX_HUFF_SYMBOLS = 288, TDEFL_LZ_HASH_BITS = 12, TDEFL_LEVEL1_HASH_SIZE_MASK = 4095, TDEFL_LZ_HASH_SHIFT = (TDEFL_LZ_HASH_BITS + 2) / 3, TDEFL_LZ_HASH_SIZE = 1 << TDEFL_LZ_HASH_BITS }; +#else +enum { TDEFL_LZ_CODE_BUF_SIZE = 64 * 1024, TDEFL_OUT_BUF_SIZE = (TDEFL_LZ_CODE_BUF_SIZE * 13 ) / 10, TDEFL_MAX_HUFF_SYMBOLS = 288, TDEFL_LZ_HASH_BITS = 15, TDEFL_LEVEL1_HASH_SIZE_MASK = 4095, TDEFL_LZ_HASH_SHIFT = (TDEFL_LZ_HASH_BITS + 2) / 3, TDEFL_LZ_HASH_SIZE = 1 << TDEFL_LZ_HASH_BITS }; +#endif + +// The low-level tdefl functions below may be used directly if the above helper functions aren't flexible enough. The low-level functions don't make any heap allocations, unlike the above helper functions. +typedef enum +{ + TDEFL_STATUS_BAD_PARAM = -2, + TDEFL_STATUS_PUT_BUF_FAILED = -1, + TDEFL_STATUS_OKAY = 0, + TDEFL_STATUS_DONE = 1, +} tdefl_status; + +// Must map to MZ_NO_FLUSH, MZ_SYNC_FLUSH, etc. enums +typedef enum +{ + TDEFL_NO_FLUSH = 0, + TDEFL_SYNC_FLUSH = 2, + TDEFL_FULL_FLUSH = 3, + TDEFL_FINISH = 4 +} tdefl_flush; + +// tdefl's compression state structure. +typedef struct +{ + tdefl_put_buf_func_ptr m_pPut_buf_func; + void *m_pPut_buf_user; + mz_uint m_flags, m_max_probes[2]; + int m_greedy_parsing; + mz_uint m_adler32, m_lookahead_pos, m_lookahead_size, m_dict_size; + mz_uint8 *m_pLZ_code_buf, *m_pLZ_flags, *m_pOutput_buf, *m_pOutput_buf_end; + mz_uint m_num_flags_left, m_total_lz_bytes, m_lz_code_buf_dict_pos, m_bits_in, m_bit_buffer; + mz_uint m_saved_match_dist, m_saved_match_len, m_saved_lit, m_output_flush_ofs, m_output_flush_remaining, m_finished, m_block_index, m_wants_to_finish; + tdefl_status m_prev_return_status; + const void *m_pIn_buf; + void *m_pOut_buf; + size_t *m_pIn_buf_size, *m_pOut_buf_size; + tdefl_flush m_flush; + const mz_uint8 *m_pSrc; + size_t m_src_buf_left, m_out_buf_ofs; + mz_uint8 m_dict[TDEFL_LZ_DICT_SIZE + TDEFL_MAX_MATCH_LEN - 1]; + mz_uint16 m_huff_count[TDEFL_MAX_HUFF_TABLES][TDEFL_MAX_HUFF_SYMBOLS]; + mz_uint16 m_huff_codes[TDEFL_MAX_HUFF_TABLES][TDEFL_MAX_HUFF_SYMBOLS]; + mz_uint8 m_huff_code_sizes[TDEFL_MAX_HUFF_TABLES][TDEFL_MAX_HUFF_SYMBOLS]; + mz_uint8 m_lz_code_buf[TDEFL_LZ_CODE_BUF_SIZE]; + mz_uint16 m_next[TDEFL_LZ_DICT_SIZE]; + mz_uint16 m_hash[TDEFL_LZ_HASH_SIZE]; + mz_uint8 m_output_buf[TDEFL_OUT_BUF_SIZE]; +} tdefl_compressor; + +// Initializes the compressor. +// There is no corresponding deinit() function because the tdefl API's do not dynamically allocate memory. +// pBut_buf_func: If NULL, output data will be supplied to the specified callback. In this case, the user should call the tdefl_compress_buffer() API for compression. +// If pBut_buf_func is NULL the user should always call the tdefl_compress() API. +// flags: See the above enums (TDEFL_HUFFMAN_ONLY, TDEFL_WRITE_ZLIB_HEADER, etc.) +tdefl_status tdefl_init(tdefl_compressor *d, tdefl_put_buf_func_ptr pPut_buf_func, void *pPut_buf_user, int flags); + +// Compresses a block of data, consuming as much of the specified input buffer as possible, and writing as much compressed data to the specified output buffer as possible. +tdefl_status tdefl_compress(tdefl_compressor *d, const void *pIn_buf, size_t *pIn_buf_size, void *pOut_buf, size_t *pOut_buf_size, tdefl_flush flush); + +// tdefl_compress_buffer() is only usable when the tdefl_init() is called with a non-NULL tdefl_put_buf_func_ptr. +// tdefl_compress_buffer() always consumes the entire input buffer. +tdefl_status tdefl_compress_buffer(tdefl_compressor *d, const void *pIn_buf, size_t in_buf_size, tdefl_flush flush); + +tdefl_status tdefl_get_prev_return_status(tdefl_compressor *d); +mz_uint32 tdefl_get_adler32(tdefl_compressor *d); + +// Can't use tdefl_create_comp_flags_from_zip_params if MINIZ_NO_ZLIB_APIS isn't defined, because it uses some of its macros. +#ifndef MINIZ_NO_ZLIB_APIS +// Create tdefl_compress() flags given zlib-style compression parameters. +// level may range from [0,10] (where 10 is absolute max compression, but may be much slower on some files) +// window_bits may be -15 (raw deflate) or 15 (zlib) +// strategy may be either MZ_DEFAULT_STRATEGY, MZ_FILTERED, MZ_HUFFMAN_ONLY, MZ_RLE, or MZ_FIXED +mz_uint tdefl_create_comp_flags_from_zip_params(int level, int window_bits, int strategy); +#endif // #ifndef MINIZ_NO_ZLIB_APIS + +#ifdef __cplusplus +} +#endif + +#endif // MINIZ_HEADER_INCLUDED + diff --git a/components/esp32/include/rom/queue.h b/components/esp32/include/rom/queue.h new file mode 100755 index 0000000000..29ee670600 --- /dev/null +++ b/components/esp32/include/rom/queue.h @@ -0,0 +1,645 @@ +/*- + * Copyright (c) 1991, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)queue.h 8.5 (Berkeley) 8/20/94 + * $FreeBSD$ + */ + +#ifndef _SYS_QUEUE_H_ +#define _SYS_QUEUE_H_ + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/* + * This file defines four types of data structures: singly-linked lists, + * singly-linked tail queues, lists and tail queues. + * + * A singly-linked list is headed by a single forward pointer. The elements + * are singly linked for minimum space and pointer manipulation overhead at + * the expense of O(n) removal for arbitrary elements. New elements can be + * added to the list after an existing element or at the head of the list. + * Elements being removed from the head of the list should use the explicit + * macro for this purpose for optimum efficiency. A singly-linked list may + * only be traversed in the forward direction. Singly-linked lists are ideal + * for applications with large datasets and few or no removals or for + * implementing a LIFO queue. + * + * A singly-linked tail queue is headed by a pair of pointers, one to the + * head of the list and the other to the tail of the list. The elements are + * singly linked for minimum space and pointer manipulation overhead at the + * expense of O(n) removal for arbitrary elements. New elements can be added + * to the list after an existing element, at the head of the list, or at the + * end of the list. Elements being removed from the head of the tail queue + * should use the explicit macro for this purpose for optimum efficiency. + * A singly-linked tail queue may only be traversed in the forward direction. + * Singly-linked tail queues are ideal for applications with large datasets + * and few or no removals or for implementing a FIFO queue. + * + * A list is headed by a single forward pointer (or an array of forward + * pointers for a hash table header). The elements are doubly linked + * so that an arbitrary element can be removed without a need to + * traverse the list. New elements can be added to the list before + * or after an existing element or at the head of the list. A list + * may only be traversed in the forward direction. + * + * A tail queue is headed by a pair of pointers, one to the head of the + * list and the other to the tail of the list. The elements are doubly + * linked so that an arbitrary element can be removed without a need to + * traverse the list. New elements can be added to the list before or + * after an existing element, at the head of the list, or at the end of + * the list. A tail queue may be traversed in either direction. + * + * For details on the use of these macros, see the queue(3) manual page. + * + * + * SLIST LIST STAILQ TAILQ + * _HEAD + + + + + * _HEAD_INITIALIZER + + + + + * _ENTRY + + + + + * _INIT + + + + + * _EMPTY + + + + + * _FIRST + + + + + * _NEXT + + + + + * _PREV - - - + + * _LAST - - + + + * _FOREACH + + + + + * _FOREACH_SAFE + + + + + * _FOREACH_REVERSE - - - + + * _FOREACH_REVERSE_SAFE - - - + + * _INSERT_HEAD + + + + + * _INSERT_BEFORE - + - + + * _INSERT_AFTER + + + + + * _INSERT_TAIL - - + + + * _CONCAT - - + + + * _REMOVE_AFTER + - + - + * _REMOVE_HEAD + - + - + * _REMOVE + + + + + * + */ +#ifdef QUEUE_MACRO_DEBUG +/* Store the last 2 places the queue element or head was altered */ +struct qm_trace { + char * lastfile; + int lastline; + char * prevfile; + int prevline; +}; + +#define TRACEBUF struct qm_trace trace; +#define TRASHIT(x) do {(x) = (void *)-1;} while (0) +#define QMD_SAVELINK(name, link) void **name = (void *)&(link) + +#define QMD_TRACE_HEAD(head) do { \ + (head)->trace.prevline = (head)->trace.lastline; \ + (head)->trace.prevfile = (head)->trace.lastfile; \ + (head)->trace.lastline = __LINE__; \ + (head)->trace.lastfile = __FILE__; \ +} while (0) + +#define QMD_TRACE_ELEM(elem) do { \ + (elem)->trace.prevline = (elem)->trace.lastline; \ + (elem)->trace.prevfile = (elem)->trace.lastfile; \ + (elem)->trace.lastline = __LINE__; \ + (elem)->trace.lastfile = __FILE__; \ +} while (0) + +#else +#define QMD_TRACE_ELEM(elem) +#define QMD_TRACE_HEAD(head) +#define QMD_SAVELINK(name, link) +#define TRACEBUF +#define TRASHIT(x) +#endif /* QUEUE_MACRO_DEBUG */ + +/* + * Singly-linked List declarations. + */ +#define SLIST_HEAD(name, type) \ +struct name { \ + struct type *slh_first; /* first element */ \ +} + +#define SLIST_HEAD_INITIALIZER(head) \ + { NULL } + +#define SLIST_ENTRY(type) \ +struct { \ + struct type *sle_next; /* next element */ \ +} + +/* + * Singly-linked List functions. + */ +#define SLIST_EMPTY(head) ((head)->slh_first == NULL) + +#define SLIST_FIRST(head) ((head)->slh_first) + +#define SLIST_FOREACH(var, head, field) \ + for ((var) = SLIST_FIRST((head)); \ + (var); \ + (var) = SLIST_NEXT((var), field)) + +#define SLIST_FOREACH_SAFE(var, head, field, tvar) \ + for ((var) = SLIST_FIRST((head)); \ + (var) && ((tvar) = SLIST_NEXT((var), field), 1); \ + (var) = (tvar)) + +#define SLIST_FOREACH_PREVPTR(var, varp, head, field) \ + for ((varp) = &SLIST_FIRST((head)); \ + ((var) = *(varp)) != NULL; \ + (varp) = &SLIST_NEXT((var), field)) + +#define SLIST_INIT(head) do { \ + SLIST_FIRST((head)) = NULL; \ +} while (0) + +#define SLIST_INSERT_AFTER(slistelm, elm, field) do { \ + SLIST_NEXT((elm), field) = SLIST_NEXT((slistelm), field); \ + SLIST_NEXT((slistelm), field) = (elm); \ +} while (0) + +#define SLIST_INSERT_HEAD(head, elm, field) do { \ + SLIST_NEXT((elm), field) = SLIST_FIRST((head)); \ + SLIST_FIRST((head)) = (elm); \ +} while (0) + +#define SLIST_NEXT(elm, field) ((elm)->field.sle_next) + +#define SLIST_REMOVE(head, elm, type, field) do { \ + QMD_SAVELINK(oldnext, (elm)->field.sle_next); \ + if (SLIST_FIRST((head)) == (elm)) { \ + SLIST_REMOVE_HEAD((head), field); \ + } \ + else { \ + struct type *curelm = SLIST_FIRST((head)); \ + while (SLIST_NEXT(curelm, field) != (elm)) \ + curelm = SLIST_NEXT(curelm, field); \ + SLIST_REMOVE_AFTER(curelm, field); \ + } \ + TRASHIT(*oldnext); \ +} while (0) + +#define SLIST_REMOVE_AFTER(elm, field) do { \ + SLIST_NEXT(elm, field) = \ + SLIST_NEXT(SLIST_NEXT(elm, field), field); \ +} while (0) + +#define SLIST_REMOVE_HEAD(head, field) do { \ + SLIST_FIRST((head)) = SLIST_NEXT(SLIST_FIRST((head)), field); \ +} while (0) + +/* + * Singly-linked Tail queue declarations. + */ +#define STAILQ_HEAD(name, type) \ +struct name { \ + struct type *stqh_first;/* first element */ \ + struct type **stqh_last;/* addr of last next element */ \ +} + +#define STAILQ_HEAD_INITIALIZER(head) \ + { NULL, &(head).stqh_first } + +#define STAILQ_ENTRY(type) \ +struct { \ + struct type *stqe_next; /* next element */ \ +} + +/* + * Singly-linked Tail queue functions. + */ +#define STAILQ_CONCAT(head1, head2) do { \ + if (!STAILQ_EMPTY((head2))) { \ + *(head1)->stqh_last = (head2)->stqh_first; \ + (head1)->stqh_last = (head2)->stqh_last; \ + STAILQ_INIT((head2)); \ + } \ +} while (0) + +#define STAILQ_EMPTY(head) ((head)->stqh_first == NULL) + +#define STAILQ_FIRST(head) ((head)->stqh_first) + +#define STAILQ_FOREACH(var, head, field) \ + for((var) = STAILQ_FIRST((head)); \ + (var); \ + (var) = STAILQ_NEXT((var), field)) + + +#define STAILQ_FOREACH_SAFE(var, head, field, tvar) \ + for ((var) = STAILQ_FIRST((head)); \ + (var) && ((tvar) = STAILQ_NEXT((var), field), 1); \ + (var) = (tvar)) + +#define STAILQ_INIT(head) do { \ + STAILQ_FIRST((head)) = NULL; \ + (head)->stqh_last = &STAILQ_FIRST((head)); \ +} while (0) + +#define STAILQ_INSERT_AFTER(head, tqelm, elm, field) do { \ + if ((STAILQ_NEXT((elm), field) = STAILQ_NEXT((tqelm), field)) == NULL)\ + (head)->stqh_last = &STAILQ_NEXT((elm), field); \ + STAILQ_NEXT((tqelm), field) = (elm); \ +} while (0) + +#define STAILQ_INSERT_HEAD(head, elm, field) do { \ + if ((STAILQ_NEXT((elm), field) = STAILQ_FIRST((head))) == NULL) \ + (head)->stqh_last = &STAILQ_NEXT((elm), field); \ + STAILQ_FIRST((head)) = (elm); \ +} while (0) + +#define STAILQ_INSERT_TAIL(head, elm, field) do { \ + STAILQ_NEXT((elm), field) = NULL; \ + *(head)->stqh_last = (elm); \ + (head)->stqh_last = &STAILQ_NEXT((elm), field); \ +} while (0) + +#define STAILQ_LAST(head, type, field) \ + (STAILQ_EMPTY((head)) ? \ + NULL : \ + ((struct type *)(void *) \ + ((char *)((head)->stqh_last) - __offsetof(struct type, field)))) + +#define STAILQ_NEXT(elm, field) ((elm)->field.stqe_next) + +#define STAILQ_REMOVE(head, elm, type, field) do { \ + QMD_SAVELINK(oldnext, (elm)->field.stqe_next); \ + if (STAILQ_FIRST((head)) == (elm)) { \ + STAILQ_REMOVE_HEAD((head), field); \ + } \ + else { \ + struct type *curelm = STAILQ_FIRST((head)); \ + while (STAILQ_NEXT(curelm, field) != (elm)) \ + curelm = STAILQ_NEXT(curelm, field); \ + STAILQ_REMOVE_AFTER(head, curelm, field); \ + } \ + TRASHIT(*oldnext); \ +} while (0) + +#define STAILQ_REMOVE_HEAD(head, field) do { \ + if ((STAILQ_FIRST((head)) = \ + STAILQ_NEXT(STAILQ_FIRST((head)), field)) == NULL) \ + (head)->stqh_last = &STAILQ_FIRST((head)); \ +} while (0) + +#define STAILQ_REMOVE_AFTER(head, elm, field) do { \ + if ((STAILQ_NEXT(elm, field) = \ + STAILQ_NEXT(STAILQ_NEXT(elm, field), field)) == NULL) \ + (head)->stqh_last = &STAILQ_NEXT((elm), field); \ +} while (0) + +#define STAILQ_SWAP(head1, head2, type) do { \ + struct type *swap_first = STAILQ_FIRST(head1); \ + struct type **swap_last = (head1)->stqh_last; \ + STAILQ_FIRST(head1) = STAILQ_FIRST(head2); \ + (head1)->stqh_last = (head2)->stqh_last; \ + STAILQ_FIRST(head2) = swap_first; \ + (head2)->stqh_last = swap_last; \ + if (STAILQ_EMPTY(head1)) \ + (head1)->stqh_last = &STAILQ_FIRST(head1); \ + if (STAILQ_EMPTY(head2)) \ + (head2)->stqh_last = &STAILQ_FIRST(head2); \ +} while (0) + +#define STAILQ_INSERT_CHAIN_HEAD(head, elm_chead, elm_ctail, field) do { \ + if ((STAILQ_NEXT(elm_ctail, field) = STAILQ_FIRST(head)) == NULL ) { \ + (head)->stqh_last = &STAILQ_NEXT(elm_ctail, field); \ + } \ + STAILQ_FIRST(head) = (elm_chead); \ +} while (0) + + +/* + * List declarations. + */ +#define LIST_HEAD(name, type) \ +struct name { \ + struct type *lh_first; /* first element */ \ +} + +#define LIST_HEAD_INITIALIZER(head) \ + { NULL } + +#define LIST_ENTRY(type) \ +struct { \ + struct type *le_next; /* next element */ \ + struct type **le_prev; /* address of previous next element */ \ +} + +/* + * List functions. + */ + +#if (defined(_KERNEL) && defined(INVARIANTS)) +#define QMD_LIST_CHECK_HEAD(head, field) do { \ + if (LIST_FIRST((head)) != NULL && \ + LIST_FIRST((head))->field.le_prev != \ + &LIST_FIRST((head))) \ + panic("Bad list head %p first->prev != head", (head)); \ +} while (0) + +#define QMD_LIST_CHECK_NEXT(elm, field) do { \ + if (LIST_NEXT((elm), field) != NULL && \ + LIST_NEXT((elm), field)->field.le_prev != \ + &((elm)->field.le_next)) \ + panic("Bad link elm %p next->prev != elm", (elm)); \ +} while (0) + +#define QMD_LIST_CHECK_PREV(elm, field) do { \ + if (*(elm)->field.le_prev != (elm)) \ + panic("Bad link elm %p prev->next != elm", (elm)); \ +} while (0) +#else +#define QMD_LIST_CHECK_HEAD(head, field) +#define QMD_LIST_CHECK_NEXT(elm, field) +#define QMD_LIST_CHECK_PREV(elm, field) +#endif /* (_KERNEL && INVARIANTS) */ + +#define LIST_EMPTY(head) ((head)->lh_first == NULL) + +#define LIST_FIRST(head) ((head)->lh_first) + +#define LIST_FOREACH(var, head, field) \ + for ((var) = LIST_FIRST((head)); \ + (var); \ + (var) = LIST_NEXT((var), field)) + +#define LIST_FOREACH_SAFE(var, head, field, tvar) \ + for ((var) = LIST_FIRST((head)); \ + (var) && ((tvar) = LIST_NEXT((var), field), 1); \ + (var) = (tvar)) + +#define LIST_INIT(head) do { \ + LIST_FIRST((head)) = NULL; \ +} while (0) + +#define LIST_INSERT_AFTER(listelm, elm, field) do { \ + QMD_LIST_CHECK_NEXT(listelm, field); \ + if ((LIST_NEXT((elm), field) = LIST_NEXT((listelm), field)) != NULL)\ + LIST_NEXT((listelm), field)->field.le_prev = \ + &LIST_NEXT((elm), field); \ + LIST_NEXT((listelm), field) = (elm); \ + (elm)->field.le_prev = &LIST_NEXT((listelm), field); \ +} while (0) + +#define LIST_INSERT_BEFORE(listelm, elm, field) do { \ + QMD_LIST_CHECK_PREV(listelm, field); \ + (elm)->field.le_prev = (listelm)->field.le_prev; \ + LIST_NEXT((elm), field) = (listelm); \ + *(listelm)->field.le_prev = (elm); \ + (listelm)->field.le_prev = &LIST_NEXT((elm), field); \ +} while (0) + +#define LIST_INSERT_HEAD(head, elm, field) do { \ + QMD_LIST_CHECK_HEAD((head), field); \ + if ((LIST_NEXT((elm), field) = LIST_FIRST((head))) != NULL) \ + LIST_FIRST((head))->field.le_prev = &LIST_NEXT((elm), field);\ + LIST_FIRST((head)) = (elm); \ + (elm)->field.le_prev = &LIST_FIRST((head)); \ +} while (0) + +#define LIST_NEXT(elm, field) ((elm)->field.le_next) + +#define LIST_REMOVE(elm, field) do { \ + QMD_SAVELINK(oldnext, (elm)->field.le_next); \ + QMD_SAVELINK(oldprev, (elm)->field.le_prev); \ + QMD_LIST_CHECK_NEXT(elm, field); \ + QMD_LIST_CHECK_PREV(elm, field); \ + if (LIST_NEXT((elm), field) != NULL) \ + LIST_NEXT((elm), field)->field.le_prev = \ + (elm)->field.le_prev; \ + *(elm)->field.le_prev = LIST_NEXT((elm), field); \ + TRASHIT(*oldnext); \ + TRASHIT(*oldprev); \ +} while (0) + +#define LIST_SWAP(head1, head2, type, field) do { \ + struct type *swap_tmp = LIST_FIRST((head1)); \ + LIST_FIRST((head1)) = LIST_FIRST((head2)); \ + LIST_FIRST((head2)) = swap_tmp; \ + if ((swap_tmp = LIST_FIRST((head1))) != NULL) \ + swap_tmp->field.le_prev = &LIST_FIRST((head1)); \ + if ((swap_tmp = LIST_FIRST((head2))) != NULL) \ + swap_tmp->field.le_prev = &LIST_FIRST((head2)); \ +} while (0) + +/* + * Tail queue declarations. + */ +#define TAILQ_HEAD(name, type) \ +struct name { \ + struct type *tqh_first; /* first element */ \ + struct type **tqh_last; /* addr of last next element */ \ + TRACEBUF \ +} + +#define TAILQ_HEAD_INITIALIZER(head) \ + { NULL, &(head).tqh_first } + +#define TAILQ_ENTRY(type) \ +struct { \ + struct type *tqe_next; /* next element */ \ + struct type **tqe_prev; /* address of previous next element */ \ + TRACEBUF \ +} + +/* + * Tail queue functions. + */ +#if (defined(_KERNEL) && defined(INVARIANTS)) +#define QMD_TAILQ_CHECK_HEAD(head, field) do { \ + if (!TAILQ_EMPTY(head) && \ + TAILQ_FIRST((head))->field.tqe_prev != \ + &TAILQ_FIRST((head))) \ + panic("Bad tailq head %p first->prev != head", (head)); \ +} while (0) + +#define QMD_TAILQ_CHECK_TAIL(head, field) do { \ + if (*(head)->tqh_last != NULL) \ + panic("Bad tailq NEXT(%p->tqh_last) != NULL", (head)); \ +} while (0) + +#define QMD_TAILQ_CHECK_NEXT(elm, field) do { \ + if (TAILQ_NEXT((elm), field) != NULL && \ + TAILQ_NEXT((elm), field)->field.tqe_prev != \ + &((elm)->field.tqe_next)) \ + panic("Bad link elm %p next->prev != elm", (elm)); \ +} while (0) + +#define QMD_TAILQ_CHECK_PREV(elm, field) do { \ + if (*(elm)->field.tqe_prev != (elm)) \ + panic("Bad link elm %p prev->next != elm", (elm)); \ +} while (0) +#else +#define QMD_TAILQ_CHECK_HEAD(head, field) +#define QMD_TAILQ_CHECK_TAIL(head, headname) +#define QMD_TAILQ_CHECK_NEXT(elm, field) +#define QMD_TAILQ_CHECK_PREV(elm, field) +#endif /* (_KERNEL && INVARIANTS) */ + +#define TAILQ_CONCAT(head1, head2, field) do { \ + if (!TAILQ_EMPTY(head2)) { \ + *(head1)->tqh_last = (head2)->tqh_first; \ + (head2)->tqh_first->field.tqe_prev = (head1)->tqh_last; \ + (head1)->tqh_last = (head2)->tqh_last; \ + TAILQ_INIT((head2)); \ + QMD_TRACE_HEAD(head1); \ + QMD_TRACE_HEAD(head2); \ + } \ +} while (0) + +#define TAILQ_EMPTY(head) ((head)->tqh_first == NULL) + +#define TAILQ_FIRST(head) ((head)->tqh_first) + +#define TAILQ_FOREACH(var, head, field) \ + for ((var) = TAILQ_FIRST((head)); \ + (var); \ + (var) = TAILQ_NEXT((var), field)) + +#define TAILQ_FOREACH_SAFE(var, head, field, tvar) \ + for ((var) = TAILQ_FIRST((head)); \ + (var) && ((tvar) = TAILQ_NEXT((var), field), 1); \ + (var) = (tvar)) + +#define TAILQ_FOREACH_REVERSE(var, head, headname, field) \ + for ((var) = TAILQ_LAST((head), headname); \ + (var); \ + (var) = TAILQ_PREV((var), headname, field)) + +#define TAILQ_FOREACH_REVERSE_SAFE(var, head, headname, field, tvar) \ + for ((var) = TAILQ_LAST((head), headname); \ + (var) && ((tvar) = TAILQ_PREV((var), headname, field), 1); \ + (var) = (tvar)) + +#define TAILQ_INIT(head) do { \ + TAILQ_FIRST((head)) = NULL; \ + (head)->tqh_last = &TAILQ_FIRST((head)); \ + QMD_TRACE_HEAD(head); \ +} while (0) + +#define TAILQ_INSERT_AFTER(head, listelm, elm, field) do { \ + QMD_TAILQ_CHECK_NEXT(listelm, field); \ + if ((TAILQ_NEXT((elm), field) = TAILQ_NEXT((listelm), field)) != NULL)\ + TAILQ_NEXT((elm), field)->field.tqe_prev = \ + &TAILQ_NEXT((elm), field); \ + else { \ + (head)->tqh_last = &TAILQ_NEXT((elm), field); \ + QMD_TRACE_HEAD(head); \ + } \ + TAILQ_NEXT((listelm), field) = (elm); \ + (elm)->field.tqe_prev = &TAILQ_NEXT((listelm), field); \ + QMD_TRACE_ELEM(&(elm)->field); \ + QMD_TRACE_ELEM(&listelm->field); \ +} while (0) + +#define TAILQ_INSERT_BEFORE(listelm, elm, field) do { \ + QMD_TAILQ_CHECK_PREV(listelm, field); \ + (elm)->field.tqe_prev = (listelm)->field.tqe_prev; \ + TAILQ_NEXT((elm), field) = (listelm); \ + *(listelm)->field.tqe_prev = (elm); \ + (listelm)->field.tqe_prev = &TAILQ_NEXT((elm), field); \ + QMD_TRACE_ELEM(&(elm)->field); \ + QMD_TRACE_ELEM(&listelm->field); \ +} while (0) + +#define TAILQ_INSERT_HEAD(head, elm, field) do { \ + QMD_TAILQ_CHECK_HEAD(head, field); \ + if ((TAILQ_NEXT((elm), field) = TAILQ_FIRST((head))) != NULL) \ + TAILQ_FIRST((head))->field.tqe_prev = \ + &TAILQ_NEXT((elm), field); \ + else \ + (head)->tqh_last = &TAILQ_NEXT((elm), field); \ + TAILQ_FIRST((head)) = (elm); \ + (elm)->field.tqe_prev = &TAILQ_FIRST((head)); \ + QMD_TRACE_HEAD(head); \ + QMD_TRACE_ELEM(&(elm)->field); \ +} while (0) + +#define TAILQ_INSERT_TAIL(head, elm, field) do { \ + QMD_TAILQ_CHECK_TAIL(head, field); \ + TAILQ_NEXT((elm), field) = NULL; \ + (elm)->field.tqe_prev = (head)->tqh_last; \ + *(head)->tqh_last = (elm); \ + (head)->tqh_last = &TAILQ_NEXT((elm), field); \ + QMD_TRACE_HEAD(head); \ + QMD_TRACE_ELEM(&(elm)->field); \ +} while (0) + +#define TAILQ_LAST(head, headname) \ + (*(((struct headname *)((head)->tqh_last))->tqh_last)) + +#define TAILQ_NEXT(elm, field) ((elm)->field.tqe_next) + +#define TAILQ_PREV(elm, headname, field) \ + (*(((struct headname *)((elm)->field.tqe_prev))->tqh_last)) + +#define TAILQ_REMOVE(head, elm, field) do { \ + QMD_SAVELINK(oldnext, (elm)->field.tqe_next); \ + QMD_SAVELINK(oldprev, (elm)->field.tqe_prev); \ + QMD_TAILQ_CHECK_NEXT(elm, field); \ + QMD_TAILQ_CHECK_PREV(elm, field); \ + if ((TAILQ_NEXT((elm), field)) != NULL) \ + TAILQ_NEXT((elm), field)->field.tqe_prev = \ + (elm)->field.tqe_prev; \ + else { \ + (head)->tqh_last = (elm)->field.tqe_prev; \ + QMD_TRACE_HEAD(head); \ + } \ + *(elm)->field.tqe_prev = TAILQ_NEXT((elm), field); \ + TRASHIT(*oldnext); \ + TRASHIT(*oldprev); \ + QMD_TRACE_ELEM(&(elm)->field); \ +} while (0) + +#define TAILQ_SWAP(head1, head2, type, field) do { \ + struct type *swap_first = (head1)->tqh_first; \ + struct type **swap_last = (head1)->tqh_last; \ + (head1)->tqh_first = (head2)->tqh_first; \ + (head1)->tqh_last = (head2)->tqh_last; \ + (head2)->tqh_first = swap_first; \ + (head2)->tqh_last = swap_last; \ + if ((swap_first = (head1)->tqh_first) != NULL) \ + swap_first->field.tqe_prev = &(head1)->tqh_first; \ + else \ + (head1)->tqh_last = &(head1)->tqh_first; \ + if ((swap_first = (head2)->tqh_first) != NULL) \ + swap_first->field.tqe_prev = &(head2)->tqh_first; \ + else \ + (head2)->tqh_last = &(head2)->tqh_first; \ +} while (0) + +#ifdef __cplusplus +} +#endif + +#endif /* !_SYS_QUEUE_H_ */ diff --git a/components/esp32/include/rom/rtc.h b/components/esp32/include/rom/rtc.h new file mode 100644 index 0000000000..31323646f0 --- /dev/null +++ b/components/esp32/include/rom/rtc.h @@ -0,0 +1,168 @@ +// Copyright 2010-2016 Espressif Systems (Shanghai) PTE LTD +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at + +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#ifndef _ROM_RTC_H_ +#define _ROM_RTC_H_ + +#include "ets_sys.h" + +#include +#include + +#include "soc/soc.h" + +#ifdef __cplusplus +extern "C" { +#endif + +typedef enum { + AWAKE = 0, //CPU ON + LIGHT_SLEEP = BIT0, //CPU waiti, PLL ON. We don't need explicitly set this mode. + DEEP_SLEEP = BIT1 //CPU OFF, PLL OFF, only specific timer could wake up +} SLEEP_MODE; + +typedef enum { + NO_MEAN = 0, + POWERON_RESET = 1, //1 Vbat power on reset, RTC reset +// EXT_SYS_RESET = 2, //4 External System reset, RTC reset + SW_RESET = 3, //6 Software warm reset + OWDT_RESET = 4, //5 Watch dog reset + DEEPSLEEP_RESET = 5, //2 Deep sleep timer reach reset. + SDIO_RESET = 6, //3 Deep sleep Pbint power on reset [boot] + TG0WDT_SYS_RESET = 7, + TG1WDT_SYS_RESET = 8, + RTCWDT_SYS_RESET = 9, + INTRUSION_RESET = 10, + TGWDT_CPU_RESET = 11, + SW_CPU_RESET = 12, + RTCWDT_CPU_RESET = 13, + EXT_CPU_RESET = 14, + RTCWDT_BROWN_OUT_RESET = 15, + RTCWDT_RTC_RESET = 16 +} RESET_REASON; + +typedef enum { + NO_SLEEP = 0, + EXT_EVENT0_TRIG = BIT0, + EXT_EVENT1_TRIG = BIT1, + GPIO_TRIG = BIT2, + TIMER_EXPIRE = BIT3, + SDIO_TRIG = BIT4, + MAC_TRIG = BIT5, + UART0_TRIG = BIT6, + UART1_TRIG = BIT7, + TOUCH_TRIG = BIT8, + SAR_TRIG = BIT9, + BT_TRIG = BIT10 +} WAKEUP_REASON; + +typedef enum { + DISEN_WAKEUP = NO_SLEEP, + EXT_EVENT0_TRIG_EN = EXT_EVENT0_TRIG, + EXT_EVENT1_TRIG_EN = EXT_EVENT1_TRIG, + GPIO_TRIG_EN = GPIO_TRIG, + TIMER_EXPIRE_EN = TIMER_EXPIRE, + SDIO_TRIG_EN = SDIO_TRIG, + MAC_TRIG_EN = MAC_TRIG, + UART0_TRIG_EN = UART0_TRIG, + UART1_TRIG_EN = UART1_TRIG, + TOUCH_TRIG_EN = TOUCH_TRIG, + SAR_TRIG_EN = SAR_TRIG, + BT_TRIG_EN = BT_TRIG +} WAKEUP_ENABLE; + +typedef enum { + NO_INT = 0, + WAKEUP_INT = BIT0, + REJECT_INT = BIT1, + SDIO_IDLE_INT = BIT2, + RTC_WDT_INT = BIT3, + RTC_TIME_VALID_INT = BIT4 +} RTC_INT_REASON; + +typedef enum { + DISEN_INT = 0, + WAKEUP_INT_EN = WAKEUP_INT, + REJECT_INT_EN = REJECT_INT, + SDIO_IDLE_INT_EN = SDIO_IDLE_INT, + RTC_WDT_INT_EN = RTC_WDT_INT, + RTC_TIME_VALID_INT_EN = RTC_TIME_VALID_INT +}RTC_INT_EN; + + + +// Alive memory is a special memory block which could restore data during system +// deep sleep. power management and wlan profile data may need put into this +// memory area. +// Should create a dram segment in link script. +#define ALIVE_MEMORY_ADDR +#define ALIVE_MEMORY_SIZE (1024 * 2) + +void rtc_hw_init(void); + +RESET_REASON rtc_get_reset_reason(int cpu_no); +void software_reset(void); +void software_reset_cpu(int cpu_no); +void rtc_select_apb_bridge(bool sel); +void rtc_set_sleep_mode(SLEEP_MODE mode, uint32_t sleep_sec, uint32_t wakeup_mode); + +uint8_t ets_rtc_recovery(void); + +#define MAX_DEEPSLEEP_DURATION (0xffffffff / RTC_CLK_FREQ) +#define SECOND_TO_RTC_TICK(second) ((second)*RTC_CLK_FREQ) //32KHz +#define CALIB_VALUE_TO_RTC_TICK(microsecond, clk_mkz, n_rtc,nclk) ((microsecond)*(clk_mkz)*(n_rtc)/(nclk)) //32KHz +#define RTC_TICK_TO_SECOND(tick) ((tick)/RTC_CLK_FREQ ) +#define GET_CURRENT_TICK() (READ_PERI_REG(RTC_TIME)) +#define SET_WAKEUP_TICK(tick) (WRITE_PERI_REG(RTC_TIMER0, tick)) + +//#define GET_WAKEUP_CAUSE() GET_PERI_REG_BITS2(RTC_STATE1, RTC_CNTL_WAKEUP_CAUSE, RTC_CNTL_WAKEUP_CAUSE_S) +#define DISABLE_RTC_INT(int_type) CLEAR_PERI_REG_MASK(RTC_INT_ENA, int_type) +#define ENABLE_RTC_INT(int_type) SET_PERI_REG_MASK(RTC_INT_ENA, int_type) +#define CLR_RTC_INT(int_type) SET_PERI_REG_MASK(RTC_INT_CLR, int_type) +#define GET_RTC_INT_CAUSE() GET_PERI_REG_BITS(RTC_INT_RAW, RTC_INT_RAW_MSB,RTC_INT_RAW_LSB) + +void rtc_register_deepsleep_timer(ETSTimer *timer, uint32_t tmout); +void rtc_disable_deepsleep_timer(void); + +void rtc_enter_sleep(void); +void ets_rtc_int_register(void); +void dtm_set_intr_mask(uint32_t mask); +uint32_t dtm_get_intr_mask(void); +void dtm_set_params(uint32_t sleep_mode, uint32_t sleep_tm_ms, uint32_t wakeup_tm_ms, uint32_t sleep_times, uint32_t rxbcn_len); +void save_rxbcn_mactime(uint32_t rxbcn_mactime); +void save_tsf_us(uint32_t tsf_us); + +typedef void (* ets_idle_cb_t)(void *arg); + +typedef uint32_t (* ETS_GET_MACTIME)(void); +typedef void (* ETS_WAKEUP_INIT)(void); + +void dtm_params_init(ETS_GET_MACTIME get_mactime, ETS_WAKEUP_INIT wakeup_init); + +void ets_set_idle_cb(ets_idle_cb_t func, void *arg); + +void ets_enter_sleep(void); + +void rtc_intr_handler(void *); + +#define ETS_SLEEP_START(pfunc, parg) ets_set_idle_cb((pfunc), (parg)); + +#define ETS_SLEEP_END() ets_set_idle_cb(NULL, NULL); + +#ifdef __cplusplus +} +#endif + +#endif /* _ROM_RTC_H_ */ + diff --git a/components/esp32/include/rom/secure_boot.h b/components/esp32/include/rom/secure_boot.h new file mode 100644 index 0000000000..1e39d3453d --- /dev/null +++ b/components/esp32/include/rom/secure_boot.h @@ -0,0 +1,41 @@ +// Copyright 2015-2016 Espressif Systems (Shanghai) PTE LTD +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at + +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +#ifndef _ROM_SECURE_BOOT_H_ +#define _ROM_SECURE_BOOT_H_ + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +void ets_secure_boot_start(void); + +void ets_secure_boot_finish(void); + +void ets_secure_boot_hash(uint32_t *buf); + +void ets_secure_boot_obtain(void); + +int ets_secure_boot_check(uint32_t *buf); + +void ets_secure_boot_rd_iv(uint32_t *buf); + +void ets_secure_boot_rd_abstract(uint32_t *buf); + +#ifdef __cplusplus +} +#endif + +#endif /* _ROM_SECURE_BOOT_H_ */ diff --git a/components/esp32/include/rom/sha.h b/components/esp32/include/rom/sha.h new file mode 100644 index 0000000000..a5536bd3ba --- /dev/null +++ b/components/esp32/include/rom/sha.h @@ -0,0 +1,50 @@ +// Copyright 2015-2016 Espressif Systems (Shanghai) PTE LTD +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at + +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +#ifndef _ROM_SHA_H_ +#define _ROM_SHA_H_ + +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct SHAContext { + bool start; + uint32_t total_input_bits[4]; +} SHA_CTX; + +enum SHA_TYPE { + SHA1 = 0, + SHA2_256, + SHA2_384, + SHA2_512 +}; + +void ets_sha_init(SHA_CTX *ctx); + +void ets_sha_enable(void); + +void ets_sha_disable(void); + +void ets_sha_update(SHA_CTX *ctx, enum SHA_TYPE type, const uint8_t *input, size_t input_bits); + +void ets_sha_finish(SHA_CTX *ctx, enum SHA_TYPE type, uint8_t *output); + +#ifdef __cplusplus +} +#endif + +#endif /* _ROM_SHA_H_ */ diff --git a/components/esp32/include/rom/spi_flash.h b/components/esp32/include/rom/spi_flash.h new file mode 100644 index 0000000000..b619948377 --- /dev/null +++ b/components/esp32/include/rom/spi_flash.h @@ -0,0 +1,145 @@ +// Copyright 2010-2016 Espressif Systems (Shanghai) PTE LTD +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at + +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +#ifndef _ROM_SPI_FLASH_H_ +#define _ROM_SPI_FLASH_H_ + +#include +#include + +#include "esp_attr.h" + +#include "soc/spi_register.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#define PERIPHS_SPI_FLASH_CMD SPI_CMD(1) +#define PERIPHS_SPI_FLASH_ADDR SPI_ADDR(1) +#define PERIPHS_SPI_FLASH_CTRL SPI_CTRL(1) +#define PERIPHS_SPI_FLASH_CTRL1 SPI_CTRL1(1) +#define PERIPHS_SPI_FLASH_STATUS SPI_RD_STATUS(1) +#define PERIPHS_SPI_FLASH_USRREG SPI_USER(1) +#define PERIPHS_SPI_FLASH_USRREG1 SPI_USER1(1) +#define PERIPHS_SPI_FLASH_USRREG2 SPI_USER2(1) +#define PERIPHS_SPI_FLASH_C0 SPI_W0(1) +#define PERIPHS_SPI_FLASH_C1 SPI_W1(1) +#define PERIPHS_SPI_FLASH_C2 SPI_W2(1) +#define PERIPHS_SPI_FLASH_C3 SPI_W3(1) +#define PERIPHS_SPI_FLASH_C4 SPI_W4(1) +#define PERIPHS_SPI_FLASH_C5 SPI_W5(1) +#define PERIPHS_SPI_FLASH_C6 SPI_W6(1) +#define PERIPHS_SPI_FLASH_C7 SPI_W7(1) +#define PERIPHS_SPI_FLASH_TX_CRC SPI_TX_CRC(1) + +#define SPI0_R_QIO_DUMMY_CYCLELEN 3 +#define SPI0_R_QIO_ADDR_BITSLEN 31 +#define SPI0_R_FAST_DUMMY_CYCLELEN 7 +#define SPI0_R_DIO_DUMMY_CYCLELEN 3 +#define SPI0_R_FAST_ADDR_BITSLEN 23 +#define SPI0_R_SIO_ADDR_BITSLEN 23 + +#define SPI1_R_QIO_DUMMY_CYCLELEN 3 +#define SPI1_R_QIO_ADDR_BITSLEN 31 +#define SPI1_R_FAST_DUMMY_CYCLELEN 7 +#define SPI1_R_DIO_DUMMY_CYCLELEN 3 +#define SPI1_R_DIO_ADDR_BITSLEN 31 +#define SPI1_R_FAST_ADDR_BITSLEN 23 +#define SPI1_R_SIO_ADDR_BITSLEN 23 + +#define SPI_W_SIO_ADDR_BITSLEN 23 + +#define TWO_BYTE_STATUS_EN SPI_WRSR_2B + +//SPI address register +#define SPI_FLASH_BYTES_LEN 24 +#define SPI_BUFF_BYTE_WRITE_NUM 32 +#define SPI_BUFF_BYTE_READ_NUM 64 +#define SPI_BUFF_BYTE_READ_BITS 0x3f + +//SPI status register +#define SPI_FLASH_BUSY_FLAG BIT0 +#define SPI_FLASH_WRENABLE_FLAG BIT1 +#define SPI_FLASH_BP0 BIT2 +#define SPI_FLASH_BP1 BIT3 +#define SPI_FLASH_BP2 BIT4 +#define FLASH_WR_PROTECT (SPI_FLASH_BP0|SPI_FLASH_BP1|SPI_FLASH_BP2) +#define SPI_FLASH_QE BIT9 + +typedef enum { + SPI_FLASH_QIO_MODE = 0, + SPI_FLASH_QOUT_MODE, + SPI_FLASH_DIO_MODE, + SPI_FLASH_DOUT_MODE, + SPI_FLASH_FASTRD_MODE, + SPI_FLASH_SLOWRD_MODE +} SpiFlashRdMode; + +typedef enum { + SPI_FLASH_RESULT_OK, + SPI_FLASH_RESULT_ERR, + SPI_FLASH_RESULT_TIMEOUT +} SpiFlashOpResult; + +typedef struct{ + uint32_t deviceId; + uint32_t chip_size; // chip size in bytes + uint32_t block_size; + uint32_t sector_size; + uint32_t page_size; + uint32_t status_mask; +} SpiFlashChip; + +typedef struct { + uint8_t data_length; + uint8_t read_cmd0; + uint8_t read_cmd1; + uint8_t write_cmd; + uint16_t data_mask; + uint16_t data; +} SpiCommonCmd; + +void SelectSpiQIO(uint8_t wp_gpio_num, uint32_t ishspi) ROMFN_ATTR; +void SetSpiDrvs(uint8_t wp_gpio_num, uint32_t ishspi, uint8_t* drvs) ROMFN_ATTR; +void SelectSpiFunction(uint32_t ishspi) ROMFN_ATTR; +SpiFlashOpResult SPIEraseChip(void) ROMFN_ATTR; +SpiFlashOpResult SPIEraseBlock(uint32_t block_num) ROMFN_ATTR; +SpiFlashOpResult SPIEraseSector(uint32_t sector_num) ROMFN_ATTR; +SpiFlashOpResult SPIWrite(uint32_t dest_addr, const uint32_t* src, int32_t len) ROMFN_ATTR; +void SPI_Write_Encrypt_Enable() ROMFN_ATTR; +SpiFlashOpResult SPI_Prepare_Encrypt_Data(uint32_t flash_addr, uint32_t* data) ROMFN_ATTR; +void SPI_Write_Encrypt_Disable() ROMFN_ATTR; +SpiFlashOpResult SPI_Encrypt_Write(uint32_t flash_addr, uint32_t* data, uint32_t len) ROMFN_ATTR; +SpiFlashOpResult SPIRead(uint32_t src_addr, uint32_t* dest, int32_t len) ROMFN_ATTR; +SpiFlashOpResult SPIReadModeCnfig(SpiFlashRdMode mode, bool legacy) ROMFN_ATTR; +SpiFlashOpResult SPIMasterReadModeCnfig(SpiFlashRdMode mode) ROMFN_ATTR; +SpiFlashOpResult SPIClkConfig(uint8_t freqdiv, uint8_t spi) ROMFN_ATTR; +uint16_t SPI_Common_Command(SpiCommonCmd * cmd) ROMFN_ATTR; +SpiFlashOpResult SPIUnlock() ROMFN_ATTR; +SpiFlashOpResult SPIEraseArea(uint32_t start_addr, uint32_t area_len) ROMFN_ATTR; +SpiFlashOpResult SPILock() ROMFN_ATTR; +SpiFlashOpResult SPIParamCfg(uint32_t deviceId, uint32_t chip_size, uint32_t block_size, uint32_t sector_size, uint32_t page_size, uint32_t status_mask) ROMFN_ATTR; +SpiFlashOpResult SPI_user_command_read(uint32_t * status, uint8_t cmd) ROMFN_ATTR; +void spi_cache_sram_init() ROMFN_ATTR; + +//ETS_STATUS ets_unpack_flash_code(uint32_t pos, uint32_t *entry_addr, bool jump, bool sb_need_check, bool config) ROMFN_ATTR; +//ETS_STATUS ets_unpack_flash_code_legacy(uint32_t pos, uint32_t *entry_addr, bool jump, bool config) ROMFN_ATTR; + +void spi_flash_attach(uint32_t ishspi, bool legacy) ROMFN_ATTR; + +#ifdef __cplusplus +} +#endif + +#endif /* _ROM_SPI_FLASH_H_ */ diff --git a/components/esp32/include/rom/ssc.h b/components/esp32/include/rom/ssc.h new file mode 100755 index 0000000000..509e0da2f8 --- /dev/null +++ b/components/esp32/include/rom/ssc.h @@ -0,0 +1,85 @@ +// Copyright 2011-2016 Espressif Systems (Shanghai) PTE LTD +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at + +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#ifndef _ROM_SSC_H_ +#define _ROM_SSC_H_ + +#include "esp_types.h" + +#include "esp_attr.h" + +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct cmd_s { + char *cmd_str; +#define CMD_T_ASYNC 0x01 +#define CMD_T_SYNC 0x02 + uint8_t flag; + uint8_t id; + void (* cmd_func)(void); + void (* cmd_callback)(void *arg); +} ssc_cmd_t; + +#define ssc_printf ets_printf +#define SSC_CMD_N 10 //since the command not added in ssc_cmd.c +#define MAX_LINE_N 40 +#define PROMPT ":>" +#define SSC_EVT_N 4 + + +#define SSC_PRIO 30 +enum { + CMD_SET_SSID = 0, + CMD_SCAN, + CMD_CONNECT, + CMD_DISCONNECT, + CMD_SET_MACADDR, + CMD_PING, + CMD_PING_COUNT, + CMD_PING_LENGTH, + CMD_SET_IP, +// CMD_RD_I2C, +// CMD_SET_NULL, it's just for solving the old rom bug +// CMD_SET_I2C, +// CMD_RD_I2CM, +// CMD_SET_I2CM, +// CMD_SET_PBUS, +// CMD_SET_TXTONE, +// CMD_SET_STOPTONE, + CMD_END, +}; + +enum { + SIG_SSC_RUNCMD, + SIG_SSC_CMDDONE, + SIG_SSC_RESTART, + SIG_SSC_UART_RX_CHAR, +}; + +void ssc_attach(void) ROMFN_ATTR; +void ssc_cmd_done(int cmd_id, STATUS status) ROMFN_ATTR; +int ssc_param_len(void) ROMFN_ATTR; +char * ssc_param_str(void) ROMFN_ATTR; +void ssc_register(ssc_cmd_t *cmdset, uint8_t cmdnum, void (* help)(void)) ROMFN_ATTR; + +extern ssc_cmd_t sscCmdSet[]; +void ssc_help(void); + +#ifdef __cplusplus +} +#endif + +#endif /* _ROM_SSC_H_ */ diff --git a/components/esp32/include/rom/tbconsole.h b/components/esp32/include/rom/tbconsole.h new file mode 100644 index 0000000000..891c2732a5 --- /dev/null +++ b/components/esp32/include/rom/tbconsole.h @@ -0,0 +1,27 @@ +// Copyright 2015-2016 Espressif Systems (Shanghai) PTE LTD +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at + +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +#ifndef _ROM_TBCONSOLE_H_ +#define _ROM_TBCONSOLE_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +void start_tb_console(); + +#ifdef __cplusplus +} +#endif + +#endif /* _ROM_TBCONSOLE_H_ */ diff --git a/components/esp32/include/rom/tjpgd.h b/components/esp32/include/rom/tjpgd.h new file mode 100644 index 0000000000..31fbc97cce --- /dev/null +++ b/components/esp32/include/rom/tjpgd.h @@ -0,0 +1,99 @@ +/*----------------------------------------------------------------------------/ +/ TJpgDec - Tiny JPEG Decompressor include file (C)ChaN, 2012 +/----------------------------------------------------------------------------*/ +#ifndef _TJPGDEC +#define _TJPGDEC +/*---------------------------------------------------------------------------*/ +/* System Configurations */ + +#define JD_SZBUF 512 /* Size of stream input buffer */ +#define JD_FORMAT 0 /* Output pixel format 0:RGB888 (3 BYTE/pix), 1:RGB565 (1 WORD/pix) */ +#define JD_USE_SCALE 1 /* Use descaling feature for output */ +#define JD_TBLCLIP 1 /* Use table for saturation (might be a bit faster but increases 1K bytes of code size) */ + +/*---------------------------------------------------------------------------*/ + +#ifdef __cplusplus +extern "C" { +#endif + +/* These types must be 16-bit, 32-bit or larger integer */ +typedef int INT; +typedef unsigned int UINT; + +/* These types must be 8-bit integer */ +typedef char CHAR; +typedef unsigned char UCHAR; +typedef unsigned char BYTE; + +/* These types must be 16-bit integer */ +typedef short SHORT; +typedef unsigned short USHORT; +typedef unsigned short WORD; +typedef unsigned short WCHAR; + +/* These types must be 32-bit integer */ +typedef long LONG; +typedef unsigned long ULONG; +typedef unsigned long DWORD; + + +/* Error code */ +typedef enum { + JDR_OK = 0, /* 0: Succeeded */ + JDR_INTR, /* 1: Interrupted by output function */ + JDR_INP, /* 2: Device error or wrong termination of input stream */ + JDR_MEM1, /* 3: Insufficient memory pool for the image */ + JDR_MEM2, /* 4: Insufficient stream input buffer */ + JDR_PAR, /* 5: Parameter error */ + JDR_FMT1, /* 6: Data format error (may be damaged data) */ + JDR_FMT2, /* 7: Right format but not supported */ + JDR_FMT3 /* 8: Not supported JPEG standard */ +} JRESULT; + + + +/* Rectangular structure */ +typedef struct { + WORD left, right, top, bottom; +} JRECT; + + + +/* Decompressor object structure */ +typedef struct JDEC JDEC; +struct JDEC { + UINT dctr; /* Number of bytes available in the input buffer */ + BYTE* dptr; /* Current data read ptr */ + BYTE* inbuf; /* Bit stream input buffer */ + BYTE dmsk; /* Current bit in the current read byte */ + BYTE scale; /* Output scaling ratio */ + BYTE msx, msy; /* MCU size in unit of block (width, height) */ + BYTE qtid[3]; /* Quantization table ID of each component */ + SHORT dcv[3]; /* Previous DC element of each component */ + WORD nrst; /* Restart inverval */ + UINT width, height; /* Size of the input image (pixel) */ + BYTE* huffbits[2][2]; /* Huffman bit distribution tables [id][dcac] */ + WORD* huffcode[2][2]; /* Huffman code word tables [id][dcac] */ + BYTE* huffdata[2][2]; /* Huffman decoded data tables [id][dcac] */ + LONG* qttbl[4]; /* Dequaitizer tables [id] */ + void* workbuf; /* Working buffer for IDCT and RGB output */ + BYTE* mcubuf; /* Working buffer for the MCU */ + void* pool; /* Pointer to available memory pool */ + UINT sz_pool; /* Size of momory pool (bytes available) */ + UINT (*infunc)(JDEC*, BYTE*, UINT);/* Pointer to jpeg stream input function */ + void* device; /* Pointer to I/O device identifiler for the session */ +}; + + + +/* TJpgDec API functions */ +JRESULT jd_prepare (JDEC*, UINT(*)(JDEC*,BYTE*,UINT), void*, UINT, void*); +JRESULT jd_decomp (JDEC*, UINT(*)(JDEC*,void*,JRECT*), BYTE); + + +#ifdef __cplusplus +} +#endif + +#endif /* _TJPGDEC */ diff --git a/components/esp32/include/rom/uart.h b/components/esp32/include/rom/uart.h new file mode 100755 index 0000000000..b295697730 --- /dev/null +++ b/components/esp32/include/rom/uart.h @@ -0,0 +1,187 @@ +// Copyright 2010-2016 Espressif Systems (Shanghai) PTE LTD +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at + +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#ifndef _ROM_UART_H_ +#define _ROM_UART_H_ + +#include "esp_types.h" +#include "esp_attr.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#define RX_BUFF_SIZE 0x100 +#define TX_BUFF_SIZE 100 + +//uart int enalbe register ctrl bits +#define UART_RCV_INTEN BIT0 +#define UART_TRX_INTEN BIT1 +#define UART_LINE_STATUS_INTEN BIT2 + +//uart int identification ctrl bits +#define UART_INT_FLAG_MASK 0x0E + +//uart fifo ctrl bits +#define UART_CLR_RCV_FIFO BIT1 +#define UART_CLR_TRX_FIFO BIT2 +#define UART_RCVFIFO_TRG_LVL_BITS BIT6 + +//uart line control bits +#define UART_DIV_LATCH_ACCESS_BIT BIT7 + +//uart line status bits +#define UART_RCV_DATA_RDY_FLAG BIT0 +#define UART_RCV_OVER_FLOW_FLAG BIT1 +#define UART_RCV_PARITY_ERR_FLAG BIT2 +#define UART_RCV_FRAME_ERR_FLAG BIT3 +#define UART_BRK_INT_FLAG BIT4 +#define UART_TRX_FIFO_EMPTY_FLAG BIT5 +#define UART_TRX_ALL_EMPTY_FLAG BIT6 // include fifo and shift reg +#define UART_RCV_ERR_FLAG BIT7 + +//send and receive message frame head +#define FRAME_FLAG 0x7E + +typedef enum{ + UART_LINE_STATUS_INT_FLAG = 0x06, + UART_RCV_FIFO_INT_FLAG = 0x04, + UART_RCV_TMOUT_INT_FLAG = 0x0C, + UART_TXBUFF_EMPTY_INT_FLAG = 0x02 +} UartIntType; //consider bit0 for int_flag + +typedef enum { + RCV_ONE_BYTE = 0x0, + RCV_FOUR_BYTE = 0x1, + RCV_EIGHT_BYTE = 0x2, + RCV_FOURTEEN_BYTE = 0x3 +} UartRcvFifoTrgLvl; + +typedef enum { + FIVE_BITS = 0x0, + SIX_BITS = 0x1, + SEVEN_BITS = 0x2, + EIGHT_BITS = 0x3 +} UartBitsNum4Char; + +typedef enum { + ONE_STOP_BIT = 1, + ONE_HALF_STOP_BIT = 2, + TWO_STOP_BIT = 3 +} UartStopBitsNum; + +typedef enum { + NONE_BITS = 0, + ODD_BITS = 2, + EVEN_BITS = 3 + +} UartParityMode; + +typedef enum { + STICK_PARITY_DIS = 0, + STICK_PARITY_EN = 2 +} UartExistParity; + +typedef enum { + BIT_RATE_9600 = 9600, + BIT_RATE_19200 = 19200, + BIT_RATE_38400 = 38400, + BIT_RATE_57600 = 57600, + BIT_RATE_115200 = 115200, + BIT_RATE_230400 = 230400, + BIT_RATE_460800 = 460800, + BIT_RATE_921600 = 921600 +} UartBautRate; + +typedef enum { + NONE_CTRL, + HARDWARE_CTRL, + XON_XOFF_CTRL +} UartFlowCtrl; + +typedef enum { + EMPTY, + UNDER_WRITE, + WRITE_OVER +} RcvMsgBuffState; + +typedef struct { +// uint32_t RcvBuffSize; + uint8_t *pRcvMsgBuff; + uint8_t *pWritePos; + uint8_t *pReadPos; + uint8_t TrigLvl; //JLU: may need to pad + RcvMsgBuffState BuffState; +}RcvMsgBuff; + +typedef struct { + uint32_t TrxBuffSize; + uint8_t *pTrxBuff; +} TrxMsgBuff; + +typedef enum { + BAUD_RATE_DET, + WAIT_SYNC_FRM, + SRCH_MSG_HEAD, + RCV_MSG_BODY, + RCV_ESC_CHAR, +} RcvMsgState; + +typedef struct{ + UartBautRate baut_rate; + UartBitsNum4Char data_bits; + UartExistParity exist_parity; + UartParityMode parity; // chip size in byte + UartStopBitsNum stop_bits; + UartFlowCtrl flow_ctrl; + uint8_t buff_uart_no; //indicate which uart use tx/rx buffer + uint8_t tx_uart_no; + RcvMsgBuff rcv_buff; +// TrxMsgBuff trx_buff; + RcvMsgState rcv_state; + int received; +} UartDevice; + +void Uart_Init(uint8_t uart_no, uint32_t clock) ROMFN_ATTR; +STATUS UartTxString(uint8_t* pString) ROMFN_ATTR; +STATUS UartRxString(uint8_t* pString, uint8_t MaxStrlen) ROMFN_ATTR; + +STATUS uart_tx_one_char(uint8_t TxChar) ROMFN_ATTR;//for print +STATUS uart_tx_one_char2(uint8_t TxChar) ROMFN_ATTR;//for send message +STATUS uart_rx_one_char(uint8_t* pRxChar) ROMFN_ATTR; +char uart_rx_one_char_block(void) ROMFN_ATTR; +void uart_rx_intr_handler(void * para) ROMFN_ATTR; +STATUS uart_rx_readbuff( RcvMsgBuff* pRxBuff, uint8_t* pRxByte) ROMFN_ATTR; +STATUS UartGetCmdLn(uint8_t * pCmdLn) ROMFN_ATTR; +UartDevice * GetUartDevice() ROMFN_ATTR; + +void uartToggleInterrupt(bool en) ROMFN_ATTR; + +STATUS SendMsg(uint8_t *pData, uint16_t DataLen) ROMFN_ATTR; + +STATUS RcvMsg(uint8_t *pData, uint16_t MaxDataLen, uint8_t is_sync) ROMFN_ATTR; + +void uartAttach() ROMFN_ATTR; +void uart_div_modify(uint8_t uart_no, uint32_t DivLatchValue) ROMFN_ATTR; +int uart_baudrate_detect(uint8_t uart_no, uint8_t is_sync) ROMFN_ATTR; +void uart_buff_switch(uint8_t uart_no) ROMFN_ATTR; +void uart_tx_flush(uint8_t uart_no) ROMFN_ATTR; +void uart_tx_wait_idle(uint8_t uart_no) ROMFN_ATTR; +extern UartDevice UartDev; + +#ifdef __cplusplus +} +#endif + +#endif /* _ROM_UART_H_ */ diff --git a/components/esp32/include/rom/wdt.h b/components/esp32/include/rom/wdt.h new file mode 100644 index 0000000000..04a31c3293 --- /dev/null +++ b/components/esp32/include/rom/wdt.h @@ -0,0 +1,40 @@ +// Copyright 2010-2016 Espressif Systems (Shanghai) PTE LTD +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at + +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#ifndef _ROM_WDT_H_ +#define _ROM_WDT_H_ + +#include "soc.h" +#include "ets_sys.h" + +#define WDT_RESET_VALUE 0x73 +#define WDT_RESET_LEN 7 //real time: (1<<(WDT_RESET_LEN+1))*pclk +#define WDT_CONTROL_ENABLED BIT0 +#define WDT_MODE_SET(v) (v) +#define WDT_TARGET_SET(v) (v) +#define WDT_ADDRESS 0 + +#define SEC_TO_WDT_TICK(s) (s * WDT_CLK_FREQ) //it's Pclk clock,44MHz + +typedef enum{ + NEXT_OVERFLOW_RESET = 0, + NEXT_OVERFLOW_NO_RESET = 1, + EACH_OVERFLOW_RESET = 2, +} WDT_RESP_MODE; + +#define WDT_DEFAULT_FEED_INTERVAL WDT_INTERVAL_SIX_SEC /* 6 seconds */ +#define WDT_DEFAULT_EXPIRE_INTERVAL WDT_INTERVAL_TWELVE_SEC /* 12 seconds */ + +#endif /* _ROM_WDT_H_ */ + diff --git a/components/esp32/include/soc/bb_reg.h b/components/esp32/include/soc/bb_reg.h new file mode 100755 index 0000000000..0b52f66aea --- /dev/null +++ b/components/esp32/include/soc/bb_reg.h @@ -0,0 +1,102 @@ +// Copyright 2010-2016 Espressif Systems (Shanghai) PTE LTD +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at + +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#ifndef _SOC_BB_REG_H_ +#define _SOC_BB_REG_H_ + +#define apb_bb_offset 0x6001c000 + +#define BB_DLY apb_bb_offset + 0x00009b00 // reg 00 +#define BB_TEST apb_bb_offset + 0x00009b08 // reg 02 +#define BB_TM1 apb_bb_offset + 0x00009b0c // reg 03 +#define BB_TM_CNTL apb_bb_offset + 0x00009b14 // reg 05 +#define BB_DEL_CNTL apb_bb_offset + 0x00009b28 // reg 10 +#define BB_PARAL_CNTL apb_bb_offset + 0x00009b2c // reg 11 +#define BB_FSM1 apb_bb_offset + 0x00009b44 // reg 17 +#define BB_MXG apb_bb_offset + 0x00009b48 // reg 18 +#define BB_MNOF apb_bb_offset + 0x00009b4c // reg 19 +#define BB_SIZE apb_bb_offset + 0x00009b50 // reg 20 +#define BB_TM3a apb_bb_offset + 0x00009b54 // reg 21 +#define BB_TM4a apb_bb_offset + 0x00009b58 // reg 22 +#define BB_GAIN apb_bb_offset + 0x00009b5c // reg 23 +#define BB_CNTL apb_bb_offset + 0x00009b60 // reg 24 +#define BB_CAD apb_bb_offset + 0x00009b64 // reg 25 +#define BB_DET apb_bb_offset + 0x00009b68 // reg 26 +#define BB_DETL apb_bb_offset + 0x00009b6c // reg 27 + +#define BB_MASK_PCLL apb_bb_offset + 0x00009d08 // reg 66 +#define BB_MASK_PCLH apb_bb_offset + 0x00009d0c // reg 67 +#define BB_RX_CTRL4 apb_bb_offset + 0x00009d10 // reg 68 +#define BB_RX_CTRL apb_bb_offset + 0x00009d1c // reg 71 +#define BB_RX_CTRL2 apb_bb_offset + 0x00009d20 // reg 72 +#define BB_RX_CTRL3 apb_bb_offset + 0x00009d24 // reg 73 +#define BB_DEL4 apb_bb_offset + 0x00009d40 // reg 80 +#define BB_TM5 apb_bb_offset + 0x00009d44 // reg 81 +#define BB_TM6 apb_bb_offset + 0x00009d48 // reg 82 +#define BB_PMCTRL apb_bb_offset + 0x00009d4c // reg 83 +#define BB_PWR apb_bb_offset + 0x00009d68 // reg 90 +#define BB_BCTRL2 apb_bb_offset + 0x00009d70 // reg 92 + +#define BB_MASK_PL apb_bb_offset + 0x00009884 // reg 97 +#define BB_MASK_PCHL apb_bb_offset + 0x00009888 // reg 98 +#define BB_MASK_PCHH apb_bb_offset + 0x0000988c // reg 99 + +#define BB_MASK_CL apb_bb_offset + 0x0000989c // reg 103 +#define BB_TONE apb_bb_offset + 0x000098a0 // reg 104 +#define BB_MASK_CH apb_bb_offset + 0x000098d4 // reg 117 +#define BB_SER apb_bb_offset + 0x000098ec // reg 123 +#define BB_GN_TB apb_bb_offset + 0x00009e00 // reg 128 + +#define BB_MODE apb_bb_offset + 0x00009c00 // reg 640 +#define BB_TXCTRL apb_bb_offset + 0x00009c04 // reg 641 +#define BB_BCTRL3 apb_bb_offset + 0x00009c08 // reg 642 +#define BB_BCTRL apb_bb_offset + 0x00009c28 // reg 650 +#define BB_SMCTRL apb_bb_offset + 0x00009c48 // reg 658 +#define BB_SMCTRL2 apb_bb_offset + 0x00009c4C // reg 659 +#define BB_TXCNT apb_bb_offset + 0x00009c58 // reg 662 +#define BB_RXCTRL apb_bb_offset + 0x00009c68 // reg 666 + +#define BB_TXGAIN apb_bb_offset + 0x00009900 // reg 704 + +#define BB_RXS_CNTL apb_bb_offset + 0x00009988 // reg 738 +#define BB_MASK2_PCLL apb_bb_offset + 0x000099a8 // reg 746 +#define BB_MASK2_PCLH apb_bb_offset + 0x000099ac // reg 747 +#define BB_MASK_PH apb_bb_offset + 0x000099b0 // reg 748 +#define BB_MASK2_PCHL apb_bb_offset + 0x000099b8 // reg 750 +#define BB_MASK2_PCHH apb_bb_offset + 0x000099bc // reg 751 +// +#define BB_TX_TONE_CNTL apb_bb_offset + 0x000099f0 // reg 764 +#define BB_ADD_CNTL0 apb_bb_offset + 0x00009a28 // reg 778 +#define BB_ADD_CNTL2 apb_bb_offset + 0x00009a2c // reg 779 +#define BB_GAIN_CNTL0 apb_bb_offset + 0x00009a34 // reg 781 +#define BB_GAIN_CNTL1 apb_bb_offset + 0x00009a38 // reg 782 +#define BB_GAIN_CNTL2 apb_bb_offset + 0x00009a3c // reg 783 +#define BB_AGCMEM_CTRL apb_bb_offset + 0x00009a68 // reg 794 + +#define BB_11B_RECORD apb_bb_offset + 0x00009808 // reg 802 +#define BB_FILTER_CNTL apb_bb_offset + 0x0000980c // reg 803 +#define BB_ANALOG_CTRL1 apb_bb_offset + 0x00009838 +#define BB_ANALOG_CTRL2 apb_bb_offset + 0x0000983c //reg 815 +#define BB_ANALOG_CTRL3 apb_bb_offset + 0x00009840 //reg 816 +#define BB_RFCFG_CTRL0 apb_bb_offset + 0x00009844 //reg 817 +#define BB_RFCFG_CTRL1 apb_bb_offset + 0x00009848 //reg 818 + +#define BB_ADD_CNTL1 apb_bb_offset + 0x00009860 //reg824 +#define BB_PA_CNTL apb_bb_offset + 0x00009864 //reg825 +#define BB_RFCFG_CTRL2 apb_bb_offset + 0x0000986c //reg827 +#define BB_RXDEL_CTRL apb_bb_offset + 0x00009d18 +#define BB_RXLENGTH_CTRL apb_bb_offset + 0x00009d1c + +#endif /* _SOC_BB_REG_H_ */ + diff --git a/components/esp32/include/soc/boot_mode.h b/components/esp32/include/soc/boot_mode.h new file mode 100755 index 0000000000..5106e10cfb --- /dev/null +++ b/components/esp32/include/soc/boot_mode.h @@ -0,0 +1,104 @@ +// Copyright 2010-2016 Espressif Systems (Shanghai) PTE LTD +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at + +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#ifndef _SOC_BOOT_MODE_H_ +#define _SOC_BOOT_MODE_H_ + +#include "soc.h" + +/*SPI Boot*/ +#define IS_1XXXX(v) (((v)&0x10)==0x10) + +/*HSPI Boot*/ +#define IS_010XX(v) (((v)&0x1c)==0x08) + +/*Download Boot, SDIO/UART0/UART1*/ +#define IS_00XXX(v) (((v)&0x18)==0x00) + +/*Download Boot, SDIO/UART0/UART1,FEI_FEO V2*/ +#define IS_00X00(v) (((v)&0x1b)==0x00) + +/*Download Boot, SDIO/UART0/UART1,FEI_REO V2*/ +#define IS_00X01(v) (((v)&0x1b)==0x01) + +/*Download Boot, SDIO/UART0/UART1,REI_FEO V2*/ +#define IS_00X10(v) (((v)&0x1b)==0x02) + +/*Download Boot, SDIO/UART0/UART1,REI_FEO V2*/ +#define IS_00X11(v) (((v)&0x1b)==0x03) + +/*ATE/ANALOG Mode*/ +#define IS_01110(v) (((v)&0x1f)==0x0e) + +/*Diagnostic Mode+UART0 download Mode*/ +#define IS_01111(v) (((v)&0x1f)==0x0f) + +/*legacy SPI Boot*/ +#define IS_01100(v) (((v)&0x1f)==0x0c) + +/*SDIO_Slave download Mode V1.1*/ +#define IS_01101(v) (((v)&0x1f)==0x0d) + + + +#define BOOT_MODE_GET() (GPIO_REG_READ(GPIO_STRAP)) + +/*do not include download mode*/ +#define ETS_IS_UART_BOOT() IS_01111(BOOT_MODE_GET()) + +/*all spi boot including spi/hspi/legacy*/ +#define ETS_IS_FLASH_BOOT() (IS_1XXXX(BOOT_MODE_GET()) || IS_010XX(BOOT_MODE_GET()) || IS_01100(BOOT_MODE_GET())) + +/*all faster spi boot including spi/hspi*/ +#define ETS_IS_FAST_FLASH_BOOT() (IS_1XXXX(BOOT_MODE_GET()) || IS_010XX(BOOT_MODE_GET())) + +/*all spi boot including spi/legacy*/ +#define ETS_IS_SPI_FLASH_BOOT() (IS_1XXXX(BOOT_MODE_GET()) || IS_01100(BOOT_MODE_GET())) + +/*all spi boot including hspi/legacy*/ +#define ETS_IS_HSPI_FLASH_BOOT() IS_010XX(BOOT_MODE_GET()) + +/*all sdio V2 of failing edge input, failing edge output*/ +#define ETS_IS_SDIO_FEI_FEO_V2_BOOT() IS_00X00(BOOT_MODE_GET()) + +/*all sdio V2 of failing edge input, raising edge output*/ +#define ETS_IS_SDIO_FEI_REO_V2_BOOT() IS_00X01(BOOT_MODE_GET()) + +/*all sdio V2 of raising edge input, failing edge output*/ +#define ETS_IS_SDIO_REI_FEO_V2_BOOT() IS_00X10(BOOT_MODE_GET()) + +/*all sdio V2 of raising edge input, raising edge output*/ +#define ETS_IS_SDIO_REI_REO_V2_BOOT() IS_00X11(BOOT_MODE_GET()) + +/*all sdio V1 of raising edge input, failing edge output*/ +#define ETS_IS_SDIO_REI_FEO_V1_BOOT() IS_01101(BOOT_MODE_GET()) + +/*do not include download mode*/ +#define ETS_IS_SDIO_BOOT() IS_01101(BOOT_MODE_GET()) + +/*joint download boot*/ +#define ETS_IS_SDIO_UART_BOOT() IS_00XXX(BOOT_MODE_GET()) + +/*ATE mode*/ +#define ETS_IS_ATE_BOOT() IS_01110(BOOT_MODE_GET()) + +/*A bit to control flash boot print*/ +#define ETS_IS_PRINT_BOOT() (BOOT_MODE_GET() & 0x2) + +/*used by ETS_IS_SDIO_UART_BOOT*/ +#define SEL_NO_BOOT 0 +#define SEL_SDIO_BOOT BIT0 +#define SEL_UART_BOOT BIT1 + +#endif /* _SOC_BOOT_MODE_H_ */ diff --git a/components/esp32/include/soc/dport_reg.h b/components/esp32/include/soc/dport_reg.h new file mode 100644 index 0000000000..d91c12cc8b --- /dev/null +++ b/components/esp32/include/soc/dport_reg.h @@ -0,0 +1,1766 @@ +// Copyright 2015-2016 Espressif Systems (Shanghai) PTE LTD +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at + +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +#ifndef _SOC_DPORT_REG_H_ +#define _SOC_DPORT_REG_H_ + +#include "soc.h" + +#define PRO_BOOT_REMAP_CTRL_REG (DR_REG_DPORT_BASE + 0x000) +#define DPORT_PRO_BOOT_REMAP (BIT(0)) +#define DPORT_PRO_BOOT_REMAP_S 0 + +#define APP_BOOT_REMAP_CTRL_REG (DR_REG_DPORT_BASE + 0x004) +#define DPORT_APP_BOOT_REMAP (BIT(0)) +#define DPORT_APP_BOOT_REMAP_S 0 + +#define DPORT_ACCESS_CHECK (DR_REG_DPORT_BASE + 0x008) +#define DPORT_DPORT_ACCESS_CHECK_APP (BIT(8)) +#define DPORT_DPORT_ACCESS_CHECK_APP_S 8 +#define DPORT_DPORT_ACCESS_CHECK_PRO (BIT(0)) +#define DPORT_DPORT_ACCESS_CHECK_PRO_S 0 + +#define PRO_DPORT_APB_MASK0 (DR_REG_DPORT_BASE + 0x00C) +#define DPORT_PRODPORT_APB_MASK0 0xFFFFFFFF +#define DPORT_PRODPORT_APB_MASK0_S 0 + +#define PRO_DPORT_APB_MASK1 (DR_REG_DPORT_BASE + 0x010) +#define DPORT_PRODPORT_APB_MASK1 0xFFFFFFFF +#define DPORT_PRODPORT_APB_MASK1_S 0 + +#define APP_DPORT_APB_MASK0 (DR_REG_DPORT_BASE + 0x014) +#define DPORT_APPDPORT_APB_MASK0 0xFFFFFFFF +#define DPORT_APPDPORT_APB_MASK0_S 0 + +#define APP_DPORT_APB_MASK1 (DR_REG_DPORT_BASE + 0x018) +#define DPORT_APPDPORT_APB_MASK1 0xFFFFFFFF +#define DPORT_APPDPORT_APB_MASK1_S 0 + +#define PERI_CLK_EN (DR_REG_DPORT_BASE + 0x01C) +#define DPORT_PERI_CLK_EN 0xFFFFFFFF +#define DPORT_PERI_CLK_EN_S 0 + +#define PERI_RST_EN (DR_REG_DPORT_BASE + 0x020) +#define DPORT_PERI_RST_EN 0xFFFFFFFF +#define DPORT_PERI_RST_EN_S 0 + +#define WIFI_BB_CFG (DR_REG_DPORT_BASE + 0x024) +#define DPORT_WIFI_BB_CFG 0xFFFFFFFF +#define DPORT_WIFI_BB_CFG_S 0 + +#define WIFI_BB_CFG_2 (DR_REG_DPORT_BASE + 0x028) +#define DPORT_WIFI_BB_CFG_2 0xFFFFFFFF +#define DPORT_WIFI_BB_CFG_2_S 0 + +#define APPCPU_CTRL_REG_A (DR_REG_DPORT_BASE + 0x02C) +#define DPORT_APPCPU_RESETTING (BIT(0)) +#define DPORT_APPCPU_RESETTING_S 0 + +#define APPCPU_CTRL_REG_B (DR_REG_DPORT_BASE + 0x030) +#define DPORT_APPCPU_CLKGATE_EN (BIT(0)) +#define DPORT_APPCPU_CLKGATE_EN_S 0 + +#define APPCPU_CTRL_REG_C (DR_REG_DPORT_BASE + 0x034) +#define DPORT_APPCPU_RUNSTALL (BIT(0)) +#define DPORT_APPCPU_RUNSTALL_S 0 + +#define APPCPU_CTRL_REG_D (DR_REG_DPORT_BASE + 0x038) +#define DPORT_APPCPU_BOOT_ADDR 0xFFFFFFFF +#define DPORT_APPCPU_BOOT_ADDR_S 0 + +#define CPU_PER_CONF_REG (DR_REG_DPORT_BASE + 0x03C) +#define DPORT_FAST_CLK_RTC_SEL (BIT(3)) +#define DPORT_FAST_CLK_RTC_SEL_S 3 +#define DPORT_LOWSPEED_CLK_SEL (BIT(2)) +#define DPORT_LOWSPEED_CLK_SEL_S 2 +#define DPORT_CPUPERIOD_SEL 0x00000003 +#define DPORT_CPUPERIOD_SEL_S 0 + +#define PRO_CACHE_CTRL_REG (DR_REG_DPORT_BASE + 0x040) +#define DPORT_PRO_DRAM_HL (BIT(16)) +#define DPORT_PRO_DRAM_HL_S 16 +#define DPORT_SLAVE_REQ (BIT(15)) +#define DPORT_SLAVE_REQ_S 15 +#define DPORT_AHB_SPI_REQ (BIT(14)) +#define DPORT_AHB_SPI_REQ_S 14 +#define DPORT_PRO_SLAVE_REQ (BIT(13)) +#define DPORT_PRO_SLAVE_REQ_S 13 +#define DPORT_PRO_AHB_SPI_REQ (BIT(12)) +#define DPORT_PRO_AHB_SPI_REQ_S 12 +#define DPORT_PRO_DRAM_SPLIT (BIT(11)) +#define DPORT_PRO_DRAM_SPLIT_S 11 +#define DPORT_PRO_SINGLE_IRAM_ENA (BIT(10)) +#define DPORT_PRO_SINGLE_IRAM_ENA_S 10 +#define DPORT_PRO_CACHE_LOCK_3_EN (BIT(9)) +#define DPORT_PRO_CACHE_LOCK_3_EN_S 9 +#define DPORT_PRO_CACHE_LOCK_2_EN (BIT(8)) +#define DPORT_PRO_CACHE_LOCK_2_EN_S 8 +#define DPORT_PRO_CACHE_LOCK_1_EN (BIT(7)) +#define DPORT_PRO_CACHE_LOCK_1_EN_S 7 +#define DPORT_PRO_CACHE_LOCK_0_EN (BIT(6)) +#define DPORT_PRO_CACHE_LOCK_0_EN_S 6 +#define DPORT_PRO_CACHE_FLUSH_DONE (BIT(5)) +#define DPORT_PRO_CACHE_FLUSH_DONE_S 5 +#define DPORT_PRO_CACHE_FLUSH_ENA (BIT(4)) +#define DPORT_PRO_CACHE_FLUSH_ENA_S 4 +#define DPORT_PRO_CACHE_ENABLE (BIT(3)) +#define DPORT_PRO_CACHE_ENABLE_S 3 +#define DPORT_PRO_CACHE_MODE (BIT(2)) +#define DPORT_PRO_CACHE_MODE_S 2 + +#define PRO_CACHE_CTRL1_REG (DR_REG_DPORT_BASE + 0x044) +#define DPORT_PRO_CACHE_MMU_IA_CLR (BIT(13)) +#define DPORT_PRO_CACHE_MMU_IA_CLR_S 13 +#define DPORT_PRO_CMMU_PD (BIT(12)) +#define DPORT_PRO_CMMU_PD_S 12 +#define DPORT_PRO_CMMU_FORCE_ON (BIT(11)) +#define DPORT_PRO_CMMU_FORCE_ON_S 11 +#define DPORT_PRO_CMMU_FLASH_PAGE_MODE 0x00000003 +#define DPORT_PRO_CMMU_FLASH_PAGE_MODE_S 9 +#define DPORT_PRO_CMMU_SRAM_PAGE_MODE 0x00000007 +#define DPORT_PRO_CMMU_SRAM_PAGE_MODE_S 6 +#define DPORT_PRO_CACHE_MASK_OPSDRAM (BIT(5)) +#define DPORT_PRO_CACHE_MASK_OPSDRAM_S 5 +#define DPORT_PRO_CACHE_MASK_DROM0 (BIT(4)) +#define DPORT_PRO_CACHE_MASK_DROM0_S 4 +#define DPORT_PRO_CACHE_MASK_DRAM1 (BIT(3)) +#define DPORT_PRO_CACHE_MASK_DRAM1_S 3 +#define DPORT_PRO_CACHE_MASK_IROM0 (BIT(2)) +#define DPORT_PRO_CACHE_MASK_IROM0_S 2 +#define DPORT_PRO_CACHE_MASK_IRAM1 (BIT(1)) +#define DPORT_PRO_CACHE_MASK_IRAM1_S 1 +#define DPORT_PRO_CACHE_MASK_IRAM0 (BIT(0)) +#define DPORT_PRO_CACHE_MASK_IRAM0_S 0 + +#define PRO_CACHE_LOCK_0_ADDR_REG (DR_REG_DPORT_BASE + 0x048) +#define DPORT_PRO_CACHE_LOCK_0_ADDR_MAX 0x0000000F +#define DPORT_PRO_CACHE_LOCK_0_ADDR_MAX_S 18 +#define DPORT_PRO_CACHE_LOCK_0_ADDR_MIN 0x0000000F +#define DPORT_PRO_CACHE_LOCK_0_ADDR_MIN_S 14 +#define DPORT_PRO_CACHE_LOCK_0_ADDR_PRE 0x00003FFF +#define DPORT_PRO_CACHE_LOCK_0_ADDR_PRE_S 0 + +#define PRO_CACHE_LOCK_1_ADDR_REG (DR_REG_DPORT_BASE + 0x04C) +#define DPORT_PRO_CACHE_LOCK_1_ADDR_MAX 0x0000000F +#define DPORT_PRO_CACHE_LOCK_1_ADDR_MAX_S 18 +#define DPORT_PRO_CACHE_LOCK_1_ADDR_MIN 0x0000000F +#define DPORT_PRO_CACHE_LOCK_1_ADDR_MIN_S 14 +#define DPORT_PRO_CACHE_LOCK_1_ADDR_PRE 0x00003FFF +#define DPORT_PRO_CACHE_LOCK_1_ADDR_PRE_S 0 + +#define PRO_CACHE_LOCK_2_ADDR_REG (DR_REG_DPORT_BASE + 0x050) +#define DPORT_PRO_CACHE_LOCK_2_ADDR_MAX 0x0000000F +#define DPORT_PRO_CACHE_LOCK_2_ADDR_MAX_S 18 +#define DPORT_PRO_CACHE_LOCK_2_ADDR_MIN 0x0000000F +#define DPORT_PRO_CACHE_LOCK_2_ADDR_MIN_S 14 +#define DPORT_PRO_CACHE_LOCK_2_ADDR_PRE 0x00003FFF +#define DPORT_PRO_CACHE_LOCK_2_ADDR_PRE_S 0 + +#define PRO_CACHE_LOCK_3_ADDR_REG (DR_REG_DPORT_BASE + 0x054) +#define DPORT_PRO_CACHE_LOCK_3_ADDR_MAX 0x0000000F +#define DPORT_PRO_CACHE_LOCK_3_ADDR_MAX_S 18 +#define DPORT_PRO_CACHE_LOCK_3_ADDR_MIN 0x0000000F +#define DPORT_PRO_CACHE_LOCK_3_ADDR_MIN_S 14 +#define DPORT_PRO_CACHE_LOCK_3_ADDR_PRE 0x00003FFF +#define DPORT_PRO_CACHE_LOCK_3_ADDR_PRE_S 0 + +#define APP_CACHE_CTRL_REG (DR_REG_DPORT_BASE + 0x058) +#define DPORT_APP_DRAM_HL (BIT(14)) +#define DPORT_APP_DRAM_HL_S 14 +#define DPORT_APP_SLAVE_REQ (BIT(13)) +#define DPORT_APP_SLAVE_REQ_S 13 +#define DPORT_APP_AHB_SPI_REQ (BIT(12)) +#define DPORT_APP_AHB_SPI_REQ_S 12 +#define DPORT_APP_DRAM_SPLIT (BIT(11)) +#define DPORT_APP_DRAM_SPLIT_S 11 +#define DPORT_APP_SINGLE_IRAM_ENA (BIT(10)) +#define DPORT_APP_SINGLE_IRAM_ENA_S 10 +#define DPORT_APP_CACHE_LOCK_3_EN (BIT(9)) +#define DPORT_APP_CACHE_LOCK_3_EN_S 9 +#define DPORT_APP_CACHE_LOCK_2_EN (BIT(8)) +#define DPORT_APP_CACHE_LOCK_2_EN_S 8 +#define DPORT_APP_CACHE_LOCK_1_EN (BIT(7)) +#define DPORT_APP_CACHE_LOCK_1_EN_S 7 +#define DPORT_APP_CACHE_LOCK_0_EN (BIT(6)) +#define DPORT_APP_CACHE_LOCK_0_EN_S 6 +#define DPORT_APP_CACHE_FLUSH_DONE (BIT(5)) +#define DPORT_APP_CACHE_FLUSH_DONE_S 5 +#define DPORT_APP_CACHE_FLUSH_ENA (BIT(4)) +#define DPORT_APP_CACHE_FLUSH_ENA_S 4 +#define DPORT_APP_CACHE_ENABLE (BIT(3)) +#define DPORT_APP_CACHE_ENABLE_S 3 +#define DPORT_APP_CACHE_MODE (BIT(2)) +#define DPORT_APP_CACHE_MODE_S 2 + +#define APP_CACHE_CTRL1_REG (DR_REG_DPORT_BASE + 0x05C) +#define DPORT_APP_CACHE_MMU_IA_CLR (BIT(13)) +#define DPORT_APP_CACHE_MMU_IA_CLR_S 13 +#define DPORT_APP_CMMU_PD (BIT(12)) +#define DPORT_APP_CMMU_PD_S 12 +#define DPORT_APP_CMMU_FORCE_ON (BIT(11)) +#define DPORT_APP_CMMU_FORCE_ON_S 11 +#define DPORT_APP_CMMU_FLASH_PAGE_MODE 0x00000003 +#define DPORT_APP_CMMU_FLASH_PAGE_MODE_S 9 +#define DPORT_APP_CMMU_SRAM_PAGE_MODE 0x00000007 +#define DPORT_APP_CMMU_SRAM_PAGE_MODE_S 6 +#define DPORT_APP_CACHE_MASK_OPSDRAM (BIT(5)) +#define DPORT_APP_CACHE_MASK_OPSDRAM_S 5 +#define DPORT_APP_CACHE_MASK_DROM0 (BIT(4)) +#define DPORT_APP_CACHE_MASK_DROM0_S 4 +#define DPORT_APP_CACHE_MASK_DRAM1 (BIT(3)) +#define DPORT_APP_CACHE_MASK_DRAM1_S 3 +#define DPORT_APP_CACHE_MASK_IROM0 (BIT(2)) +#define DPORT_APP_CACHE_MASK_IROM0_S 2 +#define DPORT_APP_CACHE_MASK_IRAM1 (BIT(1)) +#define DPORT_APP_CACHE_MASK_IRAM1_S 1 +#define DPORT_APP_CACHE_MASK_IRAM0 (BIT(0)) +#define DPORT_APP_CACHE_MASK_IRAM0_S 0 + +#define APP_CACHE_LOCK_0_ADDR_REG (DR_REG_DPORT_BASE + 0x060) +#define DPORT_APP_CACHE_LOCK_0_ADDR_MAX 0x0000000F +#define DPORT_APP_CACHE_LOCK_0_ADDR_MAX_S 18 +#define DPORT_APP_CACHE_LOCK_0_ADDR_MIN 0x0000000F +#define DPORT_APP_CACHE_LOCK_0_ADDR_MIN_S 14 +#define DPORT_APP_CACHE_LOCK_0_ADDR_PRE 0x00003FFF +#define DPORT_APP_CACHE_LOCK_0_ADDR_PRE_S 0 + +#define APP_CACHE_LOCK_1_ADDR_REG (DR_REG_DPORT_BASE + 0x064) +#define DPORT_APP_CACHE_LOCK_1_ADDR_MAX 0x0000000F +#define DPORT_APP_CACHE_LOCK_1_ADDR_MAX_S 18 +#define DPORT_APP_CACHE_LOCK_1_ADDR_MIN 0x0000000F +#define DPORT_APP_CACHE_LOCK_1_ADDR_MIN_S 14 +#define DPORT_APP_CACHE_LOCK_1_ADDR_PRE 0x00003FFF +#define DPORT_APP_CACHE_LOCK_1_ADDR_PRE_S 0 + +#define APP_CACHE_LOCK_2_ADDR_REG (DR_REG_DPORT_BASE + 0x068) +#define DPORT_APP_CACHE_LOCK_2_ADDR_MAX 0x0000000F +#define DPORT_APP_CACHE_LOCK_2_ADDR_MAX_S 18 +#define DPORT_APP_CACHE_LOCK_2_ADDR_MIN 0x0000000F +#define DPORT_APP_CACHE_LOCK_2_ADDR_MIN_S 14 +#define DPORT_APP_CACHE_LOCK_2_ADDR_PRE 0x00003FFF +#define DPORT_APP_CACHE_LOCK_2_ADDR_PRE_S 0 + +#define APP_CACHE_LOCK_3_ADDR_REG (DR_REG_DPORT_BASE + 0x06C) +#define DPORT_APP_CACHE_LOCK_3_ADDR_MAX 0x0000000F +#define DPORT_APP_CACHE_LOCK_3_ADDR_MAX_S 18 +#define DPORT_APP_CACHE_LOCK_3_ADDR_MIN 0x0000000F +#define DPORT_APP_CACHE_LOCK_3_ADDR_MIN_S 14 +#define DPORT_APP_CACHE_LOCK_3_ADDR_PRE 0x00003FFF +#define DPORT_APP_CACHE_LOCK_3_ADDR_PRE_S 0 + +#define TRACEMEM_MUX_MODE (DR_REG_DPORT_BASE + 0x070) +#define DPORT_TRACEMEM_MUX_MODE 0x00000003 +#define DPORT_TRACEMEM_MUX_MODE_S 0 + +#define PRO_TRACEMEM_ENA (DR_REG_DPORT_BASE + 0x074) +#define DPORT_PRO_TRACEMEM_ENA (BIT(0)) +#define DPORT_PRO_TRACEMEM_ENA_S 0 + +#define APP_TRACEMEM_ENA (DR_REG_DPORT_BASE + 0x078) +#define DPORT_APP_TRACEMEM_ENA (BIT(0)) +#define DPORT_APP_TRACEMEM_ENA_S 0 + +#define CACHE_MUX_MODE (DR_REG_DPORT_BASE + 0x07C) +#define DPORT_CACHE_MUX_MODE 0x00000003 +#define DPORT_CACHE_MUX_MODE_S 0 + +#define IMMU_PAGE_MODE (DR_REG_DPORT_BASE + 0x080) +#define DPORT_IMMU_PAGE_MODE 0x00000003 +#define DPORT_IMMU_PAGE_MODE_S 1 +#define DPORT_INTERNAL_SRAM_IMMU_ENA (BIT(0)) +#define DPORT_INTERNAL_SRAM_IMMU_ENA_S 0 + +#define DMMU_PAGE_MODE (DR_REG_DPORT_BASE + 0x084) +#define DPORT_DMMU_PAGE_MODE 0x00000003 +#define DPORT_DMMU_PAGE_MODE_S 1 +#define DPORT_INTERNAL_SRAM_DMMU_ENA (BIT(0)) +#define DPORT_INTERNAL_SRAM_DMMU_ENA_S 0 + +#define ROM_MPU_ENA (DR_REG_DPORT_BASE + 0x088) +#define DPORT_APP_ROM_MPU_ENA (BIT(2)) +#define DPORT_APP_ROM_MPU_ENA_S 2 +#define DPORT_PRO_ROM_MPU_ENA (BIT(1)) +#define DPORT_PRO_ROM_MPU_ENA_S 1 +#define DPORT_SHARE_ROM_MPU_ENA (BIT(0)) +#define DPORT_SHARE_ROM_MPU_ENA_S 0 + +#define MEM_PD_MASK_REG (DR_REG_DPORT_BASE + 0x08C) +#define DPORT_LSLP_MEM_PD_MASK (BIT(0)) +#define DPORT_LSLP_MEM_PD_MASK_S 0 + +#define ROM_PD_CTRL_REG (DR_REG_DPORT_BASE + 0x090) +#define DPORT_SHARE_ROM_PD 0x0000003F +#define DPORT_SHARE_ROM_PD_S 2 +#define DPORT_APP_ROM_PD (BIT(1)) +#define DPORT_APP_ROM_PD_S 1 +#define DPORT_PRO_ROM_PD (BIT(0)) +#define DPORT_PRO_ROM_PD_S 0 + +#define ROM_FO_CTRL_REG (DR_REG_DPORT_BASE + 0x094) +#define DPORT_SHARE_ROM_FO 0x0000003F +#define DPORT_SHARE_ROM_FO_S 2 +#define DPORT_APP_ROM_FO (BIT(1)) +#define DPORT_APP_ROM_FO_S 1 +#define DPORT_PRO_ROM_FO (BIT(0)) +#define DPORT_PRO_ROM_FO_S 0 + +#define SRAM_PD_CTRL_REG_0 (DR_REG_DPORT_BASE + 0x098) +#define DPORT_SRAM_PD_0 0xFFFFFFFF +#define DPORT_SRAM_PD_0_S 0 + +#define SRAM_PD_CTRL_REG_1 (DR_REG_DPORT_BASE + 0x09C) +#define DPORT_SRAM_PD_1 (BIT(0)) +#define DPORT_SRAM_PD_1_S 0 + +#define SRAM_FO_CTRL_REG_0 (DR_REG_DPORT_BASE + 0x0A0) +#define DPORT_SRAM_FO_0 0xFFFFFFFF +#define DPORT_SRAM_FO_0_S 0 + +#define SRAM_FO_CTRL_REG_1 (DR_REG_DPORT_BASE + 0x0A4) +#define DPORT_SRAM_FO_1 (BIT(0)) +#define DPORT_SRAM_FO_1_S 0 + +#define IRAM_DRAM_AHB_SEL (DR_REG_DPORT_BASE + 0x0A8) +#define DPORT_MAC_DUMP_MODE 0x00000003 +#define DPORT_MAC_DUMP_MODE_S 5 +#define DPORT_MASK_AHB (BIT(4)) +#define DPORT_MASK_AHB_S 4 +#define DPORT_MASK_APP_DRAM (BIT(3)) +#define DPORT_MASK_APP_DRAM_S 3 +#define DPORT_MASK_PRO_DRAM (BIT(2)) +#define DPORT_MASK_PRO_DRAM_S 2 +#define DPORT_MASK_APP_IRAM (BIT(1)) +#define DPORT_MASK_APP_IRAM_S 1 +#define DPORT_MASK_PRO_IRAM (BIT(0)) +#define DPORT_MASK_PRO_IRAM_S 0 + +#define TAG_FO_CTRL_REG (DR_REG_DPORT_BASE + 0x0AC) +#define DPORT_APP_CACHE_TAG_PD (BIT(9)) +#define DPORT_APP_CACHE_TAG_PD_S 9 +#define DPORT_APP_CACHE_TAG_FORCE_ON (BIT(8)) +#define DPORT_APP_CACHE_TAG_FORCE_ON_S 8 +#define DPORT_PRO_CACHE_TAG_PD (BIT(1)) +#define DPORT_PRO_CACHE_TAG_PD_S 1 +#define DPORT_PRO_CACHE_TAG_FORCE_ON (BIT(0)) +#define DPORT_PRO_CACHE_TAG_FORCE_ON_S 0 + +#define AHB_LITE_MASK_REG (DR_REG_DPORT_BASE + 0x0B0) +#define DPORT_AHB_LITE_SDHOST_PID_REG 0x00000007 +#define DPORT_AHB_LITE_SDHOST_PID_REG_S 11 +#define DPORT_AHB_LITE_MASK_APPDPORT (BIT(10)) +#define DPORT_AHB_LITE_MASK_APPDPORT_S 10 +#define DPORT_AHB_LITE_MASK_PRODPORT (BIT(9)) +#define DPORT_AHB_LITE_MASK_PRODPORT_S 9 +#define DPORT_AHB_LITE_MASK_SDIO (BIT(8)) +#define DPORT_AHB_LITE_MASK_SDIO_S 8 +#define DPORT_AHB_LITE_MASK_APP (BIT(4)) +#define DPORT_AHB_LITE_MASK_APP_S 4 +#define DPORT_AHB_LITE_MASK_PRO (BIT(0)) +#define DPORT_AHB_LITE_MASK_PRO_S 0 + +#define AHB_MPU_TABLE_0 (DR_REG_DPORT_BASE + 0x0B4) +#define DPORT_AHB_ACCESS_GRANT_0 0xFFFFFFFF +#define DPORT_AHB_ACCESS_GRANT_0_S 0 + +#define AHB_MPU_TABLE_1 (DR_REG_DPORT_BASE + 0x0B8) +#define DPORT_AHB_ACCESS_GRANT_1 0x000001FF +#define DPORT_AHB_ACCESS_GRANT_1_S 0 + +#define HOST_INF_SEL (DR_REG_DPORT_BASE + 0x0BC) +#define DPORT_LINK_DEVICE_SEL 0x000000FF +#define DPORT_LINK_DEVICE_SEL_S 8 +#define DPORT_PERI_IO_SWAP 0x000000FF +#define DPORT_PERI_IO_SWAP_S 0 + +#define PERIP_CLK_EN (DR_REG_DPORT_BASE + 0x0C0) +#define DPORT_PERIP_CLK_EN 0xFFFFFFFF +#define DPORT_PERIP_CLK_EN_S 0 + +#define PERIP_RST_EN (DR_REG_DPORT_BASE + 0x0C4) +#define DPORT_PERIP_RST 0xFFFFFFFF +#define DPORT_PERIP_RST_S 0 + +#define SLAVE_SPI_CONFIG_REG (DR_REG_DPORT_BASE + 0x0C8) +#define DPORT_SPI_DECRYPT_ENABLE (BIT(12)) +#define DPORT_SPI_DECRYPT_ENABLE_S 12 +#define DPORT_SPI_ENCRYPT_ENABLE (BIT(8)) +#define DPORT_SPI_ENCRYPT_ENABLE_S 8 +#define DPORT_SLAVE_SPI_MASK_APP (BIT(4)) +#define DPORT_SLAVE_SPI_MASK_APP_S 4 +#define DPORT_SLAVE_SPI_MASK_PRO (BIT(0)) +#define DPORT_SLAVE_SPI_MASK_PRO_S 0 + +#define WIFI_CLK_EN (DR_REG_DPORT_BASE + 0x0CC) +#define DPORT_WIFI_CLK_EN 0xFFFFFFFF +#define DPORT_WIFI_CLK_EN_S 0 + +#define WIFI_RST_EN (DR_REG_DPORT_BASE + 0x0D0) +#define DPORT_SDIO_RST (BIT(5)) +#define DPORT_MAC_RST (BIT(2)) +#define DPORT_WIFI_RST 0xFFFFFFFF +#define DPORT_WIFI_RST_S 0 + +#define BT_LPCK_DIV_INT (DR_REG_DPORT_BASE + 0x0D4) +#define DPORT_BTEXTWAKEUP_REQ (BIT(12)) +#define DPORT_BTEXTWAKEUP_REQ_S 12 +#define DPORT_BT_LPCK_DIV_NUM 0x00000FFF +#define DPORT_BT_LPCK_DIV_NUM_S 0 + +#define BT_LPCK_DIV_FRAC (DR_REG_DPORT_BASE + 0x0D8) +#define DPORT_LPCLK_SEL_XTAL32K (BIT(27)) +#define DPORT_LPCLK_SEL_XTAL32K_S 27 +#define DPORT_LPCLK_SEL_XTAL (BIT(26)) +#define DPORT_LPCLK_SEL_XTAL_S 26 +#define DPORT_LPCLK_SEL_8M (BIT(25)) +#define DPORT_LPCLK_SEL_8M_S 25 +#define DPORT_LPCLK_SEL_RTC_SLOW (BIT(24)) +#define DPORT_LPCLK_SEL_RTC_SLOW_S 24 +#define DPORT_BT_LPCK_DIV_A 0x00000FFF +#define DPORT_BT_LPCK_DIV_A_S 12 +#define DPORT_BT_LPCK_DIV_B 0x00000FFF +#define DPORT_BT_LPCK_DIV_B_S 0 + +#define CPU_INTR_FROM_CPU_0_REG (DR_REG_DPORT_BASE + 0x0DC) +#define DPORT_CPU_INTR_FROM_CPU_0 (BIT(0)) +#define DPORT_CPU_INTR_FROM_CPU_0_S 0 + +#define CPU_INTR_FROM_CPU_1_REG (DR_REG_DPORT_BASE + 0x0E0) +#define DPORT_CPU_INTR_FROM_CPU_1 (BIT(0)) +#define DPORT_CPU_INTR_FROM_CPU_1_S 0 + +#define CPU_INTR_FROM_CPU_2_REG (DR_REG_DPORT_BASE + 0x0E4) +#define DPORT_CPU_INTR_FROM_CPU_2 (BIT(0)) +#define DPORT_CPU_INTR_FROM_CPU_2_S 0 + +#define CPU_INTR_FROM_CPU_3_REG (DR_REG_DPORT_BASE + 0x0E8) +#define DPORT_CPU_INTR_FROM_CPU_3 (BIT(0)) +#define DPORT_CPU_INTR_FROM_CPU_3_S 0 + +#define PRO_INTR_STATUS_REG_0 (DR_REG_DPORT_BASE + 0x0EC) +#define DPORT_PRO_INTR_STATUS_0 0xFFFFFFFF +#define DPORT_PRO_INTR_STATUS_0_S 0 + +#define PRO_INTR_STATUS_REG_1 (DR_REG_DPORT_BASE + 0x0F0) +#define DPORT_PRO_INTR_STATUS_1 0xFFFFFFFF +#define DPORT_PRO_INTR_STATUS_1_S 0 + +#define PRO_INTR_STATUS_REG_2 (DR_REG_DPORT_BASE + 0x0F4) +#define DPORT_PRO_INTR_STATUS_2 0xFFFFFFFF +#define DPORT_PRO_INTR_STATUS_2_S 0 + +#define APP_INTR_STATUS_REG_0 (DR_REG_DPORT_BASE + 0x0F8) +#define DPORT_APP_INTR_STATUS_0 0xFFFFFFFF +#define DPORT_APP_INTR_STATUS_0_S 0 + +#define APP_INTR_STATUS_REG_1 (DR_REG_DPORT_BASE + 0x0FC) +#define DPORT_APP_INTR_STATUS_1 0xFFFFFFFF +#define DPORT_APP_INTR_STATUS_1_S 0 + +#define APP_INTR_STATUS_REG_2 (DR_REG_DPORT_BASE + 0x100) +#define DPORT_APP_INTR_STATUS_2 0xFFFFFFFF +#define DPORT_APP_INTR_STATUS_2_S 0 + +#define PRO_MAC_INTR_MAP_REG (DR_REG_DPORT_BASE + 0x104) +#define DPORT_PRO_MAC_INTR_MAP 0x0000001F +#define DPORT_PRO_MAC_INTR_MAP_S 0 + +#define PRO_MAC_NMI_MAP_REG (DR_REG_DPORT_BASE + 0x108) +#define DPORT_PRO_MAC_NMI_MAP 0x0000001F +#define DPORT_PRO_MAC_NMI_MAP_S 0 + +#define PRO_BB_INT_MAP_REG (DR_REG_DPORT_BASE + 0x10C) +#define DPORT_PRO_BB_INT_MAP 0x0000001F +#define DPORT_PRO_BB_INT_MAP_S 0 + +#define PRO_BT_MAC_INT_MAP_REG (DR_REG_DPORT_BASE + 0x110) +#define DPORT_PRO_BT_MAC_INT_MAP 0x0000001F +#define DPORT_PRO_BT_MAC_INT_MAP_S 0 + +#define PRO_BT_BB_INT_MAP_REG (DR_REG_DPORT_BASE + 0x114) +#define DPORT_PRO_BT_BB_INT_MAP 0x0000001F +#define DPORT_PRO_BT_BB_INT_MAP_S 0 + +#define PRO_BT_BB_NMI_MAP_REG (DR_REG_DPORT_BASE + 0x118) +#define DPORT_PRO_BT_BB_NMI_MAP 0x0000001F +#define DPORT_PRO_BT_BB_NMI_MAP_S 0 + +#define PRO_RWBT_IRQ_MAP_REG (DR_REG_DPORT_BASE + 0x11C) +#define DPORT_PRO_RWBT_IRQ_MAP 0x0000001F +#define DPORT_PRO_RWBT_IRQ_MAP_S 0 + +#define PRO_RWBLE_IRQ_MAP_REG (DR_REG_DPORT_BASE + 0x120) +#define DPORT_PRO_RWBLE_IRQ_MAP 0x0000001F +#define DPORT_PRO_RWBLE_IRQ_MAP_S 0 + +#define PRO_RWBT_NMI_MAP_REG (DR_REG_DPORT_BASE + 0x124) +#define DPORT_PRO_RWBT_NMI_MAP 0x0000001F +#define DPORT_PRO_RWBT_NMI_MAP_S 0 + +#define PRO_RWBLE_NMI_MAP_REG (DR_REG_DPORT_BASE + 0x128) +#define DPORT_PRO_RWBLE_NMI_MAP 0x0000001F +#define DPORT_PRO_RWBLE_NMI_MAP_S 0 + +#define PRO_SLC0_INTR_MAP_REG (DR_REG_DPORT_BASE + 0x12C) +#define DPORT_PRO_SLC0_INTR_MAP 0x0000001F +#define DPORT_PRO_SLC0_INTR_MAP_S 0 + +#define PRO_SLC1_INTR_MAP_REG (DR_REG_DPORT_BASE + 0x130) +#define DPORT_PRO_SLC1_INTR_MAP 0x0000001F +#define DPORT_PRO_SLC1_INTR_MAP_S 0 + +#define PRO_UHCI0_INTR_MAP_REG (DR_REG_DPORT_BASE + 0x134) +#define DPORT_PRO_UHCI0_INTR_MAP 0x0000001F +#define DPORT_PRO_UHCI0_INTR_MAP_S 0 + +#define PRO_UHCI1_INTR_MAP_REG (DR_REG_DPORT_BASE + 0x138) +#define DPORT_PRO_UHCI1_INTR_MAP 0x0000001F +#define DPORT_PRO_UHCI1_INTR_MAP_S 0 + +#define PRO_TG_T0_LEVEL_INT_MAP_REG (DR_REG_DPORT_BASE + 0x13C) +#define DPORT_PRO_TG_T0_LEVEL_INT_MAP 0x0000001F +#define DPORT_PRO_TG_T0_LEVEL_INT_MAP_S 0 + +#define PRO_TG_T1_LEVEL_INT_MAP_REG (DR_REG_DPORT_BASE + 0x140) +#define DPORT_PRO_TG_T1_LEVEL_INT_MAP 0x0000001F +#define DPORT_PRO_TG_T1_LEVEL_INT_MAP_S 0 + +#define PRO_TG_WDT_LEVEL_INT_MAP_REG (DR_REG_DPORT_BASE + 0x144) +#define DPORT_PRO_TG_WDT_LEVEL_INT_MAP 0x0000001F +#define DPORT_PRO_TG_WDT_LEVEL_INT_MAP_S 0 + +#define PRO_TG_LACT_LEVEL_INT_MAP_REG (DR_REG_DPORT_BASE + 0x148) +#define DPORT_PRO_TG_LACT_LEVEL_INT_MAP 0x0000001F +#define DPORT_PRO_TG_LACT_LEVEL_INT_MAP_S 0 + +#define PRO_TG1_T0_LEVEL_INT_MAP_REG (DR_REG_DPORT_BASE + 0x14C) +#define DPORT_PRO_TG1_T0_LEVEL_INT_MAP 0x0000001F +#define DPORT_PRO_TG1_T0_LEVEL_INT_MAP_S 0 + +#define PRO_TG1_T1_LEVEL_INT_MAP_REG (DR_REG_DPORT_BASE + 0x150) +#define DPORT_PRO_TG1_T1_LEVEL_INT_MAP 0x0000001F +#define DPORT_PRO_TG1_T1_LEVEL_INT_MAP_S 0 + +#define PRO_TG1_WDT_LEVEL_INT_MAP_REG (DR_REG_DPORT_BASE + 0x154) +#define DPORT_PRO_TG1_WDT_LEVEL_INT_MAP 0x0000001F +#define DPORT_PRO_TG1_WDT_LEVEL_INT_MAP_S 0 + +#define PRO_TG1_LACT_LEVEL_INT_MAP_REG (DR_REG_DPORT_BASE + 0x158) +#define DPORT_PRO_TG1_LACT_LEVEL_INT_MAP 0x0000001F +#define DPORT_PRO_TG1_LACT_LEVEL_INT_MAP_S 0 + +#define PRO_GPIO_INTERRUPT_MAP_REG (DR_REG_DPORT_BASE + 0x15C) +#define DPORT_PRO_GPIO_INTERRUPT_PRO_MAP 0x0000001F +#define DPORT_PRO_GPIO_INTERRUPT_PRO_MAP_S 0 + +#define PRO_GPIO_INTERRUPT_NMI_MAP_REG (DR_REG_DPORT_BASE + 0x160) +#define DPORT_PRO_GPIO_INTERRUPT_PRO_NMI_MAP 0x0000001F +#define DPORT_PRO_GPIO_INTERRUPT_PRO_NMI_MAP_S 0 + +#define PRO_CPU_INTR_FROM_CPU_0_MAP_REG (DR_REG_DPORT_BASE + 0x164) +#define DPORT_PRO_CPU_INTR_FROM_CPU_0_MAP 0x0000001F +#define DPORT_PRO_CPU_INTR_FROM_CPU_0_MAP_S 0 + +#define PRO_CPU_INTR_FROM_CPU_1_MAP_REG (DR_REG_DPORT_BASE + 0x168) +#define DPORT_PRO_CPU_INTR_FROM_CPU_1_MAP 0x0000001F +#define DPORT_PRO_CPU_INTR_FROM_CPU_1_MAP_S 0 + +#define PRO_CPU_INTR_FROM_CPU_2_MAP_REG (DR_REG_DPORT_BASE + 0x16C) +#define DPORT_PRO_CPU_INTR_FROM_CPU_2_MAP 0x0000001F +#define DPORT_PRO_CPU_INTR_FROM_CPU_2_MAP_S 0 + +#define PRO_CPU_INTR_FROM_CPU_3_MAP_REG (DR_REG_DPORT_BASE + 0x170) +#define DPORT_PRO_CPU_INTR_FROM_CPU_3_MAP 0x0000001F +#define DPORT_PRO_CPU_INTR_FROM_CPU_3_MAP_S 0 + +#define PRO_SPI_INTR_0_MAP_REG (DR_REG_DPORT_BASE + 0x174) +#define DPORT_PRO_SPI_INTR_0_MAP 0x0000001F +#define DPORT_PRO_SPI_INTR_0_MAP_S 0 + +#define PRO_SPI_INTR_1_MAP_REG (DR_REG_DPORT_BASE + 0x178) +#define DPORT_PRO_SPI_INTR_1_MAP 0x0000001F +#define DPORT_PRO_SPI_INTR_1_MAP_S 0 + +#define PRO_SPI_INTR_2_MAP_REG (DR_REG_DPORT_BASE + 0x17C) +#define DPORT_PRO_SPI_INTR_2_MAP 0x0000001F +#define DPORT_PRO_SPI_INTR_2_MAP_S 0 + +#define PRO_SPI_INTR_3_MAP_REG (DR_REG_DPORT_BASE + 0x180) +#define DPORT_PRO_SPI_INTR_3_MAP 0x0000001F +#define DPORT_PRO_SPI_INTR_3_MAP_S 0 + +#define PRO_I2S0_INT_MAP_REG (DR_REG_DPORT_BASE + 0x184) +#define DPORT_PRO_I2S0_INT_MAP 0x0000001F +#define DPORT_PRO_I2S0_INT_MAP_S 0 + +#define PRO_I2S1_INT_MAP_REG (DR_REG_DPORT_BASE + 0x188) +#define DPORT_PRO_I2S1_INT_MAP 0x0000001F +#define DPORT_PRO_I2S1_INT_MAP_S 0 + +#define PRO_UART_INTR_MAP_REG (DR_REG_DPORT_BASE + 0x18C) +#define DPORT_PRO_UART_INTR_MAP 0x0000001F +#define DPORT_PRO_UART_INTR_MAP_S 0 + +#define PRO_UART1_INTR_MAP_REG (DR_REG_DPORT_BASE + 0x190) +#define DPORT_PRO_UART1_INTR_MAP 0x0000001F +#define DPORT_PRO_UART1_INTR_MAP_S 0 + +#define PRO_UART2_INTR_MAP_REG (DR_REG_DPORT_BASE + 0x194) +#define DPORT_PRO_UART2_INTR_MAP 0x0000001F +#define DPORT_PRO_UART2_INTR_MAP_S 0 + +#define PRO_SDIO_HOST_INTERRUPT_MAP_REG (DR_REG_DPORT_BASE + 0x198) +#define DPORT_PRO_SDIO_HOST_INTERRUPT_MAP 0x0000001F +#define DPORT_PRO_SDIO_HOST_INTERRUPT_MAP_S 0 + +#define PRO_EMAC_INT_MAP_REG (DR_REG_DPORT_BASE + 0x19C) +#define DPORT_PRO_EMAC_INT_MAP 0x0000001F +#define DPORT_PRO_EMAC_INT_MAP_S 0 + +#define PRO_PWM0_INTR_MAP_REG (DR_REG_DPORT_BASE + 0x1A0) +#define DPORT_PRO_PWM0_INTR_MAP 0x0000001F +#define DPORT_PRO_PWM0_INTR_MAP_S 0 + +#define PRO_PWM1_INTR_MAP_REG (DR_REG_DPORT_BASE + 0x1A4) +#define DPORT_PRO_PWM1_INTR_MAP 0x0000001F +#define DPORT_PRO_PWM1_INTR_MAP_S 0 + +#define PRO_PWM2_INTR_MAP_REG (DR_REG_DPORT_BASE + 0x1A8) +#define DPORT_PRO_PWM2_INTR_MAP 0x0000001F +#define DPORT_PRO_PWM2_INTR_MAP_S 0 + +#define PRO_PWM3_INTR_MAP_REG (DR_REG_DPORT_BASE + 0x1AC) +#define DPORT_PRO_PWM3_INTR_MAP 0x0000001F +#define DPORT_PRO_PWM3_INTR_MAP_S 0 + +#define PRO_LEDC_INT_MAP_REG (DR_REG_DPORT_BASE + 0x1B0) +#define DPORT_PRO_LEDC_INT_MAP 0x0000001F +#define DPORT_PRO_LEDC_INT_MAP_S 0 + +#define PRO_EFUSE_INT_MAP_REG (DR_REG_DPORT_BASE + 0x1B4) +#define DPORT_PRO_EFUSE_INT_MAP 0x0000001F +#define DPORT_PRO_EFUSE_INT_MAP_S 0 + +#define PRO_CAN_INT_MAP_REG (DR_REG_DPORT_BASE + 0x1B8) +#define DPORT_PRO_CAN_INT_MAP 0x0000001F +#define DPORT_PRO_CAN_INT_MAP_S 0 + +#define PRO_RTC_CORE_INTR_MAP_REG (DR_REG_DPORT_BASE + 0x1BC) +#define DPORT_PRO_RTC_CORE_INTR_MAP 0x0000001F +#define DPORT_PRO_RTC_CORE_INTR_MAP_S 0 + +#define PRO_RMT_INTR_MAP_REG (DR_REG_DPORT_BASE + 0x1C0) +#define DPORT_PRO_RMT_INTR_MAP 0x0000001F +#define DPORT_PRO_RMT_INTR_MAP_S 0 + +#define PRO_PCNT_INTR_MAP_REG (DR_REG_DPORT_BASE + 0x1C4) +#define DPORT_PRO_PCNT_INTR_MAP 0x0000001F +#define DPORT_PRO_PCNT_INTR_MAP_S 0 + +#define PRO_I2C_EXT0_INTR_MAP_REG (DR_REG_DPORT_BASE + 0x1C8) +#define DPORT_PRO_I2C_EXT0_INTR_MAP 0x0000001F +#define DPORT_PRO_I2C_EXT0_INTR_MAP_S 0 + +#define PRO_I2C_EXT1_INTR_MAP_REG (DR_REG_DPORT_BASE + 0x1CC) +#define DPORT_PRO_I2C_EXT1_INTR_MAP 0x0000001F +#define DPORT_PRO_I2C_EXT1_INTR_MAP_S 0 + +#define PRO_RSA_INTR_MAP_REG (DR_REG_DPORT_BASE + 0x1D0) +#define DPORT_PRO_RSA_INTR_MAP 0x0000001F +#define DPORT_PRO_RSA_INTR_MAP_S 0 + +#define PRO_SPI1_DMA_INT_MAP_REG (DR_REG_DPORT_BASE + 0x1D4) +#define DPORT_PRO_SPI1_DMA_INT_MAP 0x0000001F +#define DPORT_PRO_SPI1_DMA_INT_MAP_S 0 + +#define PRO_SPI2_DMA_INT_MAP_REG (DR_REG_DPORT_BASE + 0x1D8) +#define DPORT_PRO_SPI2_DMA_INT_MAP 0x0000001F +#define DPORT_PRO_SPI2_DMA_INT_MAP_S 0 + +#define PRO_SPI3_DMA_INT_MAP_REG (DR_REG_DPORT_BASE + 0x1DC) +#define DPORT_PRO_SPI3_DMA_INT_MAP 0x0000001F +#define DPORT_PRO_SPI3_DMA_INT_MAP_S 0 + +#define PRO_WDG_INT_MAP_REG (DR_REG_DPORT_BASE + 0x1E0) +#define DPORT_PRO_WDG_INT_MAP 0x0000001F +#define DPORT_PRO_WDG_INT_MAP_S 0 + +#define PRO_TIMER_INT1_MAP_REG (DR_REG_DPORT_BASE + 0x1E4) +#define DPORT_PRO_TIMER_INT1_MAP 0x0000001F +#define DPORT_PRO_TIMER_INT1_MAP_S 0 + +#define PRO_TIMER_INT2_MAP_REG (DR_REG_DPORT_BASE + 0x1E8) +#define DPORT_PRO_TIMER_INT2_MAP 0x0000001F +#define DPORT_PRO_TIMER_INT2_MAP_S 0 + +#define PRO_TG_T0_EDGE_INT_MAP_REG (DR_REG_DPORT_BASE + 0x1EC) +#define DPORT_PRO_TG_T0_EDGE_INT_MAP 0x0000001F +#define DPORT_PRO_TG_T0_EDGE_INT_MAP_S 0 + +#define PRO_TG_T1_EDGE_INT_MAP_REG (DR_REG_DPORT_BASE + 0x1F0) +#define DPORT_PRO_TG_T1_EDGE_INT_MAP 0x0000001F +#define DPORT_PRO_TG_T1_EDGE_INT_MAP_S 0 + +#define PRO_TG_WDT_EDGE_INT_MAP_REG (DR_REG_DPORT_BASE + 0x1F4) +#define DPORT_PRO_TG_WDT_EDGE_INT_MAP 0x0000001F +#define DPORT_PRO_TG_WDT_EDGE_INT_MAP_S 0 + +#define PRO_TG_LACT_EDGE_INT_MAP_REG (DR_REG_DPORT_BASE + 0x1F8) +#define DPORT_PRO_TG_LACT_EDGE_INT_MAP 0x0000001F +#define DPORT_PRO_TG_LACT_EDGE_INT_MAP_S 0 + +#define PRO_TG1_T0_EDGE_INT_MAP_REG (DR_REG_DPORT_BASE + 0x1FC) +#define DPORT_PRO_TG1_T0_EDGE_INT_MAP 0x0000001F +#define DPORT_PRO_TG1_T0_EDGE_INT_MAP_S 0 + +#define PRO_TG1_T1_EDGE_INT_MAP_REG (DR_REG_DPORT_BASE + 0x200) +#define DPORT_PRO_TG1_T1_EDGE_INT_MAP 0x0000001F +#define DPORT_PRO_TG1_T1_EDGE_INT_MAP_S 0 + +#define PRO_TG1_WDT_EDGE_INT_MAP_REG (DR_REG_DPORT_BASE + 0x204) +#define DPORT_PRO_TG1_WDT_EDGE_INT_MAP 0x0000001F +#define DPORT_PRO_TG1_WDT_EDGE_INT_MAP_S 0 + +#define PRO_TG1_LACT_EDGE_INT_MAP_REG (DR_REG_DPORT_BASE + 0x208) +#define DPORT_PRO_TG1_LACT_EDGE_INT_MAP 0x0000001F +#define DPORT_PRO_TG1_LACT_EDGE_INT_MAP_S 0 + +#define PRO_MMU_IA_INT_MAP_REG (DR_REG_DPORT_BASE + 0x20C) +#define DPORT_PRO_MMU_IA_INT_MAP 0x0000001F +#define DPORT_PRO_MMU_IA_INT_MAP_S 0 + +#define PRO_MPU_IA_INT_MAP_REG (DR_REG_DPORT_BASE + 0x210) +#define DPORT_PRO_MPU_IA_INT_MAP 0x0000001F +#define DPORT_PRO_MPU_IA_INT_MAP_S 0 + +#define PRO_CACHE_IA_INT_MAP_REG (DR_REG_DPORT_BASE + 0x214) +#define DPORT_PRO_CACHE_IA_INT_MAP 0x0000001F +#define DPORT_PRO_CACHE_IA_INT_MAP_S 0 + +#define APP_MAC_INTR_MAP_REG (DR_REG_DPORT_BASE + 0x218) +#define DPORT_APP_MAC_INTR_MAP 0x0000001F +#define DPORT_APP_MAC_INTR_MAP_S 0 + +#define APP_MAC_NMI_MAP_REG (DR_REG_DPORT_BASE + 0x21C) +#define DPORT_APP_MAC_NMI_MAP 0x0000001F +#define DPORT_APP_MAC_NMI_MAP_S 0 + +#define APP_BB_INT_MAP_REG (DR_REG_DPORT_BASE + 0x220) +#define DPORT_APP_BB_INT_MAP 0x0000001F +#define DPORT_APP_BB_INT_MAP_S 0 + +#define APP_BT_MAC_INT_MAP_REG (DR_REG_DPORT_BASE + 0x224) +#define DPORT_APP_BT_MAC_INT_MAP 0x0000001F +#define DPORT_APP_BT_MAC_INT_MAP_S 0 + +#define APP_BT_BB_INT_MAP_REG (DR_REG_DPORT_BASE + 0x228) +#define DPORT_APP_BT_BB_INT_MAP 0x0000001F +#define DPORT_APP_BT_BB_INT_MAP_S 0 + +#define APP_BT_BB_NMI_MAP_REG (DR_REG_DPORT_BASE + 0x22C) +#define DPORT_APP_BT_BB_NMI_MAP 0x0000001F +#define DPORT_APP_BT_BB_NMI_MAP_S 0 + +#define APP_RWBT_IRQ_MAP_REG (DR_REG_DPORT_BASE + 0x230) +#define DPORT_APP_RWBT_IRQ_MAP 0x0000001F +#define DPORT_APP_RWBT_IRQ_MAP_S 0 + +#define APP_RWBLE_IRQ_MAP_REG (DR_REG_DPORT_BASE + 0x234) +#define DPORT_APP_RWBLE_IRQ_MAP 0x0000001F +#define DPORT_APP_RWBLE_IRQ_MAP_S 0 + +#define APP_RWBT_NMI_MAP_REG (DR_REG_DPORT_BASE + 0x238) +#define DPORT_APP_RWBT_NMI_MAP 0x0000001F +#define DPORT_APP_RWBT_NMI_MAP_S 0 + +#define APP_RWBLE_NMI_MAP_REG (DR_REG_DPORT_BASE + 0x23C) +#define DPORT_APP_RWBLE_NMI_MAP 0x0000001F +#define DPORT_APP_RWBLE_NMI_MAP_S 0 + +#define APP_SLC0_INTR_MAP_REG (DR_REG_DPORT_BASE + 0x240) +#define DPORT_APP_SLC0_INTR_MAP 0x0000001F +#define DPORT_APP_SLC0_INTR_MAP_S 0 + +#define APP_SLC1_INTR_MAP_REG (DR_REG_DPORT_BASE + 0x244) +#define DPORT_APP_SLC1_INTR_MAP 0x0000001F +#define DPORT_APP_SLC1_INTR_MAP_S 0 + +#define APP_UHCI0_INTR_MAP_REG (DR_REG_DPORT_BASE + 0x248) +#define DPORT_APP_UHCI0_INTR_MAP 0x0000001F +#define DPORT_APP_UHCI0_INTR_MAP_S 0 + +#define APP_UHCI1_INTR_MAP_REG (DR_REG_DPORT_BASE + 0x24C) +#define DPORT_APP_UHCI1_INTR_MAP 0x0000001F +#define DPORT_APP_UHCI1_INTR_MAP_S 0 + +#define APP_TG_T0_LEVEL_INT_MAP_REG (DR_REG_DPORT_BASE + 0x250) +#define DPORT_APP_TG_T0_LEVEL_INT_MAP 0x0000001F +#define DPORT_APP_TG_T0_LEVEL_INT_MAP_S 0 + +#define APP_TG_T1_LEVEL_INT_MAP_REG (DR_REG_DPORT_BASE + 0x254) +#define DPORT_APP_TG_T1_LEVEL_INT_MAP 0x0000001F +#define DPORT_APP_TG_T1_LEVEL_INT_MAP_S 0 + +#define APP_TG_WDT_LEVEL_INT_MAP_REG (DR_REG_DPORT_BASE + 0x258) +#define DPORT_APP_TG_WDT_LEVEL_INT_MAP 0x0000001F +#define DPORT_APP_TG_WDT_LEVEL_INT_MAP_S 0 + +#define APP_TG_LACT_LEVEL_INT_MAP_REG (DR_REG_DPORT_BASE + 0x25C) +#define DPORT_APP_TG_LACT_LEVEL_INT_MAP 0x0000001F +#define DPORT_APP_TG_LACT_LEVEL_INT_MAP_S 0 + +#define APP_TG1_T0_LEVEL_INT_MAP_REG (DR_REG_DPORT_BASE + 0x260) +#define DPORT_APP_TG1_T0_LEVEL_INT_MAP 0x0000001F +#define DPORT_APP_TG1_T0_LEVEL_INT_MAP_S 0 + +#define APP_TG1_T1_LEVEL_INT_MAP_REG (DR_REG_DPORT_BASE + 0x264) +#define DPORT_APP_TG1_T1_LEVEL_INT_MAP 0x0000001F +#define DPORT_APP_TG1_T1_LEVEL_INT_MAP_S 0 + +#define APP_TG1_WDT_LEVEL_INT_MAP_REG (DR_REG_DPORT_BASE + 0x268) +#define DPORT_APP_TG1_WDT_LEVEL_INT_MAP 0x0000001F +#define DPORT_APP_TG1_WDT_LEVEL_INT_MAP_S 0 + +#define APP_TG1_LACT_LEVEL_INT_MAP_REG (DR_REG_DPORT_BASE + 0x26C) +#define DPORT_APP_TG1_LACT_LEVEL_INT_MAP 0x0000001F +#define DPORT_APP_TG1_LACT_LEVEL_INT_MAP_S 0 + +#define APP_GPIO_INTERRUPT_MAP_REG (DR_REG_DPORT_BASE + 0x270) +#define DPORT_APP_GPIO_INTERRUPT_APP_MAP 0x0000001F +#define DPORT_APP_GPIO_INTERRUPT_APP_MAP_S 0 + +#define APP_GPIO_INTERRUPT_NMI_MAP_REG (DR_REG_DPORT_BASE + 0x274) +#define DPORT_APP_GPIO_INTERRUPT_APP_NMI_MAP 0x0000001F +#define DPORT_APP_GPIO_INTERRUPT_APP_NMI_MAP_S 0 + +#define APP_CPU_INTR_FROM_CPU_0_MAP_REG (DR_REG_DPORT_BASE + 0x278) +#define DPORT_APP_CPU_INTR_FROM_CPU_0_MAP 0x0000001F +#define DPORT_APP_CPU_INTR_FROM_CPU_0_MAP_S 0 + +#define APP_CPU_INTR_FROM_CPU_1_MAP_REG (DR_REG_DPORT_BASE + 0x27C) +#define DPORT_APP_CPU_INTR_FROM_CPU_1_MAP 0x0000001F +#define DPORT_APP_CPU_INTR_FROM_CPU_1_MAP_S 0 + +#define APP_CPU_INTR_FROM_CPU_2_MAP_REG (DR_REG_DPORT_BASE + 0x280) +#define DPORT_APP_CPU_INTR_FROM_CPU_2_MAP 0x0000001F +#define DPORT_APP_CPU_INTR_FROM_CPU_2_MAP_S 0 + +#define APP_CPU_INTR_FROM_CPU_3_MAP_REG (DR_REG_DPORT_BASE + 0x284) +#define DPORT_APP_CPU_INTR_FROM_CPU_3_MAP 0x0000001F +#define DPORT_APP_CPU_INTR_FROM_CPU_3_MAP_S 0 + +#define APP_SPI_INTR_0_MAP_REG (DR_REG_DPORT_BASE + 0x288) +#define DPORT_APP_SPI_INTR_0_MAP 0x0000001F +#define DPORT_APP_SPI_INTR_0_MAP_S 0 + +#define APP_SPI_INTR_1_MAP_REG (DR_REG_DPORT_BASE + 0x28C) +#define DPORT_APP_SPI_INTR_1_MAP 0x0000001F +#define DPORT_APP_SPI_INTR_1_MAP_S 0 + +#define APP_SPI_INTR_2_MAP_REG (DR_REG_DPORT_BASE + 0x290) +#define DPORT_APP_SPI_INTR_2_MAP 0x0000001F +#define DPORT_APP_SPI_INTR_2_MAP_S 0 + +#define APP_SPI_INTR_3_MAP_REG (DR_REG_DPORT_BASE + 0x294) +#define DPORT_APP_SPI_INTR_3_MAP 0x0000001F +#define DPORT_APP_SPI_INTR_3_MAP_S 0 + +#define APP_I2S0_INT_MAP_REG (DR_REG_DPORT_BASE + 0x298) +#define DPORT_APP_I2S0_INT_MAP 0x0000001F +#define DPORT_APP_I2S0_INT_MAP_S 0 + +#define APP_I2S1_INT_MAP_REG (DR_REG_DPORT_BASE + 0x29C) +#define DPORT_APP_I2S1_INT_MAP 0x0000001F +#define DPORT_APP_I2S1_INT_MAP_S 0 + +#define APP_UART_INTR_MAP_REG (DR_REG_DPORT_BASE + 0x2A0) +#define DPORT_APP_UART_INTR_MAP 0x0000001F +#define DPORT_APP_UART_INTR_MAP_S 0 + +#define APP_UART1_INTR_MAP_REG (DR_REG_DPORT_BASE + 0x2A4) +#define DPORT_APP_UART1_INTR_MAP 0x0000001F +#define DPORT_APP_UART1_INTR_MAP_S 0 + +#define APP_UART2_INTR_MAP_REG (DR_REG_DPORT_BASE + 0x2A8) +#define DPORT_APP_UART2_INTR_MAP 0x0000001F +#define DPORT_APP_UART2_INTR_MAP_S 0 + +#define APP_SDIO_HOST_INTERRUPT_MAP_REG (DR_REG_DPORT_BASE + 0x2AC) +#define DPORT_APP_SDIO_HOST_INTERRUPT_MAP 0x0000001F +#define DPORT_APP_SDIO_HOST_INTERRUPT_MAP_S 0 + +#define APP_EMAC_INT_MAP_REG (DR_REG_DPORT_BASE + 0x2B0) +#define DPORT_APP_EMAC_INT_MAP 0x0000001F +#define DPORT_APP_EMAC_INT_MAP_S 0 + +#define APP_PWM0_INTR_MAP_REG (DR_REG_DPORT_BASE + 0x2B4) +#define DPORT_APP_PWM0_INTR_MAP 0x0000001F +#define DPORT_APP_PWM0_INTR_MAP_S 0 + +#define APP_PWM1_INTR_MAP_REG (DR_REG_DPORT_BASE + 0x2B8) +#define DPORT_APP_PWM1_INTR_MAP 0x0000001F +#define DPORT_APP_PWM1_INTR_MAP_S 0 + +#define APP_PWM2_INTR_MAP_REG (DR_REG_DPORT_BASE + 0x2BC) +#define DPORT_APP_PWM2_INTR_MAP 0x0000001F +#define DPORT_APP_PWM2_INTR_MAP_S 0 + +#define APP_PWM3_INTR_MAP_REG (DR_REG_DPORT_BASE + 0x2C0) +#define DPORT_APP_PWM3_INTR_MAP 0x0000001F +#define DPORT_APP_PWM3_INTR_MAP_S 0 + +#define APP_LEDC_INT_MAP_REG (DR_REG_DPORT_BASE + 0x2C4) +#define DPORT_APP_LEDC_INT_MAP 0x0000001F +#define DPORT_APP_LEDC_INT_MAP_S 0 + +#define APP_EFUSE_INT_MAP_REG (DR_REG_DPORT_BASE + 0x2C8) +#define DPORT_APP_EFUSE_INT_MAP 0x0000001F +#define DPORT_APP_EFUSE_INT_MAP_S 0 + +#define APP_CAN_INT_MAP_REG (DR_REG_DPORT_BASE + 0x2CC) +#define DPORT_APP_CAN_INT_MAP 0x0000001F +#define DPORT_APP_CAN_INT_MAP_S 0 + +#define APP_RTC_CORE_INTR_MAP_REG (DR_REG_DPORT_BASE + 0x2D0) +#define DPORT_APP_RTC_CORE_INTR_MAP 0x0000001F +#define DPORT_APP_RTC_CORE_INTR_MAP_S 0 + +#define APP_RMT_INTR_MAP_REG (DR_REG_DPORT_BASE + 0x2D4) +#define DPORT_APP_RMT_INTR_MAP 0x0000001F +#define DPORT_APP_RMT_INTR_MAP_S 0 + +#define APP_PCNT_INTR_MAP_REG (DR_REG_DPORT_BASE + 0x2D8) +#define DPORT_APP_PCNT_INTR_MAP 0x0000001F +#define DPORT_APP_PCNT_INTR_MAP_S 0 + +#define APP_I2C_EXT0_INTR_MAP_REG (DR_REG_DPORT_BASE + 0x2DC) +#define DPORT_APP_I2C_EXT0_INTR_MAP 0x0000001F +#define DPORT_APP_I2C_EXT0_INTR_MAP_S 0 + +#define APP_I2C_EXT1_INTR_MAP_REG (DR_REG_DPORT_BASE + 0x2E0) +#define DPORT_APP_I2C_EXT1_INTR_MAP 0x0000001F +#define DPORT_APP_I2C_EXT1_INTR_MAP_S 0 + +#define APP_RSA_INTR_MAP_REG (DR_REG_DPORT_BASE + 0x2E4) +#define DPORT_APP_RSA_INTR_MAP 0x0000001F +#define DPORT_APP_RSA_INTR_MAP_S 0 + +#define APP_SPI1_DMA_INT_MAP_REG (DR_REG_DPORT_BASE + 0x2E8) +#define DPORT_APP_SPI1_DMA_INT_MAP 0x0000001F +#define DPORT_APP_SPI1_DMA_INT_MAP_S 0 + +#define APP_SPI2_DMA_INT_MAP_REG (DR_REG_DPORT_BASE + 0x2EC) +#define DPORT_APP_SPI2_DMA_INT_MAP 0x0000001F +#define DPORT_APP_SPI2_DMA_INT_MAP_S 0 + +#define APP_SPI3_DMA_INT_MAP_REG (DR_REG_DPORT_BASE + 0x2F0) +#define DPORT_APP_SPI3_DMA_INT_MAP 0x0000001F +#define DPORT_APP_SPI3_DMA_INT_MAP_S 0 + +#define APP_WDG_INT_MAP_REG (DR_REG_DPORT_BASE + 0x2F4) +#define DPORT_APP_WDG_INT_MAP 0x0000001F +#define DPORT_APP_WDG_INT_MAP_S 0 + +#define APP_TIMER_INT1_MAP_REG (DR_REG_DPORT_BASE + 0x2F8) +#define DPORT_APP_TIMER_INT1_MAP 0x0000001F +#define DPORT_APP_TIMER_INT1_MAP_S 0 + +#define APP_TIMER_INT2_MAP_REG (DR_REG_DPORT_BASE + 0x2FC) +#define DPORT_APP_TIMER_INT2_MAP 0x0000001F +#define DPORT_APP_TIMER_INT2_MAP_S 0 + +#define APP_TG_T0_EDGE_INT_MAP_REG (DR_REG_DPORT_BASE + 0x300) +#define DPORT_APP_TG_T0_EDGE_INT_MAP 0x0000001F +#define DPORT_APP_TG_T0_EDGE_INT_MAP_S 0 + +#define APP_TG_T1_EDGE_INT_MAP_REG (DR_REG_DPORT_BASE + 0x304) +#define DPORT_APP_TG_T1_EDGE_INT_MAP 0x0000001F +#define DPORT_APP_TG_T1_EDGE_INT_MAP_S 0 + +#define APP_TG_WDT_EDGE_INT_MAP_REG (DR_REG_DPORT_BASE + 0x308) +#define DPORT_APP_TG_WDT_EDGE_INT_MAP 0x0000001F +#define DPORT_APP_TG_WDT_EDGE_INT_MAP_S 0 + +#define APP_TG_LACT_EDGE_INT_MAP_REG (DR_REG_DPORT_BASE + 0x30C) +#define DPORT_APP_TG_LACT_EDGE_INT_MAP 0x0000001F +#define DPORT_APP_TG_LACT_EDGE_INT_MAP_S 0 + +#define APP_TG1_T0_EDGE_INT_MAP_REG (DR_REG_DPORT_BASE + 0x310) +#define DPORT_APP_TG1_T0_EDGE_INT_MAP 0x0000001F +#define DPORT_APP_TG1_T0_EDGE_INT_MAP_S 0 + +#define APP_TG1_T1_EDGE_INT_MAP_REG (DR_REG_DPORT_BASE + 0x314) +#define DPORT_APP_TG1_T1_EDGE_INT_MAP 0x0000001F +#define DPORT_APP_TG1_T1_EDGE_INT_MAP_S 0 + +#define APP_TG1_WDT_EDGE_INT_MAP_REG (DR_REG_DPORT_BASE + 0x318) +#define DPORT_APP_TG1_WDT_EDGE_INT_MAP 0x0000001F +#define DPORT_APP_TG1_WDT_EDGE_INT_MAP_S 0 + +#define APP_TG1_LACT_EDGE_INT_MAP_REG (DR_REG_DPORT_BASE + 0x31C) +#define DPORT_APP_TG1_LACT_EDGE_INT_MAP 0x0000001F +#define DPORT_APP_TG1_LACT_EDGE_INT_MAP_S 0 + +#define APP_MMU_IA_INT_MAP_REG (DR_REG_DPORT_BASE + 0x320) +#define DPORT_APP_MMU_IA_INT_MAP 0x0000001F +#define DPORT_APP_MMU_IA_INT_MAP_S 0 + +#define APP_MPU_IA_INT_MAP_REG (DR_REG_DPORT_BASE + 0x324) +#define DPORT_APP_MPU_IA_INT_MAP 0x0000001F +#define DPORT_APP_MPU_IA_INT_MAP_S 0 + +#define APP_CACHE_IA_INT_MAP_REG (DR_REG_DPORT_BASE + 0x328) +#define DPORT_APP_CACHE_IA_INT_MAP 0x0000001F +#define DPORT_APP_CACHE_IA_INT_MAP_S 0 + +#define AHBLITE_MPU_TABLE_UART (DR_REG_DPORT_BASE + 0x32C) +#define DPORT_UART_ACCESS_GRANT_CONFIG 0x0000003F +#define DPORT_UART_ACCESS_GRANT_CONFIG_S 0 + +#define AHBLITE_MPU_TABLE_SPI1 (DR_REG_DPORT_BASE + 0x330) +#define DPORT_SPI1_ACCESS_GRANT_CONFIG 0x0000003F +#define DPORT_SPI1_ACCESS_GRANT_CONFIG_S 0 + +#define AHBLITE_MPU_TABLE_SPI0 (DR_REG_DPORT_BASE + 0x334) +#define DPORT_SPI0_ACCESS_GRANT_CONFIG 0x0000003F +#define DPORT_SPI0_ACCESS_GRANT_CONFIG_S 0 + +#define AHBLITE_MPU_TABLE_GPIO (DR_REG_DPORT_BASE + 0x338) +#define DPORT_GPIO_ACCESS_GRANT_CONFIG 0x0000003F +#define DPORT_GPIO_ACCESS_GRANT_CONFIG_S 0 + +#define AHBLITE_MPU_TABLE_FE2 (DR_REG_DPORT_BASE + 0x33C) +#define DPORT_FE2_ACCESS_GRANT_CONFIG 0x0000003F +#define DPORT_FE2_ACCESS_GRANT_CONFIG_S 0 + +#define AHBLITE_MPU_TABLE_FE (DR_REG_DPORT_BASE + 0x340) +#define DPORT_FE_ACCESS_GRANT_CONFIG 0x0000003F +#define DPORT_FE_ACCESS_GRANT_CONFIG_S 0 + +#define AHBLITE_MPU_TABLE_TIMER (DR_REG_DPORT_BASE + 0x344) +#define DPORT_TIMER_ACCESS_GRANT_CONFIG 0x0000003F +#define DPORT_TIMER_ACCESS_GRANT_CONFIG_S 0 + +#define AHBLITE_MPU_TABLE_RTC (DR_REG_DPORT_BASE + 0x348) +#define DPORT_RTC_ACCESS_GRANT_CONFIG 0x0000003F +#define DPORT_RTC_ACCESS_GRANT_CONFIG_S 0 + +#define AHBLITE_MPU_TABLE_IO_MUX (DR_REG_DPORT_BASE + 0x34C) +#define DPORT_IOMUX_ACCESS_GRANT_CONFIG 0x0000003F +#define DPORT_IOMUX_ACCESS_GRANT_CONFIG_S 0 + +#define AHBLITE_MPU_TABLE_WDG (DR_REG_DPORT_BASE + 0x350) +#define DPORT_WDG_ACCESS_GRANT_CONFIG 0x0000003F +#define DPORT_WDG_ACCESS_GRANT_CONFIG_S 0 + +#define AHBLITE_MPU_TABLE_HINF (DR_REG_DPORT_BASE + 0x354) +#define DPORT_HINF_ACCESS_GRANT_CONFIG 0x0000003F +#define DPORT_HINF_ACCESS_GRANT_CONFIG_S 0 + +#define AHBLITE_MPU_TABLE_UHCI1 (DR_REG_DPORT_BASE + 0x358) +#define DPORT_UHCI1_ACCESS_GRANT_CONFIG 0x0000003F +#define DPORT_UHCI1_ACCESS_GRANT_CONFIG_S 0 + +#define AHBLITE_MPU_TABLE_MISC (DR_REG_DPORT_BASE + 0x35C) +#define DPORT_MISC_ACCESS_GRANT_CONFIG 0x0000003F +#define DPORT_MISC_ACCESS_GRANT_CONFIG_S 0 + +#define AHBLITE_MPU_TABLE_I2C (DR_REG_DPORT_BASE + 0x360) +#define DPORT_I2C_ACCESS_GRANT_CONFIG 0x0000003F +#define DPORT_I2C_ACCESS_GRANT_CONFIG_S 0 + +#define AHBLITE_MPU_TABLE_I2S0 (DR_REG_DPORT_BASE + 0x364) +#define DPORT_I2S0_ACCESS_GRANT_CONFIG 0x0000003F +#define DPORT_I2S0_ACCESS_GRANT_CONFIG_S 0 + +#define AHBLITE_MPU_TABLE_UART1 (DR_REG_DPORT_BASE + 0x368) +#define DPORT_UART1_ACCESS_GRANT_CONFIG 0x0000003F +#define DPORT_UART1_ACCESS_GRANT_CONFIG_S 0 + +#define AHBLITE_MPU_TABLE_BT (DR_REG_DPORT_BASE + 0x36C) +#define DPORT_BT_ACCESS_GRANT_CONFIG 0x0000003F +#define DPORT_BT_ACCESS_GRANT_CONFIG_S 0 + +#define AHBLITE_MPU_TABLE_BT_BUFFER (DR_REG_DPORT_BASE + 0x370) +#define DPORT_BTBUFFER_ACCESS_GRANT_CONFIG 0x0000003F +#define DPORT_BTBUFFER_ACCESS_GRANT_CONFIG_S 0 + +#define AHBLITE_MPU_TABLE_I2C_EXT0 (DR_REG_DPORT_BASE + 0x374) +#define DPORT_I2CEXT0_ACCESS_GRANT_CONFIG 0x0000003F +#define DPORT_I2CEXT0_ACCESS_GRANT_CONFIG_S 0 + +#define AHBLITE_MPU_TABLE_UHCI0 (DR_REG_DPORT_BASE + 0x378) +#define DPORT_UHCI0_ACCESS_GRANT_CONFIG 0x0000003F +#define DPORT_UHCI0_ACCESS_GRANT_CONFIG_S 0 + +#define AHBLITE_MPU_TABLE_SLCHOST (DR_REG_DPORT_BASE + 0x37C) +#define DPORT_SLCHOST_ACCESS_GRANT_CONFIG 0x0000003F +#define DPORT_SLCHOST_ACCESS_GRANT_CONFIG_S 0 + +#define AHBLITE_MPU_TABLE_RMT (DR_REG_DPORT_BASE + 0x380) +#define DPORT_RMT_ACCESS_GRANT_CONFIG 0x0000003F +#define DPORT_RMT_ACCESS_GRANT_CONFIG_S 0 + +#define AHBLITE_MPU_TABLE_PCNT (DR_REG_DPORT_BASE + 0x384) +#define DPORT_PCNT_ACCESS_GRANT_CONFIG 0x0000003F +#define DPORT_PCNT_ACCESS_GRANT_CONFIG_S 0 + +#define AHBLITE_MPU_TABLE_SLC (DR_REG_DPORT_BASE + 0x388) +#define DPORT_SLC_ACCESS_GRANT_CONFIG 0x0000003F +#define DPORT_SLC_ACCESS_GRANT_CONFIG_S 0 + +#define AHBLITE_MPU_TABLE_LEDC (DR_REG_DPORT_BASE + 0x38C) +#define DPORT_LEDC_ACCESS_GRANT_CONFIG 0x0000003F +#define DPORT_LEDC_ACCESS_GRANT_CONFIG_S 0 + +#define AHBLITE_MPU_TABLE_EFUSE (DR_REG_DPORT_BASE + 0x390) +#define DPORT_EFUSE_ACCESS_GRANT_CONFIG 0x0000003F +#define DPORT_EFUSE_ACCESS_GRANT_CONFIG_S 0 + +#define AHBLITE_MPU_TABLE_SPI_ENCRYPT (DR_REG_DPORT_BASE + 0x394) +#define DPORT_SPI_ENCRYPY_ACCESS_GRANT_CONFIG 0x0000003F +#define DPORT_SPI_ENCRYPY_ACCESS_GRANT_CONFIG_S 0 + +#define AHBLITE_MPU_TABLE_BB (DR_REG_DPORT_BASE + 0x398) +#define DPORT_BB_ACCESS_GRANT_CONFIG 0x0000003F +#define DPORT_BB_ACCESS_GRANT_CONFIG_S 0 + +#define AHBLITE_MPU_TABLE_PWM0 (DR_REG_DPORT_BASE + 0x39C) +#define DPORT_PWM0_ACCESS_GRANT_CONFIG 0x0000003F +#define DPORT_PWM0_ACCESS_GRANT_CONFIG_S 0 + +#define AHBLITE_MPU_TABLE_TIMERGROUP (DR_REG_DPORT_BASE + 0x3A0) +#define DPORT_TIMERGROUP_ACCESS_GRANT_CONFIG 0x0000003F +#define DPORT_TIMERGROUP_ACCESS_GRANT_CONFIG_S 0 + +#define AHBLITE_MPU_TABLE_TIMERGROUP1 (DR_REG_DPORT_BASE + 0x3A4) +#define DPORT_TIMERGROUP1_ACCESS_GRANT_CONFIG 0x0000003F +#define DPORT_TIMERGROUP1_ACCESS_GRANT_CONFIG_S 0 + +#define AHBLITE_MPU_TABLE_SPI2 (DR_REG_DPORT_BASE + 0x3A8) +#define DPORT_SPI2_ACCESS_GRANT_CONFIG 0x0000003F +#define DPORT_SPI2_ACCESS_GRANT_CONFIG_S 0 + +#define AHBLITE_MPU_TABLE_SPI3 (DR_REG_DPORT_BASE + 0x3AC) +#define DPORT_SPI3_ACCESS_GRANT_CONFIG 0x0000003F +#define DPORT_SPI3_ACCESS_GRANT_CONFIG_S 0 + +#define AHBLITE_MPU_TABLE_APB_CTRL (DR_REG_DPORT_BASE + 0x3B0) +#define DPORT_APBCTRL_ACCESS_GRANT_CONFIG 0x0000003F +#define DPORT_APBCTRL_ACCESS_GRANT_CONFIG_S 0 + +#define AHBLITE_MPU_TABLE_I2C_EXT1 (DR_REG_DPORT_BASE + 0x3B4) +#define DPORT_I2CEXT1_ACCESS_GRANT_CONFIG 0x0000003F +#define DPORT_I2CEXT1_ACCESS_GRANT_CONFIG_S 0 + +#define AHBLITE_MPU_TABLE_SDIO_HOST (DR_REG_DPORT_BASE + 0x3B8) +#define DPORT_SDIOHOST_ACCESS_GRANT_CONFIG 0x0000003F +#define DPORT_SDIOHOST_ACCESS_GRANT_CONFIG_S 0 + +#define AHBLITE_MPU_TABLE_EMAC (DR_REG_DPORT_BASE + 0x3BC) +#define DPORT_EMAC_ACCESS_GRANT_CONFIG 0x0000003F +#define DPORT_EMAC_ACCESS_GRANT_CONFIG_S 0 + +#define AHBLITE_MPU_TABLE_CAN (DR_REG_DPORT_BASE + 0x3C0) +#define DPORT_CAN_ACCESS_GRANT_CONFIG 0x0000003F +#define DPORT_CAN_ACCESS_GRANT_CONFIG_S 0 + +#define AHBLITE_MPU_TABLE_PWM1 (DR_REG_DPORT_BASE + 0x3C4) +#define DPORT_PWM1_ACCESS_GRANT_CONFIG 0x0000003F +#define DPORT_PWM1_ACCESS_GRANT_CONFIG_S 0 + +#define AHBLITE_MPU_TABLE_I2S1 (DR_REG_DPORT_BASE + 0x3C8) +#define DPORT_I2S1_ACCESS_GRANT_CONFIG 0x0000003F +#define DPORT_I2S1_ACCESS_GRANT_CONFIG_S 0 + +#define AHBLITE_MPU_TABLE_UART2 (DR_REG_DPORT_BASE + 0x3CC) +#define DPORT_UART2_ACCESS_GRANT_CONFIG 0x0000003F +#define DPORT_UART2_ACCESS_GRANT_CONFIG_S 0 + +#define AHBLITE_MPU_TABLE_PWM2 (DR_REG_DPORT_BASE + 0x3D0) +#define DPORT_PWM2_ACCESS_GRANT_CONFIG 0x0000003F +#define DPORT_PWM2_ACCESS_GRANT_CONFIG_S 0 + +#define AHBLITE_MPU_TABLE_PWM3 (DR_REG_DPORT_BASE + 0x3D4) +#define DPORT_PWM3_ACCESS_GRANT_CONFIG 0x0000003F +#define DPORT_PWM3_ACCESS_GRANT_CONFIG_S 0 + +#define AHBLITE_MPU_TABLE_RWBT (DR_REG_DPORT_BASE + 0x3D8) +#define DPORT_RWBT_ACCESS_GRANT_CONFIG 0x0000003F +#define DPORT_RWBT_ACCESS_GRANT_CONFIG_S 0 + +#define AHBLITE_MPU_TABLE_BTMAC (DR_REG_DPORT_BASE + 0x3DC) +#define DPORT_BTMAC_ACCESS_GRANT_CONFIG 0x0000003F +#define DPORT_BTMAC_ACCESS_GRANT_CONFIG_S 0 + +#define AHBLITE_MPU_TABLE_WIFIMAC (DR_REG_DPORT_BASE + 0x3E0) +#define DPORT_WIFIMAC_ACCESS_GRANT_CONFIG 0x0000003F +#define DPORT_WIFIMAC_ACCESS_GRANT_CONFIG_S 0 + +#define AHBLITE_MPU_TABLE_PWR (DR_REG_DPORT_BASE + 0x3E4) +#define DPORT_PWR_ACCESS_GRANT_CONFIG 0x0000003F +#define DPORT_PWR_ACCESS_GRANT_CONFIG_S 0 + +#define MEM_ACCESS_DBUG0 (DR_REG_DPORT_BASE + 0x3E8) +#define DPORT_INTERNAL_SRAM_MMU_MULTI_HIT 0x0000000F +#define DPORT_INTERNAL_SRAM_MMU_MULTI_HIT_S 26 +#define DPORT_INTERNAL_SRAM_IA 0x00000FFF +#define DPORT_INTERNAL_SRAM_IA_S 14 +#define DPORT_INTERNAL_SRAM_MMU_AD 0x0000000F +#define DPORT_INTERNAL_SRAM_MMU_AD_S 10 +#define DPORT_SHARE_ROM_IA 0x0000000F +#define DPORT_SHARE_ROM_IA_S 6 +#define DPORT_SHARE_ROM_MPU_AD 0x00000003 +#define DPORT_SHARE_ROM_MPU_AD_S 4 +#define DPORT_APP_ROM_IA (BIT(3)) +#define DPORT_APP_ROM_IA_S 3 +#define DPORT_APP_ROM_MPU_AD (BIT(2)) +#define DPORT_APP_ROM_MPU_AD_S 2 +#define DPORT_PRO_ROM_IA (BIT(1)) +#define DPORT_PRO_ROM_IA_S 1 +#define DPORT_PRO_ROM_MPU_AD (BIT(0)) +#define DPORT_PRO_ROM_MPU_AD_S 0 + +#define MEM_ACCESS_DBUG1 (DR_REG_DPORT_BASE + 0x3EC) +#define DPORT_AHBLITE_IA (BIT(10)) +#define DPORT_AHBLITE_IA_S 10 +#define DPORT_AHBLITE_ACCESS_DENY (BIT(9)) +#define DPORT_AHBLITE_ACCESS_DENY_S 9 +#define DPORT_AHB_ACCESS_DENY (BIT(8)) +#define DPORT_AHB_ACCESS_DENY_S 8 +#define DPORT_DPORT_PIDGEN_IA 0x00000003 +#define DPORT_DPORT_PIDGEN_IA_S 6 +#define DPORT_DPORT_ARB_IA 0x00000003 +#define DPORT_DPORT_ARB_IA_S 4 +#define DPORT_INTERNAL_SRAM_MMU_MISS 0x0000000F +#define DPORT_INTERNAL_SRAM_MMU_MISS_S 0 + +#define PRO_DCACHE_DBUG_REG0 (DR_REG_DPORT_BASE + 0x3F0) +#define DPORT_PRO_RX_END (BIT(23)) +#define DPORT_PRO_RX_END_S 23 +#define DPORT_PRO_SLAVE_WDATA_V (BIT(22)) +#define DPORT_PRO_SLAVE_WDATA_V_S 22 +#define DPORT_PRO_SLAVE_WR (BIT(21)) +#define DPORT_PRO_SLAVE_WR_S 21 +#define DPORT_PRO_TX_END (BIT(20)) +#define DPORT_PRO_TX_END_S 20 +#define DPORT_PRO_WR_BAK_TO_READ (BIT(19)) +#define DPORT_PRO_WR_BAK_TO_READ_S 19 +#define DPORT_PRO_CACHE_STATE 0x00000FFF +#define DPORT_PRO_CACHE_STATE_S 7 +#define DPORT_PRO_CACHE_IA 0x0000003F +#define DPORT_PRO_CACHE_IA_S 1 +#define DPORT_PRO_CACHE_MMU_IA (BIT(0)) +#define DPORT_PRO_CACHE_MMU_IA_S 0 + +#define PRO_DCACHE_DBUG_REG1 (DR_REG_DPORT_BASE + 0x3F4) +#define DPORT_PRO_CTAG_RAM_RDATA 0xFFFFFFFF +#define DPORT_PRO_CTAG_RAM_RDATA_S 0 + +#define PRO_DCACHE_DBUG_REG2 (DR_REG_DPORT_BASE + 0x3F8) +#define DPORT_PRO_CACHE_VADDR 0x07FFFFFF +#define DPORT_PRO_CACHE_VADDR_S 0 + +#define PRO_DCACHE_DBUG_REG3 (DR_REG_DPORT_BASE + 0x3FC) +#define DPORT_PRO_CACHE_IRAM0_PID_ERROR (BIT(15)) +#define DPORT_PRO_CACHE_IRAM0_PID_ERROR_S 15 +#define DPORT_PRO_CPU_DISABLED_CACHE_IA 0x0000003F +#define DPORT_PRO_CPU_DISABLED_CACHE_IA_S 9 +#define DPORT_PRO_MMU_RDATA 0x000001FF +#define DPORT_PRO_MMU_RDATA_S 0 + +#define PRO_DCACHE_DBUG_REG4 (DR_REG_DPORT_BASE + 0x400) +#define DPORT_PRO_DRAM1ADDR0_IA 0x000FFFFF +#define DPORT_PRO_DRAM1ADDR0_IA_S 0 + +#define PRO_DCACHE_DBUG_REG5 (DR_REG_DPORT_BASE + 0x404) +#define DPORT_PRO_DROM0ADDR0_IA 0x000FFFFF +#define DPORT_PRO_DROM0ADDR0_IA_S 0 + +#define PRO_DCACHE_DBUG_REG6 (DR_REG_DPORT_BASE + 0x408) +#define DPORT_PRO_IRAM0ADDR_IA 0x000FFFFF +#define DPORT_PRO_IRAM0ADDR_IA_S 0 + +#define PRO_DCACHE_DBUG_REG7 (DR_REG_DPORT_BASE + 0x40C) +#define DPORT_PRO_IRAM1ADDR_IA 0x000FFFFF +#define DPORT_PRO_IRAM1ADDR_IA_S 0 + +#define PRO_DCACHE_DBUG_REG8 (DR_REG_DPORT_BASE + 0x410) +#define DPORT_PRO_IROM0ADDR_IA 0x000FFFFF +#define DPORT_PRO_IROM0ADDR_IA_S 0 + +#define PRO_DCACHE_DBUG_REG9 (DR_REG_DPORT_BASE + 0x414) +#define DPORT_PRO_OPSDRAMADDR_IA 0x000FFFFF +#define DPORT_PRO_OPSDRAMADDR_IA_S 0 + +#define APP_DCACHE_DBUG_REG0 (DR_REG_DPORT_BASE + 0x418) +#define DPORT_APP_RX_END (BIT(23)) +#define DPORT_APP_RX_END_S 23 +#define DPORT_APP_SLAVE_WDATA_V (BIT(22)) +#define DPORT_APP_SLAVE_WDATA_V_S 22 +#define DPORT_APP_SLAVE_WR (BIT(21)) +#define DPORT_APP_SLAVE_WR_S 21 +#define DPORT_APP_TX_END (BIT(20)) +#define DPORT_APP_TX_END_S 20 +#define DPORT_APP_WR_BAK_TO_READ (BIT(19)) +#define DPORT_APP_WR_BAK_TO_READ_S 19 +#define DPORT_APP_CACHE_STATE 0x00000FFF +#define DPORT_APP_CACHE_STATE_S 7 +#define DPORT_APP_CACHE_IA 0x0000003F +#define DPORT_APP_CACHE_IA_S 1 +#define DPORT_APP_CACHE_MMU_IA (BIT(0)) +#define DPORT_APP_CACHE_MMU_IA_S 0 + +#define APP_DCACHE_DBUG_REG1 (DR_REG_DPORT_BASE + 0x41C) +#define DPORT_APP_CTAG_RAM_RDATA 0xFFFFFFFF +#define DPORT_APP_CTAG_RAM_RDATA_S 0 + +#define APP_DCACHE_DBUG_REG2 (DR_REG_DPORT_BASE + 0x420) +#define DPORT_APP_CACHE_VADDR 0x07FFFFFF +#define DPORT_APP_CACHE_VADDR_S 0 + +#define APP_DCACHE_DBUG_REG3 (DR_REG_DPORT_BASE + 0x424) +#define DPORT_APP_CACHE_IRAM0_PID_ERROR (BIT(15)) +#define DPORT_APP_CACHE_IRAM0_PID_ERROR_S 15 +#define DPORT_APP_CPU_DISABLED_CACHE_IA 0x0000003F +#define DPORT_APP_CPU_DISABLED_CACHE_IA_S 9 +#define DPORT_APP_MMU_RDATA 0x000001FF +#define DPORT_APP_MMU_RDATA_S 0 + +#define APP_DCACHE_DBUG_REG4 (DR_REG_DPORT_BASE + 0x428) +#define DPORT_APP_DRAM1ADDR0_IA 0x000FFFFF +#define DPORT_APP_DRAM1ADDR0_IA_S 0 + +#define APP_DCACHE_DBUG_REG5 (DR_REG_DPORT_BASE + 0x42C) +#define DPORT_APP_DROM0ADDR0_IA 0x000FFFFF +#define DPORT_APP_DROM0ADDR0_IA_S 0 + +#define APP_DCACHE_DBUG_REG6 (DR_REG_DPORT_BASE + 0x430) +#define DPORT_APP_IRAM0ADDR_IA 0x000FFFFF +#define DPORT_APP_IRAM0ADDR_IA_S 0 + +#define APP_DCACHE_DBUG_REG7 (DR_REG_DPORT_BASE + 0x434) +#define DPORT_APP_IRAM1ADDR_IA 0x000FFFFF +#define DPORT_APP_IRAM1ADDR_IA_S 0 + +#define APP_DCACHE_DBUG_REG8 (DR_REG_DPORT_BASE + 0x438) +#define DPORT_APP_IROM0ADDR_IA 0x000FFFFF +#define DPORT_APP_IROM0ADDR_IA_S 0 + +#define APP_DCACHE_DBUG_REG9 (DR_REG_DPORT_BASE + 0x43C) +#define DPORT_APP_OPSDRAMADDR_IA 0x000FFFFF +#define DPORT_APP_OPSDRAMADDR_IA_S 0 + +#define PRO_CPU_RECORD_CTRL (DR_REG_DPORT_BASE + 0x440) +#define DPORT_PRO_CPU_PDEBUG_ENABLE (BIT(8)) +#define DPORT_PRO_CPU_PDEBUG_ENABLE_S 8 +#define DPORT_PRO_CPU_RECORD_DISABLE (BIT(4)) +#define DPORT_PRO_CPU_RECORD_DISABLE_S 4 +#define DPORT_PRO_CPU_RECORD_ENABLE (BIT(0)) +#define DPORT_PRO_CPU_RECORD_ENABLE_S 0 + +#define PRO_CPU_RECORD_STATUS (DR_REG_DPORT_BASE + 0x444) +#define DPORT_PRO_CPU_RECORDING (BIT(0)) +#define DPORT_PRO_CPU_RECORDING_S 0 + +#define PRO_CPU_RECORD_PID (DR_REG_DPORT_BASE + 0x448) +#define DPORT_RECORD_PRO_PID 0x00000007 +#define DPORT_RECORD_PRO_PID_S 0 + +#define PRO_CPU_RECORD_PDEBUGINST (DR_REG_DPORT_BASE + 0x44C) +#define DPORT_RECORD_PRO_PDEBUGINST 0xFFFFFFFF +#define DPORT_RECORD_PRO_PDEBUGINST_S 0 + +#define PRO_CPU_RECORD_PDEBUGSTATUS (DR_REG_DPORT_BASE + 0x450) +#define DPORT_RECORD_PRO_PDEBUGSTATUS 0x000000FF +#define DPORT_RECORD_PRO_PDEBUGSTATUS_S 0 + +#define PRO_CPU_RECORD_PDEBUGDATA (DR_REG_DPORT_BASE + 0x454) +#define DPORT_RECORD_PRO_PDEBUGDATA 0xFFFFFFFF +#define DPORT_RECORD_PRO_PDEBUGDATA_S 0 + +#define PRO_CPU_RECORD_PDEBUGPC (DR_REG_DPORT_BASE + 0x458) +#define DPORT_RECORD_PRO_PDEBUGPC 0xFFFFFFFF +#define DPORT_RECORD_PRO_PDEBUGPC_S 0 + +#define PRO_CPU_RECORD_PDEBUGLS0STAT (DR_REG_DPORT_BASE + 0x45C) +#define DPORT_RECORD_PRO_PDEBUGLS0STAT 0xFFFFFFFF +#define DPORT_RECORD_PRO_PDEBUGLS0STAT_S 0 + +#define PRO_CPU_RECORD_PDEBUGLS0ADDR (DR_REG_DPORT_BASE + 0x460) +#define DPORT_RECORD_PRO_PDEBUGLS0ADDR 0xFFFFFFFF +#define DPORT_RECORD_PRO_PDEBUGLS0ADDR_S 0 + +#define PRO_CPU_RECORD_PDEBUGLS0DATA (DR_REG_DPORT_BASE + 0x464) +#define DPORT_RECORD_PRO_PDEBUGLS0DATA 0xFFFFFFFF +#define DPORT_RECORD_PRO_PDEBUGLS0DATA_S 0 + +#define APP_CPU_RECORD_CTRL (DR_REG_DPORT_BASE + 0x468) +#define DPORT_APP_CPU_PDEBUG_ENABLE (BIT(8)) +#define DPORT_APP_CPU_PDEBUG_ENABLE_S 8 +#define DPORT_APP_CPU_RECORD_DISABLE (BIT(4)) +#define DPORT_APP_CPU_RECORD_DISABLE_S 4 +#define DPORT_APP_CPU_RECORD_ENABLE (BIT(0)) +#define DPORT_APP_CPU_RECORD_ENABLE_S 0 + +#define APP_CPU_RECORD_STATUS (DR_REG_DPORT_BASE + 0x46C) +#define DPORT_APP_CPU_RECORDING (BIT(0)) +#define DPORT_APP_CPU_RECORDING_S 0 + +#define APP_CPU_RECORD_PID (DR_REG_DPORT_BASE + 0x470) +#define DPORT_RECORD_APP_PID 0x00000007 +#define DPORT_RECORD_APP_PID_S 0 + +#define APP_CPU_RECORD_PDEBUGINST (DR_REG_DPORT_BASE + 0x474) +#define DPORT_RECORD_APP_PDEBUGINST 0xFFFFFFFF +#define DPORT_RECORD_APP_PDEBUGINST_S 0 + +#define APP_CPU_RECORD_PDEBUGSTATUS (DR_REG_DPORT_BASE + 0x478) +#define DPORT_RECORD_APP_PDEBUGSTATUS 0x000000FF +#define DPORT_RECORD_APP_PDEBUGSTATUS_S 0 + +#define APP_CPU_RECORD_PDEBUGDATA (DR_REG_DPORT_BASE + 0x47C) +#define DPORT_RECORD_APP_PDEBUGDATA 0xFFFFFFFF +#define DPORT_RECORD_APP_PDEBUGDATA_S 0 + +#define APP_CPU_RECORD_PDEBUGPC (DR_REG_DPORT_BASE + 0x480) +#define DPORT_RECORD_APP_PDEBUGPC 0xFFFFFFFF +#define DPORT_RECORD_APP_PDEBUGPC_S 0 + +#define APP_CPU_RECORD_PDEBUGLS0STAT (DR_REG_DPORT_BASE + 0x484) +#define DPORT_RECORD_APP_PDEBUGLS0STAT 0xFFFFFFFF +#define DPORT_RECORD_APP_PDEBUGLS0STAT_S 0 + +#define APP_CPU_RECORD_PDEBUGLS0ADDR (DR_REG_DPORT_BASE + 0x488) +#define DPORT_RECORD_APP_PDEBUGLS0ADDR 0xFFFFFFFF +#define DPORT_RECORD_APP_PDEBUGLS0ADDR_S 0 + +#define APP_CPU_RECORD_PDEBUGLS0DATA (DR_REG_DPORT_BASE + 0x48C) +#define DPORT_RECORD_APP_PDEBUGLS0DATA 0xFFFFFFFF +#define DPORT_RECORD_APP_PDEBUGLS0DATA_S 0 + +#define RSA_PD_CTRL_REG (DR_REG_DPORT_BASE + 0x490) +#define DPORT_RSA_PD (BIT(0)) +#define DPORT_RSA_PD_S 0 + +#define ROM_MPU_TABLE0 (DR_REG_DPORT_BASE + 0x494) +#define DPORT_ROM_MPU_TABLE0 0x00000003 +#define DPORT_ROM_MPU_TABLE0_S 0 + +#define ROM_MPU_TABLE1 (DR_REG_DPORT_BASE + 0x498) +#define DPORT_ROM_MPU_TABLE1 0x00000003 +#define DPORT_ROM_MPU_TABLE1_S 0 + +#define ROM_MPU_TABLE2 (DR_REG_DPORT_BASE + 0x49C) +#define DPORT_ROM_MPU_TABLE2 0x00000003 +#define DPORT_ROM_MPU_TABLE2_S 0 + +#define ROM_MPU_TABLE3 (DR_REG_DPORT_BASE + 0x4A0) +#define DPORT_ROM_MPU_TABLE3 0x00000003 +#define DPORT_ROM_MPU_TABLE3_S 0 + +#define SHROM_MPU_TABLE0 (DR_REG_DPORT_BASE + 0x4A4) +#define DPORT_SHROM_MPU_TABLE0 0x00000003 +#define DPORT_SHROM_MPU_TABLE0_S 0 + +#define SHROM_MPU_TABLE1 (DR_REG_DPORT_BASE + 0x4A8) +#define DPORT_SHROM_MPU_TABLE1 0x00000003 +#define DPORT_SHROM_MPU_TABLE1_S 0 + +#define SHROM_MPU_TABLE2 (DR_REG_DPORT_BASE + 0x4AC) +#define DPORT_SHROM_MPU_TABLE2 0x00000003 +#define DPORT_SHROM_MPU_TABLE2_S 0 + +#define SHROM_MPU_TABLE3 (DR_REG_DPORT_BASE + 0x4B0) +#define DPORT_SHROM_MPU_TABLE3 0x00000003 +#define DPORT_SHROM_MPU_TABLE3_S 0 + +#define SHROM_MPU_TABLE4 (DR_REG_DPORT_BASE + 0x4B4) +#define DPORT_SHROM_MPU_TABLE4 0x00000003 +#define DPORT_SHROM_MPU_TABLE4_S 0 + +#define SHROM_MPU_TABLE5 (DR_REG_DPORT_BASE + 0x4B8) +#define DPORT_SHROM_MPU_TABLE5 0x00000003 +#define DPORT_SHROM_MPU_TABLE5_S 0 + +#define SHROM_MPU_TABLE6 (DR_REG_DPORT_BASE + 0x4BC) +#define DPORT_SHROM_MPU_TABLE6 0x00000003 +#define DPORT_SHROM_MPU_TABLE6_S 0 + +#define SHROM_MPU_TABLE7 (DR_REG_DPORT_BASE + 0x4C0) +#define DPORT_SHROM_MPU_TABLE7 0x00000003 +#define DPORT_SHROM_MPU_TABLE7_S 0 + +#define SHROM_MPU_TABLE8 (DR_REG_DPORT_BASE + 0x4C4) +#define DPORT_SHROM_MPU_TABLE8 0x00000003 +#define DPORT_SHROM_MPU_TABLE8_S 0 + +#define SHROM_MPU_TABLE9 (DR_REG_DPORT_BASE + 0x4C8) +#define DPORT_SHROM_MPU_TABLE9 0x00000003 +#define DPORT_SHROM_MPU_TABLE9_S 0 + +#define SHROM_MPU_TABLE10 (DR_REG_DPORT_BASE + 0x4CC) +#define DPORT_SHROM_MPU_TABLE10 0x00000003 +#define DPORT_SHROM_MPU_TABLE10_S 0 + +#define SHROM_MPU_TABLE11 (DR_REG_DPORT_BASE + 0x4D0) +#define DPORT_SHROM_MPU_TABLE11 0x00000003 +#define DPORT_SHROM_MPU_TABLE11_S 0 + +#define SHROM_MPU_TABLE12 (DR_REG_DPORT_BASE + 0x4D4) +#define DPORT_SHROM_MPU_TABLE12 0x00000003 +#define DPORT_SHROM_MPU_TABLE12_S 0 + +#define SHROM_MPU_TABLE13 (DR_REG_DPORT_BASE + 0x4D8) +#define DPORT_SHROM_MPU_TABLE13 0x00000003 +#define DPORT_SHROM_MPU_TABLE13_S 0 + +#define SHROM_MPU_TABLE14 (DR_REG_DPORT_BASE + 0x4DC) +#define DPORT_SHROM_MPU_TABLE14 0x00000003 +#define DPORT_SHROM_MPU_TABLE14_S 0 + +#define SHROM_MPU_TABLE15 (DR_REG_DPORT_BASE + 0x4E0) +#define DPORT_SHROM_MPU_TABLE15 0x00000003 +#define DPORT_SHROM_MPU_TABLE15_S 0 + +#define SHROM_MPU_TABLE16 (DR_REG_DPORT_BASE + 0x4E4) +#define DPORT_SHROM_MPU_TABLE16 0x00000003 +#define DPORT_SHROM_MPU_TABLE16_S 0 + +#define SHROM_MPU_TABLE17 (DR_REG_DPORT_BASE + 0x4E8) +#define DPORT_SHROM_MPU_TABLE17 0x00000003 +#define DPORT_SHROM_MPU_TABLE17_S 0 + +#define SHROM_MPU_TABLE18 (DR_REG_DPORT_BASE + 0x4EC) +#define DPORT_SHROM_MPU_TABLE18 0x00000003 +#define DPORT_SHROM_MPU_TABLE18_S 0 + +#define SHROM_MPU_TABLE19 (DR_REG_DPORT_BASE + 0x4F0) +#define DPORT_SHROM_MPU_TABLE19 0x00000003 +#define DPORT_SHROM_MPU_TABLE19_S 0 + +#define SHROM_MPU_TABLE20 (DR_REG_DPORT_BASE + 0x4F4) +#define DPORT_SHROM_MPU_TABLE20 0x00000003 +#define DPORT_SHROM_MPU_TABLE20_S 0 + +#define SHROM_MPU_TABLE21 (DR_REG_DPORT_BASE + 0x4F8) +#define DPORT_SHROM_MPU_TABLE21 0x00000003 +#define DPORT_SHROM_MPU_TABLE21_S 0 + +#define SHROM_MPU_TABLE22 (DR_REG_DPORT_BASE + 0x4FC) +#define DPORT_SHROM_MPU_TABLE22 0x00000003 +#define DPORT_SHROM_MPU_TABLE22_S 0 + +#define SHROM_MPU_TABLE23 (DR_REG_DPORT_BASE + 0x500) +#define DPORT_SHROM_MPU_TABLE23 0x00000003 +#define DPORT_SHROM_MPU_TABLE23_S 0 + +#define IMMU_TABLE0 (DR_REG_DPORT_BASE + 0x504) +#define DPORT_IMMU_TABLE0 0x0000007F +#define DPORT_IMMU_TABLE0_S 0 + +#define IMMU_TABLE1 (DR_REG_DPORT_BASE + 0x508) +#define DPORT_IMMU_TABLE1 0x0000007F +#define DPORT_IMMU_TABLE1_S 0 + +#define IMMU_TABLE2 (DR_REG_DPORT_BASE + 0x50C) +#define DPORT_IMMU_TABLE2 0x0000007F +#define DPORT_IMMU_TABLE2_S 0 + +#define IMMU_TABLE3 (DR_REG_DPORT_BASE + 0x510) +#define DPORT_IMMU_TABLE3 0x0000007F +#define DPORT_IMMU_TABLE3_S 0 + +#define IMMU_TABLE4 (DR_REG_DPORT_BASE + 0x514) +#define DPORT_IMMU_TABLE4 0x0000007F +#define DPORT_IMMU_TABLE4_S 0 + +#define IMMU_TABLE5 (DR_REG_DPORT_BASE + 0x518) +#define DPORT_IMMU_TABLE5 0x0000007F +#define DPORT_IMMU_TABLE5_S 0 + +#define IMMU_TABLE6 (DR_REG_DPORT_BASE + 0x51C) +#define DPORT_IMMU_TABLE6 0x0000007F +#define DPORT_IMMU_TABLE6_S 0 + +#define IMMU_TABLE7 (DR_REG_DPORT_BASE + 0x520) +#define DPORT_IMMU_TABLE7 0x0000007F +#define DPORT_IMMU_TABLE7_S 0 + +#define IMMU_TABLE8 (DR_REG_DPORT_BASE + 0x524) +#define DPORT_IMMU_TABLE8 0x0000007F +#define DPORT_IMMU_TABLE8_S 0 + +#define IMMU_TABLE9 (DR_REG_DPORT_BASE + 0x528) +#define DPORT_IMMU_TABLE9 0x0000007F +#define DPORT_IMMU_TABLE9_S 0 + +#define IMMU_TABLE10 (DR_REG_DPORT_BASE + 0x52C) +#define DPORT_IMMU_TABLE10 0x0000007F +#define DPORT_IMMU_TABLE10_S 0 + +#define IMMU_TABLE11 (DR_REG_DPORT_BASE + 0x530) +#define DPORT_IMMU_TABLE11 0x0000007F +#define DPORT_IMMU_TABLE11_S 0 + +#define IMMU_TABLE12 (DR_REG_DPORT_BASE + 0x534) +#define DPORT_IMMU_TABLE12 0x0000007F +#define DPORT_IMMU_TABLE12_S 0 + +#define IMMU_TABLE13 (DR_REG_DPORT_BASE + 0x538) +#define DPORT_IMMU_TABLE13 0x0000007F +#define DPORT_IMMU_TABLE13_S 0 + +#define IMMU_TABLE14 (DR_REG_DPORT_BASE + 0x53C) +#define DPORT_IMMU_TABLE14 0x0000007F +#define DPORT_IMMU_TABLE14_S 0 + +#define IMMU_TABLE15 (DR_REG_DPORT_BASE + 0x540) +#define DPORT_IMMU_TABLE15 0x0000007F +#define DPORT_IMMU_TABLE15_S 0 + +#define DMMU_TABLE0 (DR_REG_DPORT_BASE + 0x544) +#define DPORT_DMMU_TABLE0 0x0000007F +#define DPORT_DMMU_TABLE0_S 0 + +#define DMMU_TABLE1 (DR_REG_DPORT_BASE + 0x548) +#define DPORT_DMMU_TABLE1 0x0000007F +#define DPORT_DMMU_TABLE1_S 0 + +#define DMMU_TABLE2 (DR_REG_DPORT_BASE + 0x54C) +#define DPORT_DMMU_TABLE2 0x0000007F +#define DPORT_DMMU_TABLE2_S 0 + +#define DMMU_TABLE3 (DR_REG_DPORT_BASE + 0x550) +#define DPORT_DMMU_TABLE3 0x0000007F +#define DPORT_DMMU_TABLE3_S 0 + +#define DMMU_TABLE4 (DR_REG_DPORT_BASE + 0x554) +#define DPORT_DMMU_TABLE4 0x0000007F +#define DPORT_DMMU_TABLE4_S 0 + +#define DMMU_TABLE5 (DR_REG_DPORT_BASE + 0x558) +#define DPORT_DMMU_TABLE5 0x0000007F +#define DPORT_DMMU_TABLE5_S 0 + +#define DMMU_TABLE6 (DR_REG_DPORT_BASE + 0x55C) +#define DPORT_DMMU_TABLE6 0x0000007F +#define DPORT_DMMU_TABLE6_S 0 + +#define DMMU_TABLE7 (DR_REG_DPORT_BASE + 0x560) +#define DPORT_DMMU_TABLE7 0x0000007F +#define DPORT_DMMU_TABLE7_S 0 + +#define DMMU_TABLE8 (DR_REG_DPORT_BASE + 0x564) +#define DPORT_DMMU_TABLE8 0x0000007F +#define DPORT_DMMU_TABLE8_S 0 + +#define DMMU_TABLE9 (DR_REG_DPORT_BASE + 0x568) +#define DPORT_DMMU_TABLE9 0x0000007F +#define DPORT_DMMU_TABLE9_S 0 + +#define DMMU_TABLE10 (DR_REG_DPORT_BASE + 0x56C) +#define DPORT_DMMU_TABLE10 0x0000007F +#define DPORT_DMMU_TABLE10_S 0 + +#define DMMU_TABLE11 (DR_REG_DPORT_BASE + 0x570) +#define DPORT_DMMU_TABLE11 0x0000007F +#define DPORT_DMMU_TABLE11_S 0 + +#define DMMU_TABLE12 (DR_REG_DPORT_BASE + 0x574) +#define DPORT_DMMU_TABLE12 0x0000007F +#define DPORT_DMMU_TABLE12_S 0 + +#define DMMU_TABLE13 (DR_REG_DPORT_BASE + 0x578) +#define DPORT_DMMU_TABLE13 0x0000007F +#define DPORT_DMMU_TABLE13_S 0 + +#define DMMU_TABLE14 (DR_REG_DPORT_BASE + 0x57C) +#define DPORT_DMMU_TABLE14 0x0000007F +#define DPORT_DMMU_TABLE14_S 0 + +#define DMMU_TABLE15 (DR_REG_DPORT_BASE + 0x580) +#define DPORT_DMMU_TABLE15 0x0000007F +#define DPORT_DMMU_TABLE15_S 0 + +#define PRO_INTRUSION_CTRL (DR_REG_DPORT_BASE + 0x584) +#define DPORT_PRO_INTRUSION_RECORD_RESET_N (BIT(0)) +#define DPORT_PRO_INTRUSION_RECORD_RESET_N_S 0 + +#define PRO_INTRUSION_STATUS (DR_REG_DPORT_BASE + 0x588) +#define DPORT_PRO_INTRUSION_RECORD 0x0000000F +#define DPORT_PRO_INTRUSION_RECORD_S 0 + +#define APP_INTRUSION_CTRL (DR_REG_DPORT_BASE + 0x58C) +#define DPORT_APP_INTRUSION_RECORD_RESET_N (BIT(0)) +#define DPORT_APP_INTRUSION_RECORD_RESET_N_S 0 + +#define APP_INTRUSION_STATUS (DR_REG_DPORT_BASE + 0x590) +#define DPORT_APP_INTRUSION_RECORD 0x0000000F +#define DPORT_APP_INTRUSION_RECORD_S 0 + +#define FRONT_END_MEM_PD (DR_REG_DPORT_BASE + 0x594) +#define DPORT_PBUS_MEM_FORCE_PD (BIT(3)) +#define DPORT_PBUS_MEM_FORCE_PD_S 3 +#define DPORT_PBUS_MEM_FORCE_PU (BIT(2)) +#define DPORT_PBUS_MEM_FORCE_PU_S 2 +#define DPORT_AGC_MEM_FORCE_PD (BIT(1)) +#define DPORT_AGC_MEM_FORCE_PD_S 1 +#define DPORT_AGC_MEM_FORCE_PU (BIT(0)) +#define DPORT_AGC_MEM_FORCE_PU_S 0 + +#define MMU_IA_INT_EN (DR_REG_DPORT_BASE + 0x598) +#define DPORT_MMU_IA_INT_EN 0x00FFFFFF +#define DPORT_MMU_IA_INT_EN_S 0 + +#define MPU_IA_INT_EN (DR_REG_DPORT_BASE + 0x59C) +#define DPORT_MPU_IA_INT_EN 0x0001FFFF +#define DPORT_MPU_IA_INT_EN_S 0 + +#define CACHE_IA_INT_EN (DR_REG_DPORT_BASE + 0x5A0) +#define DPORT_CACHE_IA_INT_EN 0x0FFFFFFF +#define DPORT_CACHE_IA_INT_EN_S 0 + +#define SECURE_BOOT_CTRL (DR_REG_DPORT_BASE + 0x5A4) +#define DPORT_SW_BOOTLOADER_SEL (BIT(0)) +#define DPORT_SW_BOOTLOADER_SEL_S 0 + +#define SPI_DMA_CHAN_SEL (DR_REG_DPORT_BASE + 0x5A8) +#define DPORT_SPI3_DMA_CHAN_SEL 0x00000003 +#define DPORT_SPI3_DMA_CHAN_SEL_S 4 +#define DPORT_SPI2_DMA_CHAN_SEL 0x00000003 +#define DPORT_SPI2_DMA_CHAN_SEL_S 2 +#define DPORT_SPI1_DMA_CHAN_SEL 0x00000003 +#define DPORT_SPI1_DMA_CHAN_SEL_S 0 + +#define PRO_VECBASE_CTRL (DR_REG_DPORT_BASE + 0x5AC) +#define DPORT_PRO_OUT_VECBASE_SEL 0x00000003 +#define DPORT_PRO_OUT_VECBASE_SEL_S 0 + +#define PRO_VECBASE_SET (DR_REG_DPORT_BASE + 0x5B0) +#define DPORT_PRO_OUT_VECBASE_REG 0x003FFFFF +#define DPORT_PRO_OUT_VECBASE_REG_S 0 + +#define APP_VECBASE_CTRL (DR_REG_DPORT_BASE + 0x5B4) +#define DPORT_APP_OUT_VECBASE_SEL 0x00000003 +#define DPORT_APP_OUT_VECBASE_SEL_S 0 + +#define APP_VECBASE_SET (DR_REG_DPORT_BASE + 0x5B8) +#define DPORT_APP_OUT_VECBASE_REG 0x003FFFFF +#define DPORT_APP_OUT_VECBASE_REG_S 0 + +#define DPORT_REG_DATE (DR_REG_DPORT_BASE + 0xFFC) +#define DPORT_DPORT_DATE 0x0FFFFFFF +#define DPORT_DPORT_DATE_S 0 +#define DPORT_DPORT_DATE_VERSION 0x1605190 + +#endif /* _SOC_DPORT_REG_H_ */ diff --git a/components/esp32/include/soc/efuse_reg.h b/components/esp32/include/soc/efuse_reg.h new file mode 100644 index 0000000000..85a6361f26 --- /dev/null +++ b/components/esp32/include/soc/efuse_reg.h @@ -0,0 +1,422 @@ +// Copyright 2015-2016 Espressif Systems (Shanghai) PTE LTD +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at + +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +#ifndef _SOC_EFUSE_REG_H_ +#define _SOC_EFUSE_REG_H_ + +#include "soc.h" + +#define EFUSE_BLK0_RDATA0 (DR_REG_EFUSE_BASE + 0x000) +#define EFUSE_RD_FLASH_CRYPT_CNT 0x000000FF +#define EFUSE_RD_FLASH_CRYPT_CNT_S 20 +#define EFUSE_RD_EFUSE_RD_DIS 0x0000000F +#define EFUSE_RD_EFUSE_RD_DIS_S 16 +#define EFUSE_RD_EFUSE_WR_DIS 0x0000FFFF +#define EFUSE_RD_EFUSE_WR_DIS_S 0 + +#define EFUSE_BLK0_RDATA1 (DR_REG_EFUSE_BASE + 0x004) +#define EFUSE_RD_WIFI_MAC_CRC_LOW 0xFFFFFFFF +#define EFUSE_RD_WIFI_MAC_CRC_LOW_S 0 + +#define EFUSE_BLK0_RDATA2 (DR_REG_EFUSE_BASE + 0x008) +#define EFUSE_RD_WIFI_MAC_CRC_HIGH 0x00FFFFFF +#define EFUSE_RD_WIFI_MAC_CRC_HIGH_S 0 + +#define EFUSE_BLK0_RDATA3 (DR_REG_EFUSE_BASE + 0x00c) +#define EFUSE_RD_CHIP_VER_RESERVE 0x00001FFF +#define EFUSE_RD_CHIP_VER_RESERVE_S 4 +#define EFUSE_RD_CHIP_VER_DIS_CACHE (BIT(3)) +#define EFUSE_RD_CHIP_VER_DIS_CACHE_S 3 +#define EFUSE_RD_CHIP_VER_32PAD (BIT(2)) +#define EFUSE_RD_CHIP_VER_32PAD_S 2 +#define EFUSE_RD_CHIP_VER_DIS_BT (BIT(1)) +#define EFUSE_RD_CHIP_VER_DIS_BT_S 1 +#define EFUSE_RD_CHIP_VER_DIS_APP_CPU (BIT(0)) +#define EFUSE_RD_CHIP_VER_DIS_APP_CPU_S 0 + +#define EFUSE_BLK0_RDATA4 (DR_REG_EFUSE_BASE + 0x010) +#define EFUSE_RD_SDIO_FORCE (BIT(16)) +#define EFUSE_RD_SDIO_FORCE_S 16 +#define EFUSE_RD_SDIO_TIEH (BIT(15)) +#define EFUSE_RD_SDIO_TIEH_S 15 +#define EFUSE_RD_XPD_SDIO_REG (BIT(14)) +#define EFUSE_RD_XPD_SDIO_REG_S 14 +#define EFUSE_RD_SDIO_DREFL 0x00000003 +#define EFUSE_RD_SDIO_DREFL_S 12 +#define EFUSE_RD_SDIO_DREFM 0x00000003 +#define EFUSE_RD_SDIO_DREFM_S 10 +#define EFUSE_RD_SDIO_DREFH 0x00000003 +#define EFUSE_RD_SDIO_DREFH_S 8 +#define EFUSE_RD_CK8M_FREQ 0x000000FF +#define EFUSE_RD_CK8M_FREQ_S 0 + +#define EFUSE_BLK0_RDATA5 (DR_REG_EFUSE_BASE + 0x014) +#define EFUSE_RD_FLASH_CRYPT_CONFIG 0x0000000F +#define EFUSE_RD_FLASH_CRYPT_CONFIG_S 28 +#define EFUSE_RD_INST_CONFIG 0x000000FF +#define EFUSE_RD_INST_CONFIG_S 20 +#define EFUSE_RD_SPI_PAD_CONFIG 0x000FFFFF +#define EFUSE_RD_SPI_PAD_CONFIG_S 0 + +#define EFUSE_BLK0_RDATA6 (DR_REG_EFUSE_BASE + 0x018) +#define EFUSE_RD_KEY_STATUS (BIT(10)) +#define EFUSE_RD_KEY_STATUS_S 10 +#define EFUSE_RD_DISABLE_DL_CACHE (BIT(9)) +#define EFUSE_RD_DISABLE_DL_CACHE_S 9 +#define EFUSE_RD_DISABLE_DL_DECRYPT (BIT(8)) +#define EFUSE_RD_DISABLE_DL_DECRYPT_S 8 +#define EFUSE_RD_DISABLE_DL_ENCRYPT (BIT(7)) +#define EFUSE_RD_DISABLE_DL_ENCRYPT_S 7 +#define EFUSE_RD_DISABLE_JTAG (BIT(6)) +#define EFUSE_RD_DISABLE_JTAG_S 6 +#define EFUSE_RD_ABS_DONE_1 (BIT(5)) +#define EFUSE_RD_ABS_DONE_1_S 5 +#define EFUSE_RD_ABS_DONE_0 (BIT(4)) +#define EFUSE_RD_ABS_DONE_0_S 4 +#define EFUSE_RD_DISABLE_SDIO_HOST (BIT(3)) +#define EFUSE_RD_DISABLE_SDIO_HOST_S 3 +#define EFUSE_RD_DIG_RESERVE (BIT(2)) +#define EFUSE_RD_DIG_RESERVE_S 2 +#define EFUSE_RD_CODING_SCHEME 0x00000003 +#define EFUSE_RD_CODING_SCHEME_S 0 + +#define EFUSE_BLK0_WDATA0 (DR_REG_EFUSE_BASE + 0x01c) +#define EFUSE_FLASH_CRYPT_CNT 0x000000FF +#define EFUSE_FLASH_CRYPT_CNT_S 20 +#define EFUSE_EFUSE_RD_DIS 0x0000000F +#define EFUSE_EFUSE_RD_DIS_S 16 +#define EFUSE_EFUSE_WR_DIS 0x0000FFFF +#define EFUSE_EFUSE_WR_DIS_S 0 + +#define EFUSE_BLK0_WDATA1 (DR_REG_EFUSE_BASE + 0x020) +#define EFUSE_WIFI_MAC_CRC_LOW 0xFFFFFFFF +#define EFUSE_WIFI_MAC_CRC_LOW_S 0 + +#define EFUSE_BLK0_WDATA2 (DR_REG_EFUSE_BASE + 0x024) +#define EFUSE_WIFI_MAC_CRC_HIGH 0x00FFFFFF +#define EFUSE_WIFI_MAC_CRC_HIGH_S 0 + +#define EFUSE_BLK0_WDATA3 (DR_REG_EFUSE_BASE + 0x028) +#define EFUSE_CHIP_VER_RESERVE 0x00001FFF +#define EFUSE_CHIP_VER_RESERVE_S 4 +#define EFUSE_CHIP_VER_DIS_CACHE (BIT(3)) +#define EFUSE_CHIP_VER_DIS_CACHE_S 3 +#define EFUSE_CHIP_VER_32PAD (BIT(2)) +#define EFUSE_CHIP_VER_32PAD_S 2 +#define EFUSE_CHIP_VER_DIS_BT (BIT(1)) +#define EFUSE_CHIP_VER_DIS_BT_S 1 +#define EFUSE_CHIP_VER_DIS_APP_CPU (BIT(0)) +#define EFUSE_CHIP_VER_DIS_APP_CPU_S 0 + +#define EFUSE_BLK0_WDATA4 (DR_REG_EFUSE_BASE + 0x02c) +#define EFUSE_SDIO_FORCE (BIT(16)) +#define EFUSE_SDIO_FORCE_S 16 +#define EFUSE_SDIO_TIEH (BIT(15)) +#define EFUSE_SDIO_TIEH_S 15 +#define EFUSE_XPD_SDIO_REG (BIT(14)) +#define EFUSE_XPD_SDIO_REG_S 14 +#define EFUSE_SDIO_DREFL 0x00000003 +#define EFUSE_SDIO_DREFL_S 12 +#define EFUSE_SDIO_DREFM 0x00000003 +#define EFUSE_SDIO_DREFM_S 10 +#define EFUSE_SDIO_DREFH 0x00000003 +#define EFUSE_SDIO_DREFH_S 8 +#define EFUSE_CK8M_FREQ 0x000000FF +#define EFUSE_CK8M_FREQ_S 0 + +#define EFUSE_BLK0_WDATA5 (DR_REG_EFUSE_BASE + 0x030) +#define EFUSE_FLASH_CRYPT_CONFIG 0x0000000F +#define EFUSE_FLASH_CRYPT_CONFIG_S 28 +#define EFUSE_INST_CONFIG 0x000000FF +#define EFUSE_INST_CONFIG_S 20 +#define EFUSE_SPI_PAD_CONFIG 0x000FFFFF +#define EFUSE_SPI_PAD_CONFIG_S 0 + +#define EFUSE_BLK0_WDATA6 (DR_REG_EFUSE_BASE + 0x034) +#define EFUSE_KEY_STATUS (BIT(10)) +#define EFUSE_KEY_STATUS_S 10 +#define EFUSE_DISABLE_DL_CACHE (BIT(9)) +#define EFUSE_DISABLE_DL_CACHE_S 9 +#define EFUSE_DISABLE_DL_DECRYPT (BIT(8)) +#define EFUSE_DISABLE_DL_DECRYPT_S 8 +#define EFUSE_DISABLE_DL_ENCRYPT (BIT(7)) +#define EFUSE_DISABLE_DL_ENCRYPT_S 7 +#define EFUSE_DISABLE_JTAG (BIT(6)) +#define EFUSE_DISABLE_JTAG_S 6 +#define EFUSE_ABS_DONE_1 (BIT(5)) +#define EFUSE_ABS_DONE_1_S 5 +#define EFUSE_ABS_DONE_0 (BIT(4)) +#define EFUSE_ABS_DONE_0_S 4 +#define EFUSE_DISABLE_SDIO_HOST (BIT(3)) +#define EFUSE_DISABLE_SDIO_HOST_S 3 +#define EFUSE_DIG_RESERVE (BIT(2)) +#define EFUSE_DIG_RESERVE_S 2 +#define EFUSE_CODING_SCHEME 0x00000003 +#define EFUSE_CODING_SCHEME_S 0 + +#define EFUSE_BLK1_RDATA0 (DR_REG_EFUSE_BASE + 0x038) +#define EFUSE_EFUSE_BLK1_DOUT0 0xFFFFFFFF +#define EFUSE_EFUSE_BLK1_DOUT0_S 0 + +#define EFUSE_BLK1_RDATA1 (DR_REG_EFUSE_BASE + 0x03c) +#define EFUSE_EFUSE_BLK1_DOUT1 0xFFFFFFFF +#define EFUSE_EFUSE_BLK1_DOUT1_S 0 + +#define EFUSE_BLK1_RDATA2 (DR_REG_EFUSE_BASE + 0x040) +#define EFUSE_EFUSE_BLK1_DOUT2 0xFFFFFFFF +#define EFUSE_EFUSE_BLK1_DOUT2_S 0 + +#define EFUSE_BLK1_RDATA3 (DR_REG_EFUSE_BASE + 0x044) +#define EFUSE_EFUSE_BLK1_DOUT3 0xFFFFFFFF +#define EFUSE_EFUSE_BLK1_DOUT3_S 0 + +#define EFUSE_BLK1_RDATA4 (DR_REG_EFUSE_BASE + 0x048) +#define EFUSE_EFUSE_BLK1_DOUT4 0xFFFFFFFF +#define EFUSE_EFUSE_BLK1_DOUT4_S 0 + +#define EFUSE_BLK1_RDATA5 (DR_REG_EFUSE_BASE + 0x04c) +#define EFUSE_EFUSE_BLK1_DOUT5 0xFFFFFFFF +#define EFUSE_EFUSE_BLK1_DOUT5_S 0 + +#define EFUSE_BLK1_RDATA6 (DR_REG_EFUSE_BASE + 0x050) +#define EFUSE_EFUSE_BLK1_DOUT6 0xFFFFFFFF +#define EFUSE_EFUSE_BLK1_DOUT6_S 0 + +#define EFUSE_BLK1_RDATA7 (DR_REG_EFUSE_BASE + 0x054) +#define EFUSE_EFUSE_BLK1_DOUT7 0xFFFFFFFF +#define EFUSE_EFUSE_BLK1_DOUT7_S 0 + +#define EFUSE_BLK2_RDATA0 (DR_REG_EFUSE_BASE + 0x058) +#define EFUSE_EFUSE_BLK2_DOUT0 0xFFFFFFFF +#define EFUSE_EFUSE_BLK2_DOUT0_S 0 + +#define EFUSE_BLK2_RDATA1 (DR_REG_EFUSE_BASE + 0x05c) +#define EFUSE_EFUSE_BLK2_DOUT1 0xFFFFFFFF +#define EFUSE_EFUSE_BLK2_DOUT1_S 0 + +#define EFUSE_BLK2_RDATA2 (DR_REG_EFUSE_BASE + 0x060) +#define EFUSE_EFUSE_BLK2_DOUT2 0xFFFFFFFF +#define EFUSE_EFUSE_BLK2_DOUT2_S 0 + +#define EFUSE_BLK2_RDATA3 (DR_REG_EFUSE_BASE + 0x064) +#define EFUSE_EFUSE_BLK2_DOUT3 0xFFFFFFFF +#define EFUSE_EFUSE_BLK2_DOUT3_S 0 + +#define EFUSE_BLK2_RDATA4 (DR_REG_EFUSE_BASE + 0x068) +#define EFUSE_EFUSE_BLK2_DOUT4 0xFFFFFFFF +#define EFUSE_EFUSE_BLK2_DOUT4_S 0 + +#define EFUSE_BLK2_RDATA5 (DR_REG_EFUSE_BASE + 0x06c) +#define EFUSE_EFUSE_BLK2_DOUT5 0xFFFFFFFF +#define EFUSE_EFUSE_BLK2_DOUT5_S 0 + +#define EFUSE_BLK2_RDATA6 (DR_REG_EFUSE_BASE + 0x070) +#define EFUSE_EFUSE_BLK2_DOUT6 0xFFFFFFFF +#define EFUSE_EFUSE_BLK2_DOUT6_S 0 + +#define EFUSE_BLK2_RDATA7 (DR_REG_EFUSE_BASE + 0x074) +#define EFUSE_EFUSE_BLK2_DOUT7 0xFFFFFFFF +#define EFUSE_EFUSE_BLK2_DOUT7_S 0 + +#define EFUSE_BLK3_RDATA0 (DR_REG_EFUSE_BASE + 0x078) +#define EFUSE_EFUSE_BLK3_DOUT0 0xFFFFFFFF +#define EFUSE_EFUSE_BLK3_DOUT0_S 0 + +#define EFUSE_BLK3_RDATA1 (DR_REG_EFUSE_BASE + 0x07c) +#define EFUSE_EFUSE_BLK3_DOUT1 0xFFFFFFFF +#define EFUSE_EFUSE_BLK3_DOUT1_S 0 + +#define EFUSE_BLK3_RDATA2 (DR_REG_EFUSE_BASE + 0x080) +#define EFUSE_EFUSE_BLK3_DOUT2 0xFFFFFFFF +#define EFUSE_EFUSE_BLK3_DOUT2_S 0 + +#define EFUSE_BLK3_RDATA3 (DR_REG_EFUSE_BASE + 0x084) +#define EFUSE_EFUSE_BLK3_DOUT3 0xFFFFFFFF +#define EFUSE_EFUSE_BLK3_DOUT3_S 0 + +#define EFUSE_BLK3_RDATA4 (DR_REG_EFUSE_BASE + 0x088) +#define EFUSE_EFUSE_BLK3_DOUT4 0xFFFFFFFF +#define EFUSE_EFUSE_BLK3_DOUT4_S 0 + +#define EFUSE_BLK3_RDATA5 (DR_REG_EFUSE_BASE + 0x08c) +#define EFUSE_EFUSE_BLK3_DOUT5 0xFFFFFFFF +#define EFUSE_EFUSE_BLK3_DOUT5_S 0 + +#define EFUSE_BLK3_RDATA6 (DR_REG_EFUSE_BASE + 0x090) +#define EFUSE_EFUSE_BLK3_DOUT6 0xFFFFFFFF +#define EFUSE_EFUSE_BLK3_DOUT6_S 0 + +#define EFUSE_BLK3_RDATA7 (DR_REG_EFUSE_BASE + 0x094) +#define EFUSE_EFUSE_BLK3_DOUT7 0xFFFFFFFF +#define EFUSE_EFUSE_BLK3_DOUT7_S 0 + +#define EFUSE_BLK1_WDATA0 (DR_REG_EFUSE_BASE + 0x098) +#define EFUSE_EFUSE_BLK1_DIN0 0xFFFFFFFF +#define EFUSE_EFUSE_BLK1_DIN0_S 0 + +#define EFUSE_BLK1_WDATA1 (DR_REG_EFUSE_BASE + 0x09c) +#define EFUSE_EFUSE_BLK1_DIN1 0xFFFFFFFF +#define EFUSE_EFUSE_BLK1_DIN1_S 0 + +#define EFUSE_BLK1_WDATA2 (DR_REG_EFUSE_BASE + 0x0a0) +#define EFUSE_EFUSE_BLK1_DIN2 0xFFFFFFFF +#define EFUSE_EFUSE_BLK1_DIN2_S 0 + +#define EFUSE_BLK1_WDATA3 (DR_REG_EFUSE_BASE + 0x0a4) +#define EFUSE_EFUSE_BLK1_DIN3 0xFFFFFFFF +#define EFUSE_EFUSE_BLK1_DIN3_S 0 + +#define EFUSE_BLK1_WDATA4 (DR_REG_EFUSE_BASE + 0x0a8) +#define EFUSE_EFUSE_BLK1_DIN4 0xFFFFFFFF +#define EFUSE_EFUSE_BLK1_DIN4_S 0 + +#define EFUSE_BLK1_WDATA5 (DR_REG_EFUSE_BASE + 0x0ac) +#define EFUSE_EFUSE_BLK1_DIN5 0xFFFFFFFF +#define EFUSE_EFUSE_BLK1_DIN5_S 0 + +#define EFUSE_BLK1_WDATA6 (DR_REG_EFUSE_BASE + 0x0b0) +#define EFUSE_EFUSE_BLK1_DIN6 0xFFFFFFFF +#define EFUSE_EFUSE_BLK1_DIN6_S 0 + +#define EFUSE_BLK1_WDATA7 (DR_REG_EFUSE_BASE + 0x0b4) +#define EFUSE_EFUSE_BLK1_DIN7 0xFFFFFFFF +#define EFUSE_EFUSE_BLK1_DIN7_S 0 + +#define EFUSE_BLK2_WDATA0 (DR_REG_EFUSE_BASE + 0x0b8) +#define EFUSE_EFUSE_BLK2_DIN0 0xFFFFFFFF +#define EFUSE_EFUSE_BLK2_DIN0_S 0 + +#define EFUSE_BLK2_WDATA1 (DR_REG_EFUSE_BASE + 0x0bc) +#define EFUSE_EFUSE_BLK2_DIN1 0xFFFFFFFF +#define EFUSE_EFUSE_BLK2_DIN1_S 0 + +#define EFUSE_BLK2_WDATA2 (DR_REG_EFUSE_BASE + 0x0c0) +#define EFUSE_EFUSE_BLK2_DIN2 0xFFFFFFFF +#define EFUSE_EFUSE_BLK2_DIN2_S 0 + +#define EFUSE_BLK2_WDATA3 (DR_REG_EFUSE_BASE + 0x0c4) +#define EFUSE_EFUSE_BLK2_DIN3 0xFFFFFFFF +#define EFUSE_EFUSE_BLK2_DIN3_S 0 + +#define EFUSE_BLK2_WDATA4 (DR_REG_EFUSE_BASE + 0x0c8) +#define EFUSE_EFUSE_BLK2_DIN4 0xFFFFFFFF +#define EFUSE_EFUSE_BLK2_DIN4_S 0 + +#define EFUSE_BLK2_WDATA5 (DR_REG_EFUSE_BASE + 0x0cc) +#define EFUSE_EFUSE_BLK2_DIN5 0xFFFFFFFF +#define EFUSE_EFUSE_BLK2_DIN5_S 0 + +#define EFUSE_BLK2_WDATA6 (DR_REG_EFUSE_BASE + 0x0d0) +#define EFUSE_EFUSE_BLK2_DIN6 0xFFFFFFFF +#define EFUSE_EFUSE_BLK2_DIN6_S 0 + +#define EFUSE_BLK2_WDATA7 (DR_REG_EFUSE_BASE + 0x0d4) +#define EFUSE_EFUSE_BLK2_DIN7 0xFFFFFFFF +#define EFUSE_EFUSE_BLK2_DIN7_S 0 + +#define EFUSE_BLK3_WDATA0 (DR_REG_EFUSE_BASE + 0x0d8) +#define EFUSE_EFUSE_BLK3_DIN0 0xFFFFFFFF +#define EFUSE_EFUSE_BLK3_DIN0_S 0 + +#define EFUSE_BLK3_WDATA1 (DR_REG_EFUSE_BASE + 0x0dc) +#define EFUSE_EFUSE_BLK3_DIN1 0xFFFFFFFF +#define EFUSE_EFUSE_BLK3_DIN1_S 0 + +#define EFUSE_BLK3_WDATA2 (DR_REG_EFUSE_BASE + 0x0e0) +#define EFUSE_EFUSE_BLK3_DIN2 0xFFFFFFFF +#define EFUSE_EFUSE_BLK3_DIN2_S 0 + +#define EFUSE_BLK3_WDATA3 (DR_REG_EFUSE_BASE + 0x0e4) +#define EFUSE_EFUSE_BLK3_DIN3 0xFFFFFFFF +#define EFUSE_EFUSE_BLK3_DIN3_S 0 + +#define EFUSE_BLK3_WDATA4 (DR_REG_EFUSE_BASE + 0x0e8) +#define EFUSE_EFUSE_BLK3_DIN4 0xFFFFFFFF +#define EFUSE_EFUSE_BLK3_DIN4_S 0 + +#define EFUSE_BLK3_WDATA5 (DR_REG_EFUSE_BASE + 0x0ec) +#define EFUSE_EFUSE_BLK3_DIN5 0xFFFFFFFF +#define EFUSE_EFUSE_BLK3_DIN5_S 0 + +#define EFUSE_BLK3_WDATA6 (DR_REG_EFUSE_BASE + 0x0f0) +#define EFUSE_EFUSE_BLK3_DIN6 0xFFFFFFFF +#define EFUSE_EFUSE_BLK3_DIN6_S 0 + +#define EFUSE_BLK3_WDATA7 (DR_REG_EFUSE_BASE + 0x0f4) +#define EFUSE_EFUSE_BLK3_DIN7 0xFFFFFFFF +#define EFUSE_EFUSE_BLK3_DIN7_S 0 + +#define EFUSE_CLK (DR_REG_EFUSE_BASE + 0x0f8) +#define EFUSE_CLK_EN (BIT(16)) +#define EFUSE_CLK_EN_S 16 +#define EFUSE_EFUSE_CLK_SEL1 0x000000FF +#define EFUSE_EFUSE_CLK_SEL1_S 8 +#define EFUSE_EFUSE_CLK_SEL0 0x000000FF +#define EFUSE_EFUSE_CLK_SEL0_S 0 + +#define EFUSE_CONF (DR_REG_EFUSE_BASE + 0x0fc) +#define EFUSE_EFUSE_FORCE_NO_WR_RD_DIS (BIT(16)) +#define EFUSE_EFUSE_FORCE_NO_WR_RD_DIS_S 16 +#define EFUSE_EFUSE_OP_CODE 0x0000FFFF +#define EFUSE_EFUSE_OP_CODE_S 0 + +#define EFUSE_STATUS (DR_REG_EFUSE_BASE + 0x100) +#define EFUSE_EFUSE_DEBUG 0xFFFFFFFF +#define EFUSE_EFUSE_DEBUG_S 0 + +#define EFUSE_CMD (DR_REG_EFUSE_BASE + 0x104) +#define EFUSE_EFUSE_PGM_CMD (BIT(1)) +#define EFUSE_EFUSE_PGM_CMD_S 1 +#define EFUSE_EFUSE_READ_CMD (BIT(0)) +#define EFUSE_EFUSE_READ_CMD_S 0 + +#define EFUSE_INT_RAW (DR_REG_EFUSE_BASE + 0x108) +#define EFUSE_EFUSE_PGM_DONE_INT_RAW (BIT(1)) +#define EFUSE_EFUSE_PGM_DONE_INT_RAW_S 1 +#define EFUSE_EFUSE_READ_DONE_INT_RAW (BIT(0)) +#define EFUSE_EFUSE_READ_DONE_INT_RAW_S 0 + +#define EFUSE_INT_ST (DR_REG_EFUSE_BASE + 0x10c) +#define EFUSE_EFUSE_PGM_DONE_INT_ST (BIT(1)) +#define EFUSE_EFUSE_PGM_DONE_INT_ST_S 1 +#define EFUSE_EFUSE_READ_DONE_INT_ST (BIT(0)) +#define EFUSE_EFUSE_READ_DONE_INT_ST_S 0 + +#define EFUSE_INT_ENA (DR_REG_EFUSE_BASE + 0x110) +#define EFUSE_EFUSE_PGM_DONE_INT_ENA (BIT(1)) +#define EFUSE_EFUSE_PGM_DONE_INT_ENA_S 1 +#define EFUSE_EFUSE_READ_DONE_INT_ENA (BIT(0)) +#define EFUSE_EFUSE_READ_DONE_INT_ENA_S 0 + +#define EFUSE_INT_CLR (DR_REG_EFUSE_BASE + 0x114) +#define EFUSE_EFUSE_PGM_DONE_INT_CLR (BIT(1)) +#define EFUSE_EFUSE_PGM_DONE_INT_CLR_S 1 +#define EFUSE_EFUSE_READ_DONE_INT_CLR (BIT(0)) +#define EFUSE_EFUSE_READ_DONE_INT_CLR_S 0 + +#define EFUSE_DAC_CONF (DR_REG_EFUSE_BASE + 0x118) +#define EFUSE_EFUSE_DAC_CLK_PAD_SEL (BIT(8)) +#define EFUSE_EFUSE_DAC_CLK_PAD_SEL_S 8 +#define EFUSE_EFUSE_DAC_CLK_DIV 0x000000FF +#define EFUSE_EFUSE_DAC_CLK_DIV_S 0 + +#define EFUSE_DEC_STATUS (DR_REG_EFUSE_BASE + 0x11c) +#define EFUSE_EFUSE_DEC_WARNINGS 0x00000FFF +#define EFUSE_EFUSE_DEC_WARNINGS_S 0 + +#define EFUSE_DATE (DR_REG_EFUSE_BASE + 0x1FC) +#define EFUSE_EFUSE_DATE 0xFFFFFFFF +#define EFUSE_EFUSE_DATE_S 0 +#define EFUSE_EFUSE_DATE_VERSION 0x16042600 + +#endif /* _SOC_EFUSE_REG_H_ */ diff --git a/components/esp32/include/soc/gpio_reg.h b/components/esp32/include/soc/gpio_reg.h new file mode 100644 index 0000000000..8e13dafa79 --- /dev/null +++ b/components/esp32/include/soc/gpio_reg.h @@ -0,0 +1,3124 @@ +// Copyright 2015-2016 Espressif Systems (Shanghai) PTE LTD +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at + +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +#ifndef _SOC_GPIO_REG_H_ +#define _SOC_GPIO_REG_H_ + +#include "soc.h" + +//for GPIO_PIN group +#define GPIO_PIN_CONFIG_MSB 12 +#define GPIO_PIN_CONFIG_LSB 11 +#define GPIO_PIN_CONFIG_MASK 0x00001800 +#define GPIO_PIN_CONFIG_GET(x) (((x) & GPIO_PIN_CONFIG_MASK) >> GPIO_PIN_CONFIG_LSB) +#define GPIO_PIN_CONFIG_SET(x) (((x) << GPIO_PIN_CONFIG_LSB) & GPIO_PIN_CONFIG_MASK) + +#define GPIO_WAKEUP_ENABLE 1 +#define GPIO_WAKEUP_DISABLE (~GPIO_WAKEUP_ENABLE) +#define GPIO_PIN_WAKEUP_ENABLE_MSB 10 +#define GPIO_PIN_WAKEUP_ENABLE_LSB 10 +#define GPIO_PIN_WAKEUP_ENABLE_MASK 0x00000400 +#define GPIO_PIN_WAKEUP_ENABLE_GET(x) (((x) & GPIO_PIN_WAKEUP_ENABLE_MASK) >> GPIO_PIN_WAKEUP_ENABLE_LSB) +#define GPIO_PIN_WAKEUP_ENABLE_SET(x) (((x) << GPIO_PIN_WAKEUP_ENABLE_LSB) & GPIO_PIN_WAKEUP_ENABLE_MASK) + +#define GPIO_PIN_INT_TYPE_MASK 0x380 +#define GPIO_PIN_INT_TYPE_MSB 9 +#define GPIO_PIN_INT_TYPE_LSB 7 +#define GPIO_PIN_INT_TYPE_GET(x) (((x) & GPIO_PIN_INT_TYPE_MASK) >> GPIO_PIN_INT_TYPE_LSB) +#define GPIO_PIN_INT_TYPE_SET(x) (((x) << GPIO_PIN_INT_TYPE_LSB) & GPIO_PIN_INT_TYPE_MASK) + +#define GPIO_PAD_DRIVER_ENABLE 1 +#define GPIO_PAD_DRIVER_DISABLE (~GPIO_PAD_DRIVER_ENABLE) +#define GPIO_PIN_PAD_DRIVER_MSB 2 +#define GPIO_PIN_PAD_DRIVER_LSB 2 +#define GPIO_PIN_PAD_DRIVER_MASK 0x00000004 +#define GPIO_PIN_PAD_DRIVER_GET(x) (((x) & GPIO_PIN_PAD_DRIVER_MASK) >> GPIO_PIN_PAD_DRIVER_LSB) +#define GPIO_PIN_PAD_DRIVER_SET(x) (((x) << GPIO_PIN_PAD_DRIVER_LSB) & GPIO_PIN_PAD_DRIVER_MASK) + +//end GPIO_PIN group + +#define GPIO_BT_SELECT (DR_REG_GPIO_BASE + 0x0000) +#define GPIO_GPIO_BT_SEL 0xFFFFFFFF +#define GPIO_GPIO_BT_SEL_S 0 + +#define GPIO_OUT (DR_REG_GPIO_BASE + 0x0004) +#define GPIO_GPIO_OUT_DATA 0xFFFFFFFF +#define GPIO_GPIO_OUT_DATA_S 0 + +#define GPIO_OUT_W1TS (DR_REG_GPIO_BASE + 0x0008) +#define GPIO_GPIO_OUT_DATA 0xFFFFFFFF +#define GPIO_GPIO_OUT_DATA_S 0 + +#define GPIO_OUT_W1TC (DR_REG_GPIO_BASE + 0x000c) +#define GPIO_GPIO_OUT_DATA 0xFFFFFFFF +#define GPIO_GPIO_OUT_DATA_S 0 + +#define GPIO_OUT1 (DR_REG_GPIO_BASE + 0x0010) +#define GPIO_GPIO_OUT_DATA_H 0x000000FF +#define GPIO_GPIO_OUT_DATA_H_S 0 + +#define GPIO_OUT1_W1TS (DR_REG_GPIO_BASE + 0x0014) +#define GPIO_GPIO_OUT_DATA_H 0x000000FF +#define GPIO_GPIO_OUT_DATA_H_S 0 + +#define GPIO_OUT1_W1TC (DR_REG_GPIO_BASE + 0x0018) +#define GPIO_GPIO_OUT_DATA_H 0x000000FF +#define GPIO_GPIO_OUT_DATA_H_S 0 + +#define GPIO_SDIO_SELECT (DR_REG_GPIO_BASE + 0x001c) +#define GPIO_GPIO_SDIO_SEL 0x000000FF +#define GPIO_GPIO_SDIO_SEL_S 0 + +#define GPIO_ENABLE (DR_REG_GPIO_BASE + 0x0020) +#define GPIO_GPIO_ENABLE_DATA 0xFFFFFFFF +#define GPIO_GPIO_ENABLE_DATA_S 0 + +#define GPIO_ENABLE_W1TS (DR_REG_GPIO_BASE + 0x0024) +#define GPIO_GPIO_ENABLE_DATA 0xFFFFFFFF +#define GPIO_GPIO_ENABLE_DATA_S 0 + +#define GPIO_ENABLE_W1TC (DR_REG_GPIO_BASE + 0x0028) +#define GPIO_GPIO_ENABLE_DATA 0xFFFFFFFF +#define GPIO_GPIO_ENABLE_DATA_S 0 + +#define GPIO_ENABLE1 (DR_REG_GPIO_BASE + 0x002c) +#define GPIO_GPIO_ENABLE_DATA_H 0x000000FF +#define GPIO_GPIO_ENABLE_DATA_H_S 0 + +#define GPIO_ENABLE1_W1TS (DR_REG_GPIO_BASE + 0x0030) +#define GPIO_GPIO_ENABLE_DATA_H 0x000000FF +#define GPIO_GPIO_ENABLE_DATA_H_S 0 + +#define GPIO_ENABLE1_W1TC (DR_REG_GPIO_BASE + 0x0034) +#define GPIO_GPIO_ENABLE_DATA_H 0x000000FF +#define GPIO_GPIO_ENABLE_DATA_H_S 0 + +#define GPIO_STRAP (DR_REG_GPIO_BASE + 0x0038) +#define GPIO_GPIO_STRAPPING 0x0000FFFF +#define GPIO_GPIO_STRAPPING_S 0 + +#define GPIO_IN (DR_REG_GPIO_BASE + 0x003c) +#define GPIO_GPIO_IN_DATA_NEXT 0xFFFFFFFF +#define GPIO_GPIO_IN_DATA_NEXT_S 0 + +#define GPIO_IN1 (DR_REG_GPIO_BASE + 0x0040) +#define GPIO_GPIO_IN_DATA_NEXT_H 0x000000FF +#define GPIO_GPIO_IN_DATA_NEXT_H_S 0 + +#define GPIO_STATUS (DR_REG_GPIO_BASE + 0x0044) +#define GPIO_GPIO_STATUS_INTERRUPT 0xFFFFFFFF +#define GPIO_GPIO_STATUS_INTERRUPT_S 0 + +#define GPIO_STATUS_W1TS (DR_REG_GPIO_BASE + 0x0048) +#define GPIO_GPIO_STATUS_INTERRUPT 0xFFFFFFFF +#define GPIO_GPIO_STATUS_INTERRUPT_S 0 + +#define GPIO_STATUS_W1TC (DR_REG_GPIO_BASE + 0x004c) +#define GPIO_GPIO_STATUS_INTERRUPT 0xFFFFFFFF +#define GPIO_GPIO_STATUS_INTERRUPT_S 0 + +#define GPIO_STATUS1 (DR_REG_GPIO_BASE + 0x0050) +#define GPIO_GPIO_STATUS_INTERRUPT_H 0x000000FF +#define GPIO_GPIO_STATUS_INTERRUPT_H_S 0 + +#define GPIO_STATUS1_W1TS (DR_REG_GPIO_BASE + 0x0054) +#define GPIO_GPIO_STATUS_INTERRUPT_H 0x000000FF +#define GPIO_GPIO_STATUS_INTERRUPT_H_S 0 + +#define GPIO_STATUS1_W1TC (DR_REG_GPIO_BASE + 0x0058) +#define GPIO_GPIO_STATUS_INTERRUPT_H 0x000000FF +#define GPIO_GPIO_STATUS_INTERRUPT_H_S 0 + +#define GPIO_ACPU_INT (DR_REG_GPIO_BASE + 0x0060) +#define GPIO_GPIO_APPCPU_INT 0xFFFFFFFF +#define GPIO_GPIO_APPCPU_INT_S 0 + +#define GPIO_ACPU_NMI_INT (DR_REG_GPIO_BASE + 0x0064) +#define GPIO_GPIO_APPCPU_NMI_INT 0xFFFFFFFF +#define GPIO_GPIO_APPCPU_NMI_INT_S 0 + +#define GPIO_PCPU_INT (DR_REG_GPIO_BASE + 0x0068) +#define GPIO_GPIO_PROCPU_INT 0xFFFFFFFF +#define GPIO_GPIO_PROCPU_INT_S 0 + +#define GPIO_PCPU_NMI_INT (DR_REG_GPIO_BASE + 0x006c) +#define GPIO_GPIO_PROCPU_NMI_INT 0xFFFFFFFF +#define GPIO_GPIO_PROCPU_NMI_INT_S 0 + +#define GPIO_CPUSDIO_INT (DR_REG_GPIO_BASE + 0x0070) +#define GPIO_GPIO_SDIO_INT 0xFFFFFFFF +#define GPIO_GPIO_SDIO_INT_S 0 + +#define GPIO_ACPU_INT1 (DR_REG_GPIO_BASE + 0x0074) +#define GPIO_GPIO_APPCPU_INT_H 0x000000FF +#define GPIO_GPIO_APPCPU_INT_H_S 0 + +#define GPIO_ACPU_NMI_INT1 (DR_REG_GPIO_BASE + 0x0078) +#define GPIO_GPIO_APPCPU_NMI_INT_H 0x000000FF +#define GPIO_GPIO_APPCPU_NMI_INT_H_S 0 + +#define GPIO_PCPU_INT1 (DR_REG_GPIO_BASE + 0x007c) +#define GPIO_GPIO_PROCPU_INT_H 0x000000FF +#define GPIO_GPIO_PROCPU_INT_H_S 0 + +#define GPIO_PCPU_NMI_INT1 (DR_REG_GPIO_BASE + 0x0080) +#define GPIO_GPIO_PROCPU_NMI_INT_H 0x000000FF +#define GPIO_GPIO_PROCPU_NMI_INT_H_S 0 + +#define GPIO_CPUSDIO_INT1 (DR_REG_GPIO_BASE + 0x0084) +#define GPIO_GPIO_SDIO_INT_H 0x000000FF +#define GPIO_GPIO_SDIO_INT_H_S 0 + +#define GPIO_PIN0 (DR_REG_GPIO_BASE + 0x0088) +#define GPIO_GPIO_PIN0_INT_ENA 0x0000001F +#define GPIO_GPIO_PIN0_INT_ENA_S 13 +#define GPIO_GPIO_PIN0_CONFIG 0x00000003 +#define GPIO_GPIO_PIN0_CONFIG_S 11 +#define GPIO_GPIO_PIN0_WAKEUP_ENABLE (BIT(10)) +#define GPIO_GPIO_PIN0_WAKEUP_ENABLE_S 10 +#define GPIO_GPIO_PIN0_INT_TYPE 0x00000007 +#define GPIO_GPIO_PIN0_INT_TYPE_S 7 +#define GPIO_GPIO_PIN0_PAD_DRIVER (BIT(2)) +#define GPIO_GPIO_PIN0_PAD_DRIVER_S 2 + +#define GPIO_PIN1 (DR_REG_GPIO_BASE + 0x008c) +#define GPIO_GPIO_PIN1_INT_ENA 0x0000001F +#define GPIO_GPIO_PIN1_INT_ENA_S 13 +#define GPIO_GPIO_PIN1_CONFIG 0x00000003 +#define GPIO_GPIO_PIN1_CONFIG_S 11 +#define GPIO_GPIO_PIN1_WAKEUP_ENABLE (BIT(10)) +#define GPIO_GPIO_PIN1_WAKEUP_ENABLE_S 10 +#define GPIO_GPIO_PIN1_INT_TYPE 0x00000007 +#define GPIO_GPIO_PIN1_INT_TYPE_S 7 +#define GPIO_GPIO_PIN1_PAD_DRIVER (BIT(2)) +#define GPIO_GPIO_PIN1_PAD_DRIVER_S 2 + +#define GPIO_PIN2 (DR_REG_GPIO_BASE + 0x0090) +#define GPIO_GPIO_PIN2_INT_ENA 0x0000001F +#define GPIO_GPIO_PIN2_INT_ENA_S 13 +#define GPIO_GPIO_PIN2_CONFIG 0x00000003 +#define GPIO_GPIO_PIN2_CONFIG_S 11 +#define GPIO_GPIO_PIN2_WAKEUP_ENABLE (BIT(10)) +#define GPIO_GPIO_PIN2_WAKEUP_ENABLE_S 10 +#define GPIO_GPIO_PIN2_INT_TYPE 0x00000007 +#define GPIO_GPIO_PIN2_INT_TYPE_S 7 +#define GPIO_GPIO_PIN2_PAD_DRIVER (BIT(2)) +#define GPIO_GPIO_PIN2_PAD_DRIVER_S 2 + +#define GPIO_PIN3 (DR_REG_GPIO_BASE + 0x0094) +#define GPIO_GPIO_PIN3_INT_ENA 0x0000001F +#define GPIO_GPIO_PIN3_INT_ENA_S 13 +#define GPIO_GPIO_PIN3_CONFIG 0x00000003 +#define GPIO_GPIO_PIN3_CONFIG_S 11 +#define GPIO_GPIO_PIN3_WAKEUP_ENABLE (BIT(10)) +#define GPIO_GPIO_PIN3_WAKEUP_ENABLE_S 10 +#define GPIO_GPIO_PIN3_INT_TYPE 0x00000007 +#define GPIO_GPIO_PIN3_INT_TYPE_S 7 +#define GPIO_GPIO_PIN3_PAD_DRIVER (BIT(2)) +#define GPIO_GPIO_PIN3_PAD_DRIVER_S 2 + +#define GPIO_PIN4 (DR_REG_GPIO_BASE + 0x0098) +#define GPIO_GPIO_PIN4_INT_ENA 0x0000001F +#define GPIO_GPIO_PIN4_INT_ENA_S 13 +#define GPIO_GPIO_PIN4_CONFIG 0x00000003 +#define GPIO_GPIO_PIN4_CONFIG_S 11 +#define GPIO_GPIO_PIN4_WAKEUP_ENABLE (BIT(10)) +#define GPIO_GPIO_PIN4_WAKEUP_ENABLE_S 10 +#define GPIO_GPIO_PIN4_INT_TYPE 0x00000007 +#define GPIO_GPIO_PIN4_INT_TYPE_S 7 +#define GPIO_GPIO_PIN4_PAD_DRIVER (BIT(2)) +#define GPIO_GPIO_PIN4_PAD_DRIVER_S 2 + +#define GPIO_PIN5 (DR_REG_GPIO_BASE + 0x009c) +#define GPIO_GPIO_PIN5_INT_ENA 0x0000001F +#define GPIO_GPIO_PIN5_INT_ENA_S 13 +#define GPIO_GPIO_PIN5_CONFIG 0x00000003 +#define GPIO_GPIO_PIN5_CONFIG_S 11 +#define GPIO_GPIO_PIN5_WAKEUP_ENABLE (BIT(10)) +#define GPIO_GPIO_PIN5_WAKEUP_ENABLE_S 10 +#define GPIO_GPIO_PIN5_INT_TYPE 0x00000007 +#define GPIO_GPIO_PIN5_INT_TYPE_S 7 +#define GPIO_GPIO_PIN5_PAD_DRIVER (BIT(2)) +#define GPIO_GPIO_PIN5_PAD_DRIVER_S 2 + +#define GPIO_PIN6 (DR_REG_GPIO_BASE + 0x00a0) +#define GPIO_GPIO_PIN6_INT_ENA 0x0000001F +#define GPIO_GPIO_PIN6_INT_ENA_S 13 +#define GPIO_GPIO_PIN6_CONFIG 0x00000003 +#define GPIO_GPIO_PIN6_CONFIG_S 11 +#define GPIO_GPIO_PIN6_WAKEUP_ENABLE (BIT(10)) +#define GPIO_GPIO_PIN6_WAKEUP_ENABLE_S 10 +#define GPIO_GPIO_PIN6_INT_TYPE 0x00000007 +#define GPIO_GPIO_PIN6_INT_TYPE_S 7 +#define GPIO_GPIO_PIN6_PAD_DRIVER (BIT(2)) +#define GPIO_GPIO_PIN6_PAD_DRIVER_S 2 + +#define GPIO_PIN7 (DR_REG_GPIO_BASE + 0x00a4) +#define GPIO_GPIO_PIN7_INT_ENA 0x0000001F +#define GPIO_GPIO_PIN7_INT_ENA_S 13 +#define GPIO_GPIO_PIN7_CONFIG 0x00000003 +#define GPIO_GPIO_PIN7_CONFIG_S 11 +#define GPIO_GPIO_PIN7_WAKEUP_ENABLE (BIT(10)) +#define GPIO_GPIO_PIN7_WAKEUP_ENABLE_S 10 +#define GPIO_GPIO_PIN7_INT_TYPE 0x00000007 +#define GPIO_GPIO_PIN7_INT_TYPE_S 7 +#define GPIO_GPIO_PIN7_PAD_DRIVER (BIT(2)) +#define GPIO_GPIO_PIN7_PAD_DRIVER_S 2 + +#define GPIO_PIN8 (DR_REG_GPIO_BASE + 0x00a8) +#define GPIO_GPIO_PIN8_INT_ENA 0x0000001F +#define GPIO_GPIO_PIN8_INT_ENA_S 13 +#define GPIO_GPIO_PIN8_CONFIG 0x00000003 +#define GPIO_GPIO_PIN8_CONFIG_S 11 +#define GPIO_GPIO_PIN8_WAKEUP_ENABLE (BIT(10)) +#define GPIO_GPIO_PIN8_WAKEUP_ENABLE_S 10 +#define GPIO_GPIO_PIN8_INT_TYPE 0x00000007 +#define GPIO_GPIO_PIN8_INT_TYPE_S 7 +#define GPIO_GPIO_PIN8_PAD_DRIVER (BIT(2)) +#define GPIO_GPIO_PIN8_PAD_DRIVER_S 2 + +#define GPIO_PIN9 (DR_REG_GPIO_BASE + 0x00ac) +#define GPIO_GPIO_PIN9_INT_ENA 0x0000001F +#define GPIO_GPIO_PIN9_INT_ENA_S 13 +#define GPIO_GPIO_PIN9_CONFIG 0x00000003 +#define GPIO_GPIO_PIN9_CONFIG_S 11 +#define GPIO_GPIO_PIN9_WAKEUP_ENABLE (BIT(10)) +#define GPIO_GPIO_PIN9_WAKEUP_ENABLE_S 10 +#define GPIO_GPIO_PIN9_INT_TYPE 0x00000007 +#define GPIO_GPIO_PIN9_INT_TYPE_S 7 +#define GPIO_GPIO_PIN9_PAD_DRIVER (BIT(2)) +#define GPIO_GPIO_PIN9_PAD_DRIVER_S 2 + +#define GPIO_PIN10 (DR_REG_GPIO_BASE + 0x00b0) +#define GPIO_GPIO_PIN10_INT_ENA 0x0000001F +#define GPIO_GPIO_PIN10_INT_ENA_S 13 +#define GPIO_GPIO_PIN10_CONFIG 0x00000003 +#define GPIO_GPIO_PIN10_CONFIG_S 11 +#define GPIO_GPIO_PIN10_WAKEUP_ENABLE (BIT(10)) +#define GPIO_GPIO_PIN10_WAKEUP_ENABLE_S 10 +#define GPIO_GPIO_PIN10_INT_TYPE 0x00000007 +#define GPIO_GPIO_PIN10_INT_TYPE_S 7 +#define GPIO_GPIO_PIN10_PAD_DRIVER (BIT(2)) +#define GPIO_GPIO_PIN10_PAD_DRIVER_S 2 + +#define GPIO_PIN11 (DR_REG_GPIO_BASE + 0x00b4) +#define GPIO_GPIO_PIN11_INT_ENA 0x0000001F +#define GPIO_GPIO_PIN11_INT_ENA_S 13 +#define GPIO_GPIO_PIN11_CONFIG 0x00000003 +#define GPIO_GPIO_PIN11_CONFIG_S 11 +#define GPIO_GPIO_PIN11_WAKEUP_ENABLE (BIT(10)) +#define GPIO_GPIO_PIN11_WAKEUP_ENABLE_S 10 +#define GPIO_GPIO_PIN11_INT_TYPE 0x00000007 +#define GPIO_GPIO_PIN11_INT_TYPE_S 7 +#define GPIO_GPIO_PIN11_PAD_DRIVER (BIT(2)) +#define GPIO_GPIO_PIN11_PAD_DRIVER_S 2 + +#define GPIO_PIN12 (DR_REG_GPIO_BASE + 0x00b8) +#define GPIO_GPIO_PIN12_INT_ENA 0x0000001F +#define GPIO_GPIO_PIN12_INT_ENA_S 13 +#define GPIO_GPIO_PIN12_CONFIG 0x00000003 +#define GPIO_GPIO_PIN12_CONFIG_S 11 +#define GPIO_GPIO_PIN12_WAKEUP_ENABLE (BIT(10)) +#define GPIO_GPIO_PIN12_WAKEUP_ENABLE_S 10 +#define GPIO_GPIO_PIN12_INT_TYPE 0x00000007 +#define GPIO_GPIO_PIN12_INT_TYPE_S 7 +#define GPIO_GPIO_PIN12_PAD_DRIVER (BIT(2)) +#define GPIO_GPIO_PIN12_PAD_DRIVER_S 2 + +#define GPIO_PIN13 (DR_REG_GPIO_BASE + 0x00bc) +#define GPIO_GPIO_PIN13_INT_ENA 0x0000001F +#define GPIO_GPIO_PIN13_INT_ENA_S 13 +#define GPIO_GPIO_PIN13_CONFIG 0x00000003 +#define GPIO_GPIO_PIN13_CONFIG_S 11 +#define GPIO_GPIO_PIN13_WAKEUP_ENABLE (BIT(10)) +#define GPIO_GPIO_PIN13_WAKEUP_ENABLE_S 10 +#define GPIO_GPIO_PIN13_INT_TYPE 0x00000007 +#define GPIO_GPIO_PIN13_INT_TYPE_S 7 +#define GPIO_GPIO_PIN13_PAD_DRIVER (BIT(2)) +#define GPIO_GPIO_PIN13_PAD_DRIVER_S 2 + +#define GPIO_PIN14 (DR_REG_GPIO_BASE + 0x00c0) +#define GPIO_GPIO_PIN14_INT_ENA 0x0000001F +#define GPIO_GPIO_PIN14_INT_ENA_S 13 +#define GPIO_GPIO_PIN14_CONFIG 0x00000003 +#define GPIO_GPIO_PIN14_CONFIG_S 11 +#define GPIO_GPIO_PIN14_WAKEUP_ENABLE (BIT(10)) +#define GPIO_GPIO_PIN14_WAKEUP_ENABLE_S 10 +#define GPIO_GPIO_PIN14_INT_TYPE 0x00000007 +#define GPIO_GPIO_PIN14_INT_TYPE_S 7 +#define GPIO_GPIO_PIN14_PAD_DRIVER (BIT(2)) +#define GPIO_GPIO_PIN14_PAD_DRIVER_S 2 + +#define GPIO_PIN15 (DR_REG_GPIO_BASE + 0x00c4) +#define GPIO_GPIO_PIN15_INT_ENA 0x0000001F +#define GPIO_GPIO_PIN15_INT_ENA_S 13 +#define GPIO_GPIO_PIN15_CONFIG 0x00000003 +#define GPIO_GPIO_PIN15_CONFIG_S 11 +#define GPIO_GPIO_PIN15_WAKEUP_ENABLE (BIT(10)) +#define GPIO_GPIO_PIN15_WAKEUP_ENABLE_S 10 +#define GPIO_GPIO_PIN15_INT_TYPE 0x00000007 +#define GPIO_GPIO_PIN15_INT_TYPE_S 7 +#define GPIO_GPIO_PIN15_PAD_DRIVER (BIT(2)) +#define GPIO_GPIO_PIN15_PAD_DRIVER_S 2 + +#define GPIO_PIN16 (DR_REG_GPIO_BASE + 0x00c8) +#define GPIO_GPIO_PIN16_INT_ENA 0x0000001F +#define GPIO_GPIO_PIN16_INT_ENA_S 13 +#define GPIO_GPIO_PIN16_CONFIG 0x00000003 +#define GPIO_GPIO_PIN16_CONFIG_S 11 +#define GPIO_GPIO_PIN16_WAKEUP_ENABLE (BIT(10)) +#define GPIO_GPIO_PIN16_WAKEUP_ENABLE_S 10 +#define GPIO_GPIO_PIN16_INT_TYPE 0x00000007 +#define GPIO_GPIO_PIN16_INT_TYPE_S 7 +#define GPIO_GPIO_PIN16_PAD_DRIVER (BIT(2)) +#define GPIO_GPIO_PIN16_PAD_DRIVER_S 2 + +#define GPIO_PIN17 (DR_REG_GPIO_BASE + 0x00cc) +#define GPIO_GPIO_PIN17_INT_ENA 0x0000001F +#define GPIO_GPIO_PIN17_INT_ENA_S 13 +#define GPIO_GPIO_PIN17_CONFIG 0x00000003 +#define GPIO_GPIO_PIN17_CONFIG_S 11 +#define GPIO_GPIO_PIN17_WAKEUP_ENABLE (BIT(10)) +#define GPIO_GPIO_PIN17_WAKEUP_ENABLE_S 10 +#define GPIO_GPIO_PIN17_INT_TYPE 0x00000007 +#define GPIO_GPIO_PIN17_INT_TYPE_S 7 +#define GPIO_GPIO_PIN17_PAD_DRIVER (BIT(2)) +#define GPIO_GPIO_PIN17_PAD_DRIVER_S 2 + +#define GPIO_PIN18 (DR_REG_GPIO_BASE + 0x00d0) +#define GPIO_GPIO_PIN18_INT_ENA 0x0000001F +#define GPIO_GPIO_PIN18_INT_ENA_S 13 +#define GPIO_GPIO_PIN18_CONFIG 0x00000003 +#define GPIO_GPIO_PIN18_CONFIG_S 11 +#define GPIO_GPIO_PIN18_WAKEUP_ENABLE (BIT(10)) +#define GPIO_GPIO_PIN18_WAKEUP_ENABLE_S 10 +#define GPIO_GPIO_PIN18_INT_TYPE 0x00000007 +#define GPIO_GPIO_PIN18_INT_TYPE_S 7 +#define GPIO_GPIO_PIN18_PAD_DRIVER (BIT(2)) +#define GPIO_GPIO_PIN18_PAD_DRIVER_S 2 + +#define GPIO_PIN19 (DR_REG_GPIO_BASE + 0x00d4) +#define GPIO_GPIO_PIN19_INT_ENA 0x0000001F +#define GPIO_GPIO_PIN19_INT_ENA_S 13 +#define GPIO_GPIO_PIN19_CONFIG 0x00000003 +#define GPIO_GPIO_PIN19_CONFIG_S 11 +#define GPIO_GPIO_PIN19_WAKEUP_ENABLE (BIT(10)) +#define GPIO_GPIO_PIN19_WAKEUP_ENABLE_S 10 +#define GPIO_GPIO_PIN19_INT_TYPE 0x00000007 +#define GPIO_GPIO_PIN19_INT_TYPE_S 7 +#define GPIO_GPIO_PIN19_PAD_DRIVER (BIT(2)) +#define GPIO_GPIO_PIN19_PAD_DRIVER_S 2 + +#define GPIO_PIN20 (DR_REG_GPIO_BASE + 0x00d8) +#define GPIO_GPIO_PIN20_INT_ENA 0x0000001F +#define GPIO_GPIO_PIN20_INT_ENA_S 13 +#define GPIO_GPIO_PIN20_CONFIG 0x00000003 +#define GPIO_GPIO_PIN20_CONFIG_S 11 +#define GPIO_GPIO_PIN20_WAKEUP_ENABLE (BIT(10)) +#define GPIO_GPIO_PIN20_WAKEUP_ENABLE_S 10 +#define GPIO_GPIO_PIN20_INT_TYPE 0x00000007 +#define GPIO_GPIO_PIN20_INT_TYPE_S 7 +#define GPIO_GPIO_PIN20_PAD_DRIVER (BIT(2)) +#define GPIO_GPIO_PIN20_PAD_DRIVER_S 2 + +#define GPIO_PIN21 (DR_REG_GPIO_BASE + 0x00dc) +#define GPIO_GPIO_PIN21_INT_ENA 0x0000001F +#define GPIO_GPIO_PIN21_INT_ENA_S 13 +#define GPIO_GPIO_PIN21_CONFIG 0x00000003 +#define GPIO_GPIO_PIN21_CONFIG_S 11 +#define GPIO_GPIO_PIN21_WAKEUP_ENABLE (BIT(10)) +#define GPIO_GPIO_PIN21_WAKEUP_ENABLE_S 10 +#define GPIO_GPIO_PIN21_INT_TYPE 0x00000007 +#define GPIO_GPIO_PIN21_INT_TYPE_S 7 +#define GPIO_GPIO_PIN21_PAD_DRIVER (BIT(2)) +#define GPIO_GPIO_PIN21_PAD_DRIVER_S 2 + +#define GPIO_PIN22 (DR_REG_GPIO_BASE + 0x00e0) +#define GPIO_GPIO_PIN22_INT_ENA 0x0000001F +#define GPIO_GPIO_PIN22_INT_ENA_S 13 +#define GPIO_GPIO_PIN22_CONFIG 0x00000003 +#define GPIO_GPIO_PIN22_CONFIG_S 11 +#define GPIO_GPIO_PIN22_WAKEUP_ENABLE (BIT(10)) +#define GPIO_GPIO_PIN22_WAKEUP_ENABLE_S 10 +#define GPIO_GPIO_PIN22_INT_TYPE 0x00000007 +#define GPIO_GPIO_PIN22_INT_TYPE_S 7 +#define GPIO_GPIO_PIN22_PAD_DRIVER (BIT(2)) +#define GPIO_GPIO_PIN22_PAD_DRIVER_S 2 + +#define GPIO_PIN23 (DR_REG_GPIO_BASE + 0x00e4) +#define GPIO_GPIO_PIN23_INT_ENA 0x0000001F +#define GPIO_GPIO_PIN23_INT_ENA_S 13 +#define GPIO_GPIO_PIN23_CONFIG 0x00000003 +#define GPIO_GPIO_PIN23_CONFIG_S 11 +#define GPIO_GPIO_PIN23_WAKEUP_ENABLE (BIT(10)) +#define GPIO_GPIO_PIN23_WAKEUP_ENABLE_S 10 +#define GPIO_GPIO_PIN23_INT_TYPE 0x00000007 +#define GPIO_GPIO_PIN23_INT_TYPE_S 7 +#define GPIO_GPIO_PIN23_PAD_DRIVER (BIT(2)) +#define GPIO_GPIO_PIN23_PAD_DRIVER_S 2 + +#define GPIO_PIN24 (DR_REG_GPIO_BASE + 0x00e8) +#define GPIO_GPIO_PIN24_INT_ENA 0x0000001F +#define GPIO_GPIO_PIN24_INT_ENA_S 13 +#define GPIO_GPIO_PIN24_CONFIG 0x00000003 +#define GPIO_GPIO_PIN24_CONFIG_S 11 +#define GPIO_GPIO_PIN24_WAKEUP_ENABLE (BIT(10)) +#define GPIO_GPIO_PIN24_WAKEUP_ENABLE_S 10 +#define GPIO_GPIO_PIN24_INT_TYPE 0x00000007 +#define GPIO_GPIO_PIN24_INT_TYPE_S 7 +#define GPIO_GPIO_PIN24_PAD_DRIVER (BIT(2)) +#define GPIO_GPIO_PIN24_PAD_DRIVER_S 2 + +#define GPIO_PIN25 (DR_REG_GPIO_BASE + 0x00ec) +#define GPIO_GPIO_PIN25_INT_ENA 0x0000001F +#define GPIO_GPIO_PIN25_INT_ENA_S 13 +#define GPIO_GPIO_PIN25_CONFIG 0x00000003 +#define GPIO_GPIO_PIN25_CONFIG_S 11 +#define GPIO_GPIO_PIN25_WAKEUP_ENABLE (BIT(10)) +#define GPIO_GPIO_PIN25_WAKEUP_ENABLE_S 10 +#define GPIO_GPIO_PIN25_INT_TYPE 0x00000007 +#define GPIO_GPIO_PIN25_INT_TYPE_S 7 +#define GPIO_GPIO_PIN25_PAD_DRIVER (BIT(2)) +#define GPIO_GPIO_PIN25_PAD_DRIVER_S 2 + +#define GPIO_PIN26 (DR_REG_GPIO_BASE + 0x00f0) +#define GPIO_GPIO_PIN26_INT_ENA 0x0000001F +#define GPIO_GPIO_PIN26_INT_ENA_S 13 +#define GPIO_GPIO_PIN26_CONFIG 0x00000003 +#define GPIO_GPIO_PIN26_CONFIG_S 11 +#define GPIO_GPIO_PIN26_WAKEUP_ENABLE (BIT(10)) +#define GPIO_GPIO_PIN26_WAKEUP_ENABLE_S 10 +#define GPIO_GPIO_PIN26_INT_TYPE 0x00000007 +#define GPIO_GPIO_PIN26_INT_TYPE_S 7 +#define GPIO_GPIO_PIN26_PAD_DRIVER (BIT(2)) +#define GPIO_GPIO_PIN26_PAD_DRIVER_S 2 + +#define GPIO_PIN27 (DR_REG_GPIO_BASE + 0x00f4) +#define GPIO_GPIO_PIN27_INT_ENA 0x0000001F +#define GPIO_GPIO_PIN27_INT_ENA_S 13 +#define GPIO_GPIO_PIN27_CONFIG 0x00000003 +#define GPIO_GPIO_PIN27_CONFIG_S 11 +#define GPIO_GPIO_PIN27_WAKEUP_ENABLE (BIT(10)) +#define GPIO_GPIO_PIN27_WAKEUP_ENABLE_S 10 +#define GPIO_GPIO_PIN27_INT_TYPE 0x00000007 +#define GPIO_GPIO_PIN27_INT_TYPE_S 7 +#define GPIO_GPIO_PIN27_PAD_DRIVER (BIT(2)) +#define GPIO_GPIO_PIN27_PAD_DRIVER_S 2 + +#define GPIO_PIN28 (DR_REG_GPIO_BASE + 0x00f8) +#define GPIO_GPIO_PIN28_INT_ENA 0x0000001F +#define GPIO_GPIO_PIN28_INT_ENA_S 13 +#define GPIO_GPIO_PIN28_CONFIG 0x00000003 +#define GPIO_GPIO_PIN28_CONFIG_S 11 +#define GPIO_GPIO_PIN28_WAKEUP_ENABLE (BIT(10)) +#define GPIO_GPIO_PIN28_WAKEUP_ENABLE_S 10 +#define GPIO_GPIO_PIN28_INT_TYPE 0x00000007 +#define GPIO_GPIO_PIN28_INT_TYPE_S 7 +#define GPIO_GPIO_PIN28_PAD_DRIVER (BIT(2)) +#define GPIO_GPIO_PIN28_PAD_DRIVER_S 2 + +#define GPIO_PIN29 (DR_REG_GPIO_BASE + 0x00fc) +#define GPIO_GPIO_PIN29_INT_ENA 0x0000001F +#define GPIO_GPIO_PIN29_INT_ENA_S 13 +#define GPIO_GPIO_PIN29_CONFIG 0x00000003 +#define GPIO_GPIO_PIN29_CONFIG_S 11 +#define GPIO_GPIO_PIN29_WAKEUP_ENABLE (BIT(10)) +#define GPIO_GPIO_PIN29_WAKEUP_ENABLE_S 10 +#define GPIO_GPIO_PIN29_INT_TYPE 0x00000007 +#define GPIO_GPIO_PIN29_INT_TYPE_S 7 +#define GPIO_GPIO_PIN29_PAD_DRIVER (BIT(2)) +#define GPIO_GPIO_PIN29_PAD_DRIVER_S 2 + +#define GPIO_PIN30 (DR_REG_GPIO_BASE + 0x0100) +#define GPIO_GPIO_PIN30_INT_ENA 0x0000001F +#define GPIO_GPIO_PIN30_INT_ENA_S 13 +#define GPIO_GPIO_PIN30_CONFIG 0x00000003 +#define GPIO_GPIO_PIN30_CONFIG_S 11 +#define GPIO_GPIO_PIN30_WAKEUP_ENABLE (BIT(10)) +#define GPIO_GPIO_PIN30_WAKEUP_ENABLE_S 10 +#define GPIO_GPIO_PIN30_INT_TYPE 0x00000007 +#define GPIO_GPIO_PIN30_INT_TYPE_S 7 +#define GPIO_GPIO_PIN30_PAD_DRIVER (BIT(2)) +#define GPIO_GPIO_PIN30_PAD_DRIVER_S 2 + +#define GPIO_PIN31 (DR_REG_GPIO_BASE + 0x0104) +#define GPIO_GPIO_PIN31_INT_ENA 0x0000001F +#define GPIO_GPIO_PIN31_INT_ENA_S 13 +#define GPIO_GPIO_PIN31_CONFIG 0x00000003 +#define GPIO_GPIO_PIN31_CONFIG_S 11 +#define GPIO_GPIO_PIN31_WAKEUP_ENABLE (BIT(10)) +#define GPIO_GPIO_PIN31_WAKEUP_ENABLE_S 10 +#define GPIO_GPIO_PIN31_INT_TYPE 0x00000007 +#define GPIO_GPIO_PIN31_INT_TYPE_S 7 +#define GPIO_GPIO_PIN31_PAD_DRIVER (BIT(2)) +#define GPIO_GPIO_PIN31_PAD_DRIVER_S 2 + +#define GPIO_PIN32 (DR_REG_GPIO_BASE + 0x0108) +#define GPIO_GPIO_PIN32_INT_ENA 0x0000001F +#define GPIO_GPIO_PIN32_INT_ENA_S 13 +#define GPIO_GPIO_PIN32_CONFIG 0x00000003 +#define GPIO_GPIO_PIN32_CONFIG_S 11 +#define GPIO_GPIO_PIN32_WAKEUP_ENABLE (BIT(10)) +#define GPIO_GPIO_PIN32_WAKEUP_ENABLE_S 10 +#define GPIO_GPIO_PIN32_INT_TYPE 0x00000007 +#define GPIO_GPIO_PIN32_INT_TYPE_S 7 +#define GPIO_GPIO_PIN32_PAD_DRIVER (BIT(2)) +#define GPIO_GPIO_PIN32_PAD_DRIVER_S 2 + +#define GPIO_PIN33 (DR_REG_GPIO_BASE + 0x010c) +#define GPIO_GPIO_PIN33_INT_ENA 0x0000001F +#define GPIO_GPIO_PIN33_INT_ENA_S 13 +#define GPIO_GPIO_PIN33_CONFIG 0x00000003 +#define GPIO_GPIO_PIN33_CONFIG_S 11 +#define GPIO_GPIO_PIN33_WAKEUP_ENABLE (BIT(10)) +#define GPIO_GPIO_PIN33_WAKEUP_ENABLE_S 10 +#define GPIO_GPIO_PIN33_INT_TYPE 0x00000007 +#define GPIO_GPIO_PIN33_INT_TYPE_S 7 +#define GPIO_GPIO_PIN33_PAD_DRIVER (BIT(2)) +#define GPIO_GPIO_PIN33_PAD_DRIVER_S 2 + +#define GPIO_PIN34 (DR_REG_GPIO_BASE + 0x0110) +#define GPIO_GPIO_PIN34_INT_ENA 0x0000001F +#define GPIO_GPIO_PIN34_INT_ENA_S 13 +#define GPIO_GPIO_PIN34_CONFIG 0x00000003 +#define GPIO_GPIO_PIN34_CONFIG_S 11 +#define GPIO_GPIO_PIN34_WAKEUP_ENABLE (BIT(10)) +#define GPIO_GPIO_PIN34_WAKEUP_ENABLE_S 10 +#define GPIO_GPIO_PIN34_INT_TYPE 0x00000007 +#define GPIO_GPIO_PIN34_INT_TYPE_S 7 +#define GPIO_GPIO_PIN34_PAD_DRIVER (BIT(2)) +#define GPIO_GPIO_PIN34_PAD_DRIVER_S 2 + +#define GPIO_PIN35 (DR_REG_GPIO_BASE + 0x0114) +#define GPIO_GPIO_PIN35_INT_ENA 0x0000001F +#define GPIO_GPIO_PIN35_INT_ENA_S 13 +#define GPIO_GPIO_PIN35_CONFIG 0x00000003 +#define GPIO_GPIO_PIN35_CONFIG_S 11 +#define GPIO_GPIO_PIN35_WAKEUP_ENABLE (BIT(10)) +#define GPIO_GPIO_PIN35_WAKEUP_ENABLE_S 10 +#define GPIO_GPIO_PIN35_INT_TYPE 0x00000007 +#define GPIO_GPIO_PIN35_INT_TYPE_S 7 +#define GPIO_GPIO_PIN35_PAD_DRIVER (BIT(2)) +#define GPIO_GPIO_PIN35_PAD_DRIVER_S 2 + +#define GPIO_PIN36 (DR_REG_GPIO_BASE + 0x0118) +#define GPIO_GPIO_PIN36_INT_ENA 0x0000001F +#define GPIO_GPIO_PIN36_INT_ENA_S 13 +#define GPIO_GPIO_PIN36_CONFIG 0x00000003 +#define GPIO_GPIO_PIN36_CONFIG_S 11 +#define GPIO_GPIO_PIN36_WAKEUP_ENABLE (BIT(10)) +#define GPIO_GPIO_PIN36_WAKEUP_ENABLE_S 10 +#define GPIO_GPIO_PIN36_INT_TYPE 0x00000007 +#define GPIO_GPIO_PIN36_INT_TYPE_S 7 +#define GPIO_GPIO_PIN36_PAD_DRIVER (BIT(2)) +#define GPIO_GPIO_PIN36_PAD_DRIVER_S 2 + +#define GPIO_PIN37 (DR_REG_GPIO_BASE + 0x011c) +#define GPIO_GPIO_PIN37_INT_ENA 0x0000001F +#define GPIO_GPIO_PIN37_INT_ENA_S 13 +#define GPIO_GPIO_PIN37_CONFIG 0x00000003 +#define GPIO_GPIO_PIN37_CONFIG_S 11 +#define GPIO_GPIO_PIN37_WAKEUP_ENABLE (BIT(10)) +#define GPIO_GPIO_PIN37_WAKEUP_ENABLE_S 10 +#define GPIO_GPIO_PIN37_INT_TYPE 0x00000007 +#define GPIO_GPIO_PIN37_INT_TYPE_S 7 +#define GPIO_GPIO_PIN37_PAD_DRIVER (BIT(2)) +#define GPIO_GPIO_PIN37_PAD_DRIVER_S 2 + +#define GPIO_PIN38 (DR_REG_GPIO_BASE + 0x0120) +#define GPIO_GPIO_PIN38_INT_ENA 0x0000001F +#define GPIO_GPIO_PIN38_INT_ENA_S 13 +#define GPIO_GPIO_PIN38_CONFIG 0x00000003 +#define GPIO_GPIO_PIN38_CONFIG_S 11 +#define GPIO_GPIO_PIN38_WAKEUP_ENABLE (BIT(10)) +#define GPIO_GPIO_PIN38_WAKEUP_ENABLE_S 10 +#define GPIO_GPIO_PIN38_INT_TYPE 0x00000007 +#define GPIO_GPIO_PIN38_INT_TYPE_S 7 +#define GPIO_GPIO_PIN38_PAD_DRIVER (BIT(2)) +#define GPIO_GPIO_PIN38_PAD_DRIVER_S 2 + +#define GPIO_PIN39 (DR_REG_GPIO_BASE + 0x0124) +#define GPIO_GPIO_PIN39_INT_ENA 0x0000001F +#define GPIO_GPIO_PIN39_INT_ENA_S 13 +#define GPIO_GPIO_PIN39_CONFIG 0x00000003 +#define GPIO_GPIO_PIN39_CONFIG_S 11 +#define GPIO_GPIO_PIN39_WAKEUP_ENABLE (BIT(10)) +#define GPIO_GPIO_PIN39_WAKEUP_ENABLE_S 10 +#define GPIO_GPIO_PIN39_INT_TYPE 0x00000007 +#define GPIO_GPIO_PIN39_INT_TYPE_S 7 +#define GPIO_GPIO_PIN39_PAD_DRIVER (BIT(2)) +#define GPIO_GPIO_PIN39_PAD_DRIVER_S 2 + +#define CALI_CONF (DR_REG_GPIO_BASE + 0x0128) +#define GPIO_CALI_START (BIT(31)) +#define GPIO_CALI_START_S 31 +#define GPIO_CALI_RTC_MAX 0x000003FF +#define GPIO_CALI_RTC_MAX_S 0 + +#define CALI_DATA (DR_REG_GPIO_BASE + 0x012c) +#define GPIO_CALI_RDY_SYNC2 (BIT(31)) +#define GPIO_CALI_RDY_SYNC2_S 31 +#define GPIO_CALI_RDY_REAL (BIT(30)) +#define GPIO_CALI_RDY_REAL_S 30 +#define GPIO_CALI_VALUE_SYNC2 0x000FFFFF +#define GPIO_CALI_VALUE_SYNC2_S 0 + +#define GPIO_FUNC0_IN_SEL_CFG (DR_REG_GPIO_BASE + 0x0130) +#define GPIO_GPIO_SIG0_IN_SEL (BIT(7)) +#define GPIO_GPIO_SIG0_IN_SEL_S 7 +#define GPIO_GPIO_FUNC0_IN_INV_SEL (BIT(6)) +#define GPIO_GPIO_FUNC0_IN_INV_SEL_S 6 +#define GPIO_GPIO_FUNC0_IN_SEL 0x0000003F +#define GPIO_GPIO_FUNC0_IN_SEL_S 0 + +#define GPIO_FUNC1_IN_SEL_CFG (DR_REG_GPIO_BASE + 0x0134) +#define GPIO_GPIO_SIG1_IN_SEL (BIT(7)) +#define GPIO_GPIO_SIG1_IN_SEL_S 7 +#define GPIO_GPIO_FUNC1_IN_INV_SEL (BIT(6)) +#define GPIO_GPIO_FUNC1_IN_INV_SEL_S 6 +#define GPIO_GPIO_FUNC1_IN_SEL 0x0000003F +#define GPIO_GPIO_FUNC1_IN_SEL_S 0 + +#define GPIO_FUNC2_IN_SEL_CFG (DR_REG_GPIO_BASE + 0x0138) +#define GPIO_GPIO_SIG2_IN_SEL (BIT(7)) +#define GPIO_GPIO_SIG2_IN_SEL_S 7 +#define GPIO_GPIO_FUNC2_IN_INV_SEL (BIT(6)) +#define GPIO_GPIO_FUNC2_IN_INV_SEL_S 6 +#define GPIO_GPIO_FUNC2_IN_SEL 0x0000003F +#define GPIO_GPIO_FUNC2_IN_SEL_S 0 + +#define GPIO_FUNC3_IN_SEL_CFG (DR_REG_GPIO_BASE + 0x013c) +#define GPIO_GPIO_SIG3_IN_SEL (BIT(7)) +#define GPIO_GPIO_SIG3_IN_SEL_S 7 +#define GPIO_GPIO_FUNC3_IN_INV_SEL (BIT(6)) +#define GPIO_GPIO_FUNC3_IN_INV_SEL_S 6 +#define GPIO_GPIO_FUNC3_IN_SEL 0x0000003F +#define GPIO_GPIO_FUNC3_IN_SEL_S 0 + +#define GPIO_FUNC4_IN_SEL_CFG (DR_REG_GPIO_BASE + 0x0140) +#define GPIO_GPIO_SIG4_IN_SEL (BIT(7)) +#define GPIO_GPIO_SIG4_IN_SEL_S 7 +#define GPIO_GPIO_FUNC4_IN_INV_SEL (BIT(6)) +#define GPIO_GPIO_FUNC4_IN_INV_SEL_S 6 +#define GPIO_GPIO_FUNC4_IN_SEL 0x0000003F +#define GPIO_GPIO_FUNC4_IN_SEL_S 0 + +#define GPIO_FUNC5_IN_SEL_CFG (DR_REG_GPIO_BASE + 0x0144) +#define GPIO_GPIO_SIG5_IN_SEL (BIT(7)) +#define GPIO_GPIO_SIG5_IN_SEL_S 7 +#define GPIO_GPIO_FUNC5_IN_INV_SEL (BIT(6)) +#define GPIO_GPIO_FUNC5_IN_INV_SEL_S 6 +#define GPIO_GPIO_FUNC5_IN_SEL 0x0000003F +#define GPIO_GPIO_FUNC5_IN_SEL_S 0 + +#define GPIO_FUNC6_IN_SEL_CFG (DR_REG_GPIO_BASE + 0x0148) +#define GPIO_GPIO_SIG6_IN_SEL (BIT(7)) +#define GPIO_GPIO_SIG6_IN_SEL_S 7 +#define GPIO_GPIO_FUNC6_IN_INV_SEL (BIT(6)) +#define GPIO_GPIO_FUNC6_IN_INV_SEL_S 6 +#define GPIO_GPIO_FUNC6_IN_SEL 0x0000003F +#define GPIO_GPIO_FUNC6_IN_SEL_S 0 + +#define GPIO_FUNC7_IN_SEL_CFG (DR_REG_GPIO_BASE + 0x014c) +#define GPIO_GPIO_SIG7_IN_SEL (BIT(7)) +#define GPIO_GPIO_SIG7_IN_SEL_S 7 +#define GPIO_GPIO_FUNC7_IN_INV_SEL (BIT(6)) +#define GPIO_GPIO_FUNC7_IN_INV_SEL_S 6 +#define GPIO_GPIO_FUNC7_IN_SEL 0x0000003F +#define GPIO_GPIO_FUNC7_IN_SEL_S 0 + +#define GPIO_FUNC8_IN_SEL_CFG (DR_REG_GPIO_BASE + 0x0150) +#define GPIO_GPIO_SIG8_IN_SEL (BIT(7)) +#define GPIO_GPIO_SIG8_IN_SEL_S 7 +#define GPIO_GPIO_FUNC8_IN_INV_SEL (BIT(6)) +#define GPIO_GPIO_FUNC8_IN_INV_SEL_S 6 +#define GPIO_GPIO_FUNC8_IN_SEL 0x0000003F +#define GPIO_GPIO_FUNC8_IN_SEL_S 0 + +#define GPIO_FUNC9_IN_SEL_CFG (DR_REG_GPIO_BASE + 0x0154) +#define GPIO_GPIO_SIG9_IN_SEL (BIT(7)) +#define GPIO_GPIO_SIG9_IN_SEL_S 7 +#define GPIO_GPIO_FUNC9_IN_INV_SEL (BIT(6)) +#define GPIO_GPIO_FUNC9_IN_INV_SEL_S 6 +#define GPIO_GPIO_FUNC9_IN_SEL 0x0000003F +#define GPIO_GPIO_FUNC9_IN_SEL_S 0 + +#define GPIO_FUNC10_IN_SEL_CFG (DR_REG_GPIO_BASE + 0x0158) +#define GPIO_GPIO_SIG10_IN_SEL (BIT(7)) +#define GPIO_GPIO_SIG10_IN_SEL_S 7 +#define GPIO_GPIO_FUNC10_IN_INV_SEL (BIT(6)) +#define GPIO_GPIO_FUNC10_IN_INV_SEL_S 6 +#define GPIO_GPIO_FUNC10_IN_SEL 0x0000003F +#define GPIO_GPIO_FUNC10_IN_SEL_S 0 + +#define GPIO_FUNC11_IN_SEL_CFG (DR_REG_GPIO_BASE + 0x015c) +#define GPIO_GPIO_SIG11_IN_SEL (BIT(7)) +#define GPIO_GPIO_SIG11_IN_SEL_S 7 +#define GPIO_GPIO_FUNC11_IN_INV_SEL (BIT(6)) +#define GPIO_GPIO_FUNC11_IN_INV_SEL_S 6 +#define GPIO_GPIO_FUNC11_IN_SEL 0x0000003F +#define GPIO_GPIO_FUNC11_IN_SEL_S 0 + +#define GPIO_FUNC12_IN_SEL_CFG (DR_REG_GPIO_BASE + 0x0160) +#define GPIO_GPIO_SIG12_IN_SEL (BIT(7)) +#define GPIO_GPIO_SIG12_IN_SEL_S 7 +#define GPIO_GPIO_FUNC12_IN_INV_SEL (BIT(6)) +#define GPIO_GPIO_FUNC12_IN_INV_SEL_S 6 +#define GPIO_GPIO_FUNC12_IN_SEL 0x0000003F +#define GPIO_GPIO_FUNC12_IN_SEL_S 0 + +#define GPIO_FUNC13_IN_SEL_CFG (DR_REG_GPIO_BASE + 0x0164) +#define GPIO_GPIO_SIG13_IN_SEL (BIT(7)) +#define GPIO_GPIO_SIG13_IN_SEL_S 7 +#define GPIO_GPIO_FUNC13_IN_INV_SEL (BIT(6)) +#define GPIO_GPIO_FUNC13_IN_INV_SEL_S 6 +#define GPIO_GPIO_FUNC13_IN_SEL 0x0000003F +#define GPIO_GPIO_FUNC13_IN_SEL_S 0 + +#define GPIO_FUNC14_IN_SEL_CFG (DR_REG_GPIO_BASE + 0x0168) +#define GPIO_GPIO_SIG14_IN_SEL (BIT(7)) +#define GPIO_GPIO_SIG14_IN_SEL_S 7 +#define GPIO_GPIO_FUNC14_IN_INV_SEL (BIT(6)) +#define GPIO_GPIO_FUNC14_IN_INV_SEL_S 6 +#define GPIO_GPIO_FUNC14_IN_SEL 0x0000003F +#define GPIO_GPIO_FUNC14_IN_SEL_S 0 + +#define GPIO_FUNC15_IN_SEL_CFG (DR_REG_GPIO_BASE + 0x016c) +#define GPIO_GPIO_SIG15_IN_SEL (BIT(7)) +#define GPIO_GPIO_SIG15_IN_SEL_S 7 +#define GPIO_GPIO_FUNC15_IN_INV_SEL (BIT(6)) +#define GPIO_GPIO_FUNC15_IN_INV_SEL_S 6 +#define GPIO_GPIO_FUNC15_IN_SEL 0x0000003F +#define GPIO_GPIO_FUNC15_IN_SEL_S 0 + +#define GPIO_FUNC16_IN_SEL_CFG (DR_REG_GPIO_BASE + 0x0170) +#define GPIO_GPIO_SIG16_IN_SEL (BIT(7)) +#define GPIO_GPIO_SIG16_IN_SEL_S 7 +#define GPIO_GPIO_FUNC16_IN_INV_SEL (BIT(6)) +#define GPIO_GPIO_FUNC16_IN_INV_SEL_S 6 +#define GPIO_GPIO_FUNC16_IN_SEL 0x0000003F +#define GPIO_GPIO_FUNC16_IN_SEL_S 0 + +#define GPIO_FUNC17_IN_SEL_CFG (DR_REG_GPIO_BASE + 0x0174) +#define GPIO_GPIO_SIG17_IN_SEL (BIT(7)) +#define GPIO_GPIO_SIG17_IN_SEL_S 7 +#define GPIO_GPIO_FUNC17_IN_INV_SEL (BIT(6)) +#define GPIO_GPIO_FUNC17_IN_INV_SEL_S 6 +#define GPIO_GPIO_FUNC17_IN_SEL 0x0000003F +#define GPIO_GPIO_FUNC17_IN_SEL_S 0 + +#define GPIO_FUNC18_IN_SEL_CFG (DR_REG_GPIO_BASE + 0x0178) +#define GPIO_GPIO_SIG18_IN_SEL (BIT(7)) +#define GPIO_GPIO_SIG18_IN_SEL_S 7 +#define GPIO_GPIO_FUNC18_IN_INV_SEL (BIT(6)) +#define GPIO_GPIO_FUNC18_IN_INV_SEL_S 6 +#define GPIO_GPIO_FUNC18_IN_SEL 0x0000003F +#define GPIO_GPIO_FUNC18_IN_SEL_S 0 + +#define GPIO_FUNC19_IN_SEL_CFG (DR_REG_GPIO_BASE + 0x017c) +#define GPIO_GPIO_SIG19_IN_SEL (BIT(7)) +#define GPIO_GPIO_SIG19_IN_SEL_S 7 +#define GPIO_GPIO_FUNC19_IN_INV_SEL (BIT(6)) +#define GPIO_GPIO_FUNC19_IN_INV_SEL_S 6 +#define GPIO_GPIO_FUNC19_IN_SEL 0x0000003F +#define GPIO_GPIO_FUNC19_IN_SEL_S 0 + +#define GPIO_FUNC20_IN_SEL_CFG (DR_REG_GPIO_BASE + 0x0180) +#define GPIO_GPIO_SIG20_IN_SEL (BIT(7)) +#define GPIO_GPIO_SIG20_IN_SEL_S 7 +#define GPIO_GPIO_FUNC20_IN_INV_SEL (BIT(6)) +#define GPIO_GPIO_FUNC20_IN_INV_SEL_S 6 +#define GPIO_GPIO_FUNC20_IN_SEL 0x0000003F +#define GPIO_GPIO_FUNC20_IN_SEL_S 0 + +#define GPIO_FUNC21_IN_SEL_CFG (DR_REG_GPIO_BASE + 0x0184) +#define GPIO_GPIO_SIG21_IN_SEL (BIT(7)) +#define GPIO_GPIO_SIG21_IN_SEL_S 7 +#define GPIO_GPIO_FUNC21_IN_INV_SEL (BIT(6)) +#define GPIO_GPIO_FUNC21_IN_INV_SEL_S 6 +#define GPIO_GPIO_FUNC21_IN_SEL 0x0000003F +#define GPIO_GPIO_FUNC21_IN_SEL_S 0 + +#define GPIO_FUNC22_IN_SEL_CFG (DR_REG_GPIO_BASE + 0x0188) +#define GPIO_GPIO_SIG22_IN_SEL (BIT(7)) +#define GPIO_GPIO_SIG22_IN_SEL_S 7 +#define GPIO_GPIO_FUNC22_IN_INV_SEL (BIT(6)) +#define GPIO_GPIO_FUNC22_IN_INV_SEL_S 6 +#define GPIO_GPIO_FUNC22_IN_SEL 0x0000003F +#define GPIO_GPIO_FUNC22_IN_SEL_S 0 + +#define GPIO_FUNC23_IN_SEL_CFG (DR_REG_GPIO_BASE + 0x018c) +#define GPIO_GPIO_SIG23_IN_SEL (BIT(7)) +#define GPIO_GPIO_SIG23_IN_SEL_S 7 +#define GPIO_GPIO_FUNC23_IN_INV_SEL (BIT(6)) +#define GPIO_GPIO_FUNC23_IN_INV_SEL_S 6 +#define GPIO_GPIO_FUNC23_IN_SEL 0x0000003F +#define GPIO_GPIO_FUNC23_IN_SEL_S 0 + +#define GPIO_FUNC24_IN_SEL_CFG (DR_REG_GPIO_BASE + 0x0190) +#define GPIO_GPIO_SIG24_IN_SEL (BIT(7)) +#define GPIO_GPIO_SIG24_IN_SEL_S 7 +#define GPIO_GPIO_FUNC24_IN_INV_SEL (BIT(6)) +#define GPIO_GPIO_FUNC24_IN_INV_SEL_S 6 +#define GPIO_GPIO_FUNC24_IN_SEL 0x0000003F +#define GPIO_GPIO_FUNC24_IN_SEL_S 0 + +#define GPIO_FUNC25_IN_SEL_CFG (DR_REG_GPIO_BASE + 0x0194) +#define GPIO_GPIO_SIG25_IN_SEL (BIT(7)) +#define GPIO_GPIO_SIG25_IN_SEL_S 7 +#define GPIO_GPIO_FUNC25_IN_INV_SEL (BIT(6)) +#define GPIO_GPIO_FUNC25_IN_INV_SEL_S 6 +#define GPIO_GPIO_FUNC25_IN_SEL 0x0000003F +#define GPIO_GPIO_FUNC25_IN_SEL_S 0 + +#define GPIO_FUNC26_IN_SEL_CFG (DR_REG_GPIO_BASE + 0x0198) +#define GPIO_GPIO_SIG26_IN_SEL (BIT(7)) +#define GPIO_GPIO_SIG26_IN_SEL_S 7 +#define GPIO_GPIO_FUNC26_IN_INV_SEL (BIT(6)) +#define GPIO_GPIO_FUNC26_IN_INV_SEL_S 6 +#define GPIO_GPIO_FUNC26_IN_SEL 0x0000003F +#define GPIO_GPIO_FUNC26_IN_SEL_S 0 + +#define GPIO_FUNC27_IN_SEL_CFG (DR_REG_GPIO_BASE + 0x019c) +#define GPIO_GPIO_SIG27_IN_SEL (BIT(7)) +#define GPIO_GPIO_SIG27_IN_SEL_S 7 +#define GPIO_GPIO_FUNC27_IN_INV_SEL (BIT(6)) +#define GPIO_GPIO_FUNC27_IN_INV_SEL_S 6 +#define GPIO_GPIO_FUNC27_IN_SEL 0x0000003F +#define GPIO_GPIO_FUNC27_IN_SEL_S 0 + +#define GPIO_FUNC28_IN_SEL_CFG (DR_REG_GPIO_BASE + 0x01a0) +#define GPIO_GPIO_SIG28_IN_SEL (BIT(7)) +#define GPIO_GPIO_SIG28_IN_SEL_S 7 +#define GPIO_GPIO_FUNC28_IN_INV_SEL (BIT(6)) +#define GPIO_GPIO_FUNC28_IN_INV_SEL_S 6 +#define GPIO_GPIO_FUNC28_IN_SEL 0x0000003F +#define GPIO_GPIO_FUNC28_IN_SEL_S 0 + +#define GPIO_FUNC29_IN_SEL_CFG (DR_REG_GPIO_BASE + 0x01a4) +#define GPIO_GPIO_SIG29_IN_SEL (BIT(7)) +#define GPIO_GPIO_SIG29_IN_SEL_S 7 +#define GPIO_GPIO_FUNC29_IN_INV_SEL (BIT(6)) +#define GPIO_GPIO_FUNC29_IN_INV_SEL_S 6 +#define GPIO_GPIO_FUNC29_IN_SEL 0x0000003F +#define GPIO_GPIO_FUNC29_IN_SEL_S 0 + +#define GPIO_FUNC30_IN_SEL_CFG (DR_REG_GPIO_BASE + 0x01a8) +#define GPIO_GPIO_SIG30_IN_SEL (BIT(7)) +#define GPIO_GPIO_SIG30_IN_SEL_S 7 +#define GPIO_GPIO_FUNC30_IN_INV_SEL (BIT(6)) +#define GPIO_GPIO_FUNC30_IN_INV_SEL_S 6 +#define GPIO_GPIO_FUNC30_IN_SEL 0x0000003F +#define GPIO_GPIO_FUNC30_IN_SEL_S 0 + +#define GPIO_FUNC31_IN_SEL_CFG (DR_REG_GPIO_BASE + 0x01ac) +#define GPIO_GPIO_SIG31_IN_SEL (BIT(7)) +#define GPIO_GPIO_SIG31_IN_SEL_S 7 +#define GPIO_GPIO_FUNC31_IN_INV_SEL (BIT(6)) +#define GPIO_GPIO_FUNC31_IN_INV_SEL_S 6 +#define GPIO_GPIO_FUNC31_IN_SEL 0x0000003F +#define GPIO_GPIO_FUNC31_IN_SEL_S 0 + +#define GPIO_FUNC32_IN_SEL_CFG (DR_REG_GPIO_BASE + 0x01b0) +#define GPIO_GPIO_SIG32_IN_SEL (BIT(7)) +#define GPIO_GPIO_SIG32_IN_SEL_S 7 +#define GPIO_GPIO_FUNC32_IN_INV_SEL (BIT(6)) +#define GPIO_GPIO_FUNC32_IN_INV_SEL_S 6 +#define GPIO_GPIO_FUNC32_IN_SEL 0x0000003F +#define GPIO_GPIO_FUNC32_IN_SEL_S 0 + +#define GPIO_FUNC33_IN_SEL_CFG (DR_REG_GPIO_BASE + 0x01b4) +#define GPIO_GPIO_SIG33_IN_SEL (BIT(7)) +#define GPIO_GPIO_SIG33_IN_SEL_S 7 +#define GPIO_GPIO_FUNC33_IN_INV_SEL (BIT(6)) +#define GPIO_GPIO_FUNC33_IN_INV_SEL_S 6 +#define GPIO_GPIO_FUNC33_IN_SEL 0x0000003F +#define GPIO_GPIO_FUNC33_IN_SEL_S 0 + +#define GPIO_FUNC34_IN_SEL_CFG (DR_REG_GPIO_BASE + 0x01b8) +#define GPIO_GPIO_SIG34_IN_SEL (BIT(7)) +#define GPIO_GPIO_SIG34_IN_SEL_S 7 +#define GPIO_GPIO_FUNC34_IN_INV_SEL (BIT(6)) +#define GPIO_GPIO_FUNC34_IN_INV_SEL_S 6 +#define GPIO_GPIO_FUNC34_IN_SEL 0x0000003F +#define GPIO_GPIO_FUNC34_IN_SEL_S 0 + +#define GPIO_FUNC35_IN_SEL_CFG (DR_REG_GPIO_BASE + 0x01bc) +#define GPIO_GPIO_SIG35_IN_SEL (BIT(7)) +#define GPIO_GPIO_SIG35_IN_SEL_S 7 +#define GPIO_GPIO_FUNC35_IN_INV_SEL (BIT(6)) +#define GPIO_GPIO_FUNC35_IN_INV_SEL_S 6 +#define GPIO_GPIO_FUNC35_IN_SEL 0x0000003F +#define GPIO_GPIO_FUNC35_IN_SEL_S 0 + +#define GPIO_FUNC36_IN_SEL_CFG (DR_REG_GPIO_BASE + 0x01c0) +#define GPIO_GPIO_SIG36_IN_SEL (BIT(7)) +#define GPIO_GPIO_SIG36_IN_SEL_S 7 +#define GPIO_GPIO_FUNC36_IN_INV_SEL (BIT(6)) +#define GPIO_GPIO_FUNC36_IN_INV_SEL_S 6 +#define GPIO_GPIO_FUNC36_IN_SEL 0x0000003F +#define GPIO_GPIO_FUNC36_IN_SEL_S 0 + +#define GPIO_FUNC37_IN_SEL_CFG (DR_REG_GPIO_BASE + 0x01c4) +#define GPIO_GPIO_SIG37_IN_SEL (BIT(7)) +#define GPIO_GPIO_SIG37_IN_SEL_S 7 +#define GPIO_GPIO_FUNC37_IN_INV_SEL (BIT(6)) +#define GPIO_GPIO_FUNC37_IN_INV_SEL_S 6 +#define GPIO_GPIO_FUNC37_IN_SEL 0x0000003F +#define GPIO_GPIO_FUNC37_IN_SEL_S 0 + +#define GPIO_FUNC38_IN_SEL_CFG (DR_REG_GPIO_BASE + 0x01c8) +#define GPIO_GPIO_SIG38_IN_SEL (BIT(7)) +#define GPIO_GPIO_SIG38_IN_SEL_S 7 +#define GPIO_GPIO_FUNC38_IN_INV_SEL (BIT(6)) +#define GPIO_GPIO_FUNC38_IN_INV_SEL_S 6 +#define GPIO_GPIO_FUNC38_IN_SEL 0x0000003F +#define GPIO_GPIO_FUNC38_IN_SEL_S 0 + +#define GPIO_FUNC39_IN_SEL_CFG (DR_REG_GPIO_BASE + 0x01cc) +#define GPIO_GPIO_SIG39_IN_SEL (BIT(7)) +#define GPIO_GPIO_SIG39_IN_SEL_S 7 +#define GPIO_GPIO_FUNC39_IN_INV_SEL (BIT(6)) +#define GPIO_GPIO_FUNC39_IN_INV_SEL_S 6 +#define GPIO_GPIO_FUNC39_IN_SEL 0x0000003F +#define GPIO_GPIO_FUNC39_IN_SEL_S 0 + +#define GPIO_FUNC40_IN_SEL_CFG (DR_REG_GPIO_BASE + 0x01d0) +#define GPIO_GPIO_SIG40_IN_SEL (BIT(7)) +#define GPIO_GPIO_SIG40_IN_SEL_S 7 +#define GPIO_GPIO_FUNC40_IN_INV_SEL (BIT(6)) +#define GPIO_GPIO_FUNC40_IN_INV_SEL_S 6 +#define GPIO_GPIO_FUNC40_IN_SEL 0x0000003F +#define GPIO_GPIO_FUNC40_IN_SEL_S 0 + +#define GPIO_FUNC41_IN_SEL_CFG (DR_REG_GPIO_BASE + 0x01d4) +#define GPIO_GPIO_SIG41_IN_SEL (BIT(7)) +#define GPIO_GPIO_SIG41_IN_SEL_S 7 +#define GPIO_GPIO_FUNC41_IN_INV_SEL (BIT(6)) +#define GPIO_GPIO_FUNC41_IN_INV_SEL_S 6 +#define GPIO_GPIO_FUNC41_IN_SEL 0x0000003F +#define GPIO_GPIO_FUNC41_IN_SEL_S 0 + +#define GPIO_FUNC42_IN_SEL_CFG (DR_REG_GPIO_BASE + 0x01d8) +#define GPIO_GPIO_SIG42_IN_SEL (BIT(7)) +#define GPIO_GPIO_SIG42_IN_SEL_S 7 +#define GPIO_GPIO_FUNC42_IN_INV_SEL (BIT(6)) +#define GPIO_GPIO_FUNC42_IN_INV_SEL_S 6 +#define GPIO_GPIO_FUNC42_IN_SEL 0x0000003F +#define GPIO_GPIO_FUNC42_IN_SEL_S 0 + +#define GPIO_FUNC43_IN_SEL_CFG (DR_REG_GPIO_BASE + 0x01dc) +#define GPIO_GPIO_SIG43_IN_SEL (BIT(7)) +#define GPIO_GPIO_SIG43_IN_SEL_S 7 +#define GPIO_GPIO_FUNC43_IN_INV_SEL (BIT(6)) +#define GPIO_GPIO_FUNC43_IN_INV_SEL_S 6 +#define GPIO_GPIO_FUNC43_IN_SEL 0x0000003F +#define GPIO_GPIO_FUNC43_IN_SEL_S 0 + +#define GPIO_FUNC44_IN_SEL_CFG (DR_REG_GPIO_BASE + 0x01e0) +#define GPIO_GPIO_SIG44_IN_SEL (BIT(7)) +#define GPIO_GPIO_SIG44_IN_SEL_S 7 +#define GPIO_GPIO_FUNC44_IN_INV_SEL (BIT(6)) +#define GPIO_GPIO_FUNC44_IN_INV_SEL_S 6 +#define GPIO_GPIO_FUNC44_IN_SEL 0x0000003F +#define GPIO_GPIO_FUNC44_IN_SEL_S 0 + +#define GPIO_FUNC45_IN_SEL_CFG (DR_REG_GPIO_BASE + 0x01e4) +#define GPIO_GPIO_SIG45_IN_SEL (BIT(7)) +#define GPIO_GPIO_SIG45_IN_SEL_S 7 +#define GPIO_GPIO_FUNC45_IN_INV_SEL (BIT(6)) +#define GPIO_GPIO_FUNC45_IN_INV_SEL_S 6 +#define GPIO_GPIO_FUNC45_IN_SEL 0x0000003F +#define GPIO_GPIO_FUNC45_IN_SEL_S 0 + +#define GPIO_FUNC46_IN_SEL_CFG (DR_REG_GPIO_BASE + 0x01e8) +#define GPIO_GPIO_SIG46_IN_SEL (BIT(7)) +#define GPIO_GPIO_SIG46_IN_SEL_S 7 +#define GPIO_GPIO_FUNC46_IN_INV_SEL (BIT(6)) +#define GPIO_GPIO_FUNC46_IN_INV_SEL_S 6 +#define GPIO_GPIO_FUNC46_IN_SEL 0x0000003F +#define GPIO_GPIO_FUNC46_IN_SEL_S 0 + +#define GPIO_FUNC47_IN_SEL_CFG (DR_REG_GPIO_BASE + 0x01ec) +#define GPIO_GPIO_SIG47_IN_SEL (BIT(7)) +#define GPIO_GPIO_SIG47_IN_SEL_S 7 +#define GPIO_GPIO_FUNC47_IN_INV_SEL (BIT(6)) +#define GPIO_GPIO_FUNC47_IN_INV_SEL_S 6 +#define GPIO_GPIO_FUNC47_IN_SEL 0x0000003F +#define GPIO_GPIO_FUNC47_IN_SEL_S 0 + +#define GPIO_FUNC48_IN_SEL_CFG (DR_REG_GPIO_BASE + 0x01f0) +#define GPIO_GPIO_SIG48_IN_SEL (BIT(7)) +#define GPIO_GPIO_SIG48_IN_SEL_S 7 +#define GPIO_GPIO_FUNC48_IN_INV_SEL (BIT(6)) +#define GPIO_GPIO_FUNC48_IN_INV_SEL_S 6 +#define GPIO_GPIO_FUNC48_IN_SEL 0x0000003F +#define GPIO_GPIO_FUNC48_IN_SEL_S 0 + +#define GPIO_FUNC49_IN_SEL_CFG (DR_REG_GPIO_BASE + 0x01f4) +#define GPIO_GPIO_SIG49_IN_SEL (BIT(7)) +#define GPIO_GPIO_SIG49_IN_SEL_S 7 +#define GPIO_GPIO_FUNC49_IN_INV_SEL (BIT(6)) +#define GPIO_GPIO_FUNC49_IN_INV_SEL_S 6 +#define GPIO_GPIO_FUNC49_IN_SEL 0x0000003F +#define GPIO_GPIO_FUNC49_IN_SEL_S 0 + +#define GPIO_FUNC50_IN_SEL_CFG (DR_REG_GPIO_BASE + 0x01f8) +#define GPIO_GPIO_SIG50_IN_SEL (BIT(7)) +#define GPIO_GPIO_SIG50_IN_SEL_S 7 +#define GPIO_GPIO_FUNC50_IN_INV_SEL (BIT(6)) +#define GPIO_GPIO_FUNC50_IN_INV_SEL_S 6 +#define GPIO_GPIO_FUNC50_IN_SEL 0x0000003F +#define GPIO_GPIO_FUNC50_IN_SEL_S 0 + +#define GPIO_FUNC51_IN_SEL_CFG (DR_REG_GPIO_BASE + 0x01fc) +#define GPIO_GPIO_SIG51_IN_SEL (BIT(7)) +#define GPIO_GPIO_SIG51_IN_SEL_S 7 +#define GPIO_GPIO_FUNC51_IN_INV_SEL (BIT(6)) +#define GPIO_GPIO_FUNC51_IN_INV_SEL_S 6 +#define GPIO_GPIO_FUNC51_IN_SEL 0x0000003F +#define GPIO_GPIO_FUNC51_IN_SEL_S 0 + +#define GPIO_FUNC52_IN_SEL_CFG (DR_REG_GPIO_BASE + 0x0200) +#define GPIO_GPIO_SIG52_IN_SEL (BIT(7)) +#define GPIO_GPIO_SIG52_IN_SEL_S 7 +#define GPIO_GPIO_FUNC52_IN_INV_SEL (BIT(6)) +#define GPIO_GPIO_FUNC52_IN_INV_SEL_S 6 +#define GPIO_GPIO_FUNC52_IN_SEL 0x0000003F +#define GPIO_GPIO_FUNC52_IN_SEL_S 0 + +#define GPIO_FUNC53_IN_SEL_CFG (DR_REG_GPIO_BASE + 0x0204) +#define GPIO_GPIO_SIG53_IN_SEL (BIT(7)) +#define GPIO_GPIO_SIG53_IN_SEL_S 7 +#define GPIO_GPIO_FUNC53_IN_INV_SEL (BIT(6)) +#define GPIO_GPIO_FUNC53_IN_INV_SEL_S 6 +#define GPIO_GPIO_FUNC53_IN_SEL 0x0000003F +#define GPIO_GPIO_FUNC53_IN_SEL_S 0 + +#define GPIO_FUNC54_IN_SEL_CFG (DR_REG_GPIO_BASE + 0x0208) +#define GPIO_GPIO_SIG54_IN_SEL (BIT(7)) +#define GPIO_GPIO_SIG54_IN_SEL_S 7 +#define GPIO_GPIO_FUNC54_IN_INV_SEL (BIT(6)) +#define GPIO_GPIO_FUNC54_IN_INV_SEL_S 6 +#define GPIO_GPIO_FUNC54_IN_SEL 0x0000003F +#define GPIO_GPIO_FUNC54_IN_SEL_S 0 + +#define GPIO_FUNC55_IN_SEL_CFG (DR_REG_GPIO_BASE + 0x020c) +#define GPIO_GPIO_SIG55_IN_SEL (BIT(7)) +#define GPIO_GPIO_SIG55_IN_SEL_S 7 +#define GPIO_GPIO_FUNC55_IN_INV_SEL (BIT(6)) +#define GPIO_GPIO_FUNC55_IN_INV_SEL_S 6 +#define GPIO_GPIO_FUNC55_IN_SEL 0x0000003F +#define GPIO_GPIO_FUNC55_IN_SEL_S 0 + +#define GPIO_FUNC56_IN_SEL_CFG (DR_REG_GPIO_BASE + 0x0210) +#define GPIO_GPIO_SIG56_IN_SEL (BIT(7)) +#define GPIO_GPIO_SIG56_IN_SEL_S 7 +#define GPIO_GPIO_FUNC56_IN_INV_SEL (BIT(6)) +#define GPIO_GPIO_FUNC56_IN_INV_SEL_S 6 +#define GPIO_GPIO_FUNC56_IN_SEL 0x0000003F +#define GPIO_GPIO_FUNC56_IN_SEL_S 0 + +#define GPIO_FUNC57_IN_SEL_CFG (DR_REG_GPIO_BASE + 0x0214) +#define GPIO_GPIO_SIG57_IN_SEL (BIT(7)) +#define GPIO_GPIO_SIG57_IN_SEL_S 7 +#define GPIO_GPIO_FUNC57_IN_INV_SEL (BIT(6)) +#define GPIO_GPIO_FUNC57_IN_INV_SEL_S 6 +#define GPIO_GPIO_FUNC57_IN_SEL 0x0000003F +#define GPIO_GPIO_FUNC57_IN_SEL_S 0 + +#define GPIO_FUNC58_IN_SEL_CFG (DR_REG_GPIO_BASE + 0x0218) +#define GPIO_GPIO_SIG58_IN_SEL (BIT(7)) +#define GPIO_GPIO_SIG58_IN_SEL_S 7 +#define GPIO_GPIO_FUNC58_IN_INV_SEL (BIT(6)) +#define GPIO_GPIO_FUNC58_IN_INV_SEL_S 6 +#define GPIO_GPIO_FUNC58_IN_SEL 0x0000003F +#define GPIO_GPIO_FUNC58_IN_SEL_S 0 + +#define GPIO_FUNC59_IN_SEL_CFG (DR_REG_GPIO_BASE + 0x021c) +#define GPIO_GPIO_SIG59_IN_SEL (BIT(7)) +#define GPIO_GPIO_SIG59_IN_SEL_S 7 +#define GPIO_GPIO_FUNC59_IN_INV_SEL (BIT(6)) +#define GPIO_GPIO_FUNC59_IN_INV_SEL_S 6 +#define GPIO_GPIO_FUNC59_IN_SEL 0x0000003F +#define GPIO_GPIO_FUNC59_IN_SEL_S 0 + +#define GPIO_FUNC60_IN_SEL_CFG (DR_REG_GPIO_BASE + 0x0220) +#define GPIO_GPIO_SIG60_IN_SEL (BIT(7)) +#define GPIO_GPIO_SIG60_IN_SEL_S 7 +#define GPIO_GPIO_FUNC60_IN_INV_SEL (BIT(6)) +#define GPIO_GPIO_FUNC60_IN_INV_SEL_S 6 +#define GPIO_GPIO_FUNC60_IN_SEL 0x0000003F +#define GPIO_GPIO_FUNC60_IN_SEL_S 0 + +#define GPIO_FUNC61_IN_SEL_CFG (DR_REG_GPIO_BASE + 0x0224) +#define GPIO_GPIO_SIG61_IN_SEL (BIT(7)) +#define GPIO_GPIO_SIG61_IN_SEL_S 7 +#define GPIO_GPIO_FUNC61_IN_INV_SEL (BIT(6)) +#define GPIO_GPIO_FUNC61_IN_INV_SEL_S 6 +#define GPIO_GPIO_FUNC61_IN_SEL 0x0000003F +#define GPIO_GPIO_FUNC61_IN_SEL_S 0 + +#define GPIO_FUNC62_IN_SEL_CFG (DR_REG_GPIO_BASE + 0x0228) +#define GPIO_GPIO_SIG62_IN_SEL (BIT(7)) +#define GPIO_GPIO_SIG62_IN_SEL_S 7 +#define GPIO_GPIO_FUNC62_IN_INV_SEL (BIT(6)) +#define GPIO_GPIO_FUNC62_IN_INV_SEL_S 6 +#define GPIO_GPIO_FUNC62_IN_SEL 0x0000003F +#define GPIO_GPIO_FUNC62_IN_SEL_S 0 + +#define GPIO_FUNC63_IN_SEL_CFG (DR_REG_GPIO_BASE + 0x022c) +#define GPIO_GPIO_SIG63_IN_SEL (BIT(7)) +#define GPIO_GPIO_SIG63_IN_SEL_S 7 +#define GPIO_GPIO_FUNC63_IN_INV_SEL (BIT(6)) +#define GPIO_GPIO_FUNC63_IN_INV_SEL_S 6 +#define GPIO_GPIO_FUNC63_IN_SEL 0x0000003F +#define GPIO_GPIO_FUNC63_IN_SEL_S 0 + +#define GPIO_FUNC64_IN_SEL_CFG (DR_REG_GPIO_BASE + 0x0230) +#define GPIO_GPIO_SIG64_IN_SEL (BIT(7)) +#define GPIO_GPIO_SIG64_IN_SEL_S 7 +#define GPIO_GPIO_FUNC64_IN_INV_SEL (BIT(6)) +#define GPIO_GPIO_FUNC64_IN_INV_SEL_S 6 +#define GPIO_GPIO_FUNC64_IN_SEL 0x0000003F +#define GPIO_GPIO_FUNC64_IN_SEL_S 0 + +#define GPIO_FUNC65_IN_SEL_CFG (DR_REG_GPIO_BASE + 0x0234) +#define GPIO_GPIO_SIG65_IN_SEL (BIT(7)) +#define GPIO_GPIO_SIG65_IN_SEL_S 7 +#define GPIO_GPIO_FUNC65_IN_INV_SEL (BIT(6)) +#define GPIO_GPIO_FUNC65_IN_INV_SEL_S 6 +#define GPIO_GPIO_FUNC65_IN_SEL 0x0000003F +#define GPIO_GPIO_FUNC65_IN_SEL_S 0 + +#define GPIO_FUNC66_IN_SEL_CFG (DR_REG_GPIO_BASE + 0x0238) +#define GPIO_GPIO_SIG66_IN_SEL (BIT(7)) +#define GPIO_GPIO_SIG66_IN_SEL_S 7 +#define GPIO_GPIO_FUNC66_IN_INV_SEL (BIT(6)) +#define GPIO_GPIO_FUNC66_IN_INV_SEL_S 6 +#define GPIO_GPIO_FUNC66_IN_SEL 0x0000003F +#define GPIO_GPIO_FUNC66_IN_SEL_S 0 + +#define GPIO_FUNC67_IN_SEL_CFG (DR_REG_GPIO_BASE + 0x023c) +#define GPIO_GPIO_SIG67_IN_SEL (BIT(7)) +#define GPIO_GPIO_SIG67_IN_SEL_S 7 +#define GPIO_GPIO_FUNC67_IN_INV_SEL (BIT(6)) +#define GPIO_GPIO_FUNC67_IN_INV_SEL_S 6 +#define GPIO_GPIO_FUNC67_IN_SEL 0x0000003F +#define GPIO_GPIO_FUNC67_IN_SEL_S 0 + +#define GPIO_FUNC68_IN_SEL_CFG (DR_REG_GPIO_BASE + 0x0240) +#define GPIO_GPIO_SIG68_IN_SEL (BIT(7)) +#define GPIO_GPIO_SIG68_IN_SEL_S 7 +#define GPIO_GPIO_FUNC68_IN_INV_SEL (BIT(6)) +#define GPIO_GPIO_FUNC68_IN_INV_SEL_S 6 +#define GPIO_GPIO_FUNC68_IN_SEL 0x0000003F +#define GPIO_GPIO_FUNC68_IN_SEL_S 0 + +#define GPIO_FUNC69_IN_SEL_CFG (DR_REG_GPIO_BASE + 0x0244) +#define GPIO_GPIO_SIG69_IN_SEL (BIT(7)) +#define GPIO_GPIO_SIG69_IN_SEL_S 7 +#define GPIO_GPIO_FUNC69_IN_INV_SEL (BIT(6)) +#define GPIO_GPIO_FUNC69_IN_INV_SEL_S 6 +#define GPIO_GPIO_FUNC69_IN_SEL 0x0000003F +#define GPIO_GPIO_FUNC69_IN_SEL_S 0 + +#define GPIO_FUNC70_IN_SEL_CFG (DR_REG_GPIO_BASE + 0x0248) +#define GPIO_GPIO_SIG70_IN_SEL (BIT(7)) +#define GPIO_GPIO_SIG70_IN_SEL_S 7 +#define GPIO_GPIO_FUNC70_IN_INV_SEL (BIT(6)) +#define GPIO_GPIO_FUNC70_IN_INV_SEL_S 6 +#define GPIO_GPIO_FUNC70_IN_SEL 0x0000003F +#define GPIO_GPIO_FUNC70_IN_SEL_S 0 + +#define GPIO_FUNC71_IN_SEL_CFG (DR_REG_GPIO_BASE + 0x024c) +#define GPIO_GPIO_SIG71_IN_SEL (BIT(7)) +#define GPIO_GPIO_SIG71_IN_SEL_S 7 +#define GPIO_GPIO_FUNC71_IN_INV_SEL (BIT(6)) +#define GPIO_GPIO_FUNC71_IN_INV_SEL_S 6 +#define GPIO_GPIO_FUNC71_IN_SEL 0x0000003F +#define GPIO_GPIO_FUNC71_IN_SEL_S 0 + +#define GPIO_FUNC72_IN_SEL_CFG (DR_REG_GPIO_BASE + 0x0250) +#define GPIO_GPIO_SIG72_IN_SEL (BIT(7)) +#define GPIO_GPIO_SIG72_IN_SEL_S 7 +#define GPIO_GPIO_FUNC72_IN_INV_SEL (BIT(6)) +#define GPIO_GPIO_FUNC72_IN_INV_SEL_S 6 +#define GPIO_GPIO_FUNC72_IN_SEL 0x0000003F +#define GPIO_GPIO_FUNC72_IN_SEL_S 0 + +#define GPIO_FUNC73_IN_SEL_CFG (DR_REG_GPIO_BASE + 0x0254) +#define GPIO_GPIO_SIG73_IN_SEL (BIT(7)) +#define GPIO_GPIO_SIG73_IN_SEL_S 7 +#define GPIO_GPIO_FUNC73_IN_INV_SEL (BIT(6)) +#define GPIO_GPIO_FUNC73_IN_INV_SEL_S 6 +#define GPIO_GPIO_FUNC73_IN_SEL 0x0000003F +#define GPIO_GPIO_FUNC73_IN_SEL_S 0 + +#define GPIO_FUNC74_IN_SEL_CFG (DR_REG_GPIO_BASE + 0x0258) +#define GPIO_GPIO_SIG74_IN_SEL (BIT(7)) +#define GPIO_GPIO_SIG74_IN_SEL_S 7 +#define GPIO_GPIO_FUNC74_IN_INV_SEL (BIT(6)) +#define GPIO_GPIO_FUNC74_IN_INV_SEL_S 6 +#define GPIO_GPIO_FUNC74_IN_SEL 0x0000003F +#define GPIO_GPIO_FUNC74_IN_SEL_S 0 + +#define GPIO_FUNC75_IN_SEL_CFG (DR_REG_GPIO_BASE + 0x025c) +#define GPIO_GPIO_SIG75_IN_SEL (BIT(7)) +#define GPIO_GPIO_SIG75_IN_SEL_S 7 +#define GPIO_GPIO_FUNC75_IN_INV_SEL (BIT(6)) +#define GPIO_GPIO_FUNC75_IN_INV_SEL_S 6 +#define GPIO_GPIO_FUNC75_IN_SEL 0x0000003F +#define GPIO_GPIO_FUNC75_IN_SEL_S 0 + +#define GPIO_FUNC76_IN_SEL_CFG (DR_REG_GPIO_BASE + 0x0260) +#define GPIO_GPIO_SIG76_IN_SEL (BIT(7)) +#define GPIO_GPIO_SIG76_IN_SEL_S 7 +#define GPIO_GPIO_FUNC76_IN_INV_SEL (BIT(6)) +#define GPIO_GPIO_FUNC76_IN_INV_SEL_S 6 +#define GPIO_GPIO_FUNC76_IN_SEL 0x0000003F +#define GPIO_GPIO_FUNC76_IN_SEL_S 0 + +#define GPIO_FUNC77_IN_SEL_CFG (DR_REG_GPIO_BASE + 0x0264) +#define GPIO_GPIO_SIG77_IN_SEL (BIT(7)) +#define GPIO_GPIO_SIG77_IN_SEL_S 7 +#define GPIO_GPIO_FUNC77_IN_INV_SEL (BIT(6)) +#define GPIO_GPIO_FUNC77_IN_INV_SEL_S 6 +#define GPIO_GPIO_FUNC77_IN_SEL 0x0000003F +#define GPIO_GPIO_FUNC77_IN_SEL_S 0 + +#define GPIO_FUNC78_IN_SEL_CFG (DR_REG_GPIO_BASE + 0x0268) +#define GPIO_GPIO_SIG78_IN_SEL (BIT(7)) +#define GPIO_GPIO_SIG78_IN_SEL_S 7 +#define GPIO_GPIO_FUNC78_IN_INV_SEL (BIT(6)) +#define GPIO_GPIO_FUNC78_IN_INV_SEL_S 6 +#define GPIO_GPIO_FUNC78_IN_SEL 0x0000003F +#define GPIO_GPIO_FUNC78_IN_SEL_S 0 + +#define GPIO_FUNC79_IN_SEL_CFG (DR_REG_GPIO_BASE + 0x026c) +#define GPIO_GPIO_SIG79_IN_SEL (BIT(7)) +#define GPIO_GPIO_SIG79_IN_SEL_S 7 +#define GPIO_GPIO_FUNC79_IN_INV_SEL (BIT(6)) +#define GPIO_GPIO_FUNC79_IN_INV_SEL_S 6 +#define GPIO_GPIO_FUNC79_IN_SEL 0x0000003F +#define GPIO_GPIO_FUNC79_IN_SEL_S 0 + +#define GPIO_FUNC80_IN_SEL_CFG (DR_REG_GPIO_BASE + 0x0270) +#define GPIO_GPIO_SIG80_IN_SEL (BIT(7)) +#define GPIO_GPIO_SIG80_IN_SEL_S 7 +#define GPIO_GPIO_FUNC80_IN_INV_SEL (BIT(6)) +#define GPIO_GPIO_FUNC80_IN_INV_SEL_S 6 +#define GPIO_GPIO_FUNC80_IN_SEL 0x0000003F +#define GPIO_GPIO_FUNC80_IN_SEL_S 0 + +#define GPIO_FUNC81_IN_SEL_CFG (DR_REG_GPIO_BASE + 0x0274) +#define GPIO_GPIO_SIG81_IN_SEL (BIT(7)) +#define GPIO_GPIO_SIG81_IN_SEL_S 7 +#define GPIO_GPIO_FUNC81_IN_INV_SEL (BIT(6)) +#define GPIO_GPIO_FUNC81_IN_INV_SEL_S 6 +#define GPIO_GPIO_FUNC81_IN_SEL 0x0000003F +#define GPIO_GPIO_FUNC81_IN_SEL_S 0 + +#define GPIO_FUNC82_IN_SEL_CFG (DR_REG_GPIO_BASE + 0x0278) +#define GPIO_GPIO_SIG82_IN_SEL (BIT(7)) +#define GPIO_GPIO_SIG82_IN_SEL_S 7 +#define GPIO_GPIO_FUNC82_IN_INV_SEL (BIT(6)) +#define GPIO_GPIO_FUNC82_IN_INV_SEL_S 6 +#define GPIO_GPIO_FUNC82_IN_SEL 0x0000003F +#define GPIO_GPIO_FUNC82_IN_SEL_S 0 + +#define GPIO_FUNC83_IN_SEL_CFG (DR_REG_GPIO_BASE + 0x027c) +#define GPIO_GPIO_SIG83_IN_SEL (BIT(7)) +#define GPIO_GPIO_SIG83_IN_SEL_S 7 +#define GPIO_GPIO_FUNC83_IN_INV_SEL (BIT(6)) +#define GPIO_GPIO_FUNC83_IN_INV_SEL_S 6 +#define GPIO_GPIO_FUNC83_IN_SEL 0x0000003F +#define GPIO_GPIO_FUNC83_IN_SEL_S 0 + +#define GPIO_FUNC84_IN_SEL_CFG (DR_REG_GPIO_BASE + 0x0280) +#define GPIO_GPIO_SIG84_IN_SEL (BIT(7)) +#define GPIO_GPIO_SIG84_IN_SEL_S 7 +#define GPIO_GPIO_FUNC84_IN_INV_SEL (BIT(6)) +#define GPIO_GPIO_FUNC84_IN_INV_SEL_S 6 +#define GPIO_GPIO_FUNC84_IN_SEL 0x0000003F +#define GPIO_GPIO_FUNC84_IN_SEL_S 0 + +#define GPIO_FUNC85_IN_SEL_CFG (DR_REG_GPIO_BASE + 0x0284) +#define GPIO_GPIO_SIG85_IN_SEL (BIT(7)) +#define GPIO_GPIO_SIG85_IN_SEL_S 7 +#define GPIO_GPIO_FUNC85_IN_INV_SEL (BIT(6)) +#define GPIO_GPIO_FUNC85_IN_INV_SEL_S 6 +#define GPIO_GPIO_FUNC85_IN_SEL 0x0000003F +#define GPIO_GPIO_FUNC85_IN_SEL_S 0 + +#define GPIO_FUNC86_IN_SEL_CFG (DR_REG_GPIO_BASE + 0x0288) +#define GPIO_GPIO_SIG86_IN_SEL (BIT(7)) +#define GPIO_GPIO_SIG86_IN_SEL_S 7 +#define GPIO_GPIO_FUNC86_IN_INV_SEL (BIT(6)) +#define GPIO_GPIO_FUNC86_IN_INV_SEL_S 6 +#define GPIO_GPIO_FUNC86_IN_SEL 0x0000003F +#define GPIO_GPIO_FUNC86_IN_SEL_S 0 + +#define GPIO_FUNC87_IN_SEL_CFG (DR_REG_GPIO_BASE + 0x028c) +#define GPIO_GPIO_SIG87_IN_SEL (BIT(7)) +#define GPIO_GPIO_SIG87_IN_SEL_S 7 +#define GPIO_GPIO_FUNC87_IN_INV_SEL (BIT(6)) +#define GPIO_GPIO_FUNC87_IN_INV_SEL_S 6 +#define GPIO_GPIO_FUNC87_IN_SEL 0x0000003F +#define GPIO_GPIO_FUNC87_IN_SEL_S 0 + +#define GPIO_FUNC88_IN_SEL_CFG (DR_REG_GPIO_BASE + 0x0290) +#define GPIO_GPIO_SIG88_IN_SEL (BIT(7)) +#define GPIO_GPIO_SIG88_IN_SEL_S 7 +#define GPIO_GPIO_FUNC88_IN_INV_SEL (BIT(6)) +#define GPIO_GPIO_FUNC88_IN_INV_SEL_S 6 +#define GPIO_GPIO_FUNC88_IN_SEL 0x0000003F +#define GPIO_GPIO_FUNC88_IN_SEL_S 0 + +#define GPIO_FUNC89_IN_SEL_CFG (DR_REG_GPIO_BASE + 0x0294) +#define GPIO_GPIO_SIG89_IN_SEL (BIT(7)) +#define GPIO_GPIO_SIG89_IN_SEL_S 7 +#define GPIO_GPIO_FUNC89_IN_INV_SEL (BIT(6)) +#define GPIO_GPIO_FUNC89_IN_INV_SEL_S 6 +#define GPIO_GPIO_FUNC89_IN_SEL 0x0000003F +#define GPIO_GPIO_FUNC89_IN_SEL_S 0 + +#define GPIO_FUNC90_IN_SEL_CFG (DR_REG_GPIO_BASE + 0x0298) +#define GPIO_GPIO_SIG90_IN_SEL (BIT(7)) +#define GPIO_GPIO_SIG90_IN_SEL_S 7 +#define GPIO_GPIO_FUNC90_IN_INV_SEL (BIT(6)) +#define GPIO_GPIO_FUNC90_IN_INV_SEL_S 6 +#define GPIO_GPIO_FUNC90_IN_SEL 0x0000003F +#define GPIO_GPIO_FUNC90_IN_SEL_S 0 + +#define GPIO_FUNC91_IN_SEL_CFG (DR_REG_GPIO_BASE + 0x029c) +#define GPIO_GPIO_SIG91_IN_SEL (BIT(7)) +#define GPIO_GPIO_SIG91_IN_SEL_S 7 +#define GPIO_GPIO_FUNC91_IN_INV_SEL (BIT(6)) +#define GPIO_GPIO_FUNC91_IN_INV_SEL_S 6 +#define GPIO_GPIO_FUNC91_IN_SEL 0x0000003F +#define GPIO_GPIO_FUNC91_IN_SEL_S 0 + +#define GPIO_FUNC92_IN_SEL_CFG (DR_REG_GPIO_BASE + 0x02a0) +#define GPIO_GPIO_SIG92_IN_SEL (BIT(7)) +#define GPIO_GPIO_SIG92_IN_SEL_S 7 +#define GPIO_GPIO_FUNC92_IN_INV_SEL (BIT(6)) +#define GPIO_GPIO_FUNC92_IN_INV_SEL_S 6 +#define GPIO_GPIO_FUNC92_IN_SEL 0x0000003F +#define GPIO_GPIO_FUNC92_IN_SEL_S 0 + +#define GPIO_FUNC93_IN_SEL_CFG (DR_REG_GPIO_BASE + 0x02a4) +#define GPIO_GPIO_SIG93_IN_SEL (BIT(7)) +#define GPIO_GPIO_SIG93_IN_SEL_S 7 +#define GPIO_GPIO_FUNC93_IN_INV_SEL (BIT(6)) +#define GPIO_GPIO_FUNC93_IN_INV_SEL_S 6 +#define GPIO_GPIO_FUNC93_IN_SEL 0x0000003F +#define GPIO_GPIO_FUNC93_IN_SEL_S 0 + +#define GPIO_FUNC94_IN_SEL_CFG (DR_REG_GPIO_BASE + 0x02a8) +#define GPIO_GPIO_SIG94_IN_SEL (BIT(7)) +#define GPIO_GPIO_SIG94_IN_SEL_S 7 +#define GPIO_GPIO_FUNC94_IN_INV_SEL (BIT(6)) +#define GPIO_GPIO_FUNC94_IN_INV_SEL_S 6 +#define GPIO_GPIO_FUNC94_IN_SEL 0x0000003F +#define GPIO_GPIO_FUNC94_IN_SEL_S 0 + +#define GPIO_FUNC95_IN_SEL_CFG (DR_REG_GPIO_BASE + 0x02ac) +#define GPIO_GPIO_SIG95_IN_SEL (BIT(7)) +#define GPIO_GPIO_SIG95_IN_SEL_S 7 +#define GPIO_GPIO_FUNC95_IN_INV_SEL (BIT(6)) +#define GPIO_GPIO_FUNC95_IN_INV_SEL_S 6 +#define GPIO_GPIO_FUNC95_IN_SEL 0x0000003F +#define GPIO_GPIO_FUNC95_IN_SEL_S 0 + +#define GPIO_FUNC96_IN_SEL_CFG (DR_REG_GPIO_BASE + 0x02b0) +#define GPIO_GPIO_SIG96_IN_SEL (BIT(7)) +#define GPIO_GPIO_SIG96_IN_SEL_S 7 +#define GPIO_GPIO_FUNC96_IN_INV_SEL (BIT(6)) +#define GPIO_GPIO_FUNC96_IN_INV_SEL_S 6 +#define GPIO_GPIO_FUNC96_IN_SEL 0x0000003F +#define GPIO_GPIO_FUNC96_IN_SEL_S 0 + +#define GPIO_FUNC97_IN_SEL_CFG (DR_REG_GPIO_BASE + 0x02b4) +#define GPIO_GPIO_SIG97_IN_SEL (BIT(7)) +#define GPIO_GPIO_SIG97_IN_SEL_S 7 +#define GPIO_GPIO_FUNC97_IN_INV_SEL (BIT(6)) +#define GPIO_GPIO_FUNC97_IN_INV_SEL_S 6 +#define GPIO_GPIO_FUNC97_IN_SEL 0x0000003F +#define GPIO_GPIO_FUNC97_IN_SEL_S 0 + +#define GPIO_FUNC98_IN_SEL_CFG (DR_REG_GPIO_BASE + 0x02b8) +#define GPIO_GPIO_SIG98_IN_SEL (BIT(7)) +#define GPIO_GPIO_SIG98_IN_SEL_S 7 +#define GPIO_GPIO_FUNC98_IN_INV_SEL (BIT(6)) +#define GPIO_GPIO_FUNC98_IN_INV_SEL_S 6 +#define GPIO_GPIO_FUNC98_IN_SEL 0x0000003F +#define GPIO_GPIO_FUNC98_IN_SEL_S 0 + +#define GPIO_FUNC99_IN_SEL_CFG (DR_REG_GPIO_BASE + 0x02bc) +#define GPIO_GPIO_SIG99_IN_SEL (BIT(7)) +#define GPIO_GPIO_SIG99_IN_SEL_S 7 +#define GPIO_GPIO_FUNC99_IN_INV_SEL (BIT(6)) +#define GPIO_GPIO_FUNC99_IN_INV_SEL_S 6 +#define GPIO_GPIO_FUNC99_IN_SEL 0x0000003F +#define GPIO_GPIO_FUNC99_IN_SEL_S 0 + +#define GPIO_FUNC100_IN_SEL_CFG (DR_REG_GPIO_BASE + 0x02c0) +#define GPIO_GPIO_SIG100_IN_SEL (BIT(7)) +#define GPIO_GPIO_SIG100_IN_SEL_S 7 +#define GPIO_GPIO_FUNC100_IN_INV_SEL (BIT(6)) +#define GPIO_GPIO_FUNC100_IN_INV_SEL_S 6 +#define GPIO_GPIO_FUNC100_IN_SEL 0x0000003F +#define GPIO_GPIO_FUNC100_IN_SEL_S 0 + +#define GPIO_FUNC101_IN_SEL_CFG (DR_REG_GPIO_BASE + 0x02c4) +#define GPIO_GPIO_SIG101_IN_SEL (BIT(7)) +#define GPIO_GPIO_SIG101_IN_SEL_S 7 +#define GPIO_GPIO_FUNC101_IN_INV_SEL (BIT(6)) +#define GPIO_GPIO_FUNC101_IN_INV_SEL_S 6 +#define GPIO_GPIO_FUNC101_IN_SEL 0x0000003F +#define GPIO_GPIO_FUNC101_IN_SEL_S 0 + +#define GPIO_FUNC102_IN_SEL_CFG (DR_REG_GPIO_BASE + 0x02c8) +#define GPIO_GPIO_SIG102_IN_SEL (BIT(7)) +#define GPIO_GPIO_SIG102_IN_SEL_S 7 +#define GPIO_GPIO_FUNC102_IN_INV_SEL (BIT(6)) +#define GPIO_GPIO_FUNC102_IN_INV_SEL_S 6 +#define GPIO_GPIO_FUNC102_IN_SEL 0x0000003F +#define GPIO_GPIO_FUNC102_IN_SEL_S 0 + +#define GPIO_FUNC103_IN_SEL_CFG (DR_REG_GPIO_BASE + 0x02cc) +#define GPIO_GPIO_SIG103_IN_SEL (BIT(7)) +#define GPIO_GPIO_SIG103_IN_SEL_S 7 +#define GPIO_GPIO_FUNC103_IN_INV_SEL (BIT(6)) +#define GPIO_GPIO_FUNC103_IN_INV_SEL_S 6 +#define GPIO_GPIO_FUNC103_IN_SEL 0x0000003F +#define GPIO_GPIO_FUNC103_IN_SEL_S 0 + +#define GPIO_FUNC104_IN_SEL_CFG (DR_REG_GPIO_BASE + 0x02d0) +#define GPIO_GPIO_SIG104_IN_SEL (BIT(7)) +#define GPIO_GPIO_SIG104_IN_SEL_S 7 +#define GPIO_GPIO_FUNC104_IN_INV_SEL (BIT(6)) +#define GPIO_GPIO_FUNC104_IN_INV_SEL_S 6 +#define GPIO_GPIO_FUNC104_IN_SEL 0x0000003F +#define GPIO_GPIO_FUNC104_IN_SEL_S 0 + +#define GPIO_FUNC105_IN_SEL_CFG (DR_REG_GPIO_BASE + 0x02d4) +#define GPIO_GPIO_SIG105_IN_SEL (BIT(7)) +#define GPIO_GPIO_SIG105_IN_SEL_S 7 +#define GPIO_GPIO_FUNC105_IN_INV_SEL (BIT(6)) +#define GPIO_GPIO_FUNC105_IN_INV_SEL_S 6 +#define GPIO_GPIO_FUNC105_IN_SEL 0x0000003F +#define GPIO_GPIO_FUNC105_IN_SEL_S 0 + +#define GPIO_FUNC106_IN_SEL_CFG (DR_REG_GPIO_BASE + 0x02d8) +#define GPIO_GPIO_SIG106_IN_SEL (BIT(7)) +#define GPIO_GPIO_SIG106_IN_SEL_S 7 +#define GPIO_GPIO_FUNC106_IN_INV_SEL (BIT(6)) +#define GPIO_GPIO_FUNC106_IN_INV_SEL_S 6 +#define GPIO_GPIO_FUNC106_IN_SEL 0x0000003F +#define GPIO_GPIO_FUNC106_IN_SEL_S 0 + +#define GPIO_FUNC107_IN_SEL_CFG (DR_REG_GPIO_BASE + 0x02dc) +#define GPIO_GPIO_SIG107_IN_SEL (BIT(7)) +#define GPIO_GPIO_SIG107_IN_SEL_S 7 +#define GPIO_GPIO_FUNC107_IN_INV_SEL (BIT(6)) +#define GPIO_GPIO_FUNC107_IN_INV_SEL_S 6 +#define GPIO_GPIO_FUNC107_IN_SEL 0x0000003F +#define GPIO_GPIO_FUNC107_IN_SEL_S 0 + +#define GPIO_FUNC108_IN_SEL_CFG (DR_REG_GPIO_BASE + 0x02e0) +#define GPIO_GPIO_SIG108_IN_SEL (BIT(7)) +#define GPIO_GPIO_SIG108_IN_SEL_S 7 +#define GPIO_GPIO_FUNC108_IN_INV_SEL (BIT(6)) +#define GPIO_GPIO_FUNC108_IN_INV_SEL_S 6 +#define GPIO_GPIO_FUNC108_IN_SEL 0x0000003F +#define GPIO_GPIO_FUNC108_IN_SEL_S 0 + +#define GPIO_FUNC109_IN_SEL_CFG (DR_REG_GPIO_BASE + 0x02e4) +#define GPIO_GPIO_SIG109_IN_SEL (BIT(7)) +#define GPIO_GPIO_SIG109_IN_SEL_S 7 +#define GPIO_GPIO_FUNC109_IN_INV_SEL (BIT(6)) +#define GPIO_GPIO_FUNC109_IN_INV_SEL_S 6 +#define GPIO_GPIO_FUNC109_IN_SEL 0x0000003F +#define GPIO_GPIO_FUNC109_IN_SEL_S 0 + +#define GPIO_FUNC110_IN_SEL_CFG (DR_REG_GPIO_BASE + 0x02e8) +#define GPIO_GPIO_SIG110_IN_SEL (BIT(7)) +#define GPIO_GPIO_SIG110_IN_SEL_S 7 +#define GPIO_GPIO_FUNC110_IN_INV_SEL (BIT(6)) +#define GPIO_GPIO_FUNC110_IN_INV_SEL_S 6 +#define GPIO_GPIO_FUNC110_IN_SEL 0x0000003F +#define GPIO_GPIO_FUNC110_IN_SEL_S 0 + +#define GPIO_FUNC111_IN_SEL_CFG (DR_REG_GPIO_BASE + 0x02ec) +#define GPIO_GPIO_SIG111_IN_SEL (BIT(7)) +#define GPIO_GPIO_SIG111_IN_SEL_S 7 +#define GPIO_GPIO_FUNC111_IN_INV_SEL (BIT(6)) +#define GPIO_GPIO_FUNC111_IN_INV_SEL_S 6 +#define GPIO_GPIO_FUNC111_IN_SEL 0x0000003F +#define GPIO_GPIO_FUNC111_IN_SEL_S 0 + +#define GPIO_FUNC112_IN_SEL_CFG (DR_REG_GPIO_BASE + 0x02f0) +#define GPIO_GPIO_SIG112_IN_SEL (BIT(7)) +#define GPIO_GPIO_SIG112_IN_SEL_S 7 +#define GPIO_GPIO_FUNC112_IN_INV_SEL (BIT(6)) +#define GPIO_GPIO_FUNC112_IN_INV_SEL_S 6 +#define GPIO_GPIO_FUNC112_IN_SEL 0x0000003F +#define GPIO_GPIO_FUNC112_IN_SEL_S 0 + +#define GPIO_FUNC113_IN_SEL_CFG (DR_REG_GPIO_BASE + 0x02f4) +#define GPIO_GPIO_SIG113_IN_SEL (BIT(7)) +#define GPIO_GPIO_SIG113_IN_SEL_S 7 +#define GPIO_GPIO_FUNC113_IN_INV_SEL (BIT(6)) +#define GPIO_GPIO_FUNC113_IN_INV_SEL_S 6 +#define GPIO_GPIO_FUNC113_IN_SEL 0x0000003F +#define GPIO_GPIO_FUNC113_IN_SEL_S 0 + +#define GPIO_FUNC114_IN_SEL_CFG (DR_REG_GPIO_BASE + 0x02f8) +#define GPIO_GPIO_SIG114_IN_SEL (BIT(7)) +#define GPIO_GPIO_SIG114_IN_SEL_S 7 +#define GPIO_GPIO_FUNC114_IN_INV_SEL (BIT(6)) +#define GPIO_GPIO_FUNC114_IN_INV_SEL_S 6 +#define GPIO_GPIO_FUNC114_IN_SEL 0x0000003F +#define GPIO_GPIO_FUNC114_IN_SEL_S 0 + +#define GPIO_FUNC115_IN_SEL_CFG (DR_REG_GPIO_BASE + 0x02fc) +#define GPIO_GPIO_SIG115_IN_SEL (BIT(7)) +#define GPIO_GPIO_SIG115_IN_SEL_S 7 +#define GPIO_GPIO_FUNC115_IN_INV_SEL (BIT(6)) +#define GPIO_GPIO_FUNC115_IN_INV_SEL_S 6 +#define GPIO_GPIO_FUNC115_IN_SEL 0x0000003F +#define GPIO_GPIO_FUNC115_IN_SEL_S 0 + +#define GPIO_FUNC116_IN_SEL_CFG (DR_REG_GPIO_BASE + 0x0300) +#define GPIO_GPIO_SIG116_IN_SEL (BIT(7)) +#define GPIO_GPIO_SIG116_IN_SEL_S 7 +#define GPIO_GPIO_FUNC116_IN_INV_SEL (BIT(6)) +#define GPIO_GPIO_FUNC116_IN_INV_SEL_S 6 +#define GPIO_GPIO_FUNC116_IN_SEL 0x0000003F +#define GPIO_GPIO_FUNC116_IN_SEL_S 0 + +#define GPIO_FUNC117_IN_SEL_CFG (DR_REG_GPIO_BASE + 0x0304) +#define GPIO_GPIO_SIG117_IN_SEL (BIT(7)) +#define GPIO_GPIO_SIG117_IN_SEL_S 7 +#define GPIO_GPIO_FUNC117_IN_INV_SEL (BIT(6)) +#define GPIO_GPIO_FUNC117_IN_INV_SEL_S 6 +#define GPIO_GPIO_FUNC117_IN_SEL 0x0000003F +#define GPIO_GPIO_FUNC117_IN_SEL_S 0 + +#define GPIO_FUNC118_IN_SEL_CFG (DR_REG_GPIO_BASE + 0x0308) +#define GPIO_GPIO_SIG118_IN_SEL (BIT(7)) +#define GPIO_GPIO_SIG118_IN_SEL_S 7 +#define GPIO_GPIO_FUNC118_IN_INV_SEL (BIT(6)) +#define GPIO_GPIO_FUNC118_IN_INV_SEL_S 6 +#define GPIO_GPIO_FUNC118_IN_SEL 0x0000003F +#define GPIO_GPIO_FUNC118_IN_SEL_S 0 + +#define GPIO_FUNC119_IN_SEL_CFG (DR_REG_GPIO_BASE + 0x030c) +#define GPIO_GPIO_SIG119_IN_SEL (BIT(7)) +#define GPIO_GPIO_SIG119_IN_SEL_S 7 +#define GPIO_GPIO_FUNC119_IN_INV_SEL (BIT(6)) +#define GPIO_GPIO_FUNC119_IN_INV_SEL_S 6 +#define GPIO_GPIO_FUNC119_IN_SEL 0x0000003F +#define GPIO_GPIO_FUNC119_IN_SEL_S 0 + +#define GPIO_FUNC120_IN_SEL_CFG (DR_REG_GPIO_BASE + 0x0310) +#define GPIO_GPIO_SIG120_IN_SEL (BIT(7)) +#define GPIO_GPIO_SIG120_IN_SEL_S 7 +#define GPIO_GPIO_FUNC120_IN_INV_SEL (BIT(6)) +#define GPIO_GPIO_FUNC120_IN_INV_SEL_S 6 +#define GPIO_GPIO_FUNC120_IN_SEL 0x0000003F +#define GPIO_GPIO_FUNC120_IN_SEL_S 0 + +#define GPIO_FUNC121_IN_SEL_CFG (DR_REG_GPIO_BASE + 0x0314) +#define GPIO_GPIO_SIG121_IN_SEL (BIT(7)) +#define GPIO_GPIO_SIG121_IN_SEL_S 7 +#define GPIO_GPIO_FUNC121_IN_INV_SEL (BIT(6)) +#define GPIO_GPIO_FUNC121_IN_INV_SEL_S 6 +#define GPIO_GPIO_FUNC121_IN_SEL 0x0000003F +#define GPIO_GPIO_FUNC121_IN_SEL_S 0 + +#define GPIO_FUNC122_IN_SEL_CFG (DR_REG_GPIO_BASE + 0x0318) +#define GPIO_GPIO_SIG122_IN_SEL (BIT(7)) +#define GPIO_GPIO_SIG122_IN_SEL_S 7 +#define GPIO_GPIO_FUNC122_IN_INV_SEL (BIT(6)) +#define GPIO_GPIO_FUNC122_IN_INV_SEL_S 6 +#define GPIO_GPIO_FUNC122_IN_SEL 0x0000003F +#define GPIO_GPIO_FUNC122_IN_SEL_S 0 + +#define GPIO_FUNC123_IN_SEL_CFG (DR_REG_GPIO_BASE + 0x031c) +#define GPIO_GPIO_SIG123_IN_SEL (BIT(7)) +#define GPIO_GPIO_SIG123_IN_SEL_S 7 +#define GPIO_GPIO_FUNC123_IN_INV_SEL (BIT(6)) +#define GPIO_GPIO_FUNC123_IN_INV_SEL_S 6 +#define GPIO_GPIO_FUNC123_IN_SEL 0x0000003F +#define GPIO_GPIO_FUNC123_IN_SEL_S 0 + +#define GPIO_FUNC124_IN_SEL_CFG (DR_REG_GPIO_BASE + 0x0320) +#define GPIO_GPIO_SIG124_IN_SEL (BIT(7)) +#define GPIO_GPIO_SIG124_IN_SEL_S 7 +#define GPIO_GPIO_FUNC124_IN_INV_SEL (BIT(6)) +#define GPIO_GPIO_FUNC124_IN_INV_SEL_S 6 +#define GPIO_GPIO_FUNC124_IN_SEL 0x0000003F +#define GPIO_GPIO_FUNC124_IN_SEL_S 0 + +#define GPIO_FUNC125_IN_SEL_CFG (DR_REG_GPIO_BASE + 0x0324) +#define GPIO_GPIO_SIG125_IN_SEL (BIT(7)) +#define GPIO_GPIO_SIG125_IN_SEL_S 7 +#define GPIO_GPIO_FUNC125_IN_INV_SEL (BIT(6)) +#define GPIO_GPIO_FUNC125_IN_INV_SEL_S 6 +#define GPIO_GPIO_FUNC125_IN_SEL 0x0000003F +#define GPIO_GPIO_FUNC125_IN_SEL_S 0 + +#define GPIO_FUNC126_IN_SEL_CFG (DR_REG_GPIO_BASE + 0x0328) +#define GPIO_GPIO_SIG126_IN_SEL (BIT(7)) +#define GPIO_GPIO_SIG126_IN_SEL_S 7 +#define GPIO_GPIO_FUNC126_IN_INV_SEL (BIT(6)) +#define GPIO_GPIO_FUNC126_IN_INV_SEL_S 6 +#define GPIO_GPIO_FUNC126_IN_SEL 0x0000003F +#define GPIO_GPIO_FUNC126_IN_SEL_S 0 + +#define GPIO_FUNC127_IN_SEL_CFG (DR_REG_GPIO_BASE + 0x032c) +#define GPIO_GPIO_SIG127_IN_SEL (BIT(7)) +#define GPIO_GPIO_SIG127_IN_SEL_S 7 +#define GPIO_GPIO_FUNC127_IN_INV_SEL (BIT(6)) +#define GPIO_GPIO_FUNC127_IN_INV_SEL_S 6 +#define GPIO_GPIO_FUNC127_IN_SEL 0x0000003F +#define GPIO_GPIO_FUNC127_IN_SEL_S 0 + +#define GPIO_FUNC128_IN_SEL_CFG (DR_REG_GPIO_BASE + 0x0330) +#define GPIO_GPIO_SIG128_IN_SEL (BIT(7)) +#define GPIO_GPIO_SIG128_IN_SEL_S 7 +#define GPIO_GPIO_FUNC128_IN_INV_SEL (BIT(6)) +#define GPIO_GPIO_FUNC128_IN_INV_SEL_S 6 +#define GPIO_GPIO_FUNC128_IN_SEL 0x0000003F +#define GPIO_GPIO_FUNC128_IN_SEL_S 0 + +#define GPIO_FUNC129_IN_SEL_CFG (DR_REG_GPIO_BASE + 0x0334) +#define GPIO_GPIO_SIG129_IN_SEL (BIT(7)) +#define GPIO_GPIO_SIG129_IN_SEL_S 7 +#define GPIO_GPIO_FUNC129_IN_INV_SEL (BIT(6)) +#define GPIO_GPIO_FUNC129_IN_INV_SEL_S 6 +#define GPIO_GPIO_FUNC129_IN_SEL 0x0000003F +#define GPIO_GPIO_FUNC129_IN_SEL_S 0 + +#define GPIO_FUNC130_IN_SEL_CFG (DR_REG_GPIO_BASE + 0x0338) +#define GPIO_GPIO_SIG130_IN_SEL (BIT(7)) +#define GPIO_GPIO_SIG130_IN_SEL_S 7 +#define GPIO_GPIO_FUNC130_IN_INV_SEL (BIT(6)) +#define GPIO_GPIO_FUNC130_IN_INV_SEL_S 6 +#define GPIO_GPIO_FUNC130_IN_SEL 0x0000003F +#define GPIO_GPIO_FUNC130_IN_SEL_S 0 + +#define GPIO_FUNC131_IN_SEL_CFG (DR_REG_GPIO_BASE + 0x033c) +#define GPIO_GPIO_SIG131_IN_SEL (BIT(7)) +#define GPIO_GPIO_SIG131_IN_SEL_S 7 +#define GPIO_GPIO_FUNC131_IN_INV_SEL (BIT(6)) +#define GPIO_GPIO_FUNC131_IN_INV_SEL_S 6 +#define GPIO_GPIO_FUNC131_IN_SEL 0x0000003F +#define GPIO_GPIO_FUNC131_IN_SEL_S 0 + +#define GPIO_FUNC132_IN_SEL_CFG (DR_REG_GPIO_BASE + 0x0340) +#define GPIO_GPIO_SIG132_IN_SEL (BIT(7)) +#define GPIO_GPIO_SIG132_IN_SEL_S 7 +#define GPIO_GPIO_FUNC132_IN_INV_SEL (BIT(6)) +#define GPIO_GPIO_FUNC132_IN_INV_SEL_S 6 +#define GPIO_GPIO_FUNC132_IN_SEL 0x0000003F +#define GPIO_GPIO_FUNC132_IN_SEL_S 0 + +#define GPIO_FUNC133_IN_SEL_CFG (DR_REG_GPIO_BASE + 0x0344) +#define GPIO_GPIO_SIG133_IN_SEL (BIT(7)) +#define GPIO_GPIO_SIG133_IN_SEL_S 7 +#define GPIO_GPIO_FUNC133_IN_INV_SEL (BIT(6)) +#define GPIO_GPIO_FUNC133_IN_INV_SEL_S 6 +#define GPIO_GPIO_FUNC133_IN_SEL 0x0000003F +#define GPIO_GPIO_FUNC133_IN_SEL_S 0 + +#define GPIO_FUNC134_IN_SEL_CFG (DR_REG_GPIO_BASE + 0x0348) +#define GPIO_GPIO_SIG134_IN_SEL (BIT(7)) +#define GPIO_GPIO_SIG134_IN_SEL_S 7 +#define GPIO_GPIO_FUNC134_IN_INV_SEL (BIT(6)) +#define GPIO_GPIO_FUNC134_IN_INV_SEL_S 6 +#define GPIO_GPIO_FUNC134_IN_SEL 0x0000003F +#define GPIO_GPIO_FUNC134_IN_SEL_S 0 + +#define GPIO_FUNC135_IN_SEL_CFG (DR_REG_GPIO_BASE + 0x034c) +#define GPIO_GPIO_SIG135_IN_SEL (BIT(7)) +#define GPIO_GPIO_SIG135_IN_SEL_S 7 +#define GPIO_GPIO_FUNC135_IN_INV_SEL (BIT(6)) +#define GPIO_GPIO_FUNC135_IN_INV_SEL_S 6 +#define GPIO_GPIO_FUNC135_IN_SEL 0x0000003F +#define GPIO_GPIO_FUNC135_IN_SEL_S 0 + +#define GPIO_FUNC136_IN_SEL_CFG (DR_REG_GPIO_BASE + 0x0350) +#define GPIO_GPIO_SIG136_IN_SEL (BIT(7)) +#define GPIO_GPIO_SIG136_IN_SEL_S 7 +#define GPIO_GPIO_FUNC136_IN_INV_SEL (BIT(6)) +#define GPIO_GPIO_FUNC136_IN_INV_SEL_S 6 +#define GPIO_GPIO_FUNC136_IN_SEL 0x0000003F +#define GPIO_GPIO_FUNC136_IN_SEL_S 0 + +#define GPIO_FUNC137_IN_SEL_CFG (DR_REG_GPIO_BASE + 0x0354) +#define GPIO_GPIO_SIG137_IN_SEL (BIT(7)) +#define GPIO_GPIO_SIG137_IN_SEL_S 7 +#define GPIO_GPIO_FUNC137_IN_INV_SEL (BIT(6)) +#define GPIO_GPIO_FUNC137_IN_INV_SEL_S 6 +#define GPIO_GPIO_FUNC137_IN_SEL 0x0000003F +#define GPIO_GPIO_FUNC137_IN_SEL_S 0 + +#define GPIO_FUNC138_IN_SEL_CFG (DR_REG_GPIO_BASE + 0x0358) +#define GPIO_GPIO_SIG138_IN_SEL (BIT(7)) +#define GPIO_GPIO_SIG138_IN_SEL_S 7 +#define GPIO_GPIO_FUNC138_IN_INV_SEL (BIT(6)) +#define GPIO_GPIO_FUNC138_IN_INV_SEL_S 6 +#define GPIO_GPIO_FUNC138_IN_SEL 0x0000003F +#define GPIO_GPIO_FUNC138_IN_SEL_S 0 + +#define GPIO_FUNC139_IN_SEL_CFG (DR_REG_GPIO_BASE + 0x035c) +#define GPIO_GPIO_SIG139_IN_SEL (BIT(7)) +#define GPIO_GPIO_SIG139_IN_SEL_S 7 +#define GPIO_GPIO_FUNC139_IN_INV_SEL (BIT(6)) +#define GPIO_GPIO_FUNC139_IN_INV_SEL_S 6 +#define GPIO_GPIO_FUNC139_IN_SEL 0x0000003F +#define GPIO_GPIO_FUNC139_IN_SEL_S 0 + +#define GPIO_FUNC140_IN_SEL_CFG (DR_REG_GPIO_BASE + 0x0360) +#define GPIO_GPIO_SIG140_IN_SEL (BIT(7)) +#define GPIO_GPIO_SIG140_IN_SEL_S 7 +#define GPIO_GPIO_FUNC140_IN_INV_SEL (BIT(6)) +#define GPIO_GPIO_FUNC140_IN_INV_SEL_S 6 +#define GPIO_GPIO_FUNC140_IN_SEL 0x0000003F +#define GPIO_GPIO_FUNC140_IN_SEL_S 0 + +#define GPIO_FUNC141_IN_SEL_CFG (DR_REG_GPIO_BASE + 0x0364) +#define GPIO_GPIO_SIG141_IN_SEL (BIT(7)) +#define GPIO_GPIO_SIG141_IN_SEL_S 7 +#define GPIO_GPIO_FUNC141_IN_INV_SEL (BIT(6)) +#define GPIO_GPIO_FUNC141_IN_INV_SEL_S 6 +#define GPIO_GPIO_FUNC141_IN_SEL 0x0000003F +#define GPIO_GPIO_FUNC141_IN_SEL_S 0 + +#define GPIO_FUNC142_IN_SEL_CFG (DR_REG_GPIO_BASE + 0x0368) +#define GPIO_GPIO_SIG142_IN_SEL (BIT(7)) +#define GPIO_GPIO_SIG142_IN_SEL_S 7 +#define GPIO_GPIO_FUNC142_IN_INV_SEL (BIT(6)) +#define GPIO_GPIO_FUNC142_IN_INV_SEL_S 6 +#define GPIO_GPIO_FUNC142_IN_SEL 0x0000003F +#define GPIO_GPIO_FUNC142_IN_SEL_S 0 + +#define GPIO_FUNC143_IN_SEL_CFG (DR_REG_GPIO_BASE + 0x036c) +#define GPIO_GPIO_SIG143_IN_SEL (BIT(7)) +#define GPIO_GPIO_SIG143_IN_SEL_S 7 +#define GPIO_GPIO_FUNC143_IN_INV_SEL (BIT(6)) +#define GPIO_GPIO_FUNC143_IN_INV_SEL_S 6 +#define GPIO_GPIO_FUNC143_IN_SEL 0x0000003F +#define GPIO_GPIO_FUNC143_IN_SEL_S 0 + +#define GPIO_FUNC144_IN_SEL_CFG (DR_REG_GPIO_BASE + 0x0370) +#define GPIO_GPIO_SIG144_IN_SEL (BIT(7)) +#define GPIO_GPIO_SIG144_IN_SEL_S 7 +#define GPIO_GPIO_FUNC144_IN_INV_SEL (BIT(6)) +#define GPIO_GPIO_FUNC144_IN_INV_SEL_S 6 +#define GPIO_GPIO_FUNC144_IN_SEL 0x0000003F +#define GPIO_GPIO_FUNC144_IN_SEL_S 0 + +#define GPIO_FUNC145_IN_SEL_CFG (DR_REG_GPIO_BASE + 0x0374) +#define GPIO_GPIO_SIG145_IN_SEL (BIT(7)) +#define GPIO_GPIO_SIG145_IN_SEL_S 7 +#define GPIO_GPIO_FUNC145_IN_INV_SEL (BIT(6)) +#define GPIO_GPIO_FUNC145_IN_INV_SEL_S 6 +#define GPIO_GPIO_FUNC145_IN_SEL 0x0000003F +#define GPIO_GPIO_FUNC145_IN_SEL_S 0 + +#define GPIO_FUNC146_IN_SEL_CFG (DR_REG_GPIO_BASE + 0x0378) +#define GPIO_GPIO_SIG146_IN_SEL (BIT(7)) +#define GPIO_GPIO_SIG146_IN_SEL_S 7 +#define GPIO_GPIO_FUNC146_IN_INV_SEL (BIT(6)) +#define GPIO_GPIO_FUNC146_IN_INV_SEL_S 6 +#define GPIO_GPIO_FUNC146_IN_SEL 0x0000003F +#define GPIO_GPIO_FUNC146_IN_SEL_S 0 + +#define GPIO_FUNC147_IN_SEL_CFG (DR_REG_GPIO_BASE + 0x037c) +#define GPIO_GPIO_SIG147_IN_SEL (BIT(7)) +#define GPIO_GPIO_SIG147_IN_SEL_S 7 +#define GPIO_GPIO_FUNC147_IN_INV_SEL (BIT(6)) +#define GPIO_GPIO_FUNC147_IN_INV_SEL_S 6 +#define GPIO_GPIO_FUNC147_IN_SEL 0x0000003F +#define GPIO_GPIO_FUNC147_IN_SEL_S 0 + +#define GPIO_FUNC148_IN_SEL_CFG (DR_REG_GPIO_BASE + 0x0380) +#define GPIO_GPIO_SIG148_IN_SEL (BIT(7)) +#define GPIO_GPIO_SIG148_IN_SEL_S 7 +#define GPIO_GPIO_FUNC148_IN_INV_SEL (BIT(6)) +#define GPIO_GPIO_FUNC148_IN_INV_SEL_S 6 +#define GPIO_GPIO_FUNC148_IN_SEL 0x0000003F +#define GPIO_GPIO_FUNC148_IN_SEL_S 0 + +#define GPIO_FUNC149_IN_SEL_CFG (DR_REG_GPIO_BASE + 0x0384) +#define GPIO_GPIO_SIG149_IN_SEL (BIT(7)) +#define GPIO_GPIO_SIG149_IN_SEL_S 7 +#define GPIO_GPIO_FUNC149_IN_INV_SEL (BIT(6)) +#define GPIO_GPIO_FUNC149_IN_INV_SEL_S 6 +#define GPIO_GPIO_FUNC149_IN_SEL 0x0000003F +#define GPIO_GPIO_FUNC149_IN_SEL_S 0 + +#define GPIO_FUNC150_IN_SEL_CFG (DR_REG_GPIO_BASE + 0x0388) +#define GPIO_GPIO_SIG150_IN_SEL (BIT(7)) +#define GPIO_GPIO_SIG150_IN_SEL_S 7 +#define GPIO_GPIO_FUNC150_IN_INV_SEL (BIT(6)) +#define GPIO_GPIO_FUNC150_IN_INV_SEL_S 6 +#define GPIO_GPIO_FUNC150_IN_SEL 0x0000003F +#define GPIO_GPIO_FUNC150_IN_SEL_S 0 + +#define GPIO_FUNC151_IN_SEL_CFG (DR_REG_GPIO_BASE + 0x038c) +#define GPIO_GPIO_SIG151_IN_SEL (BIT(7)) +#define GPIO_GPIO_SIG151_IN_SEL_S 7 +#define GPIO_GPIO_FUNC151_IN_INV_SEL (BIT(6)) +#define GPIO_GPIO_FUNC151_IN_INV_SEL_S 6 +#define GPIO_GPIO_FUNC151_IN_SEL 0x0000003F +#define GPIO_GPIO_FUNC151_IN_SEL_S 0 + +#define GPIO_FUNC152_IN_SEL_CFG (DR_REG_GPIO_BASE + 0x0390) +#define GPIO_GPIO_SIG152_IN_SEL (BIT(7)) +#define GPIO_GPIO_SIG152_IN_SEL_S 7 +#define GPIO_GPIO_FUNC152_IN_INV_SEL (BIT(6)) +#define GPIO_GPIO_FUNC152_IN_INV_SEL_S 6 +#define GPIO_GPIO_FUNC152_IN_SEL 0x0000003F +#define GPIO_GPIO_FUNC152_IN_SEL_S 0 + +#define GPIO_FUNC153_IN_SEL_CFG (DR_REG_GPIO_BASE + 0x0394) +#define GPIO_GPIO_SIG153_IN_SEL (BIT(7)) +#define GPIO_GPIO_SIG153_IN_SEL_S 7 +#define GPIO_GPIO_FUNC153_IN_INV_SEL (BIT(6)) +#define GPIO_GPIO_FUNC153_IN_INV_SEL_S 6 +#define GPIO_GPIO_FUNC153_IN_SEL 0x0000003F +#define GPIO_GPIO_FUNC153_IN_SEL_S 0 + +#define GPIO_FUNC154_IN_SEL_CFG (DR_REG_GPIO_BASE + 0x0398) +#define GPIO_GPIO_SIG154_IN_SEL (BIT(7)) +#define GPIO_GPIO_SIG154_IN_SEL_S 7 +#define GPIO_GPIO_FUNC154_IN_INV_SEL (BIT(6)) +#define GPIO_GPIO_FUNC154_IN_INV_SEL_S 6 +#define GPIO_GPIO_FUNC154_IN_SEL 0x0000003F +#define GPIO_GPIO_FUNC154_IN_SEL_S 0 + +#define GPIO_FUNC155_IN_SEL_CFG (DR_REG_GPIO_BASE + 0x039c) +#define GPIO_GPIO_SIG155_IN_SEL (BIT(7)) +#define GPIO_GPIO_SIG155_IN_SEL_S 7 +#define GPIO_GPIO_FUNC155_IN_INV_SEL (BIT(6)) +#define GPIO_GPIO_FUNC155_IN_INV_SEL_S 6 +#define GPIO_GPIO_FUNC155_IN_SEL 0x0000003F +#define GPIO_GPIO_FUNC155_IN_SEL_S 0 + +#define GPIO_FUNC156_IN_SEL_CFG (DR_REG_GPIO_BASE + 0x03a0) +#define GPIO_GPIO_SIG156_IN_SEL (BIT(7)) +#define GPIO_GPIO_SIG156_IN_SEL_S 7 +#define GPIO_GPIO_FUNC156_IN_INV_SEL (BIT(6)) +#define GPIO_GPIO_FUNC156_IN_INV_SEL_S 6 +#define GPIO_GPIO_FUNC156_IN_SEL 0x0000003F +#define GPIO_GPIO_FUNC156_IN_SEL_S 0 + +#define GPIO_FUNC157_IN_SEL_CFG (DR_REG_GPIO_BASE + 0x03a4) +#define GPIO_GPIO_SIG157_IN_SEL (BIT(7)) +#define GPIO_GPIO_SIG157_IN_SEL_S 7 +#define GPIO_GPIO_FUNC157_IN_INV_SEL (BIT(6)) +#define GPIO_GPIO_FUNC157_IN_INV_SEL_S 6 +#define GPIO_GPIO_FUNC157_IN_SEL 0x0000003F +#define GPIO_GPIO_FUNC157_IN_SEL_S 0 + +#define GPIO_FUNC158_IN_SEL_CFG (DR_REG_GPIO_BASE + 0x03a8) +#define GPIO_GPIO_SIG158_IN_SEL (BIT(7)) +#define GPIO_GPIO_SIG158_IN_SEL_S 7 +#define GPIO_GPIO_FUNC158_IN_INV_SEL (BIT(6)) +#define GPIO_GPIO_FUNC158_IN_INV_SEL_S 6 +#define GPIO_GPIO_FUNC158_IN_SEL 0x0000003F +#define GPIO_GPIO_FUNC158_IN_SEL_S 0 + +#define GPIO_FUNC159_IN_SEL_CFG (DR_REG_GPIO_BASE + 0x03ac) +#define GPIO_GPIO_SIG159_IN_SEL (BIT(7)) +#define GPIO_GPIO_SIG159_IN_SEL_S 7 +#define GPIO_GPIO_FUNC159_IN_INV_SEL (BIT(6)) +#define GPIO_GPIO_FUNC159_IN_INV_SEL_S 6 +#define GPIO_GPIO_FUNC159_IN_SEL 0x0000003F +#define GPIO_GPIO_FUNC159_IN_SEL_S 0 + +#define GPIO_FUNC160_IN_SEL_CFG (DR_REG_GPIO_BASE + 0x03b0) +#define GPIO_GPIO_SIG160_IN_SEL (BIT(7)) +#define GPIO_GPIO_SIG160_IN_SEL_S 7 +#define GPIO_GPIO_FUNC160_IN_INV_SEL (BIT(6)) +#define GPIO_GPIO_FUNC160_IN_INV_SEL_S 6 +#define GPIO_GPIO_FUNC160_IN_SEL 0x0000003F +#define GPIO_GPIO_FUNC160_IN_SEL_S 0 + +#define GPIO_FUNC161_IN_SEL_CFG (DR_REG_GPIO_BASE + 0x03b4) +#define GPIO_GPIO_SIG161_IN_SEL (BIT(7)) +#define GPIO_GPIO_SIG161_IN_SEL_S 7 +#define GPIO_GPIO_FUNC161_IN_INV_SEL (BIT(6)) +#define GPIO_GPIO_FUNC161_IN_INV_SEL_S 6 +#define GPIO_GPIO_FUNC161_IN_SEL 0x0000003F +#define GPIO_GPIO_FUNC161_IN_SEL_S 0 + +#define GPIO_FUNC162_IN_SEL_CFG (DR_REG_GPIO_BASE + 0x03b8) +#define GPIO_GPIO_SIG162_IN_SEL (BIT(7)) +#define GPIO_GPIO_SIG162_IN_SEL_S 7 +#define GPIO_GPIO_FUNC162_IN_INV_SEL (BIT(6)) +#define GPIO_GPIO_FUNC162_IN_INV_SEL_S 6 +#define GPIO_GPIO_FUNC162_IN_SEL 0x0000003F +#define GPIO_GPIO_FUNC162_IN_SEL_S 0 + +#define GPIO_FUNC163_IN_SEL_CFG (DR_REG_GPIO_BASE + 0x03bc) +#define GPIO_GPIO_SIG163_IN_SEL (BIT(7)) +#define GPIO_GPIO_SIG163_IN_SEL_S 7 +#define GPIO_GPIO_FUNC163_IN_INV_SEL (BIT(6)) +#define GPIO_GPIO_FUNC163_IN_INV_SEL_S 6 +#define GPIO_GPIO_FUNC163_IN_SEL 0x0000003F +#define GPIO_GPIO_FUNC163_IN_SEL_S 0 + +#define GPIO_FUNC164_IN_SEL_CFG (DR_REG_GPIO_BASE + 0x03c0) +#define GPIO_GPIO_SIG164_IN_SEL (BIT(7)) +#define GPIO_GPIO_SIG164_IN_SEL_S 7 +#define GPIO_GPIO_FUNC164_IN_INV_SEL (BIT(6)) +#define GPIO_GPIO_FUNC164_IN_INV_SEL_S 6 +#define GPIO_GPIO_FUNC164_IN_SEL 0x0000003F +#define GPIO_GPIO_FUNC164_IN_SEL_S 0 + +#define GPIO_FUNC165_IN_SEL_CFG (DR_REG_GPIO_BASE + 0x03c4) +#define GPIO_GPIO_SIG165_IN_SEL (BIT(7)) +#define GPIO_GPIO_SIG165_IN_SEL_S 7 +#define GPIO_GPIO_FUNC165_IN_INV_SEL (BIT(6)) +#define GPIO_GPIO_FUNC165_IN_INV_SEL_S 6 +#define GPIO_GPIO_FUNC165_IN_SEL 0x0000003F +#define GPIO_GPIO_FUNC165_IN_SEL_S 0 + +#define GPIO_FUNC166_IN_SEL_CFG (DR_REG_GPIO_BASE + 0x03c8) +#define GPIO_GPIO_SIG166_IN_SEL (BIT(7)) +#define GPIO_GPIO_SIG166_IN_SEL_S 7 +#define GPIO_GPIO_FUNC166_IN_INV_SEL (BIT(6)) +#define GPIO_GPIO_FUNC166_IN_INV_SEL_S 6 +#define GPIO_GPIO_FUNC166_IN_SEL 0x0000003F +#define GPIO_GPIO_FUNC166_IN_SEL_S 0 + +#define GPIO_FUNC167_IN_SEL_CFG (DR_REG_GPIO_BASE + 0x03cc) +#define GPIO_GPIO_SIG167_IN_SEL (BIT(7)) +#define GPIO_GPIO_SIG167_IN_SEL_S 7 +#define GPIO_GPIO_FUNC167_IN_INV_SEL (BIT(6)) +#define GPIO_GPIO_FUNC167_IN_INV_SEL_S 6 +#define GPIO_GPIO_FUNC167_IN_SEL 0x0000003F +#define GPIO_GPIO_FUNC167_IN_SEL_S 0 + +#define GPIO_FUNC168_IN_SEL_CFG (DR_REG_GPIO_BASE + 0x03d0) +#define GPIO_GPIO_SIG168_IN_SEL (BIT(7)) +#define GPIO_GPIO_SIG168_IN_SEL_S 7 +#define GPIO_GPIO_FUNC168_IN_INV_SEL (BIT(6)) +#define GPIO_GPIO_FUNC168_IN_INV_SEL_S 6 +#define GPIO_GPIO_FUNC168_IN_SEL 0x0000003F +#define GPIO_GPIO_FUNC168_IN_SEL_S 0 + +#define GPIO_FUNC169_IN_SEL_CFG (DR_REG_GPIO_BASE + 0x03d4) +#define GPIO_GPIO_SIG169_IN_SEL (BIT(7)) +#define GPIO_GPIO_SIG169_IN_SEL_S 7 +#define GPIO_GPIO_FUNC169_IN_INV_SEL (BIT(6)) +#define GPIO_GPIO_FUNC169_IN_INV_SEL_S 6 +#define GPIO_GPIO_FUNC169_IN_SEL 0x0000003F +#define GPIO_GPIO_FUNC169_IN_SEL_S 0 + +#define GPIO_FUNC170_IN_SEL_CFG (DR_REG_GPIO_BASE + 0x03d8) +#define GPIO_GPIO_SIG170_IN_SEL (BIT(7)) +#define GPIO_GPIO_SIG170_IN_SEL_S 7 +#define GPIO_GPIO_FUNC170_IN_INV_SEL (BIT(6)) +#define GPIO_GPIO_FUNC170_IN_INV_SEL_S 6 +#define GPIO_GPIO_FUNC170_IN_SEL 0x0000003F +#define GPIO_GPIO_FUNC170_IN_SEL_S 0 + +#define GPIO_FUNC171_IN_SEL_CFG (DR_REG_GPIO_BASE + 0x03dc) +#define GPIO_GPIO_SIG171_IN_SEL (BIT(7)) +#define GPIO_GPIO_SIG171_IN_SEL_S 7 +#define GPIO_GPIO_FUNC171_IN_INV_SEL (BIT(6)) +#define GPIO_GPIO_FUNC171_IN_INV_SEL_S 6 +#define GPIO_GPIO_FUNC171_IN_SEL 0x0000003F +#define GPIO_GPIO_FUNC171_IN_SEL_S 0 + +#define GPIO_FUNC172_IN_SEL_CFG (DR_REG_GPIO_BASE + 0x03e0) +#define GPIO_GPIO_SIG172_IN_SEL (BIT(7)) +#define GPIO_GPIO_SIG172_IN_SEL_S 7 +#define GPIO_GPIO_FUNC172_IN_INV_SEL (BIT(6)) +#define GPIO_GPIO_FUNC172_IN_INV_SEL_S 6 +#define GPIO_GPIO_FUNC172_IN_SEL 0x0000003F +#define GPIO_GPIO_FUNC172_IN_SEL_S 0 + +#define GPIO_FUNC173_IN_SEL_CFG (DR_REG_GPIO_BASE + 0x03e4) +#define GPIO_GPIO_SIG173_IN_SEL (BIT(7)) +#define GPIO_GPIO_SIG173_IN_SEL_S 7 +#define GPIO_GPIO_FUNC173_IN_INV_SEL (BIT(6)) +#define GPIO_GPIO_FUNC173_IN_INV_SEL_S 6 +#define GPIO_GPIO_FUNC173_IN_SEL 0x0000003F +#define GPIO_GPIO_FUNC173_IN_SEL_S 0 + +#define GPIO_FUNC174_IN_SEL_CFG (DR_REG_GPIO_BASE + 0x03e8) +#define GPIO_GPIO_SIG174_IN_SEL (BIT(7)) +#define GPIO_GPIO_SIG174_IN_SEL_S 7 +#define GPIO_GPIO_FUNC174_IN_INV_SEL (BIT(6)) +#define GPIO_GPIO_FUNC174_IN_INV_SEL_S 6 +#define GPIO_GPIO_FUNC174_IN_SEL 0x0000003F +#define GPIO_GPIO_FUNC174_IN_SEL_S 0 + +#define GPIO_FUNC175_IN_SEL_CFG (DR_REG_GPIO_BASE + 0x03ec) +#define GPIO_GPIO_SIG175_IN_SEL (BIT(7)) +#define GPIO_GPIO_SIG175_IN_SEL_S 7 +#define GPIO_GPIO_FUNC175_IN_INV_SEL (BIT(6)) +#define GPIO_GPIO_FUNC175_IN_INV_SEL_S 6 +#define GPIO_GPIO_FUNC175_IN_SEL 0x0000003F +#define GPIO_GPIO_FUNC175_IN_SEL_S 0 + +#define GPIO_FUNC176_IN_SEL_CFG (DR_REG_GPIO_BASE + 0x03f0) +#define GPIO_GPIO_SIG176_IN_SEL (BIT(7)) +#define GPIO_GPIO_SIG176_IN_SEL_S 7 +#define GPIO_GPIO_FUNC176_IN_INV_SEL (BIT(6)) +#define GPIO_GPIO_FUNC176_IN_INV_SEL_S 6 +#define GPIO_GPIO_FUNC176_IN_SEL 0x0000003F +#define GPIO_GPIO_FUNC176_IN_SEL_S 0 + +#define GPIO_FUNC177_IN_SEL_CFG (DR_REG_GPIO_BASE + 0x03f4) +#define GPIO_GPIO_SIG177_IN_SEL (BIT(7)) +#define GPIO_GPIO_SIG177_IN_SEL_S 7 +#define GPIO_GPIO_FUNC177_IN_INV_SEL (BIT(6)) +#define GPIO_GPIO_FUNC177_IN_INV_SEL_S 6 +#define GPIO_GPIO_FUNC177_IN_SEL 0x0000003F +#define GPIO_GPIO_FUNC177_IN_SEL_S 0 + +#define GPIO_FUNC178_IN_SEL_CFG (DR_REG_GPIO_BASE + 0x03f8) +#define GPIO_GPIO_SIG178_IN_SEL (BIT(7)) +#define GPIO_GPIO_SIG178_IN_SEL_S 7 +#define GPIO_GPIO_FUNC178_IN_INV_SEL (BIT(6)) +#define GPIO_GPIO_FUNC178_IN_INV_SEL_S 6 +#define GPIO_GPIO_FUNC178_IN_SEL 0x0000003F +#define GPIO_GPIO_FUNC178_IN_SEL_S 0 + +#define GPIO_FUNC179_IN_SEL_CFG (DR_REG_GPIO_BASE + 0x03fc) +#define GPIO_GPIO_SIG179_IN_SEL (BIT(7)) +#define GPIO_GPIO_SIG179_IN_SEL_S 7 +#define GPIO_GPIO_FUNC179_IN_INV_SEL (BIT(6)) +#define GPIO_GPIO_FUNC179_IN_INV_SEL_S 6 +#define GPIO_GPIO_FUNC179_IN_SEL 0x0000003F +#define GPIO_GPIO_FUNC179_IN_SEL_S 0 + +#define GPIO_FUNC180_IN_SEL_CFG (DR_REG_GPIO_BASE + 0x0400) +#define GPIO_GPIO_SIG180_IN_SEL (BIT(7)) +#define GPIO_GPIO_SIG180_IN_SEL_S 7 +#define GPIO_GPIO_FUNC180_IN_INV_SEL (BIT(6)) +#define GPIO_GPIO_FUNC180_IN_INV_SEL_S 6 +#define GPIO_GPIO_FUNC180_IN_SEL 0x0000003F +#define GPIO_GPIO_FUNC180_IN_SEL_S 0 + +#define GPIO_FUNC181_IN_SEL_CFG (DR_REG_GPIO_BASE + 0x0404) +#define GPIO_GPIO_SIG181_IN_SEL (BIT(7)) +#define GPIO_GPIO_SIG181_IN_SEL_S 7 +#define GPIO_GPIO_FUNC181_IN_INV_SEL (BIT(6)) +#define GPIO_GPIO_FUNC181_IN_INV_SEL_S 6 +#define GPIO_GPIO_FUNC181_IN_SEL 0x0000003F +#define GPIO_GPIO_FUNC181_IN_SEL_S 0 + +#define GPIO_FUNC182_IN_SEL_CFG (DR_REG_GPIO_BASE + 0x0408) +#define GPIO_GPIO_SIG182_IN_SEL (BIT(7)) +#define GPIO_GPIO_SIG182_IN_SEL_S 7 +#define GPIO_GPIO_FUNC182_IN_INV_SEL (BIT(6)) +#define GPIO_GPIO_FUNC182_IN_INV_SEL_S 6 +#define GPIO_GPIO_FUNC182_IN_SEL 0x0000003F +#define GPIO_GPIO_FUNC182_IN_SEL_S 0 + +#define GPIO_FUNC183_IN_SEL_CFG (DR_REG_GPIO_BASE + 0x040c) +#define GPIO_GPIO_SIG183_IN_SEL (BIT(7)) +#define GPIO_GPIO_SIG183_IN_SEL_S 7 +#define GPIO_GPIO_FUNC183_IN_INV_SEL (BIT(6)) +#define GPIO_GPIO_FUNC183_IN_INV_SEL_S 6 +#define GPIO_GPIO_FUNC183_IN_SEL 0x0000003F +#define GPIO_GPIO_FUNC183_IN_SEL_S 0 + +#define GPIO_FUNC184_IN_SEL_CFG (DR_REG_GPIO_BASE + 0x0410) +#define GPIO_GPIO_SIG184_IN_SEL (BIT(7)) +#define GPIO_GPIO_SIG184_IN_SEL_S 7 +#define GPIO_GPIO_FUNC184_IN_INV_SEL (BIT(6)) +#define GPIO_GPIO_FUNC184_IN_INV_SEL_S 6 +#define GPIO_GPIO_FUNC184_IN_SEL 0x0000003F +#define GPIO_GPIO_FUNC184_IN_SEL_S 0 + +#define GPIO_FUNC185_IN_SEL_CFG (DR_REG_GPIO_BASE + 0x0414) +#define GPIO_GPIO_SIG185_IN_SEL (BIT(7)) +#define GPIO_GPIO_SIG185_IN_SEL_S 7 +#define GPIO_GPIO_FUNC185_IN_INV_SEL (BIT(6)) +#define GPIO_GPIO_FUNC185_IN_INV_SEL_S 6 +#define GPIO_GPIO_FUNC185_IN_SEL 0x0000003F +#define GPIO_GPIO_FUNC185_IN_SEL_S 0 + +#define GPIO_FUNC186_IN_SEL_CFG (DR_REG_GPIO_BASE + 0x0418) +#define GPIO_GPIO_SIG186_IN_SEL (BIT(7)) +#define GPIO_GPIO_SIG186_IN_SEL_S 7 +#define GPIO_GPIO_FUNC186_IN_INV_SEL (BIT(6)) +#define GPIO_GPIO_FUNC186_IN_INV_SEL_S 6 +#define GPIO_GPIO_FUNC186_IN_SEL 0x0000003F +#define GPIO_GPIO_FUNC186_IN_SEL_S 0 + +#define GPIO_FUNC187_IN_SEL_CFG (DR_REG_GPIO_BASE + 0x041c) +#define GPIO_GPIO_SIG187_IN_SEL (BIT(7)) +#define GPIO_GPIO_SIG187_IN_SEL_S 7 +#define GPIO_GPIO_FUNC187_IN_INV_SEL (BIT(6)) +#define GPIO_GPIO_FUNC187_IN_INV_SEL_S 6 +#define GPIO_GPIO_FUNC187_IN_SEL 0x0000003F +#define GPIO_GPIO_FUNC187_IN_SEL_S 0 + +#define GPIO_FUNC188_IN_SEL_CFG (DR_REG_GPIO_BASE + 0x0420) +#define GPIO_GPIO_SIG188_IN_SEL (BIT(7)) +#define GPIO_GPIO_SIG188_IN_SEL_S 7 +#define GPIO_GPIO_FUNC188_IN_INV_SEL (BIT(6)) +#define GPIO_GPIO_FUNC188_IN_INV_SEL_S 6 +#define GPIO_GPIO_FUNC188_IN_SEL 0x0000003F +#define GPIO_GPIO_FUNC188_IN_SEL_S 0 + +#define GPIO_FUNC189_IN_SEL_CFG (DR_REG_GPIO_BASE + 0x0424) +#define GPIO_GPIO_SIG189_IN_SEL (BIT(7)) +#define GPIO_GPIO_SIG189_IN_SEL_S 7 +#define GPIO_GPIO_FUNC189_IN_INV_SEL (BIT(6)) +#define GPIO_GPIO_FUNC189_IN_INV_SEL_S 6 +#define GPIO_GPIO_FUNC189_IN_SEL 0x0000003F +#define GPIO_GPIO_FUNC189_IN_SEL_S 0 + +#define GPIO_FUNC190_IN_SEL_CFG (DR_REG_GPIO_BASE + 0x0428) +#define GPIO_GPIO_SIG190_IN_SEL (BIT(7)) +#define GPIO_GPIO_SIG190_IN_SEL_S 7 +#define GPIO_GPIO_FUNC190_IN_INV_SEL (BIT(6)) +#define GPIO_GPIO_FUNC190_IN_INV_SEL_S 6 +#define GPIO_GPIO_FUNC190_IN_SEL 0x0000003F +#define GPIO_GPIO_FUNC190_IN_SEL_S 0 + +#define GPIO_FUNC191_IN_SEL_CFG (DR_REG_GPIO_BASE + 0x042c) +#define GPIO_GPIO_SIG191_IN_SEL (BIT(7)) +#define GPIO_GPIO_SIG191_IN_SEL_S 7 +#define GPIO_GPIO_FUNC191_IN_INV_SEL (BIT(6)) +#define GPIO_GPIO_FUNC191_IN_INV_SEL_S 6 +#define GPIO_GPIO_FUNC191_IN_SEL 0x0000003F +#define GPIO_GPIO_FUNC191_IN_SEL_S 0 + +#define GPIO_FUNC192_IN_SEL_CFG (DR_REG_GPIO_BASE + 0x0430) +#define GPIO_GPIO_SIG192_IN_SEL (BIT(7)) +#define GPIO_GPIO_SIG192_IN_SEL_S 7 +#define GPIO_GPIO_FUNC192_IN_INV_SEL (BIT(6)) +#define GPIO_GPIO_FUNC192_IN_INV_SEL_S 6 +#define GPIO_GPIO_FUNC192_IN_SEL 0x0000003F +#define GPIO_GPIO_FUNC192_IN_SEL_S 0 + +#define GPIO_FUNC193_IN_SEL_CFG (DR_REG_GPIO_BASE + 0x0434) +#define GPIO_GPIO_SIG193_IN_SEL (BIT(7)) +#define GPIO_GPIO_SIG193_IN_SEL_S 7 +#define GPIO_GPIO_FUNC193_IN_INV_SEL (BIT(6)) +#define GPIO_GPIO_FUNC193_IN_INV_SEL_S 6 +#define GPIO_GPIO_FUNC193_IN_SEL 0x0000003F +#define GPIO_GPIO_FUNC193_IN_SEL_S 0 + +#define GPIO_FUNC194_IN_SEL_CFG (DR_REG_GPIO_BASE + 0x0438) +#define GPIO_GPIO_SIG194_IN_SEL (BIT(7)) +#define GPIO_GPIO_SIG194_IN_SEL_S 7 +#define GPIO_GPIO_FUNC194_IN_INV_SEL (BIT(6)) +#define GPIO_GPIO_FUNC194_IN_INV_SEL_S 6 +#define GPIO_GPIO_FUNC194_IN_SEL 0x0000003F +#define GPIO_GPIO_FUNC194_IN_SEL_S 0 + +#define GPIO_FUNC195_IN_SEL_CFG (DR_REG_GPIO_BASE + 0x043c) +#define GPIO_GPIO_SIG195_IN_SEL (BIT(7)) +#define GPIO_GPIO_SIG195_IN_SEL_S 7 +#define GPIO_GPIO_FUNC195_IN_INV_SEL (BIT(6)) +#define GPIO_GPIO_FUNC195_IN_INV_SEL_S 6 +#define GPIO_GPIO_FUNC195_IN_SEL 0x0000003F +#define GPIO_GPIO_FUNC195_IN_SEL_S 0 + +#define GPIO_FUNC196_IN_SEL_CFG (DR_REG_GPIO_BASE + 0x0440) +#define GPIO_GPIO_SIG196_IN_SEL (BIT(7)) +#define GPIO_GPIO_SIG196_IN_SEL_S 7 +#define GPIO_GPIO_FUNC196_IN_INV_SEL (BIT(6)) +#define GPIO_GPIO_FUNC196_IN_INV_SEL_S 6 +#define GPIO_GPIO_FUNC196_IN_SEL 0x0000003F +#define GPIO_GPIO_FUNC196_IN_SEL_S 0 + +#define GPIO_FUNC197_IN_SEL_CFG (DR_REG_GPIO_BASE + 0x0444) +#define GPIO_GPIO_SIG197_IN_SEL (BIT(7)) +#define GPIO_GPIO_SIG197_IN_SEL_S 7 +#define GPIO_GPIO_FUNC197_IN_INV_SEL (BIT(6)) +#define GPIO_GPIO_FUNC197_IN_INV_SEL_S 6 +#define GPIO_GPIO_FUNC197_IN_SEL 0x0000003F +#define GPIO_GPIO_FUNC197_IN_SEL_S 0 + +#define GPIO_FUNC198_IN_SEL_CFG (DR_REG_GPIO_BASE + 0x0448) +#define GPIO_GPIO_SIG198_IN_SEL (BIT(7)) +#define GPIO_GPIO_SIG198_IN_SEL_S 7 +#define GPIO_GPIO_FUNC198_IN_INV_SEL (BIT(6)) +#define GPIO_GPIO_FUNC198_IN_INV_SEL_S 6 +#define GPIO_GPIO_FUNC198_IN_SEL 0x0000003F +#define GPIO_GPIO_FUNC198_IN_SEL_S 0 + +#define GPIO_FUNC199_IN_SEL_CFG (DR_REG_GPIO_BASE + 0x044c) +#define GPIO_GPIO_SIG199_IN_SEL (BIT(7)) +#define GPIO_GPIO_SIG199_IN_SEL_S 7 +#define GPIO_GPIO_FUNC199_IN_INV_SEL (BIT(6)) +#define GPIO_GPIO_FUNC199_IN_INV_SEL_S 6 +#define GPIO_GPIO_FUNC199_IN_SEL 0x0000003F +#define GPIO_GPIO_FUNC199_IN_SEL_S 0 + +#define GPIO_FUNC200_IN_SEL_CFG (DR_REG_GPIO_BASE + 0x0450) +#define GPIO_GPIO_SIG200_IN_SEL (BIT(7)) +#define GPIO_GPIO_SIG200_IN_SEL_S 7 +#define GPIO_GPIO_FUNC200_IN_INV_SEL (BIT(6)) +#define GPIO_GPIO_FUNC200_IN_INV_SEL_S 6 +#define GPIO_GPIO_FUNC200_IN_SEL 0x0000003F +#define GPIO_GPIO_FUNC200_IN_SEL_S 0 + +#define GPIO_FUNC201_IN_SEL_CFG (DR_REG_GPIO_BASE + 0x0454) +#define GPIO_GPIO_SIG201_IN_SEL (BIT(7)) +#define GPIO_GPIO_SIG201_IN_SEL_S 7 +#define GPIO_GPIO_FUNC201_IN_INV_SEL (BIT(6)) +#define GPIO_GPIO_FUNC201_IN_INV_SEL_S 6 +#define GPIO_GPIO_FUNC201_IN_SEL 0x0000003F +#define GPIO_GPIO_FUNC201_IN_SEL_S 0 + +#define GPIO_FUNC202_IN_SEL_CFG (DR_REG_GPIO_BASE + 0x0458) +#define GPIO_GPIO_SIG202_IN_SEL (BIT(7)) +#define GPIO_GPIO_SIG202_IN_SEL_S 7 +#define GPIO_GPIO_FUNC202_IN_INV_SEL (BIT(6)) +#define GPIO_GPIO_FUNC202_IN_INV_SEL_S 6 +#define GPIO_GPIO_FUNC202_IN_SEL 0x0000003F +#define GPIO_GPIO_FUNC202_IN_SEL_S 0 + +#define GPIO_FUNC203_IN_SEL_CFG (DR_REG_GPIO_BASE + 0x045c) +#define GPIO_GPIO_SIG203_IN_SEL (BIT(7)) +#define GPIO_GPIO_SIG203_IN_SEL_S 7 +#define GPIO_GPIO_FUNC203_IN_INV_SEL (BIT(6)) +#define GPIO_GPIO_FUNC203_IN_INV_SEL_S 6 +#define GPIO_GPIO_FUNC203_IN_SEL 0x0000003F +#define GPIO_GPIO_FUNC203_IN_SEL_S 0 + +#define GPIO_FUNC204_IN_SEL_CFG (DR_REG_GPIO_BASE + 0x0460) +#define GPIO_GPIO_SIG204_IN_SEL (BIT(7)) +#define GPIO_GPIO_SIG204_IN_SEL_S 7 +#define GPIO_GPIO_FUNC204_IN_INV_SEL (BIT(6)) +#define GPIO_GPIO_FUNC204_IN_INV_SEL_S 6 +#define GPIO_GPIO_FUNC204_IN_SEL 0x0000003F +#define GPIO_GPIO_FUNC204_IN_SEL_S 0 + +#define GPIO_FUNC205_IN_SEL_CFG (DR_REG_GPIO_BASE + 0x0464) +#define GPIO_GPIO_SIG205_IN_SEL (BIT(7)) +#define GPIO_GPIO_SIG205_IN_SEL_S 7 +#define GPIO_GPIO_FUNC205_IN_INV_SEL (BIT(6)) +#define GPIO_GPIO_FUNC205_IN_INV_SEL_S 6 +#define GPIO_GPIO_FUNC205_IN_SEL 0x0000003F +#define GPIO_GPIO_FUNC205_IN_SEL_S 0 + +#define GPIO_FUNC206_IN_SEL_CFG (DR_REG_GPIO_BASE + 0x0468) +#define GPIO_GPIO_SIG206_IN_SEL (BIT(7)) +#define GPIO_GPIO_SIG206_IN_SEL_S 7 +#define GPIO_GPIO_FUNC206_IN_INV_SEL (BIT(6)) +#define GPIO_GPIO_FUNC206_IN_INV_SEL_S 6 +#define GPIO_GPIO_FUNC206_IN_SEL 0x0000003F +#define GPIO_GPIO_FUNC206_IN_SEL_S 0 + +#define GPIO_FUNC207_IN_SEL_CFG (DR_REG_GPIO_BASE + 0x046c) +#define GPIO_GPIO_SIG207_IN_SEL (BIT(7)) +#define GPIO_GPIO_SIG207_IN_SEL_S 7 +#define GPIO_GPIO_FUNC207_IN_INV_SEL (BIT(6)) +#define GPIO_GPIO_FUNC207_IN_INV_SEL_S 6 +#define GPIO_GPIO_FUNC207_IN_SEL 0x0000003F +#define GPIO_GPIO_FUNC207_IN_SEL_S 0 + +#define GPIO_FUNC208_IN_SEL_CFG (DR_REG_GPIO_BASE + 0x0470) +#define GPIO_GPIO_SIG208_IN_SEL (BIT(7)) +#define GPIO_GPIO_SIG208_IN_SEL_S 7 +#define GPIO_GPIO_FUNC208_IN_INV_SEL (BIT(6)) +#define GPIO_GPIO_FUNC208_IN_INV_SEL_S 6 +#define GPIO_GPIO_FUNC208_IN_SEL 0x0000003F +#define GPIO_GPIO_FUNC208_IN_SEL_S 0 + +#define GPIO_FUNC209_IN_SEL_CFG (DR_REG_GPIO_BASE + 0x0474) +#define GPIO_GPIO_SIG209_IN_SEL (BIT(7)) +#define GPIO_GPIO_SIG209_IN_SEL_S 7 +#define GPIO_GPIO_FUNC209_IN_INV_SEL (BIT(6)) +#define GPIO_GPIO_FUNC209_IN_INV_SEL_S 6 +#define GPIO_GPIO_FUNC209_IN_SEL 0x0000003F +#define GPIO_GPIO_FUNC209_IN_SEL_S 0 + +#define GPIO_FUNC210_IN_SEL_CFG (DR_REG_GPIO_BASE + 0x0478) +#define GPIO_GPIO_SIG210_IN_SEL (BIT(7)) +#define GPIO_GPIO_SIG210_IN_SEL_S 7 +#define GPIO_GPIO_FUNC210_IN_INV_SEL (BIT(6)) +#define GPIO_GPIO_FUNC210_IN_INV_SEL_S 6 +#define GPIO_GPIO_FUNC210_IN_SEL 0x0000003F +#define GPIO_GPIO_FUNC210_IN_SEL_S 0 + +#define GPIO_FUNC211_IN_SEL_CFG (DR_REG_GPIO_BASE + 0x047c) +#define GPIO_GPIO_SIG211_IN_SEL (BIT(7)) +#define GPIO_GPIO_SIG211_IN_SEL_S 7 +#define GPIO_GPIO_FUNC211_IN_INV_SEL (BIT(6)) +#define GPIO_GPIO_FUNC211_IN_INV_SEL_S 6 +#define GPIO_GPIO_FUNC211_IN_SEL 0x0000003F +#define GPIO_GPIO_FUNC211_IN_SEL_S 0 + +#define GPIO_FUNC212_IN_SEL_CFG (DR_REG_GPIO_BASE + 0x0480) +#define GPIO_GPIO_SIG212_IN_SEL (BIT(7)) +#define GPIO_GPIO_SIG212_IN_SEL_S 7 +#define GPIO_GPIO_FUNC212_IN_INV_SEL (BIT(6)) +#define GPIO_GPIO_FUNC212_IN_INV_SEL_S 6 +#define GPIO_GPIO_FUNC212_IN_SEL 0x0000003F +#define GPIO_GPIO_FUNC212_IN_SEL_S 0 + +#define GPIO_FUNC213_IN_SEL_CFG (DR_REG_GPIO_BASE + 0x0484) +#define GPIO_GPIO_SIG213_IN_SEL (BIT(7)) +#define GPIO_GPIO_SIG213_IN_SEL_S 7 +#define GPIO_GPIO_FUNC213_IN_INV_SEL (BIT(6)) +#define GPIO_GPIO_FUNC213_IN_INV_SEL_S 6 +#define GPIO_GPIO_FUNC213_IN_SEL 0x0000003F +#define GPIO_GPIO_FUNC213_IN_SEL_S 0 + +#define GPIO_FUNC214_IN_SEL_CFG (DR_REG_GPIO_BASE + 0x0488) +#define GPIO_GPIO_SIG214_IN_SEL (BIT(7)) +#define GPIO_GPIO_SIG214_IN_SEL_S 7 +#define GPIO_GPIO_FUNC214_IN_INV_SEL (BIT(6)) +#define GPIO_GPIO_FUNC214_IN_INV_SEL_S 6 +#define GPIO_GPIO_FUNC214_IN_SEL 0x0000003F +#define GPIO_GPIO_FUNC214_IN_SEL_S 0 + +#define GPIO_FUNC215_IN_SEL_CFG (DR_REG_GPIO_BASE + 0x048c) +#define GPIO_GPIO_SIG215_IN_SEL (BIT(7)) +#define GPIO_GPIO_SIG215_IN_SEL_S 7 +#define GPIO_GPIO_FUNC215_IN_INV_SEL (BIT(6)) +#define GPIO_GPIO_FUNC215_IN_INV_SEL_S 6 +#define GPIO_GPIO_FUNC215_IN_SEL 0x0000003F +#define GPIO_GPIO_FUNC215_IN_SEL_S 0 + +#define GPIO_FUNC216_IN_SEL_CFG (DR_REG_GPIO_BASE + 0x0490) +#define GPIO_GPIO_SIG216_IN_SEL (BIT(7)) +#define GPIO_GPIO_SIG216_IN_SEL_S 7 +#define GPIO_GPIO_FUNC216_IN_INV_SEL (BIT(6)) +#define GPIO_GPIO_FUNC216_IN_INV_SEL_S 6 +#define GPIO_GPIO_FUNC216_IN_SEL 0x0000003F +#define GPIO_GPIO_FUNC216_IN_SEL_S 0 + +#define GPIO_FUNC217_IN_SEL_CFG (DR_REG_GPIO_BASE + 0x0494) +#define GPIO_GPIO_SIG217_IN_SEL (BIT(7)) +#define GPIO_GPIO_SIG217_IN_SEL_S 7 +#define GPIO_GPIO_FUNC217_IN_INV_SEL (BIT(6)) +#define GPIO_GPIO_FUNC217_IN_INV_SEL_S 6 +#define GPIO_GPIO_FUNC217_IN_SEL 0x0000003F +#define GPIO_GPIO_FUNC217_IN_SEL_S 0 + +#define GPIO_FUNC218_IN_SEL_CFG (DR_REG_GPIO_BASE + 0x0498) +#define GPIO_GPIO_SIG218_IN_SEL (BIT(7)) +#define GPIO_GPIO_SIG218_IN_SEL_S 7 +#define GPIO_GPIO_FUNC218_IN_INV_SEL (BIT(6)) +#define GPIO_GPIO_FUNC218_IN_INV_SEL_S 6 +#define GPIO_GPIO_FUNC218_IN_SEL 0x0000003F +#define GPIO_GPIO_FUNC218_IN_SEL_S 0 + +#define GPIO_FUNC219_IN_SEL_CFG (DR_REG_GPIO_BASE + 0x049c) +#define GPIO_GPIO_SIG219_IN_SEL (BIT(7)) +#define GPIO_GPIO_SIG219_IN_SEL_S 7 +#define GPIO_GPIO_FUNC219_IN_INV_SEL (BIT(6)) +#define GPIO_GPIO_FUNC219_IN_INV_SEL_S 6 +#define GPIO_GPIO_FUNC219_IN_SEL 0x0000003F +#define GPIO_GPIO_FUNC219_IN_SEL_S 0 + +#define GPIO_FUNC220_IN_SEL_CFG (DR_REG_GPIO_BASE + 0x04a0) +#define GPIO_GPIO_SIG220_IN_SEL (BIT(7)) +#define GPIO_GPIO_SIG220_IN_SEL_S 7 +#define GPIO_GPIO_FUNC220_IN_INV_SEL (BIT(6)) +#define GPIO_GPIO_FUNC220_IN_INV_SEL_S 6 +#define GPIO_GPIO_FUNC220_IN_SEL 0x0000003F +#define GPIO_GPIO_FUNC220_IN_SEL_S 0 + +#define GPIO_FUNC221_IN_SEL_CFG (DR_REG_GPIO_BASE + 0x04a4) +#define GPIO_GPIO_SIG221_IN_SEL (BIT(7)) +#define GPIO_GPIO_SIG221_IN_SEL_S 7 +#define GPIO_GPIO_FUNC221_IN_INV_SEL (BIT(6)) +#define GPIO_GPIO_FUNC221_IN_INV_SEL_S 6 +#define GPIO_GPIO_FUNC221_IN_SEL 0x0000003F +#define GPIO_GPIO_FUNC221_IN_SEL_S 0 + +#define GPIO_FUNC222_IN_SEL_CFG (DR_REG_GPIO_BASE + 0x04a8) +#define GPIO_GPIO_SIG222_IN_SEL (BIT(7)) +#define GPIO_GPIO_SIG222_IN_SEL_S 7 +#define GPIO_GPIO_FUNC222_IN_INV_SEL (BIT(6)) +#define GPIO_GPIO_FUNC222_IN_INV_SEL_S 6 +#define GPIO_GPIO_FUNC222_IN_SEL 0x0000003F +#define GPIO_GPIO_FUNC222_IN_SEL_S 0 + +#define GPIO_FUNC223_IN_SEL_CFG (DR_REG_GPIO_BASE + 0x04ac) +#define GPIO_GPIO_SIG223_IN_SEL (BIT(7)) +#define GPIO_GPIO_SIG223_IN_SEL_S 7 +#define GPIO_GPIO_FUNC223_IN_INV_SEL (BIT(6)) +#define GPIO_GPIO_FUNC223_IN_INV_SEL_S 6 +#define GPIO_GPIO_FUNC223_IN_SEL 0x0000003F +#define GPIO_GPIO_FUNC223_IN_SEL_S 0 + +#define GPIO_FUNC224_IN_SEL_CFG (DR_REG_GPIO_BASE + 0x04b0) +#define GPIO_GPIO_SIG224_IN_SEL (BIT(7)) +#define GPIO_GPIO_SIG224_IN_SEL_S 7 +#define GPIO_GPIO_FUNC224_IN_INV_SEL (BIT(6)) +#define GPIO_GPIO_FUNC224_IN_INV_SEL_S 6 +#define GPIO_GPIO_FUNC224_IN_SEL 0x0000003F +#define GPIO_GPIO_FUNC224_IN_SEL_S 0 + +#define GPIO_FUNC225_IN_SEL_CFG (DR_REG_GPIO_BASE + 0x04b4) +#define GPIO_GPIO_SIG225_IN_SEL (BIT(7)) +#define GPIO_GPIO_SIG225_IN_SEL_S 7 +#define GPIO_GPIO_FUNC225_IN_INV_SEL (BIT(6)) +#define GPIO_GPIO_FUNC225_IN_INV_SEL_S 6 +#define GPIO_GPIO_FUNC225_IN_SEL 0x0000003F +#define GPIO_GPIO_FUNC225_IN_SEL_S 0 + +#define GPIO_FUNC226_IN_SEL_CFG (DR_REG_GPIO_BASE + 0x04b8) +#define GPIO_GPIO_SIG226_IN_SEL (BIT(7)) +#define GPIO_GPIO_SIG226_IN_SEL_S 7 +#define GPIO_GPIO_FUNC226_IN_INV_SEL (BIT(6)) +#define GPIO_GPIO_FUNC226_IN_INV_SEL_S 6 +#define GPIO_GPIO_FUNC226_IN_SEL 0x0000003F +#define GPIO_GPIO_FUNC226_IN_SEL_S 0 + +#define GPIO_FUNC227_IN_SEL_CFG (DR_REG_GPIO_BASE + 0x04bc) +#define GPIO_GPIO_SIG227_IN_SEL (BIT(7)) +#define GPIO_GPIO_SIG227_IN_SEL_S 7 +#define GPIO_GPIO_FUNC227_IN_INV_SEL (BIT(6)) +#define GPIO_GPIO_FUNC227_IN_INV_SEL_S 6 +#define GPIO_GPIO_FUNC227_IN_SEL 0x0000003F +#define GPIO_GPIO_FUNC227_IN_SEL_S 0 + +#define GPIO_FUNC228_IN_SEL_CFG (DR_REG_GPIO_BASE + 0x04c0) +#define GPIO_GPIO_SIG228_IN_SEL (BIT(7)) +#define GPIO_GPIO_SIG228_IN_SEL_S 7 +#define GPIO_GPIO_FUNC228_IN_INV_SEL (BIT(6)) +#define GPIO_GPIO_FUNC228_IN_INV_SEL_S 6 +#define GPIO_GPIO_FUNC228_IN_SEL 0x0000003F +#define GPIO_GPIO_FUNC228_IN_SEL_S 0 + +#define GPIO_FUNC229_IN_SEL_CFG (DR_REG_GPIO_BASE + 0x04c4) +#define GPIO_GPIO_SIG229_IN_SEL (BIT(7)) +#define GPIO_GPIO_SIG229_IN_SEL_S 7 +#define GPIO_GPIO_FUNC229_IN_INV_SEL (BIT(6)) +#define GPIO_GPIO_FUNC229_IN_INV_SEL_S 6 +#define GPIO_GPIO_FUNC229_IN_SEL 0x0000003F +#define GPIO_GPIO_FUNC229_IN_SEL_S 0 + +#define GPIO_FUNC230_IN_SEL_CFG (DR_REG_GPIO_BASE + 0x04c8) +#define GPIO_GPIO_SIG230_IN_SEL (BIT(7)) +#define GPIO_GPIO_SIG230_IN_SEL_S 7 +#define GPIO_GPIO_FUNC230_IN_INV_SEL (BIT(6)) +#define GPIO_GPIO_FUNC230_IN_INV_SEL_S 6 +#define GPIO_GPIO_FUNC230_IN_SEL 0x0000003F +#define GPIO_GPIO_FUNC230_IN_SEL_S 0 + +#define GPIO_FUNC231_IN_SEL_CFG (DR_REG_GPIO_BASE + 0x04cc) +#define GPIO_GPIO_SIG231_IN_SEL (BIT(7)) +#define GPIO_GPIO_SIG231_IN_SEL_S 7 +#define GPIO_GPIO_FUNC231_IN_INV_SEL (BIT(6)) +#define GPIO_GPIO_FUNC231_IN_INV_SEL_S 6 +#define GPIO_GPIO_FUNC231_IN_SEL 0x0000003F +#define GPIO_GPIO_FUNC231_IN_SEL_S 0 + +#define GPIO_FUNC232_IN_SEL_CFG (DR_REG_GPIO_BASE + 0x04d0) +#define GPIO_GPIO_SIG232_IN_SEL (BIT(7)) +#define GPIO_GPIO_SIG232_IN_SEL_S 7 +#define GPIO_GPIO_FUNC232_IN_INV_SEL (BIT(6)) +#define GPIO_GPIO_FUNC232_IN_INV_SEL_S 6 +#define GPIO_GPIO_FUNC232_IN_SEL 0x0000003F +#define GPIO_GPIO_FUNC232_IN_SEL_S 0 + +#define GPIO_FUNC233_IN_SEL_CFG (DR_REG_GPIO_BASE + 0x04d4) +#define GPIO_GPIO_SIG233_IN_SEL (BIT(7)) +#define GPIO_GPIO_SIG233_IN_SEL_S 7 +#define GPIO_GPIO_FUNC233_IN_INV_SEL (BIT(6)) +#define GPIO_GPIO_FUNC233_IN_INV_SEL_S 6 +#define GPIO_GPIO_FUNC233_IN_SEL 0x0000003F +#define GPIO_GPIO_FUNC233_IN_SEL_S 0 + +#define GPIO_FUNC234_IN_SEL_CFG (DR_REG_GPIO_BASE + 0x04d8) +#define GPIO_GPIO_SIG234_IN_SEL (BIT(7)) +#define GPIO_GPIO_SIG234_IN_SEL_S 7 +#define GPIO_GPIO_FUNC234_IN_INV_SEL (BIT(6)) +#define GPIO_GPIO_FUNC234_IN_INV_SEL_S 6 +#define GPIO_GPIO_FUNC234_IN_SEL 0x0000003F +#define GPIO_GPIO_FUNC234_IN_SEL_S 0 + +#define GPIO_FUNC235_IN_SEL_CFG (DR_REG_GPIO_BASE + 0x04dc) +#define GPIO_GPIO_SIG235_IN_SEL (BIT(7)) +#define GPIO_GPIO_SIG235_IN_SEL_S 7 +#define GPIO_GPIO_FUNC235_IN_INV_SEL (BIT(6)) +#define GPIO_GPIO_FUNC235_IN_INV_SEL_S 6 +#define GPIO_GPIO_FUNC235_IN_SEL 0x0000003F +#define GPIO_GPIO_FUNC235_IN_SEL_S 0 + +#define GPIO_FUNC236_IN_SEL_CFG (DR_REG_GPIO_BASE + 0x04e0) +#define GPIO_GPIO_SIG236_IN_SEL (BIT(7)) +#define GPIO_GPIO_SIG236_IN_SEL_S 7 +#define GPIO_GPIO_FUNC236_IN_INV_SEL (BIT(6)) +#define GPIO_GPIO_FUNC236_IN_INV_SEL_S 6 +#define GPIO_GPIO_FUNC236_IN_SEL 0x0000003F +#define GPIO_GPIO_FUNC236_IN_SEL_S 0 + +#define GPIO_FUNC237_IN_SEL_CFG (DR_REG_GPIO_BASE + 0x04e4) +#define GPIO_GPIO_SIG237_IN_SEL (BIT(7)) +#define GPIO_GPIO_SIG237_IN_SEL_S 7 +#define GPIO_GPIO_FUNC237_IN_INV_SEL (BIT(6)) +#define GPIO_GPIO_FUNC237_IN_INV_SEL_S 6 +#define GPIO_GPIO_FUNC237_IN_SEL 0x0000003F +#define GPIO_GPIO_FUNC237_IN_SEL_S 0 + +#define GPIO_FUNC238_IN_SEL_CFG (DR_REG_GPIO_BASE + 0x04e8) +#define GPIO_GPIO_SIG238_IN_SEL (BIT(7)) +#define GPIO_GPIO_SIG238_IN_SEL_S 7 +#define GPIO_GPIO_FUNC238_IN_INV_SEL (BIT(6)) +#define GPIO_GPIO_FUNC238_IN_INV_SEL_S 6 +#define GPIO_GPIO_FUNC238_IN_SEL 0x0000003F +#define GPIO_GPIO_FUNC238_IN_SEL_S 0 + +#define GPIO_FUNC239_IN_SEL_CFG (DR_REG_GPIO_BASE + 0x04ec) +#define GPIO_GPIO_SIG239_IN_SEL (BIT(7)) +#define GPIO_GPIO_SIG239_IN_SEL_S 7 +#define GPIO_GPIO_FUNC239_IN_INV_SEL (BIT(6)) +#define GPIO_GPIO_FUNC239_IN_INV_SEL_S 6 +#define GPIO_GPIO_FUNC239_IN_SEL 0x0000003F +#define GPIO_GPIO_FUNC239_IN_SEL_S 0 + +#define GPIO_FUNC240_IN_SEL_CFG (DR_REG_GPIO_BASE + 0x04f0) +#define GPIO_GPIO_SIG240_IN_SEL (BIT(7)) +#define GPIO_GPIO_SIG240_IN_SEL_S 7 +#define GPIO_GPIO_FUNC240_IN_INV_SEL (BIT(6)) +#define GPIO_GPIO_FUNC240_IN_INV_SEL_S 6 +#define GPIO_GPIO_FUNC240_IN_SEL 0x0000003F +#define GPIO_GPIO_FUNC240_IN_SEL_S 0 + +#define GPIO_FUNC241_IN_SEL_CFG (DR_REG_GPIO_BASE + 0x04f4) +#define GPIO_GPIO_SIG241_IN_SEL (BIT(7)) +#define GPIO_GPIO_SIG241_IN_SEL_S 7 +#define GPIO_GPIO_FUNC241_IN_INV_SEL (BIT(6)) +#define GPIO_GPIO_FUNC241_IN_INV_SEL_S 6 +#define GPIO_GPIO_FUNC241_IN_SEL 0x0000003F +#define GPIO_GPIO_FUNC241_IN_SEL_S 0 + +#define GPIO_FUNC242_IN_SEL_CFG (DR_REG_GPIO_BASE + 0x04f8) +#define GPIO_GPIO_SIG242_IN_SEL (BIT(7)) +#define GPIO_GPIO_SIG242_IN_SEL_S 7 +#define GPIO_GPIO_FUNC242_IN_INV_SEL (BIT(6)) +#define GPIO_GPIO_FUNC242_IN_INV_SEL_S 6 +#define GPIO_GPIO_FUNC242_IN_SEL 0x0000003F +#define GPIO_GPIO_FUNC242_IN_SEL_S 0 + +#define GPIO_FUNC243_IN_SEL_CFG (DR_REG_GPIO_BASE + 0x04fc) +#define GPIO_GPIO_SIG243_IN_SEL (BIT(7)) +#define GPIO_GPIO_SIG243_IN_SEL_S 7 +#define GPIO_GPIO_FUNC243_IN_INV_SEL (BIT(6)) +#define GPIO_GPIO_FUNC243_IN_INV_SEL_S 6 +#define GPIO_GPIO_FUNC243_IN_SEL 0x0000003F +#define GPIO_GPIO_FUNC243_IN_SEL_S 0 + +#define GPIO_FUNC244_IN_SEL_CFG (DR_REG_GPIO_BASE + 0x0500) +#define GPIO_GPIO_SIG244_IN_SEL (BIT(7)) +#define GPIO_GPIO_SIG244_IN_SEL_S 7 +#define GPIO_GPIO_FUNC244_IN_INV_SEL (BIT(6)) +#define GPIO_GPIO_FUNC244_IN_INV_SEL_S 6 +#define GPIO_GPIO_FUNC244_IN_SEL 0x0000003F +#define GPIO_GPIO_FUNC244_IN_SEL_S 0 + +#define GPIO_FUNC245_IN_SEL_CFG (DR_REG_GPIO_BASE + 0x0504) +#define GPIO_GPIO_SIG245_IN_SEL (BIT(7)) +#define GPIO_GPIO_SIG245_IN_SEL_S 7 +#define GPIO_GPIO_FUNC245_IN_INV_SEL (BIT(6)) +#define GPIO_GPIO_FUNC245_IN_INV_SEL_S 6 +#define GPIO_GPIO_FUNC245_IN_SEL 0x0000003F +#define GPIO_GPIO_FUNC245_IN_SEL_S 0 + +#define GPIO_FUNC246_IN_SEL_CFG (DR_REG_GPIO_BASE + 0x0508) +#define GPIO_GPIO_SIG246_IN_SEL (BIT(7)) +#define GPIO_GPIO_SIG246_IN_SEL_S 7 +#define GPIO_GPIO_FUNC246_IN_INV_SEL (BIT(6)) +#define GPIO_GPIO_FUNC246_IN_INV_SEL_S 6 +#define GPIO_GPIO_FUNC246_IN_SEL 0x0000003F +#define GPIO_GPIO_FUNC246_IN_SEL_S 0 + +#define GPIO_FUNC247_IN_SEL_CFG (DR_REG_GPIO_BASE + 0x050c) +#define GPIO_GPIO_SIG247_IN_SEL (BIT(7)) +#define GPIO_GPIO_SIG247_IN_SEL_S 7 +#define GPIO_GPIO_FUNC247_IN_INV_SEL (BIT(6)) +#define GPIO_GPIO_FUNC247_IN_INV_SEL_S 6 +#define GPIO_GPIO_FUNC247_IN_SEL 0x0000003F +#define GPIO_GPIO_FUNC247_IN_SEL_S 0 + +#define GPIO_FUNC248_IN_SEL_CFG (DR_REG_GPIO_BASE + 0x0510) +#define GPIO_GPIO_SIG248_IN_SEL (BIT(7)) +#define GPIO_GPIO_SIG248_IN_SEL_S 7 +#define GPIO_GPIO_FUNC248_IN_INV_SEL (BIT(6)) +#define GPIO_GPIO_FUNC248_IN_INV_SEL_S 6 +#define GPIO_GPIO_FUNC248_IN_SEL 0x0000003F +#define GPIO_GPIO_FUNC248_IN_SEL_S 0 + +#define GPIO_FUNC249_IN_SEL_CFG (DR_REG_GPIO_BASE + 0x0514) +#define GPIO_GPIO_SIG249_IN_SEL (BIT(7)) +#define GPIO_GPIO_SIG249_IN_SEL_S 7 +#define GPIO_GPIO_FUNC249_IN_INV_SEL (BIT(6)) +#define GPIO_GPIO_FUNC249_IN_INV_SEL_S 6 +#define GPIO_GPIO_FUNC249_IN_SEL 0x0000003F +#define GPIO_GPIO_FUNC249_IN_SEL_S 0 + +#define GPIO_FUNC250_IN_SEL_CFG (DR_REG_GPIO_BASE + 0x0518) +#define GPIO_GPIO_SIG250_IN_SEL (BIT(7)) +#define GPIO_GPIO_SIG250_IN_SEL_S 7 +#define GPIO_GPIO_FUNC250_IN_INV_SEL (BIT(6)) +#define GPIO_GPIO_FUNC250_IN_INV_SEL_S 6 +#define GPIO_GPIO_FUNC250_IN_SEL 0x0000003F +#define GPIO_GPIO_FUNC250_IN_SEL_S 0 + +#define GPIO_FUNC251_IN_SEL_CFG (DR_REG_GPIO_BASE + 0x051c) +#define GPIO_GPIO_SIG251_IN_SEL (BIT(7)) +#define GPIO_GPIO_SIG251_IN_SEL_S 7 +#define GPIO_GPIO_FUNC251_IN_INV_SEL (BIT(6)) +#define GPIO_GPIO_FUNC251_IN_INV_SEL_S 6 +#define GPIO_GPIO_FUNC251_IN_SEL 0x0000003F +#define GPIO_GPIO_FUNC251_IN_SEL_S 0 + +#define GPIO_FUNC252_IN_SEL_CFG (DR_REG_GPIO_BASE + 0x0520) +#define GPIO_GPIO_SIG252_IN_SEL (BIT(7)) +#define GPIO_GPIO_SIG252_IN_SEL_S 7 +#define GPIO_GPIO_FUNC252_IN_INV_SEL (BIT(6)) +#define GPIO_GPIO_FUNC252_IN_INV_SEL_S 6 +#define GPIO_GPIO_FUNC252_IN_SEL 0x0000003F +#define GPIO_GPIO_FUNC252_IN_SEL_S 0 + +#define GPIO_FUNC253_IN_SEL_CFG (DR_REG_GPIO_BASE + 0x0524) +#define GPIO_GPIO_SIG253_IN_SEL (BIT(7)) +#define GPIO_GPIO_SIG253_IN_SEL_S 7 +#define GPIO_GPIO_FUNC253_IN_INV_SEL (BIT(6)) +#define GPIO_GPIO_FUNC253_IN_INV_SEL_S 6 +#define GPIO_GPIO_FUNC253_IN_SEL 0x0000003F +#define GPIO_GPIO_FUNC253_IN_SEL_S 0 + +#define GPIO_FUNC254_IN_SEL_CFG (DR_REG_GPIO_BASE + 0x0528) +#define GPIO_GPIO_SIG254_IN_SEL (BIT(7)) +#define GPIO_GPIO_SIG254_IN_SEL_S 7 +#define GPIO_GPIO_FUNC254_IN_INV_SEL (BIT(6)) +#define GPIO_GPIO_FUNC254_IN_INV_SEL_S 6 +#define GPIO_GPIO_FUNC254_IN_SEL 0x0000003F +#define GPIO_GPIO_FUNC254_IN_SEL_S 0 + +#define GPIO_FUNC255_IN_SEL_CFG (DR_REG_GPIO_BASE + 0x052c) +#define GPIO_GPIO_SIG255_IN_SEL (BIT(7)) +#define GPIO_GPIO_SIG255_IN_SEL_S 7 +#define GPIO_GPIO_FUNC255_IN_INV_SEL (BIT(6)) +#define GPIO_GPIO_FUNC255_IN_INV_SEL_S 6 +#define GPIO_GPIO_FUNC255_IN_SEL 0x0000003F +#define GPIO_GPIO_FUNC255_IN_SEL_S 0 + +#define GPIO_FUNC0_OUT_SEL_CFG (DR_REG_GPIO_BASE + 0x0530) +#define GPIO_GPIO_FUNC0_OEN_INV_SEL (BIT(11)) +#define GPIO_GPIO_FUNC0_OEN_INV_SEL_S 11 +#define GPIO_GPIO_FUNC0_OEN_SEL (BIT(10)) +#define GPIO_GPIO_FUNC0_OEN_SEL_S 10 +#define GPIO_GPIO_FUNC0_OUT_INV_SEL (BIT(9)) +#define GPIO_GPIO_FUNC0_OUT_INV_SEL_S 9 +#define GPIO_GPIO_FUNC0_OUT_SEL 0x000001FF +#define GPIO_GPIO_FUNC0_OUT_SEL_S 0 + +#define GPIO_FUNC1_OUT_SEL_CFG (DR_REG_GPIO_BASE + 0x0534) +#define GPIO_GPIO_FUNC1_OEN_INV_SEL (BIT(11)) +#define GPIO_GPIO_FUNC1_OEN_INV_SEL_S 11 +#define GPIO_GPIO_FUNC1_OEN_SEL (BIT(10)) +#define GPIO_GPIO_FUNC1_OEN_SEL_S 10 +#define GPIO_GPIO_FUNC1_OUT_INV_SEL (BIT(9)) +#define GPIO_GPIO_FUNC1_OUT_INV_SEL_S 9 +#define GPIO_GPIO_FUNC1_OUT_SEL 0x000001FF +#define GPIO_GPIO_FUNC1_OUT_SEL_S 0 + +#define GPIO_FUNC2_OUT_SEL_CFG (DR_REG_GPIO_BASE + 0x0538) +#define GPIO_GPIO_FUNC2_OEN_INV_SEL (BIT(11)) +#define GPIO_GPIO_FUNC2_OEN_INV_SEL_S 11 +#define GPIO_GPIO_FUNC2_OEN_SEL (BIT(10)) +#define GPIO_GPIO_FUNC2_OEN_SEL_S 10 +#define GPIO_GPIO_FUNC2_OUT_INV_SEL (BIT(9)) +#define GPIO_GPIO_FUNC2_OUT_INV_SEL_S 9 +#define GPIO_GPIO_FUNC2_OUT_SEL 0x000001FF +#define GPIO_GPIO_FUNC2_OUT_SEL_S 0 + +#define GPIO_FUNC3_OUT_SEL_CFG (DR_REG_GPIO_BASE + 0x053c) +#define GPIO_GPIO_FUNC3_OEN_INV_SEL (BIT(11)) +#define GPIO_GPIO_FUNC3_OEN_INV_SEL_S 11 +#define GPIO_GPIO_FUNC3_OEN_SEL (BIT(10)) +#define GPIO_GPIO_FUNC3_OEN_SEL_S 10 +#define GPIO_GPIO_FUNC3_OUT_INV_SEL (BIT(9)) +#define GPIO_GPIO_FUNC3_OUT_INV_SEL_S 9 +#define GPIO_GPIO_FUNC3_OUT_SEL 0x000001FF +#define GPIO_GPIO_FUNC3_OUT_SEL_S 0 + +#define GPIO_FUNC4_OUT_SEL_CFG (DR_REG_GPIO_BASE + 0x0540) +#define GPIO_GPIO_FUNC4_OEN_INV_SEL (BIT(11)) +#define GPIO_GPIO_FUNC4_OEN_INV_SEL_S 11 +#define GPIO_GPIO_FUNC4_OEN_SEL (BIT(10)) +#define GPIO_GPIO_FUNC4_OEN_SEL_S 10 +#define GPIO_GPIO_FUNC4_OUT_INV_SEL (BIT(9)) +#define GPIO_GPIO_FUNC4_OUT_INV_SEL_S 9 +#define GPIO_GPIO_FUNC4_OUT_SEL 0x000001FF +#define GPIO_GPIO_FUNC4_OUT_SEL_S 0 + +#define GPIO_FUNC5_OUT_SEL_CFG (DR_REG_GPIO_BASE + 0x0544) +#define GPIO_GPIO_FUNC5_OEN_INV_SEL (BIT(11)) +#define GPIO_GPIO_FUNC5_OEN_INV_SEL_S 11 +#define GPIO_GPIO_FUNC5_OEN_SEL (BIT(10)) +#define GPIO_GPIO_FUNC5_OEN_SEL_S 10 +#define GPIO_GPIO_FUNC5_OUT_INV_SEL (BIT(9)) +#define GPIO_GPIO_FUNC5_OUT_INV_SEL_S 9 +#define GPIO_GPIO_FUNC5_OUT_SEL 0x000001FF +#define GPIO_GPIO_FUNC5_OUT_SEL_S 0 + +#define GPIO_FUNC6_OUT_SEL_CFG (DR_REG_GPIO_BASE + 0x0548) +#define GPIO_GPIO_FUNC6_OEN_INV_SEL (BIT(11)) +#define GPIO_GPIO_FUNC6_OEN_INV_SEL_S 11 +#define GPIO_GPIO_FUNC6_OEN_SEL (BIT(10)) +#define GPIO_GPIO_FUNC6_OEN_SEL_S 10 +#define GPIO_GPIO_FUNC6_OUT_INV_SEL (BIT(9)) +#define GPIO_GPIO_FUNC6_OUT_INV_SEL_S 9 +#define GPIO_GPIO_FUNC6_OUT_SEL 0x000001FF +#define GPIO_GPIO_FUNC6_OUT_SEL_S 0 + +#define GPIO_FUNC7_OUT_SEL_CFG (DR_REG_GPIO_BASE + 0x054c) +#define GPIO_GPIO_FUNC7_OEN_INV_SEL (BIT(11)) +#define GPIO_GPIO_FUNC7_OEN_INV_SEL_S 11 +#define GPIO_GPIO_FUNC7_OEN_SEL (BIT(10)) +#define GPIO_GPIO_FUNC7_OEN_SEL_S 10 +#define GPIO_GPIO_FUNC7_OUT_INV_SEL (BIT(9)) +#define GPIO_GPIO_FUNC7_OUT_INV_SEL_S 9 +#define GPIO_GPIO_FUNC7_OUT_SEL 0x000001FF +#define GPIO_GPIO_FUNC7_OUT_SEL_S 0 + +#define GPIO_FUNC8_OUT_SEL_CFG (DR_REG_GPIO_BASE + 0x0550) +#define GPIO_GPIO_FUNC8_OEN_INV_SEL (BIT(11)) +#define GPIO_GPIO_FUNC8_OEN_INV_SEL_S 11 +#define GPIO_GPIO_FUNC8_OEN_SEL (BIT(10)) +#define GPIO_GPIO_FUNC8_OEN_SEL_S 10 +#define GPIO_GPIO_FUNC8_OUT_INV_SEL (BIT(9)) +#define GPIO_GPIO_FUNC8_OUT_INV_SEL_S 9 +#define GPIO_GPIO_FUNC8_OUT_SEL 0x000001FF +#define GPIO_GPIO_FUNC8_OUT_SEL_S 0 + +#define GPIO_FUNC9_OUT_SEL_CFG (DR_REG_GPIO_BASE + 0x0554) +#define GPIO_GPIO_FUNC9_OEN_INV_SEL (BIT(11)) +#define GPIO_GPIO_FUNC9_OEN_INV_SEL_S 11 +#define GPIO_GPIO_FUNC9_OEN_SEL (BIT(10)) +#define GPIO_GPIO_FUNC9_OEN_SEL_S 10 +#define GPIO_GPIO_FUNC9_OUT_INV_SEL (BIT(9)) +#define GPIO_GPIO_FUNC9_OUT_INV_SEL_S 9 +#define GPIO_GPIO_FUNC9_OUT_SEL 0x000001FF +#define GPIO_GPIO_FUNC9_OUT_SEL_S 0 + +#define GPIO_FUNC10_OUT_SEL_CFG (DR_REG_GPIO_BASE + 0x0558) +#define GPIO_GPIO_FUNC10_OEN_INV_SEL (BIT(11)) +#define GPIO_GPIO_FUNC10_OEN_INV_SEL_S 11 +#define GPIO_GPIO_FUNC10_OEN_SEL (BIT(10)) +#define GPIO_GPIO_FUNC10_OEN_SEL_S 10 +#define GPIO_GPIO_FUNC10_OUT_INV_SEL (BIT(9)) +#define GPIO_GPIO_FUNC10_OUT_INV_SEL_S 9 +#define GPIO_GPIO_FUNC10_OUT_SEL 0x000001FF +#define GPIO_GPIO_FUNC10_OUT_SEL_S 0 + +#define GPIO_FUNC11_OUT_SEL_CFG (DR_REG_GPIO_BASE + 0x055c) +#define GPIO_GPIO_FUNC11_OEN_INV_SEL (BIT(11)) +#define GPIO_GPIO_FUNC11_OEN_INV_SEL_S 11 +#define GPIO_GPIO_FUNC11_OEN_SEL (BIT(10)) +#define GPIO_GPIO_FUNC11_OEN_SEL_S 10 +#define GPIO_GPIO_FUNC11_OUT_INV_SEL (BIT(9)) +#define GPIO_GPIO_FUNC11_OUT_INV_SEL_S 9 +#define GPIO_GPIO_FUNC11_OUT_SEL 0x000001FF +#define GPIO_GPIO_FUNC11_OUT_SEL_S 0 + +#define GPIO_FUNC12_OUT_SEL_CFG (DR_REG_GPIO_BASE + 0x0560) +#define GPIO_GPIO_FUNC12_OEN_INV_SEL (BIT(11)) +#define GPIO_GPIO_FUNC12_OEN_INV_SEL_S 11 +#define GPIO_GPIO_FUNC12_OEN_SEL (BIT(10)) +#define GPIO_GPIO_FUNC12_OEN_SEL_S 10 +#define GPIO_GPIO_FUNC12_OUT_INV_SEL (BIT(9)) +#define GPIO_GPIO_FUNC12_OUT_INV_SEL_S 9 +#define GPIO_GPIO_FUNC12_OUT_SEL 0x000001FF +#define GPIO_GPIO_FUNC12_OUT_SEL_S 0 + +#define GPIO_FUNC13_OUT_SEL_CFG (DR_REG_GPIO_BASE + 0x0564) +#define GPIO_GPIO_FUNC13_OEN_INV_SEL (BIT(11)) +#define GPIO_GPIO_FUNC13_OEN_INV_SEL_S 11 +#define GPIO_GPIO_FUNC13_OEN_SEL (BIT(10)) +#define GPIO_GPIO_FUNC13_OEN_SEL_S 10 +#define GPIO_GPIO_FUNC13_OUT_INV_SEL (BIT(9)) +#define GPIO_GPIO_FUNC13_OUT_INV_SEL_S 9 +#define GPIO_GPIO_FUNC13_OUT_SEL 0x000001FF +#define GPIO_GPIO_FUNC13_OUT_SEL_S 0 + +#define GPIO_FUNC14_OUT_SEL_CFG (DR_REG_GPIO_BASE + 0x0568) +#define GPIO_GPIO_FUNC14_OEN_INV_SEL (BIT(11)) +#define GPIO_GPIO_FUNC14_OEN_INV_SEL_S 11 +#define GPIO_GPIO_FUNC14_OEN_SEL (BIT(10)) +#define GPIO_GPIO_FUNC14_OEN_SEL_S 10 +#define GPIO_GPIO_FUNC14_OUT_INV_SEL (BIT(9)) +#define GPIO_GPIO_FUNC14_OUT_INV_SEL_S 9 +#define GPIO_GPIO_FUNC14_OUT_SEL 0x000001FF +#define GPIO_GPIO_FUNC14_OUT_SEL_S 0 + +#define GPIO_FUNC15_OUT_SEL_CFG (DR_REG_GPIO_BASE + 0x056c) +#define GPIO_GPIO_FUNC15_OEN_INV_SEL (BIT(11)) +#define GPIO_GPIO_FUNC15_OEN_INV_SEL_S 11 +#define GPIO_GPIO_FUNC15_OEN_SEL (BIT(10)) +#define GPIO_GPIO_FUNC15_OEN_SEL_S 10 +#define GPIO_GPIO_FUNC15_OUT_INV_SEL (BIT(9)) +#define GPIO_GPIO_FUNC15_OUT_INV_SEL_S 9 +#define GPIO_GPIO_FUNC15_OUT_SEL 0x000001FF +#define GPIO_GPIO_FUNC15_OUT_SEL_S 0 + +#define GPIO_FUNC16_OUT_SEL_CFG (DR_REG_GPIO_BASE + 0x0570) +#define GPIO_GPIO_FUNC16_OEN_INV_SEL (BIT(11)) +#define GPIO_GPIO_FUNC16_OEN_INV_SEL_S 11 +#define GPIO_GPIO_FUNC16_OEN_SEL (BIT(10)) +#define GPIO_GPIO_FUNC16_OEN_SEL_S 10 +#define GPIO_GPIO_FUNC16_OUT_INV_SEL (BIT(9)) +#define GPIO_GPIO_FUNC16_OUT_INV_SEL_S 9 +#define GPIO_GPIO_FUNC16_OUT_SEL 0x000001FF +#define GPIO_GPIO_FUNC16_OUT_SEL_S 0 + +#define GPIO_FUNC17_OUT_SEL_CFG (DR_REG_GPIO_BASE + 0x0574) +#define GPIO_GPIO_FUNC17_OEN_INV_SEL (BIT(11)) +#define GPIO_GPIO_FUNC17_OEN_INV_SEL_S 11 +#define GPIO_GPIO_FUNC17_OEN_SEL (BIT(10)) +#define GPIO_GPIO_FUNC17_OEN_SEL_S 10 +#define GPIO_GPIO_FUNC17_OUT_INV_SEL (BIT(9)) +#define GPIO_GPIO_FUNC17_OUT_INV_SEL_S 9 +#define GPIO_GPIO_FUNC17_OUT_SEL 0x000001FF +#define GPIO_GPIO_FUNC17_OUT_SEL_S 0 + +#define GPIO_FUNC18_OUT_SEL_CFG (DR_REG_GPIO_BASE + 0x0578) +#define GPIO_GPIO_FUNC18_OEN_INV_SEL (BIT(11)) +#define GPIO_GPIO_FUNC18_OEN_INV_SEL_S 11 +#define GPIO_GPIO_FUNC18_OEN_SEL (BIT(10)) +#define GPIO_GPIO_FUNC18_OEN_SEL_S 10 +#define GPIO_GPIO_FUNC18_OUT_INV_SEL (BIT(9)) +#define GPIO_GPIO_FUNC18_OUT_INV_SEL_S 9 +#define GPIO_GPIO_FUNC18_OUT_SEL 0x000001FF +#define GPIO_GPIO_FUNC18_OUT_SEL_S 0 + +#define GPIO_FUNC19_OUT_SEL_CFG (DR_REG_GPIO_BASE + 0x057c) +#define GPIO_GPIO_FUNC19_OEN_INV_SEL (BIT(11)) +#define GPIO_GPIO_FUNC19_OEN_INV_SEL_S 11 +#define GPIO_GPIO_FUNC19_OEN_SEL (BIT(10)) +#define GPIO_GPIO_FUNC19_OEN_SEL_S 10 +#define GPIO_GPIO_FUNC19_OUT_INV_SEL (BIT(9)) +#define GPIO_GPIO_FUNC19_OUT_INV_SEL_S 9 +#define GPIO_GPIO_FUNC19_OUT_SEL 0x000001FF +#define GPIO_GPIO_FUNC19_OUT_SEL_S 0 + +#define GPIO_FUNC20_OUT_SEL_CFG (DR_REG_GPIO_BASE + 0x0580) +#define GPIO_GPIO_FUNC20_OEN_INV_SEL (BIT(11)) +#define GPIO_GPIO_FUNC20_OEN_INV_SEL_S 11 +#define GPIO_GPIO_FUNC20_OEN_SEL (BIT(10)) +#define GPIO_GPIO_FUNC20_OEN_SEL_S 10 +#define GPIO_GPIO_FUNC20_OUT_INV_SEL (BIT(9)) +#define GPIO_GPIO_FUNC20_OUT_INV_SEL_S 9 +#define GPIO_GPIO_FUNC20_OUT_SEL 0x000001FF +#define GPIO_GPIO_FUNC20_OUT_SEL_S 0 + +#define GPIO_FUNC21_OUT_SEL_CFG (DR_REG_GPIO_BASE + 0x0584) +#define GPIO_GPIO_FUNC21_OEN_INV_SEL (BIT(11)) +#define GPIO_GPIO_FUNC21_OEN_INV_SEL_S 11 +#define GPIO_GPIO_FUNC21_OEN_SEL (BIT(10)) +#define GPIO_GPIO_FUNC21_OEN_SEL_S 10 +#define GPIO_GPIO_FUNC21_OUT_INV_SEL (BIT(9)) +#define GPIO_GPIO_FUNC21_OUT_INV_SEL_S 9 +#define GPIO_GPIO_FUNC21_OUT_SEL 0x000001FF +#define GPIO_GPIO_FUNC21_OUT_SEL_S 0 + +#define GPIO_FUNC22_OUT_SEL_CFG (DR_REG_GPIO_BASE + 0x0588) +#define GPIO_GPIO_FUNC22_OEN_INV_SEL (BIT(11)) +#define GPIO_GPIO_FUNC22_OEN_INV_SEL_S 11 +#define GPIO_GPIO_FUNC22_OEN_SEL (BIT(10)) +#define GPIO_GPIO_FUNC22_OEN_SEL_S 10 +#define GPIO_GPIO_FUNC22_OUT_INV_SEL (BIT(9)) +#define GPIO_GPIO_FUNC22_OUT_INV_SEL_S 9 +#define GPIO_GPIO_FUNC22_OUT_SEL 0x000001FF +#define GPIO_GPIO_FUNC22_OUT_SEL_S 0 + +#define GPIO_FUNC23_OUT_SEL_CFG (DR_REG_GPIO_BASE + 0x058c) +#define GPIO_GPIO_FUNC23_OEN_INV_SEL (BIT(11)) +#define GPIO_GPIO_FUNC23_OEN_INV_SEL_S 11 +#define GPIO_GPIO_FUNC23_OEN_SEL (BIT(10)) +#define GPIO_GPIO_FUNC23_OEN_SEL_S 10 +#define GPIO_GPIO_FUNC23_OUT_INV_SEL (BIT(9)) +#define GPIO_GPIO_FUNC23_OUT_INV_SEL_S 9 +#define GPIO_GPIO_FUNC23_OUT_SEL 0x000001FF +#define GPIO_GPIO_FUNC23_OUT_SEL_S 0 + +#define GPIO_FUNC24_OUT_SEL_CFG (DR_REG_GPIO_BASE + 0x0590) +#define GPIO_GPIO_FUNC24_OEN_INV_SEL (BIT(11)) +#define GPIO_GPIO_FUNC24_OEN_INV_SEL_S 11 +#define GPIO_GPIO_FUNC24_OEN_SEL (BIT(10)) +#define GPIO_GPIO_FUNC24_OEN_SEL_S 10 +#define GPIO_GPIO_FUNC24_OUT_INV_SEL (BIT(9)) +#define GPIO_GPIO_FUNC24_OUT_INV_SEL_S 9 +#define GPIO_GPIO_FUNC24_OUT_SEL 0x000001FF +#define GPIO_GPIO_FUNC24_OUT_SEL_S 0 + +#define GPIO_FUNC25_OUT_SEL_CFG (DR_REG_GPIO_BASE + 0x0594) +#define GPIO_GPIO_FUNC25_OEN_INV_SEL (BIT(11)) +#define GPIO_GPIO_FUNC25_OEN_INV_SEL_S 11 +#define GPIO_GPIO_FUNC25_OEN_SEL (BIT(10)) +#define GPIO_GPIO_FUNC25_OEN_SEL_S 10 +#define GPIO_GPIO_FUNC25_OUT_INV_SEL (BIT(9)) +#define GPIO_GPIO_FUNC25_OUT_INV_SEL_S 9 +#define GPIO_GPIO_FUNC25_OUT_SEL 0x000001FF +#define GPIO_GPIO_FUNC25_OUT_SEL_S 0 + +#define GPIO_FUNC26_OUT_SEL_CFG (DR_REG_GPIO_BASE + 0x0598) +#define GPIO_GPIO_FUNC26_OEN_INV_SEL (BIT(11)) +#define GPIO_GPIO_FUNC26_OEN_INV_SEL_S 11 +#define GPIO_GPIO_FUNC26_OEN_SEL (BIT(10)) +#define GPIO_GPIO_FUNC26_OEN_SEL_S 10 +#define GPIO_GPIO_FUNC26_OUT_INV_SEL (BIT(9)) +#define GPIO_GPIO_FUNC26_OUT_INV_SEL_S 9 +#define GPIO_GPIO_FUNC26_OUT_SEL 0x000001FF +#define GPIO_GPIO_FUNC26_OUT_SEL_S 0 + +#define GPIO_FUNC27_OUT_SEL_CFG (DR_REG_GPIO_BASE + 0x059c) +#define GPIO_GPIO_FUNC27_OEN_INV_SEL (BIT(11)) +#define GPIO_GPIO_FUNC27_OEN_INV_SEL_S 11 +#define GPIO_GPIO_FUNC27_OEN_SEL (BIT(10)) +#define GPIO_GPIO_FUNC27_OEN_SEL_S 10 +#define GPIO_GPIO_FUNC27_OUT_INV_SEL (BIT(9)) +#define GPIO_GPIO_FUNC27_OUT_INV_SEL_S 9 +#define GPIO_GPIO_FUNC27_OUT_SEL 0x000001FF +#define GPIO_GPIO_FUNC27_OUT_SEL_S 0 + +#define GPIO_FUNC28_OUT_SEL_CFG (DR_REG_GPIO_BASE + 0x05a0) +#define GPIO_GPIO_FUNC28_OEN_INV_SEL (BIT(11)) +#define GPIO_GPIO_FUNC28_OEN_INV_SEL_S 11 +#define GPIO_GPIO_FUNC28_OEN_SEL (BIT(10)) +#define GPIO_GPIO_FUNC28_OEN_SEL_S 10 +#define GPIO_GPIO_FUNC28_OUT_INV_SEL (BIT(9)) +#define GPIO_GPIO_FUNC28_OUT_INV_SEL_S 9 +#define GPIO_GPIO_FUNC28_OUT_SEL 0x000001FF +#define GPIO_GPIO_FUNC28_OUT_SEL_S 0 + +#define GPIO_FUNC29_OUT_SEL_CFG (DR_REG_GPIO_BASE + 0x05a4) +#define GPIO_GPIO_FUNC29_OEN_INV_SEL (BIT(11)) +#define GPIO_GPIO_FUNC29_OEN_INV_SEL_S 11 +#define GPIO_GPIO_FUNC29_OEN_SEL (BIT(10)) +#define GPIO_GPIO_FUNC29_OEN_SEL_S 10 +#define GPIO_GPIO_FUNC29_OUT_INV_SEL (BIT(9)) +#define GPIO_GPIO_FUNC29_OUT_INV_SEL_S 9 +#define GPIO_GPIO_FUNC29_OUT_SEL 0x000001FF +#define GPIO_GPIO_FUNC29_OUT_SEL_S 0 + +#define GPIO_FUNC30_OUT_SEL_CFG (DR_REG_GPIO_BASE + 0x05a8) +#define GPIO_GPIO_FUNC30_OEN_INV_SEL (BIT(11)) +#define GPIO_GPIO_FUNC30_OEN_INV_SEL_S 11 +#define GPIO_GPIO_FUNC30_OEN_SEL (BIT(10)) +#define GPIO_GPIO_FUNC30_OEN_SEL_S 10 +#define GPIO_GPIO_FUNC30_OUT_INV_SEL (BIT(9)) +#define GPIO_GPIO_FUNC30_OUT_INV_SEL_S 9 +#define GPIO_GPIO_FUNC30_OUT_SEL 0x000001FF +#define GPIO_GPIO_FUNC30_OUT_SEL_S 0 + +#define GPIO_FUNC31_OUT_SEL_CFG (DR_REG_GPIO_BASE + 0x05ac) +#define GPIO_GPIO_FUNC31_OEN_INV_SEL (BIT(11)) +#define GPIO_GPIO_FUNC31_OEN_INV_SEL_S 11 +#define GPIO_GPIO_FUNC31_OEN_SEL (BIT(10)) +#define GPIO_GPIO_FUNC31_OEN_SEL_S 10 +#define GPIO_GPIO_FUNC31_OUT_INV_SEL (BIT(9)) +#define GPIO_GPIO_FUNC31_OUT_INV_SEL_S 9 +#define GPIO_GPIO_FUNC31_OUT_SEL 0x000001FF +#define GPIO_GPIO_FUNC31_OUT_SEL_S 0 + +#define GPIO_FUNC32_OUT_SEL_CFG (DR_REG_GPIO_BASE + 0x05b0) +#define GPIO_GPIO_FUNC32_OEN_INV_SEL (BIT(11)) +#define GPIO_GPIO_FUNC32_OEN_INV_SEL_S 11 +#define GPIO_GPIO_FUNC32_OEN_SEL (BIT(10)) +#define GPIO_GPIO_FUNC32_OEN_SEL_S 10 +#define GPIO_GPIO_FUNC32_OUT_INV_SEL (BIT(9)) +#define GPIO_GPIO_FUNC32_OUT_INV_SEL_S 9 +#define GPIO_GPIO_FUNC32_OUT_SEL 0x000001FF +#define GPIO_GPIO_FUNC32_OUT_SEL_S 0 + +#define GPIO_FUNC33_OUT_SEL_CFG (DR_REG_GPIO_BASE + 0x05b4) +#define GPIO_GPIO_FUNC33_OEN_INV_SEL (BIT(11)) +#define GPIO_GPIO_FUNC33_OEN_INV_SEL_S 11 +#define GPIO_GPIO_FUNC33_OEN_SEL (BIT(10)) +#define GPIO_GPIO_FUNC33_OEN_SEL_S 10 +#define GPIO_GPIO_FUNC33_OUT_INV_SEL (BIT(9)) +#define GPIO_GPIO_FUNC33_OUT_INV_SEL_S 9 +#define GPIO_GPIO_FUNC33_OUT_SEL 0x000001FF +#define GPIO_GPIO_FUNC33_OUT_SEL_S 0 + +#define GPIO_FUNC34_OUT_SEL_CFG (DR_REG_GPIO_BASE + 0x05b8) +#define GPIO_GPIO_FUNC34_OEN_INV_SEL (BIT(11)) +#define GPIO_GPIO_FUNC34_OEN_INV_SEL_S 11 +#define GPIO_GPIO_FUNC34_OEN_SEL (BIT(10)) +#define GPIO_GPIO_FUNC34_OEN_SEL_S 10 +#define GPIO_GPIO_FUNC34_OUT_INV_SEL (BIT(9)) +#define GPIO_GPIO_FUNC34_OUT_INV_SEL_S 9 +#define GPIO_GPIO_FUNC34_OUT_SEL 0x000001FF +#define GPIO_GPIO_FUNC34_OUT_SEL_S 0 + +#define GPIO_FUNC35_OUT_SEL_CFG (DR_REG_GPIO_BASE + 0x05bc) +#define GPIO_GPIO_FUNC35_OEN_INV_SEL (BIT(11)) +#define GPIO_GPIO_FUNC35_OEN_INV_SEL_S 11 +#define GPIO_GPIO_FUNC35_OEN_SEL (BIT(10)) +#define GPIO_GPIO_FUNC35_OEN_SEL_S 10 +#define GPIO_GPIO_FUNC35_OUT_INV_SEL (BIT(9)) +#define GPIO_GPIO_FUNC35_OUT_INV_SEL_S 9 +#define GPIO_GPIO_FUNC35_OUT_SEL 0x000001FF +#define GPIO_GPIO_FUNC35_OUT_SEL_S 0 + +#define GPIO_FUNC36_OUT_SEL_CFG (DR_REG_GPIO_BASE + 0x05c0) +#define GPIO_GPIO_FUNC36_OEN_INV_SEL (BIT(11)) +#define GPIO_GPIO_FUNC36_OEN_INV_SEL_S 11 +#define GPIO_GPIO_FUNC36_OEN_SEL (BIT(10)) +#define GPIO_GPIO_FUNC36_OEN_SEL_S 10 +#define GPIO_GPIO_FUNC36_OUT_INV_SEL (BIT(9)) +#define GPIO_GPIO_FUNC36_OUT_INV_SEL_S 9 +#define GPIO_GPIO_FUNC36_OUT_SEL 0x000001FF +#define GPIO_GPIO_FUNC36_OUT_SEL_S 0 + +#define GPIO_FUNC37_OUT_SEL_CFG (DR_REG_GPIO_BASE + 0x05c4) +#define GPIO_GPIO_FUNC37_OEN_INV_SEL (BIT(11)) +#define GPIO_GPIO_FUNC37_OEN_INV_SEL_S 11 +#define GPIO_GPIO_FUNC37_OEN_SEL (BIT(10)) +#define GPIO_GPIO_FUNC37_OEN_SEL_S 10 +#define GPIO_GPIO_FUNC37_OUT_INV_SEL (BIT(9)) +#define GPIO_GPIO_FUNC37_OUT_INV_SEL_S 9 +#define GPIO_GPIO_FUNC37_OUT_SEL 0x000001FF +#define GPIO_GPIO_FUNC37_OUT_SEL_S 0 + +#define GPIO_FUNC38_OUT_SEL_CFG (DR_REG_GPIO_BASE + 0x05c8) +#define GPIO_GPIO_FUNC38_OEN_INV_SEL (BIT(11)) +#define GPIO_GPIO_FUNC38_OEN_INV_SEL_S 11 +#define GPIO_GPIO_FUNC38_OEN_SEL (BIT(10)) +#define GPIO_GPIO_FUNC38_OEN_SEL_S 10 +#define GPIO_GPIO_FUNC38_OUT_INV_SEL (BIT(9)) +#define GPIO_GPIO_FUNC38_OUT_INV_SEL_S 9 +#define GPIO_GPIO_FUNC38_OUT_SEL 0x000001FF +#define GPIO_GPIO_FUNC38_OUT_SEL_S 0 + +#define GPIO_FUNC39_OUT_SEL_CFG (DR_REG_GPIO_BASE + 0x05cc) +#define GPIO_GPIO_FUNC39_OEN_INV_SEL (BIT(11)) +#define GPIO_GPIO_FUNC39_OEN_INV_SEL_S 11 +#define GPIO_GPIO_FUNC39_OEN_SEL (BIT(10)) +#define GPIO_GPIO_FUNC39_OEN_SEL_S 10 +#define GPIO_GPIO_FUNC39_OUT_INV_SEL (BIT(9)) +#define GPIO_GPIO_FUNC39_OUT_INV_SEL_S 9 +#define GPIO_GPIO_FUNC39_OUT_SEL 0x000001FF +#define GPIO_GPIO_FUNC39_OUT_SEL_S 0 + +#endif /* _SOC_GPIO_REG_H_ */ diff --git a/components/esp32/include/soc/gpio_sd_reg.h b/components/esp32/include/soc/gpio_sd_reg.h new file mode 100644 index 0000000000..3d9dbb2851 --- /dev/null +++ b/components/esp32/include/soc/gpio_sd_reg.h @@ -0,0 +1,80 @@ +// Copyright 2015-2016 Espressif Systems (Shanghai) PTE LTD +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at + +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +#ifndef _SOC_GPIO_SD_REG_H_ +#define _SOC_GPIO_SD_REG_H_ + +#include "soc.h" + +#define SIGMADELTA0 (DR_REG_GPIO_SD_BASE + 0x0000) +#define SIGMADELTA_SD0_PRESCALE 0x000000FF +#define SIGMADELTA_SD0_PRESCALE_S 8 +#define SIGMADELTA_SD0_IN 0x000000FF +#define SIGMADELTA_SD0_IN_S 0 + +#define SIGMADELTA1 (DR_REG_GPIO_SD_BASE + 0x0004) +#define SIGMADELTA_SD1_PRESCALE 0x000000FF +#define SIGMADELTA_SD1_PRESCALE_S 8 +#define SIGMADELTA_SD1_IN 0x000000FF +#define SIGMADELTA_SD1_IN_S 0 + +#define SIGMADELTA2 (DR_REG_GPIO_SD_BASE + 0x0008) +#define SIGMADELTA_SD2_PRESCALE 0x000000FF +#define SIGMADELTA_SD2_PRESCALE_S 8 +#define SIGMADELTA_SD2_IN 0x000000FF +#define SIGMADELTA_SD2_IN_S 0 + +#define SIGMADELTA3 (DR_REG_GPIO_SD_BASE + 0x000c) +#define SIGMADELTA_SD3_PRESCALE 0x000000FF +#define SIGMADELTA_SD3_PRESCALE_S 8 +#define SIGMADELTA_SD3_IN 0x000000FF +#define SIGMADELTA_SD3_IN_S 0 + +#define SIGMADELTA4 (DR_REG_GPIO_SD_BASE + 0x0010) +#define SIGMADELTA_SD4_PRESCALE 0x000000FF +#define SIGMADELTA_SD4_PRESCALE_S 8 +#define SIGMADELTA_SD4_IN 0x000000FF +#define SIGMADELTA_SD4_IN_S 0 + +#define SIGMADELTA5 (DR_REG_GPIO_SD_BASE + 0x0014) +#define SIGMADELTA_SD5_PRESCALE 0x000000FF +#define SIGMADELTA_SD5_PRESCALE_S 8 +#define SIGMADELTA_SD5_IN 0x000000FF +#define SIGMADELTA_SD5_IN_S 0 + +#define SIGMADELTA6 (DR_REG_GPIO_SD_BASE + 0x0018) +#define SIGMADELTA_SD6_PRESCALE 0x000000FF +#define SIGMADELTA_SD6_PRESCALE_S 8 +#define SIGMADELTA_SD6_IN 0x000000FF +#define SIGMADELTA_SD6_IN_S 0 + +#define SIGMADELTA7 (DR_REG_GPIO_SD_BASE + 0x001c) +#define SIGMADELTA_SD7_PRESCALE 0x000000FF +#define SIGMADELTA_SD7_PRESCALE_S 8 +#define SIGMADELTA_SD7_IN 0x000000FF +#define SIGMADELTA_SD7_IN_S 0 + +#define SIGMADELTA_CG (DR_REG_GPIO_SD_BASE + 0x0020) +#define SIGMADELTA_GPIO_SD_CLK_EN (BIT(31)) +#define SIGMADELTA_GPIO_SD_CLK_EN_S 31 + +#define SIGMADELTA_MISC (DR_REG_GPIO_SD_BASE + 0x0024) +#define SIGMADELTA_SPI_SWAP (BIT(31)) +#define SIGMADELTA_SPI_SWAP_S 31 + +#define SIGMADELTA_VERSION (DR_REG_GPIO_SD_BASE + 0x0028) +#define SIGMADELTA_GPIO_SD_DATE 0x0FFFFFFF +#define SIGMADELTA_GPIO_SD_DATE_S 0 +#define SIGMADELTA_GPIO_SD_DATE_VERSION 0x1506190 + +#endif /* _SOC_GPIO_SD_REG_H_ */ diff --git a/components/esp32/include/soc/gpio_sig_map.h b/components/esp32/include/soc/gpio_sig_map.h new file mode 100644 index 0000000000..dad22f92f8 --- /dev/null +++ b/components/esp32/include/soc/gpio_sig_map.h @@ -0,0 +1,422 @@ +// Copyright 2015-2016 Espressif Systems (Shanghai) PTE LTD +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at + +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +#ifndef _SOC_GPIO_SIG_MAP_H_ +#define _SOC_GPIO_SIG_MAP_H_ + +#define SPICLK_IN_IDX 0 +#define SPICLK_OUT_IDX 0 +#define SPIQ_IN_IDX 1 +#define SPIQ_OUT_IDX 1 +#define SPID_IN_IDX 2 +#define SPID_OUT_IDX 2 +#define SPIHD_IN_IDX 3 +#define SPIHD_OUT_IDX 3 +#define SPIWP_IN_IDX 4 +#define SPIWP_OUT_IDX 4 +#define SPICS0_IN_IDX 5 +#define SPICS0_OUT_IDX 5 +#define SPICS1_IN_IDX 6 +#define SPICS1_OUT_IDX 6 +#define SPICS2_IN_IDX 7 +#define SPICS2_OUT_IDX 7 +#define HSPICLK_IN_IDX 8 +#define HSPICLK_OUT_IDX 8 +#define HSPIQ_IN_IDX 9 +#define HSPIQ_OUT_IDX 9 +#define HSPID_IN_IDX 10 +#define HSPID_OUT_IDX 10 +#define HSPICS0_IN_IDX 11 +#define HSPICS0_OUT_IDX 11 +#define HSPIHD_IN_IDX 12 +#define HSPIHD_OUT_IDX 12 +#define HSPIWP_IN_IDX 13 +#define HSPIWP_OUT_IDX 13 +#define U0RXD_IN_IDX 14 +#define U0TXD_OUT_IDX 14 +#define U0CTS_IN_IDX 15 +#define U0RTS_OUT_IDX 15 +#define U0DSR_IN_IDX 16 +#define U0DTR_OUT_IDX 16 +#define U1RXD_IN_IDX 17 +#define U1TXD_OUT_IDX 17 +#define U1CTS_IN_IDX 18 +#define U1RTS_OUT_IDX 18 +#define I2CM_SCL_O_IDX 19 +#define I2CM_SDA_I_IDX 20 +#define I2CM_SDA_O_IDX 20 +#define EXT_I2C_SCL_O_IDX 21 +#define EXT_I2C_SDA_O_IDX 22 +#define EXT_I2C_SDA_I_IDX 22 +#define I2S0O_BCK_IN_IDX 23 +#define I2S0O_BCK_OUT_IDX 23 +#define I2S1O_BCK_IN_IDX 24 +#define I2S1O_BCK_OUT_IDX 24 +#define I2S0O_WS_IN_IDX 25 +#define I2S0O_WS_OUT_IDX 25 +#define I2S1O_WS_IN_IDX 26 +#define I2S1O_WS_OUT_IDX 26 +#define I2S0I_BCK_IN_IDX 27 +#define I2S0I_BCK_OUT_IDX 27 +#define I2S0I_WS_IN_IDX 28 +#define I2S0I_WS_OUT_IDX 28 +#define I2CEXT0_SCL_IN_IDX 29 +#define I2CEXT0_SCL_OUT_IDX 29 +#define I2CEXT0_SDA_IN_IDX 30 +#define I2CEXT0_SDA_OUT_IDX 30 +#define PWM0_SYNC0_IN_IDX 31 +#define SDIO_TOHOST_INT_OUT_IDX 31 +#define PWM0_SYNC1_IN_IDX 32 +#define PWM0_OUT0A_IDX 32 +#define PWM0_SYNC2_IN_IDX 33 +#define PWM0_OUT0B_IDX 33 +#define PWM0_F0_IN_IDX 34 +#define PWM0_OUT1A_IDX 34 +#define PWM0_F1_IN_IDX 35 +#define PWM0_OUT1B_IDX 35 +#define PWM0_F2_IN_IDX 36 +#define PWM0_OUT2A_IDX 36 +#define GPIO_BT_ACTIVE_IDX 37 +#define PWM0_OUT2B_IDX 37 +#define GPIO_BT_PRIORITY_IDX 38 +#define PCNT_SIG_CH0_IN0_IDX 39 +#define PCNT_SIG_CH1_IN0_IDX 40 +#define GPIO_WLAN_ACTIVE_IDX 40 +#define PCNT_CTRL_CH0_IN0_IDX 41 +#define BB_DIAG0_IDX 41 +#define PCNT_CTRL_CH1_IN0_IDX 42 +#define BB_DIAG1_IDX 42 +#define PCNT_SIG_CH0_IN1_IDX 43 +#define BB_DIAG2_IDX 43 +#define PCNT_SIG_CH1_IN1_IDX 44 +#define BB_DIAG3_IDX 44 +#define PCNT_CTRL_CH0_IN1_IDX 45 +#define BB_DIAG4_IDX 45 +#define PCNT_CTRL_CH1_IN1_IDX 46 +#define BB_DIAG5_IDX 46 +#define PCNT_SIG_CH0_IN2_IDX 47 +#define BB_DIAG6_IDX 47 +#define PCNT_SIG_CH1_IN2_IDX 48 +#define BB_DIAG7_IDX 48 +#define PCNT_CTRL_CH0_IN2_IDX 49 +#define BB_DIAG8_IDX 49 +#define PCNT_CTRL_CH1_IN2_IDX 50 +#define BB_DIAG9_IDX 50 +#define PCNT_SIG_CH0_IN3_IDX 51 +#define BB_DIAG10_IDX 51 +#define PCNT_SIG_CH1_IN3_IDX 52 +#define BB_DIAG11_IDX 52 +#define PCNT_CTRL_CH0_IN3_IDX 53 +#define BB_DIAG12_IDX 53 +#define PCNT_CTRL_CH1_IN3_IDX 54 +#define BB_DIAG13_IDX 54 +#define PCNT_SIG_CH0_IN4_IDX 55 +#define BB_DIAG14_IDX 55 +#define PCNT_SIG_CH1_IN4_IDX 56 +#define BB_DIAG15_IDX 56 +#define PCNT_CTRL_CH0_IN4_IDX 57 +#define BB_DIAG16_IDX 57 +#define PCNT_CTRL_CH1_IN4_IDX 58 +#define BB_DIAG17_IDX 58 +#define BB_DIAG18_IDX 59 +#define BB_DIAG19_IDX 60 +#define HSPICS1_IN_IDX 61 +#define HSPICS1_OUT_IDX 61 +#define HSPICS2_IN_IDX 62 +#define HSPICS2_OUT_IDX 62 +#define VSPICLK_IN_IDX 63 +#define VSPICLK_OUT_MUX_IDX 63 +#define VSPIQ_IN_IDX 64 +#define VSPIQ_OUT_IDX 64 +#define VSPID_IN_IDX 65 +#define VSPID_OUT_IDX 65 +#define VSPIHD_IN_IDX 66 +#define VSPIHD_OUT_IDX 66 +#define VSPIWP_IN_IDX 67 +#define VSPIWP_OUT_IDX 67 +#define VSPICS0_IN_IDX 68 +#define VSPICS0_OUT_IDX 68 +#define VSPICS1_IN_IDX 69 +#define VSPICS1_OUT_IDX 69 +#define VSPICS2_IN_IDX 70 +#define VSPICS2_OUT_IDX 70 +#define PCNT_SIG_CH0_IN5_IDX 71 +#define LEDC_HS_SIG_OUT0_IDX 71 +#define PCNT_SIG_CH1_IN5_IDX 72 +#define LEDC_HS_SIG_OUT1_IDX 72 +#define PCNT_CTRL_CH0_IN5_IDX 73 +#define LEDC_HS_SIG_OUT2_IDX 73 +#define PCNT_CTRL_CH1_IN5_IDX 74 +#define LEDC_HS_SIG_OUT3_IDX 74 +#define PCNT_SIG_CH0_IN6_IDX 75 +#define LEDC_HS_SIG_OUT4_IDX 75 +#define PCNT_SIG_CH1_IN6_IDX 76 +#define LEDC_HS_SIG_OUT5_IDX 76 +#define PCNT_CTRL_CH0_IN6_IDX 77 +#define LEDC_HS_SIG_OUT6_IDX 77 +#define PCNT_CTRL_CH1_IN6_IDX 78 +#define LEDC_HS_SIG_OUT7_IDX 78 +#define PCNT_SIG_CH0_IN7_IDX 79 +#define LEDC_LS_SIG_OUT0_IDX 79 +#define PCNT_SIG_CH1_IN7_IDX 80 +#define LEDC_LS_SIG_OUT1_IDX 80 +#define PCNT_CTRL_CH0_IN7_IDX 81 +#define LEDC_LS_SIG_OUT2_IDX 81 +#define PCNT_CTRL_CH1_IN7_IDX 82 +#define LEDC_LS_SIG_OUT3_IDX 82 +#define RMT_SIG_IN0_IDX 83 +#define LEDC_LS_SIG_OUT4_IDX 83 +#define RMT_SIG_IN1_IDX 84 +#define LEDC_LS_SIG_OUT5_IDX 84 +#define RMT_SIG_IN2_IDX 85 +#define LEDC_LS_SIG_OUT6_IDX 85 +#define RMT_SIG_IN3_IDX 86 +#define LEDC_LS_SIG_OUT7_IDX 86 +#define RMT_SIG_IN4_IDX 87 +#define RMT_SIG_OUT0_IDX 87 +#define RMT_SIG_IN5_IDX 88 +#define RMT_SIG_OUT1_IDX 88 +#define RMT_SIG_IN6_IDX 89 +#define RMT_SIG_OUT2_IDX 89 +#define RMT_SIG_IN7_IDX 90 +#define RMT_SIG_OUT3_IDX 90 +#define RMT_SIG_OUT4_IDX 91 +#define RMT_SIG_OUT5_IDX 92 +#define EXT_ADC_START_IDX 93 +#define RMT_SIG_OUT6_IDX 93 +#define CAN_RX_IDX 94 +#define RMT_SIG_OUT7_IDX 94 +#define I2CEXT1_SCL_IN_IDX 95 +#define I2CEXT1_SCL_OUT_IDX 95 +#define I2CEXT1_SDA_IN_IDX 96 +#define I2CEXT1_SDA_OUT_IDX 96 +#define HOST_CARD_DETECT_N_1_IDX 97 +#define HOST_CCMD_OD_PULLUP_EN_N_IDX 97 +#define HOST_CARD_DETECT_N_2_IDX 98 +#define HOST_RST_N_1_IDX 98 +#define HOST_CARD_WRITE_PRT_1_IDX 99 +#define HOST_RST_N_2_IDX 99 +#define HOST_CARD_WRITE_PRT_2_IDX 100 +#define GPIO_SD0_OUT_IDX 100 +#define HOST_CARD_INT_N_1_IDX 101 +#define GPIO_SD1_OUT_IDX 101 +#define HOST_CARD_INT_N_2_IDX 102 +#define GPIO_SD2_OUT_IDX 102 +#define PWM1_SYNC0_IN_IDX 103 +#define GPIO_SD3_OUT_IDX 103 +#define PWM1_SYNC1_IN_IDX 104 +#define GPIO_SD4_OUT_IDX 104 +#define PWM1_SYNC2_IN_IDX 105 +#define GPIO_SD5_OUT_IDX 105 +#define PWM1_F0_IN_IDX 106 +#define GPIO_SD6_OUT_IDX 106 +#define PWM1_F1_IN_IDX 107 +#define GPIO_SD7_OUT_IDX 107 +#define PWM1_F2_IN_IDX 108 +#define PWM1_OUT0A_IDX 108 +#define PWM0_CAP0_IN_IDX 109 +#define PWM1_OUT0B_IDX 109 +#define PWM0_CAP1_IN_IDX 110 +#define PWM1_OUT1A_IDX 110 +#define PWM0_CAP2_IN_IDX 111 +#define PWM1_OUT1B_IDX 111 +#define PWM1_CAP0_IN_IDX 112 +#define PWM1_OUT2A_IDX 112 +#define PWM1_CAP1_IN_IDX 113 +#define PWM1_OUT2B_IDX 113 +#define PWM1_CAP2_IN_IDX 114 +#define PWM2_OUT1H_IDX 114 +#define PWM2_FLTA_IDX 115 +#define PWM2_OUT1L_IDX 115 +#define PWM2_FLTB_IDX 116 +#define PWM2_OUT2H_IDX 116 +#define PWM2_CAP1_IN_IDX 117 +#define PWM2_OUT2L_IDX 117 +#define PWM2_CAP2_IN_IDX 118 +#define PWM2_OUT3H_IDX 118 +#define PWM2_CAP3_IN_IDX 119 +#define PWM2_OUT3L_IDX 119 +#define PWM3_FLTA_IDX 120 +#define PWM2_OUT4H_IDX 120 +#define PWM3_FLTB_IDX 121 +#define PWM2_OUT4L_IDX 121 +#define PWM3_CAP1_IN_IDX 122 +#define PWM3_CAP2_IN_IDX 123 +#define CAN_TX_IDX 123 +#define PWM3_CAP3_IN_IDX 124 +#define CAN_BUS_OFF_ON_IDX 124 +#define CAN_CLKOUT_IDX 125 +#define SPID4_IN_IDX 128 +#define SPID4_OUT_IDX 128 +#define SPID5_IN_IDX 129 +#define SPID5_OUT_IDX 129 +#define SPID6_IN_IDX 130 +#define SPID6_OUT_IDX 130 +#define SPID7_IN_IDX 131 +#define SPID7_OUT_IDX 131 +#define HSPID4_IN_IDX 132 +#define HSPID4_OUT_IDX 132 +#define HSPID5_IN_IDX 133 +#define HSPID5_OUT_IDX 133 +#define HSPID6_IN_IDX 134 +#define HSPID6_OUT_IDX 134 +#define HSPID7_IN_IDX 135 +#define HSPID7_OUT_IDX 135 +#define VSPID4_IN_IDX 136 +#define VSPID4_OUT_IDX 136 +#define VSPID5_IN_IDX 137 +#define VSPID5_OUT_IDX 137 +#define VSPID6_IN_IDX 138 +#define VSPID6_OUT_IDX 138 +#define VSPID7_IN_IDX 139 +#define VSPID7_OUT_IDX 139 +#define I2S0I_DATA_IN0_IDX 140 +#define I2S0O_DATA_OUT0_IDX 140 +#define I2S0I_DATA_IN1_IDX 141 +#define I2S0O_DATA_OUT1_IDX 141 +#define I2S0I_DATA_IN2_IDX 142 +#define I2S0O_DATA_OUT2_IDX 142 +#define I2S0I_DATA_IN3_IDX 143 +#define I2S0O_DATA_OUT3_IDX 143 +#define I2S0I_DATA_IN4_IDX 144 +#define I2S0O_DATA_OUT4_IDX 144 +#define I2S0I_DATA_IN5_IDX 145 +#define I2S0O_DATA_OUT5_IDX 145 +#define I2S0I_DATA_IN6_IDX 146 +#define I2S0O_DATA_OUT6_IDX 146 +#define I2S0I_DATA_IN7_IDX 147 +#define I2S0O_DATA_OUT7_IDX 147 +#define I2S0I_DATA_IN8_IDX 148 +#define I2S0O_DATA_OUT8_IDX 148 +#define I2S0I_DATA_IN9_IDX 149 +#define I2S0O_DATA_OUT9_IDX 149 +#define I2S0I_DATA_IN10_IDX 150 +#define I2S0O_DATA_OUT10_IDX 150 +#define I2S0I_DATA_IN11_IDX 151 +#define I2S0O_DATA_OUT11_IDX 151 +#define I2S0I_DATA_IN12_IDX 152 +#define I2S0O_DATA_OUT12_IDX 152 +#define I2S0I_DATA_IN13_IDX 153 +#define I2S0O_DATA_OUT13_IDX 153 +#define I2S0I_DATA_IN14_IDX 154 +#define I2S0O_DATA_OUT14_IDX 154 +#define I2S0I_DATA_IN15_IDX 155 +#define I2S0O_DATA_OUT15_IDX 155 +#define I2S0O_DATA_OUT16_IDX 156 +#define I2S0O_DATA_OUT17_IDX 157 +#define I2S0O_DATA_OUT18_IDX 158 +#define I2S0O_DATA_OUT19_IDX 159 +#define I2S0O_DATA_OUT20_IDX 160 +#define I2S0O_DATA_OUT21_IDX 161 +#define I2S0O_DATA_OUT22_IDX 162 +#define I2S0O_DATA_OUT23_IDX 163 +#define I2S1I_BCK_IN_IDX 164 +#define I2S1I_BCK_OUT_IDX 164 +#define I2S1I_WS_IN_IDX 165 +#define I2S1I_WS_OUT_IDX 165 +#define I2S1I_DATA_IN0_IDX 166 +#define I2S1O_DATA_OUT0_IDX 166 +#define I2S1I_DATA_IN1_IDX 167 +#define I2S1O_DATA_OUT1_IDX 167 +#define I2S1I_DATA_IN2_IDX 168 +#define I2S1O_DATA_OUT2_IDX 168 +#define I2S1I_DATA_IN3_IDX 169 +#define I2S1O_DATA_OUT3_IDX 169 +#define I2S1I_DATA_IN4_IDX 170 +#define I2S1O_DATA_OUT4_IDX 170 +#define I2S1I_DATA_IN5_IDX 171 +#define I2S1O_DATA_OUT5_IDX 171 +#define I2S1I_DATA_IN6_IDX 172 +#define I2S1O_DATA_OUT6_IDX 172 +#define I2S1I_DATA_IN7_IDX 173 +#define I2S1O_DATA_OUT7_IDX 173 +#define I2S1I_DATA_IN8_IDX 174 +#define I2S1O_DATA_OUT8_IDX 174 +#define I2S1I_DATA_IN9_IDX 175 +#define I2S1O_DATA_OUT9_IDX 175 +#define I2S1I_DATA_IN10_IDX 176 +#define I2S1O_DATA_OUT10_IDX 176 +#define I2S1I_DATA_IN11_IDX 177 +#define I2S1O_DATA_OUT11_IDX 177 +#define I2S1I_DATA_IN12_IDX 178 +#define I2S1O_DATA_OUT12_IDX 178 +#define I2S1I_DATA_IN13_IDX 179 +#define I2S1O_DATA_OUT13_IDX 179 +#define I2S1I_DATA_IN14_IDX 180 +#define I2S1O_DATA_OUT14_IDX 180 +#define I2S1I_DATA_IN15_IDX 181 +#define I2S1O_DATA_OUT15_IDX 181 +#define I2S1O_DATA_OUT16_IDX 182 +#define I2S1O_DATA_OUT17_IDX 183 +#define I2S1O_DATA_OUT18_IDX 184 +#define I2S1O_DATA_OUT19_IDX 185 +#define I2S1O_DATA_OUT20_IDX 186 +#define I2S1O_DATA_OUT21_IDX 187 +#define I2S1O_DATA_OUT22_IDX 188 +#define I2S1O_DATA_OUT23_IDX 189 +#define I2S0I_H_SYNC_IDX 190 +#define PWM3_OUT1H_IDX 190 +#define I2S0I_V_SYNC_IDX 191 +#define PWM3_OUT1L_IDX 191 +#define I2S0I_H_ENABLE_IDX 192 +#define PWM3_OUT2H_IDX 192 +#define I2S1I_H_SYNC_IDX 193 +#define PWM3_OUT2L_IDX 193 +#define I2S1I_V_SYNC_IDX 194 +#define PWM3_OUT3H_IDX 194 +#define I2S1I_H_ENABLE_IDX 195 +#define PWM3_OUT3L_IDX 195 +#define PWM3_OUT4H_IDX 196 +#define PWM3_OUT4L_IDX 197 +#define U2RXD_IN_IDX 198 +#define U2TXD_OUT_IDX 198 +#define U2CTS_IN_IDX 199 +#define U2RTS_OUT_IDX 199 +#define EMAC_MDC_I_IDX 200 +#define EMAC_MDC_O_IDX 200 +#define EMAC_MDI_I_IDX 201 +#define EMAC_MDO_O_IDX 201 +#define EMAC_CRS_I_IDX 202 +#define EMAC_CRS_O_IDX 202 +#define EMAC_COL_I_IDX 203 +#define EMAC_COL_O_IDX 203 +#define PCMFSYNC_IN_IDX 204 +#define BT_AUDIO0_IRQ_IDX 204 +#define PCMCLK_IN_IDX 205 +#define BT_AUDIO1_IRQ_IDX 205 +#define PCMDIN_IDX 206 +#define BT_AUDIO2_IRQ_IDX 206 +#define BLE_AUDIO0_IRQ_IDX 207 +#define BLE_AUDIO1_IRQ_IDX 208 +#define BLE_AUDIO2_IRQ_IDX 209 +#define PCMFSYNC_OUT_IDX 210 +#define PCMCLK_OUT_IDX 211 +#define PCMDOUT_IDX 212 +#define BLE_AUDIO_SYNC0_P_IDX 213 +#define BLE_AUDIO_SYNC1_P_IDX 214 +#define BLE_AUDIO_SYNC2_P_IDX 215 +#define ANT_SEL0_IDX 216 +#define ANT_SEL1_IDX 217 +#define ANT_SEL2_IDX 218 +#define ANT_SEL3_IDX 219 +#define ANT_SEL4_IDX 220 +#define ANT_SEL5_IDX 221 +#define ANT_SEL6_IDX 222 +#define ANT_SEL7_IDX 223 +#define SIG_IN_FUNC224_IDX 224 +#define SIG_IN_FUNC225_IDX 225 +#define SIG_IN_FUNC226_IDX 226 +#define SIG_IN_FUNC227_IDX 227 +#define SIG_IN_FUNC228_IDX 228 + +#endif /* _SOC_GPIO_SIG_MAP_H_ */ diff --git a/components/esp32/include/soc/i2s_reg.h b/components/esp32/include/soc/i2s_reg.h new file mode 100644 index 0000000000..4c31a9fae1 --- /dev/null +++ b/components/esp32/include/soc/i2s_reg.h @@ -0,0 +1,579 @@ +// Copyright 2015-2016 Espressif Systems (Shanghai) PTE LTD +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at + +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +#ifndef _SOC_I2S_REG_H_ +#define _SOC_I2S_REG_H_ + +#include "soc.h" + +#define I2SCONF (DR_REG_I2S_BASE + 0x0008) +#define I2S_I2S_SIG_LOOPBACK (BIT(18)) +#define I2S_I2S_SIG_LOOPBACK_S 18 +#define I2S_RX_MSB_RIGHT (BIT(17)) +#define I2S_RX_MSB_RIGHT_S 17 +#define I2S_TX_MSB_RIGHT (BIT(16)) +#define I2S_TX_MSB_RIGHT_S 16 +#define I2S_I2S_RX_MONO (BIT(15)) +#define I2S_I2S_RX_MONO_S 15 +#define I2S_I2S_TX_MONO (BIT(14)) +#define I2S_I2S_TX_MONO_S 14 +#define I2S_I2S_RX_SHORT_SYNC (BIT(13)) +#define I2S_I2S_RX_SHORT_SYNC_S 13 +#define I2S_I2S_TX_SHORT_SYNC (BIT(12)) +#define I2S_I2S_TX_SHORT_SYNC_S 12 +#define I2S_RX_MSB_SHIFT (BIT(11)) +#define I2S_RX_MSB_SHIFT_S 11 +#define I2S_TX_MSB_SHIFT (BIT(10)) +#define I2S_TX_MSB_SHIFT_S 10 +#define I2S_RX_RIGHT_FIRST (BIT(9)) +#define I2S_RX_RIGHT_FIRST_S 9 +#define I2S_TX_RIGHT_FIRST (BIT(8)) +#define I2S_TX_RIGHT_FIRST_S 8 +#define I2S_RX_SLAVE_MOD (BIT(7)) +#define I2S_RX_SLAVE_MOD_S 7 +#define I2S_TX_SLAVE_MOD (BIT(6)) +#define I2S_TX_SLAVE_MOD_S 6 +#define I2S_I2S_RX_START (BIT(5)) +#define I2S_I2S_RX_START_S 5 +#define I2S_I2S_TX_START (BIT(4)) +#define I2S_I2S_TX_START_S 4 +#define I2S_I2S_RX_FIFO_RESET (BIT(3)) +#define I2S_I2S_RX_FIFO_RESET_S 3 +#define I2S_I2S_TX_FIFO_RESET (BIT(2)) +#define I2S_I2S_TX_FIFO_RESET_S 2 +#define I2S_I2S_RX_RESET (BIT(1)) +#define I2S_I2S_RX_RESET_S 1 +#define I2S_I2S_TX_RESET (BIT(0)) +#define I2S_I2S_TX_RESET_S 0 + +#define I2SINT_RAW (DR_REG_I2S_BASE + 0x000c) +#define I2S_I2S_OUT_TOTAL_EOF_INT_RAW (BIT(16)) +#define I2S_I2S_OUT_TOTAL_EOF_INT_RAW_S 16 +#define I2S_I2S_IN_DSCR_EMPTY_INT_RAW (BIT(15)) +#define I2S_I2S_IN_DSCR_EMPTY_INT_RAW_S 15 +#define I2S_I2S_OUT_DSCR_ERR_INT_RAW (BIT(14)) +#define I2S_I2S_OUT_DSCR_ERR_INT_RAW_S 14 +#define I2S_I2S_IN_DSCR_ERR_INT_RAW (BIT(13)) +#define I2S_I2S_IN_DSCR_ERR_INT_RAW_S 13 +#define I2S_I2S_OUT_EOF_INT_RAW (BIT(12)) +#define I2S_I2S_OUT_EOF_INT_RAW_S 12 +#define I2S_I2S_OUT_DONE_INT_RAW (BIT(11)) +#define I2S_I2S_OUT_DONE_INT_RAW_S 11 +#define I2S_I2S_IN_ERR_EOF_INT_RAW (BIT(10)) +#define I2S_I2S_IN_ERR_EOF_INT_RAW_S 10 +#define I2S_I2S_IN_SUC_EOF_INT_RAW (BIT(9)) +#define I2S_I2S_IN_SUC_EOF_INT_RAW_S 9 +#define I2S_I2S_IN_DONE_INT_RAW (BIT(8)) +#define I2S_I2S_IN_DONE_INT_RAW_S 8 +#define I2S_I2S_TX_HUNG_INT_RAW (BIT(7)) +#define I2S_I2S_TX_HUNG_INT_RAW_S 7 +#define I2S_I2S_RX_HUNG_INT_RAW (BIT(6)) +#define I2S_I2S_RX_HUNG_INT_RAW_S 6 +#define I2S_I2S_TX_REMPTY_INT_RAW (BIT(5)) +#define I2S_I2S_TX_REMPTY_INT_RAW_S 5 +#define I2S_I2S_TX_WFULL_INT_RAW (BIT(4)) +#define I2S_I2S_TX_WFULL_INT_RAW_S 4 +#define I2S_I2S_RX_REMPTY_INT_RAW (BIT(3)) +#define I2S_I2S_RX_REMPTY_INT_RAW_S 3 +#define I2S_I2S_RX_WFULL_INT_RAW (BIT(2)) +#define I2S_I2S_RX_WFULL_INT_RAW_S 2 +#define I2S_I2S_TX_PUT_DATA_INT_RAW (BIT(1)) +#define I2S_I2S_TX_PUT_DATA_INT_RAW_S 1 +#define I2S_I2S_RX_TAKE_DATA_INT_RAW (BIT(0)) +#define I2S_I2S_RX_TAKE_DATA_INT_RAW_S 0 + +#define I2SINT_ST (DR_REG_I2S_BASE + 0x0010) +#define I2S_I2S_OUT_TOTAL_EOF_INT_ST (BIT(16)) +#define I2S_I2S_OUT_TOTAL_EOF_INT_ST_S 16 +#define I2S_I2S_IN_DSCR_EMPTY_INT_ST (BIT(15)) +#define I2S_I2S_IN_DSCR_EMPTY_INT_ST_S 15 +#define I2S_I2S_OUT_DSCR_ERR_INT_ST (BIT(14)) +#define I2S_I2S_OUT_DSCR_ERR_INT_ST_S 14 +#define I2S_I2S_IN_DSCR_ERR_INT_ST (BIT(13)) +#define I2S_I2S_IN_DSCR_ERR_INT_ST_S 13 +#define I2S_I2S_OUT_EOF_INT_ST (BIT(12)) +#define I2S_I2S_OUT_EOF_INT_ST_S 12 +#define I2S_I2S_OUT_DONE_INT_ST (BIT(11)) +#define I2S_I2S_OUT_DONE_INT_ST_S 11 +#define I2S_I2S_IN_ERR_EOF_INT_ST (BIT(10)) +#define I2S_I2S_IN_ERR_EOF_INT_ST_S 10 +#define I2S_I2S_IN_SUC_EOF_INT_ST (BIT(9)) +#define I2S_I2S_IN_SUC_EOF_INT_ST_S 9 +#define I2S_I2S_IN_DONE_INT_ST (BIT(8)) +#define I2S_I2S_IN_DONE_INT_ST_S 8 +#define I2S_I2S_TX_HUNG_INT_ST (BIT(7)) +#define I2S_I2S_TX_HUNG_INT_ST_S 7 +#define I2S_I2S_RX_HUNG_INT_ST (BIT(6)) +#define I2S_I2S_RX_HUNG_INT_ST_S 6 +#define I2S_I2S_TX_REMPTY_INT_ST (BIT(5)) +#define I2S_I2S_TX_REMPTY_INT_ST_S 5 +#define I2S_I2S_TX_WFULL_INT_ST (BIT(4)) +#define I2S_I2S_TX_WFULL_INT_ST_S 4 +#define I2S_I2S_RX_REMPTY_INT_ST (BIT(3)) +#define I2S_I2S_RX_REMPTY_INT_ST_S 3 +#define I2S_I2S_RX_WFULL_INT_ST (BIT(2)) +#define I2S_I2S_RX_WFULL_INT_ST_S 2 +#define I2S_I2S_TX_PUT_DATA_INT_ST (BIT(1)) +#define I2S_I2S_TX_PUT_DATA_INT_ST_S 1 +#define I2S_I2S_RX_TAKE_DATA_INT_ST (BIT(0)) +#define I2S_I2S_RX_TAKE_DATA_INT_ST_S 0 + +#define I2SINT_ENA (DR_REG_I2S_BASE + 0x0014) +#define I2S_I2S_OUT_TOTAL_EOF_INT_ENA (BIT(16)) +#define I2S_I2S_OUT_TOTAL_EOF_INT_ENA_S 16 +#define I2S_I2S_IN_DSCR_EMPTY_INT_ENA (BIT(15)) +#define I2S_I2S_IN_DSCR_EMPTY_INT_ENA_S 15 +#define I2S_I2S_OUT_DSCR_ERR_INT_ENA (BIT(14)) +#define I2S_I2S_OUT_DSCR_ERR_INT_ENA_S 14 +#define I2S_I2S_IN_DSCR_ERR_INT_ENA (BIT(13)) +#define I2S_I2S_IN_DSCR_ERR_INT_ENA_S 13 +#define I2S_I2S_OUT_EOF_INT_ENA (BIT(12)) +#define I2S_I2S_OUT_EOF_INT_ENA_S 12 +#define I2S_I2S_OUT_DONE_INT_ENA (BIT(11)) +#define I2S_I2S_OUT_DONE_INT_ENA_S 11 +#define I2S_I2S_IN_ERR_EOF_INT_ENA (BIT(10)) +#define I2S_I2S_IN_ERR_EOF_INT_ENA_S 10 +#define I2S_I2S_IN_SUC_EOF_INT_ENA (BIT(9)) +#define I2S_I2S_IN_SUC_EOF_INT_ENA_S 9 +#define I2S_I2S_IN_DONE_INT_ENA (BIT(8)) +#define I2S_I2S_IN_DONE_INT_ENA_S 8 +#define I2S_I2S_TX_HUNG_INT_ENA (BIT(7)) +#define I2S_I2S_TX_HUNG_INT_ENA_S 7 +#define I2S_I2S_RX_HUNG_INT_ENA (BIT(6)) +#define I2S_I2S_RX_HUNG_INT_ENA_S 6 +#define I2S_I2S_TX_REMPTY_INT_ENA (BIT(5)) +#define I2S_I2S_TX_REMPTY_INT_ENA_S 5 +#define I2S_I2S_TX_WFULL_INT_ENA (BIT(4)) +#define I2S_I2S_TX_WFULL_INT_ENA_S 4 +#define I2S_I2S_RX_REMPTY_INT_ENA (BIT(3)) +#define I2S_I2S_RX_REMPTY_INT_ENA_S 3 +#define I2S_I2S_RX_WFULL_INT_ENA (BIT(2)) +#define I2S_I2S_RX_WFULL_INT_ENA_S 2 +#define I2S_I2S_TX_PUT_DATA_INT_ENA (BIT(1)) +#define I2S_I2S_TX_PUT_DATA_INT_ENA_S 1 +#define I2S_I2S_RX_TAKE_DATA_INT_ENA (BIT(0)) +#define I2S_I2S_RX_TAKE_DATA_INT_ENA_S 0 + +#define I2SINT_CLR (DR_REG_I2S_BASE + 0x0018) +#define I2S_I2S_OUT_TOTAL_EOF_INT_CLR (BIT(16)) +#define I2S_I2S_OUT_TOTAL_EOF_INT_CLR_S 16 +#define I2S_I2S_IN_DSCR_EMPTY_INT_CLR (BIT(15)) +#define I2S_I2S_IN_DSCR_EMPTY_INT_CLR_S 15 +#define I2S_I2S_OUT_DSCR_ERR_INT_CLR (BIT(14)) +#define I2S_I2S_OUT_DSCR_ERR_INT_CLR_S 14 +#define I2S_I2S_IN_DSCR_ERR_INT_CLR (BIT(13)) +#define I2S_I2S_IN_DSCR_ERR_INT_CLR_S 13 +#define I2S_I2S_OUT_EOF_INT_CLR (BIT(12)) +#define I2S_I2S_OUT_EOF_INT_CLR_S 12 +#define I2S_I2S_OUT_DONE_INT_CLR (BIT(11)) +#define I2S_I2S_OUT_DONE_INT_CLR_S 11 +#define I2S_I2S_IN_ERR_EOF_INT_CLR (BIT(10)) +#define I2S_I2S_IN_ERR_EOF_INT_CLR_S 10 +#define I2S_I2S_IN_SUC_EOF_INT_CLR (BIT(9)) +#define I2S_I2S_IN_SUC_EOF_INT_CLR_S 9 +#define I2S_I2S_IN_DONE_INT_CLR (BIT(8)) +#define I2S_I2S_IN_DONE_INT_CLR_S 8 +#define I2S_I2S_TX_HUNG_INT_CLR (BIT(7)) +#define I2S_I2S_TX_HUNG_INT_CLR_S 7 +#define I2S_I2S_RX_HUNG_INT_CLR (BIT(6)) +#define I2S_I2S_RX_HUNG_INT_CLR_S 6 +#define I2S_I2S_TX_REMPTY_INT_CLR (BIT(5)) +#define I2S_I2S_TX_REMPTY_INT_CLR_S 5 +#define I2S_I2S_TX_WFULL_INT_CLR (BIT(4)) +#define I2S_I2S_TX_WFULL_INT_CLR_S 4 +#define I2S_I2S_RX_REMPTY_INT_CLR (BIT(3)) +#define I2S_I2S_RX_REMPTY_INT_CLR_S 3 +#define I2S_I2S_RX_WFULL_INT_CLR (BIT(2)) +#define I2S_I2S_RX_WFULL_INT_CLR_S 2 +#define I2S_I2S_PUT_DATA_INT_CLR (BIT(1)) +#define I2S_I2S_PUT_DATA_INT_CLR_S 1 +#define I2S_I2S_TAKE_DATA_INT_CLR (BIT(0)) +#define I2S_I2S_TAKE_DATA_INT_CLR_S 0 + +#define I2STIMING (DR_REG_I2S_BASE + 0x001c) +#define I2S_TX_BCK_IN_INV (BIT(24)) +#define I2S_TX_BCK_IN_INV_S 24 +#define I2S_DATA_ENABLE_DELAY 0x00000003 +#define I2S_DATA_ENABLE_DELAY_S 22 +#define I2S_RX_DSYNC_SW (BIT(21)) +#define I2S_RX_DSYNC_SW_S 21 +#define I2S_TX_DSYNC_SW (BIT(20)) +#define I2S_TX_DSYNC_SW_S 20 +#define I2S_RX_BCK_OUT_DELAY 0x00000003 +#define I2S_RX_BCK_OUT_DELAY_S 18 +#define I2S_RX_WS_OUT_DELAY 0x00000003 +#define I2S_RX_WS_OUT_DELAY_S 16 +#define I2S_TX_SD_OUT_DELAY 0x00000003 +#define I2S_TX_SD_OUT_DELAY_S 14 +#define I2S_TX_WS_OUT_DELAY 0x00000003 +#define I2S_TX_WS_OUT_DELAY_S 12 +#define I2S_TX_BCK_OUT_DELAY 0x00000003 +#define I2S_TX_BCK_OUT_DELAY_S 10 +#define I2S_RX_SD_IN_DELAY 0x00000003 +#define I2S_RX_SD_IN_DELAY_S 8 +#define I2S_RX_WS_IN_DELAY 0x00000003 +#define I2S_RX_WS_IN_DELAY_S 6 +#define I2S_RX_BCK_IN_DELAY 0x00000003 +#define I2S_RX_BCK_IN_DELAY_S 4 +#define I2S_TX_WS_IN_DELAY 0x00000003 +#define I2S_TX_WS_IN_DELAY_S 2 +#define I2S_TX_BCK_IN_DELAY 0x00000003 +#define I2S_TX_BCK_IN_DELAY_S 0 + +#define I2S_FIFO_CONF (DR_REG_I2S_BASE + 0x0020) +#define I2S_I2S_RX_FIFO_MOD_FORCE_EN (BIT(20)) +#define I2S_I2S_RX_FIFO_MOD_FORCE_EN_S 20 +#define I2S_I2S_TX_FIFO_MOD_FORCE_EN (BIT(19)) +#define I2S_I2S_TX_FIFO_MOD_FORCE_EN_S 19 +#define I2S_I2S_RX_FIFO_MOD 0x00000007 +#define I2S_I2S_RX_FIFO_MOD_S 16 +#define I2S_I2S_TX_FIFO_MOD 0x00000007 +#define I2S_I2S_TX_FIFO_MOD_S 13 +#define I2S_I2S_DSCR_EN (BIT(12)) +#define I2S_I2S_DSCR_EN_S 12 +#define I2S_I2S_TX_DATA_NUM 0x0000003F +#define I2S_I2S_TX_DATA_NUM_S 6 +#define I2S_I2S_RX_DATA_NUM 0x0000003F +#define I2S_I2S_RX_DATA_NUM_S 0 + +#define I2SRXEOF_NUM (DR_REG_I2S_BASE + 0x0024) +#define I2S_I2S_RX_EOF_NUM 0xFFFFFFFF +#define I2S_I2S_RX_EOF_NUM_S 0 + +#define I2SCONF_SIGLE_DATA (DR_REG_I2S_BASE + 0x0028) +#define I2S_I2S_SIGLE_DATA 0xFFFFFFFF +#define I2S_I2S_SIGLE_DATA_S 0 + +#define I2SCONF_CHAN (DR_REG_I2S_BASE + 0x002c) +#define I2S_RX_CHAN_MOD 0x00000003 +#define I2S_RX_CHAN_MOD_S 3 +#define I2S_TX_CHAN_MOD 0x00000007 +#define I2S_TX_CHAN_MOD_S 0 + +#define I2SOUT_LINK (DR_REG_I2S_BASE + 0x0030) +#define I2S_OUTLINK_PARK (BIT(31)) +#define I2S_OUTLINK_PARK_S 31 +#define I2S_I2S_OUTLINK_RESTART (BIT(30)) +#define I2S_I2S_OUTLINK_RESTART_S 30 +#define I2S_I2S_OUTLINK_START (BIT(29)) +#define I2S_I2S_OUTLINK_START_S 29 +#define I2S_I2S_OUTLINK_STOP (BIT(28)) +#define I2S_I2S_OUTLINK_STOP_S 28 +#define I2S_I2S_OUTLINK_ADDR 0x000FFFFF +#define I2S_I2S_OUTLINK_ADDR_S 0 + +#define I2SIN_LINK (DR_REG_I2S_BASE + 0x0034) +#define I2S_INLINK_PARK (BIT(31)) +#define I2S_INLINK_PARK_S 31 +#define I2S_I2S_INLINK_RESTART (BIT(30)) +#define I2S_I2S_INLINK_RESTART_S 30 +#define I2S_I2S_INLINK_START (BIT(29)) +#define I2S_I2S_INLINK_START_S 29 +#define I2S_I2S_INLINK_STOP (BIT(28)) +#define I2S_I2S_INLINK_STOP_S 28 +#define I2S_I2S_INLINK_ADDR 0x000FFFFF +#define I2S_I2S_INLINK_ADDR_S 0 + +#define I2S_OUT_EOF_DES_ADDR (DR_REG_I2S_BASE + 0x0038) +#define I2S_I2S_OUT_EOF_DES_ADDR 0xFFFFFFFF +#define I2S_I2S_OUT_EOF_DES_ADDR_S 0 + +#define I2S_IN_EOF_DES_ADDR (DR_REG_I2S_BASE + 0x003c) +#define I2S_I2S_IN_SUC_EOF_DES_ADDR 0xFFFFFFFF +#define I2S_I2S_IN_SUC_EOF_DES_ADDR_S 0 + +#define I2S_OUT_EOF_BFR_DES_ADDR (DR_REG_I2S_BASE + 0x0040) +#define I2S_I2S_OUT_EOF_BFR_DES_ADDR 0xFFFFFFFF +#define I2S_I2S_OUT_EOF_BFR_DES_ADDR_S 0 + +#define I2S_AHB_TEST (DR_REG_I2S_BASE + 0x0044) +#define I2S_I2S_AHB_TESTADDR 0x00000003 +#define I2S_I2S_AHB_TESTADDR_S 4 +#define I2S_I2S_AHB_TESTMODE 0x00000007 +#define I2S_I2S_AHB_TESTMODE_S 0 + +#define I2S_INLINK_DSCR (DR_REG_I2S_BASE + 0x0048) +#define I2S_I2S_INLINK_DSCR 0xFFFFFFFF +#define I2S_I2S_INLINK_DSCR_S 0 + +#define I2S_INLINK_DSCR_BF0 (DR_REG_I2S_BASE + 0x004C) +#define I2S_I2S_INLINK_DSCR_BF0 0xFFFFFFFF +#define I2S_I2S_INLINK_DSCR_BF0_S 0 + +#define I2S_INLINK_DSCR_BF1 (DR_REG_I2S_BASE + 0x0050) +#define I2S_I2S_INLINK_DSCR_BF1 0xFFFFFFFF +#define I2S_I2S_INLINK_DSCR_BF1_S 0 + +#define I2S_OUTLINK_DSCR (DR_REG_I2S_BASE + 0x0054) +#define I2S_I2S_OUTLINK_DSCR 0xFFFFFFFF +#define I2S_I2S_OUTLINK_DSCR_S 0 + +#define I2S_OUTLINK_DSCR_BF0 (DR_REG_I2S_BASE + 0x0058) +#define I2S_I2S_OUTLINK_DSCR_BF0 0xFFFFFFFF +#define I2S_I2S_OUTLINK_DSCR_BF0_S 0 + +#define I2S_OUTLINK_DSCR_BF1 (DR_REG_I2S_BASE + 0x005C) +#define I2S_I2S_OUTLINK_DSCR_BF1 0xFFFFFFFF +#define I2S_I2S_OUTLINK_DSCR_BF1_S 0 + +#define I2S_LC_CONF (DR_REG_I2S_BASE + 0x0060) +#define I2S_I2S_MEM_TRANS_EN (BIT(13)) +#define I2S_I2S_MEM_TRANS_EN_S 13 +#define I2S_I2S_CHECK_OWNER (BIT(12)) +#define I2S_I2S_CHECK_OWNER_S 12 +#define I2S_I2S_OUT_DATA_BURST_EN (BIT(11)) +#define I2S_I2S_OUT_DATA_BURST_EN_S 11 +#define I2S_I2S_INDSCR_BURST_EN (BIT(10)) +#define I2S_I2S_INDSCR_BURST_EN_S 10 +#define I2S_I2S_OUTDSCR_BURST_EN (BIT(9)) +#define I2S_I2S_OUTDSCR_BURST_EN_S 9 +#define I2S_I2S_OUT_EOF_MODE (BIT(8)) +#define I2S_I2S_OUT_EOF_MODE_S 8 +#define I2S_I2S_OUT_NO_RESTART_CLR (BIT(7)) +#define I2S_I2S_OUT_NO_RESTART_CLR_S 7 +#define I2S_I2S_OUT_AUTO_WRBACK (BIT(6)) +#define I2S_I2S_OUT_AUTO_WRBACK_S 6 +#define I2S_I2S_IN_LOOP_TEST (BIT(5)) +#define I2S_I2S_IN_LOOP_TEST_S 5 +#define I2S_I2S_OUT_LOOP_TEST (BIT(4)) +#define I2S_I2S_OUT_LOOP_TEST_S 4 +#define I2S_I2S_AHBM_RST (BIT(3)) +#define I2S_I2S_AHBM_RST_S 3 +#define I2S_I2S_AHBM_FIFO_RST (BIT(2)) +#define I2S_I2S_AHBM_FIFO_RST_S 2 +#define I2S_I2S_OUT_RST (BIT(1)) +#define I2S_I2S_OUT_RST_S 1 +#define I2S_I2S_IN_RST (BIT(0)) +#define I2S_I2S_IN_RST_S 0 + +#define I2S_OUTFIFO_PUSH (DR_REG_I2S_BASE + 0x0064) +#define I2S_I2S_OUTFIFO_PUSH (BIT(16)) +#define I2S_I2S_OUTFIFO_PUSH_S 16 +#define I2S_I2S_OUTFIFO_WDATA 0x000001FF +#define I2S_I2S_OUTFIFO_WDATA_S 0 + +#define I2S_INFIFO_POP (DR_REG_I2S_BASE + 0x0068) +#define I2S_I2S_INFIFO_POP (BIT(16)) +#define I2S_I2S_INFIFO_POP_S 16 +#define I2S_I2S_INFIFO_RDATA 0x00000FFF +#define I2S_I2S_INFIFO_RDATA_S 0 + +#define I2S_LC_STATE0 (DR_REG_I2S_BASE + 0x006C) +#define I2S_I2S_LC_STATE0 0xFFFFFFFF +#define I2S_I2S_LC_STATE0_S 0 + +#define I2S_LC_STATE1 (DR_REG_I2S_BASE + 0x0070) +#define I2S_I2S_LC_STATE1 0xFFFFFFFF +#define I2S_I2S_LC_STATE1_S 0 + +#define I2S_LC_HUNG_CONF (DR_REG_I2S_BASE + 0x0074) +#define I2S_I2S_LC_FIFO_TIMEOUT_ENA (BIT(11)) +#define I2S_I2S_LC_FIFO_TIMEOUT_ENA_S 11 +#define I2S_I2S_LC_FIFO_TIMEOUT_SHIFT 0x00000007 +#define I2S_I2S_LC_FIFO_TIMEOUT_SHIFT_S 8 +#define I2S_I2S_LC_FIFO_TIMEOUT 0x000000FF +#define I2S_I2S_LC_FIFO_TIMEOUT_S 0 + +#define I2S_CVSD_CONF0 (DR_REG_I2S_BASE + 0x0080) +#define I2S_I2S_CVSD_Y_MIN 0x0000FFFF +#define I2S_I2S_CVSD_Y_MIN_S 16 +#define I2S_I2S_CVSD_Y_MAX 0x0000FFFF +#define I2S_I2S_CVSD_Y_MAX_S 0 + +#define I2S_CVSD_CONF1 (DR_REG_I2S_BASE + 0x0084) +#define I2S_I2S_CVSD_SIGMA_MIN 0x0000FFFF +#define I2S_I2S_CVSD_SIGMA_MIN_S 16 +#define I2S_I2S_CVSD_SIGMA_MAX 0x0000FFFF +#define I2S_I2S_CVSD_SIGMA_MAX_S 0 + +#define I2S_CVSD_CONF2 (DR_REG_I2S_BASE + 0x0088) +#define I2S_I2S_CVSD_H 0x00000007 +#define I2S_I2S_CVSD_H_S 16 +#define I2S_I2S_CVSD_BETA 0x000003FF +#define I2S_I2S_CVSD_BETA_S 6 +#define I2S_I2S_CVSD_J 0x00000007 +#define I2S_I2S_CVSD_J_S 3 +#define I2S_I2S_CVSD_K 0x00000007 +#define I2S_I2S_CVSD_K_S 0 + +#define I2S_PLC_CONF0 (DR_REG_I2S_BASE + 0x008C) +#define I2S_I2S_N_MIN_ERR 0x00000007 +#define I2S_I2S_N_MIN_ERR_S 25 +#define I2S_I2S_PACK_LEN_8K 0x0000001F +#define I2S_I2S_PACK_LEN_8K_S 20 +#define I2S_I2S_MAX_SLIDE_SAMPLE 0x000000FF +#define I2S_I2S_MAX_SLIDE_SAMPLE_S 12 +#define I2S_I2S_SHIFT_RATE 0x00000007 +#define I2S_I2S_SHIFT_RATE_S 9 +#define I2S_I2S_N_ERR_SEG 0x00000007 +#define I2S_I2S_N_ERR_SEG_S 6 +#define I2S_I2S_GOOD_PACK_MAX 0x0000003F +#define I2S_I2S_GOOD_PACK_MAX_S 0 + +#define I2S_PLC_CONF1 (DR_REG_I2S_BASE + 0x0090) +#define I2S_I2S_SLIDE_WIN_LEN 0x000000FF +#define I2S_I2S_SLIDE_WIN_LEN_S 24 +#define I2S_I2S_BAD_OLA_WIN2_PARA 0x000000FF +#define I2S_I2S_BAD_OLA_WIN2_PARA_S 16 +#define I2S_I2S_BAD_OLA_WIN2_PARA_SHIFT 0x0000000F +#define I2S_I2S_BAD_OLA_WIN2_PARA_SHIFT_S 12 +#define I2S_I2S_BAD_CEF_ATTEN_PARA_SHIFT 0x0000000F +#define I2S_I2S_BAD_CEF_ATTEN_PARA_SHIFT_S 8 +#define I2S_I2S_BAD_CEF_ATTEN_PARA 0x000000FF +#define I2S_I2S_BAD_CEF_ATTEN_PARA_S 0 + +#define I2S_PLC_CONF2 (DR_REG_I2S_BASE + 0x0094) +#define I2S_I2S_MIN_PERIOD 0x0000001F +#define I2S_I2S_MIN_PERIOD_S 2 +#define I2S_I2S_CVSD_SEG_MOD 0x00000003 +#define I2S_I2S_CVSD_SEG_MOD_S 0 + +#define I2S_ESCO_CONF0 (DR_REG_I2S_BASE + 0x0098) +#define I2S_I2S_PLC2DMA_EN (BIT(12)) +#define I2S_I2S_PLC2DMA_EN_S 12 +#define I2S_I2S_PLC_EN (BIT(11)) +#define I2S_I2S_PLC_EN_S 11 +#define I2S_I2S_CVSD_DEC_RESET (BIT(10)) +#define I2S_I2S_CVSD_DEC_RESET_S 10 +#define I2S_I2S_CVSD_DEC_START (BIT(9)) +#define I2S_I2S_CVSD_DEC_START_S 9 +#define I2S_I2S_ESCO_CVSD_INF_EN (BIT(8)) +#define I2S_I2S_ESCO_CVSD_INF_EN_S 8 +#define I2S_I2S_ESCO_CVSD_PACK_LEN_8K 0x0000001F +#define I2S_I2S_ESCO_CVSD_PACK_LEN_8K_S 3 +#define I2S_I2S_ESCO_CVSD_DEC_PACK_ERR (BIT(2)) +#define I2S_I2S_ESCO_CVSD_DEC_PACK_ERR_S 2 +#define I2S_I2S_ESCO_CHAN_MOD (BIT(1)) +#define I2S_I2S_ESCO_CHAN_MOD_S 1 +#define I2S_I2S_ESCO_EN (BIT(0)) +#define I2S_I2S_ESCO_EN_S 0 + +#define I2S_SCO_CONF0 (DR_REG_I2S_BASE + 0x009c) +#define I2S_I2S_CVSD_ENC_RESET (BIT(3)) +#define I2S_I2S_CVSD_ENC_RESET_S 3 +#define I2S_I2S_CVSD_ENC_START (BIT(2)) +#define I2S_I2S_CVSD_ENC_START_S 2 +#define I2S_I2S_SCO_NO_I2S_EN (BIT(1)) +#define I2S_I2S_SCO_NO_I2S_EN_S 1 +#define I2S_I2S_SCO_WITH_I2S_EN (BIT(0)) +#define I2S_I2S_SCO_WITH_I2S_EN_S 0 + +#define I2SCONF1 (DR_REG_I2S_BASE + 0x00a0) +#define I2S_I2S_TX_ZEROS_RM_EN (BIT(9)) +#define I2S_I2S_TX_ZEROS_RM_EN_S 9 +#define I2S_I2S_TX_STOP_EN (BIT(8)) +#define I2S_I2S_TX_STOP_EN_S 8 +#define I2S_RX_PCM_BYPASS (BIT(7)) +#define I2S_RX_PCM_BYPASS_S 7 +#define I2S_RX_PCM_CONF 0x00000007 +#define I2S_RX_PCM_CONF_S 4 +#define I2S_TX_PCM_BYPASS (BIT(3)) +#define I2S_TX_PCM_BYPASS_S 3 +#define I2S_TX_PCM_CONF 0x00000007 +#define I2S_TX_PCM_CONF_S 0 + +#define I2S_PD_CONF (DR_REG_I2S_BASE + 0x00a4) +#define I2S_PLC_MEM_FORCE_PU (BIT(3)) +#define I2S_PLC_MEM_FORCE_PU_S 3 +#define I2S_PLC_MEM_FORCE_PD (BIT(2)) +#define I2S_PLC_MEM_FORCE_PD_S 2 +#define I2S_I2S_FIFO_FORCE_PU (BIT(1)) +#define I2S_I2S_FIFO_FORCE_PU_S 1 +#define I2S_I2S_FIFO_FORCE_PD (BIT(0)) +#define I2S_I2S_FIFO_FORCE_PD_S 0 + +#define I2SCONF2 (DR_REG_I2S_BASE + 0x00a8) +#define I2S_INTER_VALID_EN (BIT(7)) +#define I2S_INTER_VALID_EN_S 7 +#define I2S_EXT_ADC_START_EN (BIT(6)) +#define I2S_EXT_ADC_START_EN_S 6 +#define I2S_LCD_EN (BIT(5)) +#define I2S_LCD_EN_S 5 +#define I2S_DATA_ENABLE (BIT(4)) +#define I2S_DATA_ENABLE_S 4 +#define I2S_DATA_ENABLE_TEST_EN (BIT(3)) +#define I2S_DATA_ENABLE_TEST_EN_S 3 +#define I2S_LCD_TX_SDX2_EN (BIT(2)) +#define I2S_LCD_TX_SDX2_EN_S 2 +#define I2S_LCD_TX_WRX2_EN (BIT(1)) +#define I2S_LCD_TX_WRX2_EN_S 1 +#define I2S_CAMERA_EN (BIT(0)) +#define I2S_CAMERA_EN_S 0 + +#define I2S_CLKM_CONF (DR_REG_I2S_BASE + 0x00ac) +#define I2S_CLKA_ENA (BIT(21)) +#define I2S_CLKA_ENA_S 21 +#define I2S_CLK_EN (BIT(20)) +#define I2S_CLK_EN_S 20 +#define I2S_CLKM_DIV_A 0x0000003F +#define I2S_CLKM_DIV_A_S 14 +#define I2S_CLKM_DIV_B 0x0000003F +#define I2S_CLKM_DIV_B_S 8 +#define I2S_CLKM_DIV_NUM 0x000000FF +#define I2S_CLKM_DIV_NUM_S 0 + +#define I2S_SAMPLE_RATE_CONF (DR_REG_I2S_BASE + 0x00b0) +#define I2S_RX_BITS_MOD 0x0000003F +#define I2S_RX_BITS_MOD_S 18 +#define I2S_TX_BITS_MOD 0x0000003F +#define I2S_TX_BITS_MOD_S 12 +#define I2S_RX_BCK_DIV_NUM 0x0000003F +#define I2S_RX_BCK_DIV_NUM_S 6 +#define I2S_TX_BCK_DIV_NUM 0x0000003F +#define I2S_TX_BCK_DIV_NUM_S 0 + +#define I2S_PDM_CONF (DR_REG_I2S_BASE + 0x00b4) +#define I2S_TX_PDM_HP_BYPASS (BIT(25)) +#define I2S_TX_PDM_HP_BYPASS_S 25 +#define I2S_RX_PDM_SINC_DSR_16_EN (BIT(24)) +#define I2S_RX_PDM_SINC_DSR_16_EN_S 24 +#define I2S_TX_PDM_SIGMADELTA_IN_SHIFT 0x00000003 +#define I2S_TX_PDM_SIGMADELTA_IN_SHIFT_S 22 +#define I2S_TX_PDM_SINC_IN_SHIFT 0x00000003 +#define I2S_TX_PDM_SINC_IN_SHIFT_S 20 +#define I2S_TX_PDM_LP_IN_SHIFT 0x00000003 +#define I2S_TX_PDM_LP_IN_SHIFT_S 18 +#define I2S_TX_PDM_HP_IN_SHIFT 0x00000003 +#define I2S_TX_PDM_HP_IN_SHIFT_S 16 +#define I2S_TX_PDM_PRESCALE 0x000000FF +#define I2S_TX_PDM_PRESCALE_S 8 +#define I2S_TX_PDM_SINC_OSR2 0x0000000F +#define I2S_TX_PDM_SINC_OSR2_S 4 +#define I2S_PDM2PCM_CONV_EN (BIT(3)) +#define I2S_PDM2PCM_CONV_EN_S 3 +#define I2S_PCM2PDM_CONV_EN (BIT(2)) +#define I2S_PCM2PDM_CONV_EN_S 2 +#define I2S_RX_PDM_EN (BIT(1)) +#define I2S_RX_PDM_EN_S 1 +#define I2S_TX_PDM_EN (BIT(0)) +#define I2S_TX_PDM_EN_S 0 + +#define I2S_PDM_FREQ_CONF (DR_REG_I2S_BASE + 0x00b8) +#define I2S_TX_PDM_FP 0x000003FF +#define I2S_TX_PDM_FP_S 10 +#define I2S_TX_PDM_FS 0x000003FF +#define I2S_TX_PDM_FS_S 0 + +#define I2S_STATE (DR_REG_I2S_BASE + 0x00bc) +#define I2S_I2S_RX_FIFO_RESET_BACK (BIT(2)) +#define I2S_I2S_RX_FIFO_RESET_BACK_S 2 +#define I2S_I2S_TX_FIFO_RESET_BACK (BIT(1)) +#define I2S_I2S_TX_FIFO_RESET_BACK_S 1 +#define I2S_I2S_TX_IDLE (BIT(0)) +#define I2S_I2S_TX_IDLE_S 0 + +#define I2S_DATE (DR_REG_I2S_BASE + 0x00fc) +#define I2S_I2SDATE 0xFFFFFFFF +#define I2S_I2SDATE_S 0 + +#endif /* _SOC_I2S_REG_H_ */ diff --git a/components/esp32/include/soc/io_mux_reg.h b/components/esp32/include/soc/io_mux_reg.h new file mode 100644 index 0000000000..bc9f769b73 --- /dev/null +++ b/components/esp32/include/soc/io_mux_reg.h @@ -0,0 +1,264 @@ +// Copyright 2015-2016 Espressif Systems (Shanghai) PTE LTD +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at + +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +#ifndef _SOC_IO_MUX_REG_H_ +#define _SOC_IO_MUX_REG_H_ + +#include "soc.h" + +#define SLP_OE (BIT(0)) +#define SLP_SEL (BIT(1)) +#define SLP_PD (BIT(2)) +#define SLP_PU (BIT(3)) +#define SLP_IE (BIT(4)) +#define SLP_DRV 0x3 +#define SLP_DRV_S 5 +#define FUN_PD (BIT(7)) +#define FUN_PU (BIT(8)) +#define FUN_IE (BIT(9)) +#define FUN_DRV 0x3 +#define FUN_DRV_S 10 +#define MCU_SEL 0x7 +#define MCU_SEL_S 12 + + +#define PIN_SET_DRV(PIN_NAME, drv) REG_SET_FIELD(PIN_NAME, FUN_DRV, (drv)); +#define PIN_PULLUP_DIS(PIN_NAME) REG_CLR_BIT(PIN_NAME, FUN_PU) +#define PIN_PULLUP_EN(PIN_NAME) REG_SET_BIT(PIN_NAME, FUN_PU) +#define PIN_PULLDWN_DIS(PIN_NAME) REG_CLR_BIT(PIN_NAME, FUN_PD) +#define PIN_PULLDWN_EN(PIN_NAME) REG_SET_BIT(PIN_NAME, FUN_PD) +#define PIN_FUNC_SELECT(PIN_NAME, FUNC) REG_SET_FIELD(PIN_NAME, MCU_SEL, FUNC) + +#define PIN_CTRL (DR_REG_IO_MUX_BASE +0x00) +#define CLK_OUT3 0xf +#define CLK_OUT3_S 8 +#define CLK_OUT2 0xf +#define CLK_OUT2_S 4 +#define CLK_OUT1 0xf +#define CLK_OUT1_S 0 + +#define PERIPHS_IO_MUX_GPIO36_U (DR_REG_IO_MUX_BASE +0x04) +#define FUNC_GPIO36_GPIO36 2 +#define FUNC_GPIO36_GPIO36_0 0 + +#define PERIPHS_IO_MUX_GPIO37_U (DR_REG_IO_MUX_BASE +0x08) +#define FUNC_GPIO37_GPIO37 2 +#define FUNC_GPIO37_GPIO37_0 0 + +#define PERIPHS_IO_MUX_GPIO38_U (DR_REG_IO_MUX_BASE +0x0c) +#define FUNC_GPIO38_GPIO38 2 +#define FUNC_GPIO38_GPIO38_0 0 + +#define PERIPHS_IO_MUX_GPIO39_U (DR_REG_IO_MUX_BASE +0x10) +#define FUNC_GPIO39_GPIO39 2 +#define FUNC_GPIO39_GPIO39_0 0 + +#define PERIPHS_IO_MUX_GPIO34_U (DR_REG_IO_MUX_BASE +0x14) +#define FUNC_GPIO34_GPIO34 2 +#define FUNC_GPIO34_GPIO34_0 0 + +#define PERIPHS_IO_MUX_GPIO35_U (DR_REG_IO_MUX_BASE +0x18) +#define FUNC_GPIO35_GPIO35 2 +#define FUNC_GPIO35_GPIO35_0 0 + +#define PERIPHS_IO_MUX_GPIO32_U (DR_REG_IO_MUX_BASE +0x1c) +#define FUNC_GPIO32_GPIO32 2 +#define FUNC_GPIO32_GPIO32_0 0 + +#define PERIPHS_IO_MUX_GPIO33_U (DR_REG_IO_MUX_BASE +0x20) +#define FUNC_GPIO33_GPIO33 2 +#define FUNC_GPIO33_GPIO33_0 0 + +#define PERIPHS_IO_MUX_GPIO25_U (DR_REG_IO_MUX_BASE +0x24) +#define FUNC_GPIO25_GPIO25 2 +#define FUNC_GPIO25_GPIO25_0 0 + +#define PERIPHS_IO_MUX_GPIO26_U (DR_REG_IO_MUX_BASE +0x28) +#define FUNC_GPIO26_GPIO26 2 +#define FUNC_GPIO26_GPIO26_0 0 + +#define PERIPHS_IO_MUX_GPIO27_U (DR_REG_IO_MUX_BASE +0x2c) +#define FUNC_GPIO27_EMAC_RXD2 5 +#define FUNC_GPIO27_GPIO27 2 +#define FUNC_GPIO27_GPIO27_0 0 + +#define PERIPHS_IO_MUX_MTMS_U (DR_REG_IO_MUX_BASE +0x30) +#define FUNC_MTMS_EMAC_TXD2 5 +#define FUNC_MTMS_SD_CLK 4 +#define FUNC_MTMS_GPIO14 2 +#define FUNC_MTMS_HSPICLK 1 +#define FUNC_MTMS_MTMS 0 + +#define PERIPHS_IO_MUX_MTDI_U (DR_REG_IO_MUX_BASE +0x34) +#define FUNC_MTDI_EMAC_TXD3 5 +#define FUNC_MTDI_SD_DATA2 4 +#define FUNC_MTDI_GPIO12 2 +#define FUNC_MTDI_HSPIQ 1 +#define FUNC_MTDI_MTDI 0 + +#define PERIPHS_IO_MUX_MTCK_U (DR_REG_IO_MUX_BASE +0x38) +#define FUNC_MTCK_EMAC_RX_ER 5 +#define FUNC_MTCK_SD_DATA3 4 +#define FUNC_MTCK_U0CTS 3 +#define FUNC_MTCK_GPIO13 2 +#define FUNC_MTCK_HSPID 1 +#define FUNC_MTCK_MTCK 0 + +#define PERIPHS_IO_MUX_MTDO_U (DR_REG_IO_MUX_BASE +0x3c) +#define FUNC_MTDO_EMAC_RXD3 5 +#define FUNC_MTDO_SD_CMD 4 +#define FUNC_MTDO_U0RTS 3 +#define FUNC_MTDO_GPIO15 2 +#define FUNC_MTDO_HSPICS0 1 +#define FUNC_MTDO_MTDO 0 + +#define PERIPHS_IO_MUX_GPIO2_U (DR_REG_IO_MUX_BASE +0x40) +#define FUNC_GPIO2_EMAC_RX_DV 5 +#define FUNC_GPIO2_SD_DATA0 4 +#define FUNC_GPIO2_GPIO2 2 +#define FUNC_GPIO2_HSPIWP 1 +#define FUNC_GPIO2_GPIO2_0 0 + +#define PERIPHS_IO_MUX_GPIO0_U (DR_REG_IO_MUX_BASE +0x44) +#define FUNC_GPIO0_EMAC_TX_CLK 5 +#define FUNC_GPIO0_HS2_CMD 3 +#define FUNC_GPIO0_GPIO0 2 +#define FUNC_GPIO0_CLK_OUT1 1 +#define FUNC_GPIO0_GPIO0_0 0 + +#define PERIPHS_IO_MUX_GPIO4_U (DR_REG_IO_MUX_BASE +0x48) +#define FUNC_GPIO4_EMAC_TX_ER 5 +#define FUNC_GPIO4_SD_DATA1 4 +#define FUNC_GPIO4_GPIO4 2 +#define FUNC_GPIO4_HSPIHD 1 +#define FUNC_GPIO4_GPIO4_0 0 + +#define PERIPHS_IO_MUX_GPIO16_U (DR_REG_IO_MUX_BASE +0x4c) +#define FUNC_GPIO16_EMAC_CLK_OUT 5 +#define FUNC_GPIO16_U2RXD 4 +#define FUNC_GPIO16_HS1_DATA4 3 +#define FUNC_GPIO16_GPIO16 2 +#define FUNC_GPIO16_GPIO16_0 0 + +#define PERIPHS_IO_MUX_GPIO17_U (DR_REG_IO_MUX_BASE +0x50) +#define FUNC_GPIO17_EMAC_CLK_OUT_180 5 +#define FUNC_GPIO17_U2TXD 4 +#define FUNC_GPIO17_HS1_DATA5 3 +#define FUNC_GPIO17_GPIO17 2 +#define FUNC_GPIO17_GPIO17_0 0 + +#define PERIPHS_IO_MUX_SD_DATA2_U (DR_REG_IO_MUX_BASE +0x54) +#define FUNC_SD_DATA2_U1RXD 4 +#define FUNC_SD_DATA2_HS1_DATA2 3 +#define FUNC_SD_DATA2_GPIO9 2 +#define FUNC_SD_DATA2_SPIHD 1 +#define FUNC_SD_DATA2_SD_DATA2 0 + +#define PERIPHS_IO_MUX_SD_DATA3_U (DR_REG_IO_MUX_BASE +0x58) +#define FUNC_SD_DATA3_U1TXD 4 +#define FUNC_SD_DATA3_HS1_DATA3 3 +#define FUNC_SD_DATA3_GPIO10 2 +#define FUNC_SD_DATA3_SPIWP 1 +#define FUNC_SD_DATA3_SD_DATA3 0 + +#define PERIPHS_IO_MUX_SD_CMD_U (DR_REG_IO_MUX_BASE +0x5c) +#define FUNC_SD_CMD_U1RTS 4 +#define FUNC_SD_CMD_HS1_CMD 3 +#define FUNC_SD_CMD_GPIO11 2 +#define FUNC_SD_CMD_SPICS0 1 +#define FUNC_SD_CMD_SD_CMD 0 + +#define PERIPHS_IO_MUX_SD_CLK_U (DR_REG_IO_MUX_BASE +0x60) +#define FUNC_SD_CLK_U1CTS 4 +#define FUNC_SD_CLK_HS1_CLK 3 +#define FUNC_SD_CLK_GPIO6 2 +#define FUNC_SD_CLK_SPICLK 1 +#define FUNC_SD_CLK_SD_CLK 0 + +#define PERIPHS_IO_MUX_SD_DATA0_U (DR_REG_IO_MUX_BASE +0x64) +#define FUNC_SD_DATA0_U2RTS 4 +#define FUNC_SD_DATA0_HS1_DATA0 3 +#define FUNC_SD_DATA0_GPIO7 2 +#define FUNC_SD_DATA0_SPIQ 1 +#define FUNC_SD_DATA0_SD_DATA0 0 + +#define PERIPHS_IO_MUX_SD_DATA1_U (DR_REG_IO_MUX_BASE +0x68) +#define FUNC_SD_DATA1_U2CTS 4 +#define FUNC_SD_DATA1_HS1_DATA1 3 +#define FUNC_SD_DATA1_GPIO8 2 +#define FUNC_SD_DATA1_SPID 1 +#define FUNC_SD_DATA1_SD_DATA1 0 + +#define PERIPHS_IO_MUX_GPIO5_U (DR_REG_IO_MUX_BASE +0x6c) +#define FUNC_GPIO5_EMAC_RX_CLK 5 +#define FUNC_GPIO5_HS1_DATA6 3 +#define FUNC_GPIO5_GPIO5 2 +#define FUNC_GPIO5_VSPICS0 1 +#define FUNC_GPIO5_GPIO5_0 0 + +#define PERIPHS_IO_MUX_GPIO18_U (DR_REG_IO_MUX_BASE +0x70) +#define FUNC_GPIO18_EMAC_TXD0 5 +#define FUNC_GPIO18_HS1_DATA7 3 +#define FUNC_GPIO18_GPIO18 2 +#define FUNC_GPIO18_VSPICLK 1 +#define FUNC_GPIO18_GPIO18_0 0 + +#define PERIPHS_IO_MUX_GPIO19_U (DR_REG_IO_MUX_BASE +0x74) +#define FUNC_GPIO19_EMAC_TXD1 5 +#define FUNC_GPIO19_HS2_DATA2 3 +#define FUNC_GPIO19_GPIO19 2 +#define FUNC_GPIO19_VSPIQ 1 +#define FUNC_GPIO19_GPIO19_0 0 + +#define PERIPHS_IO_MUX_GPIO20_U (DR_REG_IO_MUX_BASE +0x78) +#define FUNC_GPIO20_GPIO20 2 +#define FUNC_GPIO20_GPIO20_0 0 + +#define PERIPHS_IO_MUX_GPIO21_U (DR_REG_IO_MUX_BASE +0x7c) +#define FUNC_GPIO21_EMAC_RXD0 5 +#define FUNC_GPIO21_HS2_DATA3 3 +#define FUNC_GPIO21_GPIO21 2 +#define FUNC_GPIO21_VSPIHD 1 +#define FUNC_GPIO21_GPIO21_0 0 + +#define PERIPHS_IO_MUX_GPIO22_U (DR_REG_IO_MUX_BASE +0x80) +#define FUNC_GPIO22_EMAC_RXD1 5 +#define FUNC_GPIO22_HS2_CLK 3 +#define FUNC_GPIO22_GPIO22 2 +#define FUNC_GPIO22_VSPIWP 1 +#define FUNC_GPIO22_GPIO22_0 0 + +#define PERIPHS_IO_MUX_U0RXD_U (DR_REG_IO_MUX_BASE +0x84) +#define FUNC_U0RXD_HS2_DATA0 3 +#define FUNC_U0RXD_GPIO3 2 +#define FUNC_U0RXD_CLK_OUT2 1 +#define FUNC_U0RXD_U0RXD 0 + +#define PERIPHS_IO_MUX_U0TXD_U (DR_REG_IO_MUX_BASE +0x88) +#define FUNC_U0TXD_HS2_DATA1 3 +#define FUNC_U0TXD_GPIO1 2 +#define FUNC_U0TXD_CLK_OUT3 1 +#define FUNC_U0TXD_U0TXD 0 + +#define PERIPHS_IO_MUX_GPIO23_U (DR_REG_IO_MUX_BASE +0x8c) +#define FUNC_GPIO23_EMAC_TX_EN 5 +#define FUNC_GPIO23_HS1_STROBE 3 +#define FUNC_GPIO23_GPIO23 2 +#define FUNC_GPIO23_VSPID 1 +#define FUNC_GPIO23_GPIO23_0 0 + +#define PERIPHS_IO_MUX_GPIO24_U (DR_REG_IO_MUX_BASE +0x90) +#define FUNC_GPIO24_GPIO24 2 +#define FUNC_GPIO24_GPIO24_0 0 + +#endif /* _SOC_IO_MUX_REG_H_ */ diff --git a/components/esp32/include/soc/pid.h b/components/esp32/include/soc/pid.h new file mode 100644 index 0000000000..bd4e9f26d2 --- /dev/null +++ b/components/esp32/include/soc/pid.h @@ -0,0 +1,65 @@ +// Copyright 2015-2016 Espressif Systems (Shanghai) PTE LTD +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at + +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +#ifndef _SOC_PID_H_ +#define _SOC_PID_H_ + +#define PROPID_GEN_BASE 0x3FF1F000 +//Bits 1..7: 1 if interrupt will be triggering PID change +#define PROPID_CONFIG_INTERRUPT_ENABLE ((PROPID_GEN_BASE)+0x000) +//Vectors for the various interrupt handlers +#define PROPID_CONFIG_INTERRUPT_ADDR_1 ((PROPID_GEN_BASE)+0x004) +#define PROPID_CONFIG_INTERRUPT_ADDR_2 ((PROPID_GEN_BASE)+0x008) +#define PROPID_CONFIG_INTERRUPT_ADDR_3 ((PROPID_GEN_BASE)+0x00C) +#define PROPID_CONFIG_INTERRUPT_ADDR_4 ((PROPID_GEN_BASE)+0x010) +#define PROPID_CONFIG_INTERRUPT_ADDR_5 ((PROPID_GEN_BASE)+0x014) +#define PROPID_CONFIG_INTERRUPT_ADDR_6 ((PROPID_GEN_BASE)+0x018) +#define PROPID_CONFIG_INTERRUPT_ADDR_7 ((PROPID_GEN_BASE)+0x01C) + +//Delay, in CPU cycles, before switching to new PID +#define PROPID_CONFIG_PID_DELAY ((PROPID_GEN_BASE)+0x020) +#define PROPID_CONFIG_NMI_DELAY ((PROPID_GEN_BASE)+0x024) + +//Last detected interrupt. Set by hw on int. +#define PROPID_TABLE_LEVEL ((PROPID_GEN_BASE)+0x028) +//PID/prev int data for each int +#define PROPID_FROM_1 ((PROPID_GEN_BASE)+0x02C) +#define PROPID_FROM_2 ((PROPID_GEN_BASE)+0x030) +#define PROPID_FROM_3 ((PROPID_GEN_BASE)+0x034) +#define PROPID_FROM_4 ((PROPID_GEN_BASE)+0x038) +#define PROPID_FROM_5 ((PROPID_GEN_BASE)+0x03C) +#define PROPID_FROM_6 ((PROPID_GEN_BASE)+0x040) +#define PROPID_FROM_7 ((PROPID_GEN_BASE)+0x044) +#define PROPID_FROM_PID_MASK 0x7 +#define PROPID_FROM_PID_S 0 +#define PROPID_FROM_INT_MASK 0xF +#define PROPID_FROM_INT_S 3 + +//PID to be set after confirm routine +#define PROPID_PID_NEW ((PROPID_GEN_BASE)+0x048) +//Write to kick off PID change +#define PROPID_PID_CONFIRM ((PROPID_GEN_BASE)+0x04c) +//current PID? +#define PROPID_PID_REG ((PROPID_GEN_BASE)+0x050) + +//Write to mask NMI +#define PROPID_PID_NMI_MASK_HW_ENABLE ((PROPID_GEN_BASE)+0x054) +//Write to unmask NMI +#define PROPID_PID_NMI_MASK_HW_DISABLE ((PROPID_GEN_BASE)+0x058) +#define PROPID_PID_NMI_MASK_HW_REG ((PROPID_GEN_BASE)+0x05c) + +//Debug regs +#define PROPID_PID ((PROPID_GEN_BASE)+0x060) +#define PROPID_NMI_MASK_HW ((PROPID_GEN_BASE)+0x064) + +#endif /* _SOC_PID_H_ */ diff --git a/components/esp32/include/soc/rtc_cntl_reg.h b/components/esp32/include/soc/rtc_cntl_reg.h new file mode 100644 index 0000000000..c94d17dbb8 --- /dev/null +++ b/components/esp32/include/soc/rtc_cntl_reg.h @@ -0,0 +1,751 @@ +// Copyright 2015-2016 Espressif Systems (Shanghai) PTE LTD +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at + +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +#ifndef _SOC_RTC_CNTL_REG_H_ +#define _SOC_RTC_CNTL_REG_H_ + +#include "soc.h" + +#define RTC_OPTIONS0 (DR_REG_RTCCNTL_BASE + 0x0) +#define RTC_CNTL_SW_SYS_RST (BIT(31)) +#define RTC_CNTL_SW_SYS_RST_S 31 +#define RTC_CNTL_DG_WRAP_FORCE_NORST (BIT(30)) +#define RTC_CNTL_DG_WRAP_FORCE_NORST_S 30 +#define RTC_CNTL_DG_WRAP_FORCE_RST (BIT(29)) +#define RTC_CNTL_DG_WRAP_FORCE_RST_S 29 +#define RTC_CNTL_ANALOG_FORCE_NOISO (BIT(28)) +#define RTC_CNTL_ANALOG_FORCE_NOISO_S 28 +#define RTC_CNTL_PLL_FORCE_NOISO (BIT(27)) +#define RTC_CNTL_PLL_FORCE_NOISO_S 27 +#define RTC_CNTL_XTL_FORCE_NOISO (BIT(26)) +#define RTC_CNTL_XTL_FORCE_NOISO_S 26 +#define RTC_CNTL_ANALOG_FORCE_ISO (BIT(25)) +#define RTC_CNTL_ANALOG_FORCE_ISO_S 25 +#define RTC_CNTL_PLL_FORCE_ISO (BIT(24)) +#define RTC_CNTL_PLL_FORCE_ISO_S 24 +#define RTC_CNTL_XTL_FORCE_ISO (BIT(23)) +#define RTC_CNTL_XTL_FORCE_ISO_S 23 +#define RTC_CNTL_BIAS_CORE_FORCE_PU (BIT(22)) +#define RTC_CNTL_BIAS_CORE_FORCE_PU_S 22 +#define RTC_CNTL_BIAS_CORE_FORCE_PD (BIT(21)) +#define RTC_CNTL_BIAS_CORE_FORCE_PD_S 21 +#define RTC_CNTL_BIAS_CORE_FOLW_12M (BIT(20)) +#define RTC_CNTL_BIAS_CORE_FOLW_12M_S 20 +#define RTC_CNTL_BIAS_I2C_FORCE_PU (BIT(19)) +#define RTC_CNTL_BIAS_I2C_FORCE_PU_S 19 +#define RTC_CNTL_BIAS_I2C_FORCE_PD (BIT(18)) +#define RTC_CNTL_BIAS_I2C_FORCE_PD_S 18 +#define RTC_CNTL_BIAS_I2C_FOLW_12M (BIT(17)) +#define RTC_CNTL_BIAS_I2C_FOLW_12M_S 17 +#define RTC_CNTL_BIAS_FORCE_NOSLEEP (BIT(16)) +#define RTC_CNTL_BIAS_FORCE_NOSLEEP_S 16 +#define RTC_CNTL_BIAS_FORCE_SLEEP (BIT(15)) +#define RTC_CNTL_BIAS_FORCE_SLEEP_S 15 +#define RTC_CNTL_BIAS_SLEEP_FOLW_12M (BIT(14)) +#define RTC_CNTL_BIAS_SLEEP_FOLW_12M_S 14 +#define RTC_CNTL_XTL_FORCE_PU (BIT(13)) +#define RTC_CNTL_XTL_FORCE_PU_S 13 +#define RTC_CNTL_XTL_FORCE_PD (BIT(12)) +#define RTC_CNTL_XTL_FORCE_PD_S 12 +#define RTC_CNTL_BBPLL_FORCE_PU (BIT(11)) +#define RTC_CNTL_BBPLL_FORCE_PU_S 11 +#define RTC_CNTL_BBPLL_FORCE_PD (BIT(10)) +#define RTC_CNTL_BBPLL_FORCE_PD_S 10 +#define RTC_CNTL_BBPLL_I2C_FORCE_PU (BIT(9)) +#define RTC_CNTL_BBPLL_I2C_FORCE_PU_S 9 +#define RTC_CNTL_BBPLL_I2C_FORCE_PD (BIT(8)) +#define RTC_CNTL_BBPLL_I2C_FORCE_PD_S 8 +#define RTC_CNTL_BB_I2C_FORCE_PU (BIT(7)) +#define RTC_CNTL_BB_I2C_FORCE_PU_S 7 +#define RTC_CNTL_BB_I2C_FORCE_PD (BIT(6)) +#define RTC_CNTL_BB_I2C_FORCE_PD_S 6 +#define RTC_CNTL_SW_PROCPU_RST (BIT(5)) +#define RTC_CNTL_SW_PROCPU_RST_S 5 +#define RTC_CNTL_SW_APPCPU_RST (BIT(4)) +#define RTC_CNTL_SW_APPCPU_RST_S 4 +#define RTC_CNTL_SW_STALL_PROCPU_C0 0x00000003 +#define RTC_CNTL_SW_STALL_PROCPU_C0_S 2 +#define RTC_CNTL_SW_STALL_APPCPU_C0 0x00000003 +#define RTC_CNTL_SW_STALL_APPCPU_C0_S 0 + +#define RTC_SLP_TIMER0 (DR_REG_RTCCNTL_BASE + 0x4) +#define RTC_CNTL_SLP_VAL_LO 0xFFFFFFFF +#define RTC_CNTL_SLP_VAL_LO_S 0 + +#define RTC_SLP_TIMER1 (DR_REG_RTCCNTL_BASE + 0x8) +#define RTC_CNTL_RTC_MAIN_TIMER_ALARM_EN (BIT(16)) +#define RTC_CNTL_RTC_MAIN_TIMER_ALARM_EN_S 16 +#define RTC_CNTL_SLP_VAL_HI 0x0000FFFF +#define RTC_CNTL_SLP_VAL_HI_S 0 + +#define RTC_TIME_UPDATE (DR_REG_RTCCNTL_BASE + 0xc) +#define RTC_CNTL_RTC_TIME_UPDATE (BIT(31)) +#define RTC_CNTL_RTC_TIME_UPDATE_S 31 +#define RTC_CNTL_RTC_TIME_VALID (BIT(30)) +#define RTC_CNTL_RTC_TIME_VALID_S 30 + +#define RTC_TIME0 (DR_REG_RTCCNTL_BASE + 0x10) +#define RTC_CNTL_RTC_TIME_LO 0xFFFFFFFF +#define RTC_CNTL_RTC_TIME_LO_S 0 + +#define RTC_TIME1 (DR_REG_RTCCNTL_BASE + 0x14) +#define RTC_CNTL_RTC_TIME_HI 0x0000FFFF +#define RTC_CNTL_RTC_TIME_HI_S 0 + +#define RTC_STATE0 (DR_REG_RTCCNTL_BASE + 0x18) +#define RTC_CNTL_SLEEP_EN (BIT(31)) +#define RTC_CNTL_SLEEP_EN_S 31 +#define RTC_CNTL_SLP_REJECT (BIT(30)) +#define RTC_CNTL_SLP_REJECT_S 30 +#define RTC_CNTL_SLP_WAKEUP (BIT(29)) +#define RTC_CNTL_SLP_WAKEUP_S 29 +#define RTC_CNTL_SDIO_ACTIVE_IND (BIT(28)) +#define RTC_CNTL_SDIO_ACTIVE_IND_S 28 +#define RTC_CNTL_SAR_SLP_TIMER_EN (BIT(24)) +#define RTC_CNTL_SAR_SLP_TIMER_EN_S 24 +#define RTC_CNTL_TOUCH_SLP_TIMER_EN (BIT(23)) +#define RTC_CNTL_TOUCH_SLP_TIMER_EN_S 23 +#define RTC_CNTL_APB2RTC_BRIDGE_SEL (BIT(22)) +#define RTC_CNTL_APB2RTC_BRIDGE_SEL_S 22 +#define RTC_CNTL_SAR_WAKEUP_FORCE_EN (BIT(21)) +#define RTC_CNTL_SAR_WAKEUP_FORCE_EN_S 21 +#define RTC_CNTL_TOUCH_WAKEUP_FORCE_EN (BIT(20)) +#define RTC_CNTL_TOUCH_WAKEUP_FORCE_EN_S 20 + +#define RTC_TIMER1 (DR_REG_RTCCNTL_BASE + 0x1c) +#define RTC_CNTL_PLL_BUF_WAIT 0x000000FF +#define RTC_CNTL_PLL_BUF_WAIT_S 24 +#define RTC_CNTL_XTL_BUF_WAIT 0x000003FF +#define RTC_CNTL_XTL_BUF_WAIT_S 14 +#define RTC_CNTL_CK12M_WAIT 0x000000FF +#define RTC_CNTL_CK12M_WAIT_S 6 +#define RTC_CNTL_CPU_STALL_WAIT 0x0000001F +#define RTC_CNTL_CPU_STALL_WAIT_S 1 +#define RTC_CNTL_CPU_STALL_EN (BIT(0)) +#define RTC_CNTL_CPU_STALL_EN_S 0 + +#define RTC_TIMER2 (DR_REG_RTCCNTL_BASE + 0x20) +#define RTC_CNTL_MIN_TIME_CK12M_OFF 0x000000FF +#define RTC_CNTL_MIN_TIME_CK12M_OFF_S 24 +#define RTC_CNTL_SAR_TOUCH_START_WAIT 0x000001FF +#define RTC_CNTL_SAR_TOUCH_START_WAIT_S 15 + +#define RTC_TIMER3 (DR_REG_RTCCNTL_BASE + 0x24) +#define RTC_CNTL_ROM_RAM_POWERUP_TIMER 0x0000007F +#define RTC_CNTL_ROM_RAM_POWERUP_TIMER_S 25 +#define RTC_CNTL_ROM_RAM_WAIT_TIMER 0x000001FF +#define RTC_CNTL_ROM_RAM_WAIT_TIMER_S 16 +#define RTC_CNTL_WIFI_POWERUP_TIMER 0x0000007F +#define RTC_CNTL_WIFI_POWERUP_TIMER_S 9 +#define RTC_CNTL_WIFI_WAIT_TIMER 0x000001FF +#define RTC_CNTL_WIFI_WAIT_TIMER_S 0 + +#define RTC_TIMER4 (DR_REG_RTCCNTL_BASE + 0x28) +#define RTC_CNTL_DG_WRAP_POWERUP_TIMER 0x0000007F +#define RTC_CNTL_DG_WRAP_POWERUP_TIMER_S 25 +#define RTC_CNTL_DG_WRAP_WAIT_TIMER 0x000001FF +#define RTC_CNTL_DG_WRAP_WAIT_TIMER_S 16 +#define RTC_CNTL_RTC_POWERUP_TIMER 0x0000007F +#define RTC_CNTL_RTC_POWERUP_TIMER_S 9 +#define RTC_CNTL_RTC_WAIT_TIMER 0x000001FF +#define RTC_CNTL_RTC_WAIT_TIMER_S 0 + +#define RTC_TIMER5 (DR_REG_RTCCNTL_BASE + 0x2c) +#define RTC_CNTL_RTCMEM_POWERUP_TIMER 0x0000007F +#define RTC_CNTL_RTCMEM_POWERUP_TIMER_S 25 +#define RTC_CNTL_RTCMEM_WAIT_TIMER 0x000001FF +#define RTC_CNTL_RTCMEM_WAIT_TIMER_S 16 +#define RTC_CNTL_MIN_SLP_VAL 0x000000FF +#define RTC_CNTL_MIN_SLP_VAL_S 8 +#define RTC_CNTL_SAR_SUBTIMER_PREDIV 0x000000FF +#define RTC_CNTL_SAR_SUBTIMER_PREDIV_S 0 + +#define RTC_ANA_CONF (DR_REG_RTCCNTL_BASE + 0x30) +#define RTC_CNTL_PLL_I2C_PU (BIT(31)) +#define RTC_CNTL_PLL_I2C_PU_S 31 +#define RTC_CNTL_CKGEN_I2C_PU (BIT(30)) +#define RTC_CNTL_CKGEN_I2C_PU_S 30 +#define RTC_CNTL_RFRX_PBUS_PU (BIT(28)) +#define RTC_CNTL_RFRX_PBUS_PU_S 28 +#define RTC_CNTL_TXRF_I2C_PU (BIT(27)) +#define RTC_CNTL_TXRF_I2C_PU_S 27 +#define RTC_CNTL_PVTMON_PU (BIT(26)) +#define RTC_CNTL_PVTMON_PU_S 26 +#define RTC_CNTL_BBPLL_CAL_SLP_START (BIT(25)) +#define RTC_CNTL_BBPLL_CAL_SLP_START_S 25 +#define RTC_CNTL_PLLA_FORCE_PU (BIT(24)) +#define RTC_CNTL_PLLA_FORCE_PU_S 24 +#define RTC_CNTL_PLLA_FORCE_PD (BIT(23)) +#define RTC_CNTL_PLLA_FORCE_PD_S 23 + +#define RTC_RESET_STATE (DR_REG_RTCCNTL_BASE + 0x34) +#define RTC_CNTL_PROCPU_STAT_VECTOR_SEL (BIT(13)) +#define RTC_CNTL_PROCPU_STAT_VECTOR_SEL_S 13 +#define RTC_CNTL_APPCPU_STAT_VECTOR_SEL (BIT(12)) +#define RTC_CNTL_APPCPU_STAT_VECTOR_SEL_S 12 +#define RTC_CNTL_RESET_CAUSE_APPCPU 0x0000003F +#define RTC_CNTL_RESET_CAUSE_APPCPU_S 6 +#define RTC_CNTL_RESET_CAUSE_PROCPU 0x0000003F +#define RTC_CNTL_RESET_CAUSE_PROCPU_S 0 + +#define RTC_WAKEUP_STATE (DR_REG_RTCCNTL_BASE + 0x38) +#define RTC_CNTL_GPIO_WAKEUP_FILTER (BIT(22)) +#define RTC_CNTL_GPIO_WAKEUP_FILTER_S 22 +#define RTC_CNTL_RTC_WAKEUP_ENA 0x000007FF +#define RTC_CNTL_RTC_WAKEUP_ENA_S 11 +#define RTC_CNTL_WAKEUP_CAUSE 0x000007FF +#define RTC_CNTL_WAKEUP_CAUSE_S 0 + +#define INT_ENA_RTC (DR_REG_RTCCNTL_BASE + 0x3c) +#define RTC_CNTL_RTC_MAIN_TIMER_INT_ENA (BIT(8)) +#define RTC_CNTL_RTC_MAIN_TIMER_INT_ENA_S 8 +#define RTC_CNTL_RTC_BROWN_OUT_INT_ENA (BIT(7)) +#define RTC_CNTL_RTC_BROWN_OUT_INT_ENA_S 7 +#define RTC_CNTL_RTC_TOUCH_INT_ENA (BIT(6)) +#define RTC_CNTL_RTC_TOUCH_INT_ENA_S 6 +#define RTC_CNTL_RTC_SAR_INT_ENA (BIT(5)) +#define RTC_CNTL_RTC_SAR_INT_ENA_S 5 +#define RTC_CNTL_RTC_TIME_VALID_INT_ENA (BIT(4)) +#define RTC_CNTL_RTC_TIME_VALID_INT_ENA_S 4 +#define RTC_CNTL_RTC_WDT_INT_ENA (BIT(3)) +#define RTC_CNTL_RTC_WDT_INT_ENA_S 3 +#define RTC_CNTL_SDIO_IDLE_INT_ENA (BIT(2)) +#define RTC_CNTL_SDIO_IDLE_INT_ENA_S 2 +#define RTC_CNTL_SLP_REJECT_INT_ENA (BIT(1)) +#define RTC_CNTL_SLP_REJECT_INT_ENA_S 1 +#define RTC_CNTL_SLP_WAKEUP_INT_ENA (BIT(0)) +#define RTC_CNTL_SLP_WAKEUP_INT_ENA_S 0 + +#define INT_RAW_RTC (DR_REG_RTCCNTL_BASE + 0x40) +#define RTC_CNTL_RTC_MAIN_TIMER_INT_RAW (BIT(8)) +#define RTC_CNTL_RTC_MAIN_TIMER_INT_RAW_S 8 +#define RTC_CNTL_RTC_BROWN_OUT_INT_RAW (BIT(7)) +#define RTC_CNTL_RTC_BROWN_OUT_INT_RAW_S 7 +#define RTC_CNTL_RTC_TOUCH_INT_RAW (BIT(6)) +#define RTC_CNTL_RTC_TOUCH_INT_RAW_S 6 +#define RTC_CNTL_RTC_SAR_INT_RAW (BIT(5)) +#define RTC_CNTL_RTC_SAR_INT_RAW_S 5 +#define RTC_CNTL_RTC_TIME_VALID_INT_RAW (BIT(4)) +#define RTC_CNTL_RTC_TIME_VALID_INT_RAW_S 4 +#define RTC_CNTL_RTC_WDT_INT_RAW (BIT(3)) +#define RTC_CNTL_RTC_WDT_INT_RAW_S 3 +#define RTC_CNTL_SDIO_IDLE_INT_RAW (BIT(2)) +#define RTC_CNTL_SDIO_IDLE_INT_RAW_S 2 +#define RTC_CNTL_SLP_REJECT_INT_RAW (BIT(1)) +#define RTC_CNTL_SLP_REJECT_INT_RAW_S 1 +#define RTC_CNTL_SLP_WAKEUP_INT_RAW (BIT(0)) +#define RTC_CNTL_SLP_WAKEUP_INT_RAW_S 0 + +#define INT_ST_RTC (DR_REG_RTCCNTL_BASE + 0x44) +#define RTC_CNTL_RTC_MAIN_TIMER_INT_ST (BIT(8)) +#define RTC_CNTL_RTC_MAIN_TIMER_INT_ST_S 8 +#define RTC_CNTL_RTC_BROWN_OUT_INT_ST (BIT(7)) +#define RTC_CNTL_RTC_BROWN_OUT_INT_ST_S 7 +#define RTC_CNTL_RTC_TOUCH_INT_ST (BIT(6)) +#define RTC_CNTL_RTC_TOUCH_INT_ST_S 6 +#define RTC_CNTL_RTC_SAR_INT_ST (BIT(5)) +#define RTC_CNTL_RTC_SAR_INT_ST_S 5 +#define RTC_CNTL_RTC_TIME_VALID_INT_ST (BIT(4)) +#define RTC_CNTL_RTC_TIME_VALID_INT_ST_S 4 +#define RTC_CNTL_RTC_WDT_INT_ST (BIT(3)) +#define RTC_CNTL_RTC_WDT_INT_ST_S 3 +#define RTC_CNTL_SDIO_IDLE_INT_ST (BIT(2)) +#define RTC_CNTL_SDIO_IDLE_INT_ST_S 2 +#define RTC_CNTL_SLP_REJECT_INT_ST (BIT(1)) +#define RTC_CNTL_SLP_REJECT_INT_ST_S 1 +#define RTC_CNTL_SLP_WAKEUP_INT_ST (BIT(0)) +#define RTC_CNTL_SLP_WAKEUP_INT_ST_S 0 + +#define INT_CLR_RTC (DR_REG_RTCCNTL_BASE + 0x48) +#define RTC_CNTL_RTC_MAIN_TIMER_INT_CLR (BIT(8)) +#define RTC_CNTL_RTC_MAIN_TIMER_INT_CLR_S 8 +#define RTC_CNTL_RTC_BROWN_OUT_INT_CLR (BIT(7)) +#define RTC_CNTL_RTC_BROWN_OUT_INT_CLR_S 7 +#define RTC_CNTL_RTC_TOUCH_INT_CLR (BIT(6)) +#define RTC_CNTL_RTC_TOUCH_INT_CLR_S 6 +#define RTC_CNTL_RTC_SAR_INT_CLR (BIT(5)) +#define RTC_CNTL_RTC_SAR_INT_CLR_S 5 +#define RTC_CNTL_RTC_TIME_VALID_INT_CLR (BIT(4)) +#define RTC_CNTL_RTC_TIME_VALID_INT_CLR_S 4 +#define RTC_CNTL_RTC_WDT_INT_CLR (BIT(3)) +#define RTC_CNTL_RTC_WDT_INT_CLR_S 3 +#define RTC_CNTL_SDIO_IDLE_INT_CLR (BIT(2)) +#define RTC_CNTL_SDIO_IDLE_INT_CLR_S 2 +#define RTC_CNTL_SLP_REJECT_INT_CLR (BIT(1)) +#define RTC_CNTL_SLP_REJECT_INT_CLR_S 1 +#define RTC_CNTL_SLP_WAKEUP_INT_CLR (BIT(0)) +#define RTC_CNTL_SLP_WAKEUP_INT_CLR_S 0 + +#define RTC_STORE0 (DR_REG_RTCCNTL_BASE + 0x4c) +#define RTC_CNTL_RTC_SCRATCH0 0xFFFFFFFF +#define RTC_CNTL_RTC_SCRATCH0_S 0 + +#define RTC_STORE1 (DR_REG_RTCCNTL_BASE + 0x50) +#define RTC_CNTL_RTC_SCRATCH1 0xFFFFFFFF +#define RTC_CNTL_RTC_SCRATCH1_S 0 + +#define RTC_STORE2 (DR_REG_RTCCNTL_BASE + 0x54) +#define RTC_CNTL_RTC_SCRATCH2 0xFFFFFFFF +#define RTC_CNTL_RTC_SCRATCH2_S 0 + +#define RTC_STORE3 (DR_REG_RTCCNTL_BASE + 0x58) +#define RTC_CNTL_RTC_SCRATCH3 0xFFFFFFFF +#define RTC_CNTL_RTC_SCRATCH3_S 0 + +#define RTC_EXT_XTL_CONF (DR_REG_RTCCNTL_BASE + 0x5c) +#define RTC_CNTL_XTL_EXT_CTR_EN (BIT(31)) +#define RTC_CNTL_XTL_EXT_CTR_EN_S 31 +#define RTC_CNTL_XTL_EXT_CTR_LV (BIT(30)) +#define RTC_CNTL_XTL_EXT_CTR_LV_S 30 + +#define RTC_EXT_WAKEUP_CONF (DR_REG_RTCCNTL_BASE + 0x60) +#define RTC_CNTL_EXT_WAKEUP1_LV (BIT(31)) +#define RTC_CNTL_EXT_WAKEUP1_LV_S 31 +#define RTC_CNTL_EXT_WAKEUP0_LV (BIT(30)) +#define RTC_CNTL_EXT_WAKEUP0_LV_S 30 + +#define RTC_SLP_REJECT_CONF (DR_REG_RTCCNTL_BASE + 0x64) +#define RTC_CNTL_REJECT_CAUSE 0x0000000F +#define RTC_CNTL_REJECT_CAUSE_S 28 +#define RTC_CNTL_DEEP_SLP_REJECT_EN (BIT(27)) +#define RTC_CNTL_DEEP_SLP_REJECT_EN_S 27 +#define RTC_CNTL_LIGHT_SLP_REJECT_EN (BIT(26)) +#define RTC_CNTL_LIGHT_SLP_REJECT_EN_S 26 +#define RTC_CNTL_SDIO_REJECT_EN (BIT(25)) +#define RTC_CNTL_SDIO_REJECT_EN_S 25 +#define RTC_CNTL_GPIO_REJECT_EN (BIT(24)) +#define RTC_CNTL_GPIO_REJECT_EN_S 24 + +#define RTC_CPU_PERIOD_CONF (DR_REG_RTCCNTL_BASE + 0x68) +#define RTC_CNTL_RTC_CPUPERIOD_SEL 0x00000003 +#define RTC_CNTL_RTC_CPUPERIOD_SEL_S 30 +#define RTC_CNTL_RTC_CPUSEL_CONF (BIT(29)) +#define RTC_CNTL_RTC_CPUSEL_CONF_S 29 + +#define RTC_SDIO_ACT_CONF (DR_REG_RTCCNTL_BASE + 0x6c) +#define RTC_CNTL_SDIO_ACT_DNUM 0x000003FF +#define RTC_CNTL_SDIO_ACT_DNUM_S 22 + +#define RTC_CLK_CONF (DR_REG_RTCCNTL_BASE + 0x70) +#define RTC_CNTL_ANA_CLK_RTC_SEL 0x00000003 +#define RTC_CNTL_ANA_CLK_RTC_SEL_S 30 +#define RTC_CNTL_FAST_CLK_RTC_SEL (BIT(29)) +#define RTC_CNTL_FAST_CLK_RTC_SEL_S 29 +#define RTC_CNTL_SOC_CLK_SEL 0x00000003 +#define RTC_CNTL_SOC_CLK_SEL_S 27 +#define RTC_CNTL_CK12M_FORCE_PU (BIT(26)) +#define RTC_CNTL_CK12M_FORCE_PU_S 26 +#define RTC_CNTL_CK12M_FORCE_PD (BIT(25)) +#define RTC_CNTL_CK12M_FORCE_PD_S 25 +#define RTC_CNTL_CK12M_DFREQ 0x000000FF +#define RTC_CNTL_CK12M_DFREQ_S 17 +#define RTC_CNTL_CK12M_FORCE_NOGATING (BIT(16)) +#define RTC_CNTL_CK12M_FORCE_NOGATING_S 16 +#define RTC_CNTL_XTAL_FORCE_NOGATING (BIT(15)) +#define RTC_CNTL_XTAL_FORCE_NOGATING_S 15 +#define RTC_CNTL_CK12M_DIV_SEL 0x00000007 +#define RTC_CNTL_CK12M_DIV_SEL_S 12 +#define RTC_CNTL_CK12M_DFREQ_FORCE (BIT(11)) +#define RTC_CNTL_CK12M_DFREQ_FORCE_S 11 +#define RTC_CNTL_DIG_CLK12M_EN (BIT(10)) +#define RTC_CNTL_DIG_CLK12M_EN_S 10 +#define RTC_CNTL_DIG_CLK12M_D256_EN (BIT(9)) +#define RTC_CNTL_DIG_CLK12M_D256_EN_S 9 +#define RTC_CNTL_DIG_XTAL32K_EN (BIT(8)) +#define RTC_CNTL_DIG_XTAL32K_EN_S 8 +#define RTC_CNTL_ENB_CK12M_DIV (BIT(7)) +#define RTC_CNTL_ENB_CK12M_DIV_S 7 +#define RTC_CNTL_ENB_CK12M (BIT(6)) +#define RTC_CNTL_ENB_CK12M_S 6 +#define RTC_CNTL_CK12M_DIV 0x00000003 +#define RTC_CNTL_CK12M_DIV_S 4 + +#define RTC_SDIO_CONF (DR_REG_RTCCNTL_BASE + 0x74) +#define RTC_CNTL_XPD_SDIO_REG (BIT(31)) +#define RTC_CNTL_XPD_SDIO_REG_S 31 +#define RTC_CNTL_DREFH_SDIO 0x00000003 +#define RTC_CNTL_DREFH_SDIO_S 29 +#define RTC_CNTL_DREFM_SDIO 0x00000003 +#define RTC_CNTL_DREFM_SDIO_S 27 +#define RTC_CNTL_DREFL_SDIO 0x00000003 +#define RTC_CNTL_DREFL_SDIO_S 25 +#define RTC_CNTL_REG1P8_READY (BIT(24)) +#define RTC_CNTL_REG1P8_READY_S 24 +#define RTC_CNTL_SDIO_TIEH (BIT(23)) +#define RTC_CNTL_SDIO_TIEH_S 23 +#define RTC_CNTL_SDIO_FORCE (BIT(22)) +#define RTC_CNTL_SDIO_FORCE_S 22 +#define RTC_CNTL_SDIO_REG_PD_EN (BIT(21)) +#define RTC_CNTL_SDIO_REG_PD_EN_S 21 + +#define RTC_BIAS_CONF (DR_REG_RTCCNTL_BASE + 0x78) +#define RTC_CNTL_RST_BIAS_I2C (BIT(31)) +#define RTC_CNTL_RST_BIAS_I2C_S 31 +#define RTC_CNTL_DEC_HEARTBEAT_WIDTH (BIT(30)) +#define RTC_CNTL_DEC_HEARTBEAT_WIDTH_S 30 +#define RTC_CNTL_INC_HEARTBEAT_PERIOD (BIT(29)) +#define RTC_CNTL_INC_HEARTBEAT_PERIOD_S 29 +#define RTC_CNTL_DEC_HEARTBEAT_PERIOD (BIT(28)) +#define RTC_CNTL_DEC_HEARTBEAT_PERIOD_S 28 +#define RTC_CNTL_INC_HEARTBEAT_REFRESH (BIT(27)) +#define RTC_CNTL_INC_HEARTBEAT_REFRESH_S 27 +#define RTC_CNTL_ENB_SCK_XTAL (BIT(26)) +#define RTC_CNTL_ENB_SCK_XTAL_S 26 +#define RTC_CNTL_DBG_ATTEN 0x00000003 +#define RTC_CNTL_DBG_ATTEN_S 24 + +#define RTC_REG (DR_REG_RTCCNTL_BASE + 0x7c) +#define RTC_CNTL_RTC_REG_FORCE_PU (BIT(31)) +#define RTC_CNTL_RTC_REG_FORCE_PU_S 31 +#define RTC_CNTL_RTC_REG_FORCE_PD (BIT(30)) +#define RTC_CNTL_RTC_REG_FORCE_PD_S 30 +#define RTC_CNTL_RTC_DBOOST_FORCE_PU (BIT(29)) +#define RTC_CNTL_RTC_DBOOST_FORCE_PU_S 29 +#define RTC_CNTL_RTC_DBOOST_FORCE_PD (BIT(28)) +#define RTC_CNTL_RTC_DBOOST_FORCE_PD_S 28 +#define RTC_CNTL_RTC_DBIAS_WAK 0x00000007 +#define RTC_CNTL_RTC_DBIAS_WAK_S 25 +#define RTC_CNTL_RTC_DBIAS_SLP 0x00000007 +#define RTC_CNTL_RTC_DBIAS_SLP_S 22 +#define RTC_CNTL_SCK_DCAP 0x000000FF +#define RTC_CNTL_SCK_DCAP_S 14 +#define RTC_CNTL_DIG_REG_DBIAS_WAK 0x00000007 +#define RTC_CNTL_DIG_REG_DBIAS_WAK_S 11 +#define RTC_CNTL_DIG_REG_DBIAS_SLP 0x00000007 +#define RTC_CNTL_DIG_REG_DBIAS_SLP_S 8 +#define RTC_CNTL_SCK_DCAP_FORCE (BIT(7)) +#define RTC_CNTL_SCK_DCAP_FORCE_S 7 + +#define RTC_PWC (DR_REG_RTCCNTL_BASE + 0x80) +#define RTC_CNTL_RTC_PD_EN (BIT(20)) +#define RTC_CNTL_RTC_PD_EN_S 20 +#define RTC_CNTL_RTC_FORCE_PU (BIT(19)) +#define RTC_CNTL_RTC_FORCE_PU_S 19 +#define RTC_CNTL_RTC_FORCE_PD (BIT(18)) +#define RTC_CNTL_RTC_FORCE_PD_S 18 +#define RTC_CNTL_RTC_SLOWMEM_PD_EN (BIT(17)) +#define RTC_CNTL_RTC_SLOWMEM_PD_EN_S 17 +#define RTC_CNTL_RTC_SLOWMEM_FORCE_PU (BIT(16)) +#define RTC_CNTL_RTC_SLOWMEM_FORCE_PU_S 16 +#define RTC_CNTL_RTC_SLOWMEM_FORCE_PD (BIT(15)) +#define RTC_CNTL_RTC_SLOWMEM_FORCE_PD_S 15 +#define RTC_CNTL_RTC_FASTMEM_PD_EN (BIT(14)) +#define RTC_CNTL_RTC_FASTMEM_PD_EN_S 14 +#define RTC_CNTL_RTC_FASTMEM_FORCE_PU (BIT(13)) +#define RTC_CNTL_RTC_FASTMEM_FORCE_PU_S 13 +#define RTC_CNTL_RTC_FASTMEM_FORCE_PD (BIT(12)) +#define RTC_CNTL_RTC_FASTMEM_FORCE_PD_S 12 +#define RTC_CNTL_RTC_SLOWMEM_FORCE_LPU (BIT(11)) +#define RTC_CNTL_RTC_SLOWMEM_FORCE_LPU_S 11 +#define RTC_CNTL_RTC_SLOWMEM_FORCE_LPD (BIT(10)) +#define RTC_CNTL_RTC_SLOWMEM_FORCE_LPD_S 10 +#define RTC_CNTL_RTC_SLOWMEM_FOLW_CPU (BIT(9)) +#define RTC_CNTL_RTC_SLOWMEM_FOLW_CPU_S 9 +#define RTC_CNTL_RTC_FASTMEM_FORCE_LPU (BIT(8)) +#define RTC_CNTL_RTC_FASTMEM_FORCE_LPU_S 8 +#define RTC_CNTL_RTC_FASTMEM_FORCE_LPD (BIT(7)) +#define RTC_CNTL_RTC_FASTMEM_FORCE_LPD_S 7 +#define RTC_CNTL_RTC_FASTMEM_FOLW_CPU (BIT(6)) +#define RTC_CNTL_RTC_FASTMEM_FOLW_CPU_S 6 +#define RTC_CNTL_RTC_FORCE_NOISO (BIT(5)) +#define RTC_CNTL_RTC_FORCE_NOISO_S 5 +#define RTC_CNTL_RTC_FORCE_ISO (BIT(4)) +#define RTC_CNTL_RTC_FORCE_ISO_S 4 +#define RTC_CNTL_RTC_SLOWMEM_FORCE_ISO (BIT(3)) +#define RTC_CNTL_RTC_SLOWMEM_FORCE_ISO_S 3 +#define RTC_CNTL_RTC_SLOWMEM_FORCE_NOISO (BIT(2)) +#define RTC_CNTL_RTC_SLOWMEM_FORCE_NOISO_S 2 +#define RTC_CNTL_RTC_FASTMEM_FORCE_ISO (BIT(1)) +#define RTC_CNTL_RTC_FASTMEM_FORCE_ISO_S 1 +#define RTC_CNTL_RTC_FASTMEM_FORCE_NOISO (BIT(0)) +#define RTC_CNTL_RTC_FASTMEM_FORCE_NOISO_S 0 + +#define DIG_PWC (DR_REG_RTCCNTL_BASE + 0x84) +#define RTC_CNTL_DG_WRAP_PD_EN (BIT(31)) +#define RTC_CNTL_DG_WRAP_PD_EN_S 31 +#define RTC_CNTL_WIFI_PD_EN (BIT(30)) +#define RTC_CNTL_WIFI_PD_EN_S 30 +#define RTC_CNTL_INTER_RAM4_PD_EN (BIT(29)) +#define RTC_CNTL_INTER_RAM4_PD_EN_S 29 +#define RTC_CNTL_INTER_RAM3_PD_EN (BIT(28)) +#define RTC_CNTL_INTER_RAM3_PD_EN_S 28 +#define RTC_CNTL_INTER_RAM2_PD_EN (BIT(27)) +#define RTC_CNTL_INTER_RAM2_PD_EN_S 27 +#define RTC_CNTL_INTER_RAM1_PD_EN (BIT(26)) +#define RTC_CNTL_INTER_RAM1_PD_EN_S 26 +#define RTC_CNTL_INTER_RAM0_PD_EN (BIT(25)) +#define RTC_CNTL_INTER_RAM0_PD_EN_S 25 +#define RTC_CNTL_ROM0_PD_EN (BIT(24)) +#define RTC_CNTL_ROM0_PD_EN_S 24 +#define RTC_CNTL_DG_WRAP_FORCE_PU (BIT(20)) +#define RTC_CNTL_DG_WRAP_FORCE_PU_S 20 +#define RTC_CNTL_DG_WRAP_FORCE_PD (BIT(19)) +#define RTC_CNTL_DG_WRAP_FORCE_PD_S 19 +#define RTC_CNTL_WIFI_FORCE_PU (BIT(18)) +#define RTC_CNTL_WIFI_FORCE_PU_S 18 +#define RTC_CNTL_WIFI_FORCE_PD (BIT(17)) +#define RTC_CNTL_WIFI_FORCE_PD_S 17 +#define RTC_CNTL_INTER_RAM4_FORCE_PU (BIT(16)) +#define RTC_CNTL_INTER_RAM4_FORCE_PU_S 16 +#define RTC_CNTL_INTER_RAM4_FORCE_PD (BIT(15)) +#define RTC_CNTL_INTER_RAM4_FORCE_PD_S 15 +#define RTC_CNTL_INTER_RAM3_FORCE_PU (BIT(14)) +#define RTC_CNTL_INTER_RAM3_FORCE_PU_S 14 +#define RTC_CNTL_INTER_RAM3_FORCE_PD (BIT(13)) +#define RTC_CNTL_INTER_RAM3_FORCE_PD_S 13 +#define RTC_CNTL_INTER_RAM2_FORCE_PU (BIT(12)) +#define RTC_CNTL_INTER_RAM2_FORCE_PU_S 12 +#define RTC_CNTL_INTER_RAM2_FORCE_PD (BIT(11)) +#define RTC_CNTL_INTER_RAM2_FORCE_PD_S 11 +#define RTC_CNTL_INTER_RAM1_FORCE_PU (BIT(10)) +#define RTC_CNTL_INTER_RAM1_FORCE_PU_S 10 +#define RTC_CNTL_INTER_RAM1_FORCE_PD (BIT(9)) +#define RTC_CNTL_INTER_RAM1_FORCE_PD_S 9 +#define RTC_CNTL_INTER_RAM0_FORCE_PU (BIT(8)) +#define RTC_CNTL_INTER_RAM0_FORCE_PU_S 8 +#define RTC_CNTL_INTER_RAM0_FORCE_PD (BIT(7)) +#define RTC_CNTL_INTER_RAM0_FORCE_PD_S 7 +#define RTC_CNTL_ROM0_FORCE_PU (BIT(6)) +#define RTC_CNTL_ROM0_FORCE_PU_S 6 +#define RTC_CNTL_ROM0_FORCE_PD (BIT(5)) +#define RTC_CNTL_ROM0_FORCE_PD_S 5 +#define RTC_CNTL_LSLP_MEM_FORCE_PU (BIT(4)) +#define RTC_CNTL_LSLP_MEM_FORCE_PU_S 4 +#define RTC_CNTL_LSLP_MEM_FORCE_PD (BIT(3)) +#define RTC_CNTL_LSLP_MEM_FORCE_PD_S 3 + +#define DIG_ISO (DR_REG_RTCCNTL_BASE + 0x88) +#define RTC_CNTL_DG_WRAP_FORCE_NOISO (BIT(31)) +#define RTC_CNTL_DG_WRAP_FORCE_NOISO_S 31 +#define RTC_CNTL_DG_WRAP_FORCE_ISO (BIT(30)) +#define RTC_CNTL_DG_WRAP_FORCE_ISO_S 30 +#define RTC_CNTL_WIFI_FORCE_NOISO (BIT(29)) +#define RTC_CNTL_WIFI_FORCE_NOISO_S 29 +#define RTC_CNTL_WIFI_FORCE_ISO (BIT(28)) +#define RTC_CNTL_WIFI_FORCE_ISO_S 28 +#define RTC_CNTL_INTER_RAM4_FORCE_NOISO (BIT(27)) +#define RTC_CNTL_INTER_RAM4_FORCE_NOISO_S 27 +#define RTC_CNTL_INTER_RAM4_FORCE_ISO (BIT(26)) +#define RTC_CNTL_INTER_RAM4_FORCE_ISO_S 26 +#define RTC_CNTL_INTER_RAM3_FORCE_NOISO (BIT(25)) +#define RTC_CNTL_INTER_RAM3_FORCE_NOISO_S 25 +#define RTC_CNTL_INTER_RAM3_FORCE_ISO (BIT(24)) +#define RTC_CNTL_INTER_RAM3_FORCE_ISO_S 24 +#define RTC_CNTL_INTER_RAM2_FORCE_NOISO (BIT(23)) +#define RTC_CNTL_INTER_RAM2_FORCE_NOISO_S 23 +#define RTC_CNTL_INTER_RAM2_FORCE_ISO (BIT(22)) +#define RTC_CNTL_INTER_RAM2_FORCE_ISO_S 22 +#define RTC_CNTL_INTER_RAM1_FORCE_NOISO (BIT(21)) +#define RTC_CNTL_INTER_RAM1_FORCE_NOISO_S 21 +#define RTC_CNTL_INTER_RAM1_FORCE_ISO (BIT(20)) +#define RTC_CNTL_INTER_RAM1_FORCE_ISO_S 20 +#define RTC_CNTL_INTER_RAM0_FORCE_NOISO (BIT(19)) +#define RTC_CNTL_INTER_RAM0_FORCE_NOISO_S 19 +#define RTC_CNTL_INTER_RAM0_FORCE_ISO (BIT(18)) +#define RTC_CNTL_INTER_RAM0_FORCE_ISO_S 18 +#define RTC_CNTL_ROM0_FORCE_NOISO (BIT(17)) +#define RTC_CNTL_ROM0_FORCE_NOISO_S 17 +#define RTC_CNTL_ROM0_FORCE_ISO (BIT(16)) +#define RTC_CNTL_ROM0_FORCE_ISO_S 16 +#define RTC_CNTL_DG_PAD_FORCE_HOLD (BIT(15)) +#define RTC_CNTL_DG_PAD_FORCE_HOLD_S 15 +#define RTC_CNTL_DG_PAD_FORCE_UNHOLD (BIT(14)) +#define RTC_CNTL_DG_PAD_FORCE_UNHOLD_S 14 +#define RTC_CNTL_DG_PAD_FORCE_ISO (BIT(13)) +#define RTC_CNTL_DG_PAD_FORCE_ISO_S 13 +#define RTC_CNTL_DG_PAD_FORCE_NOISO (BIT(12)) +#define RTC_CNTL_DG_PAD_FORCE_NOISO_S 12 +#define RTC_CNTL_DG_PAD_AUTOHOLD_EN (BIT(11)) +#define RTC_CNTL_DG_PAD_AUTOHOLD_EN_S 11 +#define RTC_CNTL_CLR_DG_PAD_AUTOHOLD (BIT(10)) +#define RTC_CNTL_CLR_DG_PAD_AUTOHOLD_S 10 +#define RTC_CNTL_DG_PAD_AUTOHOLD (BIT(9)) +#define RTC_CNTL_DG_PAD_AUTOHOLD_S 9 +#define RTC_CNTL_DIG_ISO_FORCE_ON (BIT(8)) +#define RTC_CNTL_DIG_ISO_FORCE_ON_S 8 +#define RTC_CNTL_DIG_ISO_FORCE_OFF (BIT(7)) +#define RTC_CNTL_DIG_ISO_FORCE_OFF_S 7 + +#define RTC_WDTCONFIG0 (DR_REG_RTCCNTL_BASE + 0x8c) +#define RTC_CNTL_WDT_EN (BIT(31)) +#define RTC_CNTL_WDT_EN_S 31 +#define RTC_CNTL_WDT_STG0 0x00000007 +#define RTC_CNTL_WDT_STG0_S 28 +#define RTC_CNTL_WDT_STG1 0x00000007 +#define RTC_CNTL_WDT_STG1_S 25 +#define RTC_CNTL_WDT_STG2 0x00000007 +#define RTC_CNTL_WDT_STG2_S 22 +#define RTC_CNTL_WDT_STG3 0x00000007 +#define RTC_CNTL_WDT_STG3_S 19 +#define RTC_CNTL_WDT_EDGE_INT_EN (BIT(18)) +#define RTC_CNTL_WDT_EDGE_INT_EN_S 18 +#define RTC_CNTL_WDT_LEVEL_INT_EN (BIT(17)) +#define RTC_CNTL_WDT_LEVEL_INT_EN_S 17 +#define RTC_CNTL_WDT_CPU_RESET_LENGTH 0x00000007 +#define RTC_CNTL_WDT_CPU_RESET_LENGTH_S 14 +#define RTC_CNTL_WDT_SYS_RESET_LENGTH 0x00000007 +#define RTC_CNTL_WDT_SYS_RESET_LENGTH_S 11 +#define RTC_CNTL_WDT_FLASHBOOT_MOD_EN (BIT(10)) +#define RTC_CNTL_WDT_FLASHBOOT_MOD_EN_S 10 +#define RTC_CNTL_WDT_PROCPU_RESET_EN (BIT(9)) +#define RTC_CNTL_WDT_PROCPU_RESET_EN_S 9 +#define RTC_CNTL_WDT_APPCPU_RESET_EN (BIT(8)) +#define RTC_CNTL_WDT_APPCPU_RESET_EN_S 8 +#define RTC_CNTL_WDT_PAUSE_IN_SLP (BIT(7)) +#define RTC_CNTL_WDT_PAUSE_IN_SLP_S 7 + +#define RTC_WDTCONFIG1 (DR_REG_RTCCNTL_BASE + 0x90) +#define RTC_CNTL_WDT_STG0_HOLD 0xFFFFFFFF +#define RTC_CNTL_WDT_STG0_HOLD_S 0 + +#define RTC_WDTCONFIG2 (DR_REG_RTCCNTL_BASE + 0x94) +#define RTC_CNTL_WDT_STG1_HOLD 0xFFFFFFFF +#define RTC_CNTL_WDT_STG1_HOLD_S 0 + +#define RTC_WDTCONFIG3 (DR_REG_RTCCNTL_BASE + 0x98) +#define RTC_CNTL_WDT_STG2_HOLD 0xFFFFFFFF +#define RTC_CNTL_WDT_STG2_HOLD_S 0 + +#define RTC_WDTCONFIG4 (DR_REG_RTCCNTL_BASE + 0x9c) +#define RTC_CNTL_WDT_STG3_HOLD 0xFFFFFFFF +#define RTC_CNTL_WDT_STG3_HOLD_S 0 + +#define RTC_WDTFEED (DR_REG_RTCCNTL_BASE + 0xa0) +#define RTC_CNTL_RTC_WDT_FEED (BIT(31)) +#define RTC_CNTL_RTC_WDT_FEED_S 31 + +#define RTC_WDTWPROTECT (DR_REG_RTCCNTL_BASE + 0xa4) +#define RTC_CNTL_WDT_WKEY 0xFFFFFFFF +#define RTC_CNTL_WDT_WKEY_S 0 + +#define RTC_TEST_MUX (DR_REG_RTCCNTL_BASE + 0xa8) +#define RTC_CNTL_DTEST_RTC 0x00000003 +#define RTC_CNTL_DTEST_RTC_S 30 +#define RTC_CNTL_ENT_RTC (BIT(29)) +#define RTC_CNTL_ENT_RTC_S 29 + +#define RTC_SW_CPU_STALL (DR_REG_RTCCNTL_BASE + 0xac) +#define RTC_CNTL_SW_STALL_PROCPU_C1 0x0000003F +#define RTC_CNTL_SW_STALL_PROCPU_C1_S 26 +#define RTC_CNTL_SW_STALL_APPCPU_C1 0x0000003F +#define RTC_CNTL_SW_STALL_APPCPU_C1_S 20 + +#define RTC_STORE4 (DR_REG_RTCCNTL_BASE + 0xb0) +#define RTC_CNTL_RTC_SCRATCH4 0xFFFFFFFF +#define RTC_CNTL_RTC_SCRATCH4_S 0 + +#define RTC_STORE5 (DR_REG_RTCCNTL_BASE + 0xb4) +#define RTC_CNTL_RTC_SCRATCH5 0xFFFFFFFF +#define RTC_CNTL_RTC_SCRATCH5_S 0 + +#define RTC_STORE6 (DR_REG_RTCCNTL_BASE + 0xb8) +#define RTC_CNTL_RTC_SCRATCH6 0xFFFFFFFF +#define RTC_CNTL_RTC_SCRATCH6_S 0 + +#define RTC_STORE7 (DR_REG_RTCCNTL_BASE + 0xbc) +#define RTC_CNTL_RTC_SCRATCH7 0xFFFFFFFF +#define RTC_CNTL_RTC_SCRATCH7_S 0 + +#define RTC_DIAG0 (DR_REG_RTCCNTL_BASE + 0xc0) +#define RTC_CNTL_RTC_LOW_POWER_DIAG0 0xFFFFFFFF +#define RTC_CNTL_RTC_LOW_POWER_DIAG0_S 0 + +#define RTC_DIAG1 (DR_REG_RTCCNTL_BASE + 0xc4) +#define RTC_CNTL_RTC_LOW_POWER_DIAG1 0xFFFFFFFF +#define RTC_CNTL_RTC_LOW_POWER_DIAG1_S 0 + +#define RTC_HOLD_FORCE (DR_REG_RTCCNTL_BASE + 0xc8) +#define RTC_CNTL_X32N_HOLD_FORCE (BIT(17)) +#define RTC_CNTL_X32N_HOLD_FORCE_S 17 +#define RTC_CNTL_X32P_HOLD_FORCE (BIT(16)) +#define RTC_CNTL_X32P_HOLD_FORCE_S 16 +#define RTC_CNTL_TOUCH_PAD7_HOLD_FORCE (BIT(15)) +#define RTC_CNTL_TOUCH_PAD7_HOLD_FORCE_S 15 +#define RTC_CNTL_TOUCH_PAD6_HOLD_FORCE (BIT(14)) +#define RTC_CNTL_TOUCH_PAD6_HOLD_FORCE_S 14 +#define RTC_CNTL_TOUCH_PAD5_HOLD_FORCE (BIT(13)) +#define RTC_CNTL_TOUCH_PAD5_HOLD_FORCE_S 13 +#define RTC_CNTL_TOUCH_PAD4_HOLD_FORCE (BIT(12)) +#define RTC_CNTL_TOUCH_PAD4_HOLD_FORCE_S 12 +#define RTC_CNTL_TOUCH_PAD3_HOLD_FORCE (BIT(11)) +#define RTC_CNTL_TOUCH_PAD3_HOLD_FORCE_S 11 +#define RTC_CNTL_TOUCH_PAD2_HOLD_FORCE (BIT(10)) +#define RTC_CNTL_TOUCH_PAD2_HOLD_FORCE_S 10 +#define RTC_CNTL_TOUCH_PAD1_HOLD_FORCE (BIT(9)) +#define RTC_CNTL_TOUCH_PAD1_HOLD_FORCE_S 9 +#define RTC_CNTL_TOUCH_PAD0_HOLD_FORCE (BIT(8)) +#define RTC_CNTL_TOUCH_PAD0_HOLD_FORCE_S 8 +#define RTC_CNTL_SENSE4_HOLD_FORCE (BIT(7)) +#define RTC_CNTL_SENSE4_HOLD_FORCE_S 7 +#define RTC_CNTL_SENSE3_HOLD_FORCE (BIT(6)) +#define RTC_CNTL_SENSE3_HOLD_FORCE_S 6 +#define RTC_CNTL_SENSE2_HOLD_FORCE (BIT(5)) +#define RTC_CNTL_SENSE2_HOLD_FORCE_S 5 +#define RTC_CNTL_SENSE1_HOLD_FORCE (BIT(4)) +#define RTC_CNTL_SENSE1_HOLD_FORCE_S 4 +#define RTC_CNTL_PDAC2_HOLD_FORCE (BIT(3)) +#define RTC_CNTL_PDAC2_HOLD_FORCE_S 3 +#define RTC_CNTL_PDAC1_HOLD_FORCE (BIT(2)) +#define RTC_CNTL_PDAC1_HOLD_FORCE_S 2 +#define RTC_CNTL_ADC2_HOLD_FORCE (BIT(1)) +#define RTC_CNTL_ADC2_HOLD_FORCE_S 1 +#define RTC_CNTL_ADC1_HOLD_FORCE (BIT(0)) +#define RTC_CNTL_ADC1_HOLD_FORCE_S 0 + +#define RTC_EXT_WAKEUP1 (DR_REG_RTCCNTL_BASE + 0xcc) +#define RTC_CNTL_EXT_WAKEUP1_STATUS_CLR (BIT(18)) +#define RTC_CNTL_EXT_WAKEUP1_STATUS_CLR_S 18 +#define RTC_CNTL_EXT_WAKEUP1_SEL 0x0003FFFF +#define RTC_CNTL_EXT_WAKEUP1_SEL_S 0 + +#define RTC_EXT_WAKEUP1_STATUS (DR_REG_RTCCNTL_BASE + 0xd0) +#define RTC_CNTL_EXT_WAKEUP1_STATUS 0x0003FFFF +#define RTC_CNTL_EXT_WAKEUP1_STATUS_S 0 + +#define RTC_BROWN_OUT (DR_REG_RTCCNTL_BASE + 0xd4) +#define RTC_CNTL_RTC_BROWN_OUT_DET (BIT(31)) +#define RTC_CNTL_RTC_BROWN_OUT_DET_S 31 +#define RTC_CNTL_BROWN_OUT_ENA (BIT(30)) +#define RTC_CNTL_BROWN_OUT_ENA_S 30 +#define RTC_CNTL_DBROWN_OUT_THRES 0x00000007 +#define RTC_CNTL_DBROWN_OUT_THRES_S 27 +#define RTC_CNTL_BROWN_OUT_RST_ENA (BIT(26)) +#define RTC_CNTL_BROWN_OUT_RST_ENA_S 26 +#define RTC_CNTL_BROWN_OUT_RST_WAIT 0x000003FF +#define RTC_CNTL_BROWN_OUT_RST_WAIT_S 16 +#define RTC_CNTL_BROWN_OUT_PD_RF_ENA (BIT(15)) +#define RTC_CNTL_BROWN_OUT_PD_RF_ENA_S 15 +#define RTC_CNTL_BROWN_OUT_CLOSE_FLASH_ENA (BIT(14)) +#define RTC_CNTL_BROWN_OUT_CLOSE_FLASH_ENA_S 14 + +#define RTC_MEM_CONF (DR_REG_RTCCNTL_BASE + 0x40 * 4) +#define RTC_MEM_CRC_FINISH (BIT(31)) +#define RTC_MEM_CRC_FINISH_S (31) +#define RTC_MEM_CRC_LEN (0x7ff) +#define RTC_MEM_CRC_LEN_S (20) +#define RTC_MEM_CRC_ADDR (0x7ff) +#define RTC_MEM_CRC_ADDR_S (9) +#define RTC_MEM_CRC_START (BIT(8)) +#define RTC_MEM_CRC_START_S (8) +#define RTC_MEM_PID_CONF (0xff) +#define RTC_MEM_PID_CONF_S (0) + +#define RTC_MEM_CRC_RES (DR_REG_RTCCNTL_BASE + 0x41 * 4) + + +#define RTC_CNTL_DATE (DR_REG_RTCCNTL_BASE + 0x13c) +#define RTC_CNTL_RTC_CNTL_DATE 0x0FFFFFFF +#define RTC_CNTL_RTC_CNTL_DATE_S 0 +#define RTC_CNTL_RTC_CNTL_DATE_VERSION 0x1604280 + +#endif /* _SOC_RTC_CNTL_REG_H_ */ diff --git a/components/esp32/include/soc/rtc_io_reg.h b/components/esp32/include/soc/rtc_io_reg.h new file mode 100644 index 0000000000..a60167c867 --- /dev/null +++ b/components/esp32/include/soc/rtc_io_reg.h @@ -0,0 +1,723 @@ +// Copyright 2015-2016 Espressif Systems (Shanghai) PTE LTD +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at + +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +#ifndef _SOC_RTC_IO_REG_H_ +#define _SOC_RTC_IO_REG_H_ + +#include "soc.h" + +#define RTC_GPIO_OUT (DR_REG_RTCIO_BASE + 0x0) +#define RTC_IO_RTC_GPIO_OUT_DATA 0x0003FFFF +#define RTC_IO_RTC_GPIO_OUT_DATA_S 14 + +#define RTC_GPIO_OUT_W1TS (DR_REG_RTCIO_BASE + 0x4) +#define RTC_IO_RTC_GPIO_OUT_DATA_W1TS 0x0003FFFF +#define RTC_IO_RTC_GPIO_OUT_DATA_W1TS_S 14 + +#define RTC_GPIO_OUT_W1TC (DR_REG_RTCIO_BASE + 0x8) +#define RTC_IO_RTC_GPIO_OUT_DATA_W1TC 0x0003FFFF +#define RTC_IO_RTC_GPIO_OUT_DATA_W1TC_S 14 + +#define RTC_GPIO_ENABLE (DR_REG_RTCIO_BASE + 0xc) +#define RTC_IO_RTC_GPIO_ENABLE 0x0003FFFF +#define RTC_IO_RTC_GPIO_ENABLE_S 14 + +#define RTC_GPIO_ENABLE_W1TS (DR_REG_RTCIO_BASE + 0x10) +#define RTC_IO_RTC_GPIO_ENABLE_W1TS 0x0003FFFF +#define RTC_IO_RTC_GPIO_ENABLE_W1TS_S 14 + +#define RTC_GPIO_ENABLE_W1TC (DR_REG_RTCIO_BASE + 0x14) +#define RTC_IO_RTC_GPIO_ENABLE_W1TC 0x0003FFFF +#define RTC_IO_RTC_GPIO_ENABLE_W1TC_S 14 + +#define RTC_GPIO_STATUS (DR_REG_RTCIO_BASE + 0x18) +#define RTC_IO_RTC_GPIO_STATUS_INT 0x0003FFFF +#define RTC_IO_RTC_GPIO_STATUS_INT_S 14 + +#define RTC_GPIO_STATUS_W1TS (DR_REG_RTCIO_BASE + 0x1c) +#define RTC_IO_RTC_GPIO_STATUS_INT_W1TS 0x0003FFFF +#define RTC_IO_RTC_GPIO_STATUS_INT_W1TS_S 14 + +#define RTC_GPIO_STATUS_W1TC (DR_REG_RTCIO_BASE + 0x20) +#define RTC_IO_RTC_GPIO_STATUS_INT_W1TC 0x0003FFFF +#define RTC_IO_RTC_GPIO_STATUS_INT_W1TC_S 14 + +#define RTC_GPIO_IN (DR_REG_RTCIO_BASE + 0x24) +#define RTC_IO_RTC_GPIO_IN_NEXT 0x0003FFFF +#define RTC_IO_RTC_GPIO_IN_NEXT_S 14 + +#define RTC_GPIO_PIN0 (DR_REG_RTCIO_BASE + 0x28) +#define RTC_IO_RTC_GPIO_PIN0_WAKEUP_ENABLE (BIT(10)) +#define RTC_IO_RTC_GPIO_PIN0_WAKEUP_ENABLE_S 10 +#define RTC_IO_RTC_GPIO_PIN0_INT_TYPE 0x00000007 +#define RTC_IO_RTC_GPIO_PIN0_INT_TYPE_S 7 +#define RTC_IO_RTC_GPIO_PIN0_PAD_DRIVER (BIT(2)) +#define RTC_IO_RTC_GPIO_PIN0_PAD_DRIVER_S 2 + +#define RTC_GPIO_PIN1 (DR_REG_RTCIO_BASE + 0x2c) +#define RTC_IO_RTC_GPIO_PIN1_WAKEUP_ENABLE (BIT(10)) +#define RTC_IO_RTC_GPIO_PIN1_WAKEUP_ENABLE_S 10 +#define RTC_IO_RTC_GPIO_PIN1_INT_TYPE 0x00000007 +#define RTC_IO_RTC_GPIO_PIN1_INT_TYPE_S 7 +#define RTC_IO_RTC_GPIO_PIN1_PAD_DRIVER (BIT(2)) +#define RTC_IO_RTC_GPIO_PIN1_PAD_DRIVER_S 2 + +#define RTC_GPIO_PIN2 (DR_REG_RTCIO_BASE + 0x30) +#define RTC_IO_RTC_GPIO_PIN2_WAKEUP_ENABLE (BIT(10)) +#define RTC_IO_RTC_GPIO_PIN2_WAKEUP_ENABLE_S 10 +#define RTC_IO_RTC_GPIO_PIN2_INT_TYPE 0x00000007 +#define RTC_IO_RTC_GPIO_PIN2_INT_TYPE_S 7 +#define RTC_IO_RTC_GPIO_PIN2_PAD_DRIVER (BIT(2)) +#define RTC_IO_RTC_GPIO_PIN2_PAD_DRIVER_S 2 + +#define RTC_GPIO_PIN3 (DR_REG_RTCIO_BASE + 0x34) +#define RTC_IO_RTC_GPIO_PIN3_WAKEUP_ENABLE (BIT(10)) +#define RTC_IO_RTC_GPIO_PIN3_WAKEUP_ENABLE_S 10 +#define RTC_IO_RTC_GPIO_PIN3_INT_TYPE 0x00000007 +#define RTC_IO_RTC_GPIO_PIN3_INT_TYPE_S 7 +#define RTC_IO_RTC_GPIO_PIN3_PAD_DRIVER (BIT(2)) +#define RTC_IO_RTC_GPIO_PIN3_PAD_DRIVER_S 2 + +#define RTC_GPIO_PIN4 (DR_REG_RTCIO_BASE + 0x38) +#define RTC_IO_RTC_GPIO_PIN4_WAKEUP_ENABLE (BIT(10)) +#define RTC_IO_RTC_GPIO_PIN4_WAKEUP_ENABLE_S 10 +#define RTC_IO_RTC_GPIO_PIN4_INT_TYPE 0x00000007 +#define RTC_IO_RTC_GPIO_PIN4_INT_TYPE_S 7 +#define RTC_IO_RTC_GPIO_PIN4_PAD_DRIVER (BIT(2)) +#define RTC_IO_RTC_GPIO_PIN4_PAD_DRIVER_S 2 + +#define RTC_GPIO_PIN5 (DR_REG_RTCIO_BASE + 0x3c) +#define RTC_IO_RTC_GPIO_PIN5_WAKEUP_ENABLE (BIT(10)) +#define RTC_IO_RTC_GPIO_PIN5_WAKEUP_ENABLE_S 10 +#define RTC_IO_RTC_GPIO_PIN5_INT_TYPE 0x00000007 +#define RTC_IO_RTC_GPIO_PIN5_INT_TYPE_S 7 +#define RTC_IO_RTC_GPIO_PIN5_PAD_DRIVER (BIT(2)) +#define RTC_IO_RTC_GPIO_PIN5_PAD_DRIVER_S 2 + +#define RTC_GPIO_PIN6 (DR_REG_RTCIO_BASE + 0x40) +#define RTC_IO_RTC_GPIO_PIN6_WAKEUP_ENABLE (BIT(10)) +#define RTC_IO_RTC_GPIO_PIN6_WAKEUP_ENABLE_S 10 +#define RTC_IO_RTC_GPIO_PIN6_INT_TYPE 0x00000007 +#define RTC_IO_RTC_GPIO_PIN6_INT_TYPE_S 7 +#define RTC_IO_RTC_GPIO_PIN6_PAD_DRIVER (BIT(2)) +#define RTC_IO_RTC_GPIO_PIN6_PAD_DRIVER_S 2 + +#define RTC_GPIO_PIN7 (DR_REG_RTCIO_BASE + 0x44) +#define RTC_IO_RTC_GPIO_PIN7_WAKEUP_ENABLE (BIT(10)) +#define RTC_IO_RTC_GPIO_PIN7_WAKEUP_ENABLE_S 10 +#define RTC_IO_RTC_GPIO_PIN7_INT_TYPE 0x00000007 +#define RTC_IO_RTC_GPIO_PIN7_INT_TYPE_S 7 +#define RTC_IO_RTC_GPIO_PIN7_PAD_DRIVER (BIT(2)) +#define RTC_IO_RTC_GPIO_PIN7_PAD_DRIVER_S 2 + +#define RTC_GPIO_PIN8 (DR_REG_RTCIO_BASE + 0x48) +#define RTC_IO_RTC_GPIO_PIN8_WAKEUP_ENABLE (BIT(10)) +#define RTC_IO_RTC_GPIO_PIN8_WAKEUP_ENABLE_S 10 +#define RTC_IO_RTC_GPIO_PIN8_INT_TYPE 0x00000007 +#define RTC_IO_RTC_GPIO_PIN8_INT_TYPE_S 7 +#define RTC_IO_RTC_GPIO_PIN8_PAD_DRIVER (BIT(2)) +#define RTC_IO_RTC_GPIO_PIN8_PAD_DRIVER_S 2 + +#define RTC_GPIO_PIN9 (DR_REG_RTCIO_BASE + 0x4c) +#define RTC_IO_RTC_GPIO_PIN9_WAKEUP_ENABLE (BIT(10)) +#define RTC_IO_RTC_GPIO_PIN9_WAKEUP_ENABLE_S 10 +#define RTC_IO_RTC_GPIO_PIN9_INT_TYPE 0x00000007 +#define RTC_IO_RTC_GPIO_PIN9_INT_TYPE_S 7 +#define RTC_IO_RTC_GPIO_PIN9_PAD_DRIVER (BIT(2)) +#define RTC_IO_RTC_GPIO_PIN9_PAD_DRIVER_S 2 + +#define RTC_GPIO_PIN10 (DR_REG_RTCIO_BASE + 0x50) +#define RTC_IO_RTC_GPIO_PIN10_WAKEUP_ENABLE (BIT(10)) +#define RTC_IO_RTC_GPIO_PIN10_WAKEUP_ENABLE_S 10 +#define RTC_IO_RTC_GPIO_PIN10_INT_TYPE 0x00000007 +#define RTC_IO_RTC_GPIO_PIN10_INT_TYPE_S 7 +#define RTC_IO_RTC_GPIO_PIN10_PAD_DRIVER (BIT(2)) +#define RTC_IO_RTC_GPIO_PIN10_PAD_DRIVER_S 2 + +#define RTC_GPIO_PIN11 (DR_REG_RTCIO_BASE + 0x54) +#define RTC_IO_RTC_GPIO_PIN11_WAKEUP_ENABLE (BIT(10)) +#define RTC_IO_RTC_GPIO_PIN11_WAKEUP_ENABLE_S 10 +#define RTC_IO_RTC_GPIO_PIN11_INT_TYPE 0x00000007 +#define RTC_IO_RTC_GPIO_PIN11_INT_TYPE_S 7 +#define RTC_IO_RTC_GPIO_PIN11_PAD_DRIVER (BIT(2)) +#define RTC_IO_RTC_GPIO_PIN11_PAD_DRIVER_S 2 + +#define RTC_GPIO_PIN12 (DR_REG_RTCIO_BASE + 0x58) +#define RTC_IO_RTC_GPIO_PIN12_WAKEUP_ENABLE (BIT(10)) +#define RTC_IO_RTC_GPIO_PIN12_WAKEUP_ENABLE_S 10 +#define RTC_IO_RTC_GPIO_PIN12_INT_TYPE 0x00000007 +#define RTC_IO_RTC_GPIO_PIN12_INT_TYPE_S 7 +#define RTC_IO_RTC_GPIO_PIN12_PAD_DRIVER (BIT(2)) +#define RTC_IO_RTC_GPIO_PIN12_PAD_DRIVER_S 2 + +#define RTC_GPIO_PIN13 (DR_REG_RTCIO_BASE + 0x5c) +#define RTC_IO_RTC_GPIO_PIN13_WAKEUP_ENABLE (BIT(10)) +#define RTC_IO_RTC_GPIO_PIN13_WAKEUP_ENABLE_S 10 +#define RTC_IO_RTC_GPIO_PIN13_INT_TYPE 0x00000007 +#define RTC_IO_RTC_GPIO_PIN13_INT_TYPE_S 7 +#define RTC_IO_RTC_GPIO_PIN13_PAD_DRIVER (BIT(2)) +#define RTC_IO_RTC_GPIO_PIN13_PAD_DRIVER_S 2 + +#define RTC_GPIO_PIN14 (DR_REG_RTCIO_BASE + 0x60) +#define RTC_IO_RTC_GPIO_PIN14_WAKEUP_ENABLE (BIT(10)) +#define RTC_IO_RTC_GPIO_PIN14_WAKEUP_ENABLE_S 10 +#define RTC_IO_RTC_GPIO_PIN14_INT_TYPE 0x00000007 +#define RTC_IO_RTC_GPIO_PIN14_INT_TYPE_S 7 +#define RTC_IO_RTC_GPIO_PIN14_PAD_DRIVER (BIT(2)) +#define RTC_IO_RTC_GPIO_PIN14_PAD_DRIVER_S 2 + +#define RTC_GPIO_PIN15 (DR_REG_RTCIO_BASE + 0x64) +#define RTC_IO_RTC_GPIO_PIN15_WAKEUP_ENABLE (BIT(10)) +#define RTC_IO_RTC_GPIO_PIN15_WAKEUP_ENABLE_S 10 +#define RTC_IO_RTC_GPIO_PIN15_INT_TYPE 0x00000007 +#define RTC_IO_RTC_GPIO_PIN15_INT_TYPE_S 7 +#define RTC_IO_RTC_GPIO_PIN15_PAD_DRIVER (BIT(2)) +#define RTC_IO_RTC_GPIO_PIN15_PAD_DRIVER_S 2 + +#define RTC_GPIO_PIN16 (DR_REG_RTCIO_BASE + 0x68) +#define RTC_IO_RTC_GPIO_PIN16_WAKEUP_ENABLE (BIT(10)) +#define RTC_IO_RTC_GPIO_PIN16_WAKEUP_ENABLE_S 10 +#define RTC_IO_RTC_GPIO_PIN16_INT_TYPE 0x00000007 +#define RTC_IO_RTC_GPIO_PIN16_INT_TYPE_S 7 +#define RTC_IO_RTC_GPIO_PIN16_PAD_DRIVER (BIT(2)) +#define RTC_IO_RTC_GPIO_PIN16_PAD_DRIVER_S 2 + +#define RTC_GPIO_PIN17 (DR_REG_RTCIO_BASE + 0x6c) +#define RTC_IO_RTC_GPIO_PIN17_WAKEUP_ENABLE (BIT(10)) +#define RTC_IO_RTC_GPIO_PIN17_WAKEUP_ENABLE_S 10 +#define RTC_IO_RTC_GPIO_PIN17_INT_TYPE 0x00000007 +#define RTC_IO_RTC_GPIO_PIN17_INT_TYPE_S 7 +#define RTC_IO_RTC_GPIO_PIN17_PAD_DRIVER (BIT(2)) +#define RTC_IO_RTC_GPIO_PIN17_PAD_DRIVER_S 2 + +#define RTC_DEBUG_SEL (DR_REG_RTCIO_BASE + 0x70) +#define RTC_IO_RTC_DEBUG_12M_NO_GATING (BIT(25)) +#define RTC_IO_RTC_DEBUG_12M_NO_GATING_S 25 +#define RTC_IO_RTC_DEBUG_SEL4 0x0000001F +#define RTC_IO_RTC_DEBUG_SEL4_S 20 +#define RTC_IO_RTC_DEBUG_SEL3 0x0000001F +#define RTC_IO_RTC_DEBUG_SEL3_S 15 +#define RTC_IO_RTC_DEBUG_SEL2 0x0000001F +#define RTC_IO_RTC_DEBUG_SEL2_S 10 +#define RTC_IO_RTC_DEBUG_SEL1 0x0000001F +#define RTC_IO_RTC_DEBUG_SEL1_S 5 +#define RTC_IO_RTC_DEBUG_SEL0 0x0000001F +#define RTC_IO_RTC_DEBUG_SEL0_S 0 + +#define DIG_PAD_HOLD (DR_REG_RTCIO_BASE + 0x74) +#define RTC_IO_DIG_PAD_HOLD 0xFFFFFFFF +#define RTC_IO_DIG_PAD_HOLD_S 0 + +#define HALL_SENS (DR_REG_RTCIO_BASE + 0x78) +#define RTC_IO_XPD_HALL (BIT(31)) +#define RTC_IO_XPD_HALL_S 31 +#define RTC_IO_HALL_PHASE (BIT(30)) +#define RTC_IO_HALL_PHASE_S 30 + +#define SENSOR_PADS (DR_REG_RTCIO_BASE + 0x7c) +#define RTC_IO_SENSE1_HOLD (BIT(31)) +#define RTC_IO_SENSE1_HOLD_S 31 +#define RTC_IO_SENSE2_HOLD (BIT(30)) +#define RTC_IO_SENSE2_HOLD_S 30 +#define RTC_IO_SENSE3_HOLD (BIT(29)) +#define RTC_IO_SENSE3_HOLD_S 29 +#define RTC_IO_SENSE4_HOLD (BIT(28)) +#define RTC_IO_SENSE4_HOLD_S 28 +#define RTC_IO_SENSE1_MUX_SEL (BIT(27)) +#define RTC_IO_SENSE1_MUX_SEL_S 27 +#define RTC_IO_SENSE2_MUX_SEL (BIT(26)) +#define RTC_IO_SENSE2_MUX_SEL_S 26 +#define RTC_IO_SENSE3_MUX_SEL (BIT(25)) +#define RTC_IO_SENSE3_MUX_SEL_S 25 +#define RTC_IO_SENSE4_MUX_SEL (BIT(24)) +#define RTC_IO_SENSE4_MUX_SEL_S 24 +#define RTC_IO_SENSE1_FUN_SEL 0x00000003 +#define RTC_IO_SENSE1_FUN_SEL_S 22 +#define RTC_IO_SENSE1_SLP_SEL (BIT(21)) +#define RTC_IO_SENSE1_SLP_SEL_S 21 +#define RTC_IO_SENSE1_SLP_IE (BIT(20)) +#define RTC_IO_SENSE1_SLP_IE_S 20 +#define RTC_IO_SENSE1_FUN_IE (BIT(19)) +#define RTC_IO_SENSE1_FUN_IE_S 19 +#define RTC_IO_SENSE2_FUN_SEL 0x00000003 +#define RTC_IO_SENSE2_FUN_SEL_S 17 +#define RTC_IO_SENSE2_SLP_SEL (BIT(16)) +#define RTC_IO_SENSE2_SLP_SEL_S 16 +#define RTC_IO_SENSE2_SLP_IE (BIT(15)) +#define RTC_IO_SENSE2_SLP_IE_S 15 +#define RTC_IO_SENSE2_FUN_IE (BIT(14)) +#define RTC_IO_SENSE2_FUN_IE_S 14 +#define RTC_IO_SENSE3_FUN_SEL 0x00000003 +#define RTC_IO_SENSE3_FUN_SEL_S 12 +#define RTC_IO_SENSE3_SLP_SEL (BIT(11)) +#define RTC_IO_SENSE3_SLP_SEL_S 11 +#define RTC_IO_SENSE3_SLP_IE (BIT(10)) +#define RTC_IO_SENSE3_SLP_IE_S 10 +#define RTC_IO_SENSE3_FUN_IE (BIT(9)) +#define RTC_IO_SENSE3_FUN_IE_S 9 +#define RTC_IO_SENSE4_FUN_SEL 0x00000003 +#define RTC_IO_SENSE4_FUN_SEL_S 7 +#define RTC_IO_SENSE4_SLP_SEL (BIT(6)) +#define RTC_IO_SENSE4_SLP_SEL_S 6 +#define RTC_IO_SENSE4_SLP_IE (BIT(5)) +#define RTC_IO_SENSE4_SLP_IE_S 5 +#define RTC_IO_SENSE4_FUN_IE (BIT(4)) +#define RTC_IO_SENSE4_FUN_IE_S 4 + +#define ADC_PAD (DR_REG_RTCIO_BASE + 0x80) +#define RTC_IO_ADC1_HOLD (BIT(31)) +#define RTC_IO_ADC1_HOLD_S 31 +#define RTC_IO_ADC2_HOLD (BIT(30)) +#define RTC_IO_ADC2_HOLD_S 30 +#define RTC_IO_ADC1_MUX_SEL (BIT(29)) +#define RTC_IO_ADC1_MUX_SEL_S 29 +#define RTC_IO_ADC2_MUX_SEL (BIT(28)) +#define RTC_IO_ADC2_MUX_SEL_S 28 +#define RTC_IO_ADC1_FUN_SEL 0x00000003 +#define RTC_IO_ADC1_FUN_SEL_S 26 +#define RTC_IO_ADC1_SLP_SEL (BIT(25)) +#define RTC_IO_ADC1_SLP_SEL_S 25 +#define RTC_IO_ADC1_SLP_IE (BIT(24)) +#define RTC_IO_ADC1_SLP_IE_S 24 +#define RTC_IO_ADC1_FUN_IE (BIT(23)) +#define RTC_IO_ADC1_FUN_IE_S 23 +#define RTC_IO_ADC2_FUN_SEL 0x00000003 +#define RTC_IO_ADC2_FUN_SEL_S 21 +#define RTC_IO_ADC2_SLP_SEL (BIT(20)) +#define RTC_IO_ADC2_SLP_SEL_S 20 +#define RTC_IO_ADC2_SLP_IE (BIT(19)) +#define RTC_IO_ADC2_SLP_IE_S 19 +#define RTC_IO_ADC2_FUN_IE (BIT(18)) +#define RTC_IO_ADC2_FUN_IE_S 18 + +#define PAD_DAC1 (DR_REG_RTCIO_BASE + 0x84) +#define RTC_IO_PDAC1_DRV 0x00000003 +#define RTC_IO_PDAC1_DRV_S 30 +#define RTC_IO_PDAC1_HOLD (BIT(29)) +#define RTC_IO_PDAC1_HOLD_S 29 +#define RTC_IO_PDAC1_RDE (BIT(28)) +#define RTC_IO_PDAC1_RDE_S 28 +#define RTC_IO_PDAC1_RUE (BIT(27)) +#define RTC_IO_PDAC1_RUE_S 27 +#define RTC_IO_PDAC1_DAC 0x000000FF +#define RTC_IO_PDAC1_DAC_S 19 +#define RTC_IO_PDAC1_XPD_DAC (BIT(18)) +#define RTC_IO_PDAC1_XPD_DAC_S 18 +#define RTC_IO_PDAC1_MUX_SEL (BIT(17)) +#define RTC_IO_PDAC1_MUX_SEL_S 17 +#define RTC_IO_PDAC1_FUN_SEL 0x00000003 +#define RTC_IO_PDAC1_FUN_SEL_S 15 +#define RTC_IO_PDAC1_SLP_SEL (BIT(14)) +#define RTC_IO_PDAC1_SLP_SEL_S 14 +#define RTC_IO_PDAC1_SLP_IE (BIT(13)) +#define RTC_IO_PDAC1_SLP_IE_S 13 +#define RTC_IO_PDAC1_SLP_OE (BIT(12)) +#define RTC_IO_PDAC1_SLP_OE_S 12 +#define RTC_IO_PDAC1_FUN_IE (BIT(11)) +#define RTC_IO_PDAC1_FUN_IE_S 11 +#define RTC_IO_PDAC1_DAC_XPD_FORCE (BIT(10)) +#define RTC_IO_PDAC1_DAC_XPD_FORCE_S 10 + +#define PAD_DAC2 (DR_REG_RTCIO_BASE + 0x88) +#define RTC_IO_PDAC2_DRV 0x00000003 +#define RTC_IO_PDAC2_DRV_S 30 +#define RTC_IO_PDAC2_HOLD (BIT(29)) +#define RTC_IO_PDAC2_HOLD_S 29 +#define RTC_IO_PDAC2_RDE (BIT(28)) +#define RTC_IO_PDAC2_RDE_S 28 +#define RTC_IO_PDAC2_RUE (BIT(27)) +#define RTC_IO_PDAC2_RUE_S 27 +#define RTC_IO_PDAC2_DAC 0x000000FF +#define RTC_IO_PDAC2_DAC_S 19 +#define RTC_IO_PDAC2_XPD_DAC (BIT(18)) +#define RTC_IO_PDAC2_XPD_DAC_S 18 +#define RTC_IO_PDAC2_MUX_SEL (BIT(17)) +#define RTC_IO_PDAC2_MUX_SEL_S 17 +#define RTC_IO_PDAC2_FUN_SEL 0x00000003 +#define RTC_IO_PDAC2_FUN_SEL_S 15 +#define RTC_IO_PDAC2_SLP_SEL (BIT(14)) +#define RTC_IO_PDAC2_SLP_SEL_S 14 +#define RTC_IO_PDAC2_SLP_IE (BIT(13)) +#define RTC_IO_PDAC2_SLP_IE_S 13 +#define RTC_IO_PDAC2_SLP_OE (BIT(12)) +#define RTC_IO_PDAC2_SLP_OE_S 12 +#define RTC_IO_PDAC2_FUN_IE (BIT(11)) +#define RTC_IO_PDAC2_FUN_IE_S 11 +#define RTC_IO_PDAC2_DAC_XPD_FORCE (BIT(10)) +#define RTC_IO_PDAC2_DAC_XPD_FORCE_S 10 + +#define XTAL_32K_PAD (DR_REG_RTCIO_BASE + 0x8c) +#define RTC_IO_X32N_DRV 0x00000003 +#define RTC_IO_X32N_DRV_S 30 +#define RTC_IO_X32N_HOLD (BIT(29)) +#define RTC_IO_X32N_HOLD_S 29 +#define RTC_IO_X32N_RDE (BIT(28)) +#define RTC_IO_X32N_RDE_S 28 +#define RTC_IO_X32N_RUE (BIT(27)) +#define RTC_IO_X32N_RUE_S 27 +#define RTC_IO_X32P_DRV 0x00000003 +#define RTC_IO_X32P_DRV_S 25 +#define RTC_IO_X32P_HOLD (BIT(24)) +#define RTC_IO_X32P_HOLD_S 24 +#define RTC_IO_X32P_RDE (BIT(23)) +#define RTC_IO_X32P_RDE_S 23 +#define RTC_IO_X32P_RUE (BIT(22)) +#define RTC_IO_X32P_RUE_S 22 +#define RTC_IO_DAC_XTAL_32K 0x00000003 +#define RTC_IO_DAC_XTAL_32K_S 20 +#define RTC_IO_XPD_XTAL_32K (BIT(19)) +#define RTC_IO_XPD_XTAL_32K_S 19 +#define RTC_IO_X32N_MUX_SEL (BIT(18)) +#define RTC_IO_X32N_MUX_SEL_S 18 +#define RTC_IO_X32P_MUX_SEL (BIT(17)) +#define RTC_IO_X32P_MUX_SEL_S 17 +#define RTC_IO_X32N_FUN_SEL 0x00000003 +#define RTC_IO_X32N_FUN_SEL_S 15 +#define RTC_IO_X32N_SLP_SEL (BIT(14)) +#define RTC_IO_X32N_SLP_SEL_S 14 +#define RTC_IO_X32N_SLP_IE (BIT(13)) +#define RTC_IO_X32N_SLP_IE_S 13 +#define RTC_IO_X32N_SLP_OE (BIT(12)) +#define RTC_IO_X32N_SLP_OE_S 12 +#define RTC_IO_X32N_FUN_IE (BIT(11)) +#define RTC_IO_X32N_FUN_IE_S 11 +#define RTC_IO_X32P_FUN_SEL 0x00000003 +#define RTC_IO_X32P_FUN_SEL_S 9 +#define RTC_IO_X32P_SLP_SEL (BIT(8)) +#define RTC_IO_X32P_SLP_SEL_S 8 +#define RTC_IO_X32P_SLP_IE (BIT(7)) +#define RTC_IO_X32P_SLP_IE_S 7 +#define RTC_IO_X32P_SLP_OE (BIT(6)) +#define RTC_IO_X32P_SLP_OE_S 6 +#define RTC_IO_X32P_FUN_IE (BIT(5)) +#define RTC_IO_X32P_FUN_IE_S 5 +#define RTC_IO_DRES_XTAL_32K 0x00000003 +#define RTC_IO_DRES_XTAL_32K_S 3 +#define RTC_IO_DBIAS_XTAL_32K 0x00000003 +#define RTC_IO_DBIAS_XTAL_32K_S 1 + +#define TOUCH_CFG (DR_REG_RTCIO_BASE + 0x90) +#define RTC_IO_TOUCH_XPD_BIAS (BIT(31)) +#define RTC_IO_TOUCH_XPD_BIAS_S 31 +#define RTC_IO_TOUCH_DREFH 0x00000003 +#define RTC_IO_TOUCH_DREFH_S 29 +#define RTC_IO_TOUCH_DREFL 0x00000003 +#define RTC_IO_TOUCH_DREFL_S 27 +#define RTC_IO_TOUCH_DRANGE 0x00000003 +#define RTC_IO_TOUCH_DRANGE_S 25 +#define RTC_IO_TOUCH_DCUR 0x00000003 +#define RTC_IO_TOUCH_DCUR_S 23 + +#define TOUCH_PAD0 (DR_REG_RTCIO_BASE + 0x94) +#define RTC_IO_TOUCH_PAD0_HOLD (BIT(31)) +#define RTC_IO_TOUCH_PAD0_HOLD_S 31 +#define RTC_IO_TOUCH_PAD0_DRV 0x00000003 +#define RTC_IO_TOUCH_PAD0_DRV_S 29 +#define RTC_IO_TOUCH_PAD0_RDE (BIT(28)) +#define RTC_IO_TOUCH_PAD0_RDE_S 28 +#define RTC_IO_TOUCH_PAD0_RUE (BIT(27)) +#define RTC_IO_TOUCH_PAD0_RUE_S 27 +#define RTC_IO_TOUCH_PAD0_DAC 0x00000007 +#define RTC_IO_TOUCH_PAD0_DAC_S 23 +#define RTC_IO_TOUCH_PAD0_START (BIT(22)) +#define RTC_IO_TOUCH_PAD0_START_S 22 +#define RTC_IO_TOUCH_PAD0_TIE_OPT (BIT(21)) +#define RTC_IO_TOUCH_PAD0_TIE_OPT_S 21 +#define RTC_IO_TOUCH_PAD0_XPD (BIT(20)) +#define RTC_IO_TOUCH_PAD0_XPD_S 20 +#define RTC_IO_TOUCH_PAD0_MUX_SEL (BIT(19)) +#define RTC_IO_TOUCH_PAD0_MUX_SEL_S 19 +#define RTC_IO_TOUCH_PAD0_FUN_SEL 0x00000003 +#define RTC_IO_TOUCH_PAD0_FUN_SEL_S 17 +#define RTC_IO_TOUCH_PAD0_SLP_SEL (BIT(16)) +#define RTC_IO_TOUCH_PAD0_SLP_SEL_S 16 +#define RTC_IO_TOUCH_PAD0_SLP_IE (BIT(15)) +#define RTC_IO_TOUCH_PAD0_SLP_IE_S 15 +#define RTC_IO_TOUCH_PAD0_SLP_OE (BIT(14)) +#define RTC_IO_TOUCH_PAD0_SLP_OE_S 14 +#define RTC_IO_TOUCH_PAD0_FUN_IE (BIT(13)) +#define RTC_IO_TOUCH_PAD0_FUN_IE_S 13 +#define RTC_IO_TOUCH_PAD0_TO_GPIO (BIT(12)) +#define RTC_IO_TOUCH_PAD0_TO_GPIO_S 12 + +#define TOUCH_PAD1 (DR_REG_RTCIO_BASE + 0x98) +#define RTC_IO_TOUCH_PAD1_HOLD (BIT(31)) +#define RTC_IO_TOUCH_PAD1_HOLD_S 31 +#define RTC_IO_TOUCH_PAD1_DRV 0x00000003 +#define RTC_IO_TOUCH_PAD1_DRV_S 29 +#define RTC_IO_TOUCH_PAD1_RDE (BIT(28)) +#define RTC_IO_TOUCH_PAD1_RDE_S 28 +#define RTC_IO_TOUCH_PAD1_RUE (BIT(27)) +#define RTC_IO_TOUCH_PAD1_RUE_S 27 +#define RTC_IO_TOUCH_PAD1_DAC 0x00000007 +#define RTC_IO_TOUCH_PAD1_DAC_S 23 +#define RTC_IO_TOUCH_PAD1_START (BIT(22)) +#define RTC_IO_TOUCH_PAD1_START_S 22 +#define RTC_IO_TOUCH_PAD1_TIE_OPT (BIT(21)) +#define RTC_IO_TOUCH_PAD1_TIE_OPT_S 21 +#define RTC_IO_TOUCH_PAD1_XPD (BIT(20)) +#define RTC_IO_TOUCH_PAD1_XPD_S 20 +#define RTC_IO_TOUCH_PAD1_MUX_SEL (BIT(19)) +#define RTC_IO_TOUCH_PAD1_MUX_SEL_S 19 +#define RTC_IO_TOUCH_PAD1_FUN_SEL 0x00000003 +#define RTC_IO_TOUCH_PAD1_FUN_SEL_S 17 +#define RTC_IO_TOUCH_PAD1_SLP_SEL (BIT(16)) +#define RTC_IO_TOUCH_PAD1_SLP_SEL_S 16 +#define RTC_IO_TOUCH_PAD1_SLP_IE (BIT(15)) +#define RTC_IO_TOUCH_PAD1_SLP_IE_S 15 +#define RTC_IO_TOUCH_PAD1_SLP_OE (BIT(14)) +#define RTC_IO_TOUCH_PAD1_SLP_OE_S 14 +#define RTC_IO_TOUCH_PAD1_FUN_IE (BIT(13)) +#define RTC_IO_TOUCH_PAD1_FUN_IE_S 13 +#define RTC_IO_TOUCH_PAD1_TO_GPIO (BIT(12)) +#define RTC_IO_TOUCH_PAD1_TO_GPIO_S 12 + +#define TOUCH_PAD2 (DR_REG_RTCIO_BASE + 0x9c) +#define RTC_IO_TOUCH_PAD2_HOLD (BIT(31)) +#define RTC_IO_TOUCH_PAD2_HOLD_S 31 +#define RTC_IO_TOUCH_PAD2_DRV 0x00000003 +#define RTC_IO_TOUCH_PAD2_DRV_S 29 +#define RTC_IO_TOUCH_PAD2_RDE (BIT(28)) +#define RTC_IO_TOUCH_PAD2_RDE_S 28 +#define RTC_IO_TOUCH_PAD2_RUE (BIT(27)) +#define RTC_IO_TOUCH_PAD2_RUE_S 27 +#define RTC_IO_TOUCH_PAD2_DAC 0x00000007 +#define RTC_IO_TOUCH_PAD2_DAC_S 23 +#define RTC_IO_TOUCH_PAD2_START (BIT(22)) +#define RTC_IO_TOUCH_PAD2_START_S 22 +#define RTC_IO_TOUCH_PAD2_TIE_OPT (BIT(21)) +#define RTC_IO_TOUCH_PAD2_TIE_OPT_S 21 +#define RTC_IO_TOUCH_PAD2_XPD (BIT(20)) +#define RTC_IO_TOUCH_PAD2_XPD_S 20 +#define RTC_IO_TOUCH_PAD2_MUX_SEL (BIT(19)) +#define RTC_IO_TOUCH_PAD2_MUX_SEL_S 19 +#define RTC_IO_TOUCH_PAD2_FUN_SEL 0x00000003 +#define RTC_IO_TOUCH_PAD2_FUN_SEL_S 17 +#define RTC_IO_TOUCH_PAD2_SLP_SEL (BIT(16)) +#define RTC_IO_TOUCH_PAD2_SLP_SEL_S 16 +#define RTC_IO_TOUCH_PAD2_SLP_IE (BIT(15)) +#define RTC_IO_TOUCH_PAD2_SLP_IE_S 15 +#define RTC_IO_TOUCH_PAD2_SLP_OE (BIT(14)) +#define RTC_IO_TOUCH_PAD2_SLP_OE_S 14 +#define RTC_IO_TOUCH_PAD2_FUN_IE (BIT(13)) +#define RTC_IO_TOUCH_PAD2_FUN_IE_S 13 +#define RTC_IO_TOUCH_PAD2_TO_GPIO (BIT(12)) +#define RTC_IO_TOUCH_PAD2_TO_GPIO_S 12 + +#define TOUCH_PAD3 (DR_REG_RTCIO_BASE + 0xa0) +#define RTC_IO_TOUCH_PAD3_HOLD (BIT(31)) +#define RTC_IO_TOUCH_PAD3_HOLD_S 31 +#define RTC_IO_TOUCH_PAD3_DRV 0x00000003 +#define RTC_IO_TOUCH_PAD3_DRV_S 29 +#define RTC_IO_TOUCH_PAD3_RDE (BIT(28)) +#define RTC_IO_TOUCH_PAD3_RDE_S 28 +#define RTC_IO_TOUCH_PAD3_RUE (BIT(27)) +#define RTC_IO_TOUCH_PAD3_RUE_S 27 +#define RTC_IO_TOUCH_PAD3_DAC 0x00000007 +#define RTC_IO_TOUCH_PAD3_DAC_S 23 +#define RTC_IO_TOUCH_PAD3_START (BIT(22)) +#define RTC_IO_TOUCH_PAD3_START_S 22 +#define RTC_IO_TOUCH_PAD3_TIE_OPT (BIT(21)) +#define RTC_IO_TOUCH_PAD3_TIE_OPT_S 21 +#define RTC_IO_TOUCH_PAD3_XPD (BIT(20)) +#define RTC_IO_TOUCH_PAD3_XPD_S 20 +#define RTC_IO_TOUCH_PAD3_MUX_SEL (BIT(19)) +#define RTC_IO_TOUCH_PAD3_MUX_SEL_S 19 +#define RTC_IO_TOUCH_PAD3_FUN_SEL 0x00000003 +#define RTC_IO_TOUCH_PAD3_FUN_SEL_S 17 +#define RTC_IO_TOUCH_PAD3_SLP_SEL (BIT(16)) +#define RTC_IO_TOUCH_PAD3_SLP_SEL_S 16 +#define RTC_IO_TOUCH_PAD3_SLP_IE (BIT(15)) +#define RTC_IO_TOUCH_PAD3_SLP_IE_S 15 +#define RTC_IO_TOUCH_PAD3_SLP_OE (BIT(14)) +#define RTC_IO_TOUCH_PAD3_SLP_OE_S 14 +#define RTC_IO_TOUCH_PAD3_FUN_IE (BIT(13)) +#define RTC_IO_TOUCH_PAD3_FUN_IE_S 13 +#define RTC_IO_TOUCH_PAD3_TO_GPIO (BIT(12)) +#define RTC_IO_TOUCH_PAD3_TO_GPIO_S 12 + +#define TOUCH_PAD4 (DR_REG_RTCIO_BASE + 0xa4) +#define RTC_IO_TOUCH_PAD4_HOLD (BIT(31)) +#define RTC_IO_TOUCH_PAD4_HOLD_S 31 +#define RTC_IO_TOUCH_PAD4_DRV 0x00000003 +#define RTC_IO_TOUCH_PAD4_DRV_S 29 +#define RTC_IO_TOUCH_PAD4_RDE (BIT(28)) +#define RTC_IO_TOUCH_PAD4_RDE_S 28 +#define RTC_IO_TOUCH_PAD4_RUE (BIT(27)) +#define RTC_IO_TOUCH_PAD4_RUE_S 27 +#define RTC_IO_TOUCH_PAD4_DAC 0x00000007 +#define RTC_IO_TOUCH_PAD4_DAC_S 23 +#define RTC_IO_TOUCH_PAD4_START (BIT(22)) +#define RTC_IO_TOUCH_PAD4_START_S 22 +#define RTC_IO_TOUCH_PAD4_TIE_OPT (BIT(21)) +#define RTC_IO_TOUCH_PAD4_TIE_OPT_S 21 +#define RTC_IO_TOUCH_PAD4_XPD (BIT(20)) +#define RTC_IO_TOUCH_PAD4_XPD_S 20 +#define RTC_IO_TOUCH_PAD4_MUX_SEL (BIT(19)) +#define RTC_IO_TOUCH_PAD4_MUX_SEL_S 19 +#define RTC_IO_TOUCH_PAD4_FUN_SEL 0x00000003 +#define RTC_IO_TOUCH_PAD4_FUN_SEL_S 17 +#define RTC_IO_TOUCH_PAD4_SLP_SEL (BIT(16)) +#define RTC_IO_TOUCH_PAD4_SLP_SEL_S 16 +#define RTC_IO_TOUCH_PAD4_SLP_IE (BIT(15)) +#define RTC_IO_TOUCH_PAD4_SLP_IE_S 15 +#define RTC_IO_TOUCH_PAD4_SLP_OE (BIT(14)) +#define RTC_IO_TOUCH_PAD4_SLP_OE_S 14 +#define RTC_IO_TOUCH_PAD4_FUN_IE (BIT(13)) +#define RTC_IO_TOUCH_PAD4_FUN_IE_S 13 +#define RTC_IO_TOUCH_PAD4_TO_GPIO (BIT(12)) +#define RTC_IO_TOUCH_PAD4_TO_GPIO_S 12 + +#define TOUCH_PAD5 (DR_REG_RTCIO_BASE + 0xa8) +#define RTC_IO_TOUCH_PAD5_HOLD (BIT(31)) +#define RTC_IO_TOUCH_PAD5_HOLD_S 31 +#define RTC_IO_TOUCH_PAD5_DRV 0x00000003 +#define RTC_IO_TOUCH_PAD5_DRV_S 29 +#define RTC_IO_TOUCH_PAD5_RDE (BIT(28)) +#define RTC_IO_TOUCH_PAD5_RDE_S 28 +#define RTC_IO_TOUCH_PAD5_RUE (BIT(27)) +#define RTC_IO_TOUCH_PAD5_RUE_S 27 +#define RTC_IO_TOUCH_PAD5_DAC 0x00000007 +#define RTC_IO_TOUCH_PAD5_DAC_S 23 +#define RTC_IO_TOUCH_PAD5_START (BIT(22)) +#define RTC_IO_TOUCH_PAD5_START_S 22 +#define RTC_IO_TOUCH_PAD5_TIE_OPT (BIT(21)) +#define RTC_IO_TOUCH_PAD5_TIE_OPT_S 21 +#define RTC_IO_TOUCH_PAD5_XPD (BIT(20)) +#define RTC_IO_TOUCH_PAD5_XPD_S 20 +#define RTC_IO_TOUCH_PAD5_MUX_SEL (BIT(19)) +#define RTC_IO_TOUCH_PAD5_MUX_SEL_S 19 +#define RTC_IO_TOUCH_PAD5_FUN_SEL 0x00000003 +#define RTC_IO_TOUCH_PAD5_FUN_SEL_S 17 +#define RTC_IO_TOUCH_PAD5_SLP_SEL (BIT(16)) +#define RTC_IO_TOUCH_PAD5_SLP_SEL_S 16 +#define RTC_IO_TOUCH_PAD5_SLP_IE (BIT(15)) +#define RTC_IO_TOUCH_PAD5_SLP_IE_S 15 +#define RTC_IO_TOUCH_PAD5_SLP_OE (BIT(14)) +#define RTC_IO_TOUCH_PAD5_SLP_OE_S 14 +#define RTC_IO_TOUCH_PAD5_FUN_IE (BIT(13)) +#define RTC_IO_TOUCH_PAD5_FUN_IE_S 13 +#define RTC_IO_TOUCH_PAD5_TO_GPIO (BIT(12)) +#define RTC_IO_TOUCH_PAD5_TO_GPIO_S 12 + +#define TOUCH_PAD6 (DR_REG_RTCIO_BASE + 0xac) +#define RTC_IO_TOUCH_PAD6_HOLD (BIT(31)) +#define RTC_IO_TOUCH_PAD6_HOLD_S 31 +#define RTC_IO_TOUCH_PAD6_DRV 0x00000003 +#define RTC_IO_TOUCH_PAD6_DRV_S 29 +#define RTC_IO_TOUCH_PAD6_RDE (BIT(28)) +#define RTC_IO_TOUCH_PAD6_RDE_S 28 +#define RTC_IO_TOUCH_PAD6_RUE (BIT(27)) +#define RTC_IO_TOUCH_PAD6_RUE_S 27 +#define RTC_IO_TOUCH_PAD6_DAC 0x00000007 +#define RTC_IO_TOUCH_PAD6_DAC_S 23 +#define RTC_IO_TOUCH_PAD6_START (BIT(22)) +#define RTC_IO_TOUCH_PAD6_START_S 22 +#define RTC_IO_TOUCH_PAD6_TIE_OPT (BIT(21)) +#define RTC_IO_TOUCH_PAD6_TIE_OPT_S 21 +#define RTC_IO_TOUCH_PAD6_XPD (BIT(20)) +#define RTC_IO_TOUCH_PAD6_XPD_S 20 +#define RTC_IO_TOUCH_PAD6_MUX_SEL (BIT(19)) +#define RTC_IO_TOUCH_PAD6_MUX_SEL_S 19 +#define RTC_IO_TOUCH_PAD6_FUN_SEL 0x00000003 +#define RTC_IO_TOUCH_PAD6_FUN_SEL_S 17 +#define RTC_IO_TOUCH_PAD6_SLP_SEL (BIT(16)) +#define RTC_IO_TOUCH_PAD6_SLP_SEL_S 16 +#define RTC_IO_TOUCH_PAD6_SLP_IE (BIT(15)) +#define RTC_IO_TOUCH_PAD6_SLP_IE_S 15 +#define RTC_IO_TOUCH_PAD6_SLP_OE (BIT(14)) +#define RTC_IO_TOUCH_PAD6_SLP_OE_S 14 +#define RTC_IO_TOUCH_PAD6_FUN_IE (BIT(13)) +#define RTC_IO_TOUCH_PAD6_FUN_IE_S 13 +#define RTC_IO_TOUCH_PAD6_TO_GPIO (BIT(12)) +#define RTC_IO_TOUCH_PAD6_TO_GPIO_S 12 + +#define TOUCH_PAD7 (DR_REG_RTCIO_BASE + 0xb0) +#define RTC_IO_TOUCH_PAD7_HOLD (BIT(31)) +#define RTC_IO_TOUCH_PAD7_HOLD_S 31 +#define RTC_IO_TOUCH_PAD7_DRV 0x00000003 +#define RTC_IO_TOUCH_PAD7_DRV_S 29 +#define RTC_IO_TOUCH_PAD7_RDE (BIT(28)) +#define RTC_IO_TOUCH_PAD7_RDE_S 28 +#define RTC_IO_TOUCH_PAD7_RUE (BIT(27)) +#define RTC_IO_TOUCH_PAD7_RUE_S 27 +#define RTC_IO_TOUCH_PAD7_DAC 0x00000007 +#define RTC_IO_TOUCH_PAD7_DAC_S 23 +#define RTC_IO_TOUCH_PAD7_START (BIT(22)) +#define RTC_IO_TOUCH_PAD7_START_S 22 +#define RTC_IO_TOUCH_PAD7_TIE_OPT (BIT(21)) +#define RTC_IO_TOUCH_PAD7_TIE_OPT_S 21 +#define RTC_IO_TOUCH_PAD7_XPD (BIT(20)) +#define RTC_IO_TOUCH_PAD7_XPD_S 20 +#define RTC_IO_TOUCH_PAD7_MUX_SEL (BIT(19)) +#define RTC_IO_TOUCH_PAD7_MUX_SEL_S 19 +#define RTC_IO_TOUCH_PAD7_FUN_SEL 0x00000003 +#define RTC_IO_TOUCH_PAD7_FUN_SEL_S 17 +#define RTC_IO_TOUCH_PAD7_SLP_SEL (BIT(16)) +#define RTC_IO_TOUCH_PAD7_SLP_SEL_S 16 +#define RTC_IO_TOUCH_PAD7_SLP_IE (BIT(15)) +#define RTC_IO_TOUCH_PAD7_SLP_IE_S 15 +#define RTC_IO_TOUCH_PAD7_SLP_OE (BIT(14)) +#define RTC_IO_TOUCH_PAD7_SLP_OE_S 14 +#define RTC_IO_TOUCH_PAD7_FUN_IE (BIT(13)) +#define RTC_IO_TOUCH_PAD7_FUN_IE_S 13 +#define RTC_IO_TOUCH_PAD7_TO_GPIO (BIT(12)) +#define RTC_IO_TOUCH_PAD7_TO_GPIO_S 12 + +#define TOUCH_PAD8 (DR_REG_RTCIO_BASE + 0xb4) +#define RTC_IO_TOUCH_PAD8_DAC 0x00000007 +#define RTC_IO_TOUCH_PAD8_DAC_S 23 +#define RTC_IO_TOUCH_PAD8_START (BIT(22)) +#define RTC_IO_TOUCH_PAD8_START_S 22 +#define RTC_IO_TOUCH_PAD8_TIE_OPT (BIT(21)) +#define RTC_IO_TOUCH_PAD8_TIE_OPT_S 21 +#define RTC_IO_TOUCH_PAD8_XPD (BIT(20)) +#define RTC_IO_TOUCH_PAD8_XPD_S 20 +#define RTC_IO_TOUCH_PAD8_TO_GPIO (BIT(19)) +#define RTC_IO_TOUCH_PAD8_TO_GPIO_S 19 + +#define TOUCH_PAD9 (DR_REG_RTCIO_BASE + 0xb8) +#define RTC_IO_TOUCH_PAD9_DAC 0x00000007 +#define RTC_IO_TOUCH_PAD9_DAC_S 23 +#define RTC_IO_TOUCH_PAD9_START (BIT(22)) +#define RTC_IO_TOUCH_PAD9_START_S 22 +#define RTC_IO_TOUCH_PAD9_TIE_OPT (BIT(21)) +#define RTC_IO_TOUCH_PAD9_TIE_OPT_S 21 +#define RTC_IO_TOUCH_PAD9_XPD (BIT(20)) +#define RTC_IO_TOUCH_PAD9_XPD_S 20 +#define RTC_IO_TOUCH_PAD9_TO_GPIO (BIT(19)) +#define RTC_IO_TOUCH_PAD9_TO_GPIO_S 19 + +#define EXT_WAKEUP0 (DR_REG_RTCIO_BASE + 0xbc) +#define RTC_IO_EXT_WAKEUP0_SEL 0x0000001F +#define RTC_IO_EXT_WAKEUP0_SEL_S 27 + +#define XTL_EXT_CTR (DR_REG_RTCIO_BASE + 0xc0) +#define RTC_IO_XTL_EXT_CTR_SEL 0x0000001F +#define RTC_IO_XTL_EXT_CTR_SEL_S 27 + +#define SAR_I2C_IO (DR_REG_RTCIO_BASE + 0xc4) +#define RTC_IO_SAR_I2C_SDA_SEL 0x00000003 +#define RTC_IO_SAR_I2C_SDA_SEL_S 30 +#define RTC_IO_SAR_I2C_SCL_SEL 0x00000003 +#define RTC_IO_SAR_I2C_SCL_SEL_S 28 +#define RTC_IO_SAR_DEBUG_BIT_SEL 0x0000001F +#define RTC_IO_SAR_DEBUG_BIT_SEL_S 23 + +#define RTC_IO_DATE (DR_REG_RTCIO_BASE + 0xc8) +#define RTC_IO_RTC_IO_DATE 0x0FFFFFFF +#define RTC_IO_RTC_IO_DATE_S 0 +#define RTC_IO_RTC_IO_DATE_VERSION 0x1703160 + +#endif /* _SOC_RTC_IO_REG_H_ */ + diff --git a/components/esp32/include/soc/soc.h b/components/esp32/include/soc/soc.h new file mode 100755 index 0000000000..cb3d5154aa --- /dev/null +++ b/components/esp32/include/soc/soc.h @@ -0,0 +1,270 @@ +// Copyright 2010-2016 Espressif Systems (Shanghai) PTE LTD +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at + +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#ifndef _ESP32_SOC_H_ +#define _ESP32_SOC_H_ + +#include + +//Register Bits{{ +#define BIT31 0x80000000 +#define BIT30 0x40000000 +#define BIT29 0x20000000 +#define BIT28 0x10000000 +#define BIT27 0x08000000 +#define BIT26 0x04000000 +#define BIT25 0x02000000 +#define BIT24 0x01000000 +#define BIT23 0x00800000 +#define BIT22 0x00400000 +#define BIT21 0x00200000 +#define BIT20 0x00100000 +#define BIT19 0x00080000 +#define BIT18 0x00040000 +#define BIT17 0x00020000 +#define BIT16 0x00010000 +#define BIT15 0x00008000 +#define BIT14 0x00004000 +#define BIT13 0x00002000 +#define BIT12 0x00001000 +#define BIT11 0x00000800 +#define BIT10 0x00000400 +#define BIT9 0x00000200 +#define BIT8 0x00000100 +#define BIT7 0x00000080 +#define BIT6 0x00000040 +#define BIT5 0x00000020 +#define BIT4 0x00000010 +#define BIT3 0x00000008 +#define BIT2 0x00000004 +#define BIT1 0x00000002 +#define BIT0 0x00000001 +//}} + +//Registers Operation {{ +#define ETS_UNCACHED_ADDR(addr) (addr) +#define ETS_CACHED_ADDR(addr) (addr) + +#define BIT(nr) (1UL << (nr)) + +#define REG_WRITE(_r, _v) (*(volatile uint32_t *)(_r)) = (_v) +#define REG_READ(_r) (*(volatile uint32_t *)(_r)) + +#define REG_GET_BIT(_r, _b) (*(volatile uint32_t*)(_r) & (_b)) +#define REG_SET_BIT(_r, _b) (*(volatile uint32_t*)(_r) |= (_b)) +#define REG_CLR_BIT(_r, _b) (*(volatile uint32_t*)(_r) &= ~(_b)) +#define REG_SET_BITS(_r, _b, _m) (*(volatile uint32_t*)(_r) = (*(volatile uint32_t*)(_r) & ~(_m)) | ((_b) & (_m))) +#define VALUE_GET_FIELD(_r, _f) (((_r) >> (_f##_S)) & (_f)) +#define VALUE_GET_FIELD2(_r, _f) (((_r) & (_f))>> (_f##_S)) +#define VALUE_SET_FIELD(_r, _f, _v) ((_r)=(((_r) & ~((_f) << (_f##_S)))|((_v)<<(_f##_S)))) +#define VALUE_SET_FIELD2(_r, _f, _v) ((_r)=(((_r) & ~(_f))|((_v)<<(_f##_S)))) +#define FIELD_TO_VALUE(_f, _v) (((_v)&(_f))<<_f##_S) +#define FIELD_TO_VALUE2(_f, _v) (((_v)<<_f##_S) & (_f)) +#define REG_GET_FIELD(_r, _f) ((REG_READ(_r) >> (_f##_S)) & (_f)) +#define REG_SET_FIELD(_r, _f, _v) (REG_WRITE((_r),((REG_READ(_r) & ~((_f) << (_f##_S)))|(((_v) & (_f))<<(_f##_S))))) + + +#define READ_PERI_REG(addr) (*((volatile uint32_t *)ETS_UNCACHED_ADDR(addr))) +#define WRITE_PERI_REG(addr, val) (*((volatile uint32_t *)ETS_UNCACHED_ADDR(addr))) = (uint32_t)(val) +#define CLEAR_PERI_REG_MASK(reg, mask) WRITE_PERI_REG((reg), (READ_PERI_REG(reg)&(~(mask)))) +#define SET_PERI_REG_MASK(reg, mask) WRITE_PERI_REG((reg), (READ_PERI_REG(reg)|(mask))) +#define GET_PERI_REG_MASK(reg, mask) (READ_PERI_REG(reg) & (mask)) +#define GET_PERI_REG_BITS(reg, hipos,lowpos) ((READ_PERI_REG(reg)>>(lowpos))&((1<<((hipos)-(lowpos)+1))-1)) +#define SET_PERI_REG_BITS(reg,bit_map,value,shift) (WRITE_PERI_REG((reg),(READ_PERI_REG(reg)&(~((bit_map)<<(shift))))|(((value) & bit_map)<<(shift)) )) +#define GET_PERI_REG_BITS2(reg, mask,shift) ((READ_PERI_REG(reg)>>(shift))&(mask)) +//}} + +//Periheral Clock {{ +#define APB_CLK_FREQ_ROM 13*1000000 +#define CPU_CLK_FREQ_ROM APB_CLK_FREQ_ROM +#define CPU_CLK_FREQ APB_CLK_FREQ +#define APB_CLK_FREQ 40*1000000 //unit: Hz +#define UART_CLK_FREQ APB_CLK_FREQ +//#define WDT_CLK_FREQ APB_CLK_FREQ +#define TIMER_CLK_FREQ (80000000>>4) //80MHz divided by 16 +#define SPI_CLK_DIV 4 +//#define RTC_CLK_FREQ 32768 //unit:Hz +//#define RTC_CLK_FREQ 100000 //unit:Hz +//#define CALIB_CLK_MHZ 40 +#define TICKS_PER_US 13 // CPU is 80MHz +//}} + +#if 0 +//Peripheral device base address define{{ +#define DR_REG_DPORT_BASE 0x3ff00000 +#define DR_REG_UART_BASE 0x60000000 +#define DR_REG_SPI1_BASE 0x60002000 //no +#define DR_REG_SPI0_BASE 0x60003000 //no +#define DR_REG_GPIO_BASE 0x60004000 //no +#define DR_REG_FE2_BASE 0x60005000 +#define DR_REG_FE_BASE 0x60006000 +#define DR_REG_TIMER_BASE 0x60007000 //no +#define DR_REG_RTCCNTL_BASE 0x60008000 +#define DR_REG_RTCIO_BASE 0x60008400 + +#define DR_REG_RTCMEM0_BASE 0x60021000 +#define DR_REG_RTCMEM1_BASE 0x60022000 +#define DR_REG_RTCMEM2_BASE 0x60023000 + +#define DR_REG_IO_MUX_BASE 0x60009000 //no +#define DR_REG_WDG_BASE 0x6000A000 //no +#define DR_REG_HINF_BASE 0x6000B000 //no +#define DR_REG_UHCI1_BASE 0x6000C000 +//#define DR_REG_MISC_BASE 0x6000D000 //no use +#define DR_REG_I2C_BASE 0x6000E000 //no +#define DR_REG_I2S_BASE 0x6000F000 +#define DR_REG_UART1_BASE 0x60010000 +#define DR_REG_BT_BASE 0x60011000 +//#define DR_REG_BT_BUFFER_BASE 0x60012000 //no use +#define DR_REG_I2C_EXT_BASE 0x60013000 //no +#define DR_REG_UHCI0_BASE 0x60014000 +#define DR_REG_SLCHOST_BASE 0x60015000 +#define DR_REG_RMT_BASE 0x60016000 +#define DR_REG_PCNT_BASE 0x60017000 +#define DR_REG_SLC_BASE 0x60018000 +#define DR_REG_LEDC_BASE 0x60019000 +#define DR_REG_EFUSE_BASE 0x6001A000 +#define DR_REG_SPI_ENCRYPT_BASE 0x6001B000 +#define DR_REG_PWM_BASE 0x6001C000 //no +#define DR_REG_TIMERGROUP_BASE 0x6001D000 //no +#define DR_REG_TIMERGROUP1_BASE 0x6001E000 //no +#define DR_REG_BB_BASE 0x6001F000 +#define DR_REG_GPIO_SD_BASE 0x60004f00 +#else +#define DR_REG_DPORT_BASE 0x3ff00000 +#define DR_REG_UART_BASE 0x3ff40000 +#define DR_REG_SPI1_BASE 0x3ff42000 //no +#define DR_REG_SPI0_BASE 0x3ff43000 //no +#define DR_REG_GPIO_BASE 0x3ff44000 //no +#define DR_REG_FE2_BASE 0x3ff45000 +#define DR_REG_FE_BASE 0x3ff46000 +#define DR_REG_TIMER_BASE 0x3ff47000 //no +#define DR_REG_RTCCNTL_BASE 0x3ff48000 +#define DR_REG_RTCIO_BASE 0x3ff48400 + +#define DR_REG_RTCMEM0_BASE 0x3ff61000 +#define DR_REG_RTCMEM1_BASE 0x3ff62000 +#define DR_REG_RTCMEM2_BASE 0x3ff63000 + +#define DR_REG_IO_MUX_BASE 0x3ff49000 //no +#define DR_REG_WDG_BASE 0x3ff4A000 //no +#define DR_REG_HINF_BASE 0x3ff4B000 //no +#define DR_REG_UHCI1_BASE 0x3ff4C000 +//#define DR_REG_MISC_BASE 0x6000D000 //no use +#define DR_REG_I2C_BASE 0x3ff4E000 //no +#define DR_REG_I2S_BASE 0x3ff4F000 +#define DR_REG_I2S1_BASE 0x3ff6D000 +#define DR_REG_UART1_BASE 0x3ff50000 +#define DR_REG_BT_BASE 0x3ff51000 +//#define DR_REG_BT_BUFFER_BASE 0x60012000 //no use +#define DR_REG_I2C_EXT_BASE 0x3ff53000 //no +#define DR_REG_UHCI0_BASE 0x3ff54000 +#define DR_REG_SLCHOST_BASE 0x3ff55000 +#define DR_REG_RMT_BASE 0x3ff56000 +#define DR_REG_PCNT_BASE 0x3ff57000 +#define DR_REG_SLC_BASE 0x3ff58000 +#define DR_REG_LEDC_BASE 0x3ff59000 +#define DR_REG_EFUSE_BASE 0x3ff5A000 +#define DR_REG_SPI_ENCRYPT_BASE 0x3ff5B000 +#define DR_REG_PWM_BASE 0x3ff5C000 //no +#define DR_REG_TIMERS_BASE 0x3ff5F000 //no +#define DR_REG_TIMERGROUP1_BASE 0x3ff5E000 //no +#define DR_REG_BB_BASE 0x3ff5F000 +#define DR_REG_GPIO_SD_BASE 0x3ff44f00 +#endif + +//}} +#define REG_SPI_BASE(i) (DR_REG_SPI0_BASE - i*(0x1000)) +#define PERIPHS_TIMER_BASEDDR DR_REG_TIMER_BASE +#define PERIPHS_SPI_ENCRYPT_BASEADDR DR_REG_SPI_ENCRYPT_BASE + +#define UART0_UNHOLD_MASK 0x3 +#define UART1_UNHOLD_MASK 0x60 +#define SDIO_UNHOLD_MASK 0xfc +#define SPI_UNHOLD_MASK 0xfc + +// TIMER reg {{ +#define TIMER_REG_READ(addr) READ_PERI_REG(addr) +#define TIMER_REG_WRITE(addr, val) WRITE_PERI_REG(addr, val) +#define TIMER_SET_REG_MASK(reg, mask) WRITE_PERI_REG(reg, (READ_PERI_REG(reg)|(mask))) +/* Returns the current time according to the timer timer. */ +#define NOW() TIMER_REG_READ(FRC2_COUNT_ADDRESS) +//load initial_value to timer1 +#define FRC1_LOAD_ADDRESS (PERIPHS_TIMER_BASEDDR +0x00) +#define FRC1_LOAD_DATA_MSB 22 +#define FRC1_LOAD_DATA_LSB 0 +#define FRC1_LOAD_DATA_MASK 0x007fffff + +//timer1's counter value(count from initial_value to 0) +#define FRC1_COUNT_ADDRESS (PERIPHS_TIMER_BASEDDR +0x04) +#define FRC1_COUNT_DATA_MSB 22 +#define FRC1_COUNT_DATA_LSB 0 +#define FRC1_COUNT_DATA_MASK 0x007fffff + +#define FRC1_CTRL_ADDRESS (PERIPHS_TIMER_BASEDDR +0x08) +#define FRC1_CTRL_DATA_MSB 7 +#define FRC1_CTRL_DATA_LSB 0 +#define FRC1_CTRL_DATA_MASK 0x000000ff + +//clear timer1's interrupt when write this address +#define FRC1_INT_ADDRESS (PERIPHS_TIMER_BASEDDR +0x0c) +#define FRC1_INT_CLR_MSB 0 +#define FRC1_INT_CLR_LSB 0 +#define FRC1_INT_CLR_MASK 0x00000001 + +//only used for simulation +#define FRC1_TEST_ADDRESS (PERIPHS_TIMER_BASEDDR +0x10) +#define FRC1_TEST_MODE_MSB 0 +#define FRC1_TEST_MODE_LSB 0 +#define FRC1_TEST_MODE_MASK 0x00000001 + +//load initial_value to timer2 +#define FRC2_LOAD_ADDRESS (PERIPHS_TIMER_BASEDDR +0x20) +#define FRC2_LOAD_DATA_MSB 31 +#define FRC2_LOAD_DATA_LSB 0 +#define FRC2_LOAD_DATA_MASK 0xffffffff + +//timer2's counter value(count from initial_value to 0) +#define FRC2_COUNT_ADDRESS (PERIPHS_TIMER_BASEDDR +0x24) +#define FRC2_COUNT_DATA_MSB 31 +#define FRC2_COUNT_DATA_LSB 0 +#define FRC2_COUNT_DATA_MASK 0xffffffff + +#define FRC2_CTRL_ADDRESS (PERIPHS_TIMER_BASEDDR +0x28) +#define FRC2_CTRL_DATA_MSB 7 +#define FRC2_CTRL_DATA_LSB 0 +#define FRC2_CTRL_DATA_MASK 0x000000ff + +//clear interrupt when write this address +#define FRC2_INT_ADDRESS (PERIPHS_TIMER_BASEDDR +0x2c) +#define FRC2_INT_CLR_MSB 0 +#define FRC2_INT_CLR_LSB 0 +#define FRC2_INT_CLR_MASK 0x00000001 + +//set Alarm_value for timer2 to generate interrupt +#define FRC2_ALARM_ADDRESS (PERIPHS_TIMER_BASEDDR +0x30) +#define FRC2_ALARM_DATA_MSB 31 +#define FRC2_ALARM_DATA_LSB 0 +#define FRC2_ALARM_DATA_MASK 0xffffffff +// }} + +#define SPI_ENCRYPT_CNTL (PERIPHS_SPI_ENCRYPT_BASEADDR + 0x20) +#define SPI_ENCRYPT_CNTL_ENA BIT(0) + +#define SPI_ENCRYPT_ADDR (PERIPHS_SPI_ENCRYPT_BASEADDR + 0x24) + +#define SPI_ENCRYPT_CHECKDONE (PERIPHS_SPI_ENCRYPT_BASEADDR + 0x28) +#define SPI_ENCRYPT_CHECKDONE_STATUS BIT(0) + +#endif /* _ESP32_SOC_H_ */ diff --git a/components/esp32/include/soc/spi_register.h b/components/esp32/include/soc/spi_register.h new file mode 100755 index 0000000000..d292c952b6 --- /dev/null +++ b/components/esp32/include/soc/spi_register.h @@ -0,0 +1,399 @@ +// Copyright 2010-2016 Espressif Systems (Shanghai) PTE LTD +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at + +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#ifndef _SOC_SPI_REG_H_ +#define _SOC_SPI_REG_H_ + +#include "soc.h" + +#define SPI_CMD( i ) (REG_SPI_BASE( i ) + 0x0) +#define SPI_FLASH_READ (BIT(31)) +#define SPI_FLASH_WREN (BIT(30)) +#define SPI_FLASH_WRDI (BIT(29)) +#define SPI_FLASH_RDID (BIT(28)) +#define SPI_FLASH_RDSR (BIT(27)) +#define SPI_FLASH_WRSR (BIT(26)) +#define SPI_FLASH_PP (BIT(25)) +#define SPI_FLASH_SE (BIT(24)) +#define SPI_FLASH_BE (BIT(23)) +#define SPI_FLASH_CE (BIT(22)) +#define SPI_FLASH_DP (BIT(21)) +#define SPI_FLASH_RES (BIT(20)) +#define SPI_FLASH_HPM (BIT(19)) +#define SPI_USR (BIT(18)) +#define SPI_FLASH_PES (BIT(17)) +#define SPI_FLASH_PER (BIT(16)) +#define SPI_ADDR( i ) (REG_SPI_BASE( i ) + 0x4) +#define SPI_CTRL( i ) (REG_SPI_BASE( i ) + 0x8) +#define SPI_WR_BIT_ORDER (BIT(26)) +#define SPI_RD_BIT_ORDER (BIT(25)) +#define SPI_FREAD_QIO (BIT(24)) +#define SPI_FREAD_DIO (BIT(23)) +#define SPI_WRSR_2B (BIT(22)) +#define SPI_WP_REG (BIT(21)) +#define SPI_FREAD_QUAD (BIT(20)) +#define SPI_RESANDRES (BIT(15)) +#define SPI_FREAD_DUAL (BIT(14)) +#define SPI_FASTRD_MODE (BIT(13)) +#define SPI_WAIT_FLASH_IDLE_EN (BIT(12)) +#define SPI_TX_CRC_EN (BIT(11)) +#define SPI_FCS_CRC_EN (BIT(10)) +#define SPI_CTRL1( i ) (REG_SPI_BASE( i ) + 0xC) +#define SPI_CS_HOLD_DELAY 0x0000000F +#define SPI_CS_HOLD_DELAY_S 28 +#define SPI_CS_HOLD_DELAY_RES 0x00000FFF +#define SPI_CS_HOLD_DELAY_RES_S 16 +#define SPI_RD_STATUS( i ) (REG_SPI_BASE( i ) + 0x10) +#define SPI_STATUS_EXT 0x000000FF +#define SPI_STATUS_EXT_S 24 +#define SPI_WB_MODE 0x000000FF +#define SPI_WB_MODE_S 16 +#define SPI_STATUS 0x0000FFFF +#define SPI_STATUS_S 0 + +#define SPI_CTRL2( i ) (REG_SPI_BASE( i ) + 0x14) +#define SPI_CS_DELAY_NUM 0x0000000F +#define SPI_CS_DELAY_NUM_S 28 +#define SPI_CS_DELAY_MODE 0x00000003 +#define SPI_CS_DELAY_MODE_S 26 +#define SPI_MOSI_DELAY_NUM 0x00000007 +#define SPI_MOSI_DELAY_NUM_S 23 +#define SPI_MOSI_DELAY_MODE 0x00000003 +#define SPI_MOSI_DELAY_MODE_S 21 +#define SPI_MISO_DELAY_NUM 0x00000007 +#define SPI_MISO_DELAY_NUM_S 18 +#define SPI_MISO_DELAY_MODE 0x00000003 +#define SPI_MISO_DELAY_MODE_S 16 +#define SPI_CK_OUT_HIGH_MODE 0x0000000F +#define SPI_CK_OUT_HIGH_MODE_S 12 +#define SPI_CK_OUT_LOW_MODE 0x0000000F +#define SPI_CK_OUT_LOW_MODE_S 8 +#define SPI_HOLD_TIME 0x0000000F +#define SPI_HOLD_TIME_S 4 +#define SPI_SETUP_TIME 0x0000000F +#define SPI_SETUP_TIME_S 0 + +#define SPI_CLOCK( i ) (REG_SPI_BASE( i ) + 0x18) +#define SPI_CLK_EQU_SYSCLK (BIT(31)) +#define SPI_CLKDIV_PRE 0x00001FFF +#define SPI_CLKDIV_PRE_S 18 +#define SPI_CLKCNT_N 0x0000003F +#define SPI_CLKCNT_N_S 12 +#define SPI_CLKCNT_H 0x0000003F +#define SPI_CLKCNT_H_S 6 +#define SPI_CLKCNT_L 0x0000003F +#define SPI_CLKCNT_L_S 0 + +#define SPI_USER( i ) (REG_SPI_BASE( i ) + 0x1C) +#define SPI_USR_COMMAND (BIT(31)) +#define SPI_USR_ADDR (BIT(30)) +#define SPI_USR_DUMMY (BIT(29)) +#define SPI_USR_MISO (BIT(28)) +#define SPI_USR_MOSI (BIT(27)) +#define SPI_USR_DUMMY_IDLE (BIT(26)) +#define SPI_USR_MOSI_HIGHPART (BIT(25)) +#define SPI_USR_MISO_HIGHPART (BIT(24)) +#define SPI_USR_PREP_HOLD (BIT(23)) +#define SPI_USR_CMD_HOLD (BIT(22)) +#define SPI_USR_ADDR_HOLD (BIT(21)) +#define SPI_USR_DUMMY_HOLD (BIT(20)) +#define SPI_USR_DIN_HOLD (BIT(19)) +#define SPI_USR_DOUT_HOLD (BIT(18)) +#define SPI_USR_HOLD_POL (BIT(17)) +#define SPI_SIO (BIT(16)) +#define SPI_FWRITE_QIO (BIT(15)) +#define SPI_FWRITE_DIO (BIT(14)) +#define SPI_FWRITE_QUAD (BIT(13)) +#define SPI_FWRITE_DUAL (BIT(12)) +#define SPI_WR_BYTE_ORDER (BIT(11)) +#define SPI_RD_BYTE_ORDER (BIT(10)) +#define SPI_CK_OUT_EDGE (BIT(7)) +#define SPI_CK_I_EDGE (BIT(6)) +#define SPI_CS_SETUP (BIT(5)) +#define SPI_CS_HOLD (BIT(4)) +#define SPI_DOUTDIN (BIT(0)) + +#define SPI_USER1( i ) (REG_SPI_BASE( i ) + 0x20) +#define SPI_USR_ADDR_BITLEN 0x0000003F +#define SPI_USR_ADDR_BITLEN_S 26 +#define SPI_USR_DUMMY_CYCLELEN 0x000000FF +#define SPI_USR_DUMMY_CYCLELEN_S 0 + +#define SPI_USER2( i ) (REG_SPI_BASE( i ) + 0x24) +#define SPI_USR_COMMAND_BITLEN 0x0000000F +#define SPI_USR_COMMAND_BITLEN_S 28 +#define SPI_USR_COMMAND_VALUE 0x0000FFFF +#define SPI_USR_COMMAND_VALUE_S 0 + +#define SPI_MOSI_DLEN( i ) (REG_SPI_BASE( i ) + 0x28) +#define SPI_USR_MOSI_DBITLEN 0x00FFFFFF +#define SPI_USR_MOSI_DBITLEN_S 0 + +#define SPI_MISO_DLEN( i ) (REG_SPI_BASE( i ) + 0x2C) +#define SPI_USR_MISO_DBITLEN 0x00FFFFFF +#define SPI_USR_MISO_DBITLEN_S 0 + +#define SPI_SLV_WR_STATUS( i ) (REG_SPI_BASE( i ) + 0x30) +#define SPI_PIN( i ) (REG_SPI_BASE( i ) + 0x34) +#define SPI_CS_KEEP_ACTIVE (BIT(30)) +#define SPI_CK_IDLE_EDGE (BIT(29)) +#define SPI_CSCK_SEL (BIT(19)) +#define SPI_MASTER_CK_SEL 0x0000001F +#define SPI_MASTER_CK_SEL_S 11 +#define SPI_MASTER_CS_POL 0x0000001F +#define SPI_MASTER_CS_POL_S 6 +#define SPI_CK_DIS (BIT(5)) +#define SPI_CS2_DIS (BIT(2)) +#define SPI_CS1_DIS (BIT(1)) +#define SPI_CS0_DIS (BIT(0)) + +#define SPI_SLAVE( i ) (REG_SPI_BASE( i ) + 0x38) +#define SPI_SYNC_RESET (BIT(31)) +#define SPI_SLAVE_MODE (BIT(30)) +#define SPI_SLV_WR_RD_BUF_EN (BIT(29)) +#define SPI_SLV_WR_RD_STA_EN (BIT(28)) +#define SPI_SLV_CMD_DEFINE (BIT(27)) +#define SPI_TRANS_CNT 0x0000000F +#define SPI_TRANS_CNT_S 23 +#define SPI_SLV_LAST_STATE 0x00000007 +#define SPI_SLV_LAST_STATE_S 20 +#define SPI_SLV_LAST_COMMAND 0x00000007 +#define SPI_SLV_LAST_COMMAND_S 17 +#define SPI_CS_I_MODE 0x00000003 +#define SPI_CS_I_MODE_S 10 +#define SPI_INT_EN 0x0000001F +#define SPI_INT_EN_S 5 +#define SPI_TRANS_DONE (BIT(4)) +#define SPI_SLV_WR_STA_DONE (BIT(3)) +#define SPI_SLV_RD_STA_DONE (BIT(2)) +#define SPI_SLV_WR_BUF_DONE (BIT(1)) +#define SPI_SLV_RD_BUF_DONE (BIT(0)) + +#define SPI_SLAVE1( i ) (REG_SPI_BASE( i ) + 0x3C) +#define SPI_SLV_STATUS_BITLEN 0x0000001F +#define SPI_SLV_STATUS_BITLEN_S 27 +#define SPI_SLV_STATUS_FAST_EN (BIT(26)) +#define SPI_SLV_STATUS_READBACK (BIT(25)) +#define SPI_SLV_RD_ADDR_BITLEN 0x0000003F +#define SPI_SLV_RD_ADDR_BITLEN_S 10 +#define SPI_SLV_WR_ADDR_BITLEN 0x0000003F +#define SPI_SLV_WR_ADDR_BITLEN_S 4 +#define SPI_SLV_WRSTA_DUMMY_EN (BIT(3)) +#define SPI_SLV_RDSTA_DUMMY_EN (BIT(2)) +#define SPI_SLV_WRBUF_DUMMY_EN (BIT(1)) +#define SPI_SLV_RDBUF_DUMMY_EN (BIT(0)) + +#define SPI_SLAVE2( i ) (REG_SPI_BASE( i ) + 0x40) +#define SPI_SLV_WRBUF_DUMMY_CYCLELEN 0x000000FF +#define SPI_SLV_WRBUF_DUMMY_CYCLELEN_S 24 +#define SPI_SLV_RDBUF_DUMMY_CYCLELEN 0x000000FF +#define SPI_SLV_RDBUF_DUMMY_CYCLELEN_S 16 +#define SPI_SLV_WRSTA_DUMMY_CYCLELEN 0x000000FF +#define SPI_SLV_WRSTA_DUMMY_CYCLELEN_S 8 +#define SPI_SLV_RDSTA_DUMMY_CYCLELEN 0x000000FF +#define SPI_SLV_RDSTA_DUMMY_CYCLELEN_S 0 + +#define SPI_SLAVE3( i ) (REG_SPI_BASE( i ) + 0x44) +#define SPI_SLV_WRSTA_CMD_VALUE 0x000000FF +#define SPI_SLV_WRSTA_CMD_VALUE_S 24 +#define SPI_SLV_RDSTA_CMD_VALUE 0x000000FF +#define SPI_SLV_RDSTA_CMD_VALUE_S 16 +#define SPI_SLV_WRBUF_CMD_VALUE 0x000000FF +#define SPI_SLV_WRBUF_CMD_VALUE_S 8 +#define SPI_SLV_RDBUF_CMD_VALUE 0x000000FF +#define SPI_SLV_RDBUF_CMD_VALUE_S 0 + +#define SPI_SLV_WRBUF_DLEN( i ) (REG_SPI_BASE( i ) + 0x48) +#define SPI_SLV_WRBUF_DBITLEN 0x00FFFFFF +#define SPI_SLV_WRBUF_DBITLEN_S 0 + +#define SPI_SLV_RDBUF_DLEN( i ) (REG_SPI_BASE( i ) + 0x4C) +#define SPI_SLV_RDBUF_DBITLEN 0x00FFFFFF +#define SPI_SLV_RDBUF_DBITLEN_S 0 + +#define SPI_CACHE_FCTRL( i ) (REG_SPI_BASE( i ) + 0x50) +#define SPI_CACHE_FLASH_PES_EN (BIT(3)) +#define SPI_CACHE_FLASH_USR_CMD (BIT(2)) +#define SPI_CACHE_USR_CMD_4BYTE (BIT(1)) +#define SPI_CACHE_REQ_EN (BIT(0)) + +#define SPI_CACHE_SCTRL( i ) (REG_SPI_BASE( i ) + 0x54) +#define SPI_CACHE_SRAM_USR_WCMD (BIT(28)) +#define SPI_SRAM_ADDR_BITLEN 0x0000003F +#define SPI_SRAM_ADDR_BITLEN_S 22 +#define SPI_SRAM_DUMMY_CYCLELEN 0x000000FF +#define SPI_SRAM_DUMMY_CYCLELEN_S 14 +#define SPI_SRAM_BYTES_LEN 0x000000FF +#define SPI_SRAM_BYTES_LEN_S 6 +#define SPI_CACHE_SRAM_USR_RCMD (BIT(5)) +#define SPI_USR_RD_SRAM_DUMMY (BIT(4)) +#define SPI_USR_WR_SRAM_DUMMY (BIT(3)) +#define SPI_USR_SRAM_QIO (BIT(2)) +#define SPI_USR_SRAM_DIO (BIT(1)) +#define SPI_SRAM_CMD( i ) (REG_SPI_BASE( i ) + 0x58) +#define SPI_SRAM_RSTIO (BIT(4)) +#define SPI_SRAM_QIO (BIT(1)) +#define SPI_SRAM_DIO (BIT(0)) + +#define SPI_SRAM_DRD_CMD( i ) (REG_SPI_BASE( i ) + 0x5C) +#define SPI_CACHE_SRAM_USR_RD_CMD_BITLEN 0x0000000F +#define SPI_CACHE_SRAM_USR_RD_CMD_BITLEN_S 28 +#define SPI_CACHE_SRAM_USR_RD_CMD_VALUE 0x0000FFFF +#define SPI_CACHE_SRAM_USR_RD_CMD_VALUE_S 0 + +#define SPI_SRAM_DWR_CMD( i ) (REG_SPI_BASE( i ) + 0x60) +#define SPI_CACHE_SRAM_USR_WR_CMD_BITLEN 0x0000000F +#define SPI_CACHE_SRAM_USR_WR_CMD_BITLEN_S 28 +#define SPI_CACHE_SRAM_USR_WR_CMD_VALUE 0x0000FFFF +#define SPI_CACHE_SRAM_USR_WR_CMD_VALUE_S 0 + +#define SPI_SLV_RD_BIT( i ) (REG_SPI_BASE( i ) + 0x64) +#define SPI_SLV_RDATA_BIT 0x00FFFFFF +#define SPI_SLV_RDATA_BIT_S 0 + +#define SPI_W0( i ) (REG_SPI_BASE( i ) + 0x80) +#define SPI_W1( i ) (REG_SPI_BASE( i ) + 0x84) +#define SPI_W2( i ) (REG_SPI_BASE( i ) + 0x88) +#define SPI_W3( i ) (REG_SPI_BASE( i ) + 0x8C) +#define SPI_W4( i ) (REG_SPI_BASE( i ) + 0x90) +#define SPI_W5( i ) (REG_SPI_BASE( i ) + 0x94) +#define SPI_W6( i ) (REG_SPI_BASE( i ) + 0x98) +#define SPI_W7( i ) (REG_SPI_BASE( i ) + 0x9C) +#define SPI_W8( i ) (REG_SPI_BASE( i ) + 0xA0) +#define SPI_W9( i ) (REG_SPI_BASE( i ) + 0xA4) +#define SPI_W10( i ) (REG_SPI_BASE( i ) + 0xA8) +#define SPI_W11( i ) (REG_SPI_BASE( i ) + 0xAC) +#define SPI_W12( i ) (REG_SPI_BASE( i ) + 0xB0) +#define SPI_W13( i ) (REG_SPI_BASE( i ) + 0xB4) +#define SPI_W14( i ) (REG_SPI_BASE( i ) + 0xB8) +#define SPI_W15( i ) (REG_SPI_BASE( i ) + 0xBC) +#define SPI_TX_CRC( i ) (REG_SPI_BASE( i ) + 0xC0) +#define SPI_EXT0( i ) (REG_SPI_BASE( i ) + 0xF0) +#define SPI_T_PP_ENA (BIT(31)) +#define SPI_T_PP_SHIFT 0x0000000F +#define SPI_T_PP_SHIFT_S 16 +#define SPI_T_PP_TIME 0x00000FFF +#define SPI_T_PP_TIME_S 0 + +#define SPI_EXT1( i ) (REG_SPI_BASE( i ) + 0xF4) +#define SPI_T_ERASE_ENA (BIT(31)) +#define SPI_T_ERASE_SHIFT 0x0000000F +#define SPI_T_ERASE_SHIFT_S 16 +#define SPI_T_ERASE_TIME 0x00000FFF +#define SPI_T_ERASE_TIME_S 0 + +#define SPI_EXT2( i ) (REG_SPI_BASE( i ) + 0xF8) +#define SPI_ST 0x00000007 +#define SPI_ST_S 0 + +#define SPI_EXT3( i ) (REG_SPI_BASE( i ) + 0xFC) +#define SPI_INT_HOLD_ENA 0x00000003 +#define SPI_INT_HOLD_ENA_S 0 + +#define SPI_DMA_CONF( i ) (REG_SPI_BASE( i ) + 0x100) +#define SPI_DMA_CONTINUE (BIT(16)) +#define SPI_DMA_TX_STOP (BIT(15)) +#define SPI_DMA_RX_STOP (BIT(14)) +#define SPI_OUT_DATA_BURST_EN (BIT(12)) +#define SPI_INDSCR_BURST_EN (BIT(11)) +#define SPI_OUTDSCR_BURST_EN (BIT(10)) +#define SPI_OUT_EOF_MODE (BIT(9)) +#define SPI_OUT_AUTO_WRBACK (BIT(8)) +#define SPI_OUT_LOOP_TEST (BIT(7)) +#define SPI_IN_LOOP_TEST (BIT(6)) +#define SPI_AHBM_RST (BIT(5)) +#define SPI_AHBM_FIFO_RST (BIT(4)) +#define SPI_OUT_RST (BIT(3)) +#define SPI_IN_RST (BIT(2)) +#define SPI_DMA_OUT_LINK( i ) (REG_SPI_BASE( i ) + 0x104) +#define SPI_OUTLINK_RESTART (BIT(30)) +#define SPI_OUTLINK_START (BIT(29)) +#define SPI_OUTLINK_STOP (BIT(28)) +#define SPI_OUTLINK_ADDR 0x000FFFFF +#define SPI_OUTLINK_ADDR_S 0 + +#define SPI_DMA_IN_LINK( i ) (REG_SPI_BASE( i ) + 0x108) +#define SPI_INLINK_RESTART (BIT(30)) +#define SPI_INLINK_START (BIT(29)) +#define SPI_INLINK_STOP (BIT(28)) +#define SPI_INLINK_AUTO_RET (BIT(20)) +#define SPI_INLINK_ADDR 0x000FFFFF +#define SPI_INLINK_ADDR_S 0 + +#define SPI_DMA_STATUS( i ) (REG_SPI_BASE( i ) + 0x10C) +#define SPI_DMA_TX_EN (BIT(1)) +#define SPI_DMA_RX_EN (BIT(0)) + +#define SPI_DMA_INT_ENA( i ) (REG_SPI_BASE( i ) + 0x110) +#define SPI_OUT_TOTAL_EOF_INT_ENA (BIT(8)) +#define SPI_OUT_EOF_INT_ENA (BIT(7)) +#define SPI_OUT_DONE_INT_ENA (BIT(6)) +#define SPI_IN_SUC_EOF_INT_ENA (BIT(5)) +#define SPI_IN_ERR_EOF_INT_ENA (BIT(4)) +#define SPI_IN_DONE_INT_ENA (BIT(3)) +#define SPI_INLINK_DSCR_ERROR_INT_ENA (BIT(2)) +#define SPI_OUTLINK_DSCR_ERROR_INT_ENA (BIT(1)) +#define SPI_INLINK_DSCR_EMPTY_INT_ENA (BIT(0)) + +#define SPI_DMA_INT_RAW( i ) (REG_SPI_BASE( i ) + 0x114) +#define SPI_OUT_TOTAL_EOF_INT_RAW (BIT(8)) +#define SPI_OUT_EOF_INT_RAW (BIT(7)) +#define SPI_OUT_DONE_INT_RAW (BIT(6)) +#define SPI_IN_SUC_EOF_INT_RAW (BIT(5)) +#define SPI_IN_ERR_EOF_INT_RAW (BIT(4)) +#define SPI_IN_DONE_INT_RAW (BIT(3)) +#define SPI_INLINK_DSCR_ERROR_INT_RAW (BIT(2)) +#define SPI_OUTLINK_DSCR_ERROR_INT_RAW (BIT(1)) +#define SPI_INLINK_DSCR_EMPTY_INT_RAW (BIT(0)) + +#define SPI_DMA_INT_ST( i ) (REG_SPI_BASE( i ) + 0x118) +#define SPI_OUT_TOTAL_EOF_INT_ST (BIT(8)) +#define SPI_OUT_EOF_INT_ST (BIT(7)) +#define SPI_OUT_DONE_INT_ST (BIT(6)) +#define SPI_IN_SUC_EOF_INT_ST (BIT(5)) +#define SPI_IN_ERR_EOF_INT_ST (BIT(4)) +#define SPI_IN_DONE_INT_ST (BIT(3)) +#define SPI_INLINK_DSCR_ERROR_INT_ST (BIT(2)) +#define SPI_OUTLINK_DSCR_ERROR_INT_ST (BIT(1)) +#define SPI_INLINK_DSCR_EMPTY_INT_ST (BIT(0)) + +#define SPI_DMA_INT_CLR( i ) (REG_SPI_BASE( i ) + 0x11C) +#define SPI_OUT_TOTAL_EOF_INT_CLR (BIT(8)) +#define SPI_OUT_EOF_INT_CLR (BIT(7)) +#define SPI_OUT_DONE_INT_CLR (BIT(6)) +#define SPI_IN_SUC_EOF_INT_CLR (BIT(5)) +#define SPI_IN_ERR_EOF_INT_CLR (BIT(4)) +#define SPI_IN_DONE_INT_CLR (BIT(3)) +#define SPI_INLINK_DSCR_ERROR_INT_CLR (BIT(2)) +#define SPI_OUTLINK_DSCR_ERROR_INT_CLR (BIT(1)) +#define SPI_INLINK_DSCR_EMPTY_INT_CLR (BIT(0)) + +#define SPI_IN_ERR_EOF_DES_ADDR( i ) (REG_SPI_BASE( i ) + 0x120) +#define SPI_IN_SUC_EOF_DES_ADDR( i ) (REG_SPI_BASE( i ) + 0x124) +#define SPI_INLINK_DSCR( i ) (REG_SPI_BASE( i ) + 0x128) +#define SPI_INLINK_DSCR_BF0( i ) (REG_SPI_BASE( i ) + 0x12C) +#define SPI_INLINK_DSCR_BF1( i ) (REG_SPI_BASE( i ) + 0x130) +#define SPI_OUT_EOF_BFR_DES_ADDR( i ) (REG_SPI_BASE( i ) + 0x134) +#define SPI_OUT_EOF_DES_ADDR( i ) (REG_SPI_BASE( i ) + 0x138) +#define SPI_OUTLINK_DSCR( i ) (REG_SPI_BASE( i ) + 0x13C) +#define SPI_OUTLINK_DSCR_BF0( i ) (REG_SPI_BASE( i ) + 0x140) +#define SPI_OUTLINK_DSCR_BF1( i ) (REG_SPI_BASE( i ) + 0x144) +#define SPI_DMA_RSTATUS( i ) (REG_SPI_BASE( i ) + 0x148) +#define SPI_DMA_TSTATUS( i ) (REG_SPI_BASE( i ) + 0x14C) +#define SPI_REG_DATE( i ) (REG_SPI_BASE( i ) + 0x3FC) +#define SPI_DATE 0x0FFFFFFF +#define SPI_DATE_S 0 +#define SPI_DATE_VERSION 0x1604290 + +#endif /* _SOC_SPI_REG_H_ */ diff --git a/components/esp32/include/soc/timers_reg.h b/components/esp32/include/soc/timers_reg.h new file mode 100644 index 0000000000..577f375aa7 --- /dev/null +++ b/components/esp32/include/soc/timers_reg.h @@ -0,0 +1,288 @@ +// Copyright 2015-2016 Espressif Systems (Shanghai) PTE LTD +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at + +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +#ifndef _SOC_TIMERS_REG_H_ +#define _SOC_TIMER_REG_H_ + +#include "soc.h" + +#define T0CONFIG (DR_REG_TIMERS_BASE + 0x0000) +#define TIMERS_T0_EN (BIT(31)) +#define TIMERS_T0_EN_S 31 +#define TIMERS_T0_INCREASE (BIT(30)) +#define TIMERS_T0_INCREASE_S 30 +#define TIMERS_T0_AUTORELOAD (BIT(29)) +#define TIMERS_T0_AUTORELOAD_S 29 +#define TIMERS_T0_DIVIDER 0x0000FFFF +#define TIMERS_T0_DIVIDER_S 13 +#define TIMERS_T0_EDGE_INT_EN (BIT(12)) +#define TIMERS_T0_EDGE_INT_EN_S 12 +#define TIMERS_T0_LEVEL_INT_EN (BIT(11)) +#define TIMERS_T0_LEVEL_INT_EN_S 11 +#define TIMERS_T0_ALARM_EN (BIT(10)) +#define TIMERS_T0_ALARM_EN_S 10 + +#define T0LO (DR_REG_TIMERS_BASE + 0x0004) +#define TIMERS_T0_LO 0xFFFFFFFF +#define TIMERS_T0_LO_S 0 + +#define T0HI (DR_REG_TIMERS_BASE + 0x0008) +#define TIMERS_T0_HI 0xFFFFFFFF +#define TIMERS_T0_HI_S 0 + +#define T0UPDATE (DR_REG_TIMERS_BASE + 0x000c) +#define TIMERS_T0_UPDATE 0xFFFFFFFF +#define TIMERS_T0_UPDATE_S 0 + +#define T0ALARMLO (DR_REG_TIMERS_BASE + 0x0010) +#define TIMERS_T0_ALARM_LO 0xFFFFFFFF +#define TIMERS_T0_ALARM_LO_S 0 + +#define T0ALARMHI (DR_REG_TIMERS_BASE + 0x0014) +#define TIMERS_T0_ALARM_HI 0xFFFFFFFF +#define TIMERS_T0_ALARM_HI_S 0 + +#define T0LOADLO (DR_REG_TIMERS_BASE + 0x0018) +#define TIMERS_T0_LOAD_LO 0xFFFFFFFF +#define TIMERS_T0_LOAD_LO_S 0 + +#define T0LOADHI (DR_REG_TIMERS_BASE + 0x001c) +#define TIMERS_T0_LOAD_HI 0xFFFFFFFF +#define TIMERS_T0_LOAD_HI_S 0 + +#define T0LOAD (DR_REG_TIMERS_BASE + 0x0020) +#define TIMERS_T0_LOAD 0xFFFFFFFF +#define TIMERS_T0_LOAD_S 0 + +#define T1CONFIG (DR_REG_TIMERS_BASE + 0x0024) +#define TIMERS_T1_EN (BIT(31)) +#define TIMERS_T1_EN_S 31 +#define TIMERS_T1_INCREASE (BIT(30)) +#define TIMERS_T1_INCREASE_S 30 +#define TIMERS_T1_AUTORELOAD (BIT(29)) +#define TIMERS_T1_AUTORELOAD_S 29 +#define TIMERS_T1_DIVIDER 0x0000FFFF +#define TIMERS_T1_DIVIDER_S 13 +#define TIMERS_T1_EDGE_INT_EN (BIT(12)) +#define TIMERS_T1_EDGE_INT_EN_S 12 +#define TIMERS_T1_LEVEL_INT_EN (BIT(11)) +#define TIMERS_T1_LEVEL_INT_EN_S 11 +#define TIMERS_T1_ALARM_EN (BIT(10)) +#define TIMERS_T1_ALARM_EN_S 10 + +#define T1LO (DR_REG_TIMERS_BASE + 0x0028) +#define TIMERS_T1_LO 0xFFFFFFFF +#define TIMERS_T1_LO_S 0 + +#define T1HI (DR_REG_TIMERS_BASE + 0x002c) +#define TIMERS_T1_HI 0xFFFFFFFF +#define TIMERS_T1_HI_S 0 + +#define T1UPDATE (DR_REG_TIMERS_BASE + 0x0030) +#define TIMERS_T1_UPDATE 0xFFFFFFFF +#define TIMERS_T1_UPDATE_S 0 + +#define T1ALARMLO (DR_REG_TIMERS_BASE + 0x0034) +#define TIMERS_T1_ALARM_LO 0xFFFFFFFF +#define TIMERS_T1_ALARM_LO_S 0 + +#define T1ALARMHI (DR_REG_TIMERS_BASE + 0x0038) +#define TIMERS_T1_ALARM_HI 0xFFFFFFFF +#define TIMERS_T1_ALARM_HI_S 0 + +#define T1LOADLO (DR_REG_TIMERS_BASE + 0x003c) +#define TIMERS_T1_LOAD_LO 0xFFFFFFFF +#define TIMERS_T1_LOAD_LO_S 0 + +#define T1LOADHI (DR_REG_TIMERS_BASE + 0x0040) +#define TIMERS_T1_LOAD_HI 0xFFFFFFFF +#define TIMERS_T1_LOAD_HI_S 0 + +#define T1LOAD (DR_REG_TIMERS_BASE + 0x0044) +#define TIMERS_T1_LOAD 0xFFFFFFFF +#define TIMERS_T1_LOAD_S 0 + +#define WDTCONFIG0 (DR_REG_TIMERS_BASE + 0x0048) +#define TIMERS_WDT_EN (BIT(31)) +#define TIMERS_WDT_EN_S 31 +#define TIMERS_WDT_STG0 0x00000003 +#define TIMERS_WDT_STG0_S 29 +#define TIMERS_WDT_STG1 0x00000003 +#define TIMERS_WDT_STG1_S 27 +#define TIMERS_WDT_STG2 0x00000003 +#define TIMERS_WDT_STG2_S 25 +#define TIMERS_WDT_STG3 0x00000003 +#define TIMERS_WDT_STG3_S 23 +#define TIMERS_WDT_EDGE_INT_EN (BIT(22)) +#define TIMERS_WDT_EDGE_INT_EN_S 22 +#define TIMERS_WDT_LEVEL_INT_EN (BIT(21)) +#define TIMERS_WDT_LEVEL_INT_EN_S 21 +#define TIMERS_WDT_CPU_RESET_LENGTH 0x00000007 +#define TIMERS_WDT_CPU_RESET_LENGTH_S 18 +#define TIMERS_WDT_SYS_RESET_LENGTH 0x00000007 +#define TIMERS_WDT_SYS_RESET_LENGTH_S 15 +#define TIMERS_WDT_FLASHBOOT_MOD_EN (BIT(14)) +#define TIMERS_WDT_FLASHBOOT_MOD_EN_S 14 + +#define WDTCONFIG1 (DR_REG_TIMERS_BASE + 0x004c) +#define TIMERS_WDT_CLK_PRESCALE 0x0000FFFF +#define TIMERS_WDT_CLK_PRESCALE_S 16 + +#define WDTCONFIG2 (DR_REG_TIMERS_BASE + 0x0050) +#define TIMERS_WDT_STG0_HOLD 0xFFFFFFFF +#define TIMERS_WDT_STG0_HOLD_S 0 + +#define WDTCONFIG3 (DR_REG_TIMERS_BASE + 0x0054) +#define TIMERS_WDT_STG1_HOLD 0xFFFFFFFF +#define TIMERS_WDT_STG1_HOLD_S 0 + +#define WDTCONFIG4 (DR_REG_TIMERS_BASE + 0x0058) +#define TIMERS_WDT_STG2_HOLD 0xFFFFFFFF +#define TIMERS_WDT_STG2_HOLD_S 0 + +#define WDTCONFIG5 (DR_REG_TIMERS_BASE + 0x005c) +#define TIMERS_WDT_STG3_HOLD 0xFFFFFFFF +#define TIMERS_WDT_STG3_HOLD_S 0 + +#define WDTFEED (DR_REG_TIMERS_BASE + 0x0060) +#define TIMERS_WDT_FEED 0xFFFFFFFF +#define TIMERS_WDT_FEED_S 0 + +#define WDTWPROTECT (DR_REG_TIMERS_BASE + 0x0064) +#define TIMERS_WDT_WKEY 0xFFFFFFFF +#define TIMERS_WDT_WKEY_S 0 + +#define RTCCALICFG (DR_REG_TIMERS_BASE + 0x0068) +#define TIMERS_RTC_CALI_START (BIT(31)) +#define TIMERS_RTC_CALI_START_S 31 +#define TIMERS_RTC_CALI_MAX 0x00007FFF +#define TIMERS_RTC_CALI_MAX_S 16 +#define TIMERS_RTC_CALI_RDY (BIT(15)) +#define TIMERS_RTC_CALI_RDY_S 15 +#define TIMERS_RTC_CALI_CLK_SEL 0x00000003 +#define TIMERS_RTC_CALI_CLK_SEL_S 13 +#define TIMERS_RTC_CALI_START_CYCLING (BIT(12)) +#define TIMERS_RTC_CALI_START_CYCLING_S 12 + +#define RTCCALICFG1 (DR_REG_TIMERS_BASE + 0x006c) +#define TIMERS_RTC_CALI_VALUE 0x01FFFFFF +#define TIMERS_RTC_CALI_VALUE_S 7 + +#define LACTCONFIG (DR_REG_TIMERS_BASE + 0x0070) +#define TIMERS_LACT_EN (BIT(31)) +#define TIMERS_LACT_EN_S 31 +#define TIMERS_LACT_INCREASE (BIT(30)) +#define TIMERS_LACT_INCREASE_S 30 +#define TIMERS_LACT_AUTORELOAD (BIT(29)) +#define TIMERS_LACT_AUTORELOAD_S 29 +#define TIMERS_LACT_DIVIDER 0x0000FFFF +#define TIMERS_LACT_DIVIDER_S 13 +#define TIMERS_LACT_EDGE_INT_EN (BIT(12)) +#define TIMERS_LACT_EDGE_INT_EN_S 12 +#define TIMERS_LACT_LEVEL_INT_EN (BIT(11)) +#define TIMERS_LACT_LEVEL_INT_EN_S 11 +#define TIMERS_LACT_ALARM_EN (BIT(10)) +#define TIMERS_LACT_ALARM_EN_S 10 +#define TIMERS_LACT_LAC_EN (BIT(9)) +#define TIMERS_LACT_LAC_EN_S 9 +#define TIMERS_LACT_CPST_EN (BIT(8)) +#define TIMERS_LACT_CPST_EN_S 8 +#define TIMERS_LACT_RTC_ONLY (BIT(7)) +#define TIMERS_LACT_RTC_ONLY_S 7 + +#define LACTRTC (DR_REG_TIMERS_BASE + 0x0074) +#define TIMERS_LACT_RTC_STEP_LEN 0x03FFFFFF +#define TIMERS_LACT_RTC_STEP_LEN_S 6 + +#define LACTLO (DR_REG_TIMERS_BASE + 0x0078) +#define TIMERS_LACT_LO 0xFFFFFFFF +#define TIMERS_LACT_LO_S 0 + +#define LACTHI (DR_REG_TIMERS_BASE + 0x007c) +#define TIMERS_LACT_HI 0xFFFFFFFF +#define TIMERS_LACT_HI_S 0 + +#define LACTUPDATE (DR_REG_TIMERS_BASE + 0x0080) +#define TIMERS_LACT_UPDATE 0xFFFFFFFF +#define TIMERS_LACT_UPDATE_S 0 + +#define LACTALARMLO (DR_REG_TIMERS_BASE + 0x0084) +#define TIMERS_LACT_ALARM_LO 0xFFFFFFFF +#define TIMERS_LACT_ALARM_LO_S 0 + +#define LACTALARMHI (DR_REG_TIMERS_BASE + 0x0088) +#define TIMERS_LACT_ALARM_HI 0xFFFFFFFF +#define TIMERS_LACT_ALARM_HI_S 0 + +#define LACTLOADLO (DR_REG_TIMERS_BASE + 0x008c) +#define TIMERS_LACT_LOAD_LO 0xFFFFFFFF +#define TIMERS_LACT_LOAD_LO_S 0 + +#define LACTLOADHI (DR_REG_TIMERS_BASE + 0x0090) +#define TIMERS_LACT_LOAD_HI 0xFFFFFFFF +#define TIMERS_LACT_LOAD_HI_S 0 + +#define LACTLOAD (DR_REG_TIMERS_BASE + 0x0094) +#define TIMERS_LACT_LOAD 0xFFFFFFFF +#define TIMERS_LACT_LOAD_S 0 + +#define INT_ENA_TIMERS (DR_REG_TIMERS_BASE + 0x0098) +#define TIMERS_LACT_INT_ENA (BIT(3)) +#define TIMERS_LACT_INT_ENA_S 3 +#define TIMERS_WDT_INT_ENA (BIT(2)) +#define TIMERS_WDT_INT_ENA_S 2 +#define TIMERS_T1_INT_ENA (BIT(1)) +#define TIMERS_T1_INT_ENA_S 1 +#define TIMERS_T0_INT_ENA (BIT(0)) +#define TIMERS_T0_INT_ENA_S 0 + +#define INT_RAW_TIMERS (DR_REG_TIMERS_BASE + 0x009c) +#define TIMERS_LACT_INT_RAW (BIT(3)) +#define TIMERS_LACT_INT_RAW_S 3 +#define TIMERS_WDT_INT_RAW (BIT(2)) +#define TIMERS_WDT_INT_RAW_S 2 +#define TIMERS_T1_INT_RAW (BIT(1)) +#define TIMERS_T1_INT_RAW_S 1 +#define TIMERS_T0_INT_RAW (BIT(0)) +#define TIMERS_T0_INT_RAW_S 0 + +#define INT_ST_TIMERS (DR_REG_TIMERS_BASE + 0x00a0) +#define TIMERS_LACT_INT_ST (BIT(3)) +#define TIMERS_LACT_INT_ST_S 3 +#define TIMERS_WDT_INT_ST (BIT(2)) +#define TIMERS_WDT_INT_ST_S 2 +#define TIMERS_T1_INT_ST (BIT(1)) +#define TIMERS_T1_INT_ST_S 1 +#define TIMERS_T0_INT_ST (BIT(0)) +#define TIMERS_T0_INT_ST_S 0 + +#define INT_CLR_TIMERS (DR_REG_TIMERS_BASE + 0x00a4) +#define TIMERS_LACT_INT_CLR (BIT(3)) +#define TIMERS_LACT_INT_CLR_S 3 +#define TIMERS_WDT_INT_CLR (BIT(2)) +#define TIMERS_WDT_INT_CLR_S 2 +#define TIMERS_T1_INT_CLR (BIT(1)) +#define TIMERS_T1_INT_CLR_S 1 +#define TIMERS_T0_INT_CLR (BIT(0)) +#define TIMERS_T0_INT_CLR_S 0 + +#define NTIMERS_DATE (DR_REG_TIMERS_BASE + 0x00f8) +#define TIMERS_NTIMERS_DATE 0x0FFFFFFF +#define TIMERS_NTIMERS_DATE_S 0 +#define TIMERS_NTIMERS_DATE_VERSION 0x1604290 + +#define REGCLK (DR_REG_TIMERS_BASE + 0x00fc) +#define TIMERS_CLK_EN (BIT(31)) +#define TIMERS_CLK_EN_S 31 + +#endif /* _SOC_TIMER_REG_H_ */ diff --git a/components/esp32/include/soc/uart_register.h b/components/esp32/include/soc/uart_register.h new file mode 100644 index 0000000000..91bd4ddc8b --- /dev/null +++ b/components/esp32/include/soc/uart_register.h @@ -0,0 +1,1399 @@ +// Copyright 2015-2016 Espressif Systems (Shanghai) PTE LTD +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at + +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +#ifndef _SOC_UART_REG_H_ +#define _SOC_UART_REG_H_ + +#include "soc.h" + +//Slow bus +//#define REG_UART_BASE( i ) (0x60000000+(i)*0x10000) +//Fast bus +#define REG_UART_BASE( i ) (0x3ff40000+(i)*0x10000) + +#define UART_FIFO_REG(i) (REG_UART_BASE(i) + 0x0) + /* UART_RXFIFO_RD_BYTE : RO ;bitpos:[7:0] ;default: 8'b0 ; */ + /*description: R/W share the same address*/ + #define UART_RXFIFO_RD_BYTE 0x000000FF + #define UART_RXFIFO_RD_BYTE_M ((UART_RXFIFO_RD_BYTE_V)<<(UART_RXFIFO_RD_BYTE_S)) + #define UART_RXFIFO_RD_BYTE_V 0xFF + #define UART_RXFIFO_RD_BYTE_S 0 + #define UART_GET_RXFIFO_RD_BYTE(i) GET_PERI_REG_BITS2(UART_FIFO_REG(i) , UART_RXFIFO_RD_BYTE_V, UART_RXFIFO_RD_BYTE_S) + #define UART_SET_TXFIFO_WR_BYTE(i,val) SET_PERI_REG_BITS(UART_FIFO_REG(i) , UART_RXFIFO_RD_BYTE_V, val, UART_RXFIFO_RD_BYTE_S) + + + +#define UART_INT_RAW_REG(i) (REG_UART_BASE(i) + 0x4) + /* UART_AT_CMD_CHAR_DET_INT_RAW : RO ;bitpos:[18] ;default: 1'b0 ; */ + /*description: The interrupt raw bit for detecting AT_CMD char interrupt*/ + #define UART_AT_CMD_CHAR_DET_INT_RAW (BIT(18)) + #define UART_AT_CMD_CHAR_DET_INT_RAW_M (BIT(18)) + #define UART_AT_CMD_CHAR_DET_INT_RAW_V 0x1 + #define UART_AT_CMD_CHAR_DET_INT_RAW_S 18 + /* UART_RS485_CLASH_INT_RAW : RO ;bitpos:[17] ;default: 1'b0 ; */ + /*description: The interrupt raw bit for rs485 tx rx clash interrrupt*/ + #define UART_RS485_CLASH_INT_RAW (BIT(17)) + #define UART_RS485_CLASH_INT_RAW_M (BIT(17)) + #define UART_RS485_CLASH_INT_RAW_V 0x1 + #define UART_RS485_CLASH_INT_RAW_S 17 + /* UART_RS485_FRM_ERR_INT_RAW : RO ;bitpos:[16] ;default: 1'b0 ; */ + /*description: The interrupt raw bit for rs485 other rx error*/ + #define UART_RS485_FRM_ERR_INT_RAW (BIT(16)) + #define UART_RS485_FRM_ERR_INT_RAW_M (BIT(16)) + #define UART_RS485_FRM_ERR_INT_RAW_V 0x1 + #define UART_RS485_FRM_ERR_INT_RAW_S 16 + /* UART_RS485_PARITY_ERR_INT_RAW : RO ;bitpos:[15] ;default: 1'b0 ; */ + /*description: The interrupt raw bit for rs485 parity error*/ + #define UART_RS485_PARITY_ERR_INT_RAW (BIT(15)) + #define UART_RS485_PARITY_ERR_INT_RAW_M (BIT(15)) + #define UART_RS485_PARITY_ERR_INT_RAW_V 0x1 + #define UART_RS485_PARITY_ERR_INT_RAW_S 15 + /* UART_TX_DONE_INT_RAW : RO ;bitpos:[14] ;default: 1'b0 ; */ + /*description: The interrupt raw bit for tx done*/ + #define UART_TX_DONE_INT_RAW (BIT(14)) + #define UART_TX_DONE_INT_RAW_M (BIT(14)) + #define UART_TX_DONE_INT_RAW_V 0x1 + #define UART_TX_DONE_INT_RAW_S 14 + /* UART_TX_BRK_IDLE_DONE_INT_RAW : RO ;bitpos:[13] ;default: 1'b0 ; */ + /*description: The interrupt raw bit for tx send idle done(depends on the uart_tx_idle_num)*/ + #define UART_TX_BRK_IDLE_DONE_INT_RAW (BIT(13)) + #define UART_TX_BRK_IDLE_DONE_INT_RAW_M (BIT(13)) + #define UART_TX_BRK_IDLE_DONE_INT_RAW_V 0x1 + #define UART_TX_BRK_IDLE_DONE_INT_RAW_S 13 + /* UART_TX_BRK_DONE_INT_RAW : RO ;bitpos:[12] ;default: 1'b0 ; */ + /*description: The interrupt raw bit for send 0 done(depends on uart_tx_brk_num)*/ + #define UART_TX_BRK_DONE_INT_RAW (BIT(12)) + #define UART_TX_BRK_DONE_INT_RAW_M (BIT(12)) + #define UART_TX_BRK_DONE_INT_RAW_V 0x1 + #define UART_TX_BRK_DONE_INT_RAW_S 12 + /* UART_GLITCH_DET_INT_RAW : RO ;bitpos:[11] ;default: 1'b0 ; */ + /*description: The interrupt raw bit for detecting rx glitch pulse*/ + #define UART_GLITCH_DET_INT_RAW (BIT(11)) + #define UART_GLITCH_DET_INT_RAW_M (BIT(11)) + #define UART_GLITCH_DET_INT_RAW_V 0x1 + #define UART_GLITCH_DET_INT_RAW_S 11 + /* UART_SW_XOFF_INT_RAW : RO ;bitpos:[10] ;default: 1'b0 ; */ + /*description: The interrupt raw bit for rx receive xoff char(depends on the uart_xoff_char )*/ + #define UART_SW_XOFF_INT_RAW (BIT(10)) + #define UART_SW_XOFF_INT_RAW_M (BIT(10)) + #define UART_SW_XOFF_INT_RAW_V 0x1 + #define UART_SW_XOFF_INT_RAW_S 10 + /* UART_SW_XON_INT_RAW : RO ;bitpos:[9] ;default: 1'b0 ; */ + /*description: The interrupt raw bit for rx receive xon char(depends on the uart_xon_char )*/ + #define UART_SW_XON_INT_RAW (BIT(9)) + #define UART_SW_XON_INT_RAW_M (BIT(9)) + #define UART_SW_XON_INT_RAW_V 0x1 + #define UART_SW_XON_INT_RAW_S 9 + /* UART_RXFIFO_TOUT_INT_RAW : RO ;bitpos:[8] ;default: 1'b0 ; */ + /*description: The interrupt raw bit for Rx time-out interrupt(depands on the UART_RX_TOUT_THRHD)*/ + #define UART_RXFIFO_TOUT_INT_RAW (BIT(8)) + #define UART_RXFIFO_TOUT_INT_RAW_M (BIT(8)) + #define UART_RXFIFO_TOUT_INT_RAW_V 0x1 + #define UART_RXFIFO_TOUT_INT_RAW_S 8 + /* UART_BRK_DET_INT_RAW : RO ;bitpos:[7] ;default: 1'b0 ; */ + /*description: The interrupt raw bit for Rx byte start error*/ + #define UART_BRK_DET_INT_RAW (BIT(7)) + #define UART_BRK_DET_INT_RAW_M (BIT(7)) + #define UART_BRK_DET_INT_RAW_V 0x1 + #define UART_BRK_DET_INT_RAW_S 7 + /* UART_CTS_CHG_INT_RAW : RO ;bitpos:[6] ;default: 1'b0 ; */ + /*description: The interrupt raw bit for CTS changing level*/ + #define UART_CTS_CHG_INT_RAW (BIT(6)) + #define UART_CTS_CHG_INT_RAW_M (BIT(6)) + #define UART_CTS_CHG_INT_RAW_V 0x1 + #define UART_CTS_CHG_INT_RAW_S 6 + /* UART_DSR_CHG_INT_RAW : RO ;bitpos:[5] ;default: 1'b0 ; */ + /*description: The interrupt raw bit for DSR changing level*/ + #define UART_DSR_CHG_INT_RAW (BIT(5)) + #define UART_DSR_CHG_INT_RAW_M (BIT(5)) + #define UART_DSR_CHG_INT_RAW_V 0x1 + #define UART_DSR_CHG_INT_RAW_S 5 + /* UART_RXFIFO_OVF_INT_RAW : RO ;bitpos:[4] ;default: 1'b0 ; */ + /*description: The interrupt raw bit for rx fifo overflow*/ + #define UART_RXFIFO_OVF_INT_RAW (BIT(4)) + #define UART_RXFIFO_OVF_INT_RAW_M (BIT(4)) + #define UART_RXFIFO_OVF_INT_RAW_V 0x1 + #define UART_RXFIFO_OVF_INT_RAW_S 4 + /* UART_FRM_ERR_INT_RAW : RO ;bitpos:[3] ;default: 1'b0 ; */ + /*description: The interrupt raw bit for other rx error*/ + #define UART_FRM_ERR_INT_RAW (BIT(3)) + #define UART_FRM_ERR_INT_RAW_M (BIT(3)) + #define UART_FRM_ERR_INT_RAW_V 0x1 + #define UART_FRM_ERR_INT_RAW_S 3 + /* UART_PARITY_ERR_INT_RAW : RO ;bitpos:[2] ;default: 1'b0 ; */ + /*description: The interrupt raw bit for parity check error*/ + #define UART_PARITY_ERR_INT_RAW (BIT(2)) + #define UART_PARITY_ERR_INT_RAW_M (BIT(2)) + #define UART_PARITY_ERR_INT_RAW_V 0x1 + #define UART_PARITY_ERR_INT_RAW_S 2 + /* UART_TXFIFO_EMPTY_INT_RAW : RO ;bitpos:[1] ;default: 1'b0 ; */ + /*description: The interrupt raw bit for tx fifo empty interrupt(depands on UART_TXFIFO_EMPTY_THRHD bits)*/ + #define UART_TXFIFO_EMPTY_INT_RAW (BIT(1)) + #define UART_TXFIFO_EMPTY_INT_RAW_M (BIT(1)) + #define UART_TXFIFO_EMPTY_INT_RAW_V 0x1 + #define UART_TXFIFO_EMPTY_INT_RAW_S 1 + /* UART_RXFIFO_FULL_INT_RAW : RO ;bitpos:[0] ;default: 1'b0 ; */ + /*description: The interrupt raw bit for rx fifo full interrupt(depands on UART_RXFIFO_FULL_THRHD bits)*/ + #define UART_RXFIFO_FULL_INT_RAW (BIT(0)) + #define UART_RXFIFO_FULL_INT_RAW_M (BIT(0)) + #define UART_RXFIFO_FULL_INT_RAW_V 0x1 + #define UART_RXFIFO_FULL_INT_RAW_S 0 + #define UART_GET_AT_CMD_CHAR_DET_INT_RAW(i) GET_PERI_REG_BITS2(UART_INT_RAW_REG(i) , UART_AT_CMD_CHAR_DET_INT_RAW_V, UART_AT_CMD_CHAR_DET_INT_RAW_S) + #define UART_GET_RS485_CLASH_INT_RAW(i) GET_PERI_REG_BITS2(UART_INT_RAW_REG(i) , UART_RS485_CLASH_INT_RAW_V, UART_RS485_CLASH_INT_RAW_S) + #define UART_GET_RS485_FRM_ERR_INT_RAW(i) GET_PERI_REG_BITS2(UART_INT_RAW_REG(i) , UART_RS485_FRM_ERR_INT_RAW_V, UART_RS485_FRM_ERR_INT_RAW_S) + #define UART_GET_RS485_PARITY_ERR_INT_RAW(i) GET_PERI_REG_BITS2(UART_INT_RAW_REG(i) , UART_RS485_PARITY_ERR_INT_RAW_V, UART_RS485_PARITY_ERR_INT_RAW_S) + #define UART_GET_TX_DONE_INT_RAW(i) GET_PERI_REG_BITS2(UART_INT_RAW_REG(i) , UART_TX_DONE_INT_RAW_V, UART_TX_DONE_INT_RAW_S) + #define UART_GET_TX_BRK_IDLE_DONE_INT_RAW(i) GET_PERI_REG_BITS2(UART_INT_RAW_REG(i) , UART_TX_BRK_IDLE_DONE_INT_RAW_V, UART_TX_BRK_IDLE_DONE_INT_RAW_S) + #define UART_GET_TX_BRK_DONE_INT_RAW(i) GET_PERI_REG_BITS2(UART_INT_RAW_REG(i) , UART_TX_BRK_DONE_INT_RAW_V, UART_TX_BRK_DONE_INT_RAW_S) + #define UART_GET_GLITCH_DET_INT_RAW(i) GET_PERI_REG_BITS2(UART_INT_RAW_REG(i) , UART_GLITCH_DET_INT_RAW_V, UART_GLITCH_DET_INT_RAW_S) + #define UART_GET_SW_XOFF_INT_RAW(i) GET_PERI_REG_BITS2(UART_INT_RAW_REG(i) , UART_SW_XOFF_INT_RAW_V, UART_SW_XOFF_INT_RAW_S) + #define UART_GET_SW_XON_INT_RAW(i) GET_PERI_REG_BITS2(UART_INT_RAW_REG(i) , UART_SW_XON_INT_RAW_V, UART_SW_XON_INT_RAW_S) + #define UART_GET_RXFIFO_TOUT_INT_RAW(i) GET_PERI_REG_BITS2(UART_INT_RAW_REG(i) , UART_RXFIFO_TOUT_INT_RAW_V, UART_RXFIFO_TOUT_INT_RAW_S) + #define UART_GET_BRK_DET_INT_RAW(i) GET_PERI_REG_BITS2(UART_INT_RAW_REG(i) , UART_BRK_DET_INT_RAW_V, UART_BRK_DET_INT_RAW_S) + #define UART_GET_CTS_CHG_INT_RAW(i) GET_PERI_REG_BITS2(UART_INT_RAW_REG(i) , UART_CTS_CHG_INT_RAW_V, UART_CTS_CHG_INT_RAW_S) + #define UART_GET_DSR_CHG_INT_RAW(i) GET_PERI_REG_BITS2(UART_INT_RAW_REG(i) , UART_DSR_CHG_INT_RAW_V, UART_DSR_CHG_INT_RAW_S) + #define UART_GET_RXFIFO_OVF_INT_RAW(i) GET_PERI_REG_BITS2(UART_INT_RAW_REG(i) , UART_RXFIFO_OVF_INT_RAW_V, UART_RXFIFO_OVF_INT_RAW_S) + #define UART_GET_FRM_ERR_INT_RAW(i) GET_PERI_REG_BITS2(UART_INT_RAW_REG(i) , UART_FRM_ERR_INT_RAW_V, UART_FRM_ERR_INT_RAW_S) + #define UART_GET_PARITY_ERR_INT_RAW(i) GET_PERI_REG_BITS2(UART_INT_RAW_REG(i) , UART_PARITY_ERR_INT_RAW_V, UART_PARITY_ERR_INT_RAW_S) + #define UART_GET_TXFIFO_EMPTY_INT_RAW(i) GET_PERI_REG_BITS2(UART_INT_RAW_REG(i) , UART_TXFIFO_EMPTY_INT_RAW_V, UART_TXFIFO_EMPTY_INT_RAW_S) + #define UART_GET_RXFIFO_FULL_INT_RAW(i) GET_PERI_REG_BITS2(UART_INT_RAW_REG(i) , UART_RXFIFO_FULL_INT_RAW_V, UART_RXFIFO_FULL_INT_RAW_S) + + + +#define UART_INT_ST_REG(i) (REG_UART_BASE(i) + 0x8) + /* UART_AT_CMD_CHAR_DET_INT_ST : RO ;bitpos:[18] ;default: 1'b0 ; */ + /*description: The interrupt state bit for detecting AT_CMD char interrupt*/ + #define UART_AT_CMD_CHAR_DET_INT_ST (BIT(18)) + #define UART_AT_CMD_CHAR_DET_INT_ST_M (BIT(18)) + #define UART_AT_CMD_CHAR_DET_INT_ST_V 0x1 + #define UART_AT_CMD_CHAR_DET_INT_ST_S 18 + /* UART_RS485_CLASH_INT_ST : RO ;bitpos:[17] ;default: 1'b0 ; */ + /*description: The interrupt state bit for rs485 tx rx clash interrrupt*/ + #define UART_RS485_CLASH_INT_ST (BIT(17)) + #define UART_RS485_CLASH_INT_ST_M (BIT(17)) + #define UART_RS485_CLASH_INT_ST_V 0x1 + #define UART_RS485_CLASH_INT_ST_S 17 + /* UART_RS485_FRM_ERR_INT_ST : RO ;bitpos:[16] ;default: 1'b0 ; */ + /*description: The interrupt state bit for rs485 other rx error*/ + #define UART_RS485_FRM_ERR_INT_ST (BIT(16)) + #define UART_RS485_FRM_ERR_INT_ST_M (BIT(16)) + #define UART_RS485_FRM_ERR_INT_ST_V 0x1 + #define UART_RS485_FRM_ERR_INT_ST_S 16 + /* UART_RS485_PARITY_ERR_INT_ST : RO ;bitpos:[15] ;default: 1'b0 ; */ + /*description: The interrupt state bit for rs485 parity error*/ + #define UART_RS485_PARITY_ERR_INT_ST (BIT(15)) + #define UART_RS485_PARITY_ERR_INT_ST_M (BIT(15)) + #define UART_RS485_PARITY_ERR_INT_ST_V 0x1 + #define UART_RS485_PARITY_ERR_INT_ST_S 15 + /* UART_TX_DONE_INT_ST : RO ;bitpos:[14] ;default: 1'b0 ; */ + /*description: The interrupt state bit for tx done event*/ + #define UART_TX_DONE_INT_ST (BIT(14)) + #define UART_TX_DONE_INT_ST_M (BIT(14)) + #define UART_TX_DONE_INT_ST_V 0x1 + #define UART_TX_DONE_INT_ST_S 14 + /* UART_TX_BRK_IDLE_DONE_INT_ST : RO ;bitpos:[13] ;default: 1'b0 ; */ + /*description: The interrupt state bit for tx send idle done event*/ + #define UART_TX_BRK_IDLE_DONE_INT_ST (BIT(13)) + #define UART_TX_BRK_IDLE_DONE_INT_ST_M (BIT(13)) + #define UART_TX_BRK_IDLE_DONE_INT_ST_V 0x1 + #define UART_TX_BRK_IDLE_DONE_INT_ST_S 13 + /* UART_TX_BRK_DONE_INT_ST : RO ;bitpos:[12] ;default: 1'b0 ; */ + /*description: The interrupt state bit for send 0 done event*/ + #define UART_TX_BRK_DONE_INT_ST (BIT(12)) + #define UART_TX_BRK_DONE_INT_ST_M (BIT(12)) + #define UART_TX_BRK_DONE_INT_ST_V 0x1 + #define UART_TX_BRK_DONE_INT_ST_S 12 + /* UART_GLITCH_DET_INT_ST : RO ;bitpos:[11] ;default: 1'b0 ; */ + /*description: The interrupt state bit for detecting rx glitch pulse event*/ + #define UART_GLITCH_DET_INT_ST (BIT(11)) + #define UART_GLITCH_DET_INT_ST_M (BIT(11)) + #define UART_GLITCH_DET_INT_ST_V 0x1 + #define UART_GLITCH_DET_INT_ST_S 11 + /* UART_SW_XOFF_INT_ST : RO ;bitpos:[10] ;default: 1'b0 ; */ + /*description: The interrupt state bit for rx receive xoff char event*/ + #define UART_SW_XOFF_INT_ST (BIT(10)) + #define UART_SW_XOFF_INT_ST_M (BIT(10)) + #define UART_SW_XOFF_INT_ST_V 0x1 + #define UART_SW_XOFF_INT_ST_S 10 + /* UART_SW_XON_INT_ST : RO ;bitpos:[9] ;default: 1'b0 ; */ + /*description: The interrupt state bit for rx receive xon char event*/ + #define UART_SW_XON_INT_ST (BIT(9)) + #define UART_SW_XON_INT_ST_M (BIT(9)) + #define UART_SW_XON_INT_ST_V 0x1 + #define UART_SW_XON_INT_ST_S 9 + /* UART_RXFIFO_TOUT_INT_ST : RO ;bitpos:[8] ;default: 1'b0 ; */ + /*description: The interrupt state bit for Rx time-out event*/ + #define UART_RXFIFO_TOUT_INT_ST (BIT(8)) + #define UART_RXFIFO_TOUT_INT_ST_M (BIT(8)) + #define UART_RXFIFO_TOUT_INT_ST_V 0x1 + #define UART_RXFIFO_TOUT_INT_ST_S 8 + /* UART_BRK_DET_INT_ST : RO ;bitpos:[7] ;default: 1'b0 ; */ + /*description: The interrupt state bit for rx byte start error*/ + #define UART_BRK_DET_INT_ST (BIT(7)) + #define UART_BRK_DET_INT_ST_M (BIT(7)) + #define UART_BRK_DET_INT_ST_V 0x1 + #define UART_BRK_DET_INT_ST_S 7 + /* UART_CTS_CHG_INT_ST : RO ;bitpos:[6] ;default: 1'b0 ; */ + /*description: The interrupt state bit for CTS changing level*/ + #define UART_CTS_CHG_INT_ST (BIT(6)) + #define UART_CTS_CHG_INT_ST_M (BIT(6)) + #define UART_CTS_CHG_INT_ST_V 0x1 + #define UART_CTS_CHG_INT_ST_S 6 + /* UART_DSR_CHG_INT_ST : RO ;bitpos:[5] ;default: 1'b0 ; */ + /*description: The interrupt state bit for DSR changing level*/ + #define UART_DSR_CHG_INT_ST (BIT(5)) + #define UART_DSR_CHG_INT_ST_M (BIT(5)) + #define UART_DSR_CHG_INT_ST_V 0x1 + #define UART_DSR_CHG_INT_ST_S 5 + /* UART_RXFIFO_OVF_INT_ST : RO ;bitpos:[4] ;default: 1'b0 ; */ + /*description: The interrupt state bit for RX fifo overflow*/ + #define UART_RXFIFO_OVF_INT_ST (BIT(4)) + #define UART_RXFIFO_OVF_INT_ST_M (BIT(4)) + #define UART_RXFIFO_OVF_INT_ST_V 0x1 + #define UART_RXFIFO_OVF_INT_ST_S 4 + /* UART_FRM_ERR_INT_ST : RO ;bitpos:[3] ;default: 1'b0 ; */ + /*description: The interrupt state for other rx error*/ + #define UART_FRM_ERR_INT_ST (BIT(3)) + #define UART_FRM_ERR_INT_ST_M (BIT(3)) + #define UART_FRM_ERR_INT_ST_V 0x1 + #define UART_FRM_ERR_INT_ST_S 3 + /* UART_PARITY_ERR_INT_ST : RO ;bitpos:[2] ;default: 1'b0 ; */ + /*description: The interrupt state bit for rx parity error*/ + #define UART_PARITY_ERR_INT_ST (BIT(2)) + #define UART_PARITY_ERR_INT_ST_M (BIT(2)) + #define UART_PARITY_ERR_INT_ST_V 0x1 + #define UART_PARITY_ERR_INT_ST_S 2 + /* UART_TXFIFO_EMPTY_INT_ST : RO ;bitpos:[1] ;default: 1'b0 ; */ + /*description: The interrupt state bit for TX fifo empty*/ + #define UART_TXFIFO_EMPTY_INT_ST (BIT(1)) + #define UART_TXFIFO_EMPTY_INT_ST_M (BIT(1)) + #define UART_TXFIFO_EMPTY_INT_ST_V 0x1 + #define UART_TXFIFO_EMPTY_INT_ST_S 1 + /* UART_RXFIFO_FULL_INT_ST : RO ;bitpos:[0] ;default: 1'b0 ; */ + /*description: The interrupt state bit for RX fifo full event*/ + #define UART_RXFIFO_FULL_INT_ST (BIT(0)) + #define UART_RXFIFO_FULL_INT_ST_M (BIT(0)) + #define UART_RXFIFO_FULL_INT_ST_V 0x1 + #define UART_RXFIFO_FULL_INT_ST_S 0 + #define UART_GET_AT_CMD_CHAR_DET_INT_ST(i) GET_PERI_REG_BITS2(UART_INT_ST_REG(i) , UART_AT_CMD_CHAR_DET_INT_ST_V, UART_AT_CMD_CHAR_DET_INT_ST_S) + #define UART_GET_RS485_CLASH_INT_ST(i) GET_PERI_REG_BITS2(UART_INT_ST_REG(i) , UART_RS485_CLASH_INT_ST_V, UART_RS485_CLASH_INT_ST_S) + #define UART_GET_RS485_FRM_ERR_INT_ST(i) GET_PERI_REG_BITS2(UART_INT_ST_REG(i) , UART_RS485_FRM_ERR_INT_ST_V, UART_RS485_FRM_ERR_INT_ST_S) + #define UART_GET_RS485_PARITY_ERR_INT_ST(i) GET_PERI_REG_BITS2(UART_INT_ST_REG(i) , UART_RS485_PARITY_ERR_INT_ST_V, UART_RS485_PARITY_ERR_INT_ST_S) + #define UART_GET_TX_DONE_INT_ST(i) GET_PERI_REG_BITS2(UART_INT_ST_REG(i) , UART_TX_DONE_INT_ST_V, UART_TX_DONE_INT_ST_S) + #define UART_GET_TX_BRK_IDLE_DONE_INT_ST(i) GET_PERI_REG_BITS2(UART_INT_ST_REG(i) , UART_TX_BRK_IDLE_DONE_INT_ST_V, UART_TX_BRK_IDLE_DONE_INT_ST_S) + #define UART_GET_TX_BRK_DONE_INT_ST(i) GET_PERI_REG_BITS2(UART_INT_ST_REG(i) , UART_TX_BRK_DONE_INT_ST_V, UART_TX_BRK_DONE_INT_ST_S) + #define UART_GET_GLITCH_DET_INT_ST(i) GET_PERI_REG_BITS2(UART_INT_ST_REG(i) , UART_GLITCH_DET_INT_ST_V, UART_GLITCH_DET_INT_ST_S) + #define UART_GET_SW_XOFF_INT_ST(i) GET_PERI_REG_BITS2(UART_INT_ST_REG(i) , UART_SW_XOFF_INT_ST_V, UART_SW_XOFF_INT_ST_S) + #define UART_GET_SW_XON_INT_ST(i) GET_PERI_REG_BITS2(UART_INT_ST_REG(i) , UART_SW_XON_INT_ST_V, UART_SW_XON_INT_ST_S) + #define UART_GET_RXFIFO_TOUT_INT_ST(i) GET_PERI_REG_BITS2(UART_INT_ST_REG(i) , UART_RXFIFO_TOUT_INT_ST_V, UART_RXFIFO_TOUT_INT_ST_S) + #define UART_GET_BRK_DET_INT_ST(i) GET_PERI_REG_BITS2(UART_INT_ST_REG(i) , UART_BRK_DET_INT_ST_V, UART_BRK_DET_INT_ST_S) + #define UART_GET_CTS_CHG_INT_ST(i) GET_PERI_REG_BITS2(UART_INT_ST_REG(i) , UART_CTS_CHG_INT_ST_V, UART_CTS_CHG_INT_ST_S) + #define UART_GET_DSR_CHG_INT_ST(i) GET_PERI_REG_BITS2(UART_INT_ST_REG(i) , UART_DSR_CHG_INT_ST_V, UART_DSR_CHG_INT_ST_S) + #define UART_GET_RXFIFO_OVF_INT_ST(i) GET_PERI_REG_BITS2(UART_INT_ST_REG(i) , UART_RXFIFO_OVF_INT_ST_V, UART_RXFIFO_OVF_INT_ST_S) + #define UART_GET_FRM_ERR_INT_ST(i) GET_PERI_REG_BITS2(UART_INT_ST_REG(i) , UART_FRM_ERR_INT_ST_V, UART_FRM_ERR_INT_ST_S) + #define UART_GET_PARITY_ERR_INT_ST(i) GET_PERI_REG_BITS2(UART_INT_ST_REG(i) , UART_PARITY_ERR_INT_ST_V, UART_PARITY_ERR_INT_ST_S) + #define UART_GET_TXFIFO_EMPTY_INT_ST(i) GET_PERI_REG_BITS2(UART_INT_ST_REG(i) , UART_TXFIFO_EMPTY_INT_ST_V, UART_TXFIFO_EMPTY_INT_ST_S) + #define UART_GET_RXFIFO_FULL_INT_ST(i) GET_PERI_REG_BITS2(UART_INT_ST_REG(i) , UART_RXFIFO_FULL_INT_ST_V, UART_RXFIFO_FULL_INT_ST_S) + + + +#define UART_INT_ENA_REG(i) (REG_UART_BASE(i) + 0xC) + /* UART_AT_CMD_CHAR_DET_INT_ENA : R/W ;bitpos:[18] ;default: 1'b0 ; */ + /*description: The interrupt enable bit for detecting AT_CMD char interrupt*/ + #define UART_AT_CMD_CHAR_DET_INT_ENA (BIT(18)) + #define UART_AT_CMD_CHAR_DET_INT_ENA_M (BIT(18)) + #define UART_AT_CMD_CHAR_DET_INT_ENA_V 0x1 + #define UART_AT_CMD_CHAR_DET_INT_ENA_S 18 + /* UART_RS485_CLASH_INT_ENA : R/W ;bitpos:[17] ;default: 1'b0 ; */ + /*description: The interrupt enable bit for rs485 tx rx clash interrrupt*/ + #define UART_RS485_CLASH_INT_ENA (BIT(17)) + #define UART_RS485_CLASH_INT_ENA_M (BIT(17)) + #define UART_RS485_CLASH_INT_ENA_V 0x1 + #define UART_RS485_CLASH_INT_ENA_S 17 + /* UART_RS485_FRM_ERR_INT_ENA : R/W ;bitpos:[16] ;default: 1'b0 ; */ + /*description: The interrupt enable bit for rs485 other rx error*/ + #define UART_RS485_FRM_ERR_INT_ENA (BIT(16)) + #define UART_RS485_FRM_ERR_INT_ENA_M (BIT(16)) + #define UART_RS485_FRM_ERR_INT_ENA_V 0x1 + #define UART_RS485_FRM_ERR_INT_ENA_S 16 + /* UART_RS485_PARITY_ERR_INT_ENA : R/W ;bitpos:[15] ;default: 1'b0 ; */ + /*description: The interrupt enable bit for rs485 parity error*/ + #define UART_RS485_PARITY_ERR_INT_ENA (BIT(15)) + #define UART_RS485_PARITY_ERR_INT_ENA_M (BIT(15)) + #define UART_RS485_PARITY_ERR_INT_ENA_V 0x1 + #define UART_RS485_PARITY_ERR_INT_ENA_S 15 + /* UART_TX_DONE_INT_ENA : R/W ;bitpos:[14] ;default: 1'b0 ; */ + /*description: The interrupt enable bit for tx done interrupt*/ + #define UART_TX_DONE_INT_ENA (BIT(14)) + #define UART_TX_DONE_INT_ENA_M (BIT(14)) + #define UART_TX_DONE_INT_ENA_V 0x1 + #define UART_TX_DONE_INT_ENA_S 14 + /* UART_TX_BRK_IDLE_DONE_INT_ENA : R/W ;bitpos:[13] ;default: 1'b0 ; */ + /*description: The interrupt enable bit for tx send idle done interrupt*/ + #define UART_TX_BRK_IDLE_DONE_INT_ENA (BIT(13)) + #define UART_TX_BRK_IDLE_DONE_INT_ENA_M (BIT(13)) + #define UART_TX_BRK_IDLE_DONE_INT_ENA_V 0x1 + #define UART_TX_BRK_IDLE_DONE_INT_ENA_S 13 + /* UART_TX_BRK_DONE_INT_ENA : R/W ;bitpos:[12] ;default: 1'b0 ; */ + /*description: The interrupt enable bit for send 0 done interrupt*/ + #define UART_TX_BRK_DONE_INT_ENA (BIT(12)) + #define UART_TX_BRK_DONE_INT_ENA_M (BIT(12)) + #define UART_TX_BRK_DONE_INT_ENA_V 0x1 + #define UART_TX_BRK_DONE_INT_ENA_S 12 + /* UART_GLITCH_DET_INT_ENA : R/W ;bitpos:[11] ;default: 1'b0 ; */ + /*description: The interrupt enable bit for detecting rx glitch pulse interrupt*/ + #define UART_GLITCH_DET_INT_ENA (BIT(11)) + #define UART_GLITCH_DET_INT_ENA_M (BIT(11)) + #define UART_GLITCH_DET_INT_ENA_V 0x1 + #define UART_GLITCH_DET_INT_ENA_S 11 + /* UART_SW_XOFF_INT_ENA : R/W ;bitpos:[10] ;default: 1'b0 ; */ + /*description: The interrupt enable bit for rx receive xoff char interrupt*/ + #define UART_SW_XOFF_INT_ENA (BIT(10)) + #define UART_SW_XOFF_INT_ENA_M (BIT(10)) + #define UART_SW_XOFF_INT_ENA_V 0x1 + #define UART_SW_XOFF_INT_ENA_S 10 + /* UART_SW_XON_INT_ENA : R/W ;bitpos:[9] ;default: 1'b0 ; */ + /*description: The interrupt enable bit for rx receive xon char interrupt*/ + #define UART_SW_XON_INT_ENA (BIT(9)) + #define UART_SW_XON_INT_ENA_M (BIT(9)) + #define UART_SW_XON_INT_ENA_V 0x1 + #define UART_SW_XON_INT_ENA_S 9 + /* UART_RXFIFO_TOUT_INT_ENA : R/W ;bitpos:[8] ;default: 1'b0 ; */ + /*description: The interrupt enable bit for rx time-out interrupt*/ + #define UART_RXFIFO_TOUT_INT_ENA (BIT(8)) + #define UART_RXFIFO_TOUT_INT_ENA_M (BIT(8)) + #define UART_RXFIFO_TOUT_INT_ENA_V 0x1 + #define UART_RXFIFO_TOUT_INT_ENA_S 8 + /* UART_BRK_DET_INT_ENA : R/W ;bitpos:[7] ;default: 1'b0 ; */ + /*description: The interrupt enable bit for rx byte start error*/ + #define UART_BRK_DET_INT_ENA (BIT(7)) + #define UART_BRK_DET_INT_ENA_M (BIT(7)) + #define UART_BRK_DET_INT_ENA_V 0x1 + #define UART_BRK_DET_INT_ENA_S 7 + /* UART_CTS_CHG_INT_ENA : R/W ;bitpos:[6] ;default: 1'b0 ; */ + /*description: The interrupt enable bit for CTS changing level*/ + #define UART_CTS_CHG_INT_ENA (BIT(6)) + #define UART_CTS_CHG_INT_ENA_M (BIT(6)) + #define UART_CTS_CHG_INT_ENA_V 0x1 + #define UART_CTS_CHG_INT_ENA_S 6 + /* UART_DSR_CHG_INT_ENA : R/W ;bitpos:[5] ;default: 1'b0 ; */ + /*description: The interrupt enable bit for DSR changing level*/ + #define UART_DSR_CHG_INT_ENA (BIT(5)) + #define UART_DSR_CHG_INT_ENA_M (BIT(5)) + #define UART_DSR_CHG_INT_ENA_V 0x1 + #define UART_DSR_CHG_INT_ENA_S 5 + /* UART_RXFIFO_OVF_INT_ENA : R/W ;bitpos:[4] ;default: 1'b0 ; */ + /*description: The interrupt enable bit for rx fifo overflow*/ + #define UART_RXFIFO_OVF_INT_ENA (BIT(4)) + #define UART_RXFIFO_OVF_INT_ENA_M (BIT(4)) + #define UART_RXFIFO_OVF_INT_ENA_V 0x1 + #define UART_RXFIFO_OVF_INT_ENA_S 4 + /* UART_FRM_ERR_INT_ENA : R/W ;bitpos:[3] ;default: 1'b0 ; */ + /*description: The interrupt enable bit for other rx error*/ + #define UART_FRM_ERR_INT_ENA (BIT(3)) + #define UART_FRM_ERR_INT_ENA_M (BIT(3)) + #define UART_FRM_ERR_INT_ENA_V 0x1 + #define UART_FRM_ERR_INT_ENA_S 3 + /* UART_PARITY_ERR_INT_ENA : R/W ;bitpos:[2] ;default: 1'b0 ; */ + /*description: The interrupt enable bit for parity error*/ + #define UART_PARITY_ERR_INT_ENA (BIT(2)) + #define UART_PARITY_ERR_INT_ENA_M (BIT(2)) + #define UART_PARITY_ERR_INT_ENA_V 0x1 + #define UART_PARITY_ERR_INT_ENA_S 2 + /* UART_TXFIFO_EMPTY_INT_ENA : R/W ;bitpos:[1] ;default: 1'b0 ; */ + /*description: The interrupt enable bit for tx fifo empty event*/ + #define UART_TXFIFO_EMPTY_INT_ENA (BIT(1)) + #define UART_TXFIFO_EMPTY_INT_ENA_M (BIT(1)) + #define UART_TXFIFO_EMPTY_INT_ENA_V 0x1 + #define UART_TXFIFO_EMPTY_INT_ENA_S 1 + /* UART_RXFIFO_FULL_INT_ENA : R/W ;bitpos:[0] ;default: 1'b0 ; */ + /*description: The interrupt enable bit for rx fifo full event*/ + #define UART_RXFIFO_FULL_INT_ENA (BIT(0)) + #define UART_RXFIFO_FULL_INT_ENA_M (BIT(0)) + #define UART_RXFIFO_FULL_INT_ENA_V 0x1 + #define UART_RXFIFO_FULL_INT_ENA_S 0 + #define UART_GET_AT_CMD_CHAR_DET_INT_ENA(i) GET_PERI_REG_BITS2(UART_INT_ENA_REG(i) , UART_AT_CMD_CHAR_DET_INT_ENA_V, UART_AT_CMD_CHAR_DET_INT_ENA_S) + #define UART_SET_AT_CMD_CHAR_DET_INT_ENA(i,val) SET_PERI_REG_BITS(UART_INT_ENA_REG(i) ,UART_AT_CMD_CHAR_DET_INT_ENA_V,(val),UART_AT_CMD_CHAR_DET_INT_ENA_S) + #define UART_GET_RS485_CLASH_INT_ENA(i) GET_PERI_REG_BITS2(UART_INT_ENA_REG(i) , UART_RS485_CLASH_INT_ENA_V, UART_RS485_CLASH_INT_ENA_S) + #define UART_SET_RS485_CLASH_INT_ENA(i,val) SET_PERI_REG_BITS(UART_INT_ENA_REG(i) ,UART_RS485_CLASH_INT_ENA_V,(val),UART_RS485_CLASH_INT_ENA_S) + #define UART_GET_RS485_FRM_ERR_INT_ENA(i) GET_PERI_REG_BITS2(UART_INT_ENA_REG(i) , UART_RS485_FRM_ERR_INT_ENA_V, UART_RS485_FRM_ERR_INT_ENA_S) + #define UART_SET_RS485_FRM_ERR_INT_ENA(i,val) SET_PERI_REG_BITS(UART_INT_ENA_REG(i) ,UART_RS485_FRM_ERR_INT_ENA_V,(val),UART_RS485_FRM_ERR_INT_ENA_S) + #define UART_GET_RS485_PARITY_ERR_INT_ENA(i) GET_PERI_REG_BITS2(UART_INT_ENA_REG(i) , UART_RS485_PARITY_ERR_INT_ENA_V, UART_RS485_PARITY_ERR_INT_ENA_S) + #define UART_SET_RS485_PARITY_ERR_INT_ENA(i,val) SET_PERI_REG_BITS(UART_INT_ENA_REG(i) ,UART_RS485_PARITY_ERR_INT_ENA_V,(val),UART_RS485_PARITY_ERR_INT_ENA_S) + #define UART_GET_TX_DONE_INT_ENA(i) GET_PERI_REG_BITS2(UART_INT_ENA_REG(i) , UART_TX_DONE_INT_ENA_V, UART_TX_DONE_INT_ENA_S) + #define UART_SET_TX_DONE_INT_ENA(i,val) SET_PERI_REG_BITS(UART_INT_ENA_REG(i) ,UART_TX_DONE_INT_ENA_V,(val),UART_TX_DONE_INT_ENA_S) + #define UART_GET_TX_BRK_IDLE_DONE_INT_ENA(i) GET_PERI_REG_BITS2(UART_INT_ENA_REG(i) , UART_TX_BRK_IDLE_DONE_INT_ENA_V, UART_TX_BRK_IDLE_DONE_INT_ENA_S) + #define UART_SET_TX_BRK_IDLE_DONE_INT_ENA(i,val) SET_PERI_REG_BITS(UART_INT_ENA_REG(i) ,UART_TX_BRK_IDLE_DONE_INT_ENA_V,(val),UART_TX_BRK_IDLE_DONE_INT_ENA_S) + #define UART_GET_TX_BRK_DONE_INT_ENA(i) GET_PERI_REG_BITS2(UART_INT_ENA_REG(i) , UART_TX_BRK_DONE_INT_ENA_V, UART_TX_BRK_DONE_INT_ENA_S) + #define UART_SET_TX_BRK_DONE_INT_ENA(i,val) SET_PERI_REG_BITS(UART_INT_ENA_REG(i) ,UART_TX_BRK_DONE_INT_ENA_V,(val),UART_TX_BRK_DONE_INT_ENA_S) + #define UART_GET_GLITCH_DET_INT_ENA(i) GET_PERI_REG_BITS2(UART_INT_ENA_REG(i) , UART_GLITCH_DET_INT_ENA_V, UART_GLITCH_DET_INT_ENA_S) + #define UART_SET_GLITCH_DET_INT_ENA(i,val) SET_PERI_REG_BITS(UART_INT_ENA_REG(i) ,UART_GLITCH_DET_INT_ENA_V,(val),UART_GLITCH_DET_INT_ENA_S) + #define UART_GET_SW_XOFF_INT_ENA(i) GET_PERI_REG_BITS2(UART_INT_ENA_REG(i) , UART_SW_XOFF_INT_ENA_V, UART_SW_XOFF_INT_ENA_S) + #define UART_SET_SW_XOFF_INT_ENA(i,val) SET_PERI_REG_BITS(UART_INT_ENA_REG(i) ,UART_SW_XOFF_INT_ENA_V,(val),UART_SW_XOFF_INT_ENA_S) + #define UART_GET_SW_XON_INT_ENA(i) GET_PERI_REG_BITS2(UART_INT_ENA_REG(i) , UART_SW_XON_INT_ENA_V, UART_SW_XON_INT_ENA_S) + #define UART_SET_SW_XON_INT_ENA(i,val) SET_PERI_REG_BITS(UART_INT_ENA_REG(i) ,UART_SW_XON_INT_ENA_V,(val),UART_SW_XON_INT_ENA_S) + #define UART_GET_RXFIFO_TOUT_INT_ENA(i) GET_PERI_REG_BITS2(UART_INT_ENA_REG(i) , UART_RXFIFO_TOUT_INT_ENA_V, UART_RXFIFO_TOUT_INT_ENA_S) + #define UART_SET_RXFIFO_TOUT_INT_ENA(i,val) SET_PERI_REG_BITS(UART_INT_ENA_REG(i) ,UART_RXFIFO_TOUT_INT_ENA_V,(val),UART_RXFIFO_TOUT_INT_ENA_S) + #define UART_GET_BRK_DET_INT_ENA(i) GET_PERI_REG_BITS2(UART_INT_ENA_REG(i) , UART_BRK_DET_INT_ENA_V, UART_BRK_DET_INT_ENA_S) + #define UART_SET_BRK_DET_INT_ENA(i,val) SET_PERI_REG_BITS(UART_INT_ENA_REG(i) ,UART_BRK_DET_INT_ENA_V,(val),UART_BRK_DET_INT_ENA_S) + #define UART_GET_CTS_CHG_INT_ENA(i) GET_PERI_REG_BITS2(UART_INT_ENA_REG(i) , UART_CTS_CHG_INT_ENA_V, UART_CTS_CHG_INT_ENA_S) + #define UART_SET_CTS_CHG_INT_ENA(i,val) SET_PERI_REG_BITS(UART_INT_ENA_REG(i) ,UART_CTS_CHG_INT_ENA_V,(val),UART_CTS_CHG_INT_ENA_S) + #define UART_GET_DSR_CHG_INT_ENA(i) GET_PERI_REG_BITS2(UART_INT_ENA_REG(i) , UART_DSR_CHG_INT_ENA_V, UART_DSR_CHG_INT_ENA_S) + #define UART_SET_DSR_CHG_INT_ENA(i,val) SET_PERI_REG_BITS(UART_INT_ENA_REG(i) ,UART_DSR_CHG_INT_ENA_V,(val),UART_DSR_CHG_INT_ENA_S) + #define UART_GET_RXFIFO_OVF_INT_ENA(i) GET_PERI_REG_BITS2(UART_INT_ENA_REG(i) , UART_RXFIFO_OVF_INT_ENA_V, UART_RXFIFO_OVF_INT_ENA_S) + #define UART_SET_RXFIFO_OVF_INT_ENA(i,val) SET_PERI_REG_BITS(UART_INT_ENA_REG(i) ,UART_RXFIFO_OVF_INT_ENA_V,(val),UART_RXFIFO_OVF_INT_ENA_S) + #define UART_GET_FRM_ERR_INT_ENA(i) GET_PERI_REG_BITS2(UART_INT_ENA_REG(i) , UART_FRM_ERR_INT_ENA_V, UART_FRM_ERR_INT_ENA_S) + #define UART_SET_FRM_ERR_INT_ENA(i,val) SET_PERI_REG_BITS(UART_INT_ENA_REG(i) ,UART_FRM_ERR_INT_ENA_V,(val),UART_FRM_ERR_INT_ENA_S) + #define UART_GET_PARITY_ERR_INT_ENA(i) GET_PERI_REG_BITS2(UART_INT_ENA_REG(i) , UART_PARITY_ERR_INT_ENA_V, UART_PARITY_ERR_INT_ENA_S) + #define UART_SET_PARITY_ERR_INT_ENA(i,val) SET_PERI_REG_BITS(UART_INT_ENA_REG(i) ,UART_PARITY_ERR_INT_ENA_V,(val),UART_PARITY_ERR_INT_ENA_S) + #define UART_GET_TXFIFO_EMPTY_INT_ENA(i) GET_PERI_REG_BITS2(UART_INT_ENA_REG(i) , UART_TXFIFO_EMPTY_INT_ENA_V, UART_TXFIFO_EMPTY_INT_ENA_S) + #define UART_SET_TXFIFO_EMPTY_INT_ENA(i,val) SET_PERI_REG_BITS(UART_INT_ENA_REG(i) ,UART_TXFIFO_EMPTY_INT_ENA_V,(val),UART_TXFIFO_EMPTY_INT_ENA_S) + #define UART_GET_RXFIFO_FULL_INT_ENA(i) GET_PERI_REG_BITS2(UART_INT_ENA_REG(i) , UART_RXFIFO_FULL_INT_ENA_V, UART_RXFIFO_FULL_INT_ENA_S) + #define UART_SET_RXFIFO_FULL_INT_ENA(i,val) SET_PERI_REG_BITS(UART_INT_ENA_REG(i) ,UART_RXFIFO_FULL_INT_ENA_V,(val),UART_RXFIFO_FULL_INT_ENA_S) + + + +#define UART_INT_CLR_REG(i) (REG_UART_BASE(i) + 0x10) + /* UART_AT_CMD_CHAR_DET_INT_CLR : WO ;bitpos:[18] ;default: 1'b0 ; */ + /*description: Set this bit for detecting AT_CMD char interrupt*/ + #define UART_AT_CMD_CHAR_DET_INT_CLR (BIT(18)) + #define UART_AT_CMD_CHAR_DET_INT_CLR_M (BIT(18)) + #define UART_AT_CMD_CHAR_DET_INT_CLR_V 0x1 + #define UART_AT_CMD_CHAR_DET_INT_CLR_S 18 + /* UART_RS485_CLASH_INT_CLR : WO ;bitpos:[17] ;default: 1'b0 ; */ + /*description: Set this bit for rs485 tx rx clash interrrupt*/ + #define UART_RS485_CLASH_INT_CLR (BIT(17)) + #define UART_RS485_CLASH_INT_CLR_M (BIT(17)) + #define UART_RS485_CLASH_INT_CLR_V 0x1 + #define UART_RS485_CLASH_INT_CLR_S 17 + /* UART_RS485_FRM_ERR_INT_CLR : WO ;bitpos:[16] ;default: 1'b0 ; */ + /*description: Set this bit for rs485 other rx error*/ + #define UART_RS485_FRM_ERR_INT_CLR (BIT(16)) + #define UART_RS485_FRM_ERR_INT_CLR_M (BIT(16)) + #define UART_RS485_FRM_ERR_INT_CLR_V 0x1 + #define UART_RS485_FRM_ERR_INT_CLR_S 16 + /* UART_RS485_PARITY_ERR_INT_CLR : WO ;bitpos:[15] ;default: 1'b0 ; */ + /*description: Set this bit for rs485 parity error interrupt*/ + #define UART_RS485_PARITY_ERR_INT_CLR (BIT(15)) + #define UART_RS485_PARITY_ERR_INT_CLR_M (BIT(15)) + #define UART_RS485_PARITY_ERR_INT_CLR_V 0x1 + #define UART_RS485_PARITY_ERR_INT_CLR_S 15 + /* UART_TX_DONE_INT_CLR : WO ;bitpos:[14] ;default: 1'b0 ; */ + /*description: Set this bit to clear the tx done interrupt*/ + #define UART_TX_DONE_INT_CLR (BIT(14)) + #define UART_TX_DONE_INT_CLR_M (BIT(14)) + #define UART_TX_DONE_INT_CLR_V 0x1 + #define UART_TX_DONE_INT_CLR_S 14 + /* UART_TX_BRK_IDLE_DONE_INT_CLR : WO ;bitpos:[13] ;default: 1'b0 ; */ + /*description: Set this bit to clear the tx send idle done interrupt*/ + #define UART_TX_BRK_IDLE_DONE_INT_CLR (BIT(13)) + #define UART_TX_BRK_IDLE_DONE_INT_CLR_M (BIT(13)) + #define UART_TX_BRK_IDLE_DONE_INT_CLR_V 0x1 + #define UART_TX_BRK_IDLE_DONE_INT_CLR_S 13 + /* UART_TX_BRK_DONE_INT_CLR : WO ;bitpos:[12] ;default: 1'b0 ; */ + /*description: Set this bit to clear the send 0 done interrupt*/ + #define UART_TX_BRK_DONE_INT_CLR (BIT(12)) + #define UART_TX_BRK_DONE_INT_CLR_M (BIT(12)) + #define UART_TX_BRK_DONE_INT_CLR_V 0x1 + #define UART_TX_BRK_DONE_INT_CLR_S 12 + /* UART_GLITCH_DET_INT_CLR : WO ;bitpos:[11] ;default: 1'b0 ; */ + /*description: Set this bit to clear the detecting rx glitch pulse interrupt*/ + #define UART_GLITCH_DET_INT_CLR (BIT(11)) + #define UART_GLITCH_DET_INT_CLR_M (BIT(11)) + #define UART_GLITCH_DET_INT_CLR_V 0x1 + #define UART_GLITCH_DET_INT_CLR_S 11 + /* UART_SW_XOFF_INT_CLR : WO ;bitpos:[10] ;default: 1'b0 ; */ + /*description: Set this bit to clear the rx receive xoff char interrupt*/ + #define UART_SW_XOFF_INT_CLR (BIT(10)) + #define UART_SW_XOFF_INT_CLR_M (BIT(10)) + #define UART_SW_XOFF_INT_CLR_V 0x1 + #define UART_SW_XOFF_INT_CLR_S 10 + /* UART_SW_XON_INT_CLR : WO ;bitpos:[9] ;default: 1'b0 ; */ + /*description: Set this bit to clear the rx receive xon char interrupt*/ + #define UART_SW_XON_INT_CLR (BIT(9)) + #define UART_SW_XON_INT_CLR_M (BIT(9)) + #define UART_SW_XON_INT_CLR_V 0x1 + #define UART_SW_XON_INT_CLR_S 9 + /* UART_RXFIFO_TOUT_INT_CLR : WO ;bitpos:[8] ;default: 1'b0 ; */ + /*description: Set this bit to clear the rx time-out interrupt*/ + #define UART_RXFIFO_TOUT_INT_CLR (BIT(8)) + #define UART_RXFIFO_TOUT_INT_CLR_M (BIT(8)) + #define UART_RXFIFO_TOUT_INT_CLR_V 0x1 + #define UART_RXFIFO_TOUT_INT_CLR_S 8 + /* UART_BRK_DET_INT_CLR : WO ;bitpos:[7] ;default: 1'b0 ; */ + /*description: Set this bit to clear the rx byte start interrupt*/ + #define UART_BRK_DET_INT_CLR (BIT(7)) + #define UART_BRK_DET_INT_CLR_M (BIT(7)) + #define UART_BRK_DET_INT_CLR_V 0x1 + #define UART_BRK_DET_INT_CLR_S 7 + /* UART_CTS_CHG_INT_CLR : WO ;bitpos:[6] ;default: 1'b0 ; */ + /*description: Set this bit to clear the CTS changing interrupt*/ + #define UART_CTS_CHG_INT_CLR (BIT(6)) + #define UART_CTS_CHG_INT_CLR_M (BIT(6)) + #define UART_CTS_CHG_INT_CLR_V 0x1 + #define UART_CTS_CHG_INT_CLR_S 6 + /* UART_DSR_CHG_INT_CLR : WO ;bitpos:[5] ;default: 1'b0 ; */ + /*description: Set this bit to clear the DSR changing interrupt*/ + #define UART_DSR_CHG_INT_CLR (BIT(5)) + #define UART_DSR_CHG_INT_CLR_M (BIT(5)) + #define UART_DSR_CHG_INT_CLR_V 0x1 + #define UART_DSR_CHG_INT_CLR_S 5 + /* UART_RXFIFO_OVF_INT_CLR : WO ;bitpos:[4] ;default: 1'b0 ; */ + /*description: Set this bit to clear the rx fifo over-flow interrupt*/ + #define UART_RXFIFO_OVF_INT_CLR (BIT(4)) + #define UART_RXFIFO_OVF_INT_CLR_M (BIT(4)) + #define UART_RXFIFO_OVF_INT_CLR_V 0x1 + #define UART_RXFIFO_OVF_INT_CLR_S 4 + /* UART_FRM_ERR_INT_CLR : WO ;bitpos:[3] ;default: 1'b0 ; */ + /*description: Set this bit to clear other rx error interrupt*/ + #define UART_FRM_ERR_INT_CLR (BIT(3)) + #define UART_FRM_ERR_INT_CLR_M (BIT(3)) + #define UART_FRM_ERR_INT_CLR_V 0x1 + #define UART_FRM_ERR_INT_CLR_S 3 + /* UART_PARITY_ERR_INT_CLR : WO ;bitpos:[2] ;default: 1'b0 ; */ + /*description: Set this bit to clear the parity error interrupt*/ + #define UART_PARITY_ERR_INT_CLR (BIT(2)) + #define UART_PARITY_ERR_INT_CLR_M (BIT(2)) + #define UART_PARITY_ERR_INT_CLR_V 0x1 + #define UART_PARITY_ERR_INT_CLR_S 2 + /* UART_TXFIFO_EMPTY_INT_CLR : WO ;bitpos:[1] ;default: 1'b0 ; */ + /*description: Set this bit to clear the tx fifo empty interrupt*/ + #define UART_TXFIFO_EMPTY_INT_CLR (BIT(1)) + #define UART_TXFIFO_EMPTY_INT_CLR_M (BIT(1)) + #define UART_TXFIFO_EMPTY_INT_CLR_V 0x1 + #define UART_TXFIFO_EMPTY_INT_CLR_S 1 + /* UART_RXFIFO_FULL_INT_CLR : WO ;bitpos:[0] ;default: 1'b0 ; */ + /*description: Set this bit to clear the rx fifo full interrupt*/ + #define UART_RXFIFO_FULL_INT_CLR (BIT(0)) + #define UART_RXFIFO_FULL_INT_CLR_M (BIT(0)) + #define UART_RXFIFO_FULL_INT_CLR_V 0x1 + #define UART_RXFIFO_FULL_INT_CLR_S 0 + #define UART_SET_AT_CMD_CHAR_DET_INT_CLR(i,val) SET_PERI_REG_BITS(UART_INT_CLR_REG(i) ,UART_AT_CMD_CHAR_DET_INT_CLR_V,(val),UART_AT_CMD_CHAR_DET_INT_CLR_S) + #define UART_SET_RS485_CLASH_INT_CLR(i,val) SET_PERI_REG_BITS(UART_INT_CLR_REG(i) ,UART_RS485_CLASH_INT_CLR_V,(val),UART_RS485_CLASH_INT_CLR_S) + #define UART_SET_RS485_FRM_ERR_INT_CLR(i,val) SET_PERI_REG_BITS(UART_INT_CLR_REG(i) ,UART_RS485_FRM_ERR_INT_CLR_V,(val),UART_RS485_FRM_ERR_INT_CLR_S) + #define UART_SET_RS485_PARITY_ERR_INT_CLR(i,val) SET_PERI_REG_BITS(UART_INT_CLR_REG(i) ,UART_RS485_PARITY_ERR_INT_CLR_V,(val),UART_RS485_PARITY_ERR_INT_CLR_S) + #define UART_SET_TX_DONE_INT_CLR(i,val) SET_PERI_REG_BITS(UART_INT_CLR_REG(i) ,UART_TX_DONE_INT_CLR_V,(val),UART_TX_DONE_INT_CLR_S) + #define UART_SET_TX_BRK_IDLE_DONE_INT_CLR(i,val) SET_PERI_REG_BITS(UART_INT_CLR_REG(i) ,UART_TX_BRK_IDLE_DONE_INT_CLR_V,(val),UART_TX_BRK_IDLE_DONE_INT_CLR_S) + #define UART_SET_TX_BRK_DONE_INT_CLR(i,val) SET_PERI_REG_BITS(UART_INT_CLR_REG(i) ,UART_TX_BRK_DONE_INT_CLR_V,(val),UART_TX_BRK_DONE_INT_CLR_S) + #define UART_SET_GLITCH_DET_INT_CLR(i,val) SET_PERI_REG_BITS(UART_INT_CLR_REG(i) ,UART_GLITCH_DET_INT_CLR_V,(val),UART_GLITCH_DET_INT_CLR_S) + #define UART_SET_SW_XOFF_INT_CLR(i,val) SET_PERI_REG_BITS(UART_INT_CLR_REG(i) ,UART_SW_XOFF_INT_CLR_V,(val),UART_SW_XOFF_INT_CLR_S) + #define UART_SET_SW_XON_INT_CLR(i,val) SET_PERI_REG_BITS(UART_INT_CLR_REG(i) ,UART_SW_XON_INT_CLR_V,(val),UART_SW_XON_INT_CLR_S) + #define UART_SET_RXFIFO_TOUT_INT_CLR(i,val) SET_PERI_REG_BITS(UART_INT_CLR_REG(i) ,UART_RXFIFO_TOUT_INT_CLR_V,(val),UART_RXFIFO_TOUT_INT_CLR_S) + #define UART_SET_BRK_DET_INT_CLR(i,val) SET_PERI_REG_BITS(UART_INT_CLR_REG(i) ,UART_BRK_DET_INT_CLR_V,(val),UART_BRK_DET_INT_CLR_S) + #define UART_SET_CTS_CHG_INT_CLR(i,val) SET_PERI_REG_BITS(UART_INT_CLR_REG(i) ,UART_CTS_CHG_INT_CLR_V,(val),UART_CTS_CHG_INT_CLR_S) + #define UART_SET_DSR_CHG_INT_CLR(i,val) SET_PERI_REG_BITS(UART_INT_CLR_REG(i) ,UART_DSR_CHG_INT_CLR_V,(val),UART_DSR_CHG_INT_CLR_S) + #define UART_SET_RXFIFO_OVF_INT_CLR(i,val) SET_PERI_REG_BITS(UART_INT_CLR_REG(i) ,UART_RXFIFO_OVF_INT_CLR_V,(val),UART_RXFIFO_OVF_INT_CLR_S) + #define UART_SET_FRM_ERR_INT_CLR(i,val) SET_PERI_REG_BITS(UART_INT_CLR_REG(i) ,UART_FRM_ERR_INT_CLR_V,(val),UART_FRM_ERR_INT_CLR_S) + #define UART_SET_PARITY_ERR_INT_CLR(i,val) SET_PERI_REG_BITS(UART_INT_CLR_REG(i) ,UART_PARITY_ERR_INT_CLR_V,(val),UART_PARITY_ERR_INT_CLR_S) + #define UART_SET_TXFIFO_EMPTY_INT_CLR(i,val) SET_PERI_REG_BITS(UART_INT_CLR_REG(i) ,UART_TXFIFO_EMPTY_INT_CLR_V,(val),UART_TXFIFO_EMPTY_INT_CLR_S) + #define UART_SET_RXFIFO_FULL_INT_CLR(i,val) SET_PERI_REG_BITS(UART_INT_CLR_REG(i) ,UART_RXFIFO_FULL_INT_CLR_V,(val),UART_RXFIFO_FULL_INT_CLR_S) + + + +#define UART_CLKDIV_REG(i) (REG_UART_BASE(i) + 0x14) + /* UART_CLKDIV_FRAG : R/W ;bitpos:[23:20] ;default: 4'b0 ; */ + /*description: The decimal part of divider*/ + #define UART_CLKDIV_FRAG 0x0000000F + #define UART_CLKDIV_FRAG_M ((UART_CLKDIV_FRAG_V)<<(UART_CLKDIV_FRAG_S)) + #define UART_CLKDIV_FRAG_V 0xF + #define UART_CLKDIV_FRAG_S 20 + /* UART_CLKDIV : R/W ;bitpos:[19:0] ;default: 20'h2B6 ; */ + /*description: The interger part of divider BAUDRATE = UART_CLK_FREQ / UART_CLKDIV*/ + #define UART_CLKDIV 0x000FFFFF + #define UART_CLKDIV_M ((UART_CLKDIV_V)<<(UART_CLKDIV_S)) + #define UART_CLKDIV_V 0xFFFFF + #define UART_CLKDIV_S 0 + #define UART_GET_CLKDIV_FRAG(i) GET_PERI_REG_BITS2(UART_CLKDIV_REG(i) , UART_CLKDIV_FRAG_V, UART_CLKDIV_FRAG_S) + #define UART_SET_CLKDIV_FRAG(i,val) SET_PERI_REG_BITS(UART_CLKDIV_REG(i) ,UART_CLKDIV_FRAG_V,(val),UART_CLKDIV_FRAG_S) + #define UART_GET_CLKDIV(i) GET_PERI_REG_BITS2(UART_CLKDIV_REG(i) , UART_CLKDIV_V, UART_CLKDIV_S) + #define UART_SET_CLKDIV(i,val) SET_PERI_REG_BITS(UART_CLKDIV_REG(i) ,UART_CLKDIV_V,(val),UART_CLKDIV_S) + + + +#define UART_AUTOBAUD_REG(i) (REG_UART_BASE(i) + 0x18) + /* UART_GLITCH_FILT : R/W ;bitpos:[15:8] ;default: 8'h10 ; */ + /*description: ignore the glitch when pulse cnt is lower then this value*/ + #define UART_GLITCH_FILT 0x000000FF + #define UART_GLITCH_FILT_M ((UART_GLITCH_FILT_V)<<(UART_GLITCH_FILT_S)) + #define UART_GLITCH_FILT_V 0xFF + #define UART_GLITCH_FILT_S 8 + /* UART_AUTOBAUD_EN : R/W ;bitpos:[0] ;default: 1'b0 ; */ + /*description: Set this bit to enable baudrate detect*/ + #define UART_AUTOBAUD_EN (BIT(0)) + #define UART_AUTOBAUD_EN_M (BIT(0)) + #define UART_AUTOBAUD_EN_V 0x1 + #define UART_AUTOBAUD_EN_S 0 + #define UART_GET_GLITCH_FILT(i) GET_PERI_REG_BITS2(UART_AUTOBAUD_REG(i) , UART_GLITCH_FILT_V, UART_GLITCH_FILT_S) + #define UART_SET_GLITCH_FILT(i,val) SET_PERI_REG_BITS(UART_AUTOBAUD_REG(i) ,UART_GLITCH_FILT_V,(val),UART_GLITCH_FILT_S) + #define UART_GET_AUTOBAUD_EN(i) GET_PERI_REG_BITS2(UART_AUTOBAUD_REG(i) , UART_AUTOBAUD_EN_V, UART_AUTOBAUD_EN_S) + #define UART_SET_AUTOBAUD_EN(i,val) SET_PERI_REG_BITS(UART_AUTOBAUD_REG(i) ,UART_AUTOBAUD_EN_V,(val),UART_AUTOBAUD_EN_S) + + + +#define UART_STATUS_REG(i) (REG_UART_BASE(i) + 0x1C) + /* UART_TXD : RO ;bitpos:[31] ;default: 8'h0 ; */ + /*description: The level of the internal uart txd value*/ + #define UART_TXD (BIT(31)) + #define UART_TXD_M (BIT(31)) + #define UART_TXD_V 0x1 + #define UART_TXD_S 31 + /* UART_RTSN : RO ;bitpos:[30] ;default: 1'b0 ; */ + /*description: The level of the internal uart rts pin*/ + #define UART_RTSN (BIT(30)) + #define UART_RTSN_M (BIT(30)) + #define UART_RTSN_V 0x1 + #define UART_RTSN_S 30 + /* UART_DTRN : RO ;bitpos:[29] ;default: 1'b0 ; */ + /*description: The level of the internaluart dtr pin*/ + #define UART_DTRN (BIT(29)) + #define UART_DTRN_M (BIT(29)) + #define UART_DTRN_V 0x1 + #define UART_DTRN_S 29 + /* UART_ST_UTX_OUT : RO ;bitpos:[27:24] ;default: 4'b0 ; */ + /*description: The state for transmitting data. 4'd0:TX_IDLE*/ + #define UART_ST_UTX_OUT 0x0000000F + #define UART_ST_UTX_OUT_M ((UART_ST_UTX_OUT_V)<<(UART_ST_UTX_OUT_S)) + #define UART_ST_UTX_OUT_V 0xF + #define UART_ST_UTX_OUT_S 24 + /* UART_TXFIFO_CNT : RO ;bitpos:[23:16] ;default: 8'b0 ; */ + /*description: Number of data in UART TX fifo*/ + #define UART_TXFIFO_CNT 0x000000FF + #define UART_TXFIFO_CNT_M ((UART_TXFIFO_CNT_V)<<(UART_TXFIFO_CNT_S)) + #define UART_TXFIFO_CNT_V 0xFF + #define UART_TXFIFO_CNT_S 16 + /* UART_RXD : RO ;bitpos:[15] ;default: 1'b0 ; */ + /*description: The level of the internal uart rxd value*/ + #define UART_RXD (BIT(15)) + #define UART_RXD_M (BIT(15)) + #define UART_RXD_V 0x1 + #define UART_RXD_S 15 + /* UART_CTSN : RO ;bitpos:[14] ;default: 1'b0 ; */ + /*description: The level of the internal uart cts value*/ + #define UART_CTSN (BIT(14)) + #define UART_CTSN_M (BIT(14)) + #define UART_CTSN_V 0x1 + #define UART_CTSN_S 14 + /* UART_DSRN : RO ;bitpos:[13] ;default: 1'b0 ; */ + /*description: The level of the internal uart dsr value*/ + #define UART_DSRN (BIT(13)) + #define UART_DSRN_M (BIT(13)) + #define UART_DSRN_V 0x1 + #define UART_DSRN_S 13 + /* UART_ST_URX_OUT : RO ;bitpos:[11:8] ;default: 4'b0 ; */ + /*description: The state for receiving data. 4‘d0: RX_IDLE*/ + #define UART_ST_URX_OUT 0x0000000F + #define UART_ST_URX_OUT_M ((UART_ST_URX_OUT_V)<<(UART_ST_URX_OUT_S)) + #define UART_ST_URX_OUT_V 0xF + #define UART_ST_URX_OUT_S 8 + /* UART_RXFIFO_CNT : RO ;bitpos:[7:0] ;default: 8'b0 ; */ + /*description: Number of data in UART RX fifo*/ + #define UART_RXFIFO_CNT 0x000000FF + #define UART_RXFIFO_CNT_M ((UART_RXFIFO_CNT_V)<<(UART_RXFIFO_CNT_S)) + #define UART_RXFIFO_CNT_V 0xFF + #define UART_RXFIFO_CNT_S 0 + #define UART_GET_TXD(i) GET_PERI_REG_BITS2(UART_STATUS_REG(i) , UART_TXD_V, UART_TXD_S) + #define UART_GET_RTSN(i) GET_PERI_REG_BITS2(UART_STATUS_REG(i) , UART_RTSN_V, UART_RTSN_S) + #define UART_GET_DTRN(i) GET_PERI_REG_BITS2(UART_STATUS_REG(i) , UART_DTRN_V, UART_DTRN_S) + #define UART_GET_ST_UTX_OUT(i) GET_PERI_REG_BITS2(UART_STATUS_REG(i) , UART_ST_UTX_OUT_V, UART_ST_UTX_OUT_S) + #define UART_GET_TXFIFO_CNT(i) GET_PERI_REG_BITS2(UART_STATUS_REG(i) , UART_TXFIFO_CNT_V, UART_TXFIFO_CNT_S) + #define UART_GET_RXD(i) GET_PERI_REG_BITS2(UART_STATUS_REG(i) , UART_RXD_V, UART_RXD_S) + #define UART_GET_CTSN(i) GET_PERI_REG_BITS2(UART_STATUS_REG(i) , UART_CTSN_V, UART_CTSN_S) + #define UART_GET_DSRN(i) GET_PERI_REG_BITS2(UART_STATUS_REG(i) , UART_DSRN_V, UART_DSRN_S) + #define UART_GET_ST_URX_OUT(i) GET_PERI_REG_BITS2(UART_STATUS_REG(i) , UART_ST_URX_OUT_V, UART_ST_URX_OUT_S) + #define UART_GET_RXFIFO_CNT(i) GET_PERI_REG_BITS2(UART_STATUS_REG(i) , UART_RXFIFO_CNT_V, UART_RXFIFO_CNT_S) + + + +#define UART_CONF0_REG(i) (REG_UART_BASE(i) + 0x20) + /* UART_TICK_REF_ALWAYS_ON : R/W ;bitpos:[27] ;default: 1'b1 ; */ + /*description: 1:use apb clock:use referrence clock*/ + #define UART_TICK_REF_ALWAYS_ON (BIT(27)) + #define UART_TICK_REF_ALWAYS_ON_M (BIT(27)) + #define UART_TICK_REF_ALWAYS_ON_V 0x1 + #define UART_TICK_REF_ALWAYS_ON_S 27 + /* UART_ERR_WR_MASK : R/W ;bitpos:[26] ;default: 1'b0 ; */ + /*description: 1:rx stop storing data int rxfifo when data is error 0:if received data is wrong*/ + #define UART_ERR_WR_MASK (BIT(26)) + #define UART_ERR_WR_MASK_M (BIT(26)) + #define UART_ERR_WR_MASK_V 0x1 + #define UART_ERR_WR_MASK_S 26 + /* UART_CLK_EN : R/W ;bitpos:[25] ;default: 1'h0 ; */ + /*description: 1:force clock on for registers:support clock only when write registers*/ + #define UART_CLK_EN (BIT(25)) + #define UART_CLK_EN_M (BIT(25)) + #define UART_CLK_EN_V 0x1 + #define UART_CLK_EN_S 25 + /* UART_DTR_INV : R/W ;bitpos:[24] ;default: 1'h0 ; */ + /*description: Set this bit to inverse uart dtr level*/ + #define UART_DTR_INV (BIT(24)) + #define UART_DTR_INV_M (BIT(24)) + #define UART_DTR_INV_V 0x1 + #define UART_DTR_INV_S 24 + /* UART_RTS_INV : R/W ;bitpos:[23] ;default: 1'h0 ; */ + /*description: Set this bit to inverse uart rts level*/ + #define UART_RTS_INV (BIT(23)) + #define UART_RTS_INV_M (BIT(23)) + #define UART_RTS_INV_V 0x1 + #define UART_RTS_INV_S 23 + /* UART_TXD_INV : R/W ;bitpos:[22] ;default: 1'h0 ; */ + /*description: Set this bit to inverse uart txd level*/ + #define UART_TXD_INV (BIT(22)) + #define UART_TXD_INV_M (BIT(22)) + #define UART_TXD_INV_V 0x1 + #define UART_TXD_INV_S 22 + /* UART_DSR_INV : R/W ;bitpos:[21] ;default: 1'h0 ; */ + /*description: Set this bit to inverse uart dsr level*/ + #define UART_DSR_INV (BIT(21)) + #define UART_DSR_INV_M (BIT(21)) + #define UART_DSR_INV_V 0x1 + #define UART_DSR_INV_S 21 + /* UART_CTS_INV : R/W ;bitpos:[20] ;default: 1'h0 ; */ + /*description: Set this bit to inverse uart cts level*/ + #define UART_CTS_INV (BIT(20)) + #define UART_CTS_INV_M (BIT(20)) + #define UART_CTS_INV_V 0x1 + #define UART_CTS_INV_S 20 + /* UART_RXD_INV : R/W ;bitpos:[19] ;default: 1'h0 ; */ + /*description: Set this bit to inverse uart rxd level*/ + #define UART_RXD_INV (BIT(19)) + #define UART_RXD_INV_M (BIT(19)) + #define UART_RXD_INV_V 0x1 + #define UART_RXD_INV_S 19 + /* UART_TXFIFO_RST : R/W ;bitpos:[18] ;default: 1'h0 ; */ + /*description: Set this bit to reset uart tx fifo*/ + #define UART_TXFIFO_RST (BIT(18)) + #define UART_TXFIFO_RST_M (BIT(18)) + #define UART_TXFIFO_RST_V 0x1 + #define UART_TXFIFO_RST_S 18 + /* UART_RXFIFO_RST : R/W ;bitpos:[17] ;default: 1'h0 ; */ + /*description: Set this bit to reset uart rx fifo*/ + #define UART_RXFIFO_RST (BIT(17)) + #define UART_RXFIFO_RST_M (BIT(17)) + #define UART_RXFIFO_RST_V 0x1 + #define UART_RXFIFO_RST_S 17 + /* UART_IRDA_EN : R/W ;bitpos:[16] ;default: 1'h0 ; */ + /*description: Set this bit to enable irda protocol*/ + #define UART_IRDA_EN (BIT(16)) + #define UART_IRDA_EN_M (BIT(16)) + #define UART_IRDA_EN_V 0x1 + #define UART_IRDA_EN_S 16 + /* UART_TX_FLOW_EN : R/W ;bitpos:[15] ;default: 1'b0 ; */ + /*description: Set this bit to enable tx flow control*/ + #define UART_TX_FLOW_EN (BIT(15)) + #define UART_TX_FLOW_EN_M (BIT(15)) + #define UART_TX_FLOW_EN_V 0x1 + #define UART_TX_FLOW_EN_S 15 + /* UART_LOOPBACK : R/W ;bitpos:[14] ;default: 1'b0 ; */ + /*description: Set this bit to enable uart loopback test mode*/ + #define UART_LOOPBACK (BIT(14)) + #define UART_LOOPBACK_M (BIT(14)) + #define UART_LOOPBACK_V 0x1 + #define UART_LOOPBACK_S 14 + /* UART_IRDA_RX_INV : R/W ;bitpos:[13] ;default: 1'b0 ; */ + /*description: Set this bit to inverse irda rx level*/ + #define UART_IRDA_RX_INV (BIT(13)) + #define UART_IRDA_RX_INV_M (BIT(13)) + #define UART_IRDA_RX_INV_V 0x1 + #define UART_IRDA_RX_INV_S 13 + /* UART_IRDA_TX_INV : R/W ;bitpos:[12] ;default: 1'b0 ; */ + /*description: Set this bit to inverse irda tx level*/ + #define UART_IRDA_TX_INV (BIT(12)) + #define UART_IRDA_TX_INV_M (BIT(12)) + #define UART_IRDA_TX_INV_V 0x1 + #define UART_IRDA_TX_INV_S 12 + /* UART_IRDA_WCTL : R/W ;bitpos:[11] ;default: 1'b0 ; */ + /*description: 1:the tx 11th bit is the same to the 10th bit 0:set tx 11th bit to 0*/ + #define UART_IRDA_WCTL (BIT(11)) + #define UART_IRDA_WCTL_M (BIT(11)) + #define UART_IRDA_WCTL_V 0x1 + #define UART_IRDA_WCTL_S 11 + /* UART_IRDA_TX_EN : R/W ;bitpos:[10] ;default: 1'b0 ; */ + /*description: Set this bit to enable irda to send data*/ + #define UART_IRDA_TX_EN (BIT(10)) + #define UART_IRDA_TX_EN_M (BIT(10)) + #define UART_IRDA_TX_EN_V 0x1 + #define UART_IRDA_TX_EN_S 10 + /* UART_IRDA_DPLX : R/W ;bitpos:[9] ;default: 1'b0 ; */ + /*description: Set this bit to enable irda duplex mode*/ + #define UART_IRDA_DPLX (BIT(9)) + #define UART_IRDA_DPLX_M (BIT(9)) + #define UART_IRDA_DPLX_V 0x1 + #define UART_IRDA_DPLX_S 9 + /* UART_TXD_BRK : R/W ;bitpos:[8] ;default: 1'b0 ; */ + /*description: Set this bit to enbale tx send 0*/ + #define UART_TXD_BRK (BIT(8)) + #define UART_TXD_BRK_M (BIT(8)) + #define UART_TXD_BRK_V 0x1 + #define UART_TXD_BRK_S 8 + /* UART_SW_DTR : R/W ;bitpos:[7] ;default: 1'b0 ; */ + /*description: sw dtr*/ + #define UART_SW_DTR (BIT(7)) + #define UART_SW_DTR_M (BIT(7)) + #define UART_SW_DTR_V 0x1 + #define UART_SW_DTR_S 7 + /* UART_SW_RTS : R/W ;bitpos:[6] ;default: 1'b0 ; */ + /*description: sw rts*/ + #define UART_SW_RTS (BIT(6)) + #define UART_SW_RTS_M (BIT(6)) + #define UART_SW_RTS_V 0x1 + #define UART_SW_RTS_S 6 + /* UART_STOP_BIT_NUM : R/W ;bitpos:[5:4] ;default: 2'd1 ; */ + /*description: Set stop bit: 1:1bit 2:1.5bits 3:2bits*/ + #define UART_STOP_BIT_NUM 0x00000003 + #define UART_STOP_BIT_NUM_M ((UART_STOP_BIT_NUM_V)<<(UART_STOP_BIT_NUM_S)) + #define UART_STOP_BIT_NUM_V 0x3 + #define UART_STOP_BIT_NUM_S 4 + /* UART_BIT_NUM : R/W ;bitpos:[3:2] ;default: 2'd3 ; */ + /*description: Set bit num: 0:5bits 1:6bits 2:7bits 3:8bits*/ + #define UART_BIT_NUM 0x00000003 + #define UART_BIT_NUM_M ((UART_BIT_NUM_V)<<(UART_BIT_NUM_S)) + #define UART_BIT_NUM_V 0x3 + #define UART_BIT_NUM_S 2 + /* UART_PARITY_EN : R/W ;bitpos:[1] ;default: 1'b0 ; */ + /*description: Set this bit to enable uart parity check*/ + #define UART_PARITY_EN (BIT(1)) + #define UART_PARITY_EN_M (BIT(1)) + #define UART_PARITY_EN_V 0x1 + #define UART_PARITY_EN_S 1 + /* UART_PARITY : R/W ;bitpos:[0] ;default: 1'b0 ; */ + /*description: Set parity check: 0:even 1:odd*/ + #define UART_PARITY (BIT(0)) + #define UART_PARITY_M (BIT(0)) + #define UART_PARITY_V 0x1 + #define UART_PARITY_S 0 + #define UART_GET_TICK_REF_ALWAYS_ON(i) GET_PERI_REG_BITS2(UART_CONF0_REG(i) , UART_TICK_REF_ALWAYS_ON_V, UART_TICK_REF_ALWAYS_ON_S) + #define UART_SET_TICK_REF_ALWAYS_ON(i,val) SET_PERI_REG_BITS(UART_CONF0_REG(i) ,UART_TICK_REF_ALWAYS_ON_V,(val),UART_TICK_REF_ALWAYS_ON_S) + #define UART_GET_ERR_WR_MASK(i) GET_PERI_REG_BITS2(UART_CONF0_REG(i) , UART_ERR_WR_MASK_V, UART_ERR_WR_MASK_S) + #define UART_SET_ERR_WR_MASK(i,val) SET_PERI_REG_BITS(UART_CONF0_REG(i) ,UART_ERR_WR_MASK_V,(val),UART_ERR_WR_MASK_S) + #define UART_GET_REG_CLK_EN(i) GET_PERI_REG_BITS2(UART_CONF0_REG(i) , UART_CLK_EN_V, UART_CLK_EN_S) + #define UART_SET_REG_CLK_EN(i,val) SET_PERI_REG_BITS(UART_CONF0_REG(i) ,UART_CLK_EN_V,(val),UART_CLK_EN_S) + #define UART_GET_DTR_INV(i) GET_PERI_REG_BITS2(UART_CONF0_REG(i) , UART_DTR_INV_V, UART_DTR_INV_S) + #define UART_SET_DTR_INV(i,val) SET_PERI_REG_BITS(UART_CONF0_REG(i) ,UART_DTR_INV_V,(val),UART_DTR_INV_S) + #define UART_GET_RTS_INV(i) GET_PERI_REG_BITS2(UART_CONF0_REG(i) , UART_RTS_INV_V, UART_RTS_INV_S) + #define UART_SET_RTS_INV(i,val) SET_PERI_REG_BITS(UART_CONF0_REG(i) ,UART_RTS_INV_V,(val),UART_RTS_INV_S) + #define UART_GET_TXD_INV(i) GET_PERI_REG_BITS2(UART_CONF0_REG(i) , UART_TXD_INV_V, UART_TXD_INV_S) + #define UART_SET_TXD_INV(i,val) SET_PERI_REG_BITS(UART_CONF0_REG(i) ,UART_TXD_INV_V,(val),UART_TXD_INV_S) + #define UART_GET_DSR_INV(i) GET_PERI_REG_BITS2(UART_CONF0_REG(i) , UART_DSR_INV_V, UART_DSR_INV_S) + #define UART_SET_DSR_INV(i,val) SET_PERI_REG_BITS(UART_CONF0_REG(i) ,UART_DSR_INV_V,(val),UART_DSR_INV_S) + #define UART_GET_CTS_INV(i) GET_PERI_REG_BITS2(UART_CONF0_REG(i) , UART_CTS_INV_V, UART_CTS_INV_S) + #define UART_SET_CTS_INV(i,val) SET_PERI_REG_BITS(UART_CONF0_REG(i) ,UART_CTS_INV_V,(val),UART_CTS_INV_S) + #define UART_GET_RXD_INV(i) GET_PERI_REG_BITS2(UART_CONF0_REG(i) , UART_RXD_INV_V, UART_RXD_INV_S) + #define UART_SET_RXD_INV(i,val) SET_PERI_REG_BITS(UART_CONF0_REG(i) ,UART_RXD_INV_V,(val),UART_RXD_INV_S) + #define UART_GET_TXFIFO_RST(i) GET_PERI_REG_BITS2(UART_CONF0_REG(i) , UART_TXFIFO_RST_V, UART_TXFIFO_RST_S) + #define UART_SET_TXFIFO_RST(i,val) SET_PERI_REG_BITS(UART_CONF0_REG(i) ,UART_TXFIFO_RST_V,(val),UART_TXFIFO_RST_S) + #define UART_GET_RXFIFO_RST(i) GET_PERI_REG_BITS2(UART_CONF0_REG(i) , UART_RXFIFO_RST_V, UART_RXFIFO_RST_S) + #define UART_SET_RXFIFO_RST(i,val) SET_PERI_REG_BITS(UART_CONF0_REG(i) ,UART_RXFIFO_RST_V,(val),UART_RXFIFO_RST_S) + #define UART_GET_IRDA_EN(i) GET_PERI_REG_BITS2(UART_CONF0_REG(i) , UART_IRDA_EN_V, UART_IRDA_EN_S) + #define UART_SET_IRDA_EN(i,val) SET_PERI_REG_BITS(UART_CONF0_REG(i) ,UART_IRDA_EN_V,(val),UART_IRDA_EN_S) + #define UART_GET_TX_FLOW_EN(i) GET_PERI_REG_BITS2(UART_CONF0_REG(i) , UART_TX_FLOW_EN_V, UART_TX_FLOW_EN_S) + #define UART_SET_TX_FLOW_EN(i,val) SET_PERI_REG_BITS(UART_CONF0_REG(i) ,UART_TX_FLOW_EN_V,(val),UART_TX_FLOW_EN_S) + #define UART_GET_LOOPBACK(i) GET_PERI_REG_BITS2(UART_CONF0_REG(i) , UART_LOOPBACK_V, UART_LOOPBACK_S) + #define UART_SET_LOOPBACK(i,val) SET_PERI_REG_BITS(UART_CONF0_REG(i) ,UART_LOOPBACK_V,(val),UART_LOOPBACK_S) + #define UART_GET_IRDA_RX_INV(i) GET_PERI_REG_BITS2(UART_CONF0_REG(i) , UART_IRDA_RX_INV_V, UART_IRDA_RX_INV_S) + #define UART_SET_IRDA_RX_INV(i,val) SET_PERI_REG_BITS(UART_CONF0_REG(i) ,UART_IRDA_RX_INV_V,(val),UART_IRDA_RX_INV_S) + #define UART_GET_IRDA_TX_INV(i) GET_PERI_REG_BITS2(UART_CONF0_REG(i) , UART_IRDA_TX_INV_V, UART_IRDA_TX_INV_S) + #define UART_SET_IRDA_TX_INV(i,val) SET_PERI_REG_BITS(UART_CONF0_REG(i) ,UART_IRDA_TX_INV_V,(val),UART_IRDA_TX_INV_S) + #define UART_GET_IRDA_WCTL(i) GET_PERI_REG_BITS2(UART_CONF0_REG(i) , UART_IRDA_WCTL_V, UART_IRDA_WCTL_S) + #define UART_SET_IRDA_WCTL(i,val) SET_PERI_REG_BITS(UART_CONF0_REG(i) ,UART_IRDA_WCTL_V,(val),UART_IRDA_WCTL_S) + #define UART_GET_IRDA_TX_EN(i) GET_PERI_REG_BITS2(UART_CONF0_REG(i) , UART_IRDA_TX_EN_V, UART_IRDA_TX_EN_S) + #define UART_SET_IRDA_TX_EN(i,val) SET_PERI_REG_BITS(UART_CONF0_REG(i) ,UART_IRDA_TX_EN_V,(val),UART_IRDA_TX_EN_S) + #define UART_GET_IRDA_DPLX(i) GET_PERI_REG_BITS2(UART_CONF0_REG(i) , UART_IRDA_DPLX_V, UART_IRDA_DPLX_S) + #define UART_SET_IRDA_DPLX(i,val) SET_PERI_REG_BITS(UART_CONF0_REG(i) ,UART_IRDA_DPLX_V,(val),UART_IRDA_DPLX_S) + #define UART_GET_TXD_BRK(i) GET_PERI_REG_BITS2(UART_CONF0_REG(i) , UART_TXD_BRK_V, UART_TXD_BRK_S) + #define UART_SET_TXD_BRK(i,val) SET_PERI_REG_BITS(UART_CONF0_REG(i) ,UART_TXD_BRK_V,(val),UART_TXD_BRK_S) + #define UART_GET_SW_DTR(i) GET_PERI_REG_BITS2(UART_CONF0_REG(i) , UART_SW_DTR_V, UART_SW_DTR_S) + #define UART_SET_SW_DTR(i,val) SET_PERI_REG_BITS(UART_CONF0_REG(i) ,UART_SW_DTR_V,(val),UART_SW_DTR_S) + #define UART_GET_SW_RTS(i) GET_PERI_REG_BITS2(UART_CONF0_REG(i) , UART_SW_RTS_V, UART_SW_RTS_S) + #define UART_SET_SW_RTS(i,val) SET_PERI_REG_BITS(UART_CONF0_REG(i) ,UART_SW_RTS_V,(val),UART_SW_RTS_S) + #define UART_GET_STOP_BIT_NUM(i) GET_PERI_REG_BITS2(UART_CONF0_REG(i) , UART_STOP_BIT_NUM_V, UART_STOP_BIT_NUM_S) + #define UART_SET_STOP_BIT_NUM(i,val) SET_PERI_REG_BITS(UART_CONF0_REG(i) ,UART_STOP_BIT_NUM_V,(val),UART_STOP_BIT_NUM_S) + #define UART_GET_BIT_NUM(i) GET_PERI_REG_BITS2(UART_CONF0_REG(i) , UART_BIT_NUM_V, UART_BIT_NUM_S) + #define UART_SET_BIT_NUM(i,val) SET_PERI_REG_BITS(UART_CONF0_REG(i) ,UART_BIT_NUM_V,(val),UART_BIT_NUM_S) + #define UART_GET_PARITY_EN(i) GET_PERI_REG_BITS2(UART_CONF0_REG(i) , UART_PARITY_EN_V, UART_PARITY_EN_S) + #define UART_SET_PARITY_EN(i,val) SET_PERI_REG_BITS(UART_CONF0_REG(i) ,UART_PARITY_EN_V,(val),UART_PARITY_EN_S) + #define UART_GET_PARITY(i) GET_PERI_REG_BITS2(UART_CONF0_REG(i) , UART_PARITY_V, UART_PARITY_S) + #define UART_SET_PARITY(i,val) SET_PERI_REG_BITS(UART_CONF0_REG(i) ,UART_PARITY_V,(val),UART_PARITY_S) + + + +#define UART_CONF1_REG(i) (REG_UART_BASE(i) + 0x24) + /* UART_RX_TOUT_EN : R/W ;bitpos:[31] ;default: 1'b0 ; */ + /*description: Set this bit to enable rx time-out function*/ + #define UART_RX_TOUT_EN (BIT(31)) + #define UART_RX_TOUT_EN_M (BIT(31)) + #define UART_RX_TOUT_EN_V 0x1 + #define UART_RX_TOUT_EN_S 31 + /* UART_RX_TOUT_THRHD : R/W ;bitpos:[30:24] ;default: 7'b0 ; */ + /*description: Config bits for rx time-out threshold*/ + #define UART_RX_TOUT_THRHD 0x0000007F + #define UART_RX_TOUT_THRHD_M ((UART_RX_TOUT_THRHD_V)<<(UART_RX_TOUT_THRHD_S)) + #define UART_RX_TOUT_THRHD_V 0x7F + #define UART_RX_TOUT_THRHD_S 24 + /* UART_RX_FLOW_EN : R/W ;bitpos:[23] ;default: 1'b0 ; */ + /*description: Set this bit to enable rx hardware flow control*/ + #define UART_RX_FLOW_EN (BIT(23)) + #define UART_RX_FLOW_EN_M (BIT(23)) + #define UART_RX_FLOW_EN_V 0x1 + #define UART_RX_FLOW_EN_S 23 + /* UART_RX_FLOW_THRHD : R/W ;bitpos:[22:16] ;default: 7'h0 ; */ + /*description: The config bits for rx flow control threshold*/ + #define UART_RX_FLOW_THRHD 0x0000007F + #define UART_RX_FLOW_THRHD_M ((UART_RX_FLOW_THRHD_V)<<(UART_RX_FLOW_THRHD_S)) + #define UART_RX_FLOW_THRHD_V 0x7F + #define UART_RX_FLOW_THRHD_S 16 + /* UART_TXFIFO_EMPTY_THRHD : R/W ;bitpos:[14:8] ;default: 7'h60 ; */ + /*description: The config bits for tx fifo empty threshold*/ + #define UART_TXFIFO_EMPTY_THRHD 0x0000007F + #define UART_TXFIFO_EMPTY_THRHD_M ((UART_TXFIFO_EMPTY_THRHD_V)<<(UART_TXFIFO_EMPTY_THRHD_S)) + #define UART_TXFIFO_EMPTY_THRHD_V 0x7F + #define UART_TXFIFO_EMPTY_THRHD_S 8 + /* UART_RXFIFO_FULL_THRHD : R/W ;bitpos:[6:0] ;default: 7'h60 ; */ + /*description: The config bits for rx fifo full threshold*/ + #define UART_RXFIFO_FULL_THRHD 0x0000007F + #define UART_RXFIFO_FULL_THRHD_M ((UART_RXFIFO_FULL_THRHD_V)<<(UART_RXFIFO_FULL_THRHD_S)) + #define UART_RXFIFO_FULL_THRHD_V 0x7F + #define UART_RXFIFO_FULL_THRHD_S 0 + #define UART_GET_RX_TOUT_EN(i) GET_PERI_REG_BITS2(UART_CONF1_REG(i) , UART_RX_TOUT_EN_V, UART_RX_TOUT_EN_S) + #define UART_SET_RX_TOUT_EN(i,val) SET_PERI_REG_BITS(UART_CONF1_REG(i) ,UART_RX_TOUT_EN_V,(val),UART_RX_TOUT_EN_S) + #define UART_GET_RX_TOUT_THRHD(i) GET_PERI_REG_BITS2(UART_CONF1_REG(i) , UART_RX_TOUT_THRHD_V, UART_RX_TOUT_THRHD_S) + #define UART_SET_RX_TOUT_THRHD(i,val) SET_PERI_REG_BITS(UART_CONF1_REG(i) ,UART_RX_TOUT_THRHD_V,(val),UART_RX_TOUT_THRHD_S) + #define UART_GET_RX_FLOW_EN(i) GET_PERI_REG_BITS2(UART_CONF1_REG(i) , UART_RX_FLOW_EN_V, UART_RX_FLOW_EN_S) + #define UART_SET_RX_FLOW_EN(i,val) SET_PERI_REG_BITS(UART_CONF1_REG(i) ,UART_RX_FLOW_EN_V,(val),UART_RX_FLOW_EN_S) + #define UART_GET_RX_FLOW_THRHD(i) GET_PERI_REG_BITS2(UART_CONF1_REG(i) , UART_RX_FLOW_THRHD_V, UART_RX_FLOW_THRHD_S) + #define UART_SET_RX_FLOW_THRHD(i,val) SET_PERI_REG_BITS(UART_CONF1_REG(i) ,UART_RX_FLOW_THRHD_V,(val),UART_RX_FLOW_THRHD_S) + #define UART_GET_TXFIFO_EMPTY_THRHD(i) GET_PERI_REG_BITS2(UART_CONF1_REG(i) , UART_TXFIFO_EMPTY_THRHD_V, UART_TXFIFO_EMPTY_THRHD_S) + #define UART_SET_TXFIFO_EMPTY_THRHD(i,val) SET_PERI_REG_BITS(UART_CONF1_REG(i) ,UART_TXFIFO_EMPTY_THRHD_V,(val),UART_TXFIFO_EMPTY_THRHD_S) + #define UART_GET_RXFIFO_FULL_THRHD(i) GET_PERI_REG_BITS2(UART_CONF1_REG(i) , UART_RXFIFO_FULL_THRHD_V, UART_RXFIFO_FULL_THRHD_S) + #define UART_SET_RXFIFO_FULL_THRHD(i,val) SET_PERI_REG_BITS(UART_CONF1_REG(i) ,UART_RXFIFO_FULL_THRHD_V,(val),UART_RXFIFO_FULL_THRHD_S) + + + +#define UART_LOWPULSE_REG(i) (REG_UART_BASE(i) + 0x28) + /* UART_LOWPULSE_MIN_CNT : RO ;bitpos:[19:0] ;default: 20'hFFFFF ; */ + /*description: used in baudrate detect*/ + #define UART_LOWPULSE_MIN_CNT 0x000FFFFF + #define UART_LOWPULSE_MIN_CNT_M ((UART_LOWPULSE_MIN_CNT_V)<<(UART_LOWPULSE_MIN_CNT_S)) + #define UART_LOWPULSE_MIN_CNT_V 0xFFFFF + #define UART_LOWPULSE_MIN_CNT_S 0 + #define UART_GET_LOWPULSE_MIN_CNT(i) GET_PERI_REG_BITS2(UART_LOWPULSE_REG(i) , UART_LOWPULSE_MIN_CNT_V, UART_LOWPULSE_MIN_CNT_S) + + + +#define UART_HIGHPULSE_REG(i) (REG_UART_BASE(i) + 0x2C) + /* UART_HIGHPULSE_MIN_CNT : RO ;bitpos:[19:0] ;default: 20'hFFFFF ; */ + /*description: used in baudrate detect*/ + #define UART_HIGHPULSE_MIN_CNT 0x000FFFFF + #define UART_HIGHPULSE_MIN_CNT_M ((UART_HIGHPULSE_MIN_CNT_V)<<(UART_HIGHPULSE_MIN_CNT_S)) + #define UART_HIGHPULSE_MIN_CNT_V 0xFFFFF + #define UART_HIGHPULSE_MIN_CNT_S 0 + #define UART_GET_HIGHPULSE_MIN_CNT(i) GET_PERI_REG_BITS2(UART_HIGHPULSE_REG(i) , UART_HIGHPULSE_MIN_CNT_V, UART_HIGHPULSE_MIN_CNT_S) + + + +#define UART_RXD_CNT_REG(i) (REG_UART_BASE(i) + 0x30) + /* UART_RXD_EDGE_CNT : RO ;bitpos:[9:0] ;default: 10'h0 ; */ + /*description: used in baudrate detect*/ + #define UART_RXD_EDGE_CNT 0x000003FF + #define UART_RXD_EDGE_CNT_M ((UART_RXD_EDGE_CNT_V)<<(UART_RXD_EDGE_CNT_S)) + #define UART_RXD_EDGE_CNT_V 0x3FF + #define UART_RXD_EDGE_CNT_S 0 + #define UART_GET_RXD_EDGE_CNT(i) GET_PERI_REG_BITS2(UART_RXD_CNT_REG(i) , UART_RXD_EDGE_CNT_V, UART_RXD_EDGE_CNT_S) + + + +#define UART_FLOW_CONF_REG(i) (REG_UART_BASE(i) + 0x34) + /* UART_SEND_XOFF : R/W ;bitpos:[5] ;default: 1'b0 ; */ + /*description: */ + #define UART_SEND_XOFF (BIT(5)) + #define UART_SEND_XOFF_M (BIT(5)) + #define UART_SEND_XOFF_V 0x1 + #define UART_SEND_XOFF_S 5 + /* UART_SEND_XON : R/W ;bitpos:[4] ;default: 1'b0 ; */ + /*description: */ + #define UART_SEND_XON (BIT(4)) + #define UART_SEND_XON_M (BIT(4)) + #define UART_SEND_XON_V 0x1 + #define UART_SEND_XON_S 4 + /* UART_FORCE_XOFF : R/W ;bitpos:[3] ;default: 1'b0 ; */ + /*description: Set this bit to set ctsn*/ + #define UART_FORCE_XOFF (BIT(3)) + #define UART_FORCE_XOFF_M (BIT(3)) + #define UART_FORCE_XOFF_V 0x1 + #define UART_FORCE_XOFF_S 3 + /* UART_FORCE_XON : R/W ;bitpos:[2] ;default: 1'b0 ; */ + /*description: Set this bit to clear ctsn*/ + #define UART_FORCE_XON (BIT(2)) + #define UART_FORCE_XON_M (BIT(2)) + #define UART_FORCE_XON_V 0x1 + #define UART_FORCE_XON_S 2 + /* UART_XONOFF_DEL : R/W ;bitpos:[1] ;default: 1'b0 ; */ + /*description: Set this bit to remove flow control char from rx data*/ + #define UART_XONOFF_DEL (BIT(1)) + #define UART_XONOFF_DEL_M (BIT(1)) + #define UART_XONOFF_DEL_V 0x1 + #define UART_XONOFF_DEL_S 1 + /* UART_SW_FLOW_CON_EN : R/W ;bitpos:[0] ;default: 1'b0 ; */ + /*description: Set this bit to enable sw flow control*/ + #define UART_SW_FLOW_CON_EN (BIT(0)) + #define UART_SW_FLOW_CON_EN_M (BIT(0)) + #define UART_SW_FLOW_CON_EN_V 0x1 + #define UART_SW_FLOW_CON_EN_S 0 + #define UART_GET_SEND_XOFF(i) GET_PERI_REG_BITS2(UART_FLOW_CONF_REG(i) , UART_SEND_XOFF_V, UART_SEND_XOFF_S) + #define UART_SET_SEND_XOFF(i,val) SET_PERI_REG_BITS(UART_FLOW_CONF_REG(i) ,UART_SEND_XOFF_V,(val),UART_SEND_XOFF_S) + #define UART_GET_SEND_XON(i) GET_PERI_REG_BITS2(UART_FLOW_CONF_REG(i) , UART_SEND_XON_V, UART_SEND_XON_S) + #define UART_SET_SEND_XON(i,val) SET_PERI_REG_BITS(UART_FLOW_CONF_REG(i) ,UART_SEND_XON_V,(val),UART_SEND_XON_S) + #define UART_GET_FORCE_XOFF(i) GET_PERI_REG_BITS2(UART_FLOW_CONF_REG(i) , UART_FORCE_XOFF_V, UART_FORCE_XOFF_S) + #define UART_SET_FORCE_XOFF(i,val) SET_PERI_REG_BITS(UART_FLOW_CONF_REG(i) ,UART_FORCE_XOFF_V,(val),UART_FORCE_XOFF_S) + #define UART_GET_FORCE_XON(i) GET_PERI_REG_BITS2(UART_FLOW_CONF_REG(i) , UART_FORCE_XON_V, UART_FORCE_XON_S) + #define UART_SET_FORCE_XON(i,val) SET_PERI_REG_BITS(UART_FLOW_CONF_REG(i) ,UART_FORCE_XON_V,(val),UART_FORCE_XON_S) + #define UART_GET_XONOFF_DEL(i) GET_PERI_REG_BITS2(UART_FLOW_CONF_REG(i) , UART_XONOFF_DEL_V, UART_XONOFF_DEL_S) + #define UART_SET_XONOFF_DEL(i,val) SET_PERI_REG_BITS(UART_FLOW_CONF_REG(i) ,UART_XONOFF_DEL_V,(val),UART_XONOFF_DEL_S) + #define UART_GET_SW_FLOW_CON_EN(i) GET_PERI_REG_BITS2(UART_FLOW_CONF_REG(i) , UART_SW_FLOW_CON_EN_V, UART_SW_FLOW_CON_EN_S) + #define UART_SET_SW_FLOW_CON_EN(i,val) SET_PERI_REG_BITS(UART_FLOW_CONF_REG(i) ,UART_SW_FLOW_CON_EN_V,(val),UART_SW_FLOW_CON_EN_S) + + + +#define UART_SLEEP_CONF_REG(i) (REG_UART_BASE(i) + 0x38) + /* UART_ACTIVE_THRESHOLD : R/W ;bitpos:[9:0] ;default: 10'hf0 ; */ + /*description: when the num of rx level change is more than this value*/ + #define UART_ACTIVE_THRESHOLD 0x000003FF + #define UART_ACTIVE_THRESHOLD_M ((UART_ACTIVE_THRESHOLD_V)<<(UART_ACTIVE_THRESHOLD_S)) + #define UART_ACTIVE_THRESHOLD_V 0x3FF + #define UART_ACTIVE_THRESHOLD_S 0 + #define UART_GET_ACTIVE_THRESHOLD(i) GET_PERI_REG_BITS2(UART_SLEEP_CONF_REG(i) , UART_ACTIVE_THRESHOLD_V, UART_ACTIVE_THRESHOLD_S) + #define UART_SET_ACTIVE_THRESHOLD(i,val) SET_PERI_REG_BITS(UART_SLEEP_CONF_REG(i) ,UART_ACTIVE_THRESHOLD_V,(val),UART_ACTIVE_THRESHOLD_S) + + + +#define UART_SWFC_CONF_REG(i) (REG_UART_BASE(i) + 0x3C) + /* UART_XOFF_CHAR : R/W ;bitpos:[31:24] ;default: 8'h13 ; */ + /*description: xoff char*/ + #define UART_XOFF_CHAR 0x000000FF + #define UART_XOFF_CHAR_M ((UART_XOFF_CHAR_V)<<(UART_XOFF_CHAR_S)) + #define UART_XOFF_CHAR_V 0xFF + #define UART_XOFF_CHAR_S 24 + /* UART_XON_CHAR : R/W ;bitpos:[23:16] ;default: 8'h11 ; */ + /*description: xon char*/ + #define UART_XON_CHAR 0x000000FF + #define UART_XON_CHAR_M ((UART_XON_CHAR_V)<<(UART_XON_CHAR_S)) + #define UART_XON_CHAR_V 0xFF + #define UART_XON_CHAR_S 16 + /* UART_XOFF_THRESHOLD : R/W ;bitpos:[15:8] ;default: 8'he0 ; */ + /*description: rx stop receiving data when rxfifo_cnt is more than this value*/ + #define UART_XOFF_THRESHOLD 0x000000FF + #define UART_XOFF_THRESHOLD_M ((UART_XOFF_THRESHOLD_V)<<(UART_XOFF_THRESHOLD_S)) + #define UART_XOFF_THRESHOLD_V 0xFF + #define UART_XOFF_THRESHOLD_S 8 + /* UART_XON_THRESHOLD : R/W ;bitpos:[7:0] ;default: 8'h0 ; */ + /*description: rx continue receiving data when rxfifo cnt is less then this value*/ + #define UART_XON_THRESHOLD 0x000000FF + #define UART_XON_THRESHOLD_M ((UART_XON_THRESHOLD_V)<<(UART_XON_THRESHOLD_S)) + #define UART_XON_THRESHOLD_V 0xFF + #define UART_XON_THRESHOLD_S 0 + #define UART_GET_XOFF_CH(i) GET_PERI_REG_BITS2(UART_SWFC_CONF_REG(i) , UART_XOFF_CHAR_V, UART_XOFF_CHAR_S) + #define UART_SET_XOFF_CH(i,val) SET_PERI_REG_BITS(UART_SWFC_CONF_REG(i) ,UART_XOFF_CHAR_V,(val),UART_XOFF_CHAR_S) + #define UART_GET_XON_CH(i) GET_PERI_REG_BITS2(UART_SWFC_CONF_REG(i) , UART_XON_CHAR_V, UART_XON_CHAR_S) + #define UART_SET_XON_CH(i,val) SET_PERI_REG_BITS(UART_SWFC_CONF_REG(i) ,UART_XON_CHAR_V,(val),UART_XON_CHAR_S) + #define UART_GET_XOFF_THRESHOLD(i) GET_PERI_REG_BITS2(UART_SWFC_CONF_REG(i) , UART_XOFF_THRESHOLD_V, UART_XOFF_THRESHOLD_S) + #define UART_SET_XOFF_THRESHOLD(i,val) SET_PERI_REG_BITS(UART_SWFC_CONF_REG(i) ,UART_XOFF_THRESHOLD_V,(val),UART_XOFF_THRESHOLD_S) + #define UART_GET_XON_THRESHOLD(i) GET_PERI_REG_BITS2(UART_SWFC_CONF_REG(i) , UART_XON_THRESHOLD_V, UART_XON_THRESHOLD_S) + #define UART_SET_XON_THRESHOLD(i,val) SET_PERI_REG_BITS(UART_SWFC_CONF_REG(i) ,UART_XON_THRESHOLD_V,(val),UART_XON_THRESHOLD_S) + + + +#define UART_IDLE_CONF_REG(i) (REG_UART_BASE(i) + 0x40) + /* UART_TX_BRK_NUM : R/W ;bitpos:[27:20] ;default: 8'ha ; */ + /*description: brk number config*/ + #define UART_TX_BRK_NUM 0x000000FF + #define UART_TX_BRK_NUM_M ((UART_TX_BRK_NUM_V)<<(UART_TX_BRK_NUM_S)) + #define UART_TX_BRK_NUM_V 0xFF + #define UART_TX_BRK_NUM_S 20 + /* UART_TX_IDLE_NUM : R/W ;bitpos:[19:10] ;default: 10'h100 ; */ + /*description: idle number config*/ + #define UART_TX_IDLE_NUM 0x000003FF + #define UART_TX_IDLE_NUM_M ((UART_TX_IDLE_NUM_V)<<(UART_TX_IDLE_NUM_S)) + #define UART_TX_IDLE_NUM_V 0x3FF + #define UART_TX_IDLE_NUM_S 10 + /* UART_RX_IDLE_THRHD : R/W ;bitpos:[9:0] ;default: 10'h100 ; */ + /*description: rx idle number config*/ + #define UART_RX_IDLE_THRHD 0x000003FF + #define UART_RX_IDLE_THRHD_M ((UART_RX_IDLE_THRHD_V)<<(UART_RX_IDLE_THRHD_S)) + #define UART_RX_IDLE_THRHD_V 0x3FF + #define UART_RX_IDLE_THRHD_S 0 + #define UART_GET_TX_BRK_NUM(i) GET_PERI_REG_BITS2(UART_IDLE_CONF_REG(i) , UART_TX_BRK_NUM_V, UART_TX_BRK_NUM_S) + #define UART_SET_TX_BRK_NUM(i,val) SET_PERI_REG_BITS(UART_IDLE_CONF_REG(i) ,UART_TX_BRK_NUM_V,(val),UART_TX_BRK_NUM_S) + #define UART_GET_TX_IDLE_NUM(i) GET_PERI_REG_BITS2(UART_IDLE_CONF_REG(i) , UART_TX_IDLE_NUM_V, UART_TX_IDLE_NUM_S) + #define UART_SET_TX_IDLE_NUM(i,val) SET_PERI_REG_BITS(UART_IDLE_CONF_REG(i) ,UART_TX_IDLE_NUM_V,(val),UART_TX_IDLE_NUM_S) + #define UART_GET_RX_IDLE_THRHD(i) GET_PERI_REG_BITS2(UART_IDLE_CONF_REG(i) , UART_RX_IDLE_THRHD_V, UART_RX_IDLE_THRHD_S) + #define UART_SET_RX_IDLE_THRHD(i,val) SET_PERI_REG_BITS(UART_IDLE_CONF_REG(i) ,UART_RX_IDLE_THRHD_V,(val),UART_RX_IDLE_THRHD_S) + + + +#define UART_RS485_CONF_REG(i) (REG_UART_BASE(i) + 0x44) + /* UART_RS485_TX_DLY_NUM : R/W ;bitpos:[9:6] ;default: 4'b0 ; */ + /*description: config this reg to delay tx signal*/ + #define UART_RS485_TX_DLY_NUM 0x0000000F + #define UART_RS485_TX_DLY_NUM_M ((UART_RS485_TX_DLY_NUM_V)<<(UART_RS485_TX_DLY_NUM_S)) + #define UART_RS485_TX_DLY_NUM_V 0xF + #define UART_RS485_TX_DLY_NUM_S 6 + /* UART_RS485_RX_DLY_NUM : R/W ;bitpos:[5] ;default: 1'b0 ; */ + /*description: config this reg to delay rx signal*/ + #define UART_RS485_RX_DLY_NUM (BIT(5)) + #define UART_RS485_RX_DLY_NUM_M (BIT(5)) + #define UART_RS485_RX_DLY_NUM_V 0x1 + #define UART_RS485_RX_DLY_NUM_S 5 + /* UART_RS485RXBY_TX_EN : R/W ;bitpos:[4] ;default: 1'b0 ; */ + /*description: set this bit to enable tx when rx is busy*/ + #define UART_RS485RXBY_TX_EN (BIT(4)) + #define UART_RS485RXBY_TX_EN_M (BIT(4)) + #define UART_RS485RXBY_TX_EN_V 0x1 + #define UART_RS485RXBY_TX_EN_S 4 + /* UART_RS485TX_RX_EN : R/W ;bitpos:[3] ;default: 1'b0 ; */ + /*description: set this bit to enable rx receiving when tx is sending*/ + #define UART_RS485TX_RX_EN (BIT(3)) + #define UART_RS485TX_RX_EN_M (BIT(3)) + #define UART_RS485TX_RX_EN_V 0x1 + #define UART_RS485TX_RX_EN_S 3 + /* UART_DL1_EN : R/W ;bitpos:[2] ;default: 1'b0 ; */ + /*description: set this bit to add 1 bit stop bit(after data)*/ + #define UART_DL1_EN (BIT(2)) + #define UART_DL1_EN_M (BIT(2)) + #define UART_DL1_EN_V 0x1 + #define UART_DL1_EN_S 2 + /* UART_DL0_EN : R/W ;bitpos:[1] ;default: 1'b0 ; */ + /*description: set this bit to add 1 bit stop bit(before data)*/ + #define UART_DL0_EN (BIT(1)) + #define UART_DL0_EN_M (BIT(1)) + #define UART_DL0_EN_V 0x1 + #define UART_DL0_EN_S 1 + /* UART_RS485_EN : R/W ;bitpos:[0] ;default: 1'b0 ; */ + /*description: set this bit to enable rs485 protocol*/ + #define UART_RS485_EN (BIT(0)) + #define UART_RS485_EN_M (BIT(0)) + #define UART_RS485_EN_V 0x1 + #define UART_RS485_EN_S 0 + #define UART_GET_RS485_TX_DLY_NUM(i) GET_PERI_REG_BITS2(UART_RS485_CONF_REG(i) , UART_RS485_TX_DLY_NUM_V, UART_RS485_TX_DLY_NUM_S) + #define UART_SET_RS485_TX_DLY_NUM(i,val) SET_PERI_REG_BITS(UART_RS485_CONF_REG(i) ,UART_RS485_TX_DLY_NUM_V,(val),UART_RS485_TX_DLY_NUM_S) + #define UART_GET_RS485_RX_DLY_NUM(i) GET_PERI_REG_BITS2(UART_RS485_CONF_REG(i) , UART_RS485_RX_DLY_NUM_V, UART_RS485_RX_DLY_NUM_S) + #define UART_SET_RS485_RX_DLY_NUM(i,val) SET_PERI_REG_BITS(UART_RS485_CONF_REG(i) ,UART_RS485_RX_DLY_NUM_V,(val),UART_RS485_RX_DLY_NUM_S) + #define UART_GET_RS485RXBY_TX_EN(i) GET_PERI_REG_BITS2(UART_RS485_CONF_REG(i) , UART_RS485RXBY_TX_EN_V, UART_RS485RXBY_TX_EN_S) + #define UART_SET_RS485RXBY_TX_EN(i,val) SET_PERI_REG_BITS(UART_RS485_CONF_REG(i) ,UART_RS485RXBY_TX_EN_V,(val),UART_RS485RXBY_TX_EN_S) + #define UART_GET_RS485TX_RX_EN(i) GET_PERI_REG_BITS2(UART_RS485_CONF_REG(i) , UART_RS485TX_RX_EN_V, UART_RS485TX_RX_EN_S) + #define UART_SET_RS485TX_RX_EN(i,val) SET_PERI_REG_BITS(UART_RS485_CONF_REG(i) ,UART_RS485TX_RX_EN_V,(val),UART_RS485TX_RX_EN_S) + #define UART_GET_DL1_EN(i) GET_PERI_REG_BITS2(UART_RS485_CONF_REG(i) , UART_DL1_EN_V, UART_DL1_EN_S) + #define UART_SET_DL1_EN(i,val) SET_PERI_REG_BITS(UART_RS485_CONF_REG(i) ,UART_DL1_EN_V,(val),UART_DL1_EN_S) + #define UART_GET_DL0_EN(i) GET_PERI_REG_BITS2(UART_RS485_CONF_REG(i) , UART_DL0_EN_V, UART_DL0_EN_S) + #define UART_SET_DL0_EN(i,val) SET_PERI_REG_BITS(UART_RS485_CONF_REG(i) ,UART_DL0_EN_V,(val),UART_DL0_EN_S) + #define UART_GET_RS485_EN(i) GET_PERI_REG_BITS2(UART_RS485_CONF_REG(i) , UART_RS485_EN_V, UART_RS485_EN_S) + #define UART_SET_RS485_EN(i,val) SET_PERI_REG_BITS(UART_RS485_CONF_REG(i) ,UART_RS485_EN_V,(val),UART_RS485_EN_S) + + + +#define UART_AT_CMD_PRECNT_REG(i) (REG_UART_BASE(i) + 0x48) + /* UART_PRE_IDLE_NUM : R/W ;bitpos:[23:0] ;default: 24'h186a00 ; */ + /*description: config the idle time before receiving AT_CMD*/ + #define UART_PRE_IDLE_NUM 0x00FFFFFF + #define UART_PRE_IDLE_NUM_M ((UART_PRE_IDLE_NUM_V)<<(UART_PRE_IDLE_NUM_S)) + #define UART_PRE_IDLE_NUM_V 0xFFFFFF + #define UART_PRE_IDLE_NUM_S 0 + #define UART_GET_PRE_IDLE_NUM(i) GET_PERI_REG_BITS2(UART_AT_CMD_PRECNT_REG(i) , UART_PRE_IDLE_NUM_V, UART_PRE_IDLE_NUM_S) + #define UART_SET_PRE_IDLE_NUM(i,val) SET_PERI_REG_BITS(UART_AT_CMD_PRECNT_REG(i) ,UART_PRE_IDLE_NUM_V,(val),UART_PRE_IDLE_NUM_S) + + + +#define UART_AT_CMD_POSTCNT_REG(i) (REG_UART_BASE(i) + 0x4c) + /* UART_POST_IDLE_NUM : R/W ;bitpos:[23:0] ;default: 24'h186a00 ; */ + /*description: config the idle time after receiving AT_CMD*/ + #define UART_POST_IDLE_NUM 0x00FFFFFF + #define UART_POST_IDLE_NUM_M ((UART_POST_IDLE_NUM_V)<<(UART_POST_IDLE_NUM_S)) + #define UART_POST_IDLE_NUM_V 0xFFFFFF + #define UART_POST_IDLE_NUM_S 0 + #define UART_GET_POST_IDLE_NUM(i) GET_PERI_REG_BITS2(UART_AT_CMD_POSTCNT_REG(i) , UART_POST_IDLE_NUM_V, UART_POST_IDLE_NUM_S) + #define UART_SET_POST_IDLE_NUM(i,val) SET_PERI_REG_BITS(UART_AT_CMD_POSTCNT_REG(i) ,UART_POST_IDLE_NUM_V,(val),UART_POST_IDLE_NUM_S) + + + +#define UART_AT_CMD_GAPTOUT_REG(i) (REG_UART_BASE(i) + 0x50) + /* UART_RX_GAP_TOUT : R/W ;bitpos:[23:0] ;default: 24'h1e00 ; */ + /*description: config the time between receiving two AT_CMD*/ + #define UART_RX_GAP_TOUT 0x00FFFFFF + #define UART_RX_GAP_TOUT_M ((UART_RX_GAP_TOUT_V)<<(UART_RX_GAP_TOUT_S)) + #define UART_RX_GAP_TOUT_V 0xFFFFFF + #define UART_RX_GAP_TOUT_S 0 + #define UART_GET_RX_GAP_TOUT(i) GET_PERI_REG_BITS2(UART_AT_CMD_GAPTOUT_REG(i) , UART_RX_GAP_TOUT_V, UART_RX_GAP_TOUT_S) + #define UART_SET_RX_GAP_TOUT(i,val) SET_PERI_REG_BITS(UART_AT_CMD_GAPTOUT_REG(i) ,UART_RX_GAP_TOUT_V,(val),UART_RX_GAP_TOUT_S) + + + +#define UART_AT_CMD_CHAR_REG(i) (REG_UART_BASE(i) + 0x54) + /* UART_CHAR_NUM : R/W ;bitpos:[15:8] ;default: 8'd3 ; */ + /*description: config the continous num of AT_CMD*/ + #define UART_CHAR_NUM 0x000000FF + #define UART_CHAR_NUM_M ((UART_CHAR_NUM_V)<<(UART_CHAR_NUM_S)) + #define UART_CHAR_NUM_V 0xFF + #define UART_CHAR_NUM_S 8 + /* UART_AT_CMD_CHAR : R/W ;bitpos:[7:0] ;default: 8'h2b ; */ + /*description: config AT_CMD*/ + #define UART_AT_CMD_CHAR 0x000000FF + #define UART_AT_CMD_CHAR_M ((UART_AT_CMD_CHAR_V)<<(UART_AT_CMD_CHAR_S)) + #define UART_AT_CMD_CHAR_V 0xFF + #define UART_AT_CMD_CHAR_S 0 + #define UART_GET_CHAR_NUM(i) GET_PERI_REG_BITS2(UART_AT_CMD_CHAR_REG(i) , UART_CHAR_NUM_V, UART_CHAR_NUM_S) + #define UART_SET_CHAR_NUM(i,val) SET_PERI_REG_BITS(UART_AT_CMD_CHAR_REG(i) ,UART_CHAR_NUM_V,(val),UART_CHAR_NUM_S) + #define UART_GET_AT_CMD_CHAR(i) GET_PERI_REG_BITS2(UART_AT_CMD_CHAR_REG(i) , UART_AT_CMD_CHAR_V, UART_AT_CMD_CHAR_S) + #define UART_SET_AT_CMD_CHAR(i,val) SET_PERI_REG_BITS(UART_AT_CMD_CHAR_REG(i) ,UART_AT_CMD_CHAR_V,(val),UART_AT_CMD_CHAR_S) + + + +#define UART_MEM_CONF_REG(i) (REG_UART_BASE(i) + 0x58) + /* UART_TX_MEM_EMPTY_THRHD : R/W ;bitpos:[30:28] ;default: 3'h0 ; */ + /*description: the most significant bits of tx fifo empty threashold*/ + #define UART_TX_MEM_EMPTY_THRHD 0x00000007 + #define UART_TX_MEM_EMPTY_THRHD_M ((UART_TX_MEM_EMPTY_THRHD_V)<<(UART_TX_MEM_EMPTY_THRHD_S)) + #define UART_TX_MEM_EMPTY_THRHD_V 0x7 + #define UART_TX_MEM_EMPTY_THRHD_S 28 + /* UART_RX_MEM_FULL_THRHD : R/W ;bitpos:[27:25] ;default: 3'h0 ; */ + /*description: the most significant bits of rx fifo full threashold*/ + #define UART_RX_MEM_FULL_THRHD 0x00000007 + #define UART_RX_MEM_FULL_THRHD_M ((UART_RX_MEM_FULL_THRHD_V)<<(UART_RX_MEM_FULL_THRHD_S)) + #define UART_RX_MEM_FULL_THRHD_V 0x7 + #define UART_RX_MEM_FULL_THRHD_S 25 + /* UART_XOFF_THRESHOLD_H2 : R/W ;bitpos:[24:23] ;default: 2'h0 ; */ + /*description: the most significant bits of uart xoff flow threashold*/ + #define UART_XOFF_THRESHOLD_H2 0x00000003 + #define UART_XOFF_THRESHOLD_H2_M ((UART_XOFF_THRESHOLD_H2_V)<<(UART_XOFF_THRESHOLD_H2_S)) + #define UART_XOFF_THRESHOLD_H2_V 0x3 + #define UART_XOFF_THRESHOLD_H2_S 23 + /* UART_XON_THRESHOLD_H2 : R/W ;bitpos:[22:21] ;default: 2'h0 ; */ + /*description: the most significant bits of uart xon flow threshold*/ + #define UART_XON_THRESHOLD_H2 0x00000003 + #define UART_XON_THRESHOLD_H2_M ((UART_XON_THRESHOLD_H2_V)<<(UART_XON_THRESHOLD_H2_S)) + #define UART_XON_THRESHOLD_H2_V 0x3 + #define UART_XON_THRESHOLD_H2_S 21 + /* UART_RX_TOUT_THRHD_H3 : R/W ;bitpos:[20:18] ;default: 3h0 ; */ + /*description: the most significant bits of rx timeout threshold*/ + #define UART_RX_TOUT_THRHD_H3 0x00000007 + #define UART_RX_TOUT_THRHD_H3_M ((UART_RX_TOUT_THRHD_H3_V)<<(UART_RX_TOUT_THRHD_H3_S)) + #define UART_RX_TOUT_THRHD_H3_V 0x7 + #define UART_RX_TOUT_THRHD_H3_S 18 + /* UART_RX_FLOW_THRHD_H3 : R/W ;bitpos:[17:15] ;default: 3'h0 ; */ + /*description: the most significant bits of rx flow control threshold*/ + #define UART_RX_FLOW_THRHD_H3 0x00000007 + #define UART_RX_FLOW_THRHD_H3_M ((UART_RX_FLOW_THRHD_H3_V)<<(UART_RX_FLOW_THRHD_H3_S)) + #define UART_RX_FLOW_THRHD_H3_V 0x7 + #define UART_RX_FLOW_THRHD_H3_S 15 + /* UART_TX_SIZE : R/W ;bitpos:[10:7] ;default: 3'h0 ; */ + /*description: config tx_mem's size(128*reg_rx_size)*/ + #define UART_TX_SIZE 0x0000000F + #define UART_TX_SIZE_M ((UART_TX_SIZE_V)<<(UART_TX_SIZE_S)) + #define UART_TX_SIZE_V 0xF + #define UART_TX_SIZE_S 7 + /* UART_RX_SIZE : R/W ;bitpos:[6:3] ;default: 3'h0 ; */ + /*description: config rx mem's size(128*reg_rx_size)*/ + #define UART_RX_SIZE 0x0000000F + #define UART_RX_SIZE_M ((UART_RX_SIZE_V)<<(UART_RX_SIZE_S)) + #define UART_RX_SIZE_V 0xF + #define UART_RX_SIZE_S 3 + /* UART_MEM_PD : R/W ;bitpos:[0] ;default: 1'b0 ; */ + /*description: set this bit to pull_down mem's pd signal*/ + #define UART_MEM_PD (BIT(0)) + #define UART_MEM_PD_M (BIT(0)) + #define UART_MEM_PD_V 0x1 + #define UART_MEM_PD_S 0 + #define UART_GET_TX_MEM_EMPTY_THRHD(i) GET_PERI_REG_BITS2(UART_MEM_CONF_REG(i) , UART_TX_MEM_EMPTY_THRHD_V, UART_TX_MEM_EMPTY_THRHD_S) + #define UART_SET_TX_MEM_EMPTY_THRHD(i,val) SET_PERI_REG_BITS(UART_MEM_CONF_REG(i) ,UART_TX_MEM_EMPTY_THRHD_V,(val),UART_TX_MEM_EMPTY_THRHD_S) + #define UART_GET_RX_MEM_FULL_THRHD(i) GET_PERI_REG_BITS2(UART_MEM_CONF_REG(i) , UART_RX_MEM_FULL_THRHD_V, UART_RX_MEM_FULL_THRHD_S) + #define UART_SET_RX_MEM_FULL_THRHD(i,val) SET_PERI_REG_BITS(UART_MEM_CONF_REG(i) ,UART_RX_MEM_FULL_THRHD_V,(val),UART_RX_MEM_FULL_THRHD_S) + #define UART_GET_XOFF_THRESHOLD_H2(i) GET_PERI_REG_BITS2(UART_MEM_CONF_REG(i) , UART_XOFF_THRESHOLD_H2_V, UART_XOFF_THRESHOLD_H2_S) + #define UART_SET_XOFF_THRESHOLD_H2(i,val) SET_PERI_REG_BITS(UART_MEM_CONF_REG(i) ,UART_XOFF_THRESHOLD_H2_V,(val),UART_XOFF_THRESHOLD_H2_S) + #define UART_GET_XON_THRESHOLD_H2(i) GET_PERI_REG_BITS2(UART_MEM_CONF_REG(i) , UART_XON_THRESHOLD_H2_V, UART_XON_THRESHOLD_H2_S) + #define UART_SET_XON_THRESHOLD_H2(i,val) SET_PERI_REG_BITS(UART_MEM_CONF_REG(i) ,UART_XON_THRESHOLD_H2_V,(val),UART_XON_THRESHOLD_H2_S) + #define UART_GET_RX_TOUT_THRHD_H3(i) GET_PERI_REG_BITS2(UART_MEM_CONF_REG(i) , UART_RX_TOUT_THRHD_H3_V, UART_RX_TOUT_THRHD_H3_S) + #define UART_SET_RX_TOUT_THRHD_H3(i,val) SET_PERI_REG_BITS(UART_MEM_CONF_REG(i) ,UART_RX_TOUT_THRHD_H3_V,(val),UART_RX_TOUT_THRHD_H3_S) + #define UART_GET_RX_FLOW_THRHD_H3(i) GET_PERI_REG_BITS2(UART_MEM_CONF_REG(i) , UART_RX_FLOW_THRHD_H3_V, UART_RX_FLOW_THRHD_H3_S) + #define UART_SET_RX_FLOW_THRHD_H3(i,val) SET_PERI_REG_BITS(UART_MEM_CONF_REG(i) ,UART_RX_FLOW_THRHD_H3_V,(val),UART_RX_FLOW_THRHD_H3_S) + #define UART_GET_REG_TX_SIZE(i) GET_PERI_REG_BITS2(UART_MEM_CONF_REG(i) , UART_TX_SIZE_V, UART_TX_SIZE_S) + #define UART_SET_REG_TX_SIZE(i,val) SET_PERI_REG_BITS(UART_MEM_CONF_REG(i) ,UART_TX_SIZE_V,(val),UART_TX_SIZE_S) + #define UART_GET_REG_RX_SIZE(i) GET_PERI_REG_BITS2(UART_MEM_CONF_REG(i) , UART_RX_SIZE_V, UART_RX_SIZE_S) + #define UART_SET_REG_RX_SIZE(i,val) SET_PERI_REG_BITS(UART_MEM_CONF_REG(i) ,UART_RX_SIZE_V,(val),UART_RX_SIZE_S) + #define UART_GET_REG_MEM_PD(i) GET_PERI_REG_BITS2(UART_MEM_CONF_REG(i) , UART_MEM_PD_V, UART_MEM_PD_S) + #define UART_SET_REG_MEM_PD(i,val) SET_PERI_REG_BITS(UART_MEM_CONF_REG(i) ,UART_MEM_PD_V,(val),UART_MEM_PD_S) + + + +#define UART_MEM_TX_STATUS_REG(i) (REG_UART_BASE(i) + 0x5c) + /* UART_TX_RADDR_CHX : RO ;bitpos:[23:13] ;default: 11'b0 ; */ + /*description: uartx tx mem's read address*/ + #define UART_TX_RADDR_CHX 0x000007FF + #define UART_TX_RADDR_CHX_M ((UART_TX_RADDR_CHX_V)<<(UART_TX_RADDR_CHX_S)) + #define UART_TX_RADDR_CHX_V 0x7FF + #define UART_TX_RADDR_CHX_S 13 + /* UART_APB_TX_WADDR_CHX : RO ;bitpos:[12:2] ;default: 11'b0 ; */ + /*description: uartx tx mem's write address*/ + #define UART_APB_TX_WADDR_CHX 0x000007FF + #define UART_APB_TX_WADDR_CHX_M ((UART_APB_TX_WADDR_CHX_V)<<(UART_APB_TX_WADDR_CHX_S)) + #define UART_APB_TX_WADDR_CHX_V 0x7FF + #define UART_APB_TX_WADDR_CHX_S 2 + #define UART_GET_TX_RADDR_CHX(i) GET_PERI_REG_BITS2(UART_MEM_TX_STATUS_REG(i) , UART_TX_RADDR_CHX_V, UART_TX_RADDR_CHX_S) + #define UART_GET_APB_TX_WADDR_CHX(i) GET_PERI_REG_BITS2(UART_MEM_TX_STATUS_REG(i) , UART_APB_TX_WADDR_CHX_V, UART_APB_TX_WADDR_CHX_S) + + + +#define UART_MEM_RX_STATUS_REG(i) (REG_UART_BASE(i) + 0x60) + /* UART_RX_WADDR_CHX : RO ;bitpos:[23:13] ;default: 11'b0 ; */ + /*description: uartx rx mem's write address*/ + #define UART_RX_WADDR_CHX 0x000007FF + #define UART_RX_WADDR_CHX_M ((UART_RX_WADDR_CHX_V)<<(UART_RX_WADDR_CHX_S)) + #define UART_RX_WADDR_CHX_V 0x7FF + #define UART_RX_WADDR_CHX_S 13 + /* UART_APB_RX_RADDR_CHX : RO ;bitpos:[12:2] ;default: 11'b0 ; */ + /*description: uartx rx mem's read address*/ + #define UART_APB_RX_RADDR_CHX 0x000007FF + #define UART_APB_RX_RADDR_CHX_M ((UART_APB_RX_RADDR_CHX_V)<<(UART_APB_RX_RADDR_CHX_S)) + #define UART_APB_RX_RADDR_CHX_V 0x7FF + #define UART_APB_RX_RADDR_CHX_S 2 + #define UART_GET_RX_WADDR_CHX(i) GET_PERI_REG_BITS2(UART_MEM_RX_STATUS_REG(i) , UART_RX_WADDR_CHX_V, UART_RX_WADDR_CHX_S) + #define UART_GET_APB_RX_RADDR_CHX(i) GET_PERI_REG_BITS2(UART_MEM_RX_STATUS_REG(i) , UART_APB_RX_RADDR_CHX_V, UART_APB_RX_RADDR_CHX_S) + + + +#define UART_DATE_REG(i) (REG_UART_BASE(i) + 0x78) + /* UART_DATE : R/W ;bitpos:[31:0] ;default: 32'h15122500 ; */ + /*description: */ + #define UART_DATE 0xFFFFFFFF + #define UART_DATE_M ((UART_DATE_V)<<(UART_DATE_S)) + #define UART_DATE_V 0xFFFFFFFF + #define UART_DATE_S 0 + #define UART_GET_DATE(i) GET_PERI_REG_BITS2(UART_DATE_REG(i) , UART_DATE_V, UART_DATE_S) + #define UART_SET_DATE(i,val) SET_PERI_REG_BITS(UART_DATE_REG(i) ,UART_DATE_V,(val),UART_DATE_S) + + + +#define UART_ID_REG(i) (REG_UART_BASE(i) + 0x7C) + /* UART_ID : R/W ;bitpos:[31:0] ;default: 32'h0500 ; */ + /*description: */ + #define UART_ID 0xFFFFFFFF + #define UART_ID_M ((UART_ID_V)<<(UART_ID_S)) + #define UART_ID_V 0xFFFFFFFF + #define UART_ID_S 0 + #define UART_GET_ID(i) GET_PERI_REG_BITS2(UART_ID_REG(i) , UART_ID_V, UART_ID_S) + #define UART_SET_ID(i,val) SET_PERI_REG_BITS(UART_ID_REG(i) ,UART_ID_V,(val),UART_ID_S) + + + + + + +#endif /* _SOC_UART_REG_H_ */ + + diff --git a/components/esp32/include/soc/uhci0_reg.h b/components/esp32/include/soc/uhci0_reg.h new file mode 100644 index 0000000000..353a96eaa8 --- /dev/null +++ b/components/esp32/include/soc/uhci0_reg.h @@ -0,0 +1,350 @@ +// Copyright 2015-2016 Espressif Systems (Shanghai) PTE LTD +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at + +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +#ifndef _SOC_UHCI0_REG_H_ +#define _SOC_UHCI0_REG_H_ + +#include "soc.h" + +#define UHCI0_CONF0 ( DR_REG_UHCI0_BASE + 0x0) +#define UHCI0_UART_RX_BRK_EOF_EN (BIT(22)) +#define UHCI0_CLK_EN (BIT(21)) +#define UHCI0_ENCODE_CRC_EN (BIT(20)) +#define UHCI0_LEN_EOF_EN (BIT(19)) +#define UHCI0_UART_IDLE_EOF_EN (BIT(18)) +#define UHCI0_CRC_REC_EN (BIT(17)) +#define UHCI0_HEAD_EN (BIT(16)) +#define UHCI0_SEPER_EN (BIT(15)) +#define UHCI0_MEM_TRANS_EN (BIT(14)) +#define UHCI0_RX_DATA_BURST_EN (BIT(13)) +#define UHCI0_TXDSCR_BURST_EN (BIT(12)) +#define UHCI0_RXDSCR_BURST_EN (BIT(11)) +#define UHCI0_UART1_CE (BIT(10)) +#define UHCI0_UART0_CE (BIT(9)) +#define UHCI0_TO_EOF_MODE (BIT(8)) +#define UHCI0_RX_NO_RESTART_CLR (BIT(7)) +#define UHCI0_RX_AUTO_WRBACK (BIT(6)) +#define UHCI0_RX_LOOP_TEST (BIT(5)) +#define UHCI0_TX_LOOP_TEST (BIT(4)) +#define UHCI0_AHBM_RST (BIT(3)) +#define UHCI0_AHBM_FIFO_RST (BIT(2)) +#define UHCI0_RX_RST (BIT(1)) +#define UHCI0_TX_RST (BIT(0)) + +#define UHCI0_INT_RAW ( DR_REG_UHCI0_BASE + 0x4) +#define UHCI0_UHCI_SEND_A_Q_INT_RAW (BIT(15)) +#define UHCI0_UHCI_SEND_S_Q_INT_RAW (BIT(14)) +#define UHCI0_UHCI_TO_TOTAL_EOF_INT_RAW (BIT(13)) +#define UHCI0_UHCI_RXLINK_EOF_ERR_INT_RAW (BIT(12)) +#define UHCI0_UHCI_TX_DSCR_EMPTY_INT_RAW (BIT(11)) +#define UHCI0_UHCI_RX_DSCR_ERR_INT_RAW (BIT(10)) +#define UHCI0_UHCI_TX_DSCR_ERR_INT_RAW (BIT(9)) +#define UHCI0_UHCI_TO_EOF_INT_RAW (BIT(8)) +#define UHCI0_UHCI_RX_DONE_INT_RAW (BIT(7)) +#define UHCI0_UHCI_FROM_ERR_EOF_INT_RAW (BIT(6)) +#define UHCI0_UHCI_FROM_SUC_EOF_INT_RAW (BIT(5)) +#define UHCI0_UHCI_TX_DONE_INT_RAW (BIT(4)) +#define UHCI0_UHCI_TX_HUNG_INT_RAW (BIT(3)) +#define UHCI0_UHCI_RX_HUNG_INT_RAW (BIT(2)) +#define UHCI0_UHCI_TX_START_INT_RAW (BIT(1)) +#define UHCI0_UHCI_RX_START_INT_RAW (BIT(0)) + +#define UHCI0_INT_ST ( DR_REG_UHCI0_BASE + 0x8) +#define UHCI0_UHCI_SEND_A_Q_INT_ST (BIT(15)) +#define UHCI0_UHCI_SEND_S_Q_INT_ST (BIT(14)) +#define UHCI0_UHCI_TO_TOTAL_EOF_INT_ST (BIT(13)) +#define UHCI0_UHCI_RXLINK_EOF_ERR_INT_ST (BIT(12)) +#define UHCI0_UHCI_TX_DSCR_EMPTY_INT_ST (BIT(11)) +#define UHCI0_UHCI_RX_DSCR_ERR_INT_ST (BIT(10)) +#define UHCI0_UHCI_TX_DSCR_ERR_INT_ST (BIT(9)) +#define UHCI0_UHCI_TO_EOF_INT_ST (BIT(8)) +#define UHCI0_UHCI_RX_DONE_INT_ST (BIT(7)) +#define UHCI0_UHCI_FROM_ERR_EOF_INT_ST (BIT(6)) +#define UHCI0_UHCI_FROM_SUC_EOF_INT_ST (BIT(5)) +#define UHCI0_UHCI_TX_DONE_INT_ST (BIT(4)) +#define UHCI0_UHCI_TX_HUNG_INT_ST (BIT(3)) +#define UHCI0_UHCI_RX_HUNG_INT_ST (BIT(2)) +#define UHCI0_UHCI_TX_START_INT_ST (BIT(1)) +#define UHCI0_UHCI_RX_START_INT_ST (BIT(0)) + +#define UHCI0_INT_ENA ( DR_REG_UHCI0_BASE + 0xC) +#define UHCI0_UHCI_SEND_A_Q_INT_ENA (BIT(15)) +#define UHCI0_UHCI_SEND_S_Q_INT_ENA (BIT(14)) +#define UHCI0_UHCI_TO_TOTAL_EOF_INT_ENA (BIT(13)) +#define UHCI0_UHCI_RXLINK_EOF_ERR_INT_ENA (BIT(12)) +#define UHCI0_UHCI_TX_DSCR_EMPTY_INT_ENA (BIT(11)) +#define UHCI0_UHCI_RX_DSCR_ERR_INT_ENA (BIT(10)) +#define UHCI0_UHCI_TX_DSCR_ERR_INT_ENA (BIT(9)) +#define UHCI0_UHCI_TO_EOF_INT_ENA (BIT(8)) +#define UHCI0_UHCI_RX_DONE_INT_ENA (BIT(7)) +#define UHCI0_UHCI_FROM_ERR_EOF_INT_ENA (BIT(6)) +#define UHCI0_UHCI_FROM_SUC_EOF_INT_ENA (BIT(5)) +#define UHCI0_UHCI_TX_DONE_INT_ENA (BIT(4)) +#define UHCI0_UHCI_TX_HUNG_INT_ENA (BIT(3)) +#define UHCI0_UHCI_RX_HUNG_INT_ENA (BIT(2)) +#define UHCI0_UHCI_TX_START_INT_ENA (BIT(1)) +#define UHCI0_UHCI_RX_START_INT_ENA (BIT(0)) + +#define UHCI0_INT_CLR ( DR_REG_UHCI0_BASE + 0x10) +#define UHCI0_SEND_A_REG_Q_INT_CLR (BIT(15)) +#define UHCI0_SEND_S_REG_Q_INT_CLR (BIT(14)) +#define UHCI0_TO_TOTAL_EOF_INT_CLR (BIT(13)) +#define UHCI0_RXLINK_EOF_ERR_INT_CLR (BIT(12)) +#define UHCI0_TX_DSCR_EMPTY_INT_CLR (BIT(11)) +#define UHCI0_RX_DSCR_ERR_INT_CLR (BIT(10)) +#define UHCI0_TX_DSCR_ERR_INT_CLR (BIT(9)) +#define UHCI0_TO_EOF_INT_CLR (BIT(8)) +#define UHCI0_RX_DONE_INT_CLR (BIT(7)) +#define UHCI0_FROM_ERR_EOF_INT_CLR (BIT(6)) +#define UHCI0_FROM_SUC_EOF_INT_CLR (BIT(5)) +#define UHCI0_TX_DONE_INT_CLR (BIT(4)) +#define UHCI0_TX_HUNG_INT_CLR (BIT(3)) +#define UHCI0_RX_HUNG_INT_CLR (BIT(2)) +#define UHCI0_TX_START_INT_CLR (BIT(1)) +#define UHCI0_RX_START_INT_CLR (BIT(0)) + +#define UHCI0_RX_STATUS ( DR_REG_UHCI0_BASE + 0x14) +#define UHCI0_RX_EMPTY (BIT(1)) +#define UHCI0_RX_FULL (BIT(0)) + +#define UHCI0_RXFIFO_PUSH ( DR_REG_UHCI0_BASE + 0x18) +#define UHCI0_RXFIFO_PUSH_EN (BIT(16)) +#define UHCI0_RXFIFO_WDATA 0x000001FF +#define UHCI0_RXFIFO_WDATA_S 0 + +#define UHCI0_TX_STATUS ( DR_REG_UHCI0_BASE + 0x1C) +#define UHCI0_UHCI_RX_ERR_CAUSE 0x00000007 +#define UHCI0_UHCI_RX_ERR_CAUSE_S 4 +#define UHCI0_TX_EMPTY (BIT(1)) +#define UHCI0_TX_FULL (BIT(0)) + +#define UHCI0_TX_POP ( DR_REG_UHCI0_BASE + 0x20) +#define UHCI0_TXFIFO_POP (BIT(16)) +#define UHCI0_TXFIFO_RDATA 0x00000FFF +#define UHCI0_TXFIFO_RDATA_S 0 + +#define UHCI0_RX_LINK ( DR_REG_UHCI0_BASE + 0x24) +#define UHCI0_UHCI_RXLINK_PARK (BIT(31)) +#define UHCI0_RXLINK_RESTART (BIT(30)) +#define UHCI0_RXLINK_START (BIT(29)) +#define UHCI0_RXLINK_STOP (BIT(28)) +#define UHCI0_RXLINK_ADDR 0x000FFFFF +#define UHCI0_RXLINK_ADDR_S 0 + +#define UHCI0_TX_LINK ( DR_REG_UHCI0_BASE + 0x28) +#define UHCI0_UHCI_TXLINK_PARK (BIT(31)) +#define UHCI0_TXLINK_RESTART (BIT(30)) +#define UHCI0_TXLINK_START (BIT(29)) +#define UHCI0_TXLINK_STOP (BIT(28)) +#define UHCI0_TXLINK_AUTO_RET (BIT(20)) +#define UHCI0_TXLINK_ADDR 0x000FFFFF +#define UHCI0_TXLINK_ADDR_S 0 + +#define UHCI0_CONF1 ( DR_REG_UHCI0_BASE + 0x2C) +#define UHCI0_SW_START (BIT(8)) +#define UHCI0_WAIT_SW_START (BIT(7)) +#define UHCI0_CHECK_OWNER (BIT(6)) +#define UHCI0_TX_ACK_NUM_RE (BIT(5)) +#define UHCI0_TX_CHECK_SUM_RE (BIT(4)) +#define UHCI0_SAVE_HEAD (BIT(3)) +#define UHCI0_CRC_DISABLE (BIT(2)) +#define UHCI0_CHECK_SEQ_EN (BIT(1)) +#define UHCI0_CHECK_SUM_EN (BIT(0)) + +#define UHCI0_STATE0 ( DR_REG_UHCI0_BASE + 0x30) +#define UHCI0_UHCI_STATE0 0xFFFFFFFF +#define UHCI0_UHCI_STATE0_S 0 + +#define UHCI0_STATE1 ( DR_REG_UHCI0_BASE + 0x34) +#define UHCI0_UHCI_STATE1 0xFFFFFFFF +#define UHCI0_UHCI_STATE1_S 0 + +#define UHCI0_RX_EOF_DES_ADDR ( DR_REG_UHCI0_BASE + 0x38) +#define UHCI0_TO_EOF_DES_ADDR 0xFFFFFFFF +#define UHCI0_TO_EOF_DES_ADDR_S 0 + +#define UHCI0_TX_SUC_EOF_DES_ADDR ( DR_REG_UHCI0_BASE + 0x3C) +#define UHCI0_FROM_SUC_EOF_DES_ADDR 0xFFFFFFFF +#define UHCI0_FROM_SUC_EOF_DES_ADDR_S 0 + +#define UHCI0_TX_ERR_EOF_DES_ADDR ( DR_REG_UHCI0_BASE + 0x40) +#define UHCI0_FROM_ERR_EOF_DES_ADDR 0xFFFFFFFF +#define UHCI0_FROM_ERR_EOF_DES_ADDR_S 0 + +#define UHCI0_RX_EOF_BFR_DES_ADDR ( DR_REG_UHCI0_BASE + 0x44) +#define UHCI0_TO_EOF_BFR_DES_ADDR 0xFFFFFFFF +#define UHCI0_TO_EOF_BFR_DES_ADDR_S 0 + +#define UHCI0_AHB_TEST ( DR_REG_UHCI0_BASE + 0x48) +#define UHCI0_AHB_TESTADDR 0x00000003 +#define UHCI0_AHB_TESTADDR_S 4 +#define UHCI0_AHB_TESTMODE 0x00000007 +#define UHCI0_AHB_TESTMODE_S 0 + +#define UHCI0_TX_DSCR ( DR_REG_UHCI0_BASE + 0x4C) +#define UHCI0_TXLINK_DSCR 0xFFFFFFFF +#define UHCI0_TXLINK_DSCR_S 0 + +#define UHCI0_TX_DSCR_BF0 ( DR_REG_UHCI0_BASE + 0x50) +#define UHCI0_TXLINK_DSCR_BF0 0xFFFFFFFF +#define UHCI0_TXLINK_DSCR_BF0_S 0 + +#define UHCI0_TX_DSCR_BF1 ( DR_REG_UHCI0_BASE + 0x54) +#define UHCI0_TXLINK_DSCR_BF1 0xFFFFFFFF +#define UHCI0_TXLINK_DSCR_BF1_S 0 + +#define UHCI0_RX_DSCR ( DR_REG_UHCI0_BASE + 0x58) +#define UHCI0_RXLINK_DSCR 0xFFFFFFFF +#define UHCI0_RXLINK_DSCR_S 0 + +#define UHCI0_RX_DSCR_BF0 ( DR_REG_UHCI0_BASE + 0x5C) +#define UHCI0_RXLINK_DSCR_BF0 0xFFFFFFFF +#define UHCI0_RXLINK_DSCR_BF0_S 0 + +#define UHCI0_RX_DSCR_BF1 ( DR_REG_UHCI0_BASE + 0x60) +#define UHCI0_RXLINK_DSCR_BF1 0xFFFFFFFF +#define UHCI0_RXLINK_DSCR_BF1_S 0 + +#define UHCI0_ESCAPE_CONF ( DR_REG_UHCI0_BASE + 0x64) +#define UHCI0_RX_13_ESC_EN (BIT(7)) +#define UHCI0_RX_11_ESC_EN (BIT(6)) +#define UHCI0_RX_DB_ESC_EN (BIT(5)) +#define UHCI0_RX_C0_ESC_EN (BIT(4)) +#define UHCI0_TX_13_ESC_EN (BIT(3)) +#define UHCI0_TX_11_ESC_EN (BIT(2)) +#define UHCI0_TX_DB_ESC_EN (BIT(1)) +#define UHCI0_TX_C0_ESC_EN (BIT(0)) + +#define UHCI0_HUNG_CONF ( DR_REG_UHCI0_BASE + 0x68) +#define UHCI0_RXFIFO_TIMEOUT_ENA (BIT(23)) +#define UHCI0_RXFIFO_TIMEOUT_SHIFT 0x00000007 +#define UHCI0_RXFIFO_TIMEOUT_SHIFT_S 20 +#define UHCI0_RXFIFO_TIMEOUT 0x000000FF +#define UHCI0_RXFIFO_TIMEOUT_S 12 +#define UHCI0_TXFIFO_TIMEOUT_ENA (BIT(11)) +#define UHCI0_TXFIFO_TIMEOUT_SHIFT 0x00000007 +#define UHCI0_TXFIFO_TIMEOUT_SHIFT_S 8 +#define UHCI0_TXFIFO_TIMEOUT 0x000000FF +#define UHCI0_TXFIFO_TIMEOUT_S 0 + +#define UHCI0_ACK_NUM ( DR_REG_UHCI0_BASE + 0x6C) + +#define UHCI0_RX_HEAD ( DR_REG_UHCI0_BASE + 0x70) +#define UHCI0_UHCI_RX_HEAD 0xFFFFFFFF +#define UHCI0_UHCI_RX_HEAD_S 0 + +#define UHCI0_QUICK_SENT ( DR_REG_UHCI0_BASE + 0x74) +#define UHCI0_ALWAYS_SEND_EN (BIT(7)) +#define UHCI0_ALWAYS_SEND_NUM 0x00000007 +#define UHCI0_ALWAYS_SEND_NUM_S 4 +#define UHCI0_SINGLE_SEND_EN (BIT(3)) +#define UHCI0_SINGLE_SEND_NUM 0x00000007 +#define UHCI0_SINGLE_SEND_NUM_S 0 + +#define UHCI0_REG_Q0_WORD0 ( DR_REG_UHCI0_BASE + 0x78) +#define UHCI0_SEND_Q0_WORD0 0xFFFFFFFF +#define UHCI0_SEND_Q0_WORD0_S 0 + +#define UHCI0_REG_Q0_WORD1 ( DR_REG_UHCI0_BASE + 0x7C) +#define UHCI0_SEND_Q0_WORD1 0xFFFFFFFF +#define UHCI0_SEND_Q0_WORD1_S 0 + +#define UHCI0_REG_Q1_WORD0 ( DR_REG_UHCI0_BASE + 0x80) +#define UHCI0_SEND_Q1_WORD0 0xFFFFFFFF +#define UHCI0_SEND_Q1_WORD0_S 0 + +#define UHCI0_REG_Q1_WORD1 ( DR_REG_UHCI0_BASE + 0x84) +#define UHCI0_SEND_Q1_WORD1 0xFFFFFFFF +#define UHCI0_SEND_Q1_WORD1_S 0 + +#define UHCI0_REG_Q2_WORD0 ( DR_REG_UHCI0_BASE + 0x88) +#define UHCI0_SEND_Q2_WORD0 0xFFFFFFFF +#define UHCI0_SEND_Q2_WORD0_S 0 + +#define UHCI0_REG_Q2_WORD1 ( DR_REG_UHCI0_BASE + 0x8C) +#define UHCI0_SEND_Q2_WORD1 0xFFFFFFFF +#define UHCI0_SEND_Q2_WORD1_S 0 + +#define UHCI0_REG_Q3_WORD0 ( DR_REG_UHCI0_BASE + 0x90) +#define UHCI0_SEND_Q3_WORD0 0xFFFFFFFF +#define UHCI0_SEND_Q3_WORD0_S 0 + +#define UHCI0_REG_Q3_WORD1 ( DR_REG_UHCI0_BASE + 0x94) +#define UHCI0_SEND_Q3_WORD1 0xFFFFFFFF +#define UHCI0_SEND_Q3_WORD1_S 0 + +#define UHCI0_REG_Q4_WORD0 ( DR_REG_UHCI0_BASE + 0x98) +#define UHCI0_SEND_Q4_WORD0 0xFFFFFFFF +#define UHCI0_SEND_Q4_WORD0_S 0 + +#define UHCI0_REG_Q4_WORD1 ( DR_REG_UHCI0_BASE + 0x9C) +#define UHCI0_SEND_Q4_WORD1 0xFFFFFFFF +#define UHCI0_SEND_Q4_WORD1_S 0 + +#define UHCI0_REG_Q5_WORD0 ( DR_REG_UHCI0_BASE + 0xA0) +#define UHCI0_SEND_Q5_WORD0 0xFFFFFFFF +#define UHCI0_SEND_Q5_WORD0_S 0 + +#define UHCI0_REG_Q5_WORD1 ( DR_REG_UHCI0_BASE + 0xA4) +#define UHCI0_SEND_Q5_WORD1 0xFFFFFFFF +#define UHCI0_SEND_Q5_WORD1_S 0 + +#define UHCI0_REG_Q6_WORD0 ( DR_REG_UHCI0_BASE + 0xA8) +#define UHCI0_SEND_Q6_WORD0 0xFFFFFFFF +#define UHCI0_SEND_Q6_WORD0_S 0 + +#define UHCI0_REG_Q6_WORD1 ( DR_REG_UHCI0_BASE + 0xAC) +#define UHCI0_SEND_Q6_WORD1 0xFFFFFFFF +#define UHCI0_SEND_Q6_WORD1_S 0 + +#define UHCI0_ESC_CONF0 ( DR_REG_UHCI0_BASE + 0xB0) +#define UHCI0_SEPER_ESC_CHAR1 0x000000FF +#define UHCI0_SEPER_ESC_CHAR1_S 16 +#define UHCI0_SEPER_ESC_CHAR0 0x000000FF +#define UHCI0_SEPER_ESC_CHAR0_S 8 +#define UHCI0_SEPER_CHAR 0x000000FF +#define UHCI0_SEPER_CHAR_S 0 + +#define UHCI0_ESC_CONF1 ( DR_REG_UHCI0_BASE + 0xB4) +#define UHCI0_ESC_SEQ0_CHAR1 0x000000FF +#define UHCI0_ESC_SEQ0_CHAR1_S 16 +#define UHCI0_ESC_SEQ0_CHAR0 0x000000FF +#define UHCI0_ESC_SEQ0_CHAR0_S 8 +#define UHCI0_ESC_SEQ0 0x000000FF +#define UHCI0_ESC_SEQ0_S 0 + +#define UHCI0_ESC_CONF2 ( DR_REG_UHCI0_BASE + 0xB8) +#define UHCI0_ESC_SEQ1_CHAR1 0x000000FF +#define UHCI0_ESC_SEQ1_CHAR1_S 16 +#define UHCI0_ESC_SEQ1_CHAR0 0x000000FF +#define UHCI0_ESC_SEQ1_CHAR0_S 8 +#define UHCI0_ESC_SEQ1 0x000000FF +#define UHCI0_ESC_SEQ1_S 0 + +#define UHCI0_ESC_CONF3 ( DR_REG_UHCI0_BASE + 0xBC) +#define UHCI0_ESC_SEQ2_CHAR1 0x000000FF +#define UHCI0_ESC_SEQ2_CHAR1_S 16 +#define UHCI0_ESC_SEQ2_CHAR0 0x000000FF +#define UHCI0_ESC_SEQ2_CHAR0_S 8 +#define UHCI0_ESC_SEQ2 0x000000FF +#define UHCI0_ESC_SEQ2_S 0 + +#define UHCI0_PKT_THRES ( DR_REG_UHCI0_BASE + 0xC0) +#define UHCI0_PKT_THRS 0x00001FFF +#define UHCI0_PKT_THRS_S 0 + +#define UHCI0_DATA ( DR_REG_UHCI0_BASE + 0xFC) +#define UHCI0_UHCI_DATA 0xFFFFFFFF +#define UHCI0_UHCI_DATA_S 0 + +#endif /* _SOC_UHCI0_REG_H_ */ diff --git a/components/esp32/include/xtensa/board.h b/components/esp32/include/xtensa/board.h new file mode 100755 index 0000000000..c6b04a2505 --- /dev/null +++ b/components/esp32/include/xtensa/board.h @@ -0,0 +1,28 @@ +/* This header is supposed to be obtained from /xtensa/board.h + using a -I directive passed to the compiler. */ + +#error "Unspecified board. Missing -I directive to select supported Xtensa board, usually -I XTENSA_TOOLS_ROOT/xtensa-elf/include/xtensa/ (XTENSA_TOOLS_ROOT is root of Xtensa Tools install, see xt-run --show-config=xttools)" + +/* + * Copyright (c) 2013 Tensilica Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY + * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + diff --git a/components/esp32/include/xtensa/c6x-compat.h b/components/esp32/include/xtensa/c6x-compat.h new file mode 100755 index 0000000000..4b17987ea9 --- /dev/null +++ b/components/esp32/include/xtensa/c6x-compat.h @@ -0,0 +1,1758 @@ +/* + * Copyright (c) 2006-2010 Tensilica Inc. ALL RIGHTS RESERVED. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#ifndef __C6X_COMPAT__H +#define __C6X_COMPAT__H + +/* Unimplemented functions _gmpy, _gmpy4, _xormpy, _lssub, _cmpy, _cmpyr, + _cmpyr1, _ddotpl2r, _ddotph2r */ + + +typedef long long C6X_COMPAT_LONG40; + + +#define _memd8(a) (*((double*)(a))) +#define _memd8_const(a) (*((const double*)(a))) + +#define _amemd8(a) (*((double*)(a))) +#define _amemd8_const(a) (*((const double*)(a))) + +#define _mem8(a) (*((unsigned long long*)(a))) +#define _mem8_const(a) (*((const unsigned long long*)(a))) + +#define _mem4(a) (*((unsigned*)(a))) +#define _mem4_const(a) (*((const unsigned*)(a))) +#define _amem4_const(a) (*((const unsigned*)(a))) + +/* NOTE: To emulate a C6X properly you should define global variables + for your Xtensa with these names. Some of the emulation routines + will set these values. */ + +extern int _carry; +extern int _overflow; + +// Utility routines + + +#define TESTBIT(x,n) (((x) >> (n)) & 1) + +#define NSA_BITS 32 + +static inline unsigned int norm_shift_amt_U_and_non_U(int is_signed, int inp) { +int j=0, k=0; +int x=inp; +if (is_signed) { + /* Invert signed val if negative */ + x= TESTBIT(x,(NSA_BITS-1))? ~x: x; + x= (x&1)|(x<<1); /* Shift up to return count-1 */ + if (x ==0) + return NSA_BITS-1; + } + if (x ==0) + return NSA_BITS; + /* Now count leading zeros */ + for (j=0, k=NSA_BITS-1; k>=0; j++, k--) { + if (TESTBIT(x,k)) + return j; + } + return NSA_BITS; +} + + + +static inline long long +orig_L40_set( long long L40_var1) { + long long L40_var_out; + + L40_var_out = L40_var1 & 0x000000ffffffffffLL; + + if( L40_var1 & 0x8000000000LL) + L40_var_out = L40_var_out | 0xffffff0000000000LL; + + return( L40_var_out); +} + + + +static inline signed long long +util_saturate_n_no_state(signed long long t, int n) +{ + signed long long maxv, minv; + maxv = (1LL << (n-1)) - 1; + minv = (-1LL << (n-1)); + if (t > maxv) { + t = maxv; + } else if (t < minv) { + t = minv; + } + return t; +} + + +static inline signed long long +util_saturate_n_sgn(signed long long t, int n) +{ + signed long long result; + signed long long maxv, minv; + maxv = (1LL << (n-1)) - 1; + minv = (-1LL << (n-1)); + if (t > 0) { + result = maxv; + _overflow = 1; + } else if (t < 0) { + result = minv; + _overflow = 1; + } else { + result = 0; + } + return result; +} + + + + +/* well-behaved signed shift right (left on negative) with + saturation */ +static inline signed long long +util_shift_right_saturate_n(signed long long t, int shval, int n) +{ + /* n should be <= 62 */ + long long result; + + signed long long mask; + int actual_shift = shval; + long long shft = actual_shift > 0 ? actual_shift : -actual_shift; + + if (t == 0 || actual_shift == 0) + return t; + + if (actual_shift >= n) { + return (t < 0) ? -1 : 0; + } + if (actual_shift <= -n) { + return util_saturate_n_sgn(t, n); + } + if (actual_shift > 0) { + return t >> actual_shift; + } + /* actual_shift < 0. Check for saturation after shift. */ + mask = (-1LL << (n-shft-1)); + if (t > 0 && ((mask & t) != 0)) { + return util_saturate_n_sgn(t, n); + } + if (t < 0 && ((mask & t) != mask)) { + return util_saturate_n_sgn(t, n); + } + result = t << shft; + + return result; +} + + +/* Implemented c6x standard C compatibility functions (alphabetical + order) */ + + +static inline int _abs(int src1) { + if ((unsigned) src1 == (unsigned) 0x80000000) { + return 0x7fffffff; + } + return abs(src1); +} + + +static inline int _abs2(int src1) { + short s1[2],r[2]; + int result; + *((int*)s1) = src1; + if ((unsigned short) s1[1] == (unsigned short) 0x8000) r[1] = 0x7fff; + else r[1] = abs(s1[1]); + if ((unsigned short) s1[0] == (unsigned short) 0x8000) r[0] = 0x7fff; + else r[0] = abs(s1[0]); + result = *(int*)r; + return result; + } + + + + +static inline int _add2(int src1, int src2) { + short s1[2], s2[2], r[2]; + int result; + *((int*)s1) = src1; + *((int*)s2) = src2; + r[0] = s1[0] + s2[0]; + r[1] = s1[1] + s2[1]; + result = *(int*)r; + return result; +} + +static inline int _add4(int src1, int src2) { + char c1[4], c2[4], r[4]; + int result; + *((int*)c1) = src1; + *((int*)c2) = src2; + r[0] = c1[0] + c2[0]; + r[1] = c1[1] + c2[1]; + r[2] = c1[2] + c2[2]; + r[3] = c1[3] + c2[3]; + result = *(int*)r; + return result; +} + + + +static inline long long _addsub(unsigned int src1, unsigned int src2) +{ + + int res_lo; + int res_hi; + + res_hi = src1+src2; + res_lo = src1-src2; + return (((unsigned long long) res_hi) << 32) | ((unsigned int) res_lo) ; +} + + +static inline long long _addsub2(unsigned int src1, unsigned int src2) +{ + short s1[2], s2[2], ra[2], rs[2]; + int res_lo; + int res_hi; + + *((int*)s1) = src1; + *((int*)s2) = src2; + ra[0] = s1[0] + s2[0]; + ra[1] = s1[1] + s2[1]; + rs[0] = s1[0] - s2[0]; + rs[1] = s1[1] - s2[1]; + + res_hi = *(int*)ra; + res_lo = *(int*)rs; + return (((unsigned long long) res_hi) << 32) | ((unsigned int) res_lo) ; +} + + +static inline int _avg2(int src1, int src2) { + int low = (((int)1 + (short) src1 + (short) src2) >> 1) & 0XFFFF; + int high1 = src1 >> 16; + int high2 = src2 >> 16; + int high = ((high1 + high2 + 1) >> 1)<< 16; + return high | low; +} + + + +static inline unsigned int _avgu4(unsigned int src1, unsigned int src2) { +unsigned int res0 = ((src1 & 0xFF) + (src2 & 0xFF) + 1) >> 1; + unsigned int res1 = (((src1 & 0xFF00) >> 8) + ((src2 & 0xFF00) >> 8) + 1) >> 1; + unsigned int res2 = (((src1 & 0xFF0000) >> 16) + ((src2 & 0xFF0000) >> 16) + 1) >> 1; + unsigned int res3 = (((src1 & 0xFF000000) >> 24) + ((src2 & 0xFF000000) >> 24) + 1) >> 1; + return (res3 << 24) | (res2 << 16) | (res1 << 8) | res0; +} + + +static inline int TEN_popc (unsigned char b) +{ + int i, result = 0; + for (i = 0; i < 8; i++){ + if (b & 0x1) + result++; + b >>= 1; + } + return result; +} + +static inline unsigned int _bitc4(unsigned int src1) +{ + unsigned int res0 = TEN_popc(src1 & 0xFF); + unsigned int res1 = TEN_popc((src1 & 0xFF00) >> 8); + unsigned int res2 = TEN_popc((src1 & 0xFF0000) >> 16); + unsigned int res3 = TEN_popc((src1 & 0xFF000000) >> 24); + return (res3 << 24) | (res2 << 16) | (res1 << 8) | res0; +} + +static inline unsigned int _bitr(unsigned int src) { + int i; + unsigned r = 0; + for (i = 0; i< 32; ++i) { + r = r | (((src >> i) & 1)<<(31-i)); + } + return r; +} + + +static inline unsigned int _clr(unsigned int src2, int csta, int cstb) +{ + csta &= 0x1f; + cstb &= 0x1f; + if (csta > cstb) + return src2; + else { + unsigned int mask = (((1 << (cstb - csta)) << 1) - 1) << csta; + return src2 & (~mask); + } +} + +static inline unsigned int _clrr(unsigned int src2, int src1) +{ + unsigned int csta = (src1 >> 5) & 0x1f; + unsigned int cstb = src1 & 0x1f; + if (csta > cstb) + return src2; + else { + unsigned int mask = (((1 << (cstb - csta)) << 1) - 1) << csta; + return src2 & (~mask); + } +} + + + + +static inline int _cmpeq2(int src1, int src2) { + short s1[2], s2[2]; + int r0, r1; + int result; + *((int*)s1) = src1; + *((int*)s2) = src2; + r0 = s1[0] == s2[0] ? 1 : 0; + r1 = s1[1] == s2[1] ? 1 : 0; + result = (r1 << 1) | r0; + return result; +} + +static inline int _cmpeq4(int src1, int src2) { + char s1[4], s2[4]; + int r0, r1, r2, r3; + int result; + *((int*)s1) = src1; + *((int*)s2) = src2; + r0 = s1[0] == s2[0] ? 1 : 0; + r1 = s1[1] == s2[1] ? 1 : 0; + r2 = s1[2] == s2[2] ? 1 : 0; + r3 = s1[3] == s2[3] ? 1 : 0; + result = (r3 << 3) | (r2 << 2) | (r1 << 1) | r0; + return result; +} + + +static inline int _cmpgt2(int src1, int src2) { + short s1[2], s2[2]; + int r1, r0; + int result; + *((int*)s1) = src1; + *((int*)s2) = src2; + r0 = s1[0] > s2[0] ? 1 : 0; + r1 = s1[1] > s2[1] ? 1 : 0; + result = (r1<<1) | r0; + return result; +} + + +static inline unsigned int _cmpgtu4(unsigned int src1, unsigned int src2) { + unsigned int s1_0 = (src1 & 0xFF); + unsigned int s1_1 = (src1 & 0xFF00) >> 8; + unsigned int s1_2 = (src1 & 0xFF0000) >> 16; + unsigned int s1_3 = (src1 & 0xFF000000) >> 24; + + unsigned int s2_0 = (src2 & 0xFF); + unsigned int s2_1 = (src2 & 0xFF00) >> 8; + unsigned int s2_2 = (src2 & 0xFF0000) >> 16; + unsigned int s2_3 = (src2 & 0xFF000000) >> 24; + + unsigned int result = 0; + + if (s1_0 > s2_0) + result |= 0x1; + + if (s1_1 > s2_1) + result |= 0x2; + + if (s1_2 > s2_2) + result |= 0x4; + + if (s1_3 > s2_3) + result |= 0x8; + + return result; +} + + + + +static inline long long _ddotp4(unsigned int src1, unsigned int src2) { + unsigned int res0, res1; + short s1_0 = (src1 & 0xffff); + short s1_1 = (src1 & 0xfff0000) >> 16; + + unsigned short s2_0 = (src2 & 0xff); + unsigned short s2_1 = (src2 & 0xff00) >> 8; + unsigned short s2_2 = (src2 & 0xff0000) >> 16; + unsigned short s2_3 = (src2 & 0xff000000) >> 24; + + res0 = ((int)s1_0) * s2_0 + ((int)s1_1) * s2_1; + res1 = ((int)s1_0) * s2_2 + ((int)s1_1) * s2_3; + + return (res1 << 16) | res0; +} + + +static inline long long _ddotph2(long long src1_o_src1_e, unsigned int src2) +{ + + unsigned int src1_o = src1_o_src1_e >> 32; + unsigned int src1_e = src1_o_src1_e & 0xFFFFFFFF; + short ls1_o = src1_o & 0XFFFF; + short hs1_o = src1_o >> 16; +// short ls1_e = src1_e & 0XFFFF; + short hs1_e = src1_e >> 16; + short ls2 = src2 & 0XFFFF; + short hs2 = src2 >> 16; + + unsigned long long res_hi = ls2 * ls1_o + hs2 * hs1_o; + unsigned int res_lo = ls1_o * hs2 + hs1_e * ls2; + return (res_hi << 32) | res_lo; +} + + +static inline long long _ddotpl2(long long src1_o_src1_e, unsigned int src2) +{ + unsigned int src1_o = src1_o_src1_e >> 32; + unsigned int src1_e = src1_o_src1_e & 0xFFFFFFFF; + short ls1_o = src1_o & 0XFFFF; +// short hs1_o = src1_o >> 16; + short ls1_e = src1_e & 0XFFFF; + short hs1_e = src1_e >> 16; + short ls2 = src2 & 0XFFFF; + short hs2 = src2 >> 16; + + unsigned long long res_hi = ls2 * hs1_e + hs2 * ls1_o; + unsigned res_lo = hs1_e * hs2 + ls1_e * ls2; + return (res_hi << 32) | res_lo; +} + + +static inline unsigned int _deal(unsigned int src) +{ + int i; + unsigned short lo = 0, hi = 0; + for (i = 0; i < 32; i+= 2) { + lo >>= 1; + lo |= (src & 0x1) << 15; + src >>= 1; + hi >>= 1; + hi |= (src & 0x1) << 15; + src >>= 1; + } + return (hi << 16) | lo; +} + + +static inline long long _dmv(unsigned int src1, unsigned int src2) +{ + return (((long long) src1) << 32) | src2; +} + + +static inline int _dotpn2(int src1, int src2) { +short int s1_h = src1>>16; + short int s1_l = src1; + short int s2_h = src2>>16; + short int s2_l = src2; + return s1_h * s2_h - s1_l * s2_l; +} + + +static inline int _dotp2(int src1, int src2) { + short int s1_h = src1>>16; + short int s1_l = src1; + short int s2_h = src2>>16; + short int s2_l = src2; + return s1_h * s2_h + s1_l * s2_l; +} + + + +static inline int _dotpnrsu2(int src1, unsigned int src2) +{ + short ls1 = src1 & 0XFFFF; + unsigned short ls2 = src2 & 0XFFFF; + short hs1 = src1 >> 16; + unsigned short hs2 = src2 >> 16; + + int result = (((long long) (int)(hs1 * hs2)) - ((long long) (int)(ls1 * ls2)) + (1 << 15)) >> 16; + return result; +} + + + +static inline int _dotprsu2(int src1, unsigned int src2) { + short ls1 = src1 & 0XFFFF; + unsigned short ls2 = (src2 & 0XFFFF); + short hs1 = src1 >> 16; + unsigned short hs2 = (src2 >> 16); + + int result = (((long long) (int) (ls1 * ls2)) + ((long long) (int) (hs1 * hs2)) + (1LL << 15)) >> 16; + return result; +} + + + + + + + +static inline int _dotpsu4(int src1, unsigned int src2) { + int result; + signed char s1_0 = (src1 & 0xff); + signed char s1_1 = (src1 & 0xff00) >> 8; + signed char s1_2 = (src1 & 0xff0000) >> 16; + signed char s1_3 = (src1 & 0xff000000) >> 24; + + unsigned int s2_0 = (src2 & 0xff); + unsigned int s2_1 = (src2 & 0xff00) >> 8; + unsigned int s2_2 = (src2 & 0xff0000) >> 16; + unsigned int s2_3 = (src2 & 0xff000000) >> 24; + + result = s1_0 * s2_0 + s1_1 * s2_1 + s1_2 * s2_2 + s1_3 * s2_3; + return result; +} + + +static inline unsigned int _dotpu4(unsigned int src1, unsigned int src2) { + unsigned char v1_0 = src1 & 0xff; + unsigned char v1_1 = (src1>>8) & 0xff; + unsigned char v1_2 = (src1>>16) & 0xff; + unsigned char v1_3 = (src1>>24) & 0xff; + + unsigned char v2_0 = src2 & 0xff; + unsigned char v2_1 = (src2>>8) & 0xff; + unsigned char v2_2 = (src2>>16) & 0xff; + unsigned char v2_3 = (src2>>24) & 0xff; + + unsigned v = v1_0 * v2_0 + v1_1 * v2_1 + v1_2 * v2_2 + v1_3 * v2_3; + return v; +} + + +static inline long long _dpack2(unsigned int src1, unsigned int src2){ +unsigned short s1[2], s2[2]; +*((int*)s1) = src1; +*((int*)s2) = src2; +return ((unsigned long long) s1[1] << 48) | ((unsigned long long) s2[1] << 32) | ((unsigned long long) s1[0] << 16) | ((unsigned long long) s2[0]); +} + + +static inline long long _dpackx2(unsigned int src1, unsigned int src2){ +unsigned short s1[2], s2[2]; +*((int*)s1) = src1; +*((int*)s2) = src2; +return ((unsigned long long) s2[0] << 48) | ((unsigned long long) s1[1] << 32) | ((unsigned long long) s1[0] << 16) | ((unsigned long long) s2[1]); +} + +static inline int _ext(int src2, unsigned int csta, unsigned int cstb) +{ + return (src2 << csta) >> cstb; +} + +static inline int _extr(int src2, int src1) +{ + unsigned int csta = (src1 >> 5) & 0x1f; + unsigned int cstb = src1 & 0x1f; + return (src2 << csta) >> cstb; +} + +static inline unsigned int _extu(unsigned int src2, unsigned int csta, unsigned int cstb) +{ + return (src2 << csta) >> cstb; +} + +static inline unsigned int _extur(unsigned int src2, int src1) +{ + unsigned int csta = (src1 >> 5) & 0x1f; + unsigned int cstb = src1 & 0x1f; + return (src2 << csta) >> cstb; +} + + +static inline unsigned long long _hi(double src) { + unsigned long long v; + *(double*)&v = src; + return v>>32; +} + +static inline unsigned int _hill (long long src) +{ + return (unsigned int) (src >> 32); +} + + + +static inline double _itod(unsigned hi, unsigned lo) { + double v; + unsigned long long ll = ((((unsigned long long)(hi))<<32) | (unsigned long long)((unsigned)lo)); + *((unsigned long long *)&v) = ll; + return v; +} + + +static inline long long _itoll(unsigned int src2, unsigned int src1) +{ + return (((long long) src2) << 32) | src1; +} + + +static inline C6X_COMPAT_LONG40 _labs(C6X_COMPAT_LONG40 src2) +{ + long long maxv = (1LL << (40 -1)) - 1; + long long minv = (-1LL << (40 - 1)); + C6X_COMPAT_LONG40 lres = orig_L40_set(src2); + + lres = lres < 0 ? -lres : lres; + if (lres > maxv) lres = maxv; + else if (lres < minv) lres = minv; + + return lres; +} + + +static inline C6X_COMPAT_LONG40 _ldotp2(int src1, int src2) { +return (C6X_COMPAT_LONG40) _dotp2(src1, src2); +} + + +static inline unsigned int _lmbd(unsigned int src1, unsigned int src2) +{ + return norm_shift_amt_U_and_non_U(0,(((int) (src1 << 31)) >> 31) ^ (~src2)); +} + + +static inline unsigned int _lnorm(C6X_COMPAT_LONG40 src2) { +if (src2 == 0) + return 39; + else { + int hi = (int)(src2 >> 32); + int lo = (int)src2; + + + long long temp = (unsigned long long)(unsigned)lo | (unsigned long long)hi << 32; + temp = orig_L40_set(temp); + + if (temp == 0) return 0; + int cnt = 0; + while (((temp >> 39) & 1) == ((temp >> 38) & 1)) { + temp <<= 1; + cnt++; + } + return cnt; + } +} + + +static inline unsigned long long _lo(double src) { + unsigned long long v; + *(double*)&v = src; + return v; +} + + +static inline unsigned int _loll (long long src) +{ + return (unsigned int) src; +} + + +static inline C6X_COMPAT_LONG40 _lsadd(int src1, C6X_COMPAT_LONG40 src2) +{ + long long maxv = (1LL << (40 -1)) - 1; + long long minv = (-1LL << (40 - 1)); + int hi = (int)(src2 >> 32); + int lo = (int)src2; + long long src2_int = (unsigned long long)(unsigned)lo | (unsigned long long)hi << 32; + + + long long src2_int2 = orig_L40_set(src2_int); + + long long res = src1 + src2_int2; + + if (res > maxv) { + res = maxv; + _overflow = 1; + } + else if (res < minv) { + res = minv; + _overflow = 1; + } + + long long res2 = orig_L40_set(res); + + res2 = (signed char)(res2 >> 32); + + C6X_COMPAT_LONG40 lres = (((C6X_COMPAT_LONG40) res2) << 32) | ((unsigned int)res); + return lres; +} + + + +static inline int _max2 (int src1, int src2) { + short s1[2], s2[2], r[2]; + int result; + *((int*)s1) = src1; + *((int*)s2) = src2; + r[0] = s1[0] > s2[0] ? s1[0] : s2[0]; + r[1] = s1[1] > s2[1] ? s1[1] : s2[1]; + result = *(int*)r; + return result; +} + + + + + + +static inline unsigned int _maxu4(unsigned int src1, unsigned int src2) { + unsigned int res0, res1, res2, res3; + unsigned int s1_0 = res0 = (src1 & 0xFF); + unsigned int s1_1 = res1 = (src1 & 0xFF00) >> 8; + unsigned int s1_2 = res2 = (src1 & 0xFF0000) >> 16; + unsigned int s1_3 = res3 = (src1 & 0xFF000000) >> 24; + + unsigned int s2_0 = (src2 & 0xFF); + unsigned int s2_1 = (src2 & 0xFF00) >> 8; + unsigned int s2_2 = (src2 & 0xFF0000) >> 16; + unsigned int s2_3 = (src2 & 0xFF000000) >> 24; + +// unsigned int res = 0; + + if (s1_0 < s2_0) + res0 = s2_0; + + if (s1_1 < s2_1) + res1 = s2_1; + + if (s1_2 < s2_2) + res2 = s2_2; + + if (s1_3 < s2_3) + res3 = s2_3; + + return (res3 << 24) | (res2 << 16) | (res1 << 8) | res0; + + +} + +static inline int _min2(int src1, int src2) { + short s1[2], s2[2], r[2]; + int result; + *((int*)s1) = src1; + *((int*)s2) = src2; + r[0] = s1[0] < s2[0] ? s1[0] : s2[0]; + r[1] = s1[1] < s2[1] ? s1[1] : s2[1]; + result = *(int*)r; + return result; +} + + +static inline unsigned int _minu4(unsigned int src1, unsigned int src2) { +unsigned int res0, res1, res2, res3; + unsigned int s1_0 = res0 = (src1 & 0xFF); + unsigned int s1_1 = res1 = (src1 & 0xFF00) >> 8; + unsigned int s1_2 = res2 = (src1 & 0xFF0000) >> 16; + unsigned int s1_3 = res3 = (src1 & 0xFF000000) >> 24; + + unsigned int s2_0 = (src2 & 0xFF); + unsigned int s2_1 = (src2 & 0xFF00) >> 8; + unsigned int s2_2 = (src2 & 0xFF0000) >> 16; + unsigned int s2_3 = (src2 & 0xFF000000) >> 24; + +// unsigned int res = 0; + + if (s1_0 > s2_0) + res0 = s2_0; + + if (s1_1 > s2_1) + res1 = s2_1; + + if (s1_2 > s2_2) + res2 = s2_2; + + if (s1_3 > s2_3) + res3 = s2_3; + + return (res3 << 24) | (res2 << 16) | (res1 << 8) | res0; +} + + +static inline int _mpy(int src1, int src2) { +return (short) src1 * (short) src2; +} + + +static inline int _mpyh(int src1, int src2) { +return (short) (src1 >> 16) * (short) (src2 >> 16); +} + + +static inline long long _mpyhill (int src1, int src2) +{ + short s1 = src1 >> 16; + return ((long long) src2) * s1; +} + +static inline int _mpyhir(int src1, int src2) +{ + short s1 = src1 >> 16; + long long result = ((long long) src2) * s1 + (1 << 14); + result >>= 15; + return result; +} + + +static inline int _mpyhl(int src1, int src2) { +return (short) (src1 >> 16) * (short) (src2); +} + +static inline unsigned int _mpyhlu(unsigned int src1, unsigned int src2) { +return (unsigned short) (src1 >> 16) * (unsigned short) (src2); +} + +static inline int _mpyhslu(int src1, unsigned int src2) { +return (short) (src1 >> 16) * (unsigned short) src2; +} + + +static inline int _mpyhsu(int src1, unsigned int src2) { +return (short) (src1 >>16) * (unsigned short) (src2 >>16); +} + + +static inline unsigned int _mpyhu(unsigned int src1, unsigned int src2) { +return (unsigned short) (src1 >>16) * (unsigned short) (src2 >> 16); +} + + +static inline int _mpyhuls(unsigned int src1, int src2) { +return (unsigned short) (src1 >>16) * (signed short) (src2); +} + + +static inline int _mpyhus(unsigned int src1, int src2) { +return (unsigned short) (src1 >> 16) * (short) (src2 >>16); +} + + + +static inline long long _mpyidll (int src1, int src2) +{ + return (long long) src1 * src2; +} + + +static inline int _mpylh(int src1, int src2) { +return (signed short) (src1 & 0xffff) * (signed short) (src2 >> 16); +} + +static inline unsigned int _mpylhu(unsigned int src1, unsigned int src2) { +return (unsigned short) src1 * (unsigned short) (src2 >> 16); +} + + +static inline long long _mpylill (int src1, int src2) +{ + return ((long long) src2) * ((short)src1); +} + + + +static inline int _mpylir(int src1, int src2) +{ + short s1 = src1; + long long result = ((long long) src2) * s1 + (1 << 14); + result >>= 15; + return result; +} + + +static inline int _mpylshu(int src1, unsigned int src2) { +return (short) src1 * (unsigned short) (src2 >> 16); +} + + +static inline int _mpyluhs(unsigned int src1, int src2) { +return (unsigned short) src1 * (short) (src2 >> 16); +} + + + +static inline int _mpysu(int src1, unsigned int src2) { +return (short) src1 * (unsigned short) src2; +} + + + +static inline long long _mpysu4ll (int src1, unsigned int src2) { + unsigned short res0, res1, res2, res3; + signed char s1_0 = (src1 & 0xff); + signed char s1_1 = (src1 & 0xff00) >> 8; + signed char s1_2 = (src1 & 0xff0000) >> 16; + signed char s1_3 = (src1 & 0xff000000) >> 24; + + unsigned short s2_0 = (src2 & 0xff); + unsigned short s2_1 = (src2 & 0xff00) >> 8; + unsigned short s2_2 = (src2 & 0xff0000) >> 16; + unsigned short s2_3 = (src2 & 0xff000000) >> 24; + + res0 = s1_0 * s2_0; + res1 = s1_1 * s2_1; + res2 = s1_2 * s2_2; + res3 = s1_3 * s2_3; + + return (((unsigned long long) res3) << 48) + | (((unsigned long long) res2) << 32) + | (((unsigned long long) res1) << 16) + | res0; +} + +static inline unsigned int _mpyu(unsigned int src1, unsigned int src2) { + unsigned v = (unsigned short)src1 * (unsigned short)src2; + return v; +} + +static inline int _mpyus(unsigned int src1, int src2) { +return (unsigned short) src1 * (short) src2; +} + +static inline long long _mpyu4ll (unsigned int src1, unsigned int src2) { + unsigned short res0, res1, res2, res3; + unsigned char s1_0 = (src1 & 0xff); + unsigned char s1_1 = (src1 & 0xff00) >> 8; + unsigned char s1_2 = (src1 & 0xff0000) >> 16; + unsigned char s1_3 = (src1 & 0xff000000) >> 24; + + unsigned short s2_0 = (src2 & 0xff); + unsigned short s2_1 = (src2 & 0xff00) >> 8; + unsigned short s2_2 = (src2 & 0xff0000) >> 16; + unsigned short s2_3 = (src2 & 0xff000000) >> 24; + + res0 = s1_0 * s2_0; + res1 = s1_1 * s2_1; + res2 = s1_2 * s2_2; + res3 = s1_3 * s2_3; + + return (((unsigned long long) res3) << 48) + | (((unsigned long long) res2) << 32) + | (((unsigned long long) res1) << 16) + | res0; +} + + +static inline long long _mpy2ir(unsigned int src1, unsigned int src2) +{ + if ((src1 == 0x8000) && (src2 == 0x80000000)) { + _overflow = 1; + return 0; + } + else { + short ls1 = src1 & 0xffff; + short hs1 = src1 >> 16; + unsigned long long hi = (((long long) hs1) * (int) src2 + (1 << 14)) >> 15; + unsigned long long lo = ((((long long) ls1) * (int) src2 + (1 << 14)) >> 15) & 0xFFFFFFFF; + return (hi << 32) | lo; + } +} + + +static inline long long _mpy2ll (int src1, int src2) { + short ls1 = src1 & 0xffff; + short hs1 = src1 >> 16; + short ls2 = src2 & 0xffff; + short hs2 = src2 >> 16; + + unsigned long long hi = hs1 * hs2; + unsigned long long lo = (ls1 * ls2) & 0xFFFFFFFF; + + return (hi << 32) | lo; + +} + + +static inline int _mpy32(int src1, int src2) +{ + return src1 * src2; +} + + +static inline long long _mpy32ll(int src1, int src2) +{ + return ((long long) src1) * src2; +} + +static inline long long _mpy32su(int src1, unsigned int src2) +{ + return ((long long) src1) * ((int) src2); +} + +static inline long long _mpy32u(unsigned int src1, unsigned int src2) +{ + return ((long long) ((int) src1)) * ((long long) ((int) src2)); +} + +static inline long long _mpy32us(unsigned int src1, int src2) +{ + return ((int) src1) * ((long long) src2); +} + +static inline int _mvd (int src2) +{ + return src2; +} + + +static inline unsigned int _norm(int src2) +{ + return norm_shift_amt_U_and_non_U(1,src2); +} + + +static inline unsigned int _pack2 (unsigned int src1, unsigned int src2) { + short s1[2], s2[2], r[2]; + int result; + *((int*)s1) = src1; + *((int*)s2) = src2; + r[0] = s2[0]; + r[1] = s1[0]; + result = *(int*)r; + return result; +} + + +static inline int _packh2 (unsigned int src1, unsigned int src2) { + unsigned v0 = src1 & 0xffff0000; + unsigned v1 = src2 >> 16; + unsigned v = v0|v1; + return v; + +} + +static inline unsigned int _packh4 (unsigned int src1, unsigned int src2) { + unsigned v3 = (src1 >> 24) & 0xff; + unsigned v2 = (src1 >> 8) & 0xff; + unsigned v1 = (src2 >> 24) & 0xff; + unsigned v0 = (src2 >> 8) & 0xff; + unsigned v = (v3<<24) | (v2<<16) | (v1 << 8) | v0; + return v; +} + +static inline unsigned int _packhl2 (unsigned int src1, unsigned int src2) { + unsigned v0 = src1 & 0xffff0000; + unsigned v1 = src2 & 0x0000ffff; + unsigned v = v0|v1; + return v; +} + +static inline unsigned int _packlh2 (unsigned int src1, unsigned int src2) { + unsigned v0 = src1 << 16; + unsigned v1 = (src2 >> 16) & 0xffff; + unsigned v = v0|v1; + return v; +} + + + + +static inline unsigned int _packl4 (unsigned int src1, unsigned int src2) { + unsigned v3 = (src1 >> 16) & 0xff; + unsigned v2 = (src1) & 0xff; + unsigned v1 = (src2 >> 16) & 0xff; + unsigned v0 = (src2) & 0xff; + unsigned v = (v3<<24) | (v2<<16) | (v1 << 8) | v0; + return v; +} + + + + +static inline unsigned int _rpack2 (unsigned int src1, unsigned int src2) { +int s1 = (int) src1; +int s2 = (int) src2; +s1 = util_shift_right_saturate_n (s1, -1, 32); +s2 = util_shift_right_saturate_n (s2, -1, 32); +return (unsigned int) (s1 & 0xffff0000) | (unsigned int) ((s2 & 0xffff0000) >>16); +} + + +static inline unsigned int _rotl (unsigned int src1, unsigned int src2) +{ + src2 &= 0x1f; + return (src1 << src2) | (src1 >> (32 - src2)); +} + + +static inline int _sadd(int src1, int src2) { +signed long long res; +signed long long maxv, minv; +maxv = (1LL << (32-1)) - 1; +minv = (-1LL << (32-1)); +res = (long long) src1 + (long long) src2; +if (res > maxv) { + res = maxv; + _overflow = 1; + } +else if (res < minv ) { + res = minv; + _overflow = 1; + } +return (int) res; +} + +static inline long long _saddsub(unsigned int src1, unsigned int src2) { +int radd; +signed long long rsub; + +signed long long maxv, minv; +maxv = (1LL << (32-1)) - 1; +minv = (-1LL << (32-1)); + +radd = (int) src1 + (int) src2; + +// saturate on subtract, not add + + +rsub = (long long) ((int) src1) - (long long) ((int) src2); +if (rsub > maxv) { + rsub = maxv; + /* NOTE: TI c6x does NOT set the overflow register even if results saturate */ + /* _overflow = 1; */ + } +else if (rsub < minv ) { + rsub = minv; + /* NOTE: TI c6x does NOT set the overflow register even if results saturate */ + /* _overflow = 1; */ + } + +return (((unsigned long long) radd) << 32) | ( rsub & 0x00000000ffffffff ) ; +} + + + +static inline long long _saddsub2(unsigned int src1, unsigned int src2) { +signed int radd[2]; +signed int rsub[2]; +signed short s1[2], s2[2]; + +signed int maxv, minv; +maxv = (1L << (16-1)) - 1; +minv = (-1L << (16-1)); + +*((int*)s1) = src1; +*((int*)s2) = src2; + +radd[0] = (int) s1[0] + (int) s2[0]; +radd[1] = (int) s1[1] + (int) s2[1]; + +rsub[0] = (int) s1[0] - (int) s2[0]; +rsub[1] = (int) s1[1] - (int) s2[1]; + +if (radd[0] > maxv) { + radd[0] = maxv; + /* NOTE: TI c6x does NOT set the overflow register even if results saturate */ + /* _overflow = 1; */ + } +else if (radd[0] < minv ) { + radd[0] = minv; + /* NOTE: TI c6x does NOT set the overflow register even if results saturate */ + /* _overflow = 1; */ + } + +if (radd[1] > maxv) { + radd[1] = maxv; + /* NOTE: TI c6x does NOT set the overflow register even if results saturate */ + /* _overflow = 1; */ + } +else if (radd[1] < minv ) { + radd[1] = minv; + /* NOTE: TI c6x does NOT set the overflow register even if results saturate */ + /* _overflow = 1; */ + } + + +if (rsub[0] > maxv) { + rsub[0] = maxv; + /* NOTE: TI c6x does NOT set the overflow register even if results saturate */ + /* _overflow = 1; */ + } +else if (rsub[0] < minv ) { + rsub[0] = minv; + /* NOTE: TI c6x does NOT set the overflow register even if results saturate */ + /* _overflow = 1; */ + } + +if (rsub[1] > maxv) { + rsub[1] = maxv; + /* NOTE: TI c6x does NOT set the overflow register even if results saturate */ + /* _overflow = 1; */ + } +else if (rsub[1] < minv ) { + rsub[1] = minv; + /* NOTE: TI c6x does NOT set the overflow register even if results saturate */ + /* _overflow = 1; */ + } + + +return ((((unsigned long long) radd[1]) & 0x000000000000ffff) << 48) | + ((((unsigned long long) radd[0]) & 0x000000000000ffff) << 32) | + ((((unsigned long long) rsub[1]) & 0x000000000000ffff) << 16) | + ((((unsigned long long) rsub[0]) & 0x000000000000ffff)); +} + + + +static inline int _sadd2(int src1, int src2) { +signed short s1[2], s2[2]; +signed int r[2], maxv, minv; + +maxv = (1L << (16-1)) - 1; +minv = (-1L << (16-1)); + + +*((int*)s1) = src1; +*((int*)s2) = src2; + +r[0] = (int) s1[0] + (int) s2[0]; +r[1] = (int) s1[1] + (int) s2[1]; + +if (r[0] > maxv) { + r[0] = maxv; + /* NOTE: TI c6x does NOT set the overflow register even if results saturate */ + /* _overflow = 1; */ + } +else if (r[0] < minv ) { + r[0] = minv; + /* NOTE: TI c6x does NOT set the overflow register even if results saturate */ + /* _overflow = 1; */ + } +if (r[1] > maxv) { + r[1] = maxv; + /* NOTE: TI c6x does NOT set the overflow register even if results saturate */ + /* _overflow = 1; */ + } +else if (r[1] < minv ) { + r[1] = minv; + /* NOTE: TI c6x does NOT set the overflow register even if results saturate */ + /* _overflow = 1; */ + } + +return ((r[1] & 0xffff) << 16 ) | (r[0] & 0xffff) ; +} + + +static inline int _saddus2(unsigned int src1, int src2) { +int res0, res1; + unsigned int s1_0 = (src1 & 0xffff); + unsigned int s1_1 = (src1 & 0xffff0000) >> 16; + + short s2_0 = (src2 & 0xffff); + short s2_1 = (src2 & 0xffff0000) >> 16; + + res0 = s1_0 + s2_0; + res1 = s1_1 + s2_1; + + if (res0 >= 0x10000) + res0 = 0xffff; + else if (res0 < 0) + res0 = 0; + + if (res1 >= 0x10000) + res1 = 0xffff; + else if (res1 < 0) + res1 = 0; + + return (res1 << 16) | res0; +} + + +static inline unsigned int _saddu4(unsigned int src1, unsigned int src2) { +unsigned int res0, res1, res2, res3; + unsigned int s1_0 = (src1 & 0xff); + unsigned int s1_1 = (src1 & 0xff00) >> 8; + unsigned int s1_2 = (src1 & 0xff0000) >> 16; + unsigned int s1_3 = (src1 & 0xff000000) >> 24; + + unsigned int s2_0 = (src2 & 0xff); + unsigned int s2_1 = (src2 & 0xff00) >> 8; + unsigned int s2_2 = (src2 & 0xff0000) >> 16; + unsigned int s2_3 = (src2 & 0xff000000) >> 24; + + res0 = s1_0 + s2_0; + res1 = s1_1 + s2_1; + res2 = s1_2 + s2_2; + res3 = s1_3 + s2_3; + + if (res0 >= 0x100) + res0 = 0xff; + + if (res1 >= 0x100) + res1 = 0xff; + + if (res2 >= 0x100) + res2 = 0xff; + + if (res3 >= 0x100) + res3 = 0xff; + + return (res3 << 24) | (res2 << 16) | (res1 << 8) | res0; + +} + + + +static inline int _sat(C6X_COMPAT_LONG40 src2) +{ + long long maxv = (1LL << (32-1)) - 1; + long long minv = (-1LL << (32-1)); + + int hi = (int)(src2 >> 32); + int lo = (int)src2; + long long temp = (unsigned long long)(unsigned)lo | (unsigned long long)hi << 32; + temp = orig_L40_set(temp); + + if (temp > maxv) { + temp = maxv; + _overflow = 1; + } + else if (temp < minv) { + temp = minv; + _overflow = 1; + } + return (int) temp; +} + +static inline unsigned int _set(unsigned int src2, unsigned int csta, unsigned int cstb) +{ + csta &= 0x1f; + cstb &= 0x1f; + if (csta > cstb) + return src2; + else { + unsigned int mask = (((1 << (cstb - csta)) << 1) - 1) << csta; + return src2 | mask; + } +} + +static inline unsigned int _setr(unsigned int src2, int src1) +{ + unsigned int csta = (src1 >> 5) & 0x1f; + unsigned int cstb = src1 & 0x1f; + if (csta > cstb) + return src2; + else { + unsigned int mask = (((1 << (cstb - csta)) << 1) - 1) << csta; + return src2 | mask; + } +} + + +static inline unsigned int _shfl (unsigned int src2) +{ + unsigned short lo = src2; + unsigned short hi = src2 >> 16; + unsigned int result = 0; + int i; + for (i = 0; i < 32; i+= 2) { + result >>= 1; + result |= (lo & 0x1) << 31; + lo >>= 1; + result >>= 1; + result |= (hi & 0x1) << 31; + hi >>= 1; + } + return result; +} + +static inline long long _shfl3 (unsigned int src1, unsigned int src2) +{ + unsigned short lo = src2; + unsigned short hi = src1 >> 16; + unsigned short mid = src1; + unsigned long long result = 0; + int i; + for (i = 0; i < 32; i+= 2) { + result >>= 1; + result |= ((unsigned long long) (lo & 0x1)) << 47; + lo >>= 1; + result >>= 1; + result |= ((unsigned long long) (mid & 0x1)) << 47; + mid >>= 1; + result >>= 1; + result |= ((unsigned long long) (hi & 0x1)) << 47; + hi >>= 1; + } + return result; +} + + + +static inline unsigned int _shlmb (unsigned int src1, unsigned int src2) +{ + return (src2 << 8) | (src1 >> 24); +} + +static inline unsigned int _shrmb (unsigned int src1, unsigned int src2) +{ + return (src2 >> 8) | (src1 << 24); +} + + +static inline unsigned int _shru2 (unsigned int src1, unsigned int src2) { +unsigned short hs1 = src1 >> 16; + unsigned short ls1 = src1 & 0xFFFF; + hs1 >>= src2; + ls1 >>= src2; + return (hs1 << 16) | ls1; +} + + +static inline int _shr2 (int src1, unsigned int src2) { + short s1[2], result[2]; + *((int*)s1) = src1; + src2 = src2 & 31; + result[0] = (int)s1[0] >> src2; + result[1] = (int)s1[1] >> src2; + + return *(int*)result; +} + + +static inline int _smpy (int src1, int src2) { +unsigned long long result; +result = (((short) src1 * (short) src2) << 1); + +if ((result & 0xffffffff) == 0x80000000){ + result = 0x7fffffff; + _overflow = 1; + } +return (int) (result); +} + +static inline int _smpyh (int src1, int src2) { +unsigned long long result; +result = ((short) (src1 >> 16) * (short) (src2 >> 16)) << 1; +if ((result & 0xffffffff) == 0x80000000){ + result = 0x7fffffff; + _overflow = 1; + } +return (int) (result); +} + +static inline int _smpyhl (int src1, int src2) { +unsigned long long result; +result = ((short) (src1 >> 16) * (short) (src2)) << 1; +if ((result & 0xffffffff) == 0x80000000){ + result = 0x7fffffff; + _overflow = 1; + } +return (int) (result); +} + +static inline int _smpylh (int src1, int src2) { +unsigned long long result; +result = ((short) (src1) * (short) (src2 >> 16)) << 1; +if ((result & 0xffffffff) == 0x80000000){ + result = 0x7fffffff; + _overflow = 1; + } +return (int) (result); +} + +static inline long long _smpy2ll (int src1, int src2) { + short ls1 = src1 & 0XFFFF; + short hs1 = src1 >> 16; + short ls2 = src2 & 0XFFFF; + short hs2 = src2 >> 16; + + unsigned long long hi = (hs1 * hs2) << 1; + unsigned long long lo = ((ls1 * ls2) << 1) & 0xFFFFFFFF; + if ((hi & 0xffffffff) == 0x80000000){ + hi = 0x7fffffff; + _overflow = 1; + } + + if ((lo & 0xffffffff) == 0x80000000){ + lo = 0x7fffffff; + _overflow = 1; + } + + return (hi << 32) | lo; +} + + + + +static inline int _smpy32(int src1, int src2) +{ + long long res = (long long) src1 * src2; + res <<= 1; + res >>= 32; + return res; +} + +static inline unsigned char TEN_satu8 (short src) +{ + if (src > 0xff) + return 0xff; + else if (src < 0) + return 0; + else + return src; +} + +static inline int _spack2 (int src1, int src2) { +short s1 = (short) util_saturate_n_no_state(src1,16); +short s2 = (short) util_saturate_n_no_state(src2,16); +return ( (unsigned int) s1 << 16) | (((int) s2) & 0xFFFF); +} + + +static inline unsigned int _spacku4 (int src1, int src2) { + short lolo = src2; + short lohi = src2 >> 16; + short hilo = src1; + short hihi = src1 >> 16; + + lolo = TEN_satu8(lolo); + lohi = TEN_satu8(lohi); + hilo = TEN_satu8(hilo); + hihi = TEN_satu8(hihi); + + return (((unsigned int) hihi) << 24) | (((unsigned int) hilo) << 16) | (lohi << 8) | lolo; +} + + + +static inline int _sshl (int src1, unsigned int src2) { +short local2 = (short)(src2 & 0x7FFF); +return (int) util_shift_right_saturate_n(src1, -local2, 32); +} + + + + +static inline int _sshvl (int src2, int src1) { + short s1; + if (src1 > 31) + s1 = 31; + else if (src1 < -31) + s1 = -31; + else + s1 = src1; + + return (int) util_shift_right_saturate_n(src2, -s1, 32); +} + + + + + +static inline int _sshvr (int src2, int src1) { +short s1; + if (src1 > 31) + s1 = 31; + else if (src1 < -31) + s1 = -31; + else + s1 = src1; + return (int) util_shift_right_saturate_n(src2, s1, 32); +} + + + + +static inline int _ssub(int src1, int src2) { +signed long long res; +signed long long maxv, minv; +maxv = (1LL << (32-1)) - 1; +minv = (-1LL << (32-1)); +res = (long long) src1 - (long long) src2; +if (res > maxv) { + res = maxv; + _overflow = 1; + } +else if (res < minv ) { + res = minv; + _overflow = 1; + } +return (int) res; +} + +static inline int _ssub2(int src1, int src2) { +signed short s1[2], s2[2]; +signed int r[2], maxv, minv; + +maxv = (1L << (16-1)) - 1; +minv = (-1L << (16-1)); + + +*((int*)s1) = src1; +*((int*)s2) = src2; + +r[0] = (int) s1[0] - (int) s2[0]; +r[1] = (int) s1[1] - (int) s2[1]; + +if (r[0] > maxv) { + r[0] = maxv; + /* NOTE: TI c6x does NOT set the overflow register even if results saturate */ + /* _overflow = 1; */ + } +else if (r[0] < minv ) { + r[0] = minv; + /* NOTE: TI c6x does NOT set the overflow register even if results saturate */ + /* _overflow = 1; */ + } +if (r[1] > maxv) { + r[1] = maxv; + /* NOTE: TI c6x does NOT set the overflow register even if results saturate */ + /* _overflow = 1; */ + } +else if (r[1] < minv ) { + r[1] = minv; + /* NOTE: TI c6x does NOT set the overflow register even if results saturate */ + /* _overflow = 1; */ + } + +return ((r[1] & 0xffff) << 16 ) | (r[0] & 0xffff) ; +} + + +static inline int _subabs4 (int src1, int src2) { + int res0, res1, res2, res3; + unsigned int s1_0 = (src1 & 0xff); + unsigned int s1_1 = (src1 & 0xff00) >> 8; + unsigned int s1_2 = (src1 & 0xff0000) >> 16; + unsigned int s1_3 = (src1 & 0xff000000) >> 24; + + unsigned int s2_0 = (src2 & 0xff); + unsigned int s2_1 = (src2 & 0xff00) >> 8; + unsigned int s2_2 = (src2 & 0xff0000) >> 16; + unsigned int s2_3 = (src2 & 0xff000000) >> 24; + + res0 = s1_0 - s2_0; + res1 = s1_1 - s2_1; + res2 = s1_2 - s2_2; + res3 = s1_3 - s2_3; + + if (res0 < 0) + res0 = -res0; + + if (res1 < 0) + res1 = -res1; + + if (res2 < 0) + res2 = -res2; + + if (res3 < 0) + res3 = -res3; + + return (res3 << 24) | (res2 << 16) | (res1 << 8) | res0; +} + + +static inline unsigned int _subc (unsigned int src1, unsigned int src2) +{ + if ( src1 >= src2) + return ((src1 - src2) << 1) + 1; + else + return src1 << 1; +} + + + +static inline int _sub2(int src1, int src2) { + short s1[2], s2[2], r[2]; + int result; + *((int*)s1) = src1; + *((int*)s2) = src2; + r[0] = s1[0] - s2[0]; + r[1] = s1[1] - s2[1]; + result = *(int*)r; + return result; +} + + +static inline int _sub4(int src1, int src2) { + char c1[4], c2[4], r[4]; + int result; + *((int*)c1) = src1; + *((int*)c2) = src2; + r[0] = c1[0] - c2[0]; + r[1] = c1[1] - c2[1]; + r[2] = c1[2] - c2[2]; + r[3] = c1[3] - c2[3]; + result = *(int*)r; + return result; +} + + +static inline int _swap4 (unsigned int src1) { + unsigned char v0 = src1; + unsigned char v1 = src1 >> 8; + unsigned char v2 = src1 >> 16; + unsigned char v3 = src1 >> 24; + unsigned v = v0<<8 | v1 | v2<<24 | v3<<16; + return v; +} + +static inline unsigned int _unpkhu4 (unsigned int src1) { + unsigned v0 = src1>>24; + unsigned v1 = (src1>>16) & 0xff; + return (v0<<16) | v1; +} + +static inline unsigned int _unpklu4 (unsigned int src1) { + unsigned v1 = (src1>>8) & 0xff; + unsigned v0 = (src1) & 0xff; + return (v1<<16) | v0; +} + + + + +static inline unsigned int _xpnd2 (unsigned int src1) { + int v0 = (src1 & 0x1) ? 0x0000ffff : 0x00000000; + int v1 = (src1 & 0x2) ? 0xffff0000 : 0x00000000; + return v0|v1; +} + +static inline unsigned int _xpnd4 (unsigned int src1) { + int v0 = (src1 & 0x1) ? 0x000000ff : 0x00000000; + int v1 = (src1 & 0x2) ? 0x0000ff00 : 0x00000000; + int v2 = (src1 & 0x4) ? 0x00ff0000 : 0x00000000; + int v3 = (src1 & 0x8) ? 0xff000000 : 0x00000000; + int r = v0|v1|v2|v3; + return r; +} + + + +// end of Implemented in alphabetical order + + +#endif /* __C6X_COMPAT__H */ diff --git a/components/esp32/include/xtensa/cacheasm.h b/components/esp32/include/xtensa/cacheasm.h new file mode 100755 index 0000000000..225e01b320 --- /dev/null +++ b/components/esp32/include/xtensa/cacheasm.h @@ -0,0 +1,962 @@ +/* + * xtensa/cacheasm.h -- assembler-specific cache related definitions + * that depend on CORE configuration + * + * This file is logically part of xtensa/coreasm.h , + * but is kept separate for modularity / compilation-performance. + */ + +/* + * Copyright (c) 2001-2014 Cadence Design Systems, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY + * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +#ifndef XTENSA_CACHEASM_H +#define XTENSA_CACHEASM_H + +#include +#include +#include +#include + +/* + * This header file defines assembler macros of the form: + * cache_ + * where is 'i' or 'd' for instruction and data caches, + * and indicates the function of the macro. + * + * The following functions are defined, + * and apply only to the specified cache (I or D): + * + * reset + * Resets the cache. + * + * sync + * Makes sure any previous cache instructions have been completed; + * ie. makes sure any previous cache control operations + * have had full effect and been synchronized to memory. + * Eg. any invalidate completed [so as not to generate a hit], + * any writebacks or other pipelined writes written to memory, etc. + * + * invalidate_line (single cache line) + * invalidate_region (specified memory range) + * invalidate_all (entire cache) + * Invalidates all cache entries that cache + * data from the specified memory range. + * NOTE: locked entries are not invalidated. + * + * writeback_line (single cache line) + * writeback_region (specified memory range) + * writeback_all (entire cache) + * Writes back to memory all dirty cache entries + * that cache data from the specified memory range, + * and marks these entries as clean. + * NOTE: on some future implementations, this might + * also invalidate. + * NOTE: locked entries are written back, but never invalidated. + * NOTE: instruction caches never implement writeback. + * + * writeback_inv_line (single cache line) + * writeback_inv_region (specified memory range) + * writeback_inv_all (entire cache) + * Writes back to memory all dirty cache entries + * that cache data from the specified memory range, + * and invalidates these entries (including all clean + * cache entries that cache data from that range). + * NOTE: locked entries are written back but not invalidated. + * NOTE: instruction caches never implement writeback. + * + * lock_line (single cache line) + * lock_region (specified memory range) + * Prefetch and lock the specified memory range into cache. + * NOTE: if any part of the specified memory range cannot + * be locked, a Load/Store Error (for dcache) or Instruction + * Fetch Error (for icache) exception occurs. These macros don't + * do anything special (yet anyway) to handle this situation. + * + * unlock_line (single cache line) + * unlock_region (specified memory range) + * unlock_all (entire cache) + * Unlock cache entries that cache the specified memory range. + * Entries not already locked are unaffected. + * + * coherence_on + * coherence_off + * Turn off and on cache coherence + * + */ + + + +/*************************** GENERIC -- ALL CACHES ***************************/ + + +/* + * The following macros assume the following cache size/parameter limits + * in the current Xtensa core implementation: + * cache size: 1024 bytes minimum + * line size: 16 - 64 bytes + * way count: 1 - 4 + * + * Minimum entries per way (ie. per associativity) = 1024 / 64 / 4 = 4 + * Hence the assumption that each loop can execute four cache instructions. + * + * Correspondingly, the offset range of instructions is assumed able to cover + * four lines, ie. offsets {0,1,2,3} * line_size are assumed valid for + * both hit and indexed cache instructions. Ie. these offsets are all + * valid: 0, 16, 32, 48, 64, 96, 128, 192 (for line sizes 16, 32, 64). + * This is true of all original cache instructions + * (dhi, ihi, dhwb, dhwbi, dii, iii) which have offsets + * of 0 to 1020 in multiples of 4 (ie. 8 bits shifted by 2). + * This is also true of subsequent cache instructions + * (dhu, ihu, diu, iiu, diwb, diwbi, dpfl, ipfl) which have offsets + * of 0 to 240 in multiples of 16 (ie. 4 bits shifted by 4). + * + * (Maximum cache size, currently 32k, doesn't affect the following macros. + * Cache ways > MMU min page size cause aliasing but that's another matter.) + */ + + + +/* + * Macro to apply an 'indexed' cache instruction to the entire cache. + * + * Parameters: + * cainst instruction/ that takes an address register parameter + * and an offset parameter (in range 0 .. 3*linesize). + * size size of cache in bytes + * linesize size of cache line in bytes (always power-of-2) + * assoc_or1 number of associativities (ways/sets) in cache + * if all sets affected by cainst, + * or 1 if only one set (or not all sets) of the cache + * is affected by cainst (eg. DIWB or DIWBI [not yet ISA defined]). + * aa, ab unique address registers (temporaries). + * awb set to other than a0 if wb type of instruction + * loopokay 1 allows use of zero-overhead loops, 0 does not + * immrange range (max value) of cainst's immediate offset parameter, in bytes + * (NOTE: macro assumes immrange allows power-of-2 number of lines) + */ + + .macro cache_index_all cainst, size, linesize, assoc_or1, aa, ab, loopokay, maxofs, awb=a0 + + // Number of indices in cache (lines per way): + .set .Lindices, (\size / (\linesize * \assoc_or1)) + // Number of indices processed per loop iteration (max 4): + .set .Lperloop, .Lindices + .ifgt .Lperloop - 4 + .set .Lperloop, 4 + .endif + // Also limit instructions per loop if cache line size exceeds immediate range: + .set .Lmaxperloop, (\maxofs / \linesize) + 1 + .ifgt .Lperloop - .Lmaxperloop + .set .Lperloop, .Lmaxperloop + .endif + // Avoid addi of 128 which takes two instructions (addmi,addi): + .ifeq .Lperloop*\linesize - 128 + .ifgt .Lperloop - 1 + .set .Lperloop, .Lperloop / 2 + .endif + .endif + + // \size byte cache, \linesize byte lines, \assoc_or1 way(s) affected by each \cainst. + // XCHAL_ERRATUM_497 - don't execute using loop, to reduce the amount of added code + .ifne (\loopokay & XCHAL_HAVE_LOOPS && !XCHAL_ERRATUM_497) + + movi \aa, .Lindices / .Lperloop // number of loop iterations + // Possible improvement: need only loop if \aa > 1 ; + // however \aa == 1 is highly unlikely. + movi \ab, 0 // to iterate over cache + loop \aa, .Lend_cachex\@ + .set .Li, 0 ; .rept .Lperloop + \cainst \ab, .Li*\linesize + .set .Li, .Li+1 ; .endr + addi \ab, \ab, .Lperloop*\linesize // move to next line +.Lend_cachex\@: + + .else + + movi \aa, (\size / \assoc_or1) + // Possible improvement: need only loop if \aa > 1 ; + // however \aa == 1 is highly unlikely. + movi \ab, 0 // to iterate over cache + .ifne ((\awb !=a0) & XCHAL_ERRATUM_497) // don't use awb if set to a0 + movi \awb, 0 + .endif +.Lstart_cachex\@: + .set .Li, 0 ; .rept .Lperloop + \cainst \ab, .Li*\linesize + .set .Li, .Li+1 ; .endr + .ifne ((\awb !=a0) & XCHAL_ERRATUM_497) // do memw after 8 cainst wb instructions + addi \awb, \awb, .Lperloop + blti \awb, 8, .Lstart_memw\@ + memw + movi \awb, 0 +.Lstart_memw\@: + .endif + addi \ab, \ab, .Lperloop*\linesize // move to next line + bltu \ab, \aa, .Lstart_cachex\@ + .endif + + .endm + + +/* + * Macro to apply a 'hit' cache instruction to a memory region, + * ie. to any cache entries that cache a specified portion (region) of memory. + * Takes care of the unaligned cases, ie. may apply to one + * more cache line than $asize / lineSize if $aaddr is not aligned. + * + * + * Parameters are: + * cainst instruction/macro that takes an address register parameter + * and an offset parameter (currently always zero) + * and generates a cache instruction (eg. "dhi", "dhwb", "ihi", etc.) + * linesize_log2 log2(size of cache line in bytes) + * addr register containing start address of region (clobbered) + * asize register containing size of the region in bytes (clobbered) + * askew unique register used as temporary + * awb unique register used as temporary for erratum 497. + * + * Note: A possible optimization to this macro is to apply the operation + * to the entire cache if the region exceeds the size of the cache + * by some empirically determined amount or factor. Some experimentation + * is required to determine the appropriate factors, which also need + * to be tunable if required. + */ + + .macro cache_hit_region cainst, linesize_log2, addr, asize, askew, awb=a0 + + // Make \asize the number of iterations: + extui \askew, \addr, 0, \linesize_log2 // get unalignment amount of \addr + add \asize, \asize, \askew // ... and add it to \asize + addi \asize, \asize, (1 << \linesize_log2) - 1 // round up! + srli \asize, \asize, \linesize_log2 + + // Iterate over region: + .ifne ((\awb !=a0) & XCHAL_ERRATUM_497) // don't use awb if set to a0 + movi \awb, 0 + .endif + floopnez \asize, cacheh\@ + \cainst \addr, 0 + .ifne ((\awb !=a0) & XCHAL_ERRATUM_497) // do memw after 8 cainst wb instructions + addi \awb, \awb, 1 + blti \awb, 8, .Lstart_memw\@ + memw + movi \awb, 0 +.Lstart_memw\@: + .endif + addi \addr, \addr, (1 << \linesize_log2) // move to next line + floopend \asize, cacheh\@ + .endm + + + + + +/*************************** INSTRUCTION CACHE ***************************/ + + +/* + * Reset/initialize the instruction cache by simply invalidating it: + * (need to unlock first also, if cache locking implemented): + * + * Parameters: + * aa, ab unique address registers (temporaries) + */ + .macro icache_reset aa, ab, loopokay=0 + icache_unlock_all \aa, \ab, \loopokay + icache_invalidate_all \aa, \ab, \loopokay + .endm + + +/* + * Synchronize after an instruction cache operation, + * to be sure everything is in sync with memory as to be + * expected following any previous instruction cache control operations. + * + * Even if a config doesn't have caches, an isync is still needed + * when instructions in any memory are modified, whether by a loader + * or self-modifying code. Therefore, this macro always produces + * an isync, whether or not an icache is present. + * + * Parameters are: + * ar an address register (temporary) (currently unused, but may be used in future) + */ + .macro icache_sync ar + isync + .endm + + + +/* + * Invalidate a single line of the instruction cache. + * Parameters are: + * ar address register that contains (virtual) address to invalidate + * (may get clobbered in a future implementation, but not currently) + * offset (optional) offset to add to \ar to compute effective address to invalidate + * (note: some number of lsbits are ignored) + */ + .macro icache_invalidate_line ar, offset +#if XCHAL_ICACHE_SIZE > 0 + ihi \ar, \offset // invalidate icache line + icache_sync \ar +#endif + .endm + + + + +/* + * Invalidate instruction cache entries that cache a specified portion of memory. + * Parameters are: + * astart start address (register gets clobbered) + * asize size of the region in bytes (register gets clobbered) + * ac unique register used as temporary + */ + .macro icache_invalidate_region astart, asize, ac +#if XCHAL_ICACHE_SIZE > 0 + // Instruction cache region invalidation: + cache_hit_region ihi, XCHAL_ICACHE_LINEWIDTH, \astart, \asize, \ac + icache_sync \ac + // End of instruction cache region invalidation +#endif + .endm + + + +/* + * Invalidate entire instruction cache. + * + * Parameters: + * aa, ab unique address registers (temporaries) + */ + .macro icache_invalidate_all aa, ab, loopokay=1 +#if XCHAL_ICACHE_SIZE > 0 + // Instruction cache invalidation: + cache_index_all iii, XCHAL_ICACHE_SIZE, XCHAL_ICACHE_LINESIZE, XCHAL_ICACHE_WAYS, \aa, \ab, \loopokay, 1020 + icache_sync \aa + // End of instruction cache invalidation +#endif + .endm + + + +/* + * Lock (prefetch & lock) a single line of the instruction cache. + * + * Parameters are: + * ar address register that contains (virtual) address to lock + * (may get clobbered in a future implementation, but not currently) + * offset offset to add to \ar to compute effective address to lock + * (note: some number of lsbits are ignored) + */ + .macro icache_lock_line ar, offset +#if XCHAL_ICACHE_SIZE > 0 && XCHAL_ICACHE_LINE_LOCKABLE + ipfl \ar, \offset /* prefetch and lock icache line */ + icache_sync \ar +#endif + .endm + + + +/* + * Lock (prefetch & lock) a specified portion of memory into the instruction cache. + * Parameters are: + * astart start address (register gets clobbered) + * asize size of the region in bytes (register gets clobbered) + * ac unique register used as temporary + */ + .macro icache_lock_region astart, asize, ac +#if XCHAL_ICACHE_SIZE > 0 && XCHAL_ICACHE_LINE_LOCKABLE + // Instruction cache region lock: + cache_hit_region ipfl, XCHAL_ICACHE_LINEWIDTH, \astart, \asize, \ac + icache_sync \ac + // End of instruction cache region lock +#endif + .endm + + + +/* + * Unlock a single line of the instruction cache. + * + * Parameters are: + * ar address register that contains (virtual) address to unlock + * (may get clobbered in a future implementation, but not currently) + * offset offset to add to \ar to compute effective address to unlock + * (note: some number of lsbits are ignored) + */ + .macro icache_unlock_line ar, offset +#if XCHAL_ICACHE_SIZE > 0 && XCHAL_ICACHE_LINE_LOCKABLE + ihu \ar, \offset /* unlock icache line */ + icache_sync \ar +#endif + .endm + + + +/* + * Unlock a specified portion of memory from the instruction cache. + * Parameters are: + * astart start address (register gets clobbered) + * asize size of the region in bytes (register gets clobbered) + * ac unique register used as temporary + */ + .macro icache_unlock_region astart, asize, ac +#if XCHAL_ICACHE_SIZE > 0 && XCHAL_ICACHE_LINE_LOCKABLE + // Instruction cache region unlock: + cache_hit_region ihu, XCHAL_ICACHE_LINEWIDTH, \astart, \asize, \ac + icache_sync \ac + // End of instruction cache region unlock +#endif + .endm + + + +/* + * Unlock entire instruction cache. + * + * Parameters: + * aa, ab unique address registers (temporaries) + */ + .macro icache_unlock_all aa, ab, loopokay=1 +#if XCHAL_ICACHE_SIZE > 0 && XCHAL_ICACHE_LINE_LOCKABLE + // Instruction cache unlock: + cache_index_all iiu, XCHAL_ICACHE_SIZE, XCHAL_ICACHE_LINESIZE, 1, \aa, \ab, \loopokay, 240 + icache_sync \aa + // End of instruction cache unlock +#endif + .endm + + + + + +/*************************** DATA CACHE ***************************/ + + + +/* + * Reset/initialize the data cache by simply invalidating it + * (need to unlock first also, if cache locking implemented): + * + * Parameters: + * aa, ab unique address registers (temporaries) + */ + .macro dcache_reset aa, ab, loopokay=0 + dcache_unlock_all \aa, \ab, \loopokay + dcache_invalidate_all \aa, \ab, \loopokay + .endm + + + + +/* + * Synchronize after a data cache operation, + * to be sure everything is in sync with memory as to be + * expected following any previous data cache control operations. + * + * Parameters are: + * ar an address register (temporary) (currently unused, but may be used in future) + */ + .macro dcache_sync ar, wbtype=0 +#if XCHAL_DCACHE_SIZE > 0 + // No synchronization is needed. + // (memw may be desired e.g. after writeback operation to help ensure subsequent + // external accesses are seen to follow that writeback, however that's outside + // the scope of this macro) + + //dsync + .ifne (\wbtype & XCHAL_ERRATUM_497) + memw + .endif +#endif + .endm + + + +/* + * Turn on cache coherence. + * + * WARNING: for RE-201x.x and later hardware, any interrupt that tries + * to change MEMCTL will see its changes dropped if the interrupt comes + * in the middle of this routine. If this might be an issue, call this + * routine with interrupts disabled. + * + * Parameters are: + * ar,at two scratch address registers (both clobbered) + */ + .macro cache_coherence_on ar at +#if XCHAL_DCACHE_IS_COHERENT +# if XCHAL_HW_MIN_VERSION >= XTENSA_HWVERSION_RE_2012_0 + /* Have MEMCTL. Enable snoop responses. */ + rsr.memctl \ar + movi \at, MEMCTL_SNOOP_EN + or \ar, \ar, \at + wsr.memctl \ar +# elif XCHAL_HAVE_EXTERN_REGS && XCHAL_HAVE_MX + /* Opt into coherence for MX (for backward compatibility / testing). */ + movi \ar, 1 + movi \at, XER_CCON + wer \ar, \at + extw +# endif +#endif + .endm + + + +/* + * Turn off cache coherence. + * + * NOTE: this is generally preceded by emptying the cache; + * see xthal_cache_coherence_optout() in hal/coherence.c for details. + * + * WARNING: for RE-201x.x and later hardware, any interrupt that tries + * to change MEMCTL will see its changes dropped if the interrupt comes + * in the middle of this routine. If this might be an issue, call this + * routine with interrupts disabled. + * + * Parameters are: + * ar,at two scratch address registers (both clobbered) + */ + .macro cache_coherence_off ar at +#if XCHAL_DCACHE_IS_COHERENT +# if XCHAL_HW_MIN_VERSION >= XTENSA_HWVERSION_RE_2012_0 + /* Have MEMCTL. Disable snoop responses. */ + rsr.memctl \ar + movi \at, ~MEMCTL_SNOOP_EN + and \ar, \ar, \at + wsr.memctl \ar +# elif XCHAL_HAVE_EXTERN_REGS && XCHAL_HAVE_MX + /* Opt out of coherence, for MX (for backward compatibility / testing). */ + extw + movi \at, 0 + movi \ar, XER_CCON + wer \at, \ar + extw +# endif +#endif + .endm + + + +/* + * Synchronize after a data store operation, + * to be sure the stored data is completely off the processor + * (and assuming there is no buffering outside the processor, + * that the data is in memory). This may be required to + * ensure that the processor's write buffers are emptied. + * A MEMW followed by a read guarantees this, by definition. + * We also try to make sure the read itself completes. + * + * Parameters are: + * ar an address register (temporary) + */ + .macro write_sync ar + memw // ensure previous memory accesses are complete prior to subsequent memory accesses + l32i \ar, sp, 0 // completing this read ensures any previous write has completed, because of MEMW + //slot + add \ar, \ar, \ar // use the result of the read to help ensure the read completes (in future architectures) + .endm + + +/* + * Invalidate a single line of the data cache. + * Parameters are: + * ar address register that contains (virtual) address to invalidate + * (may get clobbered in a future implementation, but not currently) + * offset (optional) offset to add to \ar to compute effective address to invalidate + * (note: some number of lsbits are ignored) + */ + .macro dcache_invalidate_line ar, offset +#if XCHAL_DCACHE_SIZE > 0 + dhi \ar, \offset + dcache_sync \ar +#endif + .endm + + + + + +/* + * Invalidate data cache entries that cache a specified portion of memory. + * Parameters are: + * astart start address (register gets clobbered) + * asize size of the region in bytes (register gets clobbered) + * ac unique register used as temporary + */ + .macro dcache_invalidate_region astart, asize, ac +#if XCHAL_DCACHE_SIZE > 0 + // Data cache region invalidation: + cache_hit_region dhi, XCHAL_DCACHE_LINEWIDTH, \astart, \asize, \ac + dcache_sync \ac + // End of data cache region invalidation +#endif + .endm + + + +/* + * Invalidate entire data cache. + * + * Parameters: + * aa, ab unique address registers (temporaries) + */ + .macro dcache_invalidate_all aa, ab, loopokay=1 +#if XCHAL_DCACHE_SIZE > 0 + // Data cache invalidation: + cache_index_all dii, XCHAL_DCACHE_SIZE, XCHAL_DCACHE_LINESIZE, XCHAL_DCACHE_WAYS, \aa, \ab, \loopokay, 1020 + dcache_sync \aa + // End of data cache invalidation +#endif + .endm + + + +/* + * Writeback a single line of the data cache. + * Parameters are: + * ar address register that contains (virtual) address to writeback + * (may get clobbered in a future implementation, but not currently) + * offset offset to add to \ar to compute effective address to writeback + * (note: some number of lsbits are ignored) + */ + .macro dcache_writeback_line ar, offset +#if XCHAL_DCACHE_SIZE > 0 && XCHAL_DCACHE_IS_WRITEBACK + dhwb \ar, \offset + dcache_sync \ar, wbtype=1 +#endif + .endm + + + +/* + * Writeback dirty data cache entries that cache a specified portion of memory. + * Parameters are: + * astart start address (register gets clobbered) + * asize size of the region in bytes (register gets clobbered) + * ac unique register used as temporary + */ + .macro dcache_writeback_region astart, asize, ac, awb +#if XCHAL_DCACHE_SIZE > 0 && XCHAL_DCACHE_IS_WRITEBACK + // Data cache region writeback: + cache_hit_region dhwb, XCHAL_DCACHE_LINEWIDTH, \astart, \asize, \ac, \awb + dcache_sync \ac, wbtype=1 + // End of data cache region writeback +#endif + .endm + + + +/* + * Writeback entire data cache. + * Parameters: + * aa, ab unique address registers (temporaries) + */ + .macro dcache_writeback_all aa, ab, awb, loopokay=1 +#if XCHAL_DCACHE_SIZE > 0 && XCHAL_DCACHE_IS_WRITEBACK + // Data cache writeback: + cache_index_all diwb, XCHAL_DCACHE_SIZE, XCHAL_DCACHE_LINESIZE, 1, \aa, \ab, \loopokay, 240, \awb, + dcache_sync \aa, wbtype=1 + // End of data cache writeback +#endif + .endm + + + +/* + * Writeback and invalidate a single line of the data cache. + * Parameters are: + * ar address register that contains (virtual) address to writeback and invalidate + * (may get clobbered in a future implementation, but not currently) + * offset offset to add to \ar to compute effective address to writeback and invalidate + * (note: some number of lsbits are ignored) + */ + .macro dcache_writeback_inv_line ar, offset +#if XCHAL_DCACHE_SIZE > 0 + dhwbi \ar, \offset /* writeback and invalidate dcache line */ + dcache_sync \ar, wbtype=1 +#endif + .endm + + + +/* + * Writeback and invalidate data cache entries that cache a specified portion of memory. + * Parameters are: + * astart start address (register gets clobbered) + * asize size of the region in bytes (register gets clobbered) + * ac unique register used as temporary + */ + .macro dcache_writeback_inv_region astart, asize, ac, awb +#if XCHAL_DCACHE_SIZE > 0 + // Data cache region writeback and invalidate: + cache_hit_region dhwbi, XCHAL_DCACHE_LINEWIDTH, \astart, \asize, \ac, \awb + dcache_sync \ac, wbtype=1 + // End of data cache region writeback and invalidate +#endif + .endm + + + +/* + * Writeback and invalidate entire data cache. + * Parameters: + * aa, ab unique address registers (temporaries) + */ + .macro dcache_writeback_inv_all aa, ab, awb, loopokay=1 +#if XCHAL_DCACHE_SIZE > 0 + // Data cache writeback and invalidate: +#if XCHAL_DCACHE_IS_WRITEBACK + cache_index_all diwbi, XCHAL_DCACHE_SIZE, XCHAL_DCACHE_LINESIZE, 1, \aa, \ab, \loopokay, 240, \awb + dcache_sync \aa, wbtype=1 +#else /*writeback*/ + // Data cache does not support writeback, so just invalidate: */ + dcache_invalidate_all \aa, \ab, \loopokay +#endif /*writeback*/ + // End of data cache writeback and invalidate +#endif + .endm + + + + +/* + * Lock (prefetch & lock) a single line of the data cache. + * + * Parameters are: + * ar address register that contains (virtual) address to lock + * (may get clobbered in a future implementation, but not currently) + * offset offset to add to \ar to compute effective address to lock + * (note: some number of lsbits are ignored) + */ + .macro dcache_lock_line ar, offset +#if XCHAL_DCACHE_SIZE > 0 && XCHAL_DCACHE_LINE_LOCKABLE + dpfl \ar, \offset /* prefetch and lock dcache line */ + dcache_sync \ar +#endif + .endm + + + +/* + * Lock (prefetch & lock) a specified portion of memory into the data cache. + * Parameters are: + * astart start address (register gets clobbered) + * asize size of the region in bytes (register gets clobbered) + * ac unique register used as temporary + */ + .macro dcache_lock_region astart, asize, ac +#if XCHAL_DCACHE_SIZE > 0 && XCHAL_DCACHE_LINE_LOCKABLE + // Data cache region lock: + cache_hit_region dpfl, XCHAL_DCACHE_LINEWIDTH, \astart, \asize, \ac + dcache_sync \ac + // End of data cache region lock +#endif + .endm + + + +/* + * Unlock a single line of the data cache. + * + * Parameters are: + * ar address register that contains (virtual) address to unlock + * (may get clobbered in a future implementation, but not currently) + * offset offset to add to \ar to compute effective address to unlock + * (note: some number of lsbits are ignored) + */ + .macro dcache_unlock_line ar, offset +#if XCHAL_DCACHE_SIZE > 0 && XCHAL_DCACHE_LINE_LOCKABLE + dhu \ar, \offset /* unlock dcache line */ + dcache_sync \ar +#endif + .endm + + + +/* + * Unlock a specified portion of memory from the data cache. + * Parameters are: + * astart start address (register gets clobbered) + * asize size of the region in bytes (register gets clobbered) + * ac unique register used as temporary + */ + .macro dcache_unlock_region astart, asize, ac +#if XCHAL_DCACHE_SIZE > 0 && XCHAL_DCACHE_LINE_LOCKABLE + // Data cache region unlock: + cache_hit_region dhu, XCHAL_DCACHE_LINEWIDTH, \astart, \asize, \ac + dcache_sync \ac + // End of data cache region unlock +#endif + .endm + + + +/* + * Unlock entire data cache. + * + * Parameters: + * aa, ab unique address registers (temporaries) + */ + .macro dcache_unlock_all aa, ab, loopokay=1 +#if XCHAL_DCACHE_SIZE > 0 && XCHAL_DCACHE_LINE_LOCKABLE + // Data cache unlock: + cache_index_all diu, XCHAL_DCACHE_SIZE, XCHAL_DCACHE_LINESIZE, 1, \aa, \ab, \loopokay, 240 + dcache_sync \aa + // End of data cache unlock +#endif + .endm + + + +/* + * Get the number of enabled icache ways. Note that this may + * be different from the value read from the MEMCTL register. + * + * Parameters: + * aa address register where value is returned + */ + .macro icache_get_ways aa +#if XCHAL_ICACHE_SIZE > 0 +#if XCHAL_HAVE_ICACHE_DYN_WAYS + // Read from MEMCTL and shift/mask + rsr \aa, MEMCTL + extui \aa, \aa, MEMCTL_ICWU_SHIFT, MEMCTL_ICWU_BITS + blti \aa, XCHAL_ICACHE_WAYS, .Licgw + movi \aa, XCHAL_ICACHE_WAYS +.Licgw: +#else + // All ways are always enabled + movi \aa, XCHAL_ICACHE_WAYS +#endif +#else + // No icache + movi \aa, 0 +#endif + .endm + + + +/* + * Set the number of enabled icache ways. + * + * Parameters: + * aa address register specifying number of ways (trashed) + * ab,ac address register for scratch use (trashed) + */ + .macro icache_set_ways aa, ab, ac +#if XCHAL_ICACHE_SIZE > 0 +#if XCHAL_HAVE_ICACHE_DYN_WAYS + movi \ac, MEMCTL_ICWU_CLR_MASK // set up to clear bits 18-22 + rsr \ab, MEMCTL + and \ab, \ab, \ac + movi \ac, MEMCTL_INV_EN // set bit 23 + slli \aa, \aa, MEMCTL_ICWU_SHIFT // move to right spot + or \ab, \ab, \aa + or \ab, \ab, \ac + wsr \ab, MEMCTL + isync +#else + // All ways are always enabled +#endif +#else + // No icache +#endif + .endm + + + +/* + * Get the number of enabled dcache ways. Note that this may + * be different from the value read from the MEMCTL register. + * + * Parameters: + * aa address register where value is returned + */ + .macro dcache_get_ways aa +#if XCHAL_DCACHE_SIZE > 0 +#if XCHAL_HAVE_DCACHE_DYN_WAYS + // Read from MEMCTL and shift/mask + rsr \aa, MEMCTL + extui \aa, \aa, MEMCTL_DCWU_SHIFT, MEMCTL_DCWU_BITS + blti \aa, XCHAL_DCACHE_WAYS, .Ldcgw + movi \aa, XCHAL_DCACHE_WAYS +.Ldcgw: +#else + // All ways are always enabled + movi \aa, XCHAL_DCACHE_WAYS +#endif +#else + // No dcache + movi \aa, 0 +#endif + .endm + + + +/* + * Set the number of enabled dcache ways. + * + * Parameters: + * aa address register specifying number of ways (trashed) + * ab,ac address register for scratch use (trashed) + */ + .macro dcache_set_ways aa, ab, ac +#if (XCHAL_DCACHE_SIZE > 0) && XCHAL_HAVE_DCACHE_DYN_WAYS + movi \ac, MEMCTL_DCWA_CLR_MASK // set up to clear bits 13-17 + rsr \ab, MEMCTL + and \ab, \ab, \ac // clear ways allocatable + slli \ac, \aa, MEMCTL_DCWA_SHIFT + or \ab, \ab, \ac // set ways allocatable + wsr \ab, MEMCTL +#if XCHAL_DCACHE_IS_WRITEBACK + // Check if the way count is increasing or decreasing + extui \ac, \ab, MEMCTL_DCWU_SHIFT, MEMCTL_DCWU_BITS // bits 8-12 - ways in use + bge \aa, \ac, .Ldsw3 // equal or increasing + slli \ab, \aa, XCHAL_DCACHE_LINEWIDTH + XCHAL_DCACHE_SETWIDTH // start way number + slli \ac, \ac, XCHAL_DCACHE_LINEWIDTH + XCHAL_DCACHE_SETWIDTH // end way number +.Ldsw1: + diwbui.p \ab // auto-increments ab + bge \ab, \ac, .Ldsw2 + beqz \ab, .Ldsw2 + j .Ldsw1 +.Ldsw2: + rsr \ab, MEMCTL +#endif +.Ldsw3: + // No dirty data to write back, just set the new number of ways + movi \ac, MEMCTL_DCWU_CLR_MASK // set up to clear bits 8-12 + and \ab, \ab, \ac // clear ways in use + movi \ac, MEMCTL_INV_EN + or \ab, \ab, \ac // set bit 23 + slli \aa, \aa, MEMCTL_DCWU_SHIFT + or \ab, \ab, \aa // set ways in use + wsr \ab, MEMCTL +#else + // No dcache or no way disable support +#endif + .endm + +#endif /*XTENSA_CACHEASM_H*/ + diff --git a/components/esp32/include/xtensa/cacheattrasm.h b/components/esp32/include/xtensa/cacheattrasm.h new file mode 100755 index 0000000000..20c4cfd558 --- /dev/null +++ b/components/esp32/include/xtensa/cacheattrasm.h @@ -0,0 +1,436 @@ +/* + * xtensa/cacheattrasm.h -- assembler-specific CACHEATTR register related definitions + * that depend on CORE configuration + * + * This file is logically part of xtensa/coreasm.h (or perhaps xtensa/cacheasm.h), + * but is kept separate for modularity / compilation-performance. + */ + +/* + * Copyright (c) 2001-2009 Tensilica Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY + * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +#ifndef XTENSA_CACHEATTRASM_H +#define XTENSA_CACHEATTRASM_H + +#include + +/* Determine whether cache attributes are controlled using eight 512MB entries: */ +#define XCHAL_CA_8X512 (XCHAL_HAVE_CACHEATTR || XCHAL_HAVE_MIMIC_CACHEATTR || XCHAL_HAVE_XLT_CACHEATTR \ + || (XCHAL_HAVE_PTP_MMU && XCHAL_HAVE_SPANNING_WAY)) + + +/* + * This header file defines assembler macros of the form: + * cacheattr_ + * where: + * is 'i', 'd' or absent for instruction, data + * or both caches; and + * indicates the function of the macro. + * + * The following functions are defined: + * + * icacheattr_get + * Reads I-cache CACHEATTR into a2 (clobbers a3-a5). + * + * dcacheattr_get + * Reads D-cache CACHEATTR into a2 (clobbers a3-a5). + * (Note: for configs with a real CACHEATTR register, the + * above two macros are identical.) + * + * cacheattr_set + * Writes both I-cache and D-cache CACHEATTRs from a2 (a3-a8 clobbered). + * Works even when changing one's own code's attributes. + * + * icacheattr_is_enabled label + * Branches to \label if I-cache appears to have been enabled + * (eg. if CACHEATTR contains a cache-enabled attribute). + * (clobbers a2-a5,SAR) + * + * dcacheattr_is_enabled label + * Branches to \label if D-cache appears to have been enabled + * (eg. if CACHEATTR contains a cache-enabled attribute). + * (clobbers a2-a5,SAR) + * + * cacheattr_is_enabled label + * Branches to \label if either I-cache or D-cache appears to have been enabled + * (eg. if CACHEATTR contains a cache-enabled attribute). + * (clobbers a2-a5,SAR) + * + * The following macros are only defined under certain conditions: + * + * icacheattr_set (if XCHAL_HAVE_MIMIC_CACHEATTR || XCHAL_HAVE_XLT_CACHEATTR) + * Writes I-cache CACHEATTR from a2 (a3-a8 clobbered). + * + * dcacheattr_set (if XCHAL_HAVE_MIMIC_CACHEATTR || XCHAL_HAVE_XLT_CACHEATTR) + * Writes D-cache CACHEATTR from a2 (a3-a8 clobbered). + */ + + + +/*************************** GENERIC -- ALL CACHES ***************************/ + +/* + * _cacheattr_get + * + * (Internal macro.) + * Returns value of CACHEATTR register (or closest equivalent) in a2. + * + * Entry: + * (none) + * Exit: + * a2 value read from CACHEATTR + * a3-a5 clobbered (temporaries) + */ + .macro _cacheattr_get tlb +#if XCHAL_HAVE_CACHEATTR + rsr a2, CACHEATTR +#elif XCHAL_CA_8X512 + // We have a config that "mimics" CACHEATTR using a simplified + // "MMU" composed of a single statically-mapped way. + // DTLB and ITLB are independent, so there's no single + // cache attribute that can describe both. So for now + // just return the DTLB state. + movi a5, 0xE0000000 + movi a2, 0 + movi a3, XCHAL_SPANNING_WAY +1: add a3, a3, a5 // next segment + r&tlb&1 a4, a3 // get PPN+CA of segment at 0xE0000000, 0xC0000000, ..., 0 + dsync // interlock??? + slli a2, a2, 4 + extui a4, a4, 0, 4 // extract CA + or a2, a2, a4 + bgeui a3, 16, 1b +#else + // This macro isn't applicable to arbitrary MMU configurations. + // Just return zero. + movi a2, 0 +#endif + .endm + + .macro icacheattr_get + _cacheattr_get itlb + .endm + + .macro dcacheattr_get + _cacheattr_get dtlb + .endm + + +/* Default (powerup/reset) value of CACHEATTR, + all BYPASS mode (ie. disabled/bypassed caches): */ +#if XCHAL_HAVE_PTP_MMU +# define XCHAL_CACHEATTR_ALL_BYPASS 0x33333333 +#else +# define XCHAL_CACHEATTR_ALL_BYPASS 0x22222222 +#endif + +#if XCHAL_CA_8X512 + +#if XCHAL_HAVE_PTP_MMU +# define XCHAL_FCA_ENAMASK 0x0AA0 /* bitmap of fetch attributes that require enabled icache */ +# define XCHAL_LCA_ENAMASK 0x0FF0 /* bitmap of load attributes that require enabled dcache */ +# define XCHAL_SCA_ENAMASK 0x0CC0 /* bitmap of store attributes that require enabled dcache */ +#else +# define XCHAL_FCA_ENAMASK 0x003A /* bitmap of fetch attributes that require enabled icache */ +# define XCHAL_LCA_ENAMASK 0x0033 /* bitmap of load attributes that require enabled dcache */ +# define XCHAL_SCA_ENAMASK 0x0033 /* bitmap of store attributes that require enabled dcache */ +#endif +#define XCHAL_LSCA_ENAMASK (XCHAL_LCA_ENAMASK|XCHAL_SCA_ENAMASK) /* l/s attrs requiring enabled dcache */ +#define XCHAL_ALLCA_ENAMASK (XCHAL_FCA_ENAMASK|XCHAL_LSCA_ENAMASK) /* all attrs requiring enabled caches */ + +/* + * _cacheattr_is_enabled + * + * (Internal macro.) + * Branches to \label if CACHEATTR in a2 indicates an enabled + * cache, using mask in a3. + * + * Parameters: + * label where to branch to if cache is enabled + * Entry: + * a2 contains CACHEATTR value used to determine whether + * caches are enabled + * a3 16-bit constant where each bit correspond to + * one of the 16 possible CA values (in a CACHEATTR mask); + * CA values that indicate the cache is enabled + * have their corresponding bit set in this mask + * (eg. use XCHAL_xCA_ENAMASK , above) + * Exit: + * a2,a4,a5 clobbered + * SAR clobbered + */ + .macro _cacheattr_is_enabled label + movi a4, 8 // loop 8 times +.Lcaife\@: + extui a5, a2, 0, 4 // get CA nibble + ssr a5 // index into mask according to CA... + srl a5, a3 // ...and get CA's mask bit in a5 bit 0 + bbsi.l a5, 0, \label // if CA indicates cache enabled, jump to label + srli a2, a2, 4 // next nibble + addi a4, a4, -1 + bnez a4, .Lcaife\@ // loop for each nibble + .endm + +#else /* XCHAL_CA_8X512 */ + .macro _cacheattr_is_enabled label + j \label // macro not applicable, assume caches always enabled + .endm +#endif /* XCHAL_CA_8X512 */ + + + +/* + * icacheattr_is_enabled + * + * Branches to \label if I-cache is enabled. + * + * Parameters: + * label where to branch to if icache is enabled + * Entry: + * (none) + * Exit: + * a2-a5, SAR clobbered (temporaries) + */ + .macro icacheattr_is_enabled label +#if XCHAL_CA_8X512 + icacheattr_get + movi a3, XCHAL_FCA_ENAMASK +#endif + _cacheattr_is_enabled \label + .endm + +/* + * dcacheattr_is_enabled + * + * Branches to \label if D-cache is enabled. + * + * Parameters: + * label where to branch to if dcache is enabled + * Entry: + * (none) + * Exit: + * a2-a5, SAR clobbered (temporaries) + */ + .macro dcacheattr_is_enabled label +#if XCHAL_CA_8X512 + dcacheattr_get + movi a3, XCHAL_LSCA_ENAMASK +#endif + _cacheattr_is_enabled \label + .endm + +/* + * cacheattr_is_enabled + * + * Branches to \label if either I-cache or D-cache is enabled. + * + * Parameters: + * label where to branch to if a cache is enabled + * Entry: + * (none) + * Exit: + * a2-a5, SAR clobbered (temporaries) + */ + .macro cacheattr_is_enabled label +#if XCHAL_HAVE_CACHEATTR + rsr a2, CACHEATTR + movi a3, XCHAL_ALLCA_ENAMASK +#elif XCHAL_CA_8X512 + icacheattr_get + movi a3, XCHAL_FCA_ENAMASK + _cacheattr_is_enabled \label + dcacheattr_get + movi a3, XCHAL_LSCA_ENAMASK +#endif + _cacheattr_is_enabled \label + .endm + + + +/* + * The ISA does not have a defined way to change the + * instruction cache attributes of the running code, + * ie. of the memory area that encloses the current PC. + * However, each micro-architecture (or class of + * configurations within a micro-architecture) + * provides a way to deal with this issue. + * + * Here are a few macros used to implement the relevant + * approach taken. + */ + +#if XCHAL_CA_8X512 && !XCHAL_HAVE_CACHEATTR + // We have a config that "mimics" CACHEATTR using a simplified + // "MMU" composed of a single statically-mapped way. + +/* + * icacheattr_set + * + * Entry: + * a2 cacheattr value to set + * Exit: + * a2 unchanged + * a3-a8 clobbered (temporaries) + */ + .macro icacheattr_set + + movi a5, 0xE0000000 // mask of upper 3 bits + movi a6, 3f // PC where ITLB is set + movi a3, XCHAL_SPANNING_WAY // start at region 0 (0 .. 7) + mov a7, a2 // copy a2 so it doesn't get clobbered + and a6, a6, a5 // upper 3 bits of local PC area + j 3f + + // Use micro-architecture specific method. + // The following 4-instruction sequence is aligned such that + // it all fits within a single I-cache line. Sixteen byte + // alignment is sufficient for this (using XCHAL_ICACHE_LINESIZE + // actually causes problems because that can be greater than + // the alignment of the reset vector, where this macro is often + // invoked, which would cause the linker to align the reset + // vector code away from the reset vector!!). + .begin no-transform + .align 16 /*XCHAL_ICACHE_LINESIZE*/ +1: witlb a4, a3 // write wired PTE (CA, no PPN) of 512MB segment to ITLB + isync + .end no-transform + nop + nop + + sub a3, a3, a5 // next segment (add 0x20000000) + bltui a3, 16, 4f // done? + + // Note that in the WITLB loop, we don't do any load/stores + // (may not be an issue here, but it is important in the DTLB case). +2: srli a7, a7, 4 // next CA +3: +# if XCHAL_HAVE_MIMIC_CACHEATTR + extui a4, a7, 0, 4 // extract CA to set +# else /* have translation, preserve it: */ + ritlb1 a8, a3 // get current PPN+CA of segment + //dsync // interlock??? + extui a4, a7, 0, 4 // extract CA to set + srli a8, a8, 4 // clear CA but keep PPN ... + slli a8, a8, 4 // ... + add a4, a4, a8 // combine new CA with PPN to preserve +# endif + beq a3, a6, 1b // current PC's region? if so, do it in a safe way + witlb a4, a3 // write wired PTE (CA [+PPN]) of 512MB segment to ITLB + sub a3, a3, a5 // next segment (add 0x20000000) + bgeui a3, 16, 2b + isync // make sure all ifetch changes take effect +4: + .endm // icacheattr_set + + +/* + * dcacheattr_set + * + * Entry: + * a2 cacheattr value to set + * Exit: + * a2 unchanged + * a3-a8 clobbered (temporaries) + */ + + .macro dcacheattr_set + + movi a5, 0xE0000000 // mask of upper 3 bits + movi a3, XCHAL_SPANNING_WAY // start at region 0 (0 .. 7) + mov a7, a2 // copy a2 so it doesn't get clobbered + // Note that in the WDTLB loop, we don't do any load/stores +2: // (including implicit l32r via movi) because it isn't safe. +# if XCHAL_HAVE_MIMIC_CACHEATTR + extui a4, a7, 0, 4 // extract CA to set +# else /* have translation, preserve it: */ + rdtlb1 a8, a3 // get current PPN+CA of segment + //dsync // interlock??? + extui a4, a7, 0, 4 // extract CA to set + srli a8, a8, 4 // clear CA but keep PPN ... + slli a8, a8, 4 // ... + add a4, a4, a8 // combine new CA with PPN to preserve +# endif + wdtlb a4, a3 // write wired PTE (CA [+PPN]) of 512MB segment to DTLB + sub a3, a3, a5 // next segment (add 0x20000000) + srli a7, a7, 4 // next CA + bgeui a3, 16, 2b + dsync // make sure all data path changes take effect + .endm // dcacheattr_set + +#endif /* XCHAL_CA_8X512 && !XCHAL_HAVE_CACHEATTR */ + + + +/* + * cacheattr_set + * + * Macro that sets the current CACHEATTR safely + * (both i and d) according to the current contents of a2. + * It works even when changing the cache attributes of + * the currently running code. + * + * Entry: + * a2 cacheattr value to set + * Exit: + * a2 unchanged + * a3-a8 clobbered (temporaries) + */ + .macro cacheattr_set + +#if XCHAL_HAVE_CACHEATTR +# if XCHAL_ICACHE_LINESIZE < 4 + // No i-cache, so can always safely write to CACHEATTR: + wsr a2, CACHEATTR +# else + // The Athens micro-architecture, when using the old + // exception architecture option (ie. with the CACHEATTR register) + // allows changing the cache attributes of the running code + // using the following exact sequence aligned to be within + // an instruction cache line. (NOTE: using XCHAL_ICACHE_LINESIZE + // alignment actually causes problems because that can be greater + // than the alignment of the reset vector, where this macro is often + // invoked, which would cause the linker to align the reset + // vector code away from the reset vector!!). + j 1f + .begin no-transform + .align 16 /*XCHAL_ICACHE_LINESIZE*/ // align to within an I-cache line +1: wsr a2, CACHEATTR + isync + .end no-transform + nop + nop +# endif +#elif XCHAL_CA_8X512 + // DTLB and ITLB are independent, but to keep semantics + // of this macro we simply write to both. + icacheattr_set + dcacheattr_set +#else + // This macro isn't applicable to arbitrary MMU configurations. + // Do nothing in this case. +#endif + .endm + + +#endif /*XTENSA_CACHEATTRASM_H*/ + diff --git a/components/esp32/include/xtensa/config/core-isa.h b/components/esp32/include/xtensa/config/core-isa.h new file mode 100644 index 0000000000..1845647264 --- /dev/null +++ b/components/esp32/include/xtensa/config/core-isa.h @@ -0,0 +1,655 @@ +/* + * xtensa/config/core-isa.h -- HAL definitions that are dependent on Xtensa + * processor CORE configuration + * + * See , which includes this file, for more details. + */ + +/* Xtensa processor core configuration information. + + Customer ID=11657; Build=0x5fe96; Copyright (c) 1999-2016 Tensilica Inc. + + Permission is hereby granted, free of charge, to any person obtaining + a copy of this software and associated documentation files (the + "Software"), to deal in the Software without restriction, including + without limitation the rights to use, copy, modify, merge, publish, + distribute, sublicense, and/or sell copies of the Software, and to + permit persons to whom the Software is furnished to do so, subject to + the following conditions: + + The above copyright notice and this permission notice shall be included + in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY + CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ + +#ifndef _XTENSA_CORE_CONFIGURATION_H +#define _XTENSA_CORE_CONFIGURATION_H + + +/**************************************************************************** + Parameters Useful for Any Code, USER or PRIVILEGED + ****************************************************************************/ + +/* + * Note: Macros of the form XCHAL_HAVE_*** have a value of 1 if the option is + * configured, and a value of 0 otherwise. These macros are always defined. + */ + + +/*---------------------------------------------------------------------- + ISA + ----------------------------------------------------------------------*/ + +#define XCHAL_HAVE_BE 0 /* big-endian byte ordering */ +#define XCHAL_HAVE_WINDOWED 1 /* windowed registers option */ +#define XCHAL_NUM_AREGS 64 /* num of physical addr regs */ +#define XCHAL_NUM_AREGS_LOG2 6 /* log2(XCHAL_NUM_AREGS) */ +#define XCHAL_MAX_INSTRUCTION_SIZE 3 /* max instr bytes (3..8) */ +#define XCHAL_HAVE_DEBUG 1 /* debug option */ +#define XCHAL_HAVE_DENSITY 1 /* 16-bit instructions */ +#define XCHAL_HAVE_LOOPS 1 /* zero-overhead loops */ +#define XCHAL_LOOP_BUFFER_SIZE 256 /* zero-ov. loop instr buffer size */ +#define XCHAL_HAVE_NSA 1 /* NSA/NSAU instructions */ +#define XCHAL_HAVE_MINMAX 1 /* MIN/MAX instructions */ +#define XCHAL_HAVE_SEXT 1 /* SEXT instruction */ +#define XCHAL_HAVE_DEPBITS 0 /* DEPBITS instruction */ +#define XCHAL_HAVE_CLAMPS 1 /* CLAMPS instruction */ +#define XCHAL_HAVE_MUL16 1 /* MUL16S/MUL16U instructions */ +#define XCHAL_HAVE_MUL32 1 /* MULL instruction */ +#define XCHAL_HAVE_MUL32_HIGH 1 /* MULUH/MULSH instructions */ +#define XCHAL_HAVE_DIV32 1 /* QUOS/QUOU/REMS/REMU instructions */ +#define XCHAL_HAVE_L32R 1 /* L32R instruction */ +#define XCHAL_HAVE_ABSOLUTE_LITERALS 0 /* non-PC-rel (extended) L32R */ +#define XCHAL_HAVE_CONST16 0 /* CONST16 instruction */ +#define XCHAL_HAVE_ADDX 1 /* ADDX#/SUBX# instructions */ +#define XCHAL_HAVE_WIDE_BRANCHES 0 /* B*.W18 or B*.W15 instr's */ +#define XCHAL_HAVE_PREDICTED_BRANCHES 0 /* B[EQ/EQZ/NE/NEZ]T instr's */ +#define XCHAL_HAVE_CALL4AND12 1 /* (obsolete option) */ +#define XCHAL_HAVE_ABS 1 /* ABS instruction */ +/*#define XCHAL_HAVE_POPC 0*/ /* POPC instruction */ +/*#define XCHAL_HAVE_CRC 0*/ /* CRC instruction */ +#define XCHAL_HAVE_RELEASE_SYNC 1 /* L32AI/S32RI instructions */ +#define XCHAL_HAVE_S32C1I 1 /* S32C1I instruction */ +#define XCHAL_HAVE_SPECULATION 0 /* speculation */ +#define XCHAL_HAVE_FULL_RESET 1 /* all regs/state reset */ +#define XCHAL_NUM_CONTEXTS 1 /* */ +#define XCHAL_NUM_MISC_REGS 4 /* num of scratch regs (0..4) */ +#define XCHAL_HAVE_TAP_MASTER 0 /* JTAG TAP control instr's */ +#define XCHAL_HAVE_PRID 1 /* processor ID register */ +#define XCHAL_HAVE_EXTERN_REGS 1 /* WER/RER instructions */ +#define XCHAL_HAVE_MX 0 /* MX core (Tensilica internal) */ +#define XCHAL_HAVE_MP_INTERRUPTS 0 /* interrupt distributor port */ +#define XCHAL_HAVE_MP_RUNSTALL 0 /* core RunStall control port */ +#define XCHAL_HAVE_PSO 0 /* Power Shut-Off */ +#define XCHAL_HAVE_PSO_CDM 0 /* core/debug/mem pwr domains */ +#define XCHAL_HAVE_PSO_FULL_RETENTION 0 /* all regs preserved on PSO */ +#define XCHAL_HAVE_THREADPTR 1 /* THREADPTR register */ +#define XCHAL_HAVE_BOOLEANS 1 /* boolean registers */ +#define XCHAL_HAVE_CP 1 /* CPENABLE reg (coprocessor) */ +#define XCHAL_CP_MAXCFG 8 /* max allowed cp id plus one */ +#define XCHAL_HAVE_MAC16 1 /* MAC16 package */ + +#define XCHAL_HAVE_FUSION 0 /* Fusion*/ +#define XCHAL_HAVE_FUSION_FP 0 /* Fusion FP option */ +#define XCHAL_HAVE_FUSION_LOW_POWER 0 /* Fusion Low Power option */ +#define XCHAL_HAVE_FUSION_AES 0 /* Fusion BLE/Wifi AES-128 CCM option */ +#define XCHAL_HAVE_FUSION_CONVENC 0 /* Fusion Conv Encode option */ +#define XCHAL_HAVE_FUSION_LFSR_CRC 0 /* Fusion LFSR-CRC option */ +#define XCHAL_HAVE_FUSION_BITOPS 0 /* Fusion Bit Operations Support option */ +#define XCHAL_HAVE_FUSION_AVS 0 /* Fusion AVS option */ +#define XCHAL_HAVE_FUSION_16BIT_BASEBAND 0 /* Fusion 16-bit Baseband option */ +#define XCHAL_HAVE_FUSION_VITERBI 0 /* Fusion Viterbi option */ +#define XCHAL_HAVE_FUSION_SOFTDEMAP 0 /* Fusion Soft Bit Demap option */ +#define XCHAL_HAVE_HIFIPRO 0 /* HiFiPro Audio Engine pkg */ +#define XCHAL_HAVE_HIFI4 0 /* HiFi4 Audio Engine pkg */ +#define XCHAL_HAVE_HIFI4_VFPU 0 /* HiFi4 Audio Engine VFPU option */ +#define XCHAL_HAVE_HIFI3 0 /* HiFi3 Audio Engine pkg */ +#define XCHAL_HAVE_HIFI3_VFPU 0 /* HiFi3 Audio Engine VFPU option */ +#define XCHAL_HAVE_HIFI2 0 /* HiFi2 Audio Engine pkg */ +#define XCHAL_HAVE_HIFI2EP 0 /* HiFi2EP */ +#define XCHAL_HAVE_HIFI_MINI 0 + + +#define XCHAL_HAVE_VECTORFPU2005 0 /* vector or user floating-point pkg */ +#define XCHAL_HAVE_USER_DPFPU 0 /* user DP floating-point pkg */ +#define XCHAL_HAVE_USER_SPFPU 0 /* user DP floating-point pkg */ +#define XCHAL_HAVE_FP 1 /* single prec floating point */ +#define XCHAL_HAVE_FP_DIV 1 /* FP with DIV instructions */ +#define XCHAL_HAVE_FP_RECIP 1 /* FP with RECIP instructions */ +#define XCHAL_HAVE_FP_SQRT 1 /* FP with SQRT instructions */ +#define XCHAL_HAVE_FP_RSQRT 1 /* FP with RSQRT instructions */ +#define XCHAL_HAVE_DFP 0 /* double precision FP pkg */ +#define XCHAL_HAVE_DFP_DIV 0 /* DFP with DIV instructions */ +#define XCHAL_HAVE_DFP_RECIP 0 /* DFP with RECIP instructions*/ +#define XCHAL_HAVE_DFP_SQRT 0 /* DFP with SQRT instructions */ +#define XCHAL_HAVE_DFP_RSQRT 0 /* DFP with RSQRT instructions*/ +#define XCHAL_HAVE_DFP_ACCEL 1 /* double precision FP acceleration pkg */ +#define XCHAL_HAVE_DFP_accel XCHAL_HAVE_DFP_ACCEL /* for backward compatibility */ + +#define XCHAL_HAVE_DFPU_SINGLE_ONLY 1 /* DFPU Coprocessor, single precision only */ +#define XCHAL_HAVE_DFPU_SINGLE_DOUBLE 0 /* DFPU Coprocessor, single and double precision */ +#define XCHAL_HAVE_VECTRA1 0 /* Vectra I pkg */ +#define XCHAL_HAVE_VECTRALX 0 /* Vectra LX pkg */ +#define XCHAL_HAVE_PDX4 0 /* PDX4 */ +#define XCHAL_HAVE_CONNXD2 0 /* ConnX D2 pkg */ +#define XCHAL_HAVE_CONNXD2_DUALLSFLIX 0 /* ConnX D2 & Dual LoadStore Flix */ +#define XCHAL_HAVE_BBE16 0 /* ConnX BBE16 pkg */ +#define XCHAL_HAVE_BBE16_RSQRT 0 /* BBE16 & vector recip sqrt */ +#define XCHAL_HAVE_BBE16_VECDIV 0 /* BBE16 & vector divide */ +#define XCHAL_HAVE_BBE16_DESPREAD 0 /* BBE16 & despread */ +#define XCHAL_HAVE_BBENEP 0 /* ConnX BBENEP pkgs */ +#define XCHAL_HAVE_BSP3 0 /* ConnX BSP3 pkg */ +#define XCHAL_HAVE_BSP3_TRANSPOSE 0 /* BSP3 & transpose32x32 */ +#define XCHAL_HAVE_SSP16 0 /* ConnX SSP16 pkg */ +#define XCHAL_HAVE_SSP16_VITERBI 0 /* SSP16 & viterbi */ +#define XCHAL_HAVE_TURBO16 0 /* ConnX Turbo16 pkg */ +#define XCHAL_HAVE_BBP16 0 /* ConnX BBP16 pkg */ +#define XCHAL_HAVE_FLIX3 0 /* basic 3-way FLIX option */ +#define XCHAL_HAVE_GRIVPEP 0 /* GRIVPEP is General Release of IVPEP */ +#define XCHAL_HAVE_GRIVPEP_HISTOGRAM 0 /* Histogram option on GRIVPEP */ + + +/*---------------------------------------------------------------------- + MISC + ----------------------------------------------------------------------*/ + +#define XCHAL_NUM_LOADSTORE_UNITS 1 /* load/store units */ +#define XCHAL_NUM_WRITEBUFFER_ENTRIES 4 /* size of write buffer */ +#define XCHAL_INST_FETCH_WIDTH 4 /* instr-fetch width in bytes */ +#define XCHAL_DATA_WIDTH 4 /* data width in bytes */ +#define XCHAL_DATA_PIPE_DELAY 2 /* d-side pipeline delay + (1 = 5-stage, 2 = 7-stage) */ +#define XCHAL_CLOCK_GATING_GLOBAL 1 /* global clock gating */ +#define XCHAL_CLOCK_GATING_FUNCUNIT 1 /* funct. unit clock gating */ +/* In T1050, applies to selected core load and store instructions (see ISA): */ +#define XCHAL_UNALIGNED_LOAD_EXCEPTION 0 /* unaligned loads cause exc. */ +#define XCHAL_UNALIGNED_STORE_EXCEPTION 0 /* unaligned stores cause exc.*/ +#define XCHAL_UNALIGNED_LOAD_HW 1 /* unaligned loads work in hw */ +#define XCHAL_UNALIGNED_STORE_HW 1 /* unaligned stores work in hw*/ + +#define XCHAL_SW_VERSION 1100003 /* sw version of this header */ + +#define XCHAL_CORE_ID "esp32_v3_49_prod" /* alphanum core name + (CoreID) set in the Xtensa + Processor Generator */ + +#define XCHAL_BUILD_UNIQUE_ID 0x0005FE96 /* 22-bit sw build ID */ + +/* + * These definitions describe the hardware targeted by this software. + */ +#define XCHAL_HW_CONFIGID0 0xC2BCFFFE /* ConfigID hi 32 bits*/ +#define XCHAL_HW_CONFIGID1 0x1CC5FE96 /* ConfigID lo 32 bits*/ +#define XCHAL_HW_VERSION_NAME "LX6.0.3" /* full version name */ +#define XCHAL_HW_VERSION_MAJOR 2600 /* major ver# of targeted hw */ +#define XCHAL_HW_VERSION_MINOR 3 /* minor ver# of targeted hw */ +#define XCHAL_HW_VERSION 260003 /* major*100+minor */ +#define XCHAL_HW_REL_LX6 1 +#define XCHAL_HW_REL_LX6_0 1 +#define XCHAL_HW_REL_LX6_0_3 1 +#define XCHAL_HW_CONFIGID_RELIABLE 1 +/* If software targets a *range* of hardware versions, these are the bounds: */ +#define XCHAL_HW_MIN_VERSION_MAJOR 2600 /* major v of earliest tgt hw */ +#define XCHAL_HW_MIN_VERSION_MINOR 3 /* minor v of earliest tgt hw */ +#define XCHAL_HW_MIN_VERSION 260003 /* earliest targeted hw */ +#define XCHAL_HW_MAX_VERSION_MAJOR 2600 /* major v of latest tgt hw */ +#define XCHAL_HW_MAX_VERSION_MINOR 3 /* minor v of latest tgt hw */ +#define XCHAL_HW_MAX_VERSION 260003 /* latest targeted hw */ + + +/*---------------------------------------------------------------------- + CACHE + ----------------------------------------------------------------------*/ + +#define XCHAL_ICACHE_LINESIZE 4 /* I-cache line size in bytes */ +#define XCHAL_DCACHE_LINESIZE 4 /* D-cache line size in bytes */ +#define XCHAL_ICACHE_LINEWIDTH 2 /* log2(I line size in bytes) */ +#define XCHAL_DCACHE_LINEWIDTH 2 /* log2(D line size in bytes) */ + +#define XCHAL_ICACHE_SIZE 0 /* I-cache size in bytes or 0 */ +#define XCHAL_DCACHE_SIZE 0 /* D-cache size in bytes or 0 */ + +#define XCHAL_DCACHE_IS_WRITEBACK 0 /* writeback feature */ +#define XCHAL_DCACHE_IS_COHERENT 0 /* MP coherence feature */ + +#define XCHAL_HAVE_PREFETCH 0 /* PREFCTL register */ +#define XCHAL_HAVE_PREFETCH_L1 0 /* prefetch to L1 dcache */ +#define XCHAL_PREFETCH_CASTOUT_LINES 0 /* dcache pref. castout bufsz */ +#define XCHAL_PREFETCH_ENTRIES 0 /* cache prefetch entries */ +#define XCHAL_PREFETCH_BLOCK_ENTRIES 0 /* prefetch block streams */ +#define XCHAL_HAVE_CACHE_BLOCKOPS 0 /* block prefetch for caches */ +#define XCHAL_HAVE_ICACHE_TEST 0 /* Icache test instructions */ +#define XCHAL_HAVE_DCACHE_TEST 0 /* Dcache test instructions */ +#define XCHAL_HAVE_ICACHE_DYN_WAYS 0 /* Icache dynamic way support */ +#define XCHAL_HAVE_DCACHE_DYN_WAYS 0 /* Dcache dynamic way support */ + + + + +/**************************************************************************** + Parameters Useful for PRIVILEGED (Supervisory or Non-Virtualized) Code + ****************************************************************************/ + + +#ifndef XTENSA_HAL_NON_PRIVILEGED_ONLY + +/*---------------------------------------------------------------------- + CACHE + ----------------------------------------------------------------------*/ + +#define XCHAL_HAVE_PIF 1 /* any outbound PIF present */ +#define XCHAL_HAVE_AXI 0 /* AXI bus */ + +#define XCHAL_HAVE_PIF_WR_RESP 0 /* pif write response */ +#define XCHAL_HAVE_PIF_REQ_ATTR 0 /* pif attribute */ + +/* If present, cache size in bytes == (ways * 2^(linewidth + setwidth)). */ + +/* Number of cache sets in log2(lines per way): */ +#define XCHAL_ICACHE_SETWIDTH 0 +#define XCHAL_DCACHE_SETWIDTH 0 + +/* Cache set associativity (number of ways): */ +#define XCHAL_ICACHE_WAYS 1 +#define XCHAL_DCACHE_WAYS 1 + +/* Cache features: */ +#define XCHAL_ICACHE_LINE_LOCKABLE 0 +#define XCHAL_DCACHE_LINE_LOCKABLE 0 +#define XCHAL_ICACHE_ECC_PARITY 0 +#define XCHAL_DCACHE_ECC_PARITY 0 + +/* Cache access size in bytes (affects operation of SICW instruction): */ +#define XCHAL_ICACHE_ACCESS_SIZE 1 +#define XCHAL_DCACHE_ACCESS_SIZE 1 + +#define XCHAL_DCACHE_BANKS 0 /* number of banks */ + +/* Number of encoded cache attr bits (see for decoded bits): */ +#define XCHAL_CA_BITS 4 + + +/*---------------------------------------------------------------------- + INTERNAL I/D RAM/ROMs and XLMI + ----------------------------------------------------------------------*/ + +#define XCHAL_NUM_INSTROM 1 /* number of core instr. ROMs */ +#define XCHAL_NUM_INSTRAM 2 /* number of core instr. RAMs */ +#define XCHAL_NUM_DATAROM 1 /* number of core data ROMs */ +#define XCHAL_NUM_DATARAM 2 /* number of core data RAMs */ +#define XCHAL_NUM_URAM 0 /* number of core unified RAMs*/ +#define XCHAL_NUM_XLMI 1 /* number of core XLMI ports */ + +/* Instruction ROM 0: */ +#define XCHAL_INSTROM0_VADDR 0x40800000 /* virtual address */ +#define XCHAL_INSTROM0_PADDR 0x40800000 /* physical address */ +#define XCHAL_INSTROM0_SIZE 4194304 /* size in bytes */ +#define XCHAL_INSTROM0_ECC_PARITY 0 /* ECC/parity type, 0=none */ + +/* Instruction RAM 0: */ +#define XCHAL_INSTRAM0_VADDR 0x40000000 /* virtual address */ +#define XCHAL_INSTRAM0_PADDR 0x40000000 /* physical address */ +#define XCHAL_INSTRAM0_SIZE 4194304 /* size in bytes */ +#define XCHAL_INSTRAM0_ECC_PARITY 0 /* ECC/parity type, 0=none */ + +/* Instruction RAM 1: */ +#define XCHAL_INSTRAM1_VADDR 0x40400000 /* virtual address */ +#define XCHAL_INSTRAM1_PADDR 0x40400000 /* physical address */ +#define XCHAL_INSTRAM1_SIZE 4194304 /* size in bytes */ +#define XCHAL_INSTRAM1_ECC_PARITY 0 /* ECC/parity type, 0=none */ + +/* Data ROM 0: */ +#define XCHAL_DATAROM0_VADDR 0x3F400000 /* virtual address */ +#define XCHAL_DATAROM0_PADDR 0x3F400000 /* physical address */ +#define XCHAL_DATAROM0_SIZE 4194304 /* size in bytes */ +#define XCHAL_DATAROM0_ECC_PARITY 0 /* ECC/parity type, 0=none */ +#define XCHAL_DATAROM0_BANKS 1 /* number of banks */ + +/* Data RAM 0: */ +#define XCHAL_DATARAM0_VADDR 0x3FF80000 /* virtual address */ +#define XCHAL_DATARAM0_PADDR 0x3FF80000 /* physical address */ +#define XCHAL_DATARAM0_SIZE 524288 /* size in bytes */ +#define XCHAL_DATARAM0_ECC_PARITY 0 /* ECC/parity type, 0=none */ +#define XCHAL_DATARAM0_BANKS 1 /* number of banks */ + +/* Data RAM 1: */ +#define XCHAL_DATARAM1_VADDR 0x3F800000 /* virtual address */ +#define XCHAL_DATARAM1_PADDR 0x3F800000 /* physical address */ +#define XCHAL_DATARAM1_SIZE 4194304 /* size in bytes */ +#define XCHAL_DATARAM1_ECC_PARITY 0 /* ECC/parity type, 0=none */ +#define XCHAL_DATARAM1_BANKS 1 /* number of banks */ + +/* XLMI Port 0: */ +#define XCHAL_XLMI0_VADDR 0x3FF00000 /* virtual address */ +#define XCHAL_XLMI0_PADDR 0x3FF00000 /* physical address */ +#define XCHAL_XLMI0_SIZE 524288 /* size in bytes */ +#define XCHAL_XLMI0_ECC_PARITY 0 /* ECC/parity type, 0=none */ + +#define XCHAL_HAVE_IMEM_LOADSTORE 1 /* can load/store to IROM/IRAM*/ + + +/*---------------------------------------------------------------------- + INTERRUPTS and TIMERS + ----------------------------------------------------------------------*/ + +#define XCHAL_HAVE_INTERRUPTS 1 /* interrupt option */ +#define XCHAL_HAVE_HIGHPRI_INTERRUPTS 1 /* med/high-pri. interrupts */ +#define XCHAL_HAVE_NMI 1 /* non-maskable interrupt */ +#define XCHAL_HAVE_CCOUNT 1 /* CCOUNT reg. (timer option) */ +#define XCHAL_NUM_TIMERS 3 /* number of CCOMPAREn regs */ +#define XCHAL_NUM_INTERRUPTS 32 /* number of interrupts */ +#define XCHAL_NUM_INTERRUPTS_LOG2 5 /* ceil(log2(NUM_INTERRUPTS)) */ +#define XCHAL_NUM_EXTINTERRUPTS 26 /* num of external interrupts */ +#define XCHAL_NUM_INTLEVELS 6 /* number of interrupt levels + (not including level zero) */ +#define XCHAL_EXCM_LEVEL 3 /* level masked by PS.EXCM */ + /* (always 1 in XEA1; levels 2 .. EXCM_LEVEL are "medium priority") */ + +/* Masks of interrupts at each interrupt level: */ +#define XCHAL_INTLEVEL1_MASK 0x000637FF +#define XCHAL_INTLEVEL2_MASK 0x00380000 +#define XCHAL_INTLEVEL3_MASK 0x28C08800 +#define XCHAL_INTLEVEL4_MASK 0x53000000 +#define XCHAL_INTLEVEL5_MASK 0x84010000 +#define XCHAL_INTLEVEL6_MASK 0x00000000 +#define XCHAL_INTLEVEL7_MASK 0x00004000 + +/* Masks of interrupts at each range 1..n of interrupt levels: */ +#define XCHAL_INTLEVEL1_ANDBELOW_MASK 0x000637FF +#define XCHAL_INTLEVEL2_ANDBELOW_MASK 0x003E37FF +#define XCHAL_INTLEVEL3_ANDBELOW_MASK 0x28FEBFFF +#define XCHAL_INTLEVEL4_ANDBELOW_MASK 0x7BFEBFFF +#define XCHAL_INTLEVEL5_ANDBELOW_MASK 0xFFFFBFFF +#define XCHAL_INTLEVEL6_ANDBELOW_MASK 0xFFFFBFFF +#define XCHAL_INTLEVEL7_ANDBELOW_MASK 0xFFFFFFFF + +/* Level of each interrupt: */ +#define XCHAL_INT0_LEVEL 1 +#define XCHAL_INT1_LEVEL 1 +#define XCHAL_INT2_LEVEL 1 +#define XCHAL_INT3_LEVEL 1 +#define XCHAL_INT4_LEVEL 1 +#define XCHAL_INT5_LEVEL 1 +#define XCHAL_INT6_LEVEL 1 +#define XCHAL_INT7_LEVEL 1 +#define XCHAL_INT8_LEVEL 1 +#define XCHAL_INT9_LEVEL 1 +#define XCHAL_INT10_LEVEL 1 +#define XCHAL_INT11_LEVEL 3 +#define XCHAL_INT12_LEVEL 1 +#define XCHAL_INT13_LEVEL 1 +#define XCHAL_INT14_LEVEL 7 +#define XCHAL_INT15_LEVEL 3 +#define XCHAL_INT16_LEVEL 5 +#define XCHAL_INT17_LEVEL 1 +#define XCHAL_INT18_LEVEL 1 +#define XCHAL_INT19_LEVEL 2 +#define XCHAL_INT20_LEVEL 2 +#define XCHAL_INT21_LEVEL 2 +#define XCHAL_INT22_LEVEL 3 +#define XCHAL_INT23_LEVEL 3 +#define XCHAL_INT24_LEVEL 4 +#define XCHAL_INT25_LEVEL 4 +#define XCHAL_INT26_LEVEL 5 +#define XCHAL_INT27_LEVEL 3 +#define XCHAL_INT28_LEVEL 4 +#define XCHAL_INT29_LEVEL 3 +#define XCHAL_INT30_LEVEL 4 +#define XCHAL_INT31_LEVEL 5 +#define XCHAL_DEBUGLEVEL 6 /* debug interrupt level */ +#define XCHAL_HAVE_DEBUG_EXTERN_INT 1 /* OCD external db interrupt */ +#define XCHAL_NMILEVEL 7 /* NMI "level" (for use with + EXCSAVE/EPS/EPC_n, RFI n) */ + +/* Type of each interrupt: */ +#define XCHAL_INT0_TYPE XTHAL_INTTYPE_EXTERN_LEVEL +#define XCHAL_INT1_TYPE XTHAL_INTTYPE_EXTERN_LEVEL +#define XCHAL_INT2_TYPE XTHAL_INTTYPE_EXTERN_LEVEL +#define XCHAL_INT3_TYPE XTHAL_INTTYPE_EXTERN_LEVEL +#define XCHAL_INT4_TYPE XTHAL_INTTYPE_EXTERN_LEVEL +#define XCHAL_INT5_TYPE XTHAL_INTTYPE_EXTERN_LEVEL +#define XCHAL_INT6_TYPE XTHAL_INTTYPE_TIMER +#define XCHAL_INT7_TYPE XTHAL_INTTYPE_SOFTWARE +#define XCHAL_INT8_TYPE XTHAL_INTTYPE_EXTERN_LEVEL +#define XCHAL_INT9_TYPE XTHAL_INTTYPE_EXTERN_LEVEL +#define XCHAL_INT10_TYPE XTHAL_INTTYPE_EXTERN_EDGE +#define XCHAL_INT11_TYPE XTHAL_INTTYPE_PROFILING +#define XCHAL_INT12_TYPE XTHAL_INTTYPE_EXTERN_LEVEL +#define XCHAL_INT13_TYPE XTHAL_INTTYPE_EXTERN_LEVEL +#define XCHAL_INT14_TYPE XTHAL_INTTYPE_NMI +#define XCHAL_INT15_TYPE XTHAL_INTTYPE_TIMER +#define XCHAL_INT16_TYPE XTHAL_INTTYPE_TIMER +#define XCHAL_INT17_TYPE XTHAL_INTTYPE_EXTERN_LEVEL +#define XCHAL_INT18_TYPE XTHAL_INTTYPE_EXTERN_LEVEL +#define XCHAL_INT19_TYPE XTHAL_INTTYPE_EXTERN_LEVEL +#define XCHAL_INT20_TYPE XTHAL_INTTYPE_EXTERN_LEVEL +#define XCHAL_INT21_TYPE XTHAL_INTTYPE_EXTERN_LEVEL +#define XCHAL_INT22_TYPE XTHAL_INTTYPE_EXTERN_EDGE +#define XCHAL_INT23_TYPE XTHAL_INTTYPE_EXTERN_LEVEL +#define XCHAL_INT24_TYPE XTHAL_INTTYPE_EXTERN_LEVEL +#define XCHAL_INT25_TYPE XTHAL_INTTYPE_EXTERN_LEVEL +#define XCHAL_INT26_TYPE XTHAL_INTTYPE_EXTERN_LEVEL +#define XCHAL_INT27_TYPE XTHAL_INTTYPE_EXTERN_LEVEL +#define XCHAL_INT28_TYPE XTHAL_INTTYPE_EXTERN_EDGE +#define XCHAL_INT29_TYPE XTHAL_INTTYPE_SOFTWARE +#define XCHAL_INT30_TYPE XTHAL_INTTYPE_EXTERN_EDGE +#define XCHAL_INT31_TYPE XTHAL_INTTYPE_EXTERN_LEVEL + +/* Masks of interrupts for each type of interrupt: */ +#define XCHAL_INTTYPE_MASK_UNCONFIGURED 0x00000000 +#define XCHAL_INTTYPE_MASK_SOFTWARE 0x20000080 +#define XCHAL_INTTYPE_MASK_EXTERN_EDGE 0x50400400 +#define XCHAL_INTTYPE_MASK_EXTERN_LEVEL 0x8FBE333F +#define XCHAL_INTTYPE_MASK_TIMER 0x00018040 +#define XCHAL_INTTYPE_MASK_NMI 0x00004000 +#define XCHAL_INTTYPE_MASK_WRITE_ERROR 0x00000000 +#define XCHAL_INTTYPE_MASK_PROFILING 0x00000800 + +/* Interrupt numbers assigned to specific interrupt sources: */ +#define XCHAL_TIMER0_INTERRUPT 6 /* CCOMPARE0 */ +#define XCHAL_TIMER1_INTERRUPT 15 /* CCOMPARE1 */ +#define XCHAL_TIMER2_INTERRUPT 16 /* CCOMPARE2 */ +#define XCHAL_TIMER3_INTERRUPT XTHAL_TIMER_UNCONFIGURED +#define XCHAL_NMI_INTERRUPT 14 /* non-maskable interrupt */ +#define XCHAL_PROFILING_INTERRUPT 11 /* profiling interrupt */ + +/* Interrupt numbers for levels at which only one interrupt is configured: */ +#define XCHAL_INTLEVEL7_NUM 14 +/* (There are many interrupts each at level(s) 1, 2, 3, 4, 5.) */ + + +/* + * External interrupt mapping. + * These macros describe how Xtensa processor interrupt numbers + * (as numbered internally, eg. in INTERRUPT and INTENABLE registers) + * map to external BInterrupt pins, for those interrupts + * configured as external (level-triggered, edge-triggered, or NMI). + * See the Xtensa processor databook for more details. + */ + +/* Core interrupt numbers mapped to each EXTERNAL BInterrupt pin number: */ +#define XCHAL_EXTINT0_NUM 0 /* (intlevel 1) */ +#define XCHAL_EXTINT1_NUM 1 /* (intlevel 1) */ +#define XCHAL_EXTINT2_NUM 2 /* (intlevel 1) */ +#define XCHAL_EXTINT3_NUM 3 /* (intlevel 1) */ +#define XCHAL_EXTINT4_NUM 4 /* (intlevel 1) */ +#define XCHAL_EXTINT5_NUM 5 /* (intlevel 1) */ +#define XCHAL_EXTINT6_NUM 8 /* (intlevel 1) */ +#define XCHAL_EXTINT7_NUM 9 /* (intlevel 1) */ +#define XCHAL_EXTINT8_NUM 10 /* (intlevel 1) */ +#define XCHAL_EXTINT9_NUM 12 /* (intlevel 1) */ +#define XCHAL_EXTINT10_NUM 13 /* (intlevel 1) */ +#define XCHAL_EXTINT11_NUM 14 /* (intlevel 7) */ +#define XCHAL_EXTINT12_NUM 17 /* (intlevel 1) */ +#define XCHAL_EXTINT13_NUM 18 /* (intlevel 1) */ +#define XCHAL_EXTINT14_NUM 19 /* (intlevel 2) */ +#define XCHAL_EXTINT15_NUM 20 /* (intlevel 2) */ +#define XCHAL_EXTINT16_NUM 21 /* (intlevel 2) */ +#define XCHAL_EXTINT17_NUM 22 /* (intlevel 3) */ +#define XCHAL_EXTINT18_NUM 23 /* (intlevel 3) */ +#define XCHAL_EXTINT19_NUM 24 /* (intlevel 4) */ +#define XCHAL_EXTINT20_NUM 25 /* (intlevel 4) */ +#define XCHAL_EXTINT21_NUM 26 /* (intlevel 5) */ +#define XCHAL_EXTINT22_NUM 27 /* (intlevel 3) */ +#define XCHAL_EXTINT23_NUM 28 /* (intlevel 4) */ +#define XCHAL_EXTINT24_NUM 30 /* (intlevel 4) */ +#define XCHAL_EXTINT25_NUM 31 /* (intlevel 5) */ +/* EXTERNAL BInterrupt pin numbers mapped to each core interrupt number: */ +#define XCHAL_INT0_EXTNUM 0 /* (intlevel 1) */ +#define XCHAL_INT1_EXTNUM 1 /* (intlevel 1) */ +#define XCHAL_INT2_EXTNUM 2 /* (intlevel 1) */ +#define XCHAL_INT3_EXTNUM 3 /* (intlevel 1) */ +#define XCHAL_INT4_EXTNUM 4 /* (intlevel 1) */ +#define XCHAL_INT5_EXTNUM 5 /* (intlevel 1) */ +#define XCHAL_INT8_EXTNUM 6 /* (intlevel 1) */ +#define XCHAL_INT9_EXTNUM 7 /* (intlevel 1) */ +#define XCHAL_INT10_EXTNUM 8 /* (intlevel 1) */ +#define XCHAL_INT12_EXTNUM 9 /* (intlevel 1) */ +#define XCHAL_INT13_EXTNUM 10 /* (intlevel 1) */ +#define XCHAL_INT14_EXTNUM 11 /* (intlevel 7) */ +#define XCHAL_INT17_EXTNUM 12 /* (intlevel 1) */ +#define XCHAL_INT18_EXTNUM 13 /* (intlevel 1) */ +#define XCHAL_INT19_EXTNUM 14 /* (intlevel 2) */ +#define XCHAL_INT20_EXTNUM 15 /* (intlevel 2) */ +#define XCHAL_INT21_EXTNUM 16 /* (intlevel 2) */ +#define XCHAL_INT22_EXTNUM 17 /* (intlevel 3) */ +#define XCHAL_INT23_EXTNUM 18 /* (intlevel 3) */ +#define XCHAL_INT24_EXTNUM 19 /* (intlevel 4) */ +#define XCHAL_INT25_EXTNUM 20 /* (intlevel 4) */ +#define XCHAL_INT26_EXTNUM 21 /* (intlevel 5) */ +#define XCHAL_INT27_EXTNUM 22 /* (intlevel 3) */ +#define XCHAL_INT28_EXTNUM 23 /* (intlevel 4) */ +#define XCHAL_INT30_EXTNUM 24 /* (intlevel 4) */ +#define XCHAL_INT31_EXTNUM 25 /* (intlevel 5) */ + + +/*---------------------------------------------------------------------- + EXCEPTIONS and VECTORS + ----------------------------------------------------------------------*/ + +#define XCHAL_XEA_VERSION 2 /* Xtensa Exception Architecture + number: 1 == XEA1 (old) + 2 == XEA2 (new) + 0 == XEAX (extern) or TX */ +#define XCHAL_HAVE_XEA1 0 /* Exception Architecture 1 */ +#define XCHAL_HAVE_XEA2 1 /* Exception Architecture 2 */ +#define XCHAL_HAVE_XEAX 0 /* External Exception Arch. */ +#define XCHAL_HAVE_EXCEPTIONS 1 /* exception option */ +#define XCHAL_HAVE_HALT 0 /* halt architecture option */ +#define XCHAL_HAVE_BOOTLOADER 0 /* boot loader (for TX) */ +#define XCHAL_HAVE_MEM_ECC_PARITY 0 /* local memory ECC/parity */ +#define XCHAL_HAVE_VECTOR_SELECT 1 /* relocatable vectors */ +#define XCHAL_HAVE_VECBASE 1 /* relocatable vectors */ +#define XCHAL_VECBASE_RESET_VADDR 0x40000000 /* VECBASE reset value */ +#define XCHAL_VECBASE_RESET_PADDR 0x40000000 +#define XCHAL_RESET_VECBASE_OVERLAP 0 + +#define XCHAL_RESET_VECTOR0_VADDR 0x50000000 +#define XCHAL_RESET_VECTOR0_PADDR 0x50000000 +#define XCHAL_RESET_VECTOR1_VADDR 0x40000400 +#define XCHAL_RESET_VECTOR1_PADDR 0x40000400 +#define XCHAL_RESET_VECTOR_VADDR 0x40000400 +#define XCHAL_RESET_VECTOR_PADDR 0x40000400 +#define XCHAL_USER_VECOFS 0x00000340 +#define XCHAL_USER_VECTOR_VADDR 0x40000340 +#define XCHAL_USER_VECTOR_PADDR 0x40000340 +#define XCHAL_KERNEL_VECOFS 0x00000300 +#define XCHAL_KERNEL_VECTOR_VADDR 0x40000300 +#define XCHAL_KERNEL_VECTOR_PADDR 0x40000300 +#define XCHAL_DOUBLEEXC_VECOFS 0x000003C0 +#define XCHAL_DOUBLEEXC_VECTOR_VADDR 0x400003C0 +#define XCHAL_DOUBLEEXC_VECTOR_PADDR 0x400003C0 +#define XCHAL_WINDOW_OF4_VECOFS 0x00000000 +#define XCHAL_WINDOW_UF4_VECOFS 0x00000040 +#define XCHAL_WINDOW_OF8_VECOFS 0x00000080 +#define XCHAL_WINDOW_UF8_VECOFS 0x000000C0 +#define XCHAL_WINDOW_OF12_VECOFS 0x00000100 +#define XCHAL_WINDOW_UF12_VECOFS 0x00000140 +#define XCHAL_WINDOW_VECTORS_VADDR 0x40000000 +#define XCHAL_WINDOW_VECTORS_PADDR 0x40000000 +#define XCHAL_INTLEVEL2_VECOFS 0x00000180 +#define XCHAL_INTLEVEL2_VECTOR_VADDR 0x40000180 +#define XCHAL_INTLEVEL2_VECTOR_PADDR 0x40000180 +#define XCHAL_INTLEVEL3_VECOFS 0x000001C0 +#define XCHAL_INTLEVEL3_VECTOR_VADDR 0x400001C0 +#define XCHAL_INTLEVEL3_VECTOR_PADDR 0x400001C0 +#define XCHAL_INTLEVEL4_VECOFS 0x00000200 +#define XCHAL_INTLEVEL4_VECTOR_VADDR 0x40000200 +#define XCHAL_INTLEVEL4_VECTOR_PADDR 0x40000200 +#define XCHAL_INTLEVEL5_VECOFS 0x00000240 +#define XCHAL_INTLEVEL5_VECTOR_VADDR 0x40000240 +#define XCHAL_INTLEVEL5_VECTOR_PADDR 0x40000240 +#define XCHAL_INTLEVEL6_VECOFS 0x00000280 +#define XCHAL_INTLEVEL6_VECTOR_VADDR 0x40000280 +#define XCHAL_INTLEVEL6_VECTOR_PADDR 0x40000280 +#define XCHAL_DEBUG_VECOFS XCHAL_INTLEVEL6_VECOFS +#define XCHAL_DEBUG_VECTOR_VADDR XCHAL_INTLEVEL6_VECTOR_VADDR +#define XCHAL_DEBUG_VECTOR_PADDR XCHAL_INTLEVEL6_VECTOR_PADDR +#define XCHAL_NMI_VECOFS 0x000002C0 +#define XCHAL_NMI_VECTOR_VADDR 0x400002C0 +#define XCHAL_NMI_VECTOR_PADDR 0x400002C0 +#define XCHAL_INTLEVEL7_VECOFS XCHAL_NMI_VECOFS +#define XCHAL_INTLEVEL7_VECTOR_VADDR XCHAL_NMI_VECTOR_VADDR +#define XCHAL_INTLEVEL7_VECTOR_PADDR XCHAL_NMI_VECTOR_PADDR + + +/*---------------------------------------------------------------------- + DEBUG MODULE + ----------------------------------------------------------------------*/ + +/* Misc */ +#define XCHAL_HAVE_DEBUG_ERI 1 /* ERI to debug module */ +#define XCHAL_HAVE_DEBUG_APB 1 /* APB to debug module */ +#define XCHAL_HAVE_DEBUG_JTAG 1 /* JTAG to debug module */ + +/* On-Chip Debug (OCD) */ +#define XCHAL_HAVE_OCD 1 /* OnChipDebug option */ +#define XCHAL_NUM_IBREAK 2 /* number of IBREAKn regs */ +#define XCHAL_NUM_DBREAK 2 /* number of DBREAKn regs */ +#define XCHAL_HAVE_OCD_DIR_ARRAY 0 /* faster OCD option (to LX4) */ +#define XCHAL_HAVE_OCD_LS32DDR 1 /* L32DDR/S32DDR (faster OCD) */ + +/* TRAX (in core) */ +#define XCHAL_HAVE_TRAX 1 /* TRAX in debug module */ +#define XCHAL_TRAX_MEM_SIZE 16384 /* TRAX memory size in bytes */ +#define XCHAL_TRAX_MEM_SHAREABLE 1 /* start/end regs; ready sig. */ +#define XCHAL_TRAX_ATB_WIDTH 32 /* ATB width (bits), 0=no ATB */ +#define XCHAL_TRAX_TIME_WIDTH 0 /* timestamp bitwidth, 0=none */ + +/* Perf counters */ +#define XCHAL_NUM_PERF_COUNTERS 2 /* performance counters */ + + +/*---------------------------------------------------------------------- + MMU + ----------------------------------------------------------------------*/ + +/* See core-matmap.h header file for more details. */ + +#define XCHAL_HAVE_TLBS 1 /* inverse of HAVE_CACHEATTR */ +#define XCHAL_HAVE_SPANNING_WAY 1 /* one way maps I+D 4GB vaddr */ +#define XCHAL_SPANNING_WAY 0 /* TLB spanning way number */ +#define XCHAL_HAVE_IDENTITY_MAP 1 /* vaddr == paddr always */ +#define XCHAL_HAVE_CACHEATTR 0 /* CACHEATTR register present */ +#define XCHAL_HAVE_MIMIC_CACHEATTR 1 /* region protection */ +#define XCHAL_HAVE_XLT_CACHEATTR 0 /* region prot. w/translation */ +#define XCHAL_HAVE_PTP_MMU 0 /* full MMU (with page table + [autorefill] and protection) + usable for an MMU-based OS */ +/* If none of the above last 4 are set, it's a custom TLB configuration. */ + +#define XCHAL_MMU_ASID_BITS 0 /* number of bits in ASIDs */ +#define XCHAL_MMU_RINGS 1 /* number of rings (1..4) */ +#define XCHAL_MMU_RING_BITS 0 /* num of bits in RING field */ + +#endif /* !XTENSA_HAL_NON_PRIVILEGED_ONLY */ + + +#endif /* _XTENSA_CORE_CONFIGURATION_H */ + diff --git a/components/esp32/include/xtensa/config/core-matmap.h b/components/esp32/include/xtensa/config/core-matmap.h new file mode 100644 index 0000000000..b101f1e6aa --- /dev/null +++ b/components/esp32/include/xtensa/config/core-matmap.h @@ -0,0 +1,318 @@ +/* + * xtensa/config/core-matmap.h -- Memory access and translation mapping + * parameters (CHAL) of the Xtensa processor core configuration. + * + * If you are using Xtensa Tools, see (which includes + * this file) for more details. + * + * In the Xtensa processor products released to date, all parameters + * defined in this file are derivable (at least in theory) from + * information contained in the core-isa.h header file. + * In particular, the following core configuration parameters are relevant: + * XCHAL_HAVE_CACHEATTR + * XCHAL_HAVE_MIMIC_CACHEATTR + * XCHAL_HAVE_XLT_CACHEATTR + * XCHAL_HAVE_PTP_MMU + * XCHAL_ITLB_ARF_ENTRIES_LOG2 + * XCHAL_DTLB_ARF_ENTRIES_LOG2 + * XCHAL_DCACHE_IS_WRITEBACK + * XCHAL_ICACHE_SIZE (presence of I-cache) + * XCHAL_DCACHE_SIZE (presence of D-cache) + * XCHAL_HW_VERSION_MAJOR + * XCHAL_HW_VERSION_MINOR + */ + +/* Customer ID=11657; Build=0x5fe96; Copyright (c) 1999-2016 Tensilica Inc. + + Permission is hereby granted, free of charge, to any person obtaining + a copy of this software and associated documentation files (the + "Software"), to deal in the Software without restriction, including + without limitation the rights to use, copy, modify, merge, publish, + distribute, sublicense, and/or sell copies of the Software, and to + permit persons to whom the Software is furnished to do so, subject to + the following conditions: + + The above copyright notice and this permission notice shall be included + in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY + CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ + + +#ifndef XTENSA_CONFIG_CORE_MATMAP_H +#define XTENSA_CONFIG_CORE_MATMAP_H + + +/*---------------------------------------------------------------------- + CACHE (MEMORY ACCESS) ATTRIBUTES + ----------------------------------------------------------------------*/ + + +/* Cache Attribute encodings -- lists of access modes for each cache attribute: */ +#define XCHAL_FCA_LIST XTHAL_FAM_EXCEPTION XCHAL_SEP \ + XTHAL_FAM_BYPASS XCHAL_SEP \ + XTHAL_FAM_BYPASS XCHAL_SEP \ + XTHAL_FAM_BYPASS XCHAL_SEP \ + XTHAL_FAM_BYPASS XCHAL_SEP \ + XTHAL_FAM_BYPASS XCHAL_SEP \ + XTHAL_FAM_BYPASS XCHAL_SEP \ + XTHAL_FAM_EXCEPTION XCHAL_SEP \ + XTHAL_FAM_EXCEPTION XCHAL_SEP \ + XTHAL_FAM_EXCEPTION XCHAL_SEP \ + XTHAL_FAM_EXCEPTION XCHAL_SEP \ + XTHAL_FAM_EXCEPTION XCHAL_SEP \ + XTHAL_FAM_EXCEPTION XCHAL_SEP \ + XTHAL_FAM_EXCEPTION XCHAL_SEP \ + XTHAL_FAM_EXCEPTION XCHAL_SEP \ + XTHAL_FAM_EXCEPTION +#define XCHAL_LCA_LIST XTHAL_LAM_BYPASSG XCHAL_SEP \ + XTHAL_LAM_BYPASSG XCHAL_SEP \ + XTHAL_LAM_BYPASSG XCHAL_SEP \ + XTHAL_LAM_EXCEPTION XCHAL_SEP \ + XTHAL_LAM_BYPASSG XCHAL_SEP \ + XTHAL_LAM_BYPASSG XCHAL_SEP \ + XTHAL_LAM_BYPASSG XCHAL_SEP \ + XTHAL_LAM_EXCEPTION XCHAL_SEP \ + XTHAL_LAM_EXCEPTION XCHAL_SEP \ + XTHAL_LAM_EXCEPTION XCHAL_SEP \ + XTHAL_LAM_EXCEPTION XCHAL_SEP \ + XTHAL_LAM_EXCEPTION XCHAL_SEP \ + XTHAL_LAM_EXCEPTION XCHAL_SEP \ + XTHAL_LAM_EXCEPTION XCHAL_SEP \ + XTHAL_LAM_BYPASSG XCHAL_SEP \ + XTHAL_LAM_EXCEPTION +#define XCHAL_SCA_LIST XTHAL_SAM_BYPASS XCHAL_SEP \ + XTHAL_SAM_BYPASS XCHAL_SEP \ + XTHAL_SAM_BYPASS XCHAL_SEP \ + XTHAL_SAM_EXCEPTION XCHAL_SEP \ + XTHAL_SAM_BYPASS XCHAL_SEP \ + XTHAL_SAM_BYPASS XCHAL_SEP \ + XTHAL_SAM_BYPASS XCHAL_SEP \ + XTHAL_SAM_EXCEPTION XCHAL_SEP \ + XTHAL_SAM_EXCEPTION XCHAL_SEP \ + XTHAL_SAM_EXCEPTION XCHAL_SEP \ + XTHAL_SAM_EXCEPTION XCHAL_SEP \ + XTHAL_SAM_EXCEPTION XCHAL_SEP \ + XTHAL_SAM_EXCEPTION XCHAL_SEP \ + XTHAL_SAM_EXCEPTION XCHAL_SEP \ + XTHAL_SAM_BYPASS XCHAL_SEP \ + XTHAL_SAM_EXCEPTION + + +/* + * Specific encoded cache attribute values of general interest. + * If a specific cache mode is not available, the closest available + * one is returned instead (eg. writethru instead of writeback, + * bypass instead of writethru). + */ +#define XCHAL_CA_BYPASS 2 /* cache disabled (bypassed) mode */ +#define XCHAL_CA_BYPASSBUF 6 /* cache disabled (bypassed) bufferable mode */ +#define XCHAL_CA_WRITETHRU 2 /* cache enabled (write-through) mode */ +#define XCHAL_CA_WRITEBACK 2 /* cache enabled (write-back) mode */ +#define XCHAL_HAVE_CA_WRITEBACK_NOALLOC 0 /* write-back no-allocate availability */ +#define XCHAL_CA_WRITEBACK_NOALLOC 2 /* cache enabled (write-back no-allocate) mode */ +#define XCHAL_CA_BYPASS_RW 0 /* cache disabled (bypassed) mode (no exec) */ +#define XCHAL_CA_WRITETHRU_RW 0 /* cache enabled (write-through) mode (no exec) */ +#define XCHAL_CA_WRITEBACK_RW 0 /* cache enabled (write-back) mode (no exec) */ +#define XCHAL_CA_WRITEBACK_NOALLOC_RW 0 /* cache enabled (write-back no-allocate) mode (no exec) */ +#define XCHAL_CA_ILLEGAL 15 /* no access allowed (all cause exceptions) mode */ +#define XCHAL_CA_ISOLATE 0 /* cache isolate (accesses go to cache not memory) mode */ + + +/*---------------------------------------------------------------------- + MMU + ----------------------------------------------------------------------*/ + +/* + * General notes on MMU parameters. + * + * Terminology: + * ASID = address-space ID (acts as an "extension" of virtual addresses) + * VPN = virtual page number + * PPN = physical page number + * CA = encoded cache attribute (access modes) + * TLB = translation look-aside buffer (term is stretched somewhat here) + * I = instruction (fetch accesses) + * D = data (load and store accesses) + * way = each TLB (ITLB and DTLB) consists of a number of "ways" + * that simultaneously match the virtual address of an access; + * a TLB successfully translates a virtual address if exactly + * one way matches the vaddr; if none match, it is a miss; + * if multiple match, one gets a "multihit" exception; + * each way can be independently configured in terms of number of + * entries, page sizes, which fields are writable or constant, etc. + * set = group of contiguous ways with exactly identical parameters + * ARF = auto-refill; hardware services a 1st-level miss by loading a PTE + * from the page table and storing it in one of the auto-refill ways; + * if this PTE load also misses, a miss exception is posted for s/w. + * min-wired = a "min-wired" way can be used to map a single (minimum-sized) + * page arbitrarily under program control; it has a single entry, + * is non-auto-refill (some other way(s) must be auto-refill), + * all its fields (VPN, PPN, ASID, CA) are all writable, and it + * supports the XCHAL_MMU_MIN_PTE_PAGE_SIZE page size (a current + * restriction is that this be the only page size it supports). + * + * TLB way entries are virtually indexed. + * TLB ways that support multiple page sizes: + * - must have all writable VPN and PPN fields; + * - can only use one page size at any given time (eg. setup at startup), + * selected by the respective ITLBCFG or DTLBCFG special register, + * whose bits n*4+3 .. n*4 index the list of page sizes for way n + * (XCHAL_xTLB_SETm_PAGESZ_LOG2_LIST for set m corresponding to way n); + * this list may be sparse for auto-refill ways because auto-refill + * ways have independent lists of supported page sizes sharing a + * common encoding with PTE entries; the encoding is the index into + * this list; unsupported sizes for a given way are zero in the list; + * selecting unsupported sizes results in undefined hardware behaviour; + * - is only possible for ways 0 thru 7 (due to ITLBCFG/DTLBCFG definition). + */ + +#define XCHAL_MMU_ASID_INVALID 0 /* ASID value indicating invalid address space */ +#define XCHAL_MMU_ASID_KERNEL 0 /* ASID value indicating kernel (ring 0) address space */ +#define XCHAL_MMU_SR_BITS 0 /* number of size-restriction bits supported */ +#define XCHAL_MMU_CA_BITS 4 /* number of bits needed to hold cache attribute encoding */ +#define XCHAL_MMU_MAX_PTE_PAGE_SIZE 29 /* max page size in a PTE structure (log2) */ +#define XCHAL_MMU_MIN_PTE_PAGE_SIZE 29 /* min page size in a PTE structure (log2) */ + + +/*** Instruction TLB: ***/ + +#define XCHAL_ITLB_WAY_BITS 0 /* number of bits holding the ways */ +#define XCHAL_ITLB_WAYS 1 /* number of ways (n-way set-associative TLB) */ +#define XCHAL_ITLB_ARF_WAYS 0 /* number of auto-refill ways */ +#define XCHAL_ITLB_SETS 1 /* number of sets (groups of ways with identical settings) */ + +/* Way set to which each way belongs: */ +#define XCHAL_ITLB_WAY0_SET 0 + +/* Ways sets that are used by hardware auto-refill (ARF): */ +#define XCHAL_ITLB_ARF_SETS 0 /* number of auto-refill sets */ + +/* Way sets that are "min-wired" (see terminology comment above): */ +#define XCHAL_ITLB_MINWIRED_SETS 0 /* number of "min-wired" sets */ + + +/* ITLB way set 0 (group of ways 0 thru 0): */ +#define XCHAL_ITLB_SET0_WAY 0 /* index of first way in this way set */ +#define XCHAL_ITLB_SET0_WAYS 1 /* number of (contiguous) ways in this way set */ +#define XCHAL_ITLB_SET0_ENTRIES_LOG2 3 /* log2(number of entries in this way) */ +#define XCHAL_ITLB_SET0_ENTRIES 8 /* number of entries in this way (always a power of 2) */ +#define XCHAL_ITLB_SET0_ARF 0 /* 1=autorefill by h/w, 0=non-autorefill (wired/constant/static) */ +#define XCHAL_ITLB_SET0_PAGESIZES 1 /* number of supported page sizes in this way */ +#define XCHAL_ITLB_SET0_PAGESZ_BITS 0 /* number of bits to encode the page size */ +#define XCHAL_ITLB_SET0_PAGESZ_LOG2_MIN 29 /* log2(minimum supported page size) */ +#define XCHAL_ITLB_SET0_PAGESZ_LOG2_MAX 29 /* log2(maximum supported page size) */ +#define XCHAL_ITLB_SET0_PAGESZ_LOG2_LIST 29 /* list of log2(page size)s, separated by XCHAL_SEP; + 2^PAGESZ_BITS entries in list, unsupported entries are zero */ +#define XCHAL_ITLB_SET0_ASID_CONSTMASK 0 /* constant ASID bits; 0 if all writable */ +#define XCHAL_ITLB_SET0_VPN_CONSTMASK 0x00000000 /* constant VPN bits, not including entry index bits; 0 if all writable */ +#define XCHAL_ITLB_SET0_PPN_CONSTMASK 0xE0000000 /* constant PPN bits, including entry index bits; 0 if all writable */ +#define XCHAL_ITLB_SET0_CA_CONSTMASK 0 /* constant CA bits; 0 if all writable */ +#define XCHAL_ITLB_SET0_ASID_RESET 0 /* 1 if ASID reset values defined (and all writable); 0 otherwise */ +#define XCHAL_ITLB_SET0_VPN_RESET 0 /* 1 if VPN reset values defined (and all writable); 0 otherwise */ +#define XCHAL_ITLB_SET0_PPN_RESET 0 /* 1 if PPN reset values defined (and all writable); 0 otherwise */ +#define XCHAL_ITLB_SET0_CA_RESET 1 /* 1 if CA reset values defined (and all writable); 0 otherwise */ +/* Constant VPN values for each entry of ITLB way set 0 (because VPN_CONSTMASK is non-zero): */ +#define XCHAL_ITLB_SET0_E0_VPN_CONST 0x00000000 +#define XCHAL_ITLB_SET0_E1_VPN_CONST 0x20000000 +#define XCHAL_ITLB_SET0_E2_VPN_CONST 0x40000000 +#define XCHAL_ITLB_SET0_E3_VPN_CONST 0x60000000 +#define XCHAL_ITLB_SET0_E4_VPN_CONST 0x80000000 +#define XCHAL_ITLB_SET0_E5_VPN_CONST 0xA0000000 +#define XCHAL_ITLB_SET0_E6_VPN_CONST 0xC0000000 +#define XCHAL_ITLB_SET0_E7_VPN_CONST 0xE0000000 +/* Constant PPN values for each entry of ITLB way set 0 (because PPN_CONSTMASK is non-zero): */ +#define XCHAL_ITLB_SET0_E0_PPN_CONST 0x00000000 +#define XCHAL_ITLB_SET0_E1_PPN_CONST 0x20000000 +#define XCHAL_ITLB_SET0_E2_PPN_CONST 0x40000000 +#define XCHAL_ITLB_SET0_E3_PPN_CONST 0x60000000 +#define XCHAL_ITLB_SET0_E4_PPN_CONST 0x80000000 +#define XCHAL_ITLB_SET0_E5_PPN_CONST 0xA0000000 +#define XCHAL_ITLB_SET0_E6_PPN_CONST 0xC0000000 +#define XCHAL_ITLB_SET0_E7_PPN_CONST 0xE0000000 +/* Reset CA values for each entry of ITLB way set 0 (because SET0_CA_RESET is non-zero): */ +#define XCHAL_ITLB_SET0_E0_CA_RESET 0x02 +#define XCHAL_ITLB_SET0_E1_CA_RESET 0x02 +#define XCHAL_ITLB_SET0_E2_CA_RESET 0x02 +#define XCHAL_ITLB_SET0_E3_CA_RESET 0x02 +#define XCHAL_ITLB_SET0_E4_CA_RESET 0x02 +#define XCHAL_ITLB_SET0_E5_CA_RESET 0x02 +#define XCHAL_ITLB_SET0_E6_CA_RESET 0x02 +#define XCHAL_ITLB_SET0_E7_CA_RESET 0x02 + + +/*** Data TLB: ***/ + +#define XCHAL_DTLB_WAY_BITS 0 /* number of bits holding the ways */ +#define XCHAL_DTLB_WAYS 1 /* number of ways (n-way set-associative TLB) */ +#define XCHAL_DTLB_ARF_WAYS 0 /* number of auto-refill ways */ +#define XCHAL_DTLB_SETS 1 /* number of sets (groups of ways with identical settings) */ + +/* Way set to which each way belongs: */ +#define XCHAL_DTLB_WAY0_SET 0 + +/* Ways sets that are used by hardware auto-refill (ARF): */ +#define XCHAL_DTLB_ARF_SETS 0 /* number of auto-refill sets */ + +/* Way sets that are "min-wired" (see terminology comment above): */ +#define XCHAL_DTLB_MINWIRED_SETS 0 /* number of "min-wired" sets */ + + +/* DTLB way set 0 (group of ways 0 thru 0): */ +#define XCHAL_DTLB_SET0_WAY 0 /* index of first way in this way set */ +#define XCHAL_DTLB_SET0_WAYS 1 /* number of (contiguous) ways in this way set */ +#define XCHAL_DTLB_SET0_ENTRIES_LOG2 3 /* log2(number of entries in this way) */ +#define XCHAL_DTLB_SET0_ENTRIES 8 /* number of entries in this way (always a power of 2) */ +#define XCHAL_DTLB_SET0_ARF 0 /* 1=autorefill by h/w, 0=non-autorefill (wired/constant/static) */ +#define XCHAL_DTLB_SET0_PAGESIZES 1 /* number of supported page sizes in this way */ +#define XCHAL_DTLB_SET0_PAGESZ_BITS 0 /* number of bits to encode the page size */ +#define XCHAL_DTLB_SET0_PAGESZ_LOG2_MIN 29 /* log2(minimum supported page size) */ +#define XCHAL_DTLB_SET0_PAGESZ_LOG2_MAX 29 /* log2(maximum supported page size) */ +#define XCHAL_DTLB_SET0_PAGESZ_LOG2_LIST 29 /* list of log2(page size)s, separated by XCHAL_SEP; + 2^PAGESZ_BITS entries in list, unsupported entries are zero */ +#define XCHAL_DTLB_SET0_ASID_CONSTMASK 0 /* constant ASID bits; 0 if all writable */ +#define XCHAL_DTLB_SET0_VPN_CONSTMASK 0x00000000 /* constant VPN bits, not including entry index bits; 0 if all writable */ +#define XCHAL_DTLB_SET0_PPN_CONSTMASK 0xE0000000 /* constant PPN bits, including entry index bits; 0 if all writable */ +#define XCHAL_DTLB_SET0_CA_CONSTMASK 0 /* constant CA bits; 0 if all writable */ +#define XCHAL_DTLB_SET0_ASID_RESET 0 /* 1 if ASID reset values defined (and all writable); 0 otherwise */ +#define XCHAL_DTLB_SET0_VPN_RESET 0 /* 1 if VPN reset values defined (and all writable); 0 otherwise */ +#define XCHAL_DTLB_SET0_PPN_RESET 0 /* 1 if PPN reset values defined (and all writable); 0 otherwise */ +#define XCHAL_DTLB_SET0_CA_RESET 1 /* 1 if CA reset values defined (and all writable); 0 otherwise */ +/* Constant VPN values for each entry of DTLB way set 0 (because VPN_CONSTMASK is non-zero): */ +#define XCHAL_DTLB_SET0_E0_VPN_CONST 0x00000000 +#define XCHAL_DTLB_SET0_E1_VPN_CONST 0x20000000 +#define XCHAL_DTLB_SET0_E2_VPN_CONST 0x40000000 +#define XCHAL_DTLB_SET0_E3_VPN_CONST 0x60000000 +#define XCHAL_DTLB_SET0_E4_VPN_CONST 0x80000000 +#define XCHAL_DTLB_SET0_E5_VPN_CONST 0xA0000000 +#define XCHAL_DTLB_SET0_E6_VPN_CONST 0xC0000000 +#define XCHAL_DTLB_SET0_E7_VPN_CONST 0xE0000000 +/* Constant PPN values for each entry of DTLB way set 0 (because PPN_CONSTMASK is non-zero): */ +#define XCHAL_DTLB_SET0_E0_PPN_CONST 0x00000000 +#define XCHAL_DTLB_SET0_E1_PPN_CONST 0x20000000 +#define XCHAL_DTLB_SET0_E2_PPN_CONST 0x40000000 +#define XCHAL_DTLB_SET0_E3_PPN_CONST 0x60000000 +#define XCHAL_DTLB_SET0_E4_PPN_CONST 0x80000000 +#define XCHAL_DTLB_SET0_E5_PPN_CONST 0xA0000000 +#define XCHAL_DTLB_SET0_E6_PPN_CONST 0xC0000000 +#define XCHAL_DTLB_SET0_E7_PPN_CONST 0xE0000000 +/* Reset CA values for each entry of DTLB way set 0 (because SET0_CA_RESET is non-zero): */ +#define XCHAL_DTLB_SET0_E0_CA_RESET 0x02 +#define XCHAL_DTLB_SET0_E1_CA_RESET 0x02 +#define XCHAL_DTLB_SET0_E2_CA_RESET 0x02 +#define XCHAL_DTLB_SET0_E3_CA_RESET 0x02 +#define XCHAL_DTLB_SET0_E4_CA_RESET 0x02 +#define XCHAL_DTLB_SET0_E5_CA_RESET 0x02 +#define XCHAL_DTLB_SET0_E6_CA_RESET 0x02 +#define XCHAL_DTLB_SET0_E7_CA_RESET 0x02 + + + + +#endif /*XTENSA_CONFIG_CORE_MATMAP_H*/ + diff --git a/components/esp32/include/xtensa/config/core.h b/components/esp32/include/xtensa/config/core.h new file mode 100644 index 0000000000..98f1b1961a --- /dev/null +++ b/components/esp32/include/xtensa/config/core.h @@ -0,0 +1,1405 @@ +/* + * xtensa/config/core.h -- HAL definitions dependent on CORE configuration + * + * This header file is sometimes referred to as the "compile-time HAL" or CHAL. + * It pulls definitions tailored for a specific Xtensa processor configuration. + * + * Sources for binaries meant to be configuration-independent generally avoid + * including this file (they may use the configuration-specific HAL library). + * It is normal for the HAL library source itself to include this file. + */ + +/* + * Copyright (c) 2005-2014 Cadence Design Systems, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY + * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + + +#ifndef XTENSA_CONFIG_CORE_H +#define XTENSA_CONFIG_CORE_H + +/* CONFIGURATION INDEPENDENT DEFINITIONS: */ +#ifdef __XTENSA__ +#include +#include +#else +#include "../hal.h" +#include "../xtensa-versions.h" +#endif + +/* CONFIGURATION SPECIFIC DEFINITIONS: */ +#ifdef __XTENSA__ +#include +#include +#include +#else +#include "core-isa.h" +#include "core-matmap.h" +#include "tie.h" +#endif + +#if defined (_ASMLANGUAGE) || defined (__ASSEMBLER__) +#ifdef __XTENSA__ +#include +#else +#include "tie-asm.h" +#endif +#endif /*_ASMLANGUAGE or __ASSEMBLER__*/ + + +/*---------------------------------------------------------------------- + GENERAL + ----------------------------------------------------------------------*/ + +/* + * Separators for macros that expand into arrays. + * These can be predefined by files that #include this one, + * when different separators are required. + */ +/* Element separator for macros that expand into 1-dimensional arrays: */ +#ifndef XCHAL_SEP +#define XCHAL_SEP , +#endif +/* Array separator for macros that expand into 2-dimensional arrays: */ +#ifndef XCHAL_SEP2 +#define XCHAL_SEP2 },{ +#endif + + + +/*---------------------------------------------------------------------- + ISA + ----------------------------------------------------------------------*/ + +#if XCHAL_HAVE_BE +# define XCHAL_HAVE_LE 0 +# define XCHAL_MEMORY_ORDER XTHAL_BIGENDIAN +#else +# define XCHAL_HAVE_LE 1 +# define XCHAL_MEMORY_ORDER XTHAL_LITTLEENDIAN +#endif + + + +/*---------------------------------------------------------------------- + INTERRUPTS + ----------------------------------------------------------------------*/ + +/* Indexing macros: */ +#define _XCHAL_INTLEVEL_MASK(n) XCHAL_INTLEVEL ## n ## _MASK +#define XCHAL_INTLEVEL_MASK(n) _XCHAL_INTLEVEL_MASK(n) /* n = 0 .. 15 */ +#define _XCHAL_INTLEVEL_ANDBELOWMASK(n) XCHAL_INTLEVEL ## n ## _ANDBELOW_MASK +#define XCHAL_INTLEVEL_ANDBELOW_MASK(n) _XCHAL_INTLEVEL_ANDBELOWMASK(n) /* n = 0 .. 15 */ +#define _XCHAL_INTLEVEL_NUM(n) XCHAL_INTLEVEL ## n ## _NUM +#define XCHAL_INTLEVEL_NUM(n) _XCHAL_INTLEVEL_NUM(n) /* n = 0 .. 15 */ +#define _XCHAL_INT_LEVEL(n) XCHAL_INT ## n ## _LEVEL +#define XCHAL_INT_LEVEL(n) _XCHAL_INT_LEVEL(n) /* n = 0 .. 31 */ +#define _XCHAL_INT_TYPE(n) XCHAL_INT ## n ## _TYPE +#define XCHAL_INT_TYPE(n) _XCHAL_INT_TYPE(n) /* n = 0 .. 31 */ +#define _XCHAL_TIMER_INTERRUPT(n) XCHAL_TIMER ## n ## _INTERRUPT +#define XCHAL_TIMER_INTERRUPT(n) _XCHAL_TIMER_INTERRUPT(n) /* n = 0 .. 3 */ + + +#define XCHAL_HAVE_HIGHLEVEL_INTERRUPTS XCHAL_HAVE_HIGHPRI_INTERRUPTS +#define XCHAL_NUM_LOWPRI_LEVELS 1 /* number of low-priority interrupt levels (always 1) */ +#define XCHAL_FIRST_HIGHPRI_LEVEL (XCHAL_NUM_LOWPRI_LEVELS+1) /* level of first high-priority interrupt (always 2) */ +/* Note: 1 <= LOWPRI_LEVELS <= EXCM_LEVEL < DEBUGLEVEL <= NUM_INTLEVELS < NMILEVEL <= 15 */ + +/* These values are constant for existing Xtensa processor implementations: */ +#define XCHAL_INTLEVEL0_MASK 0x00000000 +#define XCHAL_INTLEVEL8_MASK 0x00000000 +#define XCHAL_INTLEVEL9_MASK 0x00000000 +#define XCHAL_INTLEVEL10_MASK 0x00000000 +#define XCHAL_INTLEVEL11_MASK 0x00000000 +#define XCHAL_INTLEVEL12_MASK 0x00000000 +#define XCHAL_INTLEVEL13_MASK 0x00000000 +#define XCHAL_INTLEVEL14_MASK 0x00000000 +#define XCHAL_INTLEVEL15_MASK 0x00000000 + +/* Array of masks of interrupts at each interrupt level: */ +#define XCHAL_INTLEVEL_MASKS XCHAL_INTLEVEL0_MASK \ + XCHAL_SEP XCHAL_INTLEVEL1_MASK \ + XCHAL_SEP XCHAL_INTLEVEL2_MASK \ + XCHAL_SEP XCHAL_INTLEVEL3_MASK \ + XCHAL_SEP XCHAL_INTLEVEL4_MASK \ + XCHAL_SEP XCHAL_INTLEVEL5_MASK \ + XCHAL_SEP XCHAL_INTLEVEL6_MASK \ + XCHAL_SEP XCHAL_INTLEVEL7_MASK \ + XCHAL_SEP XCHAL_INTLEVEL8_MASK \ + XCHAL_SEP XCHAL_INTLEVEL9_MASK \ + XCHAL_SEP XCHAL_INTLEVEL10_MASK \ + XCHAL_SEP XCHAL_INTLEVEL11_MASK \ + XCHAL_SEP XCHAL_INTLEVEL12_MASK \ + XCHAL_SEP XCHAL_INTLEVEL13_MASK \ + XCHAL_SEP XCHAL_INTLEVEL14_MASK \ + XCHAL_SEP XCHAL_INTLEVEL15_MASK + +/* These values are constant for existing Xtensa processor implementations: */ +#define XCHAL_INTLEVEL0_ANDBELOW_MASK 0x00000000 +#define XCHAL_INTLEVEL8_ANDBELOW_MASK XCHAL_INTLEVEL7_ANDBELOW_MASK +#define XCHAL_INTLEVEL9_ANDBELOW_MASK XCHAL_INTLEVEL7_ANDBELOW_MASK +#define XCHAL_INTLEVEL10_ANDBELOW_MASK XCHAL_INTLEVEL7_ANDBELOW_MASK +#define XCHAL_INTLEVEL11_ANDBELOW_MASK XCHAL_INTLEVEL7_ANDBELOW_MASK +#define XCHAL_INTLEVEL12_ANDBELOW_MASK XCHAL_INTLEVEL7_ANDBELOW_MASK +#define XCHAL_INTLEVEL13_ANDBELOW_MASK XCHAL_INTLEVEL7_ANDBELOW_MASK +#define XCHAL_INTLEVEL14_ANDBELOW_MASK XCHAL_INTLEVEL7_ANDBELOW_MASK +#define XCHAL_INTLEVEL15_ANDBELOW_MASK XCHAL_INTLEVEL7_ANDBELOW_MASK + +/* Mask of all low-priority interrupts: */ +#define XCHAL_LOWPRI_MASK XCHAL_INTLEVEL1_ANDBELOW_MASK + +/* Mask of all interrupts masked by PS.EXCM (or CEXCM): */ +#define XCHAL_EXCM_MASK XCHAL_INTLEVEL_ANDBELOW_MASK(XCHAL_EXCM_LEVEL) + +/* Array of masks of interrupts at each range 1..n of interrupt levels: */ +#define XCHAL_INTLEVEL_ANDBELOW_MASKS XCHAL_INTLEVEL0_ANDBELOW_MASK \ + XCHAL_SEP XCHAL_INTLEVEL1_ANDBELOW_MASK \ + XCHAL_SEP XCHAL_INTLEVEL2_ANDBELOW_MASK \ + XCHAL_SEP XCHAL_INTLEVEL3_ANDBELOW_MASK \ + XCHAL_SEP XCHAL_INTLEVEL4_ANDBELOW_MASK \ + XCHAL_SEP XCHAL_INTLEVEL5_ANDBELOW_MASK \ + XCHAL_SEP XCHAL_INTLEVEL6_ANDBELOW_MASK \ + XCHAL_SEP XCHAL_INTLEVEL7_ANDBELOW_MASK \ + XCHAL_SEP XCHAL_INTLEVEL8_ANDBELOW_MASK \ + XCHAL_SEP XCHAL_INTLEVEL9_ANDBELOW_MASK \ + XCHAL_SEP XCHAL_INTLEVEL10_ANDBELOW_MASK \ + XCHAL_SEP XCHAL_INTLEVEL11_ANDBELOW_MASK \ + XCHAL_SEP XCHAL_INTLEVEL12_ANDBELOW_MASK \ + XCHAL_SEP XCHAL_INTLEVEL13_ANDBELOW_MASK \ + XCHAL_SEP XCHAL_INTLEVEL14_ANDBELOW_MASK \ + XCHAL_SEP XCHAL_INTLEVEL15_ANDBELOW_MASK + +#if 0 /*XCHAL_HAVE_NMI*/ +/* NMI "interrupt level" (for use with EXCSAVE_n, EPS_n, EPC_n, RFI n): */ +# define XCHAL_NMILEVEL (XCHAL_NUM_INTLEVELS+1) +#endif + +/* Array of levels of each possible interrupt: */ +#define XCHAL_INT_LEVELS XCHAL_INT0_LEVEL \ + XCHAL_SEP XCHAL_INT1_LEVEL \ + XCHAL_SEP XCHAL_INT2_LEVEL \ + XCHAL_SEP XCHAL_INT3_LEVEL \ + XCHAL_SEP XCHAL_INT4_LEVEL \ + XCHAL_SEP XCHAL_INT5_LEVEL \ + XCHAL_SEP XCHAL_INT6_LEVEL \ + XCHAL_SEP XCHAL_INT7_LEVEL \ + XCHAL_SEP XCHAL_INT8_LEVEL \ + XCHAL_SEP XCHAL_INT9_LEVEL \ + XCHAL_SEP XCHAL_INT10_LEVEL \ + XCHAL_SEP XCHAL_INT11_LEVEL \ + XCHAL_SEP XCHAL_INT12_LEVEL \ + XCHAL_SEP XCHAL_INT13_LEVEL \ + XCHAL_SEP XCHAL_INT14_LEVEL \ + XCHAL_SEP XCHAL_INT15_LEVEL \ + XCHAL_SEP XCHAL_INT16_LEVEL \ + XCHAL_SEP XCHAL_INT17_LEVEL \ + XCHAL_SEP XCHAL_INT18_LEVEL \ + XCHAL_SEP XCHAL_INT19_LEVEL \ + XCHAL_SEP XCHAL_INT20_LEVEL \ + XCHAL_SEP XCHAL_INT21_LEVEL \ + XCHAL_SEP XCHAL_INT22_LEVEL \ + XCHAL_SEP XCHAL_INT23_LEVEL \ + XCHAL_SEP XCHAL_INT24_LEVEL \ + XCHAL_SEP XCHAL_INT25_LEVEL \ + XCHAL_SEP XCHAL_INT26_LEVEL \ + XCHAL_SEP XCHAL_INT27_LEVEL \ + XCHAL_SEP XCHAL_INT28_LEVEL \ + XCHAL_SEP XCHAL_INT29_LEVEL \ + XCHAL_SEP XCHAL_INT30_LEVEL \ + XCHAL_SEP XCHAL_INT31_LEVEL + +/* Array of types of each possible interrupt: */ +#define XCHAL_INT_TYPES XCHAL_INT0_TYPE \ + XCHAL_SEP XCHAL_INT1_TYPE \ + XCHAL_SEP XCHAL_INT2_TYPE \ + XCHAL_SEP XCHAL_INT3_TYPE \ + XCHAL_SEP XCHAL_INT4_TYPE \ + XCHAL_SEP XCHAL_INT5_TYPE \ + XCHAL_SEP XCHAL_INT6_TYPE \ + XCHAL_SEP XCHAL_INT7_TYPE \ + XCHAL_SEP XCHAL_INT8_TYPE \ + XCHAL_SEP XCHAL_INT9_TYPE \ + XCHAL_SEP XCHAL_INT10_TYPE \ + XCHAL_SEP XCHAL_INT11_TYPE \ + XCHAL_SEP XCHAL_INT12_TYPE \ + XCHAL_SEP XCHAL_INT13_TYPE \ + XCHAL_SEP XCHAL_INT14_TYPE \ + XCHAL_SEP XCHAL_INT15_TYPE \ + XCHAL_SEP XCHAL_INT16_TYPE \ + XCHAL_SEP XCHAL_INT17_TYPE \ + XCHAL_SEP XCHAL_INT18_TYPE \ + XCHAL_SEP XCHAL_INT19_TYPE \ + XCHAL_SEP XCHAL_INT20_TYPE \ + XCHAL_SEP XCHAL_INT21_TYPE \ + XCHAL_SEP XCHAL_INT22_TYPE \ + XCHAL_SEP XCHAL_INT23_TYPE \ + XCHAL_SEP XCHAL_INT24_TYPE \ + XCHAL_SEP XCHAL_INT25_TYPE \ + XCHAL_SEP XCHAL_INT26_TYPE \ + XCHAL_SEP XCHAL_INT27_TYPE \ + XCHAL_SEP XCHAL_INT28_TYPE \ + XCHAL_SEP XCHAL_INT29_TYPE \ + XCHAL_SEP XCHAL_INT30_TYPE \ + XCHAL_SEP XCHAL_INT31_TYPE + +/* Array of masks of interrupts for each type of interrupt: */ +#define XCHAL_INTTYPE_MASKS XCHAL_INTTYPE_MASK_UNCONFIGURED \ + XCHAL_SEP XCHAL_INTTYPE_MASK_SOFTWARE \ + XCHAL_SEP XCHAL_INTTYPE_MASK_EXTERN_EDGE \ + XCHAL_SEP XCHAL_INTTYPE_MASK_EXTERN_LEVEL \ + XCHAL_SEP XCHAL_INTTYPE_MASK_TIMER \ + XCHAL_SEP XCHAL_INTTYPE_MASK_NMI \ + XCHAL_SEP XCHAL_INTTYPE_MASK_WRITE_ERROR + +/* Interrupts that can be cleared using the INTCLEAR special register: */ +#define XCHAL_INTCLEARABLE_MASK (XCHAL_INTTYPE_MASK_SOFTWARE+XCHAL_INTTYPE_MASK_EXTERN_EDGE+XCHAL_INTTYPE_MASK_WRITE_ERROR) +/* Interrupts that can be triggered using the INTSET special register: */ +#define XCHAL_INTSETTABLE_MASK XCHAL_INTTYPE_MASK_SOFTWARE + +/* Array of interrupts assigned to each timer (CCOMPARE0 to CCOMPARE3): */ +#define XCHAL_TIMER_INTERRUPTS XCHAL_TIMER0_INTERRUPT \ + XCHAL_SEP XCHAL_TIMER1_INTERRUPT \ + XCHAL_SEP XCHAL_TIMER2_INTERRUPT \ + XCHAL_SEP XCHAL_TIMER3_INTERRUPT + + + +/* For backward compatibility and for the array macros, define macros for + * each unconfigured interrupt number (unfortunately, the value of + * XTHAL_INTTYPE_UNCONFIGURED is not zero): */ +#if XCHAL_NUM_INTERRUPTS == 0 +# define XCHAL_INT0_LEVEL 0 +# define XCHAL_INT0_TYPE XTHAL_INTTYPE_UNCONFIGURED +#endif +#if XCHAL_NUM_INTERRUPTS <= 1 +# define XCHAL_INT1_LEVEL 0 +# define XCHAL_INT1_TYPE XTHAL_INTTYPE_UNCONFIGURED +#endif +#if XCHAL_NUM_INTERRUPTS <= 2 +# define XCHAL_INT2_LEVEL 0 +# define XCHAL_INT2_TYPE XTHAL_INTTYPE_UNCONFIGURED +#endif +#if XCHAL_NUM_INTERRUPTS <= 3 +# define XCHAL_INT3_LEVEL 0 +# define XCHAL_INT3_TYPE XTHAL_INTTYPE_UNCONFIGURED +#endif +#if XCHAL_NUM_INTERRUPTS <= 4 +# define XCHAL_INT4_LEVEL 0 +# define XCHAL_INT4_TYPE XTHAL_INTTYPE_UNCONFIGURED +#endif +#if XCHAL_NUM_INTERRUPTS <= 5 +# define XCHAL_INT5_LEVEL 0 +# define XCHAL_INT5_TYPE XTHAL_INTTYPE_UNCONFIGURED +#endif +#if XCHAL_NUM_INTERRUPTS <= 6 +# define XCHAL_INT6_LEVEL 0 +# define XCHAL_INT6_TYPE XTHAL_INTTYPE_UNCONFIGURED +#endif +#if XCHAL_NUM_INTERRUPTS <= 7 +# define XCHAL_INT7_LEVEL 0 +# define XCHAL_INT7_TYPE XTHAL_INTTYPE_UNCONFIGURED +#endif +#if XCHAL_NUM_INTERRUPTS <= 8 +# define XCHAL_INT8_LEVEL 0 +# define XCHAL_INT8_TYPE XTHAL_INTTYPE_UNCONFIGURED +#endif +#if XCHAL_NUM_INTERRUPTS <= 9 +# define XCHAL_INT9_LEVEL 0 +# define XCHAL_INT9_TYPE XTHAL_INTTYPE_UNCONFIGURED +#endif +#if XCHAL_NUM_INTERRUPTS <= 10 +# define XCHAL_INT10_LEVEL 0 +# define XCHAL_INT10_TYPE XTHAL_INTTYPE_UNCONFIGURED +#endif +#if XCHAL_NUM_INTERRUPTS <= 11 +# define XCHAL_INT11_LEVEL 0 +# define XCHAL_INT11_TYPE XTHAL_INTTYPE_UNCONFIGURED +#endif +#if XCHAL_NUM_INTERRUPTS <= 12 +# define XCHAL_INT12_LEVEL 0 +# define XCHAL_INT12_TYPE XTHAL_INTTYPE_UNCONFIGURED +#endif +#if XCHAL_NUM_INTERRUPTS <= 13 +# define XCHAL_INT13_LEVEL 0 +# define XCHAL_INT13_TYPE XTHAL_INTTYPE_UNCONFIGURED +#endif +#if XCHAL_NUM_INTERRUPTS <= 14 +# define XCHAL_INT14_LEVEL 0 +# define XCHAL_INT14_TYPE XTHAL_INTTYPE_UNCONFIGURED +#endif +#if XCHAL_NUM_INTERRUPTS <= 15 +# define XCHAL_INT15_LEVEL 0 +# define XCHAL_INT15_TYPE XTHAL_INTTYPE_UNCONFIGURED +#endif +#if XCHAL_NUM_INTERRUPTS <= 16 +# define XCHAL_INT16_LEVEL 0 +# define XCHAL_INT16_TYPE XTHAL_INTTYPE_UNCONFIGURED +#endif +#if XCHAL_NUM_INTERRUPTS <= 17 +# define XCHAL_INT17_LEVEL 0 +# define XCHAL_INT17_TYPE XTHAL_INTTYPE_UNCONFIGURED +#endif +#if XCHAL_NUM_INTERRUPTS <= 18 +# define XCHAL_INT18_LEVEL 0 +# define XCHAL_INT18_TYPE XTHAL_INTTYPE_UNCONFIGURED +#endif +#if XCHAL_NUM_INTERRUPTS <= 19 +# define XCHAL_INT19_LEVEL 0 +# define XCHAL_INT19_TYPE XTHAL_INTTYPE_UNCONFIGURED +#endif +#if XCHAL_NUM_INTERRUPTS <= 20 +# define XCHAL_INT20_LEVEL 0 +# define XCHAL_INT20_TYPE XTHAL_INTTYPE_UNCONFIGURED +#endif +#if XCHAL_NUM_INTERRUPTS <= 21 +# define XCHAL_INT21_LEVEL 0 +# define XCHAL_INT21_TYPE XTHAL_INTTYPE_UNCONFIGURED +#endif +#if XCHAL_NUM_INTERRUPTS <= 22 +# define XCHAL_INT22_LEVEL 0 +# define XCHAL_INT22_TYPE XTHAL_INTTYPE_UNCONFIGURED +#endif +#if XCHAL_NUM_INTERRUPTS <= 23 +# define XCHAL_INT23_LEVEL 0 +# define XCHAL_INT23_TYPE XTHAL_INTTYPE_UNCONFIGURED +#endif +#if XCHAL_NUM_INTERRUPTS <= 24 +# define XCHAL_INT24_LEVEL 0 +# define XCHAL_INT24_TYPE XTHAL_INTTYPE_UNCONFIGURED +#endif +#if XCHAL_NUM_INTERRUPTS <= 25 +# define XCHAL_INT25_LEVEL 0 +# define XCHAL_INT25_TYPE XTHAL_INTTYPE_UNCONFIGURED +#endif +#if XCHAL_NUM_INTERRUPTS <= 26 +# define XCHAL_INT26_LEVEL 0 +# define XCHAL_INT26_TYPE XTHAL_INTTYPE_UNCONFIGURED +#endif +#if XCHAL_NUM_INTERRUPTS <= 27 +# define XCHAL_INT27_LEVEL 0 +# define XCHAL_INT27_TYPE XTHAL_INTTYPE_UNCONFIGURED +#endif +#if XCHAL_NUM_INTERRUPTS <= 28 +# define XCHAL_INT28_LEVEL 0 +# define XCHAL_INT28_TYPE XTHAL_INTTYPE_UNCONFIGURED +#endif +#if XCHAL_NUM_INTERRUPTS <= 29 +# define XCHAL_INT29_LEVEL 0 +# define XCHAL_INT29_TYPE XTHAL_INTTYPE_UNCONFIGURED +#endif +#if XCHAL_NUM_INTERRUPTS <= 30 +# define XCHAL_INT30_LEVEL 0 +# define XCHAL_INT30_TYPE XTHAL_INTTYPE_UNCONFIGURED +#endif +#if XCHAL_NUM_INTERRUPTS <= 31 +# define XCHAL_INT31_LEVEL 0 +# define XCHAL_INT31_TYPE XTHAL_INTTYPE_UNCONFIGURED +#endif + + +/* + * Masks and levels corresponding to each *external* interrupt. + */ + +#define XCHAL_EXTINT0_MASK (1 << XCHAL_EXTINT0_NUM) +#define XCHAL_EXTINT0_LEVEL XCHAL_INT_LEVEL(XCHAL_EXTINT0_NUM) +#define XCHAL_EXTINT1_MASK (1 << XCHAL_EXTINT1_NUM) +#define XCHAL_EXTINT1_LEVEL XCHAL_INT_LEVEL(XCHAL_EXTINT1_NUM) +#define XCHAL_EXTINT2_MASK (1 << XCHAL_EXTINT2_NUM) +#define XCHAL_EXTINT2_LEVEL XCHAL_INT_LEVEL(XCHAL_EXTINT2_NUM) +#define XCHAL_EXTINT3_MASK (1 << XCHAL_EXTINT3_NUM) +#define XCHAL_EXTINT3_LEVEL XCHAL_INT_LEVEL(XCHAL_EXTINT3_NUM) +#define XCHAL_EXTINT4_MASK (1 << XCHAL_EXTINT4_NUM) +#define XCHAL_EXTINT4_LEVEL XCHAL_INT_LEVEL(XCHAL_EXTINT4_NUM) +#define XCHAL_EXTINT5_MASK (1 << XCHAL_EXTINT5_NUM) +#define XCHAL_EXTINT5_LEVEL XCHAL_INT_LEVEL(XCHAL_EXTINT5_NUM) +#define XCHAL_EXTINT6_MASK (1 << XCHAL_EXTINT6_NUM) +#define XCHAL_EXTINT6_LEVEL XCHAL_INT_LEVEL(XCHAL_EXTINT6_NUM) +#define XCHAL_EXTINT7_MASK (1 << XCHAL_EXTINT7_NUM) +#define XCHAL_EXTINT7_LEVEL XCHAL_INT_LEVEL(XCHAL_EXTINT7_NUM) +#define XCHAL_EXTINT8_MASK (1 << XCHAL_EXTINT8_NUM) +#define XCHAL_EXTINT8_LEVEL XCHAL_INT_LEVEL(XCHAL_EXTINT8_NUM) +#define XCHAL_EXTINT9_MASK (1 << XCHAL_EXTINT9_NUM) +#define XCHAL_EXTINT9_LEVEL XCHAL_INT_LEVEL(XCHAL_EXTINT9_NUM) +#define XCHAL_EXTINT10_MASK (1 << XCHAL_EXTINT10_NUM) +#define XCHAL_EXTINT10_LEVEL XCHAL_INT_LEVEL(XCHAL_EXTINT10_NUM) +#define XCHAL_EXTINT11_MASK (1 << XCHAL_EXTINT11_NUM) +#define XCHAL_EXTINT11_LEVEL XCHAL_INT_LEVEL(XCHAL_EXTINT11_NUM) +#define XCHAL_EXTINT12_MASK (1 << XCHAL_EXTINT12_NUM) +#define XCHAL_EXTINT12_LEVEL XCHAL_INT_LEVEL(XCHAL_EXTINT12_NUM) +#define XCHAL_EXTINT13_MASK (1 << XCHAL_EXTINT13_NUM) +#define XCHAL_EXTINT13_LEVEL XCHAL_INT_LEVEL(XCHAL_EXTINT13_NUM) +#define XCHAL_EXTINT14_MASK (1 << XCHAL_EXTINT14_NUM) +#define XCHAL_EXTINT14_LEVEL XCHAL_INT_LEVEL(XCHAL_EXTINT14_NUM) +#define XCHAL_EXTINT15_MASK (1 << XCHAL_EXTINT15_NUM) +#define XCHAL_EXTINT15_LEVEL XCHAL_INT_LEVEL(XCHAL_EXTINT15_NUM) +#define XCHAL_EXTINT16_MASK (1 << XCHAL_EXTINT16_NUM) +#define XCHAL_EXTINT16_LEVEL XCHAL_INT_LEVEL(XCHAL_EXTINT16_NUM) +#define XCHAL_EXTINT17_MASK (1 << XCHAL_EXTINT17_NUM) +#define XCHAL_EXTINT17_LEVEL XCHAL_INT_LEVEL(XCHAL_EXTINT17_NUM) +#define XCHAL_EXTINT18_MASK (1 << XCHAL_EXTINT18_NUM) +#define XCHAL_EXTINT18_LEVEL XCHAL_INT_LEVEL(XCHAL_EXTINT18_NUM) +#define XCHAL_EXTINT19_MASK (1 << XCHAL_EXTINT19_NUM) +#define XCHAL_EXTINT19_LEVEL XCHAL_INT_LEVEL(XCHAL_EXTINT19_NUM) +#define XCHAL_EXTINT20_MASK (1 << XCHAL_EXTINT20_NUM) +#define XCHAL_EXTINT20_LEVEL XCHAL_INT_LEVEL(XCHAL_EXTINT20_NUM) +#define XCHAL_EXTINT21_MASK (1 << XCHAL_EXTINT21_NUM) +#define XCHAL_EXTINT21_LEVEL XCHAL_INT_LEVEL(XCHAL_EXTINT21_NUM) +#define XCHAL_EXTINT22_MASK (1 << XCHAL_EXTINT22_NUM) +#define XCHAL_EXTINT22_LEVEL XCHAL_INT_LEVEL(XCHAL_EXTINT22_NUM) +#define XCHAL_EXTINT23_MASK (1 << XCHAL_EXTINT23_NUM) +#define XCHAL_EXTINT23_LEVEL XCHAL_INT_LEVEL(XCHAL_EXTINT23_NUM) +#define XCHAL_EXTINT24_MASK (1 << XCHAL_EXTINT24_NUM) +#define XCHAL_EXTINT24_LEVEL XCHAL_INT_LEVEL(XCHAL_EXTINT24_NUM) +#define XCHAL_EXTINT25_MASK (1 << XCHAL_EXTINT25_NUM) +#define XCHAL_EXTINT25_LEVEL XCHAL_INT_LEVEL(XCHAL_EXTINT25_NUM) +#define XCHAL_EXTINT26_MASK (1 << XCHAL_EXTINT26_NUM) +#define XCHAL_EXTINT26_LEVEL XCHAL_INT_LEVEL(XCHAL_EXTINT26_NUM) +#define XCHAL_EXTINT27_MASK (1 << XCHAL_EXTINT27_NUM) +#define XCHAL_EXTINT27_LEVEL XCHAL_INT_LEVEL(XCHAL_EXTINT27_NUM) +#define XCHAL_EXTINT28_MASK (1 << XCHAL_EXTINT28_NUM) +#define XCHAL_EXTINT28_LEVEL XCHAL_INT_LEVEL(XCHAL_EXTINT28_NUM) +#define XCHAL_EXTINT29_MASK (1 << XCHAL_EXTINT29_NUM) +#define XCHAL_EXTINT29_LEVEL XCHAL_INT_LEVEL(XCHAL_EXTINT29_NUM) +#define XCHAL_EXTINT30_MASK (1 << XCHAL_EXTINT30_NUM) +#define XCHAL_EXTINT30_LEVEL XCHAL_INT_LEVEL(XCHAL_EXTINT30_NUM) +#define XCHAL_EXTINT31_MASK (1 << XCHAL_EXTINT31_NUM) +#define XCHAL_EXTINT31_LEVEL XCHAL_INT_LEVEL(XCHAL_EXTINT31_NUM) + + +/*---------------------------------------------------------------------- + EXCEPTIONS and VECTORS + ----------------------------------------------------------------------*/ + +/* For backward compatibility ONLY -- DO NOT USE (will be removed in future release): */ +#define XCHAL_HAVE_OLD_EXC_ARCH XCHAL_HAVE_XEA1 /* (DEPRECATED) 1 if old exception architecture (XEA1), 0 otherwise (eg. XEA2) */ +#define XCHAL_HAVE_EXCM XCHAL_HAVE_XEA2 /* (DEPRECATED) 1 if PS.EXCM bit exists (currently equals XCHAL_HAVE_TLBS) */ +#ifdef XCHAL_USER_VECTOR_VADDR +#define XCHAL_PROGRAMEXC_VECTOR_VADDR XCHAL_USER_VECTOR_VADDR +#define XCHAL_USEREXC_VECTOR_VADDR XCHAL_USER_VECTOR_VADDR +#endif +#ifdef XCHAL_USER_VECTOR_PADDR +# define XCHAL_PROGRAMEXC_VECTOR_PADDR XCHAL_USER_VECTOR_PADDR +# define XCHAL_USEREXC_VECTOR_PADDR XCHAL_USER_VECTOR_PADDR +#endif +#ifdef XCHAL_KERNEL_VECTOR_VADDR +# define XCHAL_STACKEDEXC_VECTOR_VADDR XCHAL_KERNEL_VECTOR_VADDR +# define XCHAL_KERNELEXC_VECTOR_VADDR XCHAL_KERNEL_VECTOR_VADDR +#endif +#ifdef XCHAL_KERNEL_VECTOR_PADDR +# define XCHAL_STACKEDEXC_VECTOR_PADDR XCHAL_KERNEL_VECTOR_PADDR +# define XCHAL_KERNELEXC_VECTOR_PADDR XCHAL_KERNEL_VECTOR_PADDR +#endif + +#if 0 +#if XCHAL_HAVE_DEBUG +# define XCHAL_DEBUG_VECTOR_VADDR XCHAL_INTLEVEL_VECTOR_VADDR(XCHAL_DEBUGLEVEL) +/* This one should only get defined if the corresponding intlevel paddr macro exists: */ +# define XCHAL_DEBUG_VECTOR_PADDR XCHAL_INTLEVEL_VECTOR_PADDR(XCHAL_DEBUGLEVEL) +#endif +#endif + +/* Indexing macros: */ +#define _XCHAL_INTLEVEL_VECTOR_VADDR(n) XCHAL_INTLEVEL ## n ## _VECTOR_VADDR +#define XCHAL_INTLEVEL_VECTOR_VADDR(n) _XCHAL_INTLEVEL_VECTOR_VADDR(n) /* n = 0 .. 15 */ + +/* + * General Exception Causes + * (values of EXCCAUSE special register set by general exceptions, + * which vector to the user, kernel, or double-exception vectors). + * + * DEPRECATED. Please use the equivalent EXCCAUSE_xxx macros + * defined in . (Note that these have slightly + * different names, they don't just have the XCHAL_ prefix removed.) + */ +#define XCHAL_EXCCAUSE_ILLEGAL_INSTRUCTION 0 /* Illegal Instruction */ +#define XCHAL_EXCCAUSE_SYSTEM_CALL 1 /* System Call */ +#define XCHAL_EXCCAUSE_INSTRUCTION_FETCH_ERROR 2 /* Instruction Fetch Error */ +#define XCHAL_EXCCAUSE_LOAD_STORE_ERROR 3 /* Load Store Error */ +#define XCHAL_EXCCAUSE_LEVEL1_INTERRUPT 4 /* Level 1 Interrupt */ +#define XCHAL_EXCCAUSE_ALLOCA 5 /* Stack Extension Assist */ +#define XCHAL_EXCCAUSE_INTEGER_DIVIDE_BY_ZERO 6 /* Integer Divide by Zero */ +#define XCHAL_EXCCAUSE_SPECULATION 7 /* Speculation */ +#define XCHAL_EXCCAUSE_PRIVILEGED 8 /* Privileged Instruction */ +#define XCHAL_EXCCAUSE_UNALIGNED 9 /* Unaligned Load Store */ +/*10..15 reserved*/ +#define XCHAL_EXCCAUSE_ITLB_MISS 16 /* ITlb Miss Exception */ +#define XCHAL_EXCCAUSE_ITLB_MULTIHIT 17 /* ITlb Mutltihit Exception */ +#define XCHAL_EXCCAUSE_ITLB_PRIVILEGE 18 /* ITlb Privilege Exception */ +#define XCHAL_EXCCAUSE_ITLB_SIZE_RESTRICTION 19 /* ITlb Size Restriction Exception */ +#define XCHAL_EXCCAUSE_FETCH_CACHE_ATTRIBUTE 20 /* Fetch Cache Attribute Exception */ +/*21..23 reserved*/ +#define XCHAL_EXCCAUSE_DTLB_MISS 24 /* DTlb Miss Exception */ +#define XCHAL_EXCCAUSE_DTLB_MULTIHIT 25 /* DTlb Multihit Exception */ +#define XCHAL_EXCCAUSE_DTLB_PRIVILEGE 26 /* DTlb Privilege Exception */ +#define XCHAL_EXCCAUSE_DTLB_SIZE_RESTRICTION 27 /* DTlb Size Restriction Exception */ +#define XCHAL_EXCCAUSE_LOAD_CACHE_ATTRIBUTE 28 /* Load Cache Attribute Exception */ +#define XCHAL_EXCCAUSE_STORE_CACHE_ATTRIBUTE 29 /* Store Cache Attribute Exception */ +/*30..31 reserved*/ +#define XCHAL_EXCCAUSE_COPROCESSOR0_DISABLED 32 /* Coprocessor 0 disabled */ +#define XCHAL_EXCCAUSE_COPROCESSOR1_DISABLED 33 /* Coprocessor 1 disabled */ +#define XCHAL_EXCCAUSE_COPROCESSOR2_DISABLED 34 /* Coprocessor 2 disabled */ +#define XCHAL_EXCCAUSE_COPROCESSOR3_DISABLED 35 /* Coprocessor 3 disabled */ +#define XCHAL_EXCCAUSE_COPROCESSOR4_DISABLED 36 /* Coprocessor 4 disabled */ +#define XCHAL_EXCCAUSE_COPROCESSOR5_DISABLED 37 /* Coprocessor 5 disabled */ +#define XCHAL_EXCCAUSE_COPROCESSOR6_DISABLED 38 /* Coprocessor 6 disabled */ +#define XCHAL_EXCCAUSE_COPROCESSOR7_DISABLED 39 /* Coprocessor 7 disabled */ +/*40..63 reserved*/ + + +/* + * Miscellaneous special register fields. + * + * For each special register, and each field within each register: + * XCHAL__VALIDMASK is the set of bits defined in the register. + * XCHAL___BITS is the number of bits in the field. + * XCHAL___NUM is 2^bits, the number of possible values + * of the field. + * XCHAL___SHIFT is the position of the field within + * the register, starting from the least significant bit. + * + * DEPRECATED. Please use the equivalent macros defined in + * . (Note that these have different names.) + */ + +/* DBREAKC (special register number 160): */ +#define XCHAL_DBREAKC_VALIDMASK 0xC000003F +#define XCHAL_DBREAKC_MASK_BITS 6 +#define XCHAL_DBREAKC_MASK_NUM 64 +#define XCHAL_DBREAKC_MASK_SHIFT 0 +#define XCHAL_DBREAKC_MASK_MASK 0x0000003F +#define XCHAL_DBREAKC_LOADBREAK_BITS 1 +#define XCHAL_DBREAKC_LOADBREAK_NUM 2 +#define XCHAL_DBREAKC_LOADBREAK_SHIFT 30 +#define XCHAL_DBREAKC_LOADBREAK_MASK 0x40000000 +#define XCHAL_DBREAKC_STOREBREAK_BITS 1 +#define XCHAL_DBREAKC_STOREBREAK_NUM 2 +#define XCHAL_DBREAKC_STOREBREAK_SHIFT 31 +#define XCHAL_DBREAKC_STOREBREAK_MASK 0x80000000 +/* PS (special register number 230): */ +#define XCHAL_PS_VALIDMASK 0x00070F3F +#define XCHAL_PS_INTLEVEL_BITS 4 +#define XCHAL_PS_INTLEVEL_NUM 16 +#define XCHAL_PS_INTLEVEL_SHIFT 0 +#define XCHAL_PS_INTLEVEL_MASK 0x0000000F +#define XCHAL_PS_EXCM_BITS 1 +#define XCHAL_PS_EXCM_NUM 2 +#define XCHAL_PS_EXCM_SHIFT 4 +#define XCHAL_PS_EXCM_MASK 0x00000010 +#define XCHAL_PS_UM_BITS 1 +#define XCHAL_PS_UM_NUM 2 +#define XCHAL_PS_UM_SHIFT 5 +#define XCHAL_PS_UM_MASK 0x00000020 +#define XCHAL_PS_RING_BITS 2 +#define XCHAL_PS_RING_NUM 4 +#define XCHAL_PS_RING_SHIFT 6 +#define XCHAL_PS_RING_MASK 0x000000C0 +#define XCHAL_PS_OWB_BITS 4 +#define XCHAL_PS_OWB_NUM 16 +#define XCHAL_PS_OWB_SHIFT 8 +#define XCHAL_PS_OWB_MASK 0x00000F00 +#define XCHAL_PS_CALLINC_BITS 2 +#define XCHAL_PS_CALLINC_NUM 4 +#define XCHAL_PS_CALLINC_SHIFT 16 +#define XCHAL_PS_CALLINC_MASK 0x00030000 +#define XCHAL_PS_WOE_BITS 1 +#define XCHAL_PS_WOE_NUM 2 +#define XCHAL_PS_WOE_SHIFT 18 +#define XCHAL_PS_WOE_MASK 0x00040000 +/* EXCCAUSE (special register number 232): */ +#define XCHAL_EXCCAUSE_VALIDMASK 0x0000003F +#define XCHAL_EXCCAUSE_BITS 6 +#define XCHAL_EXCCAUSE_NUM 64 +#define XCHAL_EXCCAUSE_SHIFT 0 +#define XCHAL_EXCCAUSE_MASK 0x0000003F +/* DEBUGCAUSE (special register number 233): */ +#define XCHAL_DEBUGCAUSE_VALIDMASK 0x0000003F +#define XCHAL_DEBUGCAUSE_ICOUNT_BITS 1 +#define XCHAL_DEBUGCAUSE_ICOUNT_NUM 2 +#define XCHAL_DEBUGCAUSE_ICOUNT_SHIFT 0 +#define XCHAL_DEBUGCAUSE_ICOUNT_MASK 0x00000001 +#define XCHAL_DEBUGCAUSE_IBREAK_BITS 1 +#define XCHAL_DEBUGCAUSE_IBREAK_NUM 2 +#define XCHAL_DEBUGCAUSE_IBREAK_SHIFT 1 +#define XCHAL_DEBUGCAUSE_IBREAK_MASK 0x00000002 +#define XCHAL_DEBUGCAUSE_DBREAK_BITS 1 +#define XCHAL_DEBUGCAUSE_DBREAK_NUM 2 +#define XCHAL_DEBUGCAUSE_DBREAK_SHIFT 2 +#define XCHAL_DEBUGCAUSE_DBREAK_MASK 0x00000004 +#define XCHAL_DEBUGCAUSE_BREAK_BITS 1 +#define XCHAL_DEBUGCAUSE_BREAK_NUM 2 +#define XCHAL_DEBUGCAUSE_BREAK_SHIFT 3 +#define XCHAL_DEBUGCAUSE_BREAK_MASK 0x00000008 +#define XCHAL_DEBUGCAUSE_BREAKN_BITS 1 +#define XCHAL_DEBUGCAUSE_BREAKN_NUM 2 +#define XCHAL_DEBUGCAUSE_BREAKN_SHIFT 4 +#define XCHAL_DEBUGCAUSE_BREAKN_MASK 0x00000010 +#define XCHAL_DEBUGCAUSE_DEBUGINT_BITS 1 +#define XCHAL_DEBUGCAUSE_DEBUGINT_NUM 2 +#define XCHAL_DEBUGCAUSE_DEBUGINT_SHIFT 5 +#define XCHAL_DEBUGCAUSE_DEBUGINT_MASK 0x00000020 + + + + +/*---------------------------------------------------------------------- + TIMERS + ----------------------------------------------------------------------*/ + +/*#define XCHAL_HAVE_TIMERS XCHAL_HAVE_CCOUNT*/ + + + +/*---------------------------------------------------------------------- + INTERNAL I/D RAM/ROMs and XLMI + ----------------------------------------------------------------------*/ + +#define XCHAL_NUM_IROM XCHAL_NUM_INSTROM /* (DEPRECATED) */ +#define XCHAL_NUM_IRAM XCHAL_NUM_INSTRAM /* (DEPRECATED) */ +#define XCHAL_NUM_DROM XCHAL_NUM_DATAROM /* (DEPRECATED) */ +#define XCHAL_NUM_DRAM XCHAL_NUM_DATARAM /* (DEPRECATED) */ + +#define XCHAL_IROM0_VADDR XCHAL_INSTROM0_VADDR /* (DEPRECATED) */ +#define XCHAL_IROM0_PADDR XCHAL_INSTROM0_PADDR /* (DEPRECATED) */ +#define XCHAL_IROM0_SIZE XCHAL_INSTROM0_SIZE /* (DEPRECATED) */ +#define XCHAL_IROM1_VADDR XCHAL_INSTROM1_VADDR /* (DEPRECATED) */ +#define XCHAL_IROM1_PADDR XCHAL_INSTROM1_PADDR /* (DEPRECATED) */ +#define XCHAL_IROM1_SIZE XCHAL_INSTROM1_SIZE /* (DEPRECATED) */ +#define XCHAL_IRAM0_VADDR XCHAL_INSTRAM0_VADDR /* (DEPRECATED) */ +#define XCHAL_IRAM0_PADDR XCHAL_INSTRAM0_PADDR /* (DEPRECATED) */ +#define XCHAL_IRAM0_SIZE XCHAL_INSTRAM0_SIZE /* (DEPRECATED) */ +#define XCHAL_IRAM1_VADDR XCHAL_INSTRAM1_VADDR /* (DEPRECATED) */ +#define XCHAL_IRAM1_PADDR XCHAL_INSTRAM1_PADDR /* (DEPRECATED) */ +#define XCHAL_IRAM1_SIZE XCHAL_INSTRAM1_SIZE /* (DEPRECATED) */ +#define XCHAL_DROM0_VADDR XCHAL_DATAROM0_VADDR /* (DEPRECATED) */ +#define XCHAL_DROM0_PADDR XCHAL_DATAROM0_PADDR /* (DEPRECATED) */ +#define XCHAL_DROM0_SIZE XCHAL_DATAROM0_SIZE /* (DEPRECATED) */ +#define XCHAL_DROM1_VADDR XCHAL_DATAROM1_VADDR /* (DEPRECATED) */ +#define XCHAL_DROM1_PADDR XCHAL_DATAROM1_PADDR /* (DEPRECATED) */ +#define XCHAL_DROM1_SIZE XCHAL_DATAROM1_SIZE /* (DEPRECATED) */ +#define XCHAL_DRAM0_VADDR XCHAL_DATARAM0_VADDR /* (DEPRECATED) */ +#define XCHAL_DRAM0_PADDR XCHAL_DATARAM0_PADDR /* (DEPRECATED) */ +#define XCHAL_DRAM0_SIZE XCHAL_DATARAM0_SIZE /* (DEPRECATED) */ +#define XCHAL_DRAM1_VADDR XCHAL_DATARAM1_VADDR /* (DEPRECATED) */ +#define XCHAL_DRAM1_PADDR XCHAL_DATARAM1_PADDR /* (DEPRECATED) */ +#define XCHAL_DRAM1_SIZE XCHAL_DATARAM1_SIZE /* (DEPRECATED) */ + + + +/*---------------------------------------------------------------------- + CACHE + ----------------------------------------------------------------------*/ + + +/* Default PREFCTL value to enable prefetch. */ +#if XCHAL_HW_MIN_VERSION < XTENSA_HWVERSION_RE_2012_0 +#define XCHAL_CACHE_PREFCTL_DEFAULT 0x00044 /* enabled, not aggressive */ +#elif XCHAL_HW_MIN_VERSION < XTENSA_HWVERSION_RF_2014_0 +#define XCHAL_CACHE_PREFCTL_DEFAULT 0x01044 /* + enable prefetch to L1 */ +#elif XCHAL_PREFETCH_ENTRIES >= 16 +#define XCHAL_CACHE_PREFCTL_DEFAULT 0x81044 /* 12 entries for block ops */ +#elif XCHAL_PREFETCH_ENTRIES >= 8 +#define XCHAL_CACHE_PREFCTL_DEFAULT 0x51044 /* 5 entries for block ops */ +#else +#define XCHAL_CACHE_PREFCTL_DEFAULT 0x01044 /* 0 entries for block ops */ +#endif + + +/* Max for both I-cache and D-cache (used for general alignment): */ +#if XCHAL_ICACHE_LINESIZE > XCHAL_DCACHE_LINESIZE +# define XCHAL_CACHE_LINEWIDTH_MAX XCHAL_ICACHE_LINEWIDTH +# define XCHAL_CACHE_LINESIZE_MAX XCHAL_ICACHE_LINESIZE +#else +# define XCHAL_CACHE_LINEWIDTH_MAX XCHAL_DCACHE_LINEWIDTH +# define XCHAL_CACHE_LINESIZE_MAX XCHAL_DCACHE_LINESIZE +#endif + +#define XCHAL_ICACHE_SETSIZE (1< XCHAL_DCACHE_SETWIDTH +# define XCHAL_CACHE_SETWIDTH_MAX XCHAL_ICACHE_SETWIDTH +# define XCHAL_CACHE_SETSIZE_MAX XCHAL_ICACHE_SETSIZE +#else +# define XCHAL_CACHE_SETWIDTH_MAX XCHAL_DCACHE_SETWIDTH +# define XCHAL_CACHE_SETSIZE_MAX XCHAL_DCACHE_SETSIZE +#endif + +/* Instruction cache tag bits: */ +#define XCHAL_ICACHE_TAG_V_SHIFT 0 +#define XCHAL_ICACHE_TAG_V 0x1 /* valid bit */ +#if XCHAL_ICACHE_WAYS > 1 +# define XCHAL_ICACHE_TAG_F_SHIFT 1 +# define XCHAL_ICACHE_TAG_F 0x2 /* fill (LRU) bit */ +#else +# define XCHAL_ICACHE_TAG_F_SHIFT 0 +# define XCHAL_ICACHE_TAG_F 0 /* no fill (LRU) bit */ +#endif +#if XCHAL_ICACHE_LINE_LOCKABLE +# define XCHAL_ICACHE_TAG_L_SHIFT (XCHAL_ICACHE_TAG_F_SHIFT+1) +# define XCHAL_ICACHE_TAG_L (1 << XCHAL_ICACHE_TAG_L_SHIFT) /* lock bit */ +#else +# define XCHAL_ICACHE_TAG_L_SHIFT XCHAL_ICACHE_TAG_F_SHIFT +# define XCHAL_ICACHE_TAG_L 0 /* no lock bit */ +#endif +/* Data cache tag bits: */ +#define XCHAL_DCACHE_TAG_V_SHIFT 0 +#define XCHAL_DCACHE_TAG_V 0x1 /* valid bit */ +#if XCHAL_DCACHE_WAYS > 1 +# define XCHAL_DCACHE_TAG_F_SHIFT 1 +# define XCHAL_DCACHE_TAG_F 0x2 /* fill (LRU) bit */ +#else +# define XCHAL_DCACHE_TAG_F_SHIFT 0 +# define XCHAL_DCACHE_TAG_F 0 /* no fill (LRU) bit */ +#endif +#if XCHAL_DCACHE_IS_WRITEBACK +# define XCHAL_DCACHE_TAG_D_SHIFT (XCHAL_DCACHE_TAG_F_SHIFT+1) +# define XCHAL_DCACHE_TAG_D (1 << XCHAL_DCACHE_TAG_D_SHIFT) /* dirty bit */ +#else +# define XCHAL_DCACHE_TAG_D_SHIFT XCHAL_DCACHE_TAG_F_SHIFT +# define XCHAL_DCACHE_TAG_D 0 /* no dirty bit */ +#endif +#if XCHAL_DCACHE_LINE_LOCKABLE +# define XCHAL_DCACHE_TAG_L_SHIFT (XCHAL_DCACHE_TAG_D_SHIFT+1) +# define XCHAL_DCACHE_TAG_L (1 << XCHAL_DCACHE_TAG_L_SHIFT) /* lock bit */ +#else +# define XCHAL_DCACHE_TAG_L_SHIFT XCHAL_DCACHE_TAG_D_SHIFT +# define XCHAL_DCACHE_TAG_L 0 /* no lock bit */ +#endif + +/* Whether MEMCTL register has anything useful */ +#define XCHAL_USE_MEMCTL (((XCHAL_LOOP_BUFFER_SIZE > 0) || \ + XCHAL_DCACHE_IS_COHERENT || \ + XCHAL_HAVE_ICACHE_DYN_WAYS || \ + XCHAL_HAVE_DCACHE_DYN_WAYS) && \ + (XCHAL_HW_MIN_VERSION >= XTENSA_HWVERSION_RE_2012_0)) + +/* Default MEMCTL values: */ +#if XCHAL_HAVE_ICACHE_DYN_WAYS || XCHAL_HAVE_DCACHE_DYN_WAYS +/* NOTE: constant defined this way to allow movi instead of l32r in reset code. */ +#define XCHAL_CACHE_MEMCTL_DEFAULT 0xFFFFFF00 /* Init all possible ways */ +#else +#define XCHAL_CACHE_MEMCTL_DEFAULT 0x00000000 /* Nothing to do */ +#endif + +#if XCHAL_DCACHE_IS_COHERENT +#define _MEMCTL_SNOOP_EN 0x02 /* Enable snoop */ +#else +#define _MEMCTL_SNOOP_EN 0x00 /* Don't enable snoop */ +#endif + +#if (XCHAL_LOOP_BUFFER_SIZE == 0) || XCHAL_ERRATUM_453 +#define _MEMCTL_L0IBUF_EN 0x00 /* No loop buffer or don't enable */ +#else +#define _MEMCTL_L0IBUF_EN 0x01 /* Enable loop buffer */ +#endif + +#define XCHAL_SNOOP_LB_MEMCTL_DEFAULT (_MEMCTL_SNOOP_EN | _MEMCTL_L0IBUF_EN) + + +/*---------------------------------------------------------------------- + MMU + ----------------------------------------------------------------------*/ + +/* See for more details. */ + +/* Has different semantic in open source headers (where it means HAVE_PTP_MMU), + so comment out starting with RB-2008.3 release; later, might get + get reintroduced as a synonym for XCHAL_HAVE_PTP_MMU instead: */ +/*#define XCHAL_HAVE_MMU XCHAL_HAVE_TLBS*/ /* (DEPRECATED; use XCHAL_HAVE_TLBS instead) */ + +/* Indexing macros: */ +#define _XCHAL_ITLB_SET(n,_what) XCHAL_ITLB_SET ## n ## _what +#define XCHAL_ITLB_SET(n,what) _XCHAL_ITLB_SET(n, _ ## what ) +#define _XCHAL_ITLB_SET_E(n,i,_what) XCHAL_ITLB_SET ## n ## _E ## i ## _what +#define XCHAL_ITLB_SET_E(n,i,what) _XCHAL_ITLB_SET_E(n,i, _ ## what ) +#define _XCHAL_DTLB_SET(n,_what) XCHAL_DTLB_SET ## n ## _what +#define XCHAL_DTLB_SET(n,what) _XCHAL_DTLB_SET(n, _ ## what ) +#define _XCHAL_DTLB_SET_E(n,i,_what) XCHAL_DTLB_SET ## n ## _E ## i ## _what +#define XCHAL_DTLB_SET_E(n,i,what) _XCHAL_DTLB_SET_E(n,i, _ ## what ) +/* + * Example use: XCHAL_ITLB_SET(XCHAL_ITLB_ARF_SET0,ENTRIES) + * to get the value of XCHAL_ITLB_SET_ENTRIES where is the first auto-refill set. + */ + +/* Number of entries per autorefill way: */ +#define XCHAL_ITLB_ARF_ENTRIES (1< 0 && XCHAL_DTLB_ARF_WAYS > 0 && XCHAL_MMU_RINGS >= 2 +# define XCHAL_HAVE_PTP_MMU 1 /* have full MMU (with page table [autorefill] and protection) */ +#else +# define XCHAL_HAVE_PTP_MMU 0 /* don't have full MMU */ +#endif +#endif + +/* + * For full MMUs, report kernel RAM segment and kernel I/O segment static page mappings: + */ +#if XCHAL_HAVE_PTP_MMU && !XCHAL_HAVE_SPANNING_WAY +#define XCHAL_KSEG_CACHED_VADDR 0xD0000000 /* virt.addr of kernel RAM cached static map */ +#define XCHAL_KSEG_CACHED_PADDR 0x00000000 /* phys.addr of kseg_cached */ +#define XCHAL_KSEG_CACHED_SIZE 0x08000000 /* size in bytes of kseg_cached (assumed power of 2!!!) */ +#define XCHAL_KSEG_BYPASS_VADDR 0xD8000000 /* virt.addr of kernel RAM bypass (uncached) static map */ +#define XCHAL_KSEG_BYPASS_PADDR 0x00000000 /* phys.addr of kseg_bypass */ +#define XCHAL_KSEG_BYPASS_SIZE 0x08000000 /* size in bytes of kseg_bypass (assumed power of 2!!!) */ + +#define XCHAL_KIO_CACHED_VADDR 0xE0000000 /* virt.addr of kernel I/O cached static map */ +#define XCHAL_KIO_CACHED_PADDR 0xF0000000 /* phys.addr of kio_cached */ +#define XCHAL_KIO_CACHED_SIZE 0x10000000 /* size in bytes of kio_cached (assumed power of 2!!!) */ +#define XCHAL_KIO_BYPASS_VADDR 0xF0000000 /* virt.addr of kernel I/O bypass (uncached) static map */ +#define XCHAL_KIO_BYPASS_PADDR 0xF0000000 /* phys.addr of kio_bypass */ +#define XCHAL_KIO_BYPASS_SIZE 0x10000000 /* size in bytes of kio_bypass (assumed power of 2!!!) */ + +#define XCHAL_SEG_MAPPABLE_VADDR 0x00000000 /* start of largest non-static-mapped virtual addr area */ +#define XCHAL_SEG_MAPPABLE_SIZE 0xD0000000 /* size in bytes of " */ +/* define XCHAL_SEG_MAPPABLE2_xxx if more areas present, sorted in order of descending size. */ +#endif + + +/*---------------------------------------------------------------------- + MISC + ----------------------------------------------------------------------*/ + +/* Data alignment required if used for instructions: */ +#if XCHAL_INST_FETCH_WIDTH > XCHAL_DATA_WIDTH +# define XCHAL_ALIGN_MAX XCHAL_INST_FETCH_WIDTH +#else +# define XCHAL_ALIGN_MAX XCHAL_DATA_WIDTH +#endif + +/* + * Names kept for backward compatibility. + * (Here "RELEASE" is now a misnomer; these are product *versions*, not the releases + * under which they are released. In the T10##.# era there was no distinction.) + */ +#define XCHAL_HW_RELEASE_MAJOR XCHAL_HW_VERSION_MAJOR +#define XCHAL_HW_RELEASE_MINOR XCHAL_HW_VERSION_MINOR +#define XCHAL_HW_RELEASE_NAME XCHAL_HW_VERSION_NAME + + + + +/*---------------------------------------------------------------------- + COPROCESSORS and EXTRA STATE + ----------------------------------------------------------------------*/ + +#define XCHAL_EXTRA_SA_SIZE XCHAL_NCP_SA_SIZE +#define XCHAL_EXTRA_SA_ALIGN XCHAL_NCP_SA_ALIGN +#define XCHAL_CPEXTRA_SA_SIZE XCHAL_TOTAL_SA_SIZE +#define XCHAL_CPEXTRA_SA_ALIGN XCHAL_TOTAL_SA_ALIGN + +#if defined (_ASMLANGUAGE) || defined (__ASSEMBLER__) + + /* Invoked at start of save area load/store sequence macro to setup macro + * internal offsets. Not usually invoked directly. + * continue 0 for 1st sequence, 1 for subsequent consecutive ones. + * totofs offset from original ptr to next load/store location. + */ + .macro xchal_sa_start continue totofs + .ifeq \continue + .set .Lxchal_pofs_, 0 /* offset from original ptr to current \ptr */ + .set .Lxchal_ofs_, 0 /* offset from current \ptr to next load/store location */ + .endif + .if \totofs + 1 /* if totofs specified (not -1) */ + .set .Lxchal_ofs_, \totofs - .Lxchal_pofs_ /* specific offset from original ptr */ + .endif + .endm + + /* Align portion of save area and bring ptr in range if necessary. + * Used by save area load/store sequences. Not usually invoked directly. + * Allows combining multiple (sub-)sequences arbitrarily. + * ptr pointer to save area (may be off, see .Lxchal_pofs_) + * minofs,maxofs range of offset from cur ptr to next load/store loc; + * minofs <= 0 <= maxofs (0 must always be valid offset) + * range must be within +/- 30kB or so. + * ofsalign alignment granularity of minofs .. maxofs (pow of 2) + * (restriction on offset from ptr to next load/store loc) + * totalign align from orig ptr to next load/store loc (pow of 2) + */ + .macro xchal_sa_align ptr minofs maxofs ofsalign totalign + /* First align where we start accessing the next register + * per \totalign relative to original ptr (i.e. start of the save area): + */ + .set .Lxchal_ofs_, ((.Lxchal_pofs_ + .Lxchal_ofs_ + \totalign - 1) & -\totalign) - .Lxchal_pofs_ + /* If necessary, adjust \ptr to bring .Lxchal_ofs_ in acceptable range: */ + .if (((\maxofs) - .Lxchal_ofs_) & 0xC0000000) | ((.Lxchal_ofs_ - (\minofs)) & 0xC0000000) | (.Lxchal_ofs_ & (\ofsalign-1)) + .set .Ligmask, 0xFFFFFFFF /* TODO: optimize to addmi, per aligns and .Lxchal_ofs_ */ + addi \ptr, \ptr, (.Lxchal_ofs_ & .Ligmask) + .set .Lxchal_pofs_, .Lxchal_pofs_ + (.Lxchal_ofs_ & .Ligmask) + .set .Lxchal_ofs_, (.Lxchal_ofs_ & ~.Ligmask) + .endif + .endm + /* + * We could optimize for addi to expand to only addmi instead of + * "addmi;addi", where possible. Here's a partial example how: + * .set .Lmaxmask, -(\ofsalign) & -(\totalign) + * .if (((\maxofs) + ~.Lmaxmask + 1) & 0xFFFFFF00) && ((.Lxchal_ofs_ & ~.Lmaxmask) == 0) + * .set .Ligmask, 0xFFFFFF00 + * .elif ... ditto for negative ofs range ... + * .set .Ligmask, 0xFFFFFF00 + * .set ... adjust per offset ... + * .else + * .set .Ligmask, 0xFFFFFFFF + * .endif + */ + + /* Invoke this after xchal_XXX_{load,store} macros to restore \ptr. */ + .macro xchal_sa_ptr_restore ptr + .if .Lxchal_pofs_ + addi \ptr, \ptr, - .Lxchal_pofs_ + .set .Lxchal_ofs_, .Lxchal_ofs_ + .Lxchal_pofs_ + .set .Lxchal_pofs_, 0 + .endif + .endm + + /* + * Use as eg: + * xchal_atmps_store a1, SOMEOFS, XCHAL_SA_NUM_ATMPS, a4, a5 + * xchal_ncp_load a2, a0,a3,a4,a5 + * xchal_atmps_load a1, SOMEOFS, XCHAL_SA_NUM_ATMPS, a4, a5 + * + * Specify only the ARs you *haven't* saved/restored already, up to 4. + * They *must* be the *last* ARs (in same order) specified to save area + * load/store sequences. In the example above, a0 and a3 were already + * saved/restored and unused (thus available) but a4 and a5 were not. + */ +#define xchal_atmps_store xchal_atmps_loadstore s32i, +#define xchal_atmps_load xchal_atmps_loadstore l32i, + .macro xchal_atmps_loadstore inst ptr offset nreq aa=0 ab=0 ac=0 ad=0 + .set .Lnsaved_, 0 + .irp reg,\aa,\ab,\ac,\ad + .ifeq 0x\reg ; .set .Lnsaved_,.Lnsaved_+1 ; .endif + .endr + .set .Laofs_, 0 + .irp reg,\aa,\ab,\ac,\ad + .ifgt (\nreq)-.Lnsaved_ + \inst \reg, \ptr, .Laofs_+\offset + .set .Laofs_,.Laofs_+4 + .set .Lnsaved_,.Lnsaved_+1 + .endif + .endr + .endm + +/*#define xchal_ncp_load_a2 xchal_ncp_load a2,a3,a4,a5,a6*/ +/*#define xchal_ncp_store_a2 xchal_ncp_store a2,a3,a4,a5,a6*/ +#define xchal_extratie_load xchal_ncptie_load +#define xchal_extratie_store xchal_ncptie_store +#define xchal_extratie_load_a2 xchal_ncptie_load a2,a3,a4,a5,a6 +#define xchal_extratie_store_a2 xchal_ncptie_store a2,a3,a4,a5,a6 +#define xchal_extra_load xchal_ncp_load +#define xchal_extra_store xchal_ncp_store +#define xchal_extra_load_a2 xchal_ncp_load a2,a3,a4,a5,a6 +#define xchal_extra_store_a2 xchal_ncp_store a2,a3,a4,a5,a6 +#define xchal_extra_load_funcbody xchal_ncp_load a2,a3,a4,a5,a6 +#define xchal_extra_store_funcbody xchal_ncp_store a2,a3,a4,a5,a6 +#define xchal_cp0_store_a2 xchal_cp0_store a2,a3,a4,a5,a6 +#define xchal_cp0_load_a2 xchal_cp0_load a2,a3,a4,a5,a6 +#define xchal_cp1_store_a2 xchal_cp1_store a2,a3,a4,a5,a6 +#define xchal_cp1_load_a2 xchal_cp1_load a2,a3,a4,a5,a6 +#define xchal_cp2_store_a2 xchal_cp2_store a2,a3,a4,a5,a6 +#define xchal_cp2_load_a2 xchal_cp2_load a2,a3,a4,a5,a6 +#define xchal_cp3_store_a2 xchal_cp3_store a2,a3,a4,a5,a6 +#define xchal_cp3_load_a2 xchal_cp3_load a2,a3,a4,a5,a6 +#define xchal_cp4_store_a2 xchal_cp4_store a2,a3,a4,a5,a6 +#define xchal_cp4_load_a2 xchal_cp4_load a2,a3,a4,a5,a6 +#define xchal_cp5_store_a2 xchal_cp5_store a2,a3,a4,a5,a6 +#define xchal_cp5_load_a2 xchal_cp5_load a2,a3,a4,a5,a6 +#define xchal_cp6_store_a2 xchal_cp6_store a2,a3,a4,a5,a6 +#define xchal_cp6_load_a2 xchal_cp6_load a2,a3,a4,a5,a6 +#define xchal_cp7_store_a2 xchal_cp7_store a2,a3,a4,a5,a6 +#define xchal_cp7_load_a2 xchal_cp7_load a2,a3,a4,a5,a6 + +/* Empty placeholder macros for undefined coprocessors: */ +#if (XCHAL_CP_MASK & ~XCHAL_CP_PORT_MASK) == 0 +# if XCHAL_CP0_SA_SIZE == 0 + .macro xchal_cp0_store p a b c d continue=0 ofs=-1 select=-1 ; .endm + .macro xchal_cp0_load p a b c d continue=0 ofs=-1 select=-1 ; .endm +# endif +# if XCHAL_CP1_SA_SIZE == 0 + .macro xchal_cp1_store p a b c d continue=0 ofs=-1 select=-1 ; .endm + .macro xchal_cp1_load p a b c d continue=0 ofs=-1 select=-1 ; .endm +# endif +# if XCHAL_CP2_SA_SIZE == 0 + .macro xchal_cp2_store p a b c d continue=0 ofs=-1 select=-1 ; .endm + .macro xchal_cp2_load p a b c d continue=0 ofs=-1 select=-1 ; .endm +# endif +# if XCHAL_CP3_SA_SIZE == 0 + .macro xchal_cp3_store p a b c d continue=0 ofs=-1 select=-1 ; .endm + .macro xchal_cp3_load p a b c d continue=0 ofs=-1 select=-1 ; .endm +# endif +# if XCHAL_CP4_SA_SIZE == 0 + .macro xchal_cp4_store p a b c d continue=0 ofs=-1 select=-1 ; .endm + .macro xchal_cp4_load p a b c d continue=0 ofs=-1 select=-1 ; .endm +# endif +# if XCHAL_CP5_SA_SIZE == 0 + .macro xchal_cp5_store p a b c d continue=0 ofs=-1 select=-1 ; .endm + .macro xchal_cp5_load p a b c d continue=0 ofs=-1 select=-1 ; .endm +# endif +# if XCHAL_CP6_SA_SIZE == 0 + .macro xchal_cp6_store p a b c d continue=0 ofs=-1 select=-1 ; .endm + .macro xchal_cp6_load p a b c d continue=0 ofs=-1 select=-1 ; .endm +# endif +# if XCHAL_CP7_SA_SIZE == 0 + .macro xchal_cp7_store p a b c d continue=0 ofs=-1 select=-1 ; .endm + .macro xchal_cp7_load p a b c d continue=0 ofs=-1 select=-1 ; .endm +# endif +#endif + + /******************** + * Macros to create functions that save and restore the state of *any* TIE + * coprocessor (by dynamic index). + */ + + /* + * Macro that expands to the body of a function + * that stores the selected coprocessor's state (registers etc). + * Entry: a2 = ptr to save area in which to save cp state + * a3 = coprocessor number + * Exit: any register a2-a15 (?) may have been clobbered. + */ + .macro xchal_cpi_store_funcbody +#if (XCHAL_CP_MASK & ~XCHAL_CP_PORT_MASK) +# if XCHAL_CP0_SA_SIZE + bnez a3, 99f + xchal_cp0_store_a2 + j 90f +99: +# endif +# if XCHAL_CP1_SA_SIZE + bnei a3, 1, 99f + xchal_cp1_store_a2 + j 90f +99: +# endif +# if XCHAL_CP2_SA_SIZE + bnei a3, 2, 99f + xchal_cp2_store_a2 + j 90f +99: +# endif +# if XCHAL_CP3_SA_SIZE + bnei a3, 3, 99f + xchal_cp3_store_a2 + j 90f +99: +# endif +# if XCHAL_CP4_SA_SIZE + bnei a3, 4, 99f + xchal_cp4_store_a2 + j 90f +99: +# endif +# if XCHAL_CP5_SA_SIZE + bnei a3, 5, 99f + xchal_cp5_store_a2 + j 90f +99: +# endif +# if XCHAL_CP6_SA_SIZE + bnei a3, 6, 99f + xchal_cp6_store_a2 + j 90f +99: +# endif +# if XCHAL_CP7_SA_SIZE + bnei a3, 7, 99f + xchal_cp7_store_a2 + j 90f +99: +# endif +90: +#endif + .endm + + /* + * Macro that expands to the body of a function + * that loads the selected coprocessor's state (registers etc). + * Entry: a2 = ptr to save area from which to restore cp state + * a3 = coprocessor number + * Exit: any register a2-a15 (?) may have been clobbered. + */ + .macro xchal_cpi_load_funcbody +#if (XCHAL_CP_MASK & ~XCHAL_CP_PORT_MASK) +# if XCHAL_CP0_SA_SIZE + bnez a3, 99f + xchal_cp0_load_a2 + j 90f +99: +# endif +# if XCHAL_CP1_SA_SIZE + bnei a3, 1, 99f + xchal_cp1_load_a2 + j 90f +99: +# endif +# if XCHAL_CP2_SA_SIZE + bnei a3, 2, 99f + xchal_cp2_load_a2 + j 90f +99: +# endif +# if XCHAL_CP3_SA_SIZE + bnei a3, 3, 99f + xchal_cp3_load_a2 + j 90f +99: +# endif +# if XCHAL_CP4_SA_SIZE + bnei a3, 4, 99f + xchal_cp4_load_a2 + j 90f +99: +# endif +# if XCHAL_CP5_SA_SIZE + bnei a3, 5, 99f + xchal_cp5_load_a2 + j 90f +99: +# endif +# if XCHAL_CP6_SA_SIZE + bnei a3, 6, 99f + xchal_cp6_load_a2 + j 90f +99: +# endif +# if XCHAL_CP7_SA_SIZE + bnei a3, 7, 99f + xchal_cp7_load_a2 + j 90f +99: +# endif +90: +#endif + .endm + +#endif /*_ASMLANGUAGE or __ASSEMBLER__*/ + + +/* Other default macros for undefined coprocessors: */ +#ifndef XCHAL_CP0_NAME +# define XCHAL_CP0_NAME 0 +# define XCHAL_CP0_SA_CONTENTS_LIBDB_NUM 0 +# define XCHAL_CP0_SA_CONTENTS_LIBDB /* empty */ +#endif +#ifndef XCHAL_CP1_NAME +# define XCHAL_CP1_NAME 0 +# define XCHAL_CP1_SA_CONTENTS_LIBDB_NUM 0 +# define XCHAL_CP1_SA_CONTENTS_LIBDB /* empty */ +#endif +#ifndef XCHAL_CP2_NAME +# define XCHAL_CP2_NAME 0 +# define XCHAL_CP2_SA_CONTENTS_LIBDB_NUM 0 +# define XCHAL_CP2_SA_CONTENTS_LIBDB /* empty */ +#endif +#ifndef XCHAL_CP3_NAME +# define XCHAL_CP3_NAME 0 +# define XCHAL_CP3_SA_CONTENTS_LIBDB_NUM 0 +# define XCHAL_CP3_SA_CONTENTS_LIBDB /* empty */ +#endif +#ifndef XCHAL_CP4_NAME +# define XCHAL_CP4_NAME 0 +# define XCHAL_CP4_SA_CONTENTS_LIBDB_NUM 0 +# define XCHAL_CP4_SA_CONTENTS_LIBDB /* empty */ +#endif +#ifndef XCHAL_CP5_NAME +# define XCHAL_CP5_NAME 0 +# define XCHAL_CP5_SA_CONTENTS_LIBDB_NUM 0 +# define XCHAL_CP5_SA_CONTENTS_LIBDB /* empty */ +#endif +#ifndef XCHAL_CP6_NAME +# define XCHAL_CP6_NAME 0 +# define XCHAL_CP6_SA_CONTENTS_LIBDB_NUM 0 +# define XCHAL_CP6_SA_CONTENTS_LIBDB /* empty */ +#endif +#ifndef XCHAL_CP7_NAME +# define XCHAL_CP7_NAME 0 +# define XCHAL_CP7_SA_CONTENTS_LIBDB_NUM 0 +# define XCHAL_CP7_SA_CONTENTS_LIBDB /* empty */ +#endif + +#if XCHAL_CP_MASK == 0 +/* Filler info for unassigned coprocessors, to simplify arrays etc: */ +#define XCHAL_CP0_SA_SIZE 0 +#define XCHAL_CP0_SA_ALIGN 1 +#define XCHAL_CP1_SA_SIZE 0 +#define XCHAL_CP1_SA_ALIGN 1 +#define XCHAL_CP2_SA_SIZE 0 +#define XCHAL_CP2_SA_ALIGN 1 +#define XCHAL_CP3_SA_SIZE 0 +#define XCHAL_CP3_SA_ALIGN 1 +#define XCHAL_CP4_SA_SIZE 0 +#define XCHAL_CP4_SA_ALIGN 1 +#define XCHAL_CP5_SA_SIZE 0 +#define XCHAL_CP5_SA_ALIGN 1 +#define XCHAL_CP6_SA_SIZE 0 +#define XCHAL_CP6_SA_ALIGN 1 +#define XCHAL_CP7_SA_SIZE 0 +#define XCHAL_CP7_SA_ALIGN 1 +#endif + + +/* Indexing macros: */ +#define _XCHAL_CP_SA_SIZE(n) XCHAL_CP ## n ## _SA_SIZE +#define XCHAL_CP_SA_SIZE(n) _XCHAL_CP_SA_SIZE(n) /* n = 0 .. 7 */ +#define _XCHAL_CP_SA_ALIGN(n) XCHAL_CP ## n ## _SA_ALIGN +#define XCHAL_CP_SA_ALIGN(n) _XCHAL_CP_SA_ALIGN(n) /* n = 0 .. 7 */ + +#define XCHAL_CPEXTRA_SA_SIZE_TOR2 XCHAL_CPEXTRA_SA_SIZE /* Tor2Beta only - do not use */ + +/* Link-time HAL global variables that report coprocessor numbers by name + (names are case-preserved from the original TIE): */ +#if !defined(_ASMLANGUAGE) && !defined(_NOCLANGUAGE) && !defined(__ASSEMBLER__) +# define _XCJOIN(a,b) a ## b +# define XCJOIN(a,b) _XCJOIN(a,b) +# ifdef XCHAL_CP0_NAME +extern const unsigned char XCJOIN(Xthal_cp_id_,XCHAL_CP0_IDENT); +extern const unsigned int XCJOIN(Xthal_cp_mask_,XCHAL_CP0_IDENT); +# endif +# ifdef XCHAL_CP1_NAME +extern const unsigned char XCJOIN(Xthal_cp_id_,XCHAL_CP1_IDENT); +extern const unsigned int XCJOIN(Xthal_cp_mask_,XCHAL_CP1_IDENT); +# endif +# ifdef XCHAL_CP2_NAME +extern const unsigned char XCJOIN(Xthal_cp_id_,XCHAL_CP2_IDENT); +extern const unsigned int XCJOIN(Xthal_cp_mask_,XCHAL_CP2_IDENT); +# endif +# ifdef XCHAL_CP3_NAME +extern const unsigned char XCJOIN(Xthal_cp_id_,XCHAL_CP3_IDENT); +extern const unsigned int XCJOIN(Xthal_cp_mask_,XCHAL_CP3_IDENT); +# endif +# ifdef XCHAL_CP4_NAME +extern const unsigned char XCJOIN(Xthal_cp_id_,XCHAL_CP4_IDENT); +extern const unsigned int XCJOIN(Xthal_cp_mask_,XCHAL_CP4_IDENT); +# endif +# ifdef XCHAL_CP5_NAME +extern const unsigned char XCJOIN(Xthal_cp_id_,XCHAL_CP5_IDENT); +extern const unsigned int XCJOIN(Xthal_cp_mask_,XCHAL_CP5_IDENT); +# endif +# ifdef XCHAL_CP6_NAME +extern const unsigned char XCJOIN(Xthal_cp_id_,XCHAL_CP6_IDENT); +extern const unsigned int XCJOIN(Xthal_cp_mask_,XCHAL_CP6_IDENT); +# endif +# ifdef XCHAL_CP7_NAME +extern const unsigned char XCJOIN(Xthal_cp_id_,XCHAL_CP7_IDENT); +extern const unsigned int XCJOIN(Xthal_cp_mask_,XCHAL_CP7_IDENT); +# endif +#endif + + + + +/*---------------------------------------------------------------------- + DERIVED + ----------------------------------------------------------------------*/ + +#if XCHAL_HAVE_BE +#define XCHAL_INST_ILLN 0xD60F /* 2-byte illegal instruction, msb-first */ +#define XCHAL_INST_ILLN_BYTE0 0xD6 /* 2-byte illegal instruction, 1st byte */ +#define XCHAL_INST_ILLN_BYTE1 0x0F /* 2-byte illegal instruction, 2nd byte */ +#else +#define XCHAL_INST_ILLN 0xF06D /* 2-byte illegal instruction, lsb-first */ +#define XCHAL_INST_ILLN_BYTE0 0x6D /* 2-byte illegal instruction, 1st byte */ +#define XCHAL_INST_ILLN_BYTE1 0xF0 /* 2-byte illegal instruction, 2nd byte */ +#endif +/* Belongs in xtensa/hal.h: */ +#define XTHAL_INST_ILL 0x000000 /* 3-byte illegal instruction */ + + +/* + * Because information as to exactly which hardware version is targeted + * by a given software build is not always available, compile-time HAL + * Hardware-Release "_AT" macros are fuzzy (return 0, 1, or XCHAL_MAYBE): + * (Here "RELEASE" is now a misnomer; these are product *versions*, not the releases + * under which they are released. In the T10##.# era there was no distinction.) + */ +#if XCHAL_HW_CONFIGID_RELIABLE +# define XCHAL_HW_RELEASE_AT_OR_BELOW(major,minor) (XTHAL_REL_LE( XCHAL_HW_VERSION_MAJOR,XCHAL_HW_VERSION_MINOR, major,minor ) ? 1 : 0) +# define XCHAL_HW_RELEASE_AT_OR_ABOVE(major,minor) (XTHAL_REL_GE( XCHAL_HW_VERSION_MAJOR,XCHAL_HW_VERSION_MINOR, major,minor ) ? 1 : 0) +# define XCHAL_HW_RELEASE_AT(major,minor) (XTHAL_REL_EQ( XCHAL_HW_VERSION_MAJOR,XCHAL_HW_VERSION_MINOR, major,minor ) ? 1 : 0) +# define XCHAL_HW_RELEASE_MAJOR_AT(major) ((XCHAL_HW_VERSION_MAJOR == (major)) ? 1 : 0) +#else +# define XCHAL_HW_RELEASE_AT_OR_BELOW(major,minor) ( ((major) < 1040 && XCHAL_HAVE_XEA2) ? 0 \ + : ((major) > 1050 && XCHAL_HAVE_XEA1) ? 1 \ + : XTHAL_MAYBE ) +# define XCHAL_HW_RELEASE_AT_OR_ABOVE(major,minor) ( ((major) >= 2000 && XCHAL_HAVE_XEA1) ? 0 \ + : (XTHAL_REL_LE(major,minor, 1040,0) && XCHAL_HAVE_XEA2) ? 1 \ + : XTHAL_MAYBE ) +# define XCHAL_HW_RELEASE_AT(major,minor) ( (((major) < 1040 && XCHAL_HAVE_XEA2) || \ + ((major) >= 2000 && XCHAL_HAVE_XEA1)) ? 0 : XTHAL_MAYBE) +# define XCHAL_HW_RELEASE_MAJOR_AT(major) XCHAL_HW_RELEASE_AT(major,0) +#endif + +/* + * Specific errata: + */ + +/* + * Erratum T1020.H13, T1030.H7, T1040.H10, T1050.H4 (fixed in T1040.3 and T1050.1; + * relevant only in XEA1, kernel-vector mode, level-one interrupts and overflows enabled): + */ +#define XCHAL_MAYHAVE_ERRATUM_XEA1KWIN (XCHAL_HAVE_XEA1 && \ + (XCHAL_HW_RELEASE_AT_OR_BELOW(1040,2) != 0 \ + || XCHAL_HW_RELEASE_AT(1050,0))) +/* + * Erratum 453 present in RE-2013.2 up to RF-2014.0, fixed in RF-2014.1. + * Applies to specific set of configuration options. + * Part of the workaround is to add ISYNC at certain points in the code. + * The workaround gated by this macro can be disabled if not needed, e.g. if + * zero-overhead loop buffer will be disabled, by defining _NO_ERRATUM_453. + */ +#if ( XCHAL_HW_MAX_VERSION >= XTENSA_HWVERSION_RE_2013_2 && \ + XCHAL_HW_MIN_VERSION <= XTENSA_HWVERSION_RF_2014_0 && \ + XCHAL_ICACHE_SIZE != 0 && XCHAL_HAVE_PIF /*covers also AXI/AHB*/ && \ + XCHAL_HAVE_LOOPS && XCHAL_LOOP_BUFFER_SIZE != 0 && \ + XCHAL_CLOCK_GATING_GLOBAL && !defined(_NO_ERRATUM_453) ) +#define XCHAL_ERRATUM_453 1 +#else +#define XCHAL_ERRATUM_453 0 +#endif + +/* + * Erratum 497 present in RE-2012.2 up to RG/RF-2015.2 + * Applies to specific set of configuration options. + * Workaround is to add MEMWs after at most 8 cache WB instructions + */ +#if ( ((XCHAL_HW_MAX_VERSION >= XTENSA_HWVERSION_RE_2012_0 && \ + XCHAL_HW_MIN_VERSION <= XTENSA_HWVERSION_RF_2015_2) || \ + (XCHAL_HW_MAX_VERSION >= XTENSA_HWVERSION_RG_2015_0 && \ + XCHAL_HW_MIN_VERSION <= XTENSA_HWVERSION_RG_2015_2) \ + ) && \ + XCHAL_DCACHE_IS_WRITEBACK && \ + XCHAL_HAVE_AXI && \ + XCHAL_HAVE_PIF_WR_RESP && \ + XCHAL_HAVE_PIF_REQ_ATTR && !defined(_NO_ERRATUM_497) \ + ) +#define XCHAL_ERRATUM_497 1 +#else +#define XCHAL_ERRATUM_497 0 +#endif + +#endif /*XTENSA_CONFIG_CORE_H*/ + diff --git a/components/esp32/include/xtensa/config/defs.h b/components/esp32/include/xtensa/config/defs.h new file mode 100644 index 0000000000..d7c48ea84a --- /dev/null +++ b/components/esp32/include/xtensa/config/defs.h @@ -0,0 +1,38 @@ +/* Definitions for Xtensa instructions, types, and protos. */ + +/* Customer ID=11657; Build=0x5fe96; Copyright (c) 2003-2004 Tensilica Inc. + + Permission is hereby granted, free of charge, to any person obtaining + a copy of this software and associated documentation files (the + "Software"), to deal in the Software without restriction, including + without limitation the rights to use, copy, modify, merge, publish, + distribute, sublicense, and/or sell copies of the Software, and to + permit persons to whom the Software is furnished to do so, subject to + the following conditions: + + The above copyright notice and this permission notice shall be included + in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY + CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ + +/* NOTE: This file exists only for backward compatibility with T1050 + and earlier Xtensa releases. It includes only a subset of the + available header files. */ + +#ifndef _XTENSA_BASE_HEADER +#define _XTENSA_BASE_HEADER + +#ifdef __XTENSA__ + +#include +#include +#include + +#endif /* __XTENSA__ */ +#endif /* !_XTENSA_BASE_HEADER */ diff --git a/components/esp32/include/xtensa/config/specreg.h b/components/esp32/include/xtensa/config/specreg.h new file mode 100644 index 0000000000..0135d4c7f5 --- /dev/null +++ b/components/esp32/include/xtensa/config/specreg.h @@ -0,0 +1,117 @@ +/* + * Xtensa Special Register symbolic names + */ + +/* $Id: //depot/rel/Eaglenest/Xtensa/SWConfig/hal/specreg.h.tpp#1 $ */ + +/* Customer ID=11657; Build=0x5fe96; Copyright (c) 1998-2002 Tensilica Inc. + + Permission is hereby granted, free of charge, to any person obtaining + a copy of this software and associated documentation files (the + "Software"), to deal in the Software without restriction, including + without limitation the rights to use, copy, modify, merge, publish, + distribute, sublicense, and/or sell copies of the Software, and to + permit persons to whom the Software is furnished to do so, subject to + the following conditions: + + The above copyright notice and this permission notice shall be included + in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY + CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ + +#ifndef XTENSA_SPECREG_H +#define XTENSA_SPECREG_H + +/* Include these special register bitfield definitions, for historical reasons: */ +#include + + +/* Special registers: */ +#define LBEG 0 +#define LEND 1 +#define LCOUNT 2 +#define SAR 3 +#define BR 4 +#define SCOMPARE1 12 +#define ACCLO 16 +#define ACCHI 17 +#define MR_0 32 +#define MR_1 33 +#define MR_2 34 +#define MR_3 35 +#define WINDOWBASE 72 +#define WINDOWSTART 73 +#define IBREAKENABLE 96 +#define MEMCTL 97 +#define ATOMCTL 99 +#define DDR 104 +#define IBREAKA_0 128 +#define IBREAKA_1 129 +#define DBREAKA_0 144 +#define DBREAKA_1 145 +#define DBREAKC_0 160 +#define DBREAKC_1 161 +#define EPC_1 177 +#define EPC_2 178 +#define EPC_3 179 +#define EPC_4 180 +#define EPC_5 181 +#define EPC_6 182 +#define EPC_7 183 +#define DEPC 192 +#define EPS_2 194 +#define EPS_3 195 +#define EPS_4 196 +#define EPS_5 197 +#define EPS_6 198 +#define EPS_7 199 +#define EXCSAVE_1 209 +#define EXCSAVE_2 210 +#define EXCSAVE_3 211 +#define EXCSAVE_4 212 +#define EXCSAVE_5 213 +#define EXCSAVE_6 214 +#define EXCSAVE_7 215 +#define CPENABLE 224 +#define INTERRUPT 226 +#define INTENABLE 228 +#define PS 230 +#define VECBASE 231 +#define EXCCAUSE 232 +#define DEBUGCAUSE 233 +#define CCOUNT 234 +#define PRID 235 +#define ICOUNT 236 +#define ICOUNTLEVEL 237 +#define EXCVADDR 238 +#define CCOMPARE_0 240 +#define CCOMPARE_1 241 +#define CCOMPARE_2 242 +#define MISC_REG_0 244 +#define MISC_REG_1 245 +#define MISC_REG_2 246 +#define MISC_REG_3 247 + +/* Special cases (bases of special register series): */ +#define MR 32 +#define IBREAKA 128 +#define DBREAKA 144 +#define DBREAKC 160 +#define EPC 176 +#define EPS 192 +#define EXCSAVE 208 +#define CCOMPARE 240 + +/* Special names for read-only and write-only interrupt registers: */ +#define INTREAD 226 +#define INTSET 226 +#define INTCLEAR 227 + +#endif /* XTENSA_SPECREG_H */ + diff --git a/components/esp32/include/xtensa/config/system.h b/components/esp32/include/xtensa/config/system.h new file mode 100644 index 0000000000..0d56eef74f --- /dev/null +++ b/components/esp32/include/xtensa/config/system.h @@ -0,0 +1,274 @@ +/* + * xtensa/config/system.h -- HAL definitions that are dependent on SYSTEM configuration + * + * NOTE: The location and contents of this file are highly subject to change. + * + * Source for configuration-independent binaries (which link in a + * configuration-specific HAL library) must NEVER include this file. + * The HAL itself has historically included this file in some instances, + * but this is not appropriate either, because the HAL is meant to be + * core-specific but system independent. + */ + +/* Customer ID=11657; Build=0x5fe96; Copyright (c) 2000-2010 Tensilica Inc. + + Permission is hereby granted, free of charge, to any person obtaining + a copy of this software and associated documentation files (the + "Software"), to deal in the Software without restriction, including + without limitation the rights to use, copy, modify, merge, publish, + distribute, sublicense, and/or sell copies of the Software, and to + permit persons to whom the Software is furnished to do so, subject to + the following conditions: + + The above copyright notice and this permission notice shall be included + in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY + CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ + + +#ifndef XTENSA_CONFIG_SYSTEM_H +#define XTENSA_CONFIG_SYSTEM_H + +/*#include */ + + + +/*---------------------------------------------------------------------- + CONFIGURED SOFTWARE OPTIONS + ----------------------------------------------------------------------*/ + +#define XSHAL_USE_ABSOLUTE_LITERALS 0 /* (sw-only option, whether software uses absolute literals) */ +#define XSHAL_HAVE_TEXT_SECTION_LITERALS 1 /* Set if there is some memory that allows both code and literals. */ + +#define XSHAL_ABI XTHAL_ABI_WINDOWED /* (sw-only option, selected ABI) */ +/* The above maps to one of the following constants: */ +#define XTHAL_ABI_WINDOWED 0 +#define XTHAL_ABI_CALL0 1 +/* Alternatives: */ +/*#define XSHAL_WINDOWED_ABI 1*/ /* set if windowed ABI selected */ +/*#define XSHAL_CALL0_ABI 0*/ /* set if call0 ABI selected */ + +#define XSHAL_CLIB XTHAL_CLIB_NEWLIB /* (sw-only option, selected C library) */ +/* The above maps to one of the following constants: */ +#define XTHAL_CLIB_NEWLIB 0 +#define XTHAL_CLIB_UCLIBC 1 +#define XTHAL_CLIB_XCLIB 2 +/* Alternatives: */ +/*#define XSHAL_NEWLIB 1*/ /* set if newlib C library selected */ +/*#define XSHAL_UCLIBC 0*/ /* set if uCLibC C library selected */ +/*#define XSHAL_XCLIB 0*/ /* set if Xtensa C library selected */ + +#define XSHAL_USE_FLOATING_POINT 1 + +#define XSHAL_FLOATING_POINT_ABI 0 + +/* SW workarounds enabled for HW errata: */ + +/*---------------------------------------------------------------------- + DEVICE ADDRESSES + ----------------------------------------------------------------------*/ + +/* + * Strange place to find these, but the configuration GUI + * allows moving these around to account for various core + * configurations. Specific boards (and their BSP software) + * will have specific meanings for these components. + */ + +/* I/O Block areas: */ +#define XSHAL_IOBLOCK_CACHED_VADDR 0x70000000 +#define XSHAL_IOBLOCK_CACHED_PADDR 0x70000000 +#define XSHAL_IOBLOCK_CACHED_SIZE 0x0E000000 + +#define XSHAL_IOBLOCK_BYPASS_VADDR 0x90000000 +#define XSHAL_IOBLOCK_BYPASS_PADDR 0x90000000 +#define XSHAL_IOBLOCK_BYPASS_SIZE 0x0E000000 + +/* System ROM: */ +#define XSHAL_ROM_VADDR 0x50000000 +#define XSHAL_ROM_PADDR 0x50000000 +#define XSHAL_ROM_SIZE 0x01000000 +/* Largest available area (free of vectors): */ +#define XSHAL_ROM_AVAIL_VADDR 0x50000000 +#define XSHAL_ROM_AVAIL_VSIZE 0x01000000 + +/* System RAM: */ +#define XSHAL_RAM_VADDR 0x60000000 +#define XSHAL_RAM_PADDR 0x60000000 +#define XSHAL_RAM_VSIZE 0x20000000 +#define XSHAL_RAM_PSIZE 0x20000000 +#define XSHAL_RAM_SIZE XSHAL_RAM_PSIZE +/* Largest available area (free of vectors): */ +#define XSHAL_RAM_AVAIL_VADDR 0x60000000 +#define XSHAL_RAM_AVAIL_VSIZE 0x20000000 + +/* + * Shadow system RAM (same device as system RAM, at different address). + * (Emulation boards need this for the SONIC Ethernet driver + * when data caches are configured for writeback mode.) + * NOTE: on full MMU configs, this points to the BYPASS virtual address + * of system RAM, ie. is the same as XSHAL_RAM_* except that virtual + * addresses are viewed through the BYPASS static map rather than + * the CACHED static map. + */ +#define XSHAL_RAM_BYPASS_VADDR 0xA0000000 +#define XSHAL_RAM_BYPASS_PADDR 0xA0000000 +#define XSHAL_RAM_BYPASS_PSIZE 0x20000000 + +/* Alternate system RAM (different device than system RAM): */ +/*#define XSHAL_ALTRAM_[VP]ADDR ...not configured...*/ +/*#define XSHAL_ALTRAM_SIZE ...not configured...*/ + +/* Some available location in which to place devices in a simulation (eg. XTMP): */ +#define XSHAL_SIMIO_CACHED_VADDR 0xC0000000 +#define XSHAL_SIMIO_BYPASS_VADDR 0xC0000000 +#define XSHAL_SIMIO_PADDR 0xC0000000 +#define XSHAL_SIMIO_SIZE 0x20000000 + + +/*---------------------------------------------------------------------- + * For use by reference testbench exit and diagnostic routines. + */ +#define XSHAL_MAGIC_EXIT 0x0 + +/*---------------------------------------------------------------------- + * DEVICE-ADDRESS DEPENDENT... + * + * Values written to CACHEATTR special register (or its equivalent) + * to enable and disable caches in various modes. + *----------------------------------------------------------------------*/ + +/*---------------------------------------------------------------------- + BACKWARD COMPATIBILITY ... + ----------------------------------------------------------------------*/ + +/* + * NOTE: the following two macros are DEPRECATED. Use the latter + * board-specific macros instead, which are specially tuned for the + * particular target environments' memory maps. + */ +#define XSHAL_CACHEATTR_BYPASS XSHAL_XT2000_CACHEATTR_BYPASS /* disable caches in bypass mode */ +#define XSHAL_CACHEATTR_DEFAULT XSHAL_XT2000_CACHEATTR_DEFAULT /* default setting to enable caches (no writeback!) */ + +/*---------------------------------------------------------------------- + GENERIC + ----------------------------------------------------------------------*/ + +/* For the following, a 512MB region is used if it contains a system (PIF) RAM, + * system (PIF) ROM, local memory, or XLMI. */ + +/* These set any unused 512MB region to cache-BYPASS attribute: */ +#define XSHAL_ALLVALID_CACHEATTR_WRITEBACK 0x22221112 /* enable caches in write-back mode */ +#define XSHAL_ALLVALID_CACHEATTR_WRITEALLOC 0x22221112 /* enable caches in write-allocate mode */ +#define XSHAL_ALLVALID_CACHEATTR_WRITETHRU 0x22221112 /* enable caches in write-through mode */ +#define XSHAL_ALLVALID_CACHEATTR_BYPASS 0x22222222 /* disable caches in bypass mode */ +#define XSHAL_ALLVALID_CACHEATTR_DEFAULT XSHAL_ALLVALID_CACHEATTR_WRITEBACK /* default setting to enable caches */ + +/* These set any unused 512MB region to ILLEGAL attribute: */ +#define XSHAL_STRICT_CACHEATTR_WRITEBACK 0xFFFF111F /* enable caches in write-back mode */ +#define XSHAL_STRICT_CACHEATTR_WRITEALLOC 0xFFFF111F /* enable caches in write-allocate mode */ +#define XSHAL_STRICT_CACHEATTR_WRITETHRU 0xFFFF111F /* enable caches in write-through mode */ +#define XSHAL_STRICT_CACHEATTR_BYPASS 0xFFFF222F /* disable caches in bypass mode */ +#define XSHAL_STRICT_CACHEATTR_DEFAULT XSHAL_STRICT_CACHEATTR_WRITEBACK /* default setting to enable caches */ + +/* These set the first 512MB, if unused, to ILLEGAL attribute to help catch + * NULL-pointer dereference bugs; all other unused 512MB regions are set + * to cache-BYPASS attribute: */ +#define XSHAL_TRAPNULL_CACHEATTR_WRITEBACK 0x2222111F /* enable caches in write-back mode */ +#define XSHAL_TRAPNULL_CACHEATTR_WRITEALLOC 0x2222111F /* enable caches in write-allocate mode */ +#define XSHAL_TRAPNULL_CACHEATTR_WRITETHRU 0x2222111F /* enable caches in write-through mode */ +#define XSHAL_TRAPNULL_CACHEATTR_BYPASS 0x2222222F /* disable caches in bypass mode */ +#define XSHAL_TRAPNULL_CACHEATTR_DEFAULT XSHAL_TRAPNULL_CACHEATTR_WRITEBACK /* default setting to enable caches */ + +/*---------------------------------------------------------------------- + ISS (Instruction Set Simulator) SPECIFIC ... + ----------------------------------------------------------------------*/ + +/* For now, ISS defaults to the TRAPNULL settings: */ +#define XSHAL_ISS_CACHEATTR_WRITEBACK XSHAL_TRAPNULL_CACHEATTR_WRITEBACK +#define XSHAL_ISS_CACHEATTR_WRITEALLOC XSHAL_TRAPNULL_CACHEATTR_WRITEALLOC +#define XSHAL_ISS_CACHEATTR_WRITETHRU XSHAL_TRAPNULL_CACHEATTR_WRITETHRU +#define XSHAL_ISS_CACHEATTR_BYPASS XSHAL_TRAPNULL_CACHEATTR_BYPASS +#define XSHAL_ISS_CACHEATTR_DEFAULT XSHAL_TRAPNULL_CACHEATTR_WRITEBACK + +#define XSHAL_ISS_PIPE_REGIONS 0 +#define XSHAL_ISS_SDRAM_REGIONS 0 + + +/*---------------------------------------------------------------------- + XT2000 BOARD SPECIFIC ... + ----------------------------------------------------------------------*/ + +/* For the following, a 512MB region is used if it contains any system RAM, + * system ROM, local memory, XLMI, or other XT2000 board device or memory. + * Regions containing devices are forced to cache-BYPASS mode regardless + * of whether the macro is _WRITEBACK vs. _BYPASS etc. */ + +/* These set any 512MB region unused on the XT2000 to ILLEGAL attribute: */ +#define XSHAL_XT2000_CACHEATTR_WRITEBACK 0xFF22111F /* enable caches in write-back mode */ +#define XSHAL_XT2000_CACHEATTR_WRITEALLOC 0xFF22111F /* enable caches in write-allocate mode */ +#define XSHAL_XT2000_CACHEATTR_WRITETHRU 0xFF22111F /* enable caches in write-through mode */ +#define XSHAL_XT2000_CACHEATTR_BYPASS 0xFF22222F /* disable caches in bypass mode */ +#define XSHAL_XT2000_CACHEATTR_DEFAULT XSHAL_XT2000_CACHEATTR_WRITEBACK /* default setting to enable caches */ + +#define XSHAL_XT2000_PIPE_REGIONS 0x00000000 /* BusInt pipeline regions */ +#define XSHAL_XT2000_SDRAM_REGIONS 0x00000440 /* BusInt SDRAM regions */ + + +/*---------------------------------------------------------------------- + VECTOR INFO AND SIZES + ----------------------------------------------------------------------*/ + +#define XSHAL_VECTORS_PACKED 0 +#define XSHAL_STATIC_VECTOR_SELECT 1 +#define XSHAL_RESET_VECTOR_VADDR 0x40000400 +#define XSHAL_RESET_VECTOR_PADDR 0x40000400 + +/* + * Sizes allocated to vectors by the system (memory map) configuration. + * These sizes are constrained by core configuration (eg. one vector's + * code cannot overflow into another vector) but are dependent on the + * system or board (or LSP) memory map configuration. + * + * Whether or not each vector happens to be in a system ROM is also + * a system configuration matter, sometimes useful, included here also: + */ +#define XSHAL_RESET_VECTOR_SIZE 0x00000300 +#define XSHAL_RESET_VECTOR_ISROM 0 +#define XSHAL_USER_VECTOR_SIZE 0x00000038 +#define XSHAL_USER_VECTOR_ISROM 0 +#define XSHAL_PROGRAMEXC_VECTOR_SIZE XSHAL_USER_VECTOR_SIZE /* for backward compatibility */ +#define XSHAL_USEREXC_VECTOR_SIZE XSHAL_USER_VECTOR_SIZE /* for backward compatibility */ +#define XSHAL_KERNEL_VECTOR_SIZE 0x00000038 +#define XSHAL_KERNEL_VECTOR_ISROM 0 +#define XSHAL_STACKEDEXC_VECTOR_SIZE XSHAL_KERNEL_VECTOR_SIZE /* for backward compatibility */ +#define XSHAL_KERNELEXC_VECTOR_SIZE XSHAL_KERNEL_VECTOR_SIZE /* for backward compatibility */ +#define XSHAL_DOUBLEEXC_VECTOR_SIZE 0x00000040 +#define XSHAL_DOUBLEEXC_VECTOR_ISROM 0 +#define XSHAL_WINDOW_VECTORS_SIZE 0x00000178 +#define XSHAL_WINDOW_VECTORS_ISROM 0 +#define XSHAL_INTLEVEL2_VECTOR_SIZE 0x00000038 +#define XSHAL_INTLEVEL2_VECTOR_ISROM 0 +#define XSHAL_INTLEVEL3_VECTOR_SIZE 0x00000038 +#define XSHAL_INTLEVEL3_VECTOR_ISROM 0 +#define XSHAL_INTLEVEL4_VECTOR_SIZE 0x00000038 +#define XSHAL_INTLEVEL4_VECTOR_ISROM 0 +#define XSHAL_INTLEVEL5_VECTOR_SIZE 0x00000038 +#define XSHAL_INTLEVEL5_VECTOR_ISROM 0 +#define XSHAL_INTLEVEL6_VECTOR_SIZE 0x00000038 +#define XSHAL_INTLEVEL6_VECTOR_ISROM 0 +#define XSHAL_DEBUG_VECTOR_SIZE XSHAL_INTLEVEL6_VECTOR_SIZE +#define XSHAL_DEBUG_VECTOR_ISROM XSHAL_INTLEVEL6_VECTOR_ISROM +#define XSHAL_NMI_VECTOR_SIZE 0x00000038 +#define XSHAL_NMI_VECTOR_ISROM 0 +#define XSHAL_INTLEVEL7_VECTOR_SIZE XSHAL_NMI_VECTOR_SIZE + + +#endif /*XTENSA_CONFIG_SYSTEM_H*/ + diff --git a/components/esp32/include/xtensa/config/tie-asm.h b/components/esp32/include/xtensa/config/tie-asm.h new file mode 100644 index 0000000000..831d8676ae --- /dev/null +++ b/components/esp32/include/xtensa/config/tie-asm.h @@ -0,0 +1,323 @@ +/* + * tie-asm.h -- compile-time HAL assembler definitions dependent on CORE & TIE + * + * NOTE: This header file is not meant to be included directly. + */ + +/* This header file contains assembly-language definitions (assembly + macros, etc.) for this specific Xtensa processor's TIE extensions + and options. It is customized to this Xtensa processor configuration. + + Customer ID=11657; Build=0x5fe96; Copyright (c) 1999-2016 Cadence Design Systems Inc. + + Permission is hereby granted, free of charge, to any person obtaining + a copy of this software and associated documentation files (the + "Software"), to deal in the Software without restriction, including + without limitation the rights to use, copy, modify, merge, publish, + distribute, sublicense, and/or sell copies of the Software, and to + permit persons to whom the Software is furnished to do so, subject to + the following conditions: + + The above copyright notice and this permission notice shall be included + in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY + CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ + +#ifndef _XTENSA_CORE_TIE_ASM_H +#define _XTENSA_CORE_TIE_ASM_H + +/* Selection parameter values for save-area save/restore macros: */ +/* Option vs. TIE: */ +#define XTHAL_SAS_TIE 0x0001 /* custom extension or coprocessor */ +#define XTHAL_SAS_OPT 0x0002 /* optional (and not a coprocessor) */ +#define XTHAL_SAS_ANYOT 0x0003 /* both of the above */ +/* Whether used automatically by compiler: */ +#define XTHAL_SAS_NOCC 0x0004 /* not used by compiler w/o special opts/code */ +#define XTHAL_SAS_CC 0x0008 /* used by compiler without special opts/code */ +#define XTHAL_SAS_ANYCC 0x000C /* both of the above */ +/* ABI handling across function calls: */ +#define XTHAL_SAS_CALR 0x0010 /* caller-saved */ +#define XTHAL_SAS_CALE 0x0020 /* callee-saved */ +#define XTHAL_SAS_GLOB 0x0040 /* global across function calls (in thread) */ +#define XTHAL_SAS_ANYABI 0x0070 /* all of the above three */ +/* Misc */ +#define XTHAL_SAS_ALL 0xFFFF /* include all default NCP contents */ +#define XTHAL_SAS3(optie,ccuse,abi) ( ((optie) & XTHAL_SAS_ANYOT) \ + | ((ccuse) & XTHAL_SAS_ANYCC) \ + | ((abi) & XTHAL_SAS_ANYABI) ) + + + /* + * Macro to store all non-coprocessor (extra) custom TIE and optional state + * (not including zero-overhead loop registers). + * Required parameters: + * ptr Save area pointer address register (clobbered) + * (register must contain a 4 byte aligned address). + * at1..at4 Four temporary address registers (first XCHAL_NCP_NUM_ATMPS + * registers are clobbered, the remaining are unused). + * Optional parameters: + * continue If macro invoked as part of a larger store sequence, set to 1 + * if this is not the first in the sequence. Defaults to 0. + * ofs Offset from start of larger sequence (from value of first ptr + * in sequence) at which to store. Defaults to next available space + * (or 0 if is 0). + * select Select what category(ies) of registers to store, as a bitmask + * (see XTHAL_SAS_xxx constants). Defaults to all registers. + * alloc Select what category(ies) of registers to allocate; if any + * category is selected here that is not in , space for + * the corresponding registers is skipped without doing any load. + */ + .macro xchal_ncp_load ptr at1 at2 at3 at4 continue=0 ofs=-1 select=XTHAL_SAS_ALL alloc=0 + xchal_sa_start \continue, \ofs + // Optional global registers used by default by the compiler: + .ifeq (XTHAL_SAS_OPT | XTHAL_SAS_CC | XTHAL_SAS_GLOB) & ~(\select) + xchal_sa_align \ptr, 0, 1016, 4, 4 + l32i \at1, \ptr, .Lxchal_ofs_+0 + wur.THREADPTR \at1 // threadptr option + .set .Lxchal_ofs_, .Lxchal_ofs_ + 4 + .elseif ((XTHAL_SAS_OPT | XTHAL_SAS_CC | XTHAL_SAS_GLOB) & ~(\alloc)) == 0 + xchal_sa_align \ptr, 0, 1016, 4, 4 + .set .Lxchal_ofs_, .Lxchal_ofs_ + 4 + .endif + // Optional caller-saved registers used by default by the compiler: + .ifeq (XTHAL_SAS_OPT | XTHAL_SAS_CC | XTHAL_SAS_CALR) & ~(\select) + xchal_sa_align \ptr, 0, 1012, 4, 4 + l32i \at1, \ptr, .Lxchal_ofs_+0 + wsr.ACCLO \at1 // MAC16 option + l32i \at1, \ptr, .Lxchal_ofs_+4 + wsr.ACCHI \at1 // MAC16 option + .set .Lxchal_ofs_, .Lxchal_ofs_ + 8 + .elseif ((XTHAL_SAS_OPT | XTHAL_SAS_CC | XTHAL_SAS_CALR) & ~(\alloc)) == 0 + xchal_sa_align \ptr, 0, 1012, 4, 4 + .set .Lxchal_ofs_, .Lxchal_ofs_ + 8 + .endif + // Optional caller-saved registers not used by default by the compiler: + .ifeq (XTHAL_SAS_OPT | XTHAL_SAS_NOCC | XTHAL_SAS_CALR) & ~(\select) + xchal_sa_align \ptr, 0, 996, 4, 4 + l32i \at1, \ptr, .Lxchal_ofs_+0 + wsr.BR \at1 // boolean option + l32i \at1, \ptr, .Lxchal_ofs_+4 + wsr.SCOMPARE1 \at1 // conditional store option + l32i \at1, \ptr, .Lxchal_ofs_+8 + wsr.M0 \at1 // MAC16 option + l32i \at1, \ptr, .Lxchal_ofs_+12 + wsr.M1 \at1 // MAC16 option + l32i \at1, \ptr, .Lxchal_ofs_+16 + wsr.M2 \at1 // MAC16 option + l32i \at1, \ptr, .Lxchal_ofs_+20 + wsr.M3 \at1 // MAC16 option + .set .Lxchal_ofs_, .Lxchal_ofs_ + 24 + .elseif ((XTHAL_SAS_OPT | XTHAL_SAS_NOCC | XTHAL_SAS_CALR) & ~(\alloc)) == 0 + xchal_sa_align \ptr, 0, 996, 4, 4 + .set .Lxchal_ofs_, .Lxchal_ofs_ + 24 + .endif + // Custom caller-saved registers not used by default by the compiler: + .ifeq (XTHAL_SAS_TIE | XTHAL_SAS_NOCC | XTHAL_SAS_CALR) & ~(\select) + xchal_sa_align \ptr, 0, 1008, 4, 4 + l32i \at1, \ptr, .Lxchal_ofs_+0 + wur.F64R_LO \at1 // ureg 234 + l32i \at1, \ptr, .Lxchal_ofs_+4 + wur.F64R_HI \at1 // ureg 235 + l32i \at1, \ptr, .Lxchal_ofs_+8 + wur.F64S \at1 // ureg 236 + .set .Lxchal_ofs_, .Lxchal_ofs_ + 12 + .elseif ((XTHAL_SAS_TIE | XTHAL_SAS_NOCC | XTHAL_SAS_CALR) & ~(\alloc)) == 0 + xchal_sa_align \ptr, 0, 1008, 4, 4 + .set .Lxchal_ofs_, .Lxchal_ofs_ + 12 + .endif + .endm // xchal_ncp_load + + +#define XCHAL_NCP_NUM_ATMPS 1 + + /* + * Macro to store the state of TIE coprocessor FPU. + * Required parameters: + * ptr Save area pointer address register (clobbered) + * (register must contain a 4 byte aligned address). + * at1..at4 Four temporary address registers (first XCHAL_CP0_NUM_ATMPS + * registers are clobbered, the remaining are unused). + * Optional parameters are the same as for xchal_ncp_store. + */ +#define xchal_cp_FPU_store xchal_cp0_store + .macro xchal_cp0_store ptr at1 at2 at3 at4 continue=0 ofs=-1 select=XTHAL_SAS_ALL alloc=0 + xchal_sa_start \continue, \ofs + // Custom caller-saved registers not used by default by the compiler: + .ifeq (XTHAL_SAS_TIE | XTHAL_SAS_NOCC | XTHAL_SAS_CALR) & ~(\select) + xchal_sa_align \ptr, 0, 948, 4, 4 + rur.FCR \at1 // ureg 232 + s32i \at1, \ptr, .Lxchal_ofs_+0 + rur.FSR \at1 // ureg 233 + s32i \at1, \ptr, .Lxchal_ofs_+4 + ssi f0, \ptr, .Lxchal_ofs_+8 + ssi f1, \ptr, .Lxchal_ofs_+12 + ssi f2, \ptr, .Lxchal_ofs_+16 + ssi f3, \ptr, .Lxchal_ofs_+20 + ssi f4, \ptr, .Lxchal_ofs_+24 + ssi f5, \ptr, .Lxchal_ofs_+28 + ssi f6, \ptr, .Lxchal_ofs_+32 + ssi f7, \ptr, .Lxchal_ofs_+36 + ssi f8, \ptr, .Lxchal_ofs_+40 + ssi f9, \ptr, .Lxchal_ofs_+44 + ssi f10, \ptr, .Lxchal_ofs_+48 + ssi f11, \ptr, .Lxchal_ofs_+52 + ssi f12, \ptr, .Lxchal_ofs_+56 + ssi f13, \ptr, .Lxchal_ofs_+60 + ssi f14, \ptr, .Lxchal_ofs_+64 + ssi f15, \ptr, .Lxchal_ofs_+68 + .set .Lxchal_ofs_, .Lxchal_ofs_ + 72 + .elseif ((XTHAL_SAS_TIE | XTHAL_SAS_NOCC | XTHAL_SAS_CALR) & ~(\alloc)) == 0 + xchal_sa_align \ptr, 0, 948, 4, 4 + .set .Lxchal_ofs_, .Lxchal_ofs_ + 72 + .endif + .endm // xchal_cp0_store + + /* + * Macro to load the state of TIE coprocessor FPU. + * Required parameters: + * ptr Save area pointer address register (clobbered) + * (register must contain a 4 byte aligned address). + * at1..at4 Four temporary address registers (first XCHAL_CP0_NUM_ATMPS + * registers are clobbered, the remaining are unused). + * Optional parameters are the same as for xchal_ncp_load. + */ +#define xchal_cp_FPU_load xchal_cp0_load + .macro xchal_cp0_load ptr at1 at2 at3 at4 continue=0 ofs=-1 select=XTHAL_SAS_ALL alloc=0 + xchal_sa_start \continue, \ofs + // Custom caller-saved registers not used by default by the compiler: + .ifeq (XTHAL_SAS_TIE | XTHAL_SAS_NOCC | XTHAL_SAS_CALR) & ~(\select) + xchal_sa_align \ptr, 0, 948, 4, 4 + l32i \at1, \ptr, .Lxchal_ofs_+0 + wur.FCR \at1 // ureg 232 + l32i \at1, \ptr, .Lxchal_ofs_+4 + wur.FSR \at1 // ureg 233 + lsi f0, \ptr, .Lxchal_ofs_+8 + lsi f1, \ptr, .Lxchal_ofs_+12 + lsi f2, \ptr, .Lxchal_ofs_+16 + lsi f3, \ptr, .Lxchal_ofs_+20 + lsi f4, \ptr, .Lxchal_ofs_+24 + lsi f5, \ptr, .Lxchal_ofs_+28 + lsi f6, \ptr, .Lxchal_ofs_+32 + lsi f7, \ptr, .Lxchal_ofs_+36 + lsi f8, \ptr, .Lxchal_ofs_+40 + lsi f9, \ptr, .Lxchal_ofs_+44 + lsi f10, \ptr, .Lxchal_ofs_+48 + lsi f11, \ptr, .Lxchal_ofs_+52 + lsi f12, \ptr, .Lxchal_ofs_+56 + lsi f13, \ptr, .Lxchal_ofs_+60 + lsi f14, \ptr, .Lxchal_ofs_+64 + lsi f15, \ptr, .Lxchal_ofs_+68 + .set .Lxchal_ofs_, .Lxchal_ofs_ + 72 + .elseif ((XTHAL_SAS_TIE | XTHAL_SAS_NOCC | XTHAL_SAS_CALR) & ~(\alloc)) == 0 + xchal_sa_align \ptr, 0, 948, 4, 4 + .set .Lxchal_ofs_, .Lxchal_ofs_ + 72 + .endif + .endm // xchal_cp0_load + +#define XCHAL_CP0_NUM_ATMPS 1 +#define XCHAL_SA_NUM_ATMPS 1 + + /* Empty macros for unconfigured coprocessors: */ + .macro xchal_cp1_store p a b c d continue=0 ofs=-1 select=-1 ; .endm + .macro xchal_cp1_load p a b c d continue=0 ofs=-1 select=-1 ; .endm + .macro xchal_cp2_store p a b c d continue=0 ofs=-1 select=-1 ; .endm + .macro xchal_cp2_load p a b c d continue=0 ofs=-1 select=-1 ; .endm + .macro xchal_cp3_store p a b c d continue=0 ofs=-1 select=-1 ; .endm + .macro xchal_cp3_load p a b c d continue=0 ofs=-1 select=-1 ; .endm + .macro xchal_cp4_store p a b c d continue=0 ofs=-1 select=-1 ; .endm + .macro xchal_cp4_load p a b c d continue=0 ofs=-1 select=-1 ; .endm + .macro xchal_cp5_store p a b c d continue=0 ofs=-1 select=-1 ; .endm + .macro xchal_cp5_load p a b c d continue=0 ofs=-1 select=-1 ; .endm + .macro xchal_cp6_store p a b c d continue=0 ofs=-1 select=-1 ; .endm + .macro xchal_cp6_load p a b c d continue=0 ofs=-1 select=-1 ; .endm + .macro xchal_cp7_store p a b c d continue=0 ofs=-1 select=-1 ; .endm + .macro xchal_cp7_load p a b c d continue=0 ofs=-1 select=-1 ; .endm + +#endif /*_XTENSA_CORE_TIE_ASM_H*/ + diff --git a/components/esp32/include/xtensa/config/tie.h b/components/esp32/include/xtensa/config/tie.h new file mode 100644 index 0000000000..e178799708 --- /dev/null +++ b/components/esp32/include/xtensa/config/tie.h @@ -0,0 +1,182 @@ +/* + * tie.h -- compile-time HAL definitions dependent on CORE & TIE configuration + * + * NOTE: This header file is not meant to be included directly. + */ + +/* This header file describes this specific Xtensa processor's TIE extensions + that extend basic Xtensa core functionality. It is customized to this + Xtensa processor configuration. + + Customer ID=11657; Build=0x5fe96; Copyright (c) 1999-2016 Cadence Design Systems Inc. + + Permission is hereby granted, free of charge, to any person obtaining + a copy of this software and associated documentation files (the + "Software"), to deal in the Software without restriction, including + without limitation the rights to use, copy, modify, merge, publish, + distribute, sublicense, and/or sell copies of the Software, and to + permit persons to whom the Software is furnished to do so, subject to + the following conditions: + + The above copyright notice and this permission notice shall be included + in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY + CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ + +#ifndef _XTENSA_CORE_TIE_H +#define _XTENSA_CORE_TIE_H + +#define XCHAL_CP_NUM 1 /* number of coprocessors */ +#define XCHAL_CP_MAX 1 /* max CP ID + 1 (0 if none) */ +#define XCHAL_CP_MASK 0x01 /* bitmask of all CPs by ID */ +#define XCHAL_CP_PORT_MASK 0x00 /* bitmask of only port CPs */ + +/* Basic parameters of each coprocessor: */ +#define XCHAL_CP0_NAME "FPU" +#define XCHAL_CP0_IDENT FPU +#define XCHAL_CP0_SA_SIZE 72 /* size of state save area */ +#define XCHAL_CP0_SA_ALIGN 4 /* min alignment of save area */ +#define XCHAL_CP_ID_FPU 0 /* coprocessor ID (0..7) */ + +/* Filler info for unassigned coprocessors, to simplify arrays etc: */ +#define XCHAL_CP1_SA_SIZE 0 +#define XCHAL_CP1_SA_ALIGN 1 +#define XCHAL_CP2_SA_SIZE 0 +#define XCHAL_CP2_SA_ALIGN 1 +#define XCHAL_CP3_SA_SIZE 0 +#define XCHAL_CP3_SA_ALIGN 1 +#define XCHAL_CP4_SA_SIZE 0 +#define XCHAL_CP4_SA_ALIGN 1 +#define XCHAL_CP5_SA_SIZE 0 +#define XCHAL_CP5_SA_ALIGN 1 +#define XCHAL_CP6_SA_SIZE 0 +#define XCHAL_CP6_SA_ALIGN 1 +#define XCHAL_CP7_SA_SIZE 0 +#define XCHAL_CP7_SA_ALIGN 1 + +/* Save area for non-coprocessor optional and custom (TIE) state: */ +#define XCHAL_NCP_SA_SIZE 48 +#define XCHAL_NCP_SA_ALIGN 4 + +/* Total save area for optional and custom state (NCP + CPn): */ +#define XCHAL_TOTAL_SA_SIZE 128 /* with 16-byte align padding */ +#define XCHAL_TOTAL_SA_ALIGN 4 /* actual minimum alignment */ + +/* + * Detailed contents of save areas. + * NOTE: caller must define the XCHAL_SA_REG macro (not defined here) + * before expanding the XCHAL_xxx_SA_LIST() macros. + * + * XCHAL_SA_REG(s,ccused,abikind,kind,opt,name,galign,align,asize, + * dbnum,base,regnum,bitsz,gapsz,reset,x...) + * + * s = passed from XCHAL_*_LIST(s), eg. to select how to expand + * ccused = set if used by compiler without special options or code + * abikind = 0 (caller-saved), 1 (callee-saved), or 2 (thread-global) + * kind = 0 (special reg), 1 (TIE user reg), or 2 (TIE regfile reg) + * opt = 0 (custom TIE extension or coprocessor), or 1 (optional reg) + * name = lowercase reg name (no quotes) + * galign = group byte alignment (power of 2) (galign >= align) + * align = register byte alignment (power of 2) + * asize = allocated size in bytes (asize*8 == bitsz + gapsz + padsz) + * (not including any pad bytes required to galign this or next reg) + * dbnum = unique target number f/debug (see ) + * base = reg shortname w/o index (or sr=special, ur=TIE user reg) + * regnum = reg index in regfile, or special/TIE-user reg number + * bitsz = number of significant bits (regfile width, or ur/sr mask bits) + * gapsz = intervening bits, if bitsz bits not stored contiguously + * (padsz = pad bits at end [TIE regfile] or at msbits [ur,sr] of asize) + * reset = register reset value (or 0 if undefined at reset) + * x = reserved for future use (0 until then) + * + * To filter out certain registers, e.g. to expand only the non-global + * registers used by the compiler, you can do something like this: + * + * #define XCHAL_SA_REG(s,ccused,p...) SELCC##ccused(p) + * #define SELCC0(p...) + * #define SELCC1(abikind,p...) SELAK##abikind(p) + * #define SELAK0(p...) REG(p) + * #define SELAK1(p...) REG(p) + * #define SELAK2(p...) + * #define REG(kind,tie,name,galn,aln,asz,csz,dbnum,base,rnum,bsz,rst,x...) \ + * ...what you want to expand... + */ + +#define XCHAL_NCP_SA_NUM 12 +#define XCHAL_NCP_SA_LIST(s) \ + XCHAL_SA_REG(s,1,2,1,1, threadptr, 4, 4, 4,0x03E7, ur,231, 32,0,0,0) \ + XCHAL_SA_REG(s,1,0,0,1, acclo, 4, 4, 4,0x0210, sr,16 , 32,0,0,0) \ + XCHAL_SA_REG(s,1,0,0,1, acchi, 4, 4, 4,0x0211, sr,17 , 8,0,0,0) \ + XCHAL_SA_REG(s,0,0,0,1, br, 4, 4, 4,0x0204, sr,4 , 16,0,0,0) \ + XCHAL_SA_REG(s,0,0,0,1, scompare1, 4, 4, 4,0x020C, sr,12 , 32,0,0,0) \ + XCHAL_SA_REG(s,0,0,0,1, m0, 4, 4, 4,0x0220, sr,32 , 32,0,0,0) \ + XCHAL_SA_REG(s,0,0,0,1, m1, 4, 4, 4,0x0221, sr,33 , 32,0,0,0) \ + XCHAL_SA_REG(s,0,0,0,1, m2, 4, 4, 4,0x0222, sr,34 , 32,0,0,0) \ + XCHAL_SA_REG(s,0,0,0,1, m3, 4, 4, 4,0x0223, sr,35 , 32,0,0,0) \ + XCHAL_SA_REG(s,0,0,1,0, f64r_lo, 4, 4, 4,0x03EA, ur,234, 32,0,0,0) \ + XCHAL_SA_REG(s,0,0,1,0, f64r_hi, 4, 4, 4,0x03EB, ur,235, 32,0,0,0) \ + XCHAL_SA_REG(s,0,0,1,0, f64s, 4, 4, 4,0x03EC, ur,236, 32,0,0,0) + +#define XCHAL_CP0_SA_NUM 18 +#define XCHAL_CP0_SA_LIST(s) \ + XCHAL_SA_REG(s,0,0,1,0, fcr, 4, 4, 4,0x03E8, ur,232, 32,0,0,0) \ + XCHAL_SA_REG(s,0,0,1,0, fsr, 4, 4, 4,0x03E9, ur,233, 32,0,0,0) \ + XCHAL_SA_REG(s,0,0,2,0, f0, 4, 4, 4,0x0030, f,0 , 32,0,0,0) \ + XCHAL_SA_REG(s,0,0,2,0, f1, 4, 4, 4,0x0031, f,1 , 32,0,0,0) \ + XCHAL_SA_REG(s,0,0,2,0, f2, 4, 4, 4,0x0032, f,2 , 32,0,0,0) \ + XCHAL_SA_REG(s,0,0,2,0, f3, 4, 4, 4,0x0033, f,3 , 32,0,0,0) \ + XCHAL_SA_REG(s,0,0,2,0, f4, 4, 4, 4,0x0034, f,4 , 32,0,0,0) \ + XCHAL_SA_REG(s,0,0,2,0, f5, 4, 4, 4,0x0035, f,5 , 32,0,0,0) \ + XCHAL_SA_REG(s,0,0,2,0, f6, 4, 4, 4,0x0036, f,6 , 32,0,0,0) \ + XCHAL_SA_REG(s,0,0,2,0, f7, 4, 4, 4,0x0037, f,7 , 32,0,0,0) \ + XCHAL_SA_REG(s,0,0,2,0, f8, 4, 4, 4,0x0038, f,8 , 32,0,0,0) \ + XCHAL_SA_REG(s,0,0,2,0, f9, 4, 4, 4,0x0039, f,9 , 32,0,0,0) \ + XCHAL_SA_REG(s,0,0,2,0, f10, 4, 4, 4,0x003A, f,10 , 32,0,0,0) \ + XCHAL_SA_REG(s,0,0,2,0, f11, 4, 4, 4,0x003B, f,11 , 32,0,0,0) \ + XCHAL_SA_REG(s,0,0,2,0, f12, 4, 4, 4,0x003C, f,12 , 32,0,0,0) \ + XCHAL_SA_REG(s,0,0,2,0, f13, 4, 4, 4,0x003D, f,13 , 32,0,0,0) \ + XCHAL_SA_REG(s,0,0,2,0, f14, 4, 4, 4,0x003E, f,14 , 32,0,0,0) \ + XCHAL_SA_REG(s,0,0,2,0, f15, 4, 4, 4,0x003F, f,15 , 32,0,0,0) + +#define XCHAL_CP1_SA_NUM 0 +#define XCHAL_CP1_SA_LIST(s) /* empty */ + +#define XCHAL_CP2_SA_NUM 0 +#define XCHAL_CP2_SA_LIST(s) /* empty */ + +#define XCHAL_CP3_SA_NUM 0 +#define XCHAL_CP3_SA_LIST(s) /* empty */ + +#define XCHAL_CP4_SA_NUM 0 +#define XCHAL_CP4_SA_LIST(s) /* empty */ + +#define XCHAL_CP5_SA_NUM 0 +#define XCHAL_CP5_SA_LIST(s) /* empty */ + +#define XCHAL_CP6_SA_NUM 0 +#define XCHAL_CP6_SA_LIST(s) /* empty */ + +#define XCHAL_CP7_SA_NUM 0 +#define XCHAL_CP7_SA_LIST(s) /* empty */ + +/* Byte length of instruction from its first nibble (op0 field), per FLIX. */ +#define XCHAL_OP0_FORMAT_LENGTHS 3,3,3,3,3,3,3,3,2,2,2,2,2,2,3,3 +/* Byte length of instruction from its first byte, per FLIX. */ +#define XCHAL_BYTE0_FORMAT_LENGTHS \ + 3,3,3,3,3,3,3,3,2,2,2,2,2,2,3,3, 3,3,3,3,3,3,3,3,2,2,2,2,2,2,3,3,\ + 3,3,3,3,3,3,3,3,2,2,2,2,2,2,3,3, 3,3,3,3,3,3,3,3,2,2,2,2,2,2,3,3,\ + 3,3,3,3,3,3,3,3,2,2,2,2,2,2,3,3, 3,3,3,3,3,3,3,3,2,2,2,2,2,2,3,3,\ + 3,3,3,3,3,3,3,3,2,2,2,2,2,2,3,3, 3,3,3,3,3,3,3,3,2,2,2,2,2,2,3,3,\ + 3,3,3,3,3,3,3,3,2,2,2,2,2,2,3,3, 3,3,3,3,3,3,3,3,2,2,2,2,2,2,3,3,\ + 3,3,3,3,3,3,3,3,2,2,2,2,2,2,3,3, 3,3,3,3,3,3,3,3,2,2,2,2,2,2,3,3,\ + 3,3,3,3,3,3,3,3,2,2,2,2,2,2,3,3, 3,3,3,3,3,3,3,3,2,2,2,2,2,2,3,3,\ + 3,3,3,3,3,3,3,3,2,2,2,2,2,2,3,3, 3,3,3,3,3,3,3,3,2,2,2,2,2,2,3,3 + +#endif /*_XTENSA_CORE_TIE_H*/ + diff --git a/components/esp32/include/xtensa/core-macros.h b/components/esp32/include/xtensa/core-macros.h new file mode 100755 index 0000000000..663d29478a --- /dev/null +++ b/components/esp32/include/xtensa/core-macros.h @@ -0,0 +1,456 @@ +/* + * xtensa/core-macros.h -- C specific definitions + * that depend on CORE configuration + */ + +/* + * Copyright (c) 2012 Tensilica Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY + * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +#ifndef XTENSA_CACHE_H +#define XTENSA_CACHE_H + +#include + +/* Only define things for C code. */ +#if !defined(_ASMLANGUAGE) && !defined(_NOCLANGUAGE) && !defined(__ASSEMBLER__) + + + +/*************************** CACHE ***************************/ + +/* All the macros are in the lower case now and some of them + * share the name with the existing functions from hal.h. + * Including this header file will define XTHAL_USE_CACHE_MACROS + * which directs hal.h not to use the functions. + * + +/* + * Single-cache-line operations in C-callable inline assembly. + * Essentially macro versions (uppercase) of: + * + * xthal_icache_line_invalidate(void *addr); + * xthal_icache_line_lock(void *addr); + * xthal_icache_line_unlock(void *addr); + * xthal_icache_sync(void); + * + * NOTE: unlike the above functions, the following macros do NOT + * execute the xthal_icache_sync() as part of each line operation. + * This sync must be called explicitly by the caller. This is to + * allow better optimization when operating on more than one line. + * + * xthal_dcache_line_invalidate(void *addr); + * xthal_dcache_line_writeback(void *addr); + * xthal_dcache_line_writeback_inv(void *addr); + * xthal_dcache_line_lock(void *addr); + * xthal_dcache_line_unlock(void *addr); + * xthal_dcache_sync(void); + * xthal_dcache_line_prefetch_for_write(void *addr); + * xthal_dcache_line_prefetch_for_read(void *addr); + * + * All are made memory-barriers, given that's how they're typically used + * (ops operate on a whole line, so clobbers all memory not just *addr). + * + * NOTE: All the block block cache ops and line prefetches are implemented + * using intrinsics so they are better optimized regarding memory barriers etc. + * + * All block downgrade functions exist in two forms: with and without + * the 'max' parameter: This parameter allows compiler to optimize + * the functions whenever the parameter is smaller than the cache size. + * + * xthal_dcache_block_invalidate(void *addr, unsigned size); + * xthal_dcache_block_writeback(void *addr, unsigned size); + * xthal_dcache_block_writeback_inv(void *addr, unsigned size); + * xthal_dcache_block_invalidate_max(void *addr, unsigned size, unsigned max); + * xthal_dcache_block_writeback_max(void *addr, unsigned size, unsigned max); + * xthal_dcache_block_writeback_inv_max(void *addr, unsigned size, unsigned max); + * + * xthal_dcache_block_prefetch_for_read(void *addr, unsigned size); + * xthal_dcache_block_prefetch_for_write(void *addr, unsigned size); + * xthal_dcache_block_prefetch_modify(void *addr, unsigned size); + * xthal_dcache_block_prefetch_read_write(void *addr, unsigned size); + * xthal_dcache_block_prefetch_for_read_grp(void *addr, unsigned size); + * xthal_dcache_block_prefetch_for_write_grp(void *addr, unsigned size); + * xthal_dcache_block_prefetch_modify_grp(void *addr, unsigned size); + * xthal_dcache_block_prefetch_read_write_grp(void *addr, unsigned size) + * + * xthal_dcache_block_wait(); + * xthal_dcache_block_required_wait(); + * xthal_dcache_block_abort(); + * xthal_dcache_block_prefetch_end(); + * xthal_dcache_block_newgrp(); + */ + +/*** INSTRUCTION CACHE ***/ + +#define XTHAL_USE_CACHE_MACROS + +#if XCHAL_ICACHE_SIZE > 0 +# define xthal_icache_line_invalidate(addr) do { void *__a = (void*)(addr); \ + __asm__ __volatile__("ihi %0, 0" :: "a"(__a) : "memory"); \ + } while(0) +#else +# define xthal_icache_line_invalidate(addr) do {/*nothing*/} while(0) +#endif + +#if XCHAL_ICACHE_SIZE > 0 && XCHAL_ICACHE_LINE_LOCKABLE +# define xthal_icache_line_lock(addr) do { void *__a = (void*)(addr); \ + __asm__ __volatile__("ipfl %0, 0" :: "a"(__a) : "memory"); \ + } while(0) +# define xthal_icache_line_unlock(addr) do { void *__a = (void*)(addr); \ + __asm__ __volatile__("ihu %0, 0" :: "a"(__a) : "memory"); \ + } while(0) +#else +# define xthal_icache_line_lock(addr) do {/*nothing*/} while(0) +# define xthal_icache_line_unlock(addr) do {/*nothing*/} while(0) +#endif + +/* + * Even if a config doesn't have caches, an isync is still needed + * when instructions in any memory are modified, whether by a loader + * or self-modifying code. Therefore, this macro always produces + * an isync, whether or not an icache is present. + */ +#define xthal_icache_sync() \ + __asm__ __volatile__("isync":::"memory") + + +/*** DATA CACHE ***/ + +#if XCHAL_DCACHE_SIZE > 0 + +# include + +# define xthal_dcache_line_invalidate(addr) do { void *__a = (void*)(addr); \ + __asm__ __volatile__("dhi %0, 0" :: "a"(__a) : "memory"); \ + } while(0) +# define xthal_dcache_line_writeback(addr) do { void *__a = (void*)(addr); \ + __asm__ __volatile__("dhwb %0, 0" :: "a"(__a) : "memory"); \ + } while(0) +# define xthal_dcache_line_writeback_inv(addr) do { void *__a = (void*)(addr); \ + __asm__ __volatile__("dhwbi %0, 0" :: "a"(__a) : "memory"); \ + } while(0) +# define xthal_dcache_sync() \ + __asm__ __volatile__("" /*"dsync"?*/:::"memory") +# define xthal_dcache_line_prefetch_for_read(addr) do { \ + XT_DPFR((const int*)addr, 0); \ + } while(0) +#else +# define xthal_dcache_line_invalidate(addr) do {/*nothing*/} while(0) +# define xthal_dcache_line_writeback(addr) do {/*nothing*/} while(0) +# define xthal_dcache_line_writeback_inv(addr) do {/*nothing*/} while(0) +# define xthal_dcache_sync() __asm__ __volatile__("":::"memory") +# define xthal_dcache_line_prefetch_for_read(addr) do {/*nothing*/} while(0) +#endif + +#if XCHAL_DCACHE_SIZE > 0 && XCHAL_DCACHE_LINE_LOCKABLE +# define xthal_dcache_line_lock(addr) do { void *__a = (void*)(addr); \ + __asm__ __volatile__("dpfl %0, 0" :: "a"(__a) : "memory"); \ + } while(0) +# define xthal_dcache_line_unlock(addr) do { void *__a = (void*)(addr); \ + __asm__ __volatile__("dhu %0, 0" :: "a"(__a) : "memory"); \ + } while(0) +#else +# define xthal_dcache_line_lock(addr) do {/*nothing*/} while(0) +# define xthal_dcache_line_unlock(addr) do {/*nothing*/} while(0) +#endif + +#if XCHAL_DCACHE_SIZE > 0 && XCHAL_DCACHE_IS_WRITEBACK + +# define xthal_dcache_line_prefetch_for_write(addr) do { \ + XT_DPFW((const int*)addr, 0); \ + } while(0) +#else +# define xthal_dcache_line_prefetch_for_write(addr) do {/*nothing*/} while(0) +#endif + + +/***** Block Operations *****/ + +#if XCHAL_DCACHE_SIZE > 0 && XCHAL_HAVE_CACHE_BLOCKOPS + +/* upgrades */ + +# define _XTHAL_DCACHE_BLOCK_UPGRADE(addr, size, type) \ + { \ + type((const int*)addr, size); \ + } + +/*downgrades */ + +# define _XTHAL_DCACHE_BLOCK_DOWNGRADE(addr, size, type) \ + unsigned _s = size; \ + unsigned _a = addr; \ + do { \ + unsigned __s = (_s > XCHAL_DCACHE_SIZE) ? \ + XCHAL_DCACHE_SIZE : _s; \ + type((const int*)_a, __s); \ + _s -= __s; \ + _a += __s; \ + } while(_s > 0); + +# define _XTHAL_DCACHE_BLOCK_DOWNGRADE_MAX(addr, size, type, max) \ + if (max <= XCHAL_DCACHE_SIZE) { \ + unsigned _s = size; \ + unsigned _a = addr; \ + type((const int*)_a, _s); \ + } \ + else { \ + _XTHAL_DCACHE_BLOCK_DOWNGRADE(addr, size, type); \ + } + +# define xthal_dcache_block_invalidate(addr, size) do { \ + _XTHAL_DCACHE_BLOCK_DOWNGRADE(addr, size, XT_DHI_B); \ + } while(0) +# define xthal_dcache_block_writeback(addr, size) do { \ + _XTHAL_DCACHE_BLOCK_DOWNGRADE(addr, size, XT_DHWB_B); \ + } while(0) +# define xthal_dcache_block_writeback_inv(addr, size) do { \ + _XTHAL_DCACHE_BLOCK_DOWNGRADE(addr, size, XT_DHWBI_B); \ + } while(0) + +# define xthal_dcache_block_invalidate_max(addr, size, max) do { \ + _XTHAL_DCACHE_BLOCK_DOWNGRADE_MAX(addr, size, XT_DHI_B, max); \ + } while(0) +# define xthal_dcache_block_writeback_max(addr, size, max) do { \ + _XTHAL_DCACHE_BLOCK_DOWNGRADE_MAX(addr, size, XT_DHWB_B, max); \ + } while(0) +# define xthal_dcache_block_writeback_inv_max(addr, size, max) do { \ + _XTHAL_DCACHE_BLOCK_DOWNGRADE_MAX(addr, size, XT_DHWBI_B, max); \ + } while(0) + +/* upgrades that are performed even with write-thru caches */ + +# define xthal_dcache_block_prefetch_read_write(addr, size) do { \ + _XTHAL_DCACHE_BLOCK_UPGRADE(addr, size, XT_DPFW_B); \ + } while(0) +# define xthal_dcache_block_prefetch_read_write_grp(addr, size) do { \ + _XTHAL_DCACHE_BLOCK_UPGRADE(addr, size, XT_DPFW_BF); \ + } while(0) +# define xthal_dcache_block_prefetch_for_read(addr, size) do { \ + _XTHAL_DCACHE_BLOCK_UPGRADE(addr, size, XT_DPFR_B); \ + } while(0) +# define xthal_dcache_block_prefetch_for_read_grp(addr, size) do { \ + _XTHAL_DCACHE_BLOCK_UPGRADE(addr, size, XT_DPFR_BF); \ + } while(0) + +/* abort all or end optional block cache operations */ +# define xthal_dcache_block_abort() do { \ + XT_PFEND_A(); \ + } while(0) +# define xthal_dcache_block_end() do { \ + XT_PFEND_O(); \ + } while(0) + +/* wait for all/required block cache operations to finish */ +# define xthal_dcache_block_wait() do { \ + XT_PFWAIT_A(); \ + } while(0) +# define xthal_dcache_block_required_wait() do { \ + XT_PFWAIT_R(); \ + } while(0) +/* Start a new group */ +# define xthal_dcache_block_newgrp() do { \ + XT_PFNXT_F(); \ + } while(0) +#else +# define xthal_dcache_block_invalidate(addr, size) do {/*nothing*/} while(0) +# define xthal_dcache_block_writeback(addr, size) do {/*nothing*/} while(0) +# define xthal_dcache_block_writeback_inv(addr, size) do {/*nothing*/} while(0) +# define xthal_dcache_block_invalidate_max(addr, size, max) do {/*nothing*/} while(0) +# define xthal_dcache_block_writeback_max(addr, size, max) do {/*nothing*/} while(0) +# define xthal_dcache_block_writeback_inv_max(addr, size, max) do {/*nothing*/} while(0) +# define xthal_dcache_block_prefetch_read_write(addr, size) do {/*nothing*/} while(0) +# define xthal_dcache_block_prefetch_read_write_grp(addr, size) do {/*nothing*/} while(0) +# define xthal_dcache_block_prefetch_for_read(addr, size) do {/*nothing*/} while(0) +# define xthal_dcache_block_prefetch_for_read_grp(addr, size) do {/*nothing*/} while(0) +# define xthal_dcache_block_end() do {/*nothing*/} while(0) +# define xthal_dcache_block_abort() do {/*nothing*/} while(0) +# define xthal_dcache_block_wait() do {/*nothing*/} while(0) +# define xthal_dcache_block_required_wait() do {/*nothing*/} while(0) +# define xthal_dcache_block_newgrp() do {/*nothing*/} while(0) +#endif + +#if XCHAL_DCACHE_SIZE > 0 && XCHAL_HAVE_CACHE_BLOCKOPS && XCHAL_DCACHE_IS_WRITEBACK + +# define xthal_dcache_block_prefetch_for_write(addr, size) do { \ + _XTHAL_DCACHE_BLOCK_UPGRADE(addr, size, XT_DPFW_B); \ + } while(0) +# define xthal_dcache_block_prefetch_modify(addr, size) do { \ + _XTHAL_DCACHE_BLOCK_UPGRADE(addr, size, XT_DPFM_B); \ + } while(0) +# define xthal_dcache_block_prefetch_for_write_grp(addr, size) do { \ + _XTHAL_DCACHE_BLOCK_UPGRADE(addr, size, XT_DPFW_BF); \ + } while(0) +# define xthal_dcache_block_prefetch_modify_grp(addr, size) do { \ + _XTHAL_DCACHE_BLOCK_UPGRADE(addr, size, XT_DPFM_BF); \ + } while(0) +#else +# define xthal_dcache_block_prefetch_for_write(addr, size) do {/*nothing*/} while(0) +# define xthal_dcache_block_prefetch_modify(addr, size) do {/*nothing*/} while(0) +# define xthal_dcache_block_prefetch_for_write_grp(addr, size) do {/*nothing*/} while(0) +# define xthal_dcache_block_prefetch_modify_grp(addr, size) do {/*nothing*/} while(0) +#endif + +/*************************** INTERRUPTS ***************************/ + +/* + * Macro versions of: + * unsigned xthal_get_intenable( void ); + * void xthal_set_intenable( unsigned ); + * unsigned xthal_get_interrupt( void ); + * void xthal_set_intset( unsigned ); + * void xthal_set_intclear( unsigned ); + * unsigned xthal_get_ccount(void); + * void xthal_set_ccompare(int, unsigned); + * unsigned xthal_get_ccompare(int); + * + * NOTE: for {set,get}_ccompare, the first argument MUST be a decimal constant. + */ + +#if XCHAL_HAVE_INTERRUPTS +# define XTHAL_GET_INTENABLE() ({ int __intenable; \ + __asm__("rsr.intenable %0" : "=a"(__intenable)); \ + __intenable; }) +# define XTHAL_SET_INTENABLE(v) do { int __intenable = (int)(v); \ + __asm__ __volatile__("wsr.intenable %0" :: "a"(__intenable):"memory"); \ + } while(0) +# define XTHAL_GET_INTERRUPT() ({ int __interrupt; \ + __asm__("rsr.interrupt %0" : "=a"(__interrupt)); \ + __interrupt; }) +# define XTHAL_SET_INTSET(v) do { int __interrupt = (int)(v); \ + __asm__ __volatile__("wsr.intset %0" :: "a"(__interrupt):"memory"); \ + } while(0) +# define XTHAL_SET_INTCLEAR(v) do { int __interrupt = (int)(v); \ + __asm__ __volatile__("wsr.intclear %0" :: "a"(__interrupt):"memory"); \ + } while(0) +# define XTHAL_GET_CCOUNT() ({ int __ccount; \ + __asm__("rsr.ccount %0" : "=a"(__ccount)); \ + __ccount; }) +# define XTHAL_SET_CCOUNT(v) do { int __ccount = (int)(v); \ + __asm__ __volatile__("wsr.ccount %0" :: "a"(__ccount):"memory"); \ + } while(0) +# define _XTHAL_GET_CCOMPARE(n) ({ int __ccompare; \ + __asm__("rsr.ccompare" #n " %0" : "=a"(__ccompare)); \ + __ccompare; }) +# define XTHAL_GET_CCOMPARE(n) _XTHAL_GET_CCOMPARE(n) +# define _XTHAL_SET_CCOMPARE(n,v) do { int __ccompare = (int)(v); \ + __asm__ __volatile__("wsr.ccompare" #n " %0 ; esync" :: "a"(__ccompare):"memory"); \ + } while(0) +# define XTHAL_SET_CCOMPARE(n,v) _XTHAL_SET_CCOMPARE(n,v) +#else +# define XTHAL_GET_INTENABLE() 0 +# define XTHAL_SET_INTENABLE(v) do {/*nothing*/} while(0) +# define XTHAL_GET_INTERRUPT() 0 +# define XTHAL_SET_INTSET(v) do {/*nothing*/} while(0) +# define XTHAL_SET_INTCLEAR(v) do {/*nothing*/} while(0) +# define XTHAL_GET_CCOUNT() 0 +# define XTHAL_SET_CCOUNT(v) do {/*nothing*/} while(0) +# define XTHAL_GET_CCOMPARE(n) 0 +# define XTHAL_SET_CCOMPARE(n,v) do {/*nothing*/} while(0) +#endif + + +/*************************** MISC ***************************/ + +/* + * Macro or inline versions of: + * void xthal_clear_regcached_code( void ); + * unsigned xthal_get_prid( void ); + * unsigned xthal_compare_and_set( int *addr, int testval, int setval ); + */ + +#if XCHAL_HAVE_LOOPS +# define XTHAL_CLEAR_REGCACHED_CODE() \ + __asm__ __volatile__("wsr.lcount %0" :: "a"(0) : "memory") +#else +# define XTHAL_CLEAR_REGCACHED_CODE() do {/*nothing*/} while(0) +#endif + +#if XCHAL_HAVE_PRID +# define XTHAL_GET_PRID() ({ int __prid; \ + __asm__("rsr.prid %0" : "=a"(__prid)); \ + __prid; }) +#else +# define XTHAL_GET_PRID() 0 +#endif + + +static inline unsigned XTHAL_COMPARE_AND_SET( int *addr, int testval, int setval ) +{ + int result; + +#if XCHAL_HAVE_S32C1I && XCHAL_HW_MIN_VERSION_MAJOR >= 2200 + __asm__ __volatile__ ( + " wsr.scompare1 %2 \n" + " s32c1i %0, %3, 0 \n" + : "=a"(result) : "0" (setval), "a" (testval), "a" (addr) + : "memory"); +#elif XCHAL_HAVE_INTERRUPTS + int tmp; + __asm__ __volatile__ ( + " rsil %4, 15 \n" // %4 == saved ps + " l32i %0, %3, 0 \n" // %0 == value to test, return val + " bne %2, %0, 9f \n" // test + " s32i %1, %3, 0 \n" // write the new value + "9: wsr.ps %4 ; rsync \n" // restore the PS + : "=a"(result) + : "0" (setval), "a" (testval), "a" (addr), "a" (tmp) + : "memory"); +#else + __asm__ __volatile__ ( + " l32i %0, %3, 0 \n" // %0 == value to test, return val + " bne %2, %0, 9f \n" // test + " s32i %1, %3, 0 \n" // write the new value + "9: \n" + : "=a"(result) : "0" (setval), "a" (testval), "a" (addr) + : "memory"); +#endif + return result; +} + +#if XCHAL_HAVE_EXTERN_REGS + +static inline unsigned XTHAL_RER (unsigned int reg) +{ + unsigned result; + + __asm__ __volatile__ ( + " rer %0, %1" + : "=a" (result) : "a" (reg) : "memory"); + + return result; +} + +static inline void XTHAL_WER (unsigned reg, unsigned value) +{ + __asm__ __volatile__ ( + " wer %0, %1" + : : "a" (value), "a" (reg) : "memory"); +} + +#endif /* XCHAL_HAVE_EXTERN_REGS */ + +#endif /* C code */ + +#endif /*XTENSA_CACHE_H*/ + diff --git a/components/esp32/include/xtensa/coreasm.h b/components/esp32/include/xtensa/coreasm.h new file mode 100755 index 0000000000..e41e04d1bd --- /dev/null +++ b/components/esp32/include/xtensa/coreasm.h @@ -0,0 +1,939 @@ +/* + * xtensa/coreasm.h -- assembler-specific definitions that depend on CORE configuration + * + * Source for configuration-independent binaries (which link in a + * configuration-specific HAL library) must NEVER include this file. + * It is perfectly normal, however, for the HAL itself to include this file. + * + * This file must NOT include xtensa/config/system.h. Any assembler + * header file that depends on system information should likely go + * in a new systemasm.h (or sysasm.h) header file. + * + * NOTE: macro beqi32 is NOT configuration-dependent, and is placed + * here until we have a proper configuration-independent header file. + */ + +/* $Id: //depot/rel/Eaglenest/Xtensa/OS/include/xtensa/coreasm.h#3 $ */ + +/* + * Copyright (c) 2000-2014 Tensilica Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY + * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +#ifndef XTENSA_COREASM_H +#define XTENSA_COREASM_H + +/* + * Tell header files this is assembly source, so they can avoid non-assembler + * definitions (eg. C types etc): + */ +#ifndef _ASMLANGUAGE /* conditionalize to avoid cpp warnings (3rd parties might use same macro) */ +#define _ASMLANGUAGE +#endif + +#include +#include +#include + +/* + * Assembly-language specific definitions (assembly macros, etc.). + */ + +/*---------------------------------------------------------------------- + * find_ms_setbit + * + * This macro finds the most significant bit that is set in + * and return its index + in , or - 1 if is zero. + * The index counts starting at zero for the lsbit, so the return + * value ranges from -1 (no bit set) to +31 (msbit set). + * + * Parameters: + * destination address register (any register) + * source address register + * temporary address register (must be different than ) + * constant value added to result (usually 0 or 1) + * On entry: + * = undefined if different than + * = value whose most significant set bit is to be found + * = undefined + * no other registers are used by this macro. + * On exit: + * = + index of msbit set in original , + * = - 1 if original was zero. + * clobbered (if not ) + * clobbered (if not ) + * Example: + * find_ms_setbit a0, a4, a0, 0 -- return in a0 index of msbit set in a4 + */ + + .macro find_ms_setbit ad, as, at, base +#if XCHAL_HAVE_NSA + movi \at, 31+\base + nsau \as, \as // get index of \as, numbered from msbit (32 if absent) + sub \ad, \at, \as // get numbering from lsbit (0..31, -1 if absent) +#else /* XCHAL_HAVE_NSA */ + movi \at, \base // start with result of 0 (point to lsbit of 32) + + beqz \as, 2f // special case for zero argument: return -1 + bltui \as, 0x10000, 1f // is it one of the 16 lsbits? (if so, check lower 16 bits) + addi \at, \at, 16 // no, increment result to upper 16 bits (of 32) + //srli \as, \as, 16 // check upper half (shift right 16 bits) + extui \as, \as, 16, 16 // check upper half (shift right 16 bits) +1: bltui \as, 0x100, 1f // is it one of the 8 lsbits? (if so, check lower 8 bits) + addi \at, \at, 8 // no, increment result to upper 8 bits (of 16) + srli \as, \as, 8 // shift right to check upper 8 bits +1: bltui \as, 0x10, 1f // is it one of the 4 lsbits? (if so, check lower 4 bits) + addi \at, \at, 4 // no, increment result to upper 4 bits (of 8) + srli \as, \as, 4 // shift right 4 bits to check upper half +1: bltui \as, 0x4, 1f // is it one of the 2 lsbits? (if so, check lower 2 bits) + addi \at, \at, 2 // no, increment result to upper 2 bits (of 4) + srli \as, \as, 2 // shift right 2 bits to check upper half +1: bltui \as, 0x2, 1f // is it the lsbit? + addi \at, \at, 2 // no, increment result to upper bit (of 2) +2: addi \at, \at, -1 // (from just above: add 1; from beqz: return -1) + //srli \as, \as, 1 +1: // done! \at contains index of msbit set (or -1 if none set) + .if 0x\ad - 0x\at // destination different than \at ? (works because regs are a0-a15) + mov \ad, \at // then move result to \ad + .endif +#endif /* XCHAL_HAVE_NSA */ + .endm // find_ms_setbit + +/*---------------------------------------------------------------------- + * find_ls_setbit + * + * This macro finds the least significant bit that is set in , + * and return its index in . + * Usage is the same as for the find_ms_setbit macro. + * Example: + * find_ls_setbit a0, a4, a0, 0 -- return in a0 index of lsbit set in a4 + */ + + .macro find_ls_setbit ad, as, at, base + neg \at, \as // keep only the least-significant bit that is set... + and \as, \at, \as // ... in \as + find_ms_setbit \ad, \as, \at, \base + .endm // find_ls_setbit + +/*---------------------------------------------------------------------- + * find_ls_one + * + * Same as find_ls_setbit with base zero. + * Source (as) and destination (ad) registers must be different. + * Provided for backward compatibility. + */ + + .macro find_ls_one ad, as + find_ls_setbit \ad, \as, \ad, 0 + .endm // find_ls_one + +/*---------------------------------------------------------------------- + * floop, floopnez, floopgtz, floopend + * + * These macros are used for fast inner loops that + * work whether or not the Loops options is configured. + * If the Loops option is configured, they simply use + * the zero-overhead LOOP instructions; otherwise + * they use explicit decrement and branch instructions. + * + * They are used in pairs, with floop, floopnez or floopgtz + * at the beginning of the loop, and floopend at the end. + * + * Each pair of loop macro calls must be given the loop count + * address register and a unique label for that loop. + * + * Example: + * + * movi a3, 16 // loop 16 times + * floop a3, myloop1 + * : + * bnez a7, end1 // exit loop if a7 != 0 + * : + * floopend a3, myloop1 + * end1: + * + * Like the LOOP instructions, these macros cannot be + * nested, must include at least one instruction, + * cannot call functions inside the loop, etc. + * The loop can be exited by jumping to the instruction + * following floopend (or elsewhere outside the loop), + * or continued by jumping to a NOP instruction placed + * immediately before floopend. + * + * Unlike LOOP instructions, the register passed to floop* + * cannot be used inside the loop, because it is used as + * the loop counter if the Loops option is not configured. + * And its value is undefined after exiting the loop. + * And because the loop counter register is active inside + * the loop, you can't easily use this construct to loop + * across a register file using ROTW as you might with LOOP + * instructions, unless you copy the loop register along. + */ + + /* Named label version of the macros: */ + + .macro floop ar, endlabel + floop_ \ar, .Lfloopstart_\endlabel, .Lfloopend_\endlabel + .endm + + .macro floopnez ar, endlabel + floopnez_ \ar, .Lfloopstart_\endlabel, .Lfloopend_\endlabel + .endm + + .macro floopgtz ar, endlabel + floopgtz_ \ar, .Lfloopstart_\endlabel, .Lfloopend_\endlabel + .endm + + .macro floopend ar, endlabel + floopend_ \ar, .Lfloopstart_\endlabel, .Lfloopend_\endlabel + .endm + + /* Numbered local label version of the macros: */ +#if 0 /*UNTESTED*/ + .macro floop89 ar + floop_ \ar, 8, 9f + .endm + + .macro floopnez89 ar + floopnez_ \ar, 8, 9f + .endm + + .macro floopgtz89 ar + floopgtz_ \ar, 8, 9f + .endm + + .macro floopend89 ar + floopend_ \ar, 8b, 9 + .endm +#endif /*0*/ + + /* Underlying version of the macros: */ + + .macro floop_ ar, startlabel, endlabelref + .ifdef _infloop_ + .if _infloop_ + .err // Error: floop cannot be nested + .endif + .endif + .set _infloop_, 1 +#if XCHAL_HAVE_LOOPS + loop \ar, \endlabelref +#else /* XCHAL_HAVE_LOOPS */ +\startlabel: + addi \ar, \ar, -1 +#endif /* XCHAL_HAVE_LOOPS */ + .endm // floop_ + + .macro floopnez_ ar, startlabel, endlabelref + .ifdef _infloop_ + .if _infloop_ + .err // Error: floopnez cannot be nested + .endif + .endif + .set _infloop_, 1 +#if XCHAL_HAVE_LOOPS + loopnez \ar, \endlabelref +#else /* XCHAL_HAVE_LOOPS */ + beqz \ar, \endlabelref +\startlabel: + addi \ar, \ar, -1 +#endif /* XCHAL_HAVE_LOOPS */ + .endm // floopnez_ + + .macro floopgtz_ ar, startlabel, endlabelref + .ifdef _infloop_ + .if _infloop_ + .err // Error: floopgtz cannot be nested + .endif + .endif + .set _infloop_, 1 +#if XCHAL_HAVE_LOOPS + loopgtz \ar, \endlabelref +#else /* XCHAL_HAVE_LOOPS */ + bltz \ar, \endlabelref + beqz \ar, \endlabelref +\startlabel: + addi \ar, \ar, -1 +#endif /* XCHAL_HAVE_LOOPS */ + .endm // floopgtz_ + + + .macro floopend_ ar, startlabelref, endlabel + .ifndef _infloop_ + .err // Error: floopend without matching floopXXX + .endif + .ifeq _infloop_ + .err // Error: floopend without matching floopXXX + .endif + .set _infloop_, 0 +#if ! XCHAL_HAVE_LOOPS + bnez \ar, \startlabelref +#endif /* XCHAL_HAVE_LOOPS */ +\endlabel: + .endm // floopend_ + +/*---------------------------------------------------------------------- + * crsil -- conditional RSIL (read/set interrupt level) + * + * Executes the RSIL instruction if it exists, else just reads PS. + * The RSIL instruction does not exist in the new exception architecture + * if the interrupt option is not selected. + */ + + .macro crsil ar, newlevel +#if XCHAL_HAVE_OLD_EXC_ARCH || XCHAL_HAVE_INTERRUPTS + rsil \ar, \newlevel +#else + rsr \ar, PS +#endif + .endm // crsil + +/*---------------------------------------------------------------------- + * safe_movi_a0 -- move constant into a0 when L32R is not safe + * + * This macro is typically used by interrupt/exception handlers. + * Loads a 32-bit constant in a0, without using any other register, + * and without corrupting the LITBASE register, even when the + * value of the LITBASE register is unknown (eg. when application + * code and interrupt/exception handling code are built independently, + * and thus with independent values of the LITBASE register; + * debug monitors are one example of this). + * + * Worst-case size of resulting code: 17 bytes. + */ + + .macro safe_movi_a0 constant +#if XCHAL_HAVE_ABSOLUTE_LITERALS + /* Contort a PC-relative literal load even though we may be in litbase-relative mode: */ + j 1f + .begin no-transform // ensure what follows is assembled exactly as-is + .align 4 // ensure constant and call0 target ... + .byte 0 // ... are 4-byte aligned (call0 instruction is 3 bytes long) +1: call0 2f // read PC (that follows call0) in a0 + .long \constant // 32-bit constant to load into a0 +2: + .end no-transform + l32i a0, a0, 0 // load constant +#else + movi a0, \constant // no LITBASE, can assume PC-relative L32R +#endif + .endm + + + + +/*---------------------------------------------------------------------- + * window_spill{4,8,12} + * + * These macros spill callers' register windows to the stack. + * They work for both privileged and non-privileged tasks. + * Must be called from a windowed ABI context, eg. within + * a windowed ABI function (ie. valid stack frame, window + * exceptions enabled, not in exception mode, etc). + * + * This macro requires a single invocation of the window_spill_common + * macro in the same assembly unit and section. + * + * Note that using window_spill{4,8,12} macros is more efficient + * than calling a function implemented using window_spill_function, + * because the latter needs extra code to figure out the size of + * the call to the spilling function. + * + * Example usage: + * + * .text + * .align 4 + * .global some_function + * .type some_function,@function + * some_function: + * entry a1, 16 + * : + * : + * + * window_spill4 // Spill windows of some_function's callers; preserves a0..a3 only; + * // to use window_spill{8,12} in this example function we'd have + * // to increase space allocated by the entry instruction, because + * // 16 bytes only allows call4; 32 or 48 bytes (+locals) are needed + * // for call8/window_spill8 or call12/window_spill12 respectively. + * + * : + * + * retw + * + * window_spill_common // instantiates code used by window_spill4 + * + * + * On entry: + * none (if window_spill4) + * stack frame has enough space allocated for call8 (if window_spill8) + * stack frame has enough space allocated for call12 (if window_spill12) + * On exit: + * a4..a15 clobbered (if window_spill4) + * a8..a15 clobbered (if window_spill8) + * a12..a15 clobbered (if window_spill12) + * no caller windows are in live registers + */ + + .macro window_spill4 +#if XCHAL_HAVE_WINDOWED +# if XCHAL_NUM_AREGS == 16 + movi a15, 0 // for 16-register files, no need to call to reach the end +# elif XCHAL_NUM_AREGS == 32 + call4 .L__wdwspill_assist28 // call deep enough to clear out any live callers +# elif XCHAL_NUM_AREGS == 64 + call4 .L__wdwspill_assist60 // call deep enough to clear out any live callers +# endif +#endif + .endm // window_spill4 + + .macro window_spill8 +#if XCHAL_HAVE_WINDOWED +# if XCHAL_NUM_AREGS == 16 + movi a15, 0 // for 16-register files, no need to call to reach the end +# elif XCHAL_NUM_AREGS == 32 + call8 .L__wdwspill_assist24 // call deep enough to clear out any live callers +# elif XCHAL_NUM_AREGS == 64 + call8 .L__wdwspill_assist56 // call deep enough to clear out any live callers +# endif +#endif + .endm // window_spill8 + + .macro window_spill12 +#if XCHAL_HAVE_WINDOWED +# if XCHAL_NUM_AREGS == 16 + movi a15, 0 // for 16-register files, no need to call to reach the end +# elif XCHAL_NUM_AREGS == 32 + call12 .L__wdwspill_assist20 // call deep enough to clear out any live callers +# elif XCHAL_NUM_AREGS == 64 + call12 .L__wdwspill_assist52 // call deep enough to clear out any live callers +# endif +#endif + .endm // window_spill12 + + +/*---------------------------------------------------------------------- + * window_spill_function + * + * This macro outputs a function that will spill its caller's callers' + * register windows to the stack. Eg. it could be used to implement + * a version of xthal_window_spill() that works in non-privileged tasks. + * This works for both privileged and non-privileged tasks. + * + * Typical usage: + * + * .text + * .align 4 + * .global my_spill_function + * .type my_spill_function,@function + * my_spill_function: + * window_spill_function + * + * On entry to resulting function: + * none + * On exit from resulting function: + * none (no caller windows are in live registers) + */ + + .macro window_spill_function +#if XCHAL_HAVE_WINDOWED +# if XCHAL_NUM_AREGS == 32 + entry sp, 48 + bbci.l a0, 31, 1f // branch if called with call4 + bbsi.l a0, 30, 2f // branch if called with call12 + call8 .L__wdwspill_assist16 // called with call8, only need another 8 + retw +1: call12 .L__wdwspill_assist16 // called with call4, only need another 12 + retw +2: call4 .L__wdwspill_assist16 // called with call12, only need another 4 + retw +# elif XCHAL_NUM_AREGS == 64 + entry sp, 48 + bbci.l a0, 31, 1f // branch if called with call4 + bbsi.l a0, 30, 2f // branch if called with call12 + call4 .L__wdwspill_assist52 // called with call8, only need a call4 + retw +1: call8 .L__wdwspill_assist52 // called with call4, only need a call8 + retw +2: call12 .L__wdwspill_assist40 // called with call12, can skip a call12 + retw +# elif XCHAL_NUM_AREGS == 16 + entry sp, 16 + bbci.l a0, 31, 1f // branch if called with call4 + bbsi.l a0, 30, 2f // branch if called with call12 + movi a7, 0 // called with call8 + retw +1: movi a11, 0 // called with call4 +2: retw // if called with call12, everything already spilled + +// movi a15, 0 // trick to spill all but the direct caller +// j 1f +// // The entry instruction is magical in the assembler (gets auto-aligned) +// // so we have to jump to it to avoid falling through the padding. +// // We need entry/retw to know where to return. +//1: entry sp, 16 +// retw +# else +# error "unrecognized address register file size" +# endif + +#endif /* XCHAL_HAVE_WINDOWED */ + window_spill_common + .endm // window_spill_function + +/*---------------------------------------------------------------------- + * window_spill_common + * + * Common code used by any number of invocations of the window_spill## + * and window_spill_function macros. + * + * Must be instantiated exactly once within a given assembly unit, + * within call/j range of and same section as window_spill## + * macro invocations for that assembly unit. + * (Is automatically instantiated by the window_spill_function macro.) + */ + + .macro window_spill_common +#if XCHAL_HAVE_WINDOWED && (XCHAL_NUM_AREGS == 32 || XCHAL_NUM_AREGS == 64) + .ifndef .L__wdwspill_defined +# if XCHAL_NUM_AREGS >= 64 +.L__wdwspill_assist60: + entry sp, 32 + call8 .L__wdwspill_assist52 + retw +.L__wdwspill_assist56: + entry sp, 16 + call4 .L__wdwspill_assist52 + retw +.L__wdwspill_assist52: + entry sp, 48 + call12 .L__wdwspill_assist40 + retw +.L__wdwspill_assist40: + entry sp, 48 + call12 .L__wdwspill_assist28 + retw +# endif +.L__wdwspill_assist28: + entry sp, 48 + call12 .L__wdwspill_assist16 + retw +.L__wdwspill_assist24: + entry sp, 32 + call8 .L__wdwspill_assist16 + retw +.L__wdwspill_assist20: + entry sp, 16 + call4 .L__wdwspill_assist16 + retw +.L__wdwspill_assist16: + entry sp, 16 + movi a15, 0 + retw + .set .L__wdwspill_defined, 1 + .endif +#endif /* XCHAL_HAVE_WINDOWED with 32 or 64 aregs */ + .endm // window_spill_common + +/*---------------------------------------------------------------------- + * beqi32 + * + * macro implements version of beqi for arbitrary 32-bit immediate value + * + * beqi32 ax, ay, imm32, label + * + * Compares value in register ax with imm32 value and jumps to label if + * equal. Clobbers register ay if needed + * + */ + .macro beqi32 ax, ay, imm, label + .ifeq ((\imm-1) & ~7) // 1..8 ? + beqi \ax, \imm, \label + .else + .ifeq (\imm+1) // -1 ? + beqi \ax, \imm, \label + .else + .ifeq (\imm) // 0 ? + beqz \ax, \label + .else + // We could also handle immediates 10,12,16,32,64,128,256 + // but it would be a long macro... + movi \ay, \imm + beq \ax, \ay, \label + .endif + .endif + .endif + .endm // beqi32 + +/*---------------------------------------------------------------------- + * isync_retw_nop + * + * This macro must be invoked immediately after ISYNC if ISYNC + * would otherwise be immediately followed by RETW (or other instruction + * modifying WindowBase or WindowStart), in a context where + * kernel vector mode may be selected, and level-one interrupts + * and window overflows may be enabled, on an XEA1 configuration. + * + * On hardware with erratum "XEA1KWIN" (see for details), + * XEA1 code must have at least one instruction between ISYNC and RETW if + * run in kernel vector mode with interrupts and window overflows enabled. + */ + .macro isync_retw_nop +#if XCHAL_MAYHAVE_ERRATUM_XEA1KWIN + nop +#endif + .endm + +/*---------------------------------------------------------------------- + * isync_erratum453 + * + * This macro must be invoked at certain points in the code, + * such as in exception and interrupt vectors in particular, + * to work around erratum 453. + */ + .macro isync_erratum453 +#if XCHAL_ERRATUM_453 + isync +#endif + .endm + + + +/*---------------------------------------------------------------------- + * abs + * + * implements abs on machines that do not have it configured + */ + +#if !XCHAL_HAVE_ABS + .macro abs arr, ars + .ifc \arr, \ars + //src equal dest is less efficient + bgez \arr, 1f + neg \arr, \arr +1: + .else + neg \arr, \ars + movgez \arr, \ars, \ars + .endif + .endm +#endif /* !XCHAL_HAVE_ABS */ + + +/*---------------------------------------------------------------------- + * addx2 + * + * implements addx2 on machines that do not have it configured + * + */ + +#if !XCHAL_HAVE_ADDX + .macro addx2 arr, ars, art + .ifc \arr, \art + .ifc \arr, \ars + // addx2 a, a, a (not common) + .err + .else + add \arr, \ars, \art + add \arr, \ars, \art + .endif + .else + //addx2 a, b, c + //addx2 a, a, b + //addx2 a, b, b + slli \arr, \ars, 1 + add \arr, \arr, \art + .endif + .endm +#endif /* !XCHAL_HAVE_ADDX */ + +/*---------------------------------------------------------------------- + * addx4 + * + * implements addx4 on machines that do not have it configured + * + */ + +#if !XCHAL_HAVE_ADDX + .macro addx4 arr, ars, art + .ifc \arr, \art + .ifc \arr, \ars + // addx4 a, a, a (not common) + .err + .else + //# addx4 a, b, a + add \arr, \ars, \art + add \arr, \ars, \art + add \arr, \ars, \art + add \arr, \ars, \art + .endif + .else + //addx4 a, b, c + //addx4 a, a, b + //addx4 a, b, b + slli \arr, \ars, 2 + add \arr, \arr, \art + .endif + .endm +#endif /* !XCHAL_HAVE_ADDX */ + +/*---------------------------------------------------------------------- + * addx8 + * + * implements addx8 on machines that do not have it configured + * + */ + +#if !XCHAL_HAVE_ADDX + .macro addx8 arr, ars, art + .ifc \arr, \art + .ifc \arr, \ars + //addx8 a, a, a (not common) + .err + .else + //addx8 a, b, a + add \arr, \ars, \art + add \arr, \ars, \art + add \arr, \ars, \art + add \arr, \ars, \art + add \arr, \ars, \art + add \arr, \ars, \art + add \arr, \ars, \art + add \arr, \ars, \art + .endif + .else + //addx8 a, b, c + //addx8 a, a, b + //addx8 a, b, b + slli \arr, \ars, 3 + add \arr, \arr, \art + .endif + .endm +#endif /* !XCHAL_HAVE_ADDX */ + + +/*---------------------------------------------------------------------- + * rfe_rfue + * + * Maps to RFUE on XEA1, and RFE on XEA2. No mapping on XEAX. + */ + +#if XCHAL_HAVE_XEA1 + .macro rfe_rfue + rfue + .endm +#elif XCHAL_HAVE_XEA2 + .macro rfe_rfue + rfe + .endm +#endif + + +/*---------------------------------------------------------------------- + * abi_entry + * + * Generate proper function entry sequence for the current ABI + * (windowed or call0). Takes care of allocating stack space (up to 1kB) + * and saving the return PC, if necessary. The corresponding abi_return + * macro does the corresponding stack deallocation and restoring return PC. + * + * Parameters are: + * + * locsize Number of bytes to allocate on the stack + * for local variables (and for args to pass to + * callees, if any calls are made). Defaults to zero. + * The macro rounds this up to a multiple of 16. + * NOTE: large values are allowed (e.g. up to 1 GB). + * + * callsize Maximum call size made by this function. + * Leave zero (default) for leaf functions, i.e. if + * this function makes no calls to other functions. + * Otherwise must be set to 4, 8, or 12 according + * to whether the "largest" call made is a call[x]4, + * call[x]8, or call[x]12 (for call0 ABI, it makes + * no difference whether this is set to 4, 8 or 12, + * but it must be set to one of these values). + * + * NOTE: It is up to the caller to align the entry point, declare the + * function symbol, make it global, etc. + * + * NOTE: This macro relies on assembler relaxation for large values + * of locsize. It might not work with the no-transform directive. + * NOTE: For the call0 ABI, this macro ensures SP is allocated or + * de-allocated cleanly, i.e. without temporarily allocating too much + * (or allocating negatively!) due to addi relaxation. + * + * NOTE: Generating the proper sequence and register allocation for + * making calls in an ABI independent manner is a separate topic not + * covered by this macro. + * + * NOTE: To access arguments, you can't use a fixed offset from SP. + * The offset depends on the ABI, whether the function is leaf, etc. + * The simplest method is probably to use the .locsz symbol, which + * is set by this macro to the actual number of bytes allocated on + * the stack, in other words, to the offset from SP to the arguments. + * E.g. for a function whose arguments are all 32-bit integers, you + * can get the 7th and 8th arguments (1st and 2nd args stored on stack) + * using: + * l32i a2, sp, .locsz + * l32i a3, sp, .locsz+4 + * (this example works as long as locsize is under L32I's offset limit + * of 1020 minus up to 48 bytes of ABI-specific stack usage; + * otherwise you might first need to do "addi a?, sp, .locsz" + * or similar sequence). + * + * NOTE: For call0 ABI, this macro (and abi_return) may clobber a9 + * (a caller-saved register). + * + * Examples: + * abi_entry + * abi_entry 5 + * abi_entry 22, 8 + * abi_entry 0, 4 + */ + + /* + * Compute .locsz and .callsz without emitting any instructions. + * Used by both abi_entry and abi_return. + * Assumes locsize >= 0. + */ + .macro abi_entry_size locsize=0, callsize=0 +#if XCHAL_HAVE_WINDOWED && !__XTENSA_CALL0_ABI__ + .ifeq \callsize + .set .callsz, 16 + .else + .ifeq \callsize-4 + .set .callsz, 16 + .else + .ifeq \callsize-8 + .set .callsz, 32 + .else + .ifeq \callsize-12 + .set .callsz, 48 + .else + .error "abi_entry: invalid call size \callsize" + .endif + .endif + .endif + .endif + .set .locsz, .callsz + ((\locsize + 15) & -16) +#else + .set .callsz, \callsize + .if .callsz /* if calls, need space for return PC */ + .set .locsz, (\locsize + 4 + 15) & -16 + .else + .set .locsz, (\locsize + 15) & -16 + .endif +#endif + .endm + + .macro abi_entry locsize=0, callsize=0 + .iflt \locsize + .error "abi_entry: invalid negative size of locals (\locsize)" + .endif + abi_entry_size \locsize, \callsize +#if XCHAL_HAVE_WINDOWED && !__XTENSA_CALL0_ABI__ + .ifgt .locsz - 32760 /* .locsz > 32760 (ENTRY's max range)? */ + /* Funky computation to try to have assembler use addmi efficiently if possible: */ + entry sp, 0x7F00 + (.locsz & 0xF0) + addi a12, sp, - ((.locsz & -0x100) - 0x7F00) + movsp sp, a12 + .else + entry sp, .locsz + .endif +#else + .if .locsz + .ifle .locsz - 128 /* if locsz <= 128 */ + addi sp, sp, -.locsz + .if .callsz + s32i a0, sp, .locsz - 4 + .endif + .elseif .callsz /* locsz > 128, with calls: */ + movi a9, .locsz - 16 /* note: a9 is caller-saved */ + addi sp, sp, -16 + s32i a0, sp, 12 + sub sp, sp, a9 + .else /* locsz > 128, no calls: */ + movi a9, .locsz + sub sp, sp, a9 + .endif /* end */ + .endif +#endif + .endm + + + +/*---------------------------------------------------------------------- + * abi_return + * + * Generate proper function exit sequence for the current ABI + * (windowed or call0). Takes care of freeing stack space and + * restoring the return PC, if necessary. + * NOTE: This macro MUST be invoked following a corresponding + * abi_entry macro invocation. For call0 ABI in particular, + * all stack and PC restoration are done according to the last + * abi_entry macro invoked before this macro in the assembly file. + * + * Normally this macro takes no arguments. However to allow + * for placing abi_return *before* abi_entry (as must be done + * for some highly optimized assembly), it optionally takes + * exactly the same arguments as abi_entry. + */ + + .macro abi_return locsize=-1, callsize=0 + .ifge \locsize + abi_entry_size \locsize, \callsize + .endif +#if XCHAL_HAVE_WINDOWED && !__XTENSA_CALL0_ABI__ + retw +#else + .if .locsz + .iflt .locsz - 128 /* if locsz < 128 */ + .if .callsz + l32i a0, sp, .locsz - 4 + .endif + addi sp, sp, .locsz + .elseif .callsz /* locsz >= 128, with calls: */ + addi a9, sp, .locsz - 16 + l32i a0, a9, 12 + addi sp, a9, 16 + .else /* locsz >= 128, no calls: */ + movi a9, .locsz + add sp, sp, a9 + .endif /* end */ + .endif + ret +#endif + .endm + + +/* + * HW erratum fixes. + */ + + .macro hw_erratum_487_fix +#if defined XSHAL_ERRATUM_487_FIX + isync +#endif + .endm + + +#endif /*XTENSA_COREASM_H*/ + diff --git a/components/esp32/include/xtensa/corebits.h b/components/esp32/include/xtensa/corebits.h new file mode 100755 index 0000000000..0ac0c8014c --- /dev/null +++ b/components/esp32/include/xtensa/corebits.h @@ -0,0 +1,185 @@ +/* + * xtensa/corebits.h - Xtensa Special Register field positions, masks, values. + * + * (In previous releases, these were defined in specreg.h, a generated file. + * This file is not generated, ie. it is processor configuration independent.) + */ + +/* $Id: //depot/rel/Eaglenest/Xtensa/OS/include/xtensa/corebits.h#2 $ */ + +/* + * Copyright (c) 2005-2011 Tensilica Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY + * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +#ifndef XTENSA_COREBITS_H +#define XTENSA_COREBITS_H + +/* EXCCAUSE register fields: */ +#define EXCCAUSE_EXCCAUSE_SHIFT 0 +#define EXCCAUSE_EXCCAUSE_MASK 0x3F +/* EXCCAUSE register values: */ +/* + * General Exception Causes + * (values of EXCCAUSE special register set by general exceptions, + * which vector to the user, kernel, or double-exception vectors). + */ +#define EXCCAUSE_ILLEGAL 0 /* Illegal Instruction */ +#define EXCCAUSE_SYSCALL 1 /* System Call (SYSCALL instruction) */ +#define EXCCAUSE_INSTR_ERROR 2 /* Instruction Fetch Error */ +# define EXCCAUSE_IFETCHERROR 2 /* (backward compatibility macro, deprecated, avoid) */ +#define EXCCAUSE_LOAD_STORE_ERROR 3 /* Load Store Error */ +# define EXCCAUSE_LOADSTOREERROR 3 /* (backward compatibility macro, deprecated, avoid) */ +#define EXCCAUSE_LEVEL1_INTERRUPT 4 /* Level 1 Interrupt */ +# define EXCCAUSE_LEVEL1INTERRUPT 4 /* (backward compatibility macro, deprecated, avoid) */ +#define EXCCAUSE_ALLOCA 5 /* Stack Extension Assist (MOVSP instruction) for alloca */ +#define EXCCAUSE_DIVIDE_BY_ZERO 6 /* Integer Divide by Zero */ +#define EXCCAUSE_SPECULATION 7 /* Use of Failed Speculative Access (not implemented) */ +#define EXCCAUSE_PRIVILEGED 8 /* Privileged Instruction */ +#define EXCCAUSE_UNALIGNED 9 /* Unaligned Load or Store */ +/* Reserved 10..11 */ +#define EXCCAUSE_INSTR_DATA_ERROR 12 /* PIF Data Error on Instruction Fetch (RB-200x and later) */ +#define EXCCAUSE_LOAD_STORE_DATA_ERROR 13 /* PIF Data Error on Load or Store (RB-200x and later) */ +#define EXCCAUSE_INSTR_ADDR_ERROR 14 /* PIF Address Error on Instruction Fetch (RB-200x and later) */ +#define EXCCAUSE_LOAD_STORE_ADDR_ERROR 15 /* PIF Address Error on Load or Store (RB-200x and later) */ +#define EXCCAUSE_ITLB_MISS 16 /* ITLB Miss (no ITLB entry matches, hw refill also missed) */ +#define EXCCAUSE_ITLB_MULTIHIT 17 /* ITLB Multihit (multiple ITLB entries match) */ +#define EXCCAUSE_INSTR_RING 18 /* Ring Privilege Violation on Instruction Fetch */ +/* Reserved 19 */ /* Size Restriction on IFetch (not implemented) */ +#define EXCCAUSE_INSTR_PROHIBITED 20 /* Cache Attribute does not allow Instruction Fetch */ +/* Reserved 21..23 */ +#define EXCCAUSE_DTLB_MISS 24 /* DTLB Miss (no DTLB entry matches, hw refill also missed) */ +#define EXCCAUSE_DTLB_MULTIHIT 25 /* DTLB Multihit (multiple DTLB entries match) */ +#define EXCCAUSE_LOAD_STORE_RING 26 /* Ring Privilege Violation on Load or Store */ +/* Reserved 27 */ /* Size Restriction on Load/Store (not implemented) */ +#define EXCCAUSE_LOAD_PROHIBITED 28 /* Cache Attribute does not allow Load */ +#define EXCCAUSE_STORE_PROHIBITED 29 /* Cache Attribute does not allow Store */ +/* Reserved 30..31 */ +#define EXCCAUSE_CP_DISABLED(n) (32+(n)) /* Access to Coprocessor 'n' when disabled */ +#define EXCCAUSE_CP0_DISABLED 32 /* Access to Coprocessor 0 when disabled */ +#define EXCCAUSE_CP1_DISABLED 33 /* Access to Coprocessor 1 when disabled */ +#define EXCCAUSE_CP2_DISABLED 34 /* Access to Coprocessor 2 when disabled */ +#define EXCCAUSE_CP3_DISABLED 35 /* Access to Coprocessor 3 when disabled */ +#define EXCCAUSE_CP4_DISABLED 36 /* Access to Coprocessor 4 when disabled */ +#define EXCCAUSE_CP5_DISABLED 37 /* Access to Coprocessor 5 when disabled */ +#define EXCCAUSE_CP6_DISABLED 38 /* Access to Coprocessor 6 when disabled */ +#define EXCCAUSE_CP7_DISABLED 39 /* Access to Coprocessor 7 when disabled */ +/* Reserved 40..63 */ + +/* PS register fields: */ +#define PS_WOE_SHIFT 18 +#define PS_WOE_MASK 0x00040000 +#define PS_WOE PS_WOE_MASK +#define PS_CALLINC_SHIFT 16 +#define PS_CALLINC_MASK 0x00030000 +#define PS_CALLINC(n) (((n)&3)< +#include +#include + +int xt_dbfs_open(const char *pathname, int flags, mode_t mode); +int xt_dbfs_ftruncate(int fd, off_t length); +int xt_dbfs_truncate(const char * filename, off_t length); +int xt_dbfs_creat(const char *pathname, mode_t mode); +int xt_dbfs_errno(void); +int xt_dbfs_lseek(int fd, off_t offset, int whence); +ssize_t xt_dbfs_write(int fd, const void * buf, size_t bytes); + ssize_t xt_dbfs_open_append_close(const char * filename, int align, + const void * buf, size_t bytes); +ssize_t xt_dbfs_read(int fd, void * buf, size_t bytes); +int xt_dbfs_close(int fd); +int xt_dbfs_unlink(const char *pathname); + +/* By default, this function is a wrapper around sbrk, and follows + sbrk semantics: + + On success, it returns increment bytes of memory allocated from + system memory. + + On failure, it returns 0xFFFFFFFF + + + If you want to use a method of allocating memory other than sbrk, + implement xt_dbfs_sbrk in your own sources, and the linker will + automatically use that copy. +*/ +void * xt_dbfs_sbrk(int increment); + + + +#ifdef REPLACE_FS_WITH_DBFS +#define open xt_dbfs_open +#define close xt_dbfs_close +#define creat xt_dbfs_creat +#define lseek xt_dbfs_lseek +#define write xt_dbfs_write +#define read xt_dbfs_read +#define close xt_dbfs_close +#define unlink xt_dbfs_unlink + +#define rmdir NOT_IMPLEMENTED_IN_DBFS +#define opendir NOT_IMPLEMENTED_IN_DBFS +#define closedir NOT_IMPLEMENTED_IN_DBFS +#define dirfs NOT_IMPLEMENTED_IN_DBFS +#define readdir NOT_IMPLEMENTED_IN_DBFS +#define scandir NOT_IMPLEMENTED_IN_DBFS +#define seekdir NOT_IMPLEMENTED_IN_DBFS +#define telldir NOT_IMPLEMENTED_IN_DBFS + +#define fcntl NOT_IMPLEMENTED_IN_DBFS +#define dup2 NOT_IMPLEMENTED_IN_DBFS +#define dup NOT_IMPLEMENTED_IN_DBFS +#define flock NOT_IMPLEMENTED_IN_DBFS +#define lockf NOT_IMPLEMENTED_IN_DBFS +#define link NOT_IMPLEMENTED_IN_DBFS +#define stat NOT_IMPLEMENTED_IN_DBFS +#define fstat NOT_IMPLEMENTED_IN_DBFS +#define lstat NOT_IMPLEMENTED_IN_DBFS +#define chmod NOT_IMPLEMENTED_IN_DBFS +#define fchmod NOT_IMPLEMENTED_IN_DBFS +#define chmown NOT_IMPLEMENTED_IN_DBFS +#define lchown NOT_IMPLEMENTED_IN_DBFS +#define fchown NOT_IMPLEMENTED_IN_DBFS + +#endif + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/components/esp32/include/xtensa/feedback.h b/components/esp32/include/xtensa/feedback.h new file mode 100755 index 0000000000..aecb745333 --- /dev/null +++ b/components/esp32/include/xtensa/feedback.h @@ -0,0 +1,45 @@ + +/* + * Copyright (c) 2013 by Tensilica Inc. ALL RIGHTS RESERVED. + * These coded instructions, statements, and computer programs are the + * copyrighted works and confidential proprietary information of Tensilica Inc. + * They may not be modified, copied, reproduced, distributed, or disclosed to + * third parties in any manner, medium, or form, in whole or in part, without + * the prior written consent of Tensilica Inc. + */ + +#ifndef __XT_FEEDBACK_INCLUDED__ +#define __XT_FEEDBACK_INCLUDED__ + +#ifdef __cplusplus +extern "C" { +#endif + +/* xt_feedback_save_and_reset + + Save and reset the accumulated feedback data. +*/ +extern void xt_feedback_save_and_reset(void); + +/* xt_feedback_enable + + Turn on feedback accumulation. Ordinarily, feedback accumulation is on + by default. If you turn it off using xt_feedback_disable, You can turn + it on again via this function. +*/ +extern void xt_feedback_enable (void); + +/* xt_feedback_disable + + Turn off feedback accumulation. If you don't want to gather feedback for a + portion of your code, use this function and then xt_feedback_enable when + you want to start again. +*/ +extern void xt_feedback_disable (void); + +#ifdef __cplusplus +} +#endif + +#endif /* __XT_FEEDBACK_INCLUDED__ */ + diff --git a/components/esp32/include/xtensa/gdbio.h b/components/esp32/include/xtensa/gdbio.h new file mode 100755 index 0000000000..784a862978 --- /dev/null +++ b/components/esp32/include/xtensa/gdbio.h @@ -0,0 +1,80 @@ +/* Xtensa Debug-FileSystem definitions + * + * Copyright (c) 2006-2009 by Tensilica Inc. ALL RIGHTS RESERVED. + * These coded instructions, statements, and computer programs are the + * copyrighted works and confidential proprietary information of Tensilica Inc. + * They may not be modified, copied, reproduced, distributed, or disclosed to + * third parties in any manner, medium, or form, in whole or in part, without + * the prior written consent of Tensilica Inc. + */ + +#ifndef __DEBUGFS_H__ +#define __DEBUGFS_H__ + +#ifdef __cplusplus +extern "C" { +#endif + +#include +#include +#include +#include + + int _gdbio_open_r(void * ptr, const char *pathname, int flags, mode_t mode); + int _gdbio_creat_r(void * ptr, const char *pathname, mode_t mode); + int _gdbio_lseek_r(void * ptr, int fd, off_t offset, int whence); + ssize_t _gdbio_write_r(void * ptr, int fd, const void * buf, size_t bytes); + ssize_t _gdbio_read_r(void * ptr, int fd, void * buf, size_t bytes); + int _gdbio_close_r(void * ptr, int fd); + int _gdbio_unlink_r(void * ptr, const char * pathname); + + static inline + int gdbio_open(const char *pathname, int flags, mode_t mode) { + return _gdbio_open_r(&errno, pathname, flags, mode); + } + static inline int + gdbio_creat(const char *pathname, mode_t mode) { + return _gdbio_open_r(&errno, pathname, O_CREAT|O_WRONLY|O_TRUNC, mode); + } + static inline int + gdbio_errno(void) { + return errno; + } + static inline int + gdbio_lseek(int fd, off_t offset, int whence) { + return _gdbio_lseek_r(&errno, fd, offset, whence); + } + static inline + ssize_t gdbio_write(int fd, const void * buf, size_t bytes) { + return _gdbio_write_r(&errno, fd, buf, bytes); + } + static inline + ssize_t gdbio_read(int fd, void * buf, size_t bytes) { + return _gdbio_read_r(&errno, fd, buf, bytes); + } + static inline int + gdbio_close(int fd) { + return _gdbio_close_r(&errno, fd); + } + static inline int + gdbio_unlink(const char * pathname) { + return _gdbio_unlink_r(&errno, pathname); + } + +#ifdef REPLACE_FS_WITH_GDBIO +#define open gdbio_open +#define close gdbio_close +#define creat gdbio_creat +#define lseek gdbio_lseek +#define write gdbio_write +#define read gdbio_read +#define close gdbio_close +#define unlink gdbio_unlink + +#endif + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/components/esp32/include/xtensa/hal.h b/components/esp32/include/xtensa/hal.h new file mode 100755 index 0000000000..d4d95d9fe7 --- /dev/null +++ b/components/esp32/include/xtensa/hal.h @@ -0,0 +1,1024 @@ +/* + xtensa/hal.h -- contains a definition of the Core HAL interface + + All definitions in this header file are independent of any specific + Xtensa processor configuration. Thus software (eg. OS, application, + etc) can include this header file and be compiled into configuration- + independent objects that can be distributed and eventually linked + to the HAL library (libhal.a) to create a configuration-specific + final executable. + + Certain definitions, however, are release/version-specific -- such as + the XTHAL_RELEASE_xxx macros (or additions made in later versions). + + + $Id: //depot/rel/Eaglenest/Xtensa/OS/target-os-src/hal.h.tpp#4 $ + + Copyright (c) 1999-2014 Cadence Design Systems, Inc. + + Permission is hereby granted, free of charge, to any person obtaining + a copy of this software and associated documentation files (the + "Software"), to deal in the Software without restriction, including + without limitation the rights to use, copy, modify, merge, publish, + distribute, sublicense, and/or sell copies of the Software, and to + permit persons to whom the Software is furnished to do so, subject to + the following conditions: + + The above copyright notice and this permission notice shall be included + in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY + CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +*/ + +#ifndef XTENSA_HAL_H +#define XTENSA_HAL_H + + +/**************************************************************************** + Definitions Useful for Any Code, USER or PRIVILEGED + ****************************************************************************/ + + +/*---------------------------------------------------------------------- + Constant Definitions (shared with assembly) + ----------------------------------------------------------------------*/ + +/* + * Software (Xtensa Tools) version information. Not configuration-specific! + * + * NOTE: "release" is a misnomer here, these are really product "version" + * numbers. A "release" is a collection of product versions + * made available at once (together) to customers. + * In the past, release and version names all matched in T####.# form, + * making the distinction irrelevant. This is no longer the case. + */ +#define XTHAL_RELEASE_MAJOR 11000 +#define XTHAL_RELEASE_MINOR 3 +#define XTHAL_RELEASE_NAME "11.0.3" +#define XTHAL_REL_11 1 +#define XTHAL_REL_11_0 1 +#define XTHAL_REL_11_0_3 1 + +/* HAL version numbers (these names are for backward compatibility): */ +#define XTHAL_MAJOR_REV XTHAL_RELEASE_MAJOR +#define XTHAL_MINOR_REV XTHAL_RELEASE_MINOR +/* + * A bit of software release/version history on values of XTHAL_{MAJOR,MINOR}_REV: + * + * SW Version MAJOR MINOR Comment + * ======= ===== ===== ======= + * T1015.n n/a n/a (HAL not yet available) + * T1020.{0,1,2} 0 1 (HAL beta) + * T1020.{3,4} 0 2 First release. + * T1020.n (n>4) 0 2 or >3 (TBD) + * T1030.0 0 1 (HAL beta) + * T1030.{1,2} 0 3 Equivalent to first release. + * T1030.n (n>=3) 0 >= 3 (TBD) + * T1040.n 1040 n Full CHAL available from T1040.2 + * T1050.n 1050 n . + * 6.0.n 6000 n Xtensa Tools v6 (RA-200x.n) + * 7.0.n 7000 n Xtensa Tools v7 (RB-200x.n) + * 7.1.n 7010 n Xtensa Tools v7.1 (RB-200x.(n+2)) + * 8.0.n 8000 n Xtensa Tools v8 (RC-20xx.n) + * 9.0.n 9000 n Xtensa Tools v9 (RD-201x.n) + * 10.0.n 10000 n Xtensa Tools v10 (RE-201x.n) + * + * + * Note: there is a distinction between the software version with + * which something is compiled (accessible using XTHAL_RELEASE_* macros) + * and the software version with which the HAL library was compiled + * (accessible using Xthal_release_* global variables). This + * distinction is particularly relevant for vendors that distribute + * configuration-independent binaries (eg. an OS), where their customer + * might link it with a HAL of a different Xtensa software version. + * In this case, it may be appropriate for the OS to verify at run-time + * whether XTHAL_RELEASE_* and Xthal_release_* are compatible. + * [Guidelines as to which version is compatible with which are not + * currently provided explicitly, but might be inferred from reading + * OSKit documentation for all releases -- compatibility is also highly + * dependent on which HAL features are used. Each version is usually + * backward compatible, with very few exceptions if any.] + */ + +/* Version comparison operators (among major/minor pairs): */ +#define XTHAL_REL_GE(maja,mina, majb,minb) ((maja) > (majb) || \ + ((maja) == (majb) && (mina) >= (minb))) +#define XTHAL_REL_GT(maja,mina, majb,minb) ((maja) > (majb) || \ + ((maja) == (majb) && (mina) > (minb))) +#define XTHAL_REL_LE(maja,mina, majb,minb) ((maja) < (majb) || \ + ((maja) == (majb) && (mina) <= (minb))) +#define XTHAL_REL_LT(maja,mina, majb,minb) ((maja) < (majb) || \ + ((maja) == (majb) && (mina) < (minb))) +#define XTHAL_REL_EQ(maja,mina, majb,minb) ((maja) == (majb) && (mina) == (minb)) + +/* Fuzzy (3-way) logic operators: */ +#define XTHAL_MAYBE -1 /* 0=NO, 1=YES, -1=MAYBE */ +#define XTHAL_FUZZY_AND(a,b) (((a)==0 || (b)==0) ? 0 : ((a)==1 && (b)==1) ? 1 : XTHAL_MAYBE) +#define XTHAL_FUZZY_OR(a,b) (((a)==1 || (b)==1) ? 1 : ((a)==0 && (b)==0) ? 0 : XTHAL_MAYBE) +#define XTHAL_FUZZY_NOT(a) (((a)==0 || (a)==1) ? (1-(a)) : XTHAL_MAYBE) + + +/* + * Architectural limit, independent of configuration: + */ +#define XTHAL_MAX_CPS 8 /* max number of coprocessors (0..7) */ + +/* Misc: */ +#define XTHAL_LITTLEENDIAN 0 +#define XTHAL_BIGENDIAN 1 + + + +#if !defined(_ASMLANGUAGE) && !defined(_NOCLANGUAGE) && !defined(__ASSEMBLER__) +#ifdef __cplusplus +extern "C" { +#endif + +/*---------------------------------------------------------------------- + HAL + ----------------------------------------------------------------------*/ + +/* Constant to be checked in build = (XTHAL_MAJOR_REV<<16)|XTHAL_MINOR_REV */ +extern const unsigned int Xthal_rev_no; + + +/*---------------------------------------------------------------------- + Optional/Custom Processor State + ----------------------------------------------------------------------*/ + +/* save & restore the extra processor state */ +extern void xthal_save_extra(void *base); +extern void xthal_restore_extra(void *base); + +extern void xthal_save_cpregs(void *base, int); +extern void xthal_restore_cpregs(void *base, int); +/* versions specific to each coprocessor id */ +extern void xthal_save_cp0(void *base); +extern void xthal_save_cp1(void *base); +extern void xthal_save_cp2(void *base); +extern void xthal_save_cp3(void *base); +extern void xthal_save_cp4(void *base); +extern void xthal_save_cp5(void *base); +extern void xthal_save_cp6(void *base); +extern void xthal_save_cp7(void *base); +extern void xthal_restore_cp0(void *base); +extern void xthal_restore_cp1(void *base); +extern void xthal_restore_cp2(void *base); +extern void xthal_restore_cp3(void *base); +extern void xthal_restore_cp4(void *base); +extern void xthal_restore_cp5(void *base); +extern void xthal_restore_cp6(void *base); +extern void xthal_restore_cp7(void *base); +/* pointers to each of the functions above */ +extern void* Xthal_cpregs_save_fn[XTHAL_MAX_CPS]; +extern void* Xthal_cpregs_restore_fn[XTHAL_MAX_CPS]; +/* similarly for non-windowed ABI (may be same or different) */ +extern void* Xthal_cpregs_save_nw_fn[XTHAL_MAX_CPS]; +extern void* Xthal_cpregs_restore_nw_fn[XTHAL_MAX_CPS]; + +/*extern void xthal_save_all_extra(void *base);*/ +/*extern void xthal_restore_all_extra(void *base);*/ + +/* space for processor state */ +extern const unsigned int Xthal_extra_size; +extern const unsigned int Xthal_extra_align; +extern const unsigned int Xthal_cpregs_size[XTHAL_MAX_CPS]; +extern const unsigned int Xthal_cpregs_align[XTHAL_MAX_CPS]; +extern const unsigned int Xthal_all_extra_size; +extern const unsigned int Xthal_all_extra_align; +/* coprocessor names */ +extern const char * const Xthal_cp_names[XTHAL_MAX_CPS]; + +/* initialize the extra processor */ +/*extern void xthal_init_extra(void);*/ +/* initialize the TIE coprocessor */ +/*extern void xthal_init_cp(int);*/ + +/* initialize the extra processor */ +extern void xthal_init_mem_extra(void *); +/* initialize the TIE coprocessor */ +extern void xthal_init_mem_cp(void *, int); + +/* the number of TIE coprocessors contiguous from zero (for Tor2) */ +extern const unsigned int Xthal_num_coprocessors; + +/* actual number of coprocessors */ +extern const unsigned char Xthal_cp_num; +/* index of highest numbered coprocessor, plus one */ +extern const unsigned char Xthal_cp_max; +/* index of highest allowed coprocessor number, per cfg, plus one */ +/*extern const unsigned char Xthal_cp_maxcfg;*/ +/* bitmask of which coprocessors are present */ +extern const unsigned int Xthal_cp_mask; + +/* read & write extra state register */ +/*extern int xthal_read_extra(void *base, unsigned reg, unsigned *value);*/ +/*extern int xthal_write_extra(void *base, unsigned reg, unsigned value);*/ + +/* read & write a TIE coprocessor register */ +/*extern int xthal_read_cpreg(void *base, int cp, unsigned reg, unsigned *value);*/ +/*extern int xthal_write_cpreg(void *base, int cp, unsigned reg, unsigned value);*/ + +/* return coprocessor number based on register */ +/*extern int xthal_which_cp(unsigned reg);*/ + + +/*---------------------------------------------------------------------- + Register Windows + ----------------------------------------------------------------------*/ + +/* number of registers in register window */ +extern const unsigned int Xthal_num_aregs; +extern const unsigned char Xthal_num_aregs_log2; + + +/*---------------------------------------------------------------------- + Cache + ----------------------------------------------------------------------*/ + +/* size of the cache lines in log2(bytes) */ +extern const unsigned char Xthal_icache_linewidth; +extern const unsigned char Xthal_dcache_linewidth; +/* size of the cache lines in bytes (2^linewidth) */ +extern const unsigned short Xthal_icache_linesize; +extern const unsigned short Xthal_dcache_linesize; + +/* size of the caches in bytes (ways * 2^(linewidth + setwidth)) */ +extern const unsigned int Xthal_icache_size; +extern const unsigned int Xthal_dcache_size; +/* cache features */ +extern const unsigned char Xthal_dcache_is_writeback; + +/* invalidate the caches */ + +extern void xthal_icache_region_invalidate( void *addr, unsigned size ); +extern void xthal_dcache_region_invalidate( void *addr, unsigned size ); +# ifndef XTHAL_USE_CACHE_MACROS +extern void xthal_icache_line_invalidate(void *addr); +extern void xthal_dcache_line_invalidate(void *addr); +# endif +/* write dirty data back */ +extern void xthal_dcache_region_writeback( void *addr, unsigned size ); +# ifndef XTHAL_USE_CACHE_MACROS +extern void xthal_dcache_line_writeback(void *addr); +# endif +/* write dirty data back and invalidate */ +extern void xthal_dcache_region_writeback_inv( void *addr, unsigned size ); +# ifndef XTHAL_USE_CACHE_MACROS +extern void xthal_dcache_line_writeback_inv(void *addr); +/* sync icache and memory */ +extern void xthal_icache_sync( void ); +/* sync dcache and memory */ +extern void xthal_dcache_sync( void ); +#endif + +/* get number of icache ways enabled */ +extern unsigned int xthal_icache_get_ways(void); +/* set number of icache ways enabled */ +extern void xthal_icache_set_ways(unsigned int ways); +/* get number of dcache ways enabled */ +extern unsigned int xthal_dcache_get_ways(void); +/* set number of dcache ways enabled */ +extern void xthal_dcache_set_ways(unsigned int ways); + +/* coherency (low-level -- not normally called directly) */ +extern void xthal_cache_coherence_on( void ); +extern void xthal_cache_coherence_off( void ); +/* coherency (high-level) */ +extern void xthal_cache_coherence_optin( void ); +extern void xthal_cache_coherence_optout( void ); + +/* + * Cache prefetch control. + * The parameter to xthal_set_cache_prefetch() contains both + * a PREFCTL register value and a mask of which bits to actually modify. + * This allows easily combining field macros (below) by ORing, + * leaving unspecified fields unmodified. + * + * For backward compatibility with the older version of this routine + * (that took 15-bit value and mask in a 32-bit parameter, for pre-RF + * cores with only the lower 15 bits of PREFCTL defined), the 32-bit + * value and mask are staggered as follows in a 64-bit parameter: + * param[63:48] are PREFCTL[31:16] if param[31] is set + * param[47:32] are mask[31:16] if param[31] is set + * param[31] is set if mask is used, 0 if not + * param[31:16] are mask[15:0] if param[31] is set + * param[31:16] are PREFCTL[31:16] if param[31] is clear + * param[15:0] are PREFCTL[15:0] + * + * Limitation: PREFCTL register bit 31 cannot be set without masking, + * and bit 15 must always be set when using masking, so it is hoped that + * these two bits will remain reserved, read-as-zero in PREFCTL. + */ +#define XTHAL_PREFETCH_ENABLE -1 /* enable inst+data prefetch */ +#define XTHAL_PREFETCH_DISABLE 0xFFFF0000 /* disab inst+data prefetch*/ +#define XTHAL_DCACHE_PREFETCH(n) (0x800F0000+((n)&0xF)) /* data-side */ +#define XTHAL_DCACHE_PREFETCH_OFF XTHAL_DCACHE_PREFETCH(0) /* disable */ +#define XTHAL_DCACHE_PREFETCH_LOW XTHAL_DCACHE_PREFETCH(4) /* less aggr.*/ +#define XTHAL_DCACHE_PREFETCH_MEDIUM XTHAL_DCACHE_PREFETCH(5) /* mid aggr. */ +#define XTHAL_DCACHE_PREFETCH_HIGH XTHAL_DCACHE_PREFETCH(8) /* more aggr.*/ +#define XTHAL_DCACHE_PREFETCH_L1_OFF 0x90000000 /* to prefetch buffers*/ +#define XTHAL_DCACHE_PREFETCH_L1 0x90001000 /* direct to L1 dcache*/ +#define XTHAL_ICACHE_PREFETCH(n) (0x80F00000+(((n)&0xF)<<4)) /* i-side */ +#define XTHAL_ICACHE_PREFETCH_OFF XTHAL_ICACHE_PREFETCH(0) /* disable */ +#define XTHAL_ICACHE_PREFETCH_LOW XTHAL_ICACHE_PREFETCH(4) /* less aggr.*/ +#define XTHAL_ICACHE_PREFETCH_MEDIUM XTHAL_ICACHE_PREFETCH(5) /* mid aggr. */ +#define XTHAL_ICACHE_PREFETCH_HIGH XTHAL_ICACHE_PREFETCH(8) /* more aggr.*/ +#define XTHAL_ICACHE_PREFETCH_L1_OFF 0xA0000000 /* (not implemented) */ +#define XTHAL_ICACHE_PREFETCH_L1 0xA0002000 /* (not implemented) */ +#define _XTHAL_PREFETCH_BLOCKS(n) ((n)<0?0:(n)<5?(n):(n)<15?((n)>>1)+2:9) +#define XTHAL_PREFETCH_BLOCKS(n) (0x0000000F80000000ULL + \ + (((unsigned long long)_XTHAL_PREFETCH_BLOCKS(n))<<48)) + +extern int xthal_get_cache_prefetch( void ); +extern int xthal_set_cache_prefetch( int ); +extern int xthal_set_cache_prefetch_long( unsigned long long ); +/* Only use the new extended function from now on: */ +#define xthal_set_cache_prefetch xthal_set_cache_prefetch_long +#define xthal_set_cache_prefetch_nw xthal_set_cache_prefetch_long_nw + + +/*---------------------------------------------------------------------- + Debug + ----------------------------------------------------------------------*/ + +/* 1 if debug option configured, 0 if not: */ +extern const int Xthal_debug_configured; + +/* Set (plant) and remove software breakpoint, both synchronizing cache: */ +extern unsigned int xthal_set_soft_break(void *addr); +extern void xthal_remove_soft_break(void *addr, unsigned int); + + +/*---------------------------------------------------------------------- + Disassembler + ----------------------------------------------------------------------*/ + +/* Max expected size of the return buffer for a disassembled instruction (hint only): */ +#define XTHAL_DISASM_BUFSIZE 80 + +/* Disassembly option bits for selecting what to return: */ +#define XTHAL_DISASM_OPT_ADDR 0x0001 /* display address */ +#define XTHAL_DISASM_OPT_OPHEX 0x0002 /* display opcode bytes in hex */ +#define XTHAL_DISASM_OPT_OPCODE 0x0004 /* display opcode name (mnemonic) */ +#define XTHAL_DISASM_OPT_PARMS 0x0008 /* display parameters */ +#define XTHAL_DISASM_OPT_ALL 0x0FFF /* display everything */ + +/* routine to get a string for the disassembled instruction */ +extern int xthal_disassemble( unsigned char *instr_buf, void *tgt_addr, + char *buffer, unsigned buflen, unsigned options ); + +/* routine to get the size of the next instruction. Returns 0 for + illegal instruction */ +extern int xthal_disassemble_size( unsigned char *instr_buf ); + + +/*---------------------------------------------------------------------- + Instruction/Data RAM/ROM Access + ----------------------------------------------------------------------*/ + +extern void* xthal_memcpy(void *dst, const void *src, unsigned len); +extern void* xthal_bcopy(const void *src, void *dst, unsigned len); + + +/*---------------------------------------------------------------------- + MP Synchronization + ----------------------------------------------------------------------*/ + +extern int xthal_compare_and_set( int *addr, int test_val, int compare_val ); + +/*extern const char Xthal_have_s32c1i;*/ + + +/*---------------------------------------------------------------------- + Miscellaneous + ----------------------------------------------------------------------*/ + +extern const unsigned int Xthal_release_major; +extern const unsigned int Xthal_release_minor; +extern const char * const Xthal_release_name; +extern const char * const Xthal_release_internal; + +extern const unsigned char Xthal_memory_order; +extern const unsigned char Xthal_have_windowed; +extern const unsigned char Xthal_have_density; +extern const unsigned char Xthal_have_booleans; +extern const unsigned char Xthal_have_loops; +extern const unsigned char Xthal_have_nsa; +extern const unsigned char Xthal_have_minmax; +extern const unsigned char Xthal_have_sext; +extern const unsigned char Xthal_have_clamps; +extern const unsigned char Xthal_have_mac16; +extern const unsigned char Xthal_have_mul16; +extern const unsigned char Xthal_have_fp; +extern const unsigned char Xthal_have_speculation; +extern const unsigned char Xthal_have_threadptr; + +extern const unsigned char Xthal_have_pif; +extern const unsigned short Xthal_num_writebuffer_entries; + +extern const unsigned int Xthal_build_unique_id; +/* Version info for hardware targeted by software upgrades: */ +extern const unsigned int Xthal_hw_configid0; +extern const unsigned int Xthal_hw_configid1; +extern const unsigned int Xthal_hw_release_major; +extern const unsigned int Xthal_hw_release_minor; +extern const char * const Xthal_hw_release_name; +extern const char * const Xthal_hw_release_internal; + +/* Clear any remnant code-dependent state (i.e. clear loop count regs). */ +extern void xthal_clear_regcached_code( void ); + +#ifdef __cplusplus +} +#endif +#endif /*!_ASMLANGUAGE && !_NOCLANGUAGE && !__ASSEMBLER__ */ + + + + + +/**************************************************************************** + Definitions Useful for PRIVILEGED (Supervisory or Non-Virtualized) Code + ****************************************************************************/ + + +#ifndef XTENSA_HAL_NON_PRIVILEGED_ONLY + +/*---------------------------------------------------------------------- + Constant Definitions (shared with assembly) + ----------------------------------------------------------------------*/ + +/* + * Architectural limits, independent of configuration. + * Note that these are ISA-defined limits, not micro-architecture implementation + * limits enforced by the Xtensa Processor Generator (which may be stricter than + * these below). + */ +#define XTHAL_MAX_INTERRUPTS 32 /* max number of interrupts (0..31) */ +#define XTHAL_MAX_INTLEVELS 16 /* max number of interrupt levels (0..15) */ + /* (as of T1040, implementation limit is 7: 0..6) */ +#define XTHAL_MAX_TIMERS 4 /* max number of timers (CCOMPARE0..CCOMPARE3) */ + /* (as of T1040, implementation limit is 3: 0..2) */ + +/* Interrupt types: */ +#define XTHAL_INTTYPE_UNCONFIGURED 0 +#define XTHAL_INTTYPE_SOFTWARE 1 +#define XTHAL_INTTYPE_EXTERN_EDGE 2 +#define XTHAL_INTTYPE_EXTERN_LEVEL 3 +#define XTHAL_INTTYPE_TIMER 4 +#define XTHAL_INTTYPE_NMI 5 +#define XTHAL_INTTYPE_WRITE_ERROR 6 +#define XTHAL_INTTYPE_PROFILING 7 +#define XTHAL_MAX_INTTYPES 8 /* number of interrupt types */ + +/* Timer related: */ +#define XTHAL_TIMER_UNCONFIGURED -1 /* Xthal_timer_interrupt[] value for non-existent timers */ +#define XTHAL_TIMER_UNASSIGNED XTHAL_TIMER_UNCONFIGURED /* (for backwards compatibility only) */ + +/* Local Memory ECC/Parity: */ +#define XTHAL_MEMEP_PARITY 1 +#define XTHAL_MEMEP_ECC 2 +/* Flags parameter to xthal_memep_inject_error(): */ +#define XTHAL_MEMEP_F_LOCAL 0 /* local memory (default) */ +#define XTHAL_MEMEP_F_DCACHE_DATA 4 /* data cache data */ +#define XTHAL_MEMEP_F_DCACHE_TAG 5 /* data cache tag */ +#define XTHAL_MEMEP_F_ICACHE_DATA 6 /* instruction cache data */ +#define XTHAL_MEMEP_F_ICACHE_TAG 7 /* instruction cache tag */ +#define XTHAL_MEMEP_F_CORRECTABLE 16 /* inject correctable error + (default is non-corr.) */ + + +/* Access Mode bits (tentative): */ /* bit abbr unit short_name PPC equ - Description */ +#define XTHAL_AMB_EXCEPTION 0 /* 001 E EX fls: EXception none + exception on any access (aka "illegal") */ +#define XTHAL_AMB_HITCACHE 1 /* 002 C CH fls: use Cache on Hit ~(I CI) + [or H HC] way from tag match; + [or U UC] (ISA: same except Isolate case) */ +#define XTHAL_AMB_ALLOCATE 2 /* 004 A AL fl?: ALlocate none + [or F FI fill] refill cache on miss, way from LRU + (ISA: Read/Write Miss Refill) */ +#define XTHAL_AMB_WRITETHRU 3 /* 008 W WT --s: WriteThrough W WT + store immediately to memory (ISA: same) */ +#define XTHAL_AMB_ISOLATE 4 /* 010 I IS fls: ISolate none + use cache regardless of hit-vs-miss, + way from vaddr (ISA: use-cache-on-miss+hit) */ +#define XTHAL_AMB_GUARD 5 /* 020 G GU ?l?: GUard G * + non-speculative; spec/replay refs not permitted */ +#define XTHAL_AMB_COHERENT 6 /* 040 M MC ?ls: Mem/MP Coherent M + on read, other CPU/bus-master may need to supply data; + on write, maybe redirect to or flush other CPU dirty line; etc */ +#if 0 +#define XTHAL_AMB_BUFFERABLE x /* 000 B BU --s: BUfferable ? + write response may return earlier than from final destination */ +#define XTHAL_AMB_ORDERED x /* 000 O OR fls: ORdered G * + mem accesses cannot be out of order */ +#define XTHAL_AMB_FUSEWRITES x /* 000 F FW --s: FuseWrites none + allow combining/merging/coalescing multiple writes + (to same datapath data unit) into one + (implied by writeback) */ +#define XTHAL_AMB_TRUSTED x /* 000 T TR ?l?: TRusted none + memory will not bus error (if it does, + handle as fatal imprecise interrupt) */ +#define XTHAL_AMB_PREFETCH x /* 000 P PR fl?: PRefetch none + on refill, read line+1 into prefetch buffers */ +#define XTHAL_AMB_STREAM x /* 000 S ST ???: STreaming none + access one of N stream buffers */ +#endif /*0*/ + +#define XTHAL_AM_EXCEPTION (1< = bit is set + * '-' = bit is clear + * '.' = bit is irrelevant / don't care, as follows: + * E=1 makes all others irrelevant + * W,F relevant only for stores + * "2345" + * Indicates which Xtensa releases support the corresponding + * access mode. Releases for each character column are: + * 2 = prior to T1020.2: T1015 (V1.5), T1020.0, T1020.1 + * 3 = T1020.2 and later: T1020.2+, T1030 + * 4 = T1040 + * 5 = T1050 (maybe), LX1, LX2, LX2.1 + * 7 = LX2.2 + * 8 = LX3, LX4 + * 9 = LX5 + * And the character column contents are: + * = supported by release(s) + * "." = unsupported by release(s) + * "?" = support unknown + */ + /* foMGIWACE 2345789 */ +/* For instruction fetch: */ +#define XTHAL_FAM_EXCEPTION 0x001 /* ........E 2345789 exception */ +/*efine XTHAL_FAM_ISOLATE*/ /*0x012*/ /* .---I.-C- ....... isolate */ +#define XTHAL_FAM_BYPASS 0x000 /* .----.--- 2345789 bypass */ +/*efine XTHAL_FAM_NACACHED*/ /*0x002*/ /* .----.-C- ....... cached no-allocate (frozen) */ +#define XTHAL_FAM_CACHED 0x006 /* .----.AC- 2345789 cached */ +/* For data load: */ +#define XTHAL_LAM_EXCEPTION 0x001 /* ........E 2345789 exception */ +#define XTHAL_LAM_ISOLATE 0x012 /* .---I.-C- 2345789 isolate */ +#define XTHAL_LAM_BYPASS 0x000 /* .O---.--- 2...... bypass speculative */ +#define XTHAL_LAM_BYPASSG 0x020 /* .O-G-.--- .345789 bypass guarded */ +#define XTHAL_LAM_CACHED_NOALLOC 0x002 /* .O---.-C- 2345789 cached no-allocate speculative */ +#define XTHAL_LAM_NACACHED XTHAL_LAM_CACHED_NOALLOC +#define XTHAL_LAM_NACACHEDG 0x022 /* .O-G-.-C- .?..... cached no-allocate guarded */ +#define XTHAL_LAM_CACHED 0x006 /* .----.AC- 2345789 cached speculative */ +#define XTHAL_LAM_COHCACHED 0x046 /* .-M--.AC- ....*89 cached speculative MP-coherent */ +/* For data store: */ +#define XTHAL_SAM_EXCEPTION 0x001 /* ........E 2345789 exception */ +#define XTHAL_SAM_ISOLATE 0x032 /* .--GI--C- 2345789 isolate */ +#define XTHAL_SAM_BYPASS 0x028 /* -O-G-W--- 2345789 bypass */ +#define XTHAL_SAM_WRITETHRU 0x02A /* -O-G-W-C- 2345789 writethrough */ +/*efine XTHAL_SAM_WRITETHRU_ALLOC*/ /*0x02E*/ /* -O-G-WAC- ....... writethrough allocate */ +#define XTHAL_SAM_WRITEBACK 0x026 /* F--G--AC- ...5789 writeback */ +#define XTHAL_SAM_WRITEBACK_NOALLOC 0x022 /* ?--G---C- .....89 writeback no-allocate */ +#define XTHAL_SAM_COHWRITEBACK 0x066 /* F-MG--AC- ....*89 writeback MP-coherent */ +/* For PIF attributes: */ /* -PIwrWCBUUUU ...9 */ +#define XTHAL_PAM_BYPASS 0x000 /* xxx00000xxxx ...9 bypass non-bufferable */ +#define XTHAL_PAM_BYPASS_BUF 0x010 /* xxx0000bxxxx ...9 bypass */ +#define XTHAL_PAM_CACHED_NOALLOC 0x030 /* xxx0001bxxxx ...9 cached no-allocate */ +#define XTHAL_PAM_WRITETHRU 0x0B0 /* xxx0101bxxxx ...9 writethrough (WT) */ +#define XTHAL_PAM_WRITEBACK_NOALLOC 0x0F0 /* xxx0111bxxxx ...9 writeback no-alloc (WBNA) */ +#define XTHAL_PAM_WRITEBACK 0x1F0 /* xxx1111bxxxx ...9 writeback (WB) */ +/*efine XTHAL_PAM_NORMAL*/ /*0x050*/ /* xxx0010bxxxx .... (unimplemented) */ +/*efine XTHAL_PAM_WRITETHRU_WA*/ /*0x130*/ /* xxx1001bxxxx .... (unimplemented, less likely) */ +/*efine XTHAL_PAM_WRITETHRU_RWA*/ /*0x1B0*/ /* xxx1101bxxxx .... (unimplemented, less likely) */ +/*efine XTHAL_PAM_WRITEBACK_WA*/ /*0x170*/ /* xxx1011bxxxx .... (unimplemented, less likely) */ + + +#if 0 +/* + Cache attribute encoding for CACHEATTR (per ISA): + (Note: if this differs from ISA Ref Manual, ISA has precedence) + + Inst-fetches Loads Stores + ------------- ------------ ------------- +0x0 FCA_EXCEPTION LCA_NACACHED SCA_WRITETHRU cached no-allocate (previously misnamed "uncached") +0x1 FCA_CACHED LCA_CACHED SCA_WRITETHRU cached +0x2 FCA_BYPASS LCA_BYPASS_G* SCA_BYPASS bypass cache (what most people call uncached) +0x3 FCA_CACHED LCA_CACHED SCA_WRITEALLOCF write-allocate + or LCA_EXCEPTION SCA_EXCEPTION (if unimplemented) +0x4 FCA_CACHED LCA_CACHED SCA_WRITEBACK[M] write-back [MP-coherent] + or LCA_EXCEPTION SCA_EXCEPTION (if unimplemented) +0x5 FCA_CACHED LCA_CACHED SCA_WRITEBACK_NOALLOC write-back no-allocate + or FCA_EXCEPTION LCA_EXCEPTION SCA_EXCEPTION (if unimplemented) +0x6..D FCA_EXCEPTION LCA_EXCEPTION SCA_EXCEPTION (reserved) +0xE FCA_EXCEPTION LCA_ISOLATE SCA_ISOLATE isolate +0xF FCA_EXCEPTION LCA_EXCEPTION SCA_EXCEPTION illegal + * Prior to T1020.2?, guard feature not supported, this defaulted to speculative (no _G) +*/ +#endif /*0*/ + + +#if !defined(_ASMLANGUAGE) && !defined(_NOCLANGUAGE) && !defined(__ASSEMBLER__) +#ifdef __cplusplus +extern "C" { +#endif + + +/*---------------------------------------------------------------------- + Register Windows + ----------------------------------------------------------------------*/ + +/* This spill any live register windows (other than the caller's): + * (NOTE: current implementation require privileged code, but + * a user-callable implementation is possible.) */ +extern void xthal_window_spill( void ); + + +/*---------------------------------------------------------------------- + Optional/Custom Processor State + ----------------------------------------------------------------------*/ + +/* validate & invalidate the TIE register file */ +extern void xthal_validate_cp(int); +extern void xthal_invalidate_cp(int); + +/* read and write cpenable register */ +extern void xthal_set_cpenable(unsigned); +extern unsigned xthal_get_cpenable(void); + + +/*---------------------------------------------------------------------- + Interrupts + ----------------------------------------------------------------------*/ + +/* the number of interrupt levels */ +extern const unsigned char Xthal_num_intlevels; +/* the number of interrupts */ +extern const unsigned char Xthal_num_interrupts; +/* the highest level of interrupts masked by PS.EXCM */ +extern const unsigned char Xthal_excm_level; + +/* mask for level of interrupts */ +extern const unsigned int Xthal_intlevel_mask[XTHAL_MAX_INTLEVELS]; +/* mask for level 0 to N interrupts */ +extern const unsigned int Xthal_intlevel_andbelow_mask[XTHAL_MAX_INTLEVELS]; + +/* level of each interrupt */ +extern const unsigned char Xthal_intlevel[XTHAL_MAX_INTERRUPTS]; + +/* type per interrupt */ +extern const unsigned char Xthal_inttype[XTHAL_MAX_INTERRUPTS]; + +/* masks of each type of interrupt */ +extern const unsigned int Xthal_inttype_mask[XTHAL_MAX_INTTYPES]; + +/* interrupt numbers assigned to each timer interrupt */ +extern const int Xthal_timer_interrupt[XTHAL_MAX_TIMERS]; + +/* INTENABLE,INTERRUPT,INTSET,INTCLEAR register access functions: */ +extern unsigned xthal_get_intenable( void ); +extern void xthal_set_intenable( unsigned ); +extern unsigned xthal_get_interrupt( void ); +#define xthal_get_intread xthal_get_interrupt /* backward compatibility */ +extern void xthal_set_intset( unsigned ); +extern void xthal_set_intclear( unsigned ); + + +/*---------------------------------------------------------------------- + Debug + ----------------------------------------------------------------------*/ + +/* Number of instruction and data break registers: */ +extern const int Xthal_num_ibreak; +extern const int Xthal_num_dbreak; + + +/*---------------------------------------------------------------------- + Core Counter + ----------------------------------------------------------------------*/ + +/* counter info */ +extern const unsigned char Xthal_have_ccount; /* set if CCOUNT register present */ +extern const unsigned char Xthal_num_ccompare; /* number of CCOMPAREn registers */ + +/* get CCOUNT register (if not present return 0) */ +extern unsigned xthal_get_ccount(void); + +/* set and get CCOMPAREn registers (if not present, get returns 0) */ +extern void xthal_set_ccompare(int, unsigned); +extern unsigned xthal_get_ccompare(int); + + +/*---------------------------------------------------------------------- + Miscellaneous + ----------------------------------------------------------------------*/ + +extern const unsigned char Xthal_have_prid; +extern const unsigned char Xthal_have_exceptions; +extern const unsigned char Xthal_xea_version; +extern const unsigned char Xthal_have_interrupts; +extern const unsigned char Xthal_have_highlevel_interrupts; +extern const unsigned char Xthal_have_nmi; + +extern unsigned xthal_get_prid( void ); + + +/*---------------------------------------------------------------------- + Virtual interrupt prioritization (DEPRECATED) + ----------------------------------------------------------------------*/ + +/* Convert between interrupt levels (as per PS.INTLEVEL) and virtual interrupt priorities: */ +extern unsigned xthal_vpri_to_intlevel(unsigned vpri); +extern unsigned xthal_intlevel_to_vpri(unsigned intlevel); + +/* Enables/disables given set (mask) of interrupts; returns previous enabled-mask of all ints: */ +extern unsigned xthal_int_enable(unsigned); +extern unsigned xthal_int_disable(unsigned); + +/* Set/get virtual priority of an interrupt: */ +extern int xthal_set_int_vpri(int intnum, int vpri); +extern int xthal_get_int_vpri(int intnum); + +/* Set/get interrupt lockout level for exclusive access to virtual priority data structures: */ +extern void xthal_set_vpri_locklevel(unsigned intlevel); +extern unsigned xthal_get_vpri_locklevel(void); + +/* Set/get current virtual interrupt priority: */ +extern unsigned xthal_set_vpri(unsigned vpri); +extern unsigned xthal_get_vpri(void); +extern unsigned xthal_set_vpri_intlevel(unsigned intlevel); +extern unsigned xthal_set_vpri_lock(void); + + +/*---------------------------------------------------------------------- + Generic Interrupt Trampolining Support (DEPRECATED) + ----------------------------------------------------------------------*/ + +typedef void (XtHalVoidFunc)(void); + +/* Bitmask of interrupts currently trampolining down: */ +extern unsigned Xthal_tram_pending; + +/* + * Bitmask of which interrupts currently trampolining down synchronously are + * actually enabled; this bitmask is necessary because INTENABLE cannot hold + * that state (sync-trampolining interrupts must be kept disabled while + * trampolining); in the current implementation, any bit set here is not set + * in INTENABLE, and vice-versa; once a sync-trampoline is handled (at level + * one), its enable bit must be moved from here to INTENABLE: + */ +extern unsigned Xthal_tram_enabled; + +/* Bitmask of interrupts configured for sync trampolining: */ +extern unsigned Xthal_tram_sync; + +/* Trampoline support functions: */ +extern unsigned xthal_tram_pending_to_service( void ); +extern void xthal_tram_done( unsigned serviced_mask ); +extern int xthal_tram_set_sync( int intnum, int sync ); +extern XtHalVoidFunc* xthal_set_tram_trigger_func( XtHalVoidFunc *trigger_fn ); + + +/*---------------------------------------------------------------------- + Internal Memories + ----------------------------------------------------------------------*/ + +extern const unsigned char Xthal_num_instrom; +extern const unsigned char Xthal_num_instram; +extern const unsigned char Xthal_num_datarom; +extern const unsigned char Xthal_num_dataram; +extern const unsigned char Xthal_num_xlmi; + +/* Each of the following arrays contains at least one entry, + * or as many entries as needed if more than one: */ +extern const unsigned int Xthal_instrom_vaddr[]; +extern const unsigned int Xthal_instrom_paddr[]; +extern const unsigned int Xthal_instrom_size []; +extern const unsigned int Xthal_instram_vaddr[]; +extern const unsigned int Xthal_instram_paddr[]; +extern const unsigned int Xthal_instram_size []; +extern const unsigned int Xthal_datarom_vaddr[]; +extern const unsigned int Xthal_datarom_paddr[]; +extern const unsigned int Xthal_datarom_size []; +extern const unsigned int Xthal_dataram_vaddr[]; +extern const unsigned int Xthal_dataram_paddr[]; +extern const unsigned int Xthal_dataram_size []; +extern const unsigned int Xthal_xlmi_vaddr[]; +extern const unsigned int Xthal_xlmi_paddr[]; +extern const unsigned int Xthal_xlmi_size []; + + +/*---------------------------------------------------------------------- + Cache + ----------------------------------------------------------------------*/ + +/* number of cache sets in log2(lines per way) */ +extern const unsigned char Xthal_icache_setwidth; +extern const unsigned char Xthal_dcache_setwidth; +/* cache set associativity (number of ways) */ +extern const unsigned int Xthal_icache_ways; +extern const unsigned int Xthal_dcache_ways; +/* cache features */ +extern const unsigned char Xthal_icache_line_lockable; +extern const unsigned char Xthal_dcache_line_lockable; + +/* cache attribute register control (used by other HAL routines) */ +extern unsigned xthal_get_cacheattr( void ); +extern unsigned xthal_get_icacheattr( void ); +extern unsigned xthal_get_dcacheattr( void ); +extern void xthal_set_cacheattr( unsigned ); +extern void xthal_set_icacheattr( unsigned ); +extern void xthal_set_dcacheattr( unsigned ); +/* set cache attribute (access modes) for a range of memory */ +extern int xthal_set_region_attribute( void *addr, unsigned size, + unsigned cattr, unsigned flags ); +/* Bits of flags parameter to xthal_set_region_attribute(): */ +#define XTHAL_CAFLAG_EXPAND 0x000100 /* only expand allowed access to range, don't reduce it */ +#define XTHAL_CAFLAG_EXACT 0x000200 /* return error if can't apply change to exact range specified */ +#define XTHAL_CAFLAG_NO_PARTIAL 0x000400 /* don't apply change to regions partially covered by range */ +#define XTHAL_CAFLAG_NO_AUTO_WB 0x000800 /* don't writeback data after leaving writeback attribute */ +#define XTHAL_CAFLAG_NO_AUTO_INV 0x001000 /* don't invalidate after disabling cache (entering bypass) */ + +/* enable caches */ +extern void xthal_icache_enable( void ); /* DEPRECATED */ +extern void xthal_dcache_enable( void ); /* DEPRECATED */ +/* disable caches */ +extern void xthal_icache_disable( void ); /* DEPRECATED */ +extern void xthal_dcache_disable( void ); /* DEPRECATED */ + +/* invalidate the caches */ +extern void xthal_icache_all_invalidate( void ); +extern void xthal_dcache_all_invalidate( void ); +/* write dirty data back */ +extern void xthal_dcache_all_writeback( void ); +/* write dirty data back and invalidate */ +extern void xthal_dcache_all_writeback_inv( void ); +/* prefetch and lock specified memory range into cache */ +extern void xthal_icache_region_lock( void *addr, unsigned size ); +extern void xthal_dcache_region_lock( void *addr, unsigned size ); +# ifndef XTHAL_USE_CACHE_MACROS +extern void xthal_icache_line_lock(void *addr); +extern void xthal_dcache_line_lock(void *addr); +# endif +/* unlock from cache */ +extern void xthal_icache_all_unlock( void ); +extern void xthal_dcache_all_unlock( void ); +extern void xthal_icache_region_unlock( void *addr, unsigned size ); +extern void xthal_dcache_region_unlock( void *addr, unsigned size ); +# ifndef XTHAL_USE_CACHE_MACROS +extern void xthal_icache_line_unlock(void *addr); +extern void xthal_dcache_line_unlock(void *addr); +# endif + + + +/*---------------------------------------------------------------------- + Local Memory ECC/Parity + ----------------------------------------------------------------------*/ + +/* Inject memory errors; flags is bit combination of XTHAL_MEMEP_F_xxx: */ +extern void xthal_memep_inject_error(void *addr, int size, int flags); + + + +/*---------------------------------------------------------------------- + Memory Management Unit + ----------------------------------------------------------------------*/ + +extern const unsigned char Xthal_have_spanning_way; +extern const unsigned char Xthal_have_identity_map; +extern const unsigned char Xthal_have_mimic_cacheattr; +extern const unsigned char Xthal_have_xlt_cacheattr; +extern const unsigned char Xthal_have_cacheattr; +extern const unsigned char Xthal_have_tlbs; + +extern const unsigned char Xthal_mmu_asid_bits; /* 0 .. 8 */ +extern const unsigned char Xthal_mmu_asid_kernel; +extern const unsigned char Xthal_mmu_rings; /* 1 .. 4 (perhaps 0 if no MMU and/or no protection?) */ +extern const unsigned char Xthal_mmu_ring_bits; +extern const unsigned char Xthal_mmu_sr_bits; +extern const unsigned char Xthal_mmu_ca_bits; +extern const unsigned int Xthal_mmu_max_pte_page_size; +extern const unsigned int Xthal_mmu_min_pte_page_size; + +extern const unsigned char Xthal_itlb_way_bits; +extern const unsigned char Xthal_itlb_ways; +extern const unsigned char Xthal_itlb_arf_ways; +extern const unsigned char Xthal_dtlb_way_bits; +extern const unsigned char Xthal_dtlb_ways; +extern const unsigned char Xthal_dtlb_arf_ways; + +/* Convert between virtual and physical addresses (through static maps only): */ +/*** WARNING: these two functions may go away in a future release; don't depend on them! ***/ +extern int xthal_static_v2p( unsigned vaddr, unsigned *paddrp ); +extern int xthal_static_p2v( unsigned paddr, unsigned *vaddrp, unsigned cached ); + +#define XCHAL_SUCCESS 0 +#define XCHAL_ADDRESS_MISALIGNED -1 +#define XCHAL_INEXACT -2 +#define XCHAL_INVALID_ADDRESS -3 +#define XCHAL_UNSUPPORTED_ON_THIS_ARCH -4 +#define XCHAL_NO_PAGES_MAPPED -5 +#define XTHAL_NO_MAPPING -6 + +#define XCHAL_CA_R (0xC0 | 0x40000000) +#define XCHAL_CA_RX (0xD0 | 0x40000000) +#define XCHAL_CA_RW (0xE0 | 0x40000000) +#define XCHAL_CA_RWX (0xF0 | 0x40000000) + +extern int xthal_set_region_translation(void* vaddr, void* paddr, unsigned size, unsigned cache_atr, unsigned flags); +extern int xthal_v2p(void*, void**, unsigned*, unsigned*); +extern int xthal_invalidate_region(void* addr); +extern int xthal_set_region_translation_raw(void *vaddr, void *paddr, unsigned cattr); + +#ifdef __cplusplus +} +#endif +#endif /*!_ASMLANGUAGE && !_NOCLANGUAGE && !__ASSEMBLER__ */ + +#endif /* !XTENSA_HAL_NON_PRIVILEGED_ONLY */ + + + + +/**************************************************************************** + EXPERIMENTAL and DEPRECATED Definitions + ****************************************************************************/ + + +#if !defined(_ASMLANGUAGE) && !defined(_NOCLANGUAGE) && !defined(__ASSEMBLER__) +#ifdef __cplusplus +extern "C" { +#endif + +#ifdef INCLUDE_DEPRECATED_HAL_CODE +extern const unsigned char Xthal_have_old_exc_arch; +extern const unsigned char Xthal_have_mmu; +extern const unsigned int Xthal_num_regs; +extern const unsigned char Xthal_num_iroms; +extern const unsigned char Xthal_num_irams; +extern const unsigned char Xthal_num_droms; +extern const unsigned char Xthal_num_drams; +extern const unsigned int Xthal_configid0; +extern const unsigned int Xthal_configid1; +#endif + +#ifdef INCLUDE_DEPRECATED_HAL_DEBUG_CODE +#define XTHAL_24_BIT_BREAK 0x80000000 +#define XTHAL_16_BIT_BREAK 0x40000000 +extern const unsigned short Xthal_ill_inst_16[16]; +#define XTHAL_DEST_REG 0xf0000000 /* Mask for destination register */ +#define XTHAL_DEST_REG_INST 0x08000000 /* Branch address is in register */ +#define XTHAL_DEST_REL_INST 0x04000000 /* Branch address is relative */ +#define XTHAL_RFW_INST 0x00000800 +#define XTHAL_RFUE_INST 0x00000400 +#define XTHAL_RFI_INST 0x00000200 +#define XTHAL_RFE_INST 0x00000100 +#define XTHAL_RET_INST 0x00000080 +#define XTHAL_BREAK_INST 0x00000040 +#define XTHAL_SYSCALL_INST 0x00000020 +#define XTHAL_LOOP_END 0x00000010 /* Not set by xthal_inst_type */ +#define XTHAL_JUMP_INST 0x00000008 /* Call or jump instruction */ +#define XTHAL_BRANCH_INST 0x00000004 /* Branch instruction */ +#define XTHAL_24_BIT_INST 0x00000002 +#define XTHAL_16_BIT_INST 0x00000001 +typedef struct xthal_state { + unsigned pc; + unsigned ar[16]; + unsigned lbeg; + unsigned lend; + unsigned lcount; + unsigned extra_ptr; + unsigned cpregs_ptr[XTHAL_MAX_CPS]; +} XTHAL_STATE; +extern unsigned int xthal_inst_type(void *addr); +extern unsigned int xthal_branch_addr(void *addr); +extern unsigned int xthal_get_npc(XTHAL_STATE *user_state); +#endif /* INCLUDE_DEPRECATED_HAL_DEBUG_CODE */ + +#ifdef __cplusplus +} +#endif +#endif /*!_ASMLANGUAGE && !_NOCLANGUAGE && !__ASSEMBLER__ */ + +#endif /*XTENSA_HAL_H*/ + diff --git a/components/esp32/include/xtensa/jtag-xtensa.h b/components/esp32/include/xtensa/jtag-xtensa.h new file mode 100755 index 0000000000..45ac1caa40 --- /dev/null +++ b/components/esp32/include/xtensa/jtag-xtensa.h @@ -0,0 +1,99 @@ +/* Copyright (c) 2011-2012 Tensilica Inc. ALL RIGHTS RESERVED. +// These coded instructions, statements, and computer programs are the +// copyrighted works and confidential proprietary information of Tensilica Inc. +// They may not be modified, copied, reproduced, distributed, or disclosed to +// third parties in any manner, medium, or form, in whole or in part, without +// the prior written consent of Tensilica Inc. +*/ + +#ifndef _JTAG_XTENSA_H_ +#define _JTAG_XTENSA_H_ + + +/* ---------------- JTAG registers ------------------ */ + +/* -- ER and later JTAG registers */ +typedef enum { + regIR, + regBypass, + regNAR, + regNDR, + regIdcode, + regPWRCTL, + regPWRSTAT, + regJtagMAX, +} xtensaJtagReg; + +/* -- pre-ER JTAG registers */ +typedef enum { + regOldIR, + regOldBypass, + regOldDIRW, + regOldDIR, + regOldDDR, + regOldDOSR, + regOldESR, + regOldDCR, + regOldTraxNDR, + regOldTraxNAR, + regOldMAX +} xtensaOldJtagReg; + + +/* ---------------- JTAG Instructions ------------------ */ + +/* -- pre-ER JTAG instructions */ +typedef enum { + ji_EnableOCD = 0x11, + ji_DebugInt, + ji_RetDebugInt, // TBD: remove + ji_DisRetOCD, // TBD: remove + ji_ExecuteDI, + ji_LoadDI, + ji_ScanDDR, + ji_ReadDOSR, + ji_ScanDCR, + ji_LoadWDI, + ji_TRAX = 0x1c, + ji_BYPASS = 0x1f, +} xtensaJtagInstruction; + +typedef enum { + OCDNormalMode, + OCDRunMode, + OCDHaltMode, + OCDStepMode +} xtensaMode; + +typedef struct { + xtensaMode mode; + int DRsel; + XTMP_core core; + XTMP_tap tap; + int core_num; + jtagReg_t *jtagRegs; + void *dap; // used for ARM DAP only + bool isBig; + int dir_array_option; // used by pre-ER devices only + // for testing, below - FIXME - delete later + int ocdReg; + unsigned int wr_data; + XTMP_event start_OCD_trans; + bool data_cycle; + bool data_pending; +} coreSlaveData_t; + + +enum OCD_ACCESS_TYPE{ + NEXUS_ACCESS, + CS_ACCESS, +}; + +// pre-ER Xtensa initializiation +EXTERN XTMP_deviceStatus +XTMP_jtagCoreSlaveEX(XTMP_component component, XTMP_jtagSlave slave, void* mydata); + +extern char *OCDrd; +extern char *OCDwr; + +#endif diff --git a/components/esp32/include/xtensa/lcd-splc780d-4bitmode-board.h b/components/esp32/include/xtensa/lcd-splc780d-4bitmode-board.h new file mode 100755 index 0000000000..f4db588582 --- /dev/null +++ b/components/esp32/include/xtensa/lcd-splc780d-4bitmode-board.h @@ -0,0 +1,62 @@ +/******************************************************************************* +Copyright (c) 2009-2013 by Tensilica Inc. ALL RIGHTS RESERVED. +These coded instructions, statements, and computer programs are the +copyrighted works and confidential proprietary information of Tensilica Inc. +They may not be modified, copied, reproduced, distributed, or disclosed to +third parties in any manner, medium, or form, in whole or in part, without +the prior written consent of Tensilica Inc. +-------------------------------------------------------------------------------- + +lcd-splc780d-4bitmode-board.h Board-specific LCD info for these boards: + Avnet AV110 (XT-AV110) + Xilinx ML605 (XT-ML605) + Xilinx KC705 (XT-KC705) + +Interface between board-independent driver and board-specific header. + +This is used by a board-independent SPLC780D LCD controller (4 bit mode) +driver to obtain board-specific information about LCD displays on the board, +such as the controller register base address and spacing (a function of how +the address lines are connected on the board) and length of the visible window +of the display (a function of the LCD panel the controller drives). +The driver doesnot refer directly to the board-specific header, which therefore is not +constrained to use macro names consistent with other boards. + +!! Must not contain any board-specific macro names (only controller specific) !! + +Included at compile-time via an include path specific to the board. + +The listed boards contain a single MYTech MOC-16216B-B display driven by +a Sunplus SPLC870D controller. + +*******************************************************************************/ + +#ifndef _LCD_SPLC780D_4BIT_BOARD_H +#define _LCD_SPLC780D_4BIT_BOARD_H + +#include /* Board info */ + + +/* Base address of the controller's registers. */ +#ifdef SPLC780D_4BIT_VADDR +#define SPLC780D_4BIT_REGBASE SPLC780D_4BIT_VADDR +#endif + +/* +The controller's registers are connected at word addresses on these boards. +Each byte-wide register appears as the least-significant-byte (LSB) of the +word regardless of the endianness of the processor (so if using word accesses +then endianness doesn't matter). +*/ +#define SPLC780D_4BIT_REGSPACING 4 +typedef unsigned splc780d_4bit_reg_t; + +/* Include generic information shared by all boards that use this device. */ +#include + + +/* Display limits of the LCD panel. */ +#define DISPLAY_VISIBLE_LEN 16 /* length (chars) of visible window */ + +#endif /* _LCD_SPLC780D_4BIT_BOARD_H */ + diff --git a/components/esp32/include/xtensa/lcd-splc780d-4bitmode.h b/components/esp32/include/xtensa/lcd-splc780d-4bitmode.h new file mode 100755 index 0000000000..0a214bb400 --- /dev/null +++ b/components/esp32/include/xtensa/lcd-splc780d-4bitmode.h @@ -0,0 +1,105 @@ +/******************************************************************************* + +Copyright (c) 2009-2010 by Tensilica Inc. ALL RIGHTS RESERVED. +These coded instructions, statements, and computer programs are the +copyrighted works and confidential proprietary information of Tensilica Inc. +They may not be modified, copied, reproduced, distributed, or disclosed to +third parties in any manner, medium, or form, in whole or in part, without +the prior written consent of Tensilica Inc. +-------------------------------------------------------------------------------- + +lcd-SPLC780D-4bitmode.h Generic definitions for Sunplus SPLC780D LCD Controller +operating in 4 bit mode. + +This is used by board-support-packages with one or more LCD displays that use +a SPLC780D controller in 4 bit mode. A BSP provides a base address for each +instance of an SPLC780D LCD controller on the board. + +Note that LCD display operation is almost totally independent of the LCD +display, depending almost entirely on the controller. However the display +may limit the number of characters of the controller's RAM buffer that are +actually visible at one time. The length of the display's visible window +is not specifified in this controller-specific header, but comes to the +driver from the board-specific "display.h" header. + +*******************************************************************************/ + +#ifndef _LCD_SPLC780D_4BIT_H_ +#define _LCD_SPLC780D_4BIT_H_ + + +/* Offsets to controller registers from base. */ +#define SPLC780D_4BIT_INST 0 +#define SPLC780D_4BIT_DATA (SPLC780D_4BIT_INST + SPLC780D_4BIT_REGSPACING) + + +#define SPLC780D_4BIT_INST_INIT1 0xFF /* First command in + init sequence */ +#define SPLC780D_4BIT_INST_INIT2 0x30 /* Second command in + init sequence, + issued 3 times */ +#define SPLC780D_4BIT_INST_INIT3 0x20 /* Third and last command + in init sequence */ +#define SPLC780D_4BIT_INST_CLEAR 0x01 /* clear (blank) display) */ +#define SPLC780D_4BIT_INST_SET_MODE 0x28 /* Set LCD mode. Supported + setting is 4 bit data + length, 2 lines, 5*8 */ +#define SPLC780D_4BIT_INST_DSPLY_ON 0x0C /* Set Display ON */ +#define SPLC780D_4BIT_INST_CRSR_INC 0x06 /* Set cursor moving direction + as increment */ + +#define SPLC780D_4BIT_LINET_ADDR 0x80 /* clear (blank) display) */ +#define SPLC780D_4BIT_LINEB_ADDR 0xC0 /* clear (blank) display) */ + +#ifndef __ASSEMBLER__ + +/* C interface to controller registers. */ +struct splc780d_4bit_s { + splc780d_4bit_reg_t inst; /* instruction register */ + splc780d_4bit_reg_t data; /* data register */ +}; + +typedef volatile struct splc780d_4bit_s splc780d_4bit_t; + +/* +Prototypes of high level driver functions. +*/ + +/* Write an instruction byte to LCD, result in two back to back writes since the + * LCD is hooked up in 4 bit mode*/ +extern void lcd_write_inst_byte(splc780d_4bit_t *lcd, unsigned char inst); + +/* Write a data byte to LCD, result in two back to back writes since the + * LCD is hooked up in 4 bit mode*/ +extern void lcd_write_data_byte(splc780d_4bit_t *lcd, unsigned char data); + +/* +Initialize the display with default settings. +*/ +extern void splc780d_4bit_init_default(splc780d_4bit_t *lcd); + +/* +Write a single character at a given position (chars from left, starting at 0). +Wait long enough afterward for the controller to be ready for more input. +Positions beyond the end of the display are ignored. +*/ +extern void splc780d_4bit_write_char(splc780d_4bit_t *lcd, unsigned pos, const char c); + +/* +Write a string to the display starting at the left (position 0). +Blank-pad to or truncate at the end of the display (overwrites any previous +string so don't need to blank the display first). +Wait long enough after each char for the controller to be ready for more input. +*/ +extern void splc780d_4bit_write_string(splc780d_4bit_t *lcd, const char *s); + +/* +Blank (clear) the entire display. +Wait long enough afterward for the controller to be ready for more input. +*/ +extern void splc780d_4bit_blank(splc780d_4bit_t *lcd); + +#endif /* __ASSEMBLER__ */ + +#endif /* _LCD_SPLC780D_4BIT_H_ */ + diff --git a/components/esp32/include/xtensa/lcd-splc780d.h b/components/esp32/include/xtensa/lcd-splc780d.h new file mode 100755 index 0000000000..4e878e9053 --- /dev/null +++ b/components/esp32/include/xtensa/lcd-splc780d.h @@ -0,0 +1,151 @@ +/******************************************************************************* + +Copyright (c) 2006-2007 by Tensilica Inc. ALL RIGHTS RESERVED. +These coded instructions, statements, and computer programs are the +copyrighted works and confidential proprietary information of Tensilica Inc. +They may not be modified, copied, reproduced, distributed, or disclosed to +third parties in any manner, medium, or form, in whole or in part, without +the prior written consent of Tensilica Inc. +-------------------------------------------------------------------------------- + +lcd-SPLC780D.h Generic definitions for Sunplus SPLC780D LCD Controller + +This is used by board-support-packages with one or more LCD displays that use +a SPLC780D controller. A BSP provides a base address for each instance of an +SPLC780D LCD controller on the board. + +Note that LCD display operation is almost totally independent of the LCD +display, depending almost entirely on the controller. However the display +may limit the number of characters of the controller's RAM buffer that are +actually visible at one time. The length of the display's visible window +is not specifified in this controller-specific header, but comes to the +driver from the board-specific "display.h" header. + +*******************************************************************************/ + +#ifndef _LCD_SPLC780D_H_ +#define _LCD_SPLC780D_H_ + + +/* Offsets to controller registers from base. */ +#define SPLC780D_INST 0 +#define SPLC780D_DATA (SPLC780D_INST + SPLC780D_REGSPACING) + +/* +Bit fields and their values in the instruction register. +These fields are NOT orthogonal - they overlap! +Thus only one field may be written at a time, determined by the +most-significant 1 bit in the pattern (the field selector). +All less significant bits are part of the value of the selected field. +The fields and their values are grouped together to emphasize this format. +Field selector macro names end in '_' (implying something more needs +to be ORed) and the value macros are indented. The pattern written to a +bitfield is a bitwise OR of a field selector and one or more values, eg. + (SPLC780D_INST_ON_ | SPLC780D_INST_ON_DISPLAY | SPLC780D_INST_ON_CURSOR) +A single bit field (eg. SPCL780D_INST_HOME) need not have a value. + +NOTE: Controller requires a software delay after writing to the control +or data registers. For the data register it is 38us. For the control +register it is 38us for most bit fields, with the following exceptions: + SPLC780D_FUNC_ 100us. + SPLC780D_INST_CLEAR, SPLC780D_INST_HOME 1520us. +For more details and reset timing, see the SUNPLUS SPLC780D data sheet. +*/ + +#define SPLC780D_INST_CLEAR_ 0x1 /* clear (blank) display) */ + +#define SPLC780D_INST_HOME_ 0x2 /* home cursor and shift pos */ + +#define SPLC780D_INST_ENTRY_ 0x4 /* combine *ENTRY_* flags below */ +#define SPLC780D_INST_ENTRY_SHIFT 0x1 /* display shift on entry / not */ +#define SPLC780D_INST_ENTRY_INCR 0x2 /* cursor incr / decr */ +#define SPLC780D_INST_ENTRY_DECR 0 /* cursor incr / decr */ + +#define SPLC780D_INST_ON_ 0x8 /* combine *ON_* flags below */ +#define SPLC780D_INST_ON_DISPLAY 0x4 /* display on / off */ +#define SPLC780D_INST_ON_CURSOR 0x2 /* cursor on / off */ +#define SPLC780D_INST_ON_BLINK 0x1 /* blink on / off */ + +#define SPLC780D_INST_SHIFT_ 0x10 /* combine *SHIFT_* flags below */ +#define SPLC780D_INST_SHIFT_DISP 0x8 /* shift display / move cursor */ +#define SPLC780D_INST_SHIFT_CURS 0 /* shift display / move cursor */ +#define SPLC780D_INST_SHIFT_RIGHT 0x4 /* shift right / left */ +#define SPLC780D_INST_SHIFT_LEFT 0 /* shift right / left */ + +#define SPLC780D_INST_FUNC_ 0x20 /* combine *FUNC_* flags below */ +#define SPLC780D_INST_FUNC_8BIT 0x10 /* data length 8 bit / 4 bit */ +#define SPLC780D_INST_FUNC_4BIT 0 /* data length 8 bit / 4 bit */ +#define SPLC780D_INST_FUNC_2LINE 0x08 /* display lines 2 / 1 */ +#define SPLC780D_INST_FUNC_1LINE 0 /* display lines 2 / 1 */ +#define SPLC780D_INST_FUNC_F5x10 0x04 /* character font 5x10 / 5x8 */ +#define SPLC780D_INST_FUNC_F5x8 0 /* character font 5x10 / 5x8 */ + /* font must be 5x8 for 2 lines */ +#define SPLC780D_INST_CGEN_ 0x40 /* set char generator address */ +#define SPLC780D_INST_CGEN_ADDR 0x3F /* to address in this field */ +#define SPLC780D_INST_DRAM_ 0x80 /* set display data RAM address */ +#define SPLC780D_INST_DRAM_ADDR 0x7F /* to address in this field */ +#define SPLC780D_INST_DRAM_LINE2 0x40 /* address offset to line 2 */ +/* Controller limits */ +#define SPLC780D_RAMLEN_1LINE 0x50 /* length of line in RAM (1 line) */ +#define SPLC780D_RAMLEN_2LINE 0x28 /* length of line in RAM (2 line) */ + + +#ifndef __ASSEMBLER__ + +/* C interface to controller registers. */ +struct splc780d_s { + splc780d_reg_t inst; /* instruction register */ + splc780d_reg_t data; /* data register */ +}; + +typedef volatile struct splc780d_s splc780d_t; + +/* +Prototypes of high level driver functions. +*/ + +/* +Initialize the display with the FUNC_, ENTRY_ and ON_ fields as specified in +terms of the values above. The splc780d_init_default() macro is an example. +*/ +extern void splc780d_init(splc780d_t *lcd, + unsigned func, unsigned entry, unsigned on); + +/* +Initialize the display to default mode: 8-bit interface, 2 line, 5x8 font, +increment cursor on entry, display on (cursor and blinking off). +*/ +#define splc780d_init_default(lcd) \ + splc780d_init( lcd, \ + SPLC780D_INST_FUNC_8BIT \ + | SPLC780D_INST_FUNC_2LINE \ + | SPLC780D_INST_FUNC_F5x8, \ + SPLC780D_INST_ENTRY_INCR, \ + SPLC780D_INST_ON_DISPLAY \ + ) + +/* +Write a single character at a given position (chars from left, starting at 0). +Wait long enough afterward for the controller to be ready for more input. +Positions beyond the end of the display are ignored. +*/ +extern void splc780d_write_char(splc780d_t *lcd, unsigned pos, const char c); + +/* +Write a string to the display starting at the left (position 0). +Blank-pad to or truncate at the end of the display (overwrites any previous +string so don't need to blank the display first). +Wait long enough after each char for the controller to be ready for more input. +*/ +extern void splc780d_write_string(splc780d_t *lcd, const char *s); + +/* +Blank (clear) the entire display. +Wait long enough afterward for the controller to be ready for more input. +*/ +extern void splc780d_blank(splc780d_t *lcd); + +#endif /* __ASSEMBLER__ */ + +#endif /* _LCD_SPLC780D_H_ */ + diff --git a/components/esp32/include/xtensa/overlay.h b/components/esp32/include/xtensa/overlay.h new file mode 100755 index 0000000000..e959cf512f --- /dev/null +++ b/components/esp32/include/xtensa/overlay.h @@ -0,0 +1,184 @@ +// overlay.h -- Overlay manager header file +// $Id$ + +// Copyright (c) 2013 Tensilica Inc. +// +// Permission is hereby granted, free of charge, to any person obtaining +// a copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to +// permit persons to whom the Software is furnished to do so, subject to +// the following conditions: +// +// The above copyright notice and this permission notice shall be included +// in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +// CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +// SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + + +#ifndef OVERLAY_H +#define OVERLAY_H + + +#include + + +#ifdef __cplusplus +extern "C" { +#endif + +// Define this to turn off overlay support +#ifdef XT_DISABLE_OVERLAYS + +#define OVERLAY(n) +#define DECLARE_OVERLAY(n) + +#define xt_overlay_map(ov_id) +#define xt_overlay_map_async(ov_id) 0 +#define xt_overlay_map_in_progress() 0 +#define xt_overlay_get_id() 0 +#define xt_overlay_get_state(pc) 0 +#define xt_overlay_check_map(pc,ps,ovstate,sp) 0 + +#else + +// Shorthand for convenience and portability. +#define OVERLAY(n) __attribute__((overlay(n))) + +// Structure of the overlay table required by gdb and the overlay +// manager. Should not be accessed by user code unless overriding +// the load process. +struct ovly_table { + void * vma; // The overlay's mapped address. + unsigned int size; // The size of the overlay, in bytes. + void * lma; // The overlay's load address. + unsigned int mapped; // Non-zero if overlay is currently mapped; zero otherwise. +}; + +// Constructed by the linker. Required for gdb and for the overlay +// manager. Should not be accessed by user code unless overriding +// the load process. +extern struct ovly_table _ovly_table[]; + +// Functions. +void xt_overlay_map(int ov_id); +int xt_overlay_map_async(int ov_id); +int xt_overlay_map_in_progress(void); +unsigned int xt_overlay_get_state(unsigned int pc); +unsigned int xt_overlay_check_map(unsigned int * pc, unsigned int * ps, + unsigned int ovstate, unsigned int sp); +int xt_overlay_start_map(void * dst, void * src, unsigned int len, int ov_id); +int xt_overlay_is_mapping(int ov_id); +void xt_overlay_fatal_error(int ov_id); + + +// Returns the current overlay ID. If no overlay is mapped or an overlay +// is in the middle of being mapped, returns -1. Inlined to avoid calling +// out of overlay (wastes cycles, can end up reading wrong ID on interrupt +// activity). +// +static inline int xt_overlay_get_id(void) +{ +#pragma always_inline +extern short _mapping_id; +extern short _ovly_id; + + int ret; + unsigned int flags = XTOS_SET_INTLEVEL(15); + + if (_mapping_id >= 0) { + ret = -1; + } + else { + ret = _ovly_id; + } + + XTOS_RESTORE_INTLEVEL(flags); + return ret; +} + + +// The following macros are used to declare numbered overlays and generate +// the corresponding call stubs. Use as follows: +// +// DECLARE_OVERLAY(n) +// +// See documentation for more details. + +//#include + +// At this time overlays are not supported without windowing. +#if defined(__XTENSA_WINDOWED_ABI__) + +#define xstr(x) str(x) +#define str(x) #x + +// At entry, register a8 holds the return address and a9 holds the target +// function address. This stub saves a8 on the stack at (SP - 20) which +// is the only location that is safe for us to use. Then it allocates 32 +// bytes on the stack for working storage, loads the overlay number into +// a8, and jumps to the common handler. The common handler will make sure +// that the called function is loaded into memory before calling it. +// NOTE: we are using the stack area normally reserved for nested functions. +// This means nested functions cannot be used when overlays are in use. + +#define CALL_IN(num) \ + asm(".section .gnu.linkonce.t.overlay.call." xstr(num) ".text, \"ax\"\n" \ + ".global _overlay_call_in_" xstr(num) "_\n" \ + ".align 4\n" \ + "_overlay_call_in_" xstr(num) "_:\n" \ + "s32e a8, a1, -20\n" \ + "addi a8, a1, -32\n" \ + "movsp a1, a8\n" \ + "movi a8, " xstr(num) "\n" \ + "j _overlay_call_in_common\n" \ + ".size _overlay_call_in_" xstr(num) "_, . - _overlay_call_in_" xstr(num) "_\n"); + +// The call-out stub first calls the target function, then loads the overlay +// number into register a14 and jumps to the common handler. The handler will +// make sure that the caller function is present in memory before returning. +// Note that registers a10-a13 may contain return values so must be preserved. +// +// Because we came here via a call4, the return address is in a4, and the top +// 2 bits are set to the window increment. We'll restore the top 2 bits of +// the return address from the called function's address, assuming that both +// are in the same 1 GB segment. For now this is always true. + +#define CALL_OUT(num) \ + asm(".section .gnu.linkonce.t.overlay.call." xstr(num) ".text, \"ax\"\n" \ + ".global _overlay_call_out_" xstr(num) "_\n" \ + ".align 4\n" \ + "_overlay_call_out_" xstr(num) "_:\n" \ + "slli a4, a4, 2\n" \ + "srli a4, a4, 2\n" \ + "extui a8, a9, 30, 2\n" \ + "slli a8, a8, 30\n" \ + "or a4, a4, a8\n" \ + "callx8 a9\n" \ + "movi a14, " xstr(num) "\n" \ + "j _overlay_call_out_common\n" \ + ".size _overlay_call_out_" xstr(num) "_, . - _overlay_call_out_" xstr(num) "_\n"); + +// Generate a call-in and a call-out stub for each overlay. + +#define DECLARE_OVERLAY(num) \ + CALL_IN(num) \ + CALL_OUT(num) + +#endif // defined(__XTENSA_WINDOWED_ABI__) + +#endif // XT_DISABLE_OVERLAYS + +#ifdef __cplusplus +} +#endif + +#endif // OVERLAY_H + diff --git a/components/esp32/include/xtensa/overlay_os_asm.h b/components/esp32/include/xtensa/overlay_os_asm.h new file mode 100755 index 0000000000..4adc044e6a --- /dev/null +++ b/components/esp32/include/xtensa/overlay_os_asm.h @@ -0,0 +1,140 @@ +// overlay_os_asm.h -- Overlay manager assembly macros for OS use. +// $Id$ + +// Copyright (c) 2013 Tensilica Inc. +// +// Permission is hereby granted, free of charge, to any person obtaining +// a copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to +// permit persons to whom the Software is furnished to do so, subject to +// the following conditions: +// +// The above copyright notice and this permission notice shall be included +// in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +// CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +// SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + + +#ifndef OVERLAY_OS_ASM_H +#define OVERLAY_OS_ASM_H + +// The macros in here are intended to be used by RTOS task switch code +// to check overlay status. Such code is usually in assembly and cannot +// call C code without penalty. For C code usage, it is best to use the +// corresponding C functions from the library. + + +// Inline assembly version of xt_overlay_get_state(). The arguments are +// three AR registers (a0-a15): +// +// "pcreg" - should contain the outgoing task's PC, i.e. the point at +// which the task got interrupted. The return value is also +// returned in this register. +// "sr1/2" - Scratch registers. These must be distinct from "pcreg". +// +// The return value is a 32-bit result that should be saved with the +// task context and passed as-is to xt_overlay_check_map. + + .macro _xt_overlay_get_state pcreg sr1 sr2 + + movi \sr1, _mapping_id + movi \sr2, _ovly_id + l16si \sr1, \sr1, 0 + l16ui \sr2, \sr2, 0 + slli \sr1, \sr1, 16 + or \pcreg, \sr1, \sr2 + + .endm + + +// Inline assembly version of xt_overlay_check_map(). It requires 5 AR +// registers (a0-a15) as arguments. +// +// "pcreg" - should contain the interrupted task's PC, i.e. the point +// at which the task got interrupted. This will be adjusted +// if required. +// "psreg" - should contain the interrupted task's PS. This will be +// adjusted if required. +// "ovreg" - should contain the overlay state on entry. Contents may +// be clobbered. +// "spreg" - should contain the tasks stack pointer on entry. +// "sr1" - Scratch register. Must be distinct from any of the above. +// +// The return values are "pcreg" and "psreg" and these must be used +// to update the task's PC and PS. +// Note that this macro may store data below the "spreg" pointer. If +// it does, then it will also disable interrupts via the PS, so that +// the task resumes with all interrupts disabled (to avoid corrupting +// this data). +// +// (SP - 24) Overlay ID to restore +// (SP - 28) Task PC +// (SP - 32) Task PS + + .macro _xt_overlay_check_map pcreg psreg ovreg spreg sr1 + +// There are four cases to deal with: +// +// _ovly_id = -1, _mapping_id = -1 +// No overlay is mapped or mapping, nothing to do. +// +// _ovly_id >= 0, _mapping_id = -1 +// An overlay was mapped, check PC to see if we need a restore. +// +// _ovly_id = -1, _mapping_id >= 0 +// An overlay is being mapped. Either it belongs to this task, which +// implies that the PC is in the mapping function, or it does not +// belong to this task. Either way there is nothing to do. +// +// _ovly_id >= 0, _mapping_id >= 0 +// Illegal, cannot happen by design. Don't need to handle this. +// +// So, the logic is to check _ovly_id first. If this is >= 0, then +// we check the task PC. If the PC is in the regions of interest then +// we'll patch the return PC to invoke xt_overlay_restore. + +.L1: + extui \sr1, \ovreg, 0, 16 // Extract _ovly_id + bbsi.l \sr1, 15, .Lno // If -1 then we're done + mov \ovreg, \sr1 // Restore this one + +// Next check the PC to see if it falls within the ranges of interest. + +.L2: + movi \sr1, _overlay_vma // Is PC < VMA range ? + bltu \pcreg, \sr1, .L3 + movi \sr1, _overlay_vma_end // Is PC > VMA range ? + bgeu \pcreg, \sr1, .L3 + j .L4 // PC is in VMA range +.L3: + movi \sr1, _overlay_call_stubs_start // Is PC < call stubs range ? + bltu \pcreg, \sr1, .Lno + movi \sr1, _overlay_call_stubs_end // Is PC > call stubs range ? + bgeu \pcreg, \sr1, .Lno + +// If we get here then a restore is needed. Save the overlay ID, PC and PS. +// Return modified PC and PS so that xt_overlay_restore() will execute in +// the context of the task when resumed. Note that the OS resumption code +// may expect PS.EXCM to be set so we leave it as is in the return value. + +.L4: + s32e \ovreg, \spreg, -24 // Save overlay ID + s32e \pcreg, \spreg, -28 // Save task PC + s32e \psreg, \spreg, -32 // Save task PS + movi \pcreg, xt_overlay_restore // Adjust resumption PC + movi \sr1, 15 + or \psreg, \psreg, \sr1 // Set intlevel to highest +.Lno: + + .endm + +#endif // OVERLAY_OS_ASM_H + diff --git a/components/esp32/include/xtensa/sim.h b/components/esp32/include/xtensa/sim.h new file mode 100755 index 0000000000..e02087c5c0 --- /dev/null +++ b/components/esp32/include/xtensa/sim.h @@ -0,0 +1,60 @@ +/* Copyright (c) 2004-2006 by Tensilica Inc. ALL RIGHTS RESERVED. +/ These coded instructions, statements, and computer programs are the +/ copyrighted works and confidential proprietary information of Tensilica Inc. +/ They may not be modified, copied, reproduced, distributed, or disclosed to +/ third parties in any manner, medium, or form, in whole or in part, without +/ the prior written consent of Tensilica Inc. +*/ + +/* sim.h + * + * Definitions and prototypes for specific ISS SIMCALLs + * (ie. outside the standard C library). + */ + +#ifndef _INC_SIM_H_ +#define _INC_SIM_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +/* Shortcuts for enabling/disabling profiling in the Xtensa ISS */ +extern void xt_iss_profile_enable(void); +extern void xt_iss_profile_disable(void); + +/* Shortcut for setting the trace level in the Xtensa ISS */ +extern void xt_iss_trace_level(unsigned level); + +/* Generic interface for passing client commands in the Xtensa ISS: + * returns 0 on success, -1 on failure. + */ +extern int xt_iss_client_command(const char *client, const char *command); + +/* Interface for switching simulation modes in the Xtensa ISS: + * returns 0 on success, -1 on failure. + */ +#define XT_ISS_CYCLE_ACCURATE 0 +#define XT_ISS_FUNCTIONAL 1 +extern int xt_iss_switch_mode(int mode); + + +/* Interface for waiting on a system synchronization event */ +extern void xt_iss_event_wait(unsigned event_id); + +/* Interface for firing a system synchronization event */ +extern void xt_iss_event_fire(unsigned event_id); + +/* Interface for invoking a user simcall action, + * which can be registered in XTMP or XTSC. + */ +extern int xt_iss_simcall(int arg1, int arg2, int arg3, + int arg4, int arg5, int arg6); + + +#ifdef __cplusplus +} +#endif + +#endif /*_INC_SIM_H_*/ + diff --git a/components/esp32/include/xtensa/simboard.h b/components/esp32/include/xtensa/simboard.h new file mode 100755 index 0000000000..980b0b7596 --- /dev/null +++ b/components/esp32/include/xtensa/simboard.h @@ -0,0 +1,71 @@ +/* + * Copyright (c) 2001 Tensilica Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY + * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +/* simboard.h - Xtensa ISS "Board" specific definitions */ + +#ifndef _INC_SIMBOARD_H_ +#define _INC_SIMBOARD_H_ + +#include +#include + + +/* + * Device addresses. + */ + +/* System ROM: */ +#define XTBOARD_ROM_SIZE XSHAL_ROM_SIZE +#ifdef XSHAL_ROM_VADDR +#define XTBOARD_ROM_VADDR XSHAL_ROM_VADDR +#endif +#ifdef XSHAL_ROM_PADDR +#define XTBOARD_ROM_PADDR XSHAL_ROM_PADDR +#endif + +/* System RAM: */ +#define XTBOARD_RAM_SIZE XSHAL_RAM_SIZE +#ifdef XSHAL_RAM_VADDR +#define XTBOARD_RAM_VADDR XSHAL_RAM_VADDR +#endif +#ifdef XSHAL_RAM_PADDR +#define XTBOARD_RAM_PADDR XSHAL_RAM_PADDR +#endif + + +/* + * Things that depend on device addresses. + */ + +#define XTBOARD_CACHEATTR_WRITEBACK XSHAL_ISS_CACHEATTR_WRITEBACK +#define XTBOARD_CACHEATTR_WRITEALLOC XSHAL_ISS_CACHEATTR_WRITEALLOC +#define XTBOARD_CACHEATTR_WRITETHRU XSHAL_ISS_CACHEATTR_WRITETHRU +#define XTBOARD_CACHEATTR_BYPASS XSHAL_ISS_CACHEATTR_BYPASS +#define XTBOARD_CACHEATTR_DEFAULT XSHAL_ISS_CACHEATTR_DEFAULT + +#define XTBOARD_BUSINT_PIPE_REGIONS 0 +#define XTBOARD_BUSINT_SDRAM_REGIONS 0 + + +#endif /*_INC_SIMBOARD_H_*/ + diff --git a/components/esp32/include/xtensa/simcall-errno.h b/components/esp32/include/xtensa/simcall-errno.h new file mode 100755 index 0000000000..445ec90135 --- /dev/null +++ b/components/esp32/include/xtensa/simcall-errno.h @@ -0,0 +1,139 @@ +/* Error numbers for Xtensa ISS semihosting. */ + +/* Copyright (c) 2003 by Tensilica Inc. ALL RIGHTS RESERVED. + These coded instructions, statements, and computer programs are the + copyrighted works and confidential proprietary information of Tensilica Inc. + They may not be modified, copied, reproduced, distributed, or disclosed to + third parties in any manner, medium, or form, in whole or in part, without + the prior written consent of Tensilica Inc. */ + +#ifndef _SIMCALL_ERRNO_H +#define _SIMCALL_ERRNO_H + +/* Define the error numbers (using the default newlib values) with prefixes + so they can be used in ISS without conflicting with the host values. */ + +#define _SIMC_EPERM 1 +#define _SIMC_ENOENT 2 +#define _SIMC_ESRCH 3 +#define _SIMC_EINTR 4 +#define _SIMC_EIO 5 +#define _SIMC_ENXIO 6 +#define _SIMC_E2BIG 7 +#define _SIMC_ENOEXEC 8 +#define _SIMC_EBADF 9 +#define _SIMC_ECHILD 10 +#define _SIMC_EAGAIN 11 +#define _SIMC_ENOMEM 12 +#define _SIMC_EACCES 13 +#define _SIMC_EFAULT 14 +#define _SIMC_ENOTBLK 15 +#define _SIMC_EBUSY 16 +#define _SIMC_EEXIST 17 +#define _SIMC_EXDEV 18 +#define _SIMC_ENODEV 19 +#define _SIMC_ENOTDIR 20 +#define _SIMC_EISDIR 21 +#define _SIMC_EINVAL 22 +#define _SIMC_ENFILE 23 +#define _SIMC_EMFILE 24 +#define _SIMC_ENOTTY 25 +#define _SIMC_ETXTBSY 26 +#define _SIMC_EFBIG 27 +#define _SIMC_ENOSPC 28 +#define _SIMC_ESPIPE 29 +#define _SIMC_EROFS 30 +#define _SIMC_EMLINK 31 +#define _SIMC_EPIPE 32 +#define _SIMC_EDOM 33 +#define _SIMC_ERANGE 34 +#define _SIMC_ENOMSG 35 +#define _SIMC_EIDRM 36 +#define _SIMC_ECHRNG 37 +#define _SIMC_EL2NSYNC 38 +#define _SIMC_EL3HLT 39 +#define _SIMC_EL3RST 40 +#define _SIMC_ELNRNG 41 +#define _SIMC_EUNATCH 42 +#define _SIMC_ENOCSI 43 +#define _SIMC_EL2HLT 44 +#define _SIMC_EDEADLK 45 +#define _SIMC_ENOLCK 46 +#define _SIMC_EBADE 50 +#define _SIMC_EBADR 51 +#define _SIMC_EXFULL 52 +#define _SIMC_ENOANO 53 +#define _SIMC_EBADRQC 54 +#define _SIMC_EBADSLT 55 +#define _SIMC_EDEADLOCK 56 +#define _SIMC_EBFONT 57 +#define _SIMC_ENOSTR 60 +#define _SIMC_ENODATA 61 +#define _SIMC_ETIME 62 +#define _SIMC_ENOSR 63 +#define _SIMC_ENONET 64 +#define _SIMC_ENOPKG 65 +#define _SIMC_EREMOTE 66 +#define _SIMC_ENOLINK 67 +#define _SIMC_EADV 68 +#define _SIMC_ESRMNT 69 +#define _SIMC_ECOMM 70 +#define _SIMC_EPROTO 71 +#define _SIMC_EMULTIHOP 74 +#define _SIMC_ELBIN 75 +#define _SIMC_EDOTDOT 76 +#define _SIMC_EBADMSG 77 +#define _SIMC_EFTYPE 79 +#define _SIMC_ENOTUNIQ 80 +#define _SIMC_EBADFD 81 +#define _SIMC_EREMCHG 82 +#define _SIMC_ELIBACC 83 +#define _SIMC_ELIBBAD 84 +#define _SIMC_ELIBSCN 85 +#define _SIMC_ELIBMAX 86 +#define _SIMC_ELIBEXEC 87 +#define _SIMC_ENOSYS 88 +#define _SIMC_ENMFILE 89 +#define _SIMC_ENOTEMPTY 90 +#define _SIMC_ENAMETOOLONG 91 +#define _SIMC_ELOOP 92 +#define _SIMC_EOPNOTSUPP 95 +#define _SIMC_EPFNOSUPPORT 96 +#define _SIMC_ECONNRESET 104 +#define _SIMC_ENOBUFS 105 +#define _SIMC_EAFNOSUPPORT 106 +#define _SIMC_EPROTOTYPE 107 +#define _SIMC_ENOTSOCK 108 +#define _SIMC_ENOPROTOOPT 109 +#define _SIMC_ESHUTDOWN 110 +#define _SIMC_ECONNREFUSED 111 +#define _SIMC_EADDRINUSE 112 +#define _SIMC_ECONNABORTED 113 +#define _SIMC_ENETUNREACH 114 +#define _SIMC_ENETDOWN 115 +#define _SIMC_ETIMEDOUT 116 +#define _SIMC_EHOSTDOWN 117 +#define _SIMC_EHOSTUNREACH 118 +#define _SIMC_EINPROGRESS 119 +#define _SIMC_EALREADY 120 +#define _SIMC_EDESTADDRREQ 121 +#define _SIMC_EMSGSIZE 122 +#define _SIMC_EPROTONOSUPPORT 123 +#define _SIMC_ESOCKTNOSUPPORT 124 +#define _SIMC_EADDRNOTAVAIL 125 +#define _SIMC_ENETRESET 126 +#define _SIMC_EISCONN 127 +#define _SIMC_ENOTCONN 128 +#define _SIMC_ETOOMANYREFS 129 +#define _SIMC_EPROCLIM 130 +#define _SIMC_EUSERS 131 +#define _SIMC_EDQUOT 132 +#define _SIMC_ESTALE 133 +#define _SIMC_ENOTSUP 134 +#define _SIMC_ENOMEDIUM 135 +#define _SIMC_ENOSHARE 136 +#define _SIMC_ECASECLASH 137 +#define _SIMC_EILSEQ 138 +#define _SIMC_EOVERFLOW 139 + +#endif /* ! _SIMCALL_ERRNO_H */ diff --git a/components/esp32/include/xtensa/simcall-fcntl.h b/components/esp32/include/xtensa/simcall-fcntl.h new file mode 100755 index 0000000000..1c03f5595e --- /dev/null +++ b/components/esp32/include/xtensa/simcall-fcntl.h @@ -0,0 +1,21 @@ +/* File control operations for Xtensa ISS semihosting. */ + +/* Copyright (c) 2003 by Tensilica Inc. ALL RIGHTS RESERVED. + These coded instructions, statements, and computer programs are the + copyrighted works and confidential proprietary information of Tensilica Inc. + They may not be modified, copied, reproduced, distributed, or disclosed to + third parties in any manner, medium, or form, in whole or in part, without + the prior written consent of Tensilica Inc. */ + +#ifndef _SIMCALL_FCNTL_H +#define _SIMCALL_FCNTL_H + +#define _SIMC_O_APPEND 0x0008 +#define _SIMC_O_NONBLOCK 0x0080 +#define _SIMC_O_CREAT 0x0100 +#define _SIMC_O_TRUNC 0x0200 +#define _SIMC_O_EXCL 0x0400 +#define _SIMC_O_TEXT 0x4000 +#define _SIMC_O_BINARY 0x8000 + +#endif /* ! _SIMCALL_FCNTL_H */ diff --git a/components/esp32/include/xtensa/simcall.h b/components/esp32/include/xtensa/simcall.h new file mode 100755 index 0000000000..d71959eea7 --- /dev/null +++ b/components/esp32/include/xtensa/simcall.h @@ -0,0 +1,189 @@ +/* + * simcall.h - Simulator call numbers + * + * Software that runs on a simulated Xtensa processor using + * the instruction set simulator (ISS) can invoke simulator + * services using the SIMCALL instruction. The a2 register + * is set prior to executing SIMCALL to a "simcall number", + * indicating which service to invoke. This file defines the + * simcall numbers defined and/or supported by the Xtensa ISS. + * + * IMPORTANT NOTE: These numbers are highly subject to change! + * + * Copyright (c) 2002-2007 by Tensilica Inc. ALL RIGHTS RESERVED. + * These coded instructions, statements, and computer programs are the + * copyrighted works and confidential proprietary information of Tensilica Inc. + * They may not be modified, copied, reproduced, distributed, or disclosed to + * third parties in any manner, medium, or form, in whole or in part, without + * the prior written consent of Tensilica Inc. + */ + +#ifndef SIMCALL_INCLUDED +#define SIMCALL_INCLUDED + +/* + * System call like services offered by the simulator host. + * These are modeled after the Linux 2.4 kernel system calls + * for Xtensa processors. However not all system calls and + * not all functionality of a given system call are implemented, + * or necessarily have well defined or equivalent semantics in + * the context of a simulation (as opposed to a Unix kernel). + * + * These services behave largely as if they had been invoked + * as a task in the simulator host's operating system + * (eg. files accessed are those of the simulator host). + * However, these SIMCALLs model a virtual operating system + * so that various definitions, bit assignments etc + * (eg. open mode bits, errno values, etc) are independent + * of the host operating system used to run the simulation. + * Rather these definitions are specific to the Xtensa ISS. + * This way Xtensa ISA code written to use these SIMCALLs + * can (in principle) be simulated on any host. + * + * Up to 6 parameters are passed in registers a3 to a8 + * (note the 6th parameter isn't passed on the stack, + * unlike windowed function calling conventions). + * The return value is in a2. A negative value in the + * range -4096 to -1 indicates a negated error code to be + * reported in errno with a return value of -1, otherwise + * the value in a2 is returned as is. + */ + +/* These #defines need to match what's in Xtensa/OS/vxworks/xtiss/simcalls.c */ + +#define SYS_nop 0 /* n/a - setup; used to flush register windows */ +#define SYS_exit 1 /*x*/ +#define SYS_fork 2 +#define SYS_read 3 /*x*/ +#define SYS_write 4 /*x*/ +#define SYS_open 5 /*x*/ +#define SYS_close 6 /*x*/ +#define SYS_rename 7 /*x 38 - waitpid */ +#define SYS_creat 8 /*x*/ +#define SYS_link 9 /*x (not implemented on WIN32) */ +#define SYS_unlink 10 /*x*/ +#define SYS_execv 11 /* n/a - execve */ +#define SYS_execve 12 /* 11 - chdir */ +#define SYS_pipe 13 /* 42 - time */ +#define SYS_stat 14 /* 106 - mknod */ +#define SYS_chmod 15 +#define SYS_chown 16 /* 202 - lchown */ +#define SYS_utime 17 /* 30 - break */ +#define SYS_wait 18 /* n/a - oldstat */ +#define SYS_lseek 19 /*x*/ +#define SYS_getpid 20 +#define SYS_isatty 21 /* n/a - mount */ +#define SYS_fstat 22 /* 108 - oldumount */ +#define SYS_time 23 /* 13 - setuid */ +#define SYS_gettimeofday 24 /*x 78 - getuid (not implemented on WIN32) */ +#define SYS_times 25 /*X 43 - stime (Xtensa-specific implementation) */ +#define SYS_socket 26 +#define SYS_sendto 27 +#define SYS_recvfrom 28 +#define SYS_select_one 29 /* not compitible select, one file descriptor at the time */ +#define SYS_bind 30 +#define SYS_ioctl 31 + +/* + * Other... + */ +#define SYS_iss_argc 1000 /* returns value of argc */ +#define SYS_iss_argv_size 1001 /* bytes needed for argv & arg strings */ +#define SYS_iss_set_argv 1002 /* saves argv & arg strings at given addr */ + +#define SYS_memset 1004 /* fill a range of memory (fast) */ + +/* + * SIMCALLs for the ferret memory debugger. All are invoked by + * libferret.a ... ( Xtensa/Target-Libs/ferret ) + */ +#define SYS_ferret 1010 +#define SYS_malloc 1011 +#define SYS_free 1012 +#define SYS_more_heap 1013 +#define SYS_no_heap 1014 +#define SYS_enter_ferret 1015 +#define SYS_leave_ferret 1016 + +/* + * SIMCALLs for ISS client commands + */ +#define SYS_profile_enable 1020 +#define SYS_profile_disable 1021 +#define SYS_trace_level 1022 +#define SYS_client_command 1023 + +/* + * SIMCALL for simulation mode switching + */ +#define SYS_sim_mode_switch 1030 + +/* + * SIMCALLs for XTMP/XTSC event notify and core stall + */ +#define SYS_event_fire 1040 +#define SYS_event_stall 1041 + +/* + * SIMCALLs for callbacks registered in XTMP/XTSC + */ +#define SYS_callback_first 100 +#define SYS_callback_last 999 + +/* + * User defined simcall + */ +#define SYS_user_simcall 100 + +#define SYS_xmpa_errinfo 200 +#define SYS_xmpa_proc_status 201 +#define SYS_xmpa_proc_start 202 +#define SYS_xmpa_proc_stop 203 +#define SYS_xmpa_proc_mem_read 204 +#define SYS_xmpa_proc_mem_write 205 +#define SYS_xmpa_proc_mem_fill 206 +#define SYS_xmpa_proc_reg_read 207 +#define SYS_xmpa_proc_reg_write 208 + + +/* + * Extra SIMCALLs for GDB: + */ +#define SYS_gdb_break -1 /* invoked by XTOS on user exceptions if EPC points + to a break.n/break, regardless of cause! */ +#define SYS_xmon_out -2 /* invoked by XMON: ... */ +#define SYS_xmon_in -3 /* invoked by XMON: ... */ +#define SYS_xmon_flush -4 /* invoked by XMON: ... */ +#define SYS_gdb_abort -5 /* invoked by XTOS in _xtos_panic() */ +#define SYS_gdb_illegal_inst -6 /* invoked by XTOS for illegal instructions (too deeply) */ +#define SYS_xmon_init -7 /* invoked by XMON: ... */ +#define SYS_gdb_enter_sktloop -8 /* invoked by XTOS on debug exceptions */ +#define SYS_unhandled_kernel_exc -9 /* invoked by XTOS for unhandled kernel exceptions */ +#define SYS_unhandled_user_exc -10 /* invoked by XTOS for unhandled user exceptions */ +#define SYS_unhandled_double_exc -11 /* invoked by XTOS for unhandled double exceptions */ +#define SYS_unhandled_highpri_interrupt -12 /* invoked by XTOS for unhandled high-priority interrupts */ +#define SYS_xmon_close -13 /* invoked by XMON: ... */ + +/* + * SIMCALLs for vxWorks xtiss BSP: + */ +#define SYS_setup_ppp_pipes -83 +#define SYS_log_msg -84 + +/* + * SYS_select_one specifiers + */ +#define XTISS_SELECT_ONE_READ 1 +#define XTISS_SELECT_ONE_WRITE 2 +#define XTISS_SELECT_ONE_EXCEPT 3 + +/* + * SIMCALL for client calling arbitrary code in a client plug in. + * see clients/xcc_instr to see how this works. + */ + +#define SYS_client 0xC0DECAFE + + + +#endif /* !SIMCALL_INCLUDED */ diff --git a/components/esp32/include/xtensa/specreg.h b/components/esp32/include/xtensa/specreg.h new file mode 100755 index 0000000000..0b2edee017 --- /dev/null +++ b/components/esp32/include/xtensa/specreg.h @@ -0,0 +1,143 @@ +/* + * Xtensa Special Register symbolic names + */ + +/* $Id: //depot/rel/Eaglenest/Xtensa/OS/include/xtensa/specreg.h#2 $ */ + +/* + * Copyright (c) 2005-2011 Tensilica Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY + * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +#ifndef XTENSA_SPECREG_H +#define XTENSA_SPECREG_H + +/* Special registers: */ +#define LBEG 0 +#define LEND 1 +#define LCOUNT 2 +#define SAR 3 +#define BR 4 +#define LITBASE 5 +#define SCOMPARE1 12 +#define ACCLO 16 +#define ACCHI 17 +#define MR_0 32 +#define MR_1 33 +#define MR_2 34 +#define MR_3 35 +#define PREFCTL 40 +#define WINDOWBASE 72 +#define WINDOWSTART 73 +#define PTEVADDR 83 +#define RASID 90 +#define ITLBCFG 91 +#define DTLBCFG 92 +#define IBREAKENABLE 96 +#define MEMCTL 97 +#define CACHEATTR 98 +#define ATOMCTL 99 +#define DDR 104 +#define MECR 110 +#define IBREAKA_0 128 +#define IBREAKA_1 129 +#define DBREAKA_0 144 +#define DBREAKA_1 145 +#define DBREAKC_0 160 +#define DBREAKC_1 161 +#define CONFIGID0 176 +#define EPC_1 177 +#define EPC_2 178 +#define EPC_3 179 +#define EPC_4 180 +#define EPC_5 181 +#define EPC_6 182 +#define EPC_7 183 +#define DEPC 192 +#define EPS_2 194 +#define EPS_3 195 +#define EPS_4 196 +#define EPS_5 197 +#define EPS_6 198 +#define EPS_7 199 +#define CONFIGID1 208 +#define EXCSAVE_1 209 +#define EXCSAVE_2 210 +#define EXCSAVE_3 211 +#define EXCSAVE_4 212 +#define EXCSAVE_5 213 +#define EXCSAVE_6 214 +#define EXCSAVE_7 215 +#define CPENABLE 224 +#define INTERRUPT 226 +#define INTREAD INTERRUPT /* alternate name for backward compatibility */ +#define INTSET INTERRUPT /* alternate name for backward compatibility */ +#define INTCLEAR 227 +#define INTENABLE 228 +#define PS 230 +#define VECBASE 231 +#define EXCCAUSE 232 +#define DEBUGCAUSE 233 +#define CCOUNT 234 +#define PRID 235 +#define ICOUNT 236 +#define ICOUNTLEVEL 237 +#define EXCVADDR 238 +#define CCOMPARE_0 240 +#define CCOMPARE_1 241 +#define CCOMPARE_2 242 +#define MISC_REG_0 244 +#define MISC_REG_1 245 +#define MISC_REG_2 246 +#define MISC_REG_3 247 + +/* Special cases (bases of special register series): */ +#define MR 32 +#define IBREAKA 128 +#define DBREAKA 144 +#define DBREAKC 160 +#define EPC 176 +#define EPS 192 +#define EXCSAVE 208 +#define CCOMPARE 240 +#define MISC_REG 244 + +/* Tensilica-defined user registers: */ +#if 0 +/*#define ... 21..24 */ /* (545CK) */ +/*#define ... 140..143 */ /* (545CK) */ +#define EXPSTATE 230 /* Diamond */ +#define THREADPTR 231 /* threadptr option */ +#define FCR 232 /* FPU */ +#define FSR 233 /* FPU */ +#define AE_OVF_SAR 240 /* HiFi2 */ +#define AE_BITHEAD 241 /* HiFi2 */ +#define AE_TS_FTS_BU_BP 242 /* HiFi2 */ +#define AE_SD_NO 243 /* HiFi2 */ +#define VSAR 240 /* VectraLX */ +#define ROUND_LO 242 /* VectraLX */ +#define ROUND_HI 243 /* VectraLX */ +#define CBEGIN 246 /* VectraLX */ +#define CEND 247 /* VectraLX */ +#endif + +#endif /* XTENSA_SPECREG_H */ + diff --git a/components/esp32/include/xtensa/tie/xt_DFP_assist.h b/components/esp32/include/xtensa/tie/xt_DFP_assist.h new file mode 100644 index 0000000000..4d529ebd3f --- /dev/null +++ b/components/esp32/include/xtensa/tie/xt_DFP_assist.h @@ -0,0 +1,96 @@ +/* Definitions for the xt_DFP_assist TIE package */ + +/* + * Customer ID=11657; Build=0x5fe96; Copyright (c) 2004-2010 by Tensilica Inc. ALL RIGHTS RESERVED. + * These coded instructions, statements, and computer programs are the + * copyrighted works and confidential proprietary information of Tensilica Inc. + * They may not be modified, copied, reproduced, distributed, or disclosed to + * third parties in any manner, medium, or form, in whole or in part, without + * the prior written consent of Tensilica Inc. + */ + +/* Do not modify. This is automatically generated.*/ + +#ifndef _XTENSA_xt_DFP_assist_HEADER +#define _XTENSA_xt_DFP_assist_HEADER + +#ifdef __XTENSA__ +#ifdef __XCC__ + +#include + +/* + * The following prototypes describe intrinsic functions + * corresponding to TIE instructions. Some TIE instructions + * may produce multiple results (designated as "out" operands + * in the iclass section) or may have operands used as both + * inputs and outputs (designated as "inout"). However, the C + * and C++ languages do not provide syntax that can express + * the in/out/inout constraints of TIE intrinsics. + * Nevertheless, the compiler understands these constraints + * and will check that the intrinsic functions are used + * correctly. To improve the readability of these prototypes, + * the "out" and "inout" parameters are marked accordingly + * with comments. + */ + +extern void _TIE_xt_DFP_assist_F64ITER(unsigned arr /*inout*/, unsigned ars, unsigned art, immediate oper, immediate noshift); +extern unsigned _TIE_xt_DFP_assist_F64RND(unsigned ars, unsigned art, immediate mode); +extern void _TIE_xt_DFP_assist_F64ADDC(unsigned art /*inout*/, unsigned ars, immediate immZ, immediate immC); +extern void _TIE_xt_DFP_assist_F64SUBC(unsigned art /*inout*/, unsigned ars, immediate immZ, immediate immC); +extern unsigned _TIE_xt_DFP_assist_F64SIG(unsigned ars); +extern unsigned _TIE_xt_DFP_assist_F64CMPL(unsigned ars, unsigned art); +extern unsigned _TIE_xt_DFP_assist_F64CMPH(unsigned ars, unsigned art, immediate oper); +extern unsigned _TIE_xt_DFP_assist_F64NORM(unsigned ars, unsigned art, immediate mode); +extern unsigned _TIE_xt_DFP_assist_F64SEXP(unsigned ars, unsigned art); +extern unsigned _TIE_xt_DFP_assist_RF64R(immediate hilo); +extern void _TIE_xt_DFP_assist_WF64R(unsigned ars, unsigned art, immediate hilo); +extern unsigned _TIE_xt_DFP_assist_RUR_F64R_LO(void); +extern unsigned _TIE_xt_DFP_assist_RUR_F64R_HI(void); +extern void _TIE_xt_DFP_assist_WUR_F64R_LO(unsigned art); +extern void _TIE_xt_DFP_assist_WUR_F64R_HI(unsigned art); +extern unsigned _TIE_xt_DFP_assist_RUR_F64S(void); +extern void _TIE_xt_DFP_assist_WUR_F64S(unsigned art); +#define F64ITER _TIE_xt_DFP_assist_F64ITER +#define F64RND _TIE_xt_DFP_assist_F64RND +#define F64ADDC _TIE_xt_DFP_assist_F64ADDC +#define F64SUBC _TIE_xt_DFP_assist_F64SUBC +#define F64SIG _TIE_xt_DFP_assist_F64SIG +#define F64CMPL _TIE_xt_DFP_assist_F64CMPL +#define F64CMPH _TIE_xt_DFP_assist_F64CMPH +#define F64NORM _TIE_xt_DFP_assist_F64NORM +#define F64SEXP _TIE_xt_DFP_assist_F64SEXP +#define RF64R _TIE_xt_DFP_assist_RF64R +#define WF64R _TIE_xt_DFP_assist_WF64R +#define RUR_F64R_LO _TIE_xt_DFP_assist_RUR_F64R_LO +#define RF64R_LO _TIE_xt_DFP_assist_RUR_F64R_LO +#define RUR234 _TIE_xt_DFP_assist_RUR_F64R_LO +#define RUR_F64R_HI _TIE_xt_DFP_assist_RUR_F64R_HI +#define RF64R_HI _TIE_xt_DFP_assist_RUR_F64R_HI +#define RUR235 _TIE_xt_DFP_assist_RUR_F64R_HI +#define WUR_F64R_LO _TIE_xt_DFP_assist_WUR_F64R_LO +#define WF64R_LO _TIE_xt_DFP_assist_WUR_F64R_LO +#define WUR234 _TIE_xt_DFP_assist_WUR_F64R_LO +#define WUR_F64R_HI _TIE_xt_DFP_assist_WUR_F64R_HI +#define WF64R_HI _TIE_xt_DFP_assist_WUR_F64R_HI +#define WUR235 _TIE_xt_DFP_assist_WUR_F64R_HI +#define RUR_F64S _TIE_xt_DFP_assist_RUR_F64S +#define RF64S _TIE_xt_DFP_assist_RUR_F64S +#define RUR236 _TIE_xt_DFP_assist_RUR_F64S +#define WUR_F64S _TIE_xt_DFP_assist_WUR_F64S +#define WF64S _TIE_xt_DFP_assist_WUR_F64S +#define WUR236 _TIE_xt_DFP_assist_WUR_F64S + +#ifndef RUR +#define RUR(NUM) RUR##NUM() +#endif + +#ifndef WUR +#define WUR(VAL, NUM) WUR##NUM(VAL) +#endif + +#endif /* __XCC__ */ + +#endif /* __XTENSA__ */ + +#endif /* !_XTENSA_xt_DFP_assist_HEADER */ diff --git a/components/esp32/include/xtensa/tie/xt_FP.h b/components/esp32/include/xtensa/tie/xt_FP.h new file mode 100644 index 0000000000..229a108ab7 --- /dev/null +++ b/components/esp32/include/xtensa/tie/xt_FP.h @@ -0,0 +1,197 @@ +/* Definitions for the xt_FP TIE package */ + +/* + * Customer ID=11657; Build=0x5fe96; Copyright (c) 2004-2010 by Tensilica Inc. ALL RIGHTS RESERVED. + * These coded instructions, statements, and computer programs are the + * copyrighted works and confidential proprietary information of Tensilica Inc. + * They may not be modified, copied, reproduced, distributed, or disclosed to + * third parties in any manner, medium, or form, in whole or in part, without + * the prior written consent of Tensilica Inc. + */ + +/* Do not modify. This is automatically generated.*/ + +#ifndef _XTENSA_xt_FP_HEADER +#define _XTENSA_xt_FP_HEADER + +#ifdef __XTENSA__ +#ifdef __XCC__ + +#include +#include +typedef float _TIE_xt_FP_xtfloat; +typedef _TIE_xt_FP_xtfloat xtfloat; + +/* + * The following prototypes describe intrinsic functions + * corresponding to TIE instructions. Some TIE instructions + * may produce multiple results (designated as "out" operands + * in the iclass section) or may have operands used as both + * inputs and outputs (designated as "inout"). However, the C + * and C++ languages do not provide syntax that can express + * the in/out/inout constraints of TIE intrinsics. + * Nevertheless, the compiler understands these constraints + * and will check that the intrinsic functions are used + * correctly. To improve the readability of these prototypes, + * the "out" and "inout" parameters are marked accordingly + * with comments. + */ + +extern unsigned _TIE_xt_FP_RUR_FCR(void); +extern void _TIE_xt_FP_WUR_FCR(unsigned v); +extern unsigned _TIE_xt_FP_RUR_FSR(void); +extern void _TIE_xt_FP_WUR_FSR(unsigned v); +extern xtfloat _TIE_xt_FP_xtfloat_loadi(const xtfloat * p, immediate imm8x4); +extern void _TIE_xt_FP_xtfloat_storei(xtfloat t, xtfloat * p, immediate imm8x4); +extern void _TIE_xt_FP_xtfloat_loadip(xtfloat t /*out*/, const xtfloat * p /*inout*/, immediate imm8x4); +extern void _TIE_xt_FP_xtfloat_storeip(xtfloat t, xtfloat * p /*inout*/, immediate imm8x4); +extern xtfloat _TIE_xt_FP_xtfloat_loadx(const xtfloat * p, int imm8x4); +extern void _TIE_xt_FP_xtfloat_storex(xtfloat t, xtfloat * p, int imm8x4); +extern void _TIE_xt_FP_xtfloat_loadxp(xtfloat t /*out*/, const xtfloat * p /*inout*/, int imm8x4); +extern void _TIE_xt_FP_xtfloat_storexp(xtfloat t, xtfloat * p /*inout*/, int imm8x4); +extern xtfloat _TIE_xt_FP_xtfloat_move(xtfloat r); +extern int _TIE_xt_FP_ROUND_S(xtfloat s, immediate t); +extern int _TIE_xt_FP_TRUNC_S(xtfloat s, immediate t); +extern unsigned _TIE_xt_FP_UTRUNC_S(xtfloat s, immediate t); +extern int _TIE_xt_FP_FLOOR_S(xtfloat s, immediate t); +extern int _TIE_xt_FP_CEIL_S(xtfloat s, immediate t); +extern xtfloat _TIE_xt_FP_LSI(const xtfloat * p, immediate imm8x4); +extern void _TIE_xt_FP_SSI(xtfloat t, xtfloat * p, immediate imm8x4); +extern void _TIE_xt_FP_LSIP(xtfloat t /*out*/, const xtfloat * p /*inout*/, immediate imm8x4); +extern void _TIE_xt_FP_SSIP(xtfloat t, xtfloat * p /*inout*/, immediate imm8x4); +extern xtfloat _TIE_xt_FP_LSX(const xtfloat * p, int imm8x4); +extern void _TIE_xt_FP_SSX(xtfloat t, xtfloat * p, int imm8x4); +extern void _TIE_xt_FP_LSXP(xtfloat t /*out*/, const xtfloat * p /*inout*/, int imm8x4); +extern void _TIE_xt_FP_SSXP(xtfloat t, xtfloat * p /*inout*/, int imm8x4); +extern xtfloat _TIE_xt_FP_ABS_S(xtfloat s); +extern xtfloat _TIE_xt_FP_NEG_S(xtfloat s); +extern xtfloat _TIE_xt_FP_MOV_S(xtfloat s); +extern void _TIE_xt_FP_MOVEQZ_S(xtfloat r /*inout*/, xtfloat s, int t); +extern void _TIE_xt_FP_MOVNEZ_S(xtfloat r /*inout*/, xtfloat s, int t); +extern void _TIE_xt_FP_MOVLTZ_S(xtfloat r /*inout*/, xtfloat s, int t); +extern void _TIE_xt_FP_MOVGEZ_S(xtfloat r /*inout*/, xtfloat s, int t); +extern void _TIE_xt_FP_MOVF_S(xtfloat r /*inout*/, xtfloat s, xtbool t); +extern void _TIE_xt_FP_MOVT_S(xtfloat r /*inout*/, xtfloat s, xtbool t); +extern unsigned _TIE_xt_FP_RFR(xtfloat s); +extern xtfloat _TIE_xt_FP_WFR(unsigned s); +extern xtfloat _TIE_xt_FP_FLOAT_S(int s, immediate t); +extern xtfloat _TIE_xt_FP_UFLOAT_S(unsigned s, immediate t); +extern xtbool _TIE_xt_FP_OEQ_S(xtfloat s, xtfloat t); +extern xtbool _TIE_xt_FP_OLE_S(xtfloat s, xtfloat t); +extern xtbool _TIE_xt_FP_OLT_S(xtfloat s, xtfloat t); +extern xtbool _TIE_xt_FP_UEQ_S(xtfloat s, xtfloat t); +extern xtbool _TIE_xt_FP_ULE_S(xtfloat s, xtfloat t); +extern xtbool _TIE_xt_FP_ULT_S(xtfloat s, xtfloat t); +extern xtbool _TIE_xt_FP_UN_S(xtfloat s, xtfloat t); +extern xtfloat _TIE_xt_FP_ADD_S(xtfloat s, xtfloat t); +extern xtfloat _TIE_xt_FP_SUB_S(xtfloat s, xtfloat t); +extern xtfloat _TIE_xt_FP_MUL_S(xtfloat s, xtfloat t); +extern void _TIE_xt_FP_MADD_S(xtfloat r /*inout*/, xtfloat s, xtfloat t); +extern void _TIE_xt_FP_MSUB_S(xtfloat r /*inout*/, xtfloat s, xtfloat t); +extern xtfloat _TIE_xt_FP_RECIP0_S(xtfloat s); +extern xtfloat _TIE_xt_FP_DIV0_S(xtfloat s); +extern xtfloat _TIE_xt_FP_NEXP01_S(xtfloat s); +extern xtfloat _TIE_xt_FP_CONST_S(immediate s); +extern void _TIE_xt_FP_MKDADJ_S(xtfloat r /*inout*/, xtfloat s); +extern xtfloat _TIE_xt_FP_MKSADJ_S(xtfloat s); +extern void _TIE_xt_FP_ADDEXPM_S(xtfloat r /*inout*/, xtfloat s); +extern void _TIE_xt_FP_ADDEXP_S(xtfloat r /*inout*/, xtfloat s); +extern void _TIE_xt_FP_DIVN_S(xtfloat r /*inout*/, xtfloat s, xtfloat t); +extern xtfloat _TIE_xt_FP_RSQRT0_S(xtfloat s); +extern xtfloat _TIE_xt_FP_SQRT0_S(xtfloat s); +extern void _TIE_xt_FP_MADDN_S(xtfloat r /*inout*/, xtfloat s, xtfloat t); +extern xtfloat _TIE_xt_FP_DIV_S(xtfloat s, xtfloat t); +extern xtfloat _TIE_xt_FP_SQRT_S(xtfloat s); +extern xtfloat _TIE_xt_FP_RECIP_S(xtfloat s); +extern xtfloat _TIE_xt_FP_RSQRT_S(xtfloat s); +extern xtfloat _TIE_xt_FP_FSQRT_S(xtfloat s); +#define XT_RUR_FCR _TIE_xt_FP_RUR_FCR +#define RFCR _TIE_xt_FP_RUR_FCR +#define RUR232 _TIE_xt_FP_RUR_FCR +#define XT_WUR_FCR _TIE_xt_FP_WUR_FCR +#define WFCR _TIE_xt_FP_WUR_FCR +#define WUR232 _TIE_xt_FP_WUR_FCR +#define XT_RUR_FSR _TIE_xt_FP_RUR_FSR +#define RFSR _TIE_xt_FP_RUR_FSR +#define RUR233 _TIE_xt_FP_RUR_FSR +#define XT_WUR_FSR _TIE_xt_FP_WUR_FSR +#define WFSR _TIE_xt_FP_WUR_FSR +#define WUR233 _TIE_xt_FP_WUR_FSR +#define XT_xtfloat_loadi _TIE_xt_FP_xtfloat_loadi +#define XT_xtfloat_storei _TIE_xt_FP_xtfloat_storei +#define XT_xtfloat_loadip _TIE_xt_FP_xtfloat_loadip +#define XT_xtfloat_storeip _TIE_xt_FP_xtfloat_storeip +#define XT_xtfloat_loadx _TIE_xt_FP_xtfloat_loadx +#define XT_xtfloat_storex _TIE_xt_FP_xtfloat_storex +#define XT_xtfloat_loadxp _TIE_xt_FP_xtfloat_loadxp +#define XT_xtfloat_storexp _TIE_xt_FP_xtfloat_storexp +#define XT_xtfloat_move _TIE_xt_FP_xtfloat_move +#define XT_ROUND_S _TIE_xt_FP_ROUND_S +#define XT_TRUNC_S _TIE_xt_FP_TRUNC_S +#define XT_UTRUNC_S _TIE_xt_FP_UTRUNC_S +#define XT_FLOOR_S _TIE_xt_FP_FLOOR_S +#define XT_CEIL_S _TIE_xt_FP_CEIL_S +#define XT_LSI _TIE_xt_FP_LSI +#define XT_SSI _TIE_xt_FP_SSI +#define XT_LSIP _TIE_xt_FP_LSIP +#define XT_SSIP _TIE_xt_FP_SSIP +#define XT_LSX _TIE_xt_FP_LSX +#define XT_SSX _TIE_xt_FP_SSX +#define XT_LSXP _TIE_xt_FP_LSXP +#define XT_SSXP _TIE_xt_FP_SSXP +#define XT_ABS_S _TIE_xt_FP_ABS_S +#define XT_NEG_S _TIE_xt_FP_NEG_S +#define XT_MOV_S _TIE_xt_FP_MOV_S +#define XT_MOVEQZ_S _TIE_xt_FP_MOVEQZ_S +#define XT_MOVNEZ_S _TIE_xt_FP_MOVNEZ_S +#define XT_MOVLTZ_S _TIE_xt_FP_MOVLTZ_S +#define XT_MOVGEZ_S _TIE_xt_FP_MOVGEZ_S +#define XT_MOVF_S _TIE_xt_FP_MOVF_S +#define XT_MOVT_S _TIE_xt_FP_MOVT_S +#define XT_RFR _TIE_xt_FP_RFR +#define XT_WFR _TIE_xt_FP_WFR +#define XT_FLOAT_S _TIE_xt_FP_FLOAT_S +#define XT_UFLOAT_S _TIE_xt_FP_UFLOAT_S +#define XT_OEQ_S _TIE_xt_FP_OEQ_S +#define XT_OLE_S _TIE_xt_FP_OLE_S +#define XT_OLT_S _TIE_xt_FP_OLT_S +#define XT_UEQ_S _TIE_xt_FP_UEQ_S +#define XT_ULE_S _TIE_xt_FP_ULE_S +#define XT_ULT_S _TIE_xt_FP_ULT_S +#define XT_UN_S _TIE_xt_FP_UN_S +#define XT_ADD_S _TIE_xt_FP_ADD_S +#define XT_SUB_S _TIE_xt_FP_SUB_S +#define XT_MUL_S _TIE_xt_FP_MUL_S +#define XT_MADD_S _TIE_xt_FP_MADD_S +#define XT_MSUB_S _TIE_xt_FP_MSUB_S +#define XT_RECIP0_S _TIE_xt_FP_RECIP0_S +#define XT_DIV0_S _TIE_xt_FP_DIV0_S +#define XT_NEXP01_S _TIE_xt_FP_NEXP01_S +#define XT_CONST_S _TIE_xt_FP_CONST_S +#define XT_MKDADJ_S _TIE_xt_FP_MKDADJ_S +#define XT_MKSADJ_S _TIE_xt_FP_MKSADJ_S +#define XT_ADDEXPM_S _TIE_xt_FP_ADDEXPM_S +#define XT_ADDEXP_S _TIE_xt_FP_ADDEXP_S +#define XT_DIVN_S _TIE_xt_FP_DIVN_S +#define XT_RSQRT0_S _TIE_xt_FP_RSQRT0_S +#define XT_SQRT0_S _TIE_xt_FP_SQRT0_S +#define XT_MADDN_S _TIE_xt_FP_MADDN_S +#define XT_DIV_S _TIE_xt_FP_DIV_S +#define XT_SQRT_S _TIE_xt_FP_SQRT_S +#define XT_RECIP_S _TIE_xt_FP_RECIP_S +#define XT_RSQRT_S _TIE_xt_FP_RSQRT_S +#define XT_FSQRT_S _TIE_xt_FP_FSQRT_S + +#ifndef RUR +#define RUR(NUM) RUR##NUM() +#endif + +#ifndef WUR +#define WUR(VAL, NUM) WUR##NUM(VAL) +#endif + +#endif /* __XCC__ */ + +#endif /* __XTENSA__ */ + +#endif /* !_XTENSA_xt_FP_HEADER */ diff --git a/components/esp32/include/xtensa/tie/xt_MAC16.h b/components/esp32/include/xtensa/tie/xt_MAC16.h new file mode 100644 index 0000000000..b46a1db7f7 --- /dev/null +++ b/components/esp32/include/xtensa/tie/xt_MAC16.h @@ -0,0 +1,239 @@ +/* Definitions for the xt_MAC16 TIE package */ + +/* + * Customer ID=11657; Build=0x5fe96; Copyright (c) 2004-2010 by Tensilica Inc. ALL RIGHTS RESERVED. + * These coded instructions, statements, and computer programs are the + * copyrighted works and confidential proprietary information of Tensilica Inc. + * They may not be modified, copied, reproduced, distributed, or disclosed to + * third parties in any manner, medium, or form, in whole or in part, without + * the prior written consent of Tensilica Inc. + */ + +/* Do not modify. This is automatically generated.*/ + +#ifndef _XTENSA_xt_MAC16_HEADER +#define _XTENSA_xt_MAC16_HEADER + +#ifdef __XTENSA__ +#ifdef __XCC__ + +#include +#include + +/* + * The following prototypes describe intrinsic functions + * corresponding to TIE instructions. Some TIE instructions + * may produce multiple results (designated as "out" operands + * in the iclass section) or may have operands used as both + * inputs and outputs (designated as "inout"). However, the C + * and C++ languages do not provide syntax that can express + * the in/out/inout constraints of TIE intrinsics. + * Nevertheless, the compiler understands these constraints + * and will check that the intrinsic functions are used + * correctly. To improve the readability of these prototypes, + * the "out" and "inout" parameters are marked accordingly + * with comments. + */ + +extern void _TIE_xt_MAC16_UMUL_AA_HH(unsigned ars, unsigned art); +extern void _TIE_xt_MAC16_UMUL_AA_LH(unsigned ars, unsigned art); +extern void _TIE_xt_MAC16_UMUL_AA_HL(unsigned ars, unsigned art); +extern void _TIE_xt_MAC16_UMUL_AA_LL(unsigned ars, unsigned art); +extern void _TIE_xt_MAC16_MUL_AA_HH(unsigned ars, unsigned art); +extern void _TIE_xt_MAC16_MUL_AA_LH(unsigned ars, unsigned art); +extern void _TIE_xt_MAC16_MUL_AA_HL(unsigned ars, unsigned art); +extern void _TIE_xt_MAC16_MUL_AA_LL(unsigned ars, unsigned art); +extern void _TIE_xt_MAC16_MUL_AD_HH(unsigned ars, immediate my); +extern void _TIE_xt_MAC16_MUL_AD_LH(unsigned ars, immediate my); +extern void _TIE_xt_MAC16_MUL_AD_HL(unsigned ars, immediate my); +extern void _TIE_xt_MAC16_MUL_AD_LL(unsigned ars, immediate my); +extern void _TIE_xt_MAC16_MUL_DA_HH(immediate mx, unsigned art); +extern void _TIE_xt_MAC16_MUL_DA_LH(immediate mx, unsigned art); +extern void _TIE_xt_MAC16_MUL_DA_HL(immediate mx, unsigned art); +extern void _TIE_xt_MAC16_MUL_DA_LL(immediate mx, unsigned art); +extern void _TIE_xt_MAC16_MUL_DD_HH(immediate mx, immediate my); +extern void _TIE_xt_MAC16_MUL_DD_LH(immediate mx, immediate my); +extern void _TIE_xt_MAC16_MUL_DD_HL(immediate mx, immediate my); +extern void _TIE_xt_MAC16_MUL_DD_LL(immediate mx, immediate my); +extern void _TIE_xt_MAC16_MULS_AA_HH(unsigned ars, unsigned art); +extern void _TIE_xt_MAC16_MULS_AA_LH(unsigned ars, unsigned art); +extern void _TIE_xt_MAC16_MULS_AA_HL(unsigned ars, unsigned art); +extern void _TIE_xt_MAC16_MULS_AA_LL(unsigned ars, unsigned art); +extern void _TIE_xt_MAC16_MULA_AA_HH(unsigned ars, unsigned art); +extern void _TIE_xt_MAC16_MULA_AA_LH(unsigned ars, unsigned art); +extern void _TIE_xt_MAC16_MULA_AA_HL(unsigned ars, unsigned art); +extern void _TIE_xt_MAC16_MULA_AA_LL(unsigned ars, unsigned art); +extern void _TIE_xt_MAC16_MULS_AD_HH(unsigned ars, immediate my); +extern void _TIE_xt_MAC16_MULS_AD_LH(unsigned ars, immediate my); +extern void _TIE_xt_MAC16_MULS_AD_HL(unsigned ars, immediate my); +extern void _TIE_xt_MAC16_MULS_AD_LL(unsigned ars, immediate my); +extern void _TIE_xt_MAC16_MULA_AD_HH(unsigned ars, immediate my); +extern void _TIE_xt_MAC16_MULA_AD_LH(unsigned ars, immediate my); +extern void _TIE_xt_MAC16_MULA_AD_HL(unsigned ars, immediate my); +extern void _TIE_xt_MAC16_MULA_AD_LL(unsigned ars, immediate my); +extern void _TIE_xt_MAC16_MULS_DA_HH(immediate mx, unsigned art); +extern void _TIE_xt_MAC16_MULS_DA_LH(immediate mx, unsigned art); +extern void _TIE_xt_MAC16_MULS_DA_HL(immediate mx, unsigned art); +extern void _TIE_xt_MAC16_MULS_DA_LL(immediate mx, unsigned art); +extern void _TIE_xt_MAC16_MULA_DA_HH(immediate mx, unsigned art); +extern void _TIE_xt_MAC16_MULA_DA_LH(immediate mx, unsigned art); +extern void _TIE_xt_MAC16_MULA_DA_HL(immediate mx, unsigned art); +extern void _TIE_xt_MAC16_MULA_DA_LL(immediate mx, unsigned art); +extern void _TIE_xt_MAC16_MULS_DD_HH(immediate mx, immediate my); +extern void _TIE_xt_MAC16_MULS_DD_LH(immediate mx, immediate my); +extern void _TIE_xt_MAC16_MULS_DD_HL(immediate mx, immediate my); +extern void _TIE_xt_MAC16_MULS_DD_LL(immediate mx, immediate my); +extern void _TIE_xt_MAC16_MULA_DD_HH(immediate mx, immediate my); +extern void _TIE_xt_MAC16_MULA_DD_LH(immediate mx, immediate my); +extern void _TIE_xt_MAC16_MULA_DD_HL(immediate mx, immediate my); +extern void _TIE_xt_MAC16_MULA_DD_LL(immediate mx, immediate my); +extern unsigned _TIE_xt_MAC16_RSR_M0(void); +extern void _TIE_xt_MAC16_WSR_M0(unsigned art); +extern void _TIE_xt_MAC16_XSR_M0(unsigned art /*inout*/); +extern unsigned _TIE_xt_MAC16_RSR_M1(void); +extern void _TIE_xt_MAC16_WSR_M1(unsigned art); +extern void _TIE_xt_MAC16_XSR_M1(unsigned art /*inout*/); +extern unsigned _TIE_xt_MAC16_RSR_M2(void); +extern void _TIE_xt_MAC16_WSR_M2(unsigned art); +extern void _TIE_xt_MAC16_XSR_M2(unsigned art /*inout*/); +extern unsigned _TIE_xt_MAC16_RSR_M3(void); +extern void _TIE_xt_MAC16_WSR_M3(unsigned art); +extern void _TIE_xt_MAC16_XSR_M3(unsigned art /*inout*/); +extern unsigned _TIE_xt_MAC16_RSR_ACCLO(void); +extern void _TIE_xt_MAC16_WSR_ACCLO(unsigned art); +extern void _TIE_xt_MAC16_XSR_ACCLO(unsigned art /*inout*/); +extern unsigned _TIE_xt_MAC16_RSR_ACCHI(void); +extern void _TIE_xt_MAC16_WSR_ACCHI(unsigned art); +extern void _TIE_xt_MAC16_XSR_ACCHI(unsigned art /*inout*/); +extern void _TIE_xt_MAC16_MULA_DA_LL_LDDEC(immediate w, const short * s /*inout*/, immediate x, int t); +extern void _TIE_xt_MAC16_MULA_DA_LL_LDINC(immediate w, const short * s /*inout*/, immediate x, int t); +extern void _TIE_xt_MAC16_MULA_DA_HL_LDDEC(immediate w, const short * s /*inout*/, immediate x, int t); +extern void _TIE_xt_MAC16_MULA_DA_HL_LDINC(immediate w, const short * s /*inout*/, immediate x, int t); +extern void _TIE_xt_MAC16_MULA_DA_LH_LDDEC(immediate w, const short * s /*inout*/, immediate x, int t); +extern void _TIE_xt_MAC16_MULA_DA_LH_LDINC(immediate w, const short * s /*inout*/, immediate x, int t); +extern void _TIE_xt_MAC16_MULA_DA_HH_LDDEC(immediate w, const short * s /*inout*/, immediate x, int t); +extern void _TIE_xt_MAC16_MULA_DA_HH_LDINC(immediate w, const short * s /*inout*/, immediate x, int t); +extern void _TIE_xt_MAC16_MULA_DD_LL_LDDEC(immediate w, const short * s /*inout*/, immediate x, immediate y); +extern void _TIE_xt_MAC16_MULA_DD_LL_LDINC(immediate w, const short * s /*inout*/, immediate x, immediate y); +extern void _TIE_xt_MAC16_MULA_DD_HL_LDDEC(immediate w, const short * s /*inout*/, immediate x, immediate y); +extern void _TIE_xt_MAC16_MULA_DD_HL_LDINC(immediate w, const short * s /*inout*/, immediate x, immediate y); +extern void _TIE_xt_MAC16_MULA_DD_LH_LDDEC(immediate w, const short * s /*inout*/, immediate x, immediate y); +extern void _TIE_xt_MAC16_MULA_DD_LH_LDINC(immediate w, const short * s /*inout*/, immediate x, immediate y); +extern void _TIE_xt_MAC16_MULA_DD_HH_LDDEC(immediate w, const short * s /*inout*/, immediate x, immediate y); +extern void _TIE_xt_MAC16_MULA_DD_HH_LDINC(immediate w, const short * s /*inout*/, immediate x, immediate y); +extern void _TIE_xt_MAC16_LDDEC(immediate w, const short * p /*inout*/); +extern void _TIE_xt_MAC16_ULDDEC(immediate w, const unsigned short * p /*inout*/); +extern void _TIE_xt_MAC16_SLDDEC(immediate w, const short * p /*inout*/); +extern void _TIE_xt_MAC16_LDINC(immediate w, const short * p /*inout*/); +extern void _TIE_xt_MAC16_ULDINC(immediate w, const unsigned short * p /*inout*/); +extern void _TIE_xt_MAC16_SLDINC(immediate w, const short * p /*inout*/); +extern int _TIE_xt_MAC16_RSR16(void); +extern void _TIE_xt_MAC16_WSR16(int t); +extern void _TIE_xt_MAC16_XSR16(int t /*inout*/); +extern int _TIE_xt_MAC16_RSR17(void); +extern void _TIE_xt_MAC16_WSR17(int t); +extern void _TIE_xt_MAC16_XSR17(int t /*inout*/); +#define XT_UMUL_AA_HH _TIE_xt_MAC16_UMUL_AA_HH +#define XT_UMUL_AA_LH _TIE_xt_MAC16_UMUL_AA_LH +#define XT_UMUL_AA_HL _TIE_xt_MAC16_UMUL_AA_HL +#define XT_UMUL_AA_LL _TIE_xt_MAC16_UMUL_AA_LL +#define XT_MUL_AA_HH _TIE_xt_MAC16_MUL_AA_HH +#define XT_MUL_AA_LH _TIE_xt_MAC16_MUL_AA_LH +#define XT_MUL_AA_HL _TIE_xt_MAC16_MUL_AA_HL +#define XT_MUL_AA_LL _TIE_xt_MAC16_MUL_AA_LL +#define XT_MUL_AD_HH _TIE_xt_MAC16_MUL_AD_HH +#define XT_MUL_AD_LH _TIE_xt_MAC16_MUL_AD_LH +#define XT_MUL_AD_HL _TIE_xt_MAC16_MUL_AD_HL +#define XT_MUL_AD_LL _TIE_xt_MAC16_MUL_AD_LL +#define XT_MUL_DA_HH _TIE_xt_MAC16_MUL_DA_HH +#define XT_MUL_DA_LH _TIE_xt_MAC16_MUL_DA_LH +#define XT_MUL_DA_HL _TIE_xt_MAC16_MUL_DA_HL +#define XT_MUL_DA_LL _TIE_xt_MAC16_MUL_DA_LL +#define XT_MUL_DD_HH _TIE_xt_MAC16_MUL_DD_HH +#define XT_MUL_DD_LH _TIE_xt_MAC16_MUL_DD_LH +#define XT_MUL_DD_HL _TIE_xt_MAC16_MUL_DD_HL +#define XT_MUL_DD_LL _TIE_xt_MAC16_MUL_DD_LL +#define XT_MULS_AA_HH _TIE_xt_MAC16_MULS_AA_HH +#define XT_MULS_AA_LH _TIE_xt_MAC16_MULS_AA_LH +#define XT_MULS_AA_HL _TIE_xt_MAC16_MULS_AA_HL +#define XT_MULS_AA_LL _TIE_xt_MAC16_MULS_AA_LL +#define XT_MULA_AA_HH _TIE_xt_MAC16_MULA_AA_HH +#define XT_MULA_AA_LH _TIE_xt_MAC16_MULA_AA_LH +#define XT_MULA_AA_HL _TIE_xt_MAC16_MULA_AA_HL +#define XT_MULA_AA_LL _TIE_xt_MAC16_MULA_AA_LL +#define XT_MULS_AD_HH _TIE_xt_MAC16_MULS_AD_HH +#define XT_MULS_AD_LH _TIE_xt_MAC16_MULS_AD_LH +#define XT_MULS_AD_HL _TIE_xt_MAC16_MULS_AD_HL +#define XT_MULS_AD_LL _TIE_xt_MAC16_MULS_AD_LL +#define XT_MULA_AD_HH _TIE_xt_MAC16_MULA_AD_HH +#define XT_MULA_AD_LH _TIE_xt_MAC16_MULA_AD_LH +#define XT_MULA_AD_HL _TIE_xt_MAC16_MULA_AD_HL +#define XT_MULA_AD_LL _TIE_xt_MAC16_MULA_AD_LL +#define XT_MULS_DA_HH _TIE_xt_MAC16_MULS_DA_HH +#define XT_MULS_DA_LH _TIE_xt_MAC16_MULS_DA_LH +#define XT_MULS_DA_HL _TIE_xt_MAC16_MULS_DA_HL +#define XT_MULS_DA_LL _TIE_xt_MAC16_MULS_DA_LL +#define XT_MULA_DA_HH _TIE_xt_MAC16_MULA_DA_HH +#define XT_MULA_DA_LH _TIE_xt_MAC16_MULA_DA_LH +#define XT_MULA_DA_HL _TIE_xt_MAC16_MULA_DA_HL +#define XT_MULA_DA_LL _TIE_xt_MAC16_MULA_DA_LL +#define XT_MULS_DD_HH _TIE_xt_MAC16_MULS_DD_HH +#define XT_MULS_DD_LH _TIE_xt_MAC16_MULS_DD_LH +#define XT_MULS_DD_HL _TIE_xt_MAC16_MULS_DD_HL +#define XT_MULS_DD_LL _TIE_xt_MAC16_MULS_DD_LL +#define XT_MULA_DD_HH _TIE_xt_MAC16_MULA_DD_HH +#define XT_MULA_DD_LH _TIE_xt_MAC16_MULA_DD_LH +#define XT_MULA_DD_HL _TIE_xt_MAC16_MULA_DD_HL +#define XT_MULA_DD_LL _TIE_xt_MAC16_MULA_DD_LL +#define XT_RSR_M0 _TIE_xt_MAC16_RSR_M0 +#define XT_WSR_M0 _TIE_xt_MAC16_WSR_M0 +#define XT_XSR_M0 _TIE_xt_MAC16_XSR_M0 +#define XT_RSR_M1 _TIE_xt_MAC16_RSR_M1 +#define XT_WSR_M1 _TIE_xt_MAC16_WSR_M1 +#define XT_XSR_M1 _TIE_xt_MAC16_XSR_M1 +#define XT_RSR_M2 _TIE_xt_MAC16_RSR_M2 +#define XT_WSR_M2 _TIE_xt_MAC16_WSR_M2 +#define XT_XSR_M2 _TIE_xt_MAC16_XSR_M2 +#define XT_RSR_M3 _TIE_xt_MAC16_RSR_M3 +#define XT_WSR_M3 _TIE_xt_MAC16_WSR_M3 +#define XT_XSR_M3 _TIE_xt_MAC16_XSR_M3 +#define XT_RSR_ACCLO _TIE_xt_MAC16_RSR_ACCLO +#define XT_WSR_ACCLO _TIE_xt_MAC16_WSR_ACCLO +#define XT_XSR_ACCLO _TIE_xt_MAC16_XSR_ACCLO +#define XT_RSR_ACCHI _TIE_xt_MAC16_RSR_ACCHI +#define XT_WSR_ACCHI _TIE_xt_MAC16_WSR_ACCHI +#define XT_XSR_ACCHI _TIE_xt_MAC16_XSR_ACCHI +#define XT_MULA_DA_LL_LDDEC _TIE_xt_MAC16_MULA_DA_LL_LDDEC +#define XT_MULA_DA_LL_LDINC _TIE_xt_MAC16_MULA_DA_LL_LDINC +#define XT_MULA_DA_HL_LDDEC _TIE_xt_MAC16_MULA_DA_HL_LDDEC +#define XT_MULA_DA_HL_LDINC _TIE_xt_MAC16_MULA_DA_HL_LDINC +#define XT_MULA_DA_LH_LDDEC _TIE_xt_MAC16_MULA_DA_LH_LDDEC +#define XT_MULA_DA_LH_LDINC _TIE_xt_MAC16_MULA_DA_LH_LDINC +#define XT_MULA_DA_HH_LDDEC _TIE_xt_MAC16_MULA_DA_HH_LDDEC +#define XT_MULA_DA_HH_LDINC _TIE_xt_MAC16_MULA_DA_HH_LDINC +#define XT_MULA_DD_LL_LDDEC _TIE_xt_MAC16_MULA_DD_LL_LDDEC +#define XT_MULA_DD_LL_LDINC _TIE_xt_MAC16_MULA_DD_LL_LDINC +#define XT_MULA_DD_HL_LDDEC _TIE_xt_MAC16_MULA_DD_HL_LDDEC +#define XT_MULA_DD_HL_LDINC _TIE_xt_MAC16_MULA_DD_HL_LDINC +#define XT_MULA_DD_LH_LDDEC _TIE_xt_MAC16_MULA_DD_LH_LDDEC +#define XT_MULA_DD_LH_LDINC _TIE_xt_MAC16_MULA_DD_LH_LDINC +#define XT_MULA_DD_HH_LDDEC _TIE_xt_MAC16_MULA_DD_HH_LDDEC +#define XT_MULA_DD_HH_LDINC _TIE_xt_MAC16_MULA_DD_HH_LDINC +#define XT_LDDEC _TIE_xt_MAC16_LDDEC +#define XT_ULDDEC _TIE_xt_MAC16_ULDDEC +#define XT_SLDDEC _TIE_xt_MAC16_SLDDEC +#define XT_LDINC _TIE_xt_MAC16_LDINC +#define XT_ULDINC _TIE_xt_MAC16_ULDINC +#define XT_SLDINC _TIE_xt_MAC16_SLDINC +#define XT_RSR16 _TIE_xt_MAC16_RSR16 +#define XT_WSR16 _TIE_xt_MAC16_WSR16 +#define XT_XSR16 _TIE_xt_MAC16_XSR16 +#define XT_RSR17 _TIE_xt_MAC16_RSR17 +#define XT_WSR17 _TIE_xt_MAC16_WSR17 +#define XT_XSR17 _TIE_xt_MAC16_XSR17 + +#endif /* __XCC__ */ + +#endif /* __XTENSA__ */ + +#endif /* !_XTENSA_xt_MAC16_HEADER */ diff --git a/components/esp32/include/xtensa/tie/xt_MUL32.h b/components/esp32/include/xtensa/tie/xt_MUL32.h new file mode 100644 index 0000000000..91b3c3299c --- /dev/null +++ b/components/esp32/include/xtensa/tie/xt_MUL32.h @@ -0,0 +1,24 @@ +/* Definitions for the 32-bit Integer Multiply Option. */ + +/* + * Customer ID=11657; Build=0x5fe96; Copyright (c) 2009 by Tensilica Inc. ALL RIGHTS RESERVED. + * These coded instructions, statements, and computer programs are the + * copyrighted works and confidential proprietary information of Tensilica Inc. + * They may not be modified, copied, reproduced, distributed, or disclosed to + * third parties in any manner, medium, or form, in whole or in part, without + * the prior written consent of Tensilica Inc. + */ + +/* NOTE: This file exists only for backward compatibility with RB-200X.x + and earlier Xtensa releases. Starting with RC-2009.0 you should use + . */ + +#ifndef _XTENSA_xt_MUL32_HEADER +#define _XTENSA_xt_MUL32_HEADER + +#ifdef __XTENSA__ + +#include + +#endif /* __XTENSA__ */ +#endif /* !_XTENSA_xt_MUL32_HEADER */ diff --git a/components/esp32/include/xtensa/tie/xt_booleans.h b/components/esp32/include/xtensa/tie/xt_booleans.h new file mode 100644 index 0000000000..94b5b468ed --- /dev/null +++ b/components/esp32/include/xtensa/tie/xt_booleans.h @@ -0,0 +1,69 @@ +/* Definitions for the xt_booleans TIE package */ + +/* + * Customer ID=11657; Build=0x5fe96; Copyright (c) 2004-2010 by Tensilica Inc. ALL RIGHTS RESERVED. + * These coded instructions, statements, and computer programs are the + * copyrighted works and confidential proprietary information of Tensilica Inc. + * They may not be modified, copied, reproduced, distributed, or disclosed to + * third parties in any manner, medium, or form, in whole or in part, without + * the prior written consent of Tensilica Inc. + */ + +/* Do not modify. This is automatically generated.*/ + +#ifndef _XTENSA_xt_booleans_HEADER +#define _XTENSA_xt_booleans_HEADER + +#ifdef __XTENSA__ +#ifdef __XCC__ + +#include +typedef _TIE_xtbool xtbool; +typedef _TIE_xtbool2 xtbool2; +typedef _TIE_xtbool4 xtbool4; +typedef _TIE_xtbool8 xtbool8; +typedef _TIE_xtbool16 xtbool16; + +/* + * The following prototypes describe intrinsic functions + * corresponding to TIE instructions. Some TIE instructions + * may produce multiple results (designated as "out" operands + * in the iclass section) or may have operands used as both + * inputs and outputs (designated as "inout"). However, the C + * and C++ languages do not provide syntax that can express + * the in/out/inout constraints of TIE intrinsics. + * Nevertheless, the compiler understands these constraints + * and will check that the intrinsic functions are used + * correctly. To improve the readability of these prototypes, + * the "out" and "inout" parameters are marked accordingly + * with comments. + */ + +extern xtbool _TIE_xt_booleans_XORB(xtbool bs, xtbool bt); +extern xtbool _TIE_xt_booleans_ORBC(xtbool bs, xtbool bt); +extern xtbool _TIE_xt_booleans_ORB(xtbool bs, xtbool bt); +extern xtbool _TIE_xt_booleans_ANDBC(xtbool bs, xtbool bt); +extern xtbool _TIE_xt_booleans_ANDB(xtbool bs, xtbool bt); +extern xtbool _TIE_xt_booleans_ALL4(xtbool4 bs4); +extern xtbool _TIE_xt_booleans_ANY4(xtbool4 bs4); +extern xtbool _TIE_xt_booleans_ALL8(xtbool8 bs8); +extern xtbool _TIE_xt_booleans_ANY8(xtbool8 bs8); +extern void _TIE_xt_booleans_MOVT(unsigned arr /*inout*/, unsigned ars, xtbool bt); +extern void _TIE_xt_booleans_MOVF(unsigned arr /*inout*/, unsigned ars, xtbool bt); +#define XT_XORB _TIE_xt_booleans_XORB +#define XT_ORBC _TIE_xt_booleans_ORBC +#define XT_ORB _TIE_xt_booleans_ORB +#define XT_ANDBC _TIE_xt_booleans_ANDBC +#define XT_ANDB _TIE_xt_booleans_ANDB +#define XT_ALL4 _TIE_xt_booleans_ALL4 +#define XT_ANY4 _TIE_xt_booleans_ANY4 +#define XT_ALL8 _TIE_xt_booleans_ALL8 +#define XT_ANY8 _TIE_xt_booleans_ANY8 +#define XT_MOVT _TIE_xt_booleans_MOVT +#define XT_MOVF _TIE_xt_booleans_MOVF + +#endif /* __XCC__ */ + +#endif /* __XTENSA__ */ + +#endif /* !_XTENSA_xt_booleans_HEADER */ diff --git a/components/esp32/include/xtensa/tie/xt_coprocessors.h b/components/esp32/include/xtensa/tie/xt_coprocessors.h new file mode 100644 index 0000000000..27215cf1cd --- /dev/null +++ b/components/esp32/include/xtensa/tie/xt_coprocessors.h @@ -0,0 +1,48 @@ +/* Definitions for the xt_coprocessors TIE package */ + +/* + * Customer ID=11657; Build=0x5fe96; Copyright (c) 2004-2010 by Tensilica Inc. ALL RIGHTS RESERVED. + * These coded instructions, statements, and computer programs are the + * copyrighted works and confidential proprietary information of Tensilica Inc. + * They may not be modified, copied, reproduced, distributed, or disclosed to + * third parties in any manner, medium, or form, in whole or in part, without + * the prior written consent of Tensilica Inc. + */ + +/* Do not modify. This is automatically generated.*/ + +#ifndef _XTENSA_xt_coprocessors_HEADER +#define _XTENSA_xt_coprocessors_HEADER + +#ifdef __XTENSA__ +#ifdef __XCC__ + +#include + +/* + * The following prototypes describe intrinsic functions + * corresponding to TIE instructions. Some TIE instructions + * may produce multiple results (designated as "out" operands + * in the iclass section) or may have operands used as both + * inputs and outputs (designated as "inout"). However, the C + * and C++ languages do not provide syntax that can express + * the in/out/inout constraints of TIE intrinsics. + * Nevertheless, the compiler understands these constraints + * and will check that the intrinsic functions are used + * correctly. To improve the readability of these prototypes, + * the "out" and "inout" parameters are marked accordingly + * with comments. + */ + +extern unsigned _TIE_xt_coprocessors_RSR_CPENABLE(void); +extern void _TIE_xt_coprocessors_WSR_CPENABLE(unsigned art); +extern void _TIE_xt_coprocessors_XSR_CPENABLE(unsigned art /*inout*/); +#define XT_RSR_CPENABLE _TIE_xt_coprocessors_RSR_CPENABLE +#define XT_WSR_CPENABLE _TIE_xt_coprocessors_WSR_CPENABLE +#define XT_XSR_CPENABLE _TIE_xt_coprocessors_XSR_CPENABLE + +#endif /* __XCC__ */ + +#endif /* __XTENSA__ */ + +#endif /* !_XTENSA_xt_coprocessors_HEADER */ diff --git a/components/esp32/include/xtensa/tie/xt_core.h b/components/esp32/include/xtensa/tie/xt_core.h new file mode 100644 index 0000000000..469b199e6b --- /dev/null +++ b/components/esp32/include/xtensa/tie/xt_core.h @@ -0,0 +1,395 @@ +/* Definitions for the xt_core TIE package */ + +/* + * Customer ID=11657; Build=0x5fe96; Copyright (c) 2004-2010 by Tensilica Inc. ALL RIGHTS RESERVED. + * These coded instructions, statements, and computer programs are the + * copyrighted works and confidential proprietary information of Tensilica Inc. + * They may not be modified, copied, reproduced, distributed, or disclosed to + * third parties in any manner, medium, or form, in whole or in part, without + * the prior written consent of Tensilica Inc. + */ + +/* Do not modify. This is automatically generated.*/ + +#ifndef _XTENSA_xt_core_HEADER +#define _XTENSA_xt_core_HEADER + +#ifdef __XTENSA__ +#ifdef __XCC__ + + +/* + * The following prototypes describe intrinsic functions + * corresponding to TIE instructions. Some TIE instructions + * may produce multiple results (designated as "out" operands + * in the iclass section) or may have operands used as both + * inputs and outputs (designated as "inout"). However, the C + * and C++ languages do not provide syntax that can express + * the in/out/inout constraints of TIE intrinsics. + * Nevertheless, the compiler understands these constraints + * and will check that the intrinsic functions are used + * correctly. To improve the readability of these prototypes, + * the "out" and "inout" parameters are marked accordingly + * with comments. + */ + +extern void _TIE_xt_core_ILL(void); +extern void _TIE_xt_core_NOP(void); +extern void _TIE_xt_core_SIMCALL(void); +extern void _TIE_xt_core_MEMW(void); +extern void _TIE_xt_core_EXTW(void); +extern void _TIE_xt_core_ISYNC(void); +extern void _TIE_xt_core_DSYNC(void); +extern void _TIE_xt_core_ESYNC(void); +extern void _TIE_xt_core_RSYNC(void); +extern unsigned _TIE_xt_core_RSR_LBEG(void); +extern void _TIE_xt_core_WSR_LBEG(unsigned art); +extern void _TIE_xt_core_XSR_LBEG(unsigned art /*inout*/); +extern unsigned _TIE_xt_core_RSR_CONFIGID0(void); +extern void _TIE_xt_core_WSR_CONFIGID0(unsigned art); +extern unsigned _TIE_xt_core_RSR_CONFIGID1(void); +extern unsigned _TIE_xt_core_RUR_THREADPTR(void); +extern void _TIE_xt_core_WUR_THREADPTR(unsigned v); +extern unsigned _TIE_xt_core_uint32_loadi(const unsigned * p, immediate o); +extern void _TIE_xt_core_uint32_storei(unsigned c, unsigned * p, immediate o); +extern unsigned _TIE_xt_core_uint32_move(unsigned b); +extern int _TIE_xt_core_ADDI(int s, immediate i); +extern int _TIE_xt_core_OR(int s, int t); +extern int _TIE_xt_core_L32I(const int * p, immediate i); +extern void _TIE_xt_core_S32I(int r, int * p, immediate i); +extern void _TIE_xt_core_S32NB(int r, int * p, immediate i); +extern unsigned char _TIE_xt_core_L8UI(const unsigned char * p, immediate i); +extern void _TIE_xt_core_S8I(signed char r, signed char * p, immediate i); +extern unsigned short _TIE_xt_core_L16UI(const unsigned short * p, immediate i); +extern short _TIE_xt_core_L16SI(const short * p, immediate i); +extern void _TIE_xt_core_S16I(short r, short * p, immediate i); +extern int _TIE_xt_core_ADDMI(int s, immediate i); +extern int _TIE_xt_core_ADD(int s, int t); +extern int _TIE_xt_core_ADDX2(int s, int t); +extern int _TIE_xt_core_ADDX4(int s, int t); +extern int _TIE_xt_core_ADDX8(int s, int t); +extern int _TIE_xt_core_SUB(int s, int t); +extern int _TIE_xt_core_SUBX2(int s, int t); +extern int _TIE_xt_core_SUBX4(int s, int t); +extern int _TIE_xt_core_SUBX8(int s, int t); +extern int _TIE_xt_core_AND(int s, int t); +extern int _TIE_xt_core_XOR(int s, int t); +extern unsigned _TIE_xt_core_EXTUI(unsigned t, immediate i, immediate o); +extern int _TIE_xt_core_MOVI(immediate i); +extern void _TIE_xt_core_MOVEQZ(int r /*inout*/, int s, int t); +extern void _TIE_xt_core_MOVNEZ(int r /*inout*/, int s, int t); +extern void _TIE_xt_core_MOVLTZ(int r /*inout*/, int s, int t); +extern void _TIE_xt_core_MOVGEZ(int r /*inout*/, int s, int t); +extern int _TIE_xt_core_NEG(int t); +extern int _TIE_xt_core_ABS(int t); +extern void _TIE_xt_core_SSR(int s); +extern void _TIE_xt_core_SSL(int s); +extern void _TIE_xt_core_SSA8L(int s); +extern void _TIE_xt_core_SSA8B(int s); +extern void _TIE_xt_core_SSAI(immediate i); +extern int _TIE_xt_core_SLL(int s); +extern int _TIE_xt_core_SRC(int s, int t); +extern unsigned _TIE_xt_core_SRL(unsigned t); +extern int _TIE_xt_core_SRA(int t); +extern int _TIE_xt_core_SLLI(int s, immediate i); +extern int _TIE_xt_core_SRAI(int t, immediate i); +extern unsigned _TIE_xt_core_SRLI(unsigned t, immediate i); +extern int _TIE_xt_core_SSAI_SRC(int src1, int src2, immediate amount); +extern int _TIE_xt_core_SSR_SRC(int src1, int src2, int amount); +extern int _TIE_xt_core_WSR_SAR_SRC(int src1, int src2, int amount); +extern int _TIE_xt_core_SSR_SRA(int src, int amount); +extern unsigned _TIE_xt_core_SSR_SRL(unsigned src, int amount); +extern int _TIE_xt_core_SSL_SLL(int src, int amount); +extern int _TIE_xt_core_RSIL(immediate t); +extern int _TIE_xt_core_RSR_LEND(void); +extern void _TIE_xt_core_WSR_LEND(int t); +extern void _TIE_xt_core_XSR_LEND(int t /*inout*/); +extern int _TIE_xt_core_RSR_LCOUNT(void); +extern void _TIE_xt_core_WSR_LCOUNT(int t); +extern void _TIE_xt_core_XSR_LCOUNT(int t /*inout*/); +extern unsigned _TIE_xt_core_RSR_SAR(void); +extern void _TIE_xt_core_WSR_SAR(unsigned t); +extern void _TIE_xt_core_XSR_SAR(unsigned t /*inout*/); +extern unsigned _TIE_xt_core_RSR_MEMCTL(void); +extern void _TIE_xt_core_WSR_MEMCTL(unsigned t); +extern void _TIE_xt_core_XSR_MEMCTL(unsigned t /*inout*/); +extern unsigned _TIE_xt_core_RSR_LITBASE(void); +extern void _TIE_xt_core_WSR_LITBASE(unsigned t); +extern void _TIE_xt_core_XSR_LITBASE(unsigned t /*inout*/); +extern unsigned _TIE_xt_core_RSR_PS(void); +extern void _TIE_xt_core_WSR_PS(unsigned t); +extern void _TIE_xt_core_XSR_PS(unsigned t /*inout*/); +extern unsigned _TIE_xt_core_RSR_EPC1(void); +extern void _TIE_xt_core_WSR_EPC1(unsigned t); +extern void _TIE_xt_core_XSR_EPC1(unsigned t /*inout*/); +extern unsigned _TIE_xt_core_RSR_EXCSAVE1(void); +extern void _TIE_xt_core_WSR_EXCSAVE1(unsigned t); +extern void _TIE_xt_core_XSR_EXCSAVE1(unsigned t /*inout*/); +extern unsigned _TIE_xt_core_RSR_EPC2(void); +extern void _TIE_xt_core_WSR_EPC2(unsigned t); +extern void _TIE_xt_core_XSR_EPC2(unsigned t /*inout*/); +extern unsigned _TIE_xt_core_RSR_EXCSAVE2(void); +extern void _TIE_xt_core_WSR_EXCSAVE2(unsigned t); +extern void _TIE_xt_core_XSR_EXCSAVE2(unsigned t /*inout*/); +extern unsigned _TIE_xt_core_RSR_EPC3(void); +extern void _TIE_xt_core_WSR_EPC3(unsigned t); +extern void _TIE_xt_core_XSR_EPC3(unsigned t /*inout*/); +extern unsigned _TIE_xt_core_RSR_EXCSAVE3(void); +extern void _TIE_xt_core_WSR_EXCSAVE3(unsigned t); +extern void _TIE_xt_core_XSR_EXCSAVE3(unsigned t /*inout*/); +extern unsigned _TIE_xt_core_RSR_EPC4(void); +extern void _TIE_xt_core_WSR_EPC4(unsigned t); +extern void _TIE_xt_core_XSR_EPC4(unsigned t /*inout*/); +extern unsigned _TIE_xt_core_RSR_EXCSAVE4(void); +extern void _TIE_xt_core_WSR_EXCSAVE4(unsigned t); +extern void _TIE_xt_core_XSR_EXCSAVE4(unsigned t /*inout*/); +extern unsigned _TIE_xt_core_RSR_EPC5(void); +extern void _TIE_xt_core_WSR_EPC5(unsigned t); +extern void _TIE_xt_core_XSR_EPC5(unsigned t /*inout*/); +extern unsigned _TIE_xt_core_RSR_EXCSAVE5(void); +extern void _TIE_xt_core_WSR_EXCSAVE5(unsigned t); +extern void _TIE_xt_core_XSR_EXCSAVE5(unsigned t /*inout*/); +extern unsigned _TIE_xt_core_RSR_EPC6(void); +extern void _TIE_xt_core_WSR_EPC6(unsigned t); +extern void _TIE_xt_core_XSR_EPC6(unsigned t /*inout*/); +extern unsigned _TIE_xt_core_RSR_EXCSAVE6(void); +extern void _TIE_xt_core_WSR_EXCSAVE6(unsigned t); +extern void _TIE_xt_core_XSR_EXCSAVE6(unsigned t /*inout*/); +extern unsigned _TIE_xt_core_RSR_EPC7(void); +extern void _TIE_xt_core_WSR_EPC7(unsigned t); +extern void _TIE_xt_core_XSR_EPC7(unsigned t /*inout*/); +extern unsigned _TIE_xt_core_RSR_EXCSAVE7(void); +extern void _TIE_xt_core_WSR_EXCSAVE7(unsigned t); +extern void _TIE_xt_core_XSR_EXCSAVE7(unsigned t /*inout*/); +extern unsigned _TIE_xt_core_RSR_VECBASE(void); +extern void _TIE_xt_core_WSR_VECBASE(unsigned t); +extern void _TIE_xt_core_XSR_VECBASE(unsigned t /*inout*/); +extern unsigned _TIE_xt_core_RSR_EPS2(void); +extern void _TIE_xt_core_WSR_EPS2(unsigned t); +extern void _TIE_xt_core_XSR_EPS2(unsigned t /*inout*/); +extern unsigned _TIE_xt_core_RSR_EPS3(void); +extern void _TIE_xt_core_WSR_EPS3(unsigned t); +extern void _TIE_xt_core_XSR_EPS3(unsigned t /*inout*/); +extern unsigned _TIE_xt_core_RSR_EPS4(void); +extern void _TIE_xt_core_WSR_EPS4(unsigned t); +extern void _TIE_xt_core_XSR_EPS4(unsigned t /*inout*/); +extern unsigned _TIE_xt_core_RSR_EPS5(void); +extern void _TIE_xt_core_WSR_EPS5(unsigned t); +extern void _TIE_xt_core_XSR_EPS5(unsigned t /*inout*/); +extern unsigned _TIE_xt_core_RSR_EPS6(void); +extern void _TIE_xt_core_WSR_EPS6(unsigned t); +extern void _TIE_xt_core_XSR_EPS6(unsigned t /*inout*/); +extern unsigned _TIE_xt_core_RSR_EPS7(void); +extern void _TIE_xt_core_WSR_EPS7(unsigned t); +extern void _TIE_xt_core_XSR_EPS7(unsigned t /*inout*/); +extern unsigned _TIE_xt_core_RSR_EXCCAUSE(void); +extern void _TIE_xt_core_WSR_EXCCAUSE(unsigned t); +extern void _TIE_xt_core_XSR_EXCCAUSE(unsigned t /*inout*/); +extern unsigned _TIE_xt_core_RSR_EXCVADDR(void); +extern void _TIE_xt_core_WSR_EXCVADDR(unsigned t); +extern void _TIE_xt_core_XSR_EXCVADDR(unsigned t /*inout*/); +extern unsigned _TIE_xt_core_RSR_DEPC(void); +extern void _TIE_xt_core_WSR_DEPC(unsigned t); +extern void _TIE_xt_core_XSR_DEPC(unsigned t /*inout*/); +extern unsigned _TIE_xt_core_RSR_MISC0(void); +extern void _TIE_xt_core_WSR_MISC0(unsigned t); +extern void _TIE_xt_core_XSR_MISC0(unsigned t /*inout*/); +extern unsigned _TIE_xt_core_RSR_MISC1(void); +extern void _TIE_xt_core_WSR_MISC1(unsigned t); +extern void _TIE_xt_core_XSR_MISC1(unsigned t /*inout*/); +extern unsigned _TIE_xt_core_RSR_MISC2(void); +extern void _TIE_xt_core_WSR_MISC2(unsigned t); +extern void _TIE_xt_core_XSR_MISC2(unsigned t /*inout*/); +extern unsigned _TIE_xt_core_RSR_MISC3(void); +extern void _TIE_xt_core_WSR_MISC3(unsigned t); +extern void _TIE_xt_core_XSR_MISC3(unsigned t /*inout*/); +extern int _TIE_xt_core_RSR_PRID(void); +#define XT_ILL _TIE_xt_core_ILL +#define XT_NOP _TIE_xt_core_NOP +#define XT_SIMCALL _TIE_xt_core_SIMCALL +#define XT_MEMW _TIE_xt_core_MEMW +#define XT_EXTW _TIE_xt_core_EXTW +#define XT_ISYNC _TIE_xt_core_ISYNC +#define XT_DSYNC _TIE_xt_core_DSYNC +#define XT_ESYNC _TIE_xt_core_ESYNC +#define XT_RSYNC _TIE_xt_core_RSYNC +#define XT_RSR_LBEG _TIE_xt_core_RSR_LBEG +#define XT_WSR_LBEG _TIE_xt_core_WSR_LBEG +#define XT_XSR_LBEG _TIE_xt_core_XSR_LBEG +#define XT_RSR_CONFIGID0 _TIE_xt_core_RSR_CONFIGID0 +#define XT_WSR_CONFIGID0 _TIE_xt_core_WSR_CONFIGID0 +#define XT_RSR_CONFIGID1 _TIE_xt_core_RSR_CONFIGID1 +#define XT_RUR_THREADPTR _TIE_xt_core_RUR_THREADPTR +#define RTHREADPTR _TIE_xt_core_RUR_THREADPTR +#define RUR231 _TIE_xt_core_RUR_THREADPTR +#define XT_WUR_THREADPTR _TIE_xt_core_WUR_THREADPTR +#define WTHREADPTR _TIE_xt_core_WUR_THREADPTR +#define WUR231 _TIE_xt_core_WUR_THREADPTR +#define XT_uint32_loadi _TIE_xt_core_uint32_loadi +#define XT_uint32_storei _TIE_xt_core_uint32_storei +#define XT_uint32_move _TIE_xt_core_uint32_move +#define XT_ADDI _TIE_xt_core_ADDI +#define XT_OR _TIE_xt_core_OR +#define XT_L32I _TIE_xt_core_L32I +#define XT_S32I _TIE_xt_core_S32I +#define XT_S32NB _TIE_xt_core_S32NB +#define XT_L8UI _TIE_xt_core_L8UI +#define XT_S8I _TIE_xt_core_S8I +#define XT_L16UI _TIE_xt_core_L16UI +#define XT_L16SI _TIE_xt_core_L16SI +#define XT_S16I _TIE_xt_core_S16I +#define XT_ADDMI _TIE_xt_core_ADDMI +#define XT_ADD _TIE_xt_core_ADD +#define XT_ADDX2 _TIE_xt_core_ADDX2 +#define XT_ADDX4 _TIE_xt_core_ADDX4 +#define XT_ADDX8 _TIE_xt_core_ADDX8 +#define XT_SUB _TIE_xt_core_SUB +#define XT_SUBX2 _TIE_xt_core_SUBX2 +#define XT_SUBX4 _TIE_xt_core_SUBX4 +#define XT_SUBX8 _TIE_xt_core_SUBX8 +#define XT_AND _TIE_xt_core_AND +#define XT_XOR _TIE_xt_core_XOR +#define XT_EXTUI _TIE_xt_core_EXTUI +#define XT_MOVI _TIE_xt_core_MOVI +#define XT_MOVEQZ _TIE_xt_core_MOVEQZ +#define XT_MOVNEZ _TIE_xt_core_MOVNEZ +#define XT_MOVLTZ _TIE_xt_core_MOVLTZ +#define XT_MOVGEZ _TIE_xt_core_MOVGEZ +#define XT_NEG _TIE_xt_core_NEG +#define XT_ABS _TIE_xt_core_ABS +#define XT_SSR _TIE_xt_core_SSR +#define XT_SSL _TIE_xt_core_SSL +#define XT_SSA8L _TIE_xt_core_SSA8L +#define XT_SSA8B _TIE_xt_core_SSA8B +#define XT_SSAI _TIE_xt_core_SSAI +#define XT_SLL _TIE_xt_core_SLL +#define XT_SRC _TIE_xt_core_SRC +#define XT_SRL _TIE_xt_core_SRL +#define XT_SRA _TIE_xt_core_SRA +#define XT_SLLI _TIE_xt_core_SLLI +#define XT_SRAI _TIE_xt_core_SRAI +#define XT_SRLI _TIE_xt_core_SRLI +#define XT_SSAI_SRC _TIE_xt_core_SSAI_SRC +#define XT_SSR_SRC _TIE_xt_core_SSR_SRC +#define XT_WSR_SAR_SRC _TIE_xt_core_WSR_SAR_SRC +#define XT_SSR_SRA _TIE_xt_core_SSR_SRA +#define XT_SSR_SRL _TIE_xt_core_SSR_SRL +#define XT_SSL_SLL _TIE_xt_core_SSL_SLL +#define XT_RSIL _TIE_xt_core_RSIL +#define XT_RSR_LEND _TIE_xt_core_RSR_LEND +#define XT_WSR_LEND _TIE_xt_core_WSR_LEND +#define XT_XSR_LEND _TIE_xt_core_XSR_LEND +#define XT_RSR_LCOUNT _TIE_xt_core_RSR_LCOUNT +#define XT_WSR_LCOUNT _TIE_xt_core_WSR_LCOUNT +#define XT_XSR_LCOUNT _TIE_xt_core_XSR_LCOUNT +#define XT_RSR_SAR _TIE_xt_core_RSR_SAR +#define XT_WSR_SAR _TIE_xt_core_WSR_SAR +#define XT_XSR_SAR _TIE_xt_core_XSR_SAR +#define XT_RSR_MEMCTL _TIE_xt_core_RSR_MEMCTL +#define XT_WSR_MEMCTL _TIE_xt_core_WSR_MEMCTL +#define XT_XSR_MEMCTL _TIE_xt_core_XSR_MEMCTL +#define XT_RSR_LITBASE _TIE_xt_core_RSR_LITBASE +#define XT_WSR_LITBASE _TIE_xt_core_WSR_LITBASE +#define XT_XSR_LITBASE _TIE_xt_core_XSR_LITBASE +#define XT_RSR_PS _TIE_xt_core_RSR_PS +#define XT_WSR_PS _TIE_xt_core_WSR_PS +#define XT_XSR_PS _TIE_xt_core_XSR_PS +#define XT_RSR_EPC1 _TIE_xt_core_RSR_EPC1 +#define XT_WSR_EPC1 _TIE_xt_core_WSR_EPC1 +#define XT_XSR_EPC1 _TIE_xt_core_XSR_EPC1 +#define XT_RSR_EXCSAVE1 _TIE_xt_core_RSR_EXCSAVE1 +#define XT_WSR_EXCSAVE1 _TIE_xt_core_WSR_EXCSAVE1 +#define XT_XSR_EXCSAVE1 _TIE_xt_core_XSR_EXCSAVE1 +#define XT_RSR_EPC2 _TIE_xt_core_RSR_EPC2 +#define XT_WSR_EPC2 _TIE_xt_core_WSR_EPC2 +#define XT_XSR_EPC2 _TIE_xt_core_XSR_EPC2 +#define XT_RSR_EXCSAVE2 _TIE_xt_core_RSR_EXCSAVE2 +#define XT_WSR_EXCSAVE2 _TIE_xt_core_WSR_EXCSAVE2 +#define XT_XSR_EXCSAVE2 _TIE_xt_core_XSR_EXCSAVE2 +#define XT_RSR_EPC3 _TIE_xt_core_RSR_EPC3 +#define XT_WSR_EPC3 _TIE_xt_core_WSR_EPC3 +#define XT_XSR_EPC3 _TIE_xt_core_XSR_EPC3 +#define XT_RSR_EXCSAVE3 _TIE_xt_core_RSR_EXCSAVE3 +#define XT_WSR_EXCSAVE3 _TIE_xt_core_WSR_EXCSAVE3 +#define XT_XSR_EXCSAVE3 _TIE_xt_core_XSR_EXCSAVE3 +#define XT_RSR_EPC4 _TIE_xt_core_RSR_EPC4 +#define XT_WSR_EPC4 _TIE_xt_core_WSR_EPC4 +#define XT_XSR_EPC4 _TIE_xt_core_XSR_EPC4 +#define XT_RSR_EXCSAVE4 _TIE_xt_core_RSR_EXCSAVE4 +#define XT_WSR_EXCSAVE4 _TIE_xt_core_WSR_EXCSAVE4 +#define XT_XSR_EXCSAVE4 _TIE_xt_core_XSR_EXCSAVE4 +#define XT_RSR_EPC5 _TIE_xt_core_RSR_EPC5 +#define XT_WSR_EPC5 _TIE_xt_core_WSR_EPC5 +#define XT_XSR_EPC5 _TIE_xt_core_XSR_EPC5 +#define XT_RSR_EXCSAVE5 _TIE_xt_core_RSR_EXCSAVE5 +#define XT_WSR_EXCSAVE5 _TIE_xt_core_WSR_EXCSAVE5 +#define XT_XSR_EXCSAVE5 _TIE_xt_core_XSR_EXCSAVE5 +#define XT_RSR_EPC6 _TIE_xt_core_RSR_EPC6 +#define XT_WSR_EPC6 _TIE_xt_core_WSR_EPC6 +#define XT_XSR_EPC6 _TIE_xt_core_XSR_EPC6 +#define XT_RSR_EXCSAVE6 _TIE_xt_core_RSR_EXCSAVE6 +#define XT_WSR_EXCSAVE6 _TIE_xt_core_WSR_EXCSAVE6 +#define XT_XSR_EXCSAVE6 _TIE_xt_core_XSR_EXCSAVE6 +#define XT_RSR_EPC7 _TIE_xt_core_RSR_EPC7 +#define XT_WSR_EPC7 _TIE_xt_core_WSR_EPC7 +#define XT_XSR_EPC7 _TIE_xt_core_XSR_EPC7 +#define XT_RSR_EXCSAVE7 _TIE_xt_core_RSR_EXCSAVE7 +#define XT_WSR_EXCSAVE7 _TIE_xt_core_WSR_EXCSAVE7 +#define XT_XSR_EXCSAVE7 _TIE_xt_core_XSR_EXCSAVE7 +#define XT_RSR_VECBASE _TIE_xt_core_RSR_VECBASE +#define XT_WSR_VECBASE _TIE_xt_core_WSR_VECBASE +#define XT_XSR_VECBASE _TIE_xt_core_XSR_VECBASE +#define XT_RSR_EPS2 _TIE_xt_core_RSR_EPS2 +#define XT_WSR_EPS2 _TIE_xt_core_WSR_EPS2 +#define XT_XSR_EPS2 _TIE_xt_core_XSR_EPS2 +#define XT_RSR_EPS3 _TIE_xt_core_RSR_EPS3 +#define XT_WSR_EPS3 _TIE_xt_core_WSR_EPS3 +#define XT_XSR_EPS3 _TIE_xt_core_XSR_EPS3 +#define XT_RSR_EPS4 _TIE_xt_core_RSR_EPS4 +#define XT_WSR_EPS4 _TIE_xt_core_WSR_EPS4 +#define XT_XSR_EPS4 _TIE_xt_core_XSR_EPS4 +#define XT_RSR_EPS5 _TIE_xt_core_RSR_EPS5 +#define XT_WSR_EPS5 _TIE_xt_core_WSR_EPS5 +#define XT_XSR_EPS5 _TIE_xt_core_XSR_EPS5 +#define XT_RSR_EPS6 _TIE_xt_core_RSR_EPS6 +#define XT_WSR_EPS6 _TIE_xt_core_WSR_EPS6 +#define XT_XSR_EPS6 _TIE_xt_core_XSR_EPS6 +#define XT_RSR_EPS7 _TIE_xt_core_RSR_EPS7 +#define XT_WSR_EPS7 _TIE_xt_core_WSR_EPS7 +#define XT_XSR_EPS7 _TIE_xt_core_XSR_EPS7 +#define XT_RSR_EXCCAUSE _TIE_xt_core_RSR_EXCCAUSE +#define XT_WSR_EXCCAUSE _TIE_xt_core_WSR_EXCCAUSE +#define XT_XSR_EXCCAUSE _TIE_xt_core_XSR_EXCCAUSE +#define XT_RSR_EXCVADDR _TIE_xt_core_RSR_EXCVADDR +#define XT_WSR_EXCVADDR _TIE_xt_core_WSR_EXCVADDR +#define XT_XSR_EXCVADDR _TIE_xt_core_XSR_EXCVADDR +#define XT_RSR_DEPC _TIE_xt_core_RSR_DEPC +#define XT_WSR_DEPC _TIE_xt_core_WSR_DEPC +#define XT_XSR_DEPC _TIE_xt_core_XSR_DEPC +#define XT_RSR_MISC0 _TIE_xt_core_RSR_MISC0 +#define XT_WSR_MISC0 _TIE_xt_core_WSR_MISC0 +#define XT_XSR_MISC0 _TIE_xt_core_XSR_MISC0 +#define XT_RSR_MISC1 _TIE_xt_core_RSR_MISC1 +#define XT_WSR_MISC1 _TIE_xt_core_WSR_MISC1 +#define XT_XSR_MISC1 _TIE_xt_core_XSR_MISC1 +#define XT_RSR_MISC2 _TIE_xt_core_RSR_MISC2 +#define XT_WSR_MISC2 _TIE_xt_core_WSR_MISC2 +#define XT_XSR_MISC2 _TIE_xt_core_XSR_MISC2 +#define XT_RSR_MISC3 _TIE_xt_core_RSR_MISC3 +#define XT_WSR_MISC3 _TIE_xt_core_WSR_MISC3 +#define XT_XSR_MISC3 _TIE_xt_core_XSR_MISC3 +#define XT_RSR_PRID _TIE_xt_core_RSR_PRID + +#ifndef RUR +#define RUR(NUM) RUR##NUM() +#endif + +#ifndef WUR +#define WUR(VAL, NUM) WUR##NUM(VAL) +#endif + +#endif /* __XCC__ */ + +#endif /* __XTENSA__ */ + +#endif /* !_XTENSA_xt_core_HEADER */ diff --git a/components/esp32/include/xtensa/tie/xt_debug.h b/components/esp32/include/xtensa/tie/xt_debug.h new file mode 100644 index 0000000000..676fd33c78 --- /dev/null +++ b/components/esp32/include/xtensa/tie/xt_debug.h @@ -0,0 +1,116 @@ +/* Definitions for the xt_debug TIE package */ + +/* + * Customer ID=11657; Build=0x5fe96; Copyright (c) 2004-2010 by Tensilica Inc. ALL RIGHTS RESERVED. + * These coded instructions, statements, and computer programs are the + * copyrighted works and confidential proprietary information of Tensilica Inc. + * They may not be modified, copied, reproduced, distributed, or disclosed to + * third parties in any manner, medium, or form, in whole or in part, without + * the prior written consent of Tensilica Inc. + */ + +/* Do not modify. This is automatically generated.*/ + +#ifndef _XTENSA_xt_debug_HEADER +#define _XTENSA_xt_debug_HEADER + +#ifdef __XTENSA__ +#ifdef __XCC__ + +#include + +/* + * The following prototypes describe intrinsic functions + * corresponding to TIE instructions. Some TIE instructions + * may produce multiple results (designated as "out" operands + * in the iclass section) or may have operands used as both + * inputs and outputs (designated as "inout"). However, the C + * and C++ languages do not provide syntax that can express + * the in/out/inout constraints of TIE intrinsics. + * Nevertheless, the compiler understands these constraints + * and will check that the intrinsic functions are used + * correctly. To improve the readability of these prototypes, + * the "out" and "inout" parameters are marked accordingly + * with comments. + */ + +extern void _TIE_xt_debug_BREAK(immediate imms, immediate immt); +extern void _TIE_xt_debug_BREAK_N(immediate imms); +extern unsigned _TIE_xt_debug_RSR_DBREAKA0(void); +extern void _TIE_xt_debug_WSR_DBREAKA0(unsigned art); +extern void _TIE_xt_debug_XSR_DBREAKA0(unsigned art /*inout*/); +extern unsigned _TIE_xt_debug_RSR_DBREAKC0(void); +extern void _TIE_xt_debug_WSR_DBREAKC0(unsigned art); +extern void _TIE_xt_debug_XSR_DBREAKC0(unsigned art /*inout*/); +extern unsigned _TIE_xt_debug_RSR_DBREAKA1(void); +extern void _TIE_xt_debug_WSR_DBREAKA1(unsigned art); +extern void _TIE_xt_debug_XSR_DBREAKA1(unsigned art /*inout*/); +extern unsigned _TIE_xt_debug_RSR_DBREAKC1(void); +extern void _TIE_xt_debug_WSR_DBREAKC1(unsigned art); +extern void _TIE_xt_debug_XSR_DBREAKC1(unsigned art /*inout*/); +extern unsigned _TIE_xt_debug_RSR_IBREAKA0(void); +extern void _TIE_xt_debug_WSR_IBREAKA0(unsigned art); +extern void _TIE_xt_debug_XSR_IBREAKA0(unsigned art /*inout*/); +extern unsigned _TIE_xt_debug_RSR_IBREAKA1(void); +extern void _TIE_xt_debug_WSR_IBREAKA1(unsigned art); +extern void _TIE_xt_debug_XSR_IBREAKA1(unsigned art /*inout*/); +extern unsigned _TIE_xt_debug_RSR_IBREAKENABLE(void); +extern void _TIE_xt_debug_WSR_IBREAKENABLE(unsigned art); +extern void _TIE_xt_debug_XSR_IBREAKENABLE(unsigned art /*inout*/); +extern unsigned _TIE_xt_debug_RSR_DEBUGCAUSE(void); +extern void _TIE_xt_debug_WSR_DEBUGCAUSE(unsigned art); +extern void _TIE_xt_debug_XSR_DEBUGCAUSE(unsigned art /*inout*/); +extern unsigned _TIE_xt_debug_RSR_ICOUNT(void); +extern void _TIE_xt_debug_WSR_ICOUNT(unsigned art); +extern void _TIE_xt_debug_XSR_ICOUNT(unsigned art /*inout*/); +extern unsigned _TIE_xt_debug_RSR_ICOUNTLEVEL(void); +extern void _TIE_xt_debug_WSR_ICOUNTLEVEL(unsigned art); +extern void _TIE_xt_debug_XSR_ICOUNTLEVEL(unsigned art /*inout*/); +extern unsigned _TIE_xt_debug_RSR_DDR(void); +extern void _TIE_xt_debug_WSR_DDR(unsigned art); +extern void _TIE_xt_debug_XSR_DDR(unsigned art /*inout*/); +extern void _TIE_xt_debug_LDDR32_P(const void * ars /*inout*/); +extern void _TIE_xt_debug_SDDR32_P(void * ars /*inout*/); +#define XT_BREAK _TIE_xt_debug_BREAK +#define XT_BREAK_N _TIE_xt_debug_BREAK_N +#define XT_RSR_DBREAKA0 _TIE_xt_debug_RSR_DBREAKA0 +#define XT_WSR_DBREAKA0 _TIE_xt_debug_WSR_DBREAKA0 +#define XT_XSR_DBREAKA0 _TIE_xt_debug_XSR_DBREAKA0 +#define XT_RSR_DBREAKC0 _TIE_xt_debug_RSR_DBREAKC0 +#define XT_WSR_DBREAKC0 _TIE_xt_debug_WSR_DBREAKC0 +#define XT_XSR_DBREAKC0 _TIE_xt_debug_XSR_DBREAKC0 +#define XT_RSR_DBREAKA1 _TIE_xt_debug_RSR_DBREAKA1 +#define XT_WSR_DBREAKA1 _TIE_xt_debug_WSR_DBREAKA1 +#define XT_XSR_DBREAKA1 _TIE_xt_debug_XSR_DBREAKA1 +#define XT_RSR_DBREAKC1 _TIE_xt_debug_RSR_DBREAKC1 +#define XT_WSR_DBREAKC1 _TIE_xt_debug_WSR_DBREAKC1 +#define XT_XSR_DBREAKC1 _TIE_xt_debug_XSR_DBREAKC1 +#define XT_RSR_IBREAKA0 _TIE_xt_debug_RSR_IBREAKA0 +#define XT_WSR_IBREAKA0 _TIE_xt_debug_WSR_IBREAKA0 +#define XT_XSR_IBREAKA0 _TIE_xt_debug_XSR_IBREAKA0 +#define XT_RSR_IBREAKA1 _TIE_xt_debug_RSR_IBREAKA1 +#define XT_WSR_IBREAKA1 _TIE_xt_debug_WSR_IBREAKA1 +#define XT_XSR_IBREAKA1 _TIE_xt_debug_XSR_IBREAKA1 +#define XT_RSR_IBREAKENABLE _TIE_xt_debug_RSR_IBREAKENABLE +#define XT_WSR_IBREAKENABLE _TIE_xt_debug_WSR_IBREAKENABLE +#define XT_XSR_IBREAKENABLE _TIE_xt_debug_XSR_IBREAKENABLE +#define XT_RSR_DEBUGCAUSE _TIE_xt_debug_RSR_DEBUGCAUSE +#define XT_WSR_DEBUGCAUSE _TIE_xt_debug_WSR_DEBUGCAUSE +#define XT_XSR_DEBUGCAUSE _TIE_xt_debug_XSR_DEBUGCAUSE +#define XT_RSR_ICOUNT _TIE_xt_debug_RSR_ICOUNT +#define XT_WSR_ICOUNT _TIE_xt_debug_WSR_ICOUNT +#define XT_XSR_ICOUNT _TIE_xt_debug_XSR_ICOUNT +#define XT_RSR_ICOUNTLEVEL _TIE_xt_debug_RSR_ICOUNTLEVEL +#define XT_WSR_ICOUNTLEVEL _TIE_xt_debug_WSR_ICOUNTLEVEL +#define XT_XSR_ICOUNTLEVEL _TIE_xt_debug_XSR_ICOUNTLEVEL +#define XT_RSR_DDR _TIE_xt_debug_RSR_DDR +#define XT_WSR_DDR _TIE_xt_debug_WSR_DDR +#define XT_XSR_DDR _TIE_xt_debug_XSR_DDR +#define XT_LDDR32_P _TIE_xt_debug_LDDR32_P +#define XT_SDDR32_P _TIE_xt_debug_SDDR32_P + +#endif /* __XCC__ */ + +#endif /* __XTENSA__ */ + +#endif /* !_XTENSA_xt_debug_HEADER */ diff --git a/components/esp32/include/xtensa/tie/xt_density.h b/components/esp32/include/xtensa/tie/xt_density.h new file mode 100644 index 0000000000..da5c51ccf0 --- /dev/null +++ b/components/esp32/include/xtensa/tie/xt_density.h @@ -0,0 +1,58 @@ +/* Definitions for the xt_density TIE package */ + +/* + * Customer ID=11657; Build=0x5fe96; Copyright (c) 2004-2010 by Tensilica Inc. ALL RIGHTS RESERVED. + * These coded instructions, statements, and computer programs are the + * copyrighted works and confidential proprietary information of Tensilica Inc. + * They may not be modified, copied, reproduced, distributed, or disclosed to + * third parties in any manner, medium, or form, in whole or in part, without + * the prior written consent of Tensilica Inc. + */ + +/* Do not modify. This is automatically generated.*/ + +#ifndef _XTENSA_xt_density_HEADER +#define _XTENSA_xt_density_HEADER + +#ifdef __XTENSA__ +#ifdef __XCC__ + +#include + +/* + * The following prototypes describe intrinsic functions + * corresponding to TIE instructions. Some TIE instructions + * may produce multiple results (designated as "out" operands + * in the iclass section) or may have operands used as both + * inputs and outputs (designated as "inout"). However, the C + * and C++ languages do not provide syntax that can express + * the in/out/inout constraints of TIE intrinsics. + * Nevertheless, the compiler understands these constraints + * and will check that the intrinsic functions are used + * correctly. To improve the readability of these prototypes, + * the "out" and "inout" parameters are marked accordingly + * with comments. + */ + +extern void _TIE_xt_density_ILL_N(void); +extern void _TIE_xt_density_NOP_N(void); +extern int _TIE_xt_density_L32I_N(const int * p, immediate i); +extern void _TIE_xt_density_S32I_N(int t, int * p, immediate i); +extern int _TIE_xt_density_ADD_N(int s, int t); +extern int _TIE_xt_density_ADDI_N(int s, immediate i); +extern int _TIE_xt_density_MOV_N(int s); +extern int _TIE_xt_density_MOVI_N(immediate i); +#define XT_ILL_N _TIE_xt_density_ILL_N +#define XT_NOP_N _TIE_xt_density_NOP_N +#define XT_L32I_N _TIE_xt_density_L32I_N +#define XT_S32I_N _TIE_xt_density_S32I_N +#define XT_ADD_N _TIE_xt_density_ADD_N +#define XT_ADDI_N _TIE_xt_density_ADDI_N +#define XT_MOV_N _TIE_xt_density_MOV_N +#define XT_MOVI_N _TIE_xt_density_MOVI_N + +#endif /* __XCC__ */ + +#endif /* __XTENSA__ */ + +#endif /* !_XTENSA_xt_density_HEADER */ diff --git a/components/esp32/include/xtensa/tie/xt_exceptions.h b/components/esp32/include/xtensa/tie/xt_exceptions.h new file mode 100644 index 0000000000..64fb393079 --- /dev/null +++ b/components/esp32/include/xtensa/tie/xt_exceptions.h @@ -0,0 +1,45 @@ +/* Definitions for the xt_exceptions TIE package */ + +/* + * Customer ID=11657; Build=0x5fe96; Copyright (c) 2004-2010 by Tensilica Inc. ALL RIGHTS RESERVED. + * These coded instructions, statements, and computer programs are the + * copyrighted works and confidential proprietary information of Tensilica Inc. + * They may not be modified, copied, reproduced, distributed, or disclosed to + * third parties in any manner, medium, or form, in whole or in part, without + * the prior written consent of Tensilica Inc. + */ + +/* Do not modify. This is automatically generated.*/ + +#ifndef _XTENSA_xt_exceptions_HEADER +#define _XTENSA_xt_exceptions_HEADER + +#ifdef __XTENSA__ +#ifdef __XCC__ + + +/* + * The following prototypes describe intrinsic functions + * corresponding to TIE instructions. Some TIE instructions + * may produce multiple results (designated as "out" operands + * in the iclass section) or may have operands used as both + * inputs and outputs (designated as "inout"). However, the C + * and C++ languages do not provide syntax that can express + * the in/out/inout constraints of TIE intrinsics. + * Nevertheless, the compiler understands these constraints + * and will check that the intrinsic functions are used + * correctly. To improve the readability of these prototypes, + * the "out" and "inout" parameters are marked accordingly + * with comments. + */ + +extern void _TIE_xt_exceptions_EXCW(void); +extern void _TIE_xt_exceptions_SYSCALL(void); +#define XT_EXCW _TIE_xt_exceptions_EXCW +#define XT_SYSCALL _TIE_xt_exceptions_SYSCALL + +#endif /* __XCC__ */ + +#endif /* __XTENSA__ */ + +#endif /* !_XTENSA_xt_exceptions_HEADER */ diff --git a/components/esp32/include/xtensa/tie/xt_externalregisters.h b/components/esp32/include/xtensa/tie/xt_externalregisters.h new file mode 100644 index 0000000000..3196527c2f --- /dev/null +++ b/components/esp32/include/xtensa/tie/xt_externalregisters.h @@ -0,0 +1,46 @@ +/* Definitions for the xt_externalregisters TIE package */ + +/* + * Customer ID=11657; Build=0x5fe96; Copyright (c) 2004-2010 by Tensilica Inc. ALL RIGHTS RESERVED. + * These coded instructions, statements, and computer programs are the + * copyrighted works and confidential proprietary information of Tensilica Inc. + * They may not be modified, copied, reproduced, distributed, or disclosed to + * third parties in any manner, medium, or form, in whole or in part, without + * the prior written consent of Tensilica Inc. + */ + +/* Do not modify. This is automatically generated.*/ + +#ifndef _XTENSA_xt_externalregisters_HEADER +#define _XTENSA_xt_externalregisters_HEADER + +#ifdef __XTENSA__ +#ifdef __XCC__ + +#include + +/* + * The following prototypes describe intrinsic functions + * corresponding to TIE instructions. Some TIE instructions + * may produce multiple results (designated as "out" operands + * in the iclass section) or may have operands used as both + * inputs and outputs (designated as "inout"). However, the C + * and C++ languages do not provide syntax that can express + * the in/out/inout constraints of TIE intrinsics. + * Nevertheless, the compiler understands these constraints + * and will check that the intrinsic functions are used + * correctly. To improve the readability of these prototypes, + * the "out" and "inout" parameters are marked accordingly + * with comments. + */ + +extern unsigned _TIE_xt_externalregisters_RER(unsigned ars); +extern void _TIE_xt_externalregisters_WER(unsigned art, unsigned ars); +#define XT_RER _TIE_xt_externalregisters_RER +#define XT_WER _TIE_xt_externalregisters_WER + +#endif /* __XCC__ */ + +#endif /* __XTENSA__ */ + +#endif /* !_XTENSA_xt_externalregisters_HEADER */ diff --git a/components/esp32/include/xtensa/tie/xt_integerdivide.h b/components/esp32/include/xtensa/tie/xt_integerdivide.h new file mode 100644 index 0000000000..9fbe9615b7 --- /dev/null +++ b/components/esp32/include/xtensa/tie/xt_integerdivide.h @@ -0,0 +1,50 @@ +/* Definitions for the xt_integerdivide TIE package */ + +/* + * Customer ID=11657; Build=0x5fe96; Copyright (c) 2004-2010 by Tensilica Inc. ALL RIGHTS RESERVED. + * These coded instructions, statements, and computer programs are the + * copyrighted works and confidential proprietary information of Tensilica Inc. + * They may not be modified, copied, reproduced, distributed, or disclosed to + * third parties in any manner, medium, or form, in whole or in part, without + * the prior written consent of Tensilica Inc. + */ + +/* Do not modify. This is automatically generated.*/ + +#ifndef _XTENSA_xt_integerdivide_HEADER +#define _XTENSA_xt_integerdivide_HEADER + +#ifdef __XTENSA__ +#ifdef __XCC__ + +#include + +/* + * The following prototypes describe intrinsic functions + * corresponding to TIE instructions. Some TIE instructions + * may produce multiple results (designated as "out" operands + * in the iclass section) or may have operands used as both + * inputs and outputs (designated as "inout"). However, the C + * and C++ languages do not provide syntax that can express + * the in/out/inout constraints of TIE intrinsics. + * Nevertheless, the compiler understands these constraints + * and will check that the intrinsic functions are used + * correctly. To improve the readability of these prototypes, + * the "out" and "inout" parameters are marked accordingly + * with comments. + */ + +extern unsigned _TIE_xt_integerdivide_REMS(unsigned ars, unsigned art); +extern unsigned _TIE_xt_integerdivide_REMU(unsigned ars, unsigned art); +extern unsigned _TIE_xt_integerdivide_QUOS(unsigned ars, unsigned art); +extern unsigned _TIE_xt_integerdivide_QUOU(unsigned ars, unsigned art); +#define XT_REMS _TIE_xt_integerdivide_REMS +#define XT_REMU _TIE_xt_integerdivide_REMU +#define XT_QUOS _TIE_xt_integerdivide_QUOS +#define XT_QUOU _TIE_xt_integerdivide_QUOU + +#endif /* __XCC__ */ + +#endif /* __XTENSA__ */ + +#endif /* !_XTENSA_xt_integerdivide_HEADER */ diff --git a/components/esp32/include/xtensa/tie/xt_interrupt.h b/components/esp32/include/xtensa/tie/xt_interrupt.h new file mode 100644 index 0000000000..b20c94f47a --- /dev/null +++ b/components/esp32/include/xtensa/tie/xt_interrupt.h @@ -0,0 +1,56 @@ +/* Definitions for the xt_interrupt TIE package */ + +/* + * Customer ID=11657; Build=0x5fe96; Copyright (c) 2004-2010 by Tensilica Inc. ALL RIGHTS RESERVED. + * These coded instructions, statements, and computer programs are the + * copyrighted works and confidential proprietary information of Tensilica Inc. + * They may not be modified, copied, reproduced, distributed, or disclosed to + * third parties in any manner, medium, or form, in whole or in part, without + * the prior written consent of Tensilica Inc. + */ + +/* Do not modify. This is automatically generated.*/ + +#ifndef _XTENSA_xt_interrupt_HEADER +#define _XTENSA_xt_interrupt_HEADER + +#ifdef __XTENSA__ +#ifdef __XCC__ + +#include + +/* + * The following prototypes describe intrinsic functions + * corresponding to TIE instructions. Some TIE instructions + * may produce multiple results (designated as "out" operands + * in the iclass section) or may have operands used as both + * inputs and outputs (designated as "inout"). However, the C + * and C++ languages do not provide syntax that can express + * the in/out/inout constraints of TIE intrinsics. + * Nevertheless, the compiler understands these constraints + * and will check that the intrinsic functions are used + * correctly. To improve the readability of these prototypes, + * the "out" and "inout" parameters are marked accordingly + * with comments. + */ + +extern void _TIE_xt_interrupt_WAITI(immediate s); +extern unsigned _TIE_xt_interrupt_RSR_INTERRUPT(void); +extern void _TIE_xt_interrupt_WSR_INTSET(unsigned art); +extern void _TIE_xt_interrupt_WSR_INTCLEAR(unsigned art); +extern unsigned _TIE_xt_interrupt_RSR_INTENABLE(void); +extern void _TIE_xt_interrupt_WSR_INTENABLE(unsigned art); +extern void _TIE_xt_interrupt_XSR_INTENABLE(unsigned art /*inout*/); +#define XT_WAITI _TIE_xt_interrupt_WAITI +#define XT_RSR_INTERRUPT _TIE_xt_interrupt_RSR_INTERRUPT +#define XT_WSR_INTSET _TIE_xt_interrupt_WSR_INTSET +#define XT_WSR_INTCLEAR _TIE_xt_interrupt_WSR_INTCLEAR +#define XT_RSR_INTENABLE _TIE_xt_interrupt_RSR_INTENABLE +#define XT_WSR_INTENABLE _TIE_xt_interrupt_WSR_INTENABLE +#define XT_XSR_INTENABLE _TIE_xt_interrupt_XSR_INTENABLE + +#endif /* __XCC__ */ + +#endif /* __XTENSA__ */ + +#endif /* !_XTENSA_xt_interrupt_HEADER */ diff --git a/components/esp32/include/xtensa/tie/xt_ioports.h b/components/esp32/include/xtensa/tie/xt_ioports.h new file mode 100644 index 0000000000..0253bea4cf --- /dev/null +++ b/components/esp32/include/xtensa/tie/xt_ioports.h @@ -0,0 +1,66 @@ +/* Definitions for the xt_ioports TIE package */ + +/* + * Customer ID=11657; Build=0x5fe96; Copyright (c) 2004-2010 by Tensilica Inc. ALL RIGHTS RESERVED. + * These coded instructions, statements, and computer programs are the + * copyrighted works and confidential proprietary information of Tensilica Inc. + * They may not be modified, copied, reproduced, distributed, or disclosed to + * third parties in any manner, medium, or form, in whole or in part, without + * the prior written consent of Tensilica Inc. + */ + +/* Do not modify. This is automatically generated.*/ + +#ifndef _XTENSA_xt_ioports_HEADER +#define _XTENSA_xt_ioports_HEADER + +#ifdef __XTENSA__ +#ifdef __XCC__ + +#include + +/* + * The following prototypes describe intrinsic functions + * corresponding to TIE instructions. Some TIE instructions + * may produce multiple results (designated as "out" operands + * in the iclass section) or may have operands used as both + * inputs and outputs (designated as "inout"). However, the C + * and C++ languages do not provide syntax that can express + * the in/out/inout constraints of TIE intrinsics. + * Nevertheless, the compiler understands these constraints + * and will check that the intrinsic functions are used + * correctly. To improve the readability of these prototypes, + * the "out" and "inout" parameters are marked accordingly + * with comments. + */ + +extern unsigned _TIE_xt_ioports_READ_IMPWIRE(void); +extern void _TIE_xt_ioports_SETB_EXPSTATE(immediate bitindex); +extern void _TIE_xt_ioports_CLRB_EXPSTATE(immediate bitindex); +extern void _TIE_xt_ioports_WRMSK_EXPSTATE(unsigned art, unsigned ars); +extern unsigned _TIE_xt_ioports_RUR_EXPSTATE(void); +extern void _TIE_xt_ioports_WUR_EXPSTATE(unsigned v); +#define READ_IMPWIRE _TIE_xt_ioports_READ_IMPWIRE +#define SETB_EXPSTATE _TIE_xt_ioports_SETB_EXPSTATE +#define CLRB_EXPSTATE _TIE_xt_ioports_CLRB_EXPSTATE +#define WRMSK_EXPSTATE _TIE_xt_ioports_WRMSK_EXPSTATE +#define RUR_EXPSTATE _TIE_xt_ioports_RUR_EXPSTATE +#define REXPSTATE _TIE_xt_ioports_RUR_EXPSTATE +#define RUR230 _TIE_xt_ioports_RUR_EXPSTATE +#define WUR_EXPSTATE _TIE_xt_ioports_WUR_EXPSTATE +#define WEXPSTATE _TIE_xt_ioports_WUR_EXPSTATE +#define WUR230 _TIE_xt_ioports_WUR_EXPSTATE + +#ifndef RUR +#define RUR(NUM) RUR##NUM() +#endif + +#ifndef WUR +#define WUR(VAL, NUM) WUR##NUM(VAL) +#endif + +#endif /* __XCC__ */ + +#endif /* __XTENSA__ */ + +#endif /* !_XTENSA_xt_ioports_HEADER */ diff --git a/components/esp32/include/xtensa/tie/xt_misc.h b/components/esp32/include/xtensa/tie/xt_misc.h new file mode 100644 index 0000000000..a0b36f4e5d --- /dev/null +++ b/components/esp32/include/xtensa/tie/xt_misc.h @@ -0,0 +1,58 @@ +/* Definitions for the xt_misc TIE package */ + +/* + * Customer ID=11657; Build=0x5fe96; Copyright (c) 2004-2010 by Tensilica Inc. ALL RIGHTS RESERVED. + * These coded instructions, statements, and computer programs are the + * copyrighted works and confidential proprietary information of Tensilica Inc. + * They may not be modified, copied, reproduced, distributed, or disclosed to + * third parties in any manner, medium, or form, in whole or in part, without + * the prior written consent of Tensilica Inc. + */ + +/* Do not modify. This is automatically generated.*/ + +#ifndef _XTENSA_xt_misc_HEADER +#define _XTENSA_xt_misc_HEADER + +#ifdef __XTENSA__ +#ifdef __XCC__ + +#include + +/* + * The following prototypes describe intrinsic functions + * corresponding to TIE instructions. Some TIE instructions + * may produce multiple results (designated as "out" operands + * in the iclass section) or may have operands used as both + * inputs and outputs (designated as "inout"). However, the C + * and C++ languages do not provide syntax that can express + * the in/out/inout constraints of TIE intrinsics. + * Nevertheless, the compiler understands these constraints + * and will check that the intrinsic functions are used + * correctly. To improve the readability of these prototypes, + * the "out" and "inout" parameters are marked accordingly + * with comments. + */ + +extern int _TIE_xt_misc_CLAMPS(int s, immediate i); +extern int _TIE_xt_misc_MIN(int s, int t); +extern int _TIE_xt_misc_MAX(int s, int t); +extern unsigned _TIE_xt_misc_MINU(unsigned s, unsigned t); +extern unsigned _TIE_xt_misc_MAXU(unsigned s, unsigned t); +extern int _TIE_xt_misc_NSA(int s); +extern unsigned _TIE_xt_misc_NSAU(unsigned s); +extern int _TIE_xt_misc_SEXT(int s, immediate i); +#define XT_CLAMPS _TIE_xt_misc_CLAMPS +#define XT_MIN _TIE_xt_misc_MIN +#define XT_MAX _TIE_xt_misc_MAX +#define XT_MINU _TIE_xt_misc_MINU +#define XT_MAXU _TIE_xt_misc_MAXU +#define XT_NSA _TIE_xt_misc_NSA +#define XT_NSAU _TIE_xt_misc_NSAU +#define XT_SEXT _TIE_xt_misc_SEXT + +#endif /* __XCC__ */ + +#endif /* __XTENSA__ */ + +#endif /* !_XTENSA_xt_misc_HEADER */ diff --git a/components/esp32/include/xtensa/tie/xt_mmu.h b/components/esp32/include/xtensa/tie/xt_mmu.h new file mode 100644 index 0000000000..ce786c0fea --- /dev/null +++ b/components/esp32/include/xtensa/tie/xt_mmu.h @@ -0,0 +1,62 @@ +/* Definitions for the xt_mmu TIE package */ + +/* + * Customer ID=11657; Build=0x5fe96; Copyright (c) 2004-2010 by Tensilica Inc. ALL RIGHTS RESERVED. + * These coded instructions, statements, and computer programs are the + * copyrighted works and confidential proprietary information of Tensilica Inc. + * They may not be modified, copied, reproduced, distributed, or disclosed to + * third parties in any manner, medium, or form, in whole or in part, without + * the prior written consent of Tensilica Inc. + */ + +/* Do not modify. This is automatically generated.*/ + +#ifndef _XTENSA_xt_mmu_HEADER +#define _XTENSA_xt_mmu_HEADER + +#ifdef __XTENSA__ +#ifdef __XCC__ + +#include + +/* + * The following prototypes describe intrinsic functions + * corresponding to TIE instructions. Some TIE instructions + * may produce multiple results (designated as "out" operands + * in the iclass section) or may have operands used as both + * inputs and outputs (designated as "inout"). However, the C + * and C++ languages do not provide syntax that can express + * the in/out/inout constraints of TIE intrinsics. + * Nevertheless, the compiler understands these constraints + * and will check that the intrinsic functions are used + * correctly. To improve the readability of these prototypes, + * the "out" and "inout" parameters are marked accordingly + * with comments. + */ + +extern void _TIE_xt_mmu_IDTLB(unsigned ars); +extern unsigned _TIE_xt_mmu_RDTLB1(unsigned ars); +extern unsigned _TIE_xt_mmu_RDTLB0(unsigned ars); +extern unsigned _TIE_xt_mmu_PDTLB(unsigned ars); +extern void _TIE_xt_mmu_WDTLB(unsigned art, unsigned ars); +extern void _TIE_xt_mmu_IITLB(unsigned ars); +extern unsigned _TIE_xt_mmu_RITLB1(unsigned ars); +extern unsigned _TIE_xt_mmu_RITLB0(unsigned ars); +extern unsigned _TIE_xt_mmu_PITLB(unsigned ars); +extern void _TIE_xt_mmu_WITLB(unsigned art, unsigned ars); +#define XT_IDTLB _TIE_xt_mmu_IDTLB +#define XT_RDTLB1 _TIE_xt_mmu_RDTLB1 +#define XT_RDTLB0 _TIE_xt_mmu_RDTLB0 +#define XT_PDTLB _TIE_xt_mmu_PDTLB +#define XT_WDTLB _TIE_xt_mmu_WDTLB +#define XT_IITLB _TIE_xt_mmu_IITLB +#define XT_RITLB1 _TIE_xt_mmu_RITLB1 +#define XT_RITLB0 _TIE_xt_mmu_RITLB0 +#define XT_PITLB _TIE_xt_mmu_PITLB +#define XT_WITLB _TIE_xt_mmu_WITLB + +#endif /* __XCC__ */ + +#endif /* __XTENSA__ */ + +#endif /* !_XTENSA_xt_mmu_HEADER */ diff --git a/components/esp32/include/xtensa/tie/xt_mul.h b/components/esp32/include/xtensa/tie/xt_mul.h new file mode 100644 index 0000000000..e20862069d --- /dev/null +++ b/components/esp32/include/xtensa/tie/xt_mul.h @@ -0,0 +1,52 @@ +/* Definitions for the xt_mul TIE package */ + +/* + * Customer ID=11657; Build=0x5fe96; Copyright (c) 2004-2010 by Tensilica Inc. ALL RIGHTS RESERVED. + * These coded instructions, statements, and computer programs are the + * copyrighted works and confidential proprietary information of Tensilica Inc. + * They may not be modified, copied, reproduced, distributed, or disclosed to + * third parties in any manner, medium, or form, in whole or in part, without + * the prior written consent of Tensilica Inc. + */ + +/* Do not modify. This is automatically generated.*/ + +#ifndef _XTENSA_xt_mul_HEADER +#define _XTENSA_xt_mul_HEADER + +#ifdef __XTENSA__ +#ifdef __XCC__ + +#include + +/* + * The following prototypes describe intrinsic functions + * corresponding to TIE instructions. Some TIE instructions + * may produce multiple results (designated as "out" operands + * in the iclass section) or may have operands used as both + * inputs and outputs (designated as "inout"). However, the C + * and C++ languages do not provide syntax that can express + * the in/out/inout constraints of TIE intrinsics. + * Nevertheless, the compiler understands these constraints + * and will check that the intrinsic functions are used + * correctly. To improve the readability of these prototypes, + * the "out" and "inout" parameters are marked accordingly + * with comments. + */ + +extern int _TIE_xt_mul_MUL16S(short s, short t); +extern unsigned _TIE_xt_mul_MUL16U(unsigned short s, unsigned short t); +extern int _TIE_xt_mul_MULL(int s, int t); +extern unsigned _TIE_xt_mul_MULUH(unsigned s, unsigned t); +extern int _TIE_xt_mul_MULSH(int s, int t); +#define XT_MUL16S _TIE_xt_mul_MUL16S +#define XT_MUL16U _TIE_xt_mul_MUL16U +#define XT_MULL _TIE_xt_mul_MULL +#define XT_MULUH _TIE_xt_mul_MULUH +#define XT_MULSH _TIE_xt_mul_MULSH + +#endif /* __XCC__ */ + +#endif /* __XTENSA__ */ + +#endif /* !_XTENSA_xt_mul_HEADER */ diff --git a/components/esp32/include/xtensa/tie/xt_regwin.h b/components/esp32/include/xtensa/tie/xt_regwin.h new file mode 100644 index 0000000000..7bce471a03 --- /dev/null +++ b/components/esp32/include/xtensa/tie/xt_regwin.h @@ -0,0 +1,64 @@ +/* Definitions for the xt_regwin TIE package */ + +/* + * Customer ID=11657; Build=0x5fe96; Copyright (c) 2004-2010 by Tensilica Inc. ALL RIGHTS RESERVED. + * These coded instructions, statements, and computer programs are the + * copyrighted works and confidential proprietary information of Tensilica Inc. + * They may not be modified, copied, reproduced, distributed, or disclosed to + * third parties in any manner, medium, or form, in whole or in part, without + * the prior written consent of Tensilica Inc. + */ + +/* Do not modify. This is automatically generated.*/ + +#ifndef _XTENSA_xt_regwin_HEADER +#define _XTENSA_xt_regwin_HEADER + +#ifdef __XTENSA__ +#ifdef __XCC__ + +#include + +/* + * The following prototypes describe intrinsic functions + * corresponding to TIE instructions. Some TIE instructions + * may produce multiple results (designated as "out" operands + * in the iclass section) or may have operands used as both + * inputs and outputs (designated as "inout"). However, the C + * and C++ languages do not provide syntax that can express + * the in/out/inout constraints of TIE intrinsics. + * Nevertheless, the compiler understands these constraints + * and will check that the intrinsic functions are used + * correctly. To improve the readability of these prototypes, + * the "out" and "inout" parameters are marked accordingly + * with comments. + */ + +extern void _TIE_xt_regwin_ENTRY(unsigned ars /*inout*/, immediate uimm12x8); +extern void _TIE_xt_regwin_ROTW(immediate simm4); +extern int _TIE_xt_regwin_MOVSP(int s); +extern int _TIE_xt_regwin_L32E(const int * s, immediate o); +extern void _TIE_xt_regwin_S32E(int t, int * s, immediate o); +extern unsigned _TIE_xt_regwin_RSR_WINDOWBASE(void); +extern void _TIE_xt_regwin_WSR_WINDOWBASE(unsigned t); +extern void _TIE_xt_regwin_XSR_WINDOWBASE(unsigned t /*inout*/); +extern unsigned _TIE_xt_regwin_RSR_WINDOWSTART(void); +extern void _TIE_xt_regwin_WSR_WINDOWSTART(unsigned t); +extern void _TIE_xt_regwin_XSR_WINDOWSTART(unsigned t /*inout*/); +#define XT_ENTRY _TIE_xt_regwin_ENTRY +#define XT_ROTW _TIE_xt_regwin_ROTW +#define XT_MOVSP _TIE_xt_regwin_MOVSP +#define XT_L32E _TIE_xt_regwin_L32E +#define XT_S32E _TIE_xt_regwin_S32E +#define XT_RSR_WINDOWBASE _TIE_xt_regwin_RSR_WINDOWBASE +#define XT_WSR_WINDOWBASE _TIE_xt_regwin_WSR_WINDOWBASE +#define XT_XSR_WINDOWBASE _TIE_xt_regwin_XSR_WINDOWBASE +#define XT_RSR_WINDOWSTART _TIE_xt_regwin_RSR_WINDOWSTART +#define XT_WSR_WINDOWSTART _TIE_xt_regwin_WSR_WINDOWSTART +#define XT_XSR_WINDOWSTART _TIE_xt_regwin_XSR_WINDOWSTART + +#endif /* __XCC__ */ + +#endif /* __XTENSA__ */ + +#endif /* !_XTENSA_xt_regwin_HEADER */ diff --git a/components/esp32/include/xtensa/tie/xt_scmpr.h b/components/esp32/include/xtensa/tie/xt_scmpr.h new file mode 100644 index 0000000000..337c7762eb --- /dev/null +++ b/components/esp32/include/xtensa/tie/xt_scmpr.h @@ -0,0 +1,22 @@ + +/* + * Customer ID=11657; Build=0x5fe96; Copyright (c) 2004-2010 by Tensilica Inc. ALL RIGHTS RESERVED. + * These coded instructions, statements, and computer programs are the + * copyrighted works and confidential proprietary information of Tensilica Inc. + * They may not be modified, copied, reproduced, distributed, or disclosed to + * third parties in any manner, medium, or form, in whole or in part, without + * the prior written consent of Tensilica Inc. + */ + +/* Do not modify. This is automatically generated.*/ + +#ifndef _XTENSA_xt_scmpr_h_HEADER +#define _XTENSA_xt_scmpr_h_HEADER + + +/* Header includes start */ + + +/* Header includes end */ + +#endif /* !_XTENSA_xt_scmpr_h_HEADER */ diff --git a/components/esp32/include/xtensa/tie/xt_sync.h b/components/esp32/include/xtensa/tie/xt_sync.h new file mode 100644 index 0000000000..9323dfe4b8 --- /dev/null +++ b/components/esp32/include/xtensa/tie/xt_sync.h @@ -0,0 +1,60 @@ +/* Definitions for the xt_sync TIE package */ + +/* + * Customer ID=11657; Build=0x5fe96; Copyright (c) 2004-2010 by Tensilica Inc. ALL RIGHTS RESERVED. + * These coded instructions, statements, and computer programs are the + * copyrighted works and confidential proprietary information of Tensilica Inc. + * They may not be modified, copied, reproduced, distributed, or disclosed to + * third parties in any manner, medium, or form, in whole or in part, without + * the prior written consent of Tensilica Inc. + */ + +/* Do not modify. This is automatically generated.*/ + +#ifndef _XTENSA_xt_sync_HEADER +#define _XTENSA_xt_sync_HEADER + +#ifdef __XTENSA__ +#ifdef __XCC__ + +#include + +/* + * The following prototypes describe intrinsic functions + * corresponding to TIE instructions. Some TIE instructions + * may produce multiple results (designated as "out" operands + * in the iclass section) or may have operands used as both + * inputs and outputs (designated as "inout"). However, the C + * and C++ languages do not provide syntax that can express + * the in/out/inout constraints of TIE intrinsics. + * Nevertheless, the compiler understands these constraints + * and will check that the intrinsic functions are used + * correctly. To improve the readability of these prototypes, + * the "out" and "inout" parameters are marked accordingly + * with comments. + */ + +extern unsigned _TIE_xt_sync_RSR_SCOMPARE1(void); +extern void _TIE_xt_sync_WSR_SCOMPARE1(unsigned art); +extern void _TIE_xt_sync_XSR_SCOMPARE1(unsigned art /*inout*/); +extern unsigned _TIE_xt_sync_RSR_ATOMCTL(void); +extern void _TIE_xt_sync_WSR_ATOMCTL(unsigned art); +extern void _TIE_xt_sync_XSR_ATOMCTL(unsigned art /*inout*/); +extern unsigned _TIE_xt_sync_L32AI(const unsigned * p, immediate o); +extern void _TIE_xt_sync_S32RI(unsigned c, unsigned * p, immediate o); +extern void _TIE_xt_sync_S32C1I(unsigned c /*inout*/, const unsigned * p, immediate o); +#define XT_RSR_SCOMPARE1 _TIE_xt_sync_RSR_SCOMPARE1 +#define XT_WSR_SCOMPARE1 _TIE_xt_sync_WSR_SCOMPARE1 +#define XT_XSR_SCOMPARE1 _TIE_xt_sync_XSR_SCOMPARE1 +#define XT_RSR_ATOMCTL _TIE_xt_sync_RSR_ATOMCTL +#define XT_WSR_ATOMCTL _TIE_xt_sync_WSR_ATOMCTL +#define XT_XSR_ATOMCTL _TIE_xt_sync_XSR_ATOMCTL +#define XT_L32AI _TIE_xt_sync_L32AI +#define XT_S32RI _TIE_xt_sync_S32RI +#define XT_S32C1I _TIE_xt_sync_S32C1I + +#endif /* __XCC__ */ + +#endif /* __XTENSA__ */ + +#endif /* !_XTENSA_xt_sync_HEADER */ diff --git a/components/esp32/include/xtensa/tie/xt_timer.h b/components/esp32/include/xtensa/tie/xt_timer.h new file mode 100644 index 0000000000..64db45c1a4 --- /dev/null +++ b/components/esp32/include/xtensa/tie/xt_timer.h @@ -0,0 +1,66 @@ +/* Definitions for the xt_timer TIE package */ + +/* + * Customer ID=11657; Build=0x5fe96; Copyright (c) 2004-2010 by Tensilica Inc. ALL RIGHTS RESERVED. + * These coded instructions, statements, and computer programs are the + * copyrighted works and confidential proprietary information of Tensilica Inc. + * They may not be modified, copied, reproduced, distributed, or disclosed to + * third parties in any manner, medium, or form, in whole or in part, without + * the prior written consent of Tensilica Inc. + */ + +/* Do not modify. This is automatically generated.*/ + +#ifndef _XTENSA_xt_timer_HEADER +#define _XTENSA_xt_timer_HEADER + +#ifdef __XTENSA__ +#ifdef __XCC__ + +#include + +/* + * The following prototypes describe intrinsic functions + * corresponding to TIE instructions. Some TIE instructions + * may produce multiple results (designated as "out" operands + * in the iclass section) or may have operands used as both + * inputs and outputs (designated as "inout"). However, the C + * and C++ languages do not provide syntax that can express + * the in/out/inout constraints of TIE intrinsics. + * Nevertheless, the compiler understands these constraints + * and will check that the intrinsic functions are used + * correctly. To improve the readability of these prototypes, + * the "out" and "inout" parameters are marked accordingly + * with comments. + */ + +extern unsigned _TIE_xt_timer_RSR_CCOUNT(void); +extern void _TIE_xt_timer_WSR_CCOUNT(unsigned art); +extern void _TIE_xt_timer_XSR_CCOUNT(unsigned art /*inout*/); +extern unsigned _TIE_xt_timer_RSR_CCOMPARE0(void); +extern void _TIE_xt_timer_WSR_CCOMPARE0(unsigned art); +extern void _TIE_xt_timer_XSR_CCOMPARE0(unsigned art /*inout*/); +extern unsigned _TIE_xt_timer_RSR_CCOMPARE1(void); +extern void _TIE_xt_timer_WSR_CCOMPARE1(unsigned art); +extern void _TIE_xt_timer_XSR_CCOMPARE1(unsigned art /*inout*/); +extern unsigned _TIE_xt_timer_RSR_CCOMPARE2(void); +extern void _TIE_xt_timer_WSR_CCOMPARE2(unsigned art); +extern void _TIE_xt_timer_XSR_CCOMPARE2(unsigned art /*inout*/); +#define XT_RSR_CCOUNT _TIE_xt_timer_RSR_CCOUNT +#define XT_WSR_CCOUNT _TIE_xt_timer_WSR_CCOUNT +#define XT_XSR_CCOUNT _TIE_xt_timer_XSR_CCOUNT +#define XT_RSR_CCOMPARE0 _TIE_xt_timer_RSR_CCOMPARE0 +#define XT_WSR_CCOMPARE0 _TIE_xt_timer_WSR_CCOMPARE0 +#define XT_XSR_CCOMPARE0 _TIE_xt_timer_XSR_CCOMPARE0 +#define XT_RSR_CCOMPARE1 _TIE_xt_timer_RSR_CCOMPARE1 +#define XT_WSR_CCOMPARE1 _TIE_xt_timer_WSR_CCOMPARE1 +#define XT_XSR_CCOMPARE1 _TIE_xt_timer_XSR_CCOMPARE1 +#define XT_RSR_CCOMPARE2 _TIE_xt_timer_RSR_CCOMPARE2 +#define XT_WSR_CCOMPARE2 _TIE_xt_timer_WSR_CCOMPARE2 +#define XT_XSR_CCOMPARE2 _TIE_xt_timer_XSR_CCOMPARE2 + +#endif /* __XCC__ */ + +#endif /* __XTENSA__ */ + +#endif /* !_XTENSA_xt_timer_HEADER */ diff --git a/components/esp32/include/xtensa/tie/xt_trace.h b/components/esp32/include/xtensa/tie/xt_trace.h new file mode 100644 index 0000000000..8d8d07fa48 --- /dev/null +++ b/components/esp32/include/xtensa/tie/xt_trace.h @@ -0,0 +1,44 @@ +/* Definitions for the xt_trace TIE package */ + +/* + * Customer ID=11657; Build=0x5fe96; Copyright (c) 2004-2010 by Tensilica Inc. ALL RIGHTS RESERVED. + * These coded instructions, statements, and computer programs are the + * copyrighted works and confidential proprietary information of Tensilica Inc. + * They may not be modified, copied, reproduced, distributed, or disclosed to + * third parties in any manner, medium, or form, in whole or in part, without + * the prior written consent of Tensilica Inc. + */ + +/* Do not modify. This is automatically generated.*/ + +#ifndef _XTENSA_xt_trace_HEADER +#define _XTENSA_xt_trace_HEADER + +#ifdef __XTENSA__ +#ifdef __XCC__ + +#include + +/* + * The following prototypes describe intrinsic functions + * corresponding to TIE instructions. Some TIE instructions + * may produce multiple results (designated as "out" operands + * in the iclass section) or may have operands used as both + * inputs and outputs (designated as "inout"). However, the C + * and C++ languages do not provide syntax that can express + * the in/out/inout constraints of TIE intrinsics. + * Nevertheless, the compiler understands these constraints + * and will check that the intrinsic functions are used + * correctly. To improve the readability of these prototypes, + * the "out" and "inout" parameters are marked accordingly + * with comments. + */ + +extern void _TIE_xt_trace_WSR_MMID(unsigned art); +#define XT_WSR_MMID _TIE_xt_trace_WSR_MMID + +#endif /* __XCC__ */ + +#endif /* __XTENSA__ */ + +#endif /* !_XTENSA_xt_trace_HEADER */ diff --git a/components/esp32/include/xtensa/trax-api.h b/components/esp32/include/xtensa/trax-api.h new file mode 100755 index 0000000000..aa1584359b --- /dev/null +++ b/components/esp32/include/xtensa/trax-api.h @@ -0,0 +1,93 @@ +/* Misc TRAX API function definitions. + + Copyright (c) 2007-2012 Tensilica Inc. + + Permission is hereby granted, free of charge, to any person obtaining + a copy of this software and associated documentation files (the + "Software"), to deal in the Software without restriction, including + without limitation the rights to use, copy, modify, merge, publish, + distribute, sublicense, and/or sell copies of the Software, and to + permit persons to whom the Software is furnished to do so, subject to + the following conditions: + + The above copyright notice and this permission notice shall be included + in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY + CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ + +#ifndef _TRAX_API_H_ +#define _TRAX_API_H_ + +#include +#include +#include "tpack.h" +#include "traxreg.h" + +#include "xdm-regs.h" + +/* Flags for trax_stop(): */ +#define TRAX_STOP_HALT 0x0001 /* halt immediately, don't wait for post-stop-trigger capture */ +#define TRAX_STOP_QUIET 0x0002 /* don't display informative messages */ + + +/* + * Describes a TRAX channel (based on tpack). + */ +typedef struct { + tpack_channel chan; /* channel structure header */ + /* Per TRAX unit information: */ + int trax_version; /* TRAX_ID_VER(id), one of TRAX_VER_xxx macros */ + unsigned long trax_tram_size; /* size of trace RAM in bytes */ + int trax_erratum10; /* set if TRAX 1.0 erratum workarounds needed */ + int trax_erratum20; /* set if TRAX 2.0 erratum workaround needed (PR 22161)*/ + int trax_erratum20_size; + int trax_has_busy; /* has trace-busy feature */ + int trax_has_atb; /* has ATB feature */ + /*FIXME: add various features: coresight regs (don't call it that), APB, ATB, TRAM, ... */ +} trax_channel; + + +/* Prototypes: */ + +/* TRAX Protocol API: */ +extern int trax_read_register(tpack_channel *tchan, int regno, unsigned *value); +extern int trax_write_register(tpack_channel *tchan, int regno, unsigned value); +extern int trax_read_memory(tpack_channel *tchan, int address, int size, unsigned char *pdata); +extern int trax_fill_memory(tpack_channel *tchan, int address, int size, tpack_u32 pattern); +extern int trax_enumerate_devices(tpack_channel *tchan, int * buf, int * size); + +/* TRAX Network API: */ +extern unsigned long trax_ram_size(tpack_channel *traxchan); +extern unsigned long trax_ram_size_addr(tpack_channel *traxchan); +extern int trax_create_tracefile(tpack_channel *traxchan, int size, unsigned char * data, + char *filename, int hflags, const char *toolver); +extern int trax_memaccess_safe(tpack_channel *traxchan, const char *what); +extern int trax_start(tpack_channel *traxchan, int flags); +extern int trax_stop(tpack_channel *traxchan, int flags); +extern int trax_halt(tpack_channel *traxchan, int flags); +extern int trax_save(tpack_channel *traxchan, char *filename, int flags, const char *toolver, int erratum); + +/* TRAX Misc API (no network dependencies): */ +int trax_fixed_hw(unsigned * regs); +extern int trax_display_id(unsigned id, const char *prefix); +extern int trax_display_summary(unsigned id, + unsigned status, + unsigned control, + unsigned address, + unsigned delay, + unsigned trigger, + unsigned match, + unsigned startaddr, + unsigned endaddr, + const char *prefix); + +/* Other: */ + +#endif /* _TRAX_API_H_ */ + diff --git a/components/esp32/include/xtensa/trax-core-config.h b/components/esp32/include/xtensa/trax-core-config.h new file mode 100755 index 0000000000..42a03334aa --- /dev/null +++ b/components/esp32/include/xtensa/trax-core-config.h @@ -0,0 +1,144 @@ +/* Definitions for Xtensa processor config info needed for TRAX. + + Copyright (c) 2005-2011 Tensilica Inc. + + Permission is hereby granted, free of charge, to any person obtaining + a copy of this software and associated documentation files (the + "Software"), to deal in the Software without restriction, including + without limitation the rights to use, copy, modify, merge, publish, + distribute, sublicense, and/or sell copies of the Software, and to + permit persons to whom the Software is furnished to do so, subject to + the following conditions: + + The above copyright notice and this permission notice shall be included + in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY + CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ + +#ifndef TRAX_CORE_CONFIG_H +#define TRAX_CORE_CONFIG_H + +#include "xtensa-params.h" + +/* + * Vector Enumerations. + */ + +/* These must match the LX2.0 and later traceport spec: */ +#define VEC_NO_VECTOR 0 +#define VEC_FIRST VEC_RESET /* first valid vector */ +#define VEC_RESET 1 +#define VEC_DEBUG 2 +#define VEC_NMI 3 +#define VEC_USER 4 +#define VEC_KERNEL 5 +#define VEC_DOUBLE 6 +#define VEC_MEMERR 7 +#define VEC_RESERVED8 8 +#define VEC_RESERVED9 9 +#define VEC_WINO4 10 +#define VEC_WINU4 11 +#define VEC_WINO8 12 +#define VEC_WINU8 13 +#define VEC_WINO12 14 +#define VEC_WINU12 15 +#define VEC_INTLEVEL2 16 +#define VEC_INTLEVEL3 17 +#define VEC_INTLEVEL4 18 +#define VEC_INTLEVEL5 19 +#define VEC_INTLEVEL6 20 +/* These are internal, i.e. don't appear like this on traceport: */ +#define VEC_DEBUG_OCD 21 +#define VEC_UNKNOWN 22 +/* Enumerations 23 through 31 are also reserved, but putting */ +/* placeholders here seems wasteful and unnecessary. */ +#define VEC_COUNT 23 + +/* Other branch (change-of-PC-flow) type encodings; + * if PC changes due to an exception or interrupt vector, + * one of the VEC_* values above is used, otherwise + * (or if it's unknown whether it's due to an exception/interrupt) + * one of the following is used: */ + +#define BRANCH_IS_VEC(n) ((n) < VEC_COUNT) /* is known to be except/interrupt? */ +#define BRANCH_OR_VEC 24 /* unknown type of branch (branch/exception/interrupt/etc) */ +#define BRANCH_UNKNOWN 25 /* unknown type of branch (anything but except/interrupt) */ +#define BRANCH_UNKNOWN_ERR 26 /* like BRANCH_UNKNOWN with known error (non-branch instr) */ +#define BRANCH_LOOPBACK 28 /* zero-overhead loopback (from LEND to LBEG) */ +#define BRANCH_CONDTAKEN 29 /* conditional branch taken (or LOOP{NEZ,GTZ} loop skip) */ +#define BRANCH_JUMP 30 /* jump (unconditional branch, i.e. J or JX) */ +#define BRANCH_IS_CALL(n) (((n) & ~3) == 32) /* is a function call? */ +#define BRANCH_CALL0 32 /* non-windowed function call (CALL0, CALLX0) */ +#define BRANCH_CALL4 33 /* windowed function call (CALL4, CALLX4) */ +#define BRANCH_CALL8 34 /* windowed function call (CALL8, CALLX8) */ +#define BRANCH_CALL12 35 /* windowed function call (CALL12, CALLX12) */ +#define BRANCH_IS_RETURN(n) ((n) >= 36) /* is any kind of return? */ +#define BRANCH_IS_CALLRETURN(n) (((n) & ~1) == 36) /* is a function return? */ +#define BRANCH_RET 36 /* non-windowed function return (RET or RET.N) */ +#define BRANCH_RETW 37 /* windowed function return (RETW or RETW.N) */ +#define BRANCH_IS_EIRETURN(n) ((n) >= 38) /* is an except/inter. return? */ +#define BRANCH_RFE 38 /* RFE or RFUE */ +#define BRANCH_RFDE 39 /* RFDE */ +#define BRANCH_RFWO 40 /* RFWO */ +#define BRANCH_RFWU 41 /* RFWU */ +#define BRANCH_RFI_2 42 /* RFI 2 */ +#define BRANCH_RFI_3 43 /* RFI 3 */ +#define BRANCH_RFI_4 44 /* RFI 4 */ +#define BRANCH_RFI_5 45 /* RFI 5 */ +#define BRANCH_RFI_6 46 /* RFI 6 */ +#define BRANCH_RFI_NMI 47 /* RFI NMILEVEL */ +#define BRANCH_RFI_DEBUG 48 /* RFI DEBUGLEVEL */ +#define BRANCH_RFME 49 /* RFME */ +#define BRANCH_COUNT 50 /* (number of defined BRANCH_xxx values) */ + + + +typedef struct { + unsigned vaddr; + unsigned vaddr2; /* for static vectors only (reloc vectors option) */ + int is_configured; +} trax_vector_t; + + +/* + * This structure describes those portion of a Tensilica processor's + * configuration that are useful for trace. + */ +typedef struct { + char ** isa_dlls; + char * core_name; /* (XPG core name, not necessarily same as XTENSA_CORE) */ + int big_endian; /* 0 = little-endian, 1 = big-endian */ + int has_loops; /* 1 = zero overhead loops configured */ + int has_autorefill; /* 1 = TLB autorefill (MMU) configured */ + unsigned max_instr_size; /* in bytes (eg. 3, 4, 8, ...) */ + unsigned int_level_max; /* number of interrupt levels configured (without NMI) */ + int debug_level; /* debug intlevel, 0 if debug not configured */ + int nmi_level; /* NMI intlevel, 0 if NMI not configured */ + unsigned targethw_min; /* min. targeted hardware version (XTENSA_HWVERSION_) */ + unsigned targethw_max; /* max. targeted hardware version (XTENSA_HWVERSION_) */ + int reloc_vectors; /* 0 = fixed vectors, 1 = relocatable vectors */ + int statvec_select; /* 0 = stat vec base 0, 1 = stat vec base 1 (SW default) */ + int vecbase_align; /* number of bits to align VECBASE (32 - bits in VECBASE) */ + unsigned statvec_base0; /* static vector base 0 */ + unsigned statvec_base1; /* static vector base 1 */ + unsigned vecbase_reset; /* reset value of VECBASE */ + trax_vector_t vectors[VEC_COUNT]; /* all vectors... */ +} trax_core_config_t; + + +/* Globals: */ +//extern const char * const trax_vector_short_names[/*VEC_COUNT*/]; // nobody uses this one +extern const char * const trax_vector_names[/*VEC_COUNT*/]; + +/* Prototypes: */ +extern int trax_read_params (trax_core_config_t *c, xtensa_params p); +extern int trax_vector_from_address(trax_core_config_t *config, unsigned long vaddr, unsigned long *vecbases); + +#endif /* TRAX_CORE_CONFIG_H */ + diff --git a/components/esp32/include/xtensa/trax-proto.h b/components/esp32/include/xtensa/trax-proto.h new file mode 100755 index 0000000000..41d5c9fd76 --- /dev/null +++ b/components/esp32/include/xtensa/trax-proto.h @@ -0,0 +1,91 @@ +/* This file contains functions that are hidden from the user. These are + * protocol specific functions used to read and write TRAX registers + * and the trace memory + */ + +/* + * Copyright (c) 2012-2013 Tensilica Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY + * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ +#ifndef _TRAX_PROTO_H +#define _TRAX_PROTO_H + +#ifdef __cplusplus +extern "C" { +#endif + +/* Function to read register + * + * regno : The register number to be read (not ERI addressed) + * data : Location where the read value is kept + * + * returns : 0 if successful, -1 if unsuccessful + */ +int trax_read_register_eri (int regno, unsigned *data); + +/* Function to write a value into a register + * + * regno : The register number to be written (not ERI addressed) + * value : The value to be written at that register location + * + * returns : 0 if successful, -1 if unsuccessful + */ +int trax_write_register_eri (int regno, unsigned value); + +/* Function to read memory + * + * address : Address of the TraceRAM memory, each location has a word + * len : Amount of memory in bytes, to be read + * data : buffer in which the read memory is stored + * final_address: Next address to be read in the following call to this + * function (trace save mechanism) + * + * returns : 0 if successful, -1 if unsuccessful + */ +int trax_read_memory_eri (unsigned address, int len, int *data, + unsigned *final_address); + +/* Function to write a value to the memory address + * + * address : Address of the TraceRAM memory + * value : The value to be written inside that location + * + * returns : 0 if successful, -1 if unsuccessful + */ +int trax_write_memory_eri (int address, unsigned value); + +/* Function to write to a subfield of the register. + * Called by set and show parameter functions. + * + * regno : Register number + * regmask : Mask in order to toggle appropriate bits + * value : Value to be written in the masked location + * + * returns : 0 if successful, -1 if unsuccessful + */ +int trax_write_register_field_eri (int regno, unsigned regmask, + unsigned value); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/components/esp32/include/xtensa/trax-util.h b/components/esp32/include/xtensa/trax-util.h new file mode 100755 index 0000000000..123ac366df --- /dev/null +++ b/components/esp32/include/xtensa/trax-util.h @@ -0,0 +1,63 @@ +/* This file contains utility functions that can be used for polling TRAX + * or executing higher level save functionality + * It assumes that print subroutines and file I/O routines are available + * on the system + */ + +/* + * Copyright (c) 2012-2013 Tensilica Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY + * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +#ifndef _TRAX_UTIL_H +#define _TRAX_UTIL_H + + +#ifdef __cplusplus +extern "C" { +#endif + +/* User can use this function if he wants to generate a tracefile output. + * Internally it calls trax_get_trace in a loop until it realizes that + * the entire trace has been read. + * + * context : pointer to structure which contains information about the + * current TRAX session + * filename : user specified output trace file name. If the file does not + * exist, it would create the new file, else would append to it + * + * returns : 0 if successful, -1 if unsuccessful + */ +int trax_save (trax_context *context, char *filename); + +/* Displays a brief machine readable status. + * + * context : pointer to structure which contains information about the + * current TRAX session + * returns : 0 if successful, -1 if unsuccessful + */ +int trax_poll (trax_context *context); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/components/esp32/include/xtensa/trax.h b/components/esp32/include/xtensa/trax.h new file mode 100755 index 0000000000..47049c51d2 --- /dev/null +++ b/components/esp32/include/xtensa/trax.h @@ -0,0 +1,409 @@ +/* Header file for TRAX control Library */ + +/* + * Copyright (c) 2012-2013 Tensilica Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY + * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +#ifndef _TRAX_H +#define _TRAX_H + +#ifdef __cplusplus +extern "C" { +#endif + +#define TRAX_STOP_HALT 0x0001 +#define TRAX_STOP_QUIET 0x0002 + +/* Flag values to indicate if the user wanted to reverse the pcstop + * parameters */ +#define TRAX_PCSTOP_REVERSE 0x0001 +#define TRAX_PCSTOP_NO_REVERSE 0x0000 + +/* Indicating whether postsize should be in terms of bytes, instructions + * or percentage of trace size captured */ +#define TRAX_POSTSIZE_BYTES 0x0000 +#define TRAX_POSTSIZE_INSTR 0x0001 +#define TRAX_POSTSIZE_PERCENT 0x0002 + +/* Size of the header inside the trace file */ +#define TRAX_HEADER_SIZE 256 + +/* Minimum size between start and end addresses */ +#define TRAX_MIN_TRACEMEM 64 + +/* For basic debugging */ +#define DEBUG 0 + +#include + +#define ffs(i) __builtin_ffs(i) + +/* Data structures */ + +/* Represents the context of the TRAX unit and the current TRAX session. + * To be used by set and show function calls to set and show appropriate + * parameters of appropriate TRAX unit. + */ + +typedef struct { + int trax_version; /* TRAX PC version information */ + unsigned long trax_tram_size; /* If trace RAM is present,size of it */ + int hflags; /* Flags that can be used to debug, + print info, etc. */ + int address_read_last; /* During saving of the trace, this + indicates the address from which + the current trace reading must + resume */ + unsigned long bytes_read; /* bytes read uptil now */ + unsigned long total_memlen; /* Total bytes to be read based on the + trace collected in the trace RAM */ + bool get_trace_started; /* indicates that the first chunk of + bytes (which include the header) has + been read */ +} trax_context; + + +/* -----------------------TRAX Initialization ------------------------------*/ + +/* Initializing the trax context. Reads registers and sets values for version, + * trace RAM size, total memory length, etc. Most of the other values are + * initialized to their default case. + * + * context : pointer to structure which contains information about the + * current TRAX session + * + * returns : 0 if successful, -1 if unsuccessful, -2 if ram_size if + * incorrect + */ +int trax_context_init_eri (trax_context *context); + +/* -----------------Starting/Stopping TRAX session -------------------------*/ + +/* Start tracing with current parameter setting. If tracing is already in + * progress, an error is reported. Otherwise, tracing starts and any unsaved + * contents of the TraceRAM is discarded + * + * context : pointer to structure which contains information about the + * current TRAX session + * returns : 0 if successful, 1 if trace is already active, + * -1 if unsuccessful + */ +int trax_start (trax_context *context); + +/* This command initiates a stop trigger or halts a trace session based of the + * value of the flag parameter passed. In case stop trigger is initiated, any + * selected post-stop-trigger capture proceeds normally. + * If trace capture was not in progress, or a stop was already triggered, the + * return value indicates appropriately. + * + * context : pointer to structure which contains information about the + * current TRAX session + * flags : To differentiate between stopping trace without any + * post-size-trigger capture (trax_halt) or with that. + * A zero value would stop the trace based on trigger and a + * value of one would halt it + * + * returns : 0 if successful, 1 if already stopped, -1 if unsuccessful + */ +int trax_stop_halt (trax_context *context, int flags); + +/* Resets the TRAX parameters to their default values which would internally + * involve resetting the TRAX registers. To invoke another trace session or + * reset the current tracing mechanism, this function needs to be called as + * it resets parameters of the context that deal with tracing information + * + * context : pointer to structure which contains information about the + * current TRAX session + * + * returns : 0 if successful, -1 if unsuccessful + */ +int trax_reset (trax_context *context); + +/* ---------------Set/Get several TRAX parameters --------------------------*/ + +/* Sets the start address and end address (word aligned) of the trace in the + * TraceRAM. Care must be taken to ensure that the difference between the + * start and the end addresses is atleast TRAX_MIN_TRACEMEM bytes. If not, + * the values are reset to default, which is 0 for startaddr and + * traceRAM_words -1 for endaddr + * + * context : pointer to structure which contains information about the + * current TRAX session + * startaddr : value to which the start address must be set. Can be + * any value between 0 - (traceRAM_words - 1) + * endaddr : value to which the end address must be set. Can be any value + * between 0 - (traceRAM_words - 1) + * + * returns : 0 if successful, -1 if unsuccessful, -2 if the difference + * between the start and end addresses is less than + * TRAX_MIN_TRACEMEM bytes or if they are passed incorrect + * values, -3 if memory shared option is not configured, in + * which case, start and end addresses are set to default + * values instead of those passed by the user + */ +int trax_set_ram_boundaries (trax_context *context, unsigned startaddr, + unsigned endaddr); + +/* Shows the start address and end address(word aligned) of the trace in the + * TraceRAM. If incorrect, the startaddress and the endaddress values are + * set to default, i.e. 0 for startaddr and traceRAM_words - 1 for endaddr + * + * context : pointer to structure which contains information about the + * current TRAX session + * startaddr : pointer to value which will contain the start address + * endaddr : pointer to value which will contain the end address + * + * returns : 0 if successful, -1 if unsuccessful + * + */ +int trax_get_ram_boundaries (trax_context *context, unsigned *startaddr, + unsigned *endaddr); + +/* Selects stop trigger via cross-trigger input + * + * context : pointer to structure which contains information about the + * current TRAX session + * value : 0 = off (reset value), 1 = on + * + * returns : 0 if successful, -1 if unsuccessful + */ +int trax_set_ctistop (trax_context *context, unsigned value); + +/* Shows if stop-trigger via cross-trigger input is off or on + * + * context : pointer to structure which contains information about the + * current TRAX session + * returns : 0 if off, 1 if on, -1 if unsuccessful + */ +int trax_get_ctistop (trax_context *context); + +/* Selects stop trigger via processor-trigger input + * + * context : pointer to structure which contains information about the + * current TRAX session + * value : 0 = off (reset value), 1 = on + * + * returns : 0 if successful, -1 if unsuccessful + */ +int trax_set_ptistop (trax_context *context, unsigned value); + +/* Shows if stop trigger visa processor-trigger input is off or on + * + * context : pointer to structure which contains information about the + * current TRAX session + * returns : 0 if off, 1 if on, -1 if unsuccessful + */ +int trax_get_ptistop (trax_context *context); + +/* Reports cross trigger output state + * + * context : pointer to structure which contains information about the + * current TRAX session + * returns : 0 if CTO bit is reset, 1 if CTO bit is set + */ +int trax_get_cto (trax_context *context); + +/* Reports processor trigger output state + * + * context : pointer to structure which contains information about the + * current TRAX session + * returns : 0 if PTO bit is reset, 1 if PTO bit is set + */ +int trax_get_pto (trax_context *context); + +/* Selects condition that asserts cross trigger output + * + * context : pointer to structure which contains information about the + * current TRAX session + * option : 0 = off(reset value)/1 = ontrig/2 = onhalt + * + * returns : 0 if successful, -1 if unsuccessful + */ +int trax_set_ctowhen (trax_context *context, int option); + +/* Shows condition that asserted cross trigger output. It can be + * any of: ontrig or onhalt or even off + * + * context : pointer to structure which contains information about the + * current TRAX session + * + * returns : 0 if off, 1 if ontrig, 2 if onhalt, -1 if unsuccessful + */ +int trax_get_ctowhen (trax_context *context); + +/* Selects condition that asserts processor trigger output + * + * context : pointer to structure which contains information about the + * current TRAX session + * option : 0 = off(reset value)/1 = ontrig/2 = onhalt + * + * returns : 0 if successful, -1 if unsuccessful + */ +int trax_set_ptowhen (trax_context *context, int option); + + +/* Shows condition that asserted processor trigger output. It can be + * any of: ontrig or onhalt or even off + * + * context : pointer to structure which contains information about the + * current TRAX session + * returns : 0 if off, 1 if ontrig, 2 if onhalt, -1 if unsuccessful + */ +int trax_get_ptowhen (trax_context *context); + +/* Selects the trace synchronization message period. + * If ATEN enabled, we cannot allow syncper to be off, set it to reset value. + * Also, if no trace RAM, and ATEN enabled, set syncper to be reset value + * i.e. 256. A value of 1 i.e. on indicates that internally the message + * frequency is set to an optimal value. This option should be preferred + * if the user is not sure what message frequency option to set for the + * trace session. + * + * context : pointer to structure which contains information about the + * current TRAX session + * option : 0 = off, 1 = on, -1 = auto, 8, 16, 32, 64, 128, + * 256 (reset value) + * + * returns : 0 if successful, -1 if unsuccessful, -2 if incorrect + * arguments + */ +int trax_set_syncper (trax_context *context, int option); + +/* Shows trace synchronization message period. Can be one of: + * off, on, auto, 8, 16, 32, 64, 128, 256 (reset value) + * + * context : pointer to structure which contains information about the + * current TRAX session + * returns : value of sync period, 0 if off, -1 if unsuccessful + */ +int trax_get_syncper (trax_context *context); + +/* Selects stop trigger via PC match. Specifies the address or + * address range to match against program counter. Trace stops when the + * processor executes an instruction matching the specified address + * or range. + * + * context : pointer to structure which contains information about the + * current TRAX session + * index : indicates the number of stop trigger (currently there is + * only one i.e. index = 0) + * startaddress : start range of the address at which the stop trigger + * should be activated + * enaddress : end range of the address at which the stop trigger should + * be activated + * flags : If non-zero, this inverts the range. i.e. trace stops + * when the processor executes an instruction that does not + * match the specified address or range + * + * returns : 0 if successful, -1 if unsuccessful, -2 if incorrect + * arguments (unaligned) + * + * Note : For the current version of TRAX library, the endaddress and + * startaddress can differ by at most 31 bytes and the total + * range i.e. (endaddress - startaddress + 1) has to be a power + * of two + */ +int trax_set_pcstop (trax_context *context, int index, unsigned long startaddress, + unsigned long endaddress, int flags); + +/* Shows the stop trigger via PC match + * + * context : pointer to structure which contains information about the + * current TRAX session + * index : container of information about the number of stop triggers + * startaddress : container of start range of stop trigger + * endaddress : container of end range of stop trigger + * flags : container of information whcih indicates whether the + * pc stop range is inverted or not. + * + * returns : 0 if successful, -1 if unsuccessful + */ +int trax_get_pcstop (trax_context *context, int *index, + unsigned long *startaddress, + unsigned long *endaddress, int *flags); + +/* This function is used to set the amount of trace to be captured past + * the stop trigger. + * + * context : pointer to structure which contains information about the + * current TRAX session + * count_unit : contains the count of units (instructions or bytes) to be + * captured post trigger. If 0, it implies that this is off + * unit : unit of measuring the count. 0 is bytes, 1 is instructions + * 2 is percentage of trace + * + * returns : 0 if successful, -1 if unsuccessful, -2 if incorrect + * arguments + * + */ +int trax_set_postsize (trax_context *context, int count_unit, int unit); + +/* This function shows the amount of TraceRAM in terms of the number of + * instructions or bytes, captured post the stop trigger + * + * context : pointer to structure which contains information about the + * current TRAX session + * count_unit : will contain the count of units(instructions or bytes) post + * trigger + * unit : will contain information about the events that are counted + * 0 implies that the traceRAM words consumed are counted and + * 1 implies that the target processor instructions executed and + * excpetions/interrupts taken are counted + * + * returns : 0 if postsize was got successfully, -1 if unsuccessful + */ +int trax_get_postsize (trax_context *context, int *count_unit, int *unit); + +/* -------------------------- TRAX save routines ---------------------------*/ + +/* This function should be called by the user to return a chunk of + * bytes in buf. It can be a lower layer function of save, or can be + * called by the user explicitly. If bytes_actually_read contains a 0 + * after a call to this function has been made, it implies that the entire + * trace has been read successfully. + * + * context : pointer to structure which contains information about + * the current TRAX session + * buf : Buffer that is allocated by the user, all the trace + * data read would be put in this buffer, which can then + * be used to generate a tracefile. + * The first TRAX_HEADER_SIZE of the buffer will always + * contain the header information. + * bytes_to_be_read : Indicates the bytes the user wants to read. The first + * invocation would need this parameter to be + * TRAX_HEADER_SIZE at least. + * + * returns : bytes actually read during the call to this function. + * 0 implies that all the bytes in the trace have been + * read, -1 if unsuccessful read/write of + * registers or memory, -2 if trace was active while + * this function was called, -3 if user enters + * bytes_to_be_read < TRAX_HEADER_SIZE in the first + * pass + */ +int trax_get_trace (trax_context *context, void *buf, + int bytes_to_be_read); +#ifdef __cplusplus +} +#endif + +#endif /* _TRAX_H */ diff --git a/components/esp32/include/xtensa/traxfile.h b/components/esp32/include/xtensa/traxfile.h new file mode 100755 index 0000000000..4afc926a50 --- /dev/null +++ b/components/esp32/include/xtensa/traxfile.h @@ -0,0 +1,62 @@ +/* TRAX file header definition. + + Copyright (c) 2007-2012 Tensilica Inc. + + Permission is hereby granted, free of charge, to any person obtaining + a copy of this software and associated documentation files (the + "Software"), to deal in the Software without restriction, including + without limitation the rights to use, copy, modify, merge, publish, + distribute, sublicense, and/or sell copies of the Software, and to + permit persons to whom the Software is furnished to do so, subject to + the following conditions: + + The above copyright notice and this permission notice shall be included + in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY + CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ + + +#define TRAX_FHEAD_MAGIC "TRAXdmp" +#define TRAX_FHEAD_VERSION 1 + +/* Header flags: */ +#define TRAX_FHEADF_OCD_ENABLED 0x00000001 /* set if OCD was enabled while capturing trace */ +#define TRAX_FHEADF_TESTDUMP 0x00000002 /* set if is a test file + (from 'memsave' instead of 'save') */ +#define TRAX_FHEADF_OCD_ENABLED_WHILE_EXIT 0x00000004 /* set if OCD was enabled while capturing trace and + we were exiting the OCD mode */ + +/* Header at the start of a TRAX dump file. */ +typedef struct { + char magic[8]; /* 00: "TRAXdmp\0" (TRAX_FHEAD_MAGIC) */ + char endianness; /* 08: 0=little-endian, 1=big-endian */ + char version; /* 09: TRAX_FHEAD_VERSION */ + char reserved0[2]; /* 0A: ... */ + unsigned filesize; /* 0C: size of the trace file, including this header */ + unsigned trace_ofs; /* 10: start of trace output, byte offset from start of header */ + unsigned trace_size; /* 14: size of trace output in bytes */ + unsigned dumptime; /* 18: date/time of capture save (secs since 1970-01-01), 0 if unknown */ + unsigned flags; /* 1C: misc flags (TRAX_FHEAD_F_xxx) */ + char username[16]; /* 20: user doing the capture/save (up to 15 chars) */ + char toolver[24]; /* 30: tool + version used for capture/save (up to 23 chars) */ + char reserved2[40]; /* 48: (reserved - could be hostname used for dump (up to 39 chars)) */ + unsigned configid[2]; /* 70: processor ConfigID values, 0 if unknown */ + unsigned ts_freq; /* 78: timestamp frequency, 0 if not specified */ + unsigned reserved3; /* 7C: (reserved) */ + unsigned id; /* 80: TRAX registers at time of save (0 if not read) */ + unsigned control; + unsigned status; + unsigned reserved4; /* Data register (should not be read) */ + unsigned address; + unsigned trigger; + unsigned match; + unsigned delay; + unsigned trax_regs[24]; /*100: (total size) -- dummy allocation (FIXME) */ +} trax_file_header; + diff --git a/components/esp32/include/xtensa/traxreg.h b/components/esp32/include/xtensa/traxreg.h new file mode 100755 index 0000000000..282ba1feef --- /dev/null +++ b/components/esp32/include/xtensa/traxreg.h @@ -0,0 +1,199 @@ +/* TRAX register definitions + + Copyright (c) 2006-2012 Tensilica Inc. + + Permission is hereby granted, free of charge, to any person obtaining + a copy of this software and associated documentation files (the + "Software"), to deal in the Software without restriction, including + without limitation the rights to use, copy, modify, merge, publish, + distribute, sublicense, and/or sell copies of the Software, and to + permit persons to whom the Software is furnished to do so, subject to + the following conditions: + + The above copyright notice and this permission notice shall be included + in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY + CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ + +#ifndef _TRAX_REGISTERS_H_ +#define _TRAX_REGISTERS_H_ + +#define SHOW 1 +#define HIDE 0 + +#define RO 0 +#define RW 1 + +/* TRAX Register Numbers (from possible range of 0..127) */ +#if 0 +#define TRAXREG_ID 0 +#define TRAXREG_CONTROL 1 +#define TRAXREG_STATUS 2 +#define TRAXREG_DATA 3 +#define TRAXREG_ADDRESS 4 +#define TRAXREG_TRIGGER 5 +#define TRAXREG_MATCH 6 +#define TRAXREG_DELAY 7 +#define TRAXREG_STARTADDR 8 +#define TRAXREG_ENDADDR 9 +/* Internal use only (unpublished): */ +#define TRAXREG_P4CHANGE 16 +#define TRAXREG_P4REV 17 +#define TRAXREG_P4DATE 18 +#define TRAXREG_P4TIME 19 +#define TRAXREG_PDSTATUS 20 +#define TRAXREG_PDDATA 21 +#define TRAXREG_STOP_PC 22 +#define TRAXREG_STOP_ICNT 23 +#define TRAXREG_MSG_STATUS 24 +#define TRAXREG_FSM_STATUS 25 +#define TRAXREG_IB_STATUS 26 +#define TRAXREG_MAX 27 +#define TRAXREG_ITCTRL 96 +#endif +/* The registers above match the NAR addresses. So, their values are used for NAR access */ + +/* TRAX Register Fields */ + +/* TRAX ID register fields: */ +#define TRAX_ID_PRODNO 0xf0000000 /* product number (0=TRAX) */ +#define TRAX_ID_PRODOPT 0x0f000000 /* product options */ +#define TRAX_ID_MIW64 0x08000000 /* opt: instruction width */ +#define TRAX_ID_AMTRAX 0x04000000 /* opt: collection of options, + internal (VER_2_0 or later)*/ +#define TRAX_ID_MAJVER(id) (((id) >> 20) & 0x0f) +#define TRAX_ID_MINVER(id) (((id) >> 17) & 0x07) +#define TRAX_ID_VER(id) ((TRAX_ID_MAJVER(id)<<4)|TRAX_ID_MINVER(id)) +#define TRAX_ID_STDCFG 0x00010000 /* standard config */ +#define TRAX_ID_CFGID 0x0000ffff /* TRAX configuration ID */ +#define TRAX_ID_MEMSHARED 0x00001000 /* Memshared option in TRAX */ +#define TRAX_ID_FROM_VER(ver) ((((ver) & 0xf0) << 16) | (((ver) & 0x7) << 17)) +/* Other TRAX ID register macros: */ +/* TRAX versions of interest (TRAX_ID_VER(), ie. MAJVER*16 + MINVER): */ +#define TRAX_VER_1_0 0x10 /* RA */ +#define TRAX_VER_1_1 0x11 /* RB thru RC-2010.1 */ +#define TRAX_VER_2_0 0x20 /* RC-2010.2, RD-2010.0, + RD-2011.1 */ +#define TRAX_VER_2_1 0x21 /* RC-2011.3 / RD-2011.2 and + later */ +#define TRAX_VER_3_0 0x30 /* RE-2012.0 */ +#define TRAX_VER_3_1 0x31 /* RE-2012.1 */ +#define TRAX_VER_HUAWEI_3 TRAX_VER_3_0 /* For Huawei, PRs: 25223, 25224 + , 24880 */ + + +/* TRAX version 1.0 requires a couple software workarounds: */ +#define TRAX_ID_1_0_ERRATUM(id) (TRAX_ID_VER(id) == TRAX_VER_1_0) +/* TRAX version 2.0 requires software workaround for PR 22161: */ +#define TRAX_ID_MEMSZ_ERRATUM(id) (TRAX_ID_VER(id) == TRAX_VER_2_0) + +/* TRAX Control register fields: */ +#define TRAX_CONTROL_TREN 0x00000001 +#define TRAX_CONTROL_TRSTP 0x00000002 +#define TRAX_CONTROL_PCMEN 0x00000004 +#define TRAX_CONTROL_PTIEN 0x00000010 +#define TRAX_CONTROL_CTIEN 0x00000020 +#define TRAX_CONTROL_TMEN 0x00000080 /* 2.0+ */ +#define TRAX_CONTROL_CNTU 0x00000200 +#define TRAX_CONTROL_BIEN 0x00000400 +#define TRAX_CONTROL_BOEN 0x00000800 +#define TRAX_CONTROL_TSEN 0x00000800 +#define TRAX_CONTROL_SMPER 0x00007000 +#define TRAX_CONTROL_SMPER_SHIFT 12 +#define TRAX_CONTROL_PTOWT 0x00010000 +#define TRAX_CONTROL_CTOWT 0x00020000 +#define TRAX_CONTROL_PTOWS 0x00100000 +#define TRAX_CONTROL_CTOWS 0x00200000 +#define TRAX_CONTROL_ATID 0x7F000000 /* 2.0+, amtrax */ +#define TRAX_CONTROL_ATID_SHIFT 24 +#define TRAX_CONTROL_ATEN 0x80000000 /* 2.0+, amtrax */ + +#define TRAX_CONTROL_PTOWS_ER 0x00020000 /* For 3.0 */ +#define TRAX_CONTROL_CTOWT_ER 0x00100000 /* For 3.0 */ + +#define TRAX_CONTROL_ITCTO 0x00400000 /* For 3.0 */ +#define TRAX_CONTROL_ITCTIA 0x00800000 /* For 3.0 */ +#define TRAX_CONTROL_ITATV 0x01000000 /* For 3.0 */ + + +/* TRAX Status register fields: */ +#define TRAX_STATUS_TRACT 0x00000001 +#define TRAX_STATUS_TRIG 0x00000002 +#define TRAX_STATUS_PCMTG 0x00000004 +#define TRAX_STATUS_BUSY 0x00000008 /* ER ??? */ +#define TRAX_STATUS_PTITG 0x00000010 +#define TRAX_STATUS_CTITG 0x00000020 +#define TRAX_STATUS_MEMSZ 0x00001F00 +#define TRAX_STATUS_MEMSZ_SHIFT 8 +#define TRAX_STATUS_PTO 0x00010000 +#define TRAX_STATUS_CTO 0x00020000 + +#define TRAX_STATUS_ITCTOA 0x00400000 /* For 3.0 */ +#define TRAX_STATUS_ITCTI 0x00800000 /* For 3.0 */ +#define TRAX_STATUS_ITATR 0x01000000 /* For 3.0 */ + + +/* TRAX Address register fields: */ +#define TRAX_ADDRESS_TWSAT 0x80000000 +#define TRAX_ADDRESS_TWSAT_SHIFT 31 +#define TRAX_ADDRESS_TOTALMASK 0x00FFFFFF +// !!! VUakiVU. added for new TRAX: +#define TRAX_ADDRESS_WRAPCNT 0x7FE00000 /* version ???... */ +#define TRAX_ADDRESS_WRAP_SHIFT 21 + +/* TRAX PCMatch register fields: */ +#define TRAX_PCMATCH_PCML 0x0000001F +#define TRAX_PCMATCH_PCML_SHIFT 0 +#define TRAX_PCMATCH_PCMS 0x80000000 + +/* Compute trace ram buffer size (in bytes) from status register: */ +#define TRAX_MEM_SIZE(status) (1L << (((status) & TRAX_STATUS_MEMSZ) >> TRAX_STATUS_MEMSZ_SHIFT)) + +#if 0 +/* Describes a field within a register: */ +typedef struct { + const char* name; +// unsigned width; +// unsigned shift; + char width; + char shift; + char visible; /* 0 = internal use only, 1 = shown */ + char reserved; +} trax_regfield_t; +#endif + +/* Describes a TRAX register: */ +typedef struct { + const char* name; + unsigned id; + char width; + char visible; + char writable; + char reserved; + //const trax_regfield_t * fieldset; +} trax_regdef_t; + + +extern const trax_regdef_t trax_reglist[]; +extern const signed char trax_readable_regs[]; + +#ifdef __cplusplus +extern "C" { +#endif + +/* Prototypes: */ +extern int trax_find_reg(char * regname, char **errmsg); +extern const char * trax_regname(int regno); + +#ifdef __cplusplus +} +#endif + +#endif /* _TRAX_REGISTERS_H_ */ + diff --git a/components/esp32/include/xtensa/uart-16550-board.h b/components/esp32/include/xtensa/uart-16550-board.h new file mode 100755 index 0000000000..8ef8af1637 --- /dev/null +++ b/components/esp32/include/xtensa/uart-16550-board.h @@ -0,0 +1,69 @@ +/******************************************************************************* +Copyright (c) 2006-2013 by Tensilica Inc. ALL RIGHTS RESERVED. +These coded instructions, statements, and computer programs are the +copyrighted works and confidential proprietary information of Tensilica Inc. +They may not be modified, copied, reproduced, distributed, or disclosed to +third parties in any manner, medium, or form, in whole or in part, without +the prior written consent of Tensilica Inc. +-------------------------------------------------------------------------------- + +uart-16550-board.h Board-specific UART info on these boards: + Avnet AV60 (XT-AV60) + Avnet AV110 (XT-AV110) + Avnet AV200 (XT-AV200) + Xilinx ML605 (XT-ML605) + Xilinx KC705 (XT-KC705) + +Interface between board-independent driver and board-specific header. + +This is used by a board-independent 16550 UART driver to obtain board-specific +information about 1 instance of the 16550 UART on the board, such as the device +register base address and spacing (a function of how the address lines are +connected on the board) and the frequency of the UART clock. The driver does +not refer directly to the board-specific header, which therefore is not +constrained to use macro names consistent with other boards. + +!! Must not contain any board-specific macro names (only UART specific). !! + +Included at compile-time via an include path specific to the board. + +These boards contain a single 16550 UART implemented on the FPGA. +Their clock frequency comes from the board's core clock (not its own crystal) +which depends on the core config so is not a constant. Obtained via the BSP. + +*******************************************************************************/ + +#ifndef _UART_16550_BOARD_H +#define _UART_16550_BOARD_H + +#include /* BSP API */ +#include /* Board info */ + + +/* Base address of UART's registers. */ +#ifdef UART16550_VADDR +#define UART_16550_REGBASE UART16550_VADDR +#endif + +/* +The UART's registers are connected at word addresses on these boards. +Each byte-wide register appears as the least-significant-byte (LSB) of the +word regardless of the endianness of the processor. +*/ +#define UART_16550_REGSPACING 4 +typedef unsigned uart16550_reg_t; + +/* UART Clock Frequency in Hz */ +#define UART_16550_XTAL_FREQ xtbsp_clock_freq_hz() + +/* UART Interrupt Number */ +#ifdef UART16550_INTNUM +#define UART_16550_INTNUM UART16550_INTNUM +#endif + + +/* Include generic information shared by all boards that use this device. */ +#include + +#endif /* _UART_16550_BOARD_H */ + diff --git a/components/esp32/include/xtensa/uart-16550.h b/components/esp32/include/xtensa/uart-16550.h new file mode 100755 index 0000000000..c551c64c13 --- /dev/null +++ b/components/esp32/include/xtensa/uart-16550.h @@ -0,0 +1,152 @@ +/******************************************************************************* + + Copyright (c) 2006-2007 Tensilica Inc. + + Permission is hereby granted, free of charge, to any person obtaining + a copy of this software and associated documentation files (the + "Software"), to deal in the Software without restriction, including + without limitation the rights to use, copy, modify, merge, publish, + distribute, sublicense, and/or sell copies of the Software, and to + permit persons to whom the Software is furnished to do so, subject to + the following conditions: + + The above copyright notice and this permission notice shall be included + in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY + CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +-------------------------------------------------------------------------------- + +uart-16550.h Generic definitions for National Semiconductor 16550 UART + +This is used by board-support-packages with one or more 16550 compatible UARTs. +A BSP provides a base address for each instance of a 16550 UART on the board. + +Note that a 16552 DUART (Dual UART) is simply two instances of a 16550 UART. + +*******************************************************************************/ + +#ifndef _UART_16550_H_ +#define _UART_16550_H_ + +/* C interface to UART registers. */ +struct uart_dev_s { + union { + uart16550_reg_t rxb; /* DLAB=0: receive buffer, read-only */ + uart16550_reg_t txb; /* DLAB=0: transmit buffer, write-only */ + uart16550_reg_t dll; /* DLAB=1: divisor, LS byte latch */ + } w0; + union { + uart16550_reg_t ier; /* DLAB=0: interrupt-enable register */ + uart16550_reg_t dlm; /* DLAB=1: divisor, MS byte latch */ + } w1; + + union { + uart16550_reg_t isr; /* DLAB=0: interrupt status register, read-only */ + uart16550_reg_t fcr; /* DLAB=0: FIFO control register, write-only */ + uart16550_reg_t afr; /* DLAB=1: alternate function register */ + } w2; + + uart16550_reg_t lcr; /* line control-register, write-only */ + uart16550_reg_t mcr; /* modem control-regsiter, write-only */ + uart16550_reg_t lsr; /* line status register, read-only */ + uart16550_reg_t msr; /* modem status register, read-only */ + uart16550_reg_t scr; /* scratch regsiter, read/write */ +}; + + +#define _RXB(u) ((u)->w0.rxb) +#define _TXB(u) ((u)->w0.txb) +#define _DLL(u) ((u)->w0.dll) +#define _IER(u) ((u)->w1.ier) +#define _DLM(u) ((u)->w1.dlm) +#define _ISR(u) ((u)->w2.isr) +#define _FCR(u) ((u)->w2.fcr) +#define _AFR(u) ((u)->w2.afr) +#define _LCR(u) ((u)->lcr) +#define _MCR(u) ((u)->mcr) +#define _LSR(u) ((u)->lsr) +#define _MSR(u) ((u)->msr) +#define _SCR(u) ((u)->scr) + +typedef volatile struct uart_dev_s uart_dev_t; + +/* IER bits */ +#define RCVR_DATA_REG_INTENABLE 0x01 +#define XMIT_HOLD_REG_INTENABLE 0x02 +#define RCVR_STATUS_INTENABLE 0x04 +#define MODEM_STATUS_INTENABLE 0x08 + +/* FCR bits */ +#define _FIFO_ENABLE 0x01 +#define RCVR_FIFO_RESET 0x02 +#define XMIT_FIFO_RESET 0x04 +#define DMA_MODE_SELECT 0x08 +#define RCVR_TRIGGER_LSB 0x40 +#define RCVR_TRIGGER_MSB 0x80 + +/* AFR bits */ +#define AFR_CONC_WRITE 0x01 +#define AFR_BAUDOUT_SEL 0x02 +#define AFR_RXRDY_SEL 0x04 + +/* ISR bits */ +#define INT_STATUS(r) ((r)&1) +#define INT_PRIORITY(r) (((r)>>1)&0x7) + +/* LCR bits */ +#define WORD_LENGTH(n) (((n)-5)&0x3) +#define STOP_BIT_ENABLE 0x04 +#define PARITY_ENABLE 0x08 +#define EVEN_PARITY 0x10 +#define FORCE_PARITY 0x20 +#define XMIT_BREAK 0x40 +#define DLAB_ENABLE 0x80 + +/* MCR bits */ +#define _DTR 0x01 +#define _RTS 0x02 +#define _OP1 0x04 +#define _OP2 0x08 +#define LOOP_BACK 0x10 + +/* LSR Bits */ +#define RCVR_DATA_READY 0x01 +#define OVERRUN_ERROR 0x02 +#define PARITY_ERROR 0x04 +#define FRAMING_ERROR 0x08 +#define BREAK_INTERRUPT 0x10 +#define XMIT_HOLD_EMPTY 0x20 +#define XMIT_EMPTY 0x40 +#define FIFO_ERROR 0x80 +#define RCVR_READY(u) (_LSR(u)&RCVR_DATA_READY) +#define XMIT_READY(u) (_LSR(u)&XMIT_HOLD_EMPTY) + +/* MSR bits */ +#define _RDR 0x01 +#define DELTA_DSR 0x02 +#define DELTA_RI 0x04 +#define DELTA_CD 0x08 +#define _CTS 0x10 +#define _DSR 0x20 +#define _RI 0x40 +#define _CD 0x80 + + +/* Compute 16-bit divisor for baudrate generator, with rounding: */ +#define UART_DIVISOR(clock,baud) (((clock)/16 + (baud)/2)/(baud)) + +/* Prototypes of driver functions */ +extern void uart16550_init( uart_dev_t *u, unsigned baud, unsigned ndata, + unsigned parity, unsigned nstop ); +extern void uart16550_out( uart_dev_t *u, char c ); +extern char uart16550_in( uart_dev_t *u ); +extern unsigned uart16550_measure_sys_clk( uart_dev_t *u ); + +#endif /* _UART_16550_H_ */ diff --git a/components/esp32/include/xtensa/udma.h b/components/esp32/include/xtensa/udma.h new file mode 100755 index 0000000000..a5feb77701 --- /dev/null +++ b/components/esp32/include/xtensa/udma.h @@ -0,0 +1,276 @@ +/* Customer ID=11656; Build=0x5f626; Copyright (c) 2005-2014 by Cadence Design Systems, Inc. ALL RIGHTS RESERVED. + * These coded instructions, statements, and computer programs are the + * copyrighted works and confidential proprietary information of + * Cadence Design Systems, Inc. They may not be modified, copied, reproduced, + * distributed, or disclosed to third parties in any manner, medium, or form, + * in whole or in part, without the prior written consent of Cadence Design + * Systems Inc. + */ +#ifndef __UDMA_H__ +#define __UDMA_H__ + +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/* Size of the uDMA descriptor */ +#define UDMA_DESC_STRUCT_SIZE 32 + +/* Request attribute is a bit vector passed to the udma functions - udma_copy, + * udma_2d_copy, udma_add_descs. + * Bit 0 : 1 - trigger an interrupt when done, else do nothing + * Bit 1 : 0 - retry the failed request; abort after programmer specified + * number of retries. Defaults to abort with no retries. + * 1 - abort the failed request (after retries) and all pending requests + */ +#define UDMA_DONE_INTERRUPT 0x1 +#define UDMA_ERROR_ABORT 0x0 +#define UDMA_ERROR_ABORT_ALL 0x2 + +/* Enum representing various udma error conditions, udma status, and + * return values + */ +typedef enum { + UDMA_OK = 0, + UDMA_ERROR_QUEUE_FULL = 1, + UDMA_ERROR_BAD_DESC = 2, + UDMA_ERROR_DRAM_CROSSING = 3, + UDMA_ERROR_PIF_ADDR_BUS = 4, + UDMA_ERROR_PIF_DATA_BUS = 5, + UDMA_REQ_PENDING = 6, + UDMA_REQ_DONE = 7, + UDMA_ERROR_BAD_REQUEST = 8, + UDMA_ERROR_INVALID_ARG = 11, + UDMA_ERROR_INIT = 12, + UDMA_ERROR_INTERNAL = -1 +} udma_status_t; + +#ifndef __UDMA_INTERNAL_H__ +/* Opaque structure describing a uDMA descriptor */ +struct udma_desc_struct { + char _[UDMA_DESC_STRUCT_SIZE]; +} __attribute__ ((aligned (UDMA_DESC_STRUCT_SIZE))); +#endif + +typedef struct udma_desc_struct udma_desc_t; + +/* Initialize the udma control structure, the uDMA registers with + * the descriptor queue addresses, and the uDMA sync and error interrupt + * handler. This function needs to be invoked prior to using the uDMA. + * + * xmp_udma_sync_intr : Processor interrupt number to flag udma done + * xmp_udma_error_intr : Processor interrupt number to flag udma error + * + * Returns UDMA_ERROR_INIT if there was an error during initialization else + * returns UDMA_OK. + */ +extern udma_status_t +udma_init(uint32_t xmp_udma_sync_intr, uint32_t xmp_udma_error_intr); + +/* Performs a copy of a linear block of size bytes from the src + * to the dest address. If the call returns UDMA_OK, status is set to + * UDMA_REQ_PENDING or UDMA_REQ_DONE. If there is a dma error, the error code, + * which could be one of UDMA_ERROR_BAD_DESC, UDMA_ERROR_DRAM_CROSSING, + * UDMA_ERROR_PIF_ADDR_BUS, UDMA_ERROR_PIF_DATA_BUS is returned in the status. + * Status is set to UDMA_REQ_DONE if the dma completes normally. + * On completion, the callback function is invoked with the callback_data + * and status as parameters. Note, the callback is always invoked even if + * there is a dma error. + * + * src : src address of the copy + * dest : dest address of the copy + * size : number of bytes to copy + * callback_data : optional data to be passed to callback_func + * callback_func : optional callback after copy is done + * request_attr : attribute defining how to process this request + * (see description of the request attribute in top of udma.h) + * status : track status of the copy; this gets also passed + * as the second argument to the callback_func + * + * Returns UDMA_ERROR_QUEUE_FULL if no more requests can be added, else + * returns UDMA_OK. + */ +extern udma_status_t +udma_copy(void *dest, + void *src, + size_t size, + void *callback_data, + void (*callback_func)(void *, udma_status_t *status), + uint32_t request_attr, + udma_status_t *status); + +/* Performs a copy of a 2D block of data from the src to the dest + * address. If the call returns UDMA_OK, status is set to UDMA_REQ_PENDING or + * UDMA_REQ_DONE. If there is a dma error, the error code, + * which could be one of UDMA_ERROR_BAD_DESC, UDMA_ERROR_DRAM_CROSSING, + * UDMA_ERROR_PIF_ADDR_BUS, UDMA_ERROR_PIF_DATA_BUS is returned in the status. + * Status is set to UDMA_REQ_DONE if the dma completes normally. + * On completion, the callback function is invoked with the callback_data + * and status as parameters. Note, the callback is always invoked even if + * there is a dma error. + * + * src : src address of the copy + * dest : dest address of the copy + * row_size : number of bytes per row to copy + * num_rows : number of rows to copy + * src_pitch : src pitch + * dest_pitch : dest pitch + * callback_data : optional data to be passed to callback_func + * callback_func : optional callback after copy is done + * request_attr : attribute defining how to process this request + * (see description of the request attribute in top of udma.h) + * status : track status of the copy; this gets also passed + * as the second argument to the callback_func + * + * Returns UDMA_ERROR_QUEUE_FULL if no more requests can be added, else + * returns UDMA_OK. + */ +extern udma_status_t +udma_2d_copy(void *dest, + void *src, + size_t row_size, + uint32_t num_rows, + uint32_t src_pitch, + uint32_t dest_pitch, + void *callback_data, + void (*callback_func)(void *, udma_status_t *status), + uint32_t request_attr, + udma_status_t *status); + +/* Process requests that are done. Any callbacks associated + * with the completed requests gets invoked. If there are any errors, + * the error request is (and any pending request based on the request attribute) + * cancelled and the error code is returned in the status associated with + * all such cancelled requests. Callbacks associated with the cancelled + * requests are also invoked. If all requests terminate normally, the status + * of the completed requests are set to UDMA_REQ_DONE. + * + * Returns void + */ +extern void +udma_process_requests(); + +/* Sets the udma max PIF block size + * + * max_block_size : max block size to be set + * + * Returns UDMA_ERROR_INVALID_ARG if block_size is > 3, else returns UDMA_OK + */ +udma_status_t +udma_set_max_block_size(uint32_t block_size); + +/* Sets the udma max outstanding PIF requests + * + * max_outstanding : max outstanding PIF requests + * + * Returns UDMA_ERROR_INVALID_ARG if max_outstanding is not between 1 and 16 + * else returns UDMA_OK + */ +udma_status_t +udma_set_max_outstanding(uint32_t max_outstanding); + +/* Initialize a uDMA descriptor using the copy parameters. The descriptor + * is then queued separately using udma_add_desc + * + * src : src address of the copy + * dest : dest address of the copy + * row_size : number of bytes per row to copy + * num_rows : number of rows to copy + * src_pitch : src pitch + * dest_pitch : dest pitch + * notify_with_interrupt : If 1, interrupt when dma is done with this descriptor + * if 0, do nothing, else undefined + * + * Returns void + */ +extern void +udma_set_desc(void *src, + void *dest, + size_t row_size, + uint32_t num_rows, + uint32_t src_pitch, + uint32_t dest_pitch, + uint32_t notify_with_interrupt, + udma_desc_t *desc); + +/* Add multiple uDMA descriptors to the descriptor queue. If the call returns + * UDMA_OK, the status is set to UDMA_REQ_PENDING or UDMA_REQ_DONE. + * If there is a dma error, the error code, which could be one of + * UDMA_ERROR_BAD_DESC, UDMA_ERROR_DRAM_CROSSING, UDMA_ERROR_PIF_ADDR_BUS, + * UDMA_ERROR_PIF_DATA_BUS is returned in the status. Status is set + * to UDMA_REQ_DONE, if the dma completes normally. + * On completion, the callback function is invoked with the callback_data + * and status as parameters. Note, the callback is always invoked even if + * there is a dma error. + * + * desc : descriptors to be added + * num_desc : number of descriptors to be added + * callback_data : optional data to be passed to callback_func + * callback_func : optional callback after copy is done + * request_attr : attribute defining how to process this request + * (see description of the request attribute in top of udma.h) + * Note, bit 0 (for enabling interrupt) is ignored in this call. + * To interrupt on dma completion, set the + * notify_with_interrupt parameter when creating descriptors + * using udma_set_desc. + * status : track status of the copy; this gets also passed + * as the second argument to the callback_func + * + * Returns UDMA_ERROR_QUEUE_FULL if no more descriptors can be added, + * UDMA_ERROR_INVALID_ARG if num_descs == 0, else return UDMA_OK + */ +udma_status_t +udma_add_descs(udma_desc_t *descs, + uint32_t num_descs, + void *callback_data, + void (*callback_func)(void *, udma_status_t *status), + uint32_t request_attr, + udma_status_t *status); + +/* Wait for udma copy request to complete. Could spin wait or goto waiti + * based on the sleep_wait parameter. Once the request is done, the callback + * associated with this request and any prior completed requests are handled. + * Error code, if any, is returned in the status s, else s is set to + * UDMA_REQ_DONE. + * + * s : status to wait for + * sleep_wait : sleep wait if true, else spin waits + * + * Returns void + */ +extern void +udma_wait_request(volatile udma_status_t *s, uint32_t sleep_wait); + +/* Inlined function to set the src, dest address of the descriptor + * + * src : src address of the uDMA + * dest : dest address of the uDMA + * desc : descriptor to be modified + * + * Returns void + */ +void static inline +udma_set_desc_addrs(void *src, void *dest, udma_desc_t *desc) { + uint32_t *d = (uint32_t *)desc; + *d = (uintptr_t)src; + *(d+1) = (uintptr_t)dest; +} + +/* Sets the number of retries for a failed dma request + * + * max_retries : max number of retries + * + * Sets the max number of retries for a failed dma request. The default is 0, + * i.e, no retries + */ +void +udma_set_max_retries(uint32_t max_retries); + +#ifdef __cplusplus +} +#endif + +#endif /* __UDMA_H__ */ diff --git a/components/esp32/include/xtensa/xdm-regs.h b/components/esp32/include/xtensa/xdm-regs.h new file mode 100755 index 0000000000..50ee029338 --- /dev/null +++ b/components/esp32/include/xtensa/xdm-regs.h @@ -0,0 +1,530 @@ +/* xdm-regs.h - Common register and related definitions for the XDM + (Xtensa Debug Module) */ + +/* Copyright (c) 2011-2012 Tensilica Inc. + + Permission is hereby granted, free of charge, to any person obtaining + a copy of this software and associated documentation files (the + "Software"), to deal in the Software without restriction, including + without limitation the rights to use, copy, modify, merge, publish, + distribute, sublicense, and/or sell copies of the Software, and to + permit persons to whom the Software is furnished to do so, subject to + the following conditions: + + The above copyright notice and this permission notice shall be included + in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY + CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ + + +#ifndef _XDM_REGS_H_ +#define _XDM_REGS_H_ + +/* NOTE: This header file is included by C, assembler, and other sources. + So any C-specific or asm-specific content must be appropriately #ifdef'd. */ + + +/* + * XDM registers can be accessed using APB, ERI, or JTAG (via NAR). + * Address offsets for APB and ERI are the same, and for JTAG + * is different (due to the limited 7-bit NAR addressing). + * + * Here, we first provide the constants as APB / ERI address offsets. + * This is necessary for assembler code (which accesses XDM via ERI), + * because complex conversion macros between the two address maps + * don't work in the assembler. + * Conversion macros are used to convert these to/from JTAG (NAR), + * addresses, for software using JTAG. + */ +/* FIXME: maybe provide only MISC+CS registers here, and leave specific + subsystem registers in separate headers? eg. for TRAX, PERF, OCD */ + +/* XDM_.... ERI addr [NAR addr] Description...... */ + +/* TRAX */ +#define XDM_TRAX_ID 0x0000 /*[0x00] ID */ +#define XDM_TRAX_CONTROL 0x0004 /*[0x01] Control */ +#define XDM_TRAX_STATUS 0x0008 /*[0x02] Status */ +#define XDM_TRAX_DATA 0x000C /*[0x03] Data */ +#define XDM_TRAX_ADDRESS 0x0010 /*[0x04] Address */ +#define XDM_TRAX_TRIGGER 0x0014 /*[0x05] Stop PC */ +#define XDM_TRAX_MATCH 0x0018 /*[0x06] Stop PC Range */ +#define XDM_TRAX_DELAY 0x001C /*[0x07] Post Stop Trigger Capture Size */ +#define XDM_TRAX_STARTADDR 0x0020 /*[0x08] Trace Memory Start */ +#define XDM_TRAX_ENDADDR 0x0024 /*[0x09] Trace Memory End */ +#define XDM_TRAX_DEBUGPC 0x003C /*[0x0F] Debug PC */ +#define XDM_TRAX_P4CHANGE 0x0040 /*[0x10] X */ +#define XDM_TRAX_TIME0 0x0040 /*[0x10] First Time Register */ +#define XDM_TRAX_P4REV 0x0044 /*[0x11] X */ +#define XDM_TRAX_TIME1 0x0044 /*[0x11] Second Time Register */ +#define XDM_TRAX_P4DATE 0x0048 /*[0x12] X */ +#define XDM_TRAX_INTTIME_MAX 0x0048 /*[0x12] maximal Value of Timestamp IntTime */ +#define XDM_TRAX_P4TIME 0x004C /*[0x13] X */ +#define XDM_TRAX_PDSTATUS 0x0050 /*[0x14] Sample of PDebugStatus */ +#define XDM_TRAX_PDDATA 0x0054 /*[0x15] Sample of PDebugData */ +#define XDM_TRAX_STOP_PC 0x0058 /*[0x16] X */ +#define XDM_TRAX_STOP_ICNT 0x005C /*[0x16] X */ +#define XDM_TRAX_MSG_STATUS 0x0060 /*[0x17] X */ +#define XDM_TRAX_FSM_STATUS 0x0064 /*[0x18] X */ +#define XDM_TRAX_IB_STATUS 0x0068 /*[0x19] X */ +#define XDM_TRAX_STOPCNT 0x006C /*[0x1A] X */ + +/* Performance Monitoring Counters */ +#define XDM_PERF_PMG 0x1000 /*[0x20] perf. mon. global control register */ +#define XDM_PERF_INTPC 0x1010 /*[0x24] perf. mon. interrupt PC */ +#define XDM_PERF_PM0 0x1080 /*[0x28] perf. mon. counter 0 value */ +#define XDM_PERF_PM1 0x1084 /*[0x29] perf. mon. counter 1 value */ +#define XDM_PERF_PM2 0x1088 /*[0x2A] perf. mon. counter 2 value */ +#define XDM_PERF_PM3 0x108C /*[0x2B] perf. mon. counter 3 value */ +#define XDM_PERF_PM4 0x1090 /*[0x2C] perf. mon. counter 4 value */ +#define XDM_PERF_PM5 0x1094 /*[0x2D] perf. mon. counter 5 value */ +#define XDM_PERF_PM6 0x1098 /*[0x2E] perf. mon. counter 6 value */ +#define XDM_PERF_PM7 0x109C /*[0x2F] perf. mon. counter 7 value */ +#define XDM_PERF_PM(n) (0x1080+((n)<<2)) /* perfmon cnt n=0..7 value */ +#define XDM_PERF_PMCTRL0 0x1100 /*[0x30] perf. mon. counter 0 control */ +#define XDM_PERF_PMCTRL1 0x1104 /*[0x31] perf. mon. counter 1 control */ +#define XDM_PERF_PMCTRL2 0x1108 /*[0x32] perf. mon. counter 2 control */ +#define XDM_PERF_PMCTRL3 0x110C /*[0x33] perf. mon. counter 3 control */ +#define XDM_PERF_PMCTRL4 0x1110 /*[0x34] perf. mon. counter 4 control */ +#define XDM_PERF_PMCTRL5 0x1114 /*[0x35] perf. mon. counter 5 control */ +#define XDM_PERF_PMCTRL6 0x1118 /*[0x36] perf. mon. counter 6 control */ +#define XDM_PERF_PMCTRL7 0x111C /*[0x37] perf. mon. counter 7 control */ +#define XDM_PERF_PMCTRL(n) (0x1100+((n)<<2)) /* perfmon cnt n=0..7 control */ +#define XDM_PERF_PMSTAT0 0x1180 /*[0x38] perf. mon. counter 0 status */ +#define XDM_PERF_PMSTAT1 0x1184 /*[0x39] perf. mon. counter 1 status */ +#define XDM_PERF_PMSTAT2 0x1188 /*[0x3A] perf. mon. counter 2 status */ +#define XDM_PERF_PMSTAT3 0x118C /*[0x3B] perf. mon. counter 3 status */ +#define XDM_PERF_PMSTAT4 0x1190 /*[0x3C] perf. mon. counter 4 status */ +#define XDM_PERF_PMSTAT5 0x1194 /*[0x3D] perf. mon. counter 5 status */ +#define XDM_PERF_PMSTAT6 0x1198 /*[0x3E] perf. mon. counter 6 status */ +#define XDM_PERF_PMSTAT7 0x119C /*[0x3F] perf. mon. counter 7 status */ +#define XDM_PERF_PMSTAT(n) (0x1180+((n)<<2)) /* perfmon cnt n=0..7 status */ + +/* On-Chip-Debug (OCD) */ +#define XDM_OCD_ID 0x2000 /*[0x40] ID register */ +#define XDM_OCD_DCR_CLR 0x2008 /*[0x42] Debug Control reg clear */ +#define XDM_OCD_DCR_SET 0x200C /*[0x43] Debug Control reg set */ +#define XDM_OCD_DSR 0x2010 /*[0x44] Debug Status reg */ +#define XDM_OCD_DDR 0x2014 /*[0x45] Debug Data reg */ +#define XDM_OCD_DDREXEC 0x2018 /*[0x46] Debug Data reg + execute-DIR */ +#define XDM_OCD_DIR0EXEC 0x201C /*[0x47] Debug Instruction reg, word 0 + execute-DIR */ +#define XDM_OCD_DIR0 0x2020 /*[0x48] Debug Instruction reg, word 1 */ +#define XDM_OCD_DIR1 0x2024 /*[0x49] Debug Instruction reg, word 2 */ +#define XDM_OCD_DIR2 0x2028 /*[0x4A] Debug Instruction reg, word 3 */ +#define XDM_OCD_DIR3 0x202C /*[0x49] Debug Instruction reg, word 4 */ +#define XDM_OCD_DIR4 0x2030 /*[0x4C] Debug Instruction reg, word 5 */ +#define XDM_OCD_DIR5 0x2034 /*[0x4D] Debug Instruction reg, word 5 */ +#define XDM_OCD_DIR6 0x2038 /*[0x4E] Debug Instruction reg, word 6 */ +#define XDM_OCD_DIR7 0x203C /*[0x4F] Debug Instruction reg, word 7 */ + +/* Miscellaneous Registers */ +#define XDM_MISC_PWRCTL 0x3020 /*[0x58] Power and Reset Control */ +#define XDM_MISC_PWRSTAT 0x3024 /*[0x59] Power and Reset Status */ +#define XDM_MISC_ERISTAT 0x3028 /*[0x5A] ERI Transaction Status */ +#define XDM_MISC_DATETIME 0x3034 /*[0x5D] [INTERNAL] Timestamps of build */ +#define XDM_MISC_UBID 0x3038 /*[0x5E] [INTERNAL] Build Unique ID */ +#define XDM_MISC_CID 0x303C /*[0x5F] [INTERNAL] Customer ID */ + +/* CoreSight compatibility */ +#define XDM_CS_ITCTRL 0x3F00 /*[0x60] InTegration Mode control reg */ +#define XDM_CS_CLAIMSET 0x3FA0 /*[0x68] Claim Tag Set reg */ +#define XDM_CS_CLAIMCLR 0x3FA4 /*[0x69] Claim Tag Clear reg */ +#define XDM_CS_LOCK_ACCESS 0x3FB0 /*[0x6B] Lock Access (writing 0xC5ACCE55 unlocks) */ +#define XDM_CS_LOCK_STATUS 0x3FB4 /*[0x6D] Lock Status */ +#define XDM_CS_AUTH_STATUS 0x3FB8 /*[0x6E] Authentication Status */ +#define XDM_CS_DEV_ID 0x3FC8 /*[0x72] Device ID */ +#define XDM_CS_DEV_TYPE 0x3FCC /*[0x73] Device Type */ +#define XDM_CS_PER_ID4 0x3FD0 /*[0x74] Peripheral ID reg byte 4 */ +#define XDM_CS_PER_ID5 0x3FD4 /*[0x75] Peripheral ID reg byte 5 */ +#define XDM_CS_PER_ID6 0x3FD8 /*[0x76] Peripheral ID reg byte 6 */ +#define XDM_CS_PER_ID7 0x3FDC /*[0x77] Peripheral ID reg byte 7 */ +#define XDM_CS_PER_ID0 0x3FE0 /*[0x78] Peripheral ID reg byte 0 */ +#define XDM_CS_PER_ID1 0x3FE4 /*[0x79] Peripheral ID reg byte 1 */ +#define XDM_CS_PER_ID2 0x3FE8 /*[0x7A] Peripheral ID reg byte 2 */ +#define XDM_CS_PER_ID3 0x3FEC /*[0x7B] Peripheral ID reg byte 3 */ +#define XDM_CS_COMP_ID0 0x3FF0 /*[0x7C] Component ID reg byte 0 */ +#define XDM_CS_COMP_ID1 0x3FF4 /*[0x7D] Component ID reg byte 1 */ +#define XDM_CS_COMP_ID2 0x3FF8 /*[0x7E] Component ID reg byte 2 */ +#define XDM_CS_COMP_ID3 0x3FFC /*[0x7F] Component ID reg byte 3 */ + +#define CS_PER_ID0 0x00000003 +#define CS_PER_ID1 0x00000021 +#define CS_PER_ID2 0x0000000f +#define CS_PER_ID3 0x00000000 +#define CS_PER_ID4 0x00000024 + +#define CS_COMP_ID0 0x0000000d +#define CS_COMP_ID1 0x00000090 +#define CS_COMP_ID2 0x00000005 +#define CS_COMP_ID3 0x000000b1 + +#define CS_DEV_TYPE 0x00000015 + +#define XTENSA_IDCODE 0x120034e5 // FIXME (upper bits not spec. out but BE is !) +#define XTENSA_MFC_ID (XTENSA_IDCODE & 0xFFF) +#define CS_DEV_ID XTENSA_IDCODE + +#define NXS_OCD_REG(val) ((val >= 0x40) && (val <= 0x5F)) +#define NXS_TRAX_REG(val) val <= 0x3F + +#define ERI_TRAX_REG(val) ((val & 0xFFFF) < 0x1000) +#define ERI_OCD_REG(val) ((val & 0xFFFF) >= 0x2000) && ((val & 0xFFFF) < 0x4000)) + +/* Convert above 14-bit ERI/APB address/offset to 7-bit NAR address: */ +#define _XDM_ERI_TO_NAR(a) ( ((a)&0x3F80)==0x0000 ? (((a)>>2) & 0x1F) \ + : ((a)&0x3E00)==0x1000 ? (0x20 | (((a)>>2) & 7) | (((a)>>4) & 0x18)) \ + : ((a)&0x3FC0)==0x2000 ? (0x40 | (((a)>>2) & 0xF)) \ + : ((a)&0x3FE0)==0x3020 ? (0x50 | (((a)>>2) & 0xF)) \ + : ((a)&0x3FFC)==0x3F00 ? 0x60 \ + : ((a)&0x3F80)==0x3F80 ? (0x60 | (((a)>>2) & 0x1F)) \ + : -1 ) + +#define XDM_ERI_TO_NAR(a) _XDM_ERI_TO_NAR(a & 0xFFFF) + +/* Convert 7-bit NAR address back to ERI/APB address/offset: */ +#define _XDM_NAR_TO_APB(a) ((a) <= 0x1f ? ((a) << 2) \ + :(a) >= 0x20 && (a) <= 0x3F ? (0x1000 | (((a)& 7) << 2) | (((a)&0x18)<<4)) \ + :(a) >= 0x40 && (a) <= 0x4F ? (0x2000 | (((a)&0xF) << 2)) \ + :(a) >= 0x58 && (a) <= 0x5F ? (0x3000 | (((a)&0xF) << 2)) \ + :(a) == 0x60 ? (0x3F00) \ + :(a) >= 0x68 && (a) <= 0x7F ? (0x3F80 | (((a)&0x1F) << 2)) \ + : -1) + +#define XDM_NAR_TO_APB(a) _XDM_NAR_TO_APB((a & 0xFFFF)) +#define XDM_NAR_TO_ERI(a) _XDM_NAR_TO_APB((a & 0xFFFF)) | 0x000000 + +/* Convert APB to ERI address */ +#define XDM_APB_TO_ERI(a) ((a) | (0x100000)) +#define XDM_ERI_TO_APB(a) ((a) & (0x0FFFFF)) + +/*********** Bit definitions within some of the above registers ***********/ +#define OCD_ID_LSDDRP 0x01000000 +#define OCD_ID_LSDDRP_SHIFT 24 +#define OCD_ID_ENDIANESS 0x00000001 +#define OCD_ID_ENDIANESS_SHIFT 0 +#define OCD_ID_PSO 0x0000000C +#define OCD_ID_PSO_SHIFT 2 +#define OCD_ID_TRACEPORT 0x00000080 +#define OCD_ID_TRACEPORT_SHIFT 7 + +/* Power Status register. NOTE: different bit positions in JTAG vs. ERI/APB !! */ +/* ERI/APB: */ +#define PWRSTAT_CORE_DOMAIN_ON 0x00000001 /* set if core is powered on */ +#define PWRSTAT_CORE_DOMAIN_ON_SHIFT 0 +#define PWRSTAT_WAKEUP_RESET 0x00000002 /* [ERI only] 0=cold start, 1=PSO wakeup */ +#define PWRSTAT_WAKEUP_RESET_SHIFT 1 +#define PWRSTAT_CACHES_LOST_POWER 0x00000004 /* [ERI only] set if caches (/localmems?) lost power */ + /* FIXME: does this include local memories? */ +#define PWRSTAT_CACHES_LOST_POWER_SHIFT 2 +#define PWRSTAT_CORE_STILL_NEEDED 0x00000010 /* set if others keeping core awake */ +#define PWRSTAT_CORE_STILL_NEEDED_SHIFT 4 +#define PWRSTAT_MEM_DOMAIN_ON 0x00000100 /* set if memory domain is powered on */ +#define PWRSTAT_MEM_DOMAIN_ON_SHIFT 8 +#define PWRSTAT_DEBUG_DOMAIN_ON 0x00001000 /* set if debug domain is powered on */ +#define PWRSTAT_DEBUG_DOMAIN_ON_SHIFT 12 +#define PWRSTAT_ALL_ON PWRSTAT_CORE_DOMAIN_ON | PWRSTAT_MEM_DOMAIN_ON | PWRSTAT_DEBUG_DOMAIN_ON +#define PWRSTAT_CORE_WAS_RESET 0x00010000 /* [APB only] set if core got reset */ +#define PWRSTAT_CORE_WAS_RESET_SHIFT 16 +#define PWRSTAT_DEBUG_WAS_RESET 0x10000000 /* set if debug module got reset */ +#define PWRSTAT_DEBUG_WAS_RESET_SHIFT 28 +/* JTAG: */ +#define J_PWRSTAT_CORE_DOMAIN_ON 0x01 /* set if core is powered on */ +#define J_PWRSTAT_MEM_DOMAIN_ON 0x02 /* set if memory domain is powered on */ +#define J_PWRSTAT_DEBUG_DOMAIN_ON 0x04 /* set if debug domain is powered on */ +#define J_PWRSTAT_ALL_ON J_PWRSTAT_CORE_DOMAIN_ON | J_PWRSTAT_MEM_DOMAIN_ON | J_PWRSTAT_DEBUG_DOMAIN_ON +#define J_PWRSTAT_CORE_STILL_NEEDED 0x08 /* set if others keeping core awake */ +#define J_PWRSTAT_CORE_WAS_RESET 0x10 /* set if core got reset */ +#define J_PWRSTAT_DEBUG_WAS_RESET 0x40 /* set if debug module got reset */ + +/* Power Control register. NOTE: different bit positions in JTAG vs. ERI/APB !! */ +/* ERI/APB: */ +#define PWRCTL_CORE_SHUTOFF 0x00000001 /* [ERI only] core wants to shut off on WAITI */ +#define PWRCTL_CORE_SHUTOFF_SHIFT 0 +#define PWRCTL_CORE_WAKEUP 0x00000001 /* [APB only] set to force core to stay powered on */ +#define PWRCTL_CORE_WAKEUP_SHIFT 0 +#define PWRCTL_MEM_WAKEUP 0x00000100 /* set to force memory domain to stay powered on */ +#define PWRCTL_MEM_WAKEUP_SHIFT 8 +#define PWRCTL_DEBUG_WAKEUP 0x00001000 /* set to force debug domain to stay powered on */ +#define PWRCTL_DEBUG_WAKEUP_SHIFT 12 +#define PWRCTL_ALL_ON PWRCTL_CORE_WAKEUP | PWRCTL_MEM_WAKEUP | PWRCTL_DEBUG_WAKEUP +#define PWRCTL_CORE_RESET 0x00010000 /* [APB only] set to assert core reset */ +#define PWRCTL_CORE_RESET_SHIFT 16 +#define PWRCTL_DEBUG_RESET 0x10000000 /* set to assert debug module reset */ +#define PWRCTL_DEBUG_RESET_SHIFT 28 +/* JTAG: */ +#define J_PWRCTL_CORE_WAKEUP 0x01 /* set to force core to stay powered on */ +#define J_PWRCTL_MEM_WAKEUP 0x02 /* set to force memory domain to stay powered on */ +#define J_PWRCTL_DEBUG_WAKEUP 0x04 /* set to force debug domain to stay powered on */ +#define J_DEBUG_USE 0x80 /* */ +#define J_PWRCTL_ALL_ON J_DEBUG_USE | J_PWRCTL_CORE_WAKEUP | J_PWRCTL_MEM_WAKEUP | J_PWRCTL_DEBUG_WAKEUP +#define J_PWRCTL_DEBUG_ON J_DEBUG_USE | J_PWRCTL_DEBUG_WAKEUP +#define J_PWRCTL_CORE_RESET 0x10 /* set to assert core reset */ +#define J_PWRCTL_DEBUG_RESET 0x40 /* set to assert debug module reset */ + +#define J_PWRCTL_WRITE_MASK 0xFF +#define J_PWRSTAT_WRITE_MASK 0xFF + +#define PWRCTL_WRITE_MASK ~0 +#define PWRSTAT_WRITE_MASK ~0 + +/************ The following are only relevant for JTAG, so perhaps belong in OCD only **************/ + +/* XDM 5-bit JTAG Instruction Register (IR) values: */ +#define XDM_IR_PWRCTL 0x08 /* select 8-bit Power/Reset Control (PRC) */ +#define XDM_IR_PWRSTAT 0x09 /* select 8-bit Power/Reset Status (PRS) */ +#define XDM_IR_NAR_SEL 0x1c /* select altern. 8-bit NAR / 32-bit NDR (Nexus-style) */ +#define XDM_IR_NDR_SEL 0x1d /* select altern. 32-bit NDR / 8-bit NAR + (FIXME - functionality not yet in HW) */ +#define XDM_IR_IDCODE 0x1e /* select 32-bit JTAG IDCODE */ +#define XDM_IR_BYPASS 0x1f /* select 1-bit bypass */ + +#define XDM_IR_WIDTH 5 /* width of IR for Xtensa TAP */ + +/* NAR register bits: */ +#define XDM_NAR_WRITE 0x01 +#define XDM_NAR_ADDR_MASK 0xFE +#define XDM_NAR_ADDR_SHIFT 1 + +#define XDM_NAR_BUSY 0x02 +#define XDM_NAR_ERROR 0x01 + +#define NEXUS_DIR_READ 0x00 +#define NEXUS_DIR_WRITE 0x01 + +/************ Define DCR register bits **************/ + +#define DCR_ENABLEOCD 0x0000001 +#define DCR_ENABLEOCD_SHIFT 0 +#define DCR_DEBUG_INT 0x0000002 +#define DCR_DEBUG_INT_SHIFT 1 +#define DCR_DEBUG_OVERRIDE 0x0000004 +#define DCR_DEBUG_OVERRIDE_SHIFT 2 +#define DCR_DEBUG_INTERCEPT 0x0000008 +#define DCR_DEBUG_INTERCEPT_SHIFT 3 +#define DCR_MASK_NMI 0x0000020 +#define DCR_MASK_NMI_SHIFT 5 +#define DCR_STEP_ENABLE 0x0000040 +#define DCR_STEP_ENABLE_SHIFT 6 +#define DCR_BREAK_IN_EN 0x0010000 +#define DCR_BREAK_IN_EN_SHIFT 16 +#define DCR_BREAK_OUT_EN 0x0020000 +#define DCR_BREAK_OUT_EN_SHIFT 17 +#define DCR_DEBUG_INT_EN 0x0040000 +#define DCR_DEBUG_INT_EN_SHIFT 18 +#define DCR_DBG_SW_ACTIVE 0x0100000 +#define DCR_DBG_SW_ACTIVE_SHIFT 20 +#define DCR_STALL_IN_EN 0x0200000 +#define DCR_STALL_IN_EN_SHIFT 21 +#define DCR_DEBUG_OUT_EN 0x0400000 +#define DCR_DEBUG_OUT_EN_SHIFT 22 +#define DCR_BREAK_OUT_ITO 0x1000000 +#define DCR_STALL_OUT_ITO 0x2000000 +#define DCR_STALL_OUT_ITO_SHIFT 25 + +/************ Define DSR register bits **************/ + +#define DOSR_EXECDONE_ER 0x01 +#define DOSR_EXECDONE_SHIFT 0 +#define DOSR_EXCEPTION_ER 0x02 +#define DOSR_EXCEPTION_SHIFT 1 +#define DOSR_BUSY 0x04 +#define DOSR_BUSY_SHIFT 2 +#define DOSR_OVERRUN 0x08 +#define DOSR_OVERRUN_SHIFT 3 +#define DOSR_INOCDMODE_ER 0x10 +#define DOSR_INOCDMODE_SHIFT 4 +#define DOSR_CORE_WROTE_DDR_ER 0x400 +#define DOSR_CORE_WROTE_DDR_SHIFT 10 +#define DOSR_CORE_READ_DDR_ER 0x800 +#define DOSR_CORE_READ_DDR_SHIFT 11 +#define DOSR_HOST_WROTE_DDR_ER 0x4000 +#define DOSR_HOST_WROTE_DDR_SHIFT 14 +#define DOSR_HOST_READ_DDR_ER 0x8000 +#define DOSR_HOST_READ_DDR_SHIFT 15 + +#define DOSR_DEBUG_PEND_BIN 0x10000 +#define DOSR_DEBUG_PEND_HOST 0x20000 +#define DOSR_DEBUG_PEND_TRAX 0x40000 +#define DOSR_DEBUG_BIN 0x100000 +#define DOSR_DEBUG_HOST 0x200000 +#define DOSR_DEBUG_TRAX 0x400000 +#define DOSR_DEBUG_PEND_BIN_SHIFT 16 +#define DOSR_DEBUG_PEND_HOST_SHIFT 17 +#define DOSR_DEBUG_PEND_TRAX_SHIFT 18 +#define DOSR_DEBUG_BREAKIN 0x0100000 +#define DOSR_DEBUG_BREAKIN_SHIFT 20 +#define DOSR_DEBUG_HOST_SHIFT 21 +#define DOSR_DEBUG_TRAX_SHIFT 22 + +#define DOSR_DEBUG_STALL 0x1000000 +#define DOSR_DEBUG_STALL_SHIFT 24 + +#define DOSR_CORE_ON 0x40000000 +#define DOSR_CORE_ON_SHIFT 30 +#define DOSR_DEBUG_ON 0x80000000 +#define DOSR_DEBUG_ON_SHIFT 31 + +/********** Performance monitor registers bits **********/ + +#define PERF_PMG_ENABLE 0x00000001 /* global enable bit */ +#define PERF_PMG_ENABLE_SHIFT 0 + +#define PERF_PMCTRL_INT_ENABLE 0x00000001 /* assert interrupt on overflow */ +#define PERF_PMCTRL_INT_ENABLE_SHIFT 0 +#define PERF_PMCTRL_KRNLCNT 0x00000008 /* ignore TRACELEVEL */ +#define PERF_PMCTRL_KRNLCNT_SHIFT 3 +#define PERF_PMCTRL_TRACELEVEL 0x000000F0 /* count when CINTLEVEL <= TRACELEVEL */ +#define PERF_PMCTRL_TRACELEVEL_SHIFT 4 +#define PERF_PMCTRL_SELECT 0x00001F00 /* events group selector */ +#define PERF_PMCTRL_SELECT_SHIFT 8 +#define PERF_PMCTRL_MASK 0xFFFF0000 /* events mask */ +#define PERF_PMCTRL_MASK_SHIFT 16 + +#define PERF_PMSTAT_OVERFLOW 0x00000001 /* counter overflowed */ +#define PERF_PMSTAT_OVERFLOW_SHIFT 0 +#define PERF_PMSTAT_INT 0x00000010 /* interrupt asserted */ +#define PERF_PMSTAT_INT_SHIFT 4 + +#if defined (USE_XDM_REGNAME) || defined (USE_DAP_REGNAME) +/* Describes XDM register: */ +typedef struct { + int reg; + char* name; +} regdef_t; + +/*char* regname(regdef_t* list, int regno) +{ + unsigned i; + for(i = 0 ; i < (sizeof(list) / sizeof(regdef_t)); i++){ + if(list[i].reg == regno) + return list[i].name; + } + return "???"; +}*/ + +/* + * Returns the name of the specified XDM register number, + * or simply "???" if the register number is not recognized. + * FIXME - requires -1 as the last entry - change to compare the name to ??? + * or even better, make the code above to work. + */ +static char * regname(regdef_t* list, int reg) +{ + int i = 0; + while (list[i].reg != -1){ + if (list[i].reg == reg) + break; + i++; + } + return list[i].name; +} + +#if defined (USE_XDM_REGNAME) +regdef_t xdm_reglist[] = +{ + {XDM_TRAX_ID ,"TRAX_ID" }, + {XDM_TRAX_CONTROL ,"CONTROL" }, + {XDM_TRAX_STATUS ,"STATUS" }, + {XDM_TRAX_DATA ,"DATA" }, + {XDM_TRAX_ADDRESS ,"ADDRESS" }, + {XDM_TRAX_TRIGGER ,"TRIGGER PC" }, + {XDM_TRAX_MATCH ,"PC MATCH" }, + {XDM_TRAX_DELAY ,"DELAY CNT." }, + {XDM_TRAX_STARTADDR ,"START ADDRESS"}, + {XDM_TRAX_ENDADDR ,"END ADDRESS" }, + {XDM_TRAX_DEBUGPC ,"DEBUG PC" }, + {XDM_TRAX_P4CHANGE ,"P4 CHANGE" }, + {XDM_TRAX_P4REV ,"P4 REV." }, + {XDM_TRAX_P4DATE ,"P4 DATE" }, + {XDM_TRAX_P4TIME ,"P4 TIME" }, + {XDM_TRAX_PDSTATUS ,"PD STATUS" }, + {XDM_TRAX_PDDATA ,"PD DATA" }, + {XDM_TRAX_STOP_PC ,"STOP PC" }, + {XDM_TRAX_STOP_ICNT ,"STOP ICNT" }, + {XDM_TRAX_MSG_STATUS ,"MSG STAT." }, + {XDM_TRAX_FSM_STATUS ,"FSM STAT." }, + {XDM_TRAX_IB_STATUS ,"IB STAT." }, + + {XDM_OCD_ID ,"OCD_ID" }, + {XDM_OCD_DCR_CLR ,"DCR_CLR" }, + {XDM_OCD_DCR_SET ,"DCR_SET" }, + {XDM_OCD_DSR ,"DOSR" }, + {XDM_OCD_DDR ,"DDR" }, + {XDM_OCD_DDREXEC ,"DDREXEC" }, + {XDM_OCD_DIR0EXEC ,"DIR0EXEC"}, + {XDM_OCD_DIR0 ,"DIR0" }, + {XDM_OCD_DIR1 ,"DIR1" }, + {XDM_OCD_DIR2 ,"DIR2" }, + {XDM_OCD_DIR3 ,"DIR3" }, + {XDM_OCD_DIR4 ,"DIR4" }, + {XDM_OCD_DIR5 ,"DIR5" }, + {XDM_OCD_DIR6 ,"DIR6" }, + {XDM_OCD_DIR7 ,"DIR7" }, + + {XDM_PERF_PMG ,"PMG" }, + {XDM_PERF_INTPC ,"INTPC" }, + {XDM_PERF_PM0 ,"PM0 " }, + {XDM_PERF_PM1 ,"PM1 " }, + {XDM_PERF_PM2 ,"PM2 " }, + {XDM_PERF_PM3 ,"PM3 " }, + {XDM_PERF_PM4 ,"PM4 " }, + {XDM_PERF_PM5 ,"PM5 " }, + {XDM_PERF_PM6 ,"PM6 " }, + {XDM_PERF_PM7 ,"PM7 " }, + {XDM_PERF_PMCTRL0 ,"PMCTRL0"}, + {XDM_PERF_PMCTRL1 ,"PMCTRL1"}, + {XDM_PERF_PMCTRL2 ,"PMCTRL2"}, + {XDM_PERF_PMCTRL3 ,"PMCTRL3"}, + {XDM_PERF_PMCTRL4 ,"PMCTRL4"}, + {XDM_PERF_PMCTRL5 ,"PMCTRL5"}, + {XDM_PERF_PMCTRL6 ,"PMCTRL6"}, + {XDM_PERF_PMCTRL7 ,"PMCTRL7"}, + {XDM_PERF_PMSTAT0 ,"PMSTAT0"}, + {XDM_PERF_PMSTAT1 ,"PMSTAT1"}, + {XDM_PERF_PMSTAT2 ,"PMSTAT2"}, + {XDM_PERF_PMSTAT3 ,"PMSTAT3"}, + {XDM_PERF_PMSTAT4 ,"PMSTAT4"}, + {XDM_PERF_PMSTAT5 ,"PMSTAT5"}, + {XDM_PERF_PMSTAT6 ,"PMSTAT6"}, + {XDM_PERF_PMSTAT7 ,"PMSTAT7"}, + + {XDM_MISC_PWRCTL ,"PWRCTL" }, + {XDM_MISC_PWRSTAT ,"PWRSTAT" }, + {XDM_MISC_ERISTAT ,"ERISTAT" }, + {XDM_MISC_DATETIME ,"DATETIME"}, + {XDM_MISC_UBID ,"UBID" }, + {XDM_MISC_CID ,"CID" }, + + {XDM_CS_ITCTRL ,"ITCTRL" }, + {XDM_CS_CLAIMSET ,"CLAIMSET" }, + {XDM_CS_CLAIMCLR ,"CLAIMCLR" }, + {XDM_CS_LOCK_ACCESS ,"LOCK_ACCESS"}, + {XDM_CS_LOCK_STATUS ,"LOCK_STATUS"}, + {XDM_CS_AUTH_STATUS ,"AUTH_STATUS"}, + {XDM_CS_DEV_ID ,"DEV_ID" }, + {XDM_CS_DEV_TYPE ,"DEV_TYPE" }, + {XDM_CS_PER_ID4 ,"PER_ID4" }, + {XDM_CS_PER_ID5 ,"PER_ID5" }, + {XDM_CS_PER_ID6 ,"PER_ID6" }, + {XDM_CS_PER_ID7 ,"PER_ID7" }, + {XDM_CS_PER_ID0 ,"PER_ID0" }, + {XDM_CS_PER_ID1 ,"PER_ID1" }, + {XDM_CS_PER_ID2 ,"PER_ID2" }, + {XDM_CS_PER_ID3 ,"PER_ID3" }, + {XDM_CS_COMP_ID0 ,"COMP_ID0" }, + {XDM_CS_COMP_ID1 ,"COMP_ID1" }, + {XDM_CS_COMP_ID2 ,"COMP_ID2" }, + {XDM_CS_COMP_ID3 ,"COMP_ID3" }, + {-1 ,"???" }, +}; +#endif + +#endif + +#endif /* _XDM_REGS_H_ */ diff --git a/components/esp32/include/xtensa/xmon.h b/components/esp32/include/xtensa/xmon.h new file mode 100755 index 0000000000..12a757a2c1 --- /dev/null +++ b/components/esp32/include/xtensa/xmon.h @@ -0,0 +1,97 @@ +/* xmon.h - XMON definitions + * + * $Id: //depot/rel/Eaglenest/Xtensa/OS/xmon/xmon.h#3 $ + * + * Copyright (c) 2001-2013 Tensilica Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY + * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +#ifndef __H_XMON +#define __H_XMON + +/* Default GDB packet size */ +#define GDB_PKT_SIZE 4096 + +/*XMON signals */ +#define XMON_SIGINT 2 /*target was interrupted */ +#define XMON_SIGILL 4 /*illegal instruction */ +#define XMON_SIGTRAP 5 /*general exception */ +#define XMON_SIGSEGV 11 /*page faults */ + + +/* Type of log message from XMON to the application */ +typedef enum { + XMON_LOG, + XMON_TRACE, + XMON_ERR, + XMON_APP, + XMON_GDB +} xmon_log_t; + +/* Return value type for xmon_proc() (see below) */ +typedef enum { + XMON_GDB_PEND, + XMON_GDB_PKT, + XMON_NOT_GDB +} xmon_gdb_pkt_t; + +#ifdef _cplusplus +extern "C" { +#endif + +/* + * THE FOLLOWING ROUTINES ARE USED BY USER + */ +extern int _xmon_init(char* gdbBuf, int gdbPktSize, + void(*xlog)(xmon_log_t type, const char* str)); +//Initialize GDB communication and logging to the main app. +//For the logging to work, xlog function needs to be provided. +//gdbBuf - pointer to a buffer XMON can use to comm. with GDB +//gdbPktSize - Size of the allocated buffer for GDB communication. +//xlog - logger handle. + + +extern void _xmon_close(void); +//Main application can detach from xmon at any time + + +extern xmon_gdb_pkt_t _xmon_proc(char); +// Give character to XMON to check if GDB message +// Application is supposed to accumulate all the +// character in case the recognition fails and chars +// have to be sent to the original handler +// Return: XMON_GDB_PEND - send me more chars +// XMON_GDB_PKT - GDB message confirmed, C) not +// XMON_NOT_GDB - not GDB message + + +/* + * THE FOLLOWING ROUTINES NEED TO BE PROVIDED BY USER + */ +extern int _xmon_in(); // wait for character from GDB +extern void _xmon_out(char); // output a character to GDB +extern int _xmon_flush(void); // flush output characters + +#ifdef _cplusplus +} +#endif + +#endif diff --git a/components/esp32/include/xtensa/xmp-library.h b/components/esp32/include/xtensa/xmp-library.h new file mode 100755 index 0000000000..624272077c --- /dev/null +++ b/components/esp32/include/xtensa/xmp-library.h @@ -0,0 +1,789 @@ +/* Customer ID=11656; Build=0x5f626; Copyright (c) 2008-2009 by Tensilica Inc. ALL RIGHTS RESERVED. + These coded instructions, statements, and computer programs are the + copyrighted works and confidential proprietary information of Tensilica Inc. + They may not be modified, copied, reproduced, distributed, or disclosed to + third parties in any manner, medium, or form, in whole or in part, without + the prior written consent of Tensilica Inc. */ + +#ifndef _XMP_LIBRARY_H +#define _XMP_LIBRARY_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include +#include +#include +#if XCHAL_HAVE_RELEASE_SYNC +#include +#endif +#if XCHAL_HAVE_EXTERN_REGS +#include +#endif +#include +#include + +#include "xtensa/system/mpsystem.h" + +/* + W A R N I N G: + + xmp library clients should treat all data structures in this file + as opaque. They are only public to enable users to declare them + statically. +*/ + + +/* ------------------------------------------------------------------------- + When using XMP on cache-incoherent systems, these macros are helpful + to ensure that you are not reading stale data, and to ensure that + the data you write makes it all the way back to main memory. + */ + +#if !XCHAL_DCACHE_IS_COHERENT +#define XMP_WRITE_BACK_ELEMENT(x) xthal_dcache_region_writeback((void *)x, sizeof(*x)) +#define XMP_INVALIDATE_ELEMENT(x) xthal_dcache_region_invalidate((void *)x, sizeof(*x)) +#define XMP_WRITE_BACK_INVALIDATE_ELEMENT(x) xthal_dcache_region_writeback_inv((void *)x, sizeof(*x)) +#define XMP_WRITE_BACK_ARRAY(x) xthal_dcache_region_writeback((void *)x, sizeof(x)) +#define XMP_INVALIDATE_ARRAY(x) xthal_dcache_region_invalidate((void *)x, sizeof(x)) +#define XMP_WRITE_BACK_INVALIDATE_ARRAY(x) xthal_dcache_region_writeback_inv((void *)x, sizeof(x)) +#define XMP_WRITE_BACK_ARRAY_ELEMENTS(x, num_elements) xthal_dcache_region_writeback((void *)x, sizeof(*x) * num_elements) +#define XMP_INVALIDATE_ARRAY_ELEMENTS(x, num_elements) xthal_dcache_region_invalidate((void *)x, sizeof(*x) * num_elements) +#define XMP_WRITE_BACK_INVALIDATE_ARRAY_ELEMENTS(x, num_elements) xthal_dcache_region_writeback_inv((void *)x, sizeof(*x) * num_elements) +#else +#define XMP_WRITE_BACK_ELEMENT(x) +#define XMP_INVALIDATE_ELEMENT(x) +#define XMP_WRITE_BACK_INVALIDATE_ELEMENT(x) +#define XMP_WRITE_BACK_ARRAY(x) +#define XMP_INVALIDATE_ARRAY(x) +#define XMP_WRITE_BACK_INVALIDATE_ARRAY(x) +#define XMP_WRITE_BACK_ARRAY_ELEMENTS(x, num_elements) +#define XMP_INVALIDATE_ARRAY_ELEMENTS(x, num_elements) +#define XMP_WRITE_BACK_INVALIDATE_ARRAY_ELEMENTS(x, num_elements) +#endif + +/* ------------------------------------------------------------------------- + Initialization, error codes, constants and house-keeping + + Every core should call xmp_init with the number of cores in the + system. + + xmp_init should be called before you use any global synchronization + primitive or shared data. + + Further, before you use a dynamically allocated synchronization + primitives, you need to both initialize it by calling the + xmp_*_init function, and you need to have called xmp_init, which + sets up interrupt handlers and interrupt routing. + + The second parameter sets the interprocessor interrupt + routing. Passing zero instructs the library to use the default + routing, which will be suitable for most users. + +*/ + +extern void xmp_init (int num_cores, unsigned int interrupt_routing); + + +/* If you want finer-grained control than that provided by xmp_init, + you can the functions below individually--however, this is more + inconvenient and requires greater understanding of the library's + internals. Don't use them directly unless you have a good reason. +*/ + +extern void xmp_unpack_shared (void); +extern void xmp_route_interrupts (unsigned int routing); + +#if XCHAL_HAVE_MP_INTERRUPTS +extern void xmp_enable_ipi_interrupts (void); + +/* Turn off certain things enabled by xmp_init */ +extern void xmp_disable_ipi_interrupts (void); +#endif + +extern void xmp_end (void); + +/* Only valid after xmp_init. */ +extern int xmp_num_cores (void); + +/* How many cycles should a core wait before rechecking a + synchronization variable? Higher values will reduce memory + transactions, but will also result in higher latency in returning + from synchronization. +*/ +extern void xmp_spin_wait_set_cycles (unsigned int limit); + +/* If you would prefer to provide your own spin wait function, + to go to sleep, etc. Declare a function of this type, then call + this function. */ +typedef void (*xmp_spin_wait_function_t)(void); +extern void xmp_spin_wait_set_function (xmp_spin_wait_function_t func); +extern void xmp_spin(void); + +#define XMP_NO_OWNER 0x07 +#define XMP_MUTEX_DESTROYED 0xFE +#define XMP_ERROR_FATAL 0xFD + +#define XMP_MAX_CORES 0x4 + + +static inline unsigned int xmp_prid (void) +{ +#if XCHAL_HAVE_PRID + return XT_RSR_PRID() & 0xFF; +#else + return 0; +#endif +} + + +/* ------------------------------------------------------------------------- + Tracing + + A core must set a trace_file if it wants any synchronization + tracing to occur. Sharing file descriptors among cores is very + messy, so don't do it. This, unfortunately, means that two cores + contending for a mutex are not able to trace to the same file. + + Any object (except the atomic integer) can have tracing off or on. +*/ + +extern void xmp_set_trace_file (FILE * file); +extern void xmp_trace (const char * fmt, ...); + + +/* ------------------------------------------------------------------------- + Memory Allocation Functions. + + These do what you would expect, only from shared memory instead of + private memory. +*/ + +#if XCHAL_DCACHE_IS_COHERENT +extern void * xmp_malloc (size_t size); +extern void * xmp_calloc (size_t nmemb, size_t size); +extern void xmp_free (void * ptr); +#endif +extern void * xmp_sbrk(int size); + +/* ------------------------------------------------------------------------- + xmp_atomic_int_t + + The most basic synchronization primitive in the xmp library. + Atomic ints are sharable among processors, and even interrupt + levels on the same processor. However, their semantics are fairly + rudimentary. All other primitives are based on these, therefore, + changing this implementation affects all other primitives. + +*/ + +typedef unsigned int xmp_atomic_int_t; + +static inline xmp_atomic_int_t +xmp_coherent_l32ai(xmp_atomic_int_t * address) +{ + XMP_INVALIDATE_ELEMENT (address); + return XT_L32AI(address, 0); +} + +static inline void +xmp_coherent_s32ri(xmp_atomic_int_t value, xmp_atomic_int_t * address) +{ + XT_S32RI (value, address, 0); + XMP_WRITE_BACK_ELEMENT (address); +} + +#define XMP_ATOMIC_INT_INITIALIZER(value) (value) + +/* xmp_atomic_int_init - Initialize an int prior to use + + Nonsynchronizing, Nonblocking + + Usage: + value - initial value + integer - points to an uninitialized integer + + On exit: + initialized to given value + + Errors: none +*/ + +static inline void +xmp_atomic_int_init (xmp_atomic_int_t * integer, int value) +{ + xmp_coherent_s32ri (value, integer); +} + + +/* xmp_atomic_int_value - Read the value + + Nonsynchronizing, Nonblocking + + Usage: + integer - points to an int + + Returns: + the value +*/ + +static inline int +xmp_atomic_int_value (xmp_atomic_int_t * integer) +{ + return xmp_coherent_l32ai (integer); +} + + +/* xmp_atomic_int_conditional_increment - Conditionally increment integer + + Synchronizing, nonblocking + + Usage: + integer - points to an initialized integer + amount - how much to increment + prev - believed value of the integer + eg: prev = xmp_atomic_int_value (integer); + success = xmp_atomic_int_increment (integer, 1, prev); + + Returns: current value of integer - user should check if it matches + the previous value of the integer. If it does, then the update + was successful. + +*/ + +#define USE_ASSEMBLY_IMPLEMENTATION 0 + +static inline int +xmp_atomic_int_conditional_increment (xmp_atomic_int_t * integer, int amount, int prev) +{ + int val; + int saved; + +#if USE_ASSEMBLY_IMPLEMENTATION + /* %0 = prev + %1 = saved + %2 = atomic integer pointer + %3 = amount + */ + + asm volatile ("wsr.scompare1 %0\n" + "mov %1, %0\n" + "add %0, %0, %3\n" + "s32c1i %0, %2, 0\n" + : "+&a" (prev), "+&a"(saved) : "a" (integer), "a" (amount)); + + return prev; + +#else + + XT_WSR_SCOMPARE1 (prev); + val = prev + amount; + saved = val; + XT_S32C1I (val, integer, 0); + + return val; +#endif +} + + +/* xmp_atomic_int_increment - Increment integer + + Synchronizing, blocking + + Usage: + integer - points to an initialized integer + amount - how much to increment + + Returns: new value of integer + +*/ + +static inline int +xmp_atomic_int_increment (xmp_atomic_int_t * integer, int amount) +{ + int val; + int saved; +#if USE_ASSEMBLY_IMPLEMENTATION + /* %0 = val + %1 = saved + %2 = atomic integer pointer + %3 = amount + */ + + asm volatile ("l32ai %0, %2, 0\n" + "1:\n" + "wsr.scompare1 %0\n" + "mov %1, %0\n" + "add %0, %0, %3\n" + "s32c1i %0, %2, 0\n" + "bne %0, %1, 1b\n" + : "+&a" (val), "+&a"(saved) : "a" (integer), "a" (amount)); +#else + /* Accurately naming "val" is tricky. Sometimes it will be what we + want to be the new value, but sometimes it contains the value + that is currently at the location. */ + + /* Load location's current value */ + val = xmp_coherent_l32ai (integer); + + do { + XT_WSR_SCOMPARE1 (val); + saved = val; + /* Change it to what we would like to store there--"new_val" */ + val = val + amount; + /* Possibly store new_val, but reload location's current value no + matter what. */ + XT_S32C1I (val, integer, 0); + if (val != saved) + xmp_spin(); + } while (val != saved); + +#endif + return val + amount; +} + + +/* xmp_atomic_int_conditional_set - Set the value of an atomic integer + + Synchronizing, nonblocking + + Usage: + integer - points to an initialized integer + from - believed value of the integer + eg: prev = xmp_atomic_int_value (integer); + success = xmp_atomic_int_conditional_set (integer, 1, prev); + to - new value + + Returns: current value of integer - user should check if it matches + the previous value of the integer. If it does, then the update + was successful. + +*/ + +static inline int +xmp_atomic_int_conditional_set (xmp_atomic_int_t * integer, int from, int to) +{ + int val; + + /* Don't even try to update if the integer's value isn't what we + think it should be. This prevents acquiring this cache-line for + writing and therefore prevents bus transactions when various + cores contend. */ + val = xmp_coherent_l32ai(integer); + if (val == from) { + XT_WSR_SCOMPARE1 (from); + val = to; + /* Possibly store to, but reload location's current value no + matter what. */ + XT_S32C1I (val, integer, 0); + } + return val; +} + + +/* Macros to implement trivial spin locks. These are very primitive, but + can be useful when you don't need the higher-overhead synchronization. + + To use an xmp_atomic_int_t as a trivial spin lock, you should + initialize it to zero first. +*/ + +#define XMP_SIMPLE_SPINLOCK_ACQUIRE(atomic_int_ptr) \ + { while (xmp_atomic_int_conditional_set (atomic_int_ptr, 0, xmp_prid() + 1) != 0) \ + xmp_spin(); } +#define XMP_SIMPLE_SPINLOCK_RELEASE(atomic_int_ptr) \ + { while (xmp_atomic_int_conditional_set (atomic_int_ptr, xmp_prid() + 1, 0) != xmp_prid() + 1) \ + xmp_spin(); } + +#define XMP_SIMPLE_SPINLOCK_OWNER(atomic_int_ptr) (xmp_atomic_int_value(atomic_int_ptr) - 1) + + +/* ------------------------------------------------------------------------- + xmp_mutex_t - An even higher-level data structure to enforce + mutual exclusion between cores. A core which waits on a mutex might + sleep with a waiti and be interrupted by an interrupt. + + Mutexes can be normal or recursive. For a normal mutex, a core + attempting to acquire a mutex it already holds will result in + deadlock. For a recursive mutex, a core will succeed in acquiring a + mutex it already holds, and must release it as many times as it + acquired it. + + Mutexes are not sharable between interrupt levels--because + ownership is tracked by core, not thread. + + Like all xmp data structures, an object of type xmp_mutex_t + should be treated by the programmer as opaque. They are only + public in this header file to allow them to be declared statically. + + For configurations with 16-byte cache lines, this has the most + frequently used and changed data in the first line. + +*/ + +#if XCHAL_DCACHE_IS_COHERENT +typedef struct xmp_mutex_t { + xmp_atomic_int_t qlock; + unsigned int qhead; + unsigned int qtail; + unsigned char queue[XMP_MAX_CORES]; + unsigned short held; + + unsigned char owner; + unsigned char recursive : 1; + unsigned char trace : 1; + unsigned char system : 1; + unsigned char unused : 5; + const char * name; +} xmp_mutex_t __attribute__ ((aligned (XMP_MAX_DCACHE_LINESIZE))); + + +#define XMP_MUTEX_INITIALIZER(name) \ + { 0, 0, -1, {XMP_NO_OWNER, XMP_NO_OWNER, XMP_NO_OWNER, XMP_NO_OWNER}, \ + 0, XMP_NO_OWNER, XMP_MUTEX_FLAG_NORMAL, 0, 0, 0, name } + +#define XMP_RECURSIVE_MUTEX_INITIALIZER(name) \ + { 0, 0, -1, {XMP_NO_OWNER, XMP_NO_OWNER, XMP_NO_OWNER, XMP_NO_OWNER}, \ + 0, XMP_NO_OWNER, XMP_MUTEX_FLAG_RECURSIVE, 0, 0, 0, name } + +#define XMP_MUTEX_FLAG_NORMAL 0 +#define XMP_MUTEX_FLAG_RECURSIVE 1 + +#define XMP_MUTEX_ACQUIRE_FAILED -1 +#define XMP_MUTEX_ERROR_DESTROY_OWNED -2 +#define XMP_MUTEX_ERROR_NOT_OWNED -3 +#define XMP_MUTEX_ERROR_ALREADY_OWNED -4 + +/* + xmp_mutex_init + + Nonsynchronizing + Nonblocking + + Usage: + mutex - points to an uninitialized mutex + name - name if you want one, NULL if not. + recursive - use recursive semantices + + Returns + zero on success (always succeeds) + +*/ + +extern int xmp_mutex_init (xmp_mutex_t * mutex, + const char * name, + unsigned int recursive); + +/* + int xmp_mutex_destroy (xmp_mutex_t * mutex); + + Synchronizing - will fail if mutex is held by anyone -- including + current processor + Nonblocking + + Usage: + mutex - points to a mutex + + Returns + zero on success + non-zero if mutex is held +*/ + +extern int xmp_mutex_destroy (xmp_mutex_t * mutex); + + +/* + xmp_mutex_lock -- Synchronizing + xmp_mutex_trylock + + Usage: + mutex - points to a mutex + + Returns + zero on success +*/ + +extern int xmp_mutex_lock (xmp_mutex_t * mutex); +extern int xmp_mutex_trylock (xmp_mutex_t * mutex); + + +/* + xmp_mutex_unlock + + Synchronizing + Nonblocking + + Usage: + mutex - points to a mutex + + Returns + zero on success - mutex is released + non-zero on failure - mutex is owned by another core + - prid of processor that does own it + note that by the time this function + returns, the owner of the core may + have changed. +*/ + +extern int xmp_mutex_unlock (xmp_mutex_t * mutex); + + +/* + xmp_mutex_name + + Nonsynchronizing + Nonblocking + + Usage: + mutex - points to a mutex + + Returns the name of the given mutex, which may be NULL. + +*/ + +const char * xmp_mutex_name (const xmp_mutex_t * mutex); + + +/* + xmp_mutex_trace_on + xmp_mutex_trace_off + + Nonsynchronizing + Nonblocking + + Turn off and on tracing for the mutex. + + These functions are only present in the debug version of the library. +*/ + +extern void xmp_mutex_trace_on (xmp_mutex_t * mutex); +extern void xmp_mutex_trace_off (xmp_mutex_t * mutex); + + +/* ------------------------------------------------------------------------- + xmp_condition_t + + Condition Variables following Mesa semantics. + + Condition variables are not sharable among interrupt levels. + +*/ + + +typedef struct xmp_condition_t { + unsigned int qhead; + unsigned int qtail; + unsigned char queue[XMP_MAX_CORES]; + unsigned int waiting[XMP_MAX_CORES]; + + unsigned char trace : 1; + unsigned char unused : 7; + const char * name; +} xmp_condition_t __attribute__ ((aligned (XMP_MAX_DCACHE_LINESIZE))); + + +#define XMP_CONDITION_INITIALIZER(name) \ + { 0, -1, {XMP_NO_OWNER, XMP_NO_OWNER, XMP_NO_OWNER, XMP_NO_OWNER}, \ + {0, 0, 0, 0}, 0, 0, name} + + +/* xmp_condition_init - Initialize a condition variable + + Nonsynchronizing, Nonblocking + + Usage: + condition - pointer to an xmp_condition_t + + On exit: + condition initialized + + Errors: none +*/ + +extern int xmp_condition_init (xmp_condition_t * condition, + const char * name); +extern int xmp_condition_destroy (xmp_condition_t * condition); + + +/* xmp_condition_wait - Wait for a condition variable + + Synchronizing, blocking + + Usage: + condition - pointer to an xmp_condition_t + mutex - pointer to an xmp_mutex_t already acquired by the calling + process + + Errors: if the mutex isn't held by this core +*/ + +extern int xmp_condition_wait (xmp_condition_t * condition, + xmp_mutex_t * mutex); + +/* xmp_condition_signal + + - Signal the first (if any) core waiting on a condition variable + + You must hold the mutex you passed to xmp_condition_wait before + calling this function. + + Synchronizing, nonblocking + + Usage: + condition - pointer to an xmp_condition_t + + Errors: none +*/ + +extern int xmp_condition_signal (xmp_condition_t * condition); + + +/* xmp_condition_broadcast + + - Signal all cores waiting on a condition variable + + Synchronizing, nonblocking + + You must hold the mutex you passed to xmp_condition_wait before + calling this function. + + Usage: + condition - pointer to an xmp_condition_t + + Errors: none +*/ + +extern int xmp_condition_broadcast (xmp_condition_t * condition); + + +static inline const char * xmp_condition_name (const xmp_condition_t * condition) +{ + return condition->name; +} + +/* + xmp_condition_trace_on + xmp_condition_trace_off + + Nonsynchronizing + Nonblocking + + Turn off and on statistics and tracing for the condition. For + tracing you must also set a trace file for the core. + + These functions are only present in the debug-version of the library. +*/ + +extern void xmp_condition_trace_on (xmp_condition_t * condition); +extern void xmp_condition_trace_off (xmp_condition_t * condition); + +#endif /* XCHAL_DCACHE_IS_COHERENT */ + +/* ------------------------------------------------------------------------- + xmp_barrier_t + + Classic barriers that stop any core from continuing until a + specified number of cores reach that point. Once the barrier allows + cores through, the barrier is reset and will stop cores from + progressing again. + + Barriers are not sharable among interrupt levels. + +*/ + + +typedef struct xmp_barrier_t +{ + xmp_atomic_int_t count; + xmp_atomic_int_t state; + xmp_atomic_int_t sleeping; + unsigned short num_cores; + unsigned short trace : 1; + unsigned short system : 1; + const char * name; +} xmp_barrier_t __attribute__ ((aligned (XMP_MAX_DCACHE_LINESIZE))); + +#define XMP_BARRIER_INITIALIZER(number, name) \ + { 0, 0, 0, number, 0, 0, name } + + +/* xmp_barrier_init - Initialize a barrier + + Nonsynchronizing, Nonblocking + + Usage: + barrier - pointer to an xmp_barrier_t + num_cores - number of cores needed to arrive at the + barrier before any are allowed through + On exit: + barrier initialized + + Always returns zero. + + Errors: none +*/ + +extern int xmp_barrier_init (xmp_barrier_t * barrier, int num_cores, + const char * name); + + +/* xmp_barrier_wait - Wait on a barrier + + Nonsynchronizing, Nonblocking + + Usage: + barrier - pointer to an xmp_barrier_t + On exit: + Enough cores (as determined at the barrier's initialization) + have reached the barrier. + + Errors: none +*/ + +extern int xmp_barrier_wait (xmp_barrier_t * barrier); + + +static inline const char * xmp_barrier_name (const xmp_barrier_t * barrier) +{ + return barrier->name; +} + + +/* + xmp_barrier_trace_on + xmp_barrier_trace_off + + Nonsynchronizing + Nonblocking + + Turn on and off tracing for the barrier. For + tracing you must also set a trace file for the core. + + These functions are only present in the debug-version of the library. +*/ + +extern void xmp_barrier_trace_on (xmp_barrier_t * barrier); +extern void xmp_barrier_trace_off (xmp_barrier_t * barrier); + + +/* ------------------------------------------------------------------------- + Portions of the library that are internal, but belong here for + convenience. +*/ + +extern xmp_atomic_int_t _ResetSync; + +static inline void +xmp_initial_sync (int num_cores) +{ + xmp_atomic_int_increment (&_ResetSync, 1); + while (xmp_coherent_l32ai (&_ResetSync) != num_cores) + xmp_spin (); +} + +#ifdef __cplusplus +} +#endif + +#endif /* _XMP_LIBRARY_H */ diff --git a/components/esp32/include/xtensa/xos.h b/components/esp32/include/xtensa/xos.h new file mode 100755 index 0000000000..883a9c975a --- /dev/null +++ b/components/esp32/include/xtensa/xos.h @@ -0,0 +1,524 @@ +/** @file */ + +// xos.h - XOS API interface and data structures visible to user code. + +// Copyright (c) 2003-2015 Cadence Design Systems, Inc. +// +// Permission is hereby granted, free of charge, to any person obtaining +// a copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to +// permit persons to whom the Software is furnished to do so, subject to +// the following conditions: +// +// The above copyright notice and this permission notice shall be included +// in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +// CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +// SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + + +#ifndef __XOS_H__ +#define __XOS_H__ + +#ifdef __cplusplus +extern "C" { +#endif + + +#include "xos_types.h" + +#include +#if XCHAL_HAVE_INTERRUPTS +#include +#include +#endif + +#include "xos_common.h" +#include "xos_errors.h" +#include "xos_regaccess.h" + + +//----------------------------------------------------------------------------- +// Convert x into a literal string. +//----------------------------------------------------------------------------- +#define _XOS_STR(x) __XOS_STR(x) +#define __XOS_STR(x) #x + + +//----------------------------------------------------------------------------- +// XOS version. +//----------------------------------------------------------------------------- +#define XOS_VERSION_MAJOR 1 +#define XOS_VERSION_MINOR 10 +#define XOS_VERSION_STRING "1.10" ///< XOS version string. + + +//----------------------------------------------------------------------------- +// Runtime error handling. +//----------------------------------------------------------------------------- + + +//----------------------------------------------------------------------------- +/// +/// Reports a fatal error and halts XOS operation, i.e. halts the system. This +/// function will call a user-registered error handler (if one has been set) +/// and then halt the system. The user handler may do system-specific things +/// such as record the error reason in nonvolatile memory etc. +/// +/// \param errcode Error code. May be any user defined value < 0. +/// Values >=0 are reserved for use by the system. +/// +/// \param errmsg Optional text string describing the error. +/// +/// \return This function does not return. +/// +//----------------------------------------------------------------------------- +void +xos_fatal_error(int32_t errcode, const char * errmsg); + + +#if XOS_DEBUG + +// Do not call directly. +void +xos_assert(const char * file, int32_t line); + +//----------------------------------------------------------------------------- +/// +/// Check condition and fail if condition expression is false. +/// In debug builds, an assertion failure will cause a fatal error to be +/// reported. In non-debug builds, assertions are compiled out. +/// +/// NOTE: Remember that any code in XOS_ASSERT() statements gets compiled out +/// for non-debug builds. +/// +//----------------------------------------------------------------------------- + +#define XOS_ASSERT(expr) if ((expr) == 0) xos_assert(__FILE__, __LINE__) + +#else + +#define XOS_ASSERT(expr) + +#endif + + +//----------------------------------------------------------------------------- +/// +/// Interrupt handler function pointer type. +/// +//----------------------------------------------------------------------------- +typedef void (XosIntFunc)(void * arg); + +//----------------------------------------------------------------------------- +/// +/// Print handler function pointer type. +/// +//----------------------------------------------------------------------------- +typedef int32_t (XosPrintFunc)(void * arg, const char * fmt, ...); + +//----------------------------------------------------------------------------- +/// +/// Fatal error handler function pointer type. +/// +//----------------------------------------------------------------------------- +typedef void (XosFatalErrFunc)(int32_t errcode, const char * errmsg); + +//----------------------------------------------------------------------------- +/// +/// Exception handler function pointer type. +/// +//----------------------------------------------------------------------------- +typedef void (XosExcHandlerFunc)(XosExcFrame * frame); + + +//----------------------------------------------------------------------------- +/// +/// Install a user defined exception handler for the specified exception type. +/// This will override the default XOS exception handler. The handler is a C +/// function that is passed one parameter -- a pointer to the exception frame. +/// The exception frame is allocated on the stack of the thread that caused the +/// exception, and contains saved state and exception information. For details +/// of the exception frame see the structure XosExcFrame. +/// +/// \param exc Exception type (number) to override. The exception +/// numbers are enumerated in . +/// +/// \param handler Pointer to handler function to be installed. +/// To revert to the default handler, pass NULL. +/// +/// \return Returns a pointer to previous handler installed, if any. +/// +//----------------------------------------------------------------------------- +XosExcHandlerFunc * +xos_register_exception_handler(int32_t exc, XosExcHandlerFunc * handler); + + +//----------------------------------------------------------------------------- +/// +/// Install a user defined fatal error handler. This function will be called if +/// a fatal error is reported either by user code or by XOS itself. It will be +/// passed the same arguments that are passed to xos_fatal_error(). +/// +/// The handler need not return. It should make minimal assumptions about the +/// state of the system. In particular, it should not assume that further XOS +/// system calls will succeed. +/// +/// \param handler Pointer to handler function to be installed. +/// +/// \return Returns a pointer to previous handler installed, if any. +/// +//----------------------------------------------------------------------------- +XosFatalErrFunc * +xos_register_fatal_error_handler(XosFatalErrFunc * handler); + + +#ifdef _XOS_INCLUDE_INTERNAL_ +# include "xos_internal.h" +#endif + + +#include "xos_thread.h" +#include "xos_timer.h" +#include "xos_cond.h" +#include "xos_event.h" +#include "xos_mutex.h" +#include "xos_msgq.h" +#include "xos_semaphore.h" +#include "xos_stopwatch.h" + + +//----------------------------------------------------------------------------- +/// +/// Register a handler function to call when interrupt "num" occurs. +/// +/// For level-triggered and timer interrupts, the handler function will have +/// to clear the source of the interrupt before returning, to avoid infinitely +/// retaking the interrupt. Edge-triggered and software interrupts are +/// automatically cleared by the OS interrupt dispatcher (see xos_handlers.S). +/// +/// \param num Xtensa internal interrupt number (0..31). To +/// refer to a specific external interrupt number +/// (BInterrupt pin), use HAL macro XCHAL_EXTINTx_NUM +/// where 'x' is the external number. +/// +/// \param handler Pointer to handler function. +/// +/// \param arg Argument passed to handler. +/// +/// \return Returns XOS_OK if successful, else error code. +/// +//----------------------------------------------------------------------------- +int32_t +xos_register_interrupt_handler(int32_t num, XosIntFunc * handler, void * arg); + + +//----------------------------------------------------------------------------- +/// +/// Unregister a handler function for interrupt "num". If no handler was +/// installed, this function will have no effect. +/// +/// \param num Xtensa internal interrupt number (0..31). To +/// refer to a specific external interrupt number +/// (BInterrupt pin), use HAL macro XCHAL_EXTINTx_NUM +/// where 'x' is the external number. +/// +/// \return Returns XOS_OK if successful, else error code. +/// +//----------------------------------------------------------------------------- +int32_t +xos_unregister_interrupt_handler(int32_t num); + + +//----------------------------------------------------------------------------- +/// +/// Register a high priority interrupt handler for interrupt level "level". +/// +/// Unlike low and medium priority interrupt handlers, high priority handlers +/// are not installed for a specific interrupt number, but for an interrupt +/// level. The level must be above XCHAL_EXCM_LEVEL. The handler function must +/// be written in assembly since C handlers are not supported for levels above +/// XCHAL_EXCM_LEVEL. The handler function must preserve all registers except +/// a0, and must return to the dispatcher via a "ret" instruction, not "rfi". +/// +/// NOTE: This method of dispatch takes a few cycles of overhead. If you wish +/// to save even these cycles, then you can define your own dispatch function +/// to override the built-in dispatcher. See xos_handlers.S for more details. +/// +/// \param level The interrupt level to be handled. +/// +/// \param handler Pointer to handler function. +/// +/// \return Returns XOS_OK if successful, else error code. +/// +//----------------------------------------------------------------------------- +int32_t +xos_register_hp_interrupt_handler(int32_t level, void * handler); + + +//----------------------------------------------------------------------------- +/// +/// Enable a specific interrupt, by interrupt number. +/// The state (enabled vs. disabled) of individual interrupts is global, i.e. +/// not associated with any specific thread. Depending on system options and +/// implementation, this state may be stored in one of two ways: +/// - directly in the INTENABLE register, or +/// - in a global variable (this is generally the case when INTENABLE is used +/// not just to control what interrupts are enabled globally, but also for +/// software interrupt prioritization within an interrupt level, effectively +/// providing finer grained levels; in this case XOS takes care to update +/// INTENABLE whenever either the global enabled-state variable or the +/// per-thread fine-grained-level variable change). +/// Thus it is best to never access the INTENABLE register directly. +/// +/// To modify thread-specific interrupt priority level, use one of: +/// - xos_set_int_pri_level() +/// - xos_restore_int_pri_level() +/// - xos_disable_interrupts() +/// - xos_restore_interrupts() +/// +/// NOTE: To refer to a specific external interrupt number (BInterrupt pin), +/// use HAL macro XCHAL_EXTINTx_NUM where 'x' is the external interrupt +/// number. For example, to enable external interrupt 3 (BInterrupt[3]), +/// you can use: +/// +/// xos_interrupt_enable( XCHAL_EXTINT3_NUM ); +/// +/// \param intnum Interrupt number to enable. Must range between 0-31. +/// +/// \return Returns nothing. +/// +//----------------------------------------------------------------------------- +void +xos_interrupt_enable(uint32_t intnum); + + +//----------------------------------------------------------------------------- +/// +/// Disable a specific individual interrupt, by interrupt number. +/// +/// This is the counterpart to xos_interrupt_enable(). See the description +/// of xos_interrupt_enable() for further comments and notes. +/// +/// \param intnum Interrupt number to disable. Must range between 0-31. +/// +/// \return Returns nothing. +/// +//----------------------------------------------------------------------------- +void +xos_interrupt_disable(uint32_t intnum); + + +//----------------------------------------------------------------------------- +/// +/// Get the CPU's current interrupt priority level. Interrupts at or below this +/// priority level are blocked. +/// +/// \return Returns the current IPL, ranging from 0 to XCHAL_NUM_INTLEVELS. +/// +//----------------------------------------------------------------------------- +static inline uint32_t +xos_get_int_pri_level(void) +{ +#if XCHAL_HAVE_INTERRUPTS + return XT_RSR_PS() & 0xF; +#else + return 0; +#endif +} + + +//----------------------------------------------------------------------------- +/// +/// Set the CPU's interrupt priority level to the specified level, but only if +/// the current IPL is below the one requested. This function will never cause +/// the interrupt priority level to be lowered from the current level. +/// Call this function to block interrupts at or below the specified priority +/// level. +/// +/// When setting the IPL temporarily (such as in a critical section), call +/// xos_set_int_pri_level(), execute the critical code section, and then call +/// xos_restore_int_pri_level(). +/// +/// The interrupt priority level is part of the thread context, so it is saved +/// and restored across context switches. To enable and disable individual +/// interrupts globally, use the functions xos_interrupt_enable() and +/// xos_interrupt_disable() instead. +/// +/// NOTE: It is usually not required to disable interrupts at a level higher +/// than that of the highest priority interrupt that interacts with the OS +/// (i.e. calls into XOS such that threads may be woken / blocked / +/// reprioritized / switched, or otherwise access XOS data structures). +/// In XOS, that maximum level is XOS_MAX_OS_INTLEVEL, which defaults to +/// XCHAL_EXCM_LEVEL. This may be modified by editing xos_params.h and +/// rebuilding XOS. +/// +/// \param level The new interrupt priority level (IPL). +/// +/// \return Returns a value that can be used to restore the previous +/// priority level by calling xos_restore_int_pri_level(). This +/// value should be treated as opaque by application code, and +/// should be passed unchanged to the restore function. +/// +//----------------------------------------------------------------------------- +__attribute__((always_inline)) +static inline uint32_t +xos_set_int_pri_level(uint32_t level) +{ +#if XCHAL_HAVE_INTERRUPTS +#pragma no_reorder + uint32_t ps = XT_RSR_PS(); + + if (level > (ps & 0xF)) { + level = (ps & ~0xF) | level; + XT_WSR_PS(level); + XT_RSYNC(); + } + + return ps; +#else + return 0; +#endif +} + + +//----------------------------------------------------------------------------- +/// +/// Restores the CPU to a previously saved interrupt priority level. This level +/// must have been obtained by calling xos_set_int_pri_level(). +/// +/// \param oldval Return value from xos_set_int_pri_level(). +/// +/// \return Returns nothing. +/// +//----------------------------------------------------------------------------- +__attribute__((always_inline)) +static inline void +xos_restore_int_pri_level(const uint32_t oldval) +{ +#if XCHAL_HAVE_INTERRUPTS +#pragma no_reorder + XT_WSR_PS(oldval); + XT_RSYNC(); +#else + // Nothing +#endif +} + + +//----------------------------------------------------------------------------- +/// +/// Disable all interrupts that can interact directly with the OS. This is a +/// convenience function, shorthand for setting the IPL to XOS_MAX_OS_INTLEVEL. +/// +/// Returns: A value that can be used to restore the previous priority level +/// by calling xos_restore_interrupts(). This value should be treated as +/// opaque by application code, and should be passed unchanged to the restore +/// function. +/// +//----------------------------------------------------------------------------- +static inline uint32_t +xos_disable_interrupts(void) +{ + return xos_set_int_pri_level(XOS_MAX_OS_INTLEVEL); +} + + +//----------------------------------------------------------------------------- +/// +/// Restore the CPU's previously saved interrupt status. This is a convenience +/// function, the counterpart to xos_disable_interrupts(). +/// +/// \return rval Return value from xos_disable_interrupts(). +/// +/// \return Returns nothing. +/// +//----------------------------------------------------------------------------- +static inline void +xos_restore_interrupts(uint32_t rval) +{ + xos_restore_int_pri_level(rval); +} + + +#ifdef _XOS_INCLUDE_INTERNAL_ + +//----------------------------------------------------------------------------- +// Enter an OS critical section, i.e. get exclusive access to OS critical +// state and data structures. Code that manipulates the state of OS objects +// or modifies internal OS state must call this function first, to ensure +// that it has exclusive access. On a single-core system, this is equivalent +// to blocking all interrupts that can interact directly with the OS, i.e. +// all interrupts at or below XOS_MAX_OS_INTLEVEL. In a multi-core system +// this is likely to be implemented differently to achieve the same effect. +// +// Returns: A value that is to be used to restore the state of the CPU when +// exiting the critical section. This must be treated as opaque and passed +// unmodified to xos_critical_exit(). +// +// NOTE: This function is meant for use in OS code, not in applications. +//----------------------------------------------------------------------------- +__attribute__((always_inline)) +static inline uint32_t +xos_critical_enter(void) +{ +#if XCHAL_HAVE_INTERRUPTS + // This function cannot be called by high-level interrupt handlers, + // i.e. it can never be called with intlevel > XOS_MAX_OS_INTLEVEL. + // So, we do not need to check current intlevel because we will not + // ever be lowering it by setting it to XOS_MAX_OS_INTLEVEL. + // NOTE: sync after RSIL not needed. + return XT_RSIL(XOS_MAX_OS_INTLEVEL); +#else + return 0; +#endif +} + + +//----------------------------------------------------------------------------- +// Exit an OS critical section and restore CPU state. See the documentation +// for xos_critical_enter(). +// +// cflags Return value from xos_critical_enter(). +// Must be treated as an opaque value. +// +// Returns: Nothing. +// +// NOTE: This function is meant for use in OS code, not in applications. +//----------------------------------------------------------------------------- +__attribute__((always_inline)) +static inline void +xos_critical_exit(uint32_t cflags) +{ + xos_restore_int_pri_level(cflags); +} + +#endif // _XOS_INCLUDE_INTERNAL_ + + +// This file uses things defined above +#include "xos_syslog.h" + + +// Misc + +//----------------------------------------------------------------------------- +// Helper function to list all threads in system. Useful for debug. +//----------------------------------------------------------------------------- +void +xos_display_threads(void * arg, XosPrintFunc * print_fn); + + +#ifdef __cplusplus +} +#endif + +#endif // __XOS_H__ + diff --git a/components/esp32/include/xtensa/xos_common.h b/components/esp32/include/xtensa/xos_common.h new file mode 100755 index 0000000000..647cb7f457 --- /dev/null +++ b/components/esp32/include/xtensa/xos_common.h @@ -0,0 +1,362 @@ + +// xos_common.h - Macros and definitions common to C and assembly code. + +// Copyright (c) 2003-2015 Cadence Design Systems, Inc. +// +// Permission is hereby granted, free of charge, to any person obtaining +// a copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to +// permit persons to whom the Software is furnished to do so, subject to +// the following conditions: +// +// The above copyright notice and this permission notice shall be included +// in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +// CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +// SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + + +#ifndef __XOS_COMMON_H__ +#define __XOS_COMMON_H__ + +#ifdef __cplusplus +extern "C" { +#endif + + +#include +#include +#include + +#include "xos_params.h" + + +//----------------------------------------------------------------------------- +// Macros that help define structures for both C and assembler. +// These are somewhat different from the XTOS version in xtruntime-frames.h. +//----------------------------------------------------------------------------- +#if defined(_ASMLANGUAGE) || defined(__ASSEMBLER__) + +#define STRUCT_BEGIN .pushsection .text; .struct 0 +#define STRUCT_FIELD(ctype,size,asname,name) asname: .space size +#define STRUCT_AFIELD(ctype,size,asname,name,n) asname: .space (size)*(n) +#define STRUCT_END(sname) sname##Size:; .popsection + +#else + +#define STRUCT_BEGIN typedef struct { +#define STRUCT_FIELD(ctype,size,asname,name) ctype name; +#define STRUCT_AFIELD(ctype,size,asname,name,n) ctype name[n]; +#define STRUCT_END(sname) } sname; + +#endif //_ASMLANGUAGE || __ASSEMBLER__ + + +//----------------------------------------------------------------------------- +// Offsets relative to xos_globals. +//----------------------------------------------------------------------------- +#define XOS_INTLEVEL_MASK 0 // offset to the level mask +#define XOS_INTENABLE_MASK 4 // offset to the enable mask +#define XOS_CURR_THREADPTR 8 // offset to the current thread ptr +#define XOS_NEXT_THREADPTR 12 // offset to the next thread ptr +#define XOS_INTERRUPT_TABLE 16 // offset to the interrupt table + + +//----------------------------------------------------------------------------- +// Offsets for xos_interrupt_table[] entries. +//----------------------------------------------------------------------------- +#define XOS_INTTAB_HANDLER (XOS_INTERRUPT_TABLE+0) // ofs to interrupt handler +#define XOS_INTTAB_ARG (XOS_INTERRUPT_TABLE+4) // ofs to interrupt handler arg +#define XOS_INTTAB_PS (XOS_INTERRUPT_TABLE+8) // (hwpri) PS for interrupt level +#define XOS_INTTAB_LEVEL (XOS_INTERRUPT_TABLE+8) // (swpri) interrupt level (1..7) +#define XOS_INTTAB_PRI (XOS_INTERRUPT_TABLE+9) // (swpri) interrupt priority (0..255) +#define XOS_INTTAB_PRIMASK (XOS_INTERRUPT_TABLE+12) // (swpri) mask of higher pri. interrupts + + +//----------------------------------------------------------------------------- +// Exception/interrupt stack frame layout for a pre-empted thread +// tcb->resume_fn == &xos_resume_preempted_thread). +// Pointed to by thread->esf. Located just below thread's current stack ptr. +// Thread's a1 == thread->esf + XosExcFrameSize. +// NOTE: exception frame size is a multiple of 16. +//----------------------------------------------------------------------------- +STRUCT_BEGIN +STRUCT_AFIELD(long,4,FRAME_AREG,areg, 12) // a4-a15 (offsets 0 thru 44) + // (a1 is computed, a0,a2-a3 are in s32e range of a1) +//#if XCHAL_HAVE_LOOPS +STRUCT_FIELD (long,4,FRAME_LBEG,lbeg) +STRUCT_FIELD (long,4,FRAME_LEND,lend) +STRUCT_FIELD (long,4,FRAME_LCOUNT,lcount) +//#endif +//#if XCHAL_HAVE_MAC16 +STRUCT_FIELD (long,4,FRAME_ACCLO,acclo) +STRUCT_FIELD (char,1,FRAME_ACCHI,acchi) +//#endif +STRUCT_FIELD (char,1,FRAME_SAR,sar) +STRUCT_FIELD (short,2,FRAME_PAD0,pad0) // unused +STRUCT_FIELD (long,4,FRAME_EXCCAUSE,exccause) +STRUCT_FIELD (long,4,FRAME_EXCVADDR,excvaddr) +STRUCT_FIELD (long,4,FRAME_PAD1,pad1) // unused -- pad to make multiple of 16 bytes +STRUCT_FIELD (long,4,FRAME_PAD2,pad2) +STRUCT_FIELD (long,4,FRAME_PS,ps) // (XOS_FRAME_SIZE-44) in S32E range of end +STRUCT_FIELD (long,4,FRAME_PC,pc) // (XOS_FRAME_SIZE-40) in S32E range of end +STRUCT_FIELD (long,4,FRAME_A0,a0) +STRUCT_FIELD (long,4,FRAME_A2,a2) // (XOS_FRAME_SIZE-32) in S32E range of end +STRUCT_FIELD (long,4,FRAME_A3,a3) // (XOS_FRAME_SIZE-28) in S32E range of end +STRUCT_FIELD (long,4,FRAME_LEVELMASK,levelmask) // +STRUCT_FIELD (long,4,FRAME_NESTCHAIN,nestchain) // nested C function call chain ptr +// Caller's a0-a3 save area below SP. These fields MUST be the last ones in the +// struct so that they are guaranteed to be just under the original SP (before +// we allocate the exception frame). +STRUCT_AFIELD (long,4,FRAME_CWINSAVE,cwinsave, 4) // (XOS_FRAME_SIZE-16) +STRUCT_END(XosExcFrame) // NOTE: exception frame size is 128 + +#define FRAME_AR(x) (FRAME_AREG + x*4 - 16) + +#if defined(_ASMLANGUAGE) || defined(__ASSEMBLER__) +#define XOS_FRAME_SIZE XosExcFrameSize +#else +#define XOS_FRAME_SIZE sizeof(XosExcFrame) +#endif + + +//----------------------------------------------------------------------------- +// Stack frame layout for a cooperatively switched out thread +// (tcb->resume_fn == &xos_resume_cooperative_thread). +// Pointed to by thread->esf. This is a function frame. +// Thread's a1 == thread->esf. +//----------------------------------------------------------------------------- +STRUCT_BEGIN +STRUCT_FIELD (long,4,CFRAME_A0,a0) // return PC +STRUCT_FIELD (long,4,CFRAME_LEVELMASK,levelmask) +STRUCT_FIELD (long,4,CFRAME_PS,ps) +#ifdef __XTENSA_CALL0_ABI__ +STRUCT_FIELD (long,4,CFRAME_PAD0,pad0) +STRUCT_AFIELD(long,4,CFRAME_AREG,areg,4) // callee-saved regs a12-a15 +#endif +STRUCT_END(XosCoopFrame) + + +//----------------------------------------------------------------------------- +// Offsets into thread control block (must match xos_thread.h !!) +//----------------------------------------------------------------------------- +#define TCB_RESUME_FN 12 // ptr to thread resume asm sequence +#define TCB_STACK_ESF 16 // saved stack ptr (actually, ptr to ESF) +#define TCB_TIE_SAVE 20 // ptr to TIE save area +#define TCB_RETVALUE 24 // ptr to xos_block return value +#define TCB_STACK_END 36 // ptr to end of stack (thread's initial stack ptr) +#define TCB_STARTUP_ENTRY 40 // ptr to thread entry function +#define TCB_STARTUP_ARG 44 // ptr to thread entry function's arg +#define TCB_READY 48 // thread ready state (1 byte) +#define TCB_CLIB_PTR 108 // thread C lib context pointer + +#define TCB_RESUME_CCOUNT 116 // cycle count at last resume +#define TCB_CYCLE_COUNT 120 // number of cycles consumed +#define TCB_NORMAL_RESUMES 128 // number of cooperative/restart thread resumes +#define TCB_PREEMPT_RESUMES 132 // number of pre-emptive thread resumes + + +//----------------------------------------------------------------------------- +// Coprocessor state handling: +// The coprocessor state save area is allocated on the thread stack. The stack +// must be sized appropriately. Threads that do not use coprocessors need not +// allocate the storage area. +// +// Along with the save area for each coprocessor, two bitmasks with flags per +// coprocessor (laid out as in the CPENABLE reg) help manage context switching +// coprocessors as efficiently as possible: +// +// XT_CPENABLE +// The contents of a non-running thread's CPENABLE register. +// It represents the coprocessors owned (and whose state is still needed) +// by the thread. When a thread is preempted, its CPENABLE is saved here. +// When a thread solicits a context switch, its CPENABLE is cleared - the +// compiler has saved the (caller-saved) coprocessor state if needed. +// When a non-running thread loses ownership of a CP, its bit is cleared. +// When a thread runs, it's XT_CPENABLE is loaded into the CPENABLE reg. +// Avoids coprocessor exceptions when no change of ownership is needed. +// +// XT_CPSTORED +// A bitmask with the same layout as CPENABLE, a bit per coprocessor. +// Indicates whether the state of each coprocessor is saved in the state +// save area. When a thread enters the kernel, only the state of coprocs +// still enabled in CPENABLE is saved. When the coprocessor exception +// handler assigns ownership of a coprocessor to a thread, it restores +// the saved state only if this bit is set, and clears this bit. +// +// XT_CP_CS_ST +// A bitmask with the same layout as CPENABLE, a bit per co-processor. +// Indicates whether callee-saved state is saved in the state save area. +// Callee-saved state is saved by itself on a solicited context switch, +// and restored when needed by the coprocessor exception handler. +// Unsolicited switches will cause the entire coprocessor to be saved +// when necessary. +// +// XT_NCP_ASA +// Pointer to aligned save area for non-CP state. This is always filled +// in, even if there is no non-CP state to be saved. If there is no state +// to be saved then no space is actually allocated and this pointer is +// not used. +// +// XT_CP_ASA +// Pointer to aligned save area for coprocessor state. This is filled in +// only if coprocessor state is to be saved for the thread. Allows it to be +// aligned more than the overall save area (which might be stack-aligned +// or TCB-aligned). Especially relevant for Xtensa cores configured with a +// very large data path that requires alignment greater than 16 bytes (ABI +// stack alignment). +//----------------------------------------------------------------------------- + +#define ALIGNUP(n, val) (((val) + (n)-1) & -(n)) + +// Offsets of each coprocessor save area within the 'aligned save area'. +// The non-CP TIE state save area is at offset 0, so that it does not +// move around if some or all coprocessors are not to be saved. + +#define XT_NCP_SA 0 +#define XT_CP0_SA ALIGNUP(XCHAL_CP0_SA_ALIGN, XT_NCP_SA + XCHAL_NCP_SA_SIZE) +#define XT_CP1_SA ALIGNUP(XCHAL_CP1_SA_ALIGN, XT_CP0_SA + XCHAL_CP0_SA_SIZE) +#define XT_CP2_SA ALIGNUP(XCHAL_CP2_SA_ALIGN, XT_CP1_SA + XCHAL_CP1_SA_SIZE) +#define XT_CP3_SA ALIGNUP(XCHAL_CP3_SA_ALIGN, XT_CP2_SA + XCHAL_CP2_SA_SIZE) +#define XT_CP4_SA ALIGNUP(XCHAL_CP4_SA_ALIGN, XT_CP3_SA + XCHAL_CP3_SA_SIZE) +#define XT_CP5_SA ALIGNUP(XCHAL_CP5_SA_ALIGN, XT_CP4_SA + XCHAL_CP4_SA_SIZE) +#define XT_CP6_SA ALIGNUP(XCHAL_CP6_SA_ALIGN, XT_CP5_SA + XCHAL_CP5_SA_SIZE) +#define XT_CP7_SA ALIGNUP(XCHAL_CP7_SA_ALIGN, XT_CP6_SA + XCHAL_CP6_SA_SIZE) + +#define XT_TOT_SA_SIZE ALIGNUP(16, XT_CP7_SA + XCHAL_CP7_SA_SIZE) +#define XT_NCP_SA_SIZE XCHAL_NCP_SA_SIZE + +// Offsets within the overall save area + +#define XT_CPENABLE 0 // (2 bytes) coprocessors active for this thread +#define XT_CPSTORED 2 // (2 bytes) coprocessors saved for this thread +#define XT_CP_CS_ST 4 // (2 bytes) coprocessor callee-saved regs for this thread +#define XT_NCP_ASA 8 // (4 bytes) ptr to aligned save area for nonCP state +#define XT_CP_ASA 12 // (4 bytes) ptr to aligned save area for CP state + +// Overall size allows for dynamic alignment, make sure multiple of 4 bytes. +// XT_CP_SIZE - total space needed for all coprocessors + nonCP state + hdr +// XT_NCP_SIZE - total space needed for nonCP state + hdr + +#define XT_CP_SIZE ALIGNUP(4, (16 + XT_TOT_SA_SIZE + XCHAL_TOTAL_SA_ALIGN)) +#define XT_NCP_SIZE ALIGNUP(4, (16 + XT_NCP_SA_SIZE + XCHAL_TOTAL_SA_ALIGN)) + + +//----------------------------------------------------------------------------- +// Stack size computation. +// +// XOS_STACK_MIN_SIZE +// The minimum recommended stack size for any XOS thread. If you want to +// use a stack size smaller than this, you will have to verify that the +// smaller size will work under all operating conditions. +// +// XOS_STACK_MIN_SIZE_NO_CP +// The minimum recommended atack size for threads that will not use any +// coprocessor resources. No coprocessor state will be saved/restored +// for these threads. Non-CP TIE state will still be saved/restored. +// These threads must be created with the flag XOS_THREAD_NO_CP. +// +// XOS_STACK_EXTRA +// The amount of stack space used by the system to: +// - save coprocessor state +// - save non-coprocessor TIE state +// - allocate an interrupt/exception frame +// +// XOS_STACK_EXTRA_NO_CP +// The amount of stack space used by the system to: +// - save non-coprocessor TIE state +// - allocate an interrupt/exception frame +//----------------------------------------------------------------------------- + +#define XOS_STACK_EXTRA (XOS_FRAME_SIZE + XT_CP_SIZE) +#define XOS_STACK_EXTRA_NO_CP (XOS_FRAME_SIZE + XT_NCP_SIZE) + +#ifdef __XTENSA_CALL0_ABI__ +#define XOS_STACK_MIN_SIZE (XOS_STACK_EXTRA + 0x180) +#define XOS_STACK_MIN_SIZE_NO_CP (XOS_STACK_EXTRA_NO_CP + 0x180) +#else +#define XOS_STACK_MIN_SIZE (XOS_STACK_EXTRA + 0x200) +#define XOS_STACK_MIN_SIZE_NO_CP (XOS_STACK_EXTRA_NO_CP + 0x200) +#endif + + +//----------------------------------------------------------------------------- +// Items related to C library thread safety. +//----------------------------------------------------------------------------- +#if XOS_OPT_THREAD_SAFE_CLIB + +#if XSHAL_CLIB == XTHAL_CLIB_XCLIB + #if !defined(_ASMLANGUAGE) && !defined(__ASSEMBLER__) + #include + #endif + #define CLIB_THREAD_STRUCT struct _reent xclib_reent + #define GLOBAL_CLIB_PTR _reent_ptr +#elif XSHAL_CLIB == XTHAL_CLIB_NEWLIB + #if !defined(_ASMLANGUAGE) && !defined(__ASSEMBLER__) + #include + #endif + #define CLIB_THREAD_STRUCT struct _reent newlib_reent + #define GLOBAL_CLIB_PTR _impure_ptr +#else + #error The selected C runtime library is not thread safe. +#endif + +#endif // XOS_OPT_THREAD_SAFE_CLIB + + +//----------------------------------------------------------------------------- +// Check (MAX_OS_INTLEVEL,EXCM_LEVEL) +//----------------------------------------------------------------------------- +#if XOS_MAX_OS_INTLEVEL >= XCHAL_EXCM_LEVEL +# define XOS_MAX_OSEXCM_LEVEL XOS_MAX_OS_INTLEVEL +#else +# warning "XOS_MAX_OS_INTLEVEL was set below XCHAL_EXCM_LEVEL: this was never tested" +# define XOS_MAX_OSEXCM_LEVEL XCHAL_EXCM_LEVEL +#endif + + +//----------------------------------------------------------------------------- +// Detect if in interrupt context. +//----------------------------------------------------------------------------- +#if XCHAL_HAVE_INTERRUPTS +#define INTERRUPT_CONTEXT ((XT_RSR_PS() & PS_UM) == 0) +#else +#define INTERRUPT_CONTEXT 0 +#endif + + +//----------------------------------------------------------------------------- +// Xtensa tools version. +//----------------------------------------------------------------------------- +#if defined __XCC__ +#define XTTOOLS_VERSION (__XCC__ + __XCC_MINOR__) +#else +#define XTTOOLS_VERSION (0) +#endif + + +//----------------------------------------------------------------------------- +// Erratum workarounds. +//----------------------------------------------------------------------------- + +// Erratum 487 fix is available in version RF.3 onwards and RG.2 onwards. +#if ((__XCC__ == 11000) && (__XCC_MINOR__ >= 3)) || (XTTOOLS_VERSION >= 12002) +#define HWERR_487_FIX hw_erratum_487_fix +#else +#define HWERR_487_FIX +#endif + + +#ifdef __cplusplus +} +#endif + +#endif // __XOS_COMMON_H__ + diff --git a/components/esp32/include/xtensa/xos_cond.h b/components/esp32/include/xtensa/xos_cond.h new file mode 100755 index 0000000000..8116947d33 --- /dev/null +++ b/components/esp32/include/xtensa/xos_cond.h @@ -0,0 +1,145 @@ +/** @file */ + +// xos_cond.h - XOS condition variables API interface and data structures. + +// Copyright (c) 2003-2015 Cadence Design Systems, Inc. +// +// Permission is hereby granted, free of charge, to any person obtaining +// a copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to +// permit persons to whom the Software is furnished to do so, subject to +// the following conditions: +// +// The above copyright notice and this permission notice shall be included +// in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +// CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +// SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +// NOTE: Do not include this file directly in your application. Including +// xos.h will automatically include this file. + +#ifndef __XOS_COND_H__ +#define __XOS_COND_H__ + +#include "xos_types.h" + +#ifdef __cplusplus +extern "C" { +#endif + + +//----------------------------------------------------------------------------- +// +// Function pointer type for condition callbacks (defined in xos_thread.h) +// +// typedef int32_t (XosCondFunc)(void * arg, int32_t sig_value, XosThread * thread); +// +//----------------------------------------------------------------------------- + + +//----------------------------------------------------------------------------- +/// +/// Condition object. +/// +//----------------------------------------------------------------------------- +typedef struct XosCond { + XosThreadQueue queue; ///< Queue of waiters. +#if XOS_COND_DEBUG + uint32_t sig; // Signature indicates valid object. +#endif +} XosCond; + + +//----------------------------------------------------------------------------- +/// +/// Initialize a condition object before first use. The object must be +/// allocated by the caller. +/// +/// \param cond Pointer to condition object. +/// +/// \return Returns nothing. +/// +//----------------------------------------------------------------------------- +void +xos_cond_create(XosCond * cond); + + +//----------------------------------------------------------------------------- +/// +/// Destroy a condition object. Must have been previously created by calling +/// xos_cond_create(). +/// +/// \param cond Pointer to condition object. +/// +/// \return Returns nothing. +/// +//----------------------------------------------------------------------------- +void +xos_cond_delete(XosCond * cond); + + +//----------------------------------------------------------------------------- +/// +/// Wait on a condition: block until the condition is satisfied. The condition +/// is satisfied when xos_cond_signal() is called on this condition *and* the +/// condition callback function returns non-zero. If there is no callback +/// function, then the condition is automatically satisfied. +/// +/// The condition structure must have been initialized before first use by +/// calling xos_cond_create(). +/// +/// \param cond Pointer to condition object. +/// +/// \param cond_fn Pointer to a function, called by xos_cond_signal(), +/// that should return non-zero if this thread is to +/// be resumed. The function is invoked as: +/// `(*cond_fn)(cond_arg, sig_value)`. +/// +/// \param cond_arg Argument passed to cond_fn. +/// +/// \return Returns the value passed to xos_cond_signal(). +/// +//----------------------------------------------------------------------------- +int32_t +xos_cond_wait(XosCond * cond, XosCondFunc * cond_fn, void * cond_arg); + + +//----------------------------------------------------------------------------- +/// +/// Trigger the condition: wake all threads waiting on the condition, if their +/// condition function evaluates to true (non-zero). If there is no condition +/// function for a thread then it is automatically awakened. +/// +/// The condition structure must have been initialized before first use by +/// calling xos_cond_create(). +/// +/// \param cond Pointer to condition object. +/// +/// \param sig_value Value passed to all waiters, returned by +/// xos_cond_wait(). +/// +/// \return Returns the number of waiting threads that were resumed. +/// +/// NOTE: Signaling a condition that has no waiters has no effect on it, and +/// the signal is not remembered. Any thread that waits on it later must be +/// woken by another call to xos_cond_signal(). +/// +//----------------------------------------------------------------------------- +int32_t +xos_cond_signal(XosCond * cond, int32_t sig_value); + + +#ifdef __cplusplus +} +#endif + +#endif // __XOS_COND_H__ + diff --git a/components/esp32/include/xtensa/xos_errors.h b/components/esp32/include/xtensa/xos_errors.h new file mode 100755 index 0000000000..790cdde3bd --- /dev/null +++ b/components/esp32/include/xtensa/xos_errors.h @@ -0,0 +1,107 @@ +/** @file */ + +// xos_errors.h - XOS error codes. + +// Copyright (c) 2003-2015 Cadence Design Systems, Inc. +// +// Permission is hereby granted, free of charge, to any person obtaining +// a copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to +// permit persons to whom the Software is furnished to do so, subject to +// the following conditions: +// +// The above copyright notice and this permission notice shall be included +// in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +// CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +// SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +// NOTE: Do not include this file directly in your application. Including +// xos.h will automatically include this file. + + +#ifndef __XOS_ERRORS_H__ +#define __XOS_ERRORS_H__ + +#include "xos_types.h" + + +#define _XOS_ERR_FIRST (-65536) +#define _XOS_ERR_LAST (-1) + + +//----------------------------------------------------------------------------- +/// +/// List of XOS error codes. All error codes are negative integers, except for +/// XOS_OK which is zero. +/// XOS error codes occupy the range from -65536 up to -1. +/// The function IS_XOS_ERRCODE() can be used to check if a value lies within +/// the error code range. +/// +//----------------------------------------------------------------------------- +typedef enum xos_err_t { + XOS_OK = 0, + + XOS_ERR_NOT_FOUND = _XOS_ERR_FIRST, ///< Object not found + XOS_ERR_INVALID_PARAMETER, ///< Function parameter is invalid + XOS_ERR_LIMIT, ///< Limit exceeded + XOS_ERR_NOT_OWNED, ///< Object not owned by caller + XOS_ERR_MUTEX_LOCKED, ///< Mutex is already locked + XOS_ERR_MUTEX_NOT_OWNED, ///< Mutex not owned by caller + XOS_ERR_MUTEX_ALREADY_OWNED, ///< Mutex already owned by caller + XOS_ERR_MUTEX_DELETE, ///< Mutex being waited on has been deleted + XOS_ERR_COND_DELETE, ///< Condition being waited on has been deleted + XOS_ERR_SEM_DELETE, ///< Semaphore being waited on has been deleted + XOS_ERR_SEM_BUSY, ///< Semaphore is not available + XOS_ERR_EVENT_DELETE, ///< Event being waited on has been deleted + XOS_ERR_MSGQ_FULL, ///< Message queue is full + XOS_ERR_MSGQ_EMPTY, ///< Message queue is empty + XOS_ERR_MSGQ_DELETE, ///< Message queue being waited on has been deleted + XOS_ERR_TIMER_DELETE, ///< Timer being waited on has been deleted + XOS_ERR_CONTAINER_NOT_RTC, ///< Containing thread not of RTC type + XOS_ERR_CONTAINER_NOT_SAME_PRI, ///< Containing thread not at same priority + XOS_ERR_STACK_TOO_SMALL, ///< Thread stack is too small + XOS_ERR_CONTAINER_ILLEGAL, ///< Illegal container thread + XOS_ERR_ILLEGAL_OPERATION, ///< This operation is not allowed + XOS_ERR_THREAD_EXITED, ///< The thread has already exited + XOS_ERR_NO_TIMER, ///< No suitable timer found + XOS_ERR_FEATURE_NOT_PRESENT, ///< This feature is disabled or not implemented + XOS_ERR_TIMEOUT, ///< Wait timed out + + XOS_ERR_UNHANDLED_INTERRUPT, ///< No handler for interrupt + XOS_ERR_UNHANDLED_EXCEPTION, ///< No handler for exception + XOS_ERR_INTERRUPT_CONTEXT, ///< Operation is illegal in interrupt context + XOS_ERR_THREAD_BLOCKED, ///< Thread already blocked + XOS_ERR_ASSERT_FAILED, ///< Runtime assertion failure + XOS_ERR_CLIB_ERR, ///< Error in C library thread safety module + XOS_ERR_INTERNAL_ERROR, ///< XOS internal error + + XOS_ERR_LAST = _XOS_ERR_LAST, +} xos_err_t; + + +//----------------------------------------------------------------------------- +/// +/// Check if a value is a valid XOS error code. +/// +/// \param val Value to check +/// +/// \return Returns nonzero if 'val' is in the XOS error code range. +/// +//----------------------------------------------------------------------------- +static inline int32_t +IS_XOS_ERRCODE(xos_err_t val) +{ + return ((val >= _XOS_ERR_FIRST) && (val <= _XOS_ERR_LAST)); +} + + +#endif // __XOS_ERRORS_H__ + diff --git a/components/esp32/include/xtensa/xos_event.h b/components/esp32/include/xtensa/xos_event.h new file mode 100755 index 0000000000..43219a2478 --- /dev/null +++ b/components/esp32/include/xtensa/xos_event.h @@ -0,0 +1,281 @@ +/** @file */ + +// xos_event.h - XOS Event API interface and data structures. + +// Copyright (c) 2003-2015 Cadence Design Systems, Inc. +// +// Permission is hereby granted, free of charge, to any person obtaining +// a copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to +// permit persons to whom the Software is furnished to do so, subject to +// the following conditions: +// +// The above copyright notice and this permission notice shall be included +// in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +// CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +// SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +// NOTE: Do not include this file directly in your application. Including +// xos.h will automatically include this file. + +#ifndef __XOS_EVENT_H__ +#define __XOS_EVENT_H__ + +#include "xos_types.h" + +#ifdef __cplusplus +extern "C" { +#endif + + +//----------------------------------------------------------------------------- +// Defines. +//----------------------------------------------------------------------------- +#define XOS_EVENT_BITS_ALL 0xFFFFFFFF +#define XOS_EVENT_BITS_NONE 0 + + +//----------------------------------------------------------------------------- +// Event flags. +//----------------------------------------------------------------------------- + + +//----------------------------------------------------------------------------- +/// +/// Event object. +/// +//----------------------------------------------------------------------------- +typedef struct XosEvent { + XosThreadQueue waitq; ///< Queue of waiters. + uint32_t bits; ///< Event bits + uint32_t mask; ///< Specifies which bits are valid + uint16_t flags; ///< Properties. + uint16_t pad; ///< Padding +#if XOS_EVENT_DEBUG + uint32_t sig; // Valid signature indicates inited. +#endif +} XosEvent; + + +//----------------------------------------------------------------------------- +/// +/// Initialize an event object before first use. +/// +/// \param event Pointer to event object. +/// +/// \param mask Mask of active bits. Only these bits can be signaled. +/// +/// \param flags Creation flags (currently ignored, should be zero). +/// +/// \return Returns nothing. +/// +//----------------------------------------------------------------------------- +void +xos_event_create(XosEvent * event, uint32_t mask, uint32_t flags); + + +//----------------------------------------------------------------------------- +/// +/// Destroy an event object. Must have been previously created by calling +/// xos_event_create(). +/// +/// \param event Pointer to event object. +/// +/// \return Returns nothing. +/// +//----------------------------------------------------------------------------- +void +xos_event_delete(XosEvent * event); + + +//----------------------------------------------------------------------------- +/// +/// Set the specified bits in the specified event. Propagates the bit states +/// to all waiting threads and wakes them if needed. +/// +/// \param event Pointer to event object. +/// +/// \param bits Mask of bits to set. Bits not set in the mask +/// will not be modified by this call. To set all +/// the bits in the event, use the constant +/// XOS_EVENT_BITS_ALL. +/// +/// \return Returns XOS_OK on success, else error code. +/// +//----------------------------------------------------------------------------- +int32_t +xos_event_set(XosEvent * event, uint32_t bits); + + +//----------------------------------------------------------------------------- +/// +/// Clear the specified bits in the specified event. Propagates the bit states +/// to all waiting threads and wakes them if needed. +/// +/// \param event Pointer to event object. +/// +/// \param bits Mask of bits to clear. Every bit that is set in +/// the mask will be cleared from the event. Bits +/// not set in the mask will not be modified by this +/// call. To clear all the bits in an event use the +/// constant XOS_EVENT_BITS_ALL. +/// +/// \return Returns XOS_OK on success, else error code. +/// +//----------------------------------------------------------------------------- +int32_t +xos_event_clear(XosEvent * event, uint32_t bits); + + +//----------------------------------------------------------------------------- +/// +/// Clear and set the specified bits in the specified event. The two steps are +/// combined into one update, so this is faster than calling xos_event_clear() +/// and xos_event_set() separately. Only one update is sent out to waiting +/// threads. +/// +/// \param event Pointer to event object. +/// +/// \param clr_bits Mask of bits to clear. The clear operation +/// happens before the set operation. +/// +/// \param set_bits Mask of bits to set. +/// +/// \return Returns XOS_OK on success, else error code. +/// +//----------------------------------------------------------------------------- +int32_t +xos_event_clear_and_set(XosEvent * event, uint32_t clr_bits, uint32_t set_bits); + + +//----------------------------------------------------------------------------- +/// +/// Get the current state of the event object. This is a snapshot of the state +/// of the event at this time. +/// +/// \param event Pointer to event object. +/// +/// \param pstate Pointer to a uint32_t variable where the state +/// will be returned. +/// +/// \return Returns XOS_OK on success, else error code. +/// +//----------------------------------------------------------------------------- +int32_t +xos_event_get(XosEvent * event, uint32_t * pstate); + + +//----------------------------------------------------------------------------- +/// +/// Wait until all the specified bits in the wait mask become set in the given +/// event object. +/// +/// \param event Pointer to event object. +/// +/// \param bits Mask of bits to test. +/// +/// \return Returns XOS_OK on success, else error code. +/// +//----------------------------------------------------------------------------- +int32_t +xos_event_wait_all(XosEvent * event, uint32_t bits); + + +//----------------------------------------------------------------------------- +/// +/// Wait until all the specified bits in the wait mask become set in the given +/// event object, or the timeout expires. +/// +/// \param event Pointer to event object. +/// +/// \param bits Mask of bits to test. +/// +/// \param to_cycles Timeout in cycles. Convert from time to cycles +/// using the helper functions provided in xos_timer. +/// A value of zero indicates no timeout. +/// +/// \return Returns XOS_OK on success, XOS_ERR_TIMEOUT on timeout, else +/// error code. +/// +/// NOTE: If XOS_OPT_WAIT_TIMEOUT is not enabled, then the timeout value is +/// ignored, and no timeout will occur. +/// +//----------------------------------------------------------------------------- +int32_t +xos_event_wait_all_timeout(XosEvent * event, uint32_t bits, uint64_t to_cycles); + + +//----------------------------------------------------------------------------- +/// +/// Wait until any of the specified bits in the wait mask become set in the +/// given event object. +/// +/// \param event Pointer to event object. +/// +/// \param bits Mask of bits to test. +/// +/// \return Returns XOS_OK on success, else error code. +/// +//----------------------------------------------------------------------------- +int32_t +xos_event_wait_any(XosEvent * event, uint32_t bits); + + +//----------------------------------------------------------------------------- +/// +/// Wait until any of the specified bits in the wait mask become set in the +/// event object, or the timeout expires. +/// +/// \param event Pointer to event object. +/// +/// \param bits Mask of bits to test. +/// +/// \param to_cycles Timeout in cycles. Convert from time to cycles +/// using the helper functions provided in xos_timer. +/// A value of zero indicates no timeout. +/// +/// \return Returns XOS_OK on success, XOS_ERR_TIMEOUT on timeout, else +/// error code. +/// +/// NOTE: If XOS_OPT_WAIT_TIMEOUT is not enabled, then the timeout value is +/// ignored, and no timeout will occur. +/// +//----------------------------------------------------------------------------- +int32_t +xos_event_wait_any_timeout(XosEvent * event, uint32_t bits, uint64_t to_cycles); + + +//----------------------------------------------------------------------------- +/// +/// Atomically set a specified group of bits, then wait for another specified +/// group of bits to become set. +/// +/// \param event Pointer to event object. +/// +/// \param set_bits Group of bits to set. +/// +/// \param wait_bits Group of bits to wait on. All the bits in the +/// group will have to get set before the wait is +/// satisfied. +/// +/// \return Returns XOS_OK on success, else error code. +/// +//----------------------------------------------------------------------------- +int32_t +xos_event_set_and_wait(XosEvent * event, uint32_t set_bits, uint32_t wait_bits); + + +#ifdef __cplusplus +} +#endif + +#endif // __XOS_EVENT_H__ + diff --git a/components/esp32/include/xtensa/xos_internal.h b/components/esp32/include/xtensa/xos_internal.h new file mode 100755 index 0000000000..5b8c8b4662 --- /dev/null +++ b/components/esp32/include/xtensa/xos_internal.h @@ -0,0 +1,120 @@ + +// Copyright (c) 2003-2015 Cadence Design Systems, Inc. +// +// Permission is hereby granted, free of charge, to any person obtaining +// a copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to +// permit persons to whom the Software is furnished to do so, subject to +// the following conditions: +// +// The above copyright notice and this permission notice shall be included +// in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +// CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +// SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + + +#ifndef __XOS_INTERNAL_H__ +#define __XOS_INTERNAL_H__ + +#if !defined(__XOS_H__) || !defined(_XOS_INCLUDE_INTERNAL_) + #error "xos_internal.h must be included by defining _XOS_INCLUDE_INTERNAL_ before including xos.h" +#endif + +#include +#include "xos_common.h" + +#ifdef __cplusplus +extern "C" { +#endif + + +// Use this macro to suppress compiler warnings for unused variables. + +#define UNUSED(x) (void)(x) + + +#if XOS_DEBUG + +#include +#include +# define DPRINTF printf + +#else + +# define DPRINTF(x...) do {} while(0) + +#endif + + +//----------------------------------------------------------------------------- +// Internal flags for thread creation. +//----------------------------------------------------------------------------- +#define XOS_THREAD_FAKE 0x8000 // Don't allocate stack (init and idle threads). + + +//----------------------------------------------------------------------------- +// Interrupt handler table entry. This structure defines one entry in the XOS +// interrupt handler table. +//----------------------------------------------------------------------------- +typedef struct XosIntEntry { + XosIntFunc * handler; // Pointer to handler function. + void * arg; // Argument passed to handler function. +#if XOS_OPT_INTERRUPT_SWPRI + unsigned char level; // Interrupt level. + unsigned char priority; // Interrupt priority. + short reserved; // Reserved. + unsigned int primask; // Mask of interrupts at higher priority. +#else + unsigned int ps; // Value of PS when running the handler. +#endif +} XosIntEntry; + + +//----------------------------------------------------------------------------- +// Extern variables. +//----------------------------------------------------------------------------- +extern unsigned xos_intlevel_mask; +extern unsigned xos_intenable_mask; +extern XosIntEntry xos_interrupt_table[XCHAL_NUM_INTERRUPTS]; + +extern uint32_t xos_clock_freq; +extern uint32_t xos_tick_period; +extern uint64_t xos_system_ticks; +extern uint64_t xos_system_cycles; +extern uint32_t xos_num_ctx_switches; + + +/* + +One thing I noticed is different between my initial idea of stack +assignments to RTC threads, when comparing to interrupts, is that I +expected each RTC thread priority to have its own stack, whereas +interrupts of different priorities share an interrupt stack. + +It's not really a difference in memory usage, because when assigning +multiple priorities to a stack, you have to add-up worst-case for +all priorities. One possible functional difference is that with +separate stacks per priority, it's possible to dynamically change +the priority of an RTC thread (while it's running). Not sure how +valuable that might be -- changing priority is useful with priority +inheritance, to avoid priority inversion, but I don't know how often +an RTC thread might acquire a lock (it couldn't block on acquiring a +lock in the usual sense -- it could get queued waiting and be restarted +when it becomes available, or use try_lock instead of lock). + +*/ + +#ifdef __cplusplus +} +#endif + +#endif /* __XOS_INTERNAL_H__ */ + diff --git a/components/esp32/include/xtensa/xos_msgq.h b/components/esp32/include/xtensa/xos_msgq.h new file mode 100755 index 0000000000..30b9aa9032 --- /dev/null +++ b/components/esp32/include/xtensa/xos_msgq.h @@ -0,0 +1,278 @@ +/** @file */ + +// xos_msgq.h - XOS Message Queue API and data structures. + +// Copyright (c) 2003-2015 Cadence Design Systems, Inc. +// +// Permission is hereby granted, free of charge, to any person obtaining +// a copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to +// permit persons to whom the Software is furnished to do so, subject to +// the following conditions: +// +// The above copyright notice and this permission notice shall be included +// in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +// CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +// SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +// NOTE: Do not include this file directly in your application. Including +// xos.h will automatically include this file. + + +#ifndef __XOS_MSGQ_H__ +#define __XOS_MSGQ_H__ + +#include "xos_types.h" + +#ifdef __cplusplus +extern "C" { +#endif + + +//----------------------------------------------------------------------------- +// XosMsgQueue is a multi-writer multi-reader message queue implementation. +// It is completely thread-safe and can be used by interrupt handlers. +// Interrupt handlers are guaranteed not to block when trying to send or +// receive a message. Messages are copied into the queue. The queue contains +// storage for a fixed number of messages defined at queue creation time. +// Messages must be a multiple of 4 bytes long (padded if necessary) and the +// message buffers must be 4-byte aligned. +//----------------------------------------------------------------------------- + + +//----------------------------------------------------------------------------- +// Message Queue flags. +//----------------------------------------------------------------------------- +#define XOS_MSGQ_WAIT_PRIORITY 0x0000 ///< Wake waiters in priority order (default) +#define XOS_MSGQ_WAIT_FIFO 0x0001 ///< Wake waiters in FIFO order +#define XOS_MSGQ_FULL 0x0002 // Queue is full +#define XOS_MSGQ_DELETED 0x8000 // Queue is deleted + + +//----------------------------------------------------------------------------- +/// +/// XosMsgQueue object. +/// +//----------------------------------------------------------------------------- +typedef struct XosMsgQueue { + uint16_t flags; ///< queue flags + uint16_t count; ///< # of messages queue can hold + uint32_t msize; ///< message size in bytes + uint16_t head; ///< write pointer + uint16_t tail; ///< read pointer + XosThreadQueue readq; ///< reader wait queue + XosThreadQueue writeq; ///< writer wait queue +#if XOS_MSGQ_DEBUG + uint32_t sig; // debug signature +#endif +#if XOS_OPT_MSGQ_STATS + uint32_t num_send; ///< # of messages put to queue + uint32_t num_recv; ///< # of messages taken from queue + uint32_t num_send_blks; ///< # of times thread blocked on send + uint32_t num_recv_blks; ///< # of times thread blocked on recv +#endif + uint32_t msg[1]; ///< first word of message buffer +} XosMsgQueue; + + +//----------------------------------------------------------------------------- +/// +/// Use these macros to statically or dynamically allocate a message queue. +/// XOS_MSGQ_ALLOC allocates a static queue, while XOS_MSGQ_SIZE can be used +/// to allocate memory via malloc() etc. +/// +/// Static: this allocates a queue named "testq", containing 10 messages, +/// each 16 bytes long. +/// +/// XOS_MSGQ_ALLOC(testq, 10, 16); +/// +/// Dynamic: this allocates a queue named "testq", containing 10 messages, +/// each 16 bytes long. +/// +/// XosMsgQueue * testq = malloc( XOS_MSGQ_SIZE(10, 16) ); +/// +/// \param name The queue name, i.e. the name of the pointer +/// to the queue. Used as the queue handle in +/// queue API calls. +/// +/// \param num Number of messages to allocate in queue. Must be > 0. +/// +/// \param size Message size in bytes. Must be > 0 and multiple of 4. +/// +//----------------------------------------------------------------------------- + +#define XOS_MSGQ_ALLOC(name, num, size) \ + static uint8_t name ## _buf[ sizeof(XosMsgQueue) + ((num) * (size)) ]; \ + XosMsgQueue * name = (XosMsgQueue *) name ## _buf; + +#define XOS_MSGQ_SIZE(num, size) \ + (sizeof(XosMsgQueue) + ((num) * (size))) + + +//----------------------------------------------------------------------------- +/// +/// Create the message queue object. Memory for the queue must be allocated by +/// the caller, either statically or via dynamic allocation. See the macros +/// XOS_MSGQ_ALLOC and XOS_MSGQ_SIZE for examples. +/// +/// \param msgq Handle (pointer) to message queue. +/// +/// \param num Number of messages allocated in queue. Must be > 0. +/// +/// \param size Message size in bytes. Must be > 0 and multiple of 4. +/// +/// \param flags Queue flags: +/// - XOS_MSGQ_WAIT_FIFO - blocked threads will be +/// woken in FIFO order. +/// - XOS_MSGQ_WAIT_PRIORITY - blocked threads will +/// be woken in priority order (default). +/// +/// \return Returns XOS_OK on success, else error code. +/// +//----------------------------------------------------------------------------- +int32_t +xos_msgq_create(XosMsgQueue * msgq, uint16_t num, uint32_t size, uint16_t flags); + + +//----------------------------------------------------------------------------- +/// +/// Destroys the specified queue. Any waiting threads are unblocked with an +/// error return. Any messages in the queue will be lost. +/// +/// \param msgq Pointer to message queue. +/// +/// \return Returns XOS_OK on success, else error code. +/// +//----------------------------------------------------------------------------- +int32_t +xos_msgq_delete(XosMsgQueue * msgq); + + +//----------------------------------------------------------------------------- +/// +/// Put a message into the queue. The message contents are copied into the next +/// available message slot. If no space is available, this function will block +/// if called from a thread, but will return immediately if called from an +/// interrupt handler. +/// +/// \param msgq Pointer to message queue. +/// +/// \param msg Pointer to message buffer. +/// +/// \return Returns XOS_OK on success, else error code. +/// +//----------------------------------------------------------------------------- +int32_t +xos_msgq_put(XosMsgQueue * msgq, const uint32_t * msg); + + +//----------------------------------------------------------------------------- +/// +/// Put a message into the queue. The message contents are copied into the next +/// available message slot. If no space is available, this function will block +/// if called from a thread, but will return immediately if called from an +/// interrupt handler. The thread will be unblocked when space frees up in the +/// queue or the timeout expires. +/// +/// \param msgq Pointer to message queue. +/// +/// \param msg Pointer to message buffer. +/// +/// \param to_cycles Timeout in cycles. Convert from time to cycles +/// using the helper functions provided in xos_timer. +/// A value of zero indicates no timeout. +/// +/// \return Returns XOS_OK on success, XOS_ERR_TIMEOUT on timeout, else error code. +/// +/// NOTE: If XOS_OPT_WAIT_TIMEOUT is not enabled, then the timeout value is +/// ignored, and no timeout will occur. +/// +//----------------------------------------------------------------------------- +int32_t +xos_msgq_put_timeout(XosMsgQueue * msgq, const uint32_t * msg, uint64_t to_cycles); + + +//----------------------------------------------------------------------------- +/// +/// Get a message from the queue. The message contents are copied into the +/// buffer that must be provided. If no message is available, this function +/// will block if called from a thread, but will return immediately if called +/// from an interrupt handler. +/// +/// \param msgq Pointer to message queue. +/// +/// \param msg Pointer to message buffer. +/// +/// \return Returns XOS_OK on success, else error code. +/// +//----------------------------------------------------------------------------- +int32_t +xos_msgq_get(XosMsgQueue * msgq, uint32_t * msg); + + +//----------------------------------------------------------------------------- +/// +/// Get a message from the queue. The message contents are copied into the +/// buffer that must be provided. If no message is available, this function +/// will block if called from a thread, but will return immediately if called +/// from an interrupt handler. The thread will be unblocked when a message +/// arrives in the queue or the timeout expires. +/// +/// \param msgq Pointer to message queue. +/// +/// \param msg Pointer to message buffer. +/// +/// \param to_cycles Timeout in cycles. Convert from time to cycles +/// using the helper functions provided in xos_timer. +/// A value of zero indicates no timeout. +/// +/// \return Returns XOS_OK on success, XOS_ERR_TIMEOUT on timeout, else error code. +/// +/// NOTE: If XOS_OPT_WAIT_TIMEOUT is not enabled, then the timeout value is +/// ignored, and no timeout will occur. +/// +//----------------------------------------------------------------------------- +int32_t +xos_msgq_get_timeout(XosMsgQueue * msgq, uint32_t * msg, uint64_t to_cycles); + + +//----------------------------------------------------------------------------- +/// +/// Check if the queue is empty. +/// +/// \param msgq Pointer to message queue. +/// +/// \return Returns nonzero if queue is empty, zero if queue is not empty. +/// +//----------------------------------------------------------------------------- +int32_t +xos_msgq_empty(XosMsgQueue * msgq); + + +//----------------------------------------------------------------------------- +/// +/// Check if the queue is full. +/// +/// \param msgq Pointer to message queue. +/// +/// \return Returns nonzero if queue is full, zero if queue is not full. +/// +//----------------------------------------------------------------------------- +int32_t +xos_msgq_full(XosMsgQueue * msgq); + + +#ifdef __cplusplus +} +#endif + +#endif // __XOS_MSGQ_H__ + diff --git a/components/esp32/include/xtensa/xos_mutex.h b/components/esp32/include/xtensa/xos_mutex.h new file mode 100755 index 0000000000..9df5f9750b --- /dev/null +++ b/components/esp32/include/xtensa/xos_mutex.h @@ -0,0 +1,205 @@ +/** @file */ + +// xos_mutex.h - XOS Mutex API interface and data structures. + +// Copyright (c) 2003-2015 Cadence Design Systems, Inc. +// +// Permission is hereby granted, free of charge, to any person obtaining +// a copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to +// permit persons to whom the Software is furnished to do so, subject to +// the following conditions: +// +// The above copyright notice and this permission notice shall be included +// in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +// CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +// SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +// NOTE: Do not include this file directly in your application. Including +// xos.h will automatically include this file. + +#ifndef __XOS_MUTEX_H__ +#define __XOS_MUTEX_H__ + +#include "xos_types.h" + +#ifdef __cplusplus +extern "C" { +#endif + + +//----------------------------------------------------------------------------- +// Mutex flags. +//----------------------------------------------------------------------------- +#define XOS_MUTEX_WAIT_PRIORITY 0x0000 ///< Wake waiters in priority order (default) +#define XOS_MUTEX_WAIT_FIFO 0x0001 ///< Wake waiters in FIFO order +#define XOS_MUTEX_PRIORITY_CLG 0x0004 // Use priority ceiling +#define XOS_MUTEX_PRIORITY_INV 0x0008 // Protect against priority inversion + + +//----------------------------------------------------------------------------- +/// +/// XosMutex object. +/// +//----------------------------------------------------------------------------- +typedef struct XosMutex { + XosThread * owner; ///< Owning thread (null if unlocked). + XosThreadQueue waitq; ///< Queue of waiters. + uint32_t flags; ///< Properties. + uint32_t priority; + int32_t lock_count; ///< For recursive locking. +#if XOS_MUTEX_DEBUG + uint32_t sig; // Valid signature indicates inited. +#endif +} XosMutex; + + +//----------------------------------------------------------------------------- +/// +/// Initialize a mutex object before first use. +/// +/// \param mutex Pointer to mutex object. +/// +/// \param flags Creation flags: +/// - XOS_MUTEX_WAIT_FIFO -- Queue waiting threads +/// in fifo order. +/// - XOS_MUTEX_WAIT_PRIORITY -- Queue waiting threads +/// by priority. This is the default. +/// - XOS_MUTEX_PRIORITY_CLG -- Use specified priority +/// value as the mutex's priority ceiling. If the +/// owning thread has a priority lower than the mutex's +/// priority, then the thread will have its priority +/// raised to the higher value as long as it owns the +/// mutex. +/// - XOS_MUTEX_PRIORITY_INV -- Protect against priority +/// inversion. If there is a waiting thread with a +/// higher priority than the current owner thread, +/// then the owner thread's priority is raised to the +/// higher value for as long as it owns the mutex. +/// +/// \param priority Mutex's priority ceiling. This is used only if the +/// XOS_MUTEX_PRIORITY_CLG flag is set. +/// +/// \return Returns XOS_OK on success, else error code. +/// +/// NOTE: XOS_MUTEX_PRIORITY_CLG and XOS_MUTEX_PRIORITY_INV are NOT supported +/// in the current release. They will be supported in a future release. +/// +//----------------------------------------------------------------------------- +int32_t +xos_mutex_create(XosMutex * mutex, uint32_t flags, uint8_t priority); + + +//----------------------------------------------------------------------------- +/// +/// Destroy a mutex object. Must have been previously initialized by calling +/// xos_mutex_create(). +/// +/// \param mutex Pointer to mutex object. +/// +/// \return Returns XOS_OK on success, else error code. +/// +//----------------------------------------------------------------------------- +int32_t +xos_mutex_delete(XosMutex * mutex); + + +//----------------------------------------------------------------------------- +/// +/// Take ownership of the mutex: block until the mutex is owned. +/// The mutex must have been initialized. +/// +/// \param mutex Pointer to mutex object. +/// +/// \return Returns XOS_OK on success, else error code. +/// +//----------------------------------------------------------------------------- +int32_t +xos_mutex_lock(XosMutex * mutex); + + +//----------------------------------------------------------------------------- +/// +/// Take ownership of the mutex: block until the mutex is owned or the timeout +/// expires. The mutex must have been initialized. +/// +/// \param mutex Pointer to mutex object. +/// +/// \param to_cycles Timeout in cycles. Convert from time to cycles +/// using the helper functions provided in xos_timer. +/// A value of zero indicates no timeout. +/// +/// \return Returns XOS_OK on success, XOS_ERR_TIMEOUT on timeout, else error code. +/// +/// NOTE: If XOS_OPT_WAIT_TIMEOUT is not enabled, then the timeout value is +/// ignored, and no timeout will occur. +/// +//----------------------------------------------------------------------------- +int32_t +xos_mutex_lock_timeout(XosMutex * mutex, uint64_t to_cycles); + + +//----------------------------------------------------------------------------- +/// +/// Release ownership of the mutex. The mutex must have been initialized and +/// must be owned by the calling thread. +/// +/// \param mutex Pointer to mutex object. +/// +/// \return Returns XOS_OK on success, else error code. +/// +//----------------------------------------------------------------------------- +int32_t +xos_mutex_unlock(XosMutex * mutex); + + +//----------------------------------------------------------------------------- +/// +/// Try to take ownership of the mutex, but do not block if the mutex is taken. +/// Return immediately. The mutex must have been initialized. +/// +/// \param mutex Pointer to mutex object. +/// +/// \return Returns XOS_OK on success (mutex owned), else error code. +/// +//----------------------------------------------------------------------------- +int32_t +xos_mutex_trylock(XosMutex * mutex); + + +//----------------------------------------------------------------------------- +/// +/// Return the state of the mutex (locked or unlocked) but do not attempt to +/// take ownership. The mutex must have been initialized. +/// +/// \param mutex Pointer to mutex object. +/// +/// \return Returns 0 if the mutex is unlocked, 1 if it is locked, -1 on error. +/// +//----------------------------------------------------------------------------- +static inline int32_t +xos_mutex_test(XosMutex * mutex) +{ + XOS_ASSERT(mutex); + + if (mutex != XOS_NULL) { + return (mutex->owner != XOS_NULL) ? 1 : 0; + } + return -1; +} + + +#ifdef __cplusplus +} +#endif + +#endif // __XOS_MUTEX_H__ + diff --git a/components/esp32/include/xtensa/xos_params.h b/components/esp32/include/xtensa/xos_params.h new file mode 100755 index 0000000000..3fca11f21a --- /dev/null +++ b/components/esp32/include/xtensa/xos_params.h @@ -0,0 +1,276 @@ +/** @file */ + +// xos_params.h - user-settable compile time parameters for XOS. + +// Copyright (c) 2003-2015 Cadence Design Systems, Inc. +// +// Permission is hereby granted, free of charge, to any person obtaining +// a copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to +// permit persons to whom the Software is furnished to do so, subject to +// the following conditions: +// +// The above copyright notice and this permission notice shall be included +// in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +// CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +// SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + + +#ifndef __XOS_PARAMS_H__ +#define __XOS_PARAMS_H__ + +#include + +#ifdef __cplusplus +extern "C" { +#endif + + +//----------------------------------------------------------------------------- +/// +/// Number of thread priority levels. At this time XOS supports a maximum of +/// 32 priority levels (0 - 31). +/// +//----------------------------------------------------------------------------- +#ifndef XOS_NUM_PRIORITY +#define XOS_NUM_PRIORITY 16 // Default is 16 +#endif + + +//----------------------------------------------------------------------------- +/// +/// Debug flags - Set to 1 to enable debug mode (and more verbose operation). +/// Can be set individually, or define XOS_DEBUG_ALL to enable all of them. +/// +/// - XOS_DEBUG -- Generic OS debug +/// - XOS_COND_DEBUG -- Condition objects debug +/// - XOS_EVENT_DEBUG -- Event objects debug +/// - XOS_MSGQ_DEBUG -- Message queue debug +/// - XOS_MUTEX_DEBUG -- Mutex objects debug +/// - XOS_SEM_DEBUG -- Semaphore objects debug +/// - XOS_THREAD_DEBUG -- Thread module debug +/// - XOS_TIMER_DEBUG -- Timer module debug +/// +/// WARNING: Enabling one or more of these flags will affect system performance +/// and timing. +/// +/// NOTE: Not all of these have been fully implemented. +/// +//----------------------------------------------------------------------------- +#if defined XOS_DEBUG_ALL + +#define XOS_DEBUG 1 +#define XOS_THREAD_DEBUG 1 +#define XOS_TIMER_DEBUG 1 +#define XOS_COND_DEBUG 1 +#define XOS_MUTEX_DEBUG 1 +#define XOS_SEM_DEBUG 1 +#define XOS_EVENT_DEBUG 1 +#define XOS_MSGQ_DEBUG 1 + +#else + +#ifndef XOS_DEBUG +#define XOS_DEBUG 0 +#endif +#ifndef XOS_THREAD_DEBUG +#define XOS_THREAD_DEBUG 0 +#endif +#ifndef XOS_TIMER_DEBUG +#define XOS_TIMER_DEBUG 0 +#endif +#ifndef XOS_COND_DEBUG +#define XOS_COND_DEBUG 0 +#endif +#ifndef XOS_MUTEX_DEBUG +#define XOS_MUTEX_DEBUG 0 +#endif +#ifndef XOS_SEM_DEBUG +#define XOS_SEM_DEBUG 0 +#endif +#ifndef XOS_EVENT_DEBUG +#define XOS_EVENT_DEBUG 0 +#endif +#ifndef XOS_MSGQ_DEBUG +#define XOS_MSGQ_DEBUG 0 +#endif + +#endif + + +//----------------------------------------------------------------------------- +/// +/// Set this option to 1 to enable runtime statistics collection for XOS. +/// NOTE: Enabling this option does have some impact on runtime performance +/// and OS footprint. +/// +//----------------------------------------------------------------------------- +#ifndef XOS_OPT_STATS +#define XOS_OPT_STATS 1 +#endif + + +//----------------------------------------------------------------------------- +/// +/// Set this option to 1 to enable statistics tracking for message queues. +/// enabling this will cause message queue objects to increase in size, and add +/// some overhead to message queue processing. +/// +//----------------------------------------------------------------------------- +#ifndef XOS_OPT_MSGQ_STATS +#define XOS_OPT_MSGQ_STATS 0 +#endif + + +//----------------------------------------------------------------------------- +/// +/// Size of interrupt stack in bytes. Shared by all interrupt handlers. Must be +/// sized to handle worst case nested interrupts. This is also used by the idle +/// thread so must exist even if interrupts are not configured. +/// +//----------------------------------------------------------------------------- +#ifndef XOS_INT_STACK_SIZE +#if XCHAL_HAVE_INTERRUPTS +#define XOS_INT_STACK_SIZE 8192 +#else +#define XOS_INT_STACK_SIZE 32 +#endif +#endif + + +//----------------------------------------------------------------------------- +/// +/// Default maximum interrupt level at which XOS primitives may be called. +/// It is the level at which interrupts are disabled by default. +/// See also description of xos_set_int_pri_level(). +/// +//----------------------------------------------------------------------------- +#ifndef XOS_MAX_OS_INTLEVEL +#define XOS_MAX_OS_INTLEVEL XCHAL_EXCM_LEVEL +#endif + + +//----------------------------------------------------------------------------- +/// +/// Set this to 1 to enable stack checking. The stack is filled with a pattern +/// on thread creation, and the stack is checked at certain times during system +/// operation. +/// WARNING: Enabling this option can have some impact on runtime performance. +/// +//----------------------------------------------------------------------------- +#ifndef XOS_OPT_STACK_CHECK +#if XOS_DEBUG +#define XOS_OPT_STACK_CHECK 1 +#else +#define XOS_OPT_STACK_CHECK 0 +#endif +#endif + + +//----------------------------------------------------------------------------- +/// +/// Set XOS_CLOCK_FREQ to the system clock frequency if this is known ahead of +/// time. Otherwise, call xos_set_clock_freq() to set it at run time. +/// +//----------------------------------------------------------------------------- +#ifndef XOS_CLOCK_FREQ +#define XOS_CLOCK_FREQ 1000000 +#endif +#define XOS_DEFAULT_CLOCK_FREQ XOS_CLOCK_FREQ + + +//----------------------------------------------------------------------------- +/// +/// Set this option to 1 to enable software prioritization of interrupts. The +/// priority scheme applied is that a higher interrupt number at the same level +/// will have higher priority. +/// +//----------------------------------------------------------------------------- +#ifndef XOS_OPT_INTERRUPT_SWPRI +#define XOS_OPT_INTERRUPT_SWPRI 1 +#endif + + +//----------------------------------------------------------------------------- +/// +/// Set this option to 1 to use the thread-safe version of the C runtime library. +/// You may need to enable this if you call C library functions from multiple +/// threads -- see the documentation for the relevant C library to determine if +/// this is necessary. This option increases the size of the TCB. +/// NOTE: At this time only the newlib and xclib libraries are supported for +/// thread safety. +/// +//----------------------------------------------------------------------------- +#include + +#ifndef XOS_OPT_THREAD_SAFE_CLIB + +#if XSHAL_CLIB == XTHAL_CLIB_XCLIB +#define XOS_OPT_THREAD_SAFE_CLIB 1 +#elif XSHAL_CLIB == XTHAL_CLIB_NEWLIB +#define XOS_OPT_THREAD_SAFE_CLIB 1 +#else +#define XOS_OPT_THREAD_SAFE_CLIB 0 +#endif + +#endif + + +//----------------------------------------------------------------------------- +/// +/// Set this option to 1 to enable the wait timeout feature. This allows waits +/// on waitable objects to expire after a specified timeout. +/// +//----------------------------------------------------------------------------- +#ifndef XOS_OPT_WAIT_TIMEOUT +#define XOS_OPT_WAIT_TIMEOUT 1 +#endif + + +//----------------------------------------------------------------------------- +/// +/// Set this option to 1 to enable threads waiting on timer objects. If this +/// feature is not used, turning it off will make timer objects smaller, and +/// reduce the time taken by timer expiry processing (by a small amount). +/// +//----------------------------------------------------------------------------- +#ifndef XOS_OPT_TIMER_WAIT +#define XOS_OPT_TIMER_WAIT 1 +#endif + + +//----------------------------------------------------------------------------- +/// +/// Set this option to 1 to enable time-slicing between multiple threads at the +/// same priority. If this option is enabled then on every timer tick the timer +/// handler will switch out the current thread if there is another ready thread +/// at the same priority, and allow the latter thread to run. Execution will be +/// round robin switched among all the threads at the same priority. +/// +/// Currently the time slice interval is fixed to be one timer tick. +/// +/// This feature is most useful if fixed duration timer ticks are used. +/// If dynamic ticking is enabled, then time slicing will work unpredictably +/// because the interval between ticks will vary. In some cases it may be +/// better to turn time slicing off. +/// +//----------------------------------------------------------------------------- +#ifndef XOS_OPT_TIME_SLICE +#define XOS_OPT_TIME_SLICE 1 +#endif + + +#ifdef __cplusplus +} +#endif + +#endif // __XOS_PARAMS_H__ + diff --git a/components/esp32/include/xtensa/xos_regaccess.h b/components/esp32/include/xtensa/xos_regaccess.h new file mode 100755 index 0000000000..1fea5ddc28 --- /dev/null +++ b/components/esp32/include/xtensa/xos_regaccess.h @@ -0,0 +1,201 @@ + +// xos_regaccess.h - Access routines for various processor special registers. + +// Copyright (c) 2003-2015 Cadence Design Systems, Inc. +// +// Permission is hereby granted, free of charge, to any person obtaining +// a copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to +// permit persons to whom the Software is furnished to do so, subject to +// the following conditions: +// +// The above copyright notice and this permission notice shall be included +// in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +// CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +// SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +#ifndef __REGACCESS_H__ +#define __REGACCESS_H__ + +#ifdef __cplusplus +extern "C" { +#endif + +#include "xos_types.h" + +#include + +#if defined (__XCC__) +#if XCHAL_HAVE_CCOUNT +#include +#endif +#endif + + +//----------------------------------------------------------------------------- +// Read CCOUNT register. +//----------------------------------------------------------------------------- +static __inline__ uint32_t xos_get_ccount(void) +{ +#if XCHAL_HAVE_CCOUNT + +#if defined (__XCC__) + return XT_RSR_CCOUNT(); +#else + uint32_t ccount; + + __asm__ __volatile__ ( "rsr %0, ccount" : "=a" (ccount) ); + return ccount; +#endif + +#else + + return 0; + +#endif +} + + +//----------------------------------------------------------------------------- +// Read CCOMPARE0 +//----------------------------------------------------------------------------- +static __inline__ uint32_t xos_get_ccompare0(void) +{ +#if XCHAL_HAVE_CCOUNT + +#if defined (__XCC__) + return XT_RSR_CCOMPARE0(); +#else + uint32_t ccompare0; + + __asm__ __volatile__ ( "rsr %0, ccompare0" : "=a" (ccompare0)); + return ccompare0; +#endif + +#else + + return 0; + +#endif +} + + +//----------------------------------------------------------------------------- +// Read CCOMPARE1 +//----------------------------------------------------------------------------- +#if (XCHAL_NUM_TIMERS > 1) +static __inline__ uint32_t xos_get_ccompare1(void) +{ +#if defined (__XCC__) + return XT_RSR_CCOMPARE1(); +#else + uint32_t ccompare1; + + __asm__ __volatile__ ( "rsr %0, ccompare1" : "=a" (ccompare1)); + return ccompare1; +#endif +} +#endif + + +//----------------------------------------------------------------------------- +// Read CCOMPARE2 +//----------------------------------------------------------------------------- +#if (XCHAL_NUM_TIMERS > 2) +static __inline__ uint32_t xos_get_ccompare2(void) +{ +#if defined (__XCC__) + return XT_RSR_CCOMPARE2(); +#else + uint32_t ccompare2; + + __asm__ __volatile__ ( "rsr %0, ccompare2" : "=a" (ccompare2)); + return ccompare2; +#endif +} +#endif + + +//----------------------------------------------------------------------------- +// Write CCOMPARE0 +//----------------------------------------------------------------------------- +static __inline__ void xos_set_ccompare0(uint32_t val) +{ +#if XCHAL_HAVE_CCOUNT + +#if defined (__XCC__) + XT_WSR_CCOMPARE0(val); + XT_ISYNC(); +#else + __asm__ __volatile__ ( + "wsr %0, ccompare0\n" + "isync" + : + : "a" (val) + ); +#endif + +#else + + // Empty + +#endif +} + + +//----------------------------------------------------------------------------- +// Write CCOMPARE1 +//----------------------------------------------------------------------------- +#if (XCHAL_NUM_TIMERS > 1) +static __inline__ void xos_set_ccompare1(uint32_t val) +{ +#if defined (__XCC__) + XT_WSR_CCOMPARE1(val); + XT_ISYNC(); +#else + __asm__ __volatile__ ( + "wsr %0, ccompare1\n" + "isync" + : + : "a" (val) + ); +#endif +} +#endif + + +//----------------------------------------------------------------------------- +// Write CCOMPARE2 +//----------------------------------------------------------------------------- +#if (XCHAL_NUM_TIMERS > 2) +static __inline__ void xos_set_ccompare2(uint32_t val) +{ +#if defined (__XCC__) + XT_WSR_CCOMPARE2(val); + XT_ISYNC(); +#else + __asm__ __volatile__ ( + "wsr %0, ccompare2\n" + "isync" + : + : "a" (val) + ); +#endif +} +#endif + + +#ifdef __cplusplus +} +#endif + +#endif // __REGACCESS_H__ + diff --git a/components/esp32/include/xtensa/xos_semaphore.h b/components/esp32/include/xtensa/xos_semaphore.h new file mode 100755 index 0000000000..42b7914ef0 --- /dev/null +++ b/components/esp32/include/xtensa/xos_semaphore.h @@ -0,0 +1,190 @@ +/** @file */ + +// xos_semaphore.h - XOS Semaphore API interface and data structures. + +// Copyright (c) 2003-2015 Cadence Design Systems, Inc. +// +// Permission is hereby granted, free of charge, to any person obtaining +// a copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to +// permit persons to whom the Software is furnished to do so, subject to +// the following conditions: +// +// The above copyright notice and this permission notice shall be included +// in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +// CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +// SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +// NOTE: Do not include this file directly in your application. Including +// xos.h will automatically include this file. + +#ifndef __XOS_SEMAPHORE_H__ +#define __XOS_SEMAPHORE_H__ + +#include "xos_types.h" + +#ifdef __cplusplus +extern "C" { +#endif + + +//----------------------------------------------------------------------------- +// Semaphore flags. +//----------------------------------------------------------------------------- +#define XOS_SEM_WAIT_PRIORITY 0x0000 ///< Wake waiters in priority order (default) +#define XOS_SEM_WAIT_FIFO 0x0001 ///< Wake waiters in FIFO order +#define XOS_SEM_PRIORITY_INV 0x0004 // Protect against priority inversion + + +//----------------------------------------------------------------------------- +/// +/// XosSem object. +/// +//----------------------------------------------------------------------------- +typedef struct XosSem { + uint32_t count; ///< Current count + XosThreadQueue waitq; ///< Queue of waiters. + uint32_t flags; ///< Properties. +#if XOS_SEM_DEBUG + uint32_t sig; // Valid signature indicates inited. +#endif +} XosSem; + + +//----------------------------------------------------------------------------- +/// +/// Initialize a semaphore object before first use. +/// +/// \param sem Pointer to semaphore object. +/// +/// \param flags Creation flags: +/// - XOS_SEM_WAIT_FIFO -- queue waiting threads in +/// fifo order. +/// - XOS_SEM_WAIT_PRIORITY -- queue waiting threads +/// by priority. This is the default. +/// - XOS_SEM_PRIORITY_INV -- protect against priority +/// inversion. +/// +/// \param initial_count Initial count for semaphore on creation. +/// +/// \return Returns XOS_OK on success, else error code. +/// +/// NOTE: XOS_SEM_PRIORITY_INV is NOT supported in the current release. It will +/// be supported in a future release. +/// +//----------------------------------------------------------------------------- +int32_t +xos_sem_create(XosSem * sem, uint32_t flags, uint32_t initial_count); + + +//----------------------------------------------------------------------------- +/// +/// Destroy a semaphore object. Must have been previously created by calling +/// xos_sem_create(). +/// +/// \param sem Pointer to semaphore object. +/// +/// \return Returns XOS_OK on success, else error code. +/// +//----------------------------------------------------------------------------- +int32_t +xos_sem_delete(XosSem * sem); + + +//----------------------------------------------------------------------------- +/// +/// Decrement the semaphore count: block until the decrement is possible. +/// The semaphore must have been initialized. +/// +/// \param sem Pointer to semaphore object. +/// +/// \return Returns XOS_OK on success, else error code. +/// +//----------------------------------------------------------------------------- +int32_t +xos_sem_get(XosSem * sem); + + +//----------------------------------------------------------------------------- +/// +/// Decrement the semaphore count: block until the decrement is possible or +/// the timeout expires. The semaphore must have been initialized. +/// +/// \param sem Pointer to semaphore object. +/// +/// \param to_cycles Timeout in cycles. Convert from time to cycles +/// using the helper functions provided in xos_timer. +/// A value of zero indicates no timeout. +/// +/// \return Returns XOS_OK on success, XOS_ERR_TIMEOUT on timeout, else error code. +/// +/// NOTE: If XOS_OPT_WAIT_TIMEOUT is not enabled, then the timeout value is +/// ignored, and no timeout will occur. +/// +//----------------------------------------------------------------------------- +int32_t +xos_sem_get_timeout(XosSem * sem, uint64_t to_cycles); + + +//----------------------------------------------------------------------------- +/// +/// Increment the semaphore count. The semaphore must have been initialized. +/// Remember that this action may wake up a waiting thread, and if that thread +/// is higher priority then there will be an immediate context switch. +/// +/// \param sem Pointer to semaphore object. +/// +/// \return Returns XOS_OK on success, else error code. +/// +//----------------------------------------------------------------------------- +int32_t +xos_sem_put(XosSem * sem); + + +//----------------------------------------------------------------------------- +/// +/// Try to decrement the semaphore, but do not block if the semaphore count is +/// zero. Return immediately. The semaphore must have been initialized. +/// +/// \param sem Pointer to semaphore object. +/// +/// \return Returns XOS_OK on success (semaphore decremented), else error code. +/// +//----------------------------------------------------------------------------- +int32_t +xos_sem_tryget(XosSem * sem); + + +//----------------------------------------------------------------------------- +/// +/// Return the count of the semaphore but do not attempt to decrement it. +/// The semaphore must have been initialized. +/// +/// \param sem Pointer to semaphore object. +/// +/// \return Returns semaphore count, -1 on error. +/// +//----------------------------------------------------------------------------- +static inline int32_t +xos_sem_test(XosSem * sem) +{ + XOS_ASSERT(sem); + + return sem ? sem->count : -1; +} + + +#ifdef __cplusplus +} +#endif + +#endif // __XOS_SEMAPHORE_H__ + diff --git a/components/esp32/include/xtensa/xos_stopwatch.h b/components/esp32/include/xtensa/xos_stopwatch.h new file mode 100755 index 0000000000..bf71cc388b --- /dev/null +++ b/components/esp32/include/xtensa/xos_stopwatch.h @@ -0,0 +1,175 @@ +/** @file */ + +// xos_stopwatch.h - XOS Stopwatch objects and related API. + +// Copyright (c) 2003-2015 Cadence Design Systems, Inc. +// +// Permission is hereby granted, free of charge, to any person obtaining +// a copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to +// permit persons to whom the Software is furnished to do so, subject to +// the following conditions: +// +// The above copyright notice and this permission notice shall be included +// in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +// CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +// SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +// NOTE: Do not include this file directly in your application. Including +// xos.h will automatically include this file. + + +#ifndef __XOS_STOPWATCH_H__ +#define __XOS_STOPWATCH_H__ + +#ifdef __cplusplus +extern "C" { +#endif + +#include "xos_types.h" +#include "xos_params.h" + + +//----------------------------------------------------------------------------- +// A stopwatch object can be used to track elapsed time and accumulate total +// elapsed time over multiple execution periods. The stopwatch records the +// time whenever its start function is called, and stops recording the time +// when the stop function is called and updates its cumulative time counter. +// The stopwatch keeps time in cycles. This can be converted to seconds etc. +// by using the XOS conversion calls such as xos_cycles_to_secs(). +//----------------------------------------------------------------------------- + + +//----------------------------------------------------------------------------- +/// +/// XosStopwatch object. +/// +//----------------------------------------------------------------------------- +typedef struct XosStopwatch { + uint64_t total; ///< Total accumulated cycle count + uint64_t start; ///< Starting system cycle count + uint16_t active; ///< Active flag (nonzero when active) +} XosStopwatch; + + +//----------------------------------------------------------------------------- +/// +/// Initialize a stopwatch object. +/// +/// \param sw Pointer to a stopwatch object. +/// +/// \return Returns nothing. +/// +//----------------------------------------------------------------------------- +static inline void +xos_stopwatch_init(XosStopwatch * sw) +{ + sw->total = 0; + sw->start = 0; + sw->active = 0; +} + + +//----------------------------------------------------------------------------- +/// +/// Start a stopwatch. Starts cycle counting. +/// Note that this does not necessarily start counting from zero. The current +/// run (start-to-stop interval) will just get added to the accumulated count +/// in the stopwatch if any. +/// To reset the accumulated count, use xos_stopwatch_clear(). +/// +/// \param sw Pointer to a stopwatch object. +/// +/// \return Returns nothing. +/// +//----------------------------------------------------------------------------- +static inline void +xos_stopwatch_start(XosStopwatch * sw) +{ + XOS_ASSERT(!sw->active); + sw->active = 1; + sw->start = xos_get_system_cycles(); +} + + +//----------------------------------------------------------------------------- +/// +/// Stop a stopwatch. Stops cycle counting and updates total. +/// +/// \param sw Pointer to a stopwatch object. +/// +/// \return Returns nothing. +/// +//----------------------------------------------------------------------------- +static inline void +xos_stopwatch_stop(XosStopwatch * sw) +{ + XOS_ASSERT(sw->active); + sw->active = 0; + sw->total += xos_get_system_cycles() - sw->start; +} + + +//----------------------------------------------------------------------------- +/// +/// Get stopwatch accumulated count. +/// +/// \param sw Pointer to a stopwatch object. +/// +/// \return Returns the accumulated count. +/// +//----------------------------------------------------------------------------- +static inline uint64_t +xos_stopwatch_count(XosStopwatch * sw) +{ + return sw->total; +} + + +//----------------------------------------------------------------------------- +/// +/// Get elapsed time since stopwatch was started. If not started, returns zero. +/// +/// \param sw Pointer to a stopwatch object. +/// +/// \return Returns elapsed time in cycles. +/// +//----------------------------------------------------------------------------- +static inline uint64_t +xos_stopwatch_elapsed(XosStopwatch * sw) +{ + return sw->active ? xos_get_system_cycles() - sw->start : 0; +} + + +//----------------------------------------------------------------------------- +/// +/// Clears a stopwatch. Resets the accumulated count to zero, and deactivates +/// it if active. +/// +/// \param sw Pointer to a stopwatch object. +/// +/// \return Returns nothing. +/// +//----------------------------------------------------------------------------- +static inline void +xos_stopwatch_clear(XosStopwatch * sw) +{ + xos_stopwatch_init(sw); +} + + +#ifdef __cplusplus +} +#endif + +#endif // __XOS_STOPWATCH_H__ + diff --git a/components/esp32/include/xtensa/xos_syslog.h b/components/esp32/include/xtensa/xos_syslog.h new file mode 100755 index 0000000000..be56968fce --- /dev/null +++ b/components/esp32/include/xtensa/xos_syslog.h @@ -0,0 +1,330 @@ +/** @file */ + +// xos_syslog.h - XOS Event logging module. + +// Copyright (c) 2003-2015 Cadence Design Systems, Inc. +// +// Permission is hereby granted, free of charge, to any person obtaining +// a copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to +// permit persons to whom the Software is furnished to do so, subject to +// the following conditions: +// +// The above copyright notice and this permission notice shall be included +// in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +// CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +// SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +// NOTE: Do not include this file directly in your application. Including +// xos.h will automatically include this file. + + +#ifndef __XOS_SYSLOG_H__ +#define __XOS_SYSLOG_H__ + +#include "xos_types.h" + +#ifdef __cplusplus +extern "C" { +#endif + + +//----------------------------------------------------------------------------- +// The XOS system log is an array of fixed size entries. The size of the log +// is determined by the application, and memory for the log must be provided +// at init time. Every time the log function is called, an entry is made in +// the log and the next pointer advanced. When the log is full, it will wrap +// around and start overwriting the oldest entries. +// Logging can be done from C/C++ code as well as assembly code, and at any +// interrupt level, even from high level interrupt handlers. +//----------------------------------------------------------------------------- + + +//----------------------------------------------------------------------------- +// Defines. +//----------------------------------------------------------------------------- +#define XOS_SYSLOG_ENABLED 0x0001 + + +///---------------------------------------------------------------------------- +/// +/// Use this macro to compute how much memory to allocate for the syslog. +/// +///---------------------------------------------------------------------------- +#define XOS_SYSLOG_SIZE(num_entries) \ + ( sizeof(XosSysLog) + ((num_entries - 1) * sizeof(XosSysLogEntry)) ) + + +///---------------------------------------------------------------------------- +/// +/// System log entry structure. +/// +///---------------------------------------------------------------------------- +typedef struct XosSysLogEntry { + uint32_t timestamp; ///< Timestamp in clock cycles + uint32_t param1; ///< User defined value + uint32_t param2; ///< User defined value + struct XosSysLogEntry * next; ///< Link to next entry +} XosSysLogEntry; + + +///---------------------------------------------------------------------------- +/// +/// System log structure. +/// +///---------------------------------------------------------------------------- +typedef struct XosSysLog { + uint16_t flags; ///< Flags + uint16_t size; ///< Number of entries + XosSysLogEntry * next; ///< Next write position + XosSysLogEntry entries[1]; ///< First entry +} XosSysLog; + + +//----------------------------------------------------------------------------- +// Pointer to syslog area. +//----------------------------------------------------------------------------- +extern XosSysLog * xos_syslog; + + +//---------------------------------------------------------------------------- +/// +/// Initialize the syslog. Initializing the log also enables it. The system +/// log always wraps around when full and overwrites the oldest entries. +/// +/// \param log_mem Pointer to allocated memory for the log. +/// +/// \param num_entries The number of entries that the log can contain. +/// +/// \return Returns nothing. +/// +//---------------------------------------------------------------------------- +static inline void +xos_syslog_init(void * log_mem, uint16_t num_entries) +{ + uint16_t i; + + xos_syslog = (XosSysLog *) log_mem; + xos_syslog->size = num_entries; + xos_syslog->next = xos_syslog->entries; + + for (i = 0; i < num_entries - 1; i++) { + xos_syslog->entries[i].next = &(xos_syslog->entries[i+1]); + xos_syslog->entries[i].timestamp = 0; + } + xos_syslog->entries[i].next = xos_syslog->entries; + xos_syslog->entries[i].timestamp = 0; + + xos_syslog->flags = XOS_SYSLOG_ENABLED; +} + + +///---------------------------------------------------------------------------- +/// +/// Reset the syslog. All entries made up to now are abandoned and the write +/// pointer is set to the first entry location. +/// +/// No parameters. +/// +/// \return Returns nothing. +/// +///---------------------------------------------------------------------------- +static inline void +xos_syslog_clear() +{ +#if XCHAL_HAVE_INTERRUPTS + uint32_t ps = XT_RSIL(XCHAL_NUM_INTLEVELS); +#endif + + xos_syslog_init(xos_syslog, xos_syslog->size); +#if XCHAL_HAVE_INTERRUPTS + xos_restore_int_pri_level(ps); +#endif +} + + +///---------------------------------------------------------------------------- +/// +/// Enable logging to the syslog. This function needs to be called only if +/// logging had been previously disabled via xos_syslog_disable(), since +/// initializing the syslog automatically enables it. +/// +/// No parameters. +/// +/// \return Returns nothing. +/// +///---------------------------------------------------------------------------- +static inline void +xos_syslog_enable() +{ +#if XCHAL_HAVE_INTERRUPTS + uint32_t ps = XT_RSIL(XCHAL_NUM_INTLEVELS); +#endif + + xos_syslog->flags |= XOS_SYSLOG_ENABLED; +#if XCHAL_HAVE_INTERRUPTS + xos_restore_int_pri_level(ps); +#endif +} + + +///---------------------------------------------------------------------------- +/// +/// Disable logging to the syslog. It is sometimes useful to disable logging +/// while the log is being examined or dumped. +/// +/// No parameters. +/// +/// \return Returns nothing. +/// +///---------------------------------------------------------------------------- +static inline void +xos_syslog_disable() +{ +#if XCHAL_HAVE_INTERRUPTS + uint32_t ps = XT_RSIL(XCHAL_NUM_INTLEVELS); +#endif + xos_syslog->flags &= ~XOS_SYSLOG_ENABLED; +#if XCHAL_HAVE_INTERRUPTS + xos_restore_int_pri_level(ps); +#endif +} + + +///---------------------------------------------------------------------------- +/// +/// Write an entry into the syslog. This function does disable all interrupts +/// since logging can be done from interrupt handlers as well. It will write +/// into the log only if the log exists and is enabled. +/// +/// \param param1 User defined value. +/// +/// \param param2 User defined value. +/// +/// \return Returns nothing. +/// +///---------------------------------------------------------------------------- +static inline void +xos_syslog_write(uint32_t param1, uint32_t param2) +{ + if (xos_syslog != XOS_NULL) { +#if XCHAL_HAVE_INTERRUPTS + uint32_t ps = XT_RSIL(XCHAL_NUM_INTLEVELS); +#endif + + if ((xos_syslog->flags & XOS_SYSLOG_ENABLED) != 0) { + XosSysLogEntry * next = xos_syslog->next; + + next->timestamp = xos_get_ccount(); + next->param1 = param1; + next->param2 = param2; + + xos_syslog->next = next->next; + } + +#if XCHAL_HAVE_INTERRUPTS + xos_restore_int_pri_level(ps); +#endif + } +} + + +///---------------------------------------------------------------------------- +/// +/// Read the first (oldest) entry in the syslog. Will return an error if the +/// log has not been created or is empty. Storage to copy the entry must be +/// provided by the caller. +/// +/// \param entry Pointer to storage where the entry data will be +/// copied. This pointer must be passed to +/// xos_syslog_get_next(). +/// +/// \return Returns XOS_OK on success, else error code. +/// +///---------------------------------------------------------------------------- +static inline int32_t +xos_syslog_get_first(XosSysLogEntry * entry) +{ + if (xos_syslog == XOS_NULL) { + return XOS_ERR_NOT_FOUND; + } + + if (entry != XOS_NULL) { +#if XCHAL_HAVE_INTERRUPTS + uint32_t ps = XT_RSIL(XCHAL_NUM_INTLEVELS); +#endif + XosSysLogEntry * next = xos_syslog->next; + + // 'next' should be pointing to the next entry to be overwritten, if we + // have wrapped. This means it is the oldest entry. However if this entry + // has a zero timestamp then we have not wrapped, in which case we must + // look at the first entry in the list. + if (next->timestamp == 0) { + next = xos_syslog->entries; + } + + *entry = *next; +#if XCHAL_HAVE_INTERRUPTS + xos_restore_int_pri_level(ps); +#endif + return entry->timestamp ? XOS_OK : XOS_ERR_NOT_FOUND; + } + + return XOS_ERR_INVALID_PARAMETER; +} + + +///---------------------------------------------------------------------------- +/// +/// Get the next sequential entry from the syslog. This function must be called +/// only after xos_syslog_get_first() has been called. +/// +/// \param entry Pointer to storage where entry data will be copied. +/// Must be the same pointer that was passed in the call +/// to xos_syslog_get_first(), as it is used to keep track +/// of the current position. +/// +/// \return Returns XOS_OK on success, else error code. +/// +///---------------------------------------------------------------------------- +static inline int32_t +xos_syslog_get_next(XosSysLogEntry * entry) +{ + if (entry != XOS_NULL) { +#if XCHAL_HAVE_INTERRUPTS + uint32_t ps = XT_RSIL(XCHAL_NUM_INTLEVELS); +#endif + XosSysLogEntry * next = entry->next; + int32_t ret = XOS_OK; + + // Make sure we're not pointing past the last entry. + if ((next != XOS_NULL) && (next != xos_syslog->next) && (next->timestamp != 0)) { + *entry = *next; + } + else { + ret = XOS_ERR_NOT_FOUND; + } +#if XCHAL_HAVE_INTERRUPTS + xos_restore_int_pri_level(ps); +#endif + return ret; + } + + return XOS_ERR_INVALID_PARAMETER; +} + + +#ifdef __cplusplus +} +#endif + +#endif // __XOS_SYSLOG_H__ + diff --git a/components/esp32/include/xtensa/xos_thread.h b/components/esp32/include/xtensa/xos_thread.h new file mode 100755 index 0000000000..8bc5077eca --- /dev/null +++ b/components/esp32/include/xtensa/xos_thread.h @@ -0,0 +1,1086 @@ +/** @file */ + +// xos_thread.h - XOS Thread API interface and data structures. + +// Copyright (c) 2003-2015 Cadence Design Systems, Inc. +// +// Permission is hereby granted, free of charge, to any person obtaining +// a copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to +// permit persons to whom the Software is furnished to do so, subject to +// the following conditions: +// +// The above copyright notice and this permission notice shall be included +// in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +// CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +// SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +// NOTE: Do not include this file directly in your application. Including +// xos.h will automatically include this file. + + +#ifndef __XOS_THREAD_H__ +#define __XOS_THREAD_H__ + +#ifdef __cplusplus +extern "C" { +#endif + +#include "xos_types.h" +#include "xos_params.h" + + +//----------------------------------------------------------------------------- +// Number of thread priority levels. +//----------------------------------------------------------------------------- +#ifndef XOS_NUM_PRIORITY +#error "XOS_NUM_PRIORITY must be defined (in xos_params.h)." +#endif +#if XOS_NUM_PRIORITY > 32 +#error "The number of thread priority levels (XOS_NUM_PRIORITY) must be <= 32." +#endif +#define XOS_MAX_PRIORITY (XOS_NUM_PRIORITY) + + +//----------------------------------------------------------------------------- +// Macro for thread self pointer. +//----------------------------------------------------------------------------- +#define XOS_THREAD_SELF (xos_thread_id()) + + +//----------------------------------------------------------------------------- +/// +/// Thread entry function pointer type. +/// +//----------------------------------------------------------------------------- +typedef int32_t (XosThreadFunc)(void * arg, int32_t wake_value); + + +//----------------------------------------------------------------------------- +// Thread switcher function signature. +//----------------------------------------------------------------------------- +typedef struct XosThread XosThread; +typedef int32_t (XosSwitchFunc)(XosThread *); + + +//----------------------------------------------------------------------------- +/// +/// Condition evaluation callback function pointer type. +/// +//----------------------------------------------------------------------------- +typedef int32_t (XosCondFunc)(void * arg, int32_t sig_value, XosThread * thread); + + +//----------------------------------------------------------------------------- +/// +/// Thread exit handler function pointer type. +/// +//----------------------------------------------------------------------------- +typedef int32_t (XosThdExitFunc)(int32_t exitcode); + + +//----------------------------------------------------------------------------- +// Thread queue structure. Used to implement the ready queues as well +// as the wait queues. +//----------------------------------------------------------------------------- +typedef struct XosThreadQueue { + XosThread * head; // Pointer to first thread in queue, or 0 if none. + XosThread ** tail; // Pointer to last thread's r_next pointer, or + // to "head" if none. +} XosThreadQueue; + + +//----------------------------------------------------------------------------- +// Stack frame for a thread that is not running. That is, it has either +// been preempted or has yielded. +//----------------------------------------------------------------------------- +typedef union XosFrame { + XosExcFrame e; // resume_fn == &xos_resume_preempted_thread + XosCoopFrame c; // resume_fn == &xos_resume_cooperative_thread + // nothing for resume_fn == &xos_resume_idle_thread + // nothing for resume_fn == &xos_resume_by_restart +} XosFrame; + + +//----------------------------------------------------------------------------- +// Thread Control Block. Tracks the state and control information associated +// with a thread. +// +// IMPORTANT: keep this in sync with TCB_*** offsets in xos_common.h . +//----------------------------------------------------------------------------- +struct XosThread { + XosThread * r_next; // 00 Next thread in queue (eg. ready queue of + // its priority, or some queue of blocked threads) + // Should be NULL if not in any queue. + + XosThread ** r_pprev; // 04 Points to previous queue entry's r_next + // pointer (i.e. to itself), or to queue head + // if first in queue. NULL if not in any queue. + + XosThread * all_next; // 08 Next in list of all threads. + + void * resume_fn; // 12 Pointer to the routine to be called to + // resume this thread. On entry to such code: + // a2 == xos_curr_threadptr (thread being resumed) + // a3 == &xos_globals + + XosFrame * esf; // 16 Pointer to saved exception stack frame, + // just below thread's current stack pointer. + // For RTC threads, this is valid only while the + // thread is preempted, not when it is blocked. + + void * tie_save; // 20 TIE state save area. May be NULL if there + // is not TIE state saved for this thread. + + int32_t wake_value; // 24 Value returned from block call (by wake call) + // (for RTC: pass this to start function??) + + XosSwitchFunc * switch_fn; // 28 Pointer to a function that + // can be called from within this thread, to save + // this thread's state and switch to a specified + // other thread. Returns wake value. + + void * stack_base; // 32 Base of stack as specified by thread creator. + + void * stack_end; // 36 End of stack (adjusted for TIE state save area + // if any). + + XosThreadFunc * entry; // 40 Pointer to thread entry function. Used for + // RTC thread restart. + + void * arg; // 44 Argument value passed to entry function. + + bool ready; // 48 Set when thread is ready to run, and is in + // its priority queue (i.e. r_pprev is set when + // this flag is set). + + bool in_exit; // Exit flag, nonzero when in exit processing. + + int8_t priority; // Thread priority, 0 .. (XOS_MAX_PRI - 1). Higher + // numbers have higher priority. This must only be + // changed when thread is not ready, or by calling + // xos_thread_set_priority(). + + int8_t preempt_pri; // This thread's preemption blocking priority. + // (preempt_pri >= priority). A thread's priority + // must be higher than another's preempt_pri to be + // able to preempt it. Note that preempt_pri can + // change during runtime e.g. due to priority + // inheritance. + + uint32_t flags; // 52 Thread creation flags. + + const char * name; // 56 Thread name (mainly for debug). + + const char * block_cause; // 60 Reason for blocking. Valid only when thread + // not ready (r_pprev == 0). + + XosThread * container; // 64 Thread whose stack will be used to run + // this thread. Valid for RTC threads only, else NULL. + + XosThdExitFunc * exit_func; // 68 Thread exit handler function pointer. + + XosThreadQueue exit_waiters; // 72 Queue of threads waiting for this one to exit. + + XosThreadQueue * wq_ptr; // 80 If this thread is in a wait queue, this + // points to the queue. Must be NULL when + // thread not in a queue. + + XosCondFunc * cond_fn; // 84 Condition function. Valid only while thread + // is blocked on condition. + + void * cond_arg; // 88 Argument to be passed to condition function. + + uint16_t cp_mask; // 92 Mask of coprocessors used. + uint16_t cp_saved; // 94 Mask of coprocessors saved. + + uint32_t event_bits; // 96 event bits + uint32_t event_mask; // 100 event bit mask + uint32_t event_flags; // 104 event flags + + void * clib_ptr; // 108 Pointer to C lib context struct. + + uint32_t sig; // 112 Signature of valid TCB + + uint32_t resume_ccount; // 116 cycle count at resume + uint64_t cycle_count; // 120 number of cycles consumed (approx). + // NOTE: must be 8-byte aligned + uint32_t normal_resumes; // 128 Number of non-preemptive resumptions. + uint32_t preempt_resumes;// 132 Number of preemptive resumptions. + +#if XOS_OPT_THREAD_SAFE_CLIB + CLIB_THREAD_STRUCT; // C library context area. +#endif +}; + + +//----------------------------------------------------------------------------- +// User-visible flags for xos_thread_create(). +//----------------------------------------------------------------------------- +#define XOS_THREAD_SUSPEND 0x0001 ///< Create suspended instead of ready +#define XOS_THREAD_RTC 0x0002 ///< Run-to-completion thread +#define XOS_THREAD_NO_CP 0x0004 ///< Thread does not use coprocessors + + +//----------------------------------------------------------------------------- +// Flags used by thread creation extra parameters. +//----------------------------------------------------------------------------- +#define XOS_TP_COPROC_MASK 0x0001 +#define XOS_TP_PREEMPT_PRI 0x0002 +#define XOS_TP_EXIT_HANDLER 0x0004 + + +//----------------------------------------------------------------------------- +// Thread creation extra parameters. +//----------------------------------------------------------------------------- +typedef struct XosThreadParm { + uint32_t parms_mask; // Combination of XOS_TP_xxx flags indicating + // which parameters are valid. + + uint16_t cp_mask; // Mask of coprocessors the thread can access. + + uint32_t preempt_pri; // Initial preemption blocking priority. Can be + // changed later via xos_thread_set_priority(). + + XosThdExitFunc * handler; // Exit handler function. + +} XosThreadParm; + + +//----------------------------------------------------------------------------- +// Wrapper struct for RTC (run to completion) thread. +//----------------------------------------------------------------------------- +typedef struct XosRtcThread { + struct XosThread thread; +} XosRtcThread; + + +//----------------------------------------------------------------------------- +// External variables. +//----------------------------------------------------------------------------- +extern XosThread * xos_curr_threadptr; // Current active thread +extern XosThread * xos_next_threadptr; // Next ready thread +extern XosThread * xos_all_threads; // List of all threads + + +//----------------------------------------------------------------------------- +/// +/// Set thread creation parameter: the group of coprocessors that this thread +/// will use. This must be set during thread creation, and cannot be changed +/// after the thread has been created. Defining this allows reduction of +/// memory usage (for CP state saving) in some circumstances, and can also +/// speed up the context switch time. +/// +/// NOTE: Support for this is not currently implemented. If a thread uses +/// any coprocessor, space for all coprocessors must be reserved. +/// +/// \param parms Thread creation parameter structure. Must be +/// allocated by the caller. +/// +/// \param cp_mask Bitmask of coprocessors thread is allowed to +/// use. Bit 0 for coprocessor 0, etc. +/// +/// \return Returns nothing. +/// +//----------------------------------------------------------------------------- +static inline void +xos_threadp_set_cp_mask(XosThreadParm * parms, uint16_t cp_mask) +{ + if (parms != XOS_NULL) { + parms->parms_mask |= XOS_TP_COPROC_MASK; + parms->cp_mask = cp_mask; + } +} + + +//----------------------------------------------------------------------------- +/// +/// Set thread creation parameter: thread pre-emption priority. +/// +/// \param parms Thread creation parameter structure. Must be +/// allocated by caller. +/// +/// \param preempt_pri Thread pre-emption blocking priority. +/// From 0 .. XOS_NUM_PRIORITY - 1. +/// Must be greater or equal to the thread priority +/// (if not, is automatically set to thread priority). +/// +/// \return Returns nothing. +/// +//----------------------------------------------------------------------------- +static inline void +xos_threadp_set_preemption_priority(XosThreadParm * parms, int8_t preempt_pri) +{ + if (parms != XOS_NULL) { + parms->parms_mask |= XOS_TP_PREEMPT_PRI; + parms->preempt_pri = preempt_pri; + } +} + + +//----------------------------------------------------------------------------- +/// +/// Set thread creation parameter: thread exit handler. +/// +/// \param parms Thread creation parameter structure. Must be +/// allocated by caller. +/// +/// \param handler Exit handler function. +/// +/// \return Returns nothing. +//----------------------------------------------------------------------------- +static inline void +xos_threadp_set_exit_handler(XosThreadParm * parms, XosThdExitFunc * handler) +{ + if (parms != XOS_NULL) { + parms->parms_mask |= XOS_TP_EXIT_HANDLER; + parms->handler = handler; + } +} + + +//----------------------------------------------------------------------------- +/// +/// Create a new thread. If the thread is not created suspended, then it will +/// be made ready as soon as it is created, and will immediately run if it is +/// the highest priority non-blocked thread in the system. +/// +/// \param thread Pointer to the thread descriptor (an otherwise +/// unused XosThread structure, usually allocated +/// by the caller for the lifetime of the thread, +/// for example as a global variable). +/// +/// \param container Pointer to separate thread acting as "container" +/// for this one. At the moment, this is only meaningful +/// for run-to-completion (RTC) threads (identified with +/// the XOS_THREAD_RTC flag), in which case the container +/// must have the same priority and also be an RTC thread. +/// (The priority restriction may be lifted in a future +/// implementation, with appropriate constraints on dynamic +/// reprioritization of the created thread). +/// +/// \param entry Thread entry function, takes one argument. +/// +/// \param arg Argument "void*" that is passed to the thread function. +/// +/// \param name Unique name of the thread, for debug/display purposes. +/// This string must be valid for the lifetime of the thread +/// (only a pointer to it is stored in the thread control block). +/// Typically consists of identifier chars with no spaces. +/// +/// \param stack Base of initial stack for the thread, allocated by the +/// caller. Need not be aligned (initial stack pointer will be +/// computed and aligned from given stack base and size). +/// Required argument, except for run-to-completion threads +/// when container is non-NULL, in which case the container's +/// stack is used and this argument must be NULL. +/// +/// \param stack_size Size of the stack, in bytes. +/// NOTE: stack should be at least XOS_STACK_EXTRA bytes plus +/// whatever the thread actually needs if the thread will use +/// coprocessors/TIE state. If the thread will not touch the +/// coprocessors, then it should be XOS_STACK_EXTRA_NO_CP +/// plus whatever the thread actually needs. +/// Recommended minimum stack sizes are defined by the constants +/// XOS_STACK_MIN_SIZE and XOS_STACK_MIN_SIZE_NO_CP. +/// +/// For run-to-completion threads where container is non-NULL, +/// stack_size specifies the minimum stack size required for +/// the thread; it should be smaller or equal to the container's +/// stack. +/// +/// \param priority Initial thread priority. From 0 .. XOS_MAX_PRI - 1. +/// Higher numbers are higher priority. +/// +/// \param parms Pointer to extra parameters structure, or 0 if none given. +/// Use xos_thread_p_***() functions to set parameters in the +/// structure. +/// +/// \param flags Option flags: +/// - XOS_THREAD_SUSPEND -- Leave thread suspended instead of +/// making it ready. The thread can be made ready to run later +/// by calling xos_thread_resume(). +/// - XOS_THREAD_RTC -- Run-to-completion thread. +/// - XOS_THREAD_NO_CP -- Thread does not use coprocessors. +/// No coprocessor state will be saved for this thread. +/// Threads that have this flag set will not allocate any +/// storage for saving coprocessor state and so can have +/// smaller stacks. +/// +/// NOTE: xos_start_main() calls xos_thread_create() to convert main() into the 'main' +/// thread. +/// +/// \return Returns XOS_OK if successful, error code otherwise. +/// +//----------------------------------------------------------------------------- +int32_t +xos_thread_create(XosThread * thread, + XosThread * container, + XosThreadFunc * entry, + void * arg, + const char * name, + void * stack, + uint32_t stack_size, + int32_t priority, + XosThreadParm * parms, + uint32_t flags ); + + +//----------------------------------------------------------------------------- +/// +/// Remove thread and free up all resources. Thread must have exited already. +/// After this call returns, all resources allocated to the thread (e.g. TCB, +/// stack space, etc.) can be reused. +/// +/// \param thread Handle of thread to be deleted. +/// +/// \return Returns XOS_OK on success, else error code. +/// +/// NOTE: A thread cannot call this on itself. +/// +//----------------------------------------------------------------------------- +int32_t +xos_thread_delete(XosThread * thread); + + +//----------------------------------------------------------------------------- +/// +/// Force the thread to terminate. The thread execution is aborted, but exit +/// processing will still happen, i.e. the exit handler (if any) will be run. +/// After termination, any other threads waiting on this thread are notified. +/// This function cannot be called on the current thread. +/// +/// \param thread Handle of thread to be aborted. +/// +/// \param exitcode Exit code returned to any waiting threads. +/// +/// \return Returns XOS_OK on success, else error code. +/// +/// NOTE: If the thread is blocked waiting for something, the wait is aborted +/// and the thread is made ready. +/// NOTE: The thread is not guaranteed to have exited when this call returns. +/// It will be made ready and set up for exit processing, but when the exit +/// processing will actually happen depends on the state of the system and +/// the priority of the thread being aborted. +/// +//----------------------------------------------------------------------------- +int32_t +xos_thread_abort(XosThread * thread, int32_t exitcode); + + +//----------------------------------------------------------------------------- +/// +/// Exit the current thread. The exit handler (if any) will be run before the +/// thread terminates. +/// +/// \param exitcode Exit code to be returned to any waiting threads. +/// +/// \return This function does not return. +/// +/// NOTE: This is automatically called if the thread returns from its entry +/// function. The entry function's return value will be passed as the exit +/// code. +/// +//----------------------------------------------------------------------------- +void +xos_thread_exit(int32_t exitcode); + + +//----------------------------------------------------------------------------- +/// +/// Wait until the specified thread exits and get its exit code. If the thread +/// has exited already, an error will be returned. +/// +/// \param thread The thread to wait for. Cannot be "self", i.e. +/// one cannot wait on one's own exit. +/// +/// \param p_exitcode If not null, the exit code will be returned here. +/// +/// \return Returns XOS_OK on sucess, else error code. +/// +//----------------------------------------------------------------------------- +int32_t +xos_thread_join(XosThread * thread, int32_t * p_exitcode); + + +//----------------------------------------------------------------------------- +/// +/// Yield the CPU to the next thread in line. The calling thread remains ready +/// and is placed at the tail of the ready queue at its current priority level. +/// If there are no threads at the same priority level that are ready to run, +/// then this call will return immediately. +/// +/// \return Returns nothing. +/// +//----------------------------------------------------------------------------- +void +xos_thread_yield(); + + +//----------------------------------------------------------------------------- +/// +/// Suspend the specified thread. The thread will remain suspended until +/// xos_thread_resume() has been called on it. If the thread is already blocked +/// on some other condition, then this function will return an error. +/// +/// \param thread Handle of thread being suspended. A thread can +/// use the special handle XOS_THREAD_SELF to suspend +/// itself. +/// +/// \return Returns XOS_OK on success, else error code. +/// +//----------------------------------------------------------------------------- +int32_t +xos_thread_suspend(XosThread * thread); + + +//----------------------------------------------------------------------------- +/// +/// Resume a suspended thread. If the thread is not suspended or is blocked on +/// some other condition then this function will do nothing. Otherwise, it will +/// be made ready, and this can cause an immediate context switch if the thread +/// is at a higher priority than the calling thread. +/// +/// \param thread Handle of thread being resumed. +/// +/// \return Returns XOS_OK on success, else error code. +/// +//----------------------------------------------------------------------------- +int32_t +xos_thread_resume(XosThread * thread); + + +//----------------------------------------------------------------------------- +/// +/// Get the priority of the specified thread. This returns the priority of the +/// queried thread at this instant, however this can change at any time due to +/// other activity in the system. +/// +/// \param thread Handle of thread being queried. A thread can use +/// the special handle XOS_THREAD_SELF to query itself. +/// +/// \return Returns the thread's current priority, or -1 if the thread handle +/// is not valid. +/// +//----------------------------------------------------------------------------- +static inline int32_t +xos_thread_get_priority(XosThread * thread) +{ + XOS_ASSERT(thread); + return thread ? thread->priority : -1; +} + + +//----------------------------------------------------------------------------- +/// +/// Set the priority of the specified thread. The thread must exist. +/// +/// \param thread Handle of thread being affected. A thread can +/// use the special handle XOS_THREAD_SELF to specify +/// itself. +/// +/// \param priority The new priority level to be set. +/// +/// \return Returns XOS_OK on success, else error code. +/// +/// NOTE: Calling this function can result in a scheduler activation, and the +/// caller may be suspended as a result. +/// +//----------------------------------------------------------------------------- +int32_t +xos_thread_set_priority(XosThread * thread, int32_t priority); + + +//----------------------------------------------------------------------------- +/// +/// Return the name of the specified thread. +/// +/// \param thread Handle of thread being queried. A thread can use +/// the special handle XOS_THREAD_SELF to specify +/// itself. +/// +/// \return Returns a pointer to the name string if available, else NULL. +/// +//----------------------------------------------------------------------------- +static inline const char * +xos_thread_get_name(XosThread * thread) +{ + XOS_ASSERT(thread); + return thread ? thread->name : 0; +} + + +//----------------------------------------------------------------------------- +/// +/// Set the name of the specified thread. +/// +/// \param thread Handle of thread whose name is to be set. A thread +/// can use the special handle XOS_THREAD_SELF to specify +/// itself. +/// +/// \param name Pointer to the new name string. The string is not +/// copied, only the pointer is saved. So the string +/// must be persistent for the life of the thread. +/// +/// \return Returns XOS_OK on success, else error code. +/// +//----------------------------------------------------------------------------- +static inline int32_t +xos_thread_set_name(XosThread * thread, const char * name) +{ + XOS_ASSERT(thread); + if (thread != XOS_NULL) { + thread->name = name; + return XOS_OK; + } + + return XOS_ERR_INVALID_PARAMETER; +} + + +//----------------------------------------------------------------------------- +/// +/// Set an exit handler for the specified thread. The exit handler is run when +/// the thread terminates, either by calling xos_thread_exit() or by returning +/// from its entry function. It will also be called if the thread is being +/// terminated due to e.g. an unhandled exception. +/// +/// The handler must be a function defined as e.g.: +/// +/// int32_t exit_handler(int32_t exitcode); +/// +/// The exit handler runs in the context of the exiting thread, and can call +/// system services. It is provided with a single parameter which is the +/// thread's exit code (the exit code may be set to an error code if the +/// thread is being terminated due to an error or exception). The handler +/// must return a value which will be set as the thread's exit code. +/// +/// \param thread Handle of the thread for which the handler is +/// to be installed. A thread can use the special +/// handle XOS_THREAD_SELF to specify itself. +/// +/// \param func Pointer to exit handler function. To clear an +/// existing handler, pass NULL as the pointer. +/// +/// \return Returns XOS_OK on success, else error code. +/// +//----------------------------------------------------------------------------- +int32_t +xos_thread_set_exit_handler(XosThread * thread, XosThdExitFunc * func); + + +//----------------------------------------------------------------------------- +/// +/// Return the ID (handle) of the current thread. +/// +/// \return Returns the handle of the current thread. This handle can be +/// used in all XOS system calls. +/// +/// NOTE: If called from interrupt context, returns the handle of the thread +/// that was preempted. +/// +//----------------------------------------------------------------------------- +static inline XosThread * +xos_thread_id() +{ + return xos_curr_threadptr; +} + + +//----------------------------------------------------------------------------- +/// +/// Return the coprocessor mask for the specified thread. +/// +/// \param thread Handle of thread being queried. +/// +/// \return Returns the mask for the specified thread if available, else 0. +/// +//----------------------------------------------------------------------------- +static inline uint16_t +xos_thread_cp_mask(XosThread * thread) +{ + XOS_ASSERT(thread); + return thread ? thread->cp_mask : 0; +} + + +//----------------------------------------------------------------------------- +/// +/// Return the wake value for the specified thread. +/// +/// \return thread Handle of thread being queried. +/// +/// \return Returns The last set wake value. There is no way to detect what +/// action set the wake value and when. +/// +//----------------------------------------------------------------------------- +static inline int32_t +xos_thread_get_wake_value(XosThread * thread) +{ + XOS_ASSERT(thread); + return thread ? thread->wake_value : 0; +} + + +//----------------------------------------------------------------------------- +/// +/// Return the current value of the event bits for the current thread. +/// This function takes no parameters. +/// +/// \return Returns the current value of the event bits. The event bits +/// are set when the thread is woken from an event wait. They will +/// not change while the thread is running. There is no way to +/// determine when the event bits were last updated. +/// +//----------------------------------------------------------------------------- +static inline uint32_t +xos_thread_get_event_bits(void) +{ + XosThread * thread = xos_thread_id(); + return thread ? thread->event_bits : 0; +} + + +//----------------------------------------------------------------------------- +/// +/// Enum values for thread state. +/// +//----------------------------------------------------------------------------- +typedef enum xos_thread_state_t { + XOS_THREAD_STATE_INVALID = 0, ///< Invalid thread + XOS_THREAD_STATE_BLOCKED, ///< Thread is blocked + XOS_THREAD_STATE_READY, ///< Thread is ready to run + XOS_THREAD_STATE_RUNNING, ///< Thread is running + XOS_THREAD_STATE_EXITED, ///< Thread has exited +} xos_thread_state_t; + + +//----------------------------------------------------------------------------- +/// +/// Return the state of the specified thread. +/// +/// \param thread Handle of thread being queried. +/// +/// \return Returns one of the following values: +/// - XOS_THREAD_STATE_RUNNING -- The thread is currently running. +/// - XOS_THREAD_STATE_READY -- The thread is ready to run. +/// - XOS_THREAD_STATE_BLOCKED -- The thread is blocked on something. +/// - XOS_THREAD_STATE_INVALID -- The thread handle is invalid. +/// - XOS_THREAD_STATE_EXITED -- The thread has exited. +/// +//----------------------------------------------------------------------------- +xos_thread_state_t +xos_thread_get_state(XosThread * thread); + + +//----------------------------------------------------------------------------- +/// +/// Disable thread preemption. Prevents context switching to another thread. +/// However, interrupt handlers will still continue to be run. Multiple calls +/// will nest, and the same number of calls to xos_preemption_enable() will be +/// required to re-enable preemption. If the calling thread yields the CPU or +/// exits without enabling preemption, it will cause a system halt. +/// If the calling thread encounters a fatal error, preemption will be enabled +/// during fatal error handling. +/// +/// \return Returns the new value of preemption disable flag after this call. +/// +/// NOTE: Cannot be called from interrupt context. +/// +//----------------------------------------------------------------------------- +uint32_t +xos_preemption_disable(void); + + +//----------------------------------------------------------------------------- +/// +/// Enable thread preemption. Has no effect if preemption was already enabled. +/// Otherwise, it decrements the value of the preemption disable flag and if +/// the value goes to zero, enables preemption. +/// +/// \return Returns the new value of preemption disable flag after this call. +/// +/// NOTE: If scheduling gets enabled, it may cause an immediate context switch +/// if higher priority threads are ready. +/// +//----------------------------------------------------------------------------- +uint32_t +xos_preemption_enable(void); + + +//----------------------------------------------------------------------------- +/// +/// Initialize XOS thread support and start scheduler. +/// +/// Must be called from main() before calling any other thread function. +/// This function initializes thread support, creates the idle thread, and +/// starts the scheduler. It does not return to its caller. This means that +/// at least one user thread must be created before calling xos_start(). +/// Otherwise, the scheduler will run the idle thread since it will be the +/// only thread in the system, and no other thread can be created. +/// +/// NOTE: This function does not initialize timer/tick support. For timer +/// services to be available xos_start_system_timer() must be called. +/// +/// NOTE: xos_start() and xos_start_main() are exclusive, both cannot be +/// called within the same application. +/// +/// \param flags Currently unused (pass 0). +/// +/// \return Does not return. +/// +//----------------------------------------------------------------------------- +void +xos_start(uint32_t flags); + + +//----------------------------------------------------------------------------- +/// +/// Initialize XOS thread support and create init (main) thread. +/// +/// Must be called from main() before calling any other thread function. +/// This function converts the caller into the 'main' or 'init' thread, and +/// returns to the caller after completing initialization. +/// +/// NOTE: This function does not initialize timer/tick support. For timer +/// services to be available xos_start_system_timer() must be called. +/// +/// NOTE: xos_start_main() and xos_start() are exclusive, both cannot be +/// called within the same application. +/// +/// \param name Name of main thread (see xos_thread_create()). +/// +/// \param priority Initial priority of main thread. +/// +/// \param flags Currently unused (pass 0). +/// +/// \return Returns nothing. +/// +//----------------------------------------------------------------------------- +void +xos_start_main(const char * name, int8_t priority, uint32_t flags); + + +//----------------------------------------------------------------------------- +/// +/// Per-thread stats structure. +/// Note that the CPU use % is approximate, both because of cycle counting +/// and because of integer division. So all the threads' CPU % will not add +/// up to exactly 100%. +/// +//----------------------------------------------------------------------------- +typedef struct XosThreadStats { + XosThread * thread; ///< Thread handle (or pseudo-handle) + uint32_t cpu_pct; ///< CPU use % for this thread + uint32_t normal_switches; ///< Number of non-preemptive switches. + uint32_t preempt_switches; ///< Number of preemptive switches. + uint64_t cycle_count; ///< Number of cycles consumed. +} XosThreadStats; + + +//----------------------------------------------------------------------------- +// Thread pseudo-handles. +//----------------------------------------------------------------------------- +#define XOS_THD_STATS_IDLE ((XosThread *) 1) +#define XOS_THD_STATS_INTR ((XosThread *) 2) + + +//----------------------------------------------------------------------------- +/// +/// Get the thread statistics for the specified thread. Statistics are only +/// available if XOS_OPT_STATS has been enabled. Otherwise, the function +/// will return XOS_OK, but the structure contents will be undefined. +/// +/// \param thread Handle of thread being queried. The following +/// special pseudo-handles can be used: +/// - XOS_THD_STATS_IDLE -- stats for idle thread +/// - XOS_THD_STATS_INTR -- stats for interrupt processing +/// +/// \param stats Pointer to XosThreadStats struct to be filled in. +/// +/// \return Returns XOS_OK on success, else error code. +/// +/// NOTE: Can be called from interrupt context. +/// NOTE: This call will not fill in the "thread" and "cpu_pct" fields in the +/// "stats" structure. The thread handle is already known, and calculating the +/// CPU loading can take quite a bit of time so is not done here. +/// +//----------------------------------------------------------------------------- +int32_t +xos_thread_get_stats(XosThread * thread, XosThreadStats * stats); + + +//----------------------------------------------------------------------------- +/// +/// Get CPU loading statistics for the system. This function computes the CPU +/// percentage use for all threads in the system (including the idle thread and +/// the 'interrupt thread' (interrupt context). It also returns the cycle count +/// and number of context switches for each thread. +/// Statistics are only available if XOS_OPT_STATS has been enabled. +/// Otherwise, the function will return XOS_OK, but the structure contents will +/// be undefined. +/// +/// IMPORTANT: The entry for interrupt context does not contain a real thread +/// handle. It uses the pseudo-handle XOS_THD_STATS_INTR to indicate that this +/// entry reports interrupt statistics. This pseudo-handle cannot be used for +/// any other thread operations or queries. +/// +/// NOTE: This function disables interrupts while traversing the thread list. +/// It does not leave interrupts disabled during the computations, as that can +/// take a fair amount of time. +/// +/// \param stats Pointer to an array of XosThreadStats structures. +/// The array must be large enough to accommodate all +/// threads in the system. +/// +/// \param size The number of elements available in the array. If +/// this is smaller than the number of threads plus one +/// (for the interrupt context) then XOS_ERR_INVALID_PARAMETER +/// will be returned and '*size' will be set to the +/// minimum number of elements required. On a successful +/// return, '*size' is set to the number of elements +/// actually filled in. +/// +/// \param reset If nonzero, then thread stats counters are reset +/// after reading. This is useful if you want to track +/// the stats so as to get a better idea of current +/// system loading. E.g. calling this function once a +/// second with 'reset' nonzero will provide CPU load +/// information for the last second on each call. +/// +/// \return Returns XOS_OK on success, else error code. In particular, +/// XOS_ERR_INVALID_PARAMETER will be returned if the output buffer +/// is too small. +/// +//----------------------------------------------------------------------------- +int32_t +xos_get_cpu_load(XosThreadStats * stats, int32_t * size, int32_t reset); + + +#ifdef _XOS_INCLUDE_INTERNAL_ + +// Signature of valid thread object +#define XOS_THREAD_SIG 0x54485244 + + +// Extern functions +void +xos_init(void); + +bool +xos_init_done(void); + +bool +xos_started(void); + +int32_t +xos_schedule(XosThread * curr_thread); + +void +xos_q_remove(XosThreadQueue * queue, XosThread * thread); + +XosThread * +xos_q_pop(XosThreadQueue * queue); + +int32_t +xos_wake_queue(XosThreadQueue * queue, const char * expected_cause, int32_t wake_value); + +// Well known block causes +extern const char * const xos_blkon_idle; // (for idle thread only) +extern const char * const xos_blkon_suspend; +extern const char * const xos_blkon_delay; +extern const char * const xos_blkon_exited; +extern const char * const xos_blkon_join; +extern const char * const xos_blkon_event; +extern const char * const xos_blkon_condition; +extern const char * const xos_blkon_mutex; +extern const char * const xos_blkon_sem; +extern const char * const xos_blkon_msgq; + + +//----------------------------------------------------------------------------- +// Blocks the current active thread. +// +// Currently, this can be called from an interrupt handler to block the thread +// that was interrupted. Note that in interrupt context the current thread can +// already be in the blocked state, due to a previous call to this function. +// Can be called with interrupts enabled. +// +// block_cause Reason for blocking. +// +// block_queue Queue on to which this thread should be pushed once it +// is blocked. Can be NULL. +// +// must_schedule If nonzero, then forces a scheduling operation to pick +// the next thread to run, even if there are ready threads +// at the same priority level as the blocked thread. +// +// use_priority If nonzero, then the blocked thread will be queued in +// priority order in the specified block queue. If zero, +// the thread is queued in FIFO order. If no queue has +// been specified, this parameter is ignored. +// +// Returns: The value passed by xos_thread_wake(). +//----------------------------------------------------------------------------- +int32_t +xos_block(const char * block_cause, + XosThreadQueue * block_queue, + int32_t must_schedule, + int32_t use_priority); + + +//----------------------------------------------------------------------------- +// Unblocks the specified blocked thread and puts it at the tail end of its +// ready queue. Schedules it if it is higher priority than the current thread. +// No effect if the thread is not blocked with the specified cause. +// +// thread The thread to wake up (make ready). +// +// expected_cause The expected block cause of the thread. Thread will be +// woken only if its block cause matches this cause, or if +// expected_cause is zero. +// +// wake_value The value to be passed to the woken thread as a return +// value from xos_thread_block(). +// +// Returns: nothing. +// +// The target thread can be woken at a different priority by changing its +// priority while the thread is blocked. +// Can be called with interrupts enabled. Can be called in interrupt context. +//----------------------------------------------------------------------------- +void +xos_thread_wake(XosThread * thread, const char * expected_cause, int32_t wakevalue); + + +//----------------------------------------------------------------------------- +// Function to init C library per-thread and reentrancy support. +//----------------------------------------------------------------------------- +#if XOS_OPT_THREAD_SAFE_CLIB +void +xos_clib_init(void); + +void +xos_clib_thread_init(XosThread * thread); + +void +xos_clib_thread_cleanup(XosThread * thread); +#endif + +#endif + + +#ifdef __cplusplus +} +#endif + +#endif // __XOS_THREAD_H__ + diff --git a/components/esp32/include/xtensa/xos_timer.h b/components/esp32/include/xtensa/xos_timer.h new file mode 100755 index 0000000000..0d89a21929 --- /dev/null +++ b/components/esp32/include/xtensa/xos_timer.h @@ -0,0 +1,592 @@ +/** @file */ + +// xos_timer.h - XOS Timer API interface and data structures. + +// Copyright (c) 2003-2015 Cadence Design Systems, Inc. +// +// Permission is hereby granted, free of charge, to any person obtaining +// a copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to +// permit persons to whom the Software is furnished to do so, subject to +// the following conditions: +// +// The above copyright notice and this permission notice shall be included +// in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +// CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +// SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +// NOTE: Do not include this file directly in your application. Including +// xos.h will automatically include this file. + + +#ifndef __XOS_TIMER_H__ +#define __XOS_TIMER_H__ + +#include "xos_types.h" + +#ifdef __cplusplus +extern "C" { +#endif + + +//----------------------------------------------------------------------------- +/// +/// Function pointer type for timer callbacks. +/// +//----------------------------------------------------------------------------- +typedef void (XosTimerFunc)(void * arg); + + +//----------------------------------------------------------------------------- +/// +/// Timer event structure. Used to track pending timer events. +/// +//----------------------------------------------------------------------------- +typedef struct XosTimer { + struct XosTimer * next; ///< Pointer to next event in list. + uint64_t when; ///< Time (clock cycles) at which to trigger. + uint64_t delta; ///< Delta for next re-trigger, 0 if none. + XosTimerFunc * fn; ///< Function to call when timer expires. + void * arg; ///< Argument to pass to called function. + bool active; ///< Set if active (in some list of events). +#if XOS_OPT_TIMER_WAIT + XosThreadQueue waitq; ///< Queue of threads waiting on this timer. +#endif +#if XOS_TIMER_DEBUG + uint32_t signature; +#endif +} XosTimer; + + +//----------------------------------------------------------------------------- +// Extern declarations. +//----------------------------------------------------------------------------- + +// System clock frequency in cycles per second. +extern uint32_t xos_clock_freq; + + +///@{ +//----------------------------------------------------------------------------- +// Functions to convert from clock cycles to time units and vice versa. +// +// Note that these are integer conversions so for example a cycle count of less +// than one second will convert to zero seconds. +//----------------------------------------------------------------------------- + +/// Converts CPU cycles to time in seconds. +/// +/// \param cycles Number of CPU cycles. +/// +/// \return Equivalent number of seconds (truncated to integer). +static inline uint64_t +xos_cycles_to_secs(uint64_t cycles) +{ + return cycles / xos_clock_freq; +} + +/// Converts CPU cycles to time in milliseconds. +/// +/// \param cycles Number of CPU cycles. +/// +/// \return Equivalent number of milliseconds (truncated to integer). +static inline uint64_t +xos_cycles_to_msecs(uint64_t cycles) +{ + return (cycles * 1000) / xos_clock_freq; +} + +/// Converts CPU cycles to time in microseconds. +/// +/// \param cycles Number of CPU cycles. +/// +/// \return Equivalent number of microseconds (truncated to integer). +static inline uint64_t +xos_cycles_to_usecs(uint64_t cycles) +{ + return (cycles * 1000000) / xos_clock_freq; +} + +/// Converts time in seconds to CPU cycle count. +/// +/// \param secs Number of seconds. +/// +/// \return Equivalent number of CPU cycles. +static inline uint64_t +xos_secs_to_cycles(uint64_t secs) +{ + return secs * xos_clock_freq; +} + +/// Converts time in milliseconds to CPU cycle count. +/// +/// \param msecs Number of milliseconds. +/// +/// \return Equivalent number of CPU cycles. +static inline uint64_t +xos_msecs_to_cycles(uint64_t msecs) +{ + return (msecs * xos_clock_freq) / 1000; +} + +/// Converts time in microseconds to CPU cycle count. +/// +/// \param usecs Number of microseconds. +/// +/// \return Equivalent number of CPU cycles. +static inline uint64_t +xos_usecs_to_cycles(uint64_t usecs) +{ + return (usecs * xos_clock_freq) / 1000000; +} +///@} + + +//----------------------------------------------------------------------------- +/// +/// Set system clock frequency. This is expected to be set only once, and only +/// if the clock frequency is not known at compile time. +/// +/// \param freq Frequency in cycles per second. +/// +/// \return Returns nothing. +/// +//----------------------------------------------------------------------------- +static inline void +xos_set_clock_freq(uint32_t freq) +{ + xos_clock_freq = freq; +} + + +//----------------------------------------------------------------------------- +/// +/// Get current system clock frequency. +/// +/// \return Returns current system clock frequency in cycles per second. +/// +//----------------------------------------------------------------------------- +static inline uint32_t +xos_get_clock_freq() +{ + return xos_clock_freq; +} + + +//----------------------------------------------------------------------------- +/// +/// Initialize timer support and start the system timer. +/// This function must be called before calling any other timer function. +/// +/// NOTE: The smaller the tick period, the more precisely delays can be +/// specified using timers. However, we also need to make the tick period +/// large enough to allow time both to execute the tick timer interrupt handler +/// and for the application to make reasonable forward progress. If tick_period +/// is too small, the timer interrupt may re-trigger before the timer interrupt +/// handler has returned to the application, thus keeping the processor busy in +/// constantly executing the timer interrupt handler without leaving any cycles +/// for the application. Or, the application might get some cycles but only a +/// fraction of what is spent in the timer interrupt handler, thus severely +/// impacting application performance. +/// +/// The exact number of cycles needed to execute the timer interrupt handler +/// is not specified here. It depends on many factors (e.g. use of caches, +/// various processor configuration options, etc) and can vary by orders of +/// magnitude. Also note that the time to execute this handler is variable: +/// when timers expire upon a given tick timer interrupt, their respective +/// timer handler functions are called from within the interrupt handler. +/// +/// \param timer_num Which Xtensa timer to use (0..2). This timer +/// must exist and be configured at level 1 or at a +/// medium-priority interrupt level (<=EXCM_LEVEL). +/// If 'timer_num' is -1, then this function will +/// automatically choose the highest priority timer +/// that is suitable for use. This value will be +/// passed to xos_system_timer_select(). +/// +/// \param tick_period Number of clock (CCOUNT) cycles between ticks. +/// Must range between 0 and UINT32_MAX. +/// Zero is used to specify dynamic tick (tickless) +/// mode. +/// +/// \return Returns XOS_OK on success, else error code. +/// +//----------------------------------------------------------------------------- +int32_t +xos_start_system_timer(int32_t timer_num, uint32_t tick_period); + + +//----------------------------------------------------------------------------- +/// +/// Get the timer number of the system timer. Useful mainly when XOS has been +/// allowed to choose its own timer via xos_start_system_timer(). Not valid if +/// called before the system timer has been started. +/// +/// \return Returns one of XOS_SYS_TIMER_0, XOS_SYS_TIMER_1, XOS_SYS_TIMER_2 +/// or XOS_SYS_TIMER_EXTERNAL, or XOS_SYS_TIMER_NONE. +/// +//----------------------------------------------------------------------------- +int32_t +xos_get_system_timer_num(void); + + +//----------------------------------------------------------------------------- +/// +/// Initialize timer object. +/// +/// \param timer Pointer to timer event structure. +/// +/// \return Returns nothing. +/// +/// NOTE: This function should not be called on a timer object once it has +/// been activated. +/// +//----------------------------------------------------------------------------- +void xos_timer_init(XosTimer * timer); + + +//----------------------------------------------------------------------------- +// Flags for xos_timer_start(). +//----------------------------------------------------------------------------- +#define XOS_TIMER_DELTA 0x0000 +#define XOS_TIMER_PERIODIC 0x0001 +#define XOS_TIMER_ABSOLUTE 0x0002 +#define XOS_TIMER_FROM_NOW 0x0000 +#define XOS_TIMER_FROM_LAST 0x0010 + + +//----------------------------------------------------------------------------- +/// +/// Start the timer, and when the timer expires, call the specified function +/// (invoke (*fn)(arg)). If the timer is periodic, it will be automatically +/// restarted when it expires. +/// +/// The specified timer event structure must have been initialized before +/// first use by calling xos_timer_init(). +/// +/// The callback function will be called in an interrupt context. Hence it is +/// NOT safe to use any coprocessors in the function, including the FPU. If a +/// coprocessor must be used, then its state must be saved and restored across +/// its use. +/// +/// NOTE: If you are using the timer only to wait on (via xos_timer_wait()) +/// then it is not necessary to specify a callback function. You should pass +/// NULL for the callback function and zero for the callback argument. +/// +/// \param timer Pointer to timer event structure. Must have been +/// initialized. May be active or not. +/// +/// \param when When to call the function (see flags). +/// +/// \param flags Set of option flags XOS_TIMER_* \n +/// The following flags are mutually exclusive: +/// - XOS_TIMER_DELTA -- when is number of cycles from +/// [see below] (default) +/// - XOS_TIMER_PERIODIC -- when is number of cycles +/// from [see below], and timer continually +/// re-triggers at that interval +/// - XOS_TIMER_ABSOLUTE -- when is absolute value of +/// cycle count \n +/// \n +/// The following flags are mutually exclusive: +/// - XOS_TIMER_FROM_NOW -- *DELTA and *PERIODIC are +/// relative to now (default) +/// - XOS_TIMER_FROM_LAST -- *DELTA and *PERIODIC are +/// relative to the timer event's last specified expiry +/// time (usually in the future if active, in the past +/// if not, absolute 0 if was never activated). +/// +/// \param func Function to call (called in timer interrupt context). +/// This argument is optional. Specify NULL if no function +/// is to be called. +/// +/// \param arg Argument passed to callback function. Only relevant if +/// 'func' is not NULL. +/// +/// \return Returns XOS_OK on success, else error code. +/// +//----------------------------------------------------------------------------- +int32_t +xos_timer_start(XosTimer * timer, + uint64_t when, + uint32_t flags, + XosTimerFunc * func, + void * arg); + + +//----------------------------------------------------------------------------- +/// +/// Stop the timer and remove it from the list of active timers. Has no effect +/// if the timer is not active. Any waiting threads are woken up. +/// +/// The timer structure must have been initialized at least once, else its +/// contents are undefined and can lead to unpredictable results. +/// +/// \param timer Pointer to timer object. +/// +/// \return Returns XOS_OK on success, else error code. +/// +//----------------------------------------------------------------------------- +int32_t +xos_timer_stop(XosTimer * timer); + + +//----------------------------------------------------------------------------- +/// +/// Reset and restart the timer. +/// +/// The timer is reset to go off at time "when" from now. If the timer was not +/// active, it will be activated. If the timer was active, it will be restarted. +/// If the timer is periodic, the period will be set to "when". +/// The timer object must have been initialized at some point before this call. +/// +/// \param timer Pointer to timer object. +/// +/// \param when Number of cycles from now that the timer will expire. +/// +/// \return Returns XOS_OK on success, else error code. +/// +//----------------------------------------------------------------------------- +int32_t +xos_timer_restart(XosTimer * timer, uint64_t when); + + +//----------------------------------------------------------------------------- +/// +/// Check if the timer is active. The timer is active if it has been started +/// and not yet expired or canceled. +/// +/// \param timer Pointer to timer object. +/// +/// \return Returns non-zero if the timer is active, else zero. +/// +//----------------------------------------------------------------------------- +static inline int32_t +xos_timer_is_active(XosTimer * timer) +{ + return timer ? timer->active : 0; +} + + +//----------------------------------------------------------------------------- +/// +/// Get the repeat period for a periodic timer. For a one-shot timer this will +/// return zero. The period is reported in system clock cycles. +/// +/// \param timer Pointer to timer object. +/// +/// \return Returns period in cycles, or zero for non-periodic timers. +/// +//----------------------------------------------------------------------------- +static inline uint64_t +xos_timer_get_period(XosTimer * timer) +{ + return timer ? timer->delta : 0; +} + + +//----------------------------------------------------------------------------- +/// +/// Set the repeat period for a periodic timer. The period must be specified +/// in system clock cycles. +/// +/// If the timer is active, the change in period does not take effect until +/// the timer expires at least once after this call. +/// Note that setting a period of zero will effectively turn a periodic timer +/// into a one-shot timer. Similarly, a one-shot timer can be turned into a +/// periodic timer. +/// +/// \param timer Pointer to timer object. +/// +/// \param period Repeat period in system clock cycles. +/// +/// \return Returns XOS_OK on success, else error code. +/// +//----------------------------------------------------------------------------- +int32_t +xos_timer_set_period(XosTimer * timer, uint64_t period); + + +//----------------------------------------------------------------------------- +/// +/// Get the current system cycle count. This accounts for the periodic rollover +/// of the 32-bit CCOUNT cycle counter and returns a 64-bit value. +/// +/// \return Returns the current system cycle count. +/// +//----------------------------------------------------------------------------- +static inline uint64_t +xos_get_system_cycles(void) +{ + extern uint64_t xos_system_cycles; + extern uint32_t xos_last_ccount; + + // xos_last_ccount was updated when xos_system_cycles was last updated. + // We need to add in the number of cycles elapsed since then. + return xos_system_cycles + (xos_get_ccount() - xos_last_ccount); +} + + +//----------------------------------------------------------------------------- +/// +/// Put calling thread to sleep for at least the specified number of cycles. +/// The actual number of cycles spent sleeping may be larger depending upon +/// the granularity of the system timer. Once the specified time has elapsed +/// the thread will be woken and made ready. +/// +/// \param cycles Number of system clock cycles to sleep. +/// +/// \return Returns XOS_OK on success, else error code. +/// +//----------------------------------------------------------------------------- +int32_t +xos_thread_sleep(uint64_t cycles); + + +//----------------------------------------------------------------------------- +/// +/// Put calling thread to sleep for at least the specified number of msec. +/// The actual amount of time spent sleeping may be larger depending upon +/// the granularity of the system timer. Once the specified time has elapsed +/// the thread will be woken and made ready. +/// +/// \return msecs The number of milliseconds to sleep. +/// +/// \return Returns XOS_OK on success, else error code. +/// +//----------------------------------------------------------------------------- +static inline int32_t +xos_thread_sleep_msec(uint64_t msecs) +{ + return xos_thread_sleep(xos_msecs_to_cycles(msecs)); +} + + +//----------------------------------------------------------------------------- +/// +/// Put calling thread to sleep for at least the specified number of usec. +/// The actual amount of time spent sleeping may be larger depending upon +/// the granularity of the system timer. Once the specified time has elapsed +/// the thread will be woken and made ready. +/// +/// \return usecs The number of microseconds to sleep. +/// +/// \return Returns XOS_OK on success, else error code. +/// +//----------------------------------------------------------------------------- +static inline int32_t +xos_thread_sleep_usec(uint64_t usecs) +{ + return xos_thread_sleep(xos_usecs_to_cycles(usecs)); +} + + +//----------------------------------------------------------------------------- +/// +/// Wait on a timer until it expires or is cancelled. The calling thread will +/// be blocked. The timer must be active. +/// NOTE: This operation is only available if XOS_OPT_TIMER_WAIT is set +/// to 1 in the configuration options. +/// +/// \param timer Pointer to timer object. +/// +/// \return Returns XOS_OK on normal timeout, else an error code. +/// +//----------------------------------------------------------------------------- +int32_t +xos_timer_wait(XosTimer * timer); + + +//----------------------------------------------------------------------------- +// System timer control interface. +//----------------------------------------------------------------------------- + + +//----------------------------------------------------------------------------- +// Defines for system timer ID. +//----------------------------------------------------------------------------- +#define XOS_SYS_TIMER_0 0 ///< Internal timer 0 +#define XOS_SYS_TIMER_1 1 ///< Internal timer 1 +#define XOS_SYS_TIMER_2 2 ///< Internal timer 2 +#define XOS_SYS_TIMER_EXTERNAL -2 ///< External timer +#define XOS_SYS_TIMER_NONE -1 ///< No system timer selected + + +//----------------------------------------------------------------------------- +/// +/// This function handles XOS timer tick processing. It must be called by the +/// timer interrupt handler on every timer interrupt. This function computes +/// the time to the next tick and sets it up by calling xos_system_timer_set(). +/// +//----------------------------------------------------------------------------- +void +xos_tick_handler(void); + + +//----------------------------------------------------------------------------- +/// +/// Selects the timer to use. The selection may be one of the internal timers +/// or an external timer. The default implementation selects an internal timer. +/// This function can be overridden to provide custom timer processing or to +/// support an external timer. +/// +/// \param timer_num The internal timer number to select (0-2) or +/// -1 to auto-select a timer. This parameter can +/// be ignored by custom implementations that use +/// an external timer. +/// +/// \param psel Pointer to a location where the selected timer +/// ID must be returned. The timer ID must be one +/// of XOS_SYS_TIMER_0, XOS_SYS_TIMER_1, XOS_SYS_TIMER_2 +/// or XOS_SYS_TIMER_EXTERNAL. +/// +/// \return Returns XOS_OK on success, else error code. +/// +//----------------------------------------------------------------------------- +int32_t +xos_system_timer_select(int32_t timer_num, int32_t *psel); + + +//----------------------------------------------------------------------------- +/// +/// Starts the system timer and sets up the first interrupt. This function can +/// be overridden to provide custom timer processing or to support an external +/// timer. +/// +/// \param cycles The number of CPU cycles from now when the +/// first interrupt must occur. +/// +//----------------------------------------------------------------------------- +void +xos_system_timer_init(uint32_t cycles); + + +//----------------------------------------------------------------------------- +/// +/// Sets the next trigger value of the system timer. The parameter 'cycles' is +/// the number of CPU cycles from now when the interrupt must occur. +/// This function can be overridden to provide custom timer processing or to +/// support an external timer. +/// +/// \param cycles The number of CPU cycles from now when the +/// next interrupt must occur. +/// +//----------------------------------------------------------------------------- +void +xos_system_timer_set(uint32_t cycles); + + +#ifdef __cplusplus +} +#endif + +#endif // __XOS_TIMER_H__ + diff --git a/components/esp32/include/xtensa/xos_types.h b/components/esp32/include/xtensa/xos_types.h new file mode 100755 index 0000000000..a913b94a23 --- /dev/null +++ b/components/esp32/include/xtensa/xos_types.h @@ -0,0 +1,75 @@ +/** @file */ +// xos_types.h - XOS type definitions. + +// Copyright (c) 2003-2015 Cadence Design Systems, Inc. +// +// Permission is hereby granted, free of charge, to any person obtaining +// a copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to +// permit persons to whom the Software is furnished to do so, subject to +// the following conditions: +// +// The above copyright notice and this permission notice shall be included +// in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +// CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +// SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +// NOTE: Do not include this file directly in your application. Including +// xos.h will automatically include this file. + + +#ifndef __XOS_TYPES_H__ +#define __XOS_TYPES_H__ + +#if !defined(_ASMLANGUAGE) && !defined(__ASSEMBLER__) + +#ifdef __cplusplus +extern "C" { +#endif + +#include + +//----------------------------------------------------------------------------- +// The following are defined here because of the variations in the C libraries +// that we need to work with. +// - Not all of them have stdbool.h +// - Not all of them define NULL as (void *)0 +//----------------------------------------------------------------------------- + + +//----------------------------------------------------------------------------- +/// +/// XOS define for NULL value. This makes the NULL value independent of the +/// C library (not all of them define NULL the same way). +/// +//----------------------------------------------------------------------------- +#define XOS_NULL ((void *)0) + + +//----------------------------------------------------------------------------- +/// +/// XOS definition of 'bool' type. Some C libraries do not support stdbool.h. +/// +//----------------------------------------------------------------------------- +#ifndef bool +#define bool int8_t +#define false 0 ///< XOS definition of 'false' +#define true 1 ///< XOS definition of 'true' +#endif + +#ifdef __cplusplus +} +#endif + +#endif // !defined(_ASMLANGUAGE) && !defined(__ASSEMBLER__) + +#endif // __XOS_TYPES_H__ + diff --git a/components/esp32/include/xtensa/xt_perf_consts.h b/components/esp32/include/xtensa/xt_perf_consts.h new file mode 100755 index 0000000000..f063a31f77 --- /dev/null +++ b/components/esp32/include/xtensa/xt_perf_consts.h @@ -0,0 +1,283 @@ +/* + * Customer ID=11656; Build=0x5f626; Copyright (c) 2012 by Tensilica Inc. ALL RIGHTS RESERVED. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#ifndef __XT_PERF_CONSTS_H__ +#define __XT_PERF_CONSTS_H__ + +/* + * Performance monitor counter selectors + */ + +#define XTPERF_CNT_COMMITTED_INSN 0x8002 /* Instructions committed */ +#define XTPERF_CNT_BRANCH_PENALTY 0x8003 /* Branch penalty cycles */ +#define XTPERF_CNT_PIPELINE_INTERLOCKS 0x8004 /* Pipeline interlocks cycles */ +#define XTPERF_CNT_ICACHE_MISSES 0x8005 /* ICache misses penalty in cycles */ +#define XTPERF_CNT_DCACHE_MISSES 0x8006 /* DCache misses penalty in cycles */ + +#define XTPERF_CNT_CYCLES 0 /* Count cycles */ +#define XTPERF_CNT_OVERFLOW 1 /* Overflow of counter n-1 (assuming this is counter n) */ +#define XTPERF_CNT_INSN 2 /* Successfully completed instructions */ +#define XTPERF_CNT_D_STALL 3 /* Data-related GlobalStall cycles */ +#define XTPERF_CNT_I_STALL 4 /* Instruction-related and other GlobalStall cycles */ +#define XTPERF_CNT_EXR 5 /* Exceptions and pipeline replays */ +#define XTPERF_CNT_BUBBLES 6 /* Hold and other bubble cycles */ +#define XTPERF_CNT_I_TLB 7 /* Instruction TLB Accesses (per instruction retiring) */ +#define XTPERF_CNT_I_MEM 8 /* Instruction memory accesses (per instruction retiring) */ +#define XTPERF_CNT_D_TLB 9 /* Data TLB accesses */ +#define XTPERF_CNT_D_LOAD_U1 10 /* Data memory load instruction (load-store unit 1) */ +#define XTPERF_CNT_D_STORE_U1 11 /* Data memory store instruction (load-store unit 1) */ +#define XTPERF_CNT_D_ACCESS_U1 12 /* Data memory accesses (load, store, S32C1I, etc; load-store unit 1) */ +#define XTPERF_CNT_D_LOAD_U2 13 /* Data memory load instruction (load-store unit 2) */ +#define XTPERF_CNT_D_STORE_U2 14 /* Data memory store instruction (load-store unit 2) */ +#define XTPERF_CNT_D_ACCESS_U2 15 /* Data memory accesses (load, store, S32C1I, etc; load-store unit 2) */ +#define XTPERF_CNT_D_LOAD_U3 16 /* Data memory load instruction (load-store unit 3) */ +#define XTPERF_CNT_D_STORE_U3 17 /* Data memory store instruction (load-store unit 3) */ +#define XTPERF_CNT_D_ACCESS_U3 18 /* Data memory accesses (load, store, S32C1I, etc; load-store unit 3) */ +#define XTPERF_CNT_MULTIPLE_LS 22 /* Multiple Load/Store */ +#define XTPERF_CNT_OUTBOUND_PIF 23 /* Outbound PIF transactions */ +#define XTPERF_CNT_INBOUND_PIF 24 /* Inbound PIF transactions */ +#define XTPERF_CNT_PREFETCH 26 /* Prefetch events */ + + +/* + * Masks for each of the selector listed above + */ + +/* XTPERF_CNT_COMMITTED_INSN selector mask */ + +#define XTPERF_MASK_COMMITTED_INSN 0x0001 + +/* XTPERF_CNT_BRANCH_PENALTY selector mask */ + +#define XTPERF_MASK_BRANCH_PENALTY 0x0001 + +/* XTPERF_CNT_PIPELINE_INTERLOCKS selector mask */ + +#define XTPERF_MASK_PIPELINE_INTERLOCKS 0x0001 + +/* XTPERF_CNT_ICACHE_MISSES selector mask */ + +#define XTPERF_MASK_ICACHE_MISSES 0x0001 + +/* XTPERF_CNT_DCACHE_MISSES selector mask */ + +#define XTPERF_MASK_DCACHE_MISSES 0x0001 + +/* XTPERF_CNT_CYCLES selector mask */ + +#define XTPERF_MASK_CYCLES 0x0001 + +/* XTPERF_CNT_OVERFLOW selector mask */ + +#define XTPERF_MASK_OVERFLOW 0x0001 + +/* + * XTPERF_CNT_INSN selector mask + */ + +#define XTPERF_MASK_INSN_ALL 0x8DFF + +#define XTPERF_MASK_INSN_JX 0x0001 /* JX */ +#define XTPERF_MASK_INSN_CALLX 0x0002 /* CALLXn */ +#define XTPERF_MASK_INSN_RET 0x0004 /* call return i.e. RET, RETW */ +#define XTPERF_MASK_INSN_RF 0x0008 /* supervisor return i.e. RFDE, RFE, RFI, RFWO, RFWU */ +#define XTPERF_MASK_INSN_BRANCH_TAKEN 0x0010 /* Conditional branch taken, or loopgtz/loopnez skips loop */ +#define XTPERF_MASK_INSN_J 0x0020 /* J */ +#define XTPERF_MASK_INSN_CALL 0x0040 /* CALLn */ +#define XTPERF_MASK_INSN_BRANCH_NOT_TAKEN 0x0080 /* Conditional branch fall through (aka. not-taken branch) */ +#define XTPERF_MASK_INSN_LOOP_TAKEN 0x0100 /* Loop instr falls into loop (aka. taken loop) */ +#define XTPERF_MASK_INSN_LOOP_BEG 0x0400 /* Loopback taken to LBEG */ +#define XTPERF_MASK_INSN_LOOP_END 0x0800 /* Loopback falls through to LEND */ +#define XTPERF_MASK_INSN_NON_BRANCH 0x8000 /* Non-branch instruction (aka. non-CTI) */ + +/* + * XTPERF_CNT_D_STALL selector mask + */ + +#define XTPERF_MASK_D_STALL_ALL 0x01FE + +#define XTPERF_MASK_D_STALL_STORE_BUF_FULL 0x0002 /* Store buffer full stall */ +#define XTPERF_MASK_D_STALL_STORE_BUF_CONFLICT 0x0004 /* Store buffer conflict stall */ +#define XTPERF_MASK_D_STALL_CACHE_MISS 0x0008 /* DCache-miss stall */ +#define XTPERF_MASK_D_STALL_BUSY 0x0010 /* Data RAM/ROM/XLMI busy stall */ +#define XTPERF_MASK_D_STALL_IN_PIF 0x0020 /* Data inbound-PIF request stall (incl s32c1i) */ +#define XTPERF_MASK_D_STALL_MHT_LOOKUP 0x0040 /* MHT lookup stall */ +#define XTPERF_MASK_D_STALL_UNCACHED_LOAD 0x0080 /* Uncached load stall (included in MHT lookup stall) */ +#define XTPERF_MASK_D_STALL_BANK_CONFLICT 0x0100 /* Bank-conflict stall */ + +/* + * XTPERF_CNT_I_STALL selector mask + */ + +#define XTPERF_MASK_I_STALL_ALL 0x01FF + +#define XTPERF_MASK_I_STALL_CACHE_MISS 0x0001 /* ICache-miss stall */ +#define XTPERF_MASK_I_STALL_BUSY 0x0002 /* Instruction RAM/ROM busy stall */ +#define XTPERF_MASK_I_STALL_IN_PIF 0x0004 /* Instruction RAM inbound-PIF request stall */ +#define XTPERF_MASK_I_STALL_TIE_PORT 0x0008 /* TIE port stall */ +#define XTPERF_MASK_I_STALL_EXTERNAL_SIGNAL 0x0010 /* External RunStall signal status */ +#define XTPERF_MASK_I_STALL_UNCACHED_FETCH 0x0020 /* Uncached fetch stall */ +#define XTPERF_MASK_I_STALL_FAST_L32R 0x0040 /* FastL32R stall */ +#define XTPERF_MASK_I_STALL_ITERATIVE_MUL 0x0080 /* Iterative multiply stall */ +#define XTPERF_MASK_I_STALL_ITERATIVE_DIV 0x0100 /* Iterative divide stall */ + +/* + * XTPERF_CNT_EXR selector mask + */ + +#define XTPERF_MASK_EXR_ALL 0x01FF + +#define XTPERF_MASK_EXR_REPLAYS 0x0001 /* Other Pipeline Replay (i.e. excludes $ miss etc.) */ +#define XTPERF_MASK_EXR_LEVEL1_INT 0x0002 /* Level-1 interrupt */ +#define XTPERF_MASK_EXR_LEVELH_INT 0x0004 /* Greater-than-level-1 interrupt */ +#define XTPERF_MASK_EXR_DEBUG 0x0008 /* Debug exception */ +#define XTPERF_MASK_EXR_NMI 0x0010 /* NMI */ +#define XTPERF_MASK_EXR_WINDOW 0x0020 /* Window exception */ +#define XTPERF_MASK_EXR_ALLOCA 0x0040 /* Alloca exception */ +#define XTPERF_MASK_EXR_OTHER 0x0080 /* Other exceptions */ +#define XTPERF_MASK_EXR_MEM_ERR 0x0100 /* HW-corrected memory error */ + +/* + * XTPERF_CNT_BUBBLES selector mask + */ + +#define XTPERF_MASK_BUBBLES_ALL 0x01FD + +#define XTPERF_MASK_BUBBLES_PSO 0x0001 /* Processor domain PSO bubble */ +#define XTPERF_MASK_BUBBLES_R_HOLD_D_CACHE_MISS 0x0004 /* R hold caused by DCache miss */ +#define XTPERF_MASK_BUBBLES_R_HOLD_STORE_RELEASE 0x0008 /* R hold caused by Store release */ +#define XTPERF_MASK_BUBBLES_R_HOLD_REG_DEP 0x0010 /* R hold caused by register dependency */ +#define XTPERF_MASK_BUBBLES_R_HOLD_WAIT 0x0020 /* R hold caused by MEMW, EXTW or EXCW */ +#define XTPERF_MASK_BUBBLES_R_HOLD_HALT 0x0040 /* R hold caused by Halt instruction (TX only) */ +#define XTPERF_MASK_BUBBLES_CTI 0x0080 /* CTI bubble (e.g. branch delay slot) */ +#define XTPERF_MASK_BUBBLES_WAITI 0x0100 /* WAITI bubble */ + +/* + * XTPERF_CNT_I_TLB selector mask + */ + +#define XTPERF_MASK_I_TLB_ALL 0x000F + +#define XTPERF_MASK_I_TLB_HITS 0x0001 /* Hit */ +#define XTPERF_MASK_I_TLB_REPLAYS 0x0002 /* Replay of instruction due to ITLB miss */ +#define XTPERF_MASK_I_TLB_REFILLS 0x0004 /* HW-assisted TLB Refill completes */ +#define XTPERF_MASK_I_TLB_MISSES 0x0008 /* ITLB Miss Exception */ + +/* + * XTPERF_CNT_I_MEM selector mask + */ + +#define XTPERF_MASK_I_MEM_ALL 0x000F + +#define XTPERF_MASK_I_MEM_CACHE_HITS 0x0001 /* ICache Hit */ +#define XTPERF_MASK_I_MEM_CACHE_MISSES 0x0002 /* ICache Miss (includes uncached) */ +#define XTPERF_MASK_I_MEM_IRAM 0x0004 /* InstRAM or InstROM */ +#define XTPERF_MASK_I_MEM_BYPASS 0x0008 /* Bypass (i.e. uncached) fetch */ + +/* + * XTPERF_CNT_D_TLB selector mask + */ + +#define XTPERF_MASK_D_TLB_ALL 0x000F + +#define XTPERF_MASK_D_TLB_HITS 0x0001 /* Hit */ +#define XTPERF_MASK_D_TLB_REPLAYS 0x0002 /* Replay of instruction due to DTLB miss */ +#define XTPERF_MASK_D_TLB_REFILLS 0x0004 /* HW-assisted TLB Refill completes */ +#define XTPERF_MASK_D_TLB_MISSES 0x0008 /* DTLB Miss Exception */ + +/* + * XTPERF_CNT_D_LOAD_U* selector mask + */ + +#define XTPERF_MASK_D_LOAD_ALL 0x000F + +#define XTPERF_MASK_D_LOAD_CACHE_HITS 0x0001 /* Cache Hit */ +#define XTPERF_MASK_D_LOAD_CACHE_MISSES 0x0002 /* Cache Miss */ +#define XTPERF_MASK_D_LOAD_LOCAL_MEM 0x0004 /* Local memory hit */ +#define XTPERF_MASK_D_LOAD_BYPASS 0x0008 /* Bypass (i.e. uncached) load */ + +/* + * XTPERF_CNT_D_STORE_U* selector mask + */ + +#define XTPERF_MASK_D_STORE_ALL 0x000F + +#define XTPERF_MASK_D_STORE_CACHE_HITS 0x0001 /* DCache Hit */ +#define XTPERF_MASK_D_STORE_CACHE_MISSES 0x0002 /* DCache Miss */ +#define XTPERF_MASK_D_STORE_LOCAL_MEM 0x0004 /* Local memory hit */ +#define XTPERF_MASK_D_STORE_PIF 0x0008 /* PIF Store */ + +/* + * XTPERF_CNT_D_ACCESS_U* selector mask + */ + +#define XTPERF_MASK_D_ACCESS_ALL 0x000F + +#define XTPERF_MASK_D_ACCESS_CACHE_MISSES 0x0001 /* DCache Miss */ +#define XTPERF_MASK_D_ACCESS_HITS_SHARED 0x0002 /* Hit Shared */ +#define XTPERF_MASK_D_ACCESS_HITS_EXCLUSIVE 0x0004 /* Hit Exclusive */ +#define XTPERF_MASK_D_ACCESS_HITS_MODIFIED 0x0008 /* Hit Modified */ + +/* + * XTPERF_CNT_MULTIPLE_LS selector mask + */ + +#define XTPERF_MASK_MULTIPLE_LS_ALL 0x003F + +#define XTPERF_MASK_MULTIPLE_LS_0S_0L 0x0001 /* 0 stores and 0 loads */ +#define XTPERF_MASK_MULTIPLE_LS_0S_1L 0x0002 /* 0 stores and 1 loads */ +#define XTPERF_MASK_MULTIPLE_LS_1S_0L 0x0004 /* 1 stores and 0 loads */ +#define XTPERF_MASK_MULTIPLE_LS_1S_1L 0x0008 /* 1 stores and 1 loads */ +#define XTPERF_MASK_MULTIPLE_LS_0S_2L 0x0010 /* 0 stores and 2 loads */ +#define XTPERF_MASK_MULTIPLE_LS_2S_0L 0x0020 /* 2 stores and 0 loads */ + +/* + * XTPERF_CNT_OUTBOUND_PIF selector mask + */ + +#define XTPERF_MASK_OUTBOUND_PIF_ALL 0x0003 + +#define XTPERF_MASK_OUTBOUND_PIF_CASTOUT 0x0001 /* Castout */ +#define XTPERF_MASK_OUTBOUND_PIF_PREFETCH 0x0002 /* Prefetch */ + +/* + * XTPERF_CNT_INBOUND_PIF selector mask + */ + +#define XTPERF_MASK_INBOUND_PIF_ALL 0x0003 + +#define XTPERF_MASK_INBOUND_PIF_I_DMA 0x0001 /* Instruction DMA */ +#define XTPERF_MASK_INBOUND_PIF_D_DMA 0x0002 /* Data DMA */ + +/* + * XTPERF_CNT_PREFETCH selector mask + */ + +#define XTPERF_MASK_PREFETCH_ALL 0x002F + +#define XTPERF_MASK_PREFETCH_I_HIT 0x0001 /* I prefetch-buffer-lookup hit */ +#define XTPERF_MASK_PREFETCH_D_HIT 0x0002 /* D prefetch-buffer-lookup hit */ +#define XTPERF_MASK_PREFETCH_I_MISS 0x0004 /* I prefetch-buffer-lookup miss */ +#define XTPERF_MASK_PREFETCH_D_MISS 0x0008 /* D prefetch-buffer-lookup miss */ +#define XTPERF_MASK_PREFETCH_D_L1_FILL 0x0020 /* Fill directly to DCache L1 */ + +#endif /* __XT_PERF_CONSTS_H__ */ diff --git a/components/esp32/include/xtensa/xt_perfmon.h b/components/esp32/include/xtensa/xt_perfmon.h new file mode 100755 index 0000000000..959052b164 --- /dev/null +++ b/components/esp32/include/xtensa/xt_perfmon.h @@ -0,0 +1,183 @@ +/* + * Customer ID=11656; Build=0x5f626; Copyright (c) 2012 by Tensilica Inc. ALL RIGHTS RESERVED. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#ifndef __XT_PERFMON_H__ +#define __XT_PERFMON_H__ + +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +typedef int counter_id_t; + +/* xt_perf_init + + Initialize the performance monitor library. Ordinarily, this + function is called automatically via the .init section. If your + environment does not support the .init section, you will need to + call this function from your code. +*/ + +extern void xt_perf_init(void); + +/* xt_perf_enable + + Turn on the performance monitor. Ordinarily, counting is off by + default. If you turn off performance monitor using xt_perf_disable or + by call to a function that disables performance monitor, you can turn + it on again via this function. +*/ + +extern void xt_perf_enable(void); + +/* xt_perf_disable + + Turn off the performance monitor. If you want to suspend counting + events for a portion of your code, use this function and then call + xt_perf_enable when you want to start again. +*/ + +extern void xt_perf_disable(void); + +/* xt_perf_clear + + Disable performance monitor and clear all initialized hardware counters. + All counter ids are invalid after call to this function and all hardware + counters available for initialization. +*/ + +extern void xt_perf_clear (void); + +/* xt_perf_counters_num + + Returns number of free hardware performance counters. After call to xt_perf_clear + all counters are free and available for initialization. With each successful + xt_perf_init_counter/xt_perf_init_event call this number is decreasing until + no free counters available. +*/ + +extern int xt_perf_counters_num (void); + +/* xt_perf_init_counter32 + + Setup 32 bit performance counter. This function disables performance monitor + if it was enabled. + + Returns zero based counter id on success or negative value if failed. + This function may fail if there is insufficient number of free hardware + counters or function arguments are invalid. + + The counter id returned on success can be used with xt_perf_reset_counter + and xt_perf_counter32 functions. + + - events group, one of XTPERF_CNT constants defined in + xt_perf_consts.h; + - events mask for selected group. Mask bit fields for each + selector defined with XTPERF_MASK prefix in xt_perf_consts.h; + - specifies interrupt levels at which to count events; + if trace_level is greater or equal to zero events are + counted only at interrupt levels below or equal to + trace_level; if trace_level is negative events are + counted only at (-trace_level) interrupt level or higher. +*/ + + +extern counter_id_t xt_perf_init_counter32 ( unsigned int selector, + unsigned int mask, + int trace_level); + +/* xt_perf_init_counter64 + + Setup 64 bit performance counter. Library emulates 64 bit counters by handling + profiling interrupt and recording overflows of 32 bit hardware counters. + This function disables performance monitor if it was enabled. + + Returns zero based counter id on success or negative value if failed. + This function may fail if there is insufficient number of free hardware + counters or function arguments are invalid. + + The counter id returned on success can be used with xt_perf_reset_counter + and xt_perf_counter64 functions. + + - events group, one of XTPERF_CNT constants defined in + xt_perf_consts.h; + - events mask for selected group. Mask bit fields for each + selector defined with XTPERF_MASK prefix in xt_perf_consts.h; + - specifies interrupt levels at which to count events; + if trace_level is greater or equal to zero events are + counted only at interrupt levels below or equal to + trace_level; if trace_level is negative events are + counted only at (-trace_level) interrupt level or higher. +*/ + +extern counter_id_t xt_perf_init_counter64 ( unsigned int selector, + unsigned int mask, + int trace_level); + +/* xt_perf_reset_counter + + Reset counter value to 0. + Returns zero on success or non zero if failed. +*/ + +extern int xt_perf_reset_counter (counter_id_t counter_id); + +/* xt_perf_counter32 + + Read 32 bit counter value. + + Returns zero if counter id is not valid. +*/ + +extern unsigned int xt_perf_counter32 (counter_id_t counter_id); + +/* xt_perf_counter64 + + Read 64 bit counter value. + + Counter must be initialized using xt_perf_init_counter64 function. + + Returns zero if counter id is not valid. +*/ + +extern unsigned long long xt_perf_counter64 (counter_id_t counter_id); + + /* xt_perf_overflow32 + + Read overflow flag of 32 bit counter. This flag is dropped when + counter initialized or reset. Once counter overflows and wraps + around the flag is set and stays set until counter reset. + + Returns negative value if counter id is invalid, zero if counter + not overflowed, positive if in overflowed state. + */ + +extern int xt_perf_overflow32 (counter_id_t counter_id); + +#ifdef __cplusplus +} +#endif + +#endif /* __XT_PERFMON_H__ */ diff --git a/components/esp32/include/xtensa/xt_profiling.h b/components/esp32/include/xtensa/xt_profiling.h new file mode 100755 index 0000000000..650713a459 --- /dev/null +++ b/components/esp32/include/xtensa/xt_profiling.h @@ -0,0 +1,233 @@ +/* + * Customer ID=11656; Build=0x5f626; Copyright (c) 2005-2012 by Tensilica Inc. ALL RIGHTS RESERVED. + * These coded instructions, statements, and computer programs are the + * copyrighted works and confidential proprietary information of Tensilica Inc. + * They may not be modified, copied, reproduced, distributed, or disclosed to + * third parties in any manner, medium, or form, in whole or in part, without + * the prior written consent of Tensilica Inc. + */ + +#ifndef __XT_PROFILER_H__ +#define __XT_PROFILER_H__ + +#include + +#if XCHAL_NUM_PERF_COUNTERS +/* Performance monitor counters constants */ +#include + +#endif /* XCHAL_NUM_PERF_COUNTERS */ + + +#ifdef __cplusplus +extern "C" { +#endif + +/* This file defines an interface that allows a program being profiled + to control when and how it is profiled, whether it is running under + the instruction set simulator or under the hardware profiler. + + Both ISS and HWP implement this interface, although in different + ways. Both also do the right thing if you don't call any of these + functions. +*/ + + +/* +xt_profile_init + + ISS: a no op. + + HWP: Initialize the profiler. Ordinarily, this function is called + automatically via the .init section. If your environment does not + support the .init section, you will need to call this function + by hand. +*/ +extern void xt_profile_init(void); + +/* +xt_profile_add_memory + + ISS: a no op. + + HWP: + Makes "buf_size" bytes at "buf" available to the hardware profiler. + This buffer should be initialized to zeros prior to this call. + + The hardware profiler has already estimated the amount of memory it needs, + but under certain circumstances may still run out of memory. If so, you can + provide more memory with this routine. + +*/ +extern void xt_profile_add_memory(void * buf, unsigned int buf_size); + + +/* xt_profile_enable + + Turn on the profiler. Ordinarily, profiling is on by default. + If you turn off profiling using xt_profile_disable, You can turn + it on again via this function. +*/ +extern void xt_profile_enable(void); + +/* xt_profile_disable + + Turn off the profiler. If you don't want to profile a portion of your code, + use this function and then xt_profile_enable when you want to start again. +*/ +extern void xt_profile_disable(void); + +/* xt_profile_save_and_reset + + Save and reset the profiler's data. + If there were errors, either during profiling or while attempting to + write the data, no data will be written and this function will + return non-zero. + +*/ +extern int xt_profile_save_and_reset(void); + +/* xt_profile_get_frequency + + ISS: always returns 1. + + HWP: + Returns the number of cycles between samples for timer based profiler. + In performance counters based profiler always returns 1. +*/ +extern unsigned int xt_profile_get_frequency(void); + +/* xt_profile_set_frequency + + ISS: a no op. + + HWP: + Set the number of cycles between samples for timer based profiler. + Ignored in performance counters based profiler. + + sample frequency is the number of cycles to wait between samples. It should + be a multiple of 1024. + + If you set the sample frequency to a different value than was passed in xt_profile_init, + then the labels in the output will reflect the later frequency, even though some samples may + have been taken at the earlier frequency. Typically this does not make a significant difference + in the results if this function is called early enough. +*/ +extern void xt_profile_set_frequency(unsigned int sample_frequency); + +/* xt_profile_num_errors + + ISS: always returns 0 + + HWP: + Returns the number of errors that occured while taking samples. Typically these + are out of memory errors and you need to pass a bigger buffer to + xt_profile_add_memory +*/ +extern int xt_profile_num_errors(void); + + +#if XCHAL_NUM_PERF_COUNTERS + + +/* xt_profile_randomize + + ISS: not available + + HWP: Available in performance monitor based profiler. + + Turns on or off sampling period randomization mode. Period randomization + helps to avoid aliasing problems when code being profiled is highly periodic. + Profiler maintains same average sampling period but individual sampling + steps may vary. + Period randomization is turned off by default. + + - non zero turns randomization on, + zero turns randomization off. +*/ + +extern void xt_profile_randomization(int value); + +/* xt_profile_config_clear + + ISS: not available + + HWP: Available in performance monitor based profiler. + + Stops profiling if it was enabled and clears performance counters + parameters. Accumulated profile data stays in memory and will be + saved when xt_profile_save_and_reset is called or at program exit. + Number of configured performance counters is zero after this + function call. +*/ + +extern void xt_profile_config_clear(void); + + +/* xt_profile_config_num + + ISS: not available + + HWP: Available in performance monitor based profiler. + + Returns number of free performance counters. +*/ + +extern int xt_profile_config_num(void); + + +/* xt_profile_config_counter error codes +*/ + +#define XTPROF_ERR_OUT_OF_MEM -1 +#define XTPROF_ERR_INVALID_ARGS -2 +#define XTPROF_ERR_NOT_ENOUGH_COUNTERS -3 +#define XTPROF_ERR_DEFUNCT -4 + +/* xt_profile_config_counter + + ISS: not available + + HWP: Available in performance monitor based profiler. + + Allocating and initializing one or more performance counter for sampling. + Even though event may require multiple performance counters allocated the + profile data for event is merged and dumped into single gmon file. + This function disables profiling if it was enabled. + + Returns 0 on success, non zero if failed: + XTPROF_ERR_OUT_OF_MEM - memory allocation failed; + XTPROF_ERR_INVALID_ARGS - invalid function parameters; + XTPROF_ERR_NOT_ENOUGH_COUNTERS - not enough free performance counters available; + XTPROF_ERR_DEFUNCT - profiling is disabled because of previous errors + (xt_profile_num_errors() is non zero) + + - events group, one of XTPERF_CNT constants defined in xt_perf_consts.h + - events mask for selected group. Mask bit fields for each + selector defined with XTPERF_MASK prefix in xt_perf_consts.h + - specifies interrupt levels at which to take samples; + if trace_level is greater or equal to zero samples are + taken only at interrupt levels below or equal to + trace_level; if trace_level is negative samples are taken + only at (-trace_level) interrupt level or higher. + - sampling period; 1 - record every event, 2 - record every + other event and so on; + Please note - there is overhead associated with events recording, + high frequency events may produce incorrect profile when period + is too small. +*/ + +extern int xt_profile_config_counter ( unsigned int selector, + unsigned int mask, + int trace_level, + unsigned int period); + + + +#endif /* XCHAL_NUM_PERF_COUNTERS */ + +#ifdef __cplusplus +} +#endif + +#endif /* __XT_PROFILER_H__ */ diff --git a/components/esp32/include/xtensa/xt_reftb.h b/components/esp32/include/xtensa/xt_reftb.h new file mode 100755 index 0000000000..358c39f740 --- /dev/null +++ b/components/esp32/include/xtensa/xt_reftb.h @@ -0,0 +1,86 @@ +/* + * Customer ID=11656; Build=0x5f626; Copyright (c) 2009-2013 by Tensilica Inc. ALL RIGHTS RESERVED. + * These coded instructions, statements, and computer programs are the + * copyrighted works and confidential proprietary information of + * Tensilica Inc. They may be adapted and modified by bona fide + * purchasers for internal use, but neither the original nor any + * adapted or modified version may be disclosed or distributed to + * third parties in any manner, medium, or form, in whole or in part, + * without the prior written consent of Tensilica Inc. + * + * This software and its derivatives are to be executed solely on + * products incorporating a Tensilica processor. + */ + +// Utility routines for returning pass/fail status in HW simulations + +#ifndef XT_REF_TESTBENCH_H +#define XT_REF_TESTBENCH_H 1 + +#ifdef __cplusplus +extern "C" { +#endif + +// Exit routines for HW simulation +extern int diag_pass(); +extern int diag_fail(); + +// Set exit status for HW simulation +int set_diag_status(int stat); + +// Setup for user power toggling +extern int setup_power_toggle(); + +// Return exit status location +extern unsigned int* testbench_exit_location(); +// Return power toggle location +extern unsigned int* testbench_power_toggle_location(); + + +// Change exit status location +// You must also change the plusarg "+DVMagicExit" sent to the HW simulator +// or change the argument "--exit_location" sent to the ISS +extern unsigned int* set_testbench_exit_location(unsigned int*); +// Change power toggle location +// You must also change the plusarg "+DVPowerLoc" sent to the HW simulator +extern unsigned int* set_testbench_power_toggle_location(unsigned int*); + +// Exit routines with status message +// +static inline +int pass(const char *msg) +{ + return diag_pass(); +} + +static inline +int fail(const char *msg) +{ + return diag_fail(); +} + +#define POWER_TOGGLE_ON 1 +#define POWER_TOGGLE_OFF 0 + +// Routine to turn on and off power toggle +// Does a magic write that Monitors.v intercepts and appropriately turns +// SAIF dumping on and offf +// +extern volatile unsigned int *_reftb_power_toggle; + +__attribute__ ((always_inline)) +static inline +int set_power_toggle(int val) +{ +#ifdef __XTENSA__ + *_reftb_power_toggle = val; +#endif + return val; +} + +#ifdef __cplusplus +} +#endif + +#endif // XT_REF_TESTBENCH_H + diff --git a/components/esp32/include/xtensa/xtav110.h b/components/esp32/include/xtensa/xtav110.h new file mode 100755 index 0000000000..23421f0b74 --- /dev/null +++ b/components/esp32/include/xtensa/xtav110.h @@ -0,0 +1,313 @@ +/* Copyright (c) 2007-2013 by Tensilica Inc. ALL RIGHTS RESERVED. +/ These coded instructions, statements, and computer programs are the +/ copyrighted works and confidential proprietary information of Tensilica Inc. +/ They may not be modified, copied, reproduced, distributed, or disclosed to +/ third parties in any manner, medium, or form, in whole or in part, without +/ the prior written consent of Tensilica Inc. +*/ + +/* xtav110.h - Xtensa Avnet LX110 (XT-AV110) board specific definitions */ + +#ifndef _INC_XTAV110_H_ +#define _INC_XTAV110_H_ + +#include +#include + +#define XTBOARD_NAME "XT-AV110" + + +/* + * Default assignment of XTAV110 devices to external interrupts. + */ + +/* Ethernet interrupt: */ +#ifdef XCHAL_EXTINT1_NUM +#define ETHERNET_INTNUM XCHAL_EXTINT1_NUM +#define ETHERNET_INTLEVEL XCHAL_EXTINT1_LEVEL +#define ETHERNET_INTMASK XCHAL_EXTINT1_MASK +#else +#define ETHERNET_INTMASK 0 +#endif + +/* UART interrupt: */ +#ifdef XCHAL_EXTINT0_NUM +#define UART16550_INTNUM XCHAL_EXTINT0_NUM +#define UART16550_INTLEVEL XCHAL_EXTINT0_LEVEL +#define UART16550_INTMASK XCHAL_EXTINT0_MASK +#else +#define UART16550_INTMASK 0 +#endif + +/* Audio output interrupt (I2S transmitter FIFO): */ +#ifdef XCHAL_EXTINT2_NUM +#define AUDIO_I2S_OUT_INTNUM XCHAL_EXTINT2_NUM +#define AUDIO_I2S_OUT_INTLEVEL XCHAL_EXTINT2_LEVEL +#define AUDIO_I2S_OUT_INTMASK XCHAL_EXTINT2_MASK +#else +#define AUDIO_I2S_OUT_INTMASK 0 +#endif + +/* Audio input interrupt (I2S receiver FIFO): */ +#ifdef XCHAL_EXTINT3_NUM +#define AUDIO_I2S_IN_INTNUM XCHAL_EXTINT3_NUM +#define AUDIO_I2S_IN_INTLEVEL XCHAL_EXTINT3_LEVEL +#define AUDIO_I2S_IN_INTMASK XCHAL_EXTINT3_MASK +#else +#define AUDIO_I2S_IN_INTMASK 0 +#endif + +/* I2C interrupt */ +#ifdef XCHAL_EXTINT4_NUM +#define I2C_INTNUM XCHAL_EXTINT4_NUM +#define I2C_INTLEVEL XCHAL_EXTINT4_LEVEL +#define I2C_INTMASK XCHAL_EXTINT4_MASK +#else +#define I2C_INTMASK 0 +#endif + +/* USB interrupt */ +#ifdef XCHAL_EXTINT5_NUM +#define USB_INTNUM XCHAL_EXTINT5_NUM +#define USB_INTLEVEL XCHAL_EXTINT5_LEVEL +#define USB_INTMASK XCHAL_EXTINT5_MASK +#else +#define USB_INTMASK 0 +#endif + +/* + * Device addresses. + * + * Note: for endianness-independence, use 32-bit loads and stores for all + * register accesses to Ethernet, UART and LED devices. Undefined bits + * may need to be masked out if needed when reading if the actual register + * size is smaller than 32 bits. + * + * Note: XTAV110 bus byte lanes are defined in terms of msbyte and lsbyte + * relative to the processor. So 32-bit registers are accessed consistently + * from both big and little endian processors. However, this means byte + * sequences are not consistent between big and little endian processors. + * This is fine for RAM, and for ROM if ROM is created for a specific + * processor (and thus has correct byte sequences). However this may be + * unexpected for Flash, which might contain a file-system that one wants + * to use for multiple processor configurations (eg. the Flash might contain + * the Ethernet card's address, endianness-independent application data, etc). + * That is, byte sequences written in Flash by a core of a given endianness + * will be byte-swapped when seen by a core of the other endianness. + * Someone implementing an endianness-independent Flash file system will + * likely handle this byte-swapping issue in the Flash driver software. + */ + +#define XTBOARD_FLASH_MAXSIZE 0x1000000 /* 16 MB */ + +#ifdef XSHAL_IOBLOCK_BYPASS_PADDR + +/* Flash Memory: */ +# define XTBOARD_FLASH_PADDR (XSHAL_IOBLOCK_BYPASS_PADDR+0x08000000) + +/* FPGA registers: */ +# define XTBOARD_FPGAREGS_PADDR (XSHAL_IOBLOCK_BYPASS_PADDR+0x0D020000) + +/* Ethernet controller/transceiver SONIC SN83934: */ +# define ETHERNET_PADDR (XSHAL_IOBLOCK_BYPASS_PADDR+0x0D030000) + + +/* UART National-Semi PC16550D: */ +# define UART16550_PADDR (XSHAL_IOBLOCK_BYPASS_PADDR+0x0D050000) + +/* I2S transmitter */ +# define AUDIO_I2S_OUT_PADDR (XSHAL_IOBLOCK_BYPASS_PADDR+0x0D080000) + +/* I2S receiver */ +# define AUDIO_I2S_IN_PADDR (XSHAL_IOBLOCK_BYPASS_PADDR+0x0D088000) + +/* I2C master */ +# define I2C_PADDR (XSHAL_IOBLOCK_BYPASS_PADDR+0x0D090000) + +/* SPI controller */ +# define SPI_PADDR (XSHAL_IOBLOCK_BYPASS_PADDR+0x0D0A0000) + +/* Display controller Sunplus SPLC780D, 4bit mode, + * LCD Display MYTech MOC-16216B-B: */ +# define SPLC780D_4BIT_PADDR (XSHAL_IOBLOCK_BYPASS_PADDR+0x0D0C0000) + +/* USB Controller */ +# define USB_PADDR (XSHAL_IOBLOCK_BYPASS_PADDR+0x0D0D0000) + +/* Ethernet buffer: */ +# define ETHERNET_BUFFER_PADDR (XSHAL_IOBLOCK_BYPASS_PADDR+0x0D800000) + +#endif /* XSHAL_IOBLOCK_BYPASS_PADDR */ + +/* These devices might be accessed cached: */ +#ifdef XSHAL_IOBLOCK_CACHED_PADDR +# define XTBOARD_FLASH_CACHED_PADDR (XSHAL_IOBLOCK_CACHED_PADDR+0x08000000) +# define ETHERNET_BUFFER_CACHED_PADDR (XSHAL_IOBLOCK_CACHED_PADDR+0x0D800000) +#endif /* XSHAL_IOBLOCK_CACHED_PADDR */ + + +/*** Same thing over again, this time with virtual addresses: ***/ + +#ifdef XSHAL_IOBLOCK_BYPASS_VADDR + +/* Flash Memory: */ +# define XTBOARD_FLASH_VADDR (XSHAL_IOBLOCK_BYPASS_VADDR+0x08000000) + +/* FPGA registers: */ +# define XTBOARD_FPGAREGS_VADDR (XSHAL_IOBLOCK_BYPASS_VADDR+0x0D020000) + +/* Ethernet controller/transceiver SONIC SN83934: */ +# define ETHERNET_VADDR (XSHAL_IOBLOCK_BYPASS_VADDR+0x0D030000) + + +/* UART National-Semi PC16550D: */ +# define UART16550_VADDR (XSHAL_IOBLOCK_BYPASS_VADDR+0x0D050000) + +/* I2S transmitter */ +# define AUDIO_I2S_OUT_VADDR (XSHAL_IOBLOCK_BYPASS_VADDR+0x0D080000) + +/* I2S receiver */ +# define AUDIO_I2S_IN_VADDR (XSHAL_IOBLOCK_BYPASS_VADDR+0x0D088000) + +/* I2C master */ +# define I2C_VADDR (XSHAL_IOBLOCK_BYPASS_VADDR+0x0D090000) + +/* SPI controller */ +# define SPI_VADDR (XSHAL_IOBLOCK_BYPASS_VADDR+0x0D0A0000) + +/* Display controller Sunplus SPLC780D, 4bit mode, + * LCD Display MYTech MOC-16216B-B: */ +# define SPLC780D_4BIT_VADDR (XSHAL_IOBLOCK_BYPASS_VADDR+0x0D0C0000) + +/* USB Controller */ +# define USB_VADDR (XSHAL_IOBLOCK_BYPASS_VADDR+0x0D0D0000) + +/* Ethernet buffer: */ +# define ETHERNET_BUFFER_VADDR (XSHAL_IOBLOCK_BYPASS_VADDR+0x0D800000) + +#endif /* XSHAL_IOBLOCK_BYPASS_VADDR */ + +/* These devices might be accessed cached: */ +#ifdef XSHAL_IOBLOCK_CACHED_VADDR +# define XTBOARD_FLASH_CACHED_VADDR (XSHAL_IOBLOCK_CACHED_VADDR+0x08000000) +# define ETHERNET_BUFFER_CACHED_VADDR (XSHAL_IOBLOCK_CACHED_VADDR+0x0D800000) +#endif /* XSHAL_IOBLOCK_CACHED_VADDR */ + + +/* System ROM: */ +#define XTBOARD_ROM_SIZE XSHAL_ROM_SIZE +#ifdef XSHAL_ROM_VADDR +#define XTBOARD_ROM_VADDR XSHAL_ROM_VADDR +#endif +#ifdef XSHAL_ROM_PADDR +#define XTBOARD_ROM_PADDR XSHAL_ROM_PADDR +#endif + +/* System RAM: */ +#define XTBOARD_RAM_SIZE XSHAL_RAM_SIZE +#ifdef XSHAL_RAM_VADDR +#define XTBOARD_RAM_VADDR XSHAL_RAM_VADDR +#endif +#ifdef XSHAL_RAM_PADDR +#define XTBOARD_RAM_PADDR XSHAL_RAM_PADDR +#endif +#define XTBOARD_RAM_BYPASS_VADDR XSHAL_RAM_BYPASS_VADDR +#define XTBOARD_RAM_BYPASS_PADDR XSHAL_RAM_BYPASS_PADDR + + + +/* + * Things that depend on device addresses. + */ + + +#define XTBOARD_CACHEATTR_WRITEBACK XSHAL_XT2000_CACHEATTR_WRITEBACK +#define XTBOARD_CACHEATTR_WRITEALLOC XSHAL_XT2000_CACHEATTR_WRITEALLOC +#define XTBOARD_CACHEATTR_WRITETHRU XSHAL_XT2000_CACHEATTR_WRITETHRU +#define XTBOARD_CACHEATTR_BYPASS XSHAL_XT2000_CACHEATTR_BYPASS +#define XTBOARD_CACHEATTR_DEFAULT XSHAL_XT2000_CACHEATTR_DEFAULT + +#define XTBOARD_BUSINT_PIPE_REGIONS XSHAL_XT2000_PIPE_REGIONS +#define XTBOARD_BUSINT_SDRAM_REGIONS XSHAL_XT2000_SDRAM_REGIONS + + +/* + * FPGA registers. + * All these registers are normally accessed using 32-bit loads/stores. + */ + +/* Register offsets: */ +#define XTBOARD_DATECD_OFS 0x00 /* date code (read-only) */ +#define XTBOARD_CLKFRQ_OFS 0x04 /* clock frequency Hz (read-only) */ +#define XTBOARD_SYSLED_OFS 0x08 /* LEDs */ +#define XTBOARD_DIPSW_OFS 0x0C /* DIP switch bits (read-only) */ +#define XTBOARD_SWRST_OFS 0x10 /* software reset */ + +/* Physical register addresses: */ +#ifdef XTBOARD_FPGAREGS_PADDR +#define XTBOARD_DATECD_PADDR (XTBOARD_FPGAREGS_PADDR+XTBOARD_DATECD_OFS) +#define XTBOARD_CLKFRQ_PADDR (XTBOARD_FPGAREGS_PADDR+XTBOARD_CLKFRQ_OFS) +#define XTBOARD_SYSLED_PADDR (XTBOARD_FPGAREGS_PADDR+XTBOARD_SYSLED_OFS) +#define XTBOARD_DIPSW_PADDR (XTBOARD_FPGAREGS_PADDR+XTBOARD_DIPSW_OFS) +#define XTBOARD_SWRST_PADDR (XTBOARD_FPGAREGS_PADDR+XTBOARD_SWRST_OFS) +#endif + +/* Virtual register addresses: */ +#ifdef XTBOARD_FPGAREGS_VADDR +#define XTBOARD_DATECD_VADDR (XTBOARD_FPGAREGS_VADDR+XTBOARD_DATECD_OFS) +#define XTBOARD_CLKFRQ_VADDR (XTBOARD_FPGAREGS_VADDR+XTBOARD_CLKFRQ_OFS) +#define XTBOARD_SYSLED_VADDR (XTBOARD_FPGAREGS_VADDR+XTBOARD_SYSLED_OFS) +#define XTBOARD_DIPSW_VADDR (XTBOARD_FPGAREGS_VADDR+XTBOARD_DIPSW_OFS) +#define XTBOARD_SWRST_VADDR (XTBOARD_FPGAREGS_VADDR+XTBOARD_SWRST_OFS) +/* Register access (for C code): */ +#define XTBOARD_DATECD_REG (*(volatile unsigned*) XTBOARD_DATECD_VADDR) +#define XTBOARD_CLKFRQ_REG (*(volatile unsigned*) XTBOARD_CLKFRQ_VADDR) +#define XTBOARD_SYSLED_REG (*(volatile unsigned*) XTBOARD_SYSLED_VADDR) +#define XTBOARD_DIPSW_REG (*(volatile unsigned*) XTBOARD_DIPSW_VADDR) +#define XTBOARD_SWRST_REG (*(volatile unsigned*) XTBOARD_SWRST_VADDR) +#endif + +/* DATECD (date code; when core was built) bit fields: */ +/* BCD-coded month (01..12): */ +#define XTBOARD_DATECD_MONTH_SHIFT 24 +#define XTBOARD_DATECD_MONTH_BITS 8 +#define XTBOARD_DATECD_MONTH_MASK 0xFF000000 +/* BCD-coded day (01..31): */ +#define XTBOARD_DATECD_DAY_SHIFT 16 +#define XTBOARD_DATECD_DAY_BITS 8 +#define XTBOARD_DATECD_DAY_MASK 0x00FF0000 +/* BCD-coded year (2001..9999): */ +#define XTBOARD_DATECD_YEAR_SHIFT 0 +#define XTBOARD_DATECD_YEAR_BITS 16 +#define XTBOARD_DATECD_YEAR_MASK 0x0000FFFF + +/* SYSLED (system LED) bit fields: */ + +/* LED control bits (off=0, on=1): */ +#define XTBOARD_SYSLED_USER_SHIFT 0 +#define XTBOARD_SYSLED_USER_BITS 2 +#define XTBOARD_SYSLED_USER_MASK 0x00000003 + +/* DIP Switch SW5 (left=sw1=lsb=bit0, right=sw4=msb=bit3; off=0, on=1): */ +/* DIP switch bit fields (bit2/sw3 is reserved and presently unused): */ +#define XTBOARD_DIPSW_USER_SHIFT 0 /* labeled 1-2 (1=lsb) */ +#define XTBOARD_DIPSW_USER_BITS 2 +#define XTBOARD_DIPSW_USER_MASK 0x00000003 +#define XTBOARD_DIPSW_BOOT_SHIFT 3 /* labeled 8 (msb) */ +#define XTBOARD_DIPSW_BOOT_BITS 1 +#define XTBOARD_DIPSW_BOOT_MASK 0x00000008 +/* Boot settings: bit3/sw4, off=0, on=1 (this switch controls hardware): */ +#define XTBOARD_DIPSW_BOOT_RAM (0< + diff --git a/components/esp32/include/xtensa/xtav200.h b/components/esp32/include/xtensa/xtav200.h new file mode 100755 index 0000000000..f3d837efa6 --- /dev/null +++ b/components/esp32/include/xtensa/xtav200.h @@ -0,0 +1,280 @@ +/* Copyright (c) 2007-2013 by Tensilica Inc. ALL RIGHTS RESERVED. +/ These coded instructions, statements, and computer programs are the +/ copyrighted works and confidential proprietary information of Tensilica Inc. +/ They may not be modified, copied, reproduced, distributed, or disclosed to +/ third parties in any manner, medium, or form, in whole or in part, without +/ the prior written consent of Tensilica Inc. +*/ + +/* xtav200.h - Xtensa Avnet LX200 (XT-AV200) board specific definitions */ + +#ifndef _INC_XTAV200_H_ +#define _INC_XTAV200_H_ + +#include +#include + +#define XTBOARD_NAME "XT-AV200" + + +/* + * Default assignment of XTAV200 devices to external interrupts. + */ + +/* Ethernet interrupt: */ +#ifdef XCHAL_EXTINT1_NUM +#define ETHERNET_INTNUM XCHAL_EXTINT1_NUM +#define ETHERNET_INTLEVEL XCHAL_EXTINT1_LEVEL +#define ETHERNET_INTMASK XCHAL_EXTINT1_MASK +#else +#define ETHERNET_INTMASK 0 +#endif + +/* UART interrupt: */ +#ifdef XCHAL_EXTINT0_NUM +#define UART16550_INTNUM XCHAL_EXTINT0_NUM +#define UART16550_INTLEVEL XCHAL_EXTINT0_LEVEL +#define UART16550_INTMASK XCHAL_EXTINT0_MASK +#else +#define UART16550_INTMASK 0 +#endif + +/* Audio output interrupt (I2S FIFO underrun): */ +#ifdef XCHAL_EXTINT2_NUM +#define AUDIO_INTNUM XCHAL_EXTINT2_NUM +#define AUDIO_INTLEVEL XCHAL_EXTINT2_LEVEL +#define AUDIO_INTMASK XCHAL_EXTINT2_MASK +#else +#define AUDIO_INTMASK 0 +#endif + +/* Audio output (I2S FIFO level) interrupt: */ +#ifdef XCHAL_EXTINT3_NUM +#define AUDIO_I2SLVL_INTNUM XCHAL_EXTINT3_NUM +#define AUDIO_I2SLVL_INTLEVEL XCHAL_EXTINT3_LEVEL +#define AUDIO_I2SLVL_INTMASK XCHAL_EXTINT3_MASK +#else +#define AUDIO_I2SLVL_INTMASK 0 +#endif + +/* Audio input (ADC FIFO level) interrupt: */ +#ifdef XCHAL_EXTINT4_NUM +#define AUDIO_ADCLVL_INTNUM XCHAL_EXTINT4_NUM +#define AUDIO_ADCLVL_INTLEVEL XCHAL_EXTINT4_LEVEL +#define AUDIO_ADCLVL_INTMASK XCHAL_EXTINT4_MASK +#else +#define AUDIO_ADCLVL_INTMASK 0 +#endif + + +/* + * Device addresses. + * + * Note: for endianness-independence, use 32-bit loads and stores for all + * register accesses to Ethernet, UART and LED devices. Undefined bits + * may need to be masked out if needed when reading if the actual register + * size is smaller than 32 bits. + * + * Note: XTAV200 bus byte lanes are defined in terms of msbyte and lsbyte + * relative to the processor. So 32-bit registers are accessed consistently + * from both big and little endian processors. However, this means byte + * sequences are not consistent between big and little endian processors. + * This is fine for RAM, and for ROM if ROM is created for a specific + * processor (and thus has correct byte sequences). However this may be + * unexpected for Flash, which might contain a file-system that one wants + * to use for multiple processor configurations (eg. the Flash might contain + * the Ethernet card's address, endianness-independent application data, etc). + * That is, byte sequences written in Flash by a core of a given endianness + * will be byte-swapped when seen by a core of the other endianness. + * Someone implementing an endianness-independent Flash file system will + * likely handle this byte-swapping issue in the Flash driver software. + */ + +#define XTBOARD_FLASH_MAXSIZE 0x1000000 /* 16 MB */ + +#ifdef XSHAL_IOBLOCK_BYPASS_PADDR + +/* Flash Memory: */ +# define XTBOARD_FLASH_PADDR (XSHAL_IOBLOCK_BYPASS_PADDR+0x08000000) + +/* FPGA registers: */ +# define XTBOARD_FPGAREGS_PADDR (XSHAL_IOBLOCK_BYPASS_PADDR+0x0D020000) + +/* Ethernet controller/transceiver SONIC SN83934: */ +# define ETHERNET_PADDR (XSHAL_IOBLOCK_BYPASS_PADDR+0x0D030000) + +/* UART National-Semi PC16550D: */ +# define UART16550_PADDR (XSHAL_IOBLOCK_BYPASS_PADDR+0x0D050000) + +/* TI 320AIC23/28-TSSOP Stereo Audio Codec: */ +# define AUDIO_PADDR (XSHAL_IOBLOCK_BYPASS_PADDR+0x0D070000) + +/* Boot 128K Sram address: */ +# define BOOT_SRAM_PADDR (XSHAL_IOBLOCK_BYPASS_PADDR+0x0D400000) + +/* Ethernet buffer: */ +# define ETHERNET_BUFFER_PADDR (XSHAL_IOBLOCK_BYPASS_PADDR+0x0D800000) + +#endif /* XSHAL_IOBLOCK_BYPASS_PADDR */ + +/* These devices might be accessed cached: */ +#ifdef XSHAL_IOBLOCK_CACHED_PADDR +# define XTBOARD_FLASH_CACHED_PADDR (XSHAL_IOBLOCK_CACHED_PADDR+0x08000000) +# define ETHERNET_BUFFER_CACHED_PADDR (XSHAL_IOBLOCK_CACHED_PADDR+0x0D800000) +# define BOOT_SRAM_CACHED_PADDR (XSHAL_IOBLOCK_CACHED_PADDR+0x0D400000) +#endif /* XSHAL_IOBLOCK_CACHED_PADDR */ + + +/*** Same thing over again, this time with virtual addresses: ***/ + +#ifdef XSHAL_IOBLOCK_BYPASS_VADDR + +/* Flash Memory: */ +# define XTBOARD_FLASH_VADDR (XSHAL_IOBLOCK_BYPASS_VADDR+0x08000000) + +/* FPGA registers: */ +# define XTBOARD_FPGAREGS_VADDR (XSHAL_IOBLOCK_BYPASS_VADDR+0x0D020000) + +/* Ethernet controller/transceiver SONIC SN83934: */ +# define ETHERNET_VADDR (XSHAL_IOBLOCK_BYPASS_VADDR+0x0D030000) + +/* UART National-Semi PC16550D: */ +# define UART16550_VADDR (XSHAL_IOBLOCK_BYPASS_VADDR+0x0D050000) + +/* TI 320AIC23/28-TSSOP Stereo Audio Codec: */ +# define AUDIO_VADDR (XSHAL_IOBLOCK_BYPASS_VADDR+0x0D070000) + +/* 128K Sram address: */ +# define BOOT_SRAM_VADDR (XSHAL_IOBLOCK_BYPASS_VADDR+0x0D400000) + +/* Ethernet buffer: */ +# define ETHERNET_BUFFER_VADDR (XSHAL_IOBLOCK_BYPASS_VADDR+0x0D800000) + +#endif /* XSHAL_IOBLOCK_BYPASS_VADDR */ + +/* These devices might be accessed cached: */ +#ifdef XSHAL_IOBLOCK_CACHED_VADDR +# define XTBOARD_FLASH_CACHED_VADDR (XSHAL_IOBLOCK_CACHED_VADDR+0x08000000) +# define AUDIO_CACHED_VADDR (XSHAL_IOBLOCK_CACHED_VADDR+0x0D070000) +# define ETHERNET_BUFFER_CACHED_VADDR (XSHAL_IOBLOCK_CACHED_VADDR+0x0D800000) +# define BOOT_SRAM_CACHED_VADDR (XSHAL_IOBLOCK_CACHED_VADDR+0x0D400000) +#endif /* XSHAL_IOBLOCK_CACHED_VADDR */ + + +/* System ROM: */ +#define XTBOARD_ROM_SIZE XSHAL_ROM_SIZE +#ifdef XSHAL_ROM_VADDR +#define XTBOARD_ROM_VADDR XSHAL_ROM_VADDR +#endif +#ifdef XSHAL_ROM_PADDR +#define XTBOARD_ROM_PADDR XSHAL_ROM_PADDR +#endif + +/* System RAM: */ +#define XTBOARD_RAM_SIZE XSHAL_RAM_SIZE +#ifdef XSHAL_RAM_VADDR +#define XTBOARD_RAM_VADDR XSHAL_RAM_VADDR +#endif +#ifdef XSHAL_RAM_PADDR +#define XTBOARD_RAM_PADDR XSHAL_RAM_PADDR +#endif +#define XTBOARD_RAM_BYPASS_VADDR XSHAL_RAM_BYPASS_VADDR +#define XTBOARD_RAM_BYPASS_PADDR XSHAL_RAM_BYPASS_PADDR + + + +/* + * Things that depend on device addresses. + */ + + +#define XTBOARD_CACHEATTR_WRITEBACK XSHAL_XT2000_CACHEATTR_WRITEBACK +#define XTBOARD_CACHEATTR_WRITEALLOC XSHAL_XT2000_CACHEATTR_WRITEALLOC +#define XTBOARD_CACHEATTR_WRITETHRU XSHAL_XT2000_CACHEATTR_WRITETHRU +#define XTBOARD_CACHEATTR_BYPASS XSHAL_XT2000_CACHEATTR_BYPASS +#define XTBOARD_CACHEATTR_DEFAULT XSHAL_XT2000_CACHEATTR_DEFAULT + +#define XTBOARD_BUSINT_PIPE_REGIONS XSHAL_XT2000_PIPE_REGIONS +#define XTBOARD_BUSINT_SDRAM_REGIONS XSHAL_XT2000_SDRAM_REGIONS + + +/* + * FPGA registers. + * All these registers are normally accessed using 32-bit loads/stores. + */ + +/* Register offsets: */ +#define XTBOARD_DATECD_OFS 0x00 /* date code (read-only) */ +#define XTBOARD_CLKFRQ_OFS 0x04 /* clock frequency Hz (read-only) */ +#define XTBOARD_SYSLED_OFS 0x08 /* LEDs */ +#define XTBOARD_DIPSW_OFS 0x0C /* DIP switch bits (read-only) */ +#define XTBOARD_SWRST_OFS 0x10 /* software reset */ + +/* Physical register addresses: */ +#ifdef XTBOARD_FPGAREGS_PADDR +#define XTBOARD_DATECD_PADDR (XTBOARD_FPGAREGS_PADDR+XTBOARD_DATECD_OFS) +#define XTBOARD_CLKFRQ_PADDR (XTBOARD_FPGAREGS_PADDR+XTBOARD_CLKFRQ_OFS) +#define XTBOARD_SYSLED_PADDR (XTBOARD_FPGAREGS_PADDR+XTBOARD_SYSLED_OFS) +#define XTBOARD_DIPSW_PADDR (XTBOARD_FPGAREGS_PADDR+XTBOARD_DIPSW_OFS) +#define XTBOARD_SWRST_PADDR (XTBOARD_FPGAREGS_PADDR+XTBOARD_SWRST_OFS) +#endif + +/* Virtual register addresses: */ +#ifdef XTBOARD_FPGAREGS_VADDR +#define XTBOARD_DATECD_VADDR (XTBOARD_FPGAREGS_VADDR+XTBOARD_DATECD_OFS) +#define XTBOARD_CLKFRQ_VADDR (XTBOARD_FPGAREGS_VADDR+XTBOARD_CLKFRQ_OFS) +#define XTBOARD_SYSLED_VADDR (XTBOARD_FPGAREGS_VADDR+XTBOARD_SYSLED_OFS) +#define XTBOARD_DIPSW_VADDR (XTBOARD_FPGAREGS_VADDR+XTBOARD_DIPSW_OFS) +#define XTBOARD_SWRST_VADDR (XTBOARD_FPGAREGS_VADDR+XTBOARD_SWRST_OFS) +/* Register access (for C code): */ +#define XTBOARD_DATECD_REG (*(volatile unsigned*) XTBOARD_DATECD_VADDR) +#define XTBOARD_CLKFRQ_REG (*(volatile unsigned*) XTBOARD_CLKFRQ_VADDR) +#define XTBOARD_SYSLED_REG (*(volatile unsigned*) XTBOARD_SYSLED_VADDR) +#define XTBOARD_DIPSW_REG (*(volatile unsigned*) XTBOARD_DIPSW_VADDR) +#define XTBOARD_SWRST_REG (*(volatile unsigned*) XTBOARD_SWRST_VADDR) +#endif + +/* DATECD (date code; when core was built) bit fields: */ +/* BCD-coded month (01..12): */ +#define XTBOARD_DATECD_MONTH_SHIFT 24 +#define XTBOARD_DATECD_MONTH_BITS 8 +#define XTBOARD_DATECD_MONTH_MASK 0xFF000000 +/* BCD-coded day (01..31): */ +#define XTBOARD_DATECD_DAY_SHIFT 16 +#define XTBOARD_DATECD_DAY_BITS 8 +#define XTBOARD_DATECD_DAY_MASK 0x00FF0000 +/* BCD-coded year (2001..9999): */ +#define XTBOARD_DATECD_YEAR_SHIFT 0 +#define XTBOARD_DATECD_YEAR_BITS 16 +#define XTBOARD_DATECD_YEAR_MASK 0x0000FFFF + +/* SYSLED (system LED) bit fields: */ + +/* LED control bits (off=0, on=1): */ +#define XTBOARD_SYSLED_USER_SHIFT 0 +#define XTBOARD_SYSLED_USER_BITS 4 +#define XTBOARD_SYSLED_USER_MASK 0x0000000F + +/* DIP Switch (left=sw1=lsb=bit0, right=sw8=msb=bit7; off=0, on=1): */ +/* DIP switch bit fields (bit6/sw7 is reserved and presently unused): */ +#define XTBOARD_DIPSW_USER_SHIFT 0 /* labeled 1-6 (1=lsb) */ +#define XTBOARD_DIPSW_USER_BITS 6 +#define XTBOARD_DIPSW_USER_MASK 0x0000003F +#define XTBOARD_DIPSW_BOOT_SHIFT 7 /* labeled 8 (msb) */ +#define XTBOARD_DIPSW_BOOT_BITS 1 +#define XTBOARD_DIPSW_BOOT_MASK 0x00000080 +/* Boot settings: bit7/sw8, off=0, on=1 (this switch controls hardware): */ +#define XTBOARD_DIPSW_BOOT_RAM (0< + diff --git a/components/esp32/include/xtensa/xtav60.h b/components/esp32/include/xtensa/xtav60.h new file mode 100755 index 0000000000..d7c8e3aed8 --- /dev/null +++ b/components/esp32/include/xtensa/xtav60.h @@ -0,0 +1,241 @@ +/* Copyright (c) 2002-2013 by Tensilica Inc. ALL RIGHTS RESERVED. +/ These coded instructions, statements, and computer programs are the +/ copyrighted works and confidential proprietary information of Tensilica Inc. +/ They may not be modified, copied, reproduced, distributed, or disclosed to +/ third parties in any manner, medium, or form, in whole or in part, without +/ the prior written consent of Tensilica Inc. +*/ + +/* xtav60.h - Xtensa Avnet LX60 (XT-AV60) board specific definitions */ + +#ifndef _INC_XTAV60_H_ +#define _INC_XTAV60_H_ + +#include +#include + +#define XTBOARD_NAME "XT-AV60" + + +/* + * Default assignment of XTAV60 devices to external interrupts. + */ + +/* Ethernet interrupt: */ +#ifdef XCHAL_EXTINT1_NUM +#define ETHERNET_INTNUM XCHAL_EXTINT1_NUM +#define ETHERNET_INTLEVEL XCHAL_EXTINT1_LEVEL +#define ETHERNET_INTMASK XCHAL_EXTINT1_MASK +#else +#define ETHERNET_INTMASK 0 +#endif + +/* UART interrupt: */ +#ifdef XCHAL_EXTINT0_NUM +#define UART16550_INTNUM XCHAL_EXTINT0_NUM +#define UART16550_INTLEVEL XCHAL_EXTINT0_LEVEL +#define UART16550_INTMASK XCHAL_EXTINT0_MASK +#else +#define UART16550_INTMASK 0 +#endif + +/* + * Device addresses. + * + * Note: for endianness-independence, use 32-bit loads and stores for all + * register accesses to Ethernet, UART and LED devices. Undefined bits + * may need to be masked out if needed when reading if the actual register + * size is smaller than 32 bits. + * + * Note: XTAV60 bus byte lanes are defined in terms of msbyte and lsbyte + * relative to the processor. So 32-bit registers are accessed consistently + * from both big and little endian processors. However, this means byte + * sequences are not consistent between big and little endian processors. + * This is fine for RAM, and for ROM if ROM is created for a specific + * processor (and thus has correct byte sequences). However this may be + * unexpected for Flash, which might contain a file-system that one wants + * to use for multiple processor configurations (eg. the Flash might contain + * the Ethernet card's address, endianness-independent application data, etc). + * That is, byte sequences written in Flash by a core of a given endianness + * will be byte-swapped when seen by a core of the other endianness. + * Someone implementing an endianness-independent Flash file system will + * likely handle this byte-swapping issue in the Flash driver software. + */ + +#define XTBOARD_FLASH_MAXSIZE 0x400000 /* 4 MB */ + +#ifdef XSHAL_IOBLOCK_BYPASS_PADDR + +/* Flash Memory: */ +# define XTBOARD_FLASH_PADDR (XSHAL_IOBLOCK_BYPASS_PADDR+0x08000000) + +/* FPGA registers: */ +# define XTBOARD_FPGAREGS_PADDR (XSHAL_IOBLOCK_BYPASS_PADDR+0x0D020000) + +/* Ethernet controller/transceiver SONIC SN83934: */ +# define ETHERNET_PADDR (XSHAL_IOBLOCK_BYPASS_PADDR+0x0D030000) +# define ETHERNET_CONTROLLER_PADDR ETHERNET_PADDR /* legacy macro */ + +/* Display controller Sunplus SPLC780D, LCD Display MYTech MOC-16216B-B: */ +# define SPLC780D_PADDR (XSHAL_IOBLOCK_BYPASS_PADDR+0x0D040000) + +/* UART National-Semi PC16550D: */ +# define UART16550_PADDR (XSHAL_IOBLOCK_BYPASS_PADDR+0x0D050000) + +/* Boot 128K Sram address: */ +# define BOOT_SRAM_PADDR (XSHAL_IOBLOCK_BYPASS_PADDR+0x0D400000) + +/* Ethernet buffer: */ +# define ETHERNET_BUFFER_PADDR (XSHAL_IOBLOCK_BYPASS_PADDR+0x0D800000) + +#endif /* XSHAL_IOBLOCK_BYPASS_PADDR */ + +/* These devices might be accessed cached: */ +#ifdef XSHAL_IOBLOCK_CACHED_PADDR +# define XTBOARD_FLASH_CACHED_PADDR (XSHAL_IOBLOCK_CACHED_PADDR+0x08000000) +# define ETHERNET_BUFFER_CACHED_PADDR (XSHAL_IOBLOCK_CACHED_PADDR+0x0D800000) +# define BOOT_SRAM_CACHED_PADDR (XSHAL_IOBLOCK_CACHED_PADDR+0x0D400000) +#endif /* XSHAL_IOBLOCK_CACHED_PADDR */ + + +/*** Same thing over again, this time with virtual addresses: ***/ + +#ifdef XSHAL_IOBLOCK_BYPASS_VADDR + +/* Flash Memory: */ +# define XTBOARD_FLASH_VADDR (XSHAL_IOBLOCK_BYPASS_VADDR+0x08000000) + +/* FPGA registers: */ +# define XTBOARD_FPGAREGS_VADDR (XSHAL_IOBLOCK_BYPASS_VADDR+0x0D020000) + +/* Ethernet controller/transceiver SONIC SN83934: */ +# define ETHERNET_VADDR (XSHAL_IOBLOCK_BYPASS_VADDR+0x0D030000) + +/* Display controller Sunplus SPLC780D, LCD Display MYTech MOC-16216B-B: */ +# define SPLC780D_VADDR (XSHAL_IOBLOCK_BYPASS_VADDR+0x0D040000) + +/* UART National-Semi PC16550D: */ +# define UART16550_VADDR (XSHAL_IOBLOCK_BYPASS_VADDR+0x0D050000) + +/* 128K Sram address: */ +# define BOOT_SRAM_VADDR (XSHAL_IOBLOCK_BYPASS_VADDR+0x0D400000) + +/* Ethernet buffer: */ +# define ETHERNET_BUFFER_VADDR (XSHAL_IOBLOCK_BYPASS_VADDR+0x0D800000) + +#endif /* XSHAL_IOBLOCK_BYPASS_VADDR */ + +/* These devices might be accessed cached: */ +#ifdef XSHAL_IOBLOCK_CACHED_VADDR +# define XTBOARD_FLASH_CACHED_VADDR (XSHAL_IOBLOCK_CACHED_VADDR+0x08000000) +# define ETHERNET_BUFFER_CACHED_VADDR (XSHAL_IOBLOCK_CACHED_VADDR+0x0D800000) +# define BOOT_SRAM_CACHED_VADDR (XSHAL_IOBLOCK_CACHED_VADDR+0x0D400000) +#endif /* XSHAL_IOBLOCK_CACHED_VADDR */ + + +/* System ROM: */ +#define XTBOARD_ROM_SIZE XSHAL_ROM_SIZE +#ifdef XSHAL_ROM_VADDR +#define XTBOARD_ROM_VADDR XSHAL_ROM_VADDR +#endif +#ifdef XSHAL_ROM_PADDR +#define XTBOARD_ROM_PADDR XSHAL_ROM_PADDR +#endif + +/* System RAM: */ +#define XTBOARD_RAM_SIZE XSHAL_RAM_SIZE +#ifdef XSHAL_RAM_VADDR +#define XTBOARD_RAM_VADDR XSHAL_RAM_VADDR +#endif +#ifdef XSHAL_RAM_PADDR +#define XTBOARD_RAM_PADDR XSHAL_RAM_PADDR +#endif +#define XTBOARD_RAM_BYPASS_VADDR XSHAL_RAM_BYPASS_VADDR +#define XTBOARD_RAM_BYPASS_PADDR XSHAL_RAM_BYPASS_PADDR + + + +/* + * Things that depend on device addresses. + */ + + +#define XTBOARD_CACHEATTR_WRITEBACK XSHAL_XT2000_CACHEATTR_WRITEBACK +#define XTBOARD_CACHEATTR_WRITEALLOC XSHAL_XT2000_CACHEATTR_WRITEALLOC +#define XTBOARD_CACHEATTR_WRITETHRU XSHAL_XT2000_CACHEATTR_WRITETHRU +#define XTBOARD_CACHEATTR_BYPASS XSHAL_XT2000_CACHEATTR_BYPASS +#define XTBOARD_CACHEATTR_DEFAULT XSHAL_XT2000_CACHEATTR_DEFAULT + +#define XTBOARD_BUSINT_PIPE_REGIONS XSHAL_XT2000_PIPE_REGIONS +#define XTBOARD_BUSINT_SDRAM_REGIONS XSHAL_XT2000_SDRAM_REGIONS + + +/* + * FPGA registers. + * All these registers are normally accessed using 32-bit loads/stores. + */ + +/* Register offsets: */ +#define XTBOARD_DATECD_OFS 0x00 /* date code (read-only) */ +#define XTBOARD_CLKFRQ_OFS 0x04 /* clock frequency Hz (read-only) */ +#define XTBOARD_DIPSW_OFS 0x0C /* DIP switch bits (read-only) */ +#define XTBOARD_SWRST_OFS 0x10 /* software reset */ + +/* Physical register addresses: */ +#ifdef XTBOARD_FPGAREGS_PADDR +#define XTBOARD_DATECD_PADDR (XTBOARD_FPGAREGS_PADDR+XTBOARD_DATECD_OFS) +#define XTBOARD_CLKFRQ_PADDR (XTBOARD_FPGAREGS_PADDR+XTBOARD_CLKFRQ_OFS) +#define XTBOARD_DIPSW_PADDR (XTBOARD_FPGAREGS_PADDR+XTBOARD_DIPSW_OFS) +#define XTBOARD_SWRST_PADDR (XTBOARD_FPGAREGS_PADDR+XTBOARD_SWRST_OFS) +#endif + +/* Virtual register addresses: */ +#ifdef XTBOARD_FPGAREGS_VADDR +#define XTBOARD_DATECD_VADDR (XTBOARD_FPGAREGS_VADDR+XTBOARD_DATECD_OFS) +#define XTBOARD_CLKFRQ_VADDR (XTBOARD_FPGAREGS_VADDR+XTBOARD_CLKFRQ_OFS) +#define XTBOARD_DIPSW_VADDR (XTBOARD_FPGAREGS_VADDR+XTBOARD_DIPSW_OFS) +#define XTBOARD_SWRST_VADDR (XTBOARD_FPGAREGS_VADDR+XTBOARD_SWRST_OFS) +/* Register access (for C code): */ +#define XTBOARD_DATECD_REG (*(volatile unsigned*) XTBOARD_DATECD_VADDR) +#define XTBOARD_CLKFRQ_REG (*(volatile unsigned*) XTBOARD_CLKFRQ_VADDR) +#define XTBOARD_DIPSW_REG (*(volatile unsigned*) XTBOARD_DIPSW_VADDR) +#define XTBOARD_SWRST_REG (*(volatile unsigned*) XTBOARD_SWRST_VADDR) +#endif + +/* DATECD (date code; when core was built) bit fields: */ +/* BCD-coded month (01..12): */ +#define XTBOARD_DATECD_MONTH_SHIFT 24 +#define XTBOARD_DATECD_MONTH_BITS 8 +#define XTBOARD_DATECD_MONTH_MASK 0xFF000000 +/* BCD-coded day (01..31): */ +#define XTBOARD_DATECD_DAY_SHIFT 16 +#define XTBOARD_DATECD_DAY_BITS 8 +#define XTBOARD_DATECD_DAY_MASK 0x00FF0000 +/* BCD-coded year (2001..9999): */ +#define XTBOARD_DATECD_YEAR_SHIFT 0 +#define XTBOARD_DATECD_YEAR_BITS 16 +#define XTBOARD_DATECD_YEAR_MASK 0x0000FFFF + +/* DIP Switch (left=sw1=lsb=bit0, right=sw8=msb=bit7; off=0, on=1): */ +/* DIP switch bit fields (bit6/sw7 is reserved and presently unused): */ +#define XTBOARD_DIPSW_USER_SHIFT 0 /* labeled 1-6 (1=lsb) */ +#define XTBOARD_DIPSW_USER_BITS 6 +#define XTBOARD_DIPSW_USER_MASK 0x0000003F +#define XTBOARD_DIPSW_BOOT_SHIFT 7 /* labeled 8 (msb) */ +#define XTBOARD_DIPSW_BOOT_BITS 1 +#define XTBOARD_DIPSW_BOOT_MASK 0x00000080 +/* Boot settings: bit7/sw8, off=0, on=1 (this switch controls hardware): */ +#define XTBOARD_DIPSW_BOOT_RAM (0< + diff --git a/components/esp32/include/xtensa/xtav60/xtensa/lcd-splc780d-board.h b/components/esp32/include/xtensa/xtav60/xtensa/lcd-splc780d-board.h new file mode 100755 index 0000000000..629a32581a --- /dev/null +++ b/components/esp32/include/xtensa/xtav60/xtensa/lcd-splc780d-board.h @@ -0,0 +1,60 @@ +/******************************************************************************* + +Copyright (c) 2006-2007 by Tensilica Inc. ALL RIGHTS RESERVED. +These coded instructions, statements, and computer programs are the +copyrighted works and confidential proprietary information of Tensilica Inc. +They may not be modified, copied, reproduced, distributed, or disclosed to +third parties in any manner, medium, or form, in whole or in part, without +the prior written consent of Tensilica Inc. +-------------------------------------------------------------------------------- + +lcd-splc780d-board.h Board-specific LCD info on Avnet AV60 (XT-AV60) board. + +Interface between board-independent driver and board-specific header. + +This is used by a board-independent SPLC780D LCD controller driver to obtain +board-specific information about LCD displays on the board, such as the +controller register base address and spacing (a function of how the address +lines are connected on the board) and length of the visible window of the +display (a function of the LCD panel the controller drives). The driver does +not refer directly to the board-specific header, which therefore is not +constrained to use macro names consistent with other boards. + +!! Must not contain any board-specific macro names (only controller specific) !! + +Included at compile-time via an include path specific to the board. + +The XT-AV60 board contains a single MYTech MOC-16216B-B display driven by +a Sunplus SPLC870D controller. + +*******************************************************************************/ + +#ifndef _LCD_SPLC780D_BOARD_H +#define _LCD_SPLC780D_BOARD_H + +#include /* Board info */ + + +/* Base address of the controller's registers. */ +#ifdef SPLC780D_VADDR +#define SPLC780D_REGBASE SPLC780D_VADDR +#endif + +/* +The controller's registers are connected at word addresses on the XT-AV60. +Each byte-wide register appears as the least-significant-byte (LSB) of the +word regardless of the endianness of the processor (so if using word accesses +then endianness doesn't matter). +*/ +#define SPLC780D_REGSPACING 4 +typedef unsigned splc780d_reg_t; + +/* Include generic information shared by all boards that use this device. */ +#include + + +/* Display limits of the LCD panel. */ +#define DISPLAY_VISIBLE_LEN 16 /* length (chars) of visible window */ + +#endif /* _LCD_SPLC780D_BOARD_H */ + diff --git a/components/esp32/include/xtensa/xtbsp.h b/components/esp32/include/xtensa/xtbsp.h new file mode 100755 index 0000000000..62356dd868 --- /dev/null +++ b/components/esp32/include/xtensa/xtbsp.h @@ -0,0 +1,269 @@ +/******************************************************************************* + + Copyright (c) 2006-2009 Tensilica Inc. + + Permission is hereby granted, free of charge, to any person obtaining + a copy of this software and associated documentation files (the + "Software"), to deal in the Software without restriction, including + without limitation the rights to use, copy, modify, merge, publish, + distribute, sublicense, and/or sell copies of the Software, and to + permit persons to whom the Software is furnished to do so, subject to + the following conditions: + + The above copyright notice and this permission notice shall be included + in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY + CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +-------------------------------------------------------------------------------- + +xtbsp.h Xtensa Board Support Package API + +This API defines a minimal set of board-support functions that every supported +Xtensa board is expected to provide in the board-support-package (BSP) library +associated with the board-specific LSP. Only basic board functions are provided +in this board-independent API. API functions not applicable to a board must be +stubbed in its BSP library. More complex operations must use a board-specific +interface. Functions are grouped by type of peripheral device. + +*******************************************************************************/ + +#ifndef _XTBSP_H_ +#define _XTBSP_H_ + + +#ifdef __cplusplus +extern "C" { +#endif + + +/******************************************************************************* +BOARD INITIALIZATION. +The board with all its devices is initialized by xtbsp_board_init(). +Individual devices represented by this API can be reinitialized at any +time by calling their inidividual device init functions (grouped with +other device functions). This might be useful to (say) change the baud +rate of the UART. +*/ + + +/* +Initialize the board. Must call before any other API function. +Iniitializes BSP, board in general, and all devices on the board. +*/ +extern void xtbsp_board_init(void); + + +/******************************************************************************* +BOARD CHARACTERISTICS and CONVENIENCE FUNCTIONS. +Board support functions not associated with a particular peripheral device. +*/ + +/* +Return a short string representing the type of board. +If the board has a display, the string must fit on a single line. +*/ +extern const char * xtbsp_board_name(void); + +/* +Hardware reset the entire board (if possible). Does not return if successful. +If this function returns, it is stubbed out or not possible with this board. +*/ +extern void xtbsp_board_reset(void); + +/* +Return the clock frequency in Hertz. May be constant or computed. +*/ +extern unsigned xtbsp_clock_freq_hz(void); + +/* +Return the clock period in picoseconds. May be constant or computed. +*/ +extern unsigned xtbsp_clock_period_ps(void); + +/* +Spin (at least) a number of cycles per the processor's CCOUNT register. +Unlike a s/w delay loop, the duration is not affected by compiler +optimization or interrupts completed within the delay period. +If the processor doesn't have CCOUNT, a s/w delay loop is used to obtain +a rough approximation of the cycle count. +*/ +extern void xtbsp_delay_cycles(unsigned cycles); + +/* +Spin at least a number of nanoseconds (approximate and err in the high side). +BSP implementation should do this efficiently, avoiding integer overflow or +excessive loss of precision, run-time division or floating point. +Function implementation (vs. macro) allows BSP to optimize for the clock +frequency by pre-computing (or using constant) scale factors. +*/ +extern void xtbsp_delay_ns(unsigned ns); + + +/******************************************************************************* +C LIBRARY SUPPORT. +These functions are called by the C library libgloss interface. +Their names are predetermined apart from this BSP API. +*/ + +/* +Initialize the board. Called by C library initialization code. +Usually simply calls xtbsp_board_init(). +*/ +extern void board_init(void); + +/* +(Wait for and) Input a single byte from the default character I/O +device. Return -1 if there is no input device. +This device is usually a UART and this function calls xtbsp_uart_getchar(). +On some boards (eg.) it might be a directly connected keyboard. +*/ +extern int inbyte(void); + +/* +Output a single char to the default character I/O device (and wait +until it's been taken). +This device is usually a UART and this function calls xtbsp_uart_putchar(). +On some boards (eg.) it might be a directly connected bit-mapped screen. +*/ +extern void outbyte(int c); + + +/******************************************************************************* +UART (SERIAL I/O). +Supports a single UART in a simple polling mode and provides control of +receiver and transmitter data interrupts (client must provide handler). +Provides a mapping to processor interrupt number which can be used with +the HAL to control processor interrupt enable (INTENABLE) etc. +*/ + +/* Bitmasks to identify UART interrupts. */ +typedef enum xtbsp_uart_int { + xtbsp_uart_int_rx = 1<<0, + xtbsp_uart_int_tx = 1<<1, + /* mask of all valid interrupt bits */ + xtbsp_uart_int_all = (1<<2)-1 +} xtbsp_uart_int; + +/* +Return non-zero if the board has a UART. +*/ +extern int xtbsp_uart_exists(void); + +/* +Initialize the UART: + parity = 0 (none), 1 (odd), or 2 (even). + nstop = 1 or 2 (stop bits). + ndata = 7 or 8 (data bits). +Disables all UART interrupts. +Returns non-zero if failed (perhaps due to unsupported parameter values). +Must call before any of the following functions. +*/ +extern int xtbsp_uart_init(unsigned baud, unsigned ndata, + unsigned parity, unsigned nstop); +#define xtbsp_uart_init_default() xtbsp_uart_init(38400, 8, 0, 1) + +/* +(Wait for and) Input a single char from the UART. +Any pending xtbsp_uart_int_rx interrupt is cleared. +*/ +extern char xtbsp_uart_getchar(void); + +/* +(Wait for transmitter ready and) Output a single char to the UART. +Any pending xtbsp_uart_int_tx interrupt is cleared. +*/ +extern void xtbsp_uart_putchar(const char c); + +/* +Return true (non-zero) if a character has been received and is ready +to be input by xtbsp_uart_getchar() without waiting, else return 0. +*/ +extern int xtbsp_uart_get_isready(void); + +/* +Return non-zero if a character may be output by xtbsp_uart_putchar() +without waiting, else return 0. +Any pending xtbsp_uart_int_tx interrupt is cleared. +*/ +extern int xtbsp_uart_put_isready(void); + +/* +Return the enable status of all UART interrupts represented by this API, +that is those with bits defined in type xtbsp_uart_int (1 bit = enabled). +This is the enable status at the device, not the processor's INTENABLE. +*/ +extern xtbsp_uart_int xtbsp_uart_int_enable_status(void); + +/* +Enable selected UART interrupts at the device. +*/ +extern void xtbsp_uart_int_enable(const xtbsp_uart_int mask); + +/* +Disable selected UART interrupts at the device. +*/ +extern void xtbsp_uart_int_disable(const xtbsp_uart_int mask); + +/* +Return the interrupt number (0..31) to which the selected UART interrupt +is connected. May be used with the link-time HAL to obtain more information, +eg. Xthal_intlevel_mask[xtbsp_uart_int_number(xtbsp_uart_int_rx)] +This information can be used to control the processor's INTENABLE, etc. +Result is -1 if not connected, undefined if mask has more than 1 bit set. +*/ +extern int xtbsp_uart_int_number(const xtbsp_uart_int mask); + + +/******************************************************************************* +DISPLAY. +Supports a single display that can render a series of ASCII characters. +Functions are provided to perform generic display tasks such as display +a string, display character by character, or blank the display. +Chars are 7-bit printable ASCII. Strings are C style NUL \0 terminated. +These functions busy-wait for any required timing delays so the caller does +not have to deal with timing. Some displays require long delays which in +some client applications warrant a board and RTOS specific approach to +driving the display, however that is beyond the scope of this API. +*/ + +/* +Return non-zero if board has a display. +*/ +extern int xtbsp_display_exists(void); + +/* +Initialize the display. Must call before any of the following functions. +*/ +extern void xtbsp_display_init(void); + +/* +Display a single char at position pos (0 is leftmost). Other positions are +left untouched. Positions beyond the width of the display are ignored. +*/ +extern void xtbsp_display_char(unsigned pos, const char c); + +/* +Display a string. Blank-pad to or truncate at the end of the display +(overwrites any previous string so don't need to blank display first). +*/ +extern void xtbsp_display_string(const char *s); + +/* +Blank (clear) the entire display. +*/ +extern void xtbsp_display_blank(void); + + + +#ifdef __cplusplus +} +#endif + +#endif /* _XTBSP_H_ */ diff --git a/components/esp32/include/xtensa/xtensa-libdb-macros.h b/components/esp32/include/xtensa/xtensa-libdb-macros.h new file mode 100755 index 0000000000..fbbe50964c --- /dev/null +++ b/components/esp32/include/xtensa/xtensa-libdb-macros.h @@ -0,0 +1,161 @@ +/* + * xtensa-libdb-macros.h + */ + +/* $Id: //depot/rel/Eaglenest/Xtensa/Software/libdb/xtensa-libdb-macros.h#1 $ */ + +/* Copyright (c) 2004-2008 Tensilica Inc. + + Permission is hereby granted, free of charge, to any person obtaining + a copy of this software and associated documentation files (the + "Software"), to deal in the Software without restriction, including + without limitation the rights to use, copy, modify, merge, publish, + distribute, sublicense, and/or sell copies of the Software, and to + permit persons to whom the Software is furnished to do so, subject to + the following conditions: + + The above copyright notice and this permission notice shall be included + in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY + CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ + +#ifndef __H_LIBDB_MACROS +#define __H_LIBDB_MACROS + +/* + * This header file provides macros used to construct, identify and use + * "target numbers" that are assigned to various types of Xtensa processor + * registers and states. These target numbers are used by GDB in the remote + * protocol, and are thus used by all GDB debugger agents (targets). + * They are also used in ELF debugger information sections (stabs, dwarf, etc). + * + * These macros are separated from xtensa-libdb.h because they are needed + * by certain debugger agents that do not use or have access to libdb, + * e.g. the OCD daemon, RedBoot, XMON, etc. + * + * For the time being, for compatibility with certain 3rd party debugger + * software vendors, target numbers are limited to 16 bits. It is + * conceivable that this will be extended in the future to 32 bits. + */ + +#ifdef __cplusplus +extern "C" { +#endif + +#ifndef uint32 + #define uint32 unsigned int +#endif +#ifndef int32 + #define int32 int +#endif + + +/* + * Macros to form register "target numbers" for various standard registers/states: + */ +#define XTENSA_DBREGN_INVALID -1 /* not a valid target number */ +#define XTENSA_DBREGN_A(n) (0x0000+(n)) /* address registers a0..a15 */ +#define XTENSA_DBREGN_B(n) (0x0010+(n)) /* boolean bits b0..b15 */ +#define XTENSA_DBREGN_PC 0x0020 /* program counter */ + /* 0x0021 RESERVED for use by Tensilica */ +#define XTENSA_DBREGN_BO(n) (0x0022+(n)) /* boolean octuple-bits bo0..bo1 */ +#define XTENSA_DBREGN_BQ(n) (0x0024+(n)) /* boolean quadruple-bits bq0..bq3 */ +#define XTENSA_DBREGN_BD(n) (0x0028+(n)) /* boolean double-bits bd0..bd7 */ +#define XTENSA_DBREGN_F(n) (0x0030+(n)) /* floating point registers f0..f15 */ +#define XTENSA_DBREGN_VEC(n) (0x0040+(n)) /* Vectra vec regs v0..v15 */ +#define XTENSA_DBREGN_VSEL(n) (0x0050+(n)) /* Vectra sel s0..s3 (V1) ..s7 (V2) */ +#define XTENSA_DBREGN_VALIGN(n) (0x0058+(n)) /* Vectra valign regs u0..u3 */ +#define XTENSA_DBREGN_VCOEFF(n) (0x005C+(n)) /* Vectra I vcoeff regs c0..c1 */ + /* 0x005E..0x005F RESERVED for use by Tensilica */ +#define XTENSA_DBREGN_AEP(n) (0x0060+(n)) /* HiFi2 Audio Engine regs aep0..aep7 */ +#define XTENSA_DBREGN_AEQ(n) (0x0068+(n)) /* HiFi2 Audio Engine regs aeq0..aeq3 */ + /* 0x006C..0x00FF RESERVED for use by Tensilica */ +#define XTENSA_DBREGN_AR(n) (0x0100+(n)) /* physical address regs ar0..ar63 + (note: only with window option) */ + /* 0x0140..0x01FF RESERVED for use by Tensilica */ +#define XTENSA_DBREGN_SREG(n) (0x0200+(n)) /* special registers 0..255 (core) */ +#define XTENSA_DBREGN_BR XTENSA_DBREGN_SREG(0x04) /* all 16 boolean bits, BR */ +#define XTENSA_DBREGN_MR(n) XTENSA_DBREGN_SREG(0x20+(n)) /* MAC16 registers m0..m3 */ +#define XTENSA_DBREGN_UREG(n) (0x0300+(n)) /* user registers 0..255 (TIE) */ + /* 0x0400..0x0FFF RESERVED for use by Tensilica */ + /* 0x1000..0x1FFF user-defined regfiles */ + /* 0x2000..0xEFFF other states (and regfiles) */ +#define XTENSA_DBREGN_DBAGENT(n) (0xF000+(n)) /* non-processor "registers" 0..4095 for + 3rd-party debugger agent defined use */ + /* > 0xFFFF (32-bit) RESERVED for use by Tensilica */ +/*#define XTENSA_DBREGN_CONTEXT(n) (0x02000000+((n)<<20))*/ /* add this macro's value to a target + number to identify a specific context 0..31 + for context-replicated registers */ +#define XTENSA_DBREGN_MASK 0xFFFF /* mask of valid target_number bits */ +#define XTENSA_DBREGN_WRITE_SIDE 0x04000000 /* flag to request write half of a register + split into distinct read and write entries + with the same target number (currently only + valid in a couple of libdb API functions; + see xtensa-libdb.h for details) */ + +/* + * Macros to identify specific ranges of target numbers (formed above): + * NOTE: any context number (or other upper 12 bits) are considered + * modifiers and are thus stripped out for identification purposes. + */ +#define XTENSA_DBREGN_IS_VALID(tn) (((tn) & ~0xFFFF) == 0) /* just tests it's 16-bit unsigned */ +#define XTENSA_DBREGN_IS_A(tn) (((tn) & 0xFFF0)==0x0000) /* is a0..a15 */ +#define XTENSA_DBREGN_IS_B(tn) (((tn) & 0xFFF0)==0x0010) /* is b0..b15 */ +#define XTENSA_DBREGN_IS_PC(tn) (((tn) & 0xFFFF)==0x0020) /* is program counter */ +#define XTENSA_DBREGN_IS_BO(tn) (((tn) & 0xFFFE)==0x0022) /* is bo0..bo1 */ +#define XTENSA_DBREGN_IS_BQ(tn) (((tn) & 0xFFFC)==0x0024) /* is bq0..bq3 */ +#define XTENSA_DBREGN_IS_BD(tn) (((tn) & 0xFFF8)==0x0028) /* is bd0..bd7 */ +#define XTENSA_DBREGN_IS_F(tn) (((tn) & 0xFFF0)==0x0030) /* is f0..f15 */ +#define XTENSA_DBREGN_IS_VEC(tn) (((tn) & 0xFFF0)==0x0040) /* is v0..v15 */ +#define XTENSA_DBREGN_IS_VSEL(tn) (((tn) & 0xFFF8)==0x0050) /* is s0..s7 (s0..s3 in V1) */ +#define XTENSA_DBREGN_IS_VALIGN(tn) (((tn) & 0xFFFC)==0x0058) /* is u0..u3 */ +#define XTENSA_DBREGN_IS_VCOEFF(tn) (((tn) & 0xFFFE)==0x005C) /* is c0..c1 */ +#define XTENSA_DBREGN_IS_AEP(tn) (((tn) & 0xFFF8)==0x0060) /* is aep0..aep7 */ +#define XTENSA_DBREGN_IS_AEQ(tn) (((tn) & 0xFFFC)==0x0068) /* is aeq0..aeq3 */ +#define XTENSA_DBREGN_IS_AR(tn) (((tn) & 0xFFC0)==0x0100) /* is ar0..ar63 */ +#define XTENSA_DBREGN_IS_SREG(tn) (((tn) & 0xFF00)==0x0200) /* is special register */ +#define XTENSA_DBREGN_IS_BR(tn) (((tn) & 0xFFFF)==XTENSA_DBREGN_SREG(0x04)) /* is BR */ +#define XTENSA_DBREGN_IS_MR(tn) (((tn) & 0xFFFC)==XTENSA_DBREGN_SREG(0x20)) /* m0..m3 */ +#define XTENSA_DBREGN_IS_UREG(tn) (((tn) & 0xFF00)==0x0300) /* is user register */ +#define XTENSA_DBREGN_IS_DBAGENT(tn) (((tn) & 0xF000)==0xF000) /* is non-processor */ +/*#define XTENSA_DBREGN_IS_CONTEXT(tn) (((tn) & 0x02000000) != 0)*/ /* specifies context # */ + +/* + * Macros to extract register index from a register "target number" + * when a specific range has been identified using one of the _IS_ macros above. + * These macros only return a useful value if the corresponding _IS_ macro returns true. + */ +#define XTENSA_DBREGN_A_INDEX(tn) ((tn) & 0x0F) /* 0..15 for a0..a15 */ +#define XTENSA_DBREGN_B_INDEX(tn) ((tn) & 0x0F) /* 0..15 for b0..b15 */ +#define XTENSA_DBREGN_BO_INDEX(tn) ((tn) & 0x01) /* 0..1 for bo0..bo1 */ +#define XTENSA_DBREGN_BQ_INDEX(tn) ((tn) & 0x03) /* 0..3 for bq0..bq3 */ +#define XTENSA_DBREGN_BD_INDEX(tn) ((tn) & 0x07) /* 0..7 for bd0..bd7 */ +#define XTENSA_DBREGN_F_INDEX(tn) ((tn) & 0x0F) /* 0..15 for f0..f15 */ +#define XTENSA_DBREGN_VEC_INDEX(tn) ((tn) & 0x0F) /* 0..15 for v0..v15 */ +#define XTENSA_DBREGN_VSEL_INDEX(tn) ((tn) & 0x07) /* 0..7 for s0..s7 */ +#define XTENSA_DBREGN_VALIGN_INDEX(tn) ((tn) & 0x03) /* 0..3 for u0..u3 */ +#define XTENSA_DBREGN_VCOEFF_INDEX(tn) ((tn) & 0x01) /* 0..1 for c0..c1 */ +#define XTENSA_DBREGN_AEP_INDEX(tn) ((tn) & 0x07) /* 0..7 for aep0..aep7 */ +#define XTENSA_DBREGN_AEQ_INDEX(tn) ((tn) & 0x03) /* 0..3 for aeq0..aeq3 */ +#define XTENSA_DBREGN_AR_INDEX(tn) ((tn) & 0x3F) /* 0..63 for ar0..ar63 */ +#define XTENSA_DBREGN_SREG_INDEX(tn) ((tn) & 0xFF) /* 0..255 for special registers */ +#define XTENSA_DBREGN_MR_INDEX(tn) ((tn) & 0x03) /* 0..3 for m0..m3 */ +#define XTENSA_DBREGN_UREG_INDEX(tn) ((tn) & 0xFF) /* 0..255 for user registers */ +#define XTENSA_DBREGN_DBAGENT_INDEX(tn) ((tn) & 0xFFF) /* 0..4095 for non-processor */ +/*#define XTENSA_DBREGN_CONTEXT_INDEX(tn) (((tn) >> 20) & 0x1F)*/ /* 0..31 context numbers */ + + + + +#ifdef __cplusplus +} +#endif + +#endif /* __H_LIBDB_MACROS */ + diff --git a/components/esp32/include/xtensa/xtensa-versions.h b/components/esp32/include/xtensa/xtensa-versions.h new file mode 100755 index 0000000000..abed3a18dc --- /dev/null +++ b/components/esp32/include/xtensa/xtensa-versions.h @@ -0,0 +1,347 @@ +/* + xtensa-versions.h -- definitions of Xtensa version and release numbers + + This file defines most Xtensa-related product versions and releases + that exist so far. + It also provides a bit of information about which ones are current. + This file changes every release, as versions/releases get added. + + + $Id: //depot/rel/Eaglenest/Xtensa/Software/misc/xtensa-versions.h.tpp#2 $ + + Copyright (c) 2006-2010 Tensilica Inc. + + Permission is hereby granted, free of charge, to any person obtaining + a copy of this software and associated documentation files (the + "Software"), to deal in the Software without restriction, including + without limitation the rights to use, copy, modify, merge, publish, + distribute, sublicense, and/or sell copies of the Software, and to + permit persons to whom the Software is furnished to do so, subject to + the following conditions: + + The above copyright notice and this permission notice shall be included + in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY + CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +*/ + +#ifndef XTENSA_VERSIONS_H +#define XTENSA_VERSIONS_H + + +/* + * NOTE: A "release" is a collection of product versions + * made available at once (together) to customers. + * In the past, release and version names all matched in T####.# form, + * making the distinction irrelevant. + * Starting with the RA-2004.1 release, this is no longer the case. + */ + + +/* Hardware (Xtensa/Diamond processor) versions: */ +#define XTENSA_HWVERSION_T1020_0 102000 /* versions T1020.0 */ +#define XTENSA_HWCIDSCHEME_T1020_0 10 +#define XTENSA_HWCIDVERS_T1020_0 2 +#define XTENSA_HWVERSION_T1020_1 102001 /* versions T1020.1 */ +#define XTENSA_HWCIDSCHEME_T1020_1 10 +#define XTENSA_HWCIDVERS_T1020_1 3 +#define XTENSA_HWVERSION_T1020_2B 102002 /* versions T1020.2b */ +#define XTENSA_HWCIDSCHEME_T1020_2B 10 +#define XTENSA_HWCIDVERS_T1020_2B 5 +#define XTENSA_HWVERSION_T1020_2 102002 /* versions T1020.2 */ +#define XTENSA_HWCIDSCHEME_T1020_2 10 +#define XTENSA_HWCIDVERS_T1020_2 4 +#define XTENSA_HWVERSION_T1020_3 102003 /* versions T1020.3 */ +#define XTENSA_HWCIDSCHEME_T1020_3 10 +#define XTENSA_HWCIDVERS_T1020_3 6 +#define XTENSA_HWVERSION_T1020_4 102004 /* versions T1020.4 */ +#define XTENSA_HWCIDSCHEME_T1020_4 10 +#define XTENSA_HWCIDVERS_T1020_4 7 +#define XTENSA_HWVERSION_T1030_0 103000 /* versions T1030.0 */ +#define XTENSA_HWCIDSCHEME_T1030_0 10 +#define XTENSA_HWCIDVERS_T1030_0 9 +#define XTENSA_HWVERSION_T1030_1 103001 /* versions T1030.1 */ +#define XTENSA_HWCIDSCHEME_T1030_1 10 +#define XTENSA_HWCIDVERS_T1030_1 10 +#define XTENSA_HWVERSION_T1030_2 103002 /* versions T1030.2 */ +#define XTENSA_HWCIDSCHEME_T1030_2 10 +#define XTENSA_HWCIDVERS_T1030_2 11 +#define XTENSA_HWVERSION_T1030_3 103003 /* versions T1030.3 */ +#define XTENSA_HWCIDSCHEME_T1030_3 10 +#define XTENSA_HWCIDVERS_T1030_3 12 +#define XTENSA_HWVERSION_T1040_0 104000 /* versions T1040.0 */ +#define XTENSA_HWCIDSCHEME_T1040_0 10 +#define XTENSA_HWCIDVERS_T1040_0 15 +#define XTENSA_HWVERSION_T1040_1 104001 /* versions T1040.1 */ +#define XTENSA_HWCIDSCHEME_T1040_1 01 +#define XTENSA_HWCIDVERS_T1040_1 32 +#define XTENSA_HWVERSION_T1040_1P 104001 /* versions T1040.1-prehotfix */ +#define XTENSA_HWCIDSCHEME_T1040_1P 10 +#define XTENSA_HWCIDVERS_T1040_1P 16 +#define XTENSA_HWVERSION_T1040_2 104002 /* versions T1040.2 */ +#define XTENSA_HWCIDSCHEME_T1040_2 01 +#define XTENSA_HWCIDVERS_T1040_2 33 +#define XTENSA_HWVERSION_T1040_3 104003 /* versions T1040.3 */ +#define XTENSA_HWCIDSCHEME_T1040_3 01 +#define XTENSA_HWCIDVERS_T1040_3 34 +#define XTENSA_HWVERSION_T1050_0 105000 /* versions T1050.0 */ +#define XTENSA_HWCIDSCHEME_T1050_0 1100 +#define XTENSA_HWCIDVERS_T1050_0 1 +#define XTENSA_HWVERSION_T1050_1 105001 /* versions T1050.1 */ +#define XTENSA_HWCIDSCHEME_T1050_1 1100 +#define XTENSA_HWCIDVERS_T1050_1 2 +#define XTENSA_HWVERSION_T1050_2 105002 /* versions T1050.2 */ +#define XTENSA_HWCIDSCHEME_T1050_2 1100 +#define XTENSA_HWCIDVERS_T1050_2 4 +#define XTENSA_HWVERSION_T1050_3 105003 /* versions T1050.3 */ +#define XTENSA_HWCIDSCHEME_T1050_3 1100 +#define XTENSA_HWCIDVERS_T1050_3 6 +#define XTENSA_HWVERSION_T1050_4 105004 /* versions T1050.4 */ +#define XTENSA_HWCIDSCHEME_T1050_4 1100 +#define XTENSA_HWCIDVERS_T1050_4 7 +#define XTENSA_HWVERSION_T1050_5 105005 /* versions T1050.5 */ +#define XTENSA_HWCIDSCHEME_T1050_5 1100 +#define XTENSA_HWCIDVERS_T1050_5 8 +#define XTENSA_HWVERSION_RA_2004_1 210000 /* versions LX1.0.0 */ +#define XTENSA_HWCIDSCHEME_RA_2004_1 1100 +#define XTENSA_HWCIDVERS_RA_2004_1 3 +#define XTENSA_HWVERSION_RA_2005_1 210001 /* versions LX1.0.1 */ +#define XTENSA_HWCIDSCHEME_RA_2005_1 1100 +#define XTENSA_HWCIDVERS_RA_2005_1 20 +#define XTENSA_HWVERSION_RA_2005_2 210002 /* versions LX1.0.2 */ +#define XTENSA_HWCIDSCHEME_RA_2005_2 1100 +#define XTENSA_HWCIDVERS_RA_2005_2 21 +#define XTENSA_HWVERSION_RA_2005_3 210003 /* versions LX1.0.3, X6.0.3 */ +#define XTENSA_HWCIDSCHEME_RA_2005_3 1100 +#define XTENSA_HWCIDVERS_RA_2005_3 22 +#define XTENSA_HWVERSION_RA_2006_4 210004 /* versions LX1.0.4, X6.0.4 */ +#define XTENSA_HWCIDSCHEME_RA_2006_4 1100 +#define XTENSA_HWCIDVERS_RA_2006_4 23 +#define XTENSA_HWVERSION_RA_2006_5 210005 /* versions LX1.0.5, X6.0.5 */ +#define XTENSA_HWCIDSCHEME_RA_2006_5 1100 +#define XTENSA_HWCIDVERS_RA_2006_5 24 +#define XTENSA_HWVERSION_RA_2006_6 210006 /* versions LX1.0.6, X6.0.6 */ +#define XTENSA_HWCIDSCHEME_RA_2006_6 1100 +#define XTENSA_HWCIDVERS_RA_2006_6 25 +#define XTENSA_HWVERSION_RA_2007_7 210007 /* versions LX1.0.7, X6.0.7 */ +#define XTENSA_HWCIDSCHEME_RA_2007_7 1100 +#define XTENSA_HWCIDVERS_RA_2007_7 26 +#define XTENSA_HWVERSION_RA_2008_8 210008 /* versions LX1.0.8, X6.0.8 */ +#define XTENSA_HWCIDSCHEME_RA_2008_8 1100 +#define XTENSA_HWCIDVERS_RA_2008_8 27 +#define XTENSA_HWVERSION_RB_2006_0 220000 /* versions LX2.0.0, X7.0.0 */ +#define XTENSA_HWCIDSCHEME_RB_2006_0 1100 +#define XTENSA_HWCIDVERS_RB_2006_0 48 +#define XTENSA_HWVERSION_RB_2007_1 220001 /* versions LX2.0.1, X7.0.1 */ +#define XTENSA_HWCIDSCHEME_RB_2007_1 1100 +#define XTENSA_HWCIDVERS_RB_2007_1 49 +#define XTENSA_HWVERSION_RB_2007_2 221000 /* versions LX2.1.0, X7.1.0 */ +#define XTENSA_HWCIDSCHEME_RB_2007_2 1100 +#define XTENSA_HWCIDVERS_RB_2007_2 52 +#define XTENSA_HWVERSION_RB_2008_3 221001 /* versions LX2.1.1, X7.1.1 */ +#define XTENSA_HWCIDSCHEME_RB_2008_3 1100 +#define XTENSA_HWCIDVERS_RB_2008_3 53 +#define XTENSA_HWVERSION_RB_2008_4 221002 /* versions LX2.1.2, X7.1.2 */ +#define XTENSA_HWCIDSCHEME_RB_2008_4 1100 +#define XTENSA_HWCIDVERS_RB_2008_4 54 +#define XTENSA_HWVERSION_RB_2009_5 221003 /* versions LX2.1.3, X7.1.3 */ +#define XTENSA_HWCIDSCHEME_RB_2009_5 1100 +#define XTENSA_HWCIDVERS_RB_2009_5 55 +#define XTENSA_HWVERSION_RB_2007_2_MP 221100 /* versions LX2.1.8-MP, X7.1.8-MP */ +#define XTENSA_HWCIDSCHEME_RB_2007_2_MP 1100 +#define XTENSA_HWCIDVERS_RB_2007_2_MP 64 +#define XTENSA_HWVERSION_RC_2009_0 230000 /* versions LX3.0.0, X8.0.0, MX1.0.0 */ +#define XTENSA_HWCIDSCHEME_RC_2009_0 1100 +#define XTENSA_HWCIDVERS_RC_2009_0 65 +#define XTENSA_HWVERSION_RC_2010_1 230001 /* versions LX3.0.1, X8.0.1, MX1.0.1 */ +#define XTENSA_HWCIDSCHEME_RC_2010_1 1100 +#define XTENSA_HWCIDVERS_RC_2010_1 66 +#define XTENSA_HWVERSION_RC_2010_2 230002 /* versions LX3.0.2, X8.0.2, MX1.0.2 */ +#define XTENSA_HWCIDSCHEME_RC_2010_2 1100 +#define XTENSA_HWCIDVERS_RC_2010_2 67 +#define XTENSA_HWVERSION_RC_2011_3 230003 /* versions LX3.0.3, X8.0.3, MX1.0.3 */ +#define XTENSA_HWCIDSCHEME_RC_2011_3 1100 +#define XTENSA_HWCIDVERS_RC_2011_3 68 +#define XTENSA_HWVERSION_RD_2010_0 240000 /* versions LX4.0.0, X9.0.0, MX1.1.0, TX1.0.0 */ +#define XTENSA_HWCIDSCHEME_RD_2010_0 1100 +#define XTENSA_HWCIDVERS_RD_2010_0 80 +#define XTENSA_HWVERSION_RD_2011_1 240001 /* versions LX4.0.1, X9.0.1, MX1.1.1, TX1.0.1 */ +#define XTENSA_HWCIDSCHEME_RD_2011_1 1100 +#define XTENSA_HWCIDVERS_RD_2011_1 81 +#define XTENSA_HWVERSION_RD_2011_2 240002 /* versions LX4.0.2, X9.0.2, MX1.1.2, TX1.0.2 */ +#define XTENSA_HWCIDSCHEME_RD_2011_2 1100 +#define XTENSA_HWCIDVERS_RD_2011_2 82 +#define XTENSA_HWVERSION_RD_2011_3 240003 /* versions LX4.0.3, X9.0.3, MX1.1.3, TX1.0.3 */ +#define XTENSA_HWCIDSCHEME_RD_2011_3 1100 +#define XTENSA_HWCIDVERS_RD_2011_3 83 +#define XTENSA_HWVERSION_RD_2012_4 240004 /* versions LX4.0.4, X9.0.4, MX1.1.4, TX1.0.4 */ +#define XTENSA_HWCIDSCHEME_RD_2012_4 1100 +#define XTENSA_HWCIDVERS_RD_2012_4 84 +#define XTENSA_HWVERSION_RD_2012_5 240005 /* versions LX4.0.5, X9.0.5, MX1.1.5, TX1.0.5 */ +#define XTENSA_HWCIDSCHEME_RD_2012_5 1100 +#define XTENSA_HWCIDVERS_RD_2012_5 85 +#define XTENSA_HWVERSION_RE_2012_0 250000 /* versions LX5.0.0, X10.0.0, MX1.2.0, TX2.0.0 */ +#define XTENSA_HWCIDSCHEME_RE_2012_0 1100 +#define XTENSA_HWCIDVERS_RE_2012_0 96 +#define XTENSA_HWVERSION_RE_2012_1 250001 /* versions LX5.0.1, X10.0.1, MX1.2.1, TX2.0.1 */ +#define XTENSA_HWCIDSCHEME_RE_2012_1 1100 +#define XTENSA_HWCIDVERS_RE_2012_1 97 +#define XTENSA_HWVERSION_RE_2013_2 250002 /* versions LX5.0.2, X10.0.2, MX1.2.2, TX2.0.2 */ +#define XTENSA_HWCIDSCHEME_RE_2013_2 1100 +#define XTENSA_HWCIDVERS_RE_2013_2 98 +#define XTENSA_HWVERSION_RE_2013_3 250003 /* versions LX5.0.3, X10.0.3, MX1.2.3, TX2.0.3 */ +#define XTENSA_HWCIDSCHEME_RE_2013_3 1100 +#define XTENSA_HWCIDVERS_RE_2013_3 99 +#define XTENSA_HWVERSION_RE_2013_4 250004 /* versions LX5.0.4, X10.0.4, MX1.2.4, TX2.0.4 */ +#define XTENSA_HWCIDSCHEME_RE_2013_4 1100 +#define XTENSA_HWCIDVERS_RE_2013_4 100 +#define XTENSA_HWVERSION_RE_2014_5 250005 /* versions LX5.0.5, X10.0.5, MX1.2.5, TX2.0.5 */ +#define XTENSA_HWCIDSCHEME_RE_2014_5 1100 +#define XTENSA_HWCIDVERS_RE_2014_5 101 +#define XTENSA_HWVERSION_RE_2015_6 250006 /* versions LX5.0.6, X10.0.6, MX1.2.6, TX2.0.6 */ +#define XTENSA_HWCIDSCHEME_RE_2015_6 1100 +#define XTENSA_HWCIDVERS_RE_2015_6 102 +#define XTENSA_HWVERSION_RF_2014_0 260000 /* versions LX6.0.0, X11.0.0, MX1.3.0, TX3.0.0 */ +#define XTENSA_HWCIDSCHEME_RF_2014_0 1100 +#define XTENSA_HWCIDVERS_RF_2014_0 112 +#define XTENSA_HWVERSION_RF_2014_1 260001 /* versions LX6.0.1, X11.0.1 */ +#define XTENSA_HWCIDSCHEME_RF_2014_1 1100 +#define XTENSA_HWCIDVERS_RF_2014_1 113 +#define XTENSA_HWVERSION_RF_2015_2 260002 /* versions LX6.0.2, X11.0.2 */ +#define XTENSA_HWCIDSCHEME_RF_2015_2 1100 +#define XTENSA_HWCIDVERS_RF_2015_2 114 +#define XTENSA_HWVERSION_RF_2015_3 260003 /* versions LX6.0.3, X11.0.3 */ +#define XTENSA_HWCIDSCHEME_RF_2015_3 1100 +#define XTENSA_HWCIDVERS_RF_2015_3 115 +#define XTENSA_HWVERSION_RG_2015_0 270000 /* versions LX7.0.0, X12.0.0, NX1.0.0, SX1.0.0, MX1.4.0, TX4.0.0 */ +#define XTENSA_HWCIDSCHEME_RG_2015_0 1100 +#define XTENSA_HWCIDVERS_RG_2015_0 128 + +/* Software (Xtensa Tools) versions: */ +#define XTENSA_SWVERSION_T1020_0 102000 /* versions T1020.0 */ +#define XTENSA_SWVERSION_T1020_1 102001 /* versions T1020.1 */ +#define XTENSA_SWVERSION_T1020_2B 102002 /* versions T1020.2b */ +#define XTENSA_SWVERSION_T1020_2 102002 /* versions T1020.2 */ +#define XTENSA_SWVERSION_T1020_3 102003 /* versions T1020.3 */ +#define XTENSA_SWVERSION_T1020_4 102004 /* versions T1020.4 */ +#define XTENSA_SWVERSION_T1030_0 103000 /* versions T1030.0 */ +#define XTENSA_SWVERSION_T1030_1 103001 /* versions T1030.1 */ +#define XTENSA_SWVERSION_T1030_2 103002 /* versions T1030.2 */ +#define XTENSA_SWVERSION_T1030_3 103003 /* versions T1030.3 */ +#define XTENSA_SWVERSION_T1040_0 104000 /* versions T1040.0 */ +#define XTENSA_SWVERSION_T1040_1 104001 /* versions T1040.1 */ +#define XTENSA_SWVERSION_T1040_1P 104001 /* versions T1040.1-prehotfix */ +#define XTENSA_SWVERSION_T1040_2 104002 /* versions T1040.2 */ +#define XTENSA_SWVERSION_T1040_3 104003 /* versions T1040.3 */ +#define XTENSA_SWVERSION_T1050_0 105000 /* versions T1050.0 */ +#define XTENSA_SWVERSION_T1050_1 105001 /* versions T1050.1 */ +#define XTENSA_SWVERSION_T1050_2 105002 /* versions T1050.2 */ +#define XTENSA_SWVERSION_T1050_3 105003 /* versions T1050.3 */ +#define XTENSA_SWVERSION_T1050_4 105004 /* versions T1050.4 */ +#define XTENSA_SWVERSION_T1050_5 105005 /* versions T1050.5 */ +#define XTENSA_SWVERSION_RA_2004_1 600000 /* versions 6.0.0 */ +#define XTENSA_SWVERSION_RA_2005_1 600001 /* versions 6.0.1 */ +#define XTENSA_SWVERSION_RA_2005_2 600002 /* versions 6.0.2 */ +#define XTENSA_SWVERSION_RA_2005_3 600003 /* versions 6.0.3 */ +#define XTENSA_SWVERSION_RA_2006_4 600004 /* versions 6.0.4 */ +#define XTENSA_SWVERSION_RA_2006_5 600005 /* versions 6.0.5 */ +#define XTENSA_SWVERSION_RA_2006_6 600006 /* versions 6.0.6 */ +#define XTENSA_SWVERSION_RA_2007_7 600007 /* versions 6.0.7 */ +#define XTENSA_SWVERSION_RA_2008_8 600008 /* versions 6.0.8 */ +#define XTENSA_SWVERSION_RB_2006_0 700000 /* versions 7.0.0 */ +#define XTENSA_SWVERSION_RB_2007_1 700001 /* versions 7.0.1 */ +#define XTENSA_SWVERSION_RB_2007_2 701000 /* versions 7.1.0 */ +#define XTENSA_SWVERSION_RB_2008_3 701001 /* versions 7.1.1 */ +#define XTENSA_SWVERSION_RB_2008_4 701002 /* versions 7.1.2 */ +#define XTENSA_SWVERSION_RB_2009_5 701003 /* versions 7.1.3 */ +#define XTENSA_SWVERSION_RB_2007_2_MP 701100 /* versions 7.1.8-MP */ +#define XTENSA_SWVERSION_RC_2009_0 800000 /* versions 8.0.0 */ +#define XTENSA_SWVERSION_RC_2010_1 800001 /* versions 8.0.1 */ +#define XTENSA_SWVERSION_RC_2010_2 800002 /* versions 8.0.2 */ +#define XTENSA_SWVERSION_RC_2011_3 800003 /* versions 8.0.3 */ +#define XTENSA_SWVERSION_RD_2010_0 900000 /* versions 9.0.0 */ +#define XTENSA_SWVERSION_RD_2011_1 900001 /* versions 9.0.1 */ +#define XTENSA_SWVERSION_RD_2011_2 900002 /* versions 9.0.2 */ +#define XTENSA_SWVERSION_RD_2011_3 900003 /* versions 9.0.3 */ +#define XTENSA_SWVERSION_RD_2012_4 900004 /* versions 9.0.4 */ +#define XTENSA_SWVERSION_RD_2012_5 900005 /* versions 9.0.5 */ +#define XTENSA_SWVERSION_RE_2012_0 1000000 /* versions 10.0.0 */ +#define XTENSA_SWVERSION_RE_2012_1 1000001 /* versions 10.0.1 */ +#define XTENSA_SWVERSION_RE_2013_2 1000002 /* versions 10.0.2 */ +#define XTENSA_SWVERSION_RE_2013_3 1000003 /* versions 10.0.3 */ +#define XTENSA_SWVERSION_RE_2013_4 1000004 /* versions 10.0.4 */ +#define XTENSA_SWVERSION_RE_2014_5 1000005 /* versions 10.0.5 */ +#define XTENSA_SWVERSION_RE_2015_6 1000006 /* versions 10.0.6 */ +#define XTENSA_SWVERSION_RF_2014_0 1100000 /* versions 11.0.0 */ +#define XTENSA_SWVERSION_RF_2014_1 1100001 /* versions 11.0.1 */ +#define XTENSA_SWVERSION_RF_2015_2 1100002 /* versions 11.0.2 */ +#define XTENSA_SWVERSION_RF_2015_3 1100003 /* versions 11.0.3 */ +#define XTENSA_SWVERSION_RG_2015_0 1200000 /* versions 12.0.0 */ +#define XTENSA_SWVERSION_T1040_1_PREHOTFIX XTENSA_SWVERSION_T1040_1P /* T1040.1-prehotfix */ +#define XTENSA_SWVERSION_6_0_0 XTENSA_SWVERSION_RA_2004_1 /* 6.0.0 */ +#define XTENSA_SWVERSION_6_0_1 XTENSA_SWVERSION_RA_2005_1 /* 6.0.1 */ +#define XTENSA_SWVERSION_6_0_2 XTENSA_SWVERSION_RA_2005_2 /* 6.0.2 */ +#define XTENSA_SWVERSION_6_0_3 XTENSA_SWVERSION_RA_2005_3 /* 6.0.3 */ +#define XTENSA_SWVERSION_6_0_4 XTENSA_SWVERSION_RA_2006_4 /* 6.0.4 */ +#define XTENSA_SWVERSION_6_0_5 XTENSA_SWVERSION_RA_2006_5 /* 6.0.5 */ +#define XTENSA_SWVERSION_6_0_6 XTENSA_SWVERSION_RA_2006_6 /* 6.0.6 */ +#define XTENSA_SWVERSION_6_0_7 XTENSA_SWVERSION_RA_2007_7 /* 6.0.7 */ +#define XTENSA_SWVERSION_6_0_8 XTENSA_SWVERSION_RA_2008_8 /* 6.0.8 */ +#define XTENSA_SWVERSION_7_0_0 XTENSA_SWVERSION_RB_2006_0 /* 7.0.0 */ +#define XTENSA_SWVERSION_7_0_1 XTENSA_SWVERSION_RB_2007_1 /* 7.0.1 */ +#define XTENSA_SWVERSION_7_1_0 XTENSA_SWVERSION_RB_2007_2 /* 7.1.0 */ +#define XTENSA_SWVERSION_7_1_1 XTENSA_SWVERSION_RB_2008_3 /* 7.1.1 */ +#define XTENSA_SWVERSION_7_1_2 XTENSA_SWVERSION_RB_2008_4 /* 7.1.2 */ +#define XTENSA_SWVERSION_7_1_3 XTENSA_SWVERSION_RB_2009_5 /* 7.1.3 */ +#define XTENSA_SWVERSION_7_1_8_MP XTENSA_SWVERSION_RB_2007_2_MP /* 7.1.8-MP */ +#define XTENSA_SWVERSION_8_0_0 XTENSA_SWVERSION_RC_2009_0 /* 8.0.0 */ +#define XTENSA_SWVERSION_8_0_1 XTENSA_SWVERSION_RC_2010_1 /* 8.0.1 */ +#define XTENSA_SWVERSION_8_0_2 XTENSA_SWVERSION_RC_2010_2 /* 8.0.2 */ +#define XTENSA_SWVERSION_8_0_3 XTENSA_SWVERSION_RC_2011_3 /* 8.0.3 */ +#define XTENSA_SWVERSION_9_0_0 XTENSA_SWVERSION_RD_2010_0 /* 9.0.0 */ +#define XTENSA_SWVERSION_9_0_1 XTENSA_SWVERSION_RD_2011_1 /* 9.0.1 */ +#define XTENSA_SWVERSION_9_0_2 XTENSA_SWVERSION_RD_2011_2 /* 9.0.2 */ +#define XTENSA_SWVERSION_9_0_3 XTENSA_SWVERSION_RD_2011_3 /* 9.0.3 */ +#define XTENSA_SWVERSION_9_0_4 XTENSA_SWVERSION_RD_2012_4 /* 9.0.4 */ +#define XTENSA_SWVERSION_9_0_5 XTENSA_SWVERSION_RD_2012_5 /* 9.0.5 */ +#define XTENSA_SWVERSION_10_0_0 XTENSA_SWVERSION_RE_2012_0 /* 10.0.0 */ +#define XTENSA_SWVERSION_10_0_1 XTENSA_SWVERSION_RE_2012_1 /* 10.0.1 */ +#define XTENSA_SWVERSION_10_0_2 XTENSA_SWVERSION_RE_2013_2 /* 10.0.2 */ +#define XTENSA_SWVERSION_10_0_3 XTENSA_SWVERSION_RE_2013_3 /* 10.0.3 */ +#define XTENSA_SWVERSION_10_0_4 XTENSA_SWVERSION_RE_2013_4 /* 10.0.4 */ +#define XTENSA_SWVERSION_10_0_5 XTENSA_SWVERSION_RE_2014_5 /* 10.0.5 */ +#define XTENSA_SWVERSION_10_0_6 XTENSA_SWVERSION_RE_2015_6 /* 10.0.6 */ +#define XTENSA_SWVERSION_11_0_0 XTENSA_SWVERSION_RF_2014_0 /* 11.0.0 */ +#define XTENSA_SWVERSION_11_0_1 XTENSA_SWVERSION_RF_2014_1 /* 11.0.1 */ +#define XTENSA_SWVERSION_11_0_2 XTENSA_SWVERSION_RF_2015_2 /* 11.0.2 */ +#define XTENSA_SWVERSION_11_0_3 XTENSA_SWVERSION_RF_2015_3 /* 11.0.3 */ +#define XTENSA_SWVERSION_12_0_0 XTENSA_SWVERSION_RG_2015_0 /* 12.0.0 */ + + +/* The current release: */ +#define XTENSA_RELEASE_NAME "RF-2015.3" +#define XTENSA_RELEASE_CANONICAL_NAME "RF-2015.3" + +/* The product versions within the current release: */ +#define XTENSA_SWVERSION XTENSA_SWVERSION_RF_2015_3 +#define XTENSA_SWVERSION_NAME "11.0.3" +#define XTENSA_SWVERSION_CANONICAL_NAME "11.0.3" +#define XTENSA_SWVERSION_MAJORMID_NAME "11.0" +#define XTENSA_SWVERSION_MAJOR_NAME "11" +/* For product licensing (not necessarily same as *_MAJORMID_NAME): */ +#define XTENSA_SWVERSION_LICENSE_NAME "11.0" + +/* Note: there may be multiple hardware products in one release, + and software can target older hardware, so the notion of + "current" hardware versions is partially configuration dependent. + For now, "current" hardware product version info is left out + to avoid confusion. */ + +#endif /*XTENSA_VERSIONS_H*/ + diff --git a/components/esp32/include/xtensa/xtensa-xer.h b/components/esp32/include/xtensa/xtensa-xer.h new file mode 100755 index 0000000000..900bda3338 --- /dev/null +++ b/components/esp32/include/xtensa/xtensa-xer.h @@ -0,0 +1,149 @@ +/* xer-constants.h -- various constants describing external registers accessed + via wer and rer. + + TODO: find a better prefix. Also conditionalize certain constants based + on number of cores and interrupts actually present. +*/ + +/* + * Copyright (c) 1999-2008 Tensilica Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY + * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +#include + +#define NUM_INTERRUPTS 27 +#define NUM_CORES 4 + +/* Routing of NMI (BInterrupt2) and interrupts 0..n-1 (BInterrupt3+) + RER reads + WER writes + */ + +#define XER_MIROUT 0x0000 +#define XER_MIROUT_LAST (XER_MIROUT + NUM_INTERRUPTS) + + +/* IPI to core M (all 16 causes). + + RER reads + WER clears + */ +#define XER_MIPICAUSE 0x0100 +#define XER_MIPICAUSE_FIELD_A_FIRST 0x0 +#define XER_MIPICAUSE_FIELD_A_LAST 0x0 +#define XER_MIPICAUSE_FIELD_B_FIRST 0x1 +#define XER_MIPICAUSE_FIELD_B_LAST 0x3 +#define XER_MIPICAUSE_FIELD_C_FIRST 0x4 +#define XER_MIPICAUSE_FIELD_C_LAST 0x7 +#define XER_MIPICAUSE_FIELD_D_FIRST 0x8 +#define XER_MIPICAUSE_FIELD_D_LAST 0xF + + +/* IPI from cause bit 0..15 + + RER invalid + WER sets +*/ +#define XER_MIPISET 0x0140 +#define XER_MIPISET_LAST 0x014F + + +/* Global enable + + RER read + WER clear +*/ +#define XER_MIENG 0x0180 + + +/* Global enable + + RER invalid + WER set +*/ +#define XER_MIENG_SET 0x0184 + +/* Global assert + + RER read + WER clear +*/ +#define XER_MIASG 0x0188 + + +/* Global enable + + RER invalid + WER set +*/ +#define XER_MIASG_SET 0x018C + + +/* IPI partition register + + RER read + WER write +*/ +#define XER_PART 0x0190 +#define XER_IPI0 0x0 +#define XER_IPI1 0x1 +#define XER_IPI2 0x2 +#define XER_IPI3 0x3 + +#define XER_PART_ROUTE_IPI(NUM, FIELD) ((NUM) << ((FIELD) << 2)) + +#define XER_PART_ROUTE_IPI_CAUSE(TO_A, TO_B, TO_C, TO_D) \ + (XER_PART_ROUTE_IPI(TO_A, XER_IPI0) | \ + XER_PART_ROUTE_IPI(TO_B, XER_IPI1) | \ + XER_PART_ROUTE_IPI(TO_C, XER_IPI2) | \ + XER_PART_ROUTE_IPI(TO_D, XER_IPI3)) + +#define XER_IPI_WAKE_EXT_INTERRUPT XCHAL_EXTINT0_NUM +#define XER_IPI_WAKE_CAUSE XER_MIPICAUSE_FIELD_C_FIRST +#define XER_IPI_WAKE_ADDRESS (XER_MIPISET + XER_IPI_WAKE_CAUSE) +#define XER_DEFAULT_IPI_ROUTING XER_PART_ROUTE_IPI_CAUSE(XER_IPI1, XER_IPI0, XER_IPI2, XER_IPI3) + + +/* System configuration ID + + RER read + WER invalid +*/ +#define XER_SYSCFGID 0x01A0 + + +/* RunStall to slave processors + + RER read + WER write +*/ +#define XER_MPSCORE 0x0200 + + +/* Cache coherency ON + + RER read + WER write +*/ +#define XER_CCON 0x0220 + + diff --git a/components/esp32/include/xtensa/xtkc705.h b/components/esp32/include/xtensa/xtkc705.h new file mode 100755 index 0000000000..831c15d541 --- /dev/null +++ b/components/esp32/include/xtensa/xtkc705.h @@ -0,0 +1,14 @@ +/* Copyright (c) 2006-2013 by Tensilica Inc. ALL RIGHTS RESERVED. +/ These coded instructions, statements, and computer programs are the +/ copyrighted works and confidential proprietary information of Tensilica Inc. +/ They may not be modified, copied, reproduced, distributed, or disclosed to +/ third parties in any manner, medium, or form, in whole or in part, without +/ the prior written consent of Tensilica Inc. +*/ + +/* xtkc705.h - Xtensa Xilinx KC705 (XT-KC705) board specific definitions */ + +/* 99.9% same as ML605, just indicate we're KC705 and include ML605 header: */ +#define XTBOARD_IS_KC705 1 +#include + diff --git a/components/esp32/include/xtensa/xtkc705/xtensa/board.h b/components/esp32/include/xtensa/xtkc705/xtensa/board.h new file mode 100755 index 0000000000..5d2d834802 --- /dev/null +++ b/components/esp32/include/xtensa/xtkc705/xtensa/board.h @@ -0,0 +1,13 @@ +/* + * board.h - Include board-specific definitions + * + * Copyright (c) 2013 by Tensilica Inc. ALL RIGHTS RESERVED. + * These coded instructions, statements, and computer programs are the + * copyrighted works and confidential proprietary information of Tensilica Inc. + * They may not be modified, copied, reproduced, distributed, or disclosed to + * third parties in any manner, medium, or form, in whole or in part, without + * the prior written consent of Tensilica Inc. + */ + +#include + diff --git a/components/esp32/include/xtensa/xtload-api.h b/components/esp32/include/xtensa/xtload-api.h new file mode 100755 index 0000000000..4e2297f510 --- /dev/null +++ b/components/esp32/include/xtensa/xtload-api.h @@ -0,0 +1,77 @@ +/* Customer ID=11656; Build=0x5f626; Copyright (c) 2003-2012 Tensilica Inc. ALL RIGHTS RESERVED. + These coded instructions, statements, and computer programs are the + copyrighted works and confidential proprietary information of Tensilica Inc. + They may not be modified, copied, reproduced, distributed, or disclosed to + third parties in any manner, medium, or form, in whole or in part, without + the prior written consent of Tensilica Inc. */ + +#ifndef _XTLOAD_API_H +#define _XTLOAD_API_H + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +#define XTENSA_BYTES_PER_WORD 4 +#define XLOAD_ALL_CORES -1 + +typedef int core_number_t; +typedef uint32_t xtload_address_t; +typedef uint32_t xtload_word_count_t; +typedef uint32_t * xtload_word_ptr_t; + +/* These functions correspond one-to-one with xt-load script + commands. See the documentation for xt-load for their usage. + + There are however, several higher-level script commands--such as + load-elf-file--which don't have direct analogues here. These + "missing" commands are essentially just macros that result in + several of these commands below. Note that you can execute several + of these commands, then the results of a script, or vice-versa. + */ + +void xtload_bootloader_wake (void); +void xtload_bootloader_sleep (void); +void xtload_bootloader_done (void); +void xtload_bootloader_not_done (void); +void xtload_reset_and_cont (core_number_t core); +void xtload_stall_and_reset (core_number_t core); +#define xtload_reset_and_stall xtload_stall_and_reset +void xtload_stall_and_target (core_number_t core); +void xtload_ignore_and_stall (core_number_t core); +void xtload_ignore_and_cont (core_number_t core); +#define xtload_ignore_and_continue xtload_ignore_and_cont +void xtload_read_words (xtload_address_t addr, xtload_word_count_t count); +void xtload_zero_words (xtload_address_t addr, xtload_word_count_t count); +void xtload_write_words (int swap, xtload_address_t addr, + xtload_word_ptr_t ptr, xtload_word_count_t count); +void xtload_setup_write_words (xtload_address_t addr, xtload_word_count_t count); +void xtload_read_register (core_number_t core); + +/* *I M P O R T A N T* + + The bootloader API calls this function whenever it outputs a word + to the bootloader hardware chain. + + Because the API has no information about how the bootloader + hardware is connected to the host hardware, the user must + implement this function to write a word to the bootloader's register. + + A user's implementation might write the bytes to an Xtensa queue or + to a memory-mapped register. + + For example, xt-load uses this API just like any other client. Its + implementation of this function simply writes this word to an + output file. +*/ + +void xtload_user_output_word (uint32_t word); + +#ifdef __cplusplus +} +#endif + +#endif /* _XTLOAD_API_H */ + diff --git a/components/esp32/include/xtensa/xtml605.h b/components/esp32/include/xtensa/xtml605.h new file mode 100755 index 0000000000..5f54d700d1 --- /dev/null +++ b/components/esp32/include/xtensa/xtml605.h @@ -0,0 +1,338 @@ +/* Copyright (c) 2007-2013 by Tensilica Inc. ALL RIGHTS RESERVED. +/ These coded instructions, statements, and computer programs are the +/ copyrighted works and confidential proprietary information of Tensilica Inc. +/ They may not be modified, copied, reproduced, distributed, or disclosed to +/ third parties in any manner, medium, or form, in whole or in part, without +/ the prior written consent of Tensilica Inc. +*/ + +/* xtml605.h - Xtensa Xilinx ML605 (XT-ML605) board specific definitions */ +/* xtkc705.h - Also includes this, for the Xilinx KC705 (XT-KC705). */ + +#ifndef _INC_ML605_H_ +#define _INC_ML605_H_ + +#include +#include + +#if XTBOARD_IS_KC705 +#define XTBOARD_NAME "XT-KC705" +#else +#define XTBOARD_NAME "XT-ML605" +#endif + + +/* + * Default assignment of ML605 devices to external interrupts. + */ + +/* Ethernet interrupt: */ +#ifdef XCHAL_EXTINT1_NUM +#define ETHERNET_INTNUM XCHAL_EXTINT1_NUM +#define ETHERNET_INTLEVEL XCHAL_EXTINT1_LEVEL +#define ETHERNET_INTMASK XCHAL_EXTINT1_MASK +#else +#define ETHERNET_INTMASK 0 +#endif + +/* UART interrupt: */ +#ifdef XCHAL_EXTINT0_NUM +#define UART16550_INTNUM XCHAL_EXTINT0_NUM +#define UART16550_INTLEVEL XCHAL_EXTINT0_LEVEL +#define UART16550_INTMASK XCHAL_EXTINT0_MASK +#else +#define UART16550_INTMASK 0 +#endif + +/* Audio output interrupt (I2S transmitter FIFO): */ +#ifdef XCHAL_EXTINT2_NUM +#define AUDIO_I2S_OUT_INTNUM XCHAL_EXTINT2_NUM +#define AUDIO_I2S_OUT_INTLEVEL XCHAL_EXTINT2_LEVEL +#define AUDIO_I2S_OUT_INTMASK XCHAL_EXTINT2_MASK +#else +#define AUDIO_I2S_OUT_INTMASK 0 +#endif + +/* Audio input interrupt (I2S receiver FIFO): */ +#ifdef XCHAL_EXTINT3_NUM +#define AUDIO_I2S_IN_INTNUM XCHAL_EXTINT3_NUM +#define AUDIO_I2S_IN_INTLEVEL XCHAL_EXTINT3_LEVEL +#define AUDIO_I2S_IN_INTMASK XCHAL_EXTINT3_MASK +#else +#define AUDIO_I2S_IN_INTMASK 0 +#endif + +/* I2C interrupt */ +#ifdef XCHAL_EXTINT4_NUM +#define I2C_INTNUM XCHAL_EXTINT4_NUM +#define I2C_INTLEVEL XCHAL_EXTINT4_LEVEL +#define I2C_INTMASK XCHAL_EXTINT4_MASK +#else +#define I2C_INTMASK 0 +#endif + +/* USB interrupt */ +#ifdef XCHAL_EXTINT5_NUM +#define USB_INTNUM XCHAL_EXTINT5_NUM +#define USB_INTLEVEL XCHAL_EXTINT5_LEVEL +#define USB_INTMASK XCHAL_EXTINT5_MASK +#else +#define USB_INTMASK 0 +#endif + +/* + * Device addresses. + * + * Note: for endianness-independence, use 32-bit loads and stores for all + * register accesses to Ethernet, UART and LED devices. Undefined bits + * may need to be masked out if needed when reading if the actual register + * size is smaller than 32 bits. + * + * Note: ML605 bus byte lanes are defined in terms of msbyte and lsbyte + * relative to the processor. So 32-bit registers are accessed consistently + * from both big and little endian processors. However, this means byte + * sequences are not consistent between big and little endian processors. + * This is fine for RAM, and for ROM if ROM is created for a specific + * processor (and thus has correct byte sequences). However this may be + * unexpected for Flash, which might contain a file-system that one wants + * to use for multiple processor configurations (eg. the Flash might contain + * the Ethernet card's address, endianness-independent application data, etc). + * That is, byte sequences written in Flash by a core of a given endianness + * will be byte-swapped when seen by a core of the other endianness. + * Someone implementing an endianness-independent Flash file system will + * likely handle this byte-swapping issue in the Flash driver software. + */ + +#define ML605_FLASH_MAXSIZE 0x01000000 /* 16 MB */ +#define ML605_FLASH_IOBLOCK_OFS 0x08000000 + +#define KC705_FLASH_MAXSIZE 0x08000000 /* 128 MB */ +#define KC705_FLASH_IOBLOCK_OFS 0x00000000 + +#if XTBOARD_IS_KC705 +#define XTBOARD_FLASH_MAXSIZE KC705_FLASH_MAXSIZE +#define XTBOARD_FLASH_IO_OFS KC705_FLASH_IOBLOCK_OFS +#else +#define XTBOARD_FLASH_MAXSIZE ML605_FLASH_MAXSIZE +#define XTBOARD_FLASH_IO_OFS ML605_FLASH_IOBLOCK_OFS +#endif + +#ifdef XSHAL_IOBLOCK_BYPASS_PADDR + +/* Flash Memory: */ +# define XTBOARD_FLASH_PADDR (XSHAL_IOBLOCK_BYPASS_PADDR+XTBOARD_FLASH_IO_OFS) + +/* FPGA registers: */ +# define XTBOARD_FPGAREGS_PADDR (XSHAL_IOBLOCK_BYPASS_PADDR+0x0D020000) + +/* Ethernet controller/transceiver SONIC SN83934: */ +# define ETHERNET_PADDR (XSHAL_IOBLOCK_BYPASS_PADDR+0x0D030000) + + +/* UART National-Semi PC16550D: */ +# define UART16550_PADDR (XSHAL_IOBLOCK_BYPASS_PADDR+0x0D050000) + +/* I2S transmitter */ +# define AUDIO_I2S_OUT_PADDR (XSHAL_IOBLOCK_BYPASS_PADDR+0x0D080000) + +/* I2S receiver */ +# define AUDIO_I2S_IN_PADDR (XSHAL_IOBLOCK_BYPASS_PADDR+0x0D088000) + +/* I2C master */ +# define I2C_PADDR (XSHAL_IOBLOCK_BYPASS_PADDR+0x0D090000) + +/* SPI controller */ +# define SPI_PADDR (XSHAL_IOBLOCK_BYPASS_PADDR+0x0D0A0000) + +/* Display controller Sunplus SPLC780D, 4bit mode, + * LCD Display MYTech MOC-16216B-B: */ +# define SPLC780D_4BIT_PADDR (XSHAL_IOBLOCK_BYPASS_PADDR+0x0D0C0000) + +/* USB Controller */ +# define USB_PADDR (XSHAL_IOBLOCK_BYPASS_PADDR+0x0D0D0000) + +/* Ethernet buffer: */ +# define ETHERNET_BUFFER_PADDR (XSHAL_IOBLOCK_BYPASS_PADDR+0x0D800000) + +#endif /* XSHAL_IOBLOCK_BYPASS_PADDR */ + +/* These devices might be accessed cached: */ +#ifdef XSHAL_IOBLOCK_CACHED_PADDR +# define XTBOARD_FLASH_CACHED_PADDR (XSHAL_IOBLOCK_CACHED_PADDR+XTBOARD_FLASH_IO_OFS) +# define ETHERNET_BUFFER_CACHED_PADDR (XSHAL_IOBLOCK_CACHED_PADDR+0x0D800000) +#endif /* XSHAL_IOBLOCK_CACHED_PADDR */ + + +/*** Same thing over again, this time with virtual addresses: ***/ + +#ifdef XSHAL_IOBLOCK_BYPASS_VADDR + +/* Flash Memory: */ +# define XTBOARD_FLASH_VADDR (XSHAL_IOBLOCK_BYPASS_VADDR+XTBOARD_FLASH_IO_OFS) + +/* FPGA registers: */ +# define XTBOARD_FPGAREGS_VADDR (XSHAL_IOBLOCK_BYPASS_VADDR+0x0D020000) + +/* Ethernet controller/transceiver SONIC SN83934: */ +# define ETHERNET_VADDR (XSHAL_IOBLOCK_BYPASS_VADDR+0x0D030000) + + +/* UART National-Semi PC16550D: */ +# define UART16550_VADDR (XSHAL_IOBLOCK_BYPASS_VADDR+0x0D050000) + +/* I2S transmitter */ +# define AUDIO_I2S_OUT_VADDR (XSHAL_IOBLOCK_BYPASS_VADDR+0x0D080000) + +/* I2S receiver */ +# define AUDIO_I2S_IN_VADDR (XSHAL_IOBLOCK_BYPASS_VADDR+0x0D088000) + +/* I2C master */ +# define I2C_VADDR (XSHAL_IOBLOCK_BYPASS_VADDR+0x0D090000) + +/* SPI controller */ +# define SPI_VADDR (XSHAL_IOBLOCK_BYPASS_VADDR+0x0D0A0000) + +/* Display controller Sunplus SPLC780D, 4bit mode, + * LCD Display MYTech MOC-16216B-B: */ +# define SPLC780D_4BIT_VADDR (XSHAL_IOBLOCK_BYPASS_VADDR+0x0D0C0000) + +/* USB Controller */ +# define USB_VADDR (XSHAL_IOBLOCK_BYPASS_VADDR+0x0D0D0000) + +/* Ethernet buffer: */ +# define ETHERNET_BUFFER_VADDR (XSHAL_IOBLOCK_BYPASS_VADDR+0x0D800000) + +#endif /* XSHAL_IOBLOCK_BYPASS_VADDR */ + +/* These devices might be accessed cached: */ +#ifdef XSHAL_IOBLOCK_CACHED_VADDR +# define XTBOARD_FLASH_CACHED_VADDR (XSHAL_IOBLOCK_CACHED_VADDR+XTBOARD_FLASH_IO_OFS) +# define ETHERNET_BUFFER_CACHED_VADDR (XSHAL_IOBLOCK_CACHED_VADDR+0x0D800000) +#endif /* XSHAL_IOBLOCK_CACHED_VADDR */ + + +/* System ROM: */ +#define XTBOARD_ROM_SIZE XSHAL_ROM_SIZE +#ifdef XSHAL_ROM_VADDR +#define XTBOARD_ROM_VADDR XSHAL_ROM_VADDR +#endif +#ifdef XSHAL_ROM_PADDR +#define XTBOARD_ROM_PADDR XSHAL_ROM_PADDR +#endif + +/* System RAM: */ +#define XTBOARD_RAM_SIZE XSHAL_RAM_SIZE +#ifdef XSHAL_RAM_VADDR +#define XTBOARD_RAM_VADDR XSHAL_RAM_VADDR +#endif +#ifdef XSHAL_RAM_PADDR +#define XTBOARD_RAM_PADDR XSHAL_RAM_PADDR +#endif +#define XTBOARD_RAM_BYPASS_VADDR XSHAL_RAM_BYPASS_VADDR +#define XTBOARD_RAM_BYPASS_PADDR XSHAL_RAM_BYPASS_PADDR + + + +/* + * Things that depend on device addresses. + */ + + +#define XTBOARD_CACHEATTR_WRITEBACK XSHAL_XT2000_CACHEATTR_WRITEBACK +#define XTBOARD_CACHEATTR_WRITEALLOC XSHAL_XT2000_CACHEATTR_WRITEALLOC +#define XTBOARD_CACHEATTR_WRITETHRU XSHAL_XT2000_CACHEATTR_WRITETHRU +#define XTBOARD_CACHEATTR_BYPASS XSHAL_XT2000_CACHEATTR_BYPASS +#define XTBOARD_CACHEATTR_DEFAULT XSHAL_XT2000_CACHEATTR_DEFAULT + +#define XTBOARD_BUSINT_PIPE_REGIONS XSHAL_XT2000_PIPE_REGIONS +#define XTBOARD_BUSINT_SDRAM_REGIONS XSHAL_XT2000_SDRAM_REGIONS + + +/* + * FPGA registers. + * All these registers are normally accessed using 32-bit loads/stores. + */ + +/* Register offsets: */ +#define XTBOARD_DATECD_OFS 0x00 /* date code (read-only) */ +#define XTBOARD_CLKFRQ_OFS 0x04 /* clock frequency Hz (read-only) */ +#define XTBOARD_SYSLED_OFS 0x08 /* LEDs */ +#define XTBOARD_DIPSW_OFS 0x0C /* DIP switch bits (read-only) */ +#define XTBOARD_SWRST_OFS 0x10 /* software reset */ + +/* Physical register addresses: */ +#ifdef XTBOARD_FPGAREGS_PADDR +#define XTBOARD_DATECD_PADDR (XTBOARD_FPGAREGS_PADDR+XTBOARD_DATECD_OFS) +#define XTBOARD_CLKFRQ_PADDR (XTBOARD_FPGAREGS_PADDR+XTBOARD_CLKFRQ_OFS) +#define XTBOARD_SYSLED_PADDR (XTBOARD_FPGAREGS_PADDR+XTBOARD_SYSLED_OFS) +#define XTBOARD_DIPSW_PADDR (XTBOARD_FPGAREGS_PADDR+XTBOARD_DIPSW_OFS) +#define XTBOARD_SWRST_PADDR (XTBOARD_FPGAREGS_PADDR+XTBOARD_SWRST_OFS) +#endif + +/* Virtual register addresses: */ +#ifdef XTBOARD_FPGAREGS_VADDR +#define XTBOARD_DATECD_VADDR (XTBOARD_FPGAREGS_VADDR+XTBOARD_DATECD_OFS) +#define XTBOARD_CLKFRQ_VADDR (XTBOARD_FPGAREGS_VADDR+XTBOARD_CLKFRQ_OFS) +#define XTBOARD_SYSLED_VADDR (XTBOARD_FPGAREGS_VADDR+XTBOARD_SYSLED_OFS) +#define XTBOARD_DIPSW_VADDR (XTBOARD_FPGAREGS_VADDR+XTBOARD_DIPSW_OFS) +#define XTBOARD_SWRST_VADDR (XTBOARD_FPGAREGS_VADDR+XTBOARD_SWRST_OFS) +/* Register access (for C code): */ +#define XTBOARD_DATECD_REG (*(volatile unsigned*) XTBOARD_DATECD_VADDR) +#define XTBOARD_CLKFRQ_REG (*(volatile unsigned*) XTBOARD_CLKFRQ_VADDR) +#define XTBOARD_SYSLED_REG (*(volatile unsigned*) XTBOARD_SYSLED_VADDR) +#define XTBOARD_DIPSW_REG (*(volatile unsigned*) XTBOARD_DIPSW_VADDR) +#define XTBOARD_SWRST_REG (*(volatile unsigned*) XTBOARD_SWRST_VADDR) +#endif + +/* DATECD (date code; when core was built) bit fields: */ +/* BCD-coded month (01..12): */ +#define XTBOARD_DATECD_MONTH_SHIFT 24 +#define XTBOARD_DATECD_MONTH_BITS 8 +#define XTBOARD_DATECD_MONTH_MASK 0xFF000000 +/* BCD-coded day (01..31): */ +#define XTBOARD_DATECD_DAY_SHIFT 16 +#define XTBOARD_DATECD_DAY_BITS 8 +#define XTBOARD_DATECD_DAY_MASK 0x00FF0000 +/* BCD-coded year (2001..9999): */ +#define XTBOARD_DATECD_YEAR_SHIFT 0 +#define XTBOARD_DATECD_YEAR_BITS 16 +#define XTBOARD_DATECD_YEAR_MASK 0x0000FFFF + +/* SYSLED (system LED) bit fields: */ + +/* LED control bits (off=0, on=1): */ +#define XTBOARD_SYSLED_USER_SHIFT 0 +#define XTBOARD_SYSLED_USER_BITS 2 +#define XTBOARD_SYSLED_USER_MASK 0x00000003 + +/* DIP Switch SW? (left=sw1=lsb=bit0, right=sw4=msb=bit3; off=0, on=1): */ +/* DIP switch bit fields (bit2/sw3 is reserved and presently unused): */ +#if XTBOARD_IS_KC705 +#define XTBOARD_DIPSW_USER_SHIFT 0 +#define XTBOARD_DIPSW_USER_BITS 2 +#define XTBOARD_DIPSW_USER_MASK 0x00000003 +#define XTBOARD_DIPSW_BOOT_SHIFT 3 +#define XTBOARD_DIPSW_BOOT_BITS 1 +#define XTBOARD_DIPSW_BOOT_MASK 0x00000008 +#else /* ML605: */ +#define XTBOARD_DIPSW_USER_SHIFT 0 +#define XTBOARD_DIPSW_USER_BITS 6 +#define XTBOARD_DIPSW_USER_MASK 0x0000003F +#define XTBOARD_DIPSW_BOOT_SHIFT 7 +#define XTBOARD_DIPSW_BOOT_BITS 1 +#define XTBOARD_DIPSW_BOOT_MASK 0x00000080 +#endif /*ML605*/ +#define XTBOARD_DIPSW_BOOT_RAM (0< + diff --git a/components/esp32/include/xtensa/xtruntime-core-state.h b/components/esp32/include/xtensa/xtruntime-core-state.h new file mode 100755 index 0000000000..37d203c215 --- /dev/null +++ b/components/esp32/include/xtensa/xtruntime-core-state.h @@ -0,0 +1,212 @@ +/* xtruntime-core-state.h - core state save area (used eg. by PSO) */ +/* $Id: //depot/rel/Eaglenest/Xtensa/OS/include/xtensa/xtruntime-core-state.h#1 $ */ + +/* + * Copyright (c) 2012-2013 Tensilica Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY + * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +#ifndef _XTOS_CORE_STATE_H_ +#define _XTOS_CORE_STATE_H_ + +/* Import STRUCT_xxx macros for defining structures: */ +#include +#include +#include + +//#define XTOS_PSO_TEST 1 // uncommented for internal PSO testing only + +#define CORE_STATE_SIGNATURE 0xB1C5AFED // pattern that indicates state was saved + + +/* + * Save area for saving entire core state, such as across Power Shut-Off (PSO). + */ + +STRUCT_BEGIN +STRUCT_FIELD (long,4,CS_SA_,signature) // for checking whether state was saved +STRUCT_FIELD (long,4,CS_SA_,restore_label) +STRUCT_FIELD (long,4,CS_SA_,aftersave_label) +STRUCT_AFIELD(long,4,CS_SA_,areg,XCHAL_NUM_AREGS) +#if XCHAL_HAVE_WINDOWED +STRUCT_AFIELD(long,4,CS_SA_,caller_regs,16) // save a max of 16 caller regs +STRUCT_FIELD (long,4,CS_SA_,caller_regs_saved) // flag to show if caller regs saved +#endif +#if XCHAL_HAVE_PSO_CDM +STRUCT_FIELD (long,4,CS_SA_,pwrctl) +#endif +#if XCHAL_HAVE_WINDOWED +STRUCT_FIELD (long,4,CS_SA_,windowbase) +STRUCT_FIELD (long,4,CS_SA_,windowstart) +#endif +STRUCT_FIELD (long,4,CS_SA_,sar) +#if XCHAL_HAVE_EXCEPTIONS +STRUCT_FIELD (long,4,CS_SA_,epc1) +STRUCT_FIELD (long,4,CS_SA_,ps) +STRUCT_FIELD (long,4,CS_SA_,excsave1) +# ifdef XCHAL_DOUBLEEXC_VECTOR_VADDR +STRUCT_FIELD (long,4,CS_SA_,depc) +# endif +#endif +#if XCHAL_NUM_INTLEVELS + XCHAL_HAVE_NMI >= 2 +STRUCT_AFIELD(long,4,CS_SA_,epc, XCHAL_NUM_INTLEVELS + XCHAL_HAVE_NMI - 1) +STRUCT_AFIELD(long,4,CS_SA_,eps, XCHAL_NUM_INTLEVELS + XCHAL_HAVE_NMI - 1) +STRUCT_AFIELD(long,4,CS_SA_,excsave,XCHAL_NUM_INTLEVELS + XCHAL_HAVE_NMI - 1) +#endif +#if XCHAL_HAVE_LOOPS +STRUCT_FIELD (long,4,CS_SA_,lcount) +STRUCT_FIELD (long,4,CS_SA_,lbeg) +STRUCT_FIELD (long,4,CS_SA_,lend) +#endif +#if XCHAL_HAVE_ABSOLUTE_LITERALS +STRUCT_FIELD (long,4,CS_SA_,litbase) +#endif +#if XCHAL_HAVE_VECBASE +STRUCT_FIELD (long,4,CS_SA_,vecbase) +#endif +#if XCHAL_HAVE_S32C1I && (XCHAL_HW_MIN_VERSION >= XTENSA_HWVERSION_RC_2009_0) /* have ATOMCTL ? */ +STRUCT_FIELD (long,4,CS_SA_,atomctl) +#endif +#if XCHAL_HAVE_PREFETCH +STRUCT_FIELD (long,4,CS_SA_,prefctl) +#endif +#if XCHAL_USE_MEMCTL +STRUCT_FIELD (long,4,CS_SA_,memctl) +#endif +#if XCHAL_HAVE_CCOUNT +STRUCT_FIELD (long,4,CS_SA_,ccount) +STRUCT_AFIELD(long,4,CS_SA_,ccompare, XCHAL_NUM_TIMERS) +#endif +#if XCHAL_HAVE_INTERRUPTS +STRUCT_FIELD (long,4,CS_SA_,intenable) +STRUCT_FIELD (long,4,CS_SA_,interrupt) +#endif +#if XCHAL_HAVE_DEBUG +STRUCT_FIELD (long,4,CS_SA_,icount) +STRUCT_FIELD (long,4,CS_SA_,icountlevel) +STRUCT_FIELD (long,4,CS_SA_,debugcause) +// DDR not saved +# if XCHAL_NUM_DBREAK +STRUCT_AFIELD(long,4,CS_SA_,dbreakc, XCHAL_NUM_DBREAK) +STRUCT_AFIELD(long,4,CS_SA_,dbreaka, XCHAL_NUM_DBREAK) +# endif +# if XCHAL_NUM_IBREAK +STRUCT_AFIELD(long,4,CS_SA_,ibreaka, XCHAL_NUM_IBREAK) +STRUCT_FIELD (long,4,CS_SA_,ibreakenable) +# endif +#endif +#if XCHAL_NUM_MISC_REGS +STRUCT_AFIELD(long,4,CS_SA_,misc,XCHAL_NUM_MISC_REGS) +#endif +#if XCHAL_HAVE_MEM_ECC_PARITY +STRUCT_FIELD (long,4,CS_SA_,mepc) +STRUCT_FIELD (long,4,CS_SA_,meps) +STRUCT_FIELD (long,4,CS_SA_,mesave) +STRUCT_FIELD (long,4,CS_SA_,mesr) +STRUCT_FIELD (long,4,CS_SA_,mecr) +STRUCT_FIELD (long,4,CS_SA_,mevaddr) +#endif + +/* We put this ahead of TLB and other TIE state, + to keep it within S32I/L32I offset range. */ +#if XCHAL_HAVE_CP +STRUCT_FIELD (long,4,CS_SA_,cpenable) +#endif + +/* TLB state */ +#if XCHAL_HAVE_MIMIC_CACHEATTR || XCHAL_HAVE_XLT_CACHEATTR +STRUCT_AFIELD(long,4,CS_SA_,tlbs,8*2) +#endif +#if XCHAL_HAVE_PTP_MMU +/* Compute number of auto-refill (ARF) entries as max of I and D, + to simplify TLB save logic. On the unusual configs with + ITLB ARF != DTLB ARF entries, we'll just end up + saving/restoring some extra entries redundantly. */ +# if XCHAL_DTLB_ARF_ENTRIES_LOG2 + XCHAL_ITLB_ARF_ENTRIES_LOG2 > 4 +# define ARF_ENTRIES 8 +# else +# define ARF_ENTRIES 4 +# endif +STRUCT_FIELD (long,4,CS_SA_,ptevaddr) +STRUCT_FIELD (long,4,CS_SA_,rasid) +STRUCT_FIELD (long,4,CS_SA_,dtlbcfg) +STRUCT_FIELD (long,4,CS_SA_,itlbcfg) +/*** WARNING: past this point, field offsets may be larger than S32I/L32I range ***/ +STRUCT_AFIELD(long,4,CS_SA_,tlbs,((4*ARF_ENTRIES+4)*2+3)*2) +# if XCHAL_HAVE_SPANNING_WAY /* MMU v3 */ +STRUCT_AFIELD(long,4,CS_SA_,tlbs_ways56,(4+8)*2*2) +# endif +#endif + +/* TIE state */ +/* NOTE: NCP area is aligned to XCHAL_TOTAL_SA_ALIGN not XCHAL_NCP_SA_ALIGN, + because the offsets of all subsequent coprocessor save areas are relative + to the NCP save area. */ +STRUCT_AFIELD_A(char,1,XCHAL_TOTAL_SA_ALIGN,CS_SA_,ncp,XCHAL_NCP_SA_SIZE) +#if XCHAL_HAVE_CP +STRUCT_AFIELD_A(char,1,XCHAL_CP0_SA_ALIGN,CS_SA_,cp0,XCHAL_CP0_SA_SIZE) +STRUCT_AFIELD_A(char,1,XCHAL_CP1_SA_ALIGN,CS_SA_,cp1,XCHAL_CP1_SA_SIZE) +STRUCT_AFIELD_A(char,1,XCHAL_CP2_SA_ALIGN,CS_SA_,cp2,XCHAL_CP2_SA_SIZE) +STRUCT_AFIELD_A(char,1,XCHAL_CP3_SA_ALIGN,CS_SA_,cp3,XCHAL_CP3_SA_SIZE) +STRUCT_AFIELD_A(char,1,XCHAL_CP4_SA_ALIGN,CS_SA_,cp4,XCHAL_CP4_SA_SIZE) +STRUCT_AFIELD_A(char,1,XCHAL_CP5_SA_ALIGN,CS_SA_,cp5,XCHAL_CP5_SA_SIZE) +STRUCT_AFIELD_A(char,1,XCHAL_CP6_SA_ALIGN,CS_SA_,cp6,XCHAL_CP6_SA_SIZE) +STRUCT_AFIELD_A(char,1,XCHAL_CP7_SA_ALIGN,CS_SA_,cp7,XCHAL_CP7_SA_SIZE) +//STRUCT_AFIELD_A(char,1,XCHAL_CP8_SA_ALIGN,CS_SA_,cp8,XCHAL_CP8_SA_SIZE) +//STRUCT_AFIELD_A(char,1,XCHAL_CP9_SA_ALIGN,CS_SA_,cp9,XCHAL_CP9_SA_SIZE) +//STRUCT_AFIELD_A(char,1,XCHAL_CP10_SA_ALIGN,CS_SA_,cp10,XCHAL_CP10_SA_SIZE) +//STRUCT_AFIELD_A(char,1,XCHAL_CP11_SA_ALIGN,CS_SA_,cp11,XCHAL_CP11_SA_SIZE) +//STRUCT_AFIELD_A(char,1,XCHAL_CP12_SA_ALIGN,CS_SA_,cp12,XCHAL_CP12_SA_SIZE) +//STRUCT_AFIELD_A(char,1,XCHAL_CP13_SA_ALIGN,CS_SA_,cp13,XCHAL_CP13_SA_SIZE) +//STRUCT_AFIELD_A(char,1,XCHAL_CP14_SA_ALIGN,CS_SA_,cp14,XCHAL_CP14_SA_SIZE) +//STRUCT_AFIELD_A(char,1,XCHAL_CP15_SA_ALIGN,CS_SA_,cp15,XCHAL_CP15_SA_SIZE) +#endif + +STRUCT_END(XtosCoreState) + + + +// These are part of non-coprocessor state (ncp): +#if XCHAL_HAVE_MAC16 +//STRUCT_FIELD (long,4,CS_SA_,acclo) +//STRUCT_FIELD (long,4,CS_SA_,acchi) +//STRUCT_AFIELD(long,4,CS_SA_,mr, 4) +#endif +#if XCHAL_HAVE_THREADPTR +//STRUCT_FIELD (long,4,CS_SA_,threadptr) +#endif +#if XCHAL_HAVE_S32C1I +//STRUCT_FIELD (long,4,CS_SA_,scompare1) +#endif +#if XCHAL_HAVE_BOOLEANS +//STRUCT_FIELD (long,4,CS_SA_,br) +#endif + +// Not saved: +// EXCCAUSE ?? +// DEBUGCAUSE ?? +// EXCVADDR ?? +// DDR +// INTERRUPT +// ... locked cache lines ... + +#endif /* _XTOS_CORE_STATE_H_ */ + diff --git a/components/esp32/include/xtensa/xtruntime-frames.h b/components/esp32/include/xtensa/xtruntime-frames.h new file mode 100755 index 0000000000..8b5a7463ab --- /dev/null +++ b/components/esp32/include/xtensa/xtruntime-frames.h @@ -0,0 +1,162 @@ +/* xtruntime-frames.h - exception stack frames for single-threaded run-time */ +/* $Id: //depot/rel/Eaglenest/Xtensa/OS/include/xtensa/xtruntime-frames.h#1 $ */ + +/* + * Copyright (c) 2002-2012 Tensilica Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY + * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +#ifndef _XTRUNTIME_FRAMES_H_ +#define _XTRUNTIME_FRAMES_H_ + +#include + +/* Macros that help define structures for both C and assembler: */ +#if defined(_ASMLANGUAGE) || defined(__ASSEMBLER__) +#define STRUCT_BEGIN .pushsection .text; .struct 0 +#define STRUCT_FIELD(ctype,size,pre,name) pre##name: .space size +#define STRUCT_AFIELD(ctype,size,pre,name,n) pre##name: .if n ; .space (size)*(n) ; .endif +#define STRUCT_AFIELD_A(ctype,size,align,pre,name,n) .balign align ; pre##name: .if n ; .space (size)*(n) ; .endif +#define STRUCT_END(sname) sname##Size:; .popsection +#else /*_ASMLANGUAGE||__ASSEMBLER__*/ +#define STRUCT_BEGIN typedef struct { +#define STRUCT_FIELD(ctype,size,pre,name) ctype name; +#define STRUCT_AFIELD(ctype,size,pre,name,n) ctype name[n]; +#define STRUCT_AFIELD_A(ctype,size,align,pre,name,n) ctype name[n] __attribute__((aligned(align))); +#define STRUCT_END(sname) } sname; +#endif /*_ASMLANGUAGE||__ASSEMBLER__*/ + + +/* + * Kernel vector mode exception stack frame. + * + * NOTE: due to the limited range of addi used in the current + * kernel exception vector, and the fact that historically + * the vector is limited to 12 bytes, the size of this + * stack frame is limited to 128 bytes (currently at 64). + */ +STRUCT_BEGIN +STRUCT_FIELD (long,4,KEXC_,pc) /* "parm" */ +STRUCT_FIELD (long,4,KEXC_,ps) +STRUCT_AFIELD(long,4,KEXC_,areg, 4) /* a12 .. a15 */ +STRUCT_FIELD (long,4,KEXC_,sar) /* "save" */ +#if XCHAL_HAVE_LOOPS +STRUCT_FIELD (long,4,KEXC_,lcount) +STRUCT_FIELD (long,4,KEXC_,lbeg) +STRUCT_FIELD (long,4,KEXC_,lend) +#endif +#if XCHAL_HAVE_MAC16 +STRUCT_FIELD (long,4,KEXC_,acclo) +STRUCT_FIELD (long,4,KEXC_,acchi) +STRUCT_AFIELD(long,4,KEXC_,mr, 4) +#endif +STRUCT_END(KernelFrame) + + +/* + * User vector mode exception stack frame: + * + * WARNING: if you modify this structure, you MUST modify the + * computation of the pad size (ALIGNPAD) accordingly. + */ +STRUCT_BEGIN +STRUCT_FIELD (long,4,UEXC_,pc) +STRUCT_FIELD (long,4,UEXC_,ps) +STRUCT_FIELD (long,4,UEXC_,sar) +STRUCT_FIELD (long,4,UEXC_,vpri) +#ifdef __XTENSA_CALL0_ABI__ +STRUCT_FIELD (long,4,UEXC_,a0) +#endif +STRUCT_FIELD (long,4,UEXC_,a2) +STRUCT_FIELD (long,4,UEXC_,a3) +STRUCT_FIELD (long,4,UEXC_,a4) +STRUCT_FIELD (long,4,UEXC_,a5) +#ifdef __XTENSA_CALL0_ABI__ +STRUCT_FIELD (long,4,UEXC_,a6) +STRUCT_FIELD (long,4,UEXC_,a7) +STRUCT_FIELD (long,4,UEXC_,a8) +STRUCT_FIELD (long,4,UEXC_,a9) +STRUCT_FIELD (long,4,UEXC_,a10) +STRUCT_FIELD (long,4,UEXC_,a11) +STRUCT_FIELD (long,4,UEXC_,a12) +STRUCT_FIELD (long,4,UEXC_,a13) +STRUCT_FIELD (long,4,UEXC_,a14) +STRUCT_FIELD (long,4,UEXC_,a15) +#endif +STRUCT_FIELD (long,4,UEXC_,exccause) /* NOTE: can probably rid of this one (pass direct) */ +#if XCHAL_HAVE_LOOPS +STRUCT_FIELD (long,4,UEXC_,lcount) +STRUCT_FIELD (long,4,UEXC_,lbeg) +STRUCT_FIELD (long,4,UEXC_,lend) +#endif +#if XCHAL_HAVE_MAC16 +STRUCT_FIELD (long,4,UEXC_,acclo) +STRUCT_FIELD (long,4,UEXC_,acchi) +STRUCT_AFIELD(long,4,UEXC_,mr, 4) +#endif +/* ALIGNPAD is the 16-byte alignment padding. */ +#ifdef __XTENSA_CALL0_ABI__ +# define CALL0_ABI 1 +#else +# define CALL0_ABI 0 +#endif +#define ALIGNPAD ((3 + XCHAL_HAVE_LOOPS*1 + XCHAL_HAVE_MAC16*2 + CALL0_ABI*1) & 3) +#if ALIGNPAD +STRUCT_AFIELD(long,4,UEXC_,pad, ALIGNPAD) /* 16-byte alignment padding */ +#endif +/*STRUCT_AFIELD_A(char,1,XCHAL_CPEXTRA_SA_ALIGN,UEXC_,ureg, (XCHAL_CPEXTRA_SA_SIZE+3)&-4)*/ /* not used */ +STRUCT_END(UserFrame) + + +#if defined(_ASMLANGUAGE) || defined(__ASSEMBLER__) + + +/* Check for UserFrameSize small enough not to require rounding...: */ + /* Skip 16-byte save area, then 32-byte space for 8 regs of call12 + * (which overlaps with 16-byte GCC nested func chaining area), + * then exception stack frame: */ + .set UserFrameTotalSize, 16+32+UserFrameSize + /* Greater than 112 bytes? (max range of ADDI, both signs, when aligned to 16 bytes): */ + .ifgt UserFrameTotalSize-112 + /* Round up to 256-byte multiple to accelerate immediate adds: */ + .set UserFrameTotalSize, ((UserFrameTotalSize+255) & 0xFFFFFF00) + .endif +# define ESF_TOTALSIZE UserFrameTotalSize + +#endif /* _ASMLANGUAGE || __ASSEMBLER__ */ + + +#if XCHAL_NUM_CONTEXTS > 1 +/* Structure of info stored on new context's stack for setup: */ +STRUCT_BEGIN +STRUCT_FIELD (long,4,INFO_,sp) +STRUCT_FIELD (long,4,INFO_,arg1) +STRUCT_FIELD (long,4,INFO_,funcpc) +STRUCT_FIELD (long,4,INFO_,prevps) +STRUCT_END(SetupInfo) +#endif + + +#define KERNELSTACKSIZE 1024 + + +#endif /* _XTRUNTIME_FRAMES_H_ */ + diff --git a/components/esp32/include/xtensa/xtruntime.h b/components/esp32/include/xtensa/xtruntime.h new file mode 100755 index 0000000000..9dae1f4b23 --- /dev/null +++ b/components/esp32/include/xtensa/xtruntime.h @@ -0,0 +1,221 @@ +/* + * xtruntime.h -- general C definitions for single-threaded run-time + * + * Copyright (c) 2002-2013 Tensilica Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY + * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +#ifndef XTRUNTIME_H +#define XTRUNTIME_H + +#include +#include +#include + +#ifndef XTSTR +#define _XTSTR(x) # x +#define XTSTR(x) _XTSTR(x) +#endif + +/* _xtos_core_shutoff() flags parameter values: */ +#define XTOS_KEEPON_MEM 0x00000100 /* ==PWRCTL_MEM_WAKEUP */ +#define XTOS_KEEPON_MEM_SHIFT 8 +#define XTOS_KEEPON_DEBUG 0x00001000 /* ==PWRCTL_DEBUG_WAKEUP */ +#define XTOS_KEEPON_DEBUG_SHIFT 12 + +#define XTOS_COREF_PSO 0x00000001 /* do power shutoff */ +#define XTOS_COREF_PSO_SHIFT 0 + +#define _xtos_set_execption_handler _xtos_set_exception_handler /* backward compatibility */ +#define _xtos_set_saved_intenable _xtos_ints_on /* backward compatibility */ +#define _xtos_clear_saved_intenable _xtos_ints_off /* backward compatibility */ + +#if !defined(_ASMLANGUAGE) && !defined(__ASSEMBLER__) + +#ifdef __cplusplus +extern "C" { +#endif + +/*typedef void (_xtos_timerdelta_func)(int);*/ +#ifdef __cplusplus +typedef void (_xtos_handler_func)(...); +#else +typedef void (_xtos_handler_func)(); +#endif +typedef _xtos_handler_func *_xtos_handler; + +/* + * unsigned XTOS_SET_INTLEVEL(int intlevel); + * This macro sets the current interrupt level. + * The 'intlevel' parameter must be a constant. + * This macro returns a 32-bit value that must be passed to + * XTOS_RESTORE_INTLEVEL() to restore the previous interrupt level. + * XTOS_RESTORE_JUST_INTLEVEL() also does this, but in XEA2 configs + * it restores only PS.INTLEVEL rather than the entire PS register + * and thus is slower. + */ +#if !XCHAL_HAVE_INTERRUPTS +# define XTOS_SET_INTLEVEL(intlevel) 0 +# define XTOS_SET_MIN_INTLEVEL(intlevel) 0 +# define XTOS_RESTORE_INTLEVEL(restoreval) +# define XTOS_RESTORE_JUST_INTLEVEL(restoreval) +#elif XCHAL_HAVE_XEA2 +/* In XEA2, we can simply safely set PS.INTLEVEL directly: */ +/* NOTE: these asm macros don't modify memory, but they are marked + * as such to act as memory access barriers to the compiler because + * these macros are sometimes used to delineate critical sections; + * function calls are natural barriers (the compiler does not know + * whether a function modifies memory) unless declared to be inlined. */ +# define XTOS_SET_INTLEVEL(intlevel) ({ unsigned __tmp; \ + __asm__ __volatile__( "rsil %0, " XTSTR(intlevel) "\n" \ + : "=a" (__tmp) : : "memory" ); \ + __tmp;}) +# define XTOS_SET_MIN_INTLEVEL(intlevel) ({ unsigned __tmp, __tmp2, __tmp3; \ + __asm__ __volatile__( "rsr %0, " XTSTR(PS) "\n" /* get old (current) PS.INTLEVEL */ \ + "movi %2, " XTSTR(intlevel) "\n" \ + "extui %1, %0, 0, 4\n" /* keep only INTLEVEL bits of parameter */ \ + "blt %2, %1, 1f\n" \ + "rsil %0, " XTSTR(intlevel) "\n" \ + "1:\n" \ + : "=a" (__tmp), "=&a" (__tmp2), "=&a" (__tmp3) : : "memory" ); \ + __tmp;}) +# define XTOS_RESTORE_INTLEVEL(restoreval) do{ unsigned __tmp = (restoreval); \ + __asm__ __volatile__( "wsr %0, " XTSTR(PS) " ; rsync\n" \ + : : "a" (__tmp) : "memory" ); \ + }while(0) +# define XTOS_RESTORE_JUST_INTLEVEL(restoreval) _xtos_set_intlevel(restoreval) +#else +/* In XEA1, we have to rely on INTENABLE register virtualization: */ +extern unsigned _xtos_set_vpri( unsigned vpri ); +extern unsigned _xtos_vpri_enabled; /* current virtual priority */ +# define XTOS_SET_INTLEVEL(intlevel) _xtos_set_vpri(~XCHAL_INTLEVEL_ANDBELOW_MASK(intlevel)) +# define XTOS_SET_MIN_INTLEVEL(intlevel) _xtos_set_vpri(_xtos_vpri_enabled & ~XCHAL_INTLEVEL_ANDBELOW_MASK(intlevel)) +# define XTOS_RESTORE_INTLEVEL(restoreval) _xtos_set_vpri(restoreval) +# define XTOS_RESTORE_JUST_INTLEVEL(restoreval) _xtos_set_vpri(restoreval) +#endif + +/* + * The following macros build upon the above. They are generally used + * instead of invoking the SET_INTLEVEL and SET_MIN_INTLEVEL macros directly. + * They all return a value that can be used with XTOS_RESTORE_INTLEVEL() + * or _xtos_restore_intlevel() or _xtos_restore_just_intlevel() to restore + * the effective interrupt level to what it was before the macro was invoked. + * In XEA2, the DISABLE macros are much faster than the MASK macros + * (in all configs, DISABLE sets the effective interrupt level, whereas MASK + * makes ensures the effective interrupt level is at least the level given + * without lowering it; in XEA2 with INTENABLE virtualization, these macros + * affect PS.INTLEVEL only, not the virtual priority, so DISABLE has partial + * MASK semantics). + * + * A typical critical section sequence might be: + * unsigned rval = XTOS_DISABLE_EXCM_INTERRUPTS; + * ... critical section ... + * XTOS_RESTORE_INTLEVEL(rval); + */ +/* Enable all interrupts (those activated with _xtos_ints_on()): */ +#define XTOS_ENABLE_INTERRUPTS XTOS_SET_INTLEVEL(0) +/* Disable low priority level interrupts (they can interact with the OS): */ +#define XTOS_DISABLE_LOWPRI_INTERRUPTS XTOS_SET_INTLEVEL(XCHAL_NUM_LOWPRI_LEVELS) +#define XTOS_MASK_LOWPRI_INTERRUPTS XTOS_SET_MIN_INTLEVEL(XCHAL_NUM_LOWPRI_LEVELS) +/* Disable interrupts that can interact with the OS: */ +#define XTOS_DISABLE_EXCM_INTERRUPTS XTOS_SET_INTLEVEL(XCHAL_EXCM_LEVEL) +#define XTOS_MASK_EXCM_INTERRUPTS XTOS_SET_MIN_INTLEVEL(XCHAL_EXCM_LEVEL) +#if 0 /* XTOS_LOCK_LEVEL is not exported to applications */ +/* Disable interrupts that can interact with the OS, or manipulate virtual INTENABLE: */ +#define XTOS_DISABLE_LOCK_INTERRUPTS XTOS_SET_INTLEVEL(XTOS_LOCK_LEVEL) +#define XTOS_MASK_LOCK_INTERRUPTS XTOS_SET_MIN_INTLEVEL(XTOS_LOCK_LEVEL) +#endif +/* Disable ALL interrupts (not for common use, particularly if one's processor + * configuration has high-level interrupts and one cares about their latency): */ +#define XTOS_DISABLE_ALL_INTERRUPTS XTOS_SET_INTLEVEL(15) + + +extern unsigned int _xtos_ints_off( unsigned int mask ); +extern unsigned int _xtos_ints_on( unsigned int mask ); +extern unsigned _xtos_set_intlevel( int intlevel ); +extern unsigned _xtos_set_min_intlevel( int intlevel ); +extern unsigned _xtos_restore_intlevel( unsigned restoreval ); +extern unsigned _xtos_restore_just_intlevel( unsigned restoreval ); +extern _xtos_handler _xtos_set_interrupt_handler( int n, _xtos_handler f ); +extern _xtos_handler _xtos_set_interrupt_handler_arg( int n, _xtos_handler f, void *arg ); +extern _xtos_handler _xtos_set_exception_handler( int n, _xtos_handler f ); + +extern void _xtos_memep_initrams( void ); +extern void _xtos_memep_enable( int flags ); + +/* For use with the tiny LSP (see LSP reference manual). */ +#if XCHAL_NUM_INTLEVELS >= 1 +extern void _xtos_dispatch_level1_interrupts( void ); +#endif +#if XCHAL_NUM_INTLEVELS >= 2 +extern void _xtos_dispatch_level2_interrupts( void ); +#endif +#if XCHAL_NUM_INTLEVELS >= 3 +extern void _xtos_dispatch_level3_interrupts( void ); +#endif +#if XCHAL_NUM_INTLEVELS >= 4 +extern void _xtos_dispatch_level4_interrupts( void ); +#endif +#if XCHAL_NUM_INTLEVELS >= 5 +extern void _xtos_dispatch_level5_interrupts( void ); +#endif +#if XCHAL_NUM_INTLEVELS >= 6 +extern void _xtos_dispatch_level6_interrupts( void ); +#endif + +/* Deprecated (but kept because they were documented): */ +extern unsigned int _xtos_read_ints( void ); /* use xthal_get_interrupt() instead */ +extern void _xtos_clear_ints( unsigned int mask ); /* use xthal_set_intclear() instead */ + + +/* Power shut-off related routines. */ +extern int _xtos_core_shutoff(unsigned flags); +extern int _xtos_core_save(unsigned flags, XtosCoreState *savearea, void *code); +extern void _xtos_core_restore(unsigned retvalue, XtosCoreState *savearea); + + +#if XCHAL_NUM_CONTEXTS > 1 +extern unsigned _xtos_init_context(int context_num, int stack_size, + _xtos_handler_func *start_func, int arg1); +#endif + +/* Deprecated: */ +#if XCHAL_NUM_TIMERS > 0 +extern void _xtos_timer_0_delta( int cycles ); +#endif +#if XCHAL_NUM_TIMERS > 1 +extern void _xtos_timer_1_delta( int cycles ); +#endif +#if XCHAL_NUM_TIMERS > 2 +extern void _xtos_timer_2_delta( int cycles ); +#endif +#if XCHAL_NUM_TIMERS > 3 +extern void _xtos_timer_3_delta( int cycles ); +#endif + +#ifdef __cplusplus +} +#endif + +#endif /* !_ASMLANGUAGE && !__ASSEMBLER__ */ + +#endif /* XTRUNTIME_H */ + diff --git a/components/esp32/include/xtensa/xtutil.h b/components/esp32/include/xtensa/xtutil.h new file mode 100755 index 0000000000..fb05c37057 --- /dev/null +++ b/components/esp32/include/xtensa/xtutil.h @@ -0,0 +1,61 @@ + +/* $Id$ */ +/*******************************************************************************/ +/* Copyright (c) 2001-2013 by Tensilica Inc. ALL RIGHTS RESERVED. */ +/* These coded instructions, statements, and computer programs are the */ +/* copyrighted works and confidential proprietary information of Tensilica Inc.*/ +/* They may not be modified, copied, reproduced, distributed, or disclosed to */ +/* third parties in any manner, medium, or form, in whole or in part, without */ +/* the prior written consent of Tensilica Inc. */ +/*******************************************************************************/ + +#ifndef XTUTIL_H +#define XTUTIL_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include + +extern int xt_putchar(int c); +extern int xt_puts(const char * s); +extern void xt_putn(unsigned n); +extern int xt_atoi(const char * s); +extern int xt_printf(const char *fmt, ...); +extern int xt_sprintf(char * buf, const char * fmt, ...); + +typedef int xt_output_fn(int *, int, const void *, int); +extern xt_output_fn * xt_set_output_fn(xt_output_fn * fn); + +#ifdef XTUTIL_LIB + +// Only defined if building library + +typedef void (xt_outbuf_fn)(void *, char *, int); + +extern int xt_vprintf(xt_outbuf_fn * out, void * outarg, const char * fmt, va_list ap); + +#else + +// Only defined if building application and overriding + +#ifndef XTUTIL_NO_OVERRIDE + +#define putchar xt_putchar +#define puts xt_puts +#define putn xt_putn +#define atoi xt_atoi +#define printf xt_printf +#define sprintf xt_sprintf + +#endif // XTUTIL_NO_OVERRIDE + +#endif // XTUTIL_LIB + +#ifdef __cplusplus +} +#endif + +#endif // XTUTIL_H + diff --git a/components/esp32/ld/eagle.fpga32.rom.addr.v7.ld b/components/esp32/ld/eagle.fpga32.rom.addr.v7.ld new file mode 100644 index 0000000000..3777405fe4 --- /dev/null +++ b/components/esp32/ld/eagle.fpga32.rom.addr.v7.ld @@ -0,0 +1,1829 @@ +/* +ESP32 ROM address table +Generated for ROM with MD5sum: +ab8282ae908fe9e7a63fb2a4ac2df013 ../../rom_image/prorom.elf +*/ +PROVIDE ( abort = 0x4000bba4 ); +PROVIDE ( abs = 0x40056340 ); +PROVIDE ( __absvdi2 = 0x4006387c ); +PROVIDE ( __absvsi2 = 0x40063868 ); +PROVIDE ( Add2SelfBigHex256 = 0x40015b7c ); +PROVIDE ( AddBigHex256 = 0x40015b28 ); +PROVIDE ( AddBigHexModP256 = 0x40015c98 ); +PROVIDE ( __adddf3 = 0x40002590 ); +PROVIDE ( AddP256 = 0x40015c74 ); +PROVIDE ( AddPdiv2_256 = 0x40015ce0 ); +PROVIDE ( __addsf3 = 0x400020e8 ); +PROVIDE ( __addvdi3 = 0x40002cbc ); +PROVIDE ( __addvsi3 = 0x40002c98 ); +PROVIDE ( aes_128_cbc_decrypt = 0x4005cc7c ); +PROVIDE ( aes_128_cbc_encrypt = 0x4005cc18 ); +PROVIDE ( aes_unwrap = 0x4005ccf0 ); +PROVIDE ( app_gpio_arg = 0x3ffe003c ); +PROVIDE ( app_gpio_handler = 0x3ffe0040 ); +PROVIDE ( __ascii_wctomb = 0x40058ef0 ); +PROVIDE ( asctime = 0x40059588 ); +PROVIDE ( asctime_r = 0x40000ec8 ); +PROVIDE ( __ashldi3 = 0x4000c818 ); +PROVIDE ( __ashrdi3 = 0x4000c830 ); +PROVIDE ( asiprintf = 0x40056d9c ); +PROVIDE ( _asiprintf_r = 0x40056d4c ); +PROVIDE ( asniprintf = 0x40056cd8 ); +PROVIDE ( _asniprintf_r = 0x40056c64 ); +PROVIDE ( asnprintf = 0x40056cd8 ); +PROVIDE ( _asnprintf_r = 0x40056c64 ); +PROVIDE ( asprintf = 0x40056d9c ); +PROVIDE ( _asprintf_r = 0x40056d4c ); +PROVIDE ( atoi = 0x400566c4 ); +PROVIDE ( _atoi_r = 0x400566d4 ); +PROVIDE ( atol = 0x400566ec ); +PROVIDE ( _atol_r = 0x400566fc ); +PROVIDE ( base64_decode = 0x4005ced8 ); +PROVIDE ( base64_encode = 0x4005cdbc ); +PROVIDE ( BasePoint_x_256 = 0x3ff97488 ); +PROVIDE ( BasePoint_y_256 = 0x3ff97468 ); +PROVIDE ( bigHexInversion256 = 0x400168f0 ); +PROVIDE ( bigHexP256 = 0x3ff973bc ); +PROVIDE ( __bswapdi2 = 0x400649c4 ); +PROVIDE ( __bswapsi2 = 0x4006499c ); +PROVIDE ( btdm_r_ble_bt_handler_tab_p_get = 0x40019b0c ); +PROVIDE ( btdm_r_btdm_option_data_p_get = 0x40010004 ); +PROVIDE ( btdm_r_btdm_rom_version_get = 0x40010078 ); +PROVIDE ( btdm_r_data_init = 0x4001002c ); +PROVIDE ( btdm_r_import_rf_phy_func_p_get = 0x40054298 ); +PROVIDE ( btdm_r_ip_func_p_get = 0x40019af0 ); +PROVIDE ( btdm_r_ip_func_p_set = 0x40019afc ); +PROVIDE ( btdm_r_modules_func_p_get = 0x4005427c ); +PROVIDE ( btdm_r_modules_func_p_set = 0x40054270 ); +PROVIDE ( btdm_r_plf_func_p_set = 0x40054288 ); +PROVIDE ( bt_util_buf_env = 0x3ffb8bd4 ); +PROVIDE ( bzero = 0x4000c1f4 ); +PROVIDE ( cache_flash_mmu_set = 0x400095e0 ); +PROVIDE ( Cache_Flush = 0x40009a14 ); +PROVIDE ( Cache_Read_Disable = 0x40009ab8 ); +PROVIDE ( Cache_Read_Enable = 0x40009a84 ); +PROVIDE ( Cache_Read_Init = 0x40009950 ); +PROVIDE ( cache_sram_mmu_set = 0x400097f4 ); +PROVIDE ( calloc = 0x4000bee4 ); +PROVIDE ( _calloc_r = 0x4000bbf8 ); +PROVIDE ( check_pos = 0x400068b8 ); +PROVIDE ( _cleanup = 0x40001df8 ); +PROVIDE ( _cleanup_r = 0x40001d48 ); +PROVIDE ( __clear_cache = 0x40063860 ); +PROVIDE ( close = 0x40001778 ); +PROVIDE ( _close_r = 0x4000bd3c ); +PROVIDE ( __clrsbdi2 = 0x40064a38 ); +PROVIDE ( __clrsbsi2 = 0x40064a20 ); +PROVIDE ( __clzdi2 = 0x4000ca50 ); +PROVIDE ( __clzsi2 = 0x4000c7e8 ); +PROVIDE ( __cmpdi2 = 0x40063820 ); +PROVIDE ( co_default_bdaddr = 0x3ffae704 ); +PROVIDE ( co_null_bdaddr = 0x3ffb80e0 ); +PROVIDE ( co_sca2ppm = 0x3ff971e8 ); +PROVIDE ( crc16_be = 0x4005d09c ); +PROVIDE ( crc16_le = 0x4005d05c ); +PROVIDE ( crc32_be = 0x4005d024 ); +PROVIDE ( crc32_le = 0x4005cfec ); +PROVIDE ( crc8_be = 0x4005d114 ); +PROVIDE ( crc8_le = 0x4005d0e0 ); +PROVIDE ( creat = 0x40000e8c ); +PROVIDE ( ctime = 0x400595b0 ); +PROVIDE ( ctime_r = 0x400595c4 ); +PROVIDE ( _ctype_ = 0x3ff96354 ); +PROVIDE ( __ctype_ptr__ = 0x3ff96350 ); +PROVIDE ( __ctzdi2 = 0x4000ca64 ); +PROVIDE ( __ctzsi2 = 0x4000c7f0 ); +PROVIDE ( _data_end = 0x4000d5c8 ); +PROVIDE ( _data_end_btdm_rom = 0x4000d4f8 ); +PROVIDE ( _data_start = 0x4000d4f8 ); +PROVIDE ( _data_start_btdm_rom = 0x4000d4f4 ); +PROVIDE ( _daylight = 0x3ffae0a4 ); +PROVIDE ( dbg_default_handler = 0x3ff97218 ); +PROVIDE ( dbg_state = 0x3ffb8d5d ); +PROVIDE ( DebugE256PublicKey_x = 0x3ff97428 ); +PROVIDE ( DebugE256PublicKey_y = 0x3ff97408 ); +PROVIDE ( DebugE256SecretKey = 0x3ff973e8 ); +PROVIDE ( _DebugExceptionVector = 0x40000280 ); +PROVIDE ( debug_timer = 0x3ffe042c ); +PROVIDE ( debug_timerfn = 0x3ffe0430 ); +PROVIDE ( dh_group14_generator = 0x3ff9ac60 ); +PROVIDE ( dh_group14_prime = 0x3ff9ab60 ); +PROVIDE ( dh_group15_generator = 0x3ff9ab5f ); +PROVIDE ( dh_group15_prime = 0x3ff9a9df ); +PROVIDE ( dh_group16_generator = 0x3ff9a9de ); +PROVIDE ( dh_group16_prime = 0x3ff9a7de ); +PROVIDE ( dh_group17_generator = 0x3ff9a7dd ); +PROVIDE ( dh_group17_prime = 0x3ff9a4dd ); +PROVIDE ( dh_group18_generator = 0x3ff9a4dc ); +PROVIDE ( dh_group18_prime = 0x3ff9a0dc ); +PROVIDE ( dh_group1_generator = 0x3ff9ae03 ); +PROVIDE ( dh_group1_prime = 0x3ff9ada3 ); +PROVIDE ( dh_group2_generator = 0x3ff9ada2 ); +PROVIDE ( dh_group2_prime = 0x3ff9ad22 ); +PROVIDE ( dh_group5_generator = 0x3ff9ad21 ); +PROVIDE ( dh_group5_prime = 0x3ff9ac61 ); +PROVIDE ( div = 0x40056348 ); +PROVIDE ( __divdc3 = 0x40064460 ); +PROVIDE ( __divdf3 = 0x40002954 ); +PROVIDE ( __divdi3 = 0x4000ca84 ); +PROVIDE ( __divsc3 = 0x40064200 ); +PROVIDE ( __divsf3 = 0x4000234c ); +PROVIDE ( __divsi3 = 0x4000c7b8 ); +PROVIDE ( _DoubleExceptionVector = 0x400003c0 ); +PROVIDE ( dummy_len_plus = 0x3ffae290 ); +PROVIDE ( __dummy_lock = 0x4000c728 ); +PROVIDE ( __dummy_lock_try = 0x4000c730 ); +PROVIDE ( ecc_env = 0x3ffb8d60 ); +PROVIDE ( ecc_Jacobian_InfinityPoint256 = 0x3ff972e8 ); +PROVIDE ( em_buf_env = 0x3ffb8d74 ); +PROVIDE ( environ = 0x3ffae0b4 ); +PROVIDE ( __env_lock = 0x40001fd4 ); +PROVIDE ( __env_unlock = 0x40001fe0 ); +PROVIDE ( __eqdf2 = 0x400636a8 ); +PROVIDE ( __eqsf2 = 0x40063374 ); +PROVIDE ( esp_crc8 = 0x4005d144 ); +PROVIDE ( _etext = 0x4000d66c ); +PROVIDE ( ets_aes_crypt = 0x4005c9b8 ); +PROVIDE ( ets_aes_disable = 0x4005c8f8 ); +PROVIDE ( ets_aes_enable = 0x4005c8cc ); +PROVIDE ( ets_aes_set_endian = 0x4005c928 ); +PROVIDE ( ets_aes_setkey_dec = 0x4005c994 ); +PROVIDE ( ets_aes_setkey_enc = 0x4005c97c ); +PROVIDE ( ets_bigint_disable = 0x4005c4e0 ); +PROVIDE ( ets_bigint_enable = 0x4005c498 ); +PROVIDE ( ets_bigint_mod_mult_getz = 0x4005c818 ); +PROVIDE ( ets_bigint_mod_mult_prepare = 0x4005c7b4 ); +PROVIDE ( ets_bigint_mod_power_getz = 0x4005c614 ); +PROVIDE ( ets_bigint_mod_power_prepare = 0x4005c54c ); +PROVIDE ( ets_bigint_montgomery_mult_getz = 0x4005c7a4 ); +PROVIDE ( ets_bigint_montgomery_mult_prepare = 0x4005c6fc ); +PROVIDE ( ets_bigint_mult_getz = 0x4005c6e8 ); +PROVIDE ( ets_bigint_mult_prepare = 0x4005c630 ); +PROVIDE ( ets_bigint_wait_finish = 0x4005c520 ); +PROVIDE ( ets_delay_us = 0x40008534 ); +PROVIDE ( ets_efuse_get_8M_clock = 0x40008710 ); +PROVIDE ( ets_efuse_get_spiconfig = 0x40008658 ); +PROVIDE ( ets_efuse_program_op = 0x40008628 ); +PROVIDE ( ets_efuse_read_op = 0x40008600 ); +PROVIDE ( ets_get_cpu_frequency = 0x4000855c ); +PROVIDE ( ets_get_detected_xtal_freq = 0x40008588 ); +PROVIDE ( ets_get_xtal_scale = 0x4000856c ); +PROVIDE ( ets_install_putc1 = 0x40007d18 ); +PROVIDE ( ets_install_putc2 = 0x40007d38 ); +PROVIDE ( ets_install_uart_printf = 0x40007d28 ); +PROVIDE ( ets_intr_count = 0x3ffe03fc ); +PROVIDE ( ets_intr_lock = 0x400067b0 ); +PROVIDE ( ets_intr_unlock = 0x400067c4 ); +PROVIDE ( ets_isr_attach = 0x400067ec ); +PROVIDE ( ets_isr_mask = 0x400067fc ); +PROVIDE ( ets_isr_unmask = 0x40006808 ); +PROVIDE ( ets_post = 0x4000673c ); +PROVIDE ( ets_printf = 0x40007d54 ); +PROVIDE ( ets_readySet_ = 0x3ffe01f0 ); +PROVIDE ( ets_run = 0x400066bc ); +PROVIDE ( ets_secure_boot_check = 0x4005cb40 ); +PROVIDE ( ets_secure_boot_check_finish = 0x4005cc04 ); +PROVIDE ( ets_secure_boot_check_start = 0x4005cbcc ); +PROVIDE ( ets_secure_boot_finish = 0x4005ca84 ); +PROVIDE ( ets_secure_boot_hash = 0x4005cad4 ); +PROVIDE ( ets_secure_boot_obtain = 0x4005cb14 ); +PROVIDE ( ets_secure_boot_rd_abstract = 0x4005cba8 ); +PROVIDE ( ets_secure_boot_rd_iv = 0x4005cb84 ); +PROVIDE ( ets_secure_boot_start = 0x4005ca34 ); +PROVIDE ( ets_set_appcpu_boot_addr = 0x4000689c ); +PROVIDE ( ets_set_idle_cb = 0x40006674 ); +PROVIDE ( ets_set_startup_callback = 0x4000688c ); +PROVIDE ( ets_set_user_start = 0x4000687c ); +PROVIDE ( ets_sha_disable = 0x4005c0a8 ); +PROVIDE ( ets_sha_enable = 0x4005c07c ); +PROVIDE ( ets_sha_finish = 0x4005c104 ); +PROVIDE ( ets_sha_init = 0x4005c0d4 ); +PROVIDE ( ets_sha_update = 0x4005c2a0 ); +PROVIDE ( ets_startup_callback = 0x3ffe0404 ); +PROVIDE ( ets_task = 0x40006688 ); +PROVIDE ( ets_timer_arm = 0x40008368 ); +PROVIDE ( ets_timer_arm_us = 0x400083ac ); +PROVIDE ( ets_timer_disarm = 0x400083ec ); +PROVIDE ( ets_timer_done = 0x40008428 ); +PROVIDE ( ets_timer_handler_isr = 0x40008454 ); +PROVIDE ( ets_timer_init = 0x400084e8 ); +PROVIDE ( ets_timer_setfn = 0x40008350 ); +PROVIDE ( ets_unpack_flash_code = 0x40007018 ); +PROVIDE ( ets_unpack_flash_code_legacy = 0x4000694c ); +PROVIDE ( ets_update_cpu_frequency = 0x40008550 ); +PROVIDE ( ets_waiti0 = 0x400067d8 ); +PROVIDE ( exc_cause_table = 0x3ff991d0 ); +PROVIDE ( _exit_r = 0x4000bd28 ); +PROVIDE ( __extendsfdf2 = 0x40002c34 ); +PROVIDE ( fclose = 0x400020ac ); +PROVIDE ( _fclose_r = 0x40001fec ); +PROVIDE ( fflush = 0x40059394 ); +PROVIDE ( _fflush_r = 0x40059320 ); +PROVIDE ( __ffsdi2 = 0x4000ca2c ); +PROVIDE ( __ffssi2 = 0x4000c804 ); +PROVIDE ( FilePacketSendDeflatedReqMsgProc = 0x40008b24 ); +PROVIDE ( FilePacketSendReqMsgProc = 0x40008860 ); +PROVIDE ( _findenv_r = 0x40001f44 ); +PROVIDE ( fiprintf = 0x40056efc ); +PROVIDE ( _fiprintf_r = 0x40056ed8 ); +PROVIDE ( fiscanf = 0x40058884 ); +PROVIDE ( _fiscanf_r = 0x400588b4 ); +PROVIDE ( __fixdfdi = 0x40002ac4 ); +PROVIDE ( __fixdfsi = 0x40002a78 ); +PROVIDE ( __fixsfdi = 0x4000244c ); +PROVIDE ( __fixsfsi = 0x4000240c ); +PROVIDE ( __fixunsdfsi = 0x40002b30 ); +PROVIDE ( __fixunssfdi = 0x40002504 ); +PROVIDE ( __fixunssfsi = 0x400024ac ); +PROVIDE ( FlashDwnLdDeflatedStartMsgProc = 0x40008ad8 ); +PROVIDE ( FlashDwnLdParamCfgMsgProc = 0x4000891c ); +PROVIDE ( FlashDwnLdStartMsgProc = 0x40008820 ); +PROVIDE ( FlashDwnLdStopDeflatedReqMsgProc = 0x40008c18 ); +PROVIDE ( FlashDwnLdStopReqMsgProc = 0x400088ec ); +PROVIDE ( __floatdidf = 0x4000c988 ); +PROVIDE ( __floatdisf = 0x4000c8c0 ); +PROVIDE ( __floatsidf = 0x4000c944 ); +PROVIDE ( __floatsisf = 0x4000c870 ); +PROVIDE ( __floatundidf = 0x4000c978 ); +PROVIDE ( __floatundisf = 0x4000c8b0 ); +PROVIDE ( __floatunsidf = 0x4000c938 ); +PROVIDE ( __floatunsisf = 0x4000c864 ); +PROVIDE ( __fp_lock_all = 0x40001f1c ); +PROVIDE ( fprintf = 0x40056efc ); +PROVIDE ( _fprintf_r = 0x40056ed8 ); +PROVIDE ( __fp_unlock_all = 0x40001f30 ); +PROVIDE ( fputwc = 0x40058ea8 ); +PROVIDE ( __fputwc = 0x40058da0 ); +PROVIDE ( _fputwc_r = 0x40058e4c ); +PROVIDE ( free = 0x4000beb8 ); +PROVIDE ( _free_r = 0x4000bbcc ); +PROVIDE ( fscanf = 0x40058884 ); +PROVIDE ( _fscanf_r = 0x400588b4 ); +PROVIDE ( _fstat_r = 0x4000bccc ); +PROVIDE ( _fwalk = 0x4000c738 ); +PROVIDE ( _fwalk_reent = 0x4000c770 ); +PROVIDE ( __gcc_bcmp = 0x40064a70 ); +PROVIDE ( __gedf2 = 0x40063768 ); +PROVIDE ( _GeneralException = 0x40000e14 ); +PROVIDE ( __gesf2 = 0x4006340c ); +PROVIDE ( __get_current_time_locale = 0x40001834 ); +PROVIDE ( _getenv_r = 0x40001fbc ); +PROVIDE ( _getpid_r = 0x4000bcfc ); +PROVIDE ( __getreent = 0x4000be8c ); +PROVIDE ( _gettimeofday_r = 0x4000bc58 ); +PROVIDE ( __gettzinfo = 0x40001fcc ); +PROVIDE ( GetUartDevice = 0x40009598 ); +PROVIDE ( GF_Jacobian_Point_Addition256 = 0x400163a4 ); +PROVIDE ( GF_Jacobian_Point_Double256 = 0x40016260 ); +PROVIDE ( GF_Point_Jacobian_To_Affine256 = 0x40016b0c ); +PROVIDE ( _global_impure_ptr = 0x3ffae0b0 ); +PROVIDE ( gmtime = 0x40059848 ); +PROVIDE ( gmtime_r = 0x40059868 ); +PROVIDE ( g_phyFuns_instance = 0x3ffae0c4 ); +PROVIDE ( gpio_init = 0x40009c20 ); +PROVIDE ( gpio_input_get = 0x40009b88 ); +PROVIDE ( gpio_input_get_high = 0x40009b9c ); +PROVIDE ( gpio_intr_ack = 0x40009dd4 ); +PROVIDE ( gpio_intr_ack_high = 0x40009e1c ); +PROVIDE ( gpio_intr_handler_register = 0x40009e6c ); +PROVIDE ( gpio_intr_pending = 0x40009cec ); +PROVIDE ( gpio_intr_pending_high = 0x40009cf8 ); +PROVIDE ( gpio_matrix_in = 0x40009edc ); +PROVIDE ( gpio_matrix_out = 0x40009f0c ); +PROVIDE ( gpio_output_set = 0x40009b24 ); +PROVIDE ( gpio_output_set_high = 0x40009b5c ); +PROVIDE ( gpio_pad_hold = 0x4000a734 ); +PROVIDE ( gpio_pad_pulldown = 0x4000a348 ); +PROVIDE ( gpio_pad_pullup = 0x4000a22c ); +PROVIDE ( gpio_pad_select_gpio = 0x40009fdc ); +PROVIDE ( gpio_pad_set_drv = 0x4000a11c ); +PROVIDE ( gpio_pad_unhold = 0x4000a484 ); +PROVIDE ( gpio_pending_mask = 0x3ffe0038 ); +PROVIDE ( gpio_pending_mask_high = 0x3ffe0044 ); +PROVIDE ( gpio_pin_intr_state_set = 0x40009d04 ); +PROVIDE ( gpio_pin_wakeup_disable = 0x40009eb0 ); +PROVIDE ( gpio_pin_wakeup_enable = 0x40009e7c ); +PROVIDE ( gpio_register_get = 0x40009cbc ); +PROVIDE ( gpio_register_set = 0x40009bbc ); +PROVIDE ( __gtdf2 = 0x400636dc ); +PROVIDE ( __gtsf2 = 0x400633a0 ); +PROVIDE ( gTxMsg = 0x3ffe0050 ); +PROVIDE ( hci_cmd_desc_root_tab = 0x3ff976d4 ); +PROVIDE ( hci_cmd_desc_tab_ctrl_bb = 0x3ff97b70 ); +PROVIDE ( hci_cmd_desc_tab_info_par = 0x3ff97b1c ); +PROVIDE ( hci_cmd_desc_tab_le = 0x3ff97870 ); +PROVIDE ( hci_cmd_desc_tab_lk_ctrl = 0x3ff97fc0 ); +PROVIDE ( hci_cmd_desc_tab_lk_pol = 0x3ff97f3c ); +PROVIDE ( hci_cmd_desc_tab_stat_par = 0x3ff97ac8 ); +PROVIDE ( hci_cmd_desc_tab_testing = 0x3ff97a98 ); +PROVIDE ( hci_cmd_desc_tab_vs = 0x3ff97714 ); +PROVIDE ( hci_command_handler = 0x4004c928 ); +PROVIDE ( hci_env = 0x3ffb9350 ); +PROVIDE ( hci_evt_dbg_desc_tab = 0x3ff9750c ); +PROVIDE ( hci_evt_desc_tab = 0x3ff9751c ); +PROVIDE ( hci_evt_le_desc_tab = 0x3ff974b4 ); +PROVIDE ( hci_fc_env = 0x3ffb9340 ); +PROVIDE ( hmac_md5 = 0x4005d264 ); +PROVIDE ( hmac_md5_vector = 0x4005d17c ); +PROVIDE ( hmac_sha1 = 0x40060acc ); +PROVIDE ( hmac_sha1_vector = 0x400609e4 ); +PROVIDE ( hmac_sha256 = 0x40060d58 ); +PROVIDE ( hmac_sha256_vector = 0x40060c84 ); +PROVIDE ( intr_matrix_set = 0x4000681c ); +PROVIDE ( iprintf = 0x40056978 ); +PROVIDE ( _iprintf_r = 0x40056944 ); +PROVIDE ( isalnum = 0x40000f04 ); +PROVIDE ( isalpha = 0x40000f18 ); +PROVIDE ( isascii = 0x4000c20c ); +PROVIDE ( _isatty_r = 0x40000ea0 ); +PROVIDE ( isblank = 0x40000f2c ); +PROVIDE ( iscanf = 0x40058760 ); +PROVIDE ( _iscanf_r = 0x4005879c ); +PROVIDE ( iscntrl = 0x40000f50 ); +PROVIDE ( isdigit = 0x40000f64 ); +PROVIDE ( isgraph = 0x40000f94 ); +PROVIDE ( islower = 0x40000f78 ); +PROVIDE ( isprint = 0x40000fa8 ); +PROVIDE ( ispunct = 0x40000fc0 ); +PROVIDE ( isspace = 0x40000fd4 ); +PROVIDE ( isupper = 0x40000fe8 ); +PROVIDE ( itoa = 0x400566b4 ); +PROVIDE ( __itoa = 0x40056678 ); +PROVIDE ( jd_decomp = 0x400613e8 ); +PROVIDE ( jd_prepare = 0x40060fa8 ); +PROVIDE ( ke_env = 0x3ffb93cc ); +PROVIDE ( _KernelExceptionVector = 0x40000300 ); +PROVIDE ( _kill_r = 0x4000bd10 ); +PROVIDE ( labs = 0x40056370 ); +PROVIDE ( lb_default_handler = 0x3ff982b8 ); +PROVIDE ( lb_default_state_tab_p_get = 0x4001c198 ); +PROVIDE ( lb_env = 0x3ffb9424 ); +PROVIDE ( lb_hci_cmd_handler_tab_p_get = 0x4001c18c ); +PROVIDE ( lb_state = 0x3ffb94e8 ); +PROVIDE ( lc_default_handler = 0x3ff98648 ); +PROVIDE ( lc_default_state_tab_p_get = 0x4002f494 ); +PROVIDE ( lc_env = 0x3ffb94ec ); +PROVIDE ( lc_hci_cmd_handler_tab_p_get = 0x4002f488 ); +PROVIDE ( lc_state = 0x3ffb9508 ); +PROVIDE ( ld_acl_br_sizes = 0x3ff98a2a ); +PROVIDE ( ld_acl_br_types = 0x3ff98a36 ); +PROVIDE ( ld_acl_edr_sizes = 0x3ff98a14 ); +PROVIDE ( ld_acl_edr_types = 0x3ff98a22 ); +PROVIDE ( ld_env = 0x3ffb9510 ); +PROVIDE ( ldiv = 0x40056378 ); +PROVIDE ( ld_pcm_settings_dft = 0x3ff98a0c ); +PROVIDE ( ld_sched_params = 0x3ffb96c0 ); +PROVIDE ( ld_sync_train_channels = 0x3ff98a3c ); +PROVIDE ( __ledf2 = 0x40063704 ); +PROVIDE ( __lesf2 = 0x400633c0 ); +PROVIDE ( _Level2FromVector = 0x40000954 ); +PROVIDE ( _Level2Vector = 0x40000180 ); +PROVIDE ( _Level3FromVector = 0x40000a28 ); +PROVIDE ( _Level3Vector = 0x400001c0 ); +PROVIDE ( _Level4FromVector = 0x40000af8 ); +PROVIDE ( _Level4Vector = 0x40000200 ); +PROVIDE ( _Level5FromVector = 0x40000c68 ); +PROVIDE ( _Level5Vector = 0x40000240 ); +PROVIDE ( _LevelOneInterrupt = 0x40000835 ); +PROVIDE ( _link_r = 0x4000bc9c ); +PROVIDE ( llc_default_handler = 0x3ff98b3c ); +PROVIDE ( llc_default_state_tab_p_get = 0x40046058 ); +PROVIDE ( llc_env = 0x3ffb96d0 ); +PROVIDE ( llc_hci_acl_data_tx_handler = 0x40042398 ); +PROVIDE ( llc_hci_cmd_handler_tab_p_get = 0x40042358 ); +PROVIDE ( llc_hci_command_handler = 0x40042360 ); +PROVIDE ( llcp_pdu_handler_tab_p_get = 0x40043f64 ); +PROVIDE ( llc_state = 0x3ffb96f8 ); +PROVIDE ( lldesc_build_chain = 0x4000a850 ); +PROVIDE ( lldesc_num2link = 0x4000a948 ); +PROVIDE ( lldesc_set_owner = 0x4000a974 ); +PROVIDE ( lld_evt_env = 0x3ffb9704 ); +PROVIDE ( lld_pdu_adv_pk_desc_tab = 0x3ff98c70 ); +PROVIDE ( lld_pdu_llcp_pk_desc_tab = 0x3ff98b68 ); +PROVIDE ( LLM_AA_CT1 = 0x3ff98d8a ); +PROVIDE ( LLM_AA_CT2 = 0x3ff98d88 ); +PROVIDE ( llm_default_handler = 0x3ff98d80 ); +PROVIDE ( llm_default_state_tab_p_get = 0x4004e718 ); +PROVIDE ( llm_hci_cmd_handler_tab_p_get = 0x4004c920 ); +PROVIDE ( llm_le_env = 0x3ffb976c ); +PROVIDE ( llm_local_cmds = 0x3ff98d38 ); +PROVIDE ( llm_local_data_len_values = 0x3ff98d1c ); +PROVIDE ( llm_local_le_feats = 0x3ff98d30 ); +PROVIDE ( llm_local_le_states = 0x3ff98d28 ); +PROVIDE ( llm_state = 0x3ffb985c ); +PROVIDE ( lm_default_handler = 0x3ff990e0 ); +PROVIDE ( lm_default_state_tab_p_get = 0x40054268 ); +PROVIDE ( lm_env = 0x3ffb9860 ); +PROVIDE ( lm_hci_cmd_handler_tab_p_get = 0x4005425c ); +PROVIDE ( lm_local_supp_feats = 0x3ff990ee ); +PROVIDE ( lm_n_page_tab = 0x3ff990e8 ); +PROVIDE ( lmp_desc_tab = 0x3ff96e6c ); +PROVIDE ( lmp_ext_desc_tab = 0x3ff96d9c ); +PROVIDE ( lm_state = 0x3ffb9a1c ); +PROVIDE ( __locale_charset = 0x40059540 ); +PROVIDE ( __locale_cjk_lang = 0x40059558 ); +PROVIDE ( localeconv = 0x4005957c ); +PROVIDE ( _localeconv_r = 0x40059560 ); +PROVIDE ( __locale_mb_cur_max = 0x40059548 ); +PROVIDE ( __locale_msgcharset = 0x40059550 ); +PROVIDE ( localtime = 0x400595dc ); +PROVIDE ( localtime_r = 0x400595fc ); +PROVIDE ( _lock_acquire = 0x4000be14 ); +PROVIDE ( _lock_acquire_recursive = 0x4000be28 ); +PROVIDE ( _lock_close = 0x4000bdec ); +PROVIDE ( _lock_close_recursive = 0x4000be00 ); +PROVIDE ( _lock_init = 0x4000bdc4 ); +PROVIDE ( _lock_init_recursive = 0x4000bdd8 ); +PROVIDE ( _lock_release = 0x4000be64 ); +PROVIDE ( _lock_release_recursive = 0x4000be78 ); +PROVIDE ( _lock_try_acquire = 0x4000be3c ); +PROVIDE ( _lock_try_acquire_recursive = 0x4000be50 ); +PROVIDE ( longjmp = 0x400562cc ); +PROVIDE ( _lseek_r = 0x4000bd8c ); +PROVIDE ( __lshrdi3 = 0x4000c84c ); +PROVIDE ( __ltdf2 = 0x40063790 ); +PROVIDE ( __ltsf2 = 0x4006342c ); +PROVIDE ( main = 0x400076c4 ); +PROVIDE ( malloc = 0x4000bea0 ); +PROVIDE ( _malloc_r = 0x4000bbb4 ); +PROVIDE ( maxSecretKey_256 = 0x3ff97448 ); +PROVIDE ( __mb_cur_max = 0x3ff96530 ); +PROVIDE ( MD5Final = 0x4005db1c ); +PROVIDE ( MD5Init = 0x4005da7c ); +PROVIDE ( MD5Update = 0x4005da9c ); +PROVIDE ( md5_vector = 0x4005db80 ); +PROVIDE ( memccpy = 0x4000c220 ); +PROVIDE ( memchr = 0x4000c244 ); +PROVIDE ( memcmp = 0x4000c260 ); +PROVIDE ( memcpy = 0x4000c2c8 ); +PROVIDE ( MemDwnLdStartMsgProc = 0x40008948 ); +PROVIDE ( MemDwnLdStopReqMsgProc = 0x400089dc ); +PROVIDE ( memmove = 0x4000c3c0 ); +PROVIDE ( MemPacketSendReqMsgProc = 0x40008978 ); +PROVIDE ( memrchr = 0x4000c400 ); +PROVIDE ( memset = 0x4000c44c ); +PROVIDE ( mktime = 0x4005a5e8 ); +PROVIDE ( mmu_init = 0x400095a4 ); +PROVIDE ( __moddi3 = 0x4000cd4c ); +PROVIDE ( __modsi3 = 0x4000c7c0 ); +PROVIDE ( __month_lengths = 0x3ff9609c ); +PROVIDE ( __muldc3 = 0x40063bf4 ); +PROVIDE ( __muldf3 = 0x4006358c ); +PROVIDE ( __muldi3 = 0x4000c9fc ); +PROVIDE ( __mulsc3 = 0x40063934 ); +PROVIDE ( __mulsf3 = 0x400632c8 ); +PROVIDE ( __mulsi3 = 0x4000c7b0 ); +PROVIDE ( MultiplyBigHexByUint32_256 = 0x40016214 ); +PROVIDE ( MultiplyBigHexModP256 = 0x400160b8 ); +PROVIDE ( MultiplyByU32ModP256 = 0x40015fdc ); +PROVIDE ( multofup = 0x4000ab8c ); +PROVIDE ( __mulvdi3 = 0x40002d78 ); +PROVIDE ( __mulvsi3 = 0x40002d60 ); +PROVIDE ( mz_adler32 = 0x4005edbc ); +PROVIDE ( mz_crc32 = 0x4005ee88 ); +PROVIDE ( mz_free = 0x4005eed4 ); +PROVIDE ( __nedf2 = 0x400636a8 ); +PROVIDE ( __negdf2 = 0x400634a0 ); +PROVIDE ( __negdi2 = 0x4000ca14 ); +PROVIDE ( __negsf2 = 0x400020c0 ); +PROVIDE ( __negvdi2 = 0x40002e98 ); +PROVIDE ( __negvsi2 = 0x40002e78 ); +PROVIDE ( __nesf2 = 0x40063374 ); +PROVIDE ( _NMIExceptionVector = 0x400002c0 ); +PROVIDE ( notEqual256 = 0x40015b04 ); +PROVIDE ( __nsau_data = 0x3ff96544 ); +PROVIDE ( one_bits = 0x3ff971f8 ); +PROVIDE ( open = 0x4000178c ); +PROVIDE ( _open_r = 0x4000bd54 ); +PROVIDE ( __paritysi2 = 0x40002f3c ); +PROVIDE ( pbkdf2_sha1 = 0x40060ba4 ); +PROVIDE ( phy_get_romfuncs = 0x40004100 ); +PROVIDE ( __popcountdi2 = 0x40002ef8 ); +PROVIDE ( __popcountsi2 = 0x40002ed0 ); +PROVIDE ( __popcount_tab = 0x3ff96544 ); +PROVIDE ( __powidf2 = 0x400638d4 ); +PROVIDE ( __powisf2 = 0x4006389c ); +PROVIDE ( _Pri_4_HandlerAddress = 0x3ffe0648 ); +PROVIDE ( _Pri_5_HandlerAddress = 0x3ffe064c ); +PROVIDE ( printf = 0x40056978 ); +PROVIDE ( _printf_common = 0x40057338 ); +PROVIDE ( _printf_float = 0x4000befc ); +PROVIDE ( _printf_i = 0x40057404 ); +PROVIDE ( _printf_r = 0x40056944 ); +PROVIDE ( qsort = 0x40056424 ); +PROVIDE ( _raise_r = 0x4000bc70 ); +PROVIDE ( rand = 0x40001058 ); +PROVIDE ( rand_r = 0x400010d4 ); +PROVIDE ( r_btdm_option_data = 0x3ffae6e0 ); +PROVIDE ( r_bt_util_buf_acl_rx_alloc = 0x40010218 ); +PROVIDE ( r_bt_util_buf_acl_rx_free = 0x40010234 ); +PROVIDE ( r_bt_util_buf_acl_tx_alloc = 0x40010268 ); +PROVIDE ( r_bt_util_buf_acl_tx_free = 0x40010280 ); +PROVIDE ( r_bt_util_buf_init = 0x400100e4 ); +PROVIDE ( r_bt_util_buf_lmp_tx_alloc = 0x400101d0 ); +PROVIDE ( r_bt_util_buf_lmp_tx_free = 0x400101ec ); +PROVIDE ( r_bt_util_buf_sync_clear = 0x400103c8 ); +PROVIDE ( r_bt_util_buf_sync_init = 0x400102c4 ); +PROVIDE ( r_bt_util_buf_sync_rx_alloc = 0x40010468 ); +PROVIDE ( r_bt_util_buf_sync_rx_free = 0x4001049c ); +PROVIDE ( r_bt_util_buf_sync_tx_alloc = 0x400103ec ); +PROVIDE ( r_bt_util_buf_sync_tx_free = 0x40010428 ); +PROVIDE ( rc4_skip = 0x40060928 ); +PROVIDE ( r_co_bdaddr_compare = 0x40014324 ); +PROVIDE ( r_co_bytes_to_string = 0x400142e4 ); +PROVIDE ( r_co_list_check_size_available = 0x400142c4 ); +PROVIDE ( r_co_list_extract = 0x4001404c ); +PROVIDE ( r_co_list_extract_after = 0x40014118 ); +PROVIDE ( r_co_list_find = 0x4001419c ); +PROVIDE ( r_co_list_init = 0x40013f14 ); +PROVIDE ( r_co_list_insert_after = 0x40014254 ); +PROVIDE ( r_co_list_insert_before = 0x40014200 ); +PROVIDE ( r_co_list_merge = 0x400141bc ); +PROVIDE ( r_co_list_pool_init = 0x40013f30 ); +PROVIDE ( r_co_list_pop_front = 0x40014028 ); +PROVIDE ( r_co_list_push_back = 0x40013fb8 ); +PROVIDE ( r_co_list_push_front = 0x40013ff4 ); +PROVIDE ( r_co_list_size = 0x400142ac ); +PROVIDE ( r_co_nb_good_channels = 0x40014360 ); +PROVIDE ( r_co_slot_to_duration = 0x40014348 ); +PROVIDE ( RcvMsg = 0x4000954c ); +PROVIDE ( r_dbg_init = 0x40014394 ); +PROVIDE ( r_dbg_platform_reset_complete = 0x400143d0 ); +PROVIDE ( r_dbg_swdiag_init = 0x40014470 ); +PROVIDE ( r_dbg_swdiag_read = 0x400144a4 ); +PROVIDE ( r_dbg_swdiag_write = 0x400144d0 ); +PROVIDE ( r_E1 = 0x400108e8 ); +PROVIDE ( r_E21 = 0x40010968 ); +PROVIDE ( r_E22 = 0x400109b4 ); +PROVIDE ( r_E3 = 0x40010a58 ); +PROVIDE ( r_ea_alarm_clear = 0x40015ab4 ); +PROVIDE ( r_ea_alarm_set = 0x40015a10 ); +PROVIDE ( read = 0x400017dc ); +PROVIDE ( _read_r = 0x4000bda8 ); +PROVIDE ( r_ea_elt_cancel = 0x400150d0 ); +PROVIDE ( r_ea_elt_create = 0x40015264 ); +PROVIDE ( r_ea_elt_insert = 0x400152a8 ); +PROVIDE ( r_ea_elt_remove = 0x400154f0 ); +PROVIDE ( r_ea_finetimer_isr = 0x400155d4 ); +PROVIDE ( r_ea_init = 0x40015228 ); +PROVIDE ( r_ea_interval_create = 0x4001555c ); +PROVIDE ( r_ea_interval_delete = 0x400155a8 ); +PROVIDE ( r_ea_interval_duration_req = 0x4001597c ); +PROVIDE ( r_ea_interval_insert = 0x4001557c ); +PROVIDE ( r_ea_interval_remove = 0x40015590 ); +PROVIDE ( realloc = 0x4000becc ); +PROVIDE ( _realloc_r = 0x4000bbe0 ); +PROVIDE ( r_ea_offset_req = 0x40015748 ); +PROVIDE ( r_ea_sleep_check = 0x40015928 ); +PROVIDE ( r_ea_sw_isr = 0x40015724 ); +PROVIDE ( r_ea_time_get_halfslot_rounded = 0x40015894 ); +PROVIDE ( r_ea_time_get_slot_rounded = 0x400158d4 ); +PROVIDE ( r_ecc_abort_key256_generation = 0x40017070 ); +PROVIDE ( r_ecc_generate_key256 = 0x40016e00 ); +PROVIDE ( r_ecc_gen_new_public_key = 0x400170c0 ); +PROVIDE ( r_ecc_gen_new_secret_key = 0x400170e4 ); +PROVIDE ( r_ecc_get_debug_Keys = 0x40017224 ); +PROVIDE ( r_ecc_init = 0x40016dbc ); +PROVIDE ( RecvBuff = 0x3ffe009c ); +PROVIDE ( recv_packet = 0x40009424 ); +PROVIDE ( r_em_buf_init = 0x4001729c ); +PROVIDE ( r_em_buf_rx_buff_addr_get = 0x400173e8 ); +PROVIDE ( r_em_buf_rx_free = 0x400173c4 ); +PROVIDE ( r_em_buf_tx_buff_addr_get = 0x40017404 ); +PROVIDE ( r_em_buf_tx_free = 0x4001741c ); +PROVIDE ( _rename_r = 0x4000bc28 ); +PROVIDE ( _ResetHandler = 0x40000450 ); +PROVIDE ( _ResetVector = 0x40000400 ); +PROVIDE ( r_F1_256 = 0x400133e4 ); +PROVIDE ( r_F2_256 = 0x40013568 ); +PROVIDE ( r_F3_256 = 0x40013664 ); +PROVIDE ( RFPLL_ICP_TABLE = 0x3ffb8b7c ); +PROVIDE ( r_G_256 = 0x40013470 ); +PROVIDE ( r_H3 = 0x40013760 ); +PROVIDE ( r_H4 = 0x40013830 ); +PROVIDE ( r_h4tl_init = 0x40017878 ); +PROVIDE ( r_h4tl_start = 0x40017924 ); +PROVIDE ( r_h4tl_stop = 0x40017934 ); +PROVIDE ( r_h4tl_write = 0x400178d0 ); +PROVIDE ( r_H5 = 0x400138dc ); +PROVIDE ( r_hashConcat = 0x40013a38 ); +PROVIDE ( r_hci_acl_tx_data_alloc = 0x4001951c ); +PROVIDE ( r_hci_acl_tx_data_received = 0x40019654 ); +PROVIDE ( r_hci_bt_acl_bdaddr_register = 0x40018900 ); +PROVIDE ( r_hci_bt_acl_bdaddr_unregister = 0x400189ac ); +PROVIDE ( r_hci_bt_acl_conhdl_register = 0x4001895c ); +PROVIDE ( r_hci_cmd_get_max_param_size = 0x400192d0 ); +PROVIDE ( r_hci_cmd_received = 0x400192f8 ); +PROVIDE ( r_hci_evt_filter_add = 0x40018a64 ); +PROVIDE ( r_hci_evt_mask_set = 0x400189e4 ); +PROVIDE ( r_hci_fc_acl_buf_size_set = 0x40017988 ); +PROVIDE ( r_hci_fc_acl_en = 0x400179d8 ); +PROVIDE ( r_hci_fc_acl_packet_sent = 0x40017a3c ); +PROVIDE ( r_hci_fc_check_host_available_nb_acl_packets = 0x40017aa4 ); +PROVIDE ( r_hci_fc_check_host_available_nb_sync_packets = 0x40017ac8 ); +PROVIDE ( r_hci_fc_host_nb_acl_pkts_complete = 0x40017a6c ); +PROVIDE ( r_hci_fc_host_nb_sync_pkts_complete = 0x40017a88 ); +PROVIDE ( r_hci_fc_init = 0x40017974 ); +PROVIDE ( r_hci_fc_sync_buf_size_set = 0x400179b0 ); +PROVIDE ( r_hci_fc_sync_en = 0x40017a30 ); +PROVIDE ( r_hci_fc_sync_packet_sent = 0x40017a54 ); +PROVIDE ( r_hci_init = 0x40018538 ); +PROVIDE ( r_hci_look_for_cmd_desc = 0x40018454 ); +PROVIDE ( r_hci_look_for_dbg_evt_desc = 0x400184c4 ); +PROVIDE ( r_hci_look_for_evt_desc = 0x400184a0 ); +PROVIDE ( r_hci_look_for_le_evt_desc = 0x400184e0 ); +PROVIDE ( r_hci_reset = 0x4001856c ); +PROVIDE ( r_hci_send_2_host = 0x400185bc ); +PROVIDE ( r_hci_sync_tx_data_alloc = 0x40019754 ); +PROVIDE ( r_hci_sync_tx_data_received = 0x400197c0 ); +PROVIDE ( r_hci_tl_init = 0x40019290 ); +PROVIDE ( r_hci_tl_send = 0x40019228 ); +PROVIDE ( r_hci_util_pack = 0x40019874 ); +PROVIDE ( r_hci_util_unpack = 0x40019998 ); +PROVIDE ( r_hci_voice_settings_get = 0x40018bdc ); +PROVIDE ( r_hci_voice_settings_set = 0x40018be8 ); +PROVIDE ( r_HMAC = 0x40013968 ); +PROVIDE ( r_import_rf_phy_func = 0x3ffb8354 ); +PROVIDE ( r_import_rf_phy_func_p = 0x3ffafd64 ); +PROVIDE ( r_ip_funcs = 0x3ffae710 ); +PROVIDE ( r_ip_funcs_p = 0x3ffae70c ); +PROVIDE ( r_ke_check_malloc = 0x40019de0 ); +PROVIDE ( r_ke_event_callback_set = 0x40019ba8 ); +PROVIDE ( r_ke_event_clear = 0x40019c2c ); +PROVIDE ( r_ke_event_flush = 0x40019ccc ); +PROVIDE ( r_ke_event_get = 0x40019c78 ); +PROVIDE ( r_ke_event_get_all = 0x40019cc0 ); +PROVIDE ( r_ke_event_init = 0x40019b90 ); +PROVIDE ( r_ke_event_schedule = 0x40019cdc ); +PROVIDE ( r_ke_event_set = 0x40019be0 ); +PROVIDE ( r_ke_flush = 0x4001a374 ); +PROVIDE ( r_ke_free = 0x4001a014 ); +PROVIDE ( r_ke_get_max_mem_usage = 0x4001a1c8 ); +PROVIDE ( r_ke_get_mem_usage = 0x4001a1a0 ); +PROVIDE ( r_ke_init = 0x4001a318 ); +PROVIDE ( r_ke_is_free = 0x4001a184 ); +PROVIDE ( r_ke_malloc = 0x40019eb4 ); +PROVIDE ( r_ke_mem_init = 0x40019d3c ); +PROVIDE ( r_ke_mem_is_empty = 0x40019d8c ); +PROVIDE ( r_ke_msg_alloc = 0x4001a1e0 ); +PROVIDE ( r_ke_msg_dest_id_get = 0x4001a2e0 ); +PROVIDE ( r_ke_msg_discard = 0x4001a850 ); +PROVIDE ( r_ke_msg_forward = 0x4001a290 ); +PROVIDE ( r_ke_msg_forward_new_id = 0x4001a2ac ); +PROVIDE ( r_ke_msg_free = 0x4001a2cc ); +PROVIDE ( r_ke_msg_in_queue = 0x4001a2f8 ); +PROVIDE ( r_ke_msg_save = 0x4001a858 ); +PROVIDE ( r_ke_msg_send = 0x4001a234 ); +PROVIDE ( r_ke_msg_send_basic = 0x4001a26c ); +PROVIDE ( r_ke_msg_src_id_get = 0x4001a2ec ); +PROVIDE ( r_ke_queue_extract = 0x40055fd0 ); +PROVIDE ( r_ke_queue_insert = 0x40056020 ); +PROVIDE ( r_ke_sleep_check = 0x4001a3d8 ); +PROVIDE ( r_ke_state_get = 0x4001a7d8 ); +PROVIDE ( r_ke_state_set = 0x4001a6fc ); +PROVIDE ( r_ke_stats_get = 0x4001a3f0 ); +PROVIDE ( r_ke_task_check = 0x4001a8a4 ); +PROVIDE ( r_ke_task_create = 0x4001a674 ); +PROVIDE ( r_ke_task_delete = 0x4001a6c0 ); +PROVIDE ( r_ke_task_init = 0x4001a650 ); +PROVIDE ( r_ke_task_msg_flush = 0x4001a860 ); +PROVIDE ( r_ke_timer_active = 0x4001ac08 ); +PROVIDE ( r_ke_timer_adjust_all = 0x4001ac30 ); +PROVIDE ( r_ke_timer_clear = 0x4001ab90 ); +PROVIDE ( r_ke_timer_init = 0x4001aa9c ); +PROVIDE ( r_ke_timer_set = 0x4001aac0 ); +PROVIDE ( r_ke_timer_sleep_check = 0x4001ac50 ); +PROVIDE ( r_KPrimC = 0x40010ad4 ); +PROVIDE ( r_lb_clk_adj_activate = 0x4001ae70 ); +PROVIDE ( r_lb_clk_adj_id_get = 0x4001af14 ); +PROVIDE ( r_lb_clk_adj_period_update = 0x4001af20 ); +PROVIDE ( r_lb_init = 0x4001acd4 ); +PROVIDE ( r_lb_mst_key = 0x4001afc0 ); +PROVIDE ( r_lb_mst_key_cmp = 0x4001af74 ); +PROVIDE ( r_lb_mst_key_restart_enc = 0x4001b0d4 ); +PROVIDE ( r_lb_mst_start_act_bcst_enc = 0x4001b198 ); +PROVIDE ( r_lb_mst_stop_act_bcst_enc = 0x4001b24c ); +PROVIDE ( r_lb_reset = 0x4001ad38 ); +PROVIDE ( r_lb_send_lmp = 0x4001adbc ); +PROVIDE ( r_lb_send_pdu_clk_adj = 0x4001af3c ); +PROVIDE ( r_lb_util_get_csb_mode = 0x4001ada4 ); +PROVIDE ( r_lb_util_get_nb_broadcast = 0x4001ad80 ); +PROVIDE ( r_lb_util_get_res_lt_addr = 0x4001ad98 ); +PROVIDE ( r_lb_util_set_nb_broadcast = 0x4001ad8c ); +PROVIDE ( r_lc_afh_set = 0x4001cc74 ); +PROVIDE ( r_lc_afh_start = 0x4001d240 ); +PROVIDE ( r_lc_auth_cmp = 0x4001cd54 ); +PROVIDE ( r_lc_calc_link_key = 0x4001ce7c ); +PROVIDE ( r_lc_chg_pkt_type_cmp = 0x4001d038 ); +PROVIDE ( r_lc_chg_pkt_type_cont = 0x4001cfbc ); +PROVIDE ( r_lc_chg_pkt_type_retry = 0x4001d0ac ); +PROVIDE ( r_lc_chk_to = 0x4001d2a8 ); +PROVIDE ( r_lc_cmd_stat_send = 0x4001c914 ); +PROVIDE ( r_lc_comb_key_svr = 0x4001d30c ); +PROVIDE ( r_lc_con_cmp = 0x4001d44c ); +PROVIDE ( r_lc_con_cmp_evt_send = 0x4001d4fc ); +PROVIDE ( r_lc_conn_seq_done = 0x40021334 ); +PROVIDE ( r_lc_detach = 0x4002037c ); +PROVIDE ( r_lc_dhkey = 0x4001d564 ); +PROVIDE ( r_lc_enc_cmp = 0x4001d8bc ); +PROVIDE ( r_lc_enc_key_refresh = 0x4001d720 ); +PROVIDE ( r_lc_end_chk_colli = 0x4001d858 ); +PROVIDE ( r_lc_end_of_sniff_nego = 0x4001d9a4 ); +PROVIDE ( r_lc_enter_sniff_mode = 0x4001ddb8 ); +PROVIDE ( r_lc_epr_change_lk = 0x4001db38 ); +PROVIDE ( r_lc_epr_cmp = 0x4001da88 ); +PROVIDE ( r_lc_epr_resp = 0x4001e0b4 ); +PROVIDE ( r_lc_epr_rsw_cmp = 0x4001dd40 ); +PROVIDE ( r_lc_ext_feat = 0x40020d6c ); +PROVIDE ( r_lc_feat = 0x40020984 ); +PROVIDE ( r_lc_hl_connect = 0x400209e8 ); +PROVIDE ( r_lc_init = 0x4001c948 ); +PROVIDE ( r_lc_init_calc_f3 = 0x4001deb0 ); +PROVIDE ( r_lc_initiator_epr = 0x4001e064 ); +PROVIDE ( r_lc_init_passkey_loop = 0x4001dfc0 ); +PROVIDE ( r_lc_init_start_mutual_auth = 0x4001df60 ); +PROVIDE ( r_lc_key_exch_end = 0x4001e140 ); +PROVIDE ( r_lc_legacy_pair = 0x4001e1c0 ); +PROVIDE ( r_lc_local_switch = 0x4001e22c ); +PROVIDE ( r_lc_local_trans_mode = 0x4001e2e4 ); +PROVIDE ( r_lc_local_untrans_mode = 0x4001e3a0 ); +PROVIDE ( r_lc_loc_auth = 0x40020ecc ); +PROVIDE ( r_lc_locepr_lkref = 0x4001d648 ); +PROVIDE ( r_lc_locepr_rsw = 0x4001d5d0 ); +PROVIDE ( r_lc_loc_sniff = 0x40020a6c ); +PROVIDE ( r_lc_max_slot_mgt = 0x4001e410 ); +PROVIDE ( r_lc_mst_key = 0x4001e7c0 ); +PROVIDE ( r_lc_mst_qos_done = 0x4001ea80 ); +PROVIDE ( r_lc_mst_send_mst_key = 0x4001e8f4 ); +PROVIDE ( r_lc_mutual_auth_end = 0x4001e670 ); +PROVIDE ( r_lc_mutual_auth_end2 = 0x4001e4f4 ); +PROVIDE ( r_lc_packet_type = 0x40021038 ); +PROVIDE ( r_lc_pair = 0x40020ddc ); +PROVIDE ( r_lc_pairing_cont = 0x4001eafc ); +PROVIDE ( r_lc_passkey_comm = 0x4001ed20 ); +PROVIDE ( r_lc_prepare_all_links_for_clk_adj = 0x40021430 ); +PROVIDE ( r_lc_proc_rcv_dhkey = 0x4001edec ); +PROVIDE ( r_lc_ptt = 0x4001ee2c ); +PROVIDE ( r_lc_ptt_cmp = 0x4001eeec ); +PROVIDE ( r_lc_qos_setup = 0x4001ef50 ); +PROVIDE ( r_lc_rd_rem_name = 0x4001efd0 ); +PROVIDE ( r_lc_release = 0x4001f8a8 ); +PROVIDE ( r_lc_rem_enc = 0x4001f124 ); +PROVIDE ( r_lc_rem_name_cont = 0x4001f290 ); +PROVIDE ( r_lc_rem_nego_trans_mode = 0x4001f1b4 ); +PROVIDE ( r_lc_rem_sniff = 0x40020ca4 ); +PROVIDE ( r_lc_rem_sniff_sub_rate = 0x40020b10 ); +PROVIDE ( r_lc_rem_switch = 0x4001f070 ); +PROVIDE ( r_lc_rem_trans_mode = 0x4001f314 ); +PROVIDE ( r_lc_rem_unsniff = 0x400207a0 ); +PROVIDE ( r_lc_rem_untrans_mode = 0x4001f36c ); +PROVIDE ( r_lc_reset = 0x4001c99c ); +PROVIDE ( r_lc_resp_auth = 0x4001f518 ); +PROVIDE ( r_lc_resp_calc_f3 = 0x4001f710 ); +PROVIDE ( r_lc_resp_num_comp = 0x40020074 ); +PROVIDE ( r_lc_resp_oob_nonce = 0x4001f694 ); +PROVIDE ( r_lc_resp_oob_wait_nonce = 0x4001f66c ); +PROVIDE ( r_lc_resp_pair = 0x400208a4 ); +PROVIDE ( r_lc_resp_sec_auth = 0x4001f4a0 ); +PROVIDE ( r_lc_resp_wait_dhkey_cont = 0x4001f86c ); +PROVIDE ( r_lc_restart_enc = 0x4001f8ec ); +PROVIDE ( r_lc_restart_enc_cont = 0x4001f940 ); +PROVIDE ( r_lc_restore_afh_reporting = 0x4001f028 ); +PROVIDE ( r_lc_restore_to = 0x4001f9e0 ); +PROVIDE ( r_lc_ret_sniff_max_slot_chg = 0x4001fa30 ); +PROVIDE ( r_lc_rsw_clean_up = 0x4001dc70 ); +PROVIDE ( r_lc_rsw_done = 0x4001db94 ); +PROVIDE ( r_lc_sco_baseband_ack = 0x40022b00 ); +PROVIDE ( r_lc_sco_detach = 0x40021e40 ); +PROVIDE ( r_lc_sco_host_accept = 0x40022118 ); +PROVIDE ( r_lc_sco_host_reject = 0x400222b8 ); +PROVIDE ( r_lc_sco_host_request = 0x40021f4c ); +PROVIDE ( r_lc_sco_host_request_disc = 0x4002235c ); +PROVIDE ( r_lc_sco_init = 0x40021dc8 ); +PROVIDE ( r_lc_sco_peer_accept = 0x40022780 ); +PROVIDE ( r_lc_sco_peer_accept_disc = 0x40022a08 ); +PROVIDE ( r_lc_sco_peer_reject = 0x40022824 ); +PROVIDE ( r_lc_sco_peer_reject_disc = 0x40022a8c ); +PROVIDE ( r_lc_sco_peer_request = 0x4002240c ); +PROVIDE ( r_lc_sco_peer_request_disc = 0x400228ec ); +PROVIDE ( r_lc_sco_release = 0x40021eec ); +PROVIDE ( r_lc_sco_reset = 0x40021dfc ); +PROVIDE ( r_lc_sco_timeout = 0x40022bd4 ); +PROVIDE ( r_lc_sec_auth_compute_sres = 0x4001f3ec ); +PROVIDE ( r_lc_semi_key_cmp = 0x40020294 ); +PROVIDE ( r_lc_send_enc_chg_evt = 0x4002134c ); +PROVIDE ( r_lc_send_enc_mode = 0x40020220 ); +PROVIDE ( r_lc_send_lmp = 0x4001c1a8 ); +PROVIDE ( r_lc_send_pdu_acc = 0x4001c21c ); +PROVIDE ( r_lc_send_pdu_acc_ext4 = 0x4001c240 ); +PROVIDE ( r_lc_send_pdu_au_rand = 0x4001c308 ); +PROVIDE ( r_lc_send_pdu_auto_rate = 0x4001c5d0 ); +PROVIDE ( r_lc_send_pdu_clk_adj_ack = 0x4001c46c ); +PROVIDE ( r_lc_send_pdu_clk_adj_req = 0x4001c494 ); +PROVIDE ( r_lc_send_pdu_comb_key = 0x4001c368 ); +PROVIDE ( r_lc_send_pdu_dhkey_chk = 0x4001c8e8 ); +PROVIDE ( r_lc_send_pdu_encaps_head = 0x4001c440 ); +PROVIDE ( r_lc_send_pdu_encaps_payl = 0x4001c410 ); +PROVIDE ( r_lc_send_pdu_enc_key_sz_req = 0x4001c670 ); +PROVIDE ( r_lc_send_pdu_esco_lk_rem_req = 0x4001c5a8 ); +PROVIDE ( r_lc_send_pdu_feats_ext_req = 0x4001c6ec ); +PROVIDE ( r_lc_send_pdu_feats_res = 0x4001c694 ); +PROVIDE ( r_lc_send_pdu_in_rand = 0x4001c338 ); +PROVIDE ( r_lc_send_pdu_io_cap_res = 0x4001c72c ); +PROVIDE ( r_lc_send_pdu_lsto = 0x4001c64c ); +PROVIDE ( r_lc_send_pdu_max_slot = 0x4001c3c8 ); +PROVIDE ( r_lc_send_pdu_max_slot_req = 0x4001c3ec ); +PROVIDE ( r_lc_send_pdu_not_acc = 0x4001c26c ); +PROVIDE ( r_lc_send_pdu_not_acc_ext4 = 0x4001c294 ); +PROVIDE ( r_lc_send_pdu_num_comp_fail = 0x4001c770 ); +PROVIDE ( r_lc_send_pdu_pause_enc_aes_req = 0x4001c794 ); +PROVIDE ( r_lc_send_pdu_paus_enc_req = 0x4001c7c0 ); +PROVIDE ( r_lc_send_pdu_ptt_req = 0x4001c4c0 ); +PROVIDE ( r_lc_send_pdu_qos_req = 0x4001c82c ); +PROVIDE ( r_lc_send_pdu_resu_enc_req = 0x4001c7e4 ); +PROVIDE ( r_lc_send_pdu_sco_lk_rem_req = 0x4001c580 ); +PROVIDE ( r_lc_send_pdu_set_afh = 0x4001c2c8 ); +PROVIDE ( r_lc_send_pdu_setup_cmp = 0x4001c808 ); +PROVIDE ( r_lc_send_pdu_slot_off = 0x4001c854 ); +PROVIDE ( r_lc_send_pdu_sniff_req = 0x4001c5f0 ); +PROVIDE ( r_lc_send_pdu_sp_cfm = 0x4001c518 ); +PROVIDE ( r_lc_send_pdu_sp_nb = 0x4001c4e8 ); +PROVIDE ( r_lc_send_pdu_sres = 0x4001c548 ); +PROVIDE ( r_lc_send_pdu_tim_acc = 0x4001c6cc ); +PROVIDE ( r_lc_send_pdu_unit_key = 0x4001c398 ); +PROVIDE ( r_lc_send_pdu_unsniff_req = 0x4001c894 ); +PROVIDE ( r_lc_send_pdu_vers_req = 0x4001c8b4 ); +PROVIDE ( r_lc_skip_hl_oob_req = 0x400201bc ); +PROVIDE ( r_lc_sniff_init = 0x40022cac ); +PROVIDE ( r_lc_sniff_max_slot_chg = 0x40020590 ); +PROVIDE ( r_lc_sniff_reset = 0x40022cc8 ); +PROVIDE ( r_lc_sniff_slot_unchange = 0x40021100 ); +PROVIDE ( r_lc_sniff_sub_mode = 0x400204fc ); +PROVIDE ( r_lc_sp_end = 0x400213a8 ); +PROVIDE ( r_lc_sp_fail = 0x40020470 ); +PROVIDE ( r_lc_sp_oob_tid_fail = 0x400204cc ); +PROVIDE ( r_lc_ssr_nego = 0x4002125c ); +PROVIDE ( r_lc_start = 0x4001ca28 ); +PROVIDE ( r_lc_start_enc = 0x4001fb28 ); +PROVIDE ( r_lc_start_enc_key_size = 0x4001fd9c ); +PROVIDE ( r_lc_start_key_exch = 0x4001fe10 ); +PROVIDE ( r_lc_start_lmp_to = 0x4001fae8 ); +PROVIDE ( r_lc_start_oob = 0x4001fffc ); +PROVIDE ( r_lc_start_passkey = 0x4001feac ); +PROVIDE ( r_lc_start_passkey_loop = 0x4001ff88 ); +PROVIDE ( r_lc_stop_afh_report = 0x40020184 ); +PROVIDE ( r_lc_stop_enc = 0x40020110 ); +PROVIDE ( r_lc_switch_cmp = 0x40020448 ); +PROVIDE ( r_lc_unit_key_svr = 0x400206d8 ); +PROVIDE ( r_lc_unsniff = 0x40020c50 ); +PROVIDE ( r_lc_unsniff_cmp = 0x40020810 ); +PROVIDE ( r_lc_unsniff_cont = 0x40020750 ); +PROVIDE ( r_lc_upd_to = 0x4002065c ); +PROVIDE ( r_lc_util_convert_pref_rate_to_packet_type = 0x4002f9b0 ); +PROVIDE ( r_lc_util_get_max_packet_size = 0x4002f4ac ); +PROVIDE ( r_lc_util_get_offset_clke = 0x4002f538 ); +PROVIDE ( r_lc_util_get_offset_clkn = 0x4002f51c ); +PROVIDE ( r_lc_util_set_loc_trans_coll = 0x4002f500 ); +PROVIDE ( r_lc_version = 0x40020a30 ); +PROVIDE ( r_ld_acl_active_hop_types_get = 0x40036e10 ); +PROVIDE ( r_ld_acl_afh_confirm = 0x40036d40 ); +PROVIDE ( r_ld_acl_afh_prepare = 0x40036c84 ); +PROVIDE ( r_ld_acl_afh_set = 0x40036b60 ); +PROVIDE ( r_ld_acl_allowed_tx_packet_types_set = 0x40036810 ); +PROVIDE ( r_ld_acl_bcst_rx_dec = 0x40036394 ); +PROVIDE ( r_ld_acl_bit_off_get = 0x40036b18 ); +PROVIDE ( r_ld_acl_clk_adj_set = 0x40036a00 ); +PROVIDE ( r_ld_acl_clk_off_get = 0x40036b00 ); +PROVIDE ( r_ld_acl_clk_set = 0x40036950 ); +PROVIDE ( r_ld_acl_clock_offset_get = 0x400364c0 ); +PROVIDE ( r_ld_acl_current_tx_power_get = 0x400368f0 ); +PROVIDE ( r_ld_acl_data_flush = 0x400357bc ); +PROVIDE ( r_ld_acl_data_tx = 0x4003544c ); +PROVIDE ( r_ld_acl_edr_set = 0x4003678c ); +PROVIDE ( r_ld_acl_enc_key_load = 0x40036404 ); +PROVIDE ( r_ld_acl_flow_off = 0x40035400 ); +PROVIDE ( r_ld_acl_flow_on = 0x4003541c ); +PROVIDE ( r_ld_acl_flush_timeout_get = 0x40035f9c ); +PROVIDE ( r_ld_acl_flush_timeout_set = 0x40035fe0 ); +PROVIDE ( r_ld_acl_init = 0x40034d08 ); +PROVIDE ( r_ld_acl_lmp_flush = 0x40035d80 ); +PROVIDE ( r_ld_acl_lmp_tx = 0x40035b34 ); +PROVIDE ( r_ld_acl_lsto_get = 0x400366b4 ); +PROVIDE ( r_ld_acl_lsto_set = 0x400366f8 ); +PROVIDE ( r_ld_acl_reset = 0x40034d24 ); +PROVIDE ( r_ld_acl_role_get = 0x40036b30 ); +PROVIDE ( r_ld_acl_rssi_delta_get = 0x40037028 ); +PROVIDE ( r_ld_acl_rsw_req = 0x40035e74 ); +PROVIDE ( r_ld_acl_rx_enc = 0x40036344 ); +PROVIDE ( r_ld_acl_rx_max_slot_get = 0x40036e58 ); +PROVIDE ( r_ld_acl_rx_max_slot_set = 0x40036ea0 ); +PROVIDE ( r_ld_acl_slot_offset_get = 0x4003653c ); +PROVIDE ( r_ld_acl_slot_offset_set = 0x40036658 ); +PROVIDE ( r_ld_acl_sniff = 0x4003617c ); +PROVIDE ( r_ld_acl_sniff_trans = 0x400360a8 ); +PROVIDE ( r_ld_acl_ssr_set = 0x40036274 ); +PROVIDE ( r_ld_acl_start = 0x40034ddc ); +PROVIDE ( r_ld_acl_stop = 0x4003532c ); +PROVIDE ( r_ld_acl_test_mode_set = 0x40036f24 ); +PROVIDE ( r_ld_acl_timing_accuracy_set = 0x4003673c ); +PROVIDE ( r_ld_acl_t_poll_get = 0x40036024 ); +PROVIDE ( r_ld_acl_t_poll_set = 0x40036068 ); +PROVIDE ( r_ld_acl_tx_enc = 0x400362f8 ); +PROVIDE ( r_ld_acl_unsniff = 0x400361e0 ); +PROVIDE ( r_ld_active_check = 0x4003cac4 ); +PROVIDE ( r_ld_afh_ch_assess_data_get = 0x4003caec ); +PROVIDE ( r_ld_bcst_acl_data_tx = 0x40038d3c ); +PROVIDE ( r_ld_bcst_acl_init = 0x40038bd0 ); +PROVIDE ( r_ld_bcst_acl_reset = 0x40038bdc ); +PROVIDE ( r_ld_bcst_acl_start = 0x4003882c ); +PROVIDE ( r_ld_bcst_afh_update = 0x40038f3c ); +PROVIDE ( r_ld_bcst_enc_key_load = 0x4003906c ); +PROVIDE ( r_ld_bcst_lmp_tx = 0x40038bf8 ); +PROVIDE ( r_ld_bcst_tx_enc = 0x40038ff8 ); +PROVIDE ( r_ld_bd_addr_get = 0x4003ca20 ); +PROVIDE ( r_ld_channel_assess = 0x4003c184 ); +PROVIDE ( r_ld_class_of_dev_get = 0x4003ca34 ); +PROVIDE ( r_ld_class_of_dev_set = 0x4003ca50 ); +PROVIDE ( r_ld_csb_rx_afh_update = 0x40039af4 ); +PROVIDE ( r_ld_csb_rx_init = 0x40039690 ); +PROVIDE ( r_ld_csb_rx_reset = 0x4003969c ); +PROVIDE ( r_ld_csb_rx_start = 0x4003972c ); +PROVIDE ( r_ld_csb_rx_stop = 0x40039bb8 ); +PROVIDE ( r_ld_csb_tx_afh_update = 0x4003a5fc ); +PROVIDE ( r_ld_csb_tx_clr_data = 0x4003a71c ); +PROVIDE ( r_ld_csb_tx_dis = 0x4003a5e8 ); +PROVIDE ( r_ld_csb_tx_en = 0x4003a1c0 ); +PROVIDE ( r_ld_csb_tx_init = 0x4003a0e8 ); +PROVIDE ( r_ld_csb_tx_reset = 0x4003a0f8 ); +PROVIDE ( r_ld_csb_tx_set_data = 0x4003a6c0 ); +PROVIDE ( r_ld_fm_clk_isr = 0x4003a7a8 ); +PROVIDE ( r_ld_fm_frame_isr = 0x4003a82c ); +PROVIDE ( r_ld_fm_init = 0x4003a760 ); +PROVIDE ( r_ld_fm_prog_check = 0x4003ab28 ); +PROVIDE ( r_ld_fm_prog_disable = 0x4003a984 ); +PROVIDE ( r_ld_fm_prog_enable = 0x4003a944 ); +PROVIDE ( r_ld_fm_prog_push = 0x4003a9d4 ); +PROVIDE ( r_ld_fm_reset = 0x4003a794 ); +PROVIDE ( r_ld_fm_rx_isr = 0x4003a7f4 ); +PROVIDE ( r_ld_fm_sket_isr = 0x4003a8a4 ); +PROVIDE ( r_ld_init = 0x4003c294 ); +PROVIDE ( r_ld_inq_init = 0x4003b15c ); +PROVIDE ( r_ld_inq_reset = 0x4003b168 ); +PROVIDE ( r_ld_inq_start = 0x4003b1f0 ); +PROVIDE ( r_ld_inq_stop = 0x4003b4f0 ); +PROVIDE ( r_ld_iscan_eir_get = 0x4003c118 ); +PROVIDE ( r_ld_iscan_eir_set = 0x4003bfa0 ); +PROVIDE ( r_ld_iscan_init = 0x4003b9f0 ); +PROVIDE ( r_ld_iscan_reset = 0x4003ba14 ); +PROVIDE ( r_ld_iscan_restart = 0x4003ba44 ); +PROVIDE ( r_ld_iscan_start = 0x4003bb28 ); +PROVIDE ( r_ld_iscan_stop = 0x4003bf1c ); +PROVIDE ( r_ld_iscan_tx_pwr_get = 0x4003c138 ); +PROVIDE ( r_ld_page_init = 0x4003d808 ); +PROVIDE ( r_ld_page_reset = 0x4003d814 ); +PROVIDE ( r_ld_page_start = 0x4003d848 ); +PROVIDE ( r_ld_page_stop = 0x4003da54 ); +PROVIDE ( r_ld_pca_coarse_clock_adjust = 0x4003e324 ); +PROVIDE ( r_ld_pca_init = 0x4003deb4 ); +PROVIDE ( r_ld_pca_initiate_clock_dragging = 0x4003e4ac ); +PROVIDE ( r_ld_pca_local_config = 0x4003df6c ); +PROVIDE ( r_ld_pca_mws_frame_sync = 0x4003e104 ); +PROVIDE ( r_ld_pca_mws_moment_offset_gt = 0x4003e278 ); +PROVIDE ( r_ld_pca_mws_moment_offset_lt = 0x4003e280 ); +PROVIDE ( r_ld_pca_reporting_enable = 0x4003e018 ); +PROVIDE ( r_ld_pca_reset = 0x4003df0c ); +PROVIDE ( r_ld_pca_update_target_offset = 0x4003e050 ); +PROVIDE ( r_ld_pscan_evt_handler = 0x4003f238 ); +PROVIDE ( r_ld_pscan_init = 0x4003f474 ); +PROVIDE ( r_ld_pscan_reset = 0x4003f498 ); +PROVIDE ( r_ld_pscan_restart = 0x4003f4b8 ); +PROVIDE ( r_ld_pscan_start = 0x4003f514 ); +PROVIDE ( r_ld_pscan_stop = 0x4003f618 ); +PROVIDE ( r_ld_read_clock = 0x4003c9e4 ); +PROVIDE ( r_ld_reset = 0x4003c714 ); +PROVIDE ( r_ld_sched_acl_add = 0x4003f978 ); +PROVIDE ( r_ld_sched_acl_remove = 0x4003f99c ); +PROVIDE ( r_ld_sched_compute = 0x4003f6f8 ); +PROVIDE ( r_ld_sched_init = 0x4003f7ac ); +PROVIDE ( r_ld_sched_inq_add = 0x4003f8a8 ); +PROVIDE ( r_ld_sched_inq_remove = 0x4003f8d0 ); +PROVIDE ( r_ld_sched_iscan_add = 0x4003f7e8 ); +PROVIDE ( r_ld_sched_iscan_remove = 0x4003f808 ); +PROVIDE ( r_ld_sched_page_add = 0x4003f910 ); +PROVIDE ( r_ld_sched_page_remove = 0x4003f938 ); +PROVIDE ( r_ld_sched_pscan_add = 0x4003f828 ); +PROVIDE ( r_ld_sched_pscan_remove = 0x4003f848 ); +PROVIDE ( r_ld_sched_reset = 0x4003f7d4 ); +PROVIDE ( r_ld_sched_sco_add = 0x4003fa4c ); +PROVIDE ( r_ld_sched_sco_remove = 0x4003fa9c ); +PROVIDE ( r_ld_sched_sniff_add = 0x4003f9c4 ); +PROVIDE ( r_ld_sched_sniff_remove = 0x4003fa0c ); +PROVIDE ( r_ld_sched_sscan_add = 0x4003f868 ); +PROVIDE ( r_ld_sched_sscan_remove = 0x4003f888 ); +PROVIDE ( r_ld_sco_audio_isr = 0x40037cc8 ); +PROVIDE ( r_ld_sco_data_tx = 0x40037ee8 ); +PROVIDE ( r_ld_sco_start = 0x40037110 ); +PROVIDE ( r_ld_sco_stop = 0x40037c40 ); +PROVIDE ( r_ld_sco_update = 0x40037a74 ); +PROVIDE ( r_ld_sscan_activated = 0x4004031c ); +PROVIDE ( r_ld_sscan_init = 0x400402f0 ); +PROVIDE ( r_ld_sscan_reset = 0x400402fc ); +PROVIDE ( r_ld_sscan_start = 0x40040384 ); +PROVIDE ( r_ld_strain_init = 0x400409f4 ); +PROVIDE ( r_ld_strain_reset = 0x40040a00 ); +PROVIDE ( r_ld_strain_start = 0x40040a8c ); +PROVIDE ( r_ld_strain_stop = 0x40040df0 ); +PROVIDE ( r_ld_timing_accuracy_get = 0x4003caac ); +PROVIDE ( r_ld_util_active_master_afh_map_get = 0x4004131c ); +PROVIDE ( r_ld_util_active_master_afh_map_set = 0x40041308 ); +PROVIDE ( r_ld_util_bch_create = 0x40040fcc ); +PROVIDE ( r_ld_util_fhs_pk = 0x400411c8 ); +PROVIDE ( r_ld_util_fhs_unpk = 0x40040e54 ); +PROVIDE ( r_ld_util_stp_pk = 0x400413f4 ); +PROVIDE ( r_ld_util_stp_unpk = 0x40041324 ); +PROVIDE ( r_ld_version_get = 0x4003ca6c ); +PROVIDE ( r_ld_wlcoex_set = 0x4003caf8 ); +PROVIDE ( r_llc_ch_assess_get_current_ch_map = 0x40041574 ); +PROVIDE ( r_llc_ch_assess_get_local_ch_map = 0x4004150c ); +PROVIDE ( r_llc_ch_assess_local = 0x40041494 ); +PROVIDE ( r_llc_ch_assess_merge_ch = 0x40041588 ); +PROVIDE ( r_llc_ch_assess_reass_ch = 0x400415c0 ); +PROVIDE ( r_llc_common_cmd_complete_send = 0x40044eac ); +PROVIDE ( r_llc_common_cmd_status_send = 0x40044ee0 ); +PROVIDE ( r_llc_common_enc_change_evt_send = 0x40044f6c ); +PROVIDE ( r_llc_common_enc_key_ref_comp_evt_send = 0x40044f38 ); +PROVIDE ( r_llc_common_flush_occurred_send = 0x40044f0c ); +PROVIDE ( r_llc_common_nb_of_pkt_comp_evt_send = 0x40045000 ); +PROVIDE ( r_llc_con_update_complete_send = 0x40044d68 ); +PROVIDE ( r_llc_con_update_finished = 0x4004518c ); +PROVIDE ( r_llc_con_update_ind = 0x40045038 ); +PROVIDE ( r_llc_discon_event_complete_send = 0x40044a30 ); +PROVIDE ( r_llc_end_evt_defer = 0x40046330 ); +PROVIDE ( r_llc_feats_rd_event_send = 0x40044e0c ); +PROVIDE ( r_llc_init = 0x40044778 ); +PROVIDE ( r_llc_le_con_cmp_evt_send = 0x40044a78 ); +PROVIDE ( r_llc_llcp_ch_map_update_pdu_send = 0x40043f94 ); +PROVIDE ( r_llc_llcp_con_param_req_pdu_send = 0x400442fc ); +PROVIDE ( r_llc_llcp_con_param_rsp_pdu_send = 0x40044358 ); +PROVIDE ( r_llc_llcp_con_update_pdu_send = 0x400442c4 ); +PROVIDE ( r_llc_llcp_enc_req_pdu_send = 0x40044064 ); +PROVIDE ( r_llc_llcp_enc_rsp_pdu_send = 0x40044160 ); +PROVIDE ( r_llc_llcp_feats_req_pdu_send = 0x400443b4 ); +PROVIDE ( r_llc_llcp_feats_rsp_pdu_send = 0x400443f0 ); +PROVIDE ( r_llc_llcp_get_autorize = 0x4004475c ); +PROVIDE ( r_llc_llcp_length_req_pdu_send = 0x40044574 ); +PROVIDE ( r_llc_llcp_length_rsp_pdu_send = 0x400445ac ); +PROVIDE ( r_llc_llcp_pause_enc_req_pdu_send = 0x40043fd8 ); +PROVIDE ( r_llc_llcp_pause_enc_rsp_pdu_send = 0x40044010 ); +PROVIDE ( r_llc_llcp_ping_req_pdu_send = 0x4004454c ); +PROVIDE ( r_llc_llcp_ping_rsp_pdu_send = 0x40044560 ); +PROVIDE ( r_llc_llcp_recv_handler = 0x40044678 ); +PROVIDE ( r_llc_llcp_reject_ind_pdu_send = 0x4004425c ); +PROVIDE ( r_llc_llcp_start_enc_req_pdu_send = 0x4004441c ); +PROVIDE ( r_llc_llcp_start_enc_rsp_pdu_send = 0x400441f8 ); +PROVIDE ( r_llc_llcp_terminate_ind_pdu_send = 0x400444b0 ); +PROVIDE ( r_llc_llcp_tester_send = 0x400445e4 ); +PROVIDE ( r_llc_llcp_unknown_rsp_send_pdu = 0x40044534 ); +PROVIDE ( r_llc_llcp_version_ind_pdu_send = 0x40043f6c ); +PROVIDE ( r_llc_lsto_con_update = 0x40045098 ); +PROVIDE ( r_llc_ltk_req_send = 0x40044dc0 ); +PROVIDE ( r_llc_map_update_finished = 0x40045260 ); +PROVIDE ( r_llc_map_update_ind = 0x400450f0 ); +PROVIDE ( r_llc_pdu_acl_tx_ack_defer = 0x400464dc ); +PROVIDE ( r_llc_pdu_defer = 0x40046528 ); +PROVIDE ( r_llc_pdu_llcp_tx_ack_defer = 0x400463ac ); +PROVIDE ( r_llc_reset = 0x400447b8 ); +PROVIDE ( r_llc_start = 0x400447f4 ); +PROVIDE ( r_llc_stop = 0x400449ac ); +PROVIDE ( r_llc_util_bw_mgt = 0x4004629c ); +PROVIDE ( r_llc_util_clear_operation_ptr = 0x40046234 ); +PROVIDE ( r_llc_util_dicon_procedure = 0x40046130 ); +PROVIDE ( r_llc_util_get_free_conhdl = 0x400460c8 ); +PROVIDE ( r_llc_util_get_nb_active_link = 0x40046100 ); +PROVIDE ( r_llc_util_set_auth_payl_to_margin = 0x400461f4 ); +PROVIDE ( r_llc_util_set_llcp_discard_enable = 0x400461c8 ); +PROVIDE ( r_llc_util_update_channel_map = 0x400461ac ); +PROVIDE ( r_llc_version_rd_event_send = 0x40044e60 ); +PROVIDE ( r_lld_adv_start = 0x40048b38 ); +PROVIDE ( r_lld_adv_stop = 0x40048ea0 ); +PROVIDE ( r_lld_ch_map_ind = 0x4004a2f4 ); +PROVIDE ( r_lld_con_param_req = 0x40049f0c ); +PROVIDE ( r_lld_con_param_rsp = 0x40049e00 ); +PROVIDE ( r_lld_con_start = 0x400491f8 ); +PROVIDE ( r_lld_con_stop = 0x40049fdc ); +PROVIDE ( r_lld_con_update_after_param_req = 0x40049bcc ); +PROVIDE ( r_lld_con_update_ind = 0x4004a30c ); +PROVIDE ( r_lld_con_update_req = 0x40049b60 ); +PROVIDE ( r_lld_core_reset = 0x40048a9c ); +PROVIDE ( r_lld_crypt_isr = 0x4004a324 ); +PROVIDE ( r_lld_evt_adv_create = 0x400481f4 ); +PROVIDE ( r_lld_evt_canceled = 0x400485c8 ); +PROVIDE ( r_lld_evt_channel_next = 0x40046aac ); +PROVIDE ( r_lld_evt_deffered_elt_handler = 0x400482bc ); +PROVIDE ( r_lld_evt_delete_elt_handler = 0x40046974 ); +PROVIDE ( r_lld_evt_delete_elt_push = 0x40046a3c ); +PROVIDE ( r_lld_evt_drift_compute = 0x40047670 ); +PROVIDE ( r_lld_evt_elt_delete = 0x40047538 ); +PROVIDE ( r_lld_evt_elt_insert = 0x400474c8 ); +PROVIDE ( r_lld_evt_end = 0x400483e8 ); +PROVIDE ( r_lld_evt_end_isr = 0x4004862c ); +PROVIDE ( r_lld_evt_init = 0x40046b3c ); +PROVIDE ( r_lld_evt_init_evt = 0x40046cd0 ); +PROVIDE ( r_lld_evt_move_to_master = 0x40047ba0 ); +PROVIDE ( r_lld_evt_move_to_slave = 0x40047e18 ); +PROVIDE ( r_lld_evt_prevent_stop = 0x40047adc ); +PROVIDE ( r_lld_evt_restart = 0x40046d50 ); +PROVIDE ( r_lld_evt_rx = 0x40048578 ); +PROVIDE ( r_lld_evt_rx_isr = 0x40048678 ); +PROVIDE ( r_lld_evt_scan_create = 0x40047ae8 ); +PROVIDE ( r_lld_evt_schedule = 0x40047908 ); +PROVIDE ( r_lld_evt_schedule_next = 0x400477dc ); +PROVIDE ( r_lld_evt_schedule_next_instant = 0x400476a8 ); +PROVIDE ( r_lld_evt_slave_update = 0x40048138 ); +PROVIDE ( r_lld_evt_update_create = 0x40047cd8 ); +PROVIDE ( r_lld_get_mode = 0x40049ff8 ); +PROVIDE ( r_lld_init = 0x4004873c ); +PROVIDE ( r_lld_move_to_master = 0x400499e0 ); +PROVIDE ( r_lld_move_to_slave = 0x4004a024 ); +PROVIDE ( r_lld_pdu_adv_pack = 0x4004b488 ); +PROVIDE ( r_lld_pdu_check = 0x4004ac34 ); +PROVIDE ( r_lld_pdu_data_send = 0x4004b018 ); +PROVIDE ( r_lld_pdu_data_tx_push = 0x4004aecc ); +PROVIDE ( r_lld_pdu_rx_handler = 0x4004b4d4 ); +PROVIDE ( r_lld_pdu_send_packet = 0x4004b774 ); +PROVIDE ( r_lld_pdu_tx_flush = 0x4004b414 ); +PROVIDE ( r_lld_pdu_tx_loop = 0x4004ae40 ); +PROVIDE ( r_lld_pdu_tx_prog = 0x4004b120 ); +PROVIDE ( r_lld_pdu_tx_push = 0x4004b080 ); +PROVIDE ( r_lld_ral_renew_req = 0x4004a73c ); +PROVIDE ( r_lld_scan_start = 0x40048ee0 ); +PROVIDE ( r_lld_scan_stop = 0x40049190 ); +PROVIDE ( r_lld_test_mode_rx = 0x4004a540 ); +PROVIDE ( r_lld_test_mode_tx = 0x4004a350 ); +PROVIDE ( r_lld_test_stop = 0x4004a710 ); +PROVIDE ( r_lld_util_anchor_point_move = 0x4004bacc ); +PROVIDE ( r_lld_util_compute_ce_max = 0x4004bc0c ); +PROVIDE ( r_lld_util_connection_param_set = 0x4004ba40 ); +PROVIDE ( r_lld_util_dle_set_cs_fields = 0x4004ba90 ); +PROVIDE ( r_lld_util_eff_tx_time_set = 0x4004bd88 ); +PROVIDE ( r_lld_util_elt_programmed = 0x4004bce0 ); +PROVIDE ( r_lld_util_flush_list = 0x4004bbd8 ); +PROVIDE ( r_lld_util_freq2chnl = 0x4004b9e4 ); +PROVIDE ( r_lld_util_get_bd_address = 0x4004b8ac ); +PROVIDE ( r_lld_util_get_local_offset = 0x4004ba10 ); +PROVIDE ( r_lld_util_get_peer_offset = 0x4004ba24 ); +PROVIDE ( r_lld_util_get_tx_pkt_cnt = 0x4004bd80 ); +PROVIDE ( r_lld_util_instant_get = 0x4004b890 ); +PROVIDE ( r_lld_util_instant_ongoing = 0x4004bbfc ); +PROVIDE ( r_lld_util_priority_set = 0x4004bd10 ); +PROVIDE ( r_lld_util_priority_update = 0x4004bd78 ); +PROVIDE ( r_lld_util_ral_force_rpa_renew = 0x4004b980 ); +PROVIDE ( r_lld_util_set_bd_address = 0x4004b8f8 ); +PROVIDE ( r_lld_wlcoex_set = 0x4004bd98 ); +PROVIDE ( r_llm_ble_ready = 0x4004cc34 ); +PROVIDE ( r_llm_common_cmd_complete_send = 0x4004d288 ); +PROVIDE ( r_llm_common_cmd_status_send = 0x4004d2b4 ); +PROVIDE ( r_llm_con_req_ind = 0x4004cc54 ); +PROVIDE ( r_llm_con_req_tx_cfm = 0x4004d158 ); +PROVIDE ( r_llm_create_con = 0x4004de78 ); +PROVIDE ( r_llm_encryption_done = 0x4004dff8 ); +PROVIDE ( r_llm_encryption_start = 0x4004e128 ); +PROVIDE ( r_llm_end_evt_defer = 0x4004eb6c ); +PROVIDE ( r_llm_init = 0x4004c9f8 ); +PROVIDE ( r_llm_le_adv_report_ind = 0x4004cdf4 ); +PROVIDE ( r_llm_pdu_defer = 0x4004ec48 ); +PROVIDE ( r_llm_ral_clear = 0x4004e1fc ); +PROVIDE ( r_llm_ral_dev_add = 0x4004e23c ); +PROVIDE ( r_llm_ral_dev_rm = 0x4004e3bc ); +PROVIDE ( r_llm_ral_get_rpa = 0x4004e400 ); +PROVIDE ( r_llm_ral_set_timeout = 0x4004e4a0 ); +PROVIDE ( r_llm_ral_update = 0x4004e4f8 ); +PROVIDE ( r_llm_set_adv_data = 0x4004d960 ); +PROVIDE ( r_llm_set_adv_en = 0x4004d7ec ); +PROVIDE ( r_llm_set_adv_param = 0x4004d5f4 ); +PROVIDE ( r_llm_set_scan_en = 0x4004db64 ); +PROVIDE ( r_llm_set_scan_param = 0x4004dac8 ); +PROVIDE ( r_llm_set_scan_rsp_data = 0x4004da14 ); +PROVIDE ( r_llm_test_mode_start_rx = 0x4004d534 ); +PROVIDE ( r_llm_test_mode_start_tx = 0x4004d2fc ); +PROVIDE ( r_llm_util_adv_data_update = 0x4004e8fc ); +PROVIDE ( r_llm_util_apply_bd_addr = 0x4004e868 ); +PROVIDE ( r_llm_util_bd_addr_in_ral = 0x4004eb08 ); +PROVIDE ( r_llm_util_bd_addr_in_wl = 0x4004e788 ); +PROVIDE ( r_llm_util_bd_addr_wl_position = 0x4004e720 ); +PROVIDE ( r_llm_util_bl_add = 0x4004e9ac ); +PROVIDE ( r_llm_util_bl_check = 0x4004e930 ); +PROVIDE ( r_llm_util_bl_rem = 0x4004ea70 ); +PROVIDE ( r_llm_util_check_address_validity = 0x4004e7e4 ); +PROVIDE ( r_llm_util_check_evt_mask = 0x4004e8b0 ); +PROVIDE ( r_llm_util_check_map_validity = 0x4004e800 ); +PROVIDE ( r_llm_util_get_channel_map = 0x4004e8d4 ); +PROVIDE ( r_llm_util_get_supp_features = 0x4004e8e8 ); +PROVIDE ( r_llm_util_set_public_addr = 0x4004e89c ); +PROVIDE ( r_llm_wl_clr = 0x4004dc54 ); +PROVIDE ( r_llm_wl_dev_add = 0x4004dcc0 ); +PROVIDE ( r_llm_wl_dev_add_hdl = 0x4004dd38 ); +PROVIDE ( r_llm_wl_dev_rem = 0x4004dcfc ); +PROVIDE ( r_llm_wl_dev_rem_hdl = 0x4004dde0 ); +PROVIDE ( r_lm_acl_disc = 0x4004f148 ); +PROVIDE ( r_LM_AddSniff = 0x40022d20 ); +PROVIDE ( r_lm_add_sync = 0x40051358 ); +PROVIDE ( r_lm_afh_activate_timer = 0x4004f444 ); +PROVIDE ( r_lm_afh_ch_ass_en_get = 0x4004f3f8 ); +PROVIDE ( r_lm_afh_host_ch_class_get = 0x4004f410 ); +PROVIDE ( r_lm_afh_master_ch_map_get = 0x4004f43c ); +PROVIDE ( r_lm_afh_peer_ch_class_set = 0x4004f418 ); +PROVIDE ( r_lm_check_active_sync = 0x40051334 ); +PROVIDE ( r_LM_CheckEdrFeatureRequest = 0x4002f90c ); +PROVIDE ( r_LM_CheckSwitchInstant = 0x4002f8c0 ); +PROVIDE ( r_lm_check_sync_hl_rsp = 0x4005169c ); +PROVIDE ( r_lm_clk_adj_ack_pending_clear = 0x4004f514 ); +PROVIDE ( r_lm_clk_adj_instant_pending_set = 0x4004f4d8 ); +PROVIDE ( r_LM_ComputePacketType = 0x4002f554 ); +PROVIDE ( r_LM_ComputeSniffSubRate = 0x400233ac ); +PROVIDE ( r_lm_debug_key_compare_192 = 0x4004f3a8 ); +PROVIDE ( r_lm_debug_key_compare_256 = 0x4004f3d0 ); +PROVIDE ( r_lm_dhkey_calc_init = 0x40013234 ); +PROVIDE ( r_lm_dhkey_compare = 0x400132d8 ); +PROVIDE ( r_lm_dut_mode_en_get = 0x4004f3ec ); +PROVIDE ( r_LM_ExtractMaxEncKeySize = 0x4001aca4 ); +PROVIDE ( r_lm_f1 = 0x40012bb8 ); +PROVIDE ( r_lm_f2 = 0x40012cfc ); +PROVIDE ( r_lm_f3 = 0x40013050 ); +PROVIDE ( r_lm_g = 0x40012f90 ); +PROVIDE ( r_LM_GetAFHSwitchInstant = 0x4002f86c ); +PROVIDE ( r_lm_get_auth_en = 0x4004f1ac ); +PROVIDE ( r_lm_get_common_pkt_types = 0x4002fa1c ); +PROVIDE ( r_LM_GetConnectionAcceptTimeout = 0x4004f1f4 ); +PROVIDE ( r_LM_GetFeature = 0x4002f924 ); +PROVIDE ( r_LM_GetLinkTimeout = 0x400233ec ); +PROVIDE ( r_LM_GetLocalNameSeg = 0x4004f200 ); +PROVIDE ( r_lm_get_loopback_mode = 0x4004f248 ); +PROVIDE ( r_LM_GetMasterEncKeySize = 0x4001b29c ); +PROVIDE ( r_LM_GetMasterEncRand = 0x4001b288 ); +PROVIDE ( r_LM_GetMasterKey = 0x4001b260 ); +PROVIDE ( r_LM_GetMasterKeyRand = 0x4001b274 ); +PROVIDE ( r_lm_get_min_sync_intv = 0x400517a8 ); +PROVIDE ( r_lm_get_nb_acl = 0x4004ef9c ); +PROVIDE ( r_lm_get_nb_sync_link = 0x4005179c ); +PROVIDE ( r_lm_get_nonce = 0x400131c4 ); +PROVIDE ( r_lm_get_oob_local_commit = 0x4004f374 ); +PROVIDE ( r_lm_get_oob_local_data_192 = 0x4004f2d4 ); +PROVIDE ( r_lm_get_oob_local_data_256 = 0x4004f318 ); +PROVIDE ( r_LM_GetPINType = 0x4004f1e8 ); +PROVIDE ( r_lm_get_priv_key_192 = 0x4004f278 ); +PROVIDE ( r_lm_get_priv_key_256 = 0x4004f2b8 ); +PROVIDE ( r_lm_get_pub_key_192 = 0x4004f258 ); +PROVIDE ( r_lm_get_pub_key_256 = 0x4004f298 ); +PROVIDE ( r_LM_GetQoSParam = 0x4002f6e0 ); +PROVIDE ( r_lm_get_sec_con_host_supp = 0x4004f1d4 ); +PROVIDE ( r_LM_GetSniffSubratingParam = 0x4002325c ); +PROVIDE ( r_lm_get_sp_en = 0x4004f1c0 ); +PROVIDE ( r_LM_GetSwitchInstant = 0x4002f7f8 ); +PROVIDE ( r_lm_get_synchdl = 0x4005175c ); +PROVIDE ( r_lm_get_sync_param = 0x400503b4 ); +PROVIDE ( r_lm_init = 0x4004ed34 ); +PROVIDE ( r_lm_init_sync = 0x400512d8 ); +PROVIDE ( r_lm_is_acl_con = 0x4004f47c ); +PROVIDE ( r_lm_is_acl_con_role = 0x4004f49c ); +PROVIDE ( r_lm_is_clk_adj_ack_pending = 0x4004f4e8 ); +PROVIDE ( r_lm_is_clk_adj_instant_pending = 0x4004f4c8 ); +PROVIDE ( r_lm_local_ext_fr_configured = 0x4004f540 ); +PROVIDE ( r_lm_look_for_stored_link_key = 0x4002f948 ); +PROVIDE ( r_lm_look_for_sync = 0x40051774 ); +PROVIDE ( r_lm_lt_addr_alloc = 0x4004ef1c ); +PROVIDE ( r_lm_lt_addr_free = 0x4004ef74 ); +PROVIDE ( r_lm_lt_addr_reserve = 0x4004ef48 ); +PROVIDE ( r_LM_MakeCof = 0x4002f84c ); +PROVIDE ( r_LM_MakeRandVec = 0x400112d8 ); +PROVIDE ( r_lm_master_clk_adj_req_handler = 0x40054180 ); +PROVIDE ( r_LM_MaxSlot = 0x4002f694 ); +PROVIDE ( r_lm_modif_sync = 0x40051578 ); +PROVIDE ( r_lm_n_is_zero = 0x40012170 ); +PROVIDE ( r_lm_num_clk_adj_ack_pending_set = 0x4004f500 ); +PROVIDE ( r_lm_oob_f1 = 0x40012e54 ); +PROVIDE ( r_lm_pca_sscan_link_get = 0x4004f560 ); +PROVIDE ( r_lm_pca_sscan_link_set = 0x4004f550 ); +PROVIDE ( r_lmp_pack = 0x4001135c ); +PROVIDE ( r_lmp_unpack = 0x4001149c ); +PROVIDE ( r_lm_read_features = 0x4004f0d8 ); +PROVIDE ( r_LM_RemoveSniff = 0x40023124 ); +PROVIDE ( r_LM_RemoveSniffSubrating = 0x400233c4 ); +PROVIDE ( r_lm_remove_sync = 0x400517c8 ); +PROVIDE ( r_lm_reset_sync = 0x40051304 ); +PROVIDE ( r_lm_role_switch_finished = 0x4004f028 ); +PROVIDE ( r_lm_role_switch_start = 0x4004efe0 ); +PROVIDE ( r_lm_sco_nego_end = 0x40051828 ); +PROVIDE ( r_LM_SniffSubrateNegoRequired = 0x40023334 ); +PROVIDE ( r_LM_SniffSubratingHlReq = 0x40023154 ); +PROVIDE ( r_LM_SniffSubratingPeerReq = 0x400231dc ); +PROVIDE ( r_lm_sp_debug_mode_get = 0x4004f398 ); +PROVIDE ( r_lm_sp_n192_convert_wnaf = 0x400123c0 ); +PROVIDE ( r_lm_sp_n_one = 0x400123a4 ); +PROVIDE ( r_lm_sp_p192_add = 0x40012828 ); +PROVIDE ( r_lm_sp_p192_dbl = 0x4001268c ); +PROVIDE ( r_lm_sp_p192_invert = 0x40012b6c ); +PROVIDE ( r_lm_sp_p192_point_jacobian_to_affine = 0x40012468 ); +PROVIDE ( r_lm_sp_p192_points_jacobian_to_affine = 0x400124e4 ); +PROVIDE ( r_lm_sp_p192_point_to_inf = 0x40012458 ); +PROVIDE ( r_lm_sp_pre_compute_points = 0x40012640 ); +PROVIDE ( r_lm_sp_sha256_calculate = 0x400121a0 ); +PROVIDE ( r_LM_SuppressAclPacket = 0x4002f658 ); +PROVIDE ( r_lm_sync_flow_ctrl_en_get = 0x4004f404 ); +PROVIDE ( r_LM_UpdateAclEdrPacketType = 0x4002f5d8 ); +PROVIDE ( r_LM_UpdateAclPacketType = 0x4002f584 ); +PROVIDE ( r_modules_funcs = 0x3ffafd6c ); +PROVIDE ( r_modules_funcs_p = 0x3ffafd68 ); +PROVIDE ( r_nvds_del = 0x400544c4 ); +PROVIDE ( r_nvds_get = 0x40054488 ); +PROVIDE ( r_nvds_init = 0x40054410 ); +PROVIDE ( r_nvds_lock = 0x400544fc ); +PROVIDE ( r_nvds_put = 0x40054534 ); +PROVIDE ( rom_abs_temp = 0x400054f0 ); +PROVIDE ( rom_bb_bss_bw_40_en = 0x4000401c ); +PROVIDE ( rom_bb_bss_cbw40_dig = 0x40003bac ); +PROVIDE ( rom_bb_rx_ht20_cen_bcov_en = 0x40003734 ); +PROVIDE ( rom_bb_tx_ht20_cen = 0x40003760 ); +PROVIDE ( rom_bb_wdg_test_en = 0x40003b70 ); +PROVIDE ( rom_cbw2040_cfg = 0x400040b0 ); +PROVIDE ( rom_check_noise_floor = 0x40003c78 ); +PROVIDE ( rom_chip_i2c_readReg = 0x40004110 ); +PROVIDE ( rom_chip_i2c_writeReg = 0x40004168 ); +PROVIDE ( rom_chip_v7_bt_init = 0x40004d8c ); +PROVIDE ( rom_chip_v7_rx_init = 0x40004cec ); +PROVIDE ( rom_chip_v7_rx_rifs_en = 0x40003d90 ); +PROVIDE ( rom_chip_v7_tx_init = 0x40004d18 ); +PROVIDE ( rom_clk_force_on_vit = 0x40003710 ); +PROVIDE ( rom_correct_rf_ana_gain = 0x400062a8 ); +PROVIDE ( rom_dc_iq_est = 0x400055c8 ); +PROVIDE ( rom_disable_agc = 0x40002fa4 ); +PROVIDE ( rom_enable_agc = 0x40002fcc ); +PROVIDE ( rom_en_pwdet = 0x4000506c ); +PROVIDE ( rom_gen_rx_gain_table = 0x40003e3c ); +PROVIDE ( rom_get_data_sat = 0x4000312c ); +PROVIDE ( rom_get_fm_sar_dout = 0x40005204 ); +PROVIDE ( rom_get_power_db = 0x40005fc8 ); +PROVIDE ( rom_get_pwctrl_correct = 0x400065d4 ); +PROVIDE ( rom_get_rfcal_rxiq_data = 0x40005bbc ); +PROVIDE ( rom_get_rf_gain_qdb = 0x40006290 ); +PROVIDE ( rom_get_sar_dout = 0x40006564 ); +PROVIDE ( rom_i2c_readReg = 0x40004148 ); +PROVIDE ( rom_i2c_readReg_Mask = 0x400041c0 ); +PROVIDE ( rom_i2c_writeReg = 0x400041a4 ); +PROVIDE ( rom_i2c_writeReg_Mask = 0x400041fc ); +PROVIDE ( rom_index_to_txbbgain = 0x40004df8 ); +PROVIDE ( rom_iq_est_disable = 0x40005590 ); +PROVIDE ( rom_iq_est_enable = 0x40005514 ); +PROVIDE ( rom_linear_to_db = 0x40005f64 ); +PROVIDE ( rom_loopback_mode_en = 0x400030f8 ); +PROVIDE ( rom_meas_tone_pwr_db = 0x40006004 ); +PROVIDE ( rom_mhz2ieee = 0x4000404c ); +PROVIDE ( rom_noise_floor_auto_set = 0x40003bdc ); +PROVIDE ( rom_pbus_debugmode = 0x40004458 ); +PROVIDE ( rom_pbus_force_mode = 0x40004270 ); +PROVIDE ( rom_pbus_force_test = 0x400043c0 ); +PROVIDE ( rom_pbus_rd = 0x40004414 ); +PROVIDE ( rom_pbus_rd_addr = 0x40004334 ); +PROVIDE ( rom_pbus_rd_shift = 0x40004374 ); +PROVIDE ( rom_pbus_rx_dco_cal = 0x40005620 ); +PROVIDE ( rom_pbus_set_dco = 0x40004638 ); +PROVIDE ( rom_pbus_set_rxgain = 0x40004480 ); +PROVIDE ( rom_pbus_workmode = 0x4000446c ); +PROVIDE ( rom_pbus_xpd_rx_off = 0x40004508 ); +PROVIDE ( rom_pbus_xpd_rx_on = 0x4000453c ); +PROVIDE ( rom_pbus_xpd_tx_off = 0x40004590 ); +PROVIDE ( rom_pbus_xpd_tx_on = 0x400045e0 ); +PROVIDE ( rom_phy_disable_agc = 0x40002f6c ); +PROVIDE ( rom_phy_disable_cca = 0x40003000 ); +PROVIDE ( rom_phy_enable_agc = 0x40002f88 ); +PROVIDE ( rom_phy_enable_cca = 0x4000302c ); +PROVIDE ( rom_phy_freq_correct = 0x40004b44 ); +PROVIDE ( rom_phyFuns = 0x3ffae0c0 ); +PROVIDE ( rom_phy_get_noisefloor = 0x40003c2c ); +PROVIDE ( rom_phy_get_vdd33 = 0x4000642c ); +PROVIDE ( rom_pow_usr = 0x40003044 ); +PROVIDE ( rom_read_sar_dout = 0x400051c0 ); +PROVIDE ( rom_restart_cal = 0x400046e0 ); +PROVIDE ( rom_rfcal_pwrctrl = 0x40006058 ); +PROVIDE ( rom_rfcal_rxiq = 0x40005b4c ); +PROVIDE ( rom_rfcal_txcap = 0x40005dec ); +PROVIDE ( rom_rfpll_reset = 0x40004680 ); +PROVIDE ( rom_rfpll_set_freq = 0x400047f8 ); +PROVIDE ( rom_rtc_mem_backup = 0x40003db4 ); +PROVIDE ( rom_rtc_mem_recovery = 0x40003df4 ); +PROVIDE ( rom_rx_gain_force = 0x4000351c ); +PROVIDE ( rom_rxiq_cover_mg_mp = 0x40005a68 ); +PROVIDE ( rom_rxiq_get_mis = 0x400058e4 ); +PROVIDE ( rom_rxiq_set_reg = 0x40005a00 ); +PROVIDE ( rom_set_cal_rxdc = 0x400030b8 ); +PROVIDE ( rom_set_chan_cal_interp = 0x40005ce0 ); +PROVIDE ( rom_set_channel_freq = 0x40004880 ); +PROVIDE ( rom_set_loopback_gain = 0x40003060 ); +PROVIDE ( rom_set_noise_floor = 0x40003d48 ); +PROVIDE ( rom_set_pbus_mem = 0x400031a4 ); +PROVIDE ( rom_set_rf_freq_offset = 0x40004ca8 ); +PROVIDE ( rom_set_rxclk_en = 0x40003594 ); +PROVIDE ( rom_set_txcap_reg = 0x40005d50 ); +PROVIDE ( rom_set_txclk_en = 0x40003564 ); +PROVIDE ( rom_spur_coef_cfg = 0x40003ac8 ); +PROVIDE ( rom_spur_reg_write_one_tone = 0x400037f0 ); +PROVIDE ( rom_start_tx_tone = 0x400036b4 ); +PROVIDE ( rom_start_tx_tone_step = 0x400035d0 ); +PROVIDE ( rom_stop_tx_tone = 0x40003f98 ); +PROVIDE ( _rom_store = 0x4000d66c ); +PROVIDE ( _rom_store_table = 0x4000d4f8 ); +PROVIDE ( rom_target_power_add_backoff = 0x40006268 ); +PROVIDE ( rom_tx_atten_set_interp = 0x400061cc ); +PROVIDE ( rom_txbbgain_to_index = 0x40004dc0 ); +PROVIDE ( rom_txcal_work_mode = 0x4000510c ); +PROVIDE ( rom_txdc_cal_init = 0x40004e10 ); +PROVIDE ( rom_txdc_cal_v70 = 0x40004ea4 ); +PROVIDE ( rom_txiq_cover = 0x4000538c ); +PROVIDE ( rom_txiq_get_mis_pwr = 0x400052dc ); +PROVIDE ( rom_txiq_set_reg = 0x40005154 ); +PROVIDE ( rom_tx_pwctrl_bg_init = 0x4000662c ); +PROVIDE ( rom_txtone_linear_pwr = 0x40005290 ); +PROVIDE ( rom_wait_rfpll_cal_end = 0x400047a8 ); +PROVIDE ( rom_write_gain_mem = 0x4000348c ); +PROVIDE ( rom_write_rfpll_sdm = 0x40004740 ); +PROVIDE ( roundup2 = 0x4000ab7c ); +PROVIDE ( r_plf_funcs_p = 0x3ffb8360 ); +PROVIDE ( r_rf_rw_bt_init = 0x40054868 ); +PROVIDE ( r_rf_rw_init = 0x40054b0c ); +PROVIDE ( r_rf_rw_le_init = 0x400549d0 ); +PROVIDE ( r_rwble_activity_ongoing_check = 0x40054d8c ); +PROVIDE ( r_rwble_init = 0x40054bf4 ); +PROVIDE ( r_rwble_isr = 0x40054e08 ); +PROVIDE ( r_rwble_reset = 0x40054ce8 ); +PROVIDE ( r_rwble_sleep_check = 0x40054d78 ); +PROVIDE ( r_rwble_version = 0x40054dac ); +PROVIDE ( r_rwbt_init = 0x40055160 ); +PROVIDE ( r_rwbt_isr = 0x40055248 ); +PROVIDE ( r_rwbt_reset = 0x400551bc ); +PROVIDE ( r_rwbt_sleep_check = 0x4005577c ); +PROVIDE ( r_rwbt_sleep_enter = 0x400557a4 ); +PROVIDE ( r_rwbt_sleep_wakeup = 0x400557fc ); +PROVIDE ( r_rwbt_sleep_wakeup_end = 0x400558cc ); +PROVIDE ( r_rwbt_version = 0x4005520c ); +PROVIDE ( r_rwip_assert_err = 0x40055f88 ); +PROVIDE ( r_rwip_check_wakeup_boundary = 0x400558fc ); +PROVIDE ( r_rwip_ext_wakeup_enable = 0x40055f3c ); +PROVIDE ( r_rwip_init = 0x4005595c ); +PROVIDE ( r_rwip_pca_clock_dragging_only = 0x40055f48 ); +PROVIDE ( r_rwip_prevent_sleep_clear = 0x40055ec8 ); +PROVIDE ( r_rwip_prevent_sleep_set = 0x40055e64 ); +PROVIDE ( r_rwip_reset = 0x40055ab8 ); +PROVIDE ( r_rwip_schedule = 0x40055b38 ); +PROVIDE ( r_rwip_sleep = 0x40055b5c ); +PROVIDE ( r_rwip_sleep_enable = 0x40055f30 ); +PROVIDE ( r_rwip_version = 0x40055b20 ); +PROVIDE ( r_rwip_wakeup = 0x40055dc4 ); +PROVIDE ( r_rwip_wakeup_delay_set = 0x40055e4c ); +PROVIDE ( r_rwip_wakeup_end = 0x40055e18 ); +PROVIDE ( r_rwip_wlcoex_set = 0x40055f60 ); +PROVIDE ( r_SHA_256 = 0x40013a90 ); +PROVIDE ( rtc_boot_control = 0x4000821c ); +PROVIDE ( rtc_get_reset_reason = 0x400081d4 ); +PROVIDE ( rtc_get_wakeup_cause = 0x400081f4 ); +PROVIDE ( rtc_select_apb_bridge = 0x40008288 ); +PROVIDE ( rwip_coex_cfg = 0x3ff9914c ); +PROVIDE ( rwip_priority = 0x3ff99159 ); +PROVIDE ( rwip_rf = 0x3ffbdb28 ); +PROVIDE ( rwip_rf_p_get = 0x400558f4 ); +PROVIDE ( r_XorKey = 0x400112c0 ); +PROVIDE ( sbrk = 0x400017f4 ); +PROVIDE ( _sbrk_r = 0x4000bce4 ); +PROVIDE ( scanf = 0x40058760 ); +PROVIDE ( _scanf_chars = 0x40058384 ); +PROVIDE ( _scanf_float = 0x4000bf18 ); +PROVIDE ( _scanf_i = 0x4005845c ); +PROVIDE ( _scanf_r = 0x4005879c ); +PROVIDE ( __sccl = 0x4000c498 ); +PROVIDE ( __sclose = 0x400011b8 ); +PROVIDE ( SelectSpiFunction = 0x40061f84 ); +PROVIDE ( SelectSpiQIO = 0x40061ddc ); +PROVIDE ( SendMsg = 0x40009384 ); +PROVIDE ( send_packet = 0x40009340 ); +PROVIDE ( __seofread = 0x40001148 ); +PROVIDE ( setjmp = 0x40056268 ); +PROVIDE ( setlocale = 0x40059568 ); +PROVIDE ( _setlocale_r = 0x4005950c ); +PROVIDE ( set_rtc_memory_crc = 0x40008208 ); +PROVIDE ( SetSpiDrvs = 0x40061e78 ); +PROVIDE ( __sf_fake_stderr = 0x3ff96458 ); +PROVIDE ( __sf_fake_stdin = 0x3ff96498 ); +PROVIDE ( __sf_fake_stdout = 0x3ff96478 ); +PROVIDE ( __sflush_r = 0x400591e0 ); +PROVIDE ( __sfmoreglue = 0x40001dc8 ); +PROVIDE ( __sfp = 0x40001e90 ); +PROVIDE ( __sfp_lock_acquire = 0x40001e08 ); +PROVIDE ( __sfp_lock_release = 0x40001e14 ); +PROVIDE ( __sfputs_r = 0x40057790 ); +PROVIDE ( __sfvwrite_r = 0x4005893c ); +PROVIDE ( sha1_prf = 0x40060ae8 ); +PROVIDE ( sha1_vector = 0x40060b64 ); +PROVIDE ( sha256_prf = 0x40060d70 ); +PROVIDE ( sha256_vector = 0x40060e08 ); +PROVIDE ( sha_blk_bits = 0x3ff99290 ); +PROVIDE ( sha_blk_bits_bytes = 0x3ff99288 ); +PROVIDE ( sha_blk_hash_bytes = 0x3ff9928c ); +PROVIDE ( sig_matrix = 0x3ffae293 ); +PROVIDE ( __sinit = 0x40001e38 ); +PROVIDE ( __sinit_lock_acquire = 0x40001e20 ); +PROVIDE ( __sinit_lock_release = 0x40001e2c ); +PROVIDE ( sip_after_tx_complete = 0x4000b358 ); +PROVIDE ( sip_alloc_to_host_evt = 0x4000ab9c ); +PROVIDE ( sip_get_ptr = 0x4000b34c ); +PROVIDE ( sip_get_state = 0x4000ae2c ); +PROVIDE ( sip_init_attach = 0x4000ae58 ); +PROVIDE ( sip_install_rx_ctrl_cb = 0x4000ae10 ); +PROVIDE ( sip_install_rx_data_cb = 0x4000ae20 ); +PROVIDE ( sip_is_active = 0x4000b3c0 ); +PROVIDE ( sip_post_init = 0x4000aed8 ); +PROVIDE ( sip_reclaim_from_host_cmd = 0x4000adbc ); +PROVIDE ( sip_reclaim_tx_data_pkt = 0x4000ad5c ); +PROVIDE ( siprintf = 0x40056c08 ); +PROVIDE ( _siprintf_r = 0x40056bbc ); +PROVIDE ( sip_send = 0x4000af54 ); +PROVIDE ( sip_to_host_chain_append = 0x4000aef8 ); +PROVIDE ( sip_to_host_evt_send_done = 0x4000ac04 ); +PROVIDE ( siscanf = 0x400587d0 ); +PROVIDE ( _siscanf_r = 0x40058830 ); +PROVIDE ( slc_add_credits = 0x4000baf4 ); +PROVIDE ( slc_enable = 0x4000b64c ); +PROVIDE ( slc_from_host_chain_fetch = 0x4000b7e8 ); +PROVIDE ( slc_from_host_chain_recycle = 0x4000bb10 ); +PROVIDE ( slc_has_pkt_to_host = 0x4000b5fc ); +PROVIDE ( slc_init_attach = 0x4000b918 ); +PROVIDE ( slc_init_credit = 0x4000badc ); +PROVIDE ( slc_reattach = 0x4000b62c ); +PROVIDE ( slc_send_to_host_chain = 0x4000b6a0 ); +PROVIDE ( slc_set_host_io_max_window = 0x4000b89c ); +PROVIDE ( slc_to_host_chain_recycle = 0x4000b758 ); +PROVIDE ( __smakebuf_r = 0x40059108 ); +PROVIDE ( sniprintf = 0x40056b4c ); +PROVIDE ( _sniprintf_r = 0x40056ae4 ); +PROVIDE ( snprintf = 0x40056b4c ); +PROVIDE ( _snprintf_r = 0x40056ae4 ); +PROVIDE ( software_reset = 0x4000824c ); +PROVIDE ( software_reset_cpu = 0x40008264 ); +PROVIDE ( specialModP256 = 0x4001600c ); +PROVIDE ( spi_cache_sram_init = 0x400626e4 ); +PROVIDE ( SPIClkConfig = 0x40062bc8 ); +PROVIDE ( SPI_Common_Command = 0x4006246c ); +PROVIDE ( spi_dummy_len_fix = 0x40061d90 ); +PROVIDE ( SPI_Encrypt_Write = 0x40062e78 ); +PROVIDE ( SPIEraseArea = 0x400631ac ); +PROVIDE ( SPIEraseBlock = 0x40062c4c ); +PROVIDE ( SPIEraseChip = 0x40062c14 ); +PROVIDE ( SPIEraseSector = 0x40062ccc ); +PROVIDE ( spi_flash_attach = 0x40062a6c ); +PROVIDE ( SPILock = 0x400628f0 ); +PROVIDE ( SPIMasterReadModeCnfig = 0x40062b64 ); +PROVIDE ( spi_modes = 0x3ff99270 ); +PROVIDE ( SPIParamCfg = 0x40063238 ); +PROVIDE ( SPI_Prepare_Encrypt_Data = 0x40062e1c ); +PROVIDE ( SPIRead = 0x40062ed8 ); +PROVIDE ( SPIReadModeCnfig = 0x40062944 ); +PROVIDE ( SPIUnlock = 0x400628b0 ); +PROVIDE ( SPI_user_command_read = 0x400621b0 ); +PROVIDE ( spi_w25q16 = 0x3ffae270 ); +PROVIDE ( SPIWrite = 0x40062d50 ); +PROVIDE ( SPI_Write_Encrypt_Disable = 0x40062e60 ); +PROVIDE ( SPI_Write_Encrypt_Enable = 0x40062df4 ); +PROVIDE ( sprintf = 0x40056c08 ); +PROVIDE ( _sprintf_r = 0x40056bbc ); +PROVIDE ( __sprint_r = 0x400577e4 ); +PROVIDE ( srand = 0x40001004 ); +PROVIDE ( __sread = 0x40001118 ); +PROVIDE ( __srefill_r = 0x400593d4 ); +PROVIDE ( sscanf = 0x400587d0 ); +PROVIDE ( _sscanf_r = 0x40058830 ); +PROVIDE ( __sseek = 0x40001184 ); +PROVIDE ( __ssprint_r = 0x40056ff8 ); +PROVIDE ( __ssputs_r = 0x40056f2c ); +PROVIDE ( __ssrefill_r = 0x40057fec ); +PROVIDE ( __ssvfiscanf_r = 0x4005802c ); +PROVIDE ( __ssvfscanf_r = 0x4005802c ); +PROVIDE ( __stack = 0x3ffe3f20 ); +PROVIDE ( __stack_app = 0x3ffe7e30 ); +PROVIDE ( _stack_sentry = 0x3ffe1320 ); +PROVIDE ( _stack_sentry_app = 0x3ffe5230 ); +PROVIDE ( _start = 0x40000704 ); +PROVIDE ( start_tb_console = 0x4005a980 ); +PROVIDE ( _stat_r = 0x4000bcb4 ); +PROVIDE ( _stext = 0x40000560 ); +PROVIDE ( strcasecmp = 0x400011cc ); +PROVIDE ( strcasestr = 0x40001210 ); +PROVIDE ( strcat = 0x4000c518 ); +PROVIDE ( strchr = 0x4000c53c ); +PROVIDE ( strcmp = 0x40001274 ); +PROVIDE ( strcoll = 0x40001398 ); +PROVIDE ( strcpy = 0x400013ac ); +PROVIDE ( strcspn = 0x4000c558 ); +PROVIDE ( strdup = 0x4000143c ); +PROVIDE ( _strdup_r = 0x40001450 ); +PROVIDE ( strftime = 0x40059ab4 ); +PROVIDE ( strlcat = 0x40001470 ); +PROVIDE ( strlcpy = 0x4000c584 ); +PROVIDE ( strlen = 0x400014c0 ); +PROVIDE ( strlwr = 0x40001524 ); +PROVIDE ( strncasecmp = 0x40001550 ); +PROVIDE ( strncat = 0x4000c5c4 ); +PROVIDE ( strncmp = 0x4000c5f4 ); +PROVIDE ( strncpy = 0x400015d4 ); +PROVIDE ( strndup = 0x400016b0 ); +PROVIDE ( _strndup_r = 0x400016c4 ); +PROVIDE ( strnlen = 0x4000c628 ); +PROVIDE ( strrchr = 0x40001708 ); +PROVIDE ( strsep = 0x40001734 ); +PROVIDE ( strspn = 0x4000c648 ); +PROVIDE ( strstr = 0x4000c674 ); +PROVIDE ( __strtok_r = 0x4000c6a8 ); +PROVIDE ( strtok_r = 0x4000c70c ); +PROVIDE ( strtol = 0x4005681c ); +PROVIDE ( _strtol_r = 0x40056714 ); +PROVIDE ( strtoul = 0x4005692c ); +PROVIDE ( _strtoul_r = 0x40056834 ); +PROVIDE ( strupr = 0x4000174c ); +PROVIDE ( __subdf3 = 0x400026e4 ); +PROVIDE ( __submore = 0x40058f3c ); +PROVIDE ( __subsf3 = 0x400021d0 ); +PROVIDE ( SubtractBigHex256 = 0x40015bcc ); +PROVIDE ( SubtractBigHexMod256 = 0x40015e8c ); +PROVIDE ( SubtractBigHexUint32_256 = 0x40015f8c ); +PROVIDE ( SubtractFromSelfBigHex256 = 0x40015c20 ); +PROVIDE ( SubtractFromSelfBigHexSign256 = 0x40015dc8 ); +PROVIDE ( __subvdi3 = 0x40002d20 ); +PROVIDE ( __subvsi3 = 0x40002cf8 ); +PROVIDE ( _sungetc_r = 0x40057f6c ); +PROVIDE ( _svfiprintf_r = 0x40057100 ); +PROVIDE ( __svfiscanf_r = 0x40057b08 ); +PROVIDE ( _svfprintf_r = 0x40057100 ); +PROVIDE ( __svfscanf = 0x40057f04 ); +PROVIDE ( __svfscanf_r = 0x40057b08 ); +PROVIDE ( __swbuf = 0x40058cb4 ); +PROVIDE ( __swbuf_r = 0x40058bec ); +PROVIDE ( __swrite = 0x40001150 ); +PROVIDE ( __swsetup_r = 0x40058cc8 ); +PROVIDE ( sw_to_hw = 0x3ffb8d40 ); +PROVIDE ( _SyscallException = 0x400007cf ); +PROVIDE ( syscall_table_ptr_app = 0x3ffae020 ); +PROVIDE ( syscall_table_ptr_pro = 0x3ffae024 ); +PROVIDE ( _system_r = 0x4000bc10 ); +PROVIDE ( tdefl_compress = 0x400600bc ); +PROVIDE ( tdefl_compress_buffer = 0x400607f4 ); +PROVIDE ( tdefl_compress_mem_to_mem = 0x40060900 ); +PROVIDE ( tdefl_compress_mem_to_output = 0x400608e0 ); +PROVIDE ( tdefl_get_adler32 = 0x400608d8 ); +PROVIDE ( tdefl_get_prev_return_status = 0x400608d0 ); +PROVIDE ( tdefl_init = 0x40060810 ); +PROVIDE ( tdefl_write_image_to_png_file_in_memory = 0x4006091c ); +PROVIDE ( tdefl_write_image_to_png_file_in_memory_ex = 0x40060910 ); +PROVIDE ( time = 0x40001844 ); +PROVIDE ( __time_load_locale = 0x4000183c ); +PROVIDE ( times = 0x40001808 ); +PROVIDE ( _times_r = 0x4000bc40 ); +PROVIDE ( _timezone = 0x3ffae0a0 ); +PROVIDE ( tinfl_decompress = 0x4005ef30 ); +PROVIDE ( tinfl_decompress_mem_to_callback = 0x40060090 ); +PROVIDE ( tinfl_decompress_mem_to_mem = 0x40060050 ); +PROVIDE ( toascii = 0x4000c720 ); +PROVIDE ( tolower = 0x40001868 ); +PROVIDE ( toupper = 0x40001884 ); +PROVIDE ( __truncdfsf2 = 0x40002b90 ); +PROVIDE ( __tzcalc_limits = 0x400018a0 ); +PROVIDE ( __tz_lock = 0x40001a04 ); +PROVIDE ( _tzname = 0x3ffae030 ); +PROVIDE ( tzset = 0x40001a1c ); +PROVIDE ( _tzset_r = 0x40001a28 ); +PROVIDE ( __tz_unlock = 0x40001a10 ); +PROVIDE ( uartAttach = 0x40008fd0 ); +PROVIDE ( uart_baudrate_detect = 0x40009034 ); +PROVIDE ( uart_buff_switch = 0x400093c0 ); +PROVIDE ( UartConnCheck = 0x40008738 ); +PROVIDE ( UartConnectProc = 0x40008a04 ); +PROVIDE ( UartDev = 0x3ffe019c ); +PROVIDE ( uart_div_modify = 0x400090cc ); +PROVIDE ( UartDwnLdProc = 0x40008ce8 ); +PROVIDE ( UartGetCmdLn = 0x40009564 ); +PROVIDE ( Uart_Init = 0x40009120 ); +PROVIDE ( UartRegReadProc = 0x40008a58 ); +PROVIDE ( UartRegWriteProc = 0x40008a14 ); +PROVIDE ( uart_rx_intr_handler = 0x40008f4c ); +PROVIDE ( uart_rx_one_char = 0x400092d0 ); +PROVIDE ( uart_rx_one_char_block = 0x400092a4 ); +PROVIDE ( uart_rx_readbuff = 0x40009394 ); +PROVIDE ( UartRxString = 0x400092fc ); +PROVIDE ( UartSetBaudProc = 0x40008aac ); +PROVIDE ( UartSpiAttachProc = 0x40008a6c ); +PROVIDE ( UartSpiReadProc = 0x40008a80 ); +PROVIDE ( uart_tx_flush = 0x40009258 ); +PROVIDE ( uart_tx_one_char = 0x40009200 ); +PROVIDE ( uart_tx_one_char2 = 0x4000922c ); +PROVIDE ( uart_tx_switch = 0x40009028 ); +PROVIDE ( uart_tx_wait_idle = 0x40009278 ); +PROVIDE ( __ucmpdi2 = 0x40063840 ); +PROVIDE ( __udivdi3 = 0x4000cff8 ); +PROVIDE ( __udivmoddi4 = 0x40064ab0 ); +PROVIDE ( __udivsi3 = 0x4000c7c8 ); +PROVIDE ( __udiv_w_sdiv = 0x40064aa8 ); +PROVIDE ( __umoddi3 = 0x4000d280 ); +PROVIDE ( __umodsi3 = 0x4000c7d0 ); +PROVIDE ( __umulsidi3 = 0x4000c7d8 ); +PROVIDE ( ungetc = 0x400590f4 ); +PROVIDE ( _ungetc_r = 0x40058fa0 ); +PROVIDE ( _unlink_r = 0x4000bc84 ); +PROVIDE ( __unorddf2 = 0x400637f4 ); +PROVIDE ( __unordsf2 = 0x40063478 ); +PROVIDE ( user_code_start = 0x3ffe0400 ); +PROVIDE ( _UserExceptionVector = 0x40000340 ); +PROVIDE ( utoa = 0x40056258 ); +PROVIDE ( __utoa = 0x400561f0 ); +PROVIDE ( vasiprintf = 0x40056eb8 ); +PROVIDE ( _vasiprintf_r = 0x40056e80 ); +PROVIDE ( vasniprintf = 0x40056e58 ); +PROVIDE ( _vasniprintf_r = 0x40056df8 ); +PROVIDE ( vasnprintf = 0x40056e58 ); +PROVIDE ( _vasnprintf_r = 0x40056df8 ); +PROVIDE ( vasprintf = 0x40056eb8 ); +PROVIDE ( _vasprintf_r = 0x40056e80 ); +PROVIDE ( VerifyFlashMd5Proc = 0x40008c44 ); +PROVIDE ( veryBigHexP256 = 0x3ff9736c ); +PROVIDE ( vfiprintf = 0x40057ae8 ); +PROVIDE ( _vfiprintf_r = 0x40057850 ); +PROVIDE ( vfiscanf = 0x40057eb8 ); +PROVIDE ( _vfiscanf_r = 0x40057f24 ); +PROVIDE ( vfprintf = 0x40057ae8 ); +PROVIDE ( _vfprintf_r = 0x40057850 ); +PROVIDE ( vfscanf = 0x40057eb8 ); +PROVIDE ( _vfscanf_r = 0x40057f24 ); +PROVIDE ( viprintf = 0x400569b4 ); +PROVIDE ( _viprintf_r = 0x400569e4 ); +PROVIDE ( viscanf = 0x40058698 ); +PROVIDE ( _viscanf_r = 0x400586c8 ); +PROVIDE ( vprintf = 0x400569b4 ); +PROVIDE ( _vprintf_r = 0x400569e4 ); +PROVIDE ( vscanf = 0x40058698 ); +PROVIDE ( _vscanf_r = 0x400586c8 ); +PROVIDE ( vsiprintf = 0x40056ac4 ); +PROVIDE ( _vsiprintf_r = 0x40056a90 ); +PROVIDE ( vsiscanf = 0x40058740 ); +PROVIDE ( _vsiscanf_r = 0x400586f8 ); +PROVIDE ( vsniprintf = 0x40056a68 ); +PROVIDE ( _vsniprintf_r = 0x40056a14 ); +PROVIDE ( vsnprintf = 0x40056a68 ); +PROVIDE ( _vsnprintf_r = 0x40056a14 ); +PROVIDE ( vsprintf = 0x40056ac4 ); +PROVIDE ( _vsprintf_r = 0x40056a90 ); +PROVIDE ( vsscanf = 0x40058740 ); +PROVIDE ( _vsscanf_r = 0x400586f8 ); +PROVIDE ( wcrtomb = 0x40058920 ); +PROVIDE ( _wcrtomb_r = 0x400588d8 ); +PROVIDE ( __wctomb = 0x3ff96540 ); +PROVIDE ( _wctomb_r = 0x40058f14 ); +PROVIDE ( _WindowOverflow12 = 0x40000100 ); +PROVIDE ( _WindowOverflow4 = 0x40000000 ); +PROVIDE ( _WindowOverflow8 = 0x40000080 ); +PROVIDE ( _WindowUnderflow12 = 0x40000140 ); +PROVIDE ( _WindowUnderflow4 = 0x40000040 ); +PROVIDE ( _WindowUnderflow8 = 0x400000c0 ); +PROVIDE ( write = 0x4000181c ); +PROVIDE ( _write_r = 0x4000bd70 ); +PROVIDE ( xthal_bcopy = 0x4000c098 ); +PROVIDE ( xthal_copy123 = 0x4000c124 ); +PROVIDE ( xthal_get_ccompare = 0x4000c078 ); +PROVIDE ( xthal_get_ccount = 0x4000c050 ); +PROVIDE ( xthal_get_interrupt = 0x4000c1e4 ); +PROVIDE ( xthal_get_intread = 0x4000c1e4 ); +PROVIDE ( Xthal_intlevel = 0x3ff9c2b4 ); +PROVIDE ( xthal_memcpy = 0x4000c0bc ); +PROVIDE ( xthal_set_ccompare = 0x4000c058 ); +PROVIDE ( xthal_set_intclear = 0x4000c1ec ); +PROVIDE ( _xtos_alloca_handler = 0x40000010 ); +PROVIDE ( _xtos_cause3_handler = 0x40000dd8 ); +PROVIDE ( _xtos_c_handler_table = 0x3ffe0548 ); +PROVIDE ( _xtos_c_wrapper_handler = 0x40000de8 ); +PROVIDE ( _xtos_enabled = 0x3ffe0650 ); +PROVIDE ( _xtos_exc_handler_table = 0x3ffe0448 ); +PROVIDE ( _xtos_interrupt_mask_table = 0x3ffe0758 ); +PROVIDE ( _xtos_interrupt_table = 0x3ffe0658 ); +PROVIDE ( _xtos_ints_off = 0x4000bfac ); +PROVIDE ( _xtos_ints_on = 0x4000bf88 ); +PROVIDE ( _xtos_intstruct = 0x3ffe0650 ); +PROVIDE ( _xtos_l1int_handler = 0x40000814 ); +PROVIDE ( _xtos_p_none = 0x4000bfd4 ); +PROVIDE ( _xtos_restore_intlevel = 0x40000928 ); +PROVIDE ( _xtos_return_from_exc = 0x4000c034 ); +PROVIDE ( _xtos_set_exception_handler = 0x4000074c ); +PROVIDE ( _xtos_set_interrupt_handler = 0x4000bf78 ); +PROVIDE ( _xtos_set_interrupt_handler_arg = 0x4000bf34 ); +PROVIDE ( _xtos_set_intlevel = 0x4000bfdc ); +PROVIDE ( _xtos_set_min_intlevel = 0x4000bff8 ); +PROVIDE ( _xtos_set_vpri = 0x40000934 ); +PROVIDE ( _xtos_syscall_handler = 0x40000790 ); +PROVIDE ( _xtos_unhandled_exception = 0x4000c024 ); +PROVIDE ( _xtos_unhandled_interrupt = 0x4000c01c ); +PROVIDE ( _xtos_vpri_enabled = 0x3ffe0654 ); + +PROVIDE ( I2S0 = 0x6000F000 ); \ No newline at end of file diff --git a/components/esp32/ld/eagle.fpga32.v7.ld b/components/esp32/ld/eagle.fpga32.v7.ld new file mode 100644 index 0000000000..6824486a86 --- /dev/null +++ b/components/esp32/ld/eagle.fpga32.v7.ld @@ -0,0 +1,170 @@ +/* THESE ARE THE VIRTUAL RUNTIME ADDRESSES */ +/* The load addresses are defined later using the AT statements. */ +MEMORY +{ + /* All these values assume the flash cache is on, and have the blocks this uses subtracted from the length + of the various regions. The 'data access port' dram/drom regions map to the same iram/irom regions but + are connected to the data port of the CPU and eg allow bytewise access. */ + iram0_0_seg (RX) : org = 0x40080000, len = 0x18000 /* IRAM for PRO cpu. Not sure if happy with this, this is MMU area... */ + iram0_2_seg (RX) : org = 0x400D0018, len = 0x330000 /* Even though the segment name is iram, it is actually mapped to flash */ + dram0_0_seg (RW) : org = 0x3FFC0000, len = 0x20000 /* Shared RAM, minus rom bss/data/stack.*/ + drom0_0_seg (R) : org = 0x3F400010, len = 0x800000 +} + +_heap_end = 0x3fffe000; + +/* Default entry point: */ +ENTRY(call_user_start_cpu0); + +SECTIONS +{ + /* Send .iram0 code to iram */ + .iram0.vectors : + { + /* Vectors go to IRAM */ + _init_start = ABSOLUTE(.); + /* Vectors according to builds/RF-2015.2-win32/esp108_v1_2_s5_512int_2/config.html */ + . = 0x0; + KEEP(*(.WindowVectors.text)); + . = 0x180; + KEEP(*(.Level2InterruptVector.text)); + . = 0x1c0; + KEEP(*(.Level3InterruptVector.text)); + . = 0x200; + KEEP(*(.Level4InterruptVector.text)); + . = 0x240; + KEEP(*(.Level5InterruptVector.text)); + . = 0x280; + KEEP(*(.DebugExceptionVector.text)); + . = 0x2c0; + KEEP(*(.NMIExceptionVector.text)); + . = 0x300; + KEEP(*(.KernelExceptionVector.text)); + . = 0x340; + KEEP(*(.UserExceptionVector.text)); + . = 0x3C0; + KEEP(*(.DoubleExceptionVector.text)); + . = 0x400; + *(.*Vector.literal) + + *(.UserEnter.literal); + *(.UserEnter.text); + . = ALIGN (16); + *(.entry.text) + *(.init.literal) + *(.init) + _init_end = ABSOLUTE(.); + } > iram0_0_seg + + .iram0.text : + { + /* Code marked as runnning out of IRAM */ + _iram_text_start = ABSOLUTE(.); + *(.iram1 .iram1.*) + *libfreertos.a:(.literal .text .literal.* .text.*) + *libphy.a:(.literal .text .literal.* .text.*) + *librtc.a:(.literal .text .literal.* .text.*) + *libpp.a:(.literal .text .literal.* .text.*) + *libhal.a:(.literal .text .literal.* .text.*) + _iram_text_end = ABSOLUTE(.); + } > iram0_0_seg + + /* Shared RAM */ + .dram0.bss (NOLOAD) : + { + . = ALIGN (8); + _bss_start = ABSOLUTE(.); + *(.dynsbss) + *(.sbss) + *(.sbss.*) + *(.gnu.linkonce.sb.*) + *(.scommon) + *(.sbss2) + *(.sbss2.*) + *(.gnu.linkonce.sb2.*) + *(.dynbss) + KEEP(*(.bss)) + *(.bss.*) + *(.share.mem) + *(.gnu.linkonce.b.*) + *(COMMON) + . = ALIGN (8); + _bss_end = ABSOLUTE(.); + } >dram0_0_seg + + .dram0.data : + { + _data_start = ABSOLUTE(.); + KEEP(*(.data)) + KEEP(*(.data.*)) + KEEP(*(.gnu.linkonce.d.*)) + KEEP(*(.data1)) + KEEP(*(.sdata)) + KEEP(*(.sdata.*)) + KEEP(*(.gnu.linkonce.s.*)) + KEEP(*(.sdata2)) + KEEP(*(.sdata2.*)) + KEEP(*(.gnu.linkonce.s2.*)) + KEEP(*(.jcr)) + _data_end = ABSOLUTE(.); + . = ALIGN(4); + _heap_start = ABSOLUTE(.); + } >dram0_0_seg + + .flash.rodata : + { + _rodata_start = ABSOLUTE(.); + *(.rodata) + *(.rodata.*) + *(.irom1.text) /* catch stray ICACHE_RODATA_ATTR */ + *(.gnu.linkonce.r.*) + *(.rodata1) + __XT_EXCEPTION_TABLE_ = ABSOLUTE(.); + *(.xt_except_table) + *(.gcc_except_table) + *(.gnu.linkonce.e.*) + *(.gnu.version_r) + *(.eh_frame) + . = (. + 3) & ~ 3; + /* C++ constructor and destructor tables, properly ordered: */ + __init_array_start = ABSOLUTE(.); + KEEP (*crtbegin.o(.ctors)) + KEEP (*(EXCLUDE_FILE (*crtend.o) .ctors)) + KEEP (*(SORT(.ctors.*))) + KEEP (*(.ctors)) + __init_array_end = ABSOLUTE(.); + KEEP (*crtbegin.o(.dtors)) + KEEP (*(EXCLUDE_FILE (*crtend.o) .dtors)) + KEEP (*(SORT(.dtors.*))) + KEEP (*(.dtors)) + /* C++ exception handlers table: */ + __XT_EXCEPTION_DESCS_ = ABSOLUTE(.); + *(.xt_except_desc) + *(.gnu.linkonce.h.*) + __XT_EXCEPTION_DESCS_END__ = ABSOLUTE(.); + *(.xt_except_desc_end) + *(.dynamic) + *(.gnu.version_d) + _rodata_end = ABSOLUTE(.); + /* Literals are also RO data. */ + _lit4_start = ABSOLUTE(.); + *(*.lit4) + *(.lit4.*) + *(.gnu.linkonce.lit4.*) + _lit4_end = ABSOLUTE(.); + . = ALIGN(4); + } >drom0_0_seg + + .flash.text : + { + _stext = .; + _text_start = ABSOLUTE(.); + *(.literal .text .literal.* .text.* .stub .gnu.warning .gnu.linkonce.literal.* .gnu.linkonce.t.*.literal .gnu.linkonce.t.*) + *(.irom0.text) /* catch stray ICACHE_RODATA_ATTR */ + *(.fini.literal) + *(.fini) + *(.gnu.version) + _text_end = ABSOLUTE(.); + _etext = .; + } >iram0_2_seg +} diff --git a/components/esp32/ld/elf_to_ld.sh b/components/esp32/ld/elf_to_ld.sh new file mode 100755 index 0000000000..138f24d602 --- /dev/null +++ b/components/esp32/ld/elf_to_ld.sh @@ -0,0 +1,12 @@ +#!/bin/bash + +echo '/*' +echo 'ESP32 ROM address table' +echo 'Generated for ROM with MD5sum:' +md5sum $1 +echo '*/' +xtensa-esp108-elf-nm $1 | grep '[0-9a-f] [TBRD]' | while read adr ttp nm; do + if ! echo "$nm" | grep -q -e '^_bss' -e '_heap'; then + echo "PROVIDE ( $nm = 0x$adr );"; + fi +done \ No newline at end of file diff --git a/components/esp32/lib b/components/esp32/lib new file mode 160000 index 0000000000..40dc7af7f3 --- /dev/null +++ b/components/esp32/lib @@ -0,0 +1 @@ +Subproject commit 40dc7af7f3d8da6745476e66cbd65be9b8988f6c diff --git a/components/esp32/libhal.a b/components/esp32/libhal.a new file mode 100644 index 0000000000000000000000000000000000000000..382f4e0ab2336d96e9216a63c885fda7cd3d45c1 GIT binary patch literal 462242 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%0AquOD`0GJ*n$YyS$I%4 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 +#include +#include +#include +#include +#include +#include +#include +#include "rom/libc_stubs.h" +#include "freertos/FreeRTOS.h" +#include "freertos/portmacro.h" +#include "freertos/task.h" + +int uart_tx_one_char(uint8_t c); + +void abort() { + do + { + __asm__ ("break 0,0"); + *((int*) 0) = 0; + } while(true); +} + +void* _malloc_r(struct _reent *r, size_t size) { + return pvPortMalloc(size); +} + +void _free_r(struct _reent *r, void* ptr) { + return vPortFree(ptr); +} + +// TODO: improve realloc to grow buffer in place if possible +void* _realloc_r(struct _reent *r, void* ptr, size_t size) { + void* new_chunk = pvPortMalloc(size); + if (new_chunk) { + memcpy(new_chunk, ptr, size); + vPortFree(ptr); + } + // realloc behaviour: don't free original chunk if alloc failed + return new_chunk; +} + +void* _calloc_r(struct _reent *r, size_t count, size_t size) { + void* result = pvPortMalloc(count * size); + if (result) + { + memset(result, 0, count * size); + } + return result; +} + +int _system_r(struct _reent *r, const char *str) { + abort(); + return 0; +} + +int _rename_r(struct _reent *r, const char *src, const char *dst) { + abort(); + return 0; +} + +clock_t _times_r(struct _reent *r, struct tms *ptms) { + abort(); + return 0; +} + +// TODO: read time from RTC +int _gettimeofday_r(struct _reent *r, struct timeval *tv, void *tz) { + abort(); + return 0; +} + +void _raise_r(struct _reent *r) { + abort(); +} + +int _unlink_r(struct _reent *r, const char *path) { + abort(); + return 0; +} + +int _link_r(struct _reent *r, const char* n1, const char* n2) { + abort(); + return 0; +} + +int _stat_r(struct _reent *r, const char * path, struct stat * st) { + return 0; +} + +int _fstat_r(struct _reent *r, int fd, struct stat * st) { + st->st_mode = S_IFCHR; + return 0; +} + +void* _sbrk_r(struct _reent *r, ptrdiff_t sz) { + abort(); + return 0; +} + +int _getpid_r(struct _reent *r) { + abort(); + return 0; +} + +int _kill_r(struct _reent *r, int pid, int sig) { + abort(); + return 0; +} + +void _exit_r(struct _reent *r, int e) { + abort(); +} + +int _close_r(struct _reent *r, int fd) { + return 0; +} + +int _open_r(struct _reent *r, const char * path, int flags, int mode) { + return 0; +} + +ssize_t _write_r(struct _reent *r, int fd, const void * data, size_t size) { + const char* p = (const char*) data; + if (fd == STDOUT_FILENO) { + while(size--) { + uart_tx_one_char(*p); + ++p; + } + } + return size; +} + +_off_t _lseek_r(struct _reent *r, int fd, _off_t size, int mode) { + return 0; +} + +// TODO: implement reading from UART +ssize_t _read_r(struct _reent *r, int fd, void * dst, size_t size) { + return 0; +} + +// TODO: implement locks via FreeRTOS mutexes +void _lock_init(_lock_t *lock) { +} + +void _lock_init_recursive(_lock_t *lock) { +} + +void _lock_close(_lock_t *lock) { +} + +void _lock_close_recursive(_lock_t *lock) { +} + +void _lock_acquire(_lock_t *lock) { +} + +void _lock_acquire_recursive(_lock_t *lock) { +} + +int _lock_try_acquire(_lock_t *lock) { + return 0; +} + +int _lock_try_acquire_recursive(_lock_t *lock) { + return 0; +} + +void _lock_release(_lock_t *lock) { +} + +void _lock_release_recursive(_lock_t *lock) { +} + +static struct _reent s_reent; + +/* + General ToDo that the Xtensa newlib support code did but we do not: Close every open fd a running task had when the task + is killed. Do we want that too? - JD +*/ + +extern int _printf_float(struct _reent *rptr, + void *pdata, + FILE * fp, + int (*pfunc) (struct _reent *, FILE *, _CONST char *, size_t len), + va_list * ap); + + +extern int _scanf_float(struct _reent *rptr, + void *pdata, + FILE *fp, + va_list *ap); + + +static struct syscall_stub_table s_stub_table = { + .__getreent = &__getreent, + ._malloc_r = &_malloc_r, + ._free_r = &_free_r, + ._realloc_r = &_realloc_r, + ._calloc_r = &_calloc_r, + ._abort = &abort, + ._system_r = &_system_r, + ._rename_r = &_rename_r, + ._times_r = &_times_r, + ._gettimeofday_r = &_gettimeofday_r, + ._raise_r = &_raise_r, + ._unlink_r = &_unlink_r, + ._link_r = &_link_r, + ._stat_r = &_stat_r, + ._fstat_r = &_fstat_r, + ._sbrk_r = &_sbrk_r, + ._getpid_r = &_getpid_r, + ._kill_r = &_kill_r, + ._exit_r = &_exit_r, + ._close_r = &_close_r, + ._open_r = &_open_r, + ._write_r = (int (*)(struct _reent *r, int, const void *, int)) &_write_r, + ._lseek_r = (int (*)(struct _reent *r, int, int, int)) &_lseek_r, + ._read_r = (int (*)(struct _reent *r, int, void *, int)) &_read_r, + ._lock_init = &_lock_init, + ._lock_init_recursive = &_lock_init_recursive, + ._lock_close = &_lock_close, + ._lock_close_recursive = &_lock_close_recursive, + ._lock_acquire = &_lock_acquire, + ._lock_acquire_recursive = &_lock_acquire_recursive, + ._lock_try_acquire = &_lock_try_acquire, + ._lock_try_acquire_recursive = &_lock_try_acquire_recursive, + ._lock_release = &_lock_release, + ._lock_release_recursive = &_lock_release_recursive, + ._printf_float = &_printf_float, + ._scanf_float = &_scanf_float, +}; + +void ets_setup_syscalls() { + syscall_table_ptr_pro = &s_stub_table; + syscall_table_ptr_app = &s_stub_table; + _GLOBAL_REENT = &s_reent; + environ = malloc(sizeof(char*)); + environ[0] = NULL; +} + + diff --git a/components/esp32/wifi.c b/components/esp32/wifi.c new file mode 100644 index 0000000000..38fd733dcb --- /dev/null +++ b/components/esp32/wifi.c @@ -0,0 +1,109 @@ +// Copyright 2015-2016 Espressif Systems (Shanghai) PTE LTD +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at + +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +#include +#include + +#include "esp_err.h" +#include "esp_wifi.h" +#include "esp_event.h" + +#include "freertos/FreeRTOS.h" +#include "freertos/task.h" +#include "freertos/queue.h" +#include "freertos/semphr.h" + +//#include "tcpip_adapter.h" + +#define ESP32_WORKAROUND 1 + +#if CONFIG_WIFI_ENABLED + +#ifdef ESP32_WORKAROUND + +SemaphoreHandle_t stdio_mutex_tx = NULL; +#define os_printf(fmt, ...) do {\ + if (!stdio_mutex_tx) {\ + stdio_mutex_tx = xSemaphoreCreateMutex();\ + }\ +\ + xSemaphoreTake(stdio_mutex_tx, portMAX_DELAY);\ + ets_printf(fmt, ##__VA_ARGS__);\ + xSemaphoreGive(stdio_mutex_tx);\ +} while (0) + +#endif + +static wifi_startup_cb_t startup_cb; + +#define WIFI_DEBUG os_printf +#define WIFI_API_CALL_CHECK(info, api_call, ret) \ +do{\ + esp_err_t __err = (api_call);\ + if ((ret) != __err) {\ + WIFI_DEBUG("%s %d %s ret=%d\n", __FUNCTION__, __LINE__, (info), __err);\ + return __err;\ + }\ +} while(0) + +static void esp_wifi_task(void *pvParameters) +{ + esp_err_t err; + wifi_init_config_t cfg; + cfg.event_q = (xQueueHandle)esp_event_get_handler(); + + do { + err = esp_wifi_init(&cfg); + if (err != ESP_OK) { + break; + } + + if (startup_cb) { + err = (*startup_cb)(); + if (err != ESP_OK) { + break; + } + } + + err = esp_wifi_start(); + if (err != ESP_OK) { // TODO: if already started, it's also OK + break; + } + +#if CONFIG_WIFI_AUTO_CONNECT + wifi_mode_t mode; + + esp_wifi_get_mode(&mode); + + if (mode == WIFI_MODE_STA || mode == WIFI_MODE_APSTA) { + err = esp_wifi_connect(); + if (err != ESP_OK) { + break; + } + } +#endif + } while (0); + + if (err != ESP_OK) { + esp_wifi_deinit(); + } + + vTaskDelete(NULL); +} + +void esp_wifi_startup(wifi_startup_cb_t cb) +{ + startup_cb = cb; + xTaskCreatePinnedToCore(esp_wifi_task, "wifiTask", 4096, NULL, 5, NULL, 0);// TODO: rearrange task priority +} +#endif diff --git a/components/esptool_py/Kconfig.projbuild b/components/esptool_py/Kconfig.projbuild new file mode 100644 index 0000000000..ad7fefb1ce --- /dev/null +++ b/components/esptool_py/Kconfig.projbuild @@ -0,0 +1,49 @@ +menu "Serial flasher config" + +config ESPTOOLPY_PORT + string "Default serial port" + default "/dev/ttyUSB0" + help + The serial port that's connected to the ESP chip. This can be overridden by setting the ESPPORT + environment variable. + +choice ESPTOOLPY_BAUD + prompt "Default baud rate" + default ESPTOOLPY_BAUD_115200B + help + Default baud rate to use while communicating with the ESP chip. Can be overridden by + setting the ESPBAUD variable. + +config ESPTOOLPY_BAUD_115200B + bool "115200 baud" +config ESPTOOLPY_BAUD_230400B + bool "230400 baud" +config ESPTOOLPY_BAUD_921600B + bool "921600 baud" +config ESPTOOLPY_BAUD_2MB + bool "2Mbaud" +config ESPTOOLPY_BAUD_OTHER + bool "Other baud rate" +endchoice + +config ESPTOOLPY_BAUD_OTHER_VAL + int "Other baud rate value" if ESPTOOLPY_BAUD_OTHER + default 115200 + +config ESPTOOLPY_BAUD + int + default 115200 if ESPTOOLPY_BAUD_115200B + default 230400 if ESPTOOLPY_BAUD_230400B + default 921600 if ESPTOOLPY_BAUD_921600B + default 2000000 if ESPTOOLPY_BAUD_2MB + default ESPTOOLPY_BAUD_OTHER_VAL if ESPTOOLPY_BAUD_OTHER + +config ESPTOOLPY_COMPRESSED + bool "Use compressed upload" + default "y" + help + The flasher tool can send data compressed using zlib, letting the ROM on the ESP chip + decompress it on the fly before flashing it. For most payloads, this should result in a + speed increase. + +endmenu diff --git a/components/esptool_py/LICENSE b/components/esptool_py/LICENSE new file mode 100644 index 0000000000..d159169d10 --- /dev/null +++ b/components/esptool_py/LICENSE @@ -0,0 +1,339 @@ + GNU GENERAL PUBLIC LICENSE + Version 2, June 1991 + + Copyright (C) 1989, 1991 Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +License is intended to guarantee your freedom to share and change free +software--to make sure the software is free for all its users. This +General Public License applies to most of the Free Software +Foundation's software and to any other program whose authors commit to +using it. (Some other Free Software Foundation software is covered by +the GNU Lesser General Public License instead.) You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +this service if you wish), that you receive source code or can get it +if you want it, that you can change the software or use pieces of it +in new free programs; and that you know you can do these things. + + To protect your rights, we need to make restrictions that forbid +anyone to deny you these rights or to ask you to surrender the rights. +These restrictions translate to certain responsibilities for you if you +distribute copies of the software, or if you modify it. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must give the recipients all the rights that +you have. You must make sure that they, too, receive or can get the +source code. And you must show them these terms so they know their +rights. + + We protect your rights with two steps: (1) copyright the software, and +(2) offer you this license which gives you legal permission to copy, +distribute and/or modify the software. + + Also, for each author's protection and ours, we want to make certain +that everyone understands that there is no warranty for this free +software. If the software is modified by someone else and passed on, we +want its recipients to know that what they have is not the original, so +that any problems introduced by others will not reflect on the original +authors' reputations. + + Finally, any free program is threatened constantly by software +patents. We wish to avoid the danger that redistributors of a free +program will individually obtain patent licenses, in effect making the +program proprietary. To prevent this, we have made it clear that any +patent must be licensed for everyone's free use or not licensed at all. + + The precise terms and conditions for copying, distribution and +modification follow. + + GNU GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License applies to any program or other work which contains +a notice placed by the copyright holder saying it may be distributed +under the terms of this General Public License. The "Program", below, +refers to any such program or work, and a "work based on the Program" +means either the Program or any derivative work under copyright law: +that is to say, a work containing the Program or a portion of it, +either verbatim or with modifications and/or translated into another +language. (Hereinafter, translation is included without limitation in +the term "modification".) Each licensee is addressed as "you". + +Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running the Program is not restricted, and the output from the Program +is covered only if its contents constitute a work based on the +Program (independent of having been made by running the Program). +Whether that is true depends on what the Program does. + + 1. You may copy and distribute verbatim copies of the Program's +source code as you receive it, in any medium, provided that you +conspicuously and appropriately publish on each copy an appropriate +copyright notice and disclaimer of warranty; keep intact all the +notices that refer to this License and to the absence of any warranty; +and give any other recipients of the Program a copy of this License +along with the Program. + +You may charge a fee for the physical act of transferring a copy, and +you may at your option offer warranty protection in exchange for a fee. + + 2. You may modify your copy or copies of the Program or any portion +of it, thus forming a work based on the Program, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) You must cause the modified files to carry prominent notices + stating that you changed the files and the date of any change. + + b) You must cause any work that you distribute or publish, that in + whole or in part contains or is derived from the Program or any + part thereof, to be licensed as a whole at no charge to all third + parties under the terms of this License. + + c) If the modified program normally reads commands interactively + when run, you must cause it, when started running for such + interactive use in the most ordinary way, to print or display an + announcement including an appropriate copyright notice and a + notice that there is no warranty (or else, saying that you provide + a warranty) and that users may redistribute the program under + these conditions, and telling the user how to view a copy of this + License. (Exception: if the Program itself is interactive but + does not normally print such an announcement, your work based on + the Program is not required to print an announcement.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Program, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Program, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Program. + +In addition, mere aggregation of another work not based on the Program +with the Program (or with a work based on the Program) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may copy and distribute the Program (or a work based on it, +under Section 2) in object code or executable form under the terms of +Sections 1 and 2 above provided that you also do one of the following: + + a) Accompany it with the complete corresponding machine-readable + source code, which must be distributed under the terms of Sections + 1 and 2 above on a medium customarily used for software interchange; or, + + b) Accompany it with a written offer, valid for at least three + years, to give any third party, for a charge no more than your + cost of physically performing source distribution, a complete + machine-readable copy of the corresponding source code, to be + distributed under the terms of Sections 1 and 2 above on a medium + customarily used for software interchange; or, + + c) Accompany it with the information you received as to the offer + to distribute corresponding source code. (This alternative is + allowed only for noncommercial distribution and only if you + received the program in object code or executable form with such + an offer, in accord with Subsection b above.) + +The source code for a work means the preferred form of the work for +making modifications to it. For an executable work, complete source +code means all the source code for all modules it contains, plus any +associated interface definition files, plus the scripts used to +control compilation and installation of the executable. However, as a +special exception, the source code distributed need not include +anything that is normally distributed (in either source or binary +form) with the major components (compiler, kernel, and so on) of the +operating system on which the executable runs, unless that component +itself accompanies the executable. + +If distribution of executable or object code is made by offering +access to copy from a designated place, then offering equivalent +access to copy the source code from the same place counts as +distribution of the source code, even though third parties are not +compelled to copy the source along with the object code. + + 4. You may not copy, modify, sublicense, or distribute the Program +except as expressly provided under this License. Any attempt +otherwise to copy, modify, sublicense or distribute the Program is +void, and will automatically terminate your rights under this License. +However, parties who have received copies, or rights, from you under +this License will not have their licenses terminated so long as such +parties remain in full compliance. + + 5. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Program or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Program (or any work based on the +Program), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Program or works based on it. + + 6. Each time you redistribute the Program (or any work based on the +Program), the recipient automatically receives a license from the +original licensor to copy, distribute or modify the Program subject to +these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties to +this License. + + 7. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Program at all. For example, if a patent +license would not permit royalty-free redistribution of the Program by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Program. + +If any portion of this section is held invalid or unenforceable under +any particular circumstance, the balance of the section is intended to +apply and the section as a whole is intended to apply in other +circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system, which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 8. If the distribution and/or use of the Program is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Program under this License +may add an explicit geographical distribution limitation excluding +those countries, so that distribution is permitted only in or among +countries not thus excluded. In such case, this License incorporates +the limitation as if written in the body of this License. + + 9. The Free Software Foundation may publish revised and/or new versions +of the General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + +Each version is given a distinguishing version number. If the Program +specifies a version number of this License which applies to it and "any +later version", you have the option of following the terms and conditions +either of that version or of any later version published by the Free +Software Foundation. If the Program does not specify a version number of +this License, you may choose any version ever published by the Free Software +Foundation. + + 10. If you wish to incorporate parts of the Program into other free +programs whose distribution conditions are different, write to the author +to ask for permission. For software which is copyrighted by the Free +Software Foundation, write to the Free Software Foundation; we sometimes +make exceptions for this. Our decision will be guided by the two goals +of preserving the free status of all derivatives of our free software and +of promoting the sharing and reuse of software generally. + + NO WARRANTY + + 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY +FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN +OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES +PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED +OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS +TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE +PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, +REPAIR OR CORRECTION. + + 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR +REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, +INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING +OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED +TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY +YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER +PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE +POSSIBILITY OF SUCH DAMAGES. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +convey the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + + Copyright (C) + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along + with this program; if not, write to the Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + +Also add information on how to contact you by electronic and paper mail. + +If the program is interactive, make it output a short notice like this +when it starts in an interactive mode: + + Gnomovision version 69, Copyright (C) year name of author + Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, the commands you use may +be called something other than `show w' and `show c'; they could even be +mouse-clicks or menu items--whatever suits your program. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the program, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the program + `Gnomovision' (which makes passes at compilers) written by James Hacker. + + , 1 April 1989 + Ty Coon, President of Vice + +This General Public License does not permit incorporating your program into +proprietary programs. If your program is a subroutine library, you may +consider it more useful to permit linking proprietary applications with the +library. If this is what you want to do, use the GNU Lesser General +Public License instead of this License. diff --git a/components/esptool_py/Makefile.projbuild b/components/esptool_py/Makefile.projbuild new file mode 100644 index 0000000000..4bec1f87d6 --- /dev/null +++ b/components/esptool_py/Makefile.projbuild @@ -0,0 +1,25 @@ +# Component support for esptool.py. Doesn't do much by itself, +# components have their own flash targets that can use these variables. +ESPPORT ?= $(CONFIG_ESPTOOLPY_PORT) +ESPBAUD ?= $(CONFIG_ESPTOOLPY_BAUD) + +PYTHON ?= $(call dequote,$(CONFIG_PYTHON)) + +# two commands that can be used from other components +# to invoke esptool.py (with or without serial port args) +# +# NB: esptool.py lives in the sdk/bin directory not the component directory +ESPTOOLPY := $(PYTHON) $(SDK_PATH)/bin/esptool.py --chip esp32 +ESPTOOLPY_SERIAL := $(ESPTOOLPY) --port $(ESPPORT) --baud $(ESPBAUD) + +PROJECT_FLASH_COMMAND=$(ESPTOOLPY_SERIAL) write_flash $(CONFIG_APP_OFFSET) $(PROJECT_BIN) + +$(PROJECT_BIN): $(PROJECT_ELF) + $(Q) $(ESPTOOLPY) elf2image -o $@ $< + +flash: $(PROJECT_BIN) + @echo "Flashing project app to $(CONFIG_APP_OFFSET)..." + $(Q) $(PROJECT_FLASH_COMMAND) + +# convenience target to flash bootloader, partitions, app all at once +flash_all: bootloader-flash partition_table-flash flash diff --git a/components/freertos/Kconfig b/components/freertos/Kconfig new file mode 100644 index 0000000000..8c05199f81 --- /dev/null +++ b/components/freertos/Kconfig @@ -0,0 +1,125 @@ +menu "FreeRTOS" + +# This is actually also handled in the ESP32 startup code, not only in FreeRTOS. +config FREERTOS_UNICORE + bool "Run FreeRTOS only on first core" + default n + help + This version of FreeRTOS normally takes control of all cores of + the CPU. Select this if you only want to start it on the first core. + This is needed when e.g. another process needs complete control + over the second core. + + +choice FREERTOS_CORETIMER + prompt "Xtensa timer to use as the FreeRTOS tick source" + default CONFIG_FREERTOS_CORETIMER_0 + help + FreeRTOS needs a timer with an associated interrupt to use as + the main tick source to increase counters, run timers and do + pre-emptive multitasking with. There are multiple timers available + to do this, with different interrupt priorities. Check + +config FREERTOS_CORETIMER_0 + bool "Timer 0 (int 6, level 1)" + help + Select this to use timer 0 + +config FREERTOS_CORETIMER_1 + bool "Timer 1 (int 15, level 3)" + help + Select this to use timer 1 + +config FREERTOS_CORETIMER_2 + bool "Timer 2 (int 16, level 5)" + help + Select this to use timer 2 + +endchoice + +config FREERTOS_HZ + int "Tick rate (Hz)" + range 1 10000 + default 100 + help + Select the tick rate at which FreeRTOS does pre-emptive context switching. + +choice FREERTOS_CHECK_STACKOVERFLOW + prompt "Check for stack overflow" + default FREERTOS_CHECK_STACKOVERFLOW_QUICK + help + FreeRTOS can check for stack overflows in threads and trigger an user function + called vApplicationStackOverflowHook when this happens. + +config FREERTOS_CHECK_STACKOVERFLOW_NONE + bool "No checking" + help + Do not check for stack overflows (configCHECK_FOR_STACK_OVERFLOW=0) + +config FREERTOS_CHECK_STACKOVERFLOW_PTRVAL + bool "Check by stack pointer value" + help + Check for stack overflows on each context switch by checking if + the stack pointer is in a valid range. Quick but does not detect + stack overflows that happened between context switches + (configCHECK_FOR_STACK_OVERFLOW=1) + +config FREERTOS_CHECK_STACKOVERFLOW_CANARY + bool "Check using canary bytes" + help + Places some magic bytes at the end of the stack area and on each + context switch, check if these bytes are still intact. More thorough + than just checking the pointer, but also slightly slower. + (configCHECK_FOR_STACK_OVERFLOW=2) +endchoice + +config CONFIG_FREERTOS_THREAD_LOCAL_STORAGE_POINTERS + int "Amount of thread local storage pointers" + range 0 256 + default 0 + help + FreeRTOS has the ability to store per-thread pointers in the task + control block. This controls the amount of pointers available; + 0 turns off this functionality. + +#This still needs to be implemented. +choice FREERTOS_PANIC + prompt "Panic handler behaviour" + default FREERTOS_PANIC_PRINT_REBOOT + help + If FreeRTOS detects unexpected behaviour or an unhandled exception, the panic handler is + invoked. Configure the panic handlers action here. + +config FREERTOS_PANIC_PRINT_HALT + bool "Print registers and halt" + help + Outputs the relevant registers over the serial port and halt the + processor. Needs a manual reset to restart. + +config FREERTOS_PANIC_PRINT_REBOOT + bool "Print registers and reboot" + help + Outputs the relevant registers over the serial port and immediately + reset the processor. + +config FREERTOS_PANIC_SILENT_REBOOT + bool "Silent reboot" + help + Just resets the processor without outputting anything + +config FREERTOS_PANIC_GDBSTUB + bool "Invoke GDBStub" + help + Invoke gdbstub on the serial port, allowing for gdb to attach to it to do a postmortem + of the crash. +endchoice + +config FREERTOS_DEBUG_OCDAWARE + bool "Make exception and panic handlers JTAG/OCD aware" + default y + help + The FreeRTOS panic and unhandled exception handers can detect a JTAG OCD debugger and + instead of panicking, have the debugger stop on the offending instruction. + + +endmenu diff --git a/components/freertos/Makefile b/components/freertos/Makefile new file mode 100644 index 0000000000..b00176dd1d --- /dev/null +++ b/components/freertos/Makefile @@ -0,0 +1,13 @@ +# +# Component Makefile +# +# This Makefile should, at the very least, just include $(SDK_PATH)/make/component.mk. By default, +# this will take the sources in this directory, compile them and link them into +# lib(subdirectory_name).a in the build directory. This behaviour is entirely configurable, +# please read the SDK documents if you need to do this. +# + +COMPONENT_ADD_INCLUDEDIRS := include +COMPONENT_PRIV_INCLUDEDIRS := include/freertos + +include $(SDK_PATH)/make/component.mk diff --git a/components/freertos/croutine.c b/components/freertos/croutine.c new file mode 100644 index 0000000000..6a36da9033 --- /dev/null +++ b/components/freertos/croutine.c @@ -0,0 +1,390 @@ +/* + FreeRTOS V8.2.0 - Copyright (C) 2015 Real Time Engineers Ltd. + All rights reserved + + VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION. + + This file is part of the FreeRTOS distribution. + + FreeRTOS is free software; you can redistribute it and/or modify it under + the terms of the GNU General Public License (version 2) as published by the + Free Software Foundation >>!AND MODIFIED BY!<< the FreeRTOS exception. + + *************************************************************************** + >>! NOTE: The modification to the GPL is included to allow you to !<< + >>! distribute a combined work that includes FreeRTOS without being !<< + >>! obliged to provide the source code for proprietary components !<< + >>! outside of the FreeRTOS kernel. !<< + *************************************************************************** + + FreeRTOS is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + FOR A PARTICULAR PURPOSE. Full license text is available on the following + link: http://www.freertos.org/a00114.html + + *************************************************************************** + * * + * FreeRTOS provides completely free yet professionally developed, * + * robust, strictly quality controlled, supported, and cross * + * platform software that is more than just the market leader, it * + * is the industry's de facto standard. * + * * + * Help yourself get started quickly while simultaneously helping * + * to support the FreeRTOS project by purchasing a FreeRTOS * + * tutorial book, reference manual, or both: * + * http://www.FreeRTOS.org/Documentation * + * * + *************************************************************************** + + http://www.FreeRTOS.org/FAQHelp.html - Having a problem? Start by reading + the FAQ page "My application does not run, what could be wrong?". Have you + defined configASSERT()? + + http://www.FreeRTOS.org/support - In return for receiving this top quality + embedded software for free we request you assist our global community by + participating in the support forum. + + http://www.FreeRTOS.org/training - Investing in training allows your team to + be as productive as possible as early as possible. Now you can receive + FreeRTOS training directly from Richard Barry, CEO of Real Time Engineers + Ltd, and the world's leading authority on the world's leading RTOS. + + http://www.FreeRTOS.org/plus - A selection of FreeRTOS ecosystem products, + including FreeRTOS+Trace - an indispensable productivity tool, a DOS + compatible FAT file system, and our tiny thread aware UDP/IP stack. + + http://www.FreeRTOS.org/labs - Where new FreeRTOS products go to incubate. + Come and try FreeRTOS+TCP, our new open source TCP/IP stack for FreeRTOS. + + http://www.OpenRTOS.com - Real Time Engineers ltd. license FreeRTOS to High + Integrity Systems ltd. to sell under the OpenRTOS brand. Low cost OpenRTOS + licenses offer ticketed support, indemnification and commercial middleware. + + http://www.SafeRTOS.com - High Integrity Systems also provide a safety + engineered and independently SIL3 certified version for use in safety and + mission critical applications that require provable dependability. + + 1 tab == 4 spaces! +*/ + +#include "FreeRTOS.h" +#include "task.h" +#include "croutine.h" + +/* + * Some kernel aware debuggers require data to be viewed to be global, rather + * than file scope. + */ +#ifdef portREMOVE_STATIC_QUALIFIER + #define static +#endif + + +/* Lists for ready and blocked co-routines. --------------------*/ +static List_t pxReadyCoRoutineLists[ configMAX_CO_ROUTINE_PRIORITIES ]; /*< Prioritised ready co-routines. */ +static List_t xDelayedCoRoutineList1; /*< Delayed co-routines. */ +static List_t xDelayedCoRoutineList2; /*< Delayed co-routines (two lists are used - one for delays that have overflowed the current tick count. */ +static List_t * pxDelayedCoRoutineList; /*< Points to the delayed co-routine list currently being used. */ +static List_t * pxOverflowDelayedCoRoutineList; /*< Points to the delayed co-routine list currently being used to hold co-routines that have overflowed the current tick count. */ +static List_t xPendingReadyCoRoutineList; /*< Holds co-routines that have been readied by an external event. They cannot be added directly to the ready lists as the ready lists cannot be accessed by interrupts. */ + +/* Other file private variables. --------------------------------*/ +CRCB_t * pxCurrentCoRoutine = NULL; +static UBaseType_t uxTopCoRoutineReadyPriority = 0; +static TickType_t xCoRoutineTickCount = 0, xLastTickCount = 0, xPassedTicks = 0; + +/* The initial state of the co-routine when it is created. */ +#define corINITIAL_STATE ( 0 ) + +/* + * Place the co-routine represented by pxCRCB into the appropriate ready queue + * for the priority. It is inserted at the end of the list. + * + * This macro accesses the co-routine ready lists and therefore must not be + * used from within an ISR. + */ +#define prvAddCoRoutineToReadyQueue( pxCRCB ) \ +{ \ + if( pxCRCB->uxPriority > uxTopCoRoutineReadyPriority ) \ + { \ + uxTopCoRoutineReadyPriority = pxCRCB->uxPriority; \ + } \ + vListInsertEnd( ( List_t * ) &( pxReadyCoRoutineLists[ pxCRCB->uxPriority ] ), &( pxCRCB->xGenericListItem ) ); \ +} + +/* + * Utility to ready all the lists used by the scheduler. This is called + * automatically upon the creation of the first co-routine. + */ +static void prvInitialiseCoRoutineLists( void ); + +/* + * Co-routines that are readied by an interrupt cannot be placed directly into + * the ready lists (there is no mutual exclusion). Instead they are placed in + * in the pending ready list in order that they can later be moved to the ready + * list by the co-routine scheduler. + */ +static void prvCheckPendingReadyList( void ); + +/* + * Macro that looks at the list of co-routines that are currently delayed to + * see if any require waking. + * + * Co-routines are stored in the queue in the order of their wake time - + * meaning once one co-routine has been found whose timer has not expired + * we need not look any further down the list. + */ +static void prvCheckDelayedList( void ); + +/*-----------------------------------------------------------*/ + +BaseType_t xCoRoutineCreate( crCOROUTINE_CODE pxCoRoutineCode, UBaseType_t uxPriority, UBaseType_t uxIndex ) +{ +BaseType_t xReturn; +CRCB_t *pxCoRoutine; + + /* Allocate the memory that will store the co-routine control block. */ + pxCoRoutine = ( CRCB_t * ) pvPortMalloc( sizeof( CRCB_t ) ); + if( pxCoRoutine ) + { + /* If pxCurrentCoRoutine is NULL then this is the first co-routine to + be created and the co-routine data structures need initialising. */ + if( pxCurrentCoRoutine == NULL ) + { + pxCurrentCoRoutine = pxCoRoutine; + prvInitialiseCoRoutineLists(); + } + + /* Check the priority is within limits. */ + if( uxPriority >= configMAX_CO_ROUTINE_PRIORITIES ) + { + uxPriority = configMAX_CO_ROUTINE_PRIORITIES - 1; + } + + /* Fill out the co-routine control block from the function parameters. */ + pxCoRoutine->uxState = corINITIAL_STATE; + pxCoRoutine->uxPriority = uxPriority; + pxCoRoutine->uxIndex = uxIndex; + pxCoRoutine->pxCoRoutineFunction = pxCoRoutineCode; + + /* Initialise all the other co-routine control block parameters. */ + vListInitialiseItem( &( pxCoRoutine->xGenericListItem ) ); + vListInitialiseItem( &( pxCoRoutine->xEventListItem ) ); + + /* Set the co-routine control block as a link back from the ListItem_t. + This is so we can get back to the containing CRCB from a generic item + in a list. */ + listSET_LIST_ITEM_OWNER( &( pxCoRoutine->xGenericListItem ), pxCoRoutine ); + listSET_LIST_ITEM_OWNER( &( pxCoRoutine->xEventListItem ), pxCoRoutine ); + + /* Event lists are always in priority order. */ + listSET_LIST_ITEM_VALUE( &( pxCoRoutine->xEventListItem ), ( ( TickType_t ) configMAX_CO_ROUTINE_PRIORITIES - ( TickType_t ) uxPriority ) ); + + /* Now the co-routine has been initialised it can be added to the ready + list at the correct priority. */ + prvAddCoRoutineToReadyQueue( pxCoRoutine ); + + xReturn = pdPASS; + } + else + { + xReturn = errCOULD_NOT_ALLOCATE_REQUIRED_MEMORY; + } + + return xReturn; +} +/*-----------------------------------------------------------*/ + +void vCoRoutineAddToDelayedList( TickType_t xTicksToDelay, List_t *pxEventList ) +{ +TickType_t xTimeToWake; + + /* Calculate the time to wake - this may overflow but this is + not a problem. */ + xTimeToWake = xCoRoutineTickCount + xTicksToDelay; + + /* We must remove ourselves from the ready list before adding + ourselves to the blocked list as the same list item is used for + both lists. */ + ( void ) uxListRemove( ( ListItem_t * ) &( pxCurrentCoRoutine->xGenericListItem ) ); + + /* The list item will be inserted in wake time order. */ + listSET_LIST_ITEM_VALUE( &( pxCurrentCoRoutine->xGenericListItem ), xTimeToWake ); + + if( xTimeToWake < xCoRoutineTickCount ) + { + /* Wake time has overflowed. Place this item in the + overflow list. */ + vListInsert( ( List_t * ) pxOverflowDelayedCoRoutineList, ( ListItem_t * ) &( pxCurrentCoRoutine->xGenericListItem ) ); + } + else + { + /* The wake time has not overflowed, so we can use the + current block list. */ + vListInsert( ( List_t * ) pxDelayedCoRoutineList, ( ListItem_t * ) &( pxCurrentCoRoutine->xGenericListItem ) ); + } + + if( pxEventList ) + { + /* Also add the co-routine to an event list. If this is done then the + function must be called with interrupts disabled. */ + vListInsert( pxEventList, &( pxCurrentCoRoutine->xEventListItem ) ); + } +} +/*-----------------------------------------------------------*/ + +static void prvCheckPendingReadyList( void ) +{ + /* Are there any co-routines waiting to get moved to the ready list? These + are co-routines that have been readied by an ISR. The ISR cannot access + the ready lists itself. */ + while( listLIST_IS_EMPTY( &xPendingReadyCoRoutineList ) == pdFALSE ) + { + CRCB_t *pxUnblockedCRCB; + + /* The pending ready list can be accessed by an ISR. */ + portDISABLE_INTERRUPTS(); + { + pxUnblockedCRCB = ( CRCB_t * ) listGET_OWNER_OF_HEAD_ENTRY( (&xPendingReadyCoRoutineList) ); + ( void ) uxListRemove( &( pxUnblockedCRCB->xEventListItem ) ); + } + portENABLE_INTERRUPTS(); + + ( void ) uxListRemove( &( pxUnblockedCRCB->xGenericListItem ) ); + prvAddCoRoutineToReadyQueue( pxUnblockedCRCB ); + } +} +/*-----------------------------------------------------------*/ + +static void prvCheckDelayedList( void ) +{ +CRCB_t *pxCRCB; + + xPassedTicks = xTaskGetTickCount() - xLastTickCount; + while( xPassedTicks ) + { + xCoRoutineTickCount++; + xPassedTicks--; + + /* If the tick count has overflowed we need to swap the ready lists. */ + if( xCoRoutineTickCount == 0 ) + { + List_t * pxTemp; + + /* Tick count has overflowed so we need to swap the delay lists. If there are + any items in pxDelayedCoRoutineList here then there is an error! */ + pxTemp = pxDelayedCoRoutineList; + pxDelayedCoRoutineList = pxOverflowDelayedCoRoutineList; + pxOverflowDelayedCoRoutineList = pxTemp; + } + + /* See if this tick has made a timeout expire. */ + while( listLIST_IS_EMPTY( pxDelayedCoRoutineList ) == pdFALSE ) + { + pxCRCB = ( CRCB_t * ) listGET_OWNER_OF_HEAD_ENTRY( pxDelayedCoRoutineList ); + + if( xCoRoutineTickCount < listGET_LIST_ITEM_VALUE( &( pxCRCB->xGenericListItem ) ) ) + { + /* Timeout not yet expired. */ + break; + } + + portDISABLE_INTERRUPTS(); + { + /* The event could have occurred just before this critical + section. If this is the case then the generic list item will + have been moved to the pending ready list and the following + line is still valid. Also the pvContainer parameter will have + been set to NULL so the following lines are also valid. */ + ( void ) uxListRemove( &( pxCRCB->xGenericListItem ) ); + + /* Is the co-routine waiting on an event also? */ + if( pxCRCB->xEventListItem.pvContainer ) + { + ( void ) uxListRemove( &( pxCRCB->xEventListItem ) ); + } + } + portENABLE_INTERRUPTS(); + + prvAddCoRoutineToReadyQueue( pxCRCB ); + } + } + + xLastTickCount = xCoRoutineTickCount; +} +/*-----------------------------------------------------------*/ + +void vCoRoutineSchedule( void ) +{ + /* See if any co-routines readied by events need moving to the ready lists. */ + prvCheckPendingReadyList(); + + /* See if any delayed co-routines have timed out. */ + prvCheckDelayedList(); + + /* Find the highest priority queue that contains ready co-routines. */ + while( listLIST_IS_EMPTY( &( pxReadyCoRoutineLists[ uxTopCoRoutineReadyPriority ] ) ) ) + { + if( uxTopCoRoutineReadyPriority == 0 ) + { + /* No more co-routines to check. */ + return; + } + --uxTopCoRoutineReadyPriority; + } + + /* listGET_OWNER_OF_NEXT_ENTRY walks through the list, so the co-routines + of the same priority get an equal share of the processor time. */ + listGET_OWNER_OF_NEXT_ENTRY( pxCurrentCoRoutine, &( pxReadyCoRoutineLists[ uxTopCoRoutineReadyPriority ] ) ); + + /* Call the co-routine. */ + ( pxCurrentCoRoutine->pxCoRoutineFunction )( pxCurrentCoRoutine, pxCurrentCoRoutine->uxIndex ); + + return; +} +/*-----------------------------------------------------------*/ + +static void prvInitialiseCoRoutineLists( void ) +{ +UBaseType_t uxPriority; + + for( uxPriority = 0; uxPriority < configMAX_CO_ROUTINE_PRIORITIES; uxPriority++ ) + { + vListInitialise( ( List_t * ) &( pxReadyCoRoutineLists[ uxPriority ] ) ); + } + + vListInitialise( ( List_t * ) &xDelayedCoRoutineList1 ); + vListInitialise( ( List_t * ) &xDelayedCoRoutineList2 ); + vListInitialise( ( List_t * ) &xPendingReadyCoRoutineList ); + + /* Start with pxDelayedCoRoutineList using list1 and the + pxOverflowDelayedCoRoutineList using list2. */ + pxDelayedCoRoutineList = &xDelayedCoRoutineList1; + pxOverflowDelayedCoRoutineList = &xDelayedCoRoutineList2; +} +/*-----------------------------------------------------------*/ + +BaseType_t xCoRoutineRemoveFromEventList( const List_t *pxEventList ) +{ +CRCB_t *pxUnblockedCRCB; +BaseType_t xReturn; + + /* This function is called from within an interrupt. It can only access + event lists and the pending ready list. This function assumes that a + check has already been made to ensure pxEventList is not empty. */ + pxUnblockedCRCB = ( CRCB_t * ) listGET_OWNER_OF_HEAD_ENTRY( pxEventList ); + ( void ) uxListRemove( &( pxUnblockedCRCB->xEventListItem ) ); + vListInsertEnd( ( List_t * ) &( xPendingReadyCoRoutineList ), &( pxUnblockedCRCB->xEventListItem ) ); + + if( pxUnblockedCRCB->uxPriority >= pxCurrentCoRoutine->uxPriority ) + { + xReturn = pdTRUE; + } + else + { + xReturn = pdFALSE; + } + + return xReturn; +} + diff --git a/components/freertos/event_groups.c b/components/freertos/event_groups.c new file mode 100644 index 0000000000..1aa95e0841 --- /dev/null +++ b/components/freertos/event_groups.c @@ -0,0 +1,695 @@ +/* + FreeRTOS V8.2.0 - Copyright (C) 2015 Real Time Engineers Ltd. + All rights reserved + + VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION. + + This file is part of the FreeRTOS distribution. + + FreeRTOS is free software; you can redistribute it and/or modify it under + the terms of the GNU General Public License (version 2) as published by the + Free Software Foundation >>!AND MODIFIED BY!<< the FreeRTOS exception. + + *************************************************************************** + >>! NOTE: The modification to the GPL is included to allow you to !<< + >>! distribute a combined work that includes FreeRTOS without being !<< + >>! obliged to provide the source code for proprietary components !<< + >>! outside of the FreeRTOS kernel. !<< + *************************************************************************** + + FreeRTOS is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + FOR A PARTICULAR PURPOSE. Full license text is available on the following + link: http://www.freertos.org/a00114.html + + *************************************************************************** + * * + * FreeRTOS provides completely free yet professionally developed, * + * robust, strictly quality controlled, supported, and cross * + * platform software that is more than just the market leader, it * + * is the industry's de facto standard. * + * * + * Help yourself get started quickly while simultaneously helping * + * to support the FreeRTOS project by purchasing a FreeRTOS * + * tutorial book, reference manual, or both: * + * http://www.FreeRTOS.org/Documentation * + * * + *************************************************************************** + + http://www.FreeRTOS.org/FAQHelp.html - Having a problem? Start by reading + the FAQ page "My application does not run, what could be wrong?". Have you + defined configASSERT()? + + http://www.FreeRTOS.org/support - In return for receiving this top quality + embedded software for free we request you assist our global community by + participating in the support forum. + + http://www.FreeRTOS.org/training - Investing in training allows your team to + be as productive as possible as early as possible. Now you can receive + FreeRTOS training directly from Richard Barry, CEO of Real Time Engineers + Ltd, and the world's leading authority on the world's leading RTOS. + + http://www.FreeRTOS.org/plus - A selection of FreeRTOS ecosystem products, + including FreeRTOS+Trace - an indispensable productivity tool, a DOS + compatible FAT file system, and our tiny thread aware UDP/IP stack. + + http://www.FreeRTOS.org/labs - Where new FreeRTOS products go to incubate. + Come and try FreeRTOS+TCP, our new open source TCP/IP stack for FreeRTOS. + + http://www.OpenRTOS.com - Real Time Engineers ltd. license FreeRTOS to High + Integrity Systems ltd. to sell under the OpenRTOS brand. Low cost OpenRTOS + licenses offer ticketed support, indemnification and commercial middleware. + + http://www.SafeRTOS.com - High Integrity Systems also provide a safety + engineered and independently SIL3 certified version for use in safety and + mission critical applications that require provable dependability. + + 1 tab == 4 spaces! +*/ + +/* Standard includes. */ +#include + +/* Defining MPU_WRAPPERS_INCLUDED_FROM_API_FILE prevents task.h from redefining +all the API functions to use the MPU wrappers. That should only be done when +task.h is included from an application file. */ +#define MPU_WRAPPERS_INCLUDED_FROM_API_FILE + +/* FreeRTOS includes. */ +#include "FreeRTOS.h" +#include "task.h" +#include "timers.h" +#include "event_groups.h" + +/* Lint e961 and e750 are suppressed as a MISRA exception justified because the +MPU ports require MPU_WRAPPERS_INCLUDED_FROM_API_FILE to be defined for the +header files above, but not in this file, in order to generate the correct +privileged Vs unprivileged linkage and placement. */ +#undef MPU_WRAPPERS_INCLUDED_FROM_API_FILE /*lint !e961 !e750. */ + +#if ( INCLUDE_xEventGroupSetBitFromISR == 1 ) && ( configUSE_TIMERS == 0 ) + #error configUSE_TIMERS must be set to 1 to make the xEventGroupSetBitFromISR() function available. +#endif + +#if ( INCLUDE_xEventGroupSetBitFromISR == 1 ) && ( INCLUDE_xTimerPendFunctionCall == 0 ) + #error INCLUDE_xTimerPendFunctionCall must also be set to one to make the xEventGroupSetBitFromISR() function available. +#endif + +/* The following bit fields convey control information in a task's event list +item value. It is important they don't clash with the +taskEVENT_LIST_ITEM_VALUE_IN_USE definition. */ +#if configUSE_16_BIT_TICKS == 1 + #define eventCLEAR_EVENTS_ON_EXIT_BIT 0x0100U + #define eventUNBLOCKED_DUE_TO_BIT_SET 0x0200U + #define eventWAIT_FOR_ALL_BITS 0x0400U + #define eventEVENT_BITS_CONTROL_BYTES 0xff00U +#else + #define eventCLEAR_EVENTS_ON_EXIT_BIT 0x01000000UL + #define eventUNBLOCKED_DUE_TO_BIT_SET 0x02000000UL + #define eventWAIT_FOR_ALL_BITS 0x04000000UL + #define eventEVENT_BITS_CONTROL_BYTES 0xff000000UL +#endif + +typedef struct xEventGroupDefinition +{ + EventBits_t uxEventBits; + List_t xTasksWaitingForBits; /*< List of tasks waiting for a bit to be set. */ + + #if( configUSE_TRACE_FACILITY == 1 ) + UBaseType_t uxEventGroupNumber; + #endif + +} EventGroup_t; + + +/* Again: one mux for all events. Maybe this can be made more granular. ToDo: look into that. -JD */ +static portMUX_TYPE xEventGroupMux; +static BaseType_t xMuxInitialized = pdFALSE; + + +/*-----------------------------------------------------------*/ + +/* + * Test the bits set in uxCurrentEventBits to see if the wait condition is met. + * The wait condition is defined by xWaitForAllBits. If xWaitForAllBits is + * pdTRUE then the wait condition is met if all the bits set in uxBitsToWaitFor + * are also set in uxCurrentEventBits. If xWaitForAllBits is pdFALSE then the + * wait condition is met if any of the bits set in uxBitsToWait for are also set + * in uxCurrentEventBits. + */ +static BaseType_t prvTestWaitCondition( const EventBits_t uxCurrentEventBits, const EventBits_t uxBitsToWaitFor, const BaseType_t xWaitForAllBits ); + +/*-----------------------------------------------------------*/ + +EventGroupHandle_t xEventGroupCreate( void ) +{ +EventGroup_t *pxEventBits; + + //Initialize mux, if needed + if ( xMuxInitialized == pdFALSE ) { + vPortCPUInitializeMutex( & xEventGroupMux ); + xMuxInitialized = pdTRUE; + } + + pxEventBits = pvPortMalloc( sizeof( EventGroup_t ) ); + if( pxEventBits != NULL ) + { + pxEventBits->uxEventBits = 0; + vListInitialise( &( pxEventBits->xTasksWaitingForBits ) ); + traceEVENT_GROUP_CREATE( pxEventBits ); + } + else + { + traceEVENT_GROUP_CREATE_FAILED(); + } + + return ( EventGroupHandle_t ) pxEventBits; +} +/*-----------------------------------------------------------*/ + +EventBits_t xEventGroupSync( EventGroupHandle_t xEventGroup, const EventBits_t uxBitsToSet, const EventBits_t uxBitsToWaitFor, TickType_t xTicksToWait ) +{ +EventBits_t uxOriginalBitValue, uxReturn; +EventGroup_t *pxEventBits = ( EventGroup_t * ) xEventGroup; +BaseType_t xAlreadyYielded; +BaseType_t xTimeoutOccurred = pdFALSE; + + configASSERT( ( uxBitsToWaitFor & eventEVENT_BITS_CONTROL_BYTES ) == 0 ); + configASSERT( uxBitsToWaitFor != 0 ); + #if ( ( INCLUDE_xTaskGetSchedulerState == 1 ) || ( configUSE_TIMERS == 1 ) ) + { + configASSERT( !( ( xTaskGetSchedulerState() == taskSCHEDULER_SUSPENDED ) && ( xTicksToWait != 0 ) ) ); + } + #endif + + vTaskSuspendAll(); + { + uxOriginalBitValue = pxEventBits->uxEventBits; + + ( void ) xEventGroupSetBits( xEventGroup, uxBitsToSet ); + + if( ( ( uxOriginalBitValue | uxBitsToSet ) & uxBitsToWaitFor ) == uxBitsToWaitFor ) + { + /* All the rendezvous bits are now set - no need to block. */ + uxReturn = ( uxOriginalBitValue | uxBitsToSet ); + + /* Rendezvous always clear the bits. They will have been cleared + already unless this is the only task in the rendezvous. */ + pxEventBits->uxEventBits &= ~uxBitsToWaitFor; + + xTicksToWait = 0; + } + else + { + if( xTicksToWait != ( TickType_t ) 0 ) + { + traceEVENT_GROUP_SYNC_BLOCK( xEventGroup, uxBitsToSet, uxBitsToWaitFor ); + + /* Store the bits that the calling task is waiting for in the + task's event list item so the kernel knows when a match is + found. Then enter the blocked state. */ + vTaskPlaceOnUnorderedEventList( &( pxEventBits->xTasksWaitingForBits ), ( uxBitsToWaitFor | eventCLEAR_EVENTS_ON_EXIT_BIT | eventWAIT_FOR_ALL_BITS ), xTicksToWait ); + + /* This assignment is obsolete as uxReturn will get set after + the task unblocks, but some compilers mistakenly generate a + warning about uxReturn being returned without being set if the + assignment is omitted. */ + uxReturn = 0; + } + else + { + /* The rendezvous bits were not set, but no block time was + specified - just return the current event bit value. */ + uxReturn = pxEventBits->uxEventBits; + } + } + } + xAlreadyYielded = xTaskResumeAll(); + + if( xTicksToWait != ( TickType_t ) 0 ) + { + if( xAlreadyYielded == pdFALSE ) + { + portYIELD_WITHIN_API(); + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + + /* The task blocked to wait for its required bits to be set - at this + point either the required bits were set or the block time expired. If + the required bits were set they will have been stored in the task's + event list item, and they should now be retrieved then cleared. */ + uxReturn = uxTaskResetEventItemValue(); + + if( ( uxReturn & eventUNBLOCKED_DUE_TO_BIT_SET ) == ( EventBits_t ) 0 ) + { + /* The task timed out, just return the current event bit value. */ + taskENTER_CRITICAL( &xEventGroupMux ); + { + uxReturn = pxEventBits->uxEventBits; + + /* Although the task got here because it timed out before the + bits it was waiting for were set, it is possible that since it + unblocked another task has set the bits. If this is the case + then it needs to clear the bits before exiting. */ + if( ( uxReturn & uxBitsToWaitFor ) == uxBitsToWaitFor ) + { + pxEventBits->uxEventBits &= ~uxBitsToWaitFor; + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } + taskEXIT_CRITICAL( &xEventGroupMux ); + + xTimeoutOccurred = pdTRUE; + } + else + { + /* The task unblocked because the bits were set. */ + } + + /* Control bits might be set as the task had blocked should not be + returned. */ + uxReturn &= ~eventEVENT_BITS_CONTROL_BYTES; + } + + traceEVENT_GROUP_SYNC_END( xEventGroup, uxBitsToSet, uxBitsToWaitFor, xTimeoutOccurred ); + + return uxReturn; +} +/*-----------------------------------------------------------*/ + +EventBits_t xEventGroupWaitBits( EventGroupHandle_t xEventGroup, const EventBits_t uxBitsToWaitFor, const BaseType_t xClearOnExit, const BaseType_t xWaitForAllBits, TickType_t xTicksToWait ) +{ +EventGroup_t *pxEventBits = ( EventGroup_t * ) xEventGroup; +EventBits_t uxReturn, uxControlBits = 0; +BaseType_t xWaitConditionMet, xAlreadyYielded; +BaseType_t xTimeoutOccurred = pdFALSE; + + /* Check the user is not attempting to wait on the bits used by the kernel + itself, and that at least one bit is being requested. */ + configASSERT( xEventGroup ); + configASSERT( ( uxBitsToWaitFor & eventEVENT_BITS_CONTROL_BYTES ) == 0 ); + configASSERT( uxBitsToWaitFor != 0 ); + #if ( ( INCLUDE_xTaskGetSchedulerState == 1 ) || ( configUSE_TIMERS == 1 ) ) + { + configASSERT( !( ( xTaskGetSchedulerState() == taskSCHEDULER_SUSPENDED ) && ( xTicksToWait != 0 ) ) ); + } + #endif + + vTaskSuspendAll(); + { + const EventBits_t uxCurrentEventBits = pxEventBits->uxEventBits; + + /* Check to see if the wait condition is already met or not. */ + xWaitConditionMet = prvTestWaitCondition( uxCurrentEventBits, uxBitsToWaitFor, xWaitForAllBits ); + + if( xWaitConditionMet != pdFALSE ) + { + /* The wait condition has already been met so there is no need to + block. */ + uxReturn = uxCurrentEventBits; + xTicksToWait = ( TickType_t ) 0; + + /* Clear the wait bits if requested to do so. */ + if( xClearOnExit != pdFALSE ) + { + pxEventBits->uxEventBits &= ~uxBitsToWaitFor; + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } + else if( xTicksToWait == ( TickType_t ) 0 ) + { + /* The wait condition has not been met, but no block time was + specified, so just return the current value. */ + uxReturn = uxCurrentEventBits; + } + else + { + /* The task is going to block to wait for its required bits to be + set. uxControlBits are used to remember the specified behaviour of + this call to xEventGroupWaitBits() - for use when the event bits + unblock the task. */ + if( xClearOnExit != pdFALSE ) + { + uxControlBits |= eventCLEAR_EVENTS_ON_EXIT_BIT; + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + + if( xWaitForAllBits != pdFALSE ) + { + uxControlBits |= eventWAIT_FOR_ALL_BITS; + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + + /* Store the bits that the calling task is waiting for in the + task's event list item so the kernel knows when a match is + found. Then enter the blocked state. */ + vTaskPlaceOnUnorderedEventList( &( pxEventBits->xTasksWaitingForBits ), ( uxBitsToWaitFor | uxControlBits ), xTicksToWait ); + + /* This is obsolete as it will get set after the task unblocks, but + some compilers mistakenly generate a warning about the variable + being returned without being set if it is not done. */ + uxReturn = 0; + + traceEVENT_GROUP_WAIT_BITS_BLOCK( xEventGroup, uxBitsToWaitFor ); + } + } + xAlreadyYielded = xTaskResumeAll(); + + if( xTicksToWait != ( TickType_t ) 0 ) + { + if( xAlreadyYielded == pdFALSE ) + { + portYIELD_WITHIN_API(); + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + + /* The task blocked to wait for its required bits to be set - at this + point either the required bits were set or the block time expired. If + the required bits were set they will have been stored in the task's + event list item, and they should now be retrieved then cleared. */ + uxReturn = uxTaskResetEventItemValue(); + + if( ( uxReturn & eventUNBLOCKED_DUE_TO_BIT_SET ) == ( EventBits_t ) 0 ) + { + taskENTER_CRITICAL( &xEventGroupMux ); + { + /* The task timed out, just return the current event bit value. */ + uxReturn = pxEventBits->uxEventBits; + + /* It is possible that the event bits were updated between this + task leaving the Blocked state and running again. */ + if( prvTestWaitCondition( uxReturn, uxBitsToWaitFor, xWaitForAllBits ) != pdFALSE ) + { + if( xClearOnExit != pdFALSE ) + { + pxEventBits->uxEventBits &= ~uxBitsToWaitFor; + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } + taskEXIT_CRITICAL( &xEventGroupMux ); + + /* Prevent compiler warnings when trace macros are not used. */ + xTimeoutOccurred = pdFALSE; + } + else + { + /* The task unblocked because the bits were set. */ + } + + /* The task blocked so control bits may have been set. */ + uxReturn &= ~eventEVENT_BITS_CONTROL_BYTES; + } + traceEVENT_GROUP_WAIT_BITS_END( xEventGroup, uxBitsToWaitFor, xTimeoutOccurred ); + + return uxReturn; +} +/*-----------------------------------------------------------*/ + +EventBits_t xEventGroupClearBits( EventGroupHandle_t xEventGroup, const EventBits_t uxBitsToClear ) +{ +EventGroup_t *pxEventBits = ( EventGroup_t * ) xEventGroup; +EventBits_t uxReturn; + + /* Check the user is not attempting to clear the bits used by the kernel + itself. */ + configASSERT( xEventGroup ); + configASSERT( ( uxBitsToClear & eventEVENT_BITS_CONTROL_BYTES ) == 0 ); + + taskENTER_CRITICAL( &xEventGroupMux ); + { + traceEVENT_GROUP_CLEAR_BITS( xEventGroup, uxBitsToClear ); + + /* The value returned is the event group value prior to the bits being + cleared. */ + uxReturn = pxEventBits->uxEventBits; + + /* Clear the bits. */ + pxEventBits->uxEventBits &= ~uxBitsToClear; + } + taskEXIT_CRITICAL( &xEventGroupMux ); + + return uxReturn; +} +/*-----------------------------------------------------------*/ + +#if ( ( configUSE_TRACE_FACILITY == 1 ) && ( INCLUDE_xTimerPendFunctionCall == 1 ) && ( configUSE_TIMERS == 1 ) ) + + BaseType_t xEventGroupClearBitsFromISR( EventGroupHandle_t xEventGroup, const EventBits_t uxBitsToClear ) + { + BaseType_t xReturn; + + traceEVENT_GROUP_CLEAR_BITS_FROM_ISR( xEventGroup, uxBitsToClear ); + xReturn = xTimerPendFunctionCallFromISR( vEventGroupClearBitsCallback, ( void * ) xEventGroup, ( uint32_t ) uxBitsToClear, NULL ); + + return xReturn; + } + +#endif +/*-----------------------------------------------------------*/ + +EventBits_t xEventGroupGetBitsFromISR( EventGroupHandle_t xEventGroup ) +{ +UBaseType_t uxSavedInterruptStatus; +EventGroup_t *pxEventBits = ( EventGroup_t * ) xEventGroup; +EventBits_t uxReturn; + + uxSavedInterruptStatus = portSET_INTERRUPT_MASK_FROM_ISR(); + { + uxReturn = pxEventBits->uxEventBits; + } + portCLEAR_INTERRUPT_MASK_FROM_ISR( uxSavedInterruptStatus ); + + return uxReturn; +} +/*-----------------------------------------------------------*/ + +EventBits_t xEventGroupSetBits( EventGroupHandle_t xEventGroup, const EventBits_t uxBitsToSet ) +{ +ListItem_t *pxListItem, *pxNext; +ListItem_t const *pxListEnd; +List_t *pxList; +EventBits_t uxBitsToClear = 0, uxBitsWaitedFor, uxControlBits; +EventGroup_t *pxEventBits = ( EventGroup_t * ) xEventGroup; +BaseType_t xMatchFound = pdFALSE; + + /* Check the user is not attempting to set the bits used by the kernel + itself. */ + configASSERT( xEventGroup ); + configASSERT( ( uxBitsToSet & eventEVENT_BITS_CONTROL_BYTES ) == 0 ); + + pxList = &( pxEventBits->xTasksWaitingForBits ); + pxListEnd = listGET_END_MARKER( pxList ); /*lint !e826 !e740 The mini list structure is used as the list end to save RAM. This is checked and valid. */ + vTaskSuspendAll(); + { + traceEVENT_GROUP_SET_BITS( xEventGroup, uxBitsToSet ); + + pxListItem = listGET_HEAD_ENTRY( pxList ); + + /* Set the bits. */ + pxEventBits->uxEventBits |= uxBitsToSet; + + /* See if the new bit value should unblock any tasks. */ + while( pxListItem != pxListEnd ) + { + pxNext = listGET_NEXT( pxListItem ); + uxBitsWaitedFor = listGET_LIST_ITEM_VALUE( pxListItem ); + xMatchFound = pdFALSE; + + /* Split the bits waited for from the control bits. */ + uxControlBits = uxBitsWaitedFor & eventEVENT_BITS_CONTROL_BYTES; + uxBitsWaitedFor &= ~eventEVENT_BITS_CONTROL_BYTES; + + if( ( uxControlBits & eventWAIT_FOR_ALL_BITS ) == ( EventBits_t ) 0 ) + { + /* Just looking for single bit being set. */ + if( ( uxBitsWaitedFor & pxEventBits->uxEventBits ) != ( EventBits_t ) 0 ) + { + xMatchFound = pdTRUE; + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } + else if( ( uxBitsWaitedFor & pxEventBits->uxEventBits ) == uxBitsWaitedFor ) + { + /* All bits are set. */ + xMatchFound = pdTRUE; + } + else + { + /* Need all bits to be set, but not all the bits were set. */ + } + + if( xMatchFound != pdFALSE ) + { + /* The bits match. Should the bits be cleared on exit? */ + if( ( uxControlBits & eventCLEAR_EVENTS_ON_EXIT_BIT ) != ( EventBits_t ) 0 ) + { + uxBitsToClear |= uxBitsWaitedFor; + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + + /* Store the actual event flag value in the task's event list + item before removing the task from the event list. The + eventUNBLOCKED_DUE_TO_BIT_SET bit is set so the task knows + that is was unblocked due to its required bits matching, rather + than because it timed out. */ + ( void ) xTaskRemoveFromUnorderedEventList( pxListItem, pxEventBits->uxEventBits | eventUNBLOCKED_DUE_TO_BIT_SET ); + } + + /* Move onto the next list item. Note pxListItem->pxNext is not + used here as the list item may have been removed from the event list + and inserted into the ready/pending reading list. */ + pxListItem = pxNext; + } + + /* Clear any bits that matched when the eventCLEAR_EVENTS_ON_EXIT_BIT + bit was set in the control word. */ + pxEventBits->uxEventBits &= ~uxBitsToClear; + } + ( void ) xTaskResumeAll(); + + return pxEventBits->uxEventBits; +} +/*-----------------------------------------------------------*/ + +void vEventGroupDelete( EventGroupHandle_t xEventGroup ) +{ +EventGroup_t *pxEventBits = ( EventGroup_t * ) xEventGroup; +const List_t *pxTasksWaitingForBits = &( pxEventBits->xTasksWaitingForBits ); + + vTaskSuspendAll(); + { + traceEVENT_GROUP_DELETE( xEventGroup ); + + while( listCURRENT_LIST_LENGTH( pxTasksWaitingForBits ) > ( UBaseType_t ) 0 ) + { + /* Unblock the task, returning 0 as the event list is being deleted + and cannot therefore have any bits set. */ + configASSERT( pxTasksWaitingForBits->xListEnd.pxNext != ( ListItem_t * ) &( pxTasksWaitingForBits->xListEnd ) ); + ( void ) xTaskRemoveFromUnorderedEventList( pxTasksWaitingForBits->xListEnd.pxNext, eventUNBLOCKED_DUE_TO_BIT_SET ); + } + + vPortFree( pxEventBits ); + } + ( void ) xTaskResumeAll(); +} +/*-----------------------------------------------------------*/ + +/* For internal use only - execute a 'set bits' command that was pended from +an interrupt. */ +void vEventGroupSetBitsCallback( void *pvEventGroup, const uint32_t ulBitsToSet ) +{ + ( void ) xEventGroupSetBits( pvEventGroup, ( EventBits_t ) ulBitsToSet ); +} +/*-----------------------------------------------------------*/ + +/* For internal use only - execute a 'clear bits' command that was pended from +an interrupt. */ +void vEventGroupClearBitsCallback( void *pvEventGroup, const uint32_t ulBitsToClear ) +{ + ( void ) xEventGroupClearBits( pvEventGroup, ( EventBits_t ) ulBitsToClear ); +} +/*-----------------------------------------------------------*/ + +static BaseType_t prvTestWaitCondition( const EventBits_t uxCurrentEventBits, const EventBits_t uxBitsToWaitFor, const BaseType_t xWaitForAllBits ) +{ +BaseType_t xWaitConditionMet = pdFALSE; + + if( xWaitForAllBits == pdFALSE ) + { + /* Task only has to wait for one bit within uxBitsToWaitFor to be + set. Is one already set? */ + if( ( uxCurrentEventBits & uxBitsToWaitFor ) != ( EventBits_t ) 0 ) + { + xWaitConditionMet = pdTRUE; + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } + else + { + /* Task has to wait for all the bits in uxBitsToWaitFor to be set. + Are they set already? */ + if( ( uxCurrentEventBits & uxBitsToWaitFor ) == uxBitsToWaitFor ) + { + xWaitConditionMet = pdTRUE; + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } + + return xWaitConditionMet; +} +/*-----------------------------------------------------------*/ + +#if ( ( configUSE_TRACE_FACILITY == 1 ) && ( INCLUDE_xTimerPendFunctionCall == 1 ) && ( configUSE_TIMERS == 1 ) ) + + BaseType_t xEventGroupSetBitsFromISR( EventGroupHandle_t xEventGroup, const EventBits_t uxBitsToSet, BaseType_t *pxHigherPriorityTaskWoken ) + { + BaseType_t xReturn; + + traceEVENT_GROUP_SET_BITS_FROM_ISR( xEventGroup, uxBitsToSet ); + xReturn = xTimerPendFunctionCallFromISR( vEventGroupSetBitsCallback, ( void * ) xEventGroup, ( uint32_t ) uxBitsToSet, pxHigherPriorityTaskWoken ); + + return xReturn; + } + +#endif +/*-----------------------------------------------------------*/ + +#if (configUSE_TRACE_FACILITY == 1) + + UBaseType_t uxEventGroupGetNumber( void* xEventGroup ) + { + UBaseType_t xReturn; + EventGroup_t *pxEventBits = ( EventGroup_t * ) xEventGroup; + + if( xEventGroup == NULL ) + { + xReturn = 0; + } + else + { + xReturn = pxEventBits->uxEventGroupNumber; + } + + return xReturn; + } + +#endif + diff --git a/components/freertos/gdbstub.c b/components/freertos/gdbstub.c new file mode 100644 index 0000000000..ca2395f772 --- /dev/null +++ b/components/freertos/gdbstub.c @@ -0,0 +1,365 @@ +// Copyright 2015-2016 Espressif Systems (Shanghai) PTE LTD +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at + +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +/****************************************************************************** + * Description: A stub to make the ESP32 debuggable by GDB over the serial + * port, at least enough to do a backtrace on panic. This gdbstub is read-only: + * it allows inspecting the ESP32 state + *******************************************************************************/ + +//ToDo: Clean up includes and sync to real rtos +#include "rom/ets_sys.h" + +#include "soc/uart_register.h" +#include "soc/io_mux_reg.h" + +#include "gdbstub.h" + +//Length of buffer used to reserve GDB commands. Has to be at least able to fit the G command, which +//implies a minimum size of about 320 bytes. +#define PBUFLEN 512 + +static unsigned char cmd[PBUFLEN]; //GDB command input buffer +static char chsum; //Running checksum of the output packet + +#define ATTR_GDBFN + +static void ATTR_GDBFN keepWDTalive() { + //ToDo for esp31/32 +} + + +//Receive a char from the uart. Uses polling and feeds the watchdog. +static int ATTR_GDBFN gdbRecvChar() { + int i; + while (((READ_PERI_REG(UART_STATUS_REG(0))>>UART_RXFIFO_CNT_S)&UART_RXFIFO_CNT)==0) { + keepWDTalive(); + } + i=READ_PERI_REG(UART_FIFO_REG(0)); + return i; +} + +//Send a char to the uart. +static void ATTR_GDBFN gdbSendChar(char c) { + while (((READ_PERI_REG(UART_STATUS_REG(0))>>UART_TXFIFO_CNT_S)&UART_TXFIFO_CNT)>=126) ; + WRITE_PERI_REG(UART_FIFO_REG(0), c); +} + +//Send the start of a packet; reset checksum calculation. +static void ATTR_GDBFN gdbPacketStart() { + chsum=0; + gdbSendChar('$'); +} + +//Send a char as part of a packet +static void ATTR_GDBFN gdbPacketChar(char c) { + if (c=='#' || c=='$' || c=='}' || c=='*') { + gdbSendChar('}'); + gdbSendChar(c^0x20); + chsum+=(c^0x20)+'}'; + } else { + gdbSendChar(c); + chsum+=c; + } +} + +//Send a string as part of a packet +static void ATTR_GDBFN gdbPacketStr(char *c) { + while (*c!=0) { + gdbPacketChar(*c); + c++; + } +} + +//Send a hex val as part of a packet. 'bits'/4 dictates the number of hex chars sent. +static void ATTR_GDBFN gdbPacketHex(int val, int bits) { + char hexChars[]="0123456789abcdef"; + int i; + for (i=bits; i>0; i-=4) { + gdbPacketChar(hexChars[(val>>(i-4))&0xf]); + } +} + +//Finish sending a packet. +static void ATTR_GDBFN gdbPacketEnd() { + gdbSendChar('#'); + gdbPacketHex(chsum, 8); +} + +//Error states used by the routines that grab stuff from the incoming gdb packet +#define ST_ENDPACKET -1 +#define ST_ERR -2 +#define ST_OK -3 +#define ST_CONT -4 + +//Grab a hex value from the gdb packet. Ptr will get positioned on the end +//of the hex string, as far as the routine has read into it. Bits/4 indicates +//the max amount of hex chars it gobbles up. Bits can be -1 to eat up as much +//hex chars as possible. +static long ATTR_GDBFN gdbGetHexVal(unsigned char **ptr, int bits) { + int i; + int no; + unsigned int v=0; + char c; + no=bits/4; + if (bits==-1) no=64; + for (i=0; i='0' && c<='9') { + v<<=4; + v|=(c-'0'); + } else if (c>='A' && c<='F') { + v<<=4; + v|=(c-'A')+10; + } else if (c>='a' && c<='f') { + v<<=4; + v|=(c-'a')+10; + } else if (c=='#') { + if (bits==-1) { + (*ptr)--; + return v; + } + return ST_ENDPACKET; + } else { + if (bits==-1) { + (*ptr)--; + return v; + } + return ST_ERR; + } + } + return v; +} + +//Swap an int into the form gdb wants it +static int ATTR_GDBFN iswap(int i) { + int r; + r=((i>>24)&0xff); + r|=((i>>16)&0xff)<<8; + r|=((i>>8)&0xff)<<16; + r|=((i>>0)&0xff)<<24; + return r; +} + +//Read a byte from ESP32 memory. +static unsigned char ATTR_GDBFN readbyte(unsigned int p) { + int *i=(int*)(p&(~3)); + if (p<0x20000000 || p>=0x80000000) return -1; + return *i>>((p&3)*8); +} + + +//Register file in the format exp108 gdb port expects it. +//Inspired by gdb/regformats/reg-xtensa.dat +typedef struct { + uint32_t pc; + uint32_t a[64]; + uint32_t lbeg; + uint32_t lend; + uint32_t lcount; + uint32_t sar; + uint32_t windowbase; + uint32_t windowstart; + uint32_t configid0; + uint32_t configid1; + uint32_t ps; + uint32_t threadptr; + uint32_t br; + uint32_t scompare1; + uint32_t acclo; + uint32_t acchi; + uint32_t m0; + uint32_t m1; + uint32_t m2; + uint32_t m3; + uint32_t expstate; //I'm going to assume this is exccause... + uint32_t f64r_lo; + uint32_t f64r_hi; + uint32_t f64s; + uint32_t f[16]; + uint32_t fcr; + uint32_t fsr; +} GdbRegFile; + + +GdbRegFile gdbRegFile; + +/* +//Register format as the Xtensa HAL has it: +STRUCT_FIELD (long, 4, XT_STK_EXIT, exit) +STRUCT_FIELD (long, 4, XT_STK_PC, pc) +STRUCT_FIELD (long, 4, XT_STK_PS, ps) +STRUCT_FIELD (long, 4, XT_STK_A0, a0) +[..] +STRUCT_FIELD (long, 4, XT_STK_A15, a15) +STRUCT_FIELD (long, 4, XT_STK_SAR, sar) +STRUCT_FIELD (long, 4, XT_STK_EXCCAUSE, exccause) +STRUCT_FIELD (long, 4, XT_STK_EXCVADDR, excvaddr) +STRUCT_FIELD (long, 4, XT_STK_LBEG, lbeg) +STRUCT_FIELD (long, 4, XT_STK_LEND, lend) +STRUCT_FIELD (long, 4, XT_STK_LCOUNT, lcount) +// Temporary space for saving stuff during window spill +STRUCT_FIELD (long, 4, XT_STK_TMP0, tmp0) +STRUCT_FIELD (long, 4, XT_STK_TMP1, tmp1) +STRUCT_FIELD (long, 4, XT_STK_TMP2, tmp2) +STRUCT_FIELD (long, 4, XT_STK_VPRI, vpri) +STRUCT_FIELD (long, 4, XT_STK_OVLY, ovly) +#endif +STRUCT_END(XtExcFrame) +*/ + + +static void dumpHwToRegfile(XtExcFrame *frame) { + int i; + long *frameAregs=&frame->a0; + gdbRegFile.pc=frame->pc; + for (i=0; i<16; i++) gdbRegFile.a[i]=frameAregs[i]; + for (i=16; i<64; i++) gdbRegFile.a[i]=0xDEADBEEF; + gdbRegFile.lbeg=frame->lbeg; + gdbRegFile.lend=frame->lend; + gdbRegFile.lcount=frame->lcount; + gdbRegFile.sar=frame->sar; + //All windows have been spilled to the stack by the ISR routines. The following values should indicate that. + gdbRegFile.sar=frame->sar; + gdbRegFile.windowbase=0; //0 + gdbRegFile.windowstart=0x1; //1 + gdbRegFile.configid0=0xdeadbeef; //ToDo + gdbRegFile.configid1=0xdeadbeef; //ToDo + gdbRegFile.ps=frame->ps-PS_EXCM_MASK; + gdbRegFile.threadptr=0xdeadbeef; //ToDo + gdbRegFile.br=0xdeadbeef; //ToDo + gdbRegFile.scompare1=0xdeadbeef; //ToDo + gdbRegFile.acclo=0xdeadbeef; //ToDo + gdbRegFile.acchi=0xdeadbeef; //ToDo + gdbRegFile.m0=0xdeadbeef; //ToDo + gdbRegFile.m1=0xdeadbeef; //ToDo + gdbRegFile.m2=0xdeadbeef; //ToDo + gdbRegFile.m3=0xdeadbeef; //ToDo + gdbRegFile.expstate=frame->exccause; //ToDo +} + + +//Send the reason execution is stopped to GDB. +static void sendReason() { + //exception-to-signal mapping + char exceptionSignal[]={4,31,11,11,2,6,8,0,6,7,0,0,7,7,7,7}; + int i=0; + gdbPacketStart(); + gdbPacketChar('T'); + i=gdbRegFile.expstate&0x7f; + if (i=PBUFLEN) return ST_ERR; + } + //A # has been received. Get and check the received chsum. + sentchs[0]=gdbRecvChar(); + sentchs[1]=gdbRecvChar(); + ptr=&sentchs[0]; + rchsum=gdbGetHexVal(&ptr, 8); +// ets_printf("c %x r %x\n", chsum, rchsum); + if (rchsum!=chsum) { + gdbSendChar('-'); + return ST_ERR; + } else { + gdbSendChar('+'); + return gdbHandleCommand(cmd, p); + } +} + + + +void gdbstubPanicHandler(XtExcFrame *frame) { + dumpHwToRegfile(frame); + //Make sure txd/rxd are enabled + PIN_PULLUP_DIS(PERIPHS_IO_MUX_U0TXD_U); + PIN_FUNC_SELECT(PERIPHS_IO_MUX_U0RXD_U, FUNC_U0RXD_U0RXD); + PIN_FUNC_SELECT(PERIPHS_IO_MUX_U0TXD_U, FUNC_U0TXD_U0TXD); + + sendReason(); + while(gdbReadCommand()!=ST_CONT); + while(1); +} + diff --git a/components/freertos/gdbstub.h b/components/freertos/gdbstub.h new file mode 100644 index 0000000000..5e97213c92 --- /dev/null +++ b/components/freertos/gdbstub.h @@ -0,0 +1,22 @@ +// Copyright 2015-2016 Espressif Systems (Shanghai) PTE LTD +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at + +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +#ifndef GDBSTUB_H +#define GDBSTUB_H + +#include +#include "freertos/xtensa_api.h" + +void gdbstubPanicHandler(XtExcFrame *frame); + +#endif \ No newline at end of file diff --git a/components/freertos/heap_regions.c b/components/freertos/heap_regions.c new file mode 100644 index 0000000000..d1ab6240b6 --- /dev/null +++ b/components/freertos/heap_regions.c @@ -0,0 +1,559 @@ +/* + FreeRTOS V8.2.0 - Copyright (C) 2015 Real Time Engineers Ltd. + All rights reserved + + VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION. + + This file is part of the FreeRTOS distribution. + + FreeRTOS is free software; you can redistribute it and/or modify it under + the terms of the GNU General Public License (version 2) as published by the + Free Software Foundation >>!AND MODIFIED BY!<< the FreeRTOS exception. + + *************************************************************************** + >>! NOTE: The modification to the GPL is included to allow you to !<< + >>! distribute a combined work that includes FreeRTOS without being !<< + >>! obliged to provide the source code for proprietary components !<< + >>! outside of the FreeRTOS kernel. !<< + *************************************************************************** + + FreeRTOS is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + FOR A PARTICULAR PURPOSE. Full license text is available on the following + link: http://www.freertos.org/a00114.html + + *************************************************************************** + * * + * FreeRTOS provides completely free yet professionally developed, * + * robust, strictly quality controlled, supported, and cross * + * platform software that is more than just the market leader, it * + * is the industry's de facto standard. * + * * + * Help yourself get started quickly while simultaneously helping * + * to support the FreeRTOS project by purchasing a FreeRTOS * + * tutorial book, reference manual, or both: * + * http://www.FreeRTOS.org/Documentation * + * * + *************************************************************************** + + http://www.FreeRTOS.org/FAQHelp.html - Having a problem? Start by reading + the FAQ page "My application does not run, what could be wrong?". Have you + defined configASSERT()? + + http://www.FreeRTOS.org/support - In return for receiving this top quality + embedded software for free we request you assist our global community by + participating in the support forum. + + http://www.FreeRTOS.org/training - Investing in training allows your team to + be as productive as possible as early as possible. Now you can receive + FreeRTOS training directly from Richard Barry, CEO of Real Time Engineers + Ltd, and the world's leading authority on the world's leading RTOS. + + http://www.FreeRTOS.org/plus - A selection of FreeRTOS ecosystem products, + including FreeRTOS+Trace - an indispensable productivity tool, a DOS + compatible FAT file system, and our tiny thread aware UDP/IP stack. + + http://www.FreeRTOS.org/labs - Where new FreeRTOS products go to incubate. + Come and try FreeRTOS+TCP, our new open source TCP/IP stack for FreeRTOS. + + http://www.OpenRTOS.com - Real Time Engineers ltd. license FreeRTOS to High + Integrity Systems ltd. to sell under the OpenRTOS brand. Low cost OpenRTOS + licenses offer ticketed support, indemnification and commercial middleware. + + http://www.SafeRTOS.com - High Integrity Systems also provide a safety + engineered and independently SIL3 certified version for use in safety and + mission critical applications that require provable dependability. + + 1 tab == 4 spaces! +*/ + +/* + * This is a heap allocator that can allocate memory out of several tagged memory regions, + * with the regions having differing capabilities. In the ESP32, this is used to + * allocate memory for the various applications within the space the MMU allows them + * to work with. It can also be used to e.g. allocate memory in DMA-capable regions. + * + * Usage notes: + * + * vPortDefineHeapRegions() ***must*** be called before pvPortMalloc(). + * pvPortMalloc() will be called if any task objects (tasks, queues, event + * groups, etc.) are created, therefore vPortDefineHeapRegions() ***must*** be + * called before any other objects are defined. + * + * vPortDefineHeapRegions() takes a single parameter. The parameter is an array + * of HeapRegionTagged_t structures. HeapRegion_t is defined in portable.h as + * + * typedef struct HeapRegion + * { + * uint8_t *pucStartAddress; << Start address of a block of memory that will be part of the heap. + * size_t xSizeInBytes; << Size of the block of memory. + * BaseType_t xTag; << Tag + * } HeapRegionTagged_t; + * + * 'Tag' allows you to allocate memory of a certain type. Tag -1 is special; + * it basically tells the allocator to ignore this region as if it is not + * in the array at all. This facilitates disabling memory regions. + * + * The array is terminated using a NULL zero sized region definition, and the + * memory regions defined in the array ***must*** appear in address order from + * low address to high address. So the following is a valid example of how + * to use the function. + * + * HeapRegionTagged_t xHeapRegions[] = + * { + * { ( uint8_t * ) 0x80000000UL, 0x10000, 1 }, << Defines a block of 0x10000 bytes starting at address 0x80000000, tag 1 + * { ( uint8_t * ) 0x90000000UL, 0xa0000, 2 }, << Defines a block of 0xa0000 bytes starting at address of 0x90000000, tag 2 + * { NULL, 0, 0 } << Terminates the array. + * }; + * + * vPortDefineHeapRegions( xHeapRegions ); << Pass the array into vPortDefineHeapRegions(). + * + * Note 0x80000000 is the lower address so appears in the array first. + * + * pvPortMallocTagged can be used to get memory in a tagged region. + * + */ + +/* + +ToDo: +- This malloc implementation can be somewhat slow, especially when it is called multiple times with multiple tags +when having low memory issues. ToDo: Make it quicker. + -JD + */ + + +#include + +/* Defining MPU_WRAPPERS_INCLUDED_FROM_API_FILE prevents task.h from redefining +all the API functions to use the MPU wrappers. That should only be done when +task.h is included from an application file. */ +#define MPU_WRAPPERS_INCLUDED_FROM_API_FILE + +#include "FreeRTOS.h" +#include "task.h" + +#undef MPU_WRAPPERS_INCLUDED_FROM_API_FILE + +#include "heap_regions.h" + +#include "rom/ets_sys.h" + +/* Block sizes must not get too small. */ +#define heapMINIMUM_BLOCK_SIZE ( ( size_t ) ( uxHeapStructSize << 1 ) ) + +/* Assumes 8bit bytes! */ +#define heapBITS_PER_BYTE ( ( size_t ) 8 ) + +/* Define the linked list structure. This is used to link free blocks in order +of their memory address. */ +typedef struct A_BLOCK_LINK +{ + struct A_BLOCK_LINK *pxNextFreeBlock; /*<< The next free block in the list. */ + size_t xBlockSize; /*<< The size of the free block. */ + BaseType_t xTag; /*<< Tag of this region */ +} BlockLink_t; + +//Mux to protect the memory status data +static portMUX_TYPE xMallocMutex; + +/*-----------------------------------------------------------*/ + +/* + * Inserts a block of memory that is being freed into the correct position in + * the list of free memory blocks. The block being freed will be merged with + * the block in front it and/or the block behind it if the memory blocks are + * adjacent to each other. + */ +static void prvInsertBlockIntoFreeList( BlockLink_t *pxBlockToInsert ); + +/*-----------------------------------------------------------*/ + +/* The size of the structure placed at the beginning of each allocated memory +block must by correctly byte aligned. */ +static const uint32_t uxHeapStructSize = ( ( sizeof ( BlockLink_t ) + ( portBYTE_ALIGNMENT - 1 ) ) & ~portBYTE_ALIGNMENT_MASK ); + +/* Create a couple of list links to mark the start and end of the list. */ +static BlockLink_t xStart, *pxEnd = NULL; + +/* Keeps track of the number of free bytes remaining, but says nothing about +fragmentation. */ +static size_t xFreeBytesRemaining = 0; +static size_t xMinimumEverFreeBytesRemaining = 0; + +/* Gets set to the top bit of an size_t type. When this bit in the xBlockSize +member of an BlockLink_t structure is set then the block belongs to the +application. When the bit is free the block is still part of the free heap +space. */ +static size_t xBlockAllocatedBit = 0; + +/*-----------------------------------------------------------*/ + +void *pvPortMallocTagged( size_t xWantedSize, BaseType_t tag ) +{ +BlockLink_t *pxBlock, *pxPreviousBlock, *pxNewBlockLink; +void *pvReturn = NULL; + + /* The heap must be initialised before the first call to + prvPortMalloc(). */ + configASSERT( pxEnd ); + + taskENTER_CRITICAL(&xMallocMutex); + { + /* Check the requested block size is not so large that the top bit is + set. The top bit of the block size member of the BlockLink_t structure + is used to determine who owns the block - the application or the + kernel, so it must be free. */ + if( ( xWantedSize & xBlockAllocatedBit ) == 0 ) + { + /* The wanted size is increased so it can contain a BlockLink_t + structure in addition to the requested amount of bytes. */ + if( xWantedSize > 0 ) + { + xWantedSize += uxHeapStructSize; + + /* Ensure that blocks are always aligned to the required number + of bytes. */ + if( ( xWantedSize & portBYTE_ALIGNMENT_MASK ) != 0x00 ) + { + /* Byte alignment required. */ + xWantedSize += ( portBYTE_ALIGNMENT - ( xWantedSize & portBYTE_ALIGNMENT_MASK ) ); + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + + if( ( xWantedSize > 0 ) && ( xWantedSize <= xFreeBytesRemaining ) ) + { + /* Traverse the list from the start (lowest address) block until + one of adequate size is found. */ + pxPreviousBlock = &xStart; + pxBlock = xStart.pxNextFreeBlock; + while( ( ( pxBlock->xTag != tag ) || ( pxBlock->xBlockSize < xWantedSize ) ) && ( pxBlock->pxNextFreeBlock != NULL ) ) + { +// ets_printf("Block %x -> %x\n", (uint32_t)pxBlock, (uint32_t)pxBlock->pxNextFreeBlock); + pxPreviousBlock = pxBlock; + pxBlock = pxBlock->pxNextFreeBlock; + } + + /* If the end marker was not reached then a block of adequate size + was found. */ + if( pxBlock != pxEnd ) + { + /* Return the memory space pointed to - jumping over the + BlockLink_t structure at its start. */ + pvReturn = ( void * ) ( ( ( uint8_t * ) pxPreviousBlock->pxNextFreeBlock ) + uxHeapStructSize ); + + /* This block is being returned for use so must be taken out + of the list of free blocks. */ + pxPreviousBlock->pxNextFreeBlock = pxBlock->pxNextFreeBlock; + + /* If the block is larger than required it can be split into + two. */ + if( ( pxBlock->xBlockSize - xWantedSize ) > heapMINIMUM_BLOCK_SIZE ) + { + /* This block is to be split into two. Create a new + block following the number of bytes requested. The void + cast is used to prevent byte alignment warnings from the + compiler. */ + pxNewBlockLink = ( void * ) ( ( ( uint8_t * ) pxBlock ) + xWantedSize ); + + /* Calculate the sizes of two blocks split from the + single block. */ + pxNewBlockLink->xBlockSize = pxBlock->xBlockSize - xWantedSize; + pxNewBlockLink->xTag = tag; + pxBlock->xBlockSize = xWantedSize; + + /* Insert the new block into the list of free blocks. */ + prvInsertBlockIntoFreeList( ( pxNewBlockLink ) ); + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + + xFreeBytesRemaining -= pxBlock->xBlockSize; + + if( xFreeBytesRemaining < xMinimumEverFreeBytesRemaining ) + { + xMinimumEverFreeBytesRemaining = xFreeBytesRemaining; + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + + /* The block is being returned - it is allocated and owned + by the application and has no "next" block. */ + pxBlock->xBlockSize |= xBlockAllocatedBit; + pxBlock->pxNextFreeBlock = NULL; + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + + traceMALLOC( pvReturn, xWantedSize ); + } + taskEXIT_CRITICAL(&xMallocMutex); + + #if( configUSE_MALLOC_FAILED_HOOK == 1 ) + { + if( pvReturn == NULL ) + { + extern void vApplicationMallocFailedHook( void ); + vApplicationMallocFailedHook(); + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } + #endif + + return pvReturn; +} +/*-----------------------------------------------------------*/ + +void vPortFree( void *pv ) +{ +uint8_t *puc = ( uint8_t * ) pv; +BlockLink_t *pxLink; + + if( pv != NULL ) + { + /* The memory being freed will have an BlockLink_t structure immediately + before it. */ + puc -= uxHeapStructSize; + + /* This casting is to keep the compiler from issuing warnings. */ + pxLink = ( void * ) puc; + + /* Check the block is actually allocated. */ + configASSERT( ( pxLink->xBlockSize & xBlockAllocatedBit ) != 0 ); + configASSERT( pxLink->pxNextFreeBlock == NULL ); + + if( ( pxLink->xBlockSize & xBlockAllocatedBit ) != 0 ) + { + if( pxLink->pxNextFreeBlock == NULL ) + { + /* The block is being returned to the heap - it is no longer + allocated. */ + pxLink->xBlockSize &= ~xBlockAllocatedBit; + + taskENTER_CRITICAL(&xMallocMutex); + { + /* Add this block to the list of free blocks. */ + xFreeBytesRemaining += pxLink->xBlockSize; + traceFREE( pv, pxLink->xBlockSize ); + prvInsertBlockIntoFreeList( ( ( BlockLink_t * ) pxLink ) ); + } + taskEXIT_CRITICAL(&xMallocMutex); + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } +} +/*-----------------------------------------------------------*/ + +size_t xPortGetFreeHeapSize( void ) +{ + return xFreeBytesRemaining; +} +/*-----------------------------------------------------------*/ + +size_t xPortGetMinimumEverFreeHeapSize( void ) +{ + return xMinimumEverFreeBytesRemaining; +} +/*-----------------------------------------------------------*/ + +static void prvInsertBlockIntoFreeList( BlockLink_t *pxBlockToInsert ) +{ +BlockLink_t *pxIterator; +uint8_t *puc; + + /* Iterate through the list until a block is found that has a higher address + than the block being inserted. */ + for( pxIterator = &xStart; pxIterator->pxNextFreeBlock < pxBlockToInsert; pxIterator = pxIterator->pxNextFreeBlock ) + { + /* Nothing to do here, just iterate to the right position. */ + } + + /* Do the block being inserted, and the block it is being inserted after + make a contiguous block of memory, and are the tags the same? */ + puc = ( uint8_t * ) pxIterator; + if( ( puc + pxIterator->xBlockSize ) == ( uint8_t * ) pxBlockToInsert && pxBlockToInsert->xTag==pxIterator->xTag) + { + pxIterator->xBlockSize += pxBlockToInsert->xBlockSize; + pxBlockToInsert = pxIterator; + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + + /* Do the block being inserted, and the block it is being inserted before + make a contiguous block of memory, and are the tags the same */ + puc = ( uint8_t * ) pxBlockToInsert; + if( ( puc + pxBlockToInsert->xBlockSize ) == ( uint8_t * ) pxIterator->pxNextFreeBlock && pxBlockToInsert->xTag==pxIterator->pxNextFreeBlock->xTag ) + { + if( pxIterator->pxNextFreeBlock != pxEnd ) + { + /* Form one big block from the two blocks. */ + pxBlockToInsert->xBlockSize += pxIterator->pxNextFreeBlock->xBlockSize; + pxBlockToInsert->pxNextFreeBlock = pxIterator->pxNextFreeBlock->pxNextFreeBlock; + } + else + { + pxBlockToInsert->pxNextFreeBlock = pxEnd; + } + } + else + { + pxBlockToInsert->pxNextFreeBlock = pxIterator->pxNextFreeBlock; + } + + /* If the block being inserted plugged a gap, so was merged with the block + before and the block after, then it's pxNextFreeBlock pointer will have + already been set, and should not be set here as that would make it point + to itself. */ + if( pxIterator != pxBlockToInsert ) + { + pxIterator->pxNextFreeBlock = pxBlockToInsert; + } + else + { + mtCOVERAGE_TEST_MARKER(); + } +} +/*-----------------------------------------------------------*/ + +void vPortDefineHeapRegionsTagged( const HeapRegionTagged_t * const pxHeapRegions ) +{ +BlockLink_t *pxFirstFreeBlockInRegion = NULL, *pxPreviousFreeBlock; +uint8_t *pucAlignedHeap; +size_t xTotalRegionSize, xTotalHeapSize = 0; +BaseType_t xDefinedRegions = 0, xRegIdx = 0; +uint32_t ulAddress; +const HeapRegionTagged_t *pxHeapRegion; + + /* Can only call once! */ + configASSERT( pxEnd == NULL ); + + vPortCPUInitializeMutex(&xMallocMutex); + + pxHeapRegion = &( pxHeapRegions[ xRegIdx ] ); + + while( pxHeapRegion->xSizeInBytes > 0 ) + { + if ( pxHeapRegion->xTag == -1 ) { + /* Move onto the next HeapRegionTagged_t structure. */ + xRegIdx++; + pxHeapRegion = &( pxHeapRegions[ xRegIdx ] ); + continue; + } + + xTotalRegionSize = pxHeapRegion->xSizeInBytes; + + /* Ensure the heap region starts on a correctly aligned boundary. */ + ulAddress = ( uint32_t ) pxHeapRegion->pucStartAddress; + if( ( ulAddress & portBYTE_ALIGNMENT_MASK ) != 0 ) + { + ulAddress += ( portBYTE_ALIGNMENT - 1 ); + ulAddress &= ~portBYTE_ALIGNMENT_MASK; + + /* Adjust the size for the bytes lost to alignment. */ + xTotalRegionSize -= ulAddress - ( uint32_t ) pxHeapRegion->pucStartAddress; + } + + pucAlignedHeap = ( uint8_t * ) ulAddress; + + /* Set xStart if it has not already been set. */ + if( xDefinedRegions == 0 ) + { + /* xStart is used to hold a pointer to the first item in the list of + free blocks. The void cast is used to prevent compiler warnings. */ + xStart.pxNextFreeBlock = ( BlockLink_t * ) pucAlignedHeap; + xStart.xBlockSize = ( size_t ) 0; + } + else + { + /* Should only get here if one region has already been added to the + heap. */ + configASSERT( pxEnd != NULL ); + + /* Check blocks are passed in with increasing start addresses. */ + configASSERT( ulAddress > ( uint32_t ) pxEnd ); + } + + /* Remember the location of the end marker in the previous region, if + any. */ + pxPreviousFreeBlock = pxEnd; + + /* pxEnd is used to mark the end of the list of free blocks and is + inserted at the end of the region space. */ + ulAddress = ( ( uint32_t ) pucAlignedHeap ) + xTotalRegionSize; + ulAddress -= uxHeapStructSize; + ulAddress &= ~portBYTE_ALIGNMENT_MASK; + pxEnd = ( BlockLink_t * ) ulAddress; + pxEnd->xBlockSize = 0; + pxEnd->pxNextFreeBlock = NULL; + pxEnd->xTag = -1; + + /* To start with there is a single free block in this region that is + sized to take up the entire heap region minus the space taken by the + free block structure. */ + pxFirstFreeBlockInRegion = ( BlockLink_t * ) pucAlignedHeap; + pxFirstFreeBlockInRegion->xBlockSize = ulAddress - ( uint32_t ) pxFirstFreeBlockInRegion; + pxFirstFreeBlockInRegion->pxNextFreeBlock = pxEnd; + pxFirstFreeBlockInRegion->xTag=pxHeapRegion->xTag; + + /* If this is not the first region that makes up the entire heap space + then link the previous region to this region. */ + if( pxPreviousFreeBlock != NULL ) + { + pxPreviousFreeBlock->pxNextFreeBlock = pxFirstFreeBlockInRegion; + } + + xTotalHeapSize += pxFirstFreeBlockInRegion->xBlockSize; + + /* Move onto the next HeapRegionTagged_t structure. */ + xDefinedRegions++; + xRegIdx++; + pxHeapRegion = &( pxHeapRegions[ xRegIdx ] ); + } + + xMinimumEverFreeBytesRemaining = xTotalHeapSize; + xFreeBytesRemaining = xTotalHeapSize; + + /* Check something was actually defined before it is accessed. */ + configASSERT( xTotalHeapSize ); + + /* Work out the position of the top bit in a size_t variable. */ + xBlockAllocatedBit = ( ( size_t ) 1 ) << ( ( sizeof( size_t ) * heapBITS_PER_BYTE ) - 1 ); +} + diff --git a/components/freertos/include/freertos/FreeRTOS.h b/components/freertos/include/freertos/FreeRTOS.h new file mode 100644 index 0000000000..980f53d577 --- /dev/null +++ b/components/freertos/include/freertos/FreeRTOS.h @@ -0,0 +1,791 @@ +/* + FreeRTOS V8.2.0 - Copyright (C) 2015 Real Time Engineers Ltd. + All rights reserved + + VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION. + + This file is part of the FreeRTOS distribution. + + FreeRTOS is free software; you can redistribute it and/or modify it under + the terms of the GNU General Public License (version 2) as published by the + Free Software Foundation >>!AND MODIFIED BY!<< the FreeRTOS exception. + + *************************************************************************** + >>! NOTE: The modification to the GPL is included to allow you to !<< + >>! distribute a combined work that includes FreeRTOS without being !<< + >>! obliged to provide the source code for proprietary components !<< + >>! outside of the FreeRTOS kernel. !<< + *************************************************************************** + + FreeRTOS is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + FOR A PARTICULAR PURPOSE. Full license text is available on the following + link: http://www.freertos.org/a00114.html + + *************************************************************************** + * * + * FreeRTOS provides completely free yet professionally developed, * + * robust, strictly quality controlled, supported, and cross * + * platform software that is more than just the market leader, it * + * is the industry's de facto standard. * + * * + * Help yourself get started quickly while simultaneously helping * + * to support the FreeRTOS project by purchasing a FreeRTOS * + * tutorial book, reference manual, or both: * + * http://www.FreeRTOS.org/Documentation * + * * + *************************************************************************** + + http://www.FreeRTOS.org/FAQHelp.html - Having a problem? Start by reading + the FAQ page "My application does not run, what could be wrong?". Have you + defined configASSERT()? + + http://www.FreeRTOS.org/support - In return for receiving this top quality + embedded software for free we request you assist our global community by + participating in the support forum. + + http://www.FreeRTOS.org/training - Investing in training allows your team to + be as productive as possible as early as possible. Now you can receive + FreeRTOS training directly from Richard Barry, CEO of Real Time Engineers + Ltd, and the world's leading authority on the world's leading RTOS. + + http://www.FreeRTOS.org/plus - A selection of FreeRTOS ecosystem products, + including FreeRTOS+Trace - an indispensable productivity tool, a DOS + compatible FAT file system, and our tiny thread aware UDP/IP stack. + + http://www.FreeRTOS.org/labs - Where new FreeRTOS products go to incubate. + Come and try FreeRTOS+TCP, our new open source TCP/IP stack for FreeRTOS. + + http://www.OpenRTOS.com - Real Time Engineers ltd. license FreeRTOS to High + Integrity Systems ltd. to sell under the OpenRTOS brand. Low cost OpenRTOS + licenses offer ticketed support, indemnification and commercial middleware. + + http://www.SafeRTOS.com - High Integrity Systems also provide a safety + engineered and independently SIL3 certified version for use in safety and + mission critical applications that require provable dependability. + + 1 tab == 4 spaces! +*/ + +#ifndef INC_FREERTOS_H +#define INC_FREERTOS_H + +/* + * Include the generic headers required for the FreeRTOS port being used. + */ +#include + +/* + * If stdint.h cannot be located then: + * + If using GCC ensure the -nostdint options is *not* being used. + * + Ensure the project's include path includes the directory in which your + * compiler stores stdint.h. + * + Set any compiler options necessary for it to support C99, as technically + * stdint.h is only mandatory with C99 (FreeRTOS does not require C99 in any + * other way). + * + The FreeRTOS download includes a simple stdint.h definition that can be + * used in cases where none is provided by the compiler. The files only + * contains the typedefs required to build FreeRTOS. Read the instructions + * in FreeRTOS/source/stdint.readme for more information. + */ +#include /* READ COMMENT ABOVE. */ + +#ifdef __cplusplus +extern "C" { +#endif + +/* Application specific configuration options. */ +#include "FreeRTOSConfig.h" + +/* Basic FreeRTOS definitions. */ +#include "projdefs.h" + +/* Definitions specific to the port being used. */ +#include "portable.h" + +/* + * Check all the required application specific macros have been defined. + * These macros are application specific and (as downloaded) are defined + * within FreeRTOSConfig.h. + */ + +#ifndef configMINIMAL_STACK_SIZE + #error Missing definition: configMINIMAL_STACK_SIZE must be defined in FreeRTOSConfig.h. configMINIMAL_STACK_SIZE defines the size (in words) of the stack allocated to the idle task. Refer to the demo project provided for your port for a suitable value. +#endif + +#ifndef configMAX_PRIORITIES + #error Missing definition: configMAX_PRIORITIES must be defined in FreeRTOSConfig.h. See the Configuration section of the FreeRTOS API documentation for details. +#endif + +#ifndef configUSE_PREEMPTION + #error Missing definition: configUSE_PREEMPTION must be defined in FreeRTOSConfig.h as either 1 or 0. See the Configuration section of the FreeRTOS API documentation for details. +#endif + +#ifndef configUSE_IDLE_HOOK + #error Missing definition: configUSE_IDLE_HOOK must be defined in FreeRTOSConfig.h as either 1 or 0. See the Configuration section of the FreeRTOS API documentation for details. +#endif + +#ifndef configUSE_TICK_HOOK + #error Missing definition: configUSE_TICK_HOOK must be defined in FreeRTOSConfig.h as either 1 or 0. See the Configuration section of the FreeRTOS API documentation for details. +#endif + +#ifndef configUSE_CO_ROUTINES + #error Missing definition: configUSE_CO_ROUTINES must be defined in FreeRTOSConfig.h as either 1 or 0. See the Configuration section of the FreeRTOS API documentation for details. +#endif + +#ifndef INCLUDE_vTaskPrioritySet + #error Missing definition: INCLUDE_vTaskPrioritySet must be defined in FreeRTOSConfig.h as either 1 or 0. See the Configuration section of the FreeRTOS API documentation for details. +#endif + +#ifndef INCLUDE_uxTaskPriorityGet + #error Missing definition: INCLUDE_uxTaskPriorityGet must be defined in FreeRTOSConfig.h as either 1 or 0. See the Configuration section of the FreeRTOS API documentation for details. +#endif + +#ifndef INCLUDE_vTaskDelete + #error Missing definition: INCLUDE_vTaskDelete must be defined in FreeRTOSConfig.h as either 1 or 0. See the Configuration section of the FreeRTOS API documentation for details. +#endif + +#ifndef INCLUDE_vTaskSuspend + #error Missing definition: INCLUDE_vTaskSuspend must be defined in FreeRTOSConfig.h as either 1 or 0. See the Configuration section of the FreeRTOS API documentation for details. +#endif + +#ifndef INCLUDE_vTaskDelayUntil + #error Missing definition: INCLUDE_vTaskDelayUntil must be defined in FreeRTOSConfig.h as either 1 or 0. See the Configuration section of the FreeRTOS API documentation for details. +#endif + +#ifndef INCLUDE_vTaskDelay + #error Missing definition: INCLUDE_vTaskDelay must be defined in FreeRTOSConfig.h as either 1 or 0. See the Configuration section of the FreeRTOS API documentation for details. +#endif + +#ifndef configUSE_16_BIT_TICKS + #error Missing definition: configUSE_16_BIT_TICKS must be defined in FreeRTOSConfig.h as either 1 or 0. See the Configuration section of the FreeRTOS API documentation for details. +#endif + +#if configUSE_CO_ROUTINES != 0 + #ifndef configMAX_CO_ROUTINE_PRIORITIES + #error configMAX_CO_ROUTINE_PRIORITIES must be greater than or equal to 1. + #endif +#endif + +#ifndef configMAX_PRIORITIES + #error configMAX_PRIORITIES must be defined to be greater than or equal to 1. +#endif + +#ifndef INCLUDE_xTaskGetIdleTaskHandle + #define INCLUDE_xTaskGetIdleTaskHandle 0 +#endif + +#ifndef INCLUDE_xTimerGetTimerDaemonTaskHandle + #define INCLUDE_xTimerGetTimerDaemonTaskHandle 0 +#endif + +#ifndef INCLUDE_xQueueGetMutexHolder + #define INCLUDE_xQueueGetMutexHolder 0 +#endif + +#ifndef INCLUDE_xSemaphoreGetMutexHolder + #define INCLUDE_xSemaphoreGetMutexHolder INCLUDE_xQueueGetMutexHolder +#endif + +#ifndef INCLUDE_pcTaskGetTaskName + #define INCLUDE_pcTaskGetTaskName 0 +#endif + +#ifndef configUSE_APPLICATION_TASK_TAG + #define configUSE_APPLICATION_TASK_TAG 0 +#endif + +#ifndef INCLUDE_uxTaskGetStackHighWaterMark + #define INCLUDE_uxTaskGetStackHighWaterMark 0 +#endif + +#ifndef INCLUDE_eTaskGetState + #define INCLUDE_eTaskGetState 0 +#endif + +#ifndef configUSE_RECURSIVE_MUTEXES + #define configUSE_RECURSIVE_MUTEXES 0 +#endif + +#ifndef configUSE_MUTEXES + #define configUSE_MUTEXES 0 +#endif + +#ifndef configUSE_TIMERS + #define configUSE_TIMERS 0 +#endif + +#ifndef configUSE_COUNTING_SEMAPHORES + #define configUSE_COUNTING_SEMAPHORES 0 +#endif + +#ifndef configUSE_ALTERNATIVE_API + #define configUSE_ALTERNATIVE_API 0 +#endif + +#ifndef portCRITICAL_NESTING_IN_TCB + #define portCRITICAL_NESTING_IN_TCB 0 +#endif + +#ifndef configMAX_TASK_NAME_LEN + #define configMAX_TASK_NAME_LEN 16 +#endif + +#ifndef configIDLE_SHOULD_YIELD + #define configIDLE_SHOULD_YIELD 1 +#endif + +#if configMAX_TASK_NAME_LEN < 1 + #error configMAX_TASK_NAME_LEN must be set to a minimum of 1 in FreeRTOSConfig.h +#endif + +#ifndef INCLUDE_xTaskResumeFromISR + #define INCLUDE_xTaskResumeFromISR 1 +#endif + +#ifndef INCLUDE_xEventGroupSetBitFromISR + #define INCLUDE_xEventGroupSetBitFromISR 0 +#endif + +#ifndef INCLUDE_xTimerPendFunctionCall + #define INCLUDE_xTimerPendFunctionCall 0 +#endif + +#ifndef configASSERT + #define configASSERT( x ) + #define configASSERT_DEFINED 0 +#else + #define configASSERT_DEFINED 1 +#endif + +/* The timers module relies on xTaskGetSchedulerState(). */ +#if configUSE_TIMERS == 1 + + #ifndef configTIMER_TASK_PRIORITY + #error If configUSE_TIMERS is set to 1 then configTIMER_TASK_PRIORITY must also be defined. + #endif /* configTIMER_TASK_PRIORITY */ + + #ifndef configTIMER_QUEUE_LENGTH + #error If configUSE_TIMERS is set to 1 then configTIMER_QUEUE_LENGTH must also be defined. + #endif /* configTIMER_QUEUE_LENGTH */ + + #ifndef configTIMER_TASK_STACK_DEPTH + #error If configUSE_TIMERS is set to 1 then configTIMER_TASK_STACK_DEPTH must also be defined. + #endif /* configTIMER_TASK_STACK_DEPTH */ + +#endif /* configUSE_TIMERS */ + +#ifndef INCLUDE_xTaskGetSchedulerState + #define INCLUDE_xTaskGetSchedulerState 0 +#endif + +#ifndef INCLUDE_xTaskGetCurrentTaskHandle + #define INCLUDE_xTaskGetCurrentTaskHandle 0 +#endif + + +#ifndef portSET_INTERRUPT_MASK_FROM_ISR + #define portSET_INTERRUPT_MASK_FROM_ISR() 0 +#endif + +#ifndef portCLEAR_INTERRUPT_MASK_FROM_ISR + #define portCLEAR_INTERRUPT_MASK_FROM_ISR( uxSavedStatusValue ) ( void ) uxSavedStatusValue +#endif + +#ifndef portCLEAN_UP_TCB + #define portCLEAN_UP_TCB( pxTCB ) ( void ) pxTCB +#endif + +#ifndef portPRE_TASK_DELETE_HOOK + #define portPRE_TASK_DELETE_HOOK( pvTaskToDelete, pxYieldPending ) +#endif + +#ifndef portSETUP_TCB + #define portSETUP_TCB( pxTCB ) ( void ) pxTCB +#endif + +#ifndef configQUEUE_REGISTRY_SIZE + #define configQUEUE_REGISTRY_SIZE 0U +#endif + +#if ( configQUEUE_REGISTRY_SIZE < 1 ) + #define vQueueAddToRegistry( xQueue, pcName ) + #define vQueueUnregisterQueue( xQueue ) +#endif + +#ifndef portPOINTER_SIZE_TYPE + #define portPOINTER_SIZE_TYPE uint32_t +#endif + +/* Remove any unused trace macros. */ +#ifndef traceSTART + /* Used to perform any necessary initialisation - for example, open a file + into which trace is to be written. */ + #define traceSTART() +#endif + +#ifndef traceEND + /* Use to close a trace, for example close a file into which trace has been + written. */ + #define traceEND() +#endif + +#ifndef traceTASK_SWITCHED_IN + /* Called after a task has been selected to run. pxCurrentTCB holds a pointer + to the task control block of the selected task. */ + #define traceTASK_SWITCHED_IN() +#endif + +#ifndef traceINCREASE_TICK_COUNT + /* Called before stepping the tick count after waking from tickless idle + sleep. */ + #define traceINCREASE_TICK_COUNT( x ) +#endif + +#ifndef traceLOW_POWER_IDLE_BEGIN + /* Called immediately before entering tickless idle. */ + #define traceLOW_POWER_IDLE_BEGIN() +#endif + +#ifndef traceLOW_POWER_IDLE_END + /* Called when returning to the Idle task after a tickless idle. */ + #define traceLOW_POWER_IDLE_END() +#endif + +#ifndef traceTASK_SWITCHED_OUT + /* Called before a task has been selected to run. pxCurrentTCB holds a pointer + to the task control block of the task being switched out. */ + #define traceTASK_SWITCHED_OUT() +#endif + +#ifndef traceTASK_PRIORITY_INHERIT + /* Called when a task attempts to take a mutex that is already held by a + lower priority task. pxTCBOfMutexHolder is a pointer to the TCB of the task + that holds the mutex. uxInheritedPriority is the priority the mutex holder + will inherit (the priority of the task that is attempting to obtain the + muted. */ + #define traceTASK_PRIORITY_INHERIT( pxTCBOfMutexHolder, uxInheritedPriority ) +#endif + +#ifndef traceTASK_PRIORITY_DISINHERIT + /* Called when a task releases a mutex, the holding of which had resulted in + the task inheriting the priority of a higher priority task. + pxTCBOfMutexHolder is a pointer to the TCB of the task that is releasing the + mutex. uxOriginalPriority is the task's configured (base) priority. */ + #define traceTASK_PRIORITY_DISINHERIT( pxTCBOfMutexHolder, uxOriginalPriority ) +#endif + +#ifndef traceBLOCKING_ON_QUEUE_RECEIVE + /* Task is about to block because it cannot read from a + queue/mutex/semaphore. pxQueue is a pointer to the queue/mutex/semaphore + upon which the read was attempted. pxCurrentTCB points to the TCB of the + task that attempted the read. */ + #define traceBLOCKING_ON_QUEUE_RECEIVE( pxQueue ) +#endif + +#ifndef traceBLOCKING_ON_QUEUE_SEND + /* Task is about to block because it cannot write to a + queue/mutex/semaphore. pxQueue is a pointer to the queue/mutex/semaphore + upon which the write was attempted. pxCurrentTCB points to the TCB of the + task that attempted the write. */ + #define traceBLOCKING_ON_QUEUE_SEND( pxQueue ) +#endif + +#ifndef configCHECK_FOR_STACK_OVERFLOW + #define configCHECK_FOR_STACK_OVERFLOW 0 +#endif + +/* The following event macros are embedded in the kernel API calls. */ + +#ifndef traceMOVED_TASK_TO_READY_STATE + #define traceMOVED_TASK_TO_READY_STATE( pxTCB ) +#endif + +#ifndef traceQUEUE_CREATE + #define traceQUEUE_CREATE( pxNewQueue ) +#endif + +#ifndef traceQUEUE_CREATE_FAILED + #define traceQUEUE_CREATE_FAILED( ucQueueType ) +#endif + +#ifndef traceCREATE_MUTEX + #define traceCREATE_MUTEX( pxNewQueue ) +#endif + +#ifndef traceCREATE_MUTEX_FAILED + #define traceCREATE_MUTEX_FAILED() +#endif + +#ifndef traceGIVE_MUTEX_RECURSIVE + #define traceGIVE_MUTEX_RECURSIVE( pxMutex ) +#endif + +#ifndef traceGIVE_MUTEX_RECURSIVE_FAILED + #define traceGIVE_MUTEX_RECURSIVE_FAILED( pxMutex ) +#endif + +#ifndef traceTAKE_MUTEX_RECURSIVE + #define traceTAKE_MUTEX_RECURSIVE( pxMutex ) +#endif + +#ifndef traceTAKE_MUTEX_RECURSIVE_FAILED + #define traceTAKE_MUTEX_RECURSIVE_FAILED( pxMutex ) +#endif + +#ifndef traceCREATE_COUNTING_SEMAPHORE + #define traceCREATE_COUNTING_SEMAPHORE() +#endif + +#ifndef traceCREATE_COUNTING_SEMAPHORE_FAILED + #define traceCREATE_COUNTING_SEMAPHORE_FAILED() +#endif + +#ifndef traceQUEUE_SEND + #define traceQUEUE_SEND( pxQueue ) +#endif + +#ifndef traceQUEUE_SEND_FAILED + #define traceQUEUE_SEND_FAILED( pxQueue ) +#endif + +#ifndef traceQUEUE_RECEIVE + #define traceQUEUE_RECEIVE( pxQueue ) +#endif + +#ifndef traceQUEUE_PEEK + #define traceQUEUE_PEEK( pxQueue ) +#endif + +#ifndef traceQUEUE_PEEK_FROM_ISR + #define traceQUEUE_PEEK_FROM_ISR( pxQueue ) +#endif + +#ifndef traceQUEUE_RECEIVE_FAILED + #define traceQUEUE_RECEIVE_FAILED( pxQueue ) +#endif + +#ifndef traceQUEUE_SEND_FROM_ISR + #define traceQUEUE_SEND_FROM_ISR( pxQueue ) +#endif + +#ifndef traceQUEUE_SEND_FROM_ISR_FAILED + #define traceQUEUE_SEND_FROM_ISR_FAILED( pxQueue ) +#endif + +#ifndef traceQUEUE_RECEIVE_FROM_ISR + #define traceQUEUE_RECEIVE_FROM_ISR( pxQueue ) +#endif + +#ifndef traceQUEUE_RECEIVE_FROM_ISR_FAILED + #define traceQUEUE_RECEIVE_FROM_ISR_FAILED( pxQueue ) +#endif + +#ifndef traceQUEUE_PEEK_FROM_ISR_FAILED + #define traceQUEUE_PEEK_FROM_ISR_FAILED( pxQueue ) +#endif + +#ifndef traceQUEUE_DELETE + #define traceQUEUE_DELETE( pxQueue ) +#endif + +#ifndef traceTASK_CREATE + #define traceTASK_CREATE( pxNewTCB ) +#endif + +#ifndef traceTASK_CREATE_FAILED + #define traceTASK_CREATE_FAILED() +#endif + +#ifndef traceTASK_DELETE + #define traceTASK_DELETE( pxTaskToDelete ) +#endif + +#ifndef traceTASK_DELAY_UNTIL + #define traceTASK_DELAY_UNTIL() +#endif + +#ifndef traceTASK_DELAY + #define traceTASK_DELAY() +#endif + +#ifndef traceTASK_PRIORITY_SET + #define traceTASK_PRIORITY_SET( pxTask, uxNewPriority ) +#endif + +#ifndef traceTASK_SUSPEND + #define traceTASK_SUSPEND( pxTaskToSuspend ) +#endif + +#ifndef traceTASK_RESUME + #define traceTASK_RESUME( pxTaskToResume ) +#endif + +#ifndef traceTASK_RESUME_FROM_ISR + #define traceTASK_RESUME_FROM_ISR( pxTaskToResume ) +#endif + +#ifndef traceTASK_INCREMENT_TICK + #define traceTASK_INCREMENT_TICK( xTickCount ) +#endif + +#ifndef traceTIMER_CREATE + #define traceTIMER_CREATE( pxNewTimer ) +#endif + +#ifndef traceTIMER_CREATE_FAILED + #define traceTIMER_CREATE_FAILED() +#endif + +#ifndef traceTIMER_COMMAND_SEND + #define traceTIMER_COMMAND_SEND( xTimer, xMessageID, xMessageValueValue, xReturn ) +#endif + +#ifndef traceTIMER_EXPIRED + #define traceTIMER_EXPIRED( pxTimer ) +#endif + +#ifndef traceTIMER_COMMAND_RECEIVED + #define traceTIMER_COMMAND_RECEIVED( pxTimer, xMessageID, xMessageValue ) +#endif + +#ifndef traceMALLOC + #define traceMALLOC( pvAddress, uiSize ) +#endif + +#ifndef traceFREE + #define traceFREE( pvAddress, uiSize ) +#endif + +#ifndef traceEVENT_GROUP_CREATE + #define traceEVENT_GROUP_CREATE( xEventGroup ) +#endif + +#ifndef traceEVENT_GROUP_CREATE_FAILED + #define traceEVENT_GROUP_CREATE_FAILED() +#endif + +#ifndef traceEVENT_GROUP_SYNC_BLOCK + #define traceEVENT_GROUP_SYNC_BLOCK( xEventGroup, uxBitsToSet, uxBitsToWaitFor ) +#endif + +#ifndef traceEVENT_GROUP_SYNC_END + #define traceEVENT_GROUP_SYNC_END( xEventGroup, uxBitsToSet, uxBitsToWaitFor, xTimeoutOccurred ) ( void ) xTimeoutOccurred +#endif + +#ifndef traceEVENT_GROUP_WAIT_BITS_BLOCK + #define traceEVENT_GROUP_WAIT_BITS_BLOCK( xEventGroup, uxBitsToWaitFor ) +#endif + +#ifndef traceEVENT_GROUP_WAIT_BITS_END + #define traceEVENT_GROUP_WAIT_BITS_END( xEventGroup, uxBitsToWaitFor, xTimeoutOccurred ) ( void ) xTimeoutOccurred +#endif + +#ifndef traceEVENT_GROUP_CLEAR_BITS + #define traceEVENT_GROUP_CLEAR_BITS( xEventGroup, uxBitsToClear ) +#endif + +#ifndef traceEVENT_GROUP_CLEAR_BITS_FROM_ISR + #define traceEVENT_GROUP_CLEAR_BITS_FROM_ISR( xEventGroup, uxBitsToClear ) +#endif + +#ifndef traceEVENT_GROUP_SET_BITS + #define traceEVENT_GROUP_SET_BITS( xEventGroup, uxBitsToSet ) +#endif + +#ifndef traceEVENT_GROUP_SET_BITS_FROM_ISR + #define traceEVENT_GROUP_SET_BITS_FROM_ISR( xEventGroup, uxBitsToSet ) +#endif + +#ifndef traceEVENT_GROUP_DELETE + #define traceEVENT_GROUP_DELETE( xEventGroup ) +#endif + +#ifndef tracePEND_FUNC_CALL + #define tracePEND_FUNC_CALL(xFunctionToPend, pvParameter1, ulParameter2, ret) +#endif + +#ifndef tracePEND_FUNC_CALL_FROM_ISR + #define tracePEND_FUNC_CALL_FROM_ISR(xFunctionToPend, pvParameter1, ulParameter2, ret) +#endif + +#ifndef traceQUEUE_REGISTRY_ADD + #define traceQUEUE_REGISTRY_ADD(xQueue, pcQueueName) +#endif + +#ifndef configGENERATE_RUN_TIME_STATS + #define configGENERATE_RUN_TIME_STATS 0 +#endif + +#if ( configGENERATE_RUN_TIME_STATS == 1 ) + + #ifndef portCONFIGURE_TIMER_FOR_RUN_TIME_STATS + #error If configGENERATE_RUN_TIME_STATS is defined then portCONFIGURE_TIMER_FOR_RUN_TIME_STATS must also be defined. portCONFIGURE_TIMER_FOR_RUN_TIME_STATS should call a port layer function to setup a peripheral timer/counter that can then be used as the run time counter time base. + #endif /* portCONFIGURE_TIMER_FOR_RUN_TIME_STATS */ + + #ifndef portGET_RUN_TIME_COUNTER_VALUE + #ifndef portALT_GET_RUN_TIME_COUNTER_VALUE + #error If configGENERATE_RUN_TIME_STATS is defined then either portGET_RUN_TIME_COUNTER_VALUE or portALT_GET_RUN_TIME_COUNTER_VALUE must also be defined. See the examples provided and the FreeRTOS web site for more information. + #endif /* portALT_GET_RUN_TIME_COUNTER_VALUE */ + #endif /* portGET_RUN_TIME_COUNTER_VALUE */ + +#endif /* configGENERATE_RUN_TIME_STATS */ + +#ifndef portCONFIGURE_TIMER_FOR_RUN_TIME_STATS + #define portCONFIGURE_TIMER_FOR_RUN_TIME_STATS() +#endif + +#ifndef configUSE_MALLOC_FAILED_HOOK + #define configUSE_MALLOC_FAILED_HOOK 0 +#endif + +#ifndef portPRIVILEGE_BIT + #define portPRIVILEGE_BIT ( ( UBaseType_t ) 0x00 ) +#endif + +#ifndef portYIELD_WITHIN_API + #define portYIELD_WITHIN_API portYIELD +#endif + +#ifndef pvPortMallocAligned + #define pvPortMallocAligned( x, puxStackBuffer ) ( ( ( puxStackBuffer ) == NULL ) ? ( pvPortMalloc( ( x ) ) ) : ( puxStackBuffer ) ) +#endif + +#ifndef vPortFreeAligned + #define vPortFreeAligned( pvBlockToFree ) vPortFree( pvBlockToFree ) +#endif + +#ifndef portSUPPRESS_TICKS_AND_SLEEP + #define portSUPPRESS_TICKS_AND_SLEEP( xExpectedIdleTime ) +#endif + +#ifndef configEXPECTED_IDLE_TIME_BEFORE_SLEEP + #define configEXPECTED_IDLE_TIME_BEFORE_SLEEP 2 +#endif + +#if configEXPECTED_IDLE_TIME_BEFORE_SLEEP < 2 + #error configEXPECTED_IDLE_TIME_BEFORE_SLEEP must not be less than 2 +#endif + +#ifndef configUSE_TICKLESS_IDLE + #define configUSE_TICKLESS_IDLE 0 +#endif + +#ifndef configPRE_SLEEP_PROCESSING + #define configPRE_SLEEP_PROCESSING( x ) +#endif + +#ifndef configPOST_SLEEP_PROCESSING + #define configPOST_SLEEP_PROCESSING( x ) +#endif + +#ifndef configUSE_QUEUE_SETS + #define configUSE_QUEUE_SETS 0 +#endif + +#ifndef portTASK_USES_FLOATING_POINT + #define portTASK_USES_FLOATING_POINT() +#endif + +#ifndef configUSE_TIME_SLICING + #define configUSE_TIME_SLICING 1 +#endif + +#ifndef configINCLUDE_APPLICATION_DEFINED_PRIVILEGED_FUNCTIONS + #define configINCLUDE_APPLICATION_DEFINED_PRIVILEGED_FUNCTIONS 0 +#endif + +#ifndef configUSE_NEWLIB_REENTRANT + #define configUSE_NEWLIB_REENTRANT 0 +#endif + +#ifndef configUSE_STATS_FORMATTING_FUNCTIONS + #define configUSE_STATS_FORMATTING_FUNCTIONS 0 +#endif + +#ifndef portASSERT_IF_INTERRUPT_PRIORITY_INVALID + #define portASSERT_IF_INTERRUPT_PRIORITY_INVALID() +#endif + +#ifndef configUSE_TRACE_FACILITY + #define configUSE_TRACE_FACILITY 0 +#endif + +#ifndef mtCOVERAGE_TEST_MARKER + #define mtCOVERAGE_TEST_MARKER() +#endif + +#ifndef portASSERT_IF_IN_ISR + #define portASSERT_IF_IN_ISR() +#endif + +#ifndef configUSE_PORT_OPTIMISED_TASK_SELECTION + #define configUSE_PORT_OPTIMISED_TASK_SELECTION 0 +#endif + +#ifndef configAPPLICATION_ALLOCATED_HEAP + #define configAPPLICATION_ALLOCATED_HEAP 0 +#endif + +#ifndef configUSE_TASK_NOTIFICATIONS + #define configUSE_TASK_NOTIFICATIONS 1 +#endif + +#ifndef portTICK_TYPE_IS_ATOMIC + #define portTICK_TYPE_IS_ATOMIC 0 +#endif + +#if( portTICK_TYPE_IS_ATOMIC == 0 ) + /* Either variables of tick type cannot be read atomically, or + portTICK_TYPE_IS_ATOMIC was not set - map the critical sections used when + the tick count is returned to the standard critical section macros. */ + #define portTICK_TYPE_ENTER_CRITICAL(mux) portENTER_CRITICAL(mux) + #define portTICK_TYPE_EXIT_CRITICAL(mux) portEXIT_CRITICAL(mux) + #define portTICK_TYPE_SET_INTERRUPT_MASK_FROM_ISR() portSET_INTERRUPT_MASK_FROM_ISR() + #define portTICK_TYPE_CLEAR_INTERRUPT_MASK_FROM_ISR( x ) portCLEAR_INTERRUPT_MASK_FROM_ISR( ( x ) ) +#else + /* The tick type can be read atomically, so critical sections used when the + tick count is returned can be defined away. */ + #define portTICK_TYPE_ENTER_CRITICAL() + #define portTICK_TYPE_EXIT_CRITICAL() + #define portTICK_TYPE_SET_INTERRUPT_MASK_FROM_ISR() 0 + #define portTICK_TYPE_CLEAR_INTERRUPT_MASK_FROM_ISR( x ) ( void ) x +#endif + +/* Definitions to allow backward compatibility with FreeRTOS versions prior to +V8 if desired. */ +#ifndef configENABLE_BACKWARD_COMPATIBILITY + #define configENABLE_BACKWARD_COMPATIBILITY 1 +#endif + +#if configENABLE_BACKWARD_COMPATIBILITY == 1 + #define eTaskStateGet eTaskGetState + #define portTickType TickType_t + #define xTaskHandle TaskHandle_t + #define xQueueHandle QueueHandle_t + #define xSemaphoreHandle SemaphoreHandle_t + #define xQueueSetHandle QueueSetHandle_t + #define xQueueSetMemberHandle QueueSetMemberHandle_t + #define xTimeOutType TimeOut_t + #define xMemoryRegion MemoryRegion_t + #define xTaskParameters TaskParameters_t + #define xTaskStatusType TaskStatus_t + #define xTimerHandle TimerHandle_t + #define xCoRoutineHandle CoRoutineHandle_t + #define pdTASK_HOOK_CODE TaskHookFunction_t + #define portTICK_RATE_MS portTICK_PERIOD_MS + + /* Backward compatibility within the scheduler code only - these definitions + are not really required but are included for completeness. */ + #define tmrTIMER_CALLBACK TimerCallbackFunction_t + #define pdTASK_CODE TaskFunction_t + #define xListItem ListItem_t + #define xList List_t +#endif /* configENABLE_BACKWARD_COMPATIBILITY */ + +#ifdef __cplusplus +} +#endif + +#endif /* INC_FREERTOS_H */ + diff --git a/components/freertos/include/freertos/FreeRTOSConfig.h b/components/freertos/include/freertos/FreeRTOSConfig.h new file mode 100644 index 0000000000..9ac9858235 --- /dev/null +++ b/components/freertos/include/freertos/FreeRTOSConfig.h @@ -0,0 +1,244 @@ +/* + FreeRTOS V8.2.0 - Copyright (C) 2015 Real Time Engineers Ltd. + All rights reserved + + VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION. + + This file is part of the FreeRTOS distribution. + + FreeRTOS is free software; you can redistribute it and/or modify it under + the terms of the GNU General Public License (version 2) as published by the + Free Software Foundation >>!AND MODIFIED BY!<< the FreeRTOS exception. + + *************************************************************************** + >>! NOTE: The modification to the GPL is included to allow you to !<< + >>! distribute a combined work that includes FreeRTOS without being !<< + >>! obliged to provide the source code for proprietary components !<< + >>! outside of the FreeRTOS kernel. !<< + *************************************************************************** + + FreeRTOS is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + FOR A PARTICULAR PURPOSE. Full license text is available on the following + link: http://www.freertos.org/a00114.html + + *************************************************************************** + * * + * FreeRTOS provides completely free yet professionally developed, * + * robust, strictly quality controlled, supported, and cross * + * platform software that is more than just the market leader, it * + * is the industry's de facto standard. * + * * + * Help yourself get started quickly while simultaneously helping * + * to support the FreeRTOS project by purchasing a FreeRTOS * + * tutorial book, reference manual, or both: * + * http://www.FreeRTOS.org/Documentation * + * * + *************************************************************************** + + http://www.FreeRTOS.org/FAQHelp.html - Having a problem? Start by reading + the FAQ page "My application does not run, what could be wrong?". Have you + defined configASSERT()? + + http://www.FreeRTOS.org/support - In return for receiving this top quality + embedded software for free we request you assist our global community by + participating in the support forum. + + http://www.FreeRTOS.org/training - Investing in training allows your team to + be as productive as possible as early as possible. Now you can receive + FreeRTOS training directly from Richard Barry, CEO of Real Time Engineers + Ltd, and the world's leading authority on the world's leading RTOS. + + http://www.FreeRTOS.org/plus - A selection of FreeRTOS ecosystem products, + including FreeRTOS+Trace - an indispensable productivity tool, a DOS + compatible FAT file system, and our tiny thread aware UDP/IP stack. + + http://www.FreeRTOS.org/labs - Where new FreeRTOS products go to incubate. + Come and try FreeRTOS+TCP, our new open source TCP/IP stack for FreeRTOS. + + http://www.OpenRTOS.com - Real Time Engineers ltd. license FreeRTOS to High + Integrity Systems ltd. to sell under the OpenRTOS brand. Low cost OpenRTOS + licenses offer ticketed support, indemnification and commercial middleware. + + http://www.SafeRTOS.com - High Integrity Systems also provide a safety + engineered and independently SIL3 certified version for use in safety and + mission critical applications that require provable dependability. + + 1 tab == 4 spaces! +*/ + +#ifndef FREERTOS_CONFIG_H +#define FREERTOS_CONFIG_H + +#include "sdkconfig.h" + + +/* ESP31 and ESP32 are dualcore processors. */ +#ifndef CONFIG_FREERTOS_UNICORE +#define portNUM_PROCESSORS 2 +#else +#define portNUM_PROCESSORS 1 +#endif + +#define XT_USE_THREAD_SAFE_CLIB 0 +#define configASSERT_2 0 +#define portUSING_MPU_WRAPPERS 0 +#define configUSE_MUTEX 1 +#undef XT_USE_SWPRI + +#if CONFIG_FREERTOS_CORETIMER_0 +#define XT_TIMER_INDEX 0 +#elif CONFIG_FREERTOS_CORETIMER_1 +#define XT_TIMER_INDEX 1 +#elif CONFIG_FREERTOS_CORETIMER_2 +#define XT_TIMER_INDEX 2 +#elif CONFIG_FREERTOS_CORETIMER_3 +#define XT_TIMER_INDEX 3 +#endif + +#define configNUM_THREAD_LOCAL_STORAGE_POINTERS CONFIG_FREERTOS_THREAD_LOCAL_STORAGE_POINTERS + +#define XT_CLOCK_FREQ 13000000 + +/* Required for configuration-dependent settings */ +#include "xtensa_config.h" + + +#if 1 +#ifndef __ASSEMBLER__ +#include "rom/ets_sys.h" +#define configASSERT(a) if (!(a)) ets_printf("%s:%d (%s)- assert failed!\n", __FILE__, __LINE__, __FUNCTION__) +#endif +#endif + + +/*----------------------------------------------------------- + * Application specific definitions. + * + * These definitions should be adjusted for your particular hardware and + * application requirements. + * + * Note that the default heap size is deliberately kept small so that + * the build is more likely to succeed for configurations with limited + * memory. + * + * THESE PARAMETERS ARE DESCRIBED WITHIN THE 'CONFIGURATION' SECTION OF THE + * FreeRTOS API DOCUMENTATION AVAILABLE ON THE FreeRTOS.org WEB SITE. + *----------------------------------------------------------*/ + +#define configUSE_PREEMPTION 1 +#define configUSE_IDLE_HOOK 0 + +#define configUSE_TICK_HOOK 0 + +#define configTICK_RATE_HZ ( CONFIG_FREERTOS_HZ ) + +/* Default clock rate for simulator */ +//#define configCPU_CLOCK_HZ 80000000 + +/* This has impact on speed of search for highest priority */ +#ifdef SMALL_TEST +#define configMAX_PRIORITIES ( 7 ) +#else +#define configMAX_PRIORITIES ( 25 ) +#endif + +/* Minimal stack size. This may need to be increased for your application */ +/* NOTE: The FreeRTOS demos may not work reliably with stack size < 4KB. */ +/* The Xtensa-specific examples should be fine with XT_STACK_MIN_SIZE. */ +#if !(defined XT_STACK_MIN_SIZE) +#error XT_STACK_MIN_SIZE not defined, did you include xtensa_config.h ? +#endif + +#define configMINIMAL_STACK_SIZE (XT_STACK_MIN_SIZE > 1024 ? XT_STACK_MIN_SIZE : 1024) + +/* The Xtensa port uses a separate interrupt stack. Adjust the stack size */ +/* to suit the needs of your specific application. */ +#ifndef configISR_STACK_SIZE +#define configISR_STACK_SIZE 1024//2048 +#endif + +/* Minimal heap size to make sure examples can run on memory limited + configs. Adjust this to suit your system. */ + + +//We define the heap to span all of the non-statically-allocated shared RAM. ToDo: Make sure there +//is some space left for the app and main cpu when running outside of a thread. +#define configAPPLICATION_ALLOCATED_HEAP 1 +#define configTOTAL_HEAP_SIZE (&_heap_end - &_heap_start)//( ( size_t ) (64 * 1024) ) + +#define configMAX_TASK_NAME_LEN ( 16 ) +#define configUSE_TRACE_FACILITY 0 /* Used by vTaskList in main.c */ +#define configUSE_STATS_FORMATTING_FUNCTIONS 0 /* Used by vTaskList in main.c */ +#define configUSE_TRACE_FACILITY_2 0 /* Provided by Xtensa port patch */ +#define configBENCHMARK 0 /* Provided by Xtensa port patch */ +#define configUSE_16_BIT_TICKS 0 +#define configIDLE_SHOULD_YIELD 0 +#define configQUEUE_REGISTRY_SIZE 0 + +#define configUSE_MUTEXES 1 +#define configUSE_RECURSIVE_MUTEXES 1 +#define configUSE_COUNTING_SEMAPHORES 1 + +#if CONFIG_FREERTOS_CHECK_STACKOVERFLOW_NONE +#define configCHECK_FOR_STACK_OVERFLOW 0 +#elif CONFIG_FREERTOS_CHECK_STACKOVERFLOW_PTRVAL +#define configCHECK_FOR_STACK_OVERFLOW 1 +#elif CONFIG_FREERTOS_CHECK_STACKOVERFLOW_CANARY +#define configCHECK_FOR_STACK_OVERFLOW 2 +#endif + + + + +/* Co-routine definitions. */ +#define configUSE_CO_ROUTINES 0 +#define configMAX_CO_ROUTINE_PRIORITIES ( 2 ) + +/* Set the following definitions to 1 to include the API function, or zero + to exclude the API function. */ + +#define INCLUDE_vTaskPrioritySet 1 +#define INCLUDE_uxTaskPriorityGet 1 +#define INCLUDE_vTaskDelete 1 +#define INCLUDE_vTaskCleanUpResources 0 +#define INCLUDE_vTaskSuspend 1 +#define INCLUDE_vTaskDelayUntil 1 +#define INCLUDE_vTaskDelay 1 +#define INCLUDE_uxTaskGetStackHighWaterMark 1 + +/* The priority at which the tick interrupt runs. This should probably be + kept at 1. */ +#define configKERNEL_INTERRUPT_PRIORITY 1 + +/* The maximum interrupt priority from which FreeRTOS.org API functions can + be called. Only API functions that end in ...FromISR() can be used within + interrupts. */ +#define configMAX_SYSCALL_INTERRUPT_PRIORITY XCHAL_EXCM_LEVEL + +#define configUSE_NEWLIB_REENTRANT 1 + +/* Test FreeRTOS timers (with timer task) and more. */ +/* Some files don't compile if this flag is disabled */ +#define configUSE_TIMERS 1 +#define configTIMER_TASK_PRIORITY 1 +#define configTIMER_QUEUE_LENGTH 10 +#define configTIMER_TASK_STACK_DEPTH configMINIMAL_STACK_SIZE + +#define INCLUDE_xTimerPendFunctionCall 1 +#define INCLUDE_eTaskGetState 1 +#define configUSE_QUEUE_SETS 1 + +#if (!defined XT_INTEXC_HOOKS) +#define configXT_INTEXC_HOOKS 1 /* Exception hooks used by certain tests */ +#if configUSE_TRACE_FACILITY_2 +#define configASSERT_2 1 /* Specific to Xtensa port */ +#endif +#endif + +#define configXT_BOARD 1 /* Board mode */ +#define configXT_SIMULATOR 0 + + +#endif /* FREERTOS_CONFIG_H */ + diff --git a/components/freertos/include/freertos/StackMacros.h b/components/freertos/include/freertos/StackMacros.h new file mode 100644 index 0000000000..50d2e198fc --- /dev/null +++ b/components/freertos/include/freertos/StackMacros.h @@ -0,0 +1,184 @@ +/* + FreeRTOS V8.2.0 - Copyright (C) 2015 Real Time Engineers Ltd. + All rights reserved + + VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION. + + This file is part of the FreeRTOS distribution. + + FreeRTOS is free software; you can redistribute it and/or modify it under + the terms of the GNU General Public License (version 2) as published by the + Free Software Foundation >>!AND MODIFIED BY!<< the FreeRTOS exception. + + *************************************************************************** + >>! NOTE: The modification to the GPL is included to allow you to !<< + >>! distribute a combined work that includes FreeRTOS without being !<< + >>! obliged to provide the source code for proprietary components !<< + >>! outside of the FreeRTOS kernel. !<< + *************************************************************************** + + FreeRTOS is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + FOR A PARTICULAR PURPOSE. Full license text is available on the following + link: http://www.freertos.org/a00114.html + + *************************************************************************** + * * + * FreeRTOS provides completely free yet professionally developed, * + * robust, strictly quality controlled, supported, and cross * + * platform software that is more than just the market leader, it * + * is the industry's de facto standard. * + * * + * Help yourself get started quickly while simultaneously helping * + * to support the FreeRTOS project by purchasing a FreeRTOS * + * tutorial book, reference manual, or both: * + * http://www.FreeRTOS.org/Documentation * + * * + *************************************************************************** + + http://www.FreeRTOS.org/FAQHelp.html - Having a problem? Start by reading + the FAQ page "My application does not run, what could be wrong?". Have you + defined configASSERT()? + + http://www.FreeRTOS.org/support - In return for receiving this top quality + embedded software for free we request you assist our global community by + participating in the support forum. + + http://www.FreeRTOS.org/training - Investing in training allows your team to + be as productive as possible as early as possible. Now you can receive + FreeRTOS training directly from Richard Barry, CEO of Real Time Engineers + Ltd, and the world's leading authority on the world's leading RTOS. + + http://www.FreeRTOS.org/plus - A selection of FreeRTOS ecosystem products, + including FreeRTOS+Trace - an indispensable productivity tool, a DOS + compatible FAT file system, and our tiny thread aware UDP/IP stack. + + http://www.FreeRTOS.org/labs - Where new FreeRTOS products go to incubate. + Come and try FreeRTOS+TCP, our new open source TCP/IP stack for FreeRTOS. + + http://www.OpenRTOS.com - Real Time Engineers ltd. license FreeRTOS to High + Integrity Systems ltd. to sell under the OpenRTOS brand. Low cost OpenRTOS + licenses offer ticketed support, indemnification and commercial middleware. + + http://www.SafeRTOS.com - High Integrity Systems also provide a safety + engineered and independently SIL3 certified version for use in safety and + mission critical applications that require provable dependability. + + 1 tab == 4 spaces! +*/ + +#ifndef STACK_MACROS_H +#define STACK_MACROS_H + +/* + * Call the stack overflow hook function if the stack of the task being swapped + * out is currently overflowed, or looks like it might have overflowed in the + * past. + * + * Setting configCHECK_FOR_STACK_OVERFLOW to 1 will cause the macro to check + * the current stack state only - comparing the current top of stack value to + * the stack limit. Setting configCHECK_FOR_STACK_OVERFLOW to greater than 1 + * will also cause the last few stack bytes to be checked to ensure the value + * to which the bytes were set when the task was created have not been + * overwritten. Note this second test does not guarantee that an overflowed + * stack will always be recognised. + */ + +/*-----------------------------------------------------------*/ + +#if( configCHECK_FOR_STACK_OVERFLOW == 0 ) + + /* FreeRTOSConfig.h is not set to check for stack overflows. */ + #define taskFIRST_CHECK_FOR_STACK_OVERFLOW() + #define taskSECOND_CHECK_FOR_STACK_OVERFLOW() + +#endif /* configCHECK_FOR_STACK_OVERFLOW == 0 */ +/*-----------------------------------------------------------*/ + +#if( configCHECK_FOR_STACK_OVERFLOW == 1 ) + + /* FreeRTOSConfig.h is only set to use the first method of + overflow checking. */ + #define taskSECOND_CHECK_FOR_STACK_OVERFLOW() + +#endif +/*-----------------------------------------------------------*/ + +#if( ( configCHECK_FOR_STACK_OVERFLOW > 0 ) && ( portSTACK_GROWTH < 0 ) ) + + /* Only the current stack state is to be checked. */ + #define taskFIRST_CHECK_FOR_STACK_OVERFLOW() \ + { \ + /* Is the currently saved stack pointer within the stack limit? */ \ + if( pxCurrentTCB[ xPortGetCoreID() ]->pxTopOfStack <= pxCurrentTCB[ xPortGetCoreID() ]->pxStack ) \ + { \ + vApplicationStackOverflowHook( ( TaskHandle_t ) pxCurrentTCB[ xPortGetCoreID() ], pxCurrentTCB[ xPortGetCoreID() ]->pcTaskName ); \ + } \ + } + +#endif /* configCHECK_FOR_STACK_OVERFLOW > 0 */ +/*-----------------------------------------------------------*/ + +#if( ( configCHECK_FOR_STACK_OVERFLOW > 0 ) && ( portSTACK_GROWTH > 0 ) ) + + /* Only the current stack state is to be checked. */ + #define taskFIRST_CHECK_FOR_STACK_OVERFLOW() \ + { \ + \ + /* Is the currently saved stack pointer within the stack limit? */ \ + if( pxCurrentTCB[ xPortGetCoreID() ]->pxTopOfStack >= pxCurrentTCB[ xPortGetCoreID() ]->pxEndOfStack ) \ + { \ + vApplicationStackOverflowHook( ( TaskHandle_t ) pxCurrentTCB[ xPortGetCoreID() ], pxCurrentTCB[ xPortGetCoreID() ]->pcTaskName ); \ + } \ + } + +#endif /* configCHECK_FOR_STACK_OVERFLOW == 1 */ +/*-----------------------------------------------------------*/ + +#if( ( configCHECK_FOR_STACK_OVERFLOW > 1 ) && ( portSTACK_GROWTH < 0 ) ) + + #define taskSECOND_CHECK_FOR_STACK_OVERFLOW() \ + { \ + static const uint8_t ucExpectedStackBytes[] = { tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE, \ + tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE, \ + tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE, \ + tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE, \ + tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE }; \ + \ + \ + /* Has the extremity of the task stack ever been written over? */ \ + if( memcmp( ( void * ) pxCurrentTCB[ xPortGetCoreID() ]->pxStack, ( void * ) ucExpectedStackBytes, sizeof( ucExpectedStackBytes ) ) != 0 ) \ + { \ + vApplicationStackOverflowHook( ( TaskHandle_t ) pxCurrentTCB[ xPortGetCoreID() ], pxCurrentTCB[ xPortGetCoreID() ]->pcTaskName ); \ + } \ + } + +#endif /* #if( configCHECK_FOR_STACK_OVERFLOW > 1 ) */ +/*-----------------------------------------------------------*/ + +#if( ( configCHECK_FOR_STACK_OVERFLOW > 1 ) && ( portSTACK_GROWTH > 0 ) ) + + #define taskSECOND_CHECK_FOR_STACK_OVERFLOW() \ + { \ + int8_t *pcEndOfStack = ( int8_t * ) pxCurrentTCB[ xPortGetCoreID() ]->pxEndOfStack; \ + static const uint8_t ucExpectedStackBytes[] = { tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE, \ + tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE, \ + tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE, \ + tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE, \ + tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE }; \ + \ + \ + pcEndOfStack -= sizeof( ucExpectedStackBytes ); \ + \ + /* Has the extremity of the task stack ever been written over? */ \ + if( memcmp( ( void * ) pcEndOfStack, ( void * ) ucExpectedStackBytes, sizeof( ucExpectedStackBytes ) ) != 0 ) \ + { \ + vApplicationStackOverflowHook( ( TaskHandle_t ) pxCurrentTCB[ xPortGetCoreID() ], pxCurrentTCB[ xPortGetCoreID() ]->pcTaskName ); \ + } \ + } + +#endif /* #if( configCHECK_FOR_STACK_OVERFLOW > 1 ) */ +/*-----------------------------------------------------------*/ + +#endif /* STACK_MACROS_H */ + diff --git a/components/freertos/include/freertos/croutine.h b/components/freertos/include/freertos/croutine.h new file mode 100644 index 0000000000..7dfd4b8c35 --- /dev/null +++ b/components/freertos/include/freertos/croutine.h @@ -0,0 +1,762 @@ +/* + FreeRTOS V8.2.0 - Copyright (C) 2015 Real Time Engineers Ltd. + All rights reserved + + VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION. + + This file is part of the FreeRTOS distribution. + + FreeRTOS is free software; you can redistribute it and/or modify it under + the terms of the GNU General Public License (version 2) as published by the + Free Software Foundation >>!AND MODIFIED BY!<< the FreeRTOS exception. + + *************************************************************************** + >>! NOTE: The modification to the GPL is included to allow you to !<< + >>! distribute a combined work that includes FreeRTOS without being !<< + >>! obliged to provide the source code for proprietary components !<< + >>! outside of the FreeRTOS kernel. !<< + *************************************************************************** + + FreeRTOS is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + FOR A PARTICULAR PURPOSE. Full license text is available on the following + link: http://www.freertos.org/a00114.html + + *************************************************************************** + * * + * FreeRTOS provides completely free yet professionally developed, * + * robust, strictly quality controlled, supported, and cross * + * platform software that is more than just the market leader, it * + * is the industry's de facto standard. * + * * + * Help yourself get started quickly while simultaneously helping * + * to support the FreeRTOS project by purchasing a FreeRTOS * + * tutorial book, reference manual, or both: * + * http://www.FreeRTOS.org/Documentation * + * * + *************************************************************************** + + http://www.FreeRTOS.org/FAQHelp.html - Having a problem? Start by reading + the FAQ page "My application does not run, what could be wrong?". Have you + defined configASSERT()? + + http://www.FreeRTOS.org/support - In return for receiving this top quality + embedded software for free we request you assist our global community by + participating in the support forum. + + http://www.FreeRTOS.org/training - Investing in training allows your team to + be as productive as possible as early as possible. Now you can receive + FreeRTOS training directly from Richard Barry, CEO of Real Time Engineers + Ltd, and the world's leading authority on the world's leading RTOS. + + http://www.FreeRTOS.org/plus - A selection of FreeRTOS ecosystem products, + including FreeRTOS+Trace - an indispensable productivity tool, a DOS + compatible FAT file system, and our tiny thread aware UDP/IP stack. + + http://www.FreeRTOS.org/labs - Where new FreeRTOS products go to incubate. + Come and try FreeRTOS+TCP, our new open source TCP/IP stack for FreeRTOS. + + http://www.OpenRTOS.com - Real Time Engineers ltd. license FreeRTOS to High + Integrity Systems ltd. to sell under the OpenRTOS brand. Low cost OpenRTOS + licenses offer ticketed support, indemnification and commercial middleware. + + http://www.SafeRTOS.com - High Integrity Systems also provide a safety + engineered and independently SIL3 certified version for use in safety and + mission critical applications that require provable dependability. + + 1 tab == 4 spaces! +*/ + +#ifndef CO_ROUTINE_H +#define CO_ROUTINE_H + +#ifndef INC_FREERTOS_H + #error "include FreeRTOS.h must appear in source files before include croutine.h" +#endif + +#include "list.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/* Used to hide the implementation of the co-routine control block. The +control block structure however has to be included in the header due to +the macro implementation of the co-routine functionality. */ +typedef void * CoRoutineHandle_t; + +/* Defines the prototype to which co-routine functions must conform. */ +typedef void (*crCOROUTINE_CODE)( CoRoutineHandle_t, UBaseType_t ); + +typedef struct corCoRoutineControlBlock +{ + crCOROUTINE_CODE pxCoRoutineFunction; + ListItem_t xGenericListItem; /*< List item used to place the CRCB in ready and blocked queues. */ + ListItem_t xEventListItem; /*< List item used to place the CRCB in event lists. */ + UBaseType_t uxPriority; /*< The priority of the co-routine in relation to other co-routines. */ + UBaseType_t uxIndex; /*< Used to distinguish between co-routines when multiple co-routines use the same co-routine function. */ + uint16_t uxState; /*< Used internally by the co-routine implementation. */ +} CRCB_t; /* Co-routine control block. Note must be identical in size down to uxPriority with TCB_t. */ + +/** + * croutine. h + *

+ BaseType_t xCoRoutineCreate(
+                                 crCOROUTINE_CODE pxCoRoutineCode,
+                                 UBaseType_t uxPriority,
+                                 UBaseType_t uxIndex
+                               );
+ * + * Create a new co-routine and add it to the list of co-routines that are + * ready to run. + * + * @param pxCoRoutineCode Pointer to the co-routine function. Co-routine + * functions require special syntax - see the co-routine section of the WEB + * documentation for more information. + * + * @param uxPriority The priority with respect to other co-routines at which + * the co-routine will run. + * + * @param uxIndex Used to distinguish between different co-routines that + * execute the same function. See the example below and the co-routine section + * of the WEB documentation for further information. + * + * @return pdPASS if the co-routine was successfully created and added to a ready + * list, otherwise an error code defined with ProjDefs.h. + * + * Example usage: +
+ // Co-routine to be created.
+ void vFlashCoRoutine( CoRoutineHandle_t xHandle, UBaseType_t uxIndex )
+ {
+ // Variables in co-routines must be declared static if they must maintain value across a blocking call.
+ // This may not be necessary for const variables.
+ static const char cLedToFlash[ 2 ] = { 5, 6 };
+ static const TickType_t uxFlashRates[ 2 ] = { 200, 400 };
+
+     // Must start every co-routine with a call to crSTART();
+     crSTART( xHandle );
+
+     for( ;; )
+     {
+         // This co-routine just delays for a fixed period, then toggles
+         // an LED.  Two co-routines are created using this function, so
+         // the uxIndex parameter is used to tell the co-routine which
+         // LED to flash and how int32_t to delay.  This assumes xQueue has
+         // already been created.
+         vParTestToggleLED( cLedToFlash[ uxIndex ] );
+         crDELAY( xHandle, uxFlashRates[ uxIndex ] );
+     }
+
+     // Must end every co-routine with a call to crEND();
+     crEND();
+ }
+
+ // Function that creates two co-routines.
+ void vOtherFunction( void )
+ {
+ uint8_t ucParameterToPass;
+ TaskHandle_t xHandle;
+
+     // Create two co-routines at priority 0.  The first is given index 0
+     // so (from the code above) toggles LED 5 every 200 ticks.  The second
+     // is given index 1 so toggles LED 6 every 400 ticks.
+     for( uxIndex = 0; uxIndex < 2; uxIndex++ )
+     {
+         xCoRoutineCreate( vFlashCoRoutine, 0, uxIndex );
+     }
+ }
+   
+ * \defgroup xCoRoutineCreate xCoRoutineCreate + * \ingroup Tasks + */ +BaseType_t xCoRoutineCreate( crCOROUTINE_CODE pxCoRoutineCode, UBaseType_t uxPriority, UBaseType_t uxIndex ); + + +/** + * croutine. h + *
+ void vCoRoutineSchedule( void );
+ * + * Run a co-routine. + * + * vCoRoutineSchedule() executes the highest priority co-routine that is able + * to run. The co-routine will execute until it either blocks, yields or is + * preempted by a task. Co-routines execute cooperatively so one + * co-routine cannot be preempted by another, but can be preempted by a task. + * + * If an application comprises of both tasks and co-routines then + * vCoRoutineSchedule should be called from the idle task (in an idle task + * hook). + * + * Example usage: +
+ // This idle task hook will schedule a co-routine each time it is called.
+ // The rest of the idle task will execute between co-routine calls.
+ void vApplicationIdleHook( void )
+ {
+	vCoRoutineSchedule();
+ }
+
+ // Alternatively, if you do not require any other part of the idle task to
+ // execute, the idle task hook can call vCoRoutineScheduler() within an
+ // infinite loop.
+ void vApplicationIdleHook( void )
+ {
+    for( ;; )
+    {
+        vCoRoutineSchedule();
+    }
+ }
+ 
+ * \defgroup vCoRoutineSchedule vCoRoutineSchedule + * \ingroup Tasks + */ +void vCoRoutineSchedule( void ); + +/** + * croutine. h + *
+ crSTART( CoRoutineHandle_t xHandle );
+ * + * This macro MUST always be called at the start of a co-routine function. + * + * Example usage: +
+ // Co-routine to be created.
+ void vACoRoutine( CoRoutineHandle_t xHandle, UBaseType_t uxIndex )
+ {
+ // Variables in co-routines must be declared static if they must maintain value across a blocking call.
+ static int32_t ulAVariable;
+
+     // Must start every co-routine with a call to crSTART();
+     crSTART( xHandle );
+
+     for( ;; )
+     {
+          // Co-routine functionality goes here.
+     }
+
+     // Must end every co-routine with a call to crEND();
+     crEND();
+ }
+ * \defgroup crSTART crSTART + * \ingroup Tasks + */ +#define crSTART( pxCRCB ) switch( ( ( CRCB_t * )( pxCRCB ) )->uxState ) { case 0: + +/** + * croutine. h + *
+ crEND();
+ * + * This macro MUST always be called at the end of a co-routine function. + * + * Example usage: +
+ // Co-routine to be created.
+ void vACoRoutine( CoRoutineHandle_t xHandle, UBaseType_t uxIndex )
+ {
+ // Variables in co-routines must be declared static if they must maintain value across a blocking call.
+ static int32_t ulAVariable;
+
+     // Must start every co-routine with a call to crSTART();
+     crSTART( xHandle );
+
+     for( ;; )
+     {
+          // Co-routine functionality goes here.
+     }
+
+     // Must end every co-routine with a call to crEND();
+     crEND();
+ }
+ * \defgroup crSTART crSTART + * \ingroup Tasks + */ +#define crEND() } + +/* + * These macros are intended for internal use by the co-routine implementation + * only. The macros should not be used directly by application writers. + */ +#define crSET_STATE0( xHandle ) ( ( CRCB_t * )( xHandle ) )->uxState = (__LINE__ * 2); return; case (__LINE__ * 2): +#define crSET_STATE1( xHandle ) ( ( CRCB_t * )( xHandle ) )->uxState = ((__LINE__ * 2)+1); return; case ((__LINE__ * 2)+1): + +/** + * croutine. h + *
+ crDELAY( CoRoutineHandle_t xHandle, TickType_t xTicksToDelay );
+ * + * Delay a co-routine for a fixed period of time. + * + * crDELAY can only be called from the co-routine function itself - not + * from within a function called by the co-routine function. This is because + * co-routines do not maintain their own stack. + * + * @param xHandle The handle of the co-routine to delay. This is the xHandle + * parameter of the co-routine function. + * + * @param xTickToDelay The number of ticks that the co-routine should delay + * for. The actual amount of time this equates to is defined by + * configTICK_RATE_HZ (set in FreeRTOSConfig.h). The constant portTICK_PERIOD_MS + * can be used to convert ticks to milliseconds. + * + * Example usage: +
+ // Co-routine to be created.
+ void vACoRoutine( CoRoutineHandle_t xHandle, UBaseType_t uxIndex )
+ {
+ // Variables in co-routines must be declared static if they must maintain value across a blocking call.
+ // This may not be necessary for const variables.
+ // We are to delay for 200ms.
+ static const xTickType xDelayTime = 200 / portTICK_PERIOD_MS;
+
+     // Must start every co-routine with a call to crSTART();
+     crSTART( xHandle );
+
+     for( ;; )
+     {
+        // Delay for 200ms.
+        crDELAY( xHandle, xDelayTime );
+
+        // Do something here.
+     }
+
+     // Must end every co-routine with a call to crEND();
+     crEND();
+ }
+ * \defgroup crDELAY crDELAY + * \ingroup Tasks + */ +#define crDELAY( xHandle, xTicksToDelay ) \ + if( ( xTicksToDelay ) > 0 ) \ + { \ + vCoRoutineAddToDelayedList( ( xTicksToDelay ), NULL ); \ + } \ + crSET_STATE0( ( xHandle ) ); + +/** + *
+ crQUEUE_SEND(
+                  CoRoutineHandle_t xHandle,
+                  QueueHandle_t pxQueue,
+                  void *pvItemToQueue,
+                  TickType_t xTicksToWait,
+                  BaseType_t *pxResult
+             )
+ * + * The macro's crQUEUE_SEND() and crQUEUE_RECEIVE() are the co-routine + * equivalent to the xQueueSend() and xQueueReceive() functions used by tasks. + * + * crQUEUE_SEND and crQUEUE_RECEIVE can only be used from a co-routine whereas + * xQueueSend() and xQueueReceive() can only be used from tasks. + * + * crQUEUE_SEND can only be called from the co-routine function itself - not + * from within a function called by the co-routine function. This is because + * co-routines do not maintain their own stack. + * + * See the co-routine section of the WEB documentation for information on + * passing data between tasks and co-routines and between ISR's and + * co-routines. + * + * @param xHandle The handle of the calling co-routine. This is the xHandle + * parameter of the co-routine function. + * + * @param pxQueue The handle of the queue on which the data will be posted. + * The handle is obtained as the return value when the queue is created using + * the xQueueCreate() API function. + * + * @param pvItemToQueue A pointer to the data being posted onto the queue. + * The number of bytes of each queued item is specified when the queue is + * created. This number of bytes is copied from pvItemToQueue into the queue + * itself. + * + * @param xTickToDelay The number of ticks that the co-routine should block + * to wait for space to become available on the queue, should space not be + * available immediately. The actual amount of time this equates to is defined + * by configTICK_RATE_HZ (set in FreeRTOSConfig.h). The constant + * portTICK_PERIOD_MS can be used to convert ticks to milliseconds (see example + * below). + * + * @param pxResult The variable pointed to by pxResult will be set to pdPASS if + * data was successfully posted onto the queue, otherwise it will be set to an + * error defined within ProjDefs.h. + * + * Example usage: +
+ // Co-routine function that blocks for a fixed period then posts a number onto
+ // a queue.
+ static void prvCoRoutineFlashTask( CoRoutineHandle_t xHandle, UBaseType_t uxIndex )
+ {
+ // Variables in co-routines must be declared static if they must maintain value across a blocking call.
+ static BaseType_t xNumberToPost = 0;
+ static BaseType_t xResult;
+
+    // Co-routines must begin with a call to crSTART().
+    crSTART( xHandle );
+
+    for( ;; )
+    {
+        // This assumes the queue has already been created.
+        crQUEUE_SEND( xHandle, xCoRoutineQueue, &xNumberToPost, NO_DELAY, &xResult );
+
+        if( xResult != pdPASS )
+        {
+            // The message was not posted!
+        }
+
+        // Increment the number to be posted onto the queue.
+        xNumberToPost++;
+
+        // Delay for 100 ticks.
+        crDELAY( xHandle, 100 );
+    }
+
+    // Co-routines must end with a call to crEND().
+    crEND();
+ }
+ * \defgroup crQUEUE_SEND crQUEUE_SEND + * \ingroup Tasks + */ +#define crQUEUE_SEND( xHandle, pxQueue, pvItemToQueue, xTicksToWait, pxResult ) \ +{ \ + *( pxResult ) = xQueueCRSend( ( pxQueue) , ( pvItemToQueue) , ( xTicksToWait ) ); \ + if( *( pxResult ) == errQUEUE_BLOCKED ) \ + { \ + crSET_STATE0( ( xHandle ) ); \ + *pxResult = xQueueCRSend( ( pxQueue ), ( pvItemToQueue ), 0 ); \ + } \ + if( *pxResult == errQUEUE_YIELD ) \ + { \ + crSET_STATE1( ( xHandle ) ); \ + *pxResult = pdPASS; \ + } \ +} + +/** + * croutine. h + *
+  crQUEUE_RECEIVE(
+                     CoRoutineHandle_t xHandle,
+                     QueueHandle_t pxQueue,
+                     void *pvBuffer,
+                     TickType_t xTicksToWait,
+                     BaseType_t *pxResult
+                 )
+ * + * The macro's crQUEUE_SEND() and crQUEUE_RECEIVE() are the co-routine + * equivalent to the xQueueSend() and xQueueReceive() functions used by tasks. + * + * crQUEUE_SEND and crQUEUE_RECEIVE can only be used from a co-routine whereas + * xQueueSend() and xQueueReceive() can only be used from tasks. + * + * crQUEUE_RECEIVE can only be called from the co-routine function itself - not + * from within a function called by the co-routine function. This is because + * co-routines do not maintain their own stack. + * + * See the co-routine section of the WEB documentation for information on + * passing data between tasks and co-routines and between ISR's and + * co-routines. + * + * @param xHandle The handle of the calling co-routine. This is the xHandle + * parameter of the co-routine function. + * + * @param pxQueue The handle of the queue from which the data will be received. + * The handle is obtained as the return value when the queue is created using + * the xQueueCreate() API function. + * + * @param pvBuffer The buffer into which the received item is to be copied. + * The number of bytes of each queued item is specified when the queue is + * created. This number of bytes is copied into pvBuffer. + * + * @param xTickToDelay The number of ticks that the co-routine should block + * to wait for data to become available from the queue, should data not be + * available immediately. The actual amount of time this equates to is defined + * by configTICK_RATE_HZ (set in FreeRTOSConfig.h). The constant + * portTICK_PERIOD_MS can be used to convert ticks to milliseconds (see the + * crQUEUE_SEND example). + * + * @param pxResult The variable pointed to by pxResult will be set to pdPASS if + * data was successfully retrieved from the queue, otherwise it will be set to + * an error code as defined within ProjDefs.h. + * + * Example usage: +
+ // A co-routine receives the number of an LED to flash from a queue.  It
+ // blocks on the queue until the number is received.
+ static void prvCoRoutineFlashWorkTask( CoRoutineHandle_t xHandle, UBaseType_t uxIndex )
+ {
+ // Variables in co-routines must be declared static if they must maintain value across a blocking call.
+ static BaseType_t xResult;
+ static UBaseType_t uxLEDToFlash;
+
+    // All co-routines must start with a call to crSTART().
+    crSTART( xHandle );
+
+    for( ;; )
+    {
+        // Wait for data to become available on the queue.
+        crQUEUE_RECEIVE( xHandle, xCoRoutineQueue, &uxLEDToFlash, portMAX_DELAY, &xResult );
+
+        if( xResult == pdPASS )
+        {
+            // We received the LED to flash - flash it!
+            vParTestToggleLED( uxLEDToFlash );
+        }
+    }
+
+    crEND();
+ }
+ * \defgroup crQUEUE_RECEIVE crQUEUE_RECEIVE + * \ingroup Tasks + */ +#define crQUEUE_RECEIVE( xHandle, pxQueue, pvBuffer, xTicksToWait, pxResult ) \ +{ \ + *( pxResult ) = xQueueCRReceive( ( pxQueue) , ( pvBuffer ), ( xTicksToWait ) ); \ + if( *( pxResult ) == errQUEUE_BLOCKED ) \ + { \ + crSET_STATE0( ( xHandle ) ); \ + *( pxResult ) = xQueueCRReceive( ( pxQueue) , ( pvBuffer ), 0 ); \ + } \ + if( *( pxResult ) == errQUEUE_YIELD ) \ + { \ + crSET_STATE1( ( xHandle ) ); \ + *( pxResult ) = pdPASS; \ + } \ +} + +/** + * croutine. h + *
+  crQUEUE_SEND_FROM_ISR(
+                            QueueHandle_t pxQueue,
+                            void *pvItemToQueue,
+                            BaseType_t xCoRoutinePreviouslyWoken
+                       )
+ * + * The macro's crQUEUE_SEND_FROM_ISR() and crQUEUE_RECEIVE_FROM_ISR() are the + * co-routine equivalent to the xQueueSendFromISR() and xQueueReceiveFromISR() + * functions used by tasks. + * + * crQUEUE_SEND_FROM_ISR() and crQUEUE_RECEIVE_FROM_ISR() can only be used to + * pass data between a co-routine and and ISR, whereas xQueueSendFromISR() and + * xQueueReceiveFromISR() can only be used to pass data between a task and and + * ISR. + * + * crQUEUE_SEND_FROM_ISR can only be called from an ISR to send data to a queue + * that is being used from within a co-routine. + * + * See the co-routine section of the WEB documentation for information on + * passing data between tasks and co-routines and between ISR's and + * co-routines. + * + * @param xQueue The handle to the queue on which the item is to be posted. + * + * @param pvItemToQueue A pointer to the item that is to be placed on the + * queue. The size of the items the queue will hold was defined when the + * queue was created, so this many bytes will be copied from pvItemToQueue + * into the queue storage area. + * + * @param xCoRoutinePreviouslyWoken This is included so an ISR can post onto + * the same queue multiple times from a single interrupt. The first call + * should always pass in pdFALSE. Subsequent calls should pass in + * the value returned from the previous call. + * + * @return pdTRUE if a co-routine was woken by posting onto the queue. This is + * used by the ISR to determine if a context switch may be required following + * the ISR. + * + * Example usage: +
+ // A co-routine that blocks on a queue waiting for characters to be received.
+ static void vReceivingCoRoutine( CoRoutineHandle_t xHandle, UBaseType_t uxIndex )
+ {
+ char cRxedChar;
+ BaseType_t xResult;
+
+     // All co-routines must start with a call to crSTART().
+     crSTART( xHandle );
+
+     for( ;; )
+     {
+         // Wait for data to become available on the queue.  This assumes the
+         // queue xCommsRxQueue has already been created!
+         crQUEUE_RECEIVE( xHandle, xCommsRxQueue, &uxLEDToFlash, portMAX_DELAY, &xResult );
+
+         // Was a character received?
+         if( xResult == pdPASS )
+         {
+             // Process the character here.
+         }
+     }
+
+     // All co-routines must end with a call to crEND().
+     crEND();
+ }
+
+ // An ISR that uses a queue to send characters received on a serial port to
+ // a co-routine.
+ void vUART_ISR( void )
+ {
+ char cRxedChar;
+ BaseType_t xCRWokenByPost = pdFALSE;
+
+     // We loop around reading characters until there are none left in the UART.
+     while( UART_RX_REG_NOT_EMPTY() )
+     {
+         // Obtain the character from the UART.
+         cRxedChar = UART_RX_REG;
+
+         // Post the character onto a queue.  xCRWokenByPost will be pdFALSE
+         // the first time around the loop.  If the post causes a co-routine
+         // to be woken (unblocked) then xCRWokenByPost will be set to pdTRUE.
+         // In this manner we can ensure that if more than one co-routine is
+         // blocked on the queue only one is woken by this ISR no matter how
+         // many characters are posted to the queue.
+         xCRWokenByPost = crQUEUE_SEND_FROM_ISR( xCommsRxQueue, &cRxedChar, xCRWokenByPost );
+     }
+ }
+ * \defgroup crQUEUE_SEND_FROM_ISR crQUEUE_SEND_FROM_ISR + * \ingroup Tasks + */ +#define crQUEUE_SEND_FROM_ISR( pxQueue, pvItemToQueue, xCoRoutinePreviouslyWoken ) xQueueCRSendFromISR( ( pxQueue ), ( pvItemToQueue ), ( xCoRoutinePreviouslyWoken ) ) + + +/** + * croutine. h + *
+  crQUEUE_SEND_FROM_ISR(
+                            QueueHandle_t pxQueue,
+                            void *pvBuffer,
+                            BaseType_t * pxCoRoutineWoken
+                       )
+ * + * The macro's crQUEUE_SEND_FROM_ISR() and crQUEUE_RECEIVE_FROM_ISR() are the + * co-routine equivalent to the xQueueSendFromISR() and xQueueReceiveFromISR() + * functions used by tasks. + * + * crQUEUE_SEND_FROM_ISR() and crQUEUE_RECEIVE_FROM_ISR() can only be used to + * pass data between a co-routine and and ISR, whereas xQueueSendFromISR() and + * xQueueReceiveFromISR() can only be used to pass data between a task and and + * ISR. + * + * crQUEUE_RECEIVE_FROM_ISR can only be called from an ISR to receive data + * from a queue that is being used from within a co-routine (a co-routine + * posted to the queue). + * + * See the co-routine section of the WEB documentation for information on + * passing data between tasks and co-routines and between ISR's and + * co-routines. + * + * @param xQueue The handle to the queue on which the item is to be posted. + * + * @param pvBuffer A pointer to a buffer into which the received item will be + * placed. The size of the items the queue will hold was defined when the + * queue was created, so this many bytes will be copied from the queue into + * pvBuffer. + * + * @param pxCoRoutineWoken A co-routine may be blocked waiting for space to become + * available on the queue. If crQUEUE_RECEIVE_FROM_ISR causes such a + * co-routine to unblock *pxCoRoutineWoken will get set to pdTRUE, otherwise + * *pxCoRoutineWoken will remain unchanged. + * + * @return pdTRUE an item was successfully received from the queue, otherwise + * pdFALSE. + * + * Example usage: +
+ // A co-routine that posts a character to a queue then blocks for a fixed
+ // period.  The character is incremented each time.
+ static void vSendingCoRoutine( CoRoutineHandle_t xHandle, UBaseType_t uxIndex )
+ {
+ // cChar holds its value while this co-routine is blocked and must therefore
+ // be declared static.
+ static char cCharToTx = 'a';
+ BaseType_t xResult;
+
+     // All co-routines must start with a call to crSTART().
+     crSTART( xHandle );
+
+     for( ;; )
+     {
+         // Send the next character to the queue.
+         crQUEUE_SEND( xHandle, xCoRoutineQueue, &cCharToTx, NO_DELAY, &xResult );
+
+         if( xResult == pdPASS )
+         {
+             // The character was successfully posted to the queue.
+         }
+		 else
+		 {
+			// Could not post the character to the queue.
+		 }
+
+         // Enable the UART Tx interrupt to cause an interrupt in this
+		 // hypothetical UART.  The interrupt will obtain the character
+		 // from the queue and send it.
+		 ENABLE_RX_INTERRUPT();
+
+		 // Increment to the next character then block for a fixed period.
+		 // cCharToTx will maintain its value across the delay as it is
+		 // declared static.
+		 cCharToTx++;
+		 if( cCharToTx > 'x' )
+		 {
+			cCharToTx = 'a';
+		 }
+		 crDELAY( 100 );
+     }
+
+     // All co-routines must end with a call to crEND().
+     crEND();
+ }
+
+ // An ISR that uses a queue to receive characters to send on a UART.
+ void vUART_ISR( void )
+ {
+ char cCharToTx;
+ BaseType_t xCRWokenByPost = pdFALSE;
+
+     while( UART_TX_REG_EMPTY() )
+     {
+         // Are there any characters in the queue waiting to be sent?
+		 // xCRWokenByPost will automatically be set to pdTRUE if a co-routine
+		 // is woken by the post - ensuring that only a single co-routine is
+		 // woken no matter how many times we go around this loop.
+         if( crQUEUE_RECEIVE_FROM_ISR( pxQueue, &cCharToTx, &xCRWokenByPost ) )
+		 {
+			 SEND_CHARACTER( cCharToTx );
+		 }
+     }
+ }
+ * \defgroup crQUEUE_RECEIVE_FROM_ISR crQUEUE_RECEIVE_FROM_ISR + * \ingroup Tasks + */ +#define crQUEUE_RECEIVE_FROM_ISR( pxQueue, pvBuffer, pxCoRoutineWoken ) xQueueCRReceiveFromISR( ( pxQueue ), ( pvBuffer ), ( pxCoRoutineWoken ) ) + +/* + * This function is intended for internal use by the co-routine macros only. + * The macro nature of the co-routine implementation requires that the + * prototype appears here. The function should not be used by application + * writers. + * + * Removes the current co-routine from its ready list and places it in the + * appropriate delayed list. + */ +void vCoRoutineAddToDelayedList( TickType_t xTicksToDelay, List_t *pxEventList ); + +/* + * This function is intended for internal use by the queue implementation only. + * The function should not be used by application writers. + * + * Removes the highest priority co-routine from the event list and places it in + * the pending ready list. + */ +BaseType_t xCoRoutineRemoveFromEventList( const List_t *pxEventList ); + +#ifdef __cplusplus +} +#endif + +#endif /* CO_ROUTINE_H */ diff --git a/components/freertos/include/freertos/deprecated_definitions.h b/components/freertos/include/freertos/deprecated_definitions.h new file mode 100644 index 0000000000..fb031cdde6 --- /dev/null +++ b/components/freertos/include/freertos/deprecated_definitions.h @@ -0,0 +1,321 @@ +/* + FreeRTOS V8.2.0 - Copyright (C) 2015 Real Time Engineers Ltd. + All rights reserved + + VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION. + + This file is part of the FreeRTOS distribution. + + FreeRTOS is free software; you can redistribute it and/or modify it under + the terms of the GNU General Public License (version 2) as published by the + Free Software Foundation >>!AND MODIFIED BY!<< the FreeRTOS exception. + + *************************************************************************** + >>! NOTE: The modification to the GPL is included to allow you to !<< + >>! distribute a combined work that includes FreeRTOS without being !<< + >>! obliged to provide the source code for proprietary components !<< + >>! outside of the FreeRTOS kernel. !<< + *************************************************************************** + + FreeRTOS is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + FOR A PARTICULAR PURPOSE. Full license text is available on the following + link: http://www.freertos.org/a00114.html + + *************************************************************************** + * * + * FreeRTOS provides completely free yet professionally developed, * + * robust, strictly quality controlled, supported, and cross * + * platform software that is more than just the market leader, it * + * is the industry's de facto standard. * + * * + * Help yourself get started quickly while simultaneously helping * + * to support the FreeRTOS project by purchasing a FreeRTOS * + * tutorial book, reference manual, or both: * + * http://www.FreeRTOS.org/Documentation * + * * + *************************************************************************** + + http://www.FreeRTOS.org/FAQHelp.html - Having a problem? Start by reading + the FAQ page "My application does not run, what could be wrong?". Have you + defined configASSERT()? + + http://www.FreeRTOS.org/support - In return for receiving this top quality + embedded software for free we request you assist our global community by + participating in the support forum. + + http://www.FreeRTOS.org/training - Investing in training allows your team to + be as productive as possible as early as possible. Now you can receive + FreeRTOS training directly from Richard Barry, CEO of Real Time Engineers + Ltd, and the world's leading authority on the world's leading RTOS. + + http://www.FreeRTOS.org/plus - A selection of FreeRTOS ecosystem products, + including FreeRTOS+Trace - an indispensable productivity tool, a DOS + compatible FAT file system, and our tiny thread aware UDP/IP stack. + + http://www.FreeRTOS.org/labs - Where new FreeRTOS products go to incubate. + Come and try FreeRTOS+TCP, our new open source TCP/IP stack for FreeRTOS. + + http://www.OpenRTOS.com - Real Time Engineers ltd. license FreeRTOS to High + Integrity Systems ltd. to sell under the OpenRTOS brand. Low cost OpenRTOS + licenses offer ticketed support, indemnification and commercial middleware. + + http://www.SafeRTOS.com - High Integrity Systems also provide a safety + engineered and independently SIL3 certified version for use in safety and + mission critical applications that require provable dependability. + + 1 tab == 4 spaces! +*/ + +#ifndef DEPRECATED_DEFINITIONS_H +#define DEPRECATED_DEFINITIONS_H + + +/* Each FreeRTOS port has a unique portmacro.h header file. Originally a +pre-processor definition was used to ensure the pre-processor found the correct +portmacro.h file for the port being used. That scheme was deprecated in favour +of setting the compiler's include path such that it found the correct +portmacro.h file - removing the need for the constant and allowing the +portmacro.h file to be located anywhere in relation to the port being used. The +definitions below remain in the code for backward compatibility only. New +projects should not use them. */ + +#ifdef OPEN_WATCOM_INDUSTRIAL_PC_PORT + #include "..\..\Source\portable\owatcom\16bitdos\pc\portmacro.h" + typedef void ( __interrupt __far *pxISR )(); +#endif + +#ifdef OPEN_WATCOM_FLASH_LITE_186_PORT + #include "..\..\Source\portable\owatcom\16bitdos\flsh186\portmacro.h" + typedef void ( __interrupt __far *pxISR )(); +#endif + +#ifdef GCC_MEGA_AVR + #include "../portable/GCC/ATMega323/portmacro.h" +#endif + +#ifdef IAR_MEGA_AVR + #include "../portable/IAR/ATMega323/portmacro.h" +#endif + +#ifdef MPLAB_PIC24_PORT + #include "../../Source/portable/MPLAB/PIC24_dsPIC/portmacro.h" +#endif + +#ifdef MPLAB_DSPIC_PORT + #include "../../Source/portable/MPLAB/PIC24_dsPIC/portmacro.h" +#endif + +#ifdef MPLAB_PIC18F_PORT + #include "../../Source/portable/MPLAB/PIC18F/portmacro.h" +#endif + +#ifdef MPLAB_PIC32MX_PORT + #include "../../Source/portable/MPLAB/PIC32MX/portmacro.h" +#endif + +#ifdef _FEDPICC + #include "libFreeRTOS/Include/portmacro.h" +#endif + +#ifdef SDCC_CYGNAL + #include "../../Source/portable/SDCC/Cygnal/portmacro.h" +#endif + +#ifdef GCC_ARM7 + #include "../../Source/portable/GCC/ARM7_LPC2000/portmacro.h" +#endif + +#ifdef GCC_ARM7_ECLIPSE + #include "portmacro.h" +#endif + +#ifdef ROWLEY_LPC23xx + #include "../../Source/portable/GCC/ARM7_LPC23xx/portmacro.h" +#endif + +#ifdef IAR_MSP430 + #include "..\..\Source\portable\IAR\MSP430\portmacro.h" +#endif + +#ifdef GCC_MSP430 + #include "../../Source/portable/GCC/MSP430F449/portmacro.h" +#endif + +#ifdef ROWLEY_MSP430 + #include "../../Source/portable/Rowley/MSP430F449/portmacro.h" +#endif + +#ifdef ARM7_LPC21xx_KEIL_RVDS + #include "..\..\Source\portable\RVDS\ARM7_LPC21xx\portmacro.h" +#endif + +#ifdef SAM7_GCC + #include "../../Source/portable/GCC/ARM7_AT91SAM7S/portmacro.h" +#endif + +#ifdef SAM7_IAR + #include "..\..\Source\portable\IAR\AtmelSAM7S64\portmacro.h" +#endif + +#ifdef SAM9XE_IAR + #include "..\..\Source\portable\IAR\AtmelSAM9XE\portmacro.h" +#endif + +#ifdef LPC2000_IAR + #include "..\..\Source\portable\IAR\LPC2000\portmacro.h" +#endif + +#ifdef STR71X_IAR + #include "..\..\Source\portable\IAR\STR71x\portmacro.h" +#endif + +#ifdef STR75X_IAR + #include "..\..\Source\portable\IAR\STR75x\portmacro.h" +#endif + +#ifdef STR75X_GCC + #include "..\..\Source\portable\GCC\STR75x\portmacro.h" +#endif + +#ifdef STR91X_IAR + #include "..\..\Source\portable\IAR\STR91x\portmacro.h" +#endif + +#ifdef GCC_H8S + #include "../../Source/portable/GCC/H8S2329/portmacro.h" +#endif + +#ifdef GCC_AT91FR40008 + #include "../../Source/portable/GCC/ARM7_AT91FR40008/portmacro.h" +#endif + +#ifdef RVDS_ARMCM3_LM3S102 + #include "../../Source/portable/RVDS/ARM_CM3/portmacro.h" +#endif + +#ifdef GCC_ARMCM3_LM3S102 + #include "../../Source/portable/GCC/ARM_CM3/portmacro.h" +#endif + +#ifdef GCC_ARMCM3 + #include "../../Source/portable/GCC/ARM_CM3/portmacro.h" +#endif + +#ifdef IAR_ARM_CM3 + #include "../../Source/portable/IAR/ARM_CM3/portmacro.h" +#endif + +#ifdef IAR_ARMCM3_LM + #include "../../Source/portable/IAR/ARM_CM3/portmacro.h" +#endif + +#ifdef HCS12_CODE_WARRIOR + #include "../../Source/portable/CodeWarrior/HCS12/portmacro.h" +#endif + +#ifdef MICROBLAZE_GCC + #include "../../Source/portable/GCC/MicroBlaze/portmacro.h" +#endif + +#ifdef TERN_EE + #include "..\..\Source\portable\Paradigm\Tern_EE\small\portmacro.h" +#endif + +#ifdef GCC_HCS12 + #include "../../Source/portable/GCC/HCS12/portmacro.h" +#endif + +#ifdef GCC_MCF5235 + #include "../../Source/portable/GCC/MCF5235/portmacro.h" +#endif + +#ifdef COLDFIRE_V2_GCC + #include "../../../Source/portable/GCC/ColdFire_V2/portmacro.h" +#endif + +#ifdef COLDFIRE_V2_CODEWARRIOR + #include "../../Source/portable/CodeWarrior/ColdFire_V2/portmacro.h" +#endif + +#ifdef GCC_PPC405 + #include "../../Source/portable/GCC/PPC405_Xilinx/portmacro.h" +#endif + +#ifdef GCC_PPC440 + #include "../../Source/portable/GCC/PPC440_Xilinx/portmacro.h" +#endif + +#ifdef _16FX_SOFTUNE + #include "..\..\Source\portable\Softune\MB96340\portmacro.h" +#endif + +#ifdef BCC_INDUSTRIAL_PC_PORT + /* A short file name has to be used in place of the normal + FreeRTOSConfig.h when using the Borland compiler. */ + #include "frconfig.h" + #include "..\portable\BCC\16BitDOS\PC\prtmacro.h" + typedef void ( __interrupt __far *pxISR )(); +#endif + +#ifdef BCC_FLASH_LITE_186_PORT + /* A short file name has to be used in place of the normal + FreeRTOSConfig.h when using the Borland compiler. */ + #include "frconfig.h" + #include "..\portable\BCC\16BitDOS\flsh186\prtmacro.h" + typedef void ( __interrupt __far *pxISR )(); +#endif + +#ifdef __GNUC__ + #ifdef __AVR32_AVR32A__ + #include "portmacro.h" + #endif +#endif + +#ifdef __ICCAVR32__ + #ifdef __CORE__ + #if __CORE__ == __AVR32A__ + #include "portmacro.h" + #endif + #endif +#endif + +#ifdef __91467D + #include "portmacro.h" +#endif + +#ifdef __96340 + #include "portmacro.h" +#endif + + +#ifdef __IAR_V850ES_Fx3__ + #include "../../Source/portable/IAR/V850ES/portmacro.h" +#endif + +#ifdef __IAR_V850ES_Jx3__ + #include "../../Source/portable/IAR/V850ES/portmacro.h" +#endif + +#ifdef __IAR_V850ES_Jx3_L__ + #include "../../Source/portable/IAR/V850ES/portmacro.h" +#endif + +#ifdef __IAR_V850ES_Jx2__ + #include "../../Source/portable/IAR/V850ES/portmacro.h" +#endif + +#ifdef __IAR_V850ES_Hx2__ + #include "../../Source/portable/IAR/V850ES/portmacro.h" +#endif + +#ifdef __IAR_78K0R_Kx3__ + #include "../../Source/portable/IAR/78K0R/portmacro.h" +#endif + +#ifdef __IAR_78K0R_Kx3L__ + #include "../../Source/portable/IAR/78K0R/portmacro.h" +#endif + +#endif /* DEPRECATED_DEFINITIONS_H */ + diff --git a/components/freertos/include/freertos/event_groups.h b/components/freertos/include/freertos/event_groups.h new file mode 100644 index 0000000000..c7d0156abe --- /dev/null +++ b/components/freertos/include/freertos/event_groups.h @@ -0,0 +1,730 @@ +/* + FreeRTOS V8.2.0 - Copyright (C) 2015 Real Time Engineers Ltd. + All rights reserved + + VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION. + + This file is part of the FreeRTOS distribution. + + FreeRTOS is free software; you can redistribute it and/or modify it under + the terms of the GNU General Public License (version 2) as published by the + Free Software Foundation >>!AND MODIFIED BY!<< the FreeRTOS exception. + + *************************************************************************** + >>! NOTE: The modification to the GPL is included to allow you to !<< + >>! distribute a combined work that includes FreeRTOS without being !<< + >>! obliged to provide the source code for proprietary components !<< + >>! outside of the FreeRTOS kernel. !<< + *************************************************************************** + + FreeRTOS is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + FOR A PARTICULAR PURPOSE. Full license text is available on the following + link: http://www.freertos.org/a00114.html + + *************************************************************************** + * * + * FreeRTOS provides completely free yet professionally developed, * + * robust, strictly quality controlled, supported, and cross * + * platform software that is more than just the market leader, it * + * is the industry's de facto standard. * + * * + * Help yourself get started quickly while simultaneously helping * + * to support the FreeRTOS project by purchasing a FreeRTOS * + * tutorial book, reference manual, or both: * + * http://www.FreeRTOS.org/Documentation * + * * + *************************************************************************** + + http://www.FreeRTOS.org/FAQHelp.html - Having a problem? Start by reading + the FAQ page "My application does not run, what could be wrong?". Have you + defined configASSERT()? + + http://www.FreeRTOS.org/support - In return for receiving this top quality + embedded software for free we request you assist our global community by + participating in the support forum. + + http://www.FreeRTOS.org/training - Investing in training allows your team to + be as productive as possible as early as possible. Now you can receive + FreeRTOS training directly from Richard Barry, CEO of Real Time Engineers + Ltd, and the world's leading authority on the world's leading RTOS. + + http://www.FreeRTOS.org/plus - A selection of FreeRTOS ecosystem products, + including FreeRTOS+Trace - an indispensable productivity tool, a DOS + compatible FAT file system, and our tiny thread aware UDP/IP stack. + + http://www.FreeRTOS.org/labs - Where new FreeRTOS products go to incubate. + Come and try FreeRTOS+TCP, our new open source TCP/IP stack for FreeRTOS. + + http://www.OpenRTOS.com - Real Time Engineers ltd. license FreeRTOS to High + Integrity Systems ltd. to sell under the OpenRTOS brand. Low cost OpenRTOS + licenses offer ticketed support, indemnification and commercial middleware. + + http://www.SafeRTOS.com - High Integrity Systems also provide a safety + engineered and independently SIL3 certified version for use in safety and + mission critical applications that require provable dependability. + + 1 tab == 4 spaces! +*/ + +#ifndef EVENT_GROUPS_H +#define EVENT_GROUPS_H + +#ifndef INC_FREERTOS_H + #error "include FreeRTOS.h" must appear in source files before "include event_groups.h" +#endif + +#include "timers.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * An event group is a collection of bits to which an application can assign a + * meaning. For example, an application may create an event group to convey + * the status of various CAN bus related events in which bit 0 might mean "A CAN + * message has been received and is ready for processing", bit 1 might mean "The + * application has queued a message that is ready for sending onto the CAN + * network", and bit 2 might mean "It is time to send a SYNC message onto the + * CAN network" etc. A task can then test the bit values to see which events + * are active, and optionally enter the Blocked state to wait for a specified + * bit or a group of specified bits to be active. To continue the CAN bus + * example, a CAN controlling task can enter the Blocked state (and therefore + * not consume any processing time) until either bit 0, bit 1 or bit 2 are + * active, at which time the bit that was actually active would inform the task + * which action it had to take (process a received message, send a message, or + * send a SYNC). + * + * The event groups implementation contains intelligence to avoid race + * conditions that would otherwise occur were an application to use a simple + * variable for the same purpose. This is particularly important with respect + * to when a bit within an event group is to be cleared, and when bits have to + * be set and then tested atomically - as is the case where event groups are + * used to create a synchronisation point between multiple tasks (a + * 'rendezvous'). + * + * \defgroup EventGroup + */ + + + +/** + * event_groups.h + * + * Type by which event groups are referenced. For example, a call to + * xEventGroupCreate() returns an EventGroupHandle_t variable that can then + * be used as a parameter to other event group functions. + * + * \defgroup EventGroupHandle_t EventGroupHandle_t + * \ingroup EventGroup + */ +typedef void * EventGroupHandle_t; + +/* + * The type that holds event bits always matches TickType_t - therefore the + * number of bits it holds is set by configUSE_16_BIT_TICKS (16 bits if set to 1, + * 32 bits if set to 0. + * + * \defgroup EventBits_t EventBits_t + * \ingroup EventGroup + */ +typedef TickType_t EventBits_t; + +/** + * event_groups.h + *
+ EventGroupHandle_t xEventGroupCreate( void );
+ 
+ * + * Create a new event group. This function cannot be called from an interrupt. + * + * Although event groups are not related to ticks, for internal implementation + * reasons the number of bits available for use in an event group is dependent + * on the configUSE_16_BIT_TICKS setting in FreeRTOSConfig.h. If + * configUSE_16_BIT_TICKS is 1 then each event group contains 8 usable bits (bit + * 0 to bit 7). If configUSE_16_BIT_TICKS is set to 0 then each event group has + * 24 usable bits (bit 0 to bit 23). The EventBits_t type is used to store + * event bits within an event group. + * + * @return If the event group was created then a handle to the event group is + * returned. If there was insufficient FreeRTOS heap available to create the + * event group then NULL is returned. See http://www.freertos.org/a00111.html + * + * Example usage: +
+	// Declare a variable to hold the created event group.
+	EventGroupHandle_t xCreatedEventGroup;
+
+	// Attempt to create the event group.
+	xCreatedEventGroup = xEventGroupCreate();
+
+	// Was the event group created successfully?
+	if( xCreatedEventGroup == NULL )
+	{
+		// The event group was not created because there was insufficient
+		// FreeRTOS heap available.
+	}
+	else
+	{
+		// The event group was created.
+	}
+   
+ * \defgroup xEventGroupCreate xEventGroupCreate + * \ingroup EventGroup + */ +EventGroupHandle_t xEventGroupCreate( void ) PRIVILEGED_FUNCTION; + +/** + * event_groups.h + *
+	EventBits_t xEventGroupWaitBits( 	EventGroupHandle_t xEventGroup,
+										const EventBits_t uxBitsToWaitFor,
+										const BaseType_t xClearOnExit,
+										const BaseType_t xWaitForAllBits,
+										const TickType_t xTicksToWait );
+ 
+ * + * [Potentially] block to wait for one or more bits to be set within a + * previously created event group. + * + * This function cannot be called from an interrupt. + * + * @param xEventGroup The event group in which the bits are being tested. The + * event group must have previously been created using a call to + * xEventGroupCreate(). + * + * @param uxBitsToWaitFor A bitwise value that indicates the bit or bits to test + * inside the event group. For example, to wait for bit 0 and/or bit 2 set + * uxBitsToWaitFor to 0x05. To wait for bits 0 and/or bit 1 and/or bit 2 set + * uxBitsToWaitFor to 0x07. Etc. + * + * @param xClearOnExit If xClearOnExit is set to pdTRUE then any bits within + * uxBitsToWaitFor that are set within the event group will be cleared before + * xEventGroupWaitBits() returns if the wait condition was met (if the function + * returns for a reason other than a timeout). If xClearOnExit is set to + * pdFALSE then the bits set in the event group are not altered when the call to + * xEventGroupWaitBits() returns. + * + * @param xWaitForAllBits If xWaitForAllBits is set to pdTRUE then + * xEventGroupWaitBits() will return when either all the bits in uxBitsToWaitFor + * are set or the specified block time expires. If xWaitForAllBits is set to + * pdFALSE then xEventGroupWaitBits() will return when any one of the bits set + * in uxBitsToWaitFor is set or the specified block time expires. The block + * time is specified by the xTicksToWait parameter. + * + * @param xTicksToWait The maximum amount of time (specified in 'ticks') to wait + * for one/all (depending on the xWaitForAllBits value) of the bits specified by + * uxBitsToWaitFor to become set. + * + * @return The value of the event group at the time either the bits being waited + * for became set, or the block time expired. Test the return value to know + * which bits were set. If xEventGroupWaitBits() returned because its timeout + * expired then not all the bits being waited for will be set. If + * xEventGroupWaitBits() returned because the bits it was waiting for were set + * then the returned value is the event group value before any bits were + * automatically cleared in the case that xClearOnExit parameter was set to + * pdTRUE. + * + * Example usage: +
+   #define BIT_0	( 1 << 0 )
+   #define BIT_4	( 1 << 4 )
+
+   void aFunction( EventGroupHandle_t xEventGroup )
+   {
+   EventBits_t uxBits;
+   const TickType_t xTicksToWait = 100 / portTICK_PERIOD_MS;
+
+		// Wait a maximum of 100ms for either bit 0 or bit 4 to be set within
+		// the event group.  Clear the bits before exiting.
+		uxBits = xEventGroupWaitBits(
+					xEventGroup,	// The event group being tested.
+					BIT_0 | BIT_4,	// The bits within the event group to wait for.
+					pdTRUE,			// BIT_0 and BIT_4 should be cleared before returning.
+					pdFALSE,		// Don't wait for both bits, either bit will do.
+					xTicksToWait );	// Wait a maximum of 100ms for either bit to be set.
+
+		if( ( uxBits & ( BIT_0 | BIT_4 ) ) == ( BIT_0 | BIT_4 ) )
+		{
+			// xEventGroupWaitBits() returned because both bits were set.
+		}
+		else if( ( uxBits & BIT_0 ) != 0 )
+		{
+			// xEventGroupWaitBits() returned because just BIT_0 was set.
+		}
+		else if( ( uxBits & BIT_4 ) != 0 )
+		{
+			// xEventGroupWaitBits() returned because just BIT_4 was set.
+		}
+		else
+		{
+			// xEventGroupWaitBits() returned because xTicksToWait ticks passed
+			// without either BIT_0 or BIT_4 becoming set.
+		}
+   }
+   
+ * \defgroup xEventGroupWaitBits xEventGroupWaitBits + * \ingroup EventGroup + */ +EventBits_t xEventGroupWaitBits( EventGroupHandle_t xEventGroup, const EventBits_t uxBitsToWaitFor, const BaseType_t xClearOnExit, const BaseType_t xWaitForAllBits, TickType_t xTicksToWait ) PRIVILEGED_FUNCTION; + +/** + * event_groups.h + *
+	EventBits_t xEventGroupClearBits( EventGroupHandle_t xEventGroup, const EventBits_t uxBitsToClear );
+ 
+ * + * Clear bits within an event group. This function cannot be called from an + * interrupt. + * + * @param xEventGroup The event group in which the bits are to be cleared. + * + * @param uxBitsToClear A bitwise value that indicates the bit or bits to clear + * in the event group. For example, to clear bit 3 only, set uxBitsToClear to + * 0x08. To clear bit 3 and bit 0 set uxBitsToClear to 0x09. + * + * @return The value of the event group before the specified bits were cleared. + * + * Example usage: +
+   #define BIT_0	( 1 << 0 )
+   #define BIT_4	( 1 << 4 )
+
+   void aFunction( EventGroupHandle_t xEventGroup )
+   {
+   EventBits_t uxBits;
+
+		// Clear bit 0 and bit 4 in xEventGroup.
+		uxBits = xEventGroupClearBits(
+								xEventGroup,	// The event group being updated.
+								BIT_0 | BIT_4 );// The bits being cleared.
+
+		if( ( uxBits & ( BIT_0 | BIT_4 ) ) == ( BIT_0 | BIT_4 ) )
+		{
+			// Both bit 0 and bit 4 were set before xEventGroupClearBits() was
+			// called.  Both will now be clear (not set).
+		}
+		else if( ( uxBits & BIT_0 ) != 0 )
+		{
+			// Bit 0 was set before xEventGroupClearBits() was called.  It will
+			// now be clear.
+		}
+		else if( ( uxBits & BIT_4 ) != 0 )
+		{
+			// Bit 4 was set before xEventGroupClearBits() was called.  It will
+			// now be clear.
+		}
+		else
+		{
+			// Neither bit 0 nor bit 4 were set in the first place.
+		}
+   }
+   
+ * \defgroup xEventGroupClearBits xEventGroupClearBits + * \ingroup EventGroup + */ +EventBits_t xEventGroupClearBits( EventGroupHandle_t xEventGroup, const EventBits_t uxBitsToClear ) PRIVILEGED_FUNCTION; + +/** + * event_groups.h + *
+	BaseType_t xEventGroupClearBitsFromISR( EventGroupHandle_t xEventGroup, const EventBits_t uxBitsToSet );
+ 
+ * + * A version of xEventGroupClearBits() that can be called from an interrupt. + * + * Setting bits in an event group is not a deterministic operation because there + * are an unknown number of tasks that may be waiting for the bit or bits being + * set. FreeRTOS does not allow nondeterministic operations to be performed + * while interrupts are disabled, so protects event groups that are accessed + * from tasks by suspending the scheduler rather than disabling interrupts. As + * a result event groups cannot be accessed directly from an interrupt service + * routine. Therefore xEventGroupClearBitsFromISR() sends a message to the + * timer task to have the clear operation performed in the context of the timer + * task. + * + * @param xEventGroup The event group in which the bits are to be cleared. + * + * @param uxBitsToClear A bitwise value that indicates the bit or bits to clear. + * For example, to clear bit 3 only, set uxBitsToClear to 0x08. To clear bit 3 + * and bit 0 set uxBitsToClear to 0x09. + * + * @return If the request to execute the function was posted successfully then + * pdPASS is returned, otherwise pdFALSE is returned. pdFALSE will be returned + * if the timer service queue was full. + * + * Example usage: +
+   #define BIT_0	( 1 << 0 )
+   #define BIT_4	( 1 << 4 )
+
+   // An event group which it is assumed has already been created by a call to
+   // xEventGroupCreate().
+   EventGroupHandle_t xEventGroup;
+
+   void anInterruptHandler( void )
+   {
+		// Clear bit 0 and bit 4 in xEventGroup.
+		xResult = xEventGroupClearBitsFromISR(
+							xEventGroup,	 // The event group being updated.
+							BIT_0 | BIT_4 ); // The bits being set.
+
+		if( xResult == pdPASS )
+		{
+			// The message was posted successfully.
+		}
+  }
+   
+ * \defgroup xEventGroupSetBitsFromISR xEventGroupSetBitsFromISR + * \ingroup EventGroup + */ +#if( configUSE_TRACE_FACILITY == 1 ) + BaseType_t xEventGroupClearBitsFromISR( EventGroupHandle_t xEventGroup, const EventBits_t uxBitsToSet ); +#else + #define xEventGroupClearBitsFromISR( xEventGroup, uxBitsToClear ) xTimerPendFunctionCallFromISR( vEventGroupClearBitsCallback, ( void * ) xEventGroup, ( uint32_t ) uxBitsToClear, NULL ) +#endif + +/** + * event_groups.h + *
+	EventBits_t xEventGroupSetBits( EventGroupHandle_t xEventGroup, const EventBits_t uxBitsToSet );
+ 
+ * + * Set bits within an event group. + * This function cannot be called from an interrupt. xEventGroupSetBitsFromISR() + * is a version that can be called from an interrupt. + * + * Setting bits in an event group will automatically unblock tasks that are + * blocked waiting for the bits. + * + * @param xEventGroup The event group in which the bits are to be set. + * + * @param uxBitsToSet A bitwise value that indicates the bit or bits to set. + * For example, to set bit 3 only, set uxBitsToSet to 0x08. To set bit 3 + * and bit 0 set uxBitsToSet to 0x09. + * + * @return The value of the event group at the time the call to + * xEventGroupSetBits() returns. There are two reasons why the returned value + * might have the bits specified by the uxBitsToSet parameter cleared. First, + * if setting a bit results in a task that was waiting for the bit leaving the + * blocked state then it is possible the bit will be cleared automatically + * (see the xClearBitOnExit parameter of xEventGroupWaitBits()). Second, any + * unblocked (or otherwise Ready state) task that has a priority above that of + * the task that called xEventGroupSetBits() will execute and may change the + * event group value before the call to xEventGroupSetBits() returns. + * + * Example usage: +
+   #define BIT_0	( 1 << 0 )
+   #define BIT_4	( 1 << 4 )
+
+   void aFunction( EventGroupHandle_t xEventGroup )
+   {
+   EventBits_t uxBits;
+
+		// Set bit 0 and bit 4 in xEventGroup.
+		uxBits = xEventGroupSetBits(
+							xEventGroup,	// The event group being updated.
+							BIT_0 | BIT_4 );// The bits being set.
+
+		if( ( uxBits & ( BIT_0 | BIT_4 ) ) == ( BIT_0 | BIT_4 ) )
+		{
+			// Both bit 0 and bit 4 remained set when the function returned.
+		}
+		else if( ( uxBits & BIT_0 ) != 0 )
+		{
+			// Bit 0 remained set when the function returned, but bit 4 was
+			// cleared.  It might be that bit 4 was cleared automatically as a
+			// task that was waiting for bit 4 was removed from the Blocked
+			// state.
+		}
+		else if( ( uxBits & BIT_4 ) != 0 )
+		{
+			// Bit 4 remained set when the function returned, but bit 0 was
+			// cleared.  It might be that bit 0 was cleared automatically as a
+			// task that was waiting for bit 0 was removed from the Blocked
+			// state.
+		}
+		else
+		{
+			// Neither bit 0 nor bit 4 remained set.  It might be that a task
+			// was waiting for both of the bits to be set, and the bits were
+			// cleared as the task left the Blocked state.
+		}
+   }
+   
+ * \defgroup xEventGroupSetBits xEventGroupSetBits + * \ingroup EventGroup + */ +EventBits_t xEventGroupSetBits( EventGroupHandle_t xEventGroup, const EventBits_t uxBitsToSet ) PRIVILEGED_FUNCTION; + +/** + * event_groups.h + *
+	BaseType_t xEventGroupSetBitsFromISR( EventGroupHandle_t xEventGroup, const EventBits_t uxBitsToSet, BaseType_t *pxHigherPriorityTaskWoken );
+ 
+ * + * A version of xEventGroupSetBits() that can be called from an interrupt. + * + * Setting bits in an event group is not a deterministic operation because there + * are an unknown number of tasks that may be waiting for the bit or bits being + * set. FreeRTOS does not allow nondeterministic operations to be performed in + * interrupts or from critical sections. Therefore xEventGroupSetBitFromISR() + * sends a message to the timer task to have the set operation performed in the + * context of the timer task - where a scheduler lock is used in place of a + * critical section. + * + * @param xEventGroup The event group in which the bits are to be set. + * + * @param uxBitsToSet A bitwise value that indicates the bit or bits to set. + * For example, to set bit 3 only, set uxBitsToSet to 0x08. To set bit 3 + * and bit 0 set uxBitsToSet to 0x09. + * + * @param pxHigherPriorityTaskWoken As mentioned above, calling this function + * will result in a message being sent to the timer daemon task. If the + * priority of the timer daemon task is higher than the priority of the + * currently running task (the task the interrupt interrupted) then + * *pxHigherPriorityTaskWoken will be set to pdTRUE by + * xEventGroupSetBitsFromISR(), indicating that a context switch should be + * requested before the interrupt exits. For that reason + * *pxHigherPriorityTaskWoken must be initialised to pdFALSE. See the + * example code below. + * + * @return If the request to execute the function was posted successfully then + * pdPASS is returned, otherwise pdFALSE is returned. pdFALSE will be returned + * if the timer service queue was full. + * + * Example usage: +
+   #define BIT_0	( 1 << 0 )
+   #define BIT_4	( 1 << 4 )
+
+   // An event group which it is assumed has already been created by a call to
+   // xEventGroupCreate().
+   EventGroupHandle_t xEventGroup;
+
+   void anInterruptHandler( void )
+   {
+   BaseType_t xHigherPriorityTaskWoken, xResult;
+
+		// xHigherPriorityTaskWoken must be initialised to pdFALSE.
+		xHigherPriorityTaskWoken = pdFALSE;
+
+		// Set bit 0 and bit 4 in xEventGroup.
+		xResult = xEventGroupSetBitsFromISR(
+							xEventGroup,	// The event group being updated.
+							BIT_0 | BIT_4   // The bits being set.
+							&xHigherPriorityTaskWoken );
+
+		// Was the message posted successfully?
+		if( xResult == pdPASS )
+		{
+			// If xHigherPriorityTaskWoken is now set to pdTRUE then a context
+			// switch should be requested.  The macro used is port specific and 
+			// will be either portYIELD_FROM_ISR() or portEND_SWITCHING_ISR() - 
+			// refer to the documentation page for the port being used.
+			portYIELD_FROM_ISR( xHigherPriorityTaskWoken );
+		}
+  }
+   
+ * \defgroup xEventGroupSetBitsFromISR xEventGroupSetBitsFromISR + * \ingroup EventGroup + */ +#if( configUSE_TRACE_FACILITY == 1 ) + BaseType_t xEventGroupSetBitsFromISR( EventGroupHandle_t xEventGroup, const EventBits_t uxBitsToSet, BaseType_t *pxHigherPriorityTaskWoken ); +#else + #define xEventGroupSetBitsFromISR( xEventGroup, uxBitsToSet, pxHigherPriorityTaskWoken ) xTimerPendFunctionCallFromISR( vEventGroupSetBitsCallback, ( void * ) xEventGroup, ( uint32_t ) uxBitsToSet, pxHigherPriorityTaskWoken ) +#endif + +/** + * event_groups.h + *
+	EventBits_t xEventGroupSync(	EventGroupHandle_t xEventGroup,
+									const EventBits_t uxBitsToSet,
+									const EventBits_t uxBitsToWaitFor,
+									TickType_t xTicksToWait );
+ 
+ * + * Atomically set bits within an event group, then wait for a combination of + * bits to be set within the same event group. This functionality is typically + * used to synchronise multiple tasks, where each task has to wait for the other + * tasks to reach a synchronisation point before proceeding. + * + * This function cannot be used from an interrupt. + * + * The function will return before its block time expires if the bits specified + * by the uxBitsToWait parameter are set, or become set within that time. In + * this case all the bits specified by uxBitsToWait will be automatically + * cleared before the function returns. + * + * @param xEventGroup The event group in which the bits are being tested. The + * event group must have previously been created using a call to + * xEventGroupCreate(). + * + * @param uxBitsToSet The bits to set in the event group before determining + * if, and possibly waiting for, all the bits specified by the uxBitsToWait + * parameter are set. + * + * @param uxBitsToWaitFor A bitwise value that indicates the bit or bits to test + * inside the event group. For example, to wait for bit 0 and bit 2 set + * uxBitsToWaitFor to 0x05. To wait for bits 0 and bit 1 and bit 2 set + * uxBitsToWaitFor to 0x07. Etc. + * + * @param xTicksToWait The maximum amount of time (specified in 'ticks') to wait + * for all of the bits specified by uxBitsToWaitFor to become set. + * + * @return The value of the event group at the time either the bits being waited + * for became set, or the block time expired. Test the return value to know + * which bits were set. If xEventGroupSync() returned because its timeout + * expired then not all the bits being waited for will be set. If + * xEventGroupSync() returned because all the bits it was waiting for were + * set then the returned value is the event group value before any bits were + * automatically cleared. + * + * Example usage: +
+ // Bits used by the three tasks.
+ #define TASK_0_BIT		( 1 << 0 )
+ #define TASK_1_BIT		( 1 << 1 )
+ #define TASK_2_BIT		( 1 << 2 )
+
+ #define ALL_SYNC_BITS ( TASK_0_BIT | TASK_1_BIT | TASK_2_BIT )
+
+ // Use an event group to synchronise three tasks.  It is assumed this event
+ // group has already been created elsewhere.
+ EventGroupHandle_t xEventBits;
+
+ void vTask0( void *pvParameters )
+ {
+ EventBits_t uxReturn;
+ TickType_t xTicksToWait = 100 / portTICK_PERIOD_MS;
+
+	 for( ;; )
+	 {
+		// Perform task functionality here.
+
+		// Set bit 0 in the event flag to note this task has reached the
+		// sync point.  The other two tasks will set the other two bits defined
+		// by ALL_SYNC_BITS.  All three tasks have reached the synchronisation
+		// point when all the ALL_SYNC_BITS are set.  Wait a maximum of 100ms
+		// for this to happen.
+		uxReturn = xEventGroupSync( xEventBits, TASK_0_BIT, ALL_SYNC_BITS, xTicksToWait );
+
+		if( ( uxReturn & ALL_SYNC_BITS ) == ALL_SYNC_BITS )
+		{
+			// All three tasks reached the synchronisation point before the call
+			// to xEventGroupSync() timed out.
+		}
+	}
+ }
+
+ void vTask1( void *pvParameters )
+ {
+	 for( ;; )
+	 {
+		// Perform task functionality here.
+
+		// Set bit 1 in the event flag to note this task has reached the
+		// synchronisation point.  The other two tasks will set the other two
+		// bits defined by ALL_SYNC_BITS.  All three tasks have reached the
+		// synchronisation point when all the ALL_SYNC_BITS are set.  Wait
+		// indefinitely for this to happen.
+		xEventGroupSync( xEventBits, TASK_1_BIT, ALL_SYNC_BITS, portMAX_DELAY );
+
+		// xEventGroupSync() was called with an indefinite block time, so
+		// this task will only reach here if the syncrhonisation was made by all
+		// three tasks, so there is no need to test the return value.
+	 }
+ }
+
+ void vTask2( void *pvParameters )
+ {
+	 for( ;; )
+	 {
+		// Perform task functionality here.
+
+		// Set bit 2 in the event flag to note this task has reached the
+		// synchronisation point.  The other two tasks will set the other two
+		// bits defined by ALL_SYNC_BITS.  All three tasks have reached the
+		// synchronisation point when all the ALL_SYNC_BITS are set.  Wait
+		// indefinitely for this to happen.
+		xEventGroupSync( xEventBits, TASK_2_BIT, ALL_SYNC_BITS, portMAX_DELAY );
+
+		// xEventGroupSync() was called with an indefinite block time, so
+		// this task will only reach here if the syncrhonisation was made by all
+		// three tasks, so there is no need to test the return value.
+	}
+ }
+
+ 
+ * \defgroup xEventGroupSync xEventGroupSync + * \ingroup EventGroup + */ +EventBits_t xEventGroupSync( EventGroupHandle_t xEventGroup, const EventBits_t uxBitsToSet, const EventBits_t uxBitsToWaitFor, TickType_t xTicksToWait ) PRIVILEGED_FUNCTION; + + +/** + * event_groups.h + *
+	EventBits_t xEventGroupGetBits( EventGroupHandle_t xEventGroup );
+ 
+ * + * Returns the current value of the bits in an event group. This function + * cannot be used from an interrupt. + * + * @param xEventGroup The event group being queried. + * + * @return The event group bits at the time xEventGroupGetBits() was called. + * + * \defgroup xEventGroupGetBits xEventGroupGetBits + * \ingroup EventGroup + */ +#define xEventGroupGetBits( xEventGroup ) xEventGroupClearBits( xEventGroup, 0 ) + +/** + * event_groups.h + *
+	EventBits_t xEventGroupGetBitsFromISR( EventGroupHandle_t xEventGroup );
+ 
+ * + * A version of xEventGroupGetBits() that can be called from an ISR. + * + * @param xEventGroup The event group being queried. + * + * @return The event group bits at the time xEventGroupGetBitsFromISR() was called. + * + * \defgroup xEventGroupGetBitsFromISR xEventGroupGetBitsFromISR + * \ingroup EventGroup + */ +EventBits_t xEventGroupGetBitsFromISR( EventGroupHandle_t xEventGroup ); + +/** + * event_groups.h + *
+	void xEventGroupDelete( EventGroupHandle_t xEventGroup );
+ 
+ * + * Delete an event group that was previously created by a call to + * xEventGroupCreate(). Tasks that are blocked on the event group will be + * unblocked and obtain 0 as the event group's value. + * + * @param xEventGroup The event group being deleted. + */ +void vEventGroupDelete( EventGroupHandle_t xEventGroup ); + +/* For internal use only. */ +void vEventGroupSetBitsCallback( void *pvEventGroup, const uint32_t ulBitsToSet ); +void vEventGroupClearBitsCallback( void *pvEventGroup, const uint32_t ulBitsToClear ); + +#if (configUSE_TRACE_FACILITY == 1) + UBaseType_t uxEventGroupGetNumber( void* xEventGroup ); +#endif + +#ifdef __cplusplus +} +#endif + +#endif /* EVENT_GROUPS_H */ + + diff --git a/components/freertos/include/freertos/heap_regions.h b/components/freertos/include/freertos/heap_regions.h new file mode 100644 index 0000000000..aedea42a16 --- /dev/null +++ b/components/freertos/include/freertos/heap_regions.h @@ -0,0 +1,34 @@ +// Copyright 2015-2016 Espressif Systems (Shanghai) PTE LTD +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at + +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +#ifndef _HEAP_REGIONS_H +#define _HEAP_REGIONS_H + +#include "freertos/FreeRTOS.h" + + +typedef struct HeapRegionTagged +{ + uint8_t *pucStartAddress; + size_t xSizeInBytes; + BaseType_t xTag; + uint32_t xExecAddr; +} HeapRegionTagged_t; + + +void vPortDefineHeapRegionsTagged( const HeapRegionTagged_t * const pxHeapRegions ); +void *pvPortMallocTagged( size_t xWantedSize, BaseType_t tag ); + + + +#endif \ No newline at end of file diff --git a/components/freertos/include/freertos/list.h b/components/freertos/include/freertos/list.h new file mode 100644 index 0000000000..b63df7f724 --- /dev/null +++ b/components/freertos/include/freertos/list.h @@ -0,0 +1,453 @@ +/* + FreeRTOS V8.2.0 - Copyright (C) 2015 Real Time Engineers Ltd. + All rights reserved + + VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION. + + This file is part of the FreeRTOS distribution. + + FreeRTOS is free software; you can redistribute it and/or modify it under + the terms of the GNU General Public License (version 2) as published by the + Free Software Foundation >>!AND MODIFIED BY!<< the FreeRTOS exception. + + *************************************************************************** + >>! NOTE: The modification to the GPL is included to allow you to !<< + >>! distribute a combined work that includes FreeRTOS without being !<< + >>! obliged to provide the source code for proprietary components !<< + >>! outside of the FreeRTOS kernel. !<< + *************************************************************************** + + FreeRTOS is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + FOR A PARTICULAR PURPOSE. Full license text is available on the following + link: http://www.freertos.org/a00114.html + + *************************************************************************** + * * + * FreeRTOS provides completely free yet professionally developed, * + * robust, strictly quality controlled, supported, and cross * + * platform software that is more than just the market leader, it * + * is the industry's de facto standard. * + * * + * Help yourself get started quickly while simultaneously helping * + * to support the FreeRTOS project by purchasing a FreeRTOS * + * tutorial book, reference manual, or both: * + * http://www.FreeRTOS.org/Documentation * + * * + *************************************************************************** + + http://www.FreeRTOS.org/FAQHelp.html - Having a problem? Start by reading + the FAQ page "My application does not run, what could be wrong?". Have you + defined configASSERT()? + + http://www.FreeRTOS.org/support - In return for receiving this top quality + embedded software for free we request you assist our global community by + participating in the support forum. + + http://www.FreeRTOS.org/training - Investing in training allows your team to + be as productive as possible as early as possible. Now you can receive + FreeRTOS training directly from Richard Barry, CEO of Real Time Engineers + Ltd, and the world's leading authority on the world's leading RTOS. + + http://www.FreeRTOS.org/plus - A selection of FreeRTOS ecosystem products, + including FreeRTOS+Trace - an indispensable productivity tool, a DOS + compatible FAT file system, and our tiny thread aware UDP/IP stack. + + http://www.FreeRTOS.org/labs - Where new FreeRTOS products go to incubate. + Come and try FreeRTOS+TCP, our new open source TCP/IP stack for FreeRTOS. + + http://www.OpenRTOS.com - Real Time Engineers ltd. license FreeRTOS to High + Integrity Systems ltd. to sell under the OpenRTOS brand. Low cost OpenRTOS + licenses offer ticketed support, indemnification and commercial middleware. + + http://www.SafeRTOS.com - High Integrity Systems also provide a safety + engineered and independently SIL3 certified version for use in safety and + mission critical applications that require provable dependability. + + 1 tab == 4 spaces! +*/ + +/* + * This is the list implementation used by the scheduler. While it is tailored + * heavily for the schedulers needs, it is also available for use by + * application code. + * + * list_ts can only store pointers to list_item_ts. Each ListItem_t contains a + * numeric value (xItemValue). Most of the time the lists are sorted in + * descending item value order. + * + * Lists are created already containing one list item. The value of this + * item is the maximum possible that can be stored, it is therefore always at + * the end of the list and acts as a marker. The list member pxHead always + * points to this marker - even though it is at the tail of the list. This + * is because the tail contains a wrap back pointer to the true head of + * the list. + * + * In addition to it's value, each list item contains a pointer to the next + * item in the list (pxNext), a pointer to the list it is in (pxContainer) + * and a pointer to back to the object that contains it. These later two + * pointers are included for efficiency of list manipulation. There is + * effectively a two way link between the object containing the list item and + * the list item itself. + * + * + * \page ListIntroduction List Implementation + * \ingroup FreeRTOSIntro + */ + +#ifndef INC_FREERTOS_H + #error FreeRTOS.h must be included before list.h +#endif + +#ifndef LIST_H +#define LIST_H + +/* + * The list structure members are modified from within interrupts, and therefore + * by rights should be declared volatile. However, they are only modified in a + * functionally atomic way (within critical sections of with the scheduler + * suspended) and are either passed by reference into a function or indexed via + * a volatile variable. Therefore, in all use cases tested so far, the volatile + * qualifier can be omitted in order to provide a moderate performance + * improvement without adversely affecting functional behaviour. The assembly + * instructions generated by the IAR, ARM and GCC compilers when the respective + * compiler's options were set for maximum optimisation has been inspected and + * deemed to be as intended. That said, as compiler technology advances, and + * especially if aggressive cross module optimisation is used (a use case that + * has not been exercised to any great extend) then it is feasible that the + * volatile qualifier will be needed for correct optimisation. It is expected + * that a compiler removing essential code because, without the volatile + * qualifier on the list structure members and with aggressive cross module + * optimisation, the compiler deemed the code unnecessary will result in + * complete and obvious failure of the scheduler. If this is ever experienced + * then the volatile qualifier can be inserted in the relevant places within the + * list structures by simply defining configLIST_VOLATILE to volatile in + * FreeRTOSConfig.h (as per the example at the bottom of this comment block). + * If configLIST_VOLATILE is not defined then the preprocessor directives below + * will simply #define configLIST_VOLATILE away completely. + * + * To use volatile list structure members then add the following line to + * FreeRTOSConfig.h (without the quotes): + * "#define configLIST_VOLATILE volatile" + */ +#ifndef configLIST_VOLATILE + #define configLIST_VOLATILE +#endif /* configSUPPORT_CROSS_MODULE_OPTIMISATION */ + +#ifdef __cplusplus +extern "C" { +#endif + +/* Macros that can be used to place known values within the list structures, +then check that the known values do not get corrupted during the execution of +the application. These may catch the list data structures being overwritten in +memory. They will not catch data errors caused by incorrect configuration or +use of FreeRTOS.*/ +#if( configUSE_LIST_DATA_INTEGRITY_CHECK_BYTES == 0 ) + /* Define the macros to do nothing. */ + #define listFIRST_LIST_ITEM_INTEGRITY_CHECK_VALUE + #define listSECOND_LIST_ITEM_INTEGRITY_CHECK_VALUE + #define listFIRST_LIST_INTEGRITY_CHECK_VALUE + #define listSECOND_LIST_INTEGRITY_CHECK_VALUE + #define listSET_FIRST_LIST_ITEM_INTEGRITY_CHECK_VALUE( pxItem ) + #define listSET_SECOND_LIST_ITEM_INTEGRITY_CHECK_VALUE( pxItem ) + #define listSET_LIST_INTEGRITY_CHECK_1_VALUE( pxList ) + #define listSET_LIST_INTEGRITY_CHECK_2_VALUE( pxList ) + #define listTEST_LIST_ITEM_INTEGRITY( pxItem ) + #define listTEST_LIST_INTEGRITY( pxList ) +#else + /* Define macros that add new members into the list structures. */ + #define listFIRST_LIST_ITEM_INTEGRITY_CHECK_VALUE TickType_t xListItemIntegrityValue1; + #define listSECOND_LIST_ITEM_INTEGRITY_CHECK_VALUE TickType_t xListItemIntegrityValue2; + #define listFIRST_LIST_INTEGRITY_CHECK_VALUE TickType_t xListIntegrityValue1; + #define listSECOND_LIST_INTEGRITY_CHECK_VALUE TickType_t xListIntegrityValue2; + + /* Define macros that set the new structure members to known values. */ + #define listSET_FIRST_LIST_ITEM_INTEGRITY_CHECK_VALUE( pxItem ) ( pxItem )->xListItemIntegrityValue1 = pdINTEGRITY_CHECK_VALUE + #define listSET_SECOND_LIST_ITEM_INTEGRITY_CHECK_VALUE( pxItem ) ( pxItem )->xListItemIntegrityValue2 = pdINTEGRITY_CHECK_VALUE + #define listSET_LIST_INTEGRITY_CHECK_1_VALUE( pxList ) ( pxList )->xListIntegrityValue1 = pdINTEGRITY_CHECK_VALUE + #define listSET_LIST_INTEGRITY_CHECK_2_VALUE( pxList ) ( pxList )->xListIntegrityValue2 = pdINTEGRITY_CHECK_VALUE + + /* Define macros that will assert if one of the structure members does not + contain its expected value. */ + #define listTEST_LIST_ITEM_INTEGRITY( pxItem ) configASSERT( ( ( pxItem )->xListItemIntegrityValue1 == pdINTEGRITY_CHECK_VALUE ) && ( ( pxItem )->xListItemIntegrityValue2 == pdINTEGRITY_CHECK_VALUE ) ) + #define listTEST_LIST_INTEGRITY( pxList ) configASSERT( ( ( pxList )->xListIntegrityValue1 == pdINTEGRITY_CHECK_VALUE ) && ( ( pxList )->xListIntegrityValue2 == pdINTEGRITY_CHECK_VALUE ) ) +#endif /* configUSE_LIST_DATA_INTEGRITY_CHECK_BYTES */ + + +/* + * Definition of the only type of object that a list can contain. + */ +struct xLIST_ITEM +{ + listFIRST_LIST_ITEM_INTEGRITY_CHECK_VALUE /*< Set to a known value if configUSE_LIST_DATA_INTEGRITY_CHECK_BYTES is set to 1. */ + configLIST_VOLATILE TickType_t xItemValue; /*< The value being listed. In most cases this is used to sort the list in descending order. */ + struct xLIST_ITEM * configLIST_VOLATILE pxNext; /*< Pointer to the next ListItem_t in the list. */ + struct xLIST_ITEM * configLIST_VOLATILE pxPrevious; /*< Pointer to the previous ListItem_t in the list. */ + void * pvOwner; /*< Pointer to the object (normally a TCB) that contains the list item. There is therefore a two way link between the object containing the list item and the list item itself. */ + void * configLIST_VOLATILE pvContainer; /*< Pointer to the list in which this list item is placed (if any). */ + listSECOND_LIST_ITEM_INTEGRITY_CHECK_VALUE /*< Set to a known value if configUSE_LIST_DATA_INTEGRITY_CHECK_BYTES is set to 1. */ +}; +typedef struct xLIST_ITEM ListItem_t; /* For some reason lint wants this as two separate definitions. */ + +struct xMINI_LIST_ITEM +{ + listFIRST_LIST_ITEM_INTEGRITY_CHECK_VALUE /*< Set to a known value if configUSE_LIST_DATA_INTEGRITY_CHECK_BYTES is set to 1. */ + configLIST_VOLATILE TickType_t xItemValue; + struct xLIST_ITEM * configLIST_VOLATILE pxNext; + struct xLIST_ITEM * configLIST_VOLATILE pxPrevious; +}; +typedef struct xMINI_LIST_ITEM MiniListItem_t; + +/* + * Definition of the type of queue used by the scheduler. + */ +typedef struct xLIST +{ + listFIRST_LIST_INTEGRITY_CHECK_VALUE /*< Set to a known value if configUSE_LIST_DATA_INTEGRITY_CHECK_BYTES is set to 1. */ + configLIST_VOLATILE UBaseType_t uxNumberOfItems; + ListItem_t * configLIST_VOLATILE pxIndex; /*< Used to walk through the list. Points to the last item returned by a call to listGET_OWNER_OF_NEXT_ENTRY (). */ + MiniListItem_t xListEnd; /*< List item that contains the maximum possible item value meaning it is always at the end of the list and is therefore used as a marker. */ + listSECOND_LIST_INTEGRITY_CHECK_VALUE /*< Set to a known value if configUSE_LIST_DATA_INTEGRITY_CHECK_BYTES is set to 1. */ +} List_t; + +/* + * Access macro to set the owner of a list item. The owner of a list item + * is the object (usually a TCB) that contains the list item. + * + * \page listSET_LIST_ITEM_OWNER listSET_LIST_ITEM_OWNER + * \ingroup LinkedList + */ +#define listSET_LIST_ITEM_OWNER( pxListItem, pxOwner ) ( ( pxListItem )->pvOwner = ( void * ) ( pxOwner ) ) + +/* + * Access macro to get the owner of a list item. The owner of a list item + * is the object (usually a TCB) that contains the list item. + * + * \page listSET_LIST_ITEM_OWNER listSET_LIST_ITEM_OWNER + * \ingroup LinkedList + */ +#define listGET_LIST_ITEM_OWNER( pxListItem ) ( ( pxListItem )->pvOwner ) + +/* + * Access macro to set the value of the list item. In most cases the value is + * used to sort the list in descending order. + * + * \page listSET_LIST_ITEM_VALUE listSET_LIST_ITEM_VALUE + * \ingroup LinkedList + */ +#define listSET_LIST_ITEM_VALUE( pxListItem, xValue ) ( ( pxListItem )->xItemValue = ( xValue ) ) + +/* + * Access macro to retrieve the value of the list item. The value can + * represent anything - for example the priority of a task, or the time at + * which a task should be unblocked. + * + * \page listGET_LIST_ITEM_VALUE listGET_LIST_ITEM_VALUE + * \ingroup LinkedList + */ +#define listGET_LIST_ITEM_VALUE( pxListItem ) ( ( pxListItem )->xItemValue ) + +/* + * Access macro to retrieve the value of the list item at the head of a given + * list. + * + * \page listGET_LIST_ITEM_VALUE listGET_LIST_ITEM_VALUE + * \ingroup LinkedList + */ +#define listGET_ITEM_VALUE_OF_HEAD_ENTRY( pxList ) ( ( ( pxList )->xListEnd ).pxNext->xItemValue ) + +/* + * Return the list item at the head of the list. + * + * \page listGET_HEAD_ENTRY listGET_HEAD_ENTRY + * \ingroup LinkedList + */ +#define listGET_HEAD_ENTRY( pxList ) ( ( ( pxList )->xListEnd ).pxNext ) + +/* + * Return the list item at the head of the list. + * + * \page listGET_NEXT listGET_NEXT + * \ingroup LinkedList + */ +#define listGET_NEXT( pxListItem ) ( ( pxListItem )->pxNext ) + +/* + * Return the list item that marks the end of the list + * + * \page listGET_END_MARKER listGET_END_MARKER + * \ingroup LinkedList + */ +#define listGET_END_MARKER( pxList ) ( ( ListItem_t const * ) ( &( ( pxList )->xListEnd ) ) ) + +/* + * Access macro to determine if a list contains any items. The macro will + * only have the value true if the list is empty. + * + * \page listLIST_IS_EMPTY listLIST_IS_EMPTY + * \ingroup LinkedList + */ +#define listLIST_IS_EMPTY( pxList ) ( ( BaseType_t ) ( ( pxList )->uxNumberOfItems == ( UBaseType_t ) 0 ) ) + +/* + * Access macro to return the number of items in the list. + */ +#define listCURRENT_LIST_LENGTH( pxList ) ( ( pxList )->uxNumberOfItems ) + +/* + * Access function to obtain the owner of the next entry in a list. + * + * The list member pxIndex is used to walk through a list. Calling + * listGET_OWNER_OF_NEXT_ENTRY increments pxIndex to the next item in the list + * and returns that entry's pxOwner parameter. Using multiple calls to this + * function it is therefore possible to move through every item contained in + * a list. + * + * The pxOwner parameter of a list item is a pointer to the object that owns + * the list item. In the scheduler this is normally a task control block. + * The pxOwner parameter effectively creates a two way link between the list + * item and its owner. + * + * @param pxTCB pxTCB is set to the address of the owner of the next list item. + * @param pxList The list from which the next item owner is to be returned. + * + * \page listGET_OWNER_OF_NEXT_ENTRY listGET_OWNER_OF_NEXT_ENTRY + * \ingroup LinkedList + */ +#define listGET_OWNER_OF_NEXT_ENTRY( pxTCB, pxList ) \ +{ \ +List_t * const pxConstList = ( pxList ); \ + /* Increment the index to the next item and return the item, ensuring */ \ + /* we don't return the marker used at the end of the list. */ \ + ( pxConstList )->pxIndex = ( pxConstList )->pxIndex->pxNext; \ + if( ( void * ) ( pxConstList )->pxIndex == ( void * ) &( ( pxConstList )->xListEnd ) ) \ + { \ + ( pxConstList )->pxIndex = ( pxConstList )->pxIndex->pxNext; \ + } \ + ( pxTCB ) = ( pxConstList )->pxIndex->pvOwner; \ +} + + +/* + * Access function to obtain the owner of the first entry in a list. Lists + * are normally sorted in ascending item value order. + * + * This function returns the pxOwner member of the first item in the list. + * The pxOwner parameter of a list item is a pointer to the object that owns + * the list item. In the scheduler this is normally a task control block. + * The pxOwner parameter effectively creates a two way link between the list + * item and its owner. + * + * @param pxList The list from which the owner of the head item is to be + * returned. + * + * \page listGET_OWNER_OF_HEAD_ENTRY listGET_OWNER_OF_HEAD_ENTRY + * \ingroup LinkedList + */ +#define listGET_OWNER_OF_HEAD_ENTRY( pxList ) ( (&( ( pxList )->xListEnd ))->pxNext->pvOwner ) + +/* + * Check to see if a list item is within a list. The list item maintains a + * "container" pointer that points to the list it is in. All this macro does + * is check to see if the container and the list match. + * + * @param pxList The list we want to know if the list item is within. + * @param pxListItem The list item we want to know if is in the list. + * @return pdTRUE if the list item is in the list, otherwise pdFALSE. + */ +#define listIS_CONTAINED_WITHIN( pxList, pxListItem ) ( ( BaseType_t ) ( ( pxListItem )->pvContainer == ( void * ) ( pxList ) ) ) + +/* + * Return the list a list item is contained within (referenced from). + * + * @param pxListItem The list item being queried. + * @return A pointer to the List_t object that references the pxListItem + */ +#define listLIST_ITEM_CONTAINER( pxListItem ) ( ( pxListItem )->pvContainer ) + +/* + * This provides a crude means of knowing if a list has been initialised, as + * pxList->xListEnd.xItemValue is set to portMAX_DELAY by the vListInitialise() + * function. + */ +#define listLIST_IS_INITIALISED( pxList ) ( ( pxList )->xListEnd.xItemValue == portMAX_DELAY ) + +/* + * Must be called before a list is used! This initialises all the members + * of the list structure and inserts the xListEnd item into the list as a + * marker to the back of the list. + * + * @param pxList Pointer to the list being initialised. + * + * \page vListInitialise vListInitialise + * \ingroup LinkedList + */ +void vListInitialise( List_t * const pxList ); + +/* + * Must be called before a list item is used. This sets the list container to + * null so the item does not think that it is already contained in a list. + * + * @param pxItem Pointer to the list item being initialised. + * + * \page vListInitialiseItem vListInitialiseItem + * \ingroup LinkedList + */ +void vListInitialiseItem( ListItem_t * const pxItem ); + +/* + * Insert a list item into a list. The item will be inserted into the list in + * a position determined by its item value (descending item value order). + * + * @param pxList The list into which the item is to be inserted. + * + * @param pxNewListItem The item that is to be placed in the list. + * + * \page vListInsert vListInsert + * \ingroup LinkedList + */ +void vListInsert( List_t * const pxList, ListItem_t * const pxNewListItem ); + +/* + * Insert a list item into a list. The item will be inserted in a position + * such that it will be the last item within the list returned by multiple + * calls to listGET_OWNER_OF_NEXT_ENTRY. + * + * The list member pvIndex is used to walk through a list. Calling + * listGET_OWNER_OF_NEXT_ENTRY increments pvIndex to the next item in the list. + * Placing an item in a list using vListInsertEnd effectively places the item + * in the list position pointed to by pvIndex. This means that every other + * item within the list will be returned by listGET_OWNER_OF_NEXT_ENTRY before + * the pvIndex parameter again points to the item being inserted. + * + * @param pxList The list into which the item is to be inserted. + * + * @param pxNewListItem The list item to be inserted into the list. + * + * \page vListInsertEnd vListInsertEnd + * \ingroup LinkedList + */ +void vListInsertEnd( List_t * const pxList, ListItem_t * const pxNewListItem ); + +/* + * Remove an item from a list. The list item has a pointer to the list that + * it is in, so only the list item need be passed into the function. + * + * @param uxListRemove The item to be removed. The item will remove itself from + * the list pointed to by it's pxContainer parameter. + * + * @return The number of items that remain in the list after the list item has + * been removed. + * + * \page uxListRemove uxListRemove + * \ingroup LinkedList + */ +UBaseType_t uxListRemove( ListItem_t * const pxItemToRemove ); + +#ifdef __cplusplus +} +#endif + +#endif + diff --git a/components/freertos/include/freertos/mpu_wrappers.h b/components/freertos/include/freertos/mpu_wrappers.h new file mode 100644 index 0000000000..504f6d934d --- /dev/null +++ b/components/freertos/include/freertos/mpu_wrappers.h @@ -0,0 +1,157 @@ +/* + FreeRTOS V8.2.0 - Copyright (C) 2015 Real Time Engineers Ltd. + All rights reserved + + VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION. + + This file is part of the FreeRTOS distribution. + + FreeRTOS is free software; you can redistribute it and/or modify it under + the terms of the GNU General Public License (version 2) as published by the + Free Software Foundation >>!AND MODIFIED BY!<< the FreeRTOS exception. + + *************************************************************************** + >>! NOTE: The modification to the GPL is included to allow you to !<< + >>! distribute a combined work that includes FreeRTOS without being !<< + >>! obliged to provide the source code for proprietary components !<< + >>! outside of the FreeRTOS kernel. !<< + *************************************************************************** + + FreeRTOS is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + FOR A PARTICULAR PURPOSE. Full license text is available on the following + link: http://www.freertos.org/a00114.html + + *************************************************************************** + * * + * FreeRTOS provides completely free yet professionally developed, * + * robust, strictly quality controlled, supported, and cross * + * platform software that is more than just the market leader, it * + * is the industry's de facto standard. * + * * + * Help yourself get started quickly while simultaneously helping * + * to support the FreeRTOS project by purchasing a FreeRTOS * + * tutorial book, reference manual, or both: * + * http://www.FreeRTOS.org/Documentation * + * * + *************************************************************************** + + http://www.FreeRTOS.org/FAQHelp.html - Having a problem? Start by reading + the FAQ page "My application does not run, what could be wrong?". Have you + defined configASSERT()? + + http://www.FreeRTOS.org/support - In return for receiving this top quality + embedded software for free we request you assist our global community by + participating in the support forum. + + http://www.FreeRTOS.org/training - Investing in training allows your team to + be as productive as possible as early as possible. Now you can receive + FreeRTOS training directly from Richard Barry, CEO of Real Time Engineers + Ltd, and the world's leading authority on the world's leading RTOS. + + http://www.FreeRTOS.org/plus - A selection of FreeRTOS ecosystem products, + including FreeRTOS+Trace - an indispensable productivity tool, a DOS + compatible FAT file system, and our tiny thread aware UDP/IP stack. + + http://www.FreeRTOS.org/labs - Where new FreeRTOS products go to incubate. + Come and try FreeRTOS+TCP, our new open source TCP/IP stack for FreeRTOS. + + http://www.OpenRTOS.com - Real Time Engineers ltd. license FreeRTOS to High + Integrity Systems ltd. to sell under the OpenRTOS brand. Low cost OpenRTOS + licenses offer ticketed support, indemnification and commercial middleware. + + http://www.SafeRTOS.com - High Integrity Systems also provide a safety + engineered and independently SIL3 certified version for use in safety and + mission critical applications that require provable dependability. + + 1 tab == 4 spaces! +*/ + +#ifndef MPU_WRAPPERS_H +#define MPU_WRAPPERS_H + +/* This file redefines API functions to be called through a wrapper macro, but +only for ports that are using the MPU. */ +#if portUSING_MPU_WRAPPERS + + /* MPU_WRAPPERS_INCLUDED_FROM_API_FILE will be defined when this file is + included from queue.c or task.c to prevent it from having an effect within + those files. */ + #ifndef MPU_WRAPPERS_INCLUDED_FROM_API_FILE + + #define xTaskGenericCreate MPU_xTaskGenericCreate + #define vTaskAllocateMPURegions MPU_vTaskAllocateMPURegions + #define vTaskDelete MPU_vTaskDelete + #define vTaskDelayUntil MPU_vTaskDelayUntil + #define vTaskDelay MPU_vTaskDelay + #define uxTaskPriorityGet MPU_uxTaskPriorityGet + #define vTaskPrioritySet MPU_vTaskPrioritySet + #define eTaskGetState MPU_eTaskGetState + #define vTaskSuspend MPU_vTaskSuspend + #define vTaskResume MPU_vTaskResume + #define vTaskSuspendAll MPU_vTaskSuspendAll + #define xTaskResumeAll MPU_xTaskResumeAll + #define xTaskGetTickCount MPU_xTaskGetTickCount + #define uxTaskGetNumberOfTasks MPU_uxTaskGetNumberOfTasks + #define vTaskList MPU_vTaskList + #define vTaskGetRunTimeStats MPU_vTaskGetRunTimeStats + #define vTaskSetApplicationTaskTag MPU_vTaskSetApplicationTaskTag + #define xTaskGetApplicationTaskTag MPU_xTaskGetApplicationTaskTag + #define xTaskCallApplicationTaskHook MPU_xTaskCallApplicationTaskHook + #define uxTaskGetStackHighWaterMark MPU_uxTaskGetStackHighWaterMark + #define xTaskGetCurrentTaskHandle MPU_xTaskGetCurrentTaskHandle + #define xTaskGetSchedulerState MPU_xTaskGetSchedulerState + #define xTaskGetIdleTaskHandle MPU_xTaskGetIdleTaskHandle + #define uxTaskGetSystemState MPU_uxTaskGetSystemState + + #define xQueueGenericCreate MPU_xQueueGenericCreate + #define xQueueCreateMutex MPU_xQueueCreateMutex + #define xQueueGiveMutexRecursive MPU_xQueueGiveMutexRecursive + #define xQueueTakeMutexRecursive MPU_xQueueTakeMutexRecursive + #define xQueueCreateCountingSemaphore MPU_xQueueCreateCountingSemaphore + #define xQueueGenericSend MPU_xQueueGenericSend + #define xQueueAltGenericSend MPU_xQueueAltGenericSend + #define xQueueAltGenericReceive MPU_xQueueAltGenericReceive + #define xQueueGenericReceive MPU_xQueueGenericReceive + #define uxQueueMessagesWaiting MPU_uxQueueMessagesWaiting + #define vQueueDelete MPU_vQueueDelete + #define xQueueGenericReset MPU_xQueueGenericReset + #define xQueueCreateSet MPU_xQueueCreateSet + #define xQueueSelectFromSet MPU_xQueueSelectFromSet + #define xQueueAddToSet MPU_xQueueAddToSet + #define xQueueRemoveFromSet MPU_xQueueRemoveFromSet + #define xQueuePeekFromISR MPU_xQueuePeekFromISR + #define xQueueGetMutexHolder MPU_xQueueGetMutexHolder + + #define pvPortMalloc MPU_pvPortMalloc + #define vPortFree MPU_vPortFree + #define xPortGetFreeHeapSize MPU_xPortGetFreeHeapSize + #define vPortInitialiseBlocks MPU_vPortInitialiseBlocks + + #if configQUEUE_REGISTRY_SIZE > 0 + #define vQueueAddToRegistry MPU_vQueueAddToRegistry + #define vQueueUnregisterQueue MPU_vQueueUnregisterQueue + #endif + + /* Remove the privileged function macro. */ + #define PRIVILEGED_FUNCTION + + #else /* MPU_WRAPPERS_INCLUDED_FROM_API_FILE */ + + /* Ensure API functions go in the privileged execution section. */ + #define PRIVILEGED_FUNCTION __attribute__((section("privileged_functions"))) + #define PRIVILEGED_DATA __attribute__((section("privileged_data"))) + + #endif /* MPU_WRAPPERS_INCLUDED_FROM_API_FILE */ + +#else /* portUSING_MPU_WRAPPERS */ + + #define PRIVILEGED_FUNCTION + #define PRIVILEGED_DATA + #define portUSING_MPU_WRAPPERS 0 + +#endif /* portUSING_MPU_WRAPPERS */ + + +#endif /* MPU_WRAPPERS_H */ + diff --git a/components/freertos/include/freertos/portable.h b/components/freertos/include/freertos/portable.h new file mode 100644 index 0000000000..4030ca0c03 --- /dev/null +++ b/components/freertos/include/freertos/portable.h @@ -0,0 +1,203 @@ +/* + FreeRTOS V8.2.0 - Copyright (C) 2015 Real Time Engineers Ltd. + All rights reserved + + VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION. + + This file is part of the FreeRTOS distribution. + + FreeRTOS is free software; you can redistribute it and/or modify it under + the terms of the GNU General Public License (version 2) as published by the + Free Software Foundation >>!AND MODIFIED BY!<< the FreeRTOS exception. + + *************************************************************************** + >>! NOTE: The modification to the GPL is included to allow you to !<< + >>! distribute a combined work that includes FreeRTOS without being !<< + >>! obliged to provide the source code for proprietary components !<< + >>! outside of the FreeRTOS kernel. !<< + *************************************************************************** + + FreeRTOS is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + FOR A PARTICULAR PURPOSE. Full license text is available on the following + link: http://www.freertos.org/a00114.html + + *************************************************************************** + * * + * FreeRTOS provides completely free yet professionally developed, * + * robust, strictly quality controlled, supported, and cross * + * platform software that is more than just the market leader, it * + * is the industry's de facto standard. * + * * + * Help yourself get started quickly while simultaneously helping * + * to support the FreeRTOS project by purchasing a FreeRTOS * + * tutorial book, reference manual, or both: * + * http://www.FreeRTOS.org/Documentation * + * * + *************************************************************************** + + http://www.FreeRTOS.org/FAQHelp.html - Having a problem? Start by reading + the FAQ page "My application does not run, what could be wrong?". Have you + defined configASSERT()? + + http://www.FreeRTOS.org/support - In return for receiving this top quality + embedded software for free we request you assist our global community by + participating in the support forum. + + http://www.FreeRTOS.org/training - Investing in training allows your team to + be as productive as possible as early as possible. Now you can receive + FreeRTOS training directly from Richard Barry, CEO of Real Time Engineers + Ltd, and the world's leading authority on the world's leading RTOS. + + http://www.FreeRTOS.org/plus - A selection of FreeRTOS ecosystem products, + including FreeRTOS+Trace - an indispensable productivity tool, a DOS + compatible FAT file system, and our tiny thread aware UDP/IP stack. + + http://www.FreeRTOS.org/labs - Where new FreeRTOS products go to incubate. + Come and try FreeRTOS+TCP, our new open source TCP/IP stack for FreeRTOS. + + http://www.OpenRTOS.com - Real Time Engineers ltd. license FreeRTOS to High + Integrity Systems ltd. to sell under the OpenRTOS brand. Low cost OpenRTOS + licenses offer ticketed support, indemnification and commercial middleware. + + http://www.SafeRTOS.com - High Integrity Systems also provide a safety + engineered and independently SIL3 certified version for use in safety and + mission critical applications that require provable dependability. + + 1 tab == 4 spaces! +*/ + +/*----------------------------------------------------------- + * Portable layer API. Each function must be defined for each port. + *----------------------------------------------------------*/ + +#ifndef PORTABLE_H +#define PORTABLE_H + +/* Each FreeRTOS port has a unique portmacro.h header file. Originally a +pre-processor definition was used to ensure the pre-processor found the correct +portmacro.h file for the port being used. That scheme was deprecated in favour +of setting the compiler's include path such that it found the correct +portmacro.h file - removing the need for the constant and allowing the +portmacro.h file to be located anywhere in relation to the port being used. +Purely for reasons of backward compatibility the old method is still valid, but +to make it clear that new projects should not use it, support for the port +specific constants has been moved into the deprecated_definitions.h header +file. */ +#include "deprecated_definitions.h" + +/* If portENTER_CRITICAL is not defined then including deprecated_definitions.h +did not result in a portmacro.h header file being included - and it should be +included here. In this case the path to the correct portmacro.h header file +must be set in the compiler's include path. */ +#ifndef portENTER_CRITICAL + #include "portmacro.h" +#endif + +#if portBYTE_ALIGNMENT == 8 + #define portBYTE_ALIGNMENT_MASK ( 0x0007U ) +#endif + +#if portBYTE_ALIGNMENT == 4 + #define portBYTE_ALIGNMENT_MASK ( 0x0003 ) +#endif + +#if portBYTE_ALIGNMENT == 2 + #define portBYTE_ALIGNMENT_MASK ( 0x0001 ) +#endif + +#if portBYTE_ALIGNMENT == 1 + #define portBYTE_ALIGNMENT_MASK ( 0x0000 ) +#endif + +#ifndef portBYTE_ALIGNMENT_MASK + #error "Invalid portBYTE_ALIGNMENT definition" +#endif + +#ifndef portNUM_CONFIGURABLE_REGIONS + #define portNUM_CONFIGURABLE_REGIONS 1 +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +#include "mpu_wrappers.h" + +/* + * Setup the stack of a new task so it is ready to be placed under the + * scheduler control. The registers have to be placed on the stack in + * the order that the port expects to find them. + * + */ +#if( portUSING_MPU_WRAPPERS == 1 ) + StackType_t *pxPortInitialiseStack( StackType_t *pxTopOfStack, TaskFunction_t pxCode, void *pvParameters, BaseType_t xRunPrivileged ) PRIVILEGED_FUNCTION; +#else + StackType_t *pxPortInitialiseStack( StackType_t *pxTopOfStack, TaskFunction_t pxCode, void *pvParameters ) PRIVILEGED_FUNCTION; +#endif + +/* Used by heap_5.c. */ +typedef struct HeapRegion +{ + uint8_t *pucStartAddress; + size_t xSizeInBytes; +} HeapRegion_t; + +/* + * Used to define multiple heap regions for use by heap_5.c. This function + * must be called before any calls to pvPortMalloc() - not creating a task, + * queue, semaphore, mutex, software timer, event group, etc. will result in + * pvPortMalloc being called. + * + * pxHeapRegions passes in an array of HeapRegion_t structures - each of which + * defines a region of memory that can be used as the heap. The array is + * terminated by a HeapRegions_t structure that has a size of 0. The region + * with the lowest start address must appear first in the array. + */ +void vPortDefineHeapRegions( const HeapRegion_t * const pxHeapRegions ); + + +/* + * Map to the memory management routines required for the port. + */ +void *pvPortMalloc( size_t xSize ) PRIVILEGED_FUNCTION; +void vPortFree( void *pv ) PRIVILEGED_FUNCTION; +void vPortInitialiseBlocks( void ) PRIVILEGED_FUNCTION; +size_t xPortGetFreeHeapSize( void ) PRIVILEGED_FUNCTION; +size_t xPortGetMinimumEverFreeHeapSize( void ) PRIVILEGED_FUNCTION; + +/* + * Setup the hardware ready for the scheduler to take control. This generally + * sets up a tick interrupt and sets timers for the correct tick frequency. + */ +BaseType_t xPortStartScheduler( void ) PRIVILEGED_FUNCTION; + +/* + * Undo any hardware/ISR setup that was performed by xPortStartScheduler() so + * the hardware is left in its original condition after the scheduler stops + * executing. + */ +void vPortEndScheduler( void ) PRIVILEGED_FUNCTION; + +/* + * The structures and methods of manipulating the MPU are contained within the + * port layer. + * + * Fills the xMPUSettings structure with the memory region information + * contained in xRegions. + */ +#if( portUSING_MPU_WRAPPERS == 1 ) + struct xMEMORY_REGION; + void vPortStoreTaskMPUSettings( xMPU_SETTINGS *xMPUSettings, const struct xMEMORY_REGION * const xRegions, StackType_t *pxBottomOfStack, uint16_t usStackDepth ) PRIVILEGED_FUNCTION; +#endif + +/* Multi-core: get current core ID */ +int xPortGetCoreID( void ); + + +#ifdef __cplusplus +} +#endif + +#endif /* PORTABLE_H */ + diff --git a/components/freertos/include/freertos/portbenchmark.h b/components/freertos/include/freertos/portbenchmark.h new file mode 100644 index 0000000000..4ce41d3dad --- /dev/null +++ b/components/freertos/include/freertos/portbenchmark.h @@ -0,0 +1,46 @@ +/******************************************************************************* +// Copyright (c) 2003-2015 Cadence Design Systems, Inc. +// +// Permission is hereby granted, free of charge, to any person obtaining +// a copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to +// permit persons to whom the Software is furnished to do so, subject to +// the following conditions: +// +// The above copyright notice and this permission notice shall be included +// in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +// CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +// SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +-------------------------------------------------------------------------------- +*/ + +/* + * This utility helps benchmarking interrupt latency and context switches. + * In order to enable it, set configBENCHMARK to 1 in FreeRTOSConfig.h. + * You will also need to download the FreeRTOS_trace patch that contains + * portbenchmark.c and the complete version of portbenchmark.h + */ + +#ifndef PORTBENCHMARK_H +#define PORTBENCHMARK_H + +#if configBENCHMARK + #error "You need to download the FreeRTOS_trace patch that overwrites this file" +#endif + +#define portbenchmarkINTERRUPT_DISABLE() +#define portbenchmarkINTERRUPT_RESTORE(newstate) +#define portbenchmarkIntLatency() +#define portbenchmarkIntWait() +#define portbenchmarkReset() +#define portbenchmarkPrint() + +#endif /* PORTBENCHMARK */ diff --git a/components/freertos/include/freertos/portmacro.h b/components/freertos/include/freertos/portmacro.h new file mode 100644 index 0000000000..b659a8271e --- /dev/null +++ b/components/freertos/include/freertos/portmacro.h @@ -0,0 +1,290 @@ +/* + FreeRTOS V8.2.0 - Copyright (C) 2015 Real Time Engineers Ltd. + All rights reserved + + VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION. + + *************************************************************************** + * * + * FreeRTOS provides completely free yet professionally developed, * + * robust, strictly quality controlled, supported, and cross * + * platform software that has become a de facto standard. * + * * + * Help yourself get started quickly and support the FreeRTOS * + * project by purchasing a FreeRTOS tutorial book, reference * + * manual, or both from: http://www.FreeRTOS.org/Documentation * + * * + * Thank you! * + * * + *************************************************************************** + + This file is part of the FreeRTOS distribution. + + FreeRTOS is free software; you can redistribute it and/or modify it under + the terms of the GNU General Public License (version 2) as published by the + Free Software Foundation >>!AND MODIFIED BY!<< the FreeRTOS exception. + + >>! NOTE: The modification to the GPL is included to allow you to !<< + >>! distribute a combined work that includes FreeRTOS without being !<< + >>! obliged to provide the source code for proprietary components !<< + >>! outside of the FreeRTOS kernel. !<< + + FreeRTOS is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + FOR A PARTICULAR PURPOSE. Full license text is available from the following + link: http://www.freertos.org/a00114.html + + 1 tab == 4 spaces! + + *************************************************************************** + * * + * Having a problem? Start by reading the FAQ "My application does * + * not run, what could be wrong?" * + * * + * http://www.FreeRTOS.org/FAQHelp.html * + * * + *************************************************************************** + + http://www.FreeRTOS.org - Documentation, books, training, latest versions, + license and Real Time Engineers Ltd. contact details. + + http://www.FreeRTOS.org/plus - A selection of FreeRTOS ecosystem products, + including FreeRTOS+Trace - an indispensable productivity tool, a DOS + compatible FAT file system, and our tiny thread aware UDP/IP stack. + + http://www.OpenRTOS.com - Real Time Engineers ltd license FreeRTOS to High + Integrity Systems to sell under the OpenRTOS brand. Low cost OpenRTOS + licenses offer ticketed support, indemnification and middleware. + + http://www.SafeRTOS.com - High Integrity Systems also provide a safety + engineered and independently SIL3 certified version for use in safety and + mission critical applications that require provable dependability. + + 1 tab == 4 spaces! +*/ + +#ifndef PORTMACRO_H +#define PORTMACRO_H + +#ifdef __cplusplus +extern "C" { +#endif + +#ifndef __ASSEMBLER__ + +#include + +#include +#include +#include +#include /* required for XSHAL_CLIB */ +#include + +//#include "xtensa_context.h" + +/*----------------------------------------------------------- + * Port specific definitions. + * + * The settings in this file configure FreeRTOS correctly for the + * given hardware and compiler. + * + * These settings should not be altered. + *----------------------------------------------------------- + */ + +/* Type definitions. */ + +#define portCHAR int8_t +#define portFLOAT float +#define portDOUBLE double +#define portLONG int32_t +#define portSHORT int16_t +#define portSTACK_TYPE uint8_t +#define portBASE_TYPE int + +typedef portSTACK_TYPE StackType_t; +typedef portBASE_TYPE BaseType_t; +typedef unsigned portBASE_TYPE UBaseType_t; + +#if( configUSE_16_BIT_TICKS == 1 ) + typedef uint16_t TickType_t; + #define portMAX_DELAY ( TickType_t ) 0xffff +#else + typedef uint32_t TickType_t; + #define portMAX_DELAY ( TickType_t ) 0xffffffffUL +#endif +/*-----------------------------------------------------------*/ + +// portbenchmark +#include "portbenchmark.h" + + +#define portMUX_DEBUG + +typedef struct { + volatile uint32_t mux; +#ifdef portMUX_DEBUG + const char *lastLockedFn; + int lastLockedLine; +#endif +} portMUX_TYPE; + + /* + * Kernel mux values can be: + * 0 - Uninitialized + * (0-portNUM_PROCESSORS)|(recCnt<<8)|0xB33F0000 - taken by core (val), recurse count is (recCnt) + * 0xB33FFFFF - free + * + * The magic number in the top 16 bits is there so we can detect uninitialized and corrupted muxes. + */ + +#define portMUX_MAGIC_VAL 0xB33F0000 +#define portMUX_FREE_VAL 0xB33FFFFF +#define portMUX_MAGIC_MASK 0xFFFF0000 +#define portMUX_MAGIC_SHIFT 16 +#define portMUX_CNT_MASK 0x0000FF00 +#define portMUX_CNT_SHIFT 8 +#define portMUX_VAL_MASK 0x000000FF +#define portMUX_VAL_SHIFT 0 + +/* Critical section management. NW-TODO: replace XTOS_SET_INTLEVEL with more efficient version, if any? */ +// These cannot be nested. They should be used with a lot of care and cannot be called from interrupt level. +#define portDISABLE_INTERRUPTS() do { XTOS_SET_INTLEVEL(XCHAL_EXCM_LEVEL); portbenchmarkINTERRUPT_DISABLE(); } while (0) +#define portENABLE_INTERRUPTS() do { portbenchmarkINTERRUPT_RESTORE(0); XTOS_SET_INTLEVEL(0); } while (0) + +#define portCRITICAL_NESTING_IN_TCB 1 + + +/* +Enable this to enable mux debugging. With this on, the mux code will warn you for deadlocks +and double releases etc. +*/ +#define portMUX_DEBUG + +/* +Modifications to portENTER_CRITICAL: + +The original portENTER_CRITICAL only disabled the ISRs. This is enough for single-CPU operation: by +disabling the interrupts, there is no task switch so no other tasks can meddle in the data, and because +interrupts are disabled, ISRs can't corrupt data structures either. + +For multiprocessing, things get a bit more hairy. First of all, disabling the interrupts doesn't stop +the tasks or ISRs on the other processors meddling with our CPU. For tasks, this is solved by adding +a spinlock to the portENTER_CRITICAL macro. A task running on the other CPU accessing the same data will +spinlock in the portENTER_CRITICAL code until the first CPU is done. + +For ISRs, we now also need muxes: while portENTER_CRITICAL disabling interrupts will stop ISRs on the same +CPU from meddling with the data, it does not stop interrupts on the other cores from interfering with the +data. For this, we also use a spinlock in the routines called by the ISR, but these spinlocks +do not disable the interrupts (because they already are). + +This all assumes that interrupts are either entirely disabled or enabled. Interrupr priority levels +will break this scheme. +*/ +void vPortCPUInitializeMutex(portMUX_TYPE *mux); +#ifdef portMUX_DEBUG +void vPortCPUAcquireMutex(portMUX_TYPE *mux, const char *function, int line); +portBASE_TYPE vPortCPUReleaseMutex(portMUX_TYPE *mux, const char *function, int line); +void vTaskEnterCritical( portMUX_TYPE *mux, const char *function, int line ); +void vTaskExitCritical( portMUX_TYPE *mux, const char *function, int line ); +#define portENTER_CRITICAL(mux) vTaskEnterCritical(mux, __FUNCTION__, __LINE__) +#define portEXIT_CRITICAL(mux) vTaskExitCritical(mux, __FUNCTION__, __LINE__) +#define portENTER_CRITICAL_ISR(mux) vPortCPUAcquireMutex(mux, __FUNCTION__, __LINE__) +#define portEXIT_CRITICAL_ISR(mux) vPortCPUReleaseMutex(mux, __FUNCTION__, __LINE__) +#else +void vTaskExitCritical( portMUX_TYPE *mux ); +void vTaskEnterCritical( portMUX_TYPE *mux ); +void vPortCPUAcquireMutex(portMUX_TYPE *mux); +portBASE_TYPE vPortCPUReleaseMutex(portMUX_TYPE *mux); +#define portENTER_CRITICAL(mux) vTaskEnterCritical(mux) +#define portEXIT_CRITICAL(mux) vTaskExitCritical(mux) +#define portENTER_CRITICAL_ISR(mux) vPortCPUAcquireMutex(mux) +#define portEXIT_CRITICAL_ISR(mux) vPortCPUReleaseMutex(mux) +#endif + + +// Cleaner and preferred solution allows nested interrupts disabling and restoring via local registers or stack. +// They can be called from interrupts too. +static inline unsigned portENTER_CRITICAL_NESTED() { unsigned state = XTOS_SET_INTLEVEL(XCHAL_EXCM_LEVEL); portbenchmarkINTERRUPT_DISABLE(); return state; } +#define portEXIT_CRITICAL_NESTED(state) do { portbenchmarkINTERRUPT_RESTORE(state); XTOS_RESTORE_JUST_INTLEVEL(state); } while (0) + +// These FreeRTOS versions are similar to the nested versions above +#define portSET_INTERRUPT_MASK_FROM_ISR() portENTER_CRITICAL_NESTED() +#define portCLEAR_INTERRUPT_MASK_FROM_ISR(state) portEXIT_CRITICAL_NESTED(state) + + +/*-----------------------------------------------------------*/ + +/* Architecture specifics. */ +#define portSTACK_GROWTH ( -1 ) +#define portTICK_PERIOD_MS ( ( TickType_t ) 1000 / configTICK_RATE_HZ ) +#define portBYTE_ALIGNMENT 4 +#define portNOP() XT_NOP() +/*-----------------------------------------------------------*/ + +/* Fine resolution time */ +#define portGET_RUN_TIME_COUNTER_VALUE() xthal_get_ccount() + +/* Kernel utilities. */ +void vPortYield( void ); +void _frxt_setup_switch( void ); +#define portYIELD() vPortYield() +#define portYIELD_FROM_ISR() _frxt_setup_switch() +/*-----------------------------------------------------------*/ + +/* Task function macros as described on the FreeRTOS.org WEB site. */ +#define portTASK_FUNCTION_PROTO( vFunction, pvParameters ) void vFunction( void *pvParameters ) +#define portTASK_FUNCTION( vFunction, pvParameters ) void vFunction( void *pvParameters ) + +// When coprocessors are defined, we to maintain a pointer to coprocessors area. +// We currently use a hack: redefine field xMPU_SETTINGS in TCB block as a structure that can hold: +// MPU wrappers, coprocessor area pointer, trace code structure, and more if needed. +// The field is normally used for memory protection. FreeRTOS should create another general purpose field. +typedef struct { + #if XCHAL_CP_NUM > 0 + volatile StackType_t* coproc_area; // Pointer to coprocessor save area; MUST BE FIRST + #endif + + #if portUSING_MPU_WRAPPERS + // Define here mpu_settings, which is port dependent + int mpu_setting; // Just a dummy example here; MPU not ported to Xtensa yet + #endif + + #if configUSE_TRACE_FACILITY_2 + struct { + // Cf. porttraceStamp() + int taskstamp; /* Stamp from inside task to see where we are */ + int taskstampcount; /* A counter usually incremented when we restart the task's loop */ + } porttrace; + #endif +} xMPU_SETTINGS; + +// Main hack to use MPU_wrappers even when no MPU is defined (warning: mpu_setting should not be accessed; otherwise move this above xMPU_SETTINGS) +#if (XCHAL_CP_NUM > 0 || configUSE_TRACE_FACILITY_2) && !portUSING_MPU_WRAPPERS // If MPU wrappers not used, we still need to allocate coproc area + #undef portUSING_MPU_WRAPPERS + #define portUSING_MPU_WRAPPERS 1 // Enable it to allocate coproc area + #define MPU_WRAPPERS_H // Override mpu_wrapper.h to disable unwanted code + #define PRIVILEGED_FUNCTION + #define PRIVILEGED_DATA +#endif + +// porttrace +#if configUSE_TRACE_FACILITY_2 +#include "porttrace.h" +#endif + +// configASSERT_2 if requested +#if configASSERT_2 +#include +void exit(int); +#define configASSERT( x ) if (!(x)) { porttracePrint(-1); printf("\nAssertion failed in %s:%d\n", __FILE__, __LINE__); exit(-1); } +#endif + +#endif // __ASSEMBLER__ + +#ifdef __cplusplus +} +#endif + +#endif /* PORTMACRO_H */ + diff --git a/components/freertos/include/freertos/porttrace.h b/components/freertos/include/freertos/porttrace.h new file mode 100644 index 0000000000..bf2fb41252 --- /dev/null +++ b/components/freertos/include/freertos/porttrace.h @@ -0,0 +1,42 @@ +/******************************************************************************* +// Copyright (c) 2003-2015 Cadence Design Systems, Inc. +// +// Permission is hereby granted, free of charge, to any person obtaining +// a copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to +// permit persons to whom the Software is furnished to do so, subject to +// the following conditions: +// +// The above copyright notice and this permission notice shall be included +// in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +// CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +// SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +-------------------------------------------------------------------------------- + +/* + * This utility helps tracing the entering and exiting from tasks. It maintains a circular buffer + * of tasks in the order they execute, and their execution time. + * In order to enable it, set configUSE_TRACE_FACILITY_2 to 1 in FreeRTOSConfig.h. + * You will also need to download the FreeRTOS_trace patch that contains + * porttrace.c and the complete version of porttrace.h + */ + +#ifndef PORTTRACE_H +#define PORTTRACE_H + +#if configUSE_TRACE_FACILITY_2 + #error "You need to download the FreeRTOS_trace patch that overwrites this file" +#endif + +#define porttracePrint(nelements) +#define porttraceStamp(stamp, count_incr) + +#endif /* PORTTRACE_H */ diff --git a/components/freertos/include/freertos/projdefs.h b/components/freertos/include/freertos/projdefs.h new file mode 100644 index 0000000000..1bd39c58d8 --- /dev/null +++ b/components/freertos/include/freertos/projdefs.h @@ -0,0 +1,109 @@ +/* + FreeRTOS V8.2.0 - Copyright (C) 2015 Real Time Engineers Ltd. + All rights reserved + + VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION. + + This file is part of the FreeRTOS distribution. + + FreeRTOS is free software; you can redistribute it and/or modify it under + the terms of the GNU General Public License (version 2) as published by the + Free Software Foundation >>!AND MODIFIED BY!<< the FreeRTOS exception. + + *************************************************************************** + >>! NOTE: The modification to the GPL is included to allow you to !<< + >>! distribute a combined work that includes FreeRTOS without being !<< + >>! obliged to provide the source code for proprietary components !<< + >>! outside of the FreeRTOS kernel. !<< + *************************************************************************** + + FreeRTOS is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + FOR A PARTICULAR PURPOSE. Full license text is available on the following + link: http://www.freertos.org/a00114.html + + *************************************************************************** + * * + * FreeRTOS provides completely free yet professionally developed, * + * robust, strictly quality controlled, supported, and cross * + * platform software that is more than just the market leader, it * + * is the industry's de facto standard. * + * * + * Help yourself get started quickly while simultaneously helping * + * to support the FreeRTOS project by purchasing a FreeRTOS * + * tutorial book, reference manual, or both: * + * http://www.FreeRTOS.org/Documentation * + * * + *************************************************************************** + + http://www.FreeRTOS.org/FAQHelp.html - Having a problem? Start by reading + the FAQ page "My application does not run, what could be wrong?". Have you + defined configASSERT()? + + http://www.FreeRTOS.org/support - In return for receiving this top quality + embedded software for free we request you assist our global community by + participating in the support forum. + + http://www.FreeRTOS.org/training - Investing in training allows your team to + be as productive as possible as early as possible. Now you can receive + FreeRTOS training directly from Richard Barry, CEO of Real Time Engineers + Ltd, and the world's leading authority on the world's leading RTOS. + + http://www.FreeRTOS.org/plus - A selection of FreeRTOS ecosystem products, + including FreeRTOS+Trace - an indispensable productivity tool, a DOS + compatible FAT file system, and our tiny thread aware UDP/IP stack. + + http://www.FreeRTOS.org/labs - Where new FreeRTOS products go to incubate. + Come and try FreeRTOS+TCP, our new open source TCP/IP stack for FreeRTOS. + + http://www.OpenRTOS.com - Real Time Engineers ltd. license FreeRTOS to High + Integrity Systems ltd. to sell under the OpenRTOS brand. Low cost OpenRTOS + licenses offer ticketed support, indemnification and commercial middleware. + + http://www.SafeRTOS.com - High Integrity Systems also provide a safety + engineered and independently SIL3 certified version for use in safety and + mission critical applications that require provable dependability. + + 1 tab == 4 spaces! +*/ + +#ifndef PROJDEFS_H +#define PROJDEFS_H + +/* + * Defines the prototype to which task functions must conform. Defined in this + * file to ensure the type is known before portable.h is included. + */ +typedef void (*TaskFunction_t)( void * ); + +/* Converts a time in milliseconds to a time in ticks. */ +#define pdMS_TO_TICKS( xTimeInMs ) ( ( ( TickType_t ) ( xTimeInMs ) * configTICK_RATE_HZ ) / ( TickType_t ) 1000 ) + +#define pdFALSE ( ( BaseType_t ) 0 ) +#define pdTRUE ( ( BaseType_t ) 1 ) + +#define pdPASS ( pdTRUE ) +#define pdFAIL ( pdFALSE ) +#define errQUEUE_EMPTY ( ( BaseType_t ) 0 ) +#define errQUEUE_FULL ( ( BaseType_t ) 0 ) + +/* Error definitions. */ +#define errCOULD_NOT_ALLOCATE_REQUIRED_MEMORY ( -1 ) +#define errQUEUE_BLOCKED ( -4 ) +#define errQUEUE_YIELD ( -5 ) + +/* Macros used for basic data corruption checks. */ +#ifndef configUSE_LIST_DATA_INTEGRITY_CHECK_BYTES + #define configUSE_LIST_DATA_INTEGRITY_CHECK_BYTES 0 +#endif + +#if( configUSE_16_BIT_TICKS == 1 ) + #define pdINTEGRITY_CHECK_VALUE 0x5a5a +#else + #define pdINTEGRITY_CHECK_VALUE 0x5a5a5a5aUL +#endif + +#endif /* PROJDEFS_H */ + + + diff --git a/components/freertos/include/freertos/queue.h b/components/freertos/include/freertos/queue.h new file mode 100644 index 0000000000..2095c59b0c --- /dev/null +++ b/components/freertos/include/freertos/queue.h @@ -0,0 +1,1693 @@ +/* + FreeRTOS V8.2.0 - Copyright (C) 2015 Real Time Engineers Ltd. + All rights reserved + + VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION. + + This file is part of the FreeRTOS distribution. + + FreeRTOS is free software; you can redistribute it and/or modify it under + the terms of the GNU General Public License (version 2) as published by the + Free Software Foundation >>!AND MODIFIED BY!<< the FreeRTOS exception. + + *************************************************************************** + >>! NOTE: The modification to the GPL is included to allow you to !<< + >>! distribute a combined work that includes FreeRTOS without being !<< + >>! obliged to provide the source code for proprietary components !<< + >>! outside of the FreeRTOS kernel. !<< + *************************************************************************** + + FreeRTOS is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + FOR A PARTICULAR PURPOSE. Full license text is available on the following + link: http://www.freertos.org/a00114.html + + *************************************************************************** + * * + * FreeRTOS provides completely free yet professionally developed, * + * robust, strictly quality controlled, supported, and cross * + * platform software that is more than just the market leader, it * + * is the industry's de facto standard. * + * * + * Help yourself get started quickly while simultaneously helping * + * to support the FreeRTOS project by purchasing a FreeRTOS * + * tutorial book, reference manual, or both: * + * http://www.FreeRTOS.org/Documentation * + * * + *************************************************************************** + + http://www.FreeRTOS.org/FAQHelp.html - Having a problem? Start by reading + the FAQ page "My application does not run, what could be wrong?". Have you + defined configASSERT()? + + http://www.FreeRTOS.org/support - In return for receiving this top quality + embedded software for free we request you assist our global community by + participating in the support forum. + + http://www.FreeRTOS.org/training - Investing in training allows your team to + be as productive as possible as early as possible. Now you can receive + FreeRTOS training directly from Richard Barry, CEO of Real Time Engineers + Ltd, and the world's leading authority on the world's leading RTOS. + + http://www.FreeRTOS.org/plus - A selection of FreeRTOS ecosystem products, + including FreeRTOS+Trace - an indispensable productivity tool, a DOS + compatible FAT file system, and our tiny thread aware UDP/IP stack. + + http://www.FreeRTOS.org/labs - Where new FreeRTOS products go to incubate. + Come and try FreeRTOS+TCP, our new open source TCP/IP stack for FreeRTOS. + + http://www.OpenRTOS.com - Real Time Engineers ltd. license FreeRTOS to High + Integrity Systems ltd. to sell under the OpenRTOS brand. Low cost OpenRTOS + licenses offer ticketed support, indemnification and commercial middleware. + + http://www.SafeRTOS.com - High Integrity Systems also provide a safety + engineered and independently SIL3 certified version for use in safety and + mission critical applications that require provable dependability. + + 1 tab == 4 spaces! +*/ + + +#ifndef QUEUE_H +#define QUEUE_H + +#ifndef INC_FREERTOS_H + #error "include FreeRTOS.h" must appear in source files before "include queue.h" +#endif + +#ifdef __cplusplus +extern "C" { +#endif + + +/** + * Type by which queues are referenced. For example, a call to xQueueCreate() + * returns an QueueHandle_t variable that can then be used as a parameter to + * xQueueSend(), xQueueReceive(), etc. + */ +typedef void * QueueHandle_t; + +/** + * Type by which queue sets are referenced. For example, a call to + * xQueueCreateSet() returns an xQueueSet variable that can then be used as a + * parameter to xQueueSelectFromSet(), xQueueAddToSet(), etc. + */ +typedef void * QueueSetHandle_t; + +/** + * Queue sets can contain both queues and semaphores, so the + * QueueSetMemberHandle_t is defined as a type to be used where a parameter or + * return value can be either an QueueHandle_t or an SemaphoreHandle_t. + */ +typedef void * QueueSetMemberHandle_t; + +/* For internal use only. */ +#define queueSEND_TO_BACK ( ( BaseType_t ) 0 ) +#define queueSEND_TO_FRONT ( ( BaseType_t ) 1 ) +#define queueOVERWRITE ( ( BaseType_t ) 2 ) + +/* For internal use only. These definitions *must* match those in queue.c. */ +#define queueQUEUE_TYPE_BASE ( ( uint8_t ) 0U ) +#define queueQUEUE_TYPE_SET ( ( uint8_t ) 0U ) +#define queueQUEUE_TYPE_MUTEX ( ( uint8_t ) 1U ) +#define queueQUEUE_TYPE_COUNTING_SEMAPHORE ( ( uint8_t ) 2U ) +#define queueQUEUE_TYPE_BINARY_SEMAPHORE ( ( uint8_t ) 3U ) +#define queueQUEUE_TYPE_RECURSIVE_MUTEX ( ( uint8_t ) 4U ) + +/** + * queue. h + *
+ QueueHandle_t xQueueCreate(
+							  UBaseType_t uxQueueLength,
+							  UBaseType_t uxItemSize
+						  );
+ * 
+ * + * Creates a new queue instance. This allocates the storage required by the + * new queue and returns a handle for the queue. + * + * @param uxQueueLength The maximum number of items that the queue can contain. + * + * @param uxItemSize The number of bytes each item in the queue will require. + * Items are queued by copy, not by reference, so this is the number of bytes + * that will be copied for each posted item. Each item on the queue must be + * the same size. + * + * @return If the queue is successfully create then a handle to the newly + * created queue is returned. If the queue cannot be created then 0 is + * returned. + * + * Example usage: +
+ struct AMessage
+ {
+	char ucMessageID;
+	char ucData[ 20 ];
+ };
+
+ void vATask( void *pvParameters )
+ {
+ QueueHandle_t xQueue1, xQueue2;
+
+	// Create a queue capable of containing 10 uint32_t values.
+	xQueue1 = xQueueCreate( 10, sizeof( uint32_t ) );
+	if( xQueue1 == 0 )
+	{
+		// Queue was not created and must not be used.
+	}
+
+	// Create a queue capable of containing 10 pointers to AMessage structures.
+	// These should be passed by pointer as they contain a lot of data.
+	xQueue2 = xQueueCreate( 10, sizeof( struct AMessage * ) );
+	if( xQueue2 == 0 )
+	{
+		// Queue was not created and must not be used.
+	}
+
+	// ... Rest of task code.
+ }
+ 
+ * \defgroup xQueueCreate xQueueCreate + * \ingroup QueueManagement + */ +#define xQueueCreate( uxQueueLength, uxItemSize ) xQueueGenericCreate( uxQueueLength, uxItemSize, queueQUEUE_TYPE_BASE ) + +/** + * queue. h + *
+ BaseType_t xQueueSendToToFront(
+								   QueueHandle_t	xQueue,
+								   const void		*pvItemToQueue,
+								   TickType_t		xTicksToWait
+							   );
+ * 
+ * + * This is a macro that calls xQueueGenericSend(). + * + * Post an item to the front of a queue. The item is queued by copy, not by + * reference. This function must not be called from an interrupt service + * routine. See xQueueSendFromISR () for an alternative which may be used + * in an ISR. + * + * @param xQueue The handle to the queue on which the item is to be posted. + * + * @param pvItemToQueue A pointer to the item that is to be placed on the + * queue. The size of the items the queue will hold was defined when the + * queue was created, so this many bytes will be copied from pvItemToQueue + * into the queue storage area. + * + * @param xTicksToWait The maximum amount of time the task should block + * waiting for space to become available on the queue, should it already + * be full. The call will return immediately if this is set to 0 and the + * queue is full. The time is defined in tick periods so the constant + * portTICK_PERIOD_MS should be used to convert to real time if this is required. + * + * @return pdTRUE if the item was successfully posted, otherwise errQUEUE_FULL. + * + * Example usage: +
+ struct AMessage
+ {
+	char ucMessageID;
+	char ucData[ 20 ];
+ } xMessage;
+
+ uint32_t ulVar = 10UL;
+
+ void vATask( void *pvParameters )
+ {
+ QueueHandle_t xQueue1, xQueue2;
+ struct AMessage *pxMessage;
+
+	// Create a queue capable of containing 10 uint32_t values.
+	xQueue1 = xQueueCreate( 10, sizeof( uint32_t ) );
+
+	// Create a queue capable of containing 10 pointers to AMessage structures.
+	// These should be passed by pointer as they contain a lot of data.
+	xQueue2 = xQueueCreate( 10, sizeof( struct AMessage * ) );
+
+	// ...
+
+	if( xQueue1 != 0 )
+	{
+		// Send an uint32_t.  Wait for 10 ticks for space to become
+		// available if necessary.
+		if( xQueueSendToFront( xQueue1, ( void * ) &ulVar, ( TickType_t ) 10 ) != pdPASS )
+		{
+			// Failed to post the message, even after 10 ticks.
+		}
+	}
+
+	if( xQueue2 != 0 )
+	{
+		// Send a pointer to a struct AMessage object.  Don't block if the
+		// queue is already full.
+		pxMessage = & xMessage;
+		xQueueSendToFront( xQueue2, ( void * ) &pxMessage, ( TickType_t ) 0 );
+	}
+
+	// ... Rest of task code.
+ }
+ 
+ * \defgroup xQueueSend xQueueSend + * \ingroup QueueManagement + */ +#define xQueueSendToFront( xQueue, pvItemToQueue, xTicksToWait ) xQueueGenericSend( ( xQueue ), ( pvItemToQueue ), ( xTicksToWait ), queueSEND_TO_FRONT ) + +/** + * queue. h + *
+ BaseType_t xQueueSendToBack(
+								   QueueHandle_t	xQueue,
+								   const void		*pvItemToQueue,
+								   TickType_t		xTicksToWait
+							   );
+ * 
+ * + * This is a macro that calls xQueueGenericSend(). + * + * Post an item to the back of a queue. The item is queued by copy, not by + * reference. This function must not be called from an interrupt service + * routine. See xQueueSendFromISR () for an alternative which may be used + * in an ISR. + * + * @param xQueue The handle to the queue on which the item is to be posted. + * + * @param pvItemToQueue A pointer to the item that is to be placed on the + * queue. The size of the items the queue will hold was defined when the + * queue was created, so this many bytes will be copied from pvItemToQueue + * into the queue storage area. + * + * @param xTicksToWait The maximum amount of time the task should block + * waiting for space to become available on the queue, should it already + * be full. The call will return immediately if this is set to 0 and the queue + * is full. The time is defined in tick periods so the constant + * portTICK_PERIOD_MS should be used to convert to real time if this is required. + * + * @return pdTRUE if the item was successfully posted, otherwise errQUEUE_FULL. + * + * Example usage: +
+ struct AMessage
+ {
+	char ucMessageID;
+	char ucData[ 20 ];
+ } xMessage;
+
+ uint32_t ulVar = 10UL;
+
+ void vATask( void *pvParameters )
+ {
+ QueueHandle_t xQueue1, xQueue2;
+ struct AMessage *pxMessage;
+
+	// Create a queue capable of containing 10 uint32_t values.
+	xQueue1 = xQueueCreate( 10, sizeof( uint32_t ) );
+
+	// Create a queue capable of containing 10 pointers to AMessage structures.
+	// These should be passed by pointer as they contain a lot of data.
+	xQueue2 = xQueueCreate( 10, sizeof( struct AMessage * ) );
+
+	// ...
+
+	if( xQueue1 != 0 )
+	{
+		// Send an uint32_t.  Wait for 10 ticks for space to become
+		// available if necessary.
+		if( xQueueSendToBack( xQueue1, ( void * ) &ulVar, ( TickType_t ) 10 ) != pdPASS )
+		{
+			// Failed to post the message, even after 10 ticks.
+		}
+	}
+
+	if( xQueue2 != 0 )
+	{
+		// Send a pointer to a struct AMessage object.  Don't block if the
+		// queue is already full.
+		pxMessage = & xMessage;
+		xQueueSendToBack( xQueue2, ( void * ) &pxMessage, ( TickType_t ) 0 );
+	}
+
+	// ... Rest of task code.
+ }
+ 
+ * \defgroup xQueueSend xQueueSend + * \ingroup QueueManagement + */ +#define xQueueSendToBack( xQueue, pvItemToQueue, xTicksToWait ) xQueueGenericSend( ( xQueue ), ( pvItemToQueue ), ( xTicksToWait ), queueSEND_TO_BACK ) + +/** + * queue. h + *
+ BaseType_t xQueueSend(
+							  QueueHandle_t xQueue,
+							  const void * pvItemToQueue,
+							  TickType_t xTicksToWait
+						 );
+ * 
+ * + * This is a macro that calls xQueueGenericSend(). It is included for + * backward compatibility with versions of FreeRTOS.org that did not + * include the xQueueSendToFront() and xQueueSendToBack() macros. It is + * equivalent to xQueueSendToBack(). + * + * Post an item on a queue. The item is queued by copy, not by reference. + * This function must not be called from an interrupt service routine. + * See xQueueSendFromISR () for an alternative which may be used in an ISR. + * + * @param xQueue The handle to the queue on which the item is to be posted. + * + * @param pvItemToQueue A pointer to the item that is to be placed on the + * queue. The size of the items the queue will hold was defined when the + * queue was created, so this many bytes will be copied from pvItemToQueue + * into the queue storage area. + * + * @param xTicksToWait The maximum amount of time the task should block + * waiting for space to become available on the queue, should it already + * be full. The call will return immediately if this is set to 0 and the + * queue is full. The time is defined in tick periods so the constant + * portTICK_PERIOD_MS should be used to convert to real time if this is required. + * + * @return pdTRUE if the item was successfully posted, otherwise errQUEUE_FULL. + * + * Example usage: +
+ struct AMessage
+ {
+	char ucMessageID;
+	char ucData[ 20 ];
+ } xMessage;
+
+ uint32_t ulVar = 10UL;
+
+ void vATask( void *pvParameters )
+ {
+ QueueHandle_t xQueue1, xQueue2;
+ struct AMessage *pxMessage;
+
+	// Create a queue capable of containing 10 uint32_t values.
+	xQueue1 = xQueueCreate( 10, sizeof( uint32_t ) );
+
+	// Create a queue capable of containing 10 pointers to AMessage structures.
+	// These should be passed by pointer as they contain a lot of data.
+	xQueue2 = xQueueCreate( 10, sizeof( struct AMessage * ) );
+
+	// ...
+
+	if( xQueue1 != 0 )
+	{
+		// Send an uint32_t.  Wait for 10 ticks for space to become
+		// available if necessary.
+		if( xQueueSend( xQueue1, ( void * ) &ulVar, ( TickType_t ) 10 ) != pdPASS )
+		{
+			// Failed to post the message, even after 10 ticks.
+		}
+	}
+
+	if( xQueue2 != 0 )
+	{
+		// Send a pointer to a struct AMessage object.  Don't block if the
+		// queue is already full.
+		pxMessage = & xMessage;
+		xQueueSend( xQueue2, ( void * ) &pxMessage, ( TickType_t ) 0 );
+	}
+
+	// ... Rest of task code.
+ }
+ 
+ * \defgroup xQueueSend xQueueSend + * \ingroup QueueManagement + */ +#define xQueueSend( xQueue, pvItemToQueue, xTicksToWait ) xQueueGenericSend( ( xQueue ), ( pvItemToQueue ), ( xTicksToWait ), queueSEND_TO_BACK ) + +/** + * queue. h + *
+ BaseType_t xQueueOverwrite(
+							  QueueHandle_t xQueue,
+							  const void * pvItemToQueue
+						 );
+ * 
+ * + * Only for use with queues that have a length of one - so the queue is either + * empty or full. + * + * Post an item on a queue. If the queue is already full then overwrite the + * value held in the queue. The item is queued by copy, not by reference. + * + * This function must not be called from an interrupt service routine. + * See xQueueOverwriteFromISR () for an alternative which may be used in an ISR. + * + * @param xQueue The handle of the queue to which the data is being sent. + * + * @param pvItemToQueue A pointer to the item that is to be placed on the + * queue. The size of the items the queue will hold was defined when the + * queue was created, so this many bytes will be copied from pvItemToQueue + * into the queue storage area. + * + * @return xQueueOverwrite() is a macro that calls xQueueGenericSend(), and + * therefore has the same return values as xQueueSendToFront(). However, pdPASS + * is the only value that can be returned because xQueueOverwrite() will write + * to the queue even when the queue is already full. + * + * Example usage: +
+
+ void vFunction( void *pvParameters )
+ {
+ QueueHandle_t xQueue;
+ uint32_t ulVarToSend, ulValReceived;
+
+	// Create a queue to hold one uint32_t value.  It is strongly
+	// recommended *not* to use xQueueOverwrite() on queues that can
+	// contain more than one value, and doing so will trigger an assertion
+	// if configASSERT() is defined.
+	xQueue = xQueueCreate( 1, sizeof( uint32_t ) );
+
+	// Write the value 10 to the queue using xQueueOverwrite().
+	ulVarToSend = 10;
+	xQueueOverwrite( xQueue, &ulVarToSend );
+
+	// Peeking the queue should now return 10, but leave the value 10 in
+	// the queue.  A block time of zero is used as it is known that the
+	// queue holds a value.
+	ulValReceived = 0;
+	xQueuePeek( xQueue, &ulValReceived, 0 );
+
+	if( ulValReceived != 10 )
+	{
+		// Error unless the item was removed by a different task.
+	}
+
+	// The queue is still full.  Use xQueueOverwrite() to overwrite the
+	// value held in the queue with 100.
+	ulVarToSend = 100;
+	xQueueOverwrite( xQueue, &ulVarToSend );
+
+	// This time read from the queue, leaving the queue empty once more.
+	// A block time of 0 is used again.
+	xQueueReceive( xQueue, &ulValReceived, 0 );
+
+	// The value read should be the last value written, even though the
+	// queue was already full when the value was written.
+	if( ulValReceived != 100 )
+	{
+		// Error!
+	}
+
+	// ...
+}
+ 
+ * \defgroup xQueueOverwrite xQueueOverwrite + * \ingroup QueueManagement + */ +#define xQueueOverwrite( xQueue, pvItemToQueue ) xQueueGenericSend( ( xQueue ), ( pvItemToQueue ), 0, queueOVERWRITE ) + + +/** + * queue. h + *
+ BaseType_t xQueueGenericSend(
+									QueueHandle_t xQueue,
+									const void * pvItemToQueue,
+									TickType_t xTicksToWait
+									BaseType_t xCopyPosition
+								);
+ * 
+ * + * It is preferred that the macros xQueueSend(), xQueueSendToFront() and + * xQueueSendToBack() are used in place of calling this function directly. + * + * Post an item on a queue. The item is queued by copy, not by reference. + * This function must not be called from an interrupt service routine. + * See xQueueSendFromISR () for an alternative which may be used in an ISR. + * + * @param xQueue The handle to the queue on which the item is to be posted. + * + * @param pvItemToQueue A pointer to the item that is to be placed on the + * queue. The size of the items the queue will hold was defined when the + * queue was created, so this many bytes will be copied from pvItemToQueue + * into the queue storage area. + * + * @param xTicksToWait The maximum amount of time the task should block + * waiting for space to become available on the queue, should it already + * be full. The call will return immediately if this is set to 0 and the + * queue is full. The time is defined in tick periods so the constant + * portTICK_PERIOD_MS should be used to convert to real time if this is required. + * + * @param xCopyPosition Can take the value queueSEND_TO_BACK to place the + * item at the back of the queue, or queueSEND_TO_FRONT to place the item + * at the front of the queue (for high priority messages). + * + * @return pdTRUE if the item was successfully posted, otherwise errQUEUE_FULL. + * + * Example usage: +
+ struct AMessage
+ {
+	char ucMessageID;
+	char ucData[ 20 ];
+ } xMessage;
+
+ uint32_t ulVar = 10UL;
+
+ void vATask( void *pvParameters )
+ {
+ QueueHandle_t xQueue1, xQueue2;
+ struct AMessage *pxMessage;
+
+	// Create a queue capable of containing 10 uint32_t values.
+	xQueue1 = xQueueCreate( 10, sizeof( uint32_t ) );
+
+	// Create a queue capable of containing 10 pointers to AMessage structures.
+	// These should be passed by pointer as they contain a lot of data.
+	xQueue2 = xQueueCreate( 10, sizeof( struct AMessage * ) );
+
+	// ...
+
+	if( xQueue1 != 0 )
+	{
+		// Send an uint32_t.  Wait for 10 ticks for space to become
+		// available if necessary.
+		if( xQueueGenericSend( xQueue1, ( void * ) &ulVar, ( TickType_t ) 10, queueSEND_TO_BACK ) != pdPASS )
+		{
+			// Failed to post the message, even after 10 ticks.
+		}
+	}
+
+	if( xQueue2 != 0 )
+	{
+		// Send a pointer to a struct AMessage object.  Don't block if the
+		// queue is already full.
+		pxMessage = & xMessage;
+		xQueueGenericSend( xQueue2, ( void * ) &pxMessage, ( TickType_t ) 0, queueSEND_TO_BACK );
+	}
+
+	// ... Rest of task code.
+ }
+ 
+ * \defgroup xQueueSend xQueueSend + * \ingroup QueueManagement + */ +BaseType_t xQueueGenericSend( QueueHandle_t xQueue, const void * const pvItemToQueue, TickType_t xTicksToWait, const BaseType_t xCopyPosition ) PRIVILEGED_FUNCTION; + +/** + * queue. h + *
+ BaseType_t xQueuePeek(
+							 QueueHandle_t xQueue,
+							 void *pvBuffer,
+							 TickType_t xTicksToWait
+						 );
+ * + * This is a macro that calls the xQueueGenericReceive() function. + * + * Receive an item from a queue without removing the item from the queue. + * The item is received by copy so a buffer of adequate size must be + * provided. The number of bytes copied into the buffer was defined when + * the queue was created. + * + * Successfully received items remain on the queue so will be returned again + * by the next call, or a call to xQueueReceive(). + * + * This macro must not be used in an interrupt service routine. See + * xQueuePeekFromISR() for an alternative that can be called from an interrupt + * service routine. + * + * @param xQueue The handle to the queue from which the item is to be + * received. + * + * @param pvBuffer Pointer to the buffer into which the received item will + * be copied. + * + * @param xTicksToWait The maximum amount of time the task should block + * waiting for an item to receive should the queue be empty at the time + * of the call. The time is defined in tick periods so the constant + * portTICK_PERIOD_MS should be used to convert to real time if this is required. + * xQueuePeek() will return immediately if xTicksToWait is 0 and the queue + * is empty. + * + * @return pdTRUE if an item was successfully received from the queue, + * otherwise pdFALSE. + * + * Example usage: +
+ struct AMessage
+ {
+	char ucMessageID;
+	char ucData[ 20 ];
+ } xMessage;
+
+ QueueHandle_t xQueue;
+
+ // Task to create a queue and post a value.
+ void vATask( void *pvParameters )
+ {
+ struct AMessage *pxMessage;
+
+	// Create a queue capable of containing 10 pointers to AMessage structures.
+	// These should be passed by pointer as they contain a lot of data.
+	xQueue = xQueueCreate( 10, sizeof( struct AMessage * ) );
+	if( xQueue == 0 )
+	{
+		// Failed to create the queue.
+	}
+
+	// ...
+
+	// Send a pointer to a struct AMessage object.  Don't block if the
+	// queue is already full.
+	pxMessage = & xMessage;
+	xQueueSend( xQueue, ( void * ) &pxMessage, ( TickType_t ) 0 );
+
+	// ... Rest of task code.
+ }
+
+ // Task to peek the data from the queue.
+ void vADifferentTask( void *pvParameters )
+ {
+ struct AMessage *pxRxedMessage;
+
+	if( xQueue != 0 )
+	{
+		// Peek a message on the created queue.  Block for 10 ticks if a
+		// message is not immediately available.
+		if( xQueuePeek( xQueue, &( pxRxedMessage ), ( TickType_t ) 10 ) )
+		{
+			// pcRxedMessage now points to the struct AMessage variable posted
+			// by vATask, but the item still remains on the queue.
+		}
+	}
+
+	// ... Rest of task code.
+ }
+ 
+ * \defgroup xQueueReceive xQueueReceive + * \ingroup QueueManagement + */ +#define xQueuePeek( xQueue, pvBuffer, xTicksToWait ) xQueueGenericReceive( ( xQueue ), ( pvBuffer ), ( xTicksToWait ), pdTRUE ) + +/** + * queue. h + *
+ BaseType_t xQueuePeekFromISR(
+									QueueHandle_t xQueue,
+									void *pvBuffer,
+								);
+ * + * A version of xQueuePeek() that can be called from an interrupt service + * routine (ISR). + * + * Receive an item from a queue without removing the item from the queue. + * The item is received by copy so a buffer of adequate size must be + * provided. The number of bytes copied into the buffer was defined when + * the queue was created. + * + * Successfully received items remain on the queue so will be returned again + * by the next call, or a call to xQueueReceive(). + * + * @param xQueue The handle to the queue from which the item is to be + * received. + * + * @param pvBuffer Pointer to the buffer into which the received item will + * be copied. + * + * @return pdTRUE if an item was successfully received from the queue, + * otherwise pdFALSE. + * + * \defgroup xQueuePeekFromISR xQueuePeekFromISR + * \ingroup QueueManagement + */ +BaseType_t xQueuePeekFromISR( QueueHandle_t xQueue, void * const pvBuffer ) PRIVILEGED_FUNCTION; + +/** + * queue. h + *
+ BaseType_t xQueueReceive(
+								 QueueHandle_t xQueue,
+								 void *pvBuffer,
+								 TickType_t xTicksToWait
+							);
+ * + * This is a macro that calls the xQueueGenericReceive() function. + * + * Receive an item from a queue. The item is received by copy so a buffer of + * adequate size must be provided. The number of bytes copied into the buffer + * was defined when the queue was created. + * + * Successfully received items are removed from the queue. + * + * This function must not be used in an interrupt service routine. See + * xQueueReceiveFromISR for an alternative that can. + * + * @param xQueue The handle to the queue from which the item is to be + * received. + * + * @param pvBuffer Pointer to the buffer into which the received item will + * be copied. + * + * @param xTicksToWait The maximum amount of time the task should block + * waiting for an item to receive should the queue be empty at the time + * of the call. xQueueReceive() will return immediately if xTicksToWait + * is zero and the queue is empty. The time is defined in tick periods so the + * constant portTICK_PERIOD_MS should be used to convert to real time if this is + * required. + * + * @return pdTRUE if an item was successfully received from the queue, + * otherwise pdFALSE. + * + * Example usage: +
+ struct AMessage
+ {
+	char ucMessageID;
+	char ucData[ 20 ];
+ } xMessage;
+
+ QueueHandle_t xQueue;
+
+ // Task to create a queue and post a value.
+ void vATask( void *pvParameters )
+ {
+ struct AMessage *pxMessage;
+
+	// Create a queue capable of containing 10 pointers to AMessage structures.
+	// These should be passed by pointer as they contain a lot of data.
+	xQueue = xQueueCreate( 10, sizeof( struct AMessage * ) );
+	if( xQueue == 0 )
+	{
+		// Failed to create the queue.
+	}
+
+	// ...
+
+	// Send a pointer to a struct AMessage object.  Don't block if the
+	// queue is already full.
+	pxMessage = & xMessage;
+	xQueueSend( xQueue, ( void * ) &pxMessage, ( TickType_t ) 0 );
+
+	// ... Rest of task code.
+ }
+
+ // Task to receive from the queue.
+ void vADifferentTask( void *pvParameters )
+ {
+ struct AMessage *pxRxedMessage;
+
+	if( xQueue != 0 )
+	{
+		// Receive a message on the created queue.  Block for 10 ticks if a
+		// message is not immediately available.
+		if( xQueueReceive( xQueue, &( pxRxedMessage ), ( TickType_t ) 10 ) )
+		{
+			// pcRxedMessage now points to the struct AMessage variable posted
+			// by vATask.
+		}
+	}
+
+	// ... Rest of task code.
+ }
+ 
+ * \defgroup xQueueReceive xQueueReceive + * \ingroup QueueManagement + */ +#define xQueueReceive( xQueue, pvBuffer, xTicksToWait ) xQueueGenericReceive( ( xQueue ), ( pvBuffer ), ( xTicksToWait ), pdFALSE ) + + +/** + * queue. h + *
+ BaseType_t xQueueGenericReceive(
+									   QueueHandle_t	xQueue,
+									   void	*pvBuffer,
+									   TickType_t	xTicksToWait
+									   BaseType_t	xJustPeek
+									);
+ * + * It is preferred that the macro xQueueReceive() be used rather than calling + * this function directly. + * + * Receive an item from a queue. The item is received by copy so a buffer of + * adequate size must be provided. The number of bytes copied into the buffer + * was defined when the queue was created. + * + * This function must not be used in an interrupt service routine. See + * xQueueReceiveFromISR for an alternative that can. + * + * @param xQueue The handle to the queue from which the item is to be + * received. + * + * @param pvBuffer Pointer to the buffer into which the received item will + * be copied. + * + * @param xTicksToWait The maximum amount of time the task should block + * waiting for an item to receive should the queue be empty at the time + * of the call. The time is defined in tick periods so the constant + * portTICK_PERIOD_MS should be used to convert to real time if this is required. + * xQueueGenericReceive() will return immediately if the queue is empty and + * xTicksToWait is 0. + * + * @param xJustPeek When set to true, the item received from the queue is not + * actually removed from the queue - meaning a subsequent call to + * xQueueReceive() will return the same item. When set to false, the item + * being received from the queue is also removed from the queue. + * + * @return pdTRUE if an item was successfully received from the queue, + * otherwise pdFALSE. + * + * Example usage: +
+ struct AMessage
+ {
+	char ucMessageID;
+	char ucData[ 20 ];
+ } xMessage;
+
+ QueueHandle_t xQueue;
+
+ // Task to create a queue and post a value.
+ void vATask( void *pvParameters )
+ {
+ struct AMessage *pxMessage;
+
+	// Create a queue capable of containing 10 pointers to AMessage structures.
+	// These should be passed by pointer as they contain a lot of data.
+	xQueue = xQueueCreate( 10, sizeof( struct AMessage * ) );
+	if( xQueue == 0 )
+	{
+		// Failed to create the queue.
+	}
+
+	// ...
+
+	// Send a pointer to a struct AMessage object.  Don't block if the
+	// queue is already full.
+	pxMessage = & xMessage;
+	xQueueSend( xQueue, ( void * ) &pxMessage, ( TickType_t ) 0 );
+
+	// ... Rest of task code.
+ }
+
+ // Task to receive from the queue.
+ void vADifferentTask( void *pvParameters )
+ {
+ struct AMessage *pxRxedMessage;
+
+	if( xQueue != 0 )
+	{
+		// Receive a message on the created queue.  Block for 10 ticks if a
+		// message is not immediately available.
+		if( xQueueGenericReceive( xQueue, &( pxRxedMessage ), ( TickType_t ) 10 ) )
+		{
+			// pcRxedMessage now points to the struct AMessage variable posted
+			// by vATask.
+		}
+	}
+
+	// ... Rest of task code.
+ }
+ 
+ * \defgroup xQueueReceive xQueueReceive + * \ingroup QueueManagement + */ +BaseType_t xQueueGenericReceive( QueueHandle_t xQueue, void * const pvBuffer, TickType_t xTicksToWait, const BaseType_t xJustPeek ) PRIVILEGED_FUNCTION; + +/** + * queue. h + *
UBaseType_t uxQueueMessagesWaiting( const QueueHandle_t xQueue );
+ * + * Return the number of messages stored in a queue. + * + * @param xQueue A handle to the queue being queried. + * + * @return The number of messages available in the queue. + * + * \defgroup uxQueueMessagesWaiting uxQueueMessagesWaiting + * \ingroup QueueManagement + */ +UBaseType_t uxQueueMessagesWaiting( const QueueHandle_t xQueue ) PRIVILEGED_FUNCTION; + +/** + * queue. h + *
UBaseType_t uxQueueSpacesAvailable( const QueueHandle_t xQueue );
+ * + * Return the number of free spaces available in a queue. This is equal to the + * number of items that can be sent to the queue before the queue becomes full + * if no items are removed. + * + * @param xQueue A handle to the queue being queried. + * + * @return The number of spaces available in the queue. + * + * \defgroup uxQueueMessagesWaiting uxQueueMessagesWaiting + * \ingroup QueueManagement + */ +UBaseType_t uxQueueSpacesAvailable( const QueueHandle_t xQueue ) PRIVILEGED_FUNCTION; + +/** + * queue. h + *
void vQueueDelete( QueueHandle_t xQueue );
+ * + * Delete a queue - freeing all the memory allocated for storing of items + * placed on the queue. + * + * @param xQueue A handle to the queue to be deleted. + * + * \defgroup vQueueDelete vQueueDelete + * \ingroup QueueManagement + */ +void vQueueDelete( QueueHandle_t xQueue ) PRIVILEGED_FUNCTION; + +/** + * queue. h + *
+ BaseType_t xQueueSendToFrontFromISR(
+										 QueueHandle_t xQueue,
+										 const void *pvItemToQueue,
+										 BaseType_t *pxHigherPriorityTaskWoken
+									  );
+ 
+ * + * This is a macro that calls xQueueGenericSendFromISR(). + * + * Post an item to the front of a queue. It is safe to use this macro from + * within an interrupt service routine. + * + * Items are queued by copy not reference so it is preferable to only + * queue small items, especially when called from an ISR. In most cases + * it would be preferable to store a pointer to the item being queued. + * + * @param xQueue The handle to the queue on which the item is to be posted. + * + * @param pvItemToQueue A pointer to the item that is to be placed on the + * queue. The size of the items the queue will hold was defined when the + * queue was created, so this many bytes will be copied from pvItemToQueue + * into the queue storage area. + * + * @param pxHigherPriorityTaskWoken xQueueSendToFrontFromISR() will set + * *pxHigherPriorityTaskWoken to pdTRUE if sending to the queue caused a task + * to unblock, and the unblocked task has a priority higher than the currently + * running task. If xQueueSendToFromFromISR() sets this value to pdTRUE then + * a context switch should be requested before the interrupt is exited. + * + * @return pdTRUE if the data was successfully sent to the queue, otherwise + * errQUEUE_FULL. + * + * Example usage for buffered IO (where the ISR can obtain more than one value + * per call): +
+ void vBufferISR( void )
+ {
+ char cIn;
+ BaseType_t xHigherPrioritTaskWoken;
+
+	// We have not woken a task at the start of the ISR.
+	xHigherPriorityTaskWoken = pdFALSE;
+
+	// Loop until the buffer is empty.
+	do
+	{
+		// Obtain a byte from the buffer.
+		cIn = portINPUT_BYTE( RX_REGISTER_ADDRESS );
+
+		// Post the byte.
+		xQueueSendToFrontFromISR( xRxQueue, &cIn, &xHigherPriorityTaskWoken );
+
+	} while( portINPUT_BYTE( BUFFER_COUNT ) );
+
+	// Now the buffer is empty we can switch context if necessary.
+	if( xHigherPriorityTaskWoken )
+	{
+		taskYIELD ();
+	}
+ }
+ 
+ * + * \defgroup xQueueSendFromISR xQueueSendFromISR + * \ingroup QueueManagement + */ +#define xQueueSendToFrontFromISR( xQueue, pvItemToQueue, pxHigherPriorityTaskWoken ) xQueueGenericSendFromISR( ( xQueue ), ( pvItemToQueue ), ( pxHigherPriorityTaskWoken ), queueSEND_TO_FRONT ) + + +/** + * queue. h + *
+ BaseType_t xQueueSendToBackFromISR(
+										 QueueHandle_t xQueue,
+										 const void *pvItemToQueue,
+										 BaseType_t *pxHigherPriorityTaskWoken
+									  );
+ 
+ * + * This is a macro that calls xQueueGenericSendFromISR(). + * + * Post an item to the back of a queue. It is safe to use this macro from + * within an interrupt service routine. + * + * Items are queued by copy not reference so it is preferable to only + * queue small items, especially when called from an ISR. In most cases + * it would be preferable to store a pointer to the item being queued. + * + * @param xQueue The handle to the queue on which the item is to be posted. + * + * @param pvItemToQueue A pointer to the item that is to be placed on the + * queue. The size of the items the queue will hold was defined when the + * queue was created, so this many bytes will be copied from pvItemToQueue + * into the queue storage area. + * + * @param pxHigherPriorityTaskWoken xQueueSendToBackFromISR() will set + * *pxHigherPriorityTaskWoken to pdTRUE if sending to the queue caused a task + * to unblock, and the unblocked task has a priority higher than the currently + * running task. If xQueueSendToBackFromISR() sets this value to pdTRUE then + * a context switch should be requested before the interrupt is exited. + * + * @return pdTRUE if the data was successfully sent to the queue, otherwise + * errQUEUE_FULL. + * + * Example usage for buffered IO (where the ISR can obtain more than one value + * per call): +
+ void vBufferISR( void )
+ {
+ char cIn;
+ BaseType_t xHigherPriorityTaskWoken;
+
+	// We have not woken a task at the start of the ISR.
+	xHigherPriorityTaskWoken = pdFALSE;
+
+	// Loop until the buffer is empty.
+	do
+	{
+		// Obtain a byte from the buffer.
+		cIn = portINPUT_BYTE( RX_REGISTER_ADDRESS );
+
+		// Post the byte.
+		xQueueSendToBackFromISR( xRxQueue, &cIn, &xHigherPriorityTaskWoken );
+
+	} while( portINPUT_BYTE( BUFFER_COUNT ) );
+
+	// Now the buffer is empty we can switch context if necessary.
+	if( xHigherPriorityTaskWoken )
+	{
+		taskYIELD ();
+	}
+ }
+ 
+ * + * \defgroup xQueueSendFromISR xQueueSendFromISR + * \ingroup QueueManagement + */ +#define xQueueSendToBackFromISR( xQueue, pvItemToQueue, pxHigherPriorityTaskWoken ) xQueueGenericSendFromISR( ( xQueue ), ( pvItemToQueue ), ( pxHigherPriorityTaskWoken ), queueSEND_TO_BACK ) + +/** + * queue. h + *
+ BaseType_t xQueueOverwriteFromISR(
+							  QueueHandle_t xQueue,
+							  const void * pvItemToQueue,
+							  BaseType_t *pxHigherPriorityTaskWoken
+						 );
+ * 
+ * + * A version of xQueueOverwrite() that can be used in an interrupt service + * routine (ISR). + * + * Only for use with queues that can hold a single item - so the queue is either + * empty or full. + * + * Post an item on a queue. If the queue is already full then overwrite the + * value held in the queue. The item is queued by copy, not by reference. + * + * @param xQueue The handle to the queue on which the item is to be posted. + * + * @param pvItemToQueue A pointer to the item that is to be placed on the + * queue. The size of the items the queue will hold was defined when the + * queue was created, so this many bytes will be copied from pvItemToQueue + * into the queue storage area. + * + * @param pxHigherPriorityTaskWoken xQueueOverwriteFromISR() will set + * *pxHigherPriorityTaskWoken to pdTRUE if sending to the queue caused a task + * to unblock, and the unblocked task has a priority higher than the currently + * running task. If xQueueOverwriteFromISR() sets this value to pdTRUE then + * a context switch should be requested before the interrupt is exited. + * + * @return xQueueOverwriteFromISR() is a macro that calls + * xQueueGenericSendFromISR(), and therefore has the same return values as + * xQueueSendToFrontFromISR(). However, pdPASS is the only value that can be + * returned because xQueueOverwriteFromISR() will write to the queue even when + * the queue is already full. + * + * Example usage: +
+
+ QueueHandle_t xQueue;
+
+ void vFunction( void *pvParameters )
+ {
+ 	// Create a queue to hold one uint32_t value.  It is strongly
+	// recommended *not* to use xQueueOverwriteFromISR() on queues that can
+	// contain more than one value, and doing so will trigger an assertion
+	// if configASSERT() is defined.
+	xQueue = xQueueCreate( 1, sizeof( uint32_t ) );
+}
+
+void vAnInterruptHandler( void )
+{
+// xHigherPriorityTaskWoken must be set to pdFALSE before it is used.
+BaseType_t xHigherPriorityTaskWoken = pdFALSE;
+uint32_t ulVarToSend, ulValReceived;
+
+	// Write the value 10 to the queue using xQueueOverwriteFromISR().
+	ulVarToSend = 10;
+	xQueueOverwriteFromISR( xQueue, &ulVarToSend, &xHigherPriorityTaskWoken );
+
+	// The queue is full, but calling xQueueOverwriteFromISR() again will still
+	// pass because the value held in the queue will be overwritten with the
+	// new value.
+	ulVarToSend = 100;
+	xQueueOverwriteFromISR( xQueue, &ulVarToSend, &xHigherPriorityTaskWoken );
+
+	// Reading from the queue will now return 100.
+
+	// ...
+
+	if( xHigherPrioritytaskWoken == pdTRUE )
+	{
+		// Writing to the queue caused a task to unblock and the unblocked task
+		// has a priority higher than or equal to the priority of the currently
+		// executing task (the task this interrupt interrupted).  Perform a context
+		// switch so this interrupt returns directly to the unblocked task.
+		portYIELD_FROM_ISR(); // or portEND_SWITCHING_ISR() depending on the port.
+	}
+}
+ 
+ * \defgroup xQueueOverwriteFromISR xQueueOverwriteFromISR + * \ingroup QueueManagement + */ +#define xQueueOverwriteFromISR( xQueue, pvItemToQueue, pxHigherPriorityTaskWoken ) xQueueGenericSendFromISR( ( xQueue ), ( pvItemToQueue ), ( pxHigherPriorityTaskWoken ), queueOVERWRITE ) + +/** + * queue. h + *
+ BaseType_t xQueueSendFromISR(
+									 QueueHandle_t xQueue,
+									 const void *pvItemToQueue,
+									 BaseType_t *pxHigherPriorityTaskWoken
+								);
+ 
+ * + * This is a macro that calls xQueueGenericSendFromISR(). It is included + * for backward compatibility with versions of FreeRTOS.org that did not + * include the xQueueSendToBackFromISR() and xQueueSendToFrontFromISR() + * macros. + * + * Post an item to the back of a queue. It is safe to use this function from + * within an interrupt service routine. + * + * Items are queued by copy not reference so it is preferable to only + * queue small items, especially when called from an ISR. In most cases + * it would be preferable to store a pointer to the item being queued. + * + * @param xQueue The handle to the queue on which the item is to be posted. + * + * @param pvItemToQueue A pointer to the item that is to be placed on the + * queue. The size of the items the queue will hold was defined when the + * queue was created, so this many bytes will be copied from pvItemToQueue + * into the queue storage area. + * + * @param pxHigherPriorityTaskWoken xQueueSendFromISR() will set + * *pxHigherPriorityTaskWoken to pdTRUE if sending to the queue caused a task + * to unblock, and the unblocked task has a priority higher than the currently + * running task. If xQueueSendFromISR() sets this value to pdTRUE then + * a context switch should be requested before the interrupt is exited. + * + * @return pdTRUE if the data was successfully sent to the queue, otherwise + * errQUEUE_FULL. + * + * Example usage for buffered IO (where the ISR can obtain more than one value + * per call): +
+ void vBufferISR( void )
+ {
+ char cIn;
+ BaseType_t xHigherPriorityTaskWoken;
+
+	// We have not woken a task at the start of the ISR.
+	xHigherPriorityTaskWoken = pdFALSE;
+
+	// Loop until the buffer is empty.
+	do
+	{
+		// Obtain a byte from the buffer.
+		cIn = portINPUT_BYTE( RX_REGISTER_ADDRESS );
+
+		// Post the byte.
+		xQueueSendFromISR( xRxQueue, &cIn, &xHigherPriorityTaskWoken );
+
+	} while( portINPUT_BYTE( BUFFER_COUNT ) );
+
+	// Now the buffer is empty we can switch context if necessary.
+	if( xHigherPriorityTaskWoken )
+	{
+		// Actual macro used here is port specific.
+		portYIELD_FROM_ISR ();
+	}
+ }
+ 
+ * + * \defgroup xQueueSendFromISR xQueueSendFromISR + * \ingroup QueueManagement + */ +#define xQueueSendFromISR( xQueue, pvItemToQueue, pxHigherPriorityTaskWoken ) xQueueGenericSendFromISR( ( xQueue ), ( pvItemToQueue ), ( pxHigherPriorityTaskWoken ), queueSEND_TO_BACK ) + +/** + * queue. h + *
+ BaseType_t xQueueGenericSendFromISR(
+										   QueueHandle_t		xQueue,
+										   const	void	*pvItemToQueue,
+										   BaseType_t	*pxHigherPriorityTaskWoken,
+										   BaseType_t	xCopyPosition
+									   );
+ 
+ * + * It is preferred that the macros xQueueSendFromISR(), + * xQueueSendToFrontFromISR() and xQueueSendToBackFromISR() be used in place + * of calling this function directly. xQueueGiveFromISR() is an + * equivalent for use by semaphores that don't actually copy any data. + * + * Post an item on a queue. It is safe to use this function from within an + * interrupt service routine. + * + * Items are queued by copy not reference so it is preferable to only + * queue small items, especially when called from an ISR. In most cases + * it would be preferable to store a pointer to the item being queued. + * + * @param xQueue The handle to the queue on which the item is to be posted. + * + * @param pvItemToQueue A pointer to the item that is to be placed on the + * queue. The size of the items the queue will hold was defined when the + * queue was created, so this many bytes will be copied from pvItemToQueue + * into the queue storage area. + * + * @param pxHigherPriorityTaskWoken xQueueGenericSendFromISR() will set + * *pxHigherPriorityTaskWoken to pdTRUE if sending to the queue caused a task + * to unblock, and the unblocked task has a priority higher than the currently + * running task. If xQueueGenericSendFromISR() sets this value to pdTRUE then + * a context switch should be requested before the interrupt is exited. + * + * @param xCopyPosition Can take the value queueSEND_TO_BACK to place the + * item at the back of the queue, or queueSEND_TO_FRONT to place the item + * at the front of the queue (for high priority messages). + * + * @return pdTRUE if the data was successfully sent to the queue, otherwise + * errQUEUE_FULL. + * + * Example usage for buffered IO (where the ISR can obtain more than one value + * per call): +
+ void vBufferISR( void )
+ {
+ char cIn;
+ BaseType_t xHigherPriorityTaskWokenByPost;
+
+	// We have not woken a task at the start of the ISR.
+	xHigherPriorityTaskWokenByPost = pdFALSE;
+
+	// Loop until the buffer is empty.
+	do
+	{
+		// Obtain a byte from the buffer.
+		cIn = portINPUT_BYTE( RX_REGISTER_ADDRESS );
+
+		// Post each byte.
+		xQueueGenericSendFromISR( xRxQueue, &cIn, &xHigherPriorityTaskWokenByPost, queueSEND_TO_BACK );
+
+	} while( portINPUT_BYTE( BUFFER_COUNT ) );
+
+	// Now the buffer is empty we can switch context if necessary.  Note that the
+	// name of the yield function required is port specific.
+	if( xHigherPriorityTaskWokenByPost )
+	{
+		taskYIELD_YIELD_FROM_ISR();
+	}
+ }
+ 
+ * + * \defgroup xQueueSendFromISR xQueueSendFromISR + * \ingroup QueueManagement + */ +BaseType_t xQueueGenericSendFromISR( QueueHandle_t xQueue, const void * const pvItemToQueue, BaseType_t * const pxHigherPriorityTaskWoken, const BaseType_t xCopyPosition ) PRIVILEGED_FUNCTION; +BaseType_t xQueueGiveFromISR( QueueHandle_t xQueue, BaseType_t * const pxHigherPriorityTaskWoken ) PRIVILEGED_FUNCTION; + +/** + * queue. h + *
+ BaseType_t xQueueReceiveFromISR(
+									   QueueHandle_t	xQueue,
+									   void	*pvBuffer,
+									   BaseType_t *pxTaskWoken
+								   );
+ * 
+ * + * Receive an item from a queue. It is safe to use this function from within an + * interrupt service routine. + * + * @param xQueue The handle to the queue from which the item is to be + * received. + * + * @param pvBuffer Pointer to the buffer into which the received item will + * be copied. + * + * @param pxTaskWoken A task may be blocked waiting for space to become + * available on the queue. If xQueueReceiveFromISR causes such a task to + * unblock *pxTaskWoken will get set to pdTRUE, otherwise *pxTaskWoken will + * remain unchanged. + * + * @return pdTRUE if an item was successfully received from the queue, + * otherwise pdFALSE. + * + * Example usage: +
+
+ QueueHandle_t xQueue;
+
+ // Function to create a queue and post some values.
+ void vAFunction( void *pvParameters )
+ {
+ char cValueToPost;
+ const TickType_t xTicksToWait = ( TickType_t )0xff;
+
+	// Create a queue capable of containing 10 characters.
+	xQueue = xQueueCreate( 10, sizeof( char ) );
+	if( xQueue == 0 )
+	{
+		// Failed to create the queue.
+	}
+
+	// ...
+
+	// Post some characters that will be used within an ISR.  If the queue
+	// is full then this task will block for xTicksToWait ticks.
+	cValueToPost = 'a';
+	xQueueSend( xQueue, ( void * ) &cValueToPost, xTicksToWait );
+	cValueToPost = 'b';
+	xQueueSend( xQueue, ( void * ) &cValueToPost, xTicksToWait );
+
+	// ... keep posting characters ... this task may block when the queue
+	// becomes full.
+
+	cValueToPost = 'c';
+	xQueueSend( xQueue, ( void * ) &cValueToPost, xTicksToWait );
+ }
+
+ // ISR that outputs all the characters received on the queue.
+ void vISR_Routine( void )
+ {
+ BaseType_t xTaskWokenByReceive = pdFALSE;
+ char cRxedChar;
+
+	while( xQueueReceiveFromISR( xQueue, ( void * ) &cRxedChar, &xTaskWokenByReceive) )
+	{
+		// A character was received.  Output the character now.
+		vOutputCharacter( cRxedChar );
+
+		// If removing the character from the queue woke the task that was
+		// posting onto the queue cTaskWokenByReceive will have been set to
+		// pdTRUE.  No matter how many times this loop iterates only one
+		// task will be woken.
+	}
+
+	if( cTaskWokenByPost != ( char ) pdFALSE;
+	{
+		taskYIELD ();
+	}
+ }
+ 
+ * \defgroup xQueueReceiveFromISR xQueueReceiveFromISR + * \ingroup QueueManagement + */ +BaseType_t xQueueReceiveFromISR( QueueHandle_t xQueue, void * const pvBuffer, BaseType_t * const pxHigherPriorityTaskWoken ) PRIVILEGED_FUNCTION; + +/* + * Utilities to query queues that are safe to use from an ISR. These utilities + * should be used only from witin an ISR, or within a critical section. + */ +BaseType_t xQueueIsQueueEmptyFromISR( const QueueHandle_t xQueue ) PRIVILEGED_FUNCTION; +BaseType_t xQueueIsQueueFullFromISR( const QueueHandle_t xQueue ) PRIVILEGED_FUNCTION; +UBaseType_t uxQueueMessagesWaitingFromISR( const QueueHandle_t xQueue ) PRIVILEGED_FUNCTION; + + +/* + * xQueueAltGenericSend() is an alternative version of xQueueGenericSend(). + * Likewise xQueueAltGenericReceive() is an alternative version of + * xQueueGenericReceive(). + * + * The source code that implements the alternative (Alt) API is much + * simpler because it executes everything from within a critical section. + * This is the approach taken by many other RTOSes, but FreeRTOS.org has the + * preferred fully featured API too. The fully featured API has more + * complex code that takes longer to execute, but makes much less use of + * critical sections. Therefore the alternative API sacrifices interrupt + * responsiveness to gain execution speed, whereas the fully featured API + * sacrifices execution speed to ensure better interrupt responsiveness. + */ +BaseType_t xQueueAltGenericSend( QueueHandle_t xQueue, const void * const pvItemToQueue, TickType_t xTicksToWait, BaseType_t xCopyPosition ); +BaseType_t xQueueAltGenericReceive( QueueHandle_t xQueue, void * const pvBuffer, TickType_t xTicksToWait, BaseType_t xJustPeeking ); +#define xQueueAltSendToFront( xQueue, pvItemToQueue, xTicksToWait ) xQueueAltGenericSend( ( xQueue ), ( pvItemToQueue ), ( xTicksToWait ), queueSEND_TO_FRONT ) +#define xQueueAltSendToBack( xQueue, pvItemToQueue, xTicksToWait ) xQueueAltGenericSend( ( xQueue ), ( pvItemToQueue ), ( xTicksToWait ), queueSEND_TO_BACK ) +#define xQueueAltReceive( xQueue, pvBuffer, xTicksToWait ) xQueueAltGenericReceive( ( xQueue ), ( pvBuffer ), ( xTicksToWait ), pdFALSE ) +#define xQueueAltPeek( xQueue, pvBuffer, xTicksToWait ) xQueueAltGenericReceive( ( xQueue ), ( pvBuffer ), ( xTicksToWait ), pdTRUE ) + +/* + * The functions defined above are for passing data to and from tasks. The + * functions below are the equivalents for passing data to and from + * co-routines. + * + * These functions are called from the co-routine macro implementation and + * should not be called directly from application code. Instead use the macro + * wrappers defined within croutine.h. + */ +BaseType_t xQueueCRSendFromISR( QueueHandle_t xQueue, const void *pvItemToQueue, BaseType_t xCoRoutinePreviouslyWoken ); +BaseType_t xQueueCRReceiveFromISR( QueueHandle_t xQueue, void *pvBuffer, BaseType_t *pxTaskWoken ); +BaseType_t xQueueCRSend( QueueHandle_t xQueue, const void *pvItemToQueue, TickType_t xTicksToWait ); +BaseType_t xQueueCRReceive( QueueHandle_t xQueue, void *pvBuffer, TickType_t xTicksToWait ); + +/* + * For internal use only. Use xSemaphoreCreateMutex(), + * xSemaphoreCreateCounting() or xSemaphoreGetMutexHolder() instead of calling + * these functions directly. + */ +QueueHandle_t xQueueCreateMutex( const uint8_t ucQueueType ) PRIVILEGED_FUNCTION; +QueueHandle_t xQueueCreateCountingSemaphore( const UBaseType_t uxMaxCount, const UBaseType_t uxInitialCount ) PRIVILEGED_FUNCTION; +void* xQueueGetMutexHolder( QueueHandle_t xSemaphore ) PRIVILEGED_FUNCTION; + +/* + * For internal use only. Use xSemaphoreTakeMutexRecursive() or + * xSemaphoreGiveMutexRecursive() instead of calling these functions directly. + */ +BaseType_t xQueueTakeMutexRecursive( QueueHandle_t xMutex, TickType_t xTicksToWait ) PRIVILEGED_FUNCTION; +BaseType_t xQueueGiveMutexRecursive( QueueHandle_t pxMutex ) PRIVILEGED_FUNCTION; + +/* + * Reset a queue back to its original empty state. pdPASS is returned if the + * queue is successfully reset. pdFAIL is returned if the queue could not be + * reset because there are tasks blocked on the queue waiting to either + * receive from the queue or send to the queue. + */ +#define xQueueReset( xQueue ) xQueueGenericReset( xQueue, pdFALSE ) + +/* + * The registry is provided as a means for kernel aware debuggers to + * locate queues, semaphores and mutexes. Call vQueueAddToRegistry() add + * a queue, semaphore or mutex handle to the registry if you want the handle + * to be available to a kernel aware debugger. If you are not using a kernel + * aware debugger then this function can be ignored. + * + * configQUEUE_REGISTRY_SIZE defines the maximum number of handles the + * registry can hold. configQUEUE_REGISTRY_SIZE must be greater than 0 + * within FreeRTOSConfig.h for the registry to be available. Its value + * does not effect the number of queues, semaphores and mutexes that can be + * created - just the number that the registry can hold. + * + * @param xQueue The handle of the queue being added to the registry. This + * is the handle returned by a call to xQueueCreate(). Semaphore and mutex + * handles can also be passed in here. + * + * @param pcName The name to be associated with the handle. This is the + * name that the kernel aware debugger will display. The queue registry only + * stores a pointer to the string - so the string must be persistent (global or + * preferably in ROM/Flash), not on the stack. + */ +#if configQUEUE_REGISTRY_SIZE > 0 + void vQueueAddToRegistry( QueueHandle_t xQueue, const char *pcName ) PRIVILEGED_FUNCTION; /*lint !e971 Unqualified char types are allowed for strings and single characters only. */ +#endif + +/* + * The registry is provided as a means for kernel aware debuggers to + * locate queues, semaphores and mutexes. Call vQueueAddToRegistry() add + * a queue, semaphore or mutex handle to the registry if you want the handle + * to be available to a kernel aware debugger, and vQueueUnregisterQueue() to + * remove the queue, semaphore or mutex from the register. If you are not using + * a kernel aware debugger then this function can be ignored. + * + * @param xQueue The handle of the queue being removed from the registry. + */ +#if configQUEUE_REGISTRY_SIZE > 0 + void vQueueUnregisterQueue( QueueHandle_t xQueue ) PRIVILEGED_FUNCTION; +#endif + +/* + * Generic version of the queue creation function, which is in turn called by + * any queue, semaphore or mutex creation function or macro. + */ +QueueHandle_t xQueueGenericCreate( const UBaseType_t uxQueueLength, const UBaseType_t uxItemSize, const uint8_t ucQueueType ) PRIVILEGED_FUNCTION; + +/* + * Queue sets provide a mechanism to allow a task to block (pend) on a read + * operation from multiple queues or semaphores simultaneously. + * + * See FreeRTOS/Source/Demo/Common/Minimal/QueueSet.c for an example using this + * function. + * + * A queue set must be explicitly created using a call to xQueueCreateSet() + * before it can be used. Once created, standard FreeRTOS queues and semaphores + * can be added to the set using calls to xQueueAddToSet(). + * xQueueSelectFromSet() is then used to determine which, if any, of the queues + * or semaphores contained in the set is in a state where a queue read or + * semaphore take operation would be successful. + * + * Note 1: See the documentation on http://wwwFreeRTOS.org/RTOS-queue-sets.html + * for reasons why queue sets are very rarely needed in practice as there are + * simpler methods of blocking on multiple objects. + * + * Note 2: Blocking on a queue set that contains a mutex will not cause the + * mutex holder to inherit the priority of the blocked task. + * + * Note 3: An additional 4 bytes of RAM is required for each space in a every + * queue added to a queue set. Therefore counting semaphores that have a high + * maximum count value should not be added to a queue set. + * + * Note 4: A receive (in the case of a queue) or take (in the case of a + * semaphore) operation must not be performed on a member of a queue set unless + * a call to xQueueSelectFromSet() has first returned a handle to that set member. + * + * @param uxEventQueueLength Queue sets store events that occur on + * the queues and semaphores contained in the set. uxEventQueueLength specifies + * the maximum number of events that can be queued at once. To be absolutely + * certain that events are not lost uxEventQueueLength should be set to the + * total sum of the length of the queues added to the set, where binary + * semaphores and mutexes have a length of 1, and counting semaphores have a + * length set by their maximum count value. Examples: + * + If a queue set is to hold a queue of length 5, another queue of length 12, + * and a binary semaphore, then uxEventQueueLength should be set to + * (5 + 12 + 1), or 18. + * + If a queue set is to hold three binary semaphores then uxEventQueueLength + * should be set to (1 + 1 + 1 ), or 3. + * + If a queue set is to hold a counting semaphore that has a maximum count of + * 5, and a counting semaphore that has a maximum count of 3, then + * uxEventQueueLength should be set to (5 + 3), or 8. + * + * @return If the queue set is created successfully then a handle to the created + * queue set is returned. Otherwise NULL is returned. + */ +QueueSetHandle_t xQueueCreateSet( const UBaseType_t uxEventQueueLength ) PRIVILEGED_FUNCTION; + +/* + * Adds a queue or semaphore to a queue set that was previously created by a + * call to xQueueCreateSet(). + * + * See FreeRTOS/Source/Demo/Common/Minimal/QueueSet.c for an example using this + * function. + * + * Note 1: A receive (in the case of a queue) or take (in the case of a + * semaphore) operation must not be performed on a member of a queue set unless + * a call to xQueueSelectFromSet() has first returned a handle to that set member. + * + * @param xQueueOrSemaphore The handle of the queue or semaphore being added to + * the queue set (cast to an QueueSetMemberHandle_t type). + * + * @param xQueueSet The handle of the queue set to which the queue or semaphore + * is being added. + * + * @return If the queue or semaphore was successfully added to the queue set + * then pdPASS is returned. If the queue could not be successfully added to the + * queue set because it is already a member of a different queue set then pdFAIL + * is returned. + */ +BaseType_t xQueueAddToSet( QueueSetMemberHandle_t xQueueOrSemaphore, QueueSetHandle_t xQueueSet ) PRIVILEGED_FUNCTION; + +/* + * Removes a queue or semaphore from a queue set. A queue or semaphore can only + * be removed from a set if the queue or semaphore is empty. + * + * See FreeRTOS/Source/Demo/Common/Minimal/QueueSet.c for an example using this + * function. + * + * @param xQueueOrSemaphore The handle of the queue or semaphore being removed + * from the queue set (cast to an QueueSetMemberHandle_t type). + * + * @param xQueueSet The handle of the queue set in which the queue or semaphore + * is included. + * + * @return If the queue or semaphore was successfully removed from the queue set + * then pdPASS is returned. If the queue was not in the queue set, or the + * queue (or semaphore) was not empty, then pdFAIL is returned. + */ +BaseType_t xQueueRemoveFromSet( QueueSetMemberHandle_t xQueueOrSemaphore, QueueSetHandle_t xQueueSet ) PRIVILEGED_FUNCTION; + +/* + * xQueueSelectFromSet() selects from the members of a queue set a queue or + * semaphore that either contains data (in the case of a queue) or is available + * to take (in the case of a semaphore). xQueueSelectFromSet() effectively + * allows a task to block (pend) on a read operation on all the queues and + * semaphores in a queue set simultaneously. + * + * See FreeRTOS/Source/Demo/Common/Minimal/QueueSet.c for an example using this + * function. + * + * Note 1: See the documentation on http://wwwFreeRTOS.org/RTOS-queue-sets.html + * for reasons why queue sets are very rarely needed in practice as there are + * simpler methods of blocking on multiple objects. + * + * Note 2: Blocking on a queue set that contains a mutex will not cause the + * mutex holder to inherit the priority of the blocked task. + * + * Note 3: A receive (in the case of a queue) or take (in the case of a + * semaphore) operation must not be performed on a member of a queue set unless + * a call to xQueueSelectFromSet() has first returned a handle to that set member. + * + * @param xQueueSet The queue set on which the task will (potentially) block. + * + * @param xTicksToWait The maximum time, in ticks, that the calling task will + * remain in the Blocked state (with other tasks executing) to wait for a member + * of the queue set to be ready for a successful queue read or semaphore take + * operation. + * + * @return xQueueSelectFromSet() will return the handle of a queue (cast to + * a QueueSetMemberHandle_t type) contained in the queue set that contains data, + * or the handle of a semaphore (cast to a QueueSetMemberHandle_t type) contained + * in the queue set that is available, or NULL if no such queue or semaphore + * exists before before the specified block time expires. + */ +QueueSetMemberHandle_t xQueueSelectFromSet( QueueSetHandle_t xQueueSet, const TickType_t xTicksToWait ) PRIVILEGED_FUNCTION; + +/* + * A version of xQueueSelectFromSet() that can be used from an ISR. + */ +QueueSetMemberHandle_t xQueueSelectFromSetFromISR( QueueSetHandle_t xQueueSet ) PRIVILEGED_FUNCTION; + +/* Not public API functions. */ +void vQueueWaitForMessageRestricted( QueueHandle_t xQueue, TickType_t xTicksToWait ) PRIVILEGED_FUNCTION; +BaseType_t xQueueGenericReset( QueueHandle_t xQueue, BaseType_t xNewQueue ) PRIVILEGED_FUNCTION; +void vQueueSetQueueNumber( QueueHandle_t xQueue, UBaseType_t uxQueueNumber ) PRIVILEGED_FUNCTION; +UBaseType_t uxQueueGetQueueNumber( QueueHandle_t xQueue ) PRIVILEGED_FUNCTION; +uint8_t ucQueueGetQueueType( QueueHandle_t xQueue ) PRIVILEGED_FUNCTION; + + +#ifdef __cplusplus +} +#endif + +#endif /* QUEUE_H */ + diff --git a/components/freertos/include/freertos/semphr.h b/components/freertos/include/freertos/semphr.h new file mode 100644 index 0000000000..5866ab1ec5 --- /dev/null +++ b/components/freertos/include/freertos/semphr.h @@ -0,0 +1,844 @@ +/* + FreeRTOS V8.2.0 - Copyright (C) 2015 Real Time Engineers Ltd. + All rights reserved + + VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION. + + This file is part of the FreeRTOS distribution. + + FreeRTOS is free software; you can redistribute it and/or modify it under + the terms of the GNU General Public License (version 2) as published by the + Free Software Foundation >>!AND MODIFIED BY!<< the FreeRTOS exception. + + *************************************************************************** + >>! NOTE: The modification to the GPL is included to allow you to !<< + >>! distribute a combined work that includes FreeRTOS without being !<< + >>! obliged to provide the source code for proprietary components !<< + >>! outside of the FreeRTOS kernel. !<< + *************************************************************************** + + FreeRTOS is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + FOR A PARTICULAR PURPOSE. Full license text is available on the following + link: http://www.freertos.org/a00114.html + + *************************************************************************** + * * + * FreeRTOS provides completely free yet professionally developed, * + * robust, strictly quality controlled, supported, and cross * + * platform software that is more than just the market leader, it * + * is the industry's de facto standard. * + * * + * Help yourself get started quickly while simultaneously helping * + * to support the FreeRTOS project by purchasing a FreeRTOS * + * tutorial book, reference manual, or both: * + * http://www.FreeRTOS.org/Documentation * + * * + *************************************************************************** + + http://www.FreeRTOS.org/FAQHelp.html - Having a problem? Start by reading + the FAQ page "My application does not run, what could be wrong?". Have you + defined configASSERT()? + + http://www.FreeRTOS.org/support - In return for receiving this top quality + embedded software for free we request you assist our global community by + participating in the support forum. + + http://www.FreeRTOS.org/training - Investing in training allows your team to + be as productive as possible as early as possible. Now you can receive + FreeRTOS training directly from Richard Barry, CEO of Real Time Engineers + Ltd, and the world's leading authority on the world's leading RTOS. + + http://www.FreeRTOS.org/plus - A selection of FreeRTOS ecosystem products, + including FreeRTOS+Trace - an indispensable productivity tool, a DOS + compatible FAT file system, and our tiny thread aware UDP/IP stack. + + http://www.FreeRTOS.org/labs - Where new FreeRTOS products go to incubate. + Come and try FreeRTOS+TCP, our new open source TCP/IP stack for FreeRTOS. + + http://www.OpenRTOS.com - Real Time Engineers ltd. license FreeRTOS to High + Integrity Systems ltd. to sell under the OpenRTOS brand. Low cost OpenRTOS + licenses offer ticketed support, indemnification and commercial middleware. + + http://www.SafeRTOS.com - High Integrity Systems also provide a safety + engineered and independently SIL3 certified version for use in safety and + mission critical applications that require provable dependability. + + 1 tab == 4 spaces! +*/ + +#ifndef SEMAPHORE_H +#define SEMAPHORE_H + +#ifndef INC_FREERTOS_H + #error "include FreeRTOS.h" must appear in source files before "include semphr.h" +#endif + +#include "queue.h" + +typedef QueueHandle_t SemaphoreHandle_t; + +#define semBINARY_SEMAPHORE_QUEUE_LENGTH ( ( uint8_t ) 1U ) +#define semSEMAPHORE_QUEUE_ITEM_LENGTH ( ( uint8_t ) 0U ) +#define semGIVE_BLOCK_TIME ( ( TickType_t ) 0U ) + + +/** + * semphr. h + *
vSemaphoreCreateBinary( SemaphoreHandle_t xSemaphore )
+ * + * This old vSemaphoreCreateBinary() macro is now deprecated in favour of the + * xSemaphoreCreateBinary() function. Note that binary semaphores created using + * the vSemaphoreCreateBinary() macro are created in a state such that the + * first call to 'take' the semaphore would pass, whereas binary semaphores + * created using xSemaphoreCreateBinary() are created in a state such that the + * the semaphore must first be 'given' before it can be 'taken'. + * + * Macro that implements a semaphore by using the existing queue mechanism. + * The queue length is 1 as this is a binary semaphore. The data size is 0 + * as we don't want to actually store any data - we just want to know if the + * queue is empty or full. + * + * This type of semaphore can be used for pure synchronisation between tasks or + * between an interrupt and a task. The semaphore need not be given back once + * obtained, so one task/interrupt can continuously 'give' the semaphore while + * another continuously 'takes' the semaphore. For this reason this type of + * semaphore does not use a priority inheritance mechanism. For an alternative + * that does use priority inheritance see xSemaphoreCreateMutex(). + * + * @param xSemaphore Handle to the created semaphore. Should be of type SemaphoreHandle_t. + * + * Example usage: +
+ SemaphoreHandle_t xSemaphore = NULL;
+
+ void vATask( void * pvParameters )
+ {
+    // Semaphore cannot be used before a call to vSemaphoreCreateBinary ().
+    // This is a macro so pass the variable in directly.
+    vSemaphoreCreateBinary( xSemaphore );
+
+    if( xSemaphore != NULL )
+    {
+        // The semaphore was created successfully.
+        // The semaphore can now be used.
+    }
+ }
+ 
+ * \defgroup vSemaphoreCreateBinary vSemaphoreCreateBinary + * \ingroup Semaphores + */ +#define vSemaphoreCreateBinary( xSemaphore ) \ + { \ + ( xSemaphore ) = xQueueGenericCreate( ( UBaseType_t ) 1, semSEMAPHORE_QUEUE_ITEM_LENGTH, queueQUEUE_TYPE_BINARY_SEMAPHORE ); \ + if( ( xSemaphore ) != NULL ) \ + { \ + ( void ) xSemaphoreGive( ( xSemaphore ) ); \ + } \ + } + +/** + * semphr. h + *
SemaphoreHandle_t xSemaphoreCreateBinary( void )
+ * + * The old vSemaphoreCreateBinary() macro is now deprecated in favour of this + * xSemaphoreCreateBinary() function. Note that binary semaphores created using + * the vSemaphoreCreateBinary() macro are created in a state such that the + * first call to 'take' the semaphore would pass, whereas binary semaphores + * created using xSemaphoreCreateBinary() are created in a state such that the + * the semaphore must first be 'given' before it can be 'taken'. + * + * Function that creates a semaphore by using the existing queue mechanism. + * The queue length is 1 as this is a binary semaphore. The data size is 0 + * as nothing is actually stored - all that is important is whether the queue is + * empty or full (the binary semaphore is available or not). + * + * This type of semaphore can be used for pure synchronisation between tasks or + * between an interrupt and a task. The semaphore need not be given back once + * obtained, so one task/interrupt can continuously 'give' the semaphore while + * another continuously 'takes' the semaphore. For this reason this type of + * semaphore does not use a priority inheritance mechanism. For an alternative + * that does use priority inheritance see xSemaphoreCreateMutex(). + * + * @return Handle to the created semaphore. + * + * Example usage: +
+ SemaphoreHandle_t xSemaphore = NULL;
+
+ void vATask( void * pvParameters )
+ {
+    // Semaphore cannot be used before a call to vSemaphoreCreateBinary ().
+    // This is a macro so pass the variable in directly.
+    xSemaphore = xSemaphoreCreateBinary();
+
+    if( xSemaphore != NULL )
+    {
+        // The semaphore was created successfully.
+        // The semaphore can now be used.
+    }
+ }
+ 
+ * \defgroup vSemaphoreCreateBinary vSemaphoreCreateBinary + * \ingroup Semaphores + */ +#define xSemaphoreCreateBinary() xQueueGenericCreate( ( UBaseType_t ) 1, semSEMAPHORE_QUEUE_ITEM_LENGTH, queueQUEUE_TYPE_BINARY_SEMAPHORE ) + +/** + * semphr. h + *
xSemaphoreTake(
+ *                   SemaphoreHandle_t xSemaphore,
+ *                   TickType_t xBlockTime
+ *               )
+ * + * Macro to obtain a semaphore. The semaphore must have previously been + * created with a call to vSemaphoreCreateBinary(), xSemaphoreCreateMutex() or + * xSemaphoreCreateCounting(). + * + * @param xSemaphore A handle to the semaphore being taken - obtained when + * the semaphore was created. + * + * @param xBlockTime The time in ticks to wait for the semaphore to become + * available. The macro portTICK_PERIOD_MS can be used to convert this to a + * real time. A block time of zero can be used to poll the semaphore. A block + * time of portMAX_DELAY can be used to block indefinitely (provided + * INCLUDE_vTaskSuspend is set to 1 in FreeRTOSConfig.h). + * + * @return pdTRUE if the semaphore was obtained. pdFALSE + * if xBlockTime expired without the semaphore becoming available. + * + * Example usage: +
+ SemaphoreHandle_t xSemaphore = NULL;
+
+ // A task that creates a semaphore.
+ void vATask( void * pvParameters )
+ {
+    // Create the semaphore to guard a shared resource.
+    vSemaphoreCreateBinary( xSemaphore );
+ }
+
+ // A task that uses the semaphore.
+ void vAnotherTask( void * pvParameters )
+ {
+    // ... Do other things.
+
+    if( xSemaphore != NULL )
+    {
+        // See if we can obtain the semaphore.  If the semaphore is not available
+        // wait 10 ticks to see if it becomes free.
+        if( xSemaphoreTake( xSemaphore, ( TickType_t ) 10 ) == pdTRUE )
+        {
+            // We were able to obtain the semaphore and can now access the
+            // shared resource.
+
+            // ...
+
+            // We have finished accessing the shared resource.  Release the
+            // semaphore.
+            xSemaphoreGive( xSemaphore );
+        }
+        else
+        {
+            // We could not obtain the semaphore and can therefore not access
+            // the shared resource safely.
+        }
+    }
+ }
+ 
+ * \defgroup xSemaphoreTake xSemaphoreTake + * \ingroup Semaphores + */ +#define xSemaphoreTake( xSemaphore, xBlockTime ) xQueueGenericReceive( ( QueueHandle_t ) ( xSemaphore ), NULL, ( xBlockTime ), pdFALSE ) + +/** + * semphr. h + * xSemaphoreTakeRecursive( + * SemaphoreHandle_t xMutex, + * TickType_t xBlockTime + * ) + * + * Macro to recursively obtain, or 'take', a mutex type semaphore. + * The mutex must have previously been created using a call to + * xSemaphoreCreateRecursiveMutex(); + * + * configUSE_RECURSIVE_MUTEXES must be set to 1 in FreeRTOSConfig.h for this + * macro to be available. + * + * This macro must not be used on mutexes created using xSemaphoreCreateMutex(). + * + * A mutex used recursively can be 'taken' repeatedly by the owner. The mutex + * doesn't become available again until the owner has called + * xSemaphoreGiveRecursive() for each successful 'take' request. For example, + * if a task successfully 'takes' the same mutex 5 times then the mutex will + * not be available to any other task until it has also 'given' the mutex back + * exactly five times. + * + * @param xMutex A handle to the mutex being obtained. This is the + * handle returned by xSemaphoreCreateRecursiveMutex(); + * + * @param xBlockTime The time in ticks to wait for the semaphore to become + * available. The macro portTICK_PERIOD_MS can be used to convert this to a + * real time. A block time of zero can be used to poll the semaphore. If + * the task already owns the semaphore then xSemaphoreTakeRecursive() will + * return immediately no matter what the value of xBlockTime. + * + * @return pdTRUE if the semaphore was obtained. pdFALSE if xBlockTime + * expired without the semaphore becoming available. + * + * Example usage: +
+ SemaphoreHandle_t xMutex = NULL;
+
+ // A task that creates a mutex.
+ void vATask( void * pvParameters )
+ {
+    // Create the mutex to guard a shared resource.
+    xMutex = xSemaphoreCreateRecursiveMutex();
+ }
+
+ // A task that uses the mutex.
+ void vAnotherTask( void * pvParameters )
+ {
+    // ... Do other things.
+
+    if( xMutex != NULL )
+    {
+        // See if we can obtain the mutex.  If the mutex is not available
+        // wait 10 ticks to see if it becomes free.
+        if( xSemaphoreTakeRecursive( xSemaphore, ( TickType_t ) 10 ) == pdTRUE )
+        {
+            // We were able to obtain the mutex and can now access the
+            // shared resource.
+
+            // ...
+            // For some reason due to the nature of the code further calls to
+			// xSemaphoreTakeRecursive() are made on the same mutex.  In real
+			// code these would not be just sequential calls as this would make
+			// no sense.  Instead the calls are likely to be buried inside
+			// a more complex call structure.
+            xSemaphoreTakeRecursive( xMutex, ( TickType_t ) 10 );
+            xSemaphoreTakeRecursive( xMutex, ( TickType_t ) 10 );
+
+            // The mutex has now been 'taken' three times, so will not be
+			// available to another task until it has also been given back
+			// three times.  Again it is unlikely that real code would have
+			// these calls sequentially, but instead buried in a more complex
+			// call structure.  This is just for illustrative purposes.
+            xSemaphoreGiveRecursive( xMutex );
+			xSemaphoreGiveRecursive( xMutex );
+			xSemaphoreGiveRecursive( xMutex );
+
+			// Now the mutex can be taken by other tasks.
+        }
+        else
+        {
+            // We could not obtain the mutex and can therefore not access
+            // the shared resource safely.
+        }
+    }
+ }
+ 
+ * \defgroup xSemaphoreTakeRecursive xSemaphoreTakeRecursive + * \ingroup Semaphores + */ +#define xSemaphoreTakeRecursive( xMutex, xBlockTime ) xQueueTakeMutexRecursive( ( xMutex ), ( xBlockTime ) ) + + +/* + * xSemaphoreAltTake() is an alternative version of xSemaphoreTake(). + * + * The source code that implements the alternative (Alt) API is much + * simpler because it executes everything from within a critical section. + * This is the approach taken by many other RTOSes, but FreeRTOS.org has the + * preferred fully featured API too. The fully featured API has more + * complex code that takes longer to execute, but makes much less use of + * critical sections. Therefore the alternative API sacrifices interrupt + * responsiveness to gain execution speed, whereas the fully featured API + * sacrifices execution speed to ensure better interrupt responsiveness. + */ +#define xSemaphoreAltTake( xSemaphore, xBlockTime ) xQueueAltGenericReceive( ( QueueHandle_t ) ( xSemaphore ), NULL, ( xBlockTime ), pdFALSE ) + +/** + * semphr. h + *
xSemaphoreGive( SemaphoreHandle_t xSemaphore )
+ * + * Macro to release a semaphore. The semaphore must have previously been + * created with a call to vSemaphoreCreateBinary(), xSemaphoreCreateMutex() or + * xSemaphoreCreateCounting(). and obtained using sSemaphoreTake(). + * + * This macro must not be used from an ISR. See xSemaphoreGiveFromISR () for + * an alternative which can be used from an ISR. + * + * This macro must also not be used on semaphores created using + * xSemaphoreCreateRecursiveMutex(). + * + * @param xSemaphore A handle to the semaphore being released. This is the + * handle returned when the semaphore was created. + * + * @return pdTRUE if the semaphore was released. pdFALSE if an error occurred. + * Semaphores are implemented using queues. An error can occur if there is + * no space on the queue to post a message - indicating that the + * semaphore was not first obtained correctly. + * + * Example usage: +
+ SemaphoreHandle_t xSemaphore = NULL;
+
+ void vATask( void * pvParameters )
+ {
+    // Create the semaphore to guard a shared resource.
+    vSemaphoreCreateBinary( xSemaphore );
+
+    if( xSemaphore != NULL )
+    {
+        if( xSemaphoreGive( xSemaphore ) != pdTRUE )
+        {
+            // We would expect this call to fail because we cannot give
+            // a semaphore without first "taking" it!
+        }
+
+        // Obtain the semaphore - don't block if the semaphore is not
+        // immediately available.
+        if( xSemaphoreTake( xSemaphore, ( TickType_t ) 0 ) )
+        {
+            // We now have the semaphore and can access the shared resource.
+
+            // ...
+
+            // We have finished accessing the shared resource so can free the
+            // semaphore.
+            if( xSemaphoreGive( xSemaphore ) != pdTRUE )
+            {
+                // We would not expect this call to fail because we must have
+                // obtained the semaphore to get here.
+            }
+        }
+    }
+ }
+ 
+ * \defgroup xSemaphoreGive xSemaphoreGive + * \ingroup Semaphores + */ +#define xSemaphoreGive( xSemaphore ) xQueueGenericSend( ( QueueHandle_t ) ( xSemaphore ), NULL, semGIVE_BLOCK_TIME, queueSEND_TO_BACK ) + +/** + * semphr. h + *
xSemaphoreGiveRecursive( SemaphoreHandle_t xMutex )
+ * + * Macro to recursively release, or 'give', a mutex type semaphore. + * The mutex must have previously been created using a call to + * xSemaphoreCreateRecursiveMutex(); + * + * configUSE_RECURSIVE_MUTEXES must be set to 1 in FreeRTOSConfig.h for this + * macro to be available. + * + * This macro must not be used on mutexes created using xSemaphoreCreateMutex(). + * + * A mutex used recursively can be 'taken' repeatedly by the owner. The mutex + * doesn't become available again until the owner has called + * xSemaphoreGiveRecursive() for each successful 'take' request. For example, + * if a task successfully 'takes' the same mutex 5 times then the mutex will + * not be available to any other task until it has also 'given' the mutex back + * exactly five times. + * + * @param xMutex A handle to the mutex being released, or 'given'. This is the + * handle returned by xSemaphoreCreateMutex(); + * + * @return pdTRUE if the semaphore was given. + * + * Example usage: +
+ SemaphoreHandle_t xMutex = NULL;
+
+ // A task that creates a mutex.
+ void vATask( void * pvParameters )
+ {
+    // Create the mutex to guard a shared resource.
+    xMutex = xSemaphoreCreateRecursiveMutex();
+ }
+
+ // A task that uses the mutex.
+ void vAnotherTask( void * pvParameters )
+ {
+    // ... Do other things.
+
+    if( xMutex != NULL )
+    {
+        // See if we can obtain the mutex.  If the mutex is not available
+        // wait 10 ticks to see if it becomes free.
+        if( xSemaphoreTakeRecursive( xMutex, ( TickType_t ) 10 ) == pdTRUE )
+        {
+            // We were able to obtain the mutex and can now access the
+            // shared resource.
+
+            // ...
+            // For some reason due to the nature of the code further calls to
+			// xSemaphoreTakeRecursive() are made on the same mutex.  In real
+			// code these would not be just sequential calls as this would make
+			// no sense.  Instead the calls are likely to be buried inside
+			// a more complex call structure.
+            xSemaphoreTakeRecursive( xMutex, ( TickType_t ) 10 );
+            xSemaphoreTakeRecursive( xMutex, ( TickType_t ) 10 );
+
+            // The mutex has now been 'taken' three times, so will not be
+			// available to another task until it has also been given back
+			// three times.  Again it is unlikely that real code would have
+			// these calls sequentially, it would be more likely that the calls
+			// to xSemaphoreGiveRecursive() would be called as a call stack
+			// unwound.  This is just for demonstrative purposes.
+            xSemaphoreGiveRecursive( xMutex );
+			xSemaphoreGiveRecursive( xMutex );
+			xSemaphoreGiveRecursive( xMutex );
+
+			// Now the mutex can be taken by other tasks.
+        }
+        else
+        {
+            // We could not obtain the mutex and can therefore not access
+            // the shared resource safely.
+        }
+    }
+ }
+ 
+ * \defgroup xSemaphoreGiveRecursive xSemaphoreGiveRecursive + * \ingroup Semaphores + */ +#define xSemaphoreGiveRecursive( xMutex ) xQueueGiveMutexRecursive( ( xMutex ) ) + +/* + * xSemaphoreAltGive() is an alternative version of xSemaphoreGive(). + * + * The source code that implements the alternative (Alt) API is much + * simpler because it executes everything from within a critical section. + * This is the approach taken by many other RTOSes, but FreeRTOS.org has the + * preferred fully featured API too. The fully featured API has more + * complex code that takes longer to execute, but makes much less use of + * critical sections. Therefore the alternative API sacrifices interrupt + * responsiveness to gain execution speed, whereas the fully featured API + * sacrifices execution speed to ensure better interrupt responsiveness. + */ +#define xSemaphoreAltGive( xSemaphore ) xQueueAltGenericSend( ( QueueHandle_t ) ( xSemaphore ), NULL, semGIVE_BLOCK_TIME, queueSEND_TO_BACK ) + +/** + * semphr. h + *
+ xSemaphoreGiveFromISR(
+                          SemaphoreHandle_t xSemaphore,
+                          BaseType_t *pxHigherPriorityTaskWoken
+                      )
+ * + * Macro to release a semaphore. The semaphore must have previously been + * created with a call to vSemaphoreCreateBinary() or xSemaphoreCreateCounting(). + * + * Mutex type semaphores (those created using a call to xSemaphoreCreateMutex()) + * must not be used with this macro. + * + * This macro can be used from an ISR. + * + * @param xSemaphore A handle to the semaphore being released. This is the + * handle returned when the semaphore was created. + * + * @param pxHigherPriorityTaskWoken xSemaphoreGiveFromISR() will set + * *pxHigherPriorityTaskWoken to pdTRUE if giving the semaphore caused a task + * to unblock, and the unblocked task has a priority higher than the currently + * running task. If xSemaphoreGiveFromISR() sets this value to pdTRUE then + * a context switch should be requested before the interrupt is exited. + * + * @return pdTRUE if the semaphore was successfully given, otherwise errQUEUE_FULL. + * + * Example usage: +
+ \#define LONG_TIME 0xffff
+ \#define TICKS_TO_WAIT	10
+ SemaphoreHandle_t xSemaphore = NULL;
+
+ // Repetitive task.
+ void vATask( void * pvParameters )
+ {
+    for( ;; )
+    {
+        // We want this task to run every 10 ticks of a timer.  The semaphore
+        // was created before this task was started.
+
+        // Block waiting for the semaphore to become available.
+        if( xSemaphoreTake( xSemaphore, LONG_TIME ) == pdTRUE )
+        {
+            // It is time to execute.
+
+            // ...
+
+            // We have finished our task.  Return to the top of the loop where
+            // we will block on the semaphore until it is time to execute
+            // again.  Note when using the semaphore for synchronisation with an
+			// ISR in this manner there is no need to 'give' the semaphore back.
+        }
+    }
+ }
+
+ // Timer ISR
+ void vTimerISR( void * pvParameters )
+ {
+ static uint8_t ucLocalTickCount = 0;
+ static BaseType_t xHigherPriorityTaskWoken;
+
+    // A timer tick has occurred.
+
+    // ... Do other time functions.
+
+    // Is it time for vATask () to run?
+	xHigherPriorityTaskWoken = pdFALSE;
+    ucLocalTickCount++;
+    if( ucLocalTickCount >= TICKS_TO_WAIT )
+    {
+        // Unblock the task by releasing the semaphore.
+        xSemaphoreGiveFromISR( xSemaphore, &xHigherPriorityTaskWoken );
+
+        // Reset the count so we release the semaphore again in 10 ticks time.
+        ucLocalTickCount = 0;
+    }
+
+    if( xHigherPriorityTaskWoken != pdFALSE )
+    {
+        // We can force a context switch here.  Context switching from an
+        // ISR uses port specific syntax.  Check the demo task for your port
+        // to find the syntax required.
+    }
+ }
+ 
+ * \defgroup xSemaphoreGiveFromISR xSemaphoreGiveFromISR + * \ingroup Semaphores + */ +#define xSemaphoreGiveFromISR( xSemaphore, pxHigherPriorityTaskWoken ) xQueueGiveFromISR( ( QueueHandle_t ) ( xSemaphore ), ( pxHigherPriorityTaskWoken ) ) + +/** + * semphr. h + *
+ xSemaphoreTakeFromISR(
+                          SemaphoreHandle_t xSemaphore,
+                          BaseType_t *pxHigherPriorityTaskWoken
+                      )
+ * + * Macro to take a semaphore from an ISR. The semaphore must have + * previously been created with a call to vSemaphoreCreateBinary() or + * xSemaphoreCreateCounting(). + * + * Mutex type semaphores (those created using a call to xSemaphoreCreateMutex()) + * must not be used with this macro. + * + * This macro can be used from an ISR, however taking a semaphore from an ISR + * is not a common operation. It is likely to only be useful when taking a + * counting semaphore when an interrupt is obtaining an object from a resource + * pool (when the semaphore count indicates the number of resources available). + * + * @param xSemaphore A handle to the semaphore being taken. This is the + * handle returned when the semaphore was created. + * + * @param pxHigherPriorityTaskWoken xSemaphoreTakeFromISR() will set + * *pxHigherPriorityTaskWoken to pdTRUE if taking the semaphore caused a task + * to unblock, and the unblocked task has a priority higher than the currently + * running task. If xSemaphoreTakeFromISR() sets this value to pdTRUE then + * a context switch should be requested before the interrupt is exited. + * + * @return pdTRUE if the semaphore was successfully taken, otherwise + * pdFALSE + */ +#define xSemaphoreTakeFromISR( xSemaphore, pxHigherPriorityTaskWoken ) xQueueReceiveFromISR( ( QueueHandle_t ) ( xSemaphore ), NULL, ( pxHigherPriorityTaskWoken ) ) + +/** + * semphr. h + *
SemaphoreHandle_t xSemaphoreCreateMutex( void )
+ * + * Macro that implements a mutex semaphore by using the existing queue + * mechanism. + * + * Mutexes created using this macro can be accessed using the xSemaphoreTake() + * and xSemaphoreGive() macros. The xSemaphoreTakeRecursive() and + * xSemaphoreGiveRecursive() macros should not be used. + * + * This type of semaphore uses a priority inheritance mechanism so a task + * 'taking' a semaphore MUST ALWAYS 'give' the semaphore back once the + * semaphore it is no longer required. + * + * Mutex type semaphores cannot be used from within interrupt service routines. + * + * See vSemaphoreCreateBinary() for an alternative implementation that can be + * used for pure synchronisation (where one task or interrupt always 'gives' the + * semaphore and another always 'takes' the semaphore) and from within interrupt + * service routines. + * + * @return xSemaphore Handle to the created mutex semaphore. Should be of type + * SemaphoreHandle_t. + * + * Example usage: +
+ SemaphoreHandle_t xSemaphore;
+
+ void vATask( void * pvParameters )
+ {
+    // Semaphore cannot be used before a call to xSemaphoreCreateMutex().
+    // This is a macro so pass the variable in directly.
+    xSemaphore = xSemaphoreCreateMutex();
+
+    if( xSemaphore != NULL )
+    {
+        // The semaphore was created successfully.
+        // The semaphore can now be used.
+    }
+ }
+ 
+ * \defgroup vSemaphoreCreateMutex vSemaphoreCreateMutex + * \ingroup Semaphores + */ +#define xSemaphoreCreateMutex() xQueueCreateMutex( queueQUEUE_TYPE_MUTEX ) + + +/** + * semphr. h + *
SemaphoreHandle_t xSemaphoreCreateRecursiveMutex( void )
+ * + * Macro that implements a recursive mutex by using the existing queue + * mechanism. + * + * Mutexes created using this macro can be accessed using the + * xSemaphoreTakeRecursive() and xSemaphoreGiveRecursive() macros. The + * xSemaphoreTake() and xSemaphoreGive() macros should not be used. + * + * A mutex used recursively can be 'taken' repeatedly by the owner. The mutex + * doesn't become available again until the owner has called + * xSemaphoreGiveRecursive() for each successful 'take' request. For example, + * if a task successfully 'takes' the same mutex 5 times then the mutex will + * not be available to any other task until it has also 'given' the mutex back + * exactly five times. + * + * This type of semaphore uses a priority inheritance mechanism so a task + * 'taking' a semaphore MUST ALWAYS 'give' the semaphore back once the + * semaphore it is no longer required. + * + * Mutex type semaphores cannot be used from within interrupt service routines. + * + * See vSemaphoreCreateBinary() for an alternative implementation that can be + * used for pure synchronisation (where one task or interrupt always 'gives' the + * semaphore and another always 'takes' the semaphore) and from within interrupt + * service routines. + * + * @return xSemaphore Handle to the created mutex semaphore. Should be of type + * SemaphoreHandle_t. + * + * Example usage: +
+ SemaphoreHandle_t xSemaphore;
+
+ void vATask( void * pvParameters )
+ {
+    // Semaphore cannot be used before a call to xSemaphoreCreateMutex().
+    // This is a macro so pass the variable in directly.
+    xSemaphore = xSemaphoreCreateRecursiveMutex();
+
+    if( xSemaphore != NULL )
+    {
+        // The semaphore was created successfully.
+        // The semaphore can now be used.
+    }
+ }
+ 
+ * \defgroup vSemaphoreCreateMutex vSemaphoreCreateMutex + * \ingroup Semaphores + */ +#define xSemaphoreCreateRecursiveMutex() xQueueCreateMutex( queueQUEUE_TYPE_RECURSIVE_MUTEX ) + +/** + * semphr. h + *
SemaphoreHandle_t xSemaphoreCreateCounting( UBaseType_t uxMaxCount, UBaseType_t uxInitialCount )
+ * + * Macro that creates a counting semaphore by using the existing + * queue mechanism. + * + * Counting semaphores are typically used for two things: + * + * 1) Counting events. + * + * In this usage scenario an event handler will 'give' a semaphore each time + * an event occurs (incrementing the semaphore count value), and a handler + * task will 'take' a semaphore each time it processes an event + * (decrementing the semaphore count value). The count value is therefore + * the difference between the number of events that have occurred and the + * number that have been processed. In this case it is desirable for the + * initial count value to be zero. + * + * 2) Resource management. + * + * In this usage scenario the count value indicates the number of resources + * available. To obtain control of a resource a task must first obtain a + * semaphore - decrementing the semaphore count value. When the count value + * reaches zero there are no free resources. When a task finishes with the + * resource it 'gives' the semaphore back - incrementing the semaphore count + * value. In this case it is desirable for the initial count value to be + * equal to the maximum count value, indicating that all resources are free. + * + * @param uxMaxCount The maximum count value that can be reached. When the + * semaphore reaches this value it can no longer be 'given'. + * + * @param uxInitialCount The count value assigned to the semaphore when it is + * created. + * + * @return Handle to the created semaphore. Null if the semaphore could not be + * created. + * + * Example usage: +
+ SemaphoreHandle_t xSemaphore;
+
+ void vATask( void * pvParameters )
+ {
+ SemaphoreHandle_t xSemaphore = NULL;
+
+    // Semaphore cannot be used before a call to xSemaphoreCreateCounting().
+    // The max value to which the semaphore can count should be 10, and the
+    // initial value assigned to the count should be 0.
+    xSemaphore = xSemaphoreCreateCounting( 10, 0 );
+
+    if( xSemaphore != NULL )
+    {
+        // The semaphore was created successfully.
+        // The semaphore can now be used.
+    }
+ }
+ 
+ * \defgroup xSemaphoreCreateCounting xSemaphoreCreateCounting + * \ingroup Semaphores + */ +#define xSemaphoreCreateCounting( uxMaxCount, uxInitialCount ) xQueueCreateCountingSemaphore( ( uxMaxCount ), ( uxInitialCount ) ) + +/** + * semphr. h + *
void vSemaphoreDelete( SemaphoreHandle_t xSemaphore );
+ * + * Delete a semaphore. This function must be used with care. For example, + * do not delete a mutex type semaphore if the mutex is held by a task. + * + * @param xSemaphore A handle to the semaphore to be deleted. + * + * \defgroup vSemaphoreDelete vSemaphoreDelete + * \ingroup Semaphores + */ +#define vSemaphoreDelete( xSemaphore ) vQueueDelete( ( QueueHandle_t ) ( xSemaphore ) ) + +/** + * semphr.h + *
TaskHandle_t xSemaphoreGetMutexHolder( SemaphoreHandle_t xMutex );
+ * + * If xMutex is indeed a mutex type semaphore, return the current mutex holder. + * If xMutex is not a mutex type semaphore, or the mutex is available (not held + * by a task), return NULL. + * + * Note: This is a good way of determining if the calling task is the mutex + * holder, but not a good way of determining the identity of the mutex holder as + * the holder may change between the function exiting and the returned value + * being tested. + */ +#define xSemaphoreGetMutexHolder( xSemaphore ) xQueueGetMutexHolder( ( xSemaphore ) ) + +#endif /* SEMAPHORE_H */ + + diff --git a/components/freertos/include/freertos/task.h b/components/freertos/include/freertos/task.h new file mode 100644 index 0000000000..d4b9d43c82 --- /dev/null +++ b/components/freertos/include/freertos/task.h @@ -0,0 +1,2019 @@ +/* + FreeRTOS V8.2.0 - Copyright (C) 2015 Real Time Engineers Ltd. + All rights reserved + + VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION. + + This file is part of the FreeRTOS distribution. + + FreeRTOS is free software; you can redistribute it and/or modify it under + the terms of the GNU General Public License (version 2) as published by the + Free Software Foundation >>!AND MODIFIED BY!<< the FreeRTOS exception. + + *************************************************************************** + >>! NOTE: The modification to the GPL is included to allow you to !<< + >>! distribute a combined work that includes FreeRTOS without being !<< + >>! obliged to provide the source code for proprietary components !<< + >>! outside of the FreeRTOS kernel. !<< + *************************************************************************** + + FreeRTOS is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + FOR A PARTICULAR PURPOSE. Full license text is available on the following + link: http://www.freertos.org/a00114.html + + *************************************************************************** + * * + * FreeRTOS provides completely free yet professionally developed, * + * robust, strictly quality controlled, supported, and cross * + * platform software that is more than just the market leader, it * + * is the industry's de facto standard. * + * * + * Help yourself get started quickly while simultaneously helping * + * to support the FreeRTOS project by purchasing a FreeRTOS * + * tutorial book, reference manual, or both: * + * http://www.FreeRTOS.org/Documentation * + * * + *************************************************************************** + + http://www.FreeRTOS.org/FAQHelp.html - Having a problem? Start by reading + the FAQ page "My application does not run, what could be wrong?". Have you + defined configASSERT()? + + http://www.FreeRTOS.org/support - In return for receiving this top quality + embedded software for free we request you assist our global community by + participating in the support forum. + + http://www.FreeRTOS.org/training - Investing in training allows your team to + be as productive as possible as early as possible. Now you can receive + FreeRTOS training directly from Richard Barry, CEO of Real Time Engineers + Ltd, and the world's leading authority on the world's leading RTOS. + + http://www.FreeRTOS.org/plus - A selection of FreeRTOS ecosystem products, + including FreeRTOS+Trace - an indispensable productivity tool, a DOS + compatible FAT file system, and our tiny thread aware UDP/IP stack. + + http://www.FreeRTOS.org/labs - Where new FreeRTOS products go to incubate. + Come and try FreeRTOS+TCP, our new open source TCP/IP stack for FreeRTOS. + + http://www.OpenRTOS.com - Real Time Engineers ltd. license FreeRTOS to High + Integrity Systems ltd. to sell under the OpenRTOS brand. Low cost OpenRTOS + licenses offer ticketed support, indemnification and commercial middleware. + + http://www.SafeRTOS.com - High Integrity Systems also provide a safety + engineered and independently SIL3 certified version for use in safety and + mission critical applications that require provable dependability. + + 1 tab == 4 spaces! +*/ + + +#ifndef INC_TASK_H +#define INC_TASK_H + +#ifndef INC_FREERTOS_H + #error "include FreeRTOS.h must appear in source files before include task.h" +#endif + +#include "list.h" +#include "portmacro.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/*----------------------------------------------------------- + * MACROS AND DEFINITIONS + *----------------------------------------------------------*/ + +#define tskKERNEL_VERSION_NUMBER "V8.2.0" +#define tskKERNEL_VERSION_MAJOR 8 +#define tskKERNEL_VERSION_MINOR 2 +#define tskKERNEL_VERSION_BUILD 0 + +#define tskNO_AFFINITY portNUM_PROCESSORS + +/** + * task. h + * + * Type by which tasks are referenced. For example, a call to xTaskCreate + * returns (via a pointer parameter) an TaskHandle_t variable that can then + * be used as a parameter to vTaskDelete to delete the task. + * + * \defgroup TaskHandle_t TaskHandle_t + * \ingroup Tasks + */ +typedef void * TaskHandle_t; + +/* + * Defines the prototype to which the application task hook function must + * conform. + */ +typedef BaseType_t (*TaskHookFunction_t)( void * ); + +/* Task states returned by eTaskGetState. */ +typedef enum +{ + eRunning = 0, /* A task is querying the state of itself, so must be running. */ + eReady, /* The task being queried is in a read or pending ready list. */ + eBlocked, /* The task being queried is in the Blocked state. */ + eSuspended, /* The task being queried is in the Suspended state, or is in the Blocked state with an infinite time out. */ + eDeleted /* The task being queried has been deleted, but its TCB has not yet been freed. */ +} eTaskState; + +/* Actions that can be performed when vTaskNotify() is called. */ +typedef enum +{ + eNoAction = 0, /* Notify the task without updating its notify value. */ + eSetBits, /* Set bits in the task's notification value. */ + eIncrement, /* Increment the task's notification value. */ + eSetValueWithOverwrite, /* Set the task's notification value to a specific value even if the previous value has not yet been read by the task. */ + eSetValueWithoutOverwrite /* Set the task's notification value if the previous value has been read by the task. */ +} eNotifyAction; + +/* + * Used internally only. + */ +typedef struct xTIME_OUT +{ + BaseType_t xOverflowCount; + TickType_t xTimeOnEntering; +} TimeOut_t; + +/* + * Defines the memory ranges allocated to the task when an MPU is used. + */ +typedef struct xMEMORY_REGION +{ + void *pvBaseAddress; + uint32_t ulLengthInBytes; + uint32_t ulParameters; +} MemoryRegion_t; + +/* + * Parameters required to create an MPU protected task. + */ +typedef struct xTASK_PARAMETERS +{ + TaskFunction_t pvTaskCode; + const char * const pcName; /*lint !e971 Unqualified char types are allowed for strings and single characters only. */ + uint16_t usStackDepth; + void *pvParameters; + UBaseType_t uxPriority; + StackType_t *puxStackBuffer; + MemoryRegion_t xRegions[ portNUM_CONFIGURABLE_REGIONS ]; +} TaskParameters_t; + +/* Used with the uxTaskGetSystemState() function to return the state of each task +in the system. */ +typedef struct xTASK_STATUS +{ + TaskHandle_t xHandle; /* The handle of the task to which the rest of the information in the structure relates. */ + const char *pcTaskName; /* A pointer to the task's name. This value will be invalid if the task was deleted since the structure was populated! */ /*lint !e971 Unqualified char types are allowed for strings and single characters only. */ + UBaseType_t xTaskNumber; /* A number unique to the task. */ + eTaskState eCurrentState; /* The state in which the task existed when the structure was populated. */ + UBaseType_t uxCurrentPriority; /* The priority at which the task was running (may be inherited) when the structure was populated. */ + UBaseType_t uxBasePriority; /* The priority to which the task will return if the task's current priority has been inherited to avoid unbounded priority inversion when obtaining a mutex. Only valid if configUSE_MUTEXES is defined as 1 in FreeRTOSConfig.h. */ + uint32_t ulRunTimeCounter; /* The total run time allocated to the task so far, as defined by the run time stats clock. See http://www.freertos.org/rtos-run-time-stats.html. Only valid when configGENERATE_RUN_TIME_STATS is defined as 1 in FreeRTOSConfig.h. */ + uint16_t usStackHighWaterMark; /* The minimum amount of stack space that has remained for the task since the task was created. The closer this value is to zero the closer the task has come to overflowing its stack. */ +} TaskStatus_t; + +/* Possible return values for eTaskConfirmSleepModeStatus(). */ +typedef enum +{ + eAbortSleep = 0, /* A task has been made ready or a context switch pended since portSUPPORESS_TICKS_AND_SLEEP() was called - abort entering a sleep mode. */ + eStandardSleep, /* Enter a sleep mode that will not last any longer than the expected idle time. */ + eNoTasksWaitingTimeout /* No tasks are waiting for a timeout so it is safe to enter a sleep mode that can only be exited by an external interrupt. */ +} eSleepModeStatus; + + +/** + * Defines the priority used by the idle task. This must not be modified. + * + * \ingroup TaskUtils + */ +#define tskIDLE_PRIORITY ( ( UBaseType_t ) 0U ) + +/** + * task. h + * + * Macro for forcing a context switch. + * + * \defgroup taskYIELD taskYIELD + * \ingroup SchedulerControl + */ +#define taskYIELD() portYIELD() + +/** + * task. h + * + * Macro to mark the start of a critical code region. Preemptive context + * switches cannot occur when in a critical region. + * + * NOTE: This may alter the stack (depending on the portable implementation) + * so must be used with care! + * + * \defgroup taskENTER_CRITICAL taskENTER_CRITICAL + * \ingroup SchedulerControl + */ +#define taskENTER_CRITICAL(mux) portENTER_CRITICAL(mux) +#define taskENTER_CRITICAL_ISR(mux) portENTER_CRITICAL_ISR(mux) + +/** + * task. h + * + * Macro to mark the end of a critical code region. Preemptive context + * switches cannot occur when in a critical region. + * + * NOTE: This may alter the stack (depending on the portable implementation) + * so must be used with care! + * + * \defgroup taskEXIT_CRITICAL taskEXIT_CRITICAL + * \ingroup SchedulerControl + */ +#define taskEXIT_CRITICAL(mux) portEXIT_CRITICAL(mux) +#define taskEXIT_CRITICAL_ISR(mux) portEXIT_CRITICAL_ISR(mux) + +/** + * task. h + * + * Macro to disable all maskable interrupts. + * + * \defgroup taskDISABLE_INTERRUPTS taskDISABLE_INTERRUPTS + * \ingroup SchedulerControl + */ +#define taskDISABLE_INTERRUPTS() portDISABLE_INTERRUPTS() + +/** + * task. h + * + * Macro to enable microcontroller interrupts. + * + * \defgroup taskENABLE_INTERRUPTS taskENABLE_INTERRUPTS + * \ingroup SchedulerControl + */ +#define taskENABLE_INTERRUPTS() portENABLE_INTERRUPTS() + +/* Definitions returned by xTaskGetSchedulerState(). taskSCHEDULER_SUSPENDED is +0 to generate more optimal code when configASSERT() is defined as the constant +is used in assert() statements. */ +#define taskSCHEDULER_SUSPENDED ( ( BaseType_t ) 0 ) +#define taskSCHEDULER_NOT_STARTED ( ( BaseType_t ) 1 ) +#define taskSCHEDULER_RUNNING ( ( BaseType_t ) 2 ) + + +/*----------------------------------------------------------- + * TASK CREATION API + *----------------------------------------------------------*/ + +/** + * task. h + *
+ BaseType_t xTaskCreate(
+							  TaskFunction_t pvTaskCode,
+							  const char * const pcName,
+							  uint16_t usStackDepth,
+							  void *pvParameters,
+							  UBaseType_t uxPriority,
+							  TaskHandle_t *pvCreatedTask
+						  );
+ * + * Create a new task and add it to the list of tasks that are ready to run. + * On multicore environments, this will give no specific affinity to the task. + * Use xTaskCreatePinnedToCore to give affinity. + * + * xTaskCreate() can only be used to create a task that has unrestricted + * access to the entire microcontroller memory map. Systems that include MPU + * support can alternatively create an MPU constrained task using + * xTaskCreateRestricted(). + * + * @param pvTaskCode Pointer to the task entry function. Tasks + * must be implemented to never return (i.e. continuous loop). + * + * @param pcName A descriptive name for the task. This is mainly used to + * facilitate debugging. Max length defined by configMAX_TASK_NAME_LEN - default + * is 16. + * + * @param usStackDepth The size of the task stack specified as the number of + * variables the stack can hold - not the number of bytes. For example, if + * the stack is 16 bits wide and usStackDepth is defined as 100, 200 bytes + * will be allocated for stack storage. + * + * @param pvParameters Pointer that will be used as the parameter for the task + * being created. + * + * @param uxPriority The priority at which the task should run. Systems that + * include MPU support can optionally create tasks in a privileged (system) + * mode by setting bit portPRIVILEGE_BIT of the priority parameter. For + * example, to create a privileged task at priority 2 the uxPriority parameter + * should be set to ( 2 | portPRIVILEGE_BIT ). + * + * @param pvCreatedTask Used to pass back a handle by which the created task + * can be referenced. + * + * @return pdPASS if the task was successfully created and added to a ready + * list, otherwise an error code defined in the file projdefs.h + * + * Example usage: +
+ // Task to be created.
+ void vTaskCode( void * pvParameters )
+ {
+	 for( ;; )
+	 {
+		 // Task code goes here.
+	 }
+ }
+
+ // Function that creates a task.
+ void vOtherFunction( void )
+ {
+ static uint8_t ucParameterToPass;
+ TaskHandle_t xHandle = NULL;
+
+	 // Create the task, storing the handle.  Note that the passed parameter ucParameterToPass
+	 // must exist for the lifetime of the task, so in this case is declared static.  If it was just an
+	 // an automatic stack variable it might no longer exist, or at least have been corrupted, by the time
+	 // the new task attempts to access it.
+	 xTaskCreate( vTaskCode, "NAME", STACK_SIZE, &ucParameterToPass, tskIDLE_PRIORITY, &xHandle );
+     configASSERT( xHandle );
+
+	 // Use the handle to delete the task.
+     if( xHandle != NULL )
+     {
+	     vTaskDelete( xHandle );
+     }
+ }
+   
+ * \defgroup xTaskCreate xTaskCreate + * \ingroup Tasks + */ +#define xTaskCreate( pvTaskCode, pcName, usStackDepth, pvParameters, uxPriority, pxCreatedTask ) xTaskGenericCreate( ( pvTaskCode ), ( pcName ), ( usStackDepth ), ( pvParameters ), ( uxPriority ), ( pxCreatedTask ), ( NULL ), ( NULL ), tskNO_AFFINITY ) +#define xTaskCreatePinnedToCore( pvTaskCode, pcName, usStackDepth, pvParameters, uxPriority, pxCreatedTask, xCoreID ) xTaskGenericCreate( ( pvTaskCode ), ( pcName ), ( usStackDepth ), ( pvParameters ), ( uxPriority ), ( pxCreatedTask ), ( NULL ), ( NULL ), xCoreID ) + +/** + * task. h + *
+ BaseType_t xTaskCreateRestricted( TaskParameters_t *pxTaskDefinition, TaskHandle_t *pxCreatedTask );
+ * + * xTaskCreateRestricted() should only be used in systems that include an MPU + * implementation. + * + * Create a new task and add it to the list of tasks that are ready to run. + * The function parameters define the memory regions and associated access + * permissions allocated to the task. + * + * @param pxTaskDefinition Pointer to a structure that contains a member + * for each of the normal xTaskCreate() parameters (see the xTaskCreate() API + * documentation) plus an optional stack buffer and the memory region + * definitions. + * + * @param pxCreatedTask Used to pass back a handle by which the created task + * can be referenced. + * + * @return pdPASS if the task was successfully created and added to a ready + * list, otherwise an error code defined in the file projdefs.h + * + * Example usage: +
+// Create an TaskParameters_t structure that defines the task to be created.
+static const TaskParameters_t xCheckTaskParameters =
+{
+	vATask,		// pvTaskCode - the function that implements the task.
+	"ATask",	// pcName - just a text name for the task to assist debugging.
+	100,		// usStackDepth	- the stack size DEFINED IN WORDS.
+	NULL,		// pvParameters - passed into the task function as the function parameters.
+	( 1UL | portPRIVILEGE_BIT ),// uxPriority - task priority, set the portPRIVILEGE_BIT if the task should run in a privileged state.
+	cStackBuffer,// puxStackBuffer - the buffer to be used as the task stack.
+
+	// xRegions - Allocate up to three separate memory regions for access by
+	// the task, with appropriate access permissions.  Different processors have
+	// different memory alignment requirements - refer to the FreeRTOS documentation
+	// for full information.
+	{
+		// Base address					Length	Parameters
+        { cReadWriteArray,				32,		portMPU_REGION_READ_WRITE },
+        { cReadOnlyArray,				32,		portMPU_REGION_READ_ONLY },
+        { cPrivilegedOnlyAccessArray,	128,	portMPU_REGION_PRIVILEGED_READ_WRITE }
+	}
+};
+
+int main( void )
+{
+TaskHandle_t xHandle;
+
+	// Create a task from the const structure defined above.  The task handle
+	// is requested (the second parameter is not NULL) but in this case just for
+	// demonstration purposes as its not actually used.
+	xTaskCreateRestricted( &xRegTest1Parameters, &xHandle );
+
+	// Start the scheduler.
+	vTaskStartScheduler();
+
+	// Will only get here if there was insufficient memory to create the idle
+	// and/or timer task.
+	for( ;; );
+}
+   
+ * \defgroup xTaskCreateRestricted xTaskCreateRestricted + * \ingroup Tasks + */ +#define xTaskCreateRestricted( x, pxCreatedTask ) xTaskGenericCreate( ((x)->pvTaskCode), ((x)->pcName), ((x)->usStackDepth), ((x)->pvParameters), ((x)->uxPriority), (pxCreatedTask), ((x)->puxStackBuffer), ((x)->xRegions) ) + +/** + * task. h + *
+ void vTaskAllocateMPURegions( TaskHandle_t xTask, const MemoryRegion_t * const pxRegions );
+ * + * Memory regions are assigned to a restricted task when the task is created by + * a call to xTaskCreateRestricted(). These regions can be redefined using + * vTaskAllocateMPURegions(). + * + * @param xTask The handle of the task being updated. + * + * @param xRegions A pointer to an MemoryRegion_t structure that contains the + * new memory region definitions. + * + * Example usage: +
+// Define an array of MemoryRegion_t structures that configures an MPU region
+// allowing read/write access for 1024 bytes starting at the beginning of the
+// ucOneKByte array.  The other two of the maximum 3 definable regions are
+// unused so set to zero.
+static const MemoryRegion_t xAltRegions[ portNUM_CONFIGURABLE_REGIONS ] =
+{
+	// Base address		Length		Parameters
+	{ ucOneKByte,		1024,		portMPU_REGION_READ_WRITE },
+	{ 0,				0,			0 },
+	{ 0,				0,			0 }
+};
+
+void vATask( void *pvParameters )
+{
+	// This task was created such that it has access to certain regions of
+	// memory as defined by the MPU configuration.  At some point it is
+	// desired that these MPU regions are replaced with that defined in the
+	// xAltRegions const struct above.  Use a call to vTaskAllocateMPURegions()
+	// for this purpose.  NULL is used as the task handle to indicate that this
+	// function should modify the MPU regions of the calling task.
+	vTaskAllocateMPURegions( NULL, xAltRegions );
+
+	// Now the task can continue its function, but from this point on can only
+	// access its stack and the ucOneKByte array (unless any other statically
+	// defined or shared regions have been declared elsewhere).
+}
+   
+ * \defgroup xTaskCreateRestricted xTaskCreateRestricted + * \ingroup Tasks + */ +void vTaskAllocateMPURegions( TaskHandle_t xTask, const MemoryRegion_t * const pxRegions ) PRIVILEGED_FUNCTION; + +/** + * task. h + *
void vTaskDelete( TaskHandle_t xTask );
+ * + * INCLUDE_vTaskDelete must be defined as 1 for this function to be available. + * See the configuration section for more information. + * + * Remove a task from the RTOS real time kernel's management. The task being + * deleted will be removed from all ready, blocked, suspended and event lists. + * + * NOTE: The idle task is responsible for freeing the kernel allocated + * memory from tasks that have been deleted. It is therefore important that + * the idle task is not starved of microcontroller processing time if your + * application makes any calls to vTaskDelete (). Memory allocated by the + * task code is not automatically freed, and should be freed before the task + * is deleted. + * + * See the demo application file death.c for sample code that utilises + * vTaskDelete (). + * + * @param xTask The handle of the task to be deleted. Passing NULL will + * cause the calling task to be deleted. + * + * Example usage: +
+ void vOtherFunction( void )
+ {
+ TaskHandle_t xHandle;
+
+	 // Create the task, storing the handle.
+	 xTaskCreate( vTaskCode, "NAME", STACK_SIZE, NULL, tskIDLE_PRIORITY, &xHandle );
+
+	 // Use the handle to delete the task.
+	 vTaskDelete( xHandle );
+ }
+   
+ * \defgroup vTaskDelete vTaskDelete + * \ingroup Tasks + */ +void vTaskDelete( TaskHandle_t xTaskToDelete ) PRIVILEGED_FUNCTION; + +/*----------------------------------------------------------- + * TASK CONTROL API + *----------------------------------------------------------*/ + +/** + * task. h + *
void vTaskDelay( const TickType_t xTicksToDelay );
+ * + * Delay a task for a given number of ticks. The actual time that the + * task remains blocked depends on the tick rate. The constant + * portTICK_PERIOD_MS can be used to calculate real time from the tick + * rate - with the resolution of one tick period. + * + * INCLUDE_vTaskDelay must be defined as 1 for this function to be available. + * See the configuration section for more information. + * + * + * vTaskDelay() specifies a time at which the task wishes to unblock relative to + * the time at which vTaskDelay() is called. For example, specifying a block + * period of 100 ticks will cause the task to unblock 100 ticks after + * vTaskDelay() is called. vTaskDelay() does not therefore provide a good method + * of controlling the frequency of a periodic task as the path taken through the + * code, as well as other task and interrupt activity, will effect the frequency + * at which vTaskDelay() gets called and therefore the time at which the task + * next executes. See vTaskDelayUntil() for an alternative API function designed + * to facilitate fixed frequency execution. It does this by specifying an + * absolute time (rather than a relative time) at which the calling task should + * unblock. + * + * @param xTicksToDelay The amount of time, in tick periods, that + * the calling task should block. + * + * Example usage: + + void vTaskFunction( void * pvParameters ) + { + // Block for 500ms. + const TickType_t xDelay = 500 / portTICK_PERIOD_MS; + + for( ;; ) + { + // Simply toggle the LED every 500ms, blocking between each toggle. + vToggleLED(); + vTaskDelay( xDelay ); + } + } + + * \defgroup vTaskDelay vTaskDelay + * \ingroup TaskCtrl + */ +void vTaskDelay( const TickType_t xTicksToDelay ) PRIVILEGED_FUNCTION; + +/** + * task. h + *
void vTaskDelayUntil( TickType_t *pxPreviousWakeTime, const TickType_t xTimeIncrement );
+ * + * INCLUDE_vTaskDelayUntil must be defined as 1 for this function to be available. + * See the configuration section for more information. + * + * Delay a task until a specified time. This function can be used by periodic + * tasks to ensure a constant execution frequency. + * + * This function differs from vTaskDelay () in one important aspect: vTaskDelay () will + * cause a task to block for the specified number of ticks from the time vTaskDelay () is + * called. It is therefore difficult to use vTaskDelay () by itself to generate a fixed + * execution frequency as the time between a task starting to execute and that task + * calling vTaskDelay () may not be fixed [the task may take a different path though the + * code between calls, or may get interrupted or preempted a different number of times + * each time it executes]. + * + * Whereas vTaskDelay () specifies a wake time relative to the time at which the function + * is called, vTaskDelayUntil () specifies the absolute (exact) time at which it wishes to + * unblock. + * + * The constant portTICK_PERIOD_MS can be used to calculate real time from the tick + * rate - with the resolution of one tick period. + * + * @param pxPreviousWakeTime Pointer to a variable that holds the time at which the + * task was last unblocked. The variable must be initialised with the current time + * prior to its first use (see the example below). Following this the variable is + * automatically updated within vTaskDelayUntil (). + * + * @param xTimeIncrement The cycle time period. The task will be unblocked at + * time *pxPreviousWakeTime + xTimeIncrement. Calling vTaskDelayUntil with the + * same xTimeIncrement parameter value will cause the task to execute with + * a fixed interface period. + * + * Example usage: +
+ // Perform an action every 10 ticks.
+ void vTaskFunction( void * pvParameters )
+ {
+ TickType_t xLastWakeTime;
+ const TickType_t xFrequency = 10;
+
+	 // Initialise the xLastWakeTime variable with the current time.
+	 xLastWakeTime = xTaskGetTickCount ();
+	 for( ;; )
+	 {
+		 // Wait for the next cycle.
+		 vTaskDelayUntil( &xLastWakeTime, xFrequency );
+
+		 // Perform action here.
+	 }
+ }
+   
+ * \defgroup vTaskDelayUntil vTaskDelayUntil + * \ingroup TaskCtrl + */ +void vTaskDelayUntil( TickType_t * const pxPreviousWakeTime, const TickType_t xTimeIncrement ) PRIVILEGED_FUNCTION; + +/** + * task. h + *
UBaseType_t uxTaskPriorityGet( TaskHandle_t xTask );
+ * + * INCLUDE_uxTaskPriorityGet must be defined as 1 for this function to be available. + * See the configuration section for more information. + * + * Obtain the priority of any task. + * + * @param xTask Handle of the task to be queried. Passing a NULL + * handle results in the priority of the calling task being returned. + * + * @return The priority of xTask. + * + * Example usage: +
+ void vAFunction( void )
+ {
+ TaskHandle_t xHandle;
+
+	 // Create a task, storing the handle.
+	 xTaskCreate( vTaskCode, "NAME", STACK_SIZE, NULL, tskIDLE_PRIORITY, &xHandle );
+
+	 // ...
+
+	 // Use the handle to obtain the priority of the created task.
+	 // It was created with tskIDLE_PRIORITY, but may have changed
+	 // it itself.
+	 if( uxTaskPriorityGet( xHandle ) != tskIDLE_PRIORITY )
+	 {
+		 // The task has changed it's priority.
+	 }
+
+	 // ...
+
+	 // Is our priority higher than the created task?
+	 if( uxTaskPriorityGet( xHandle ) < uxTaskPriorityGet( NULL ) )
+	 {
+		 // Our priority (obtained using NULL handle) is higher.
+	 }
+ }
+   
+ * \defgroup uxTaskPriorityGet uxTaskPriorityGet + * \ingroup TaskCtrl + */ +UBaseType_t uxTaskPriorityGet( TaskHandle_t xTask ) PRIVILEGED_FUNCTION; + +/** + * task. h + *
UBaseType_t uxTaskPriorityGetFromISR( TaskHandle_t xTask );
+ * + * A version of uxTaskPriorityGet() that can be used from an ISR. + */ +UBaseType_t uxTaskPriorityGetFromISR( TaskHandle_t xTask ) PRIVILEGED_FUNCTION; + +/** + * task. h + *
eTaskState eTaskGetState( TaskHandle_t xTask );
+ * + * INCLUDE_eTaskGetState must be defined as 1 for this function to be available. + * See the configuration section for more information. + * + * Obtain the state of any task. States are encoded by the eTaskState + * enumerated type. + * + * @param xTask Handle of the task to be queried. + * + * @return The state of xTask at the time the function was called. Note the + * state of the task might change between the function being called, and the + * functions return value being tested by the calling task. + */ +eTaskState eTaskGetState( TaskHandle_t xTask ) PRIVILEGED_FUNCTION; + +/** + * task. h + *
void vTaskPrioritySet( TaskHandle_t xTask, UBaseType_t uxNewPriority );
+ * + * INCLUDE_vTaskPrioritySet must be defined as 1 for this function to be available. + * See the configuration section for more information. + * + * Set the priority of any task. + * + * A context switch will occur before the function returns if the priority + * being set is higher than the currently executing task. + * + * @param xTask Handle to the task for which the priority is being set. + * Passing a NULL handle results in the priority of the calling task being set. + * + * @param uxNewPriority The priority to which the task will be set. + * + * Example usage: +
+ void vAFunction( void )
+ {
+ TaskHandle_t xHandle;
+
+	 // Create a task, storing the handle.
+	 xTaskCreate( vTaskCode, "NAME", STACK_SIZE, NULL, tskIDLE_PRIORITY, &xHandle );
+
+	 // ...
+
+	 // Use the handle to raise the priority of the created task.
+	 vTaskPrioritySet( xHandle, tskIDLE_PRIORITY + 1 );
+
+	 // ...
+
+	 // Use a NULL handle to raise our priority to the same value.
+	 vTaskPrioritySet( NULL, tskIDLE_PRIORITY + 1 );
+ }
+   
+ * \defgroup vTaskPrioritySet vTaskPrioritySet + * \ingroup TaskCtrl + */ +void vTaskPrioritySet( TaskHandle_t xTask, UBaseType_t uxNewPriority ) PRIVILEGED_FUNCTION; + +/** + * task. h + *
void vTaskSuspend( TaskHandle_t xTaskToSuspend );
+ * + * INCLUDE_vTaskSuspend must be defined as 1 for this function to be available. + * See the configuration section for more information. + * + * Suspend any task. When suspended a task will never get any microcontroller + * processing time, no matter what its priority. + * + * Calls to vTaskSuspend are not accumulative - + * i.e. calling vTaskSuspend () twice on the same task still only requires one + * call to vTaskResume () to ready the suspended task. + * + * @param xTaskToSuspend Handle to the task being suspended. Passing a NULL + * handle will cause the calling task to be suspended. + * + * Example usage: +
+ void vAFunction( void )
+ {
+ TaskHandle_t xHandle;
+
+	 // Create a task, storing the handle.
+	 xTaskCreate( vTaskCode, "NAME", STACK_SIZE, NULL, tskIDLE_PRIORITY, &xHandle );
+
+	 // ...
+
+	 // Use the handle to suspend the created task.
+	 vTaskSuspend( xHandle );
+
+	 // ...
+
+	 // The created task will not run during this period, unless
+	 // another task calls vTaskResume( xHandle ).
+
+	 //...
+
+
+	 // Suspend ourselves.
+	 vTaskSuspend( NULL );
+
+	 // We cannot get here unless another task calls vTaskResume
+	 // with our handle as the parameter.
+ }
+   
+ * \defgroup vTaskSuspend vTaskSuspend + * \ingroup TaskCtrl + */ +void vTaskSuspend( TaskHandle_t xTaskToSuspend ) PRIVILEGED_FUNCTION; + +/** + * task. h + *
void vTaskResume( TaskHandle_t xTaskToResume );
+ * + * INCLUDE_vTaskSuspend must be defined as 1 for this function to be available. + * See the configuration section for more information. + * + * Resumes a suspended task. + * + * A task that has been suspended by one or more calls to vTaskSuspend () + * will be made available for running again by a single call to + * vTaskResume (). + * + * @param xTaskToResume Handle to the task being readied. + * + * Example usage: +
+ void vAFunction( void )
+ {
+ TaskHandle_t xHandle;
+
+	 // Create a task, storing the handle.
+	 xTaskCreate( vTaskCode, "NAME", STACK_SIZE, NULL, tskIDLE_PRIORITY, &xHandle );
+
+	 // ...
+
+	 // Use the handle to suspend the created task.
+	 vTaskSuspend( xHandle );
+
+	 // ...
+
+	 // The created task will not run during this period, unless
+	 // another task calls vTaskResume( xHandle ).
+
+	 //...
+
+
+	 // Resume the suspended task ourselves.
+	 vTaskResume( xHandle );
+
+	 // The created task will once again get microcontroller processing
+	 // time in accordance with its priority within the system.
+ }
+   
+ * \defgroup vTaskResume vTaskResume + * \ingroup TaskCtrl + */ +void vTaskResume( TaskHandle_t xTaskToResume ) PRIVILEGED_FUNCTION; + +/** + * task. h + *
void xTaskResumeFromISR( TaskHandle_t xTaskToResume );
+ * + * INCLUDE_xTaskResumeFromISR must be defined as 1 for this function to be + * available. See the configuration section for more information. + * + * An implementation of vTaskResume() that can be called from within an ISR. + * + * A task that has been suspended by one or more calls to vTaskSuspend () + * will be made available for running again by a single call to + * xTaskResumeFromISR (). + * + * xTaskResumeFromISR() should not be used to synchronise a task with an + * interrupt if there is a chance that the interrupt could arrive prior to the + * task being suspended - as this can lead to interrupts being missed. Use of a + * semaphore as a synchronisation mechanism would avoid this eventuality. + * + * @param xTaskToResume Handle to the task being readied. + * + * @return pdTRUE if resuming the task should result in a context switch, + * otherwise pdFALSE. This is used by the ISR to determine if a context switch + * may be required following the ISR. + * + * \defgroup vTaskResumeFromISR vTaskResumeFromISR + * \ingroup TaskCtrl + */ +BaseType_t xTaskResumeFromISR( TaskHandle_t xTaskToResume ) PRIVILEGED_FUNCTION; + +/*----------------------------------------------------------- + * SCHEDULER CONTROL + *----------------------------------------------------------*/ + +/** + * task. h + *
void vTaskStartScheduler( void );
+ * + * Starts the real time kernel tick processing. After calling the kernel + * has control over which tasks are executed and when. + * + * See the demo application file main.c for an example of creating + * tasks and starting the kernel. + * + * Example usage: +
+ void vAFunction( void )
+ {
+	 // Create at least one task before starting the kernel.
+	 xTaskCreate( vTaskCode, "NAME", STACK_SIZE, NULL, tskIDLE_PRIORITY, NULL );
+
+	 // Start the real time kernel with preemption.
+	 vTaskStartScheduler ();
+
+	 // Will not get here unless a task calls vTaskEndScheduler ()
+ }
+   
+ * + * \defgroup vTaskStartScheduler vTaskStartScheduler + * \ingroup SchedulerControl + */ +void vTaskStartScheduler( void ) PRIVILEGED_FUNCTION; + +/** + * task. h + *
void vTaskEndScheduler( void );
+ * + * NOTE: At the time of writing only the x86 real mode port, which runs on a PC + * in place of DOS, implements this function. + * + * Stops the real time kernel tick. All created tasks will be automatically + * deleted and multitasking (either preemptive or cooperative) will + * stop. Execution then resumes from the point where vTaskStartScheduler () + * was called, as if vTaskStartScheduler () had just returned. + * + * See the demo application file main. c in the demo/PC directory for an + * example that uses vTaskEndScheduler (). + * + * vTaskEndScheduler () requires an exit function to be defined within the + * portable layer (see vPortEndScheduler () in port. c for the PC port). This + * performs hardware specific operations such as stopping the kernel tick. + * + * vTaskEndScheduler () will cause all of the resources allocated by the + * kernel to be freed - but will not free resources allocated by application + * tasks. + * + * Example usage: +
+ void vTaskCode( void * pvParameters )
+ {
+	 for( ;; )
+	 {
+		 // Task code goes here.
+
+		 // At some point we want to end the real time kernel processing
+		 // so call ...
+		 vTaskEndScheduler ();
+	 }
+ }
+
+ void vAFunction( void )
+ {
+	 // Create at least one task before starting the kernel.
+	 xTaskCreate( vTaskCode, "NAME", STACK_SIZE, NULL, tskIDLE_PRIORITY, NULL );
+
+	 // Start the real time kernel with preemption.
+	 vTaskStartScheduler ();
+
+	 // Will only get here when the vTaskCode () task has called
+	 // vTaskEndScheduler ().  When we get here we are back to single task
+	 // execution.
+ }
+   
+ * + * \defgroup vTaskEndScheduler vTaskEndScheduler + * \ingroup SchedulerControl + */ +void vTaskEndScheduler( void ) PRIVILEGED_FUNCTION; + +/** + * task. h + *
void vTaskSuspendAll( void );
+ * + * Suspends the scheduler without disabling interrupts. Context switches will + * not occur while the scheduler is suspended. + * + * After calling vTaskSuspendAll () the calling task will continue to execute + * without risk of being swapped out until a call to xTaskResumeAll () has been + * made. + * + * API functions that have the potential to cause a context switch (for example, + * vTaskDelayUntil(), xQueueSend(), etc.) must not be called while the scheduler + * is suspended. + * + * Example usage: +
+ void vTask1( void * pvParameters )
+ {
+	 for( ;; )
+	 {
+		 // Task code goes here.
+
+		 // ...
+
+		 // At some point the task wants to perform a long operation during
+		 // which it does not want to get swapped out.  It cannot use
+		 // taskENTER_CRITICAL ()/taskEXIT_CRITICAL () as the length of the
+		 // operation may cause interrupts to be missed - including the
+		 // ticks.
+
+		 // Prevent the real time kernel swapping out the task.
+		 vTaskSuspendAll ();
+
+		 // Perform the operation here.  There is no need to use critical
+		 // sections as we have all the microcontroller processing time.
+		 // During this time interrupts will still operate and the kernel
+		 // tick count will be maintained.
+
+		 // ...
+
+		 // The operation is complete.  Restart the kernel.
+		 xTaskResumeAll ();
+	 }
+ }
+   
+ * \defgroup vTaskSuspendAll vTaskSuspendAll + * \ingroup SchedulerControl + */ +void vTaskSuspendAll( void ) PRIVILEGED_FUNCTION; + +/** + * task. h + *
BaseType_t xTaskResumeAll( void );
+ * + * Resumes scheduler activity after it was suspended by a call to + * vTaskSuspendAll(). + * + * xTaskResumeAll() only resumes the scheduler. It does not unsuspend tasks + * that were previously suspended by a call to vTaskSuspend(). + * + * @return If resuming the scheduler caused a context switch then pdTRUE is + * returned, otherwise pdFALSE is returned. + * + * Example usage: +
+ void vTask1( void * pvParameters )
+ {
+	 for( ;; )
+	 {
+		 // Task code goes here.
+
+		 // ...
+
+		 // At some point the task wants to perform a long operation during
+		 // which it does not want to get swapped out.  It cannot use
+		 // taskENTER_CRITICAL ()/taskEXIT_CRITICAL () as the length of the
+		 // operation may cause interrupts to be missed - including the
+		 // ticks.
+
+		 // Prevent the real time kernel swapping out the task.
+		 vTaskSuspendAll ();
+
+		 // Perform the operation here.  There is no need to use critical
+		 // sections as we have all the microcontroller processing time.
+		 // During this time interrupts will still operate and the real
+		 // time kernel tick count will be maintained.
+
+		 // ...
+
+		 // The operation is complete.  Restart the kernel.  We want to force
+		 // a context switch - but there is no point if resuming the scheduler
+		 // caused a context switch already.
+		 if( !xTaskResumeAll () )
+		 {
+			  taskYIELD ();
+		 }
+	 }
+ }
+   
+ * \defgroup xTaskResumeAll xTaskResumeAll + * \ingroup SchedulerControl + */ +BaseType_t xTaskResumeAll( void ) PRIVILEGED_FUNCTION; + +/*----------------------------------------------------------- + * TASK UTILITIES + *----------------------------------------------------------*/ + +/** + * task. h + *
TickType_t xTaskGetTickCount( void );
+ * + * @return The count of ticks since vTaskStartScheduler was called. + * + * \defgroup xTaskGetTickCount xTaskGetTickCount + * \ingroup TaskUtils + */ +TickType_t xTaskGetTickCount( void ) PRIVILEGED_FUNCTION; + +/** + * task. h + *
TickType_t xTaskGetTickCountFromISR( void );
+ * + * @return The count of ticks since vTaskStartScheduler was called. + * + * This is a version of xTaskGetTickCount() that is safe to be called from an + * ISR - provided that TickType_t is the natural word size of the + * microcontroller being used or interrupt nesting is either not supported or + * not being used. + * + * \defgroup xTaskGetTickCountFromISR xTaskGetTickCountFromISR + * \ingroup TaskUtils + */ +TickType_t xTaskGetTickCountFromISR( void ) PRIVILEGED_FUNCTION; + +/** + * task. h + *
uint16_t uxTaskGetNumberOfTasks( void );
+ * + * @return The number of tasks that the real time kernel is currently managing. + * This includes all ready, blocked and suspended tasks. A task that + * has been deleted but not yet freed by the idle task will also be + * included in the count. + * + * \defgroup uxTaskGetNumberOfTasks uxTaskGetNumberOfTasks + * \ingroup TaskUtils + */ +UBaseType_t uxTaskGetNumberOfTasks( void ) PRIVILEGED_FUNCTION; + +/** + * task. h + *
char *pcTaskGetTaskName( TaskHandle_t xTaskToQuery );
+ * + * @return The text (human readable) name of the task referenced by the handle + * xTaskToQuery. A task can query its own name by either passing in its own + * handle, or by setting xTaskToQuery to NULL. INCLUDE_pcTaskGetTaskName must be + * set to 1 in FreeRTOSConfig.h for pcTaskGetTaskName() to be available. + * + * \defgroup pcTaskGetTaskName pcTaskGetTaskName + * \ingroup TaskUtils + */ +char *pcTaskGetTaskName( TaskHandle_t xTaskToQuery ) PRIVILEGED_FUNCTION; /*lint !e971 Unqualified char types are allowed for strings and single characters only. */ + +/** + * task.h + *
UBaseType_t uxTaskGetStackHighWaterMark( TaskHandle_t xTask );
+ * + * INCLUDE_uxTaskGetStackHighWaterMark must be set to 1 in FreeRTOSConfig.h for + * this function to be available. + * + * Returns the high water mark of the stack associated with xTask. That is, + * the minimum free stack space there has been (in words, so on a 32 bit machine + * a value of 1 means 4 bytes) since the task started. The smaller the returned + * number the closer the task has come to overflowing its stack. + * + * @param xTask Handle of the task associated with the stack to be checked. + * Set xTask to NULL to check the stack of the calling task. + * + * @return The smallest amount of free stack space there has been (in words, so + * actual spaces on the stack rather than bytes) since the task referenced by + * xTask was created. + */ +UBaseType_t uxTaskGetStackHighWaterMark( TaskHandle_t xTask ) PRIVILEGED_FUNCTION; + +/* When using trace macros it is sometimes necessary to include task.h before +FreeRTOS.h. When this is done TaskHookFunction_t will not yet have been defined, +so the following two prototypes will cause a compilation error. This can be +fixed by simply guarding against the inclusion of these two prototypes unless +they are explicitly required by the configUSE_APPLICATION_TASK_TAG configuration +constant. */ +#ifdef configUSE_APPLICATION_TASK_TAG + #if configUSE_APPLICATION_TASK_TAG == 1 + /** + * task.h + *
void vTaskSetApplicationTaskTag( TaskHandle_t xTask, TaskHookFunction_t pxHookFunction );
+ * + * Sets pxHookFunction to be the task hook function used by the task xTask. + * Passing xTask as NULL has the effect of setting the calling tasks hook + * function. + */ + void vTaskSetApplicationTaskTag( TaskHandle_t xTask, TaskHookFunction_t pxHookFunction ) PRIVILEGED_FUNCTION; + + /** + * task.h + *
void xTaskGetApplicationTaskTag( TaskHandle_t xTask );
+ * + * Returns the pxHookFunction value assigned to the task xTask. + */ + TaskHookFunction_t xTaskGetApplicationTaskTag( TaskHandle_t xTask ) PRIVILEGED_FUNCTION; + #endif /* configUSE_APPLICATION_TASK_TAG ==1 */ +#endif /* ifdef configUSE_APPLICATION_TASK_TAG */ +#if( configNUM_THREAD_LOCAL_STORAGE_POINTERS > 0 ) + + /* Each task contains an array of pointers that is dimensioned by the + configNUM_THREAD_LOCAL_STORAGE_POINTERS setting in FreeRTOSConfig.h. The + kernel does not use the pointers itself, so the application writer can use + the pointers for any purpose they wish. The following two functions are + used to set and query a pointer respectively. */ + void vTaskSetThreadLocalStoragePointer( TaskHandle_t xTaskToSet, BaseType_t xIndex, void *pvValue ) PRIVILEGED_FUNCTION; + void *pvTaskGetThreadLocalStoragePointer( TaskHandle_t xTaskToQuery, BaseType_t xIndex ) PRIVILEGED_FUNCTION; + +#endif + +/** + * task.h + *
BaseType_t xTaskCallApplicationTaskHook( TaskHandle_t xTask, void *pvParameter );
+ * + * Calls the hook function associated with xTask. Passing xTask as NULL has + * the effect of calling the Running tasks (the calling task) hook function. + * + * pvParameter is passed to the hook function for the task to interpret as it + * wants. The return value is the value returned by the task hook function + * registered by the user. + */ +BaseType_t xTaskCallApplicationTaskHook( TaskHandle_t xTask, void *pvParameter ) PRIVILEGED_FUNCTION; + +/** + * xTaskGetIdleTaskHandle() is only available if + * INCLUDE_xTaskGetIdleTaskHandle is set to 1 in FreeRTOSConfig.h. + * + * Simply returns the handle of the idle task. It is not valid to call + * xTaskGetIdleTaskHandle() before the scheduler has been started. + */ +TaskHandle_t xTaskGetIdleTaskHandle( void ); + +/** + * configUSE_TRACE_FACILITY must be defined as 1 in FreeRTOSConfig.h for + * uxTaskGetSystemState() to be available. + * + * uxTaskGetSystemState() populates an TaskStatus_t structure for each task in + * the system. TaskStatus_t structures contain, among other things, members + * for the task handle, task name, task priority, task state, and total amount + * of run time consumed by the task. See the TaskStatus_t structure + * definition in this file for the full member list. + * + * NOTE: This function is intended for debugging use only as its use results in + * the scheduler remaining suspended for an extended period. + * + * @param pxTaskStatusArray A pointer to an array of TaskStatus_t structures. + * The array must contain at least one TaskStatus_t structure for each task + * that is under the control of the RTOS. The number of tasks under the control + * of the RTOS can be determined using the uxTaskGetNumberOfTasks() API function. + * + * @param uxArraySize The size of the array pointed to by the pxTaskStatusArray + * parameter. The size is specified as the number of indexes in the array, or + * the number of TaskStatus_t structures contained in the array, not by the + * number of bytes in the array. + * + * @param pulTotalRunTime If configGENERATE_RUN_TIME_STATS is set to 1 in + * FreeRTOSConfig.h then *pulTotalRunTime is set by uxTaskGetSystemState() to the + * total run time (as defined by the run time stats clock, see + * http://www.freertos.org/rtos-run-time-stats.html) since the target booted. + * pulTotalRunTime can be set to NULL to omit the total run time information. + * + * @return The number of TaskStatus_t structures that were populated by + * uxTaskGetSystemState(). This should equal the number returned by the + * uxTaskGetNumberOfTasks() API function, but will be zero if the value passed + * in the uxArraySize parameter was too small. + * + * Example usage: +
+    // This example demonstrates how a human readable table of run time stats
+	// information is generated from raw data provided by uxTaskGetSystemState().
+	// The human readable table is written to pcWriteBuffer
+	void vTaskGetRunTimeStats( char *pcWriteBuffer )
+	{
+	TaskStatus_t *pxTaskStatusArray;
+	volatile UBaseType_t uxArraySize, x;
+	uint32_t ulTotalRunTime, ulStatsAsPercentage;
+
+		// Make sure the write buffer does not contain a string.
+		*pcWriteBuffer = 0x00;
+
+		// Take a snapshot of the number of tasks in case it changes while this
+		// function is executing.
+		uxArraySize = uxTaskGetNumberOfTasks();
+
+		// Allocate a TaskStatus_t structure for each task.  An array could be
+		// allocated statically at compile time.
+		pxTaskStatusArray = pvPortMalloc( uxArraySize * sizeof( TaskStatus_t ) );
+
+		if( pxTaskStatusArray != NULL )
+		{
+			// Generate raw status information about each task.
+			uxArraySize = uxTaskGetSystemState( pxTaskStatusArray, uxArraySize, &ulTotalRunTime );
+
+			// For percentage calculations.
+			ulTotalRunTime /= 100UL;
+
+			// Avoid divide by zero errors.
+			if( ulTotalRunTime > 0 )
+			{
+				// For each populated position in the pxTaskStatusArray array,
+				// format the raw data as human readable ASCII data
+				for( x = 0; x < uxArraySize; x++ )
+				{
+					// What percentage of the total run time has the task used?
+					// This will always be rounded down to the nearest integer.
+					// ulTotalRunTimeDiv100 has already been divided by 100.
+					ulStatsAsPercentage = pxTaskStatusArray[ x ].ulRunTimeCounter / ulTotalRunTime;
+
+					if( ulStatsAsPercentage > 0UL )
+					{
+						sprintf( pcWriteBuffer, "%s\t\t%lu\t\t%lu%%\r\n", pxTaskStatusArray[ x ].pcTaskName, pxTaskStatusArray[ x ].ulRunTimeCounter, ulStatsAsPercentage );
+					}
+					else
+					{
+						// If the percentage is zero here then the task has
+						// consumed less than 1% of the total run time.
+						sprintf( pcWriteBuffer, "%s\t\t%lu\t\t<1%%\r\n", pxTaskStatusArray[ x ].pcTaskName, pxTaskStatusArray[ x ].ulRunTimeCounter );
+					}
+
+					pcWriteBuffer += strlen( ( char * ) pcWriteBuffer );
+				}
+			}
+
+			// The array is no longer needed, free the memory it consumes.
+			vPortFree( pxTaskStatusArray );
+		}
+	}
+	
+ */ +UBaseType_t uxTaskGetSystemState( TaskStatus_t * const pxTaskStatusArray, const UBaseType_t uxArraySize, uint32_t * const pulTotalRunTime ); + +/** + * task. h + *
void vTaskList( char *pcWriteBuffer );
+ * + * configUSE_TRACE_FACILITY and configUSE_STATS_FORMATTING_FUNCTIONS must + * both be defined as 1 for this function to be available. See the + * configuration section of the FreeRTOS.org website for more information. + * + * NOTE 1: This function will disable interrupts for its duration. It is + * not intended for normal application runtime use but as a debug aid. + * + * Lists all the current tasks, along with their current state and stack + * usage high water mark. + * + * Tasks are reported as blocked ('B'), ready ('R'), deleted ('D') or + * suspended ('S'). + * + * PLEASE NOTE: + * + * This function is provided for convenience only, and is used by many of the + * demo applications. Do not consider it to be part of the scheduler. + * + * vTaskList() calls uxTaskGetSystemState(), then formats part of the + * uxTaskGetSystemState() output into a human readable table that displays task + * names, states and stack usage. + * + * vTaskList() has a dependency on the sprintf() C library function that might + * bloat the code size, use a lot of stack, and provide different results on + * different platforms. An alternative, tiny, third party, and limited + * functionality implementation of sprintf() is provided in many of the + * FreeRTOS/Demo sub-directories in a file called printf-stdarg.c (note + * printf-stdarg.c does not provide a full snprintf() implementation!). + * + * It is recommended that production systems call uxTaskGetSystemState() + * directly to get access to raw stats data, rather than indirectly through a + * call to vTaskList(). + * + * @param pcWriteBuffer A buffer into which the above mentioned details + * will be written, in ASCII form. This buffer is assumed to be large + * enough to contain the generated report. Approximately 40 bytes per + * task should be sufficient. + * + * \defgroup vTaskList vTaskList + * \ingroup TaskUtils + */ +void vTaskList( char * pcWriteBuffer ) PRIVILEGED_FUNCTION; /*lint !e971 Unqualified char types are allowed for strings and single characters only. */ + +/** + * task. h + *
void vTaskGetRunTimeStats( char *pcWriteBuffer );
+ * + * configGENERATE_RUN_TIME_STATS and configUSE_STATS_FORMATTING_FUNCTIONS + * must both be defined as 1 for this function to be available. The application + * must also then provide definitions for + * portCONFIGURE_TIMER_FOR_RUN_TIME_STATS() and portGET_RUN_TIME_COUNTER_VALUE() + * to configure a peripheral timer/counter and return the timers current count + * value respectively. The counter should be at least 10 times the frequency of + * the tick count. + * + * NOTE 1: This function will disable interrupts for its duration. It is + * not intended for normal application runtime use but as a debug aid. + * + * Setting configGENERATE_RUN_TIME_STATS to 1 will result in a total + * accumulated execution time being stored for each task. The resolution + * of the accumulated time value depends on the frequency of the timer + * configured by the portCONFIGURE_TIMER_FOR_RUN_TIME_STATS() macro. + * Calling vTaskGetRunTimeStats() writes the total execution time of each + * task into a buffer, both as an absolute count value and as a percentage + * of the total system execution time. + * + * NOTE 2: + * + * This function is provided for convenience only, and is used by many of the + * demo applications. Do not consider it to be part of the scheduler. + * + * vTaskGetRunTimeStats() calls uxTaskGetSystemState(), then formats part of the + * uxTaskGetSystemState() output into a human readable table that displays the + * amount of time each task has spent in the Running state in both absolute and + * percentage terms. + * + * vTaskGetRunTimeStats() has a dependency on the sprintf() C library function + * that might bloat the code size, use a lot of stack, and provide different + * results on different platforms. An alternative, tiny, third party, and + * limited functionality implementation of sprintf() is provided in many of the + * FreeRTOS/Demo sub-directories in a file called printf-stdarg.c (note + * printf-stdarg.c does not provide a full snprintf() implementation!). + * + * It is recommended that production systems call uxTaskGetSystemState() directly + * to get access to raw stats data, rather than indirectly through a call to + * vTaskGetRunTimeStats(). + * + * @param pcWriteBuffer A buffer into which the execution times will be + * written, in ASCII form. This buffer is assumed to be large enough to + * contain the generated report. Approximately 40 bytes per task should + * be sufficient. + * + * \defgroup vTaskGetRunTimeStats vTaskGetRunTimeStats + * \ingroup TaskUtils + */ +void vTaskGetRunTimeStats( char *pcWriteBuffer ) PRIVILEGED_FUNCTION; /*lint !e971 Unqualified char types are allowed for strings and single characters only. */ + +/** + * task. h + *
BaseType_t xTaskNotify( TaskHandle_t xTaskToNotify, uint32_t ulValue, eNotifyAction eAction );
+ * + * configUSE_TASK_NOTIFICATIONS must be undefined or defined as 1 for this + * function to be available. + * + * When configUSE_TASK_NOTIFICATIONS is set to one each task has its own private + * "notification value", which is a 32-bit unsigned integer (uint32_t). + * + * Events can be sent to a task using an intermediary object. Examples of such + * objects are queues, semaphores, mutexes and event groups. Task notifications + * are a method of sending an event directly to a task without the need for such + * an intermediary object. + * + * A notification sent to a task can optionally perform an action, such as + * update, overwrite or increment the task's notification value. In that way + * task notifications can be used to send data to a task, or be used as light + * weight and fast binary or counting semaphores. + * + * A notification sent to a task will remain pending until it is cleared by the + * task calling xTaskNotifyWait() or ulTaskNotifyTake(). If the task was + * already in the Blocked state to wait for a notification when the notification + * arrives then the task will automatically be removed from the Blocked state + * (unblocked) and the notification cleared. + * + * A task can use xTaskNotifyWait() to [optionally] block to wait for a + * notification to be pending, or ulTaskNotifyTake() to [optionally] block + * to wait for its notification value to have a non-zero value. The task does + * not consume any CPU time while it is in the Blocked state. + * + * See http://www.FreeRTOS.org/RTOS-task-notifications.html for details. + * + * @param xTaskToNotify The handle of the task being notified. The handle to a + * task can be returned from the xTaskCreate() API function used to create the + * task, and the handle of the currently running task can be obtained by calling + * xTaskGetCurrentTaskHandle(). + * + * @param ulValue Data that can be sent with the notification. How the data is + * used depends on the value of the eAction parameter. + * + * @param eAction Specifies how the notification updates the task's notification + * value, if at all. Valid values for eAction are as follows: + * + * eSetBits - + * The task's notification value is bitwise ORed with ulValue. xTaskNofify() + * always returns pdPASS in this case. + * + * eIncrement - + * The task's notification value is incremented. ulValue is not used and + * xTaskNotify() always returns pdPASS in this case. + * + * eSetValueWithOverwrite - + * The task's notification value is set to the value of ulValue, even if the + * task being notified had not yet processed the previous notification (the + * task already had a notification pending). xTaskNotify() always returns + * pdPASS in this case. + * + * eSetValueWithoutOverwrite - + * If the task being notified did not already have a notification pending then + * the task's notification value is set to ulValue and xTaskNotify() will + * return pdPASS. If the task being notified already had a notification + * pending then no action is performed and pdFAIL is returned. + * + * eNoAction - + * The task receives a notification without its notification value being + * updated. ulValue is not used and xTaskNotify() always returns pdPASS in + * this case. + * + * @return Dependent on the value of eAction. See the description of the + * eAction parameter. + * + * \defgroup xTaskNotify xTaskNotify + * \ingroup TaskNotifications + */ +BaseType_t xTaskNotify( TaskHandle_t xTaskToNotify, uint32_t ulValue, eNotifyAction eAction ); + +/** + * task. h + *
BaseType_t xTaskNotifyFromISR( TaskHandle_t xTaskToNotify, uint32_t ulValue, eNotifyAction eAction, BaseType_t *pxHigherPriorityTaskWoken );
+ * + * configUSE_TASK_NOTIFICATIONS must be undefined or defined as 1 for this + * function to be available. + * + * When configUSE_TASK_NOTIFICATIONS is set to one each task has its own private + * "notification value", which is a 32-bit unsigned integer (uint32_t). + * + * A version of xTaskNotify() that can be used from an interrupt service routine + * (ISR). + * + * Events can be sent to a task using an intermediary object. Examples of such + * objects are queues, semaphores, mutexes and event groups. Task notifications + * are a method of sending an event directly to a task without the need for such + * an intermediary object. + * + * A notification sent to a task can optionally perform an action, such as + * update, overwrite or increment the task's notification value. In that way + * task notifications can be used to send data to a task, or be used as light + * weight and fast binary or counting semaphores. + * + * A notification sent to a task will remain pending until it is cleared by the + * task calling xTaskNotifyWait() or ulTaskNotifyTake(). If the task was + * already in the Blocked state to wait for a notification when the notification + * arrives then the task will automatically be removed from the Blocked state + * (unblocked) and the notification cleared. + * + * A task can use xTaskNotifyWait() to [optionally] block to wait for a + * notification to be pending, or ulTaskNotifyTake() to [optionally] block + * to wait for its notification value to have a non-zero value. The task does + * not consume any CPU time while it is in the Blocked state. + * + * See http://www.FreeRTOS.org/RTOS-task-notifications.html for details. + * + * @param xTaskToNotify The handle of the task being notified. The handle to a + * task can be returned from the xTaskCreate() API function used to create the + * task, and the handle of the currently running task can be obtained by calling + * xTaskGetCurrentTaskHandle(). + * + * @param ulValue Data that can be sent with the notification. How the data is + * used depends on the value of the eAction parameter. + * + * @param eAction Specifies how the notification updates the task's notification + * value, if at all. Valid values for eAction are as follows: + * + * eSetBits - + * The task's notification value is bitwise ORed with ulValue. xTaskNofify() + * always returns pdPASS in this case. + * + * eIncrement - + * The task's notification value is incremented. ulValue is not used and + * xTaskNotify() always returns pdPASS in this case. + * + * eSetValueWithOverwrite - + * The task's notification value is set to the value of ulValue, even if the + * task being notified had not yet processed the previous notification (the + * task already had a notification pending). xTaskNotify() always returns + * pdPASS in this case. + * + * eSetValueWithoutOverwrite - + * If the task being notified did not already have a notification pending then + * the task's notification value is set to ulValue and xTaskNotify() will + * return pdPASS. If the task being notified already had a notification + * pending then no action is performed and pdFAIL is returned. + * + * eNoAction - + * The task receives a notification without its notification value being + * updated. ulValue is not used and xTaskNotify() always returns pdPASS in + * this case. + * + * @param pxHigherPriorityTaskWoken xTaskNotifyFromISR() will set + * *pxHigherPriorityTaskWoken to pdTRUE if sending the notification caused the + * task to which the notification was sent to leave the Blocked state, and the + * unblocked task has a priority higher than the currently running task. If + * xTaskNotifyFromISR() sets this value to pdTRUE then a context switch should + * be requested before the interrupt is exited. How a context switch is + * requested from an ISR is dependent on the port - see the documentation page + * for the port in use. + * + * @return Dependent on the value of eAction. See the description of the + * eAction parameter. + * + * \defgroup xTaskNotify xTaskNotify + * \ingroup TaskNotifications + */ +BaseType_t xTaskNotifyFromISR( TaskHandle_t xTaskToNotify, uint32_t ulValue, eNotifyAction eAction, BaseType_t *pxHigherPriorityTaskWoken ); + +/** + * task. h + *
BaseType_t xTaskNotifyWait( uint32_t ulBitsToClearOnEntry, uint32_t ulBitsToClearOnExit, uint32_t *pulNotificationValue, TickType_t xTicksToWait );
+ * + * configUSE_TASK_NOTIFICATIONS must be undefined or defined as 1 for this + * function to be available. + * + * When configUSE_TASK_NOTIFICATIONS is set to one each task has its own private + * "notification value", which is a 32-bit unsigned integer (uint32_t). + * + * Events can be sent to a task using an intermediary object. Examples of such + * objects are queues, semaphores, mutexes and event groups. Task notifications + * are a method of sending an event directly to a task without the need for such + * an intermediary object. + * + * A notification sent to a task can optionally perform an action, such as + * update, overwrite or increment the task's notification value. In that way + * task notifications can be used to send data to a task, or be used as light + * weight and fast binary or counting semaphores. + * + * A notification sent to a task will remain pending until it is cleared by the + * task calling xTaskNotifyWait() or ulTaskNotifyTake(). If the task was + * already in the Blocked state to wait for a notification when the notification + * arrives then the task will automatically be removed from the Blocked state + * (unblocked) and the notification cleared. + * + * A task can use xTaskNotifyWait() to [optionally] block to wait for a + * notification to be pending, or ulTaskNotifyTake() to [optionally] block + * to wait for its notification value to have a non-zero value. The task does + * not consume any CPU time while it is in the Blocked state. + * + * See http://www.FreeRTOS.org/RTOS-task-notifications.html for details. + * + * @param ulBitsToClearOnEntry Bits that are set in ulBitsToClearOnEntry value + * will be cleared in the calling task's notification value before the task + * checks to see if any notifications are pending, and optionally blocks if no + * notifications are pending. Setting ulBitsToClearOnEntry to ULONG_MAX (if + * limits.h is included) or 0xffffffffUL (if limits.h is not included) will have + * the effect of resetting the task's notification value to 0. Setting + * ulBitsToClearOnEntry to 0 will leave the task's notification value unchanged. + * + * @param ulBitsToClearOnExit If a notification is pending or received before + * the calling task exits the xTaskNotifyWait() function then the task's + * notification value (see the xTaskNotify() API function) is passed out using + * the pulNotificationValue parameter. Then any bits that are set in + * ulBitsToClearOnExit will be cleared in the task's notification value (note + * *pulNotificationValue is set before any bits are cleared). Setting + * ulBitsToClearOnExit to ULONG_MAX (if limits.h is included) or 0xffffffffUL + * (if limits.h is not included) will have the effect of resetting the task's + * notification value to 0 before the function exits. Setting + * ulBitsToClearOnExit to 0 will leave the task's notification value unchanged + * when the function exits (in which case the value passed out in + * pulNotificationValue will match the task's notification value). + * + * @param pulNotificationValue Used to pass the task's notification value out + * of the function. Note the value passed out will not be effected by the + * clearing of any bits caused by ulBitsToClearOnExit being non-zero. + * + * @param xTicksToWait The maximum amount of time that the task should wait in + * the Blocked state for a notification to be received, should a notification + * not already be pending when xTaskNotifyWait() was called. The task + * will not consume any processing time while it is in the Blocked state. This + * is specified in kernel ticks, the macro pdMS_TO_TICSK( value_in_ms ) can be + * used to convert a time specified in milliseconds to a time specified in + * ticks. + * + * @return If a notification was received (including notifications that were + * already pending when xTaskNotifyWait was called) then pdPASS is + * returned. Otherwise pdFAIL is returned. + * + * \defgroup xTaskNotifyWait xTaskNotifyWait + * \ingroup TaskNotifications + */ +BaseType_t xTaskNotifyWait( uint32_t ulBitsToClearOnEntry, uint32_t ulBitsToClearOnExit, uint32_t *pulNotificationValue, TickType_t xTicksToWait ); + +/** + * task. h + *
BaseType_t xTaskNotifyGive( TaskHandle_t xTaskToNotify );
+ * + * configUSE_TASK_NOTIFICATIONS must be undefined or defined as 1 for this macro + * to be available. + * + * When configUSE_TASK_NOTIFICATIONS is set to one each task has its own private + * "notification value", which is a 32-bit unsigned integer (uint32_t). + * + * Events can be sent to a task using an intermediary object. Examples of such + * objects are queues, semaphores, mutexes and event groups. Task notifications + * are a method of sending an event directly to a task without the need for such + * an intermediary object. + * + * A notification sent to a task can optionally perform an action, such as + * update, overwrite or increment the task's notification value. In that way + * task notifications can be used to send data to a task, or be used as light + * weight and fast binary or counting semaphores. + * + * xTaskNotifyGive() is a helper macro intended for use when task notifications + * are used as light weight and faster binary or counting semaphore equivalents. + * Actual FreeRTOS semaphores are given using the xSemaphoreGive() API function, + * the equivalent action that instead uses a task notification is + * xTaskNotifyGive(). + * + * When task notifications are being used as a binary or counting semaphore + * equivalent then the task being notified should wait for the notification + * using the ulTaskNotificationTake() API function rather than the + * xTaskNotifyWait() API function. + * + * See http://www.FreeRTOS.org/RTOS-task-notifications.html for more details. + * + * @param xTaskToNotify The handle of the task being notified. The handle to a + * task can be returned from the xTaskCreate() API function used to create the + * task, and the handle of the currently running task can be obtained by calling + * xTaskGetCurrentTaskHandle(). + * + * @return xTaskNotifyGive() is a macro that calls xTaskNotify() with the + * eAction parameter set to eIncrement - so pdPASS is always returned. + * + * \defgroup xTaskNotifyGive xTaskNotifyGive + * \ingroup TaskNotifications + */ +#define xTaskNotifyGive( xTaskToNotify ) xTaskNotify( ( xTaskToNotify ), 0, eIncrement ); + +/** + * task. h + *
void vTaskNotifyGiveFromISR( TaskHandle_t xTaskHandle, BaseType_t *pxHigherPriorityTaskWoken );
+ *
+ * configUSE_TASK_NOTIFICATIONS must be undefined or defined as 1 for this macro
+ * to be available.
+ *
+ * When configUSE_TASK_NOTIFICATIONS is set to one each task has its own private
+ * "notification value", which is a 32-bit unsigned integer (uint32_t).
+ *
+ * A version of xTaskNotifyGive() that can be called from an interrupt service
+ * routine (ISR).
+ *
+ * Events can be sent to a task using an intermediary object.  Examples of such
+ * objects are queues, semaphores, mutexes and event groups.  Task notifications
+ * are a method of sending an event directly to a task without the need for such
+ * an intermediary object.
+ *
+ * A notification sent to a task can optionally perform an action, such as
+ * update, overwrite or increment the task's notification value.  In that way
+ * task notifications can be used to send data to a task, or be used as light
+ * weight and fast binary or counting semaphores.
+ *
+ * vTaskNotifyGiveFromISR() is intended for use when task notifications are
+ * used as light weight and faster binary or counting semaphore equivalents.
+ * Actual FreeRTOS semaphores are given from an ISR using the
+ * xSemaphoreGiveFromISR() API function, the equivalent action that instead uses
+ * a task notification is vTaskNotifyGiveFromISR().
+ *
+ * When task notifications are being used as a binary or counting semaphore
+ * equivalent then the task being notified should wait for the notification
+ * using the ulTaskNotificationTake() API function rather than the
+ * xTaskNotifyWait() API function.
+ *
+ * See http://www.FreeRTOS.org/RTOS-task-notifications.html for more details.
+ *
+ * @param xTaskToNotify The handle of the task being notified.  The handle to a
+ * task can be returned from the xTaskCreate() API function used to create the
+ * task, and the handle of the currently running task can be obtained by calling
+ * xTaskGetCurrentTaskHandle().
+ *
+ * @param pxHigherPriorityTaskWoken  vTaskNotifyGiveFromISR() will set
+ * *pxHigherPriorityTaskWoken to pdTRUE if sending the notification caused the
+ * task to which the notification was sent to leave the Blocked state, and the
+ * unblocked task has a priority higher than the currently running task.  If
+ * vTaskNotifyGiveFromISR() sets this value to pdTRUE then a context switch
+ * should be requested before the interrupt is exited.  How a context switch is
+ * requested from an ISR is dependent on the port - see the documentation page
+ * for the port in use.
+ *
+ * \defgroup xTaskNotifyWait xTaskNotifyWait
+ * \ingroup TaskNotifications
+ */
+void vTaskNotifyGiveFromISR( TaskHandle_t xTaskToNotify, BaseType_t *pxHigherPriorityTaskWoken );
+
+/**
+ * task. h
+ * 
uint32_t ulTaskNotifyTake( BaseType_t xClearCountOnExit, TickType_t xTicksToWait );
+ * + * configUSE_TASK_NOTIFICATIONS must be undefined or defined as 1 for this + * function to be available. + * + * When configUSE_TASK_NOTIFICATIONS is set to one each task has its own private + * "notification value", which is a 32-bit unsigned integer (uint32_t). + * + * Events can be sent to a task using an intermediary object. Examples of such + * objects are queues, semaphores, mutexes and event groups. Task notifications + * are a method of sending an event directly to a task without the need for such + * an intermediary object. + * + * A notification sent to a task can optionally perform an action, such as + * update, overwrite or increment the task's notification value. In that way + * task notifications can be used to send data to a task, or be used as light + * weight and fast binary or counting semaphores. + * + * ulTaskNotifyTake() is intended for use when a task notification is used as a + * faster and lighter weight binary or counting semaphore alternative. Actual + * FreeRTOS semaphores are taken using the xSemaphoreTake() API function, the + * equivalent action that instead uses a task notification is + * ulTaskNotifyTake(). + * + * When a task is using its notification value as a binary or counting semaphore + * other tasks should send notifications to it using the xTaskNotifyGive() + * macro, or xTaskNotify() function with the eAction parameter set to + * eIncrement. + * + * ulTaskNotifyTake() can either clear the task's notification value to + * zero on exit, in which case the notification value acts like a binary + * semaphore, or decrement the task's notification value on exit, in which case + * the notification value acts like a counting semaphore. + * + * A task can use ulTaskNotifyTake() to [optionally] block to wait for a + * the task's notification value to be non-zero. The task does not consume any + * CPU time while it is in the Blocked state. + * + * Where as xTaskNotifyWait() will return when a notification is pending, + * ulTaskNotifyTake() will return when the task's notification value is + * not zero. + * + * See http://www.FreeRTOS.org/RTOS-task-notifications.html for details. + * + * @param xClearCountOnExit if xClearCountOnExit is pdFALSE then the task's + * notification value is decremented when the function exits. In this way the + * notification value acts like a counting semaphore. If xClearCountOnExit is + * not pdFALSE then the task's notification value is cleared to zero when the + * function exits. In this way the notification value acts like a binary + * semaphore. + * + * @param xTicksToWait The maximum amount of time that the task should wait in + * the Blocked state for the task's notification value to be greater than zero, + * should the count not already be greater than zero when + * ulTaskNotifyTake() was called. The task will not consume any processing + * time while it is in the Blocked state. This is specified in kernel ticks, + * the macro pdMS_TO_TICSK( value_in_ms ) can be used to convert a time + * specified in milliseconds to a time specified in ticks. + * + * @return The task's notification count before it is either cleared to zero or + * decremented (see the xClearCountOnExit parameter). + * + * \defgroup ulTaskNotifyTake ulTaskNotifyTake + * \ingroup TaskNotifications + */ +uint32_t ulTaskNotifyTake( BaseType_t xClearCountOnExit, TickType_t xTicksToWait ); + +/*----------------------------------------------------------- + * SCHEDULER INTERNALS AVAILABLE FOR PORTING PURPOSES + *----------------------------------------------------------*/ + +/* + * THIS FUNCTION MUST NOT BE USED FROM APPLICATION CODE. IT IS ONLY + * INTENDED FOR USE WHEN IMPLEMENTING A PORT OF THE SCHEDULER AND IS + * AN INTERFACE WHICH IS FOR THE EXCLUSIVE USE OF THE SCHEDULER. + * + * Called from the real time kernel tick (either preemptive or cooperative), + * this increments the tick count and checks if any tasks that are blocked + * for a finite period required removing from a blocked list and placing on + * a ready list. If a non-zero value is returned then a context switch is + * required because either: + * + A task was removed from a blocked list because its timeout had expired, + * or + * + Time slicing is in use and there is a task of equal priority to the + * currently running task. + */ +BaseType_t xTaskIncrementTick( void ) PRIVILEGED_FUNCTION; + +/* + * THIS FUNCTION MUST NOT BE USED FROM APPLICATION CODE. IT IS AN + * INTERFACE WHICH IS FOR THE EXCLUSIVE USE OF THE SCHEDULER. + * + * THIS FUNCTION MUST BE CALLED WITH INTERRUPTS DISABLED. + * + * Removes the calling task from the ready list and places it both + * on the list of tasks waiting for a particular event, and the + * list of delayed tasks. The task will be removed from both lists + * and replaced on the ready list should either the event occur (and + * there be no higher priority tasks waiting on the same event) or + * the delay period expires. + * + * The 'unordered' version replaces the event list item value with the + * xItemValue value, and inserts the list item at the end of the list. + * + * The 'ordered' version uses the existing event list item value (which is the + * owning tasks priority) to insert the list item into the event list is task + * priority order. + * + * @param pxEventList The list containing tasks that are blocked waiting + * for the event to occur. + * + * @param xItemValue The item value to use for the event list item when the + * event list is not ordered by task priority. + * + * @param xTicksToWait The maximum amount of time that the task should wait + * for the event to occur. This is specified in kernel ticks,the constant + * portTICK_PERIOD_MS can be used to convert kernel ticks into a real time + * period. + */ +void vTaskPlaceOnEventList( List_t * const pxEventList, const TickType_t xTicksToWait ) PRIVILEGED_FUNCTION; +void vTaskPlaceOnUnorderedEventList( List_t * pxEventList, const TickType_t xItemValue, const TickType_t xTicksToWait ) PRIVILEGED_FUNCTION; + +/* + * THIS FUNCTION MUST NOT BE USED FROM APPLICATION CODE. IT IS AN + * INTERFACE WHICH IS FOR THE EXCLUSIVE USE OF THE SCHEDULER. + * + * THIS FUNCTION MUST BE CALLED WITH INTERRUPTS DISABLED. + * + * This function performs nearly the same function as vTaskPlaceOnEventList(). + * The difference being that this function does not permit tasks to block + * indefinitely, whereas vTaskPlaceOnEventList() does. + * + */ +void vTaskPlaceOnEventListRestricted( List_t * const pxEventList, const TickType_t xTicksToWait ) PRIVILEGED_FUNCTION; + +/* + * THIS FUNCTION MUST NOT BE USED FROM APPLICATION CODE. IT IS AN + * INTERFACE WHICH IS FOR THE EXCLUSIVE USE OF THE SCHEDULER. + * + * THIS FUNCTION MUST BE CALLED WITH INTERRUPTS DISABLED. + * + * Removes a task from both the specified event list and the list of blocked + * tasks, and places it on a ready queue. + * + * xTaskRemoveFromEventList()/xTaskRemoveFromUnorderedEventList() will be called + * if either an event occurs to unblock a task, or the block timeout period + * expires. + * + * xTaskRemoveFromEventList() is used when the event list is in task priority + * order. It removes the list item from the head of the event list as that will + * have the highest priority owning task of all the tasks on the event list. + * xTaskRemoveFromUnorderedEventList() is used when the event list is not + * ordered and the event list items hold something other than the owning tasks + * priority. In this case the event list item value is updated to the value + * passed in the xItemValue parameter. + * + * @return pdTRUE if the task being removed has a higher priority than the task + * making the call, otherwise pdFALSE. + */ +BaseType_t xTaskRemoveFromEventList( const List_t * const pxEventList ) PRIVILEGED_FUNCTION; +BaseType_t xTaskRemoveFromUnorderedEventList( ListItem_t * pxEventListItem, const TickType_t xItemValue ) PRIVILEGED_FUNCTION; + +/* + * THIS FUNCTION MUST NOT BE USED FROM APPLICATION CODE. IT IS ONLY + * INTENDED FOR USE WHEN IMPLEMENTING A PORT OF THE SCHEDULER AND IS + * AN INTERFACE WHICH IS FOR THE EXCLUSIVE USE OF THE SCHEDULER. + * + * Sets the pointer to the current TCB to the TCB of the highest priority task + * that is ready to run. + */ +void vTaskSwitchContext( void ) PRIVILEGED_FUNCTION; + +/* + * THESE FUNCTIONS MUST NOT BE USED FROM APPLICATION CODE. THEY ARE USED BY + * THE EVENT BITS MODULE. + */ +TickType_t uxTaskResetEventItemValue( void ) PRIVILEGED_FUNCTION; + +/* + * Return the handle of the calling task. + */ +TaskHandle_t xTaskGetCurrentTaskHandle( void ) PRIVILEGED_FUNCTION; + +/* + * Capture the current time status for future reference. + */ +void vTaskSetTimeOutState( TimeOut_t * const pxTimeOut ) PRIVILEGED_FUNCTION; + +/* + * Compare the time status now with that previously captured to see if the + * timeout has expired. + */ +BaseType_t xTaskCheckForTimeOut( TimeOut_t * const pxTimeOut, TickType_t * const pxTicksToWait ) PRIVILEGED_FUNCTION; + +/* + * Shortcut used by the queue implementation to prevent unnecessary call to + * taskYIELD(); + */ +void vTaskMissedYield( void ) PRIVILEGED_FUNCTION; + +/* + * Returns the scheduler state as taskSCHEDULER_RUNNING, + * taskSCHEDULER_NOT_STARTED or taskSCHEDULER_SUSPENDED. + */ +BaseType_t xTaskGetSchedulerState( void ) PRIVILEGED_FUNCTION; + +/* + * Raises the priority of the mutex holder to that of the calling task should + * the mutex holder have a priority less than the calling task. + */ +void vTaskPriorityInherit( TaskHandle_t const pxMutexHolder ) PRIVILEGED_FUNCTION; + +/* + * Set the priority of a task back to its proper priority in the case that it + * inherited a higher priority while it was holding a semaphore. + */ +BaseType_t xTaskPriorityDisinherit( TaskHandle_t const pxMutexHolder ) PRIVILEGED_FUNCTION; + +/* + * Generic version of the task creation function which is in turn called by the + * xTaskCreate() and xTaskCreateRestricted() macros. + */ +BaseType_t xTaskGenericCreate( TaskFunction_t pxTaskCode, const char * const pcName, const uint16_t usStackDepth, void * const pvParameters, UBaseType_t uxPriority, TaskHandle_t * const pxCreatedTask, StackType_t * const puxStackBuffer, const MemoryRegion_t * const xRegions, const BaseType_t xCoreID) PRIVILEGED_FUNCTION; /*lint !e971 Unqualified char types are allowed for strings and single characters only. */ + +/* + * Get the uxTCBNumber assigned to the task referenced by the xTask parameter. + */ +UBaseType_t uxTaskGetTaskNumber( TaskHandle_t xTask ) PRIVILEGED_FUNCTION; + +/* + * Set the uxTaskNumber of the task referenced by the xTask parameter to + * uxHandle. + */ +void vTaskSetTaskNumber( TaskHandle_t xTask, const UBaseType_t uxHandle ) PRIVILEGED_FUNCTION; + +/* + * Only available when configUSE_TICKLESS_IDLE is set to 1. + * If tickless mode is being used, or a low power mode is implemented, then + * the tick interrupt will not execute during idle periods. When this is the + * case, the tick count value maintained by the scheduler needs to be kept up + * to date with the actual execution time by being skipped forward by a time + * equal to the idle period. + */ +void vTaskStepTick( const TickType_t xTicksToJump ) PRIVILEGED_FUNCTION; + +/* + * Only avilable when configUSE_TICKLESS_IDLE is set to 1. + * Provided for use within portSUPPRESS_TICKS_AND_SLEEP() to allow the port + * specific sleep function to determine if it is ok to proceed with the sleep, + * and if it is ok to proceed, if it is ok to sleep indefinitely. + * + * This function is necessary because portSUPPRESS_TICKS_AND_SLEEP() is only + * called with the scheduler suspended, not from within a critical section. It + * is therefore possible for an interrupt to request a context switch between + * portSUPPRESS_TICKS_AND_SLEEP() and the low power mode actually being + * entered. eTaskConfirmSleepModeStatus() should be called from a short + * critical section between the timer being stopped and the sleep mode being + * entered to ensure it is ok to proceed into the sleep mode. + */ +eSleepModeStatus eTaskConfirmSleepModeStatus( void ) PRIVILEGED_FUNCTION; + +/* + * For internal use only. Increment the mutex held count when a mutex is + * taken and return the handle of the task that has taken the mutex. + */ +void *pvTaskIncrementMutexHeldCount( void ); + +#ifdef __cplusplus +} +#endif +#endif /* INC_TASK_H */ + + + diff --git a/components/freertos/include/freertos/timers.h b/components/freertos/include/freertos/timers.h new file mode 100644 index 0000000000..f89cd1d70e --- /dev/null +++ b/components/freertos/include/freertos/timers.h @@ -0,0 +1,1125 @@ +/* + FreeRTOS V8.2.0 - Copyright (C) 2015 Real Time Engineers Ltd. + All rights reserved + + VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION. + + This file is part of the FreeRTOS distribution. + + FreeRTOS is free software; you can redistribute it and/or modify it under + the terms of the GNU General Public License (version 2) as published by the + Free Software Foundation >>!AND MODIFIED BY!<< the FreeRTOS exception. + + *************************************************************************** + >>! NOTE: The modification to the GPL is included to allow you to !<< + >>! distribute a combined work that includes FreeRTOS without being !<< + >>! obliged to provide the source code for proprietary components !<< + >>! outside of the FreeRTOS kernel. !<< + *************************************************************************** + + FreeRTOS is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + FOR A PARTICULAR PURPOSE. Full license text is available on the following + link: http://www.freertos.org/a00114.html + + *************************************************************************** + * * + * FreeRTOS provides completely free yet professionally developed, * + * robust, strictly quality controlled, supported, and cross * + * platform software that is more than just the market leader, it * + * is the industry's de facto standard. * + * * + * Help yourself get started quickly while simultaneously helping * + * to support the FreeRTOS project by purchasing a FreeRTOS * + * tutorial book, reference manual, or both: * + * http://www.FreeRTOS.org/Documentation * + * * + *************************************************************************** + + http://www.FreeRTOS.org/FAQHelp.html - Having a problem? Start by reading + the FAQ page "My application does not run, what could be wrong?". Have you + defined configASSERT()? + + http://www.FreeRTOS.org/support - In return for receiving this top quality + embedded software for free we request you assist our global community by + participating in the support forum. + + http://www.FreeRTOS.org/training - Investing in training allows your team to + be as productive as possible as early as possible. Now you can receive + FreeRTOS training directly from Richard Barry, CEO of Real Time Engineers + Ltd, and the world's leading authority on the world's leading RTOS. + + http://www.FreeRTOS.org/plus - A selection of FreeRTOS ecosystem products, + including FreeRTOS+Trace - an indispensable productivity tool, a DOS + compatible FAT file system, and our tiny thread aware UDP/IP stack. + + http://www.FreeRTOS.org/labs - Where new FreeRTOS products go to incubate. + Come and try FreeRTOS+TCP, our new open source TCP/IP stack for FreeRTOS. + + http://www.OpenRTOS.com - Real Time Engineers ltd. license FreeRTOS to High + Integrity Systems ltd. to sell under the OpenRTOS brand. Low cost OpenRTOS + licenses offer ticketed support, indemnification and commercial middleware. + + http://www.SafeRTOS.com - High Integrity Systems also provide a safety + engineered and independently SIL3 certified version for use in safety and + mission critical applications that require provable dependability. + + 1 tab == 4 spaces! +*/ + + +#ifndef TIMERS_H +#define TIMERS_H + +#ifndef INC_FREERTOS_H + #error "include FreeRTOS.h must appear in source files before include timers.h" +#endif + +/*lint -e537 This headers are only multiply included if the application code +happens to also be including task.h. */ +#include "task.h" +/*lint +e537 */ + +#ifdef __cplusplus +extern "C" { +#endif + +/*----------------------------------------------------------- + * MACROS AND DEFINITIONS + *----------------------------------------------------------*/ + +/* IDs for commands that can be sent/received on the timer queue. These are to +be used solely through the macros that make up the public software timer API, +as defined below. The commands that are sent from interrupts must use the +highest numbers as tmrFIRST_FROM_ISR_COMMAND is used to determine if the task +or interrupt version of the queue send function should be used. */ +#define tmrCOMMAND_EXECUTE_CALLBACK_FROM_ISR ( ( BaseType_t ) -2 ) +#define tmrCOMMAND_EXECUTE_CALLBACK ( ( BaseType_t ) -1 ) +#define tmrCOMMAND_START_DONT_TRACE ( ( BaseType_t ) 0 ) +#define tmrCOMMAND_START ( ( BaseType_t ) 1 ) +#define tmrCOMMAND_RESET ( ( BaseType_t ) 2 ) +#define tmrCOMMAND_STOP ( ( BaseType_t ) 3 ) +#define tmrCOMMAND_CHANGE_PERIOD ( ( BaseType_t ) 4 ) +#define tmrCOMMAND_DELETE ( ( BaseType_t ) 5 ) + +#define tmrFIRST_FROM_ISR_COMMAND ( ( BaseType_t ) 6 ) +#define tmrCOMMAND_START_FROM_ISR ( ( BaseType_t ) 6 ) +#define tmrCOMMAND_RESET_FROM_ISR ( ( BaseType_t ) 7 ) +#define tmrCOMMAND_STOP_FROM_ISR ( ( BaseType_t ) 8 ) +#define tmrCOMMAND_CHANGE_PERIOD_FROM_ISR ( ( BaseType_t ) 9 ) + + +/** + * Type by which software timers are referenced. For example, a call to + * xTimerCreate() returns an TimerHandle_t variable that can then be used to + * reference the subject timer in calls to other software timer API functions + * (for example, xTimerStart(), xTimerReset(), etc.). + */ +typedef void * TimerHandle_t; + +/* + * Defines the prototype to which timer callback functions must conform. + */ +typedef void (*TimerCallbackFunction_t)( TimerHandle_t xTimer ); + +/* + * Defines the prototype to which functions used with the + * xTimerPendFunctionCallFromISR() function must conform. + */ +typedef void (*PendedFunction_t)( void *, uint32_t ); + +/** + * TimerHandle_t xTimerCreate( const char * const pcTimerName, + * TickType_t xTimerPeriodInTicks, + * UBaseType_t uxAutoReload, + * void * pvTimerID, + * TimerCallbackFunction_t pxCallbackFunction ); + * + * Creates a new software timer instance. This allocates the storage required + * by the new timer, initialises the new timers internal state, and returns a + * handle by which the new timer can be referenced. + * + * Timers are created in the dormant state. The xTimerStart(), xTimerReset(), + * xTimerStartFromISR(), xTimerResetFromISR(), xTimerChangePeriod() and + * xTimerChangePeriodFromISR() API functions can all be used to transition a + * timer into the active state. + * + * @param pcTimerName A text name that is assigned to the timer. This is done + * purely to assist debugging. The kernel itself only ever references a timer + * by its handle, and never by its name. + * + * @param xTimerPeriodInTicks The timer period. The time is defined in tick + * periods so the constant portTICK_PERIOD_MS can be used to convert a time that + * has been specified in milliseconds. For example, if the timer must expire + * after 100 ticks, then xTimerPeriodInTicks should be set to 100. + * Alternatively, if the timer must expire after 500ms, then xPeriod can be set + * to ( 500 / portTICK_PERIOD_MS ) provided configTICK_RATE_HZ is less than or + * equal to 1000. + * + * @param uxAutoReload If uxAutoReload is set to pdTRUE then the timer will + * expire repeatedly with a frequency set by the xTimerPeriodInTicks parameter. + * If uxAutoReload is set to pdFALSE then the timer will be a one-shot timer and + * enter the dormant state after it expires. + * + * @param pvTimerID An identifier that is assigned to the timer being created. + * Typically this would be used in the timer callback function to identify which + * timer expired when the same callback function is assigned to more than one + * timer. + * + * @param pxCallbackFunction The function to call when the timer expires. + * Callback functions must have the prototype defined by TimerCallbackFunction_t, + * which is "void vCallbackFunction( TimerHandle_t xTimer );". + * + * @return If the timer is successfully created then a handle to the newly + * created timer is returned. If the timer cannot be created (because either + * there is insufficient FreeRTOS heap remaining to allocate the timer + * structures, or the timer period was set to 0) then NULL is returned. + * + * Example usage: + * @verbatim + * #define NUM_TIMERS 5 + * + * // An array to hold handles to the created timers. + * TimerHandle_t xTimers[ NUM_TIMERS ]; + * + * // An array to hold a count of the number of times each timer expires. + * int32_t lExpireCounters[ NUM_TIMERS ] = { 0 }; + * + * // Define a callback function that will be used by multiple timer instances. + * // The callback function does nothing but count the number of times the + * // associated timer expires, and stop the timer once the timer has expired + * // 10 times. + * void vTimerCallback( TimerHandle_t pxTimer ) + * { + * int32_t lArrayIndex; + * const int32_t xMaxExpiryCountBeforeStopping = 10; + * + * // Optionally do something if the pxTimer parameter is NULL. + * configASSERT( pxTimer ); + * + * // Which timer expired? + * lArrayIndex = ( int32_t ) pvTimerGetTimerID( pxTimer ); + * + * // Increment the number of times that pxTimer has expired. + * lExpireCounters[ lArrayIndex ] += 1; + * + * // If the timer has expired 10 times then stop it from running. + * if( lExpireCounters[ lArrayIndex ] == xMaxExpiryCountBeforeStopping ) + * { + * // Do not use a block time if calling a timer API function from a + * // timer callback function, as doing so could cause a deadlock! + * xTimerStop( pxTimer, 0 ); + * } + * } + * + * void main( void ) + * { + * int32_t x; + * + * // Create then start some timers. Starting the timers before the scheduler + * // has been started means the timers will start running immediately that + * // the scheduler starts. + * for( x = 0; x < NUM_TIMERS; x++ ) + * { + * xTimers[ x ] = xTimerCreate( "Timer", // Just a text name, not used by the kernel. + * ( 100 * x ), // The timer period in ticks. + * pdTRUE, // The timers will auto-reload themselves when they expire. + * ( void * ) x, // Assign each timer a unique id equal to its array index. + * vTimerCallback // Each timer calls the same callback when it expires. + * ); + * + * if( xTimers[ x ] == NULL ) + * { + * // The timer was not created. + * } + * else + * { + * // Start the timer. No block time is specified, and even if one was + * // it would be ignored because the scheduler has not yet been + * // started. + * if( xTimerStart( xTimers[ x ], 0 ) != pdPASS ) + * { + * // The timer could not be set into the Active state. + * } + * } + * } + * + * // ... + * // Create tasks here. + * // ... + * + * // Starting the scheduler will start the timers running as they have already + * // been set into the active state. + * xTaskStartScheduler(); + * + * // Should not reach here. + * for( ;; ); + * } + * @endverbatim + */ +TimerHandle_t xTimerCreate( const char * const pcTimerName, const TickType_t xTimerPeriodInTicks, const UBaseType_t uxAutoReload, void * const pvTimerID, TimerCallbackFunction_t pxCallbackFunction ) PRIVILEGED_FUNCTION; /*lint !e971 Unqualified char types are allowed for strings and single characters only. */ + +/** + * void *pvTimerGetTimerID( TimerHandle_t xTimer ); + * + * Returns the ID assigned to the timer. + * + * IDs are assigned to timers using the pvTimerID parameter of the call to + * xTimerCreated() that was used to create the timer. + * + * If the same callback function is assigned to multiple timers then the timer + * ID can be used within the callback function to identify which timer actually + * expired. + * + * @param xTimer The timer being queried. + * + * @return The ID assigned to the timer being queried. + * + * Example usage: + * + * See the xTimerCreate() API function example usage scenario. + */ +void *pvTimerGetTimerID( TimerHandle_t xTimer ) PRIVILEGED_FUNCTION; + +/** + * BaseType_t xTimerIsTimerActive( TimerHandle_t xTimer ); + * + * Queries a timer to see if it is active or dormant. + * + * A timer will be dormant if: + * 1) It has been created but not started, or + * 2) It is an expired one-shot timer that has not been restarted. + * + * Timers are created in the dormant state. The xTimerStart(), xTimerReset(), + * xTimerStartFromISR(), xTimerResetFromISR(), xTimerChangePeriod() and + * xTimerChangePeriodFromISR() API functions can all be used to transition a timer into the + * active state. + * + * @param xTimer The timer being queried. + * + * @return pdFALSE will be returned if the timer is dormant. A value other than + * pdFALSE will be returned if the timer is active. + * + * Example usage: + * @verbatim + * // This function assumes xTimer has already been created. + * void vAFunction( TimerHandle_t xTimer ) + * { + * if( xTimerIsTimerActive( xTimer ) != pdFALSE ) // or more simply and equivalently "if( xTimerIsTimerActive( xTimer ) )" + * { + * // xTimer is active, do something. + * } + * else + * { + * // xTimer is not active, do something else. + * } + * } + * @endverbatim + */ +BaseType_t xTimerIsTimerActive( TimerHandle_t xTimer ) PRIVILEGED_FUNCTION; + +/** + * TaskHandle_t xTimerGetTimerDaemonTaskHandle( void ); + * + * xTimerGetTimerDaemonTaskHandle() is only available if + * INCLUDE_xTimerGetTimerDaemonTaskHandle is set to 1 in FreeRTOSConfig.h. + * + * Simply returns the handle of the timer service/daemon task. It it not valid + * to call xTimerGetTimerDaemonTaskHandle() before the scheduler has been started. + */ +TaskHandle_t xTimerGetTimerDaemonTaskHandle( void ); + +/** + * BaseType_t xTimerStart( TimerHandle_t xTimer, TickType_t xTicksToWait ); + * + * Timer functionality is provided by a timer service/daemon task. Many of the + * public FreeRTOS timer API functions send commands to the timer service task + * through a queue called the timer command queue. The timer command queue is + * private to the kernel itself and is not directly accessible to application + * code. The length of the timer command queue is set by the + * configTIMER_QUEUE_LENGTH configuration constant. + * + * xTimerStart() starts a timer that was previously created using the + * xTimerCreate() API function. If the timer had already been started and was + * already in the active state, then xTimerStart() has equivalent functionality + * to the xTimerReset() API function. + * + * Starting a timer ensures the timer is in the active state. If the timer + * is not stopped, deleted, or reset in the mean time, the callback function + * associated with the timer will get called 'n' ticks after xTimerStart() was + * called, where 'n' is the timers defined period. + * + * It is valid to call xTimerStart() before the scheduler has been started, but + * when this is done the timer will not actually start until the scheduler is + * started, and the timers expiry time will be relative to when the scheduler is + * started, not relative to when xTimerStart() was called. + * + * The configUSE_TIMERS configuration constant must be set to 1 for xTimerStart() + * to be available. + * + * @param xTimer The handle of the timer being started/restarted. + * + * @param xTicksToWait Specifies the time, in ticks, that the calling task should + * be held in the Blocked state to wait for the start command to be successfully + * sent to the timer command queue, should the queue already be full when + * xTimerStart() was called. xTicksToWait is ignored if xTimerStart() is called + * before the scheduler is started. + * + * @return pdFAIL will be returned if the start command could not be sent to + * the timer command queue even after xTicksToWait ticks had passed. pdPASS will + * be returned if the command was successfully sent to the timer command queue. + * When the command is actually processed will depend on the priority of the + * timer service/daemon task relative to other tasks in the system, although the + * timers expiry time is relative to when xTimerStart() is actually called. The + * timer service/daemon task priority is set by the configTIMER_TASK_PRIORITY + * configuration constant. + * + * Example usage: + * + * See the xTimerCreate() API function example usage scenario. + * + */ +#define xTimerStart( xTimer, xTicksToWait ) xTimerGenericCommand( ( xTimer ), tmrCOMMAND_START, ( xTaskGetTickCount() ), NULL, ( xTicksToWait ) ) + +/** + * BaseType_t xTimerStop( TimerHandle_t xTimer, TickType_t xTicksToWait ); + * + * Timer functionality is provided by a timer service/daemon task. Many of the + * public FreeRTOS timer API functions send commands to the timer service task + * through a queue called the timer command queue. The timer command queue is + * private to the kernel itself and is not directly accessible to application + * code. The length of the timer command queue is set by the + * configTIMER_QUEUE_LENGTH configuration constant. + * + * xTimerStop() stops a timer that was previously started using either of the + * The xTimerStart(), xTimerReset(), xTimerStartFromISR(), xTimerResetFromISR(), + * xTimerChangePeriod() or xTimerChangePeriodFromISR() API functions. + * + * Stopping a timer ensures the timer is not in the active state. + * + * The configUSE_TIMERS configuration constant must be set to 1 for xTimerStop() + * to be available. + * + * @param xTimer The handle of the timer being stopped. + * + * @param xTicksToWait Specifies the time, in ticks, that the calling task should + * be held in the Blocked state to wait for the stop command to be successfully + * sent to the timer command queue, should the queue already be full when + * xTimerStop() was called. xTicksToWait is ignored if xTimerStop() is called + * before the scheduler is started. + * + * @return pdFAIL will be returned if the stop command could not be sent to + * the timer command queue even after xTicksToWait ticks had passed. pdPASS will + * be returned if the command was successfully sent to the timer command queue. + * When the command is actually processed will depend on the priority of the + * timer service/daemon task relative to other tasks in the system. The timer + * service/daemon task priority is set by the configTIMER_TASK_PRIORITY + * configuration constant. + * + * Example usage: + * + * See the xTimerCreate() API function example usage scenario. + * + */ +#define xTimerStop( xTimer, xTicksToWait ) xTimerGenericCommand( ( xTimer ), tmrCOMMAND_STOP, 0U, NULL, ( xTicksToWait ) ) + +/** + * BaseType_t xTimerChangePeriod( TimerHandle_t xTimer, + * TickType_t xNewPeriod, + * TickType_t xTicksToWait ); + * + * Timer functionality is provided by a timer service/daemon task. Many of the + * public FreeRTOS timer API functions send commands to the timer service task + * through a queue called the timer command queue. The timer command queue is + * private to the kernel itself and is not directly accessible to application + * code. The length of the timer command queue is set by the + * configTIMER_QUEUE_LENGTH configuration constant. + * + * xTimerChangePeriod() changes the period of a timer that was previously + * created using the xTimerCreate() API function. + * + * xTimerChangePeriod() can be called to change the period of an active or + * dormant state timer. + * + * The configUSE_TIMERS configuration constant must be set to 1 for + * xTimerChangePeriod() to be available. + * + * @param xTimer The handle of the timer that is having its period changed. + * + * @param xNewPeriod The new period for xTimer. Timer periods are specified in + * tick periods, so the constant portTICK_PERIOD_MS can be used to convert a time + * that has been specified in milliseconds. For example, if the timer must + * expire after 100 ticks, then xNewPeriod should be set to 100. Alternatively, + * if the timer must expire after 500ms, then xNewPeriod can be set to + * ( 500 / portTICK_PERIOD_MS ) provided configTICK_RATE_HZ is less than + * or equal to 1000. + * + * @param xTicksToWait Specifies the time, in ticks, that the calling task should + * be held in the Blocked state to wait for the change period command to be + * successfully sent to the timer command queue, should the queue already be + * full when xTimerChangePeriod() was called. xTicksToWait is ignored if + * xTimerChangePeriod() is called before the scheduler is started. + * + * @return pdFAIL will be returned if the change period command could not be + * sent to the timer command queue even after xTicksToWait ticks had passed. + * pdPASS will be returned if the command was successfully sent to the timer + * command queue. When the command is actually processed will depend on the + * priority of the timer service/daemon task relative to other tasks in the + * system. The timer service/daemon task priority is set by the + * configTIMER_TASK_PRIORITY configuration constant. + * + * Example usage: + * @verbatim + * // This function assumes xTimer has already been created. If the timer + * // referenced by xTimer is already active when it is called, then the timer + * // is deleted. If the timer referenced by xTimer is not active when it is + * // called, then the period of the timer is set to 500ms and the timer is + * // started. + * void vAFunction( TimerHandle_t xTimer ) + * { + * if( xTimerIsTimerActive( xTimer ) != pdFALSE ) // or more simply and equivalently "if( xTimerIsTimerActive( xTimer ) )" + * { + * // xTimer is already active - delete it. + * xTimerDelete( xTimer ); + * } + * else + * { + * // xTimer is not active, change its period to 500ms. This will also + * // cause the timer to start. Block for a maximum of 100 ticks if the + * // change period command cannot immediately be sent to the timer + * // command queue. + * if( xTimerChangePeriod( xTimer, 500 / portTICK_PERIOD_MS, 100 ) == pdPASS ) + * { + * // The command was successfully sent. + * } + * else + * { + * // The command could not be sent, even after waiting for 100 ticks + * // to pass. Take appropriate action here. + * } + * } + * } + * @endverbatim + */ + #define xTimerChangePeriod( xTimer, xNewPeriod, xTicksToWait ) xTimerGenericCommand( ( xTimer ), tmrCOMMAND_CHANGE_PERIOD, ( xNewPeriod ), NULL, ( xTicksToWait ) ) + +/** + * BaseType_t xTimerDelete( TimerHandle_t xTimer, TickType_t xTicksToWait ); + * + * Timer functionality is provided by a timer service/daemon task. Many of the + * public FreeRTOS timer API functions send commands to the timer service task + * through a queue called the timer command queue. The timer command queue is + * private to the kernel itself and is not directly accessible to application + * code. The length of the timer command queue is set by the + * configTIMER_QUEUE_LENGTH configuration constant. + * + * xTimerDelete() deletes a timer that was previously created using the + * xTimerCreate() API function. + * + * The configUSE_TIMERS configuration constant must be set to 1 for + * xTimerDelete() to be available. + * + * @param xTimer The handle of the timer being deleted. + * + * @param xTicksToWait Specifies the time, in ticks, that the calling task should + * be held in the Blocked state to wait for the delete command to be + * successfully sent to the timer command queue, should the queue already be + * full when xTimerDelete() was called. xTicksToWait is ignored if xTimerDelete() + * is called before the scheduler is started. + * + * @return pdFAIL will be returned if the delete command could not be sent to + * the timer command queue even after xTicksToWait ticks had passed. pdPASS will + * be returned if the command was successfully sent to the timer command queue. + * When the command is actually processed will depend on the priority of the + * timer service/daemon task relative to other tasks in the system. The timer + * service/daemon task priority is set by the configTIMER_TASK_PRIORITY + * configuration constant. + * + * Example usage: + * + * See the xTimerChangePeriod() API function example usage scenario. + */ +#define xTimerDelete( xTimer, xTicksToWait ) xTimerGenericCommand( ( xTimer ), tmrCOMMAND_DELETE, 0U, NULL, ( xTicksToWait ) ) + +/** + * BaseType_t xTimerReset( TimerHandle_t xTimer, TickType_t xTicksToWait ); + * + * Timer functionality is provided by a timer service/daemon task. Many of the + * public FreeRTOS timer API functions send commands to the timer service task + * through a queue called the timer command queue. The timer command queue is + * private to the kernel itself and is not directly accessible to application + * code. The length of the timer command queue is set by the + * configTIMER_QUEUE_LENGTH configuration constant. + * + * xTimerReset() re-starts a timer that was previously created using the + * xTimerCreate() API function. If the timer had already been started and was + * already in the active state, then xTimerReset() will cause the timer to + * re-evaluate its expiry time so that it is relative to when xTimerReset() was + * called. If the timer was in the dormant state then xTimerReset() has + * equivalent functionality to the xTimerStart() API function. + * + * Resetting a timer ensures the timer is in the active state. If the timer + * is not stopped, deleted, or reset in the mean time, the callback function + * associated with the timer will get called 'n' ticks after xTimerReset() was + * called, where 'n' is the timers defined period. + * + * It is valid to call xTimerReset() before the scheduler has been started, but + * when this is done the timer will not actually start until the scheduler is + * started, and the timers expiry time will be relative to when the scheduler is + * started, not relative to when xTimerReset() was called. + * + * The configUSE_TIMERS configuration constant must be set to 1 for xTimerReset() + * to be available. + * + * @param xTimer The handle of the timer being reset/started/restarted. + * + * @param xTicksToWait Specifies the time, in ticks, that the calling task should + * be held in the Blocked state to wait for the reset command to be successfully + * sent to the timer command queue, should the queue already be full when + * xTimerReset() was called. xTicksToWait is ignored if xTimerReset() is called + * before the scheduler is started. + * + * @return pdFAIL will be returned if the reset command could not be sent to + * the timer command queue even after xTicksToWait ticks had passed. pdPASS will + * be returned if the command was successfully sent to the timer command queue. + * When the command is actually processed will depend on the priority of the + * timer service/daemon task relative to other tasks in the system, although the + * timers expiry time is relative to when xTimerStart() is actually called. The + * timer service/daemon task priority is set by the configTIMER_TASK_PRIORITY + * configuration constant. + * + * Example usage: + * @verbatim + * // When a key is pressed, an LCD back-light is switched on. If 5 seconds pass + * // without a key being pressed, then the LCD back-light is switched off. In + * // this case, the timer is a one-shot timer. + * + * TimerHandle_t xBacklightTimer = NULL; + * + * // The callback function assigned to the one-shot timer. In this case the + * // parameter is not used. + * void vBacklightTimerCallback( TimerHandle_t pxTimer ) + * { + * // The timer expired, therefore 5 seconds must have passed since a key + * // was pressed. Switch off the LCD back-light. + * vSetBacklightState( BACKLIGHT_OFF ); + * } + * + * // The key press event handler. + * void vKeyPressEventHandler( char cKey ) + * { + * // Ensure the LCD back-light is on, then reset the timer that is + * // responsible for turning the back-light off after 5 seconds of + * // key inactivity. Wait 10 ticks for the command to be successfully sent + * // if it cannot be sent immediately. + * vSetBacklightState( BACKLIGHT_ON ); + * if( xTimerReset( xBacklightTimer, 100 ) != pdPASS ) + * { + * // The reset command was not executed successfully. Take appropriate + * // action here. + * } + * + * // Perform the rest of the key processing here. + * } + * + * void main( void ) + * { + * int32_t x; + * + * // Create then start the one-shot timer that is responsible for turning + * // the back-light off if no keys are pressed within a 5 second period. + * xBacklightTimer = xTimerCreate( "BacklightTimer", // Just a text name, not used by the kernel. + * ( 5000 / portTICK_PERIOD_MS), // The timer period in ticks. + * pdFALSE, // The timer is a one-shot timer. + * 0, // The id is not used by the callback so can take any value. + * vBacklightTimerCallback // The callback function that switches the LCD back-light off. + * ); + * + * if( xBacklightTimer == NULL ) + * { + * // The timer was not created. + * } + * else + * { + * // Start the timer. No block time is specified, and even if one was + * // it would be ignored because the scheduler has not yet been + * // started. + * if( xTimerStart( xBacklightTimer, 0 ) != pdPASS ) + * { + * // The timer could not be set into the Active state. + * } + * } + * + * // ... + * // Create tasks here. + * // ... + * + * // Starting the scheduler will start the timer running as it has already + * // been set into the active state. + * xTaskStartScheduler(); + * + * // Should not reach here. + * for( ;; ); + * } + * @endverbatim + */ +#define xTimerReset( xTimer, xTicksToWait ) xTimerGenericCommand( ( xTimer ), tmrCOMMAND_RESET, ( xTaskGetTickCount() ), NULL, ( xTicksToWait ) ) + +/** + * BaseType_t xTimerStartFromISR( TimerHandle_t xTimer, + * BaseType_t *pxHigherPriorityTaskWoken ); + * + * A version of xTimerStart() that can be called from an interrupt service + * routine. + * + * @param xTimer The handle of the timer being started/restarted. + * + * @param pxHigherPriorityTaskWoken The timer service/daemon task spends most + * of its time in the Blocked state, waiting for messages to arrive on the timer + * command queue. Calling xTimerStartFromISR() writes a message to the timer + * command queue, so has the potential to transition the timer service/daemon + * task out of the Blocked state. If calling xTimerStartFromISR() causes the + * timer service/daemon task to leave the Blocked state, and the timer service/ + * daemon task has a priority equal to or greater than the currently executing + * task (the task that was interrupted), then *pxHigherPriorityTaskWoken will + * get set to pdTRUE internally within the xTimerStartFromISR() function. If + * xTimerStartFromISR() sets this value to pdTRUE then a context switch should + * be performed before the interrupt exits. + * + * @return pdFAIL will be returned if the start command could not be sent to + * the timer command queue. pdPASS will be returned if the command was + * successfully sent to the timer command queue. When the command is actually + * processed will depend on the priority of the timer service/daemon task + * relative to other tasks in the system, although the timers expiry time is + * relative to when xTimerStartFromISR() is actually called. The timer + * service/daemon task priority is set by the configTIMER_TASK_PRIORITY + * configuration constant. + * + * Example usage: + * @verbatim + * // This scenario assumes xBacklightTimer has already been created. When a + * // key is pressed, an LCD back-light is switched on. If 5 seconds pass + * // without a key being pressed, then the LCD back-light is switched off. In + * // this case, the timer is a one-shot timer, and unlike the example given for + * // the xTimerReset() function, the key press event handler is an interrupt + * // service routine. + * + * // The callback function assigned to the one-shot timer. In this case the + * // parameter is not used. + * void vBacklightTimerCallback( TimerHandle_t pxTimer ) + * { + * // The timer expired, therefore 5 seconds must have passed since a key + * // was pressed. Switch off the LCD back-light. + * vSetBacklightState( BACKLIGHT_OFF ); + * } + * + * // The key press interrupt service routine. + * void vKeyPressEventInterruptHandler( void ) + * { + * BaseType_t xHigherPriorityTaskWoken = pdFALSE; + * + * // Ensure the LCD back-light is on, then restart the timer that is + * // responsible for turning the back-light off after 5 seconds of + * // key inactivity. This is an interrupt service routine so can only + * // call FreeRTOS API functions that end in "FromISR". + * vSetBacklightState( BACKLIGHT_ON ); + * + * // xTimerStartFromISR() or xTimerResetFromISR() could be called here + * // as both cause the timer to re-calculate its expiry time. + * // xHigherPriorityTaskWoken was initialised to pdFALSE when it was + * // declared (in this function). + * if( xTimerStartFromISR( xBacklightTimer, &xHigherPriorityTaskWoken ) != pdPASS ) + * { + * // The start command was not executed successfully. Take appropriate + * // action here. + * } + * + * // Perform the rest of the key processing here. + * + * // If xHigherPriorityTaskWoken equals pdTRUE, then a context switch + * // should be performed. The syntax required to perform a context switch + * // from inside an ISR varies from port to port, and from compiler to + * // compiler. Inspect the demos for the port you are using to find the + * // actual syntax required. + * if( xHigherPriorityTaskWoken != pdFALSE ) + * { + * // Call the interrupt safe yield function here (actual function + * // depends on the FreeRTOS port being used). + * } + * } + * @endverbatim + */ +#define xTimerStartFromISR( xTimer, pxHigherPriorityTaskWoken ) xTimerGenericCommand( ( xTimer ), tmrCOMMAND_START_FROM_ISR, ( xTaskGetTickCountFromISR() ), ( pxHigherPriorityTaskWoken ), 0U ) + +/** + * BaseType_t xTimerStopFromISR( TimerHandle_t xTimer, + * BaseType_t *pxHigherPriorityTaskWoken ); + * + * A version of xTimerStop() that can be called from an interrupt service + * routine. + * + * @param xTimer The handle of the timer being stopped. + * + * @param pxHigherPriorityTaskWoken The timer service/daemon task spends most + * of its time in the Blocked state, waiting for messages to arrive on the timer + * command queue. Calling xTimerStopFromISR() writes a message to the timer + * command queue, so has the potential to transition the timer service/daemon + * task out of the Blocked state. If calling xTimerStopFromISR() causes the + * timer service/daemon task to leave the Blocked state, and the timer service/ + * daemon task has a priority equal to or greater than the currently executing + * task (the task that was interrupted), then *pxHigherPriorityTaskWoken will + * get set to pdTRUE internally within the xTimerStopFromISR() function. If + * xTimerStopFromISR() sets this value to pdTRUE then a context switch should + * be performed before the interrupt exits. + * + * @return pdFAIL will be returned if the stop command could not be sent to + * the timer command queue. pdPASS will be returned if the command was + * successfully sent to the timer command queue. When the command is actually + * processed will depend on the priority of the timer service/daemon task + * relative to other tasks in the system. The timer service/daemon task + * priority is set by the configTIMER_TASK_PRIORITY configuration constant. + * + * Example usage: + * @verbatim + * // This scenario assumes xTimer has already been created and started. When + * // an interrupt occurs, the timer should be simply stopped. + * + * // The interrupt service routine that stops the timer. + * void vAnExampleInterruptServiceRoutine( void ) + * { + * BaseType_t xHigherPriorityTaskWoken = pdFALSE; + * + * // The interrupt has occurred - simply stop the timer. + * // xHigherPriorityTaskWoken was set to pdFALSE where it was defined + * // (within this function). As this is an interrupt service routine, only + * // FreeRTOS API functions that end in "FromISR" can be used. + * if( xTimerStopFromISR( xTimer, &xHigherPriorityTaskWoken ) != pdPASS ) + * { + * // The stop command was not executed successfully. Take appropriate + * // action here. + * } + * + * // If xHigherPriorityTaskWoken equals pdTRUE, then a context switch + * // should be performed. The syntax required to perform a context switch + * // from inside an ISR varies from port to port, and from compiler to + * // compiler. Inspect the demos for the port you are using to find the + * // actual syntax required. + * if( xHigherPriorityTaskWoken != pdFALSE ) + * { + * // Call the interrupt safe yield function here (actual function + * // depends on the FreeRTOS port being used). + * } + * } + * @endverbatim + */ +#define xTimerStopFromISR( xTimer, pxHigherPriorityTaskWoken ) xTimerGenericCommand( ( xTimer ), tmrCOMMAND_STOP_FROM_ISR, 0, ( pxHigherPriorityTaskWoken ), 0U ) + +/** + * BaseType_t xTimerChangePeriodFromISR( TimerHandle_t xTimer, + * TickType_t xNewPeriod, + * BaseType_t *pxHigherPriorityTaskWoken ); + * + * A version of xTimerChangePeriod() that can be called from an interrupt + * service routine. + * + * @param xTimer The handle of the timer that is having its period changed. + * + * @param xNewPeriod The new period for xTimer. Timer periods are specified in + * tick periods, so the constant portTICK_PERIOD_MS can be used to convert a time + * that has been specified in milliseconds. For example, if the timer must + * expire after 100 ticks, then xNewPeriod should be set to 100. Alternatively, + * if the timer must expire after 500ms, then xNewPeriod can be set to + * ( 500 / portTICK_PERIOD_MS ) provided configTICK_RATE_HZ is less than + * or equal to 1000. + * + * @param pxHigherPriorityTaskWoken The timer service/daemon task spends most + * of its time in the Blocked state, waiting for messages to arrive on the timer + * command queue. Calling xTimerChangePeriodFromISR() writes a message to the + * timer command queue, so has the potential to transition the timer service/ + * daemon task out of the Blocked state. If calling xTimerChangePeriodFromISR() + * causes the timer service/daemon task to leave the Blocked state, and the + * timer service/daemon task has a priority equal to or greater than the + * currently executing task (the task that was interrupted), then + * *pxHigherPriorityTaskWoken will get set to pdTRUE internally within the + * xTimerChangePeriodFromISR() function. If xTimerChangePeriodFromISR() sets + * this value to pdTRUE then a context switch should be performed before the + * interrupt exits. + * + * @return pdFAIL will be returned if the command to change the timers period + * could not be sent to the timer command queue. pdPASS will be returned if the + * command was successfully sent to the timer command queue. When the command + * is actually processed will depend on the priority of the timer service/daemon + * task relative to other tasks in the system. The timer service/daemon task + * priority is set by the configTIMER_TASK_PRIORITY configuration constant. + * + * Example usage: + * @verbatim + * // This scenario assumes xTimer has already been created and started. When + * // an interrupt occurs, the period of xTimer should be changed to 500ms. + * + * // The interrupt service routine that changes the period of xTimer. + * void vAnExampleInterruptServiceRoutine( void ) + * { + * BaseType_t xHigherPriorityTaskWoken = pdFALSE; + * + * // The interrupt has occurred - change the period of xTimer to 500ms. + * // xHigherPriorityTaskWoken was set to pdFALSE where it was defined + * // (within this function). As this is an interrupt service routine, only + * // FreeRTOS API functions that end in "FromISR" can be used. + * if( xTimerChangePeriodFromISR( xTimer, &xHigherPriorityTaskWoken ) != pdPASS ) + * { + * // The command to change the timers period was not executed + * // successfully. Take appropriate action here. + * } + * + * // If xHigherPriorityTaskWoken equals pdTRUE, then a context switch + * // should be performed. The syntax required to perform a context switch + * // from inside an ISR varies from port to port, and from compiler to + * // compiler. Inspect the demos for the port you are using to find the + * // actual syntax required. + * if( xHigherPriorityTaskWoken != pdFALSE ) + * { + * // Call the interrupt safe yield function here (actual function + * // depends on the FreeRTOS port being used). + * } + * } + * @endverbatim + */ +#define xTimerChangePeriodFromISR( xTimer, xNewPeriod, pxHigherPriorityTaskWoken ) xTimerGenericCommand( ( xTimer ), tmrCOMMAND_CHANGE_PERIOD_FROM_ISR, ( xNewPeriod ), ( pxHigherPriorityTaskWoken ), 0U ) + +/** + * BaseType_t xTimerResetFromISR( TimerHandle_t xTimer, + * BaseType_t *pxHigherPriorityTaskWoken ); + * + * A version of xTimerReset() that can be called from an interrupt service + * routine. + * + * @param xTimer The handle of the timer that is to be started, reset, or + * restarted. + * + * @param pxHigherPriorityTaskWoken The timer service/daemon task spends most + * of its time in the Blocked state, waiting for messages to arrive on the timer + * command queue. Calling xTimerResetFromISR() writes a message to the timer + * command queue, so has the potential to transition the timer service/daemon + * task out of the Blocked state. If calling xTimerResetFromISR() causes the + * timer service/daemon task to leave the Blocked state, and the timer service/ + * daemon task has a priority equal to or greater than the currently executing + * task (the task that was interrupted), then *pxHigherPriorityTaskWoken will + * get set to pdTRUE internally within the xTimerResetFromISR() function. If + * xTimerResetFromISR() sets this value to pdTRUE then a context switch should + * be performed before the interrupt exits. + * + * @return pdFAIL will be returned if the reset command could not be sent to + * the timer command queue. pdPASS will be returned if the command was + * successfully sent to the timer command queue. When the command is actually + * processed will depend on the priority of the timer service/daemon task + * relative to other tasks in the system, although the timers expiry time is + * relative to when xTimerResetFromISR() is actually called. The timer service/daemon + * task priority is set by the configTIMER_TASK_PRIORITY configuration constant. + * + * Example usage: + * @verbatim + * // This scenario assumes xBacklightTimer has already been created. When a + * // key is pressed, an LCD back-light is switched on. If 5 seconds pass + * // without a key being pressed, then the LCD back-light is switched off. In + * // this case, the timer is a one-shot timer, and unlike the example given for + * // the xTimerReset() function, the key press event handler is an interrupt + * // service routine. + * + * // The callback function assigned to the one-shot timer. In this case the + * // parameter is not used. + * void vBacklightTimerCallback( TimerHandle_t pxTimer ) + * { + * // The timer expired, therefore 5 seconds must have passed since a key + * // was pressed. Switch off the LCD back-light. + * vSetBacklightState( BACKLIGHT_OFF ); + * } + * + * // The key press interrupt service routine. + * void vKeyPressEventInterruptHandler( void ) + * { + * BaseType_t xHigherPriorityTaskWoken = pdFALSE; + * + * // Ensure the LCD back-light is on, then reset the timer that is + * // responsible for turning the back-light off after 5 seconds of + * // key inactivity. This is an interrupt service routine so can only + * // call FreeRTOS API functions that end in "FromISR". + * vSetBacklightState( BACKLIGHT_ON ); + * + * // xTimerStartFromISR() or xTimerResetFromISR() could be called here + * // as both cause the timer to re-calculate its expiry time. + * // xHigherPriorityTaskWoken was initialised to pdFALSE when it was + * // declared (in this function). + * if( xTimerResetFromISR( xBacklightTimer, &xHigherPriorityTaskWoken ) != pdPASS ) + * { + * // The reset command was not executed successfully. Take appropriate + * // action here. + * } + * + * // Perform the rest of the key processing here. + * + * // If xHigherPriorityTaskWoken equals pdTRUE, then a context switch + * // should be performed. The syntax required to perform a context switch + * // from inside an ISR varies from port to port, and from compiler to + * // compiler. Inspect the demos for the port you are using to find the + * // actual syntax required. + * if( xHigherPriorityTaskWoken != pdFALSE ) + * { + * // Call the interrupt safe yield function here (actual function + * // depends on the FreeRTOS port being used). + * } + * } + * @endverbatim + */ +#define xTimerResetFromISR( xTimer, pxHigherPriorityTaskWoken ) xTimerGenericCommand( ( xTimer ), tmrCOMMAND_RESET_FROM_ISR, ( xTaskGetTickCountFromISR() ), ( pxHigherPriorityTaskWoken ), 0U ) + + +/** + * BaseType_t xTimerPendFunctionCallFromISR( PendedFunction_t xFunctionToPend, + * void *pvParameter1, + * uint32_t ulParameter2, + * BaseType_t *pxHigherPriorityTaskWoken ); + * + * + * Used from application interrupt service routines to defer the execution of a + * function to the RTOS daemon task (the timer service task, hence this function + * is implemented in timers.c and is prefixed with 'Timer'). + * + * Ideally an interrupt service routine (ISR) is kept as short as possible, but + * sometimes an ISR either has a lot of processing to do, or needs to perform + * processing that is not deterministic. In these cases + * xTimerPendFunctionCallFromISR() can be used to defer processing of a function + * to the RTOS daemon task. + * + * A mechanism is provided that allows the interrupt to return directly to the + * task that will subsequently execute the pended callback function. This + * allows the callback function to execute contiguously in time with the + * interrupt - just as if the callback had executed in the interrupt itself. + * + * @param xFunctionToPend The function to execute from the timer service/ + * daemon task. The function must conform to the PendedFunction_t + * prototype. + * + * @param pvParameter1 The value of the callback function's first parameter. + * The parameter has a void * type to allow it to be used to pass any type. + * For example, unsigned longs can be cast to a void *, or the void * can be + * used to point to a structure. + * + * @param ulParameter2 The value of the callback function's second parameter. + * + * @param pxHigherPriorityTaskWoken As mentioned above, calling this function + * will result in a message being sent to the timer daemon task. If the + * priority of the timer daemon task (which is set using + * configTIMER_TASK_PRIORITY in FreeRTOSConfig.h) is higher than the priority of + * the currently running task (the task the interrupt interrupted) then + * *pxHigherPriorityTaskWoken will be set to pdTRUE within + * xTimerPendFunctionCallFromISR(), indicating that a context switch should be + * requested before the interrupt exits. For that reason + * *pxHigherPriorityTaskWoken must be initialised to pdFALSE. See the + * example code below. + * + * @return pdPASS is returned if the message was successfully sent to the + * timer daemon task, otherwise pdFALSE is returned. + * + * Example usage: + * @verbatim + * + * // The callback function that will execute in the context of the daemon task. + * // Note callback functions must all use this same prototype. + * void vProcessInterface( void *pvParameter1, uint32_t ulParameter2 ) + * { + * BaseType_t xInterfaceToService; + * + * // The interface that requires servicing is passed in the second + * // parameter. The first parameter is not used in this case. + * xInterfaceToService = ( BaseType_t ) ulParameter2; + * + * // ...Perform the processing here... + * } + * + * // An ISR that receives data packets from multiple interfaces + * void vAnISR( void ) + * { + * BaseType_t xInterfaceToService, xHigherPriorityTaskWoken; + * + * // Query the hardware to determine which interface needs processing. + * xInterfaceToService = prvCheckInterfaces(); + * + * // The actual processing is to be deferred to a task. Request the + * // vProcessInterface() callback function is executed, passing in the + * // number of the interface that needs processing. The interface to + * // service is passed in the second parameter. The first parameter is + * // not used in this case. + * xHigherPriorityTaskWoken = pdFALSE; + * xTimerPendFunctionCallFromISR( vProcessInterface, NULL, ( uint32_t ) xInterfaceToService, &xHigherPriorityTaskWoken ); + * + * // If xHigherPriorityTaskWoken is now set to pdTRUE then a context + * // switch should be requested. The macro used is port specific and will + * // be either portYIELD_FROM_ISR() or portEND_SWITCHING_ISR() - refer to + * // the documentation page for the port being used. + * portYIELD_FROM_ISR( xHigherPriorityTaskWoken ); + * + * } + * @endverbatim + */ +BaseType_t xTimerPendFunctionCallFromISR( PendedFunction_t xFunctionToPend, void *pvParameter1, uint32_t ulParameter2, BaseType_t *pxHigherPriorityTaskWoken ); + + /** + * BaseType_t xTimerPendFunctionCall( PendedFunction_t xFunctionToPend, + * void *pvParameter1, + * uint32_t ulParameter2, + * TickType_t xTicksToWait ); + * + * + * Used to defer the execution of a function to the RTOS daemon task (the timer + * service task, hence this function is implemented in timers.c and is prefixed + * with 'Timer'). + * + * @param xFunctionToPend The function to execute from the timer service/ + * daemon task. The function must conform to the PendedFunction_t + * prototype. + * + * @param pvParameter1 The value of the callback function's first parameter. + * The parameter has a void * type to allow it to be used to pass any type. + * For example, unsigned longs can be cast to a void *, or the void * can be + * used to point to a structure. + * + * @param ulParameter2 The value of the callback function's second parameter. + * + * @param xTicksToWait Calling this function will result in a message being + * sent to the timer daemon task on a queue. xTicksToWait is the amount of + * time the calling task should remain in the Blocked state (so not using any + * processing time) for space to become available on the timer queue if the + * queue is found to be full. + * + * @return pdPASS is returned if the message was successfully sent to the + * timer daemon task, otherwise pdFALSE is returned. + * + */ +BaseType_t xTimerPendFunctionCall( PendedFunction_t xFunctionToPend, void *pvParameter1, uint32_t ulParameter2, TickType_t xTicksToWait ); + +/** + * const char * const pcTimerGetTimerName( TimerHandle_t xTimer ); + * + * Returns the name that was assigned to a timer when the timer was created. + * + * @param xTimer The handle of the timer being queried. + * + * @return The name assigned to the timer specified by the xTimer parameter. + */ +const char * pcTimerGetTimerName( TimerHandle_t xTimer ); /*lint !e971 Unqualified char types are allowed for strings and single characters only. */ + +/* + * Functions beyond this part are not part of the public API and are intended + * for use by the kernel only. + */ +BaseType_t xTimerCreateTimerTask( void ) PRIVILEGED_FUNCTION; +BaseType_t xTimerGenericCommand( TimerHandle_t xTimer, const BaseType_t xCommandID, const TickType_t xOptionalValue, BaseType_t * const pxHigherPriorityTaskWoken, const TickType_t xTicksToWait ) PRIVILEGED_FUNCTION; + +#ifdef __cplusplus +} +#endif +#endif /* TIMERS_H */ + + + diff --git a/components/freertos/include/freertos/xtensa_api.h b/components/freertos/include/freertos/xtensa_api.h new file mode 100644 index 0000000000..04ad7d62d8 --- /dev/null +++ b/components/freertos/include/freertos/xtensa_api.h @@ -0,0 +1,118 @@ +/******************************************************************************* +Copyright (c) 2006-2015 Cadence Design Systems Inc. + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be included +in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +******************************************************************************/ + +/****************************************************************************** + Xtensa-specific API for RTOS ports. +******************************************************************************/ + +#ifndef __XTENSA_API_H__ +#define __XTENSA_API_H__ + +#include + +#include "xtensa_context.h" + + +/* Typedef for C-callable interrupt handler function */ +typedef void (*xt_handler)(void *); + +/* Typedef for C-callable exception handler function */ +typedef void (*xt_exc_handler)(XtExcFrame *); + + +/* +------------------------------------------------------------------------------- + Call this function to set a handler for the specified exception. + + n - Exception number (type) + f - Handler function address, NULL to uninstall handler. + + The handler will be passed a pointer to the exception frame, which is created + on the stack of the thread that caused the exception. + + If the handler returns, the thread context will be restored and the faulting + instruction will be retried. Any values in the exception frame that are + modified by the handler will be restored as part of the context. For details + of the exception frame structure see xtensa_context.h. +------------------------------------------------------------------------------- +*/ +extern xt_exc_handler xt_set_exception_handler(int n, xt_exc_handler f); + + +/* +------------------------------------------------------------------------------- + Call this function to set a handler for the specified interrupt. + + n - Interrupt number. + f - Handler function address, NULL to uninstall handler. + arg - Argument to be passed to handler. +------------------------------------------------------------------------------- +*/ +extern xt_handler xt_set_interrupt_handler(int n, xt_handler f, void * arg); + + +/* +------------------------------------------------------------------------------- + Call this function to enable the specified interrupts. + + mask - Bit mask of interrupts to be enabled. +------------------------------------------------------------------------------- +*/ +extern void xt_ints_on(unsigned int mask); + + +/* +------------------------------------------------------------------------------- + Call this function to disable the specified interrupts. + + mask - Bit mask of interrupts to be disabled. +------------------------------------------------------------------------------- +*/ +extern void xt_ints_off(unsigned int mask); + + +/* +------------------------------------------------------------------------------- + Call this function to set the specified (s/w) interrupt. +------------------------------------------------------------------------------- +*/ +static inline void xt_set_intset(unsigned int arg) +{ + xthal_set_intset(arg); +} + + +/* +------------------------------------------------------------------------------- + Call this function to clear the specified (s/w or edge-triggered) + interrupt. +------------------------------------------------------------------------------- +*/ +static inline void xt_set_intclear(unsigned int arg) +{ + xthal_set_intclear(arg); +} + + +#endif /* __XTENSA_API_H__ */ + diff --git a/components/freertos/include/freertos/xtensa_config.h b/components/freertos/include/freertos/xtensa_config.h new file mode 100644 index 0000000000..58baee2da7 --- /dev/null +++ b/components/freertos/include/freertos/xtensa_config.h @@ -0,0 +1,146 @@ +/******************************************************************************* +// Copyright (c) 2003-2015 Cadence Design Systems, Inc. +// +// Permission is hereby granted, free of charge, to any person obtaining +// a copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to +// permit persons to whom the Software is furnished to do so, subject to +// the following conditions: +// +// The above copyright notice and this permission notice shall be included +// in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +// CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +// SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +-------------------------------------------------------------------------------- + + Configuration-specific information for Xtensa build. This file must be + included in FreeRTOSConfig.h to properly set up the config-dependent + parameters correctly. + + NOTE: To enable thread-safe C library support, XT_USE_THREAD_SAFE_CLIB must + be defined to be > 0 somewhere above or on the command line. + +*******************************************************************************/ + +#ifndef XTENSA_CONFIG_H +#define XTENSA_CONFIG_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include +#include +#include /* required for XSHAL_CLIB */ + +#include "xtensa_context.h" + + +/*----------------------------------------------------------------------------- +* STACK REQUIREMENTS +* +* This section defines the minimum stack size, and the extra space required to +* be allocated for saving coprocessor state and/or C library state information +* (if thread safety is enabled for the C library). The sizes are in bytes. +* +* Stack sizes for individual tasks should be derived from these minima based on +* the maximum call depth of the task and the maximum level of interrupt nesting. +* A minimum stack size is defined by XT_STACK_MIN_SIZE. This minimum is based +* on the requirement for a task that calls nothing else but can be interrupted. +* This assumes that interrupt handlers do not call more than a few levels deep. +* If this is not true, i.e. one or more interrupt handlers make deep calls then +* the minimum must be increased. +* +* If the Xtensa processor configuration includes coprocessors, then space is +* allocated to save the coprocessor state on the stack. +* +* If thread safety is enabled for the C runtime library, (XT_USE_THREAD_SAFE_CLIB +* is defined) then space is allocated to save the C library context in the TCB. +* +* Allocating insufficient stack space is a common source of hard-to-find errors. +* During development, it is best to enable the FreeRTOS stack checking features. +* +* Usage: +* +* XT_USE_THREAD_SAFE_CLIB -- Define this to a nonzero value to enable thread-safe +* use of the C library. This will require extra stack +* space to be allocated for tasks that use the C library +* reentrant functions. See below for more information. +* +* NOTE: The Xtensa toolchain supports multiple C libraries and not all of them +* support thread safety. Check your core configuration to see which C library +* was chosen for your system. +* +* XT_STACK_MIN_SIZE -- The minimum stack size for any task. It is recommended +* that you do not use a stack smaller than this for any +* task. In case you want to use stacks smaller than this +* size, you must verify that the smaller size(s) will work +* under all operating conditions. +* +* XT_STACK_EXTRA -- The amount of extra stack space to allocate for a task +* that does not make C library reentrant calls. Add this +* to the amount of stack space required by the task itself. +* +* XT_STACK_EXTRA_CLIB -- The amount of space to allocate for C library state. +* +-----------------------------------------------------------------------------*/ + +/* Extra space required for interrupt/exception hooks. */ +#ifdef XT_INTEXC_HOOKS + #ifdef __XTENSA_CALL0_ABI__ + #define STK_INTEXC_EXTRA 0x200 + #else + #define STK_INTEXC_EXTRA 0x180 + #endif +#else + #define STK_INTEXC_EXTRA 0 +#endif + +#define XT_CLIB_CONTEXT_AREA_SIZE 0 + +/*------------------------------------------------------------------------------ + Extra size -- interrupt frame plus coprocessor save area plus hook space. + NOTE: Make sure XT_INTEXC_HOOKS is undefined unless you really need the hooks. +------------------------------------------------------------------------------*/ +#ifdef __XTENSA_CALL0_ABI__ + #define XT_XTRA_SIZE (XT_STK_FRMSZ + STK_INTEXC_EXTRA + 0x10 + XT_CP_SIZE) +#else + #define XT_XTRA_SIZE (XT_STK_FRMSZ + STK_INTEXC_EXTRA + 0x20 + XT_CP_SIZE) +#endif + +/*------------------------------------------------------------------------------ + Space allocated for user code -- function calls and local variables. + NOTE: This number can be adjusted to suit your needs. You must verify that the + amount of space you reserve is adequate for the worst-case conditions in your + application. + NOTE: The windowed ABI requires more stack, since space has to be reserved + for spilling register windows. +------------------------------------------------------------------------------*/ +#ifdef __XTENSA_CALL0_ABI__ + #define XT_USER_SIZE 0x200 +#else + #define XT_USER_SIZE 0x400 +#endif + +/* Minimum recommended stack size. */ +#define XT_STACK_MIN_SIZE ((XT_XTRA_SIZE + XT_USER_SIZE) / sizeof(unsigned char)) + +/* OS overhead with and without C library thread context. */ +#define XT_STACK_EXTRA (XT_XTRA_SIZE) +#define XT_STACK_EXTRA_CLIB (XT_XTRA_SIZE + XT_CLIB_CONTEXT_AREA_SIZE) + + +#ifdef __cplusplus +} +#endif + +#endif /* XTENSA_CONFIG_H */ + diff --git a/components/freertos/include/freertos/xtensa_context.h b/components/freertos/include/freertos/xtensa_context.h new file mode 100644 index 0000000000..3167c84726 --- /dev/null +++ b/components/freertos/include/freertos/xtensa_context.h @@ -0,0 +1,383 @@ +/******************************************************************************* +Copyright (c) 2006-2015 Cadence Design Systems Inc. + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be included +in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +-------------------------------------------------------------------------------- + + XTENSA CONTEXT FRAMES AND MACROS FOR RTOS ASSEMBLER SOURCES + +This header contains definitions and macros for use primarily by Xtensa +RTOS assembly coded source files. It includes and uses the Xtensa hardware +abstraction layer (HAL) to deal with config specifics. It may also be +included in C source files. + +!! Supports only Xtensa Exception Architecture 2 (XEA2). XEA1 not supported. !! + +NOTE: The Xtensa architecture requires stack pointer alignment to 16 bytes. + +*******************************************************************************/ + +#ifndef XTENSA_CONTEXT_H +#define XTENSA_CONTEXT_H + +#ifdef __ASSEMBLER__ +#include +#endif + +#include +#include +#include +#include + + +/* Align a value up to nearest n-byte boundary, where n is a power of 2. */ +#define ALIGNUP(n, val) (((val) + (n)-1) & -(n)) + + +/* +------------------------------------------------------------------------------- + Macros that help define structures for both C and assembler. +------------------------------------------------------------------------------- +*/ + +#ifdef STRUCT_BEGIN +#undef STRUCT_BEGIN +#undef STRUCT_FIELD +#undef STRUCT_AFIELD +#undef STRUCT_END +#endif + +#if defined(_ASMLANGUAGE) || defined(__ASSEMBLER__) + +#define STRUCT_BEGIN .pushsection .text; .struct 0 +#define STRUCT_FIELD(ctype,size,asname,name) asname: .space size +#define STRUCT_AFIELD(ctype,size,asname,name,n) asname: .space (size)*(n) +#define STRUCT_END(sname) sname##Size:; .popsection + +#else + +#define STRUCT_BEGIN typedef struct { +#define STRUCT_FIELD(ctype,size,asname,name) ctype name; +#define STRUCT_AFIELD(ctype,size,asname,name,n) ctype name[n]; +#define STRUCT_END(sname) } sname; + +#endif //_ASMLANGUAGE || __ASSEMBLER__ + + +/* +------------------------------------------------------------------------------- + INTERRUPT/EXCEPTION STACK FRAME FOR A THREAD OR NESTED INTERRUPT + + A stack frame of this structure is allocated for any interrupt or exception. + It goes on the current stack. If the RTOS has a system stack for handling + interrupts, every thread stack must allow space for just one interrupt stack + frame, then nested interrupt stack frames go on the system stack. + + The frame includes basic registers (explicit) and "extra" registers introduced + by user TIE or the use of the MAC16 option in the user's Xtensa config. + The frame size is minimized by omitting regs not applicable to user's config. + + For Windowed ABI, this stack frame includes the interruptee's base save area, + another base save area to manage gcc nested functions, and a little temporary + space to help manage the spilling of the register windows. +------------------------------------------------------------------------------- +*/ + +STRUCT_BEGIN +STRUCT_FIELD (long, 4, XT_STK_EXIT, exit) /* exit point for dispatch */ +STRUCT_FIELD (long, 4, XT_STK_PC, pc) /* return PC */ +STRUCT_FIELD (long, 4, XT_STK_PS, ps) /* return PS */ +STRUCT_FIELD (long, 4, XT_STK_A0, a0) +STRUCT_FIELD (long, 4, XT_STK_A1, a1) /* stack pointer before interrupt */ +STRUCT_FIELD (long, 4, XT_STK_A2, a2) +STRUCT_FIELD (long, 4, XT_STK_A3, a3) +STRUCT_FIELD (long, 4, XT_STK_A4, a4) +STRUCT_FIELD (long, 4, XT_STK_A5, a5) +STRUCT_FIELD (long, 4, XT_STK_A6, a6) +STRUCT_FIELD (long, 4, XT_STK_A7, a7) +STRUCT_FIELD (long, 4, XT_STK_A8, a8) +STRUCT_FIELD (long, 4, XT_STK_A9, a9) +STRUCT_FIELD (long, 4, XT_STK_A10, a10) +STRUCT_FIELD (long, 4, XT_STK_A11, a11) +STRUCT_FIELD (long, 4, XT_STK_A12, a12) +STRUCT_FIELD (long, 4, XT_STK_A13, a13) +STRUCT_FIELD (long, 4, XT_STK_A14, a14) +STRUCT_FIELD (long, 4, XT_STK_A15, a15) +STRUCT_FIELD (long, 4, XT_STK_SAR, sar) +STRUCT_FIELD (long, 4, XT_STK_EXCCAUSE, exccause) +STRUCT_FIELD (long, 4, XT_STK_EXCVADDR, excvaddr) +#if XCHAL_HAVE_LOOPS +STRUCT_FIELD (long, 4, XT_STK_LBEG, lbeg) +STRUCT_FIELD (long, 4, XT_STK_LEND, lend) +STRUCT_FIELD (long, 4, XT_STK_LCOUNT, lcount) +#endif +#ifndef __XTENSA_CALL0_ABI__ +/* Temporary space for saving stuff during window spill */ +STRUCT_FIELD (long, 4, XT_STK_TMP0, tmp0) +STRUCT_FIELD (long, 4, XT_STK_TMP1, tmp1) +STRUCT_FIELD (long, 4, XT_STK_TMP2, tmp2) +#endif +#ifdef XT_USE_SWPRI +/* Storage for virtual priority mask */ +STRUCT_FIELD (long, 4, XT_STK_VPRI, vpri) +#endif +#ifdef XT_USE_OVLY +/* Storage for overlay state */ +STRUCT_FIELD (long, 4, XT_STK_OVLY, ovly) +#endif +STRUCT_END(XtExcFrame) + +#if defined(_ASMLANGUAGE) || defined(__ASSEMBLER__) +#define XT_STK_NEXT1 XtExcFrameSize +#else +#define XT_STK_NEXT1 sizeof(XtExcFrame) +#endif + +/* Allocate extra storage if needed */ +#if XCHAL_EXTRA_SA_SIZE != 0 + +#if XCHAL_EXTRA_SA_ALIGN <= 16 +#define XT_STK_EXTRA ALIGNUP(XCHAL_EXTRA_SA_ALIGN, XT_STK_NEXT1) +#else +/* If need more alignment than stack, add space for dynamic alignment */ +#define XT_STK_EXTRA (ALIGNUP(XCHAL_EXTRA_SA_ALIGN, XT_STK_NEXT1) + XCHAL_EXTRA_SA_ALIGN) +#endif +#define XT_STK_NEXT2 (XT_STK_EXTRA + XCHAL_EXTRA_SA_SIZE) + +#else + +#define XT_STK_NEXT2 XT_STK_NEXT1 + +#endif + +/* +------------------------------------------------------------------------------- + This is the frame size. Add space for 4 registers (interruptee's base save + area) and some space for gcc nested functions if any. +------------------------------------------------------------------------------- +*/ +#define XT_STK_FRMSZ (ALIGNUP(0x10, XT_STK_NEXT2) + 0x20) + + +/* +------------------------------------------------------------------------------- + SOLICITED STACK FRAME FOR A THREAD + + A stack frame of this structure is allocated whenever a thread enters the + RTOS kernel intentionally (and synchronously) to submit to thread scheduling. + It goes on the current thread's stack. + + The solicited frame only includes registers that are required to be preserved + by the callee according to the compiler's ABI conventions, some space to save + the return address for returning to the caller, and the caller's PS register. + + For Windowed ABI, this stack frame includes the caller's base save area. + + Note on XT_SOL_EXIT field: + It is necessary to distinguish a solicited from an interrupt stack frame. + This field corresponds to XT_STK_EXIT in the interrupt stack frame and is + always at the same offset (0). It can be written with a code (usually 0) + to distinguish a solicted frame from an interrupt frame. An RTOS port may + opt to ignore this field if it has another way of distinguishing frames. +------------------------------------------------------------------------------- +*/ + +STRUCT_BEGIN +#ifdef __XTENSA_CALL0_ABI__ +STRUCT_FIELD (long, 4, XT_SOL_EXIT, exit) +STRUCT_FIELD (long, 4, XT_SOL_PC, pc) +STRUCT_FIELD (long, 4, XT_SOL_PS, ps) +STRUCT_FIELD (long, 4, XT_SOL_NEXT, next) +STRUCT_FIELD (long, 4, XT_SOL_A12, a12) /* should be on 16-byte alignment */ +STRUCT_FIELD (long, 4, XT_SOL_A13, a13) +STRUCT_FIELD (long, 4, XT_SOL_A14, a14) +STRUCT_FIELD (long, 4, XT_SOL_A15, a15) +#else +STRUCT_FIELD (long, 4, XT_SOL_EXIT, exit) +STRUCT_FIELD (long, 4, XT_SOL_PC, pc) +STRUCT_FIELD (long, 4, XT_SOL_PS, ps) +STRUCT_FIELD (long, 4, XT_SOL_NEXT, next) +STRUCT_FIELD (long, 4, XT_SOL_A0, a0) /* should be on 16-byte alignment */ +STRUCT_FIELD (long, 4, XT_SOL_A1, a1) +STRUCT_FIELD (long, 4, XT_SOL_A2, a2) +STRUCT_FIELD (long, 4, XT_SOL_A3, a3) +#endif +STRUCT_END(XtSolFrame) + +/* Size of solicited stack frame */ +#define XT_SOL_FRMSZ ALIGNUP(0x10, XtSolFrameSize) + + +/* +------------------------------------------------------------------------------- + CO-PROCESSOR STATE SAVE AREA FOR A THREAD + + The RTOS must provide an area per thread to save the state of co-processors + when that thread does not have control. Co-processors are context-switched + lazily (on demand) only when a new thread uses a co-processor instruction, + otherwise a thread retains ownership of the co-processor even when it loses + control of the processor. An Xtensa co-processor exception is triggered when + any co-processor instruction is executed by a thread that is not the owner, + and the context switch of that co-processor is then peformed by the handler. + Ownership represents which thread's state is currently in the co-processor. + + Co-processors may not be used by interrupt or exception handlers. If an + co-processor instruction is executed by an interrupt or exception handler, + the co-processor exception handler will trigger a kernel panic and freeze. + This restriction is introduced to reduce the overhead of saving and restoring + co-processor state (which can be quite large) and in particular remove that + overhead from interrupt handlers. + + The co-processor state save area may be in any convenient per-thread location + such as in the thread control block or above the thread stack area. It need + not be in the interrupt stack frame since interrupts don't use co-processors. + + Along with the save area for each co-processor, two bitmasks with flags per + co-processor (laid out as in the CPENABLE reg) help manage context-switching + co-processors as efficiently as possible: + + XT_CPENABLE + The contents of a non-running thread's CPENABLE register. + It represents the co-processors owned (and whose state is still needed) + by the thread. When a thread is preempted, its CPENABLE is saved here. + When a thread solicits a context-swtich, its CPENABLE is cleared - the + compiler has saved the (caller-saved) co-proc state if it needs to. + When a non-running thread loses ownership of a CP, its bit is cleared. + When a thread runs, it's XT_CPENABLE is loaded into the CPENABLE reg. + Avoids co-processor exceptions when no change of ownership is needed. + + XT_CPSTORED + A bitmask with the same layout as CPENABLE, a bit per co-processor. + Indicates whether the state of each co-processor is saved in the state + save area. When a thread enters the kernel, only the state of co-procs + still enabled in CPENABLE is saved. When the co-processor exception + handler assigns ownership of a co-processor to a thread, it restores + the saved state only if this bit is set, and clears this bit. + + XT_CP_CS_ST + A bitmask with the same layout as CPENABLE, a bit per co-processor. + Indicates whether callee-saved state is saved in the state save area. + Callee-saved state is saved by itself on a solicited context switch, + and restored when needed by the coprocessor exception handler. + Unsolicited switches will cause the entire coprocessor to be saved + when necessary. + + XT_CP_ASA + Pointer to the aligned save area. Allows it to be aligned more than + the overall save area (which might only be stack-aligned or TCB-aligned). + Especially relevant for Xtensa cores configured with a very large data + path that requires alignment greater than 16 bytes (ABI stack alignment). +------------------------------------------------------------------------------- +*/ + +#if XCHAL_CP_NUM > 0 + +/* Offsets of each coprocessor save area within the 'aligned save area': */ +#define XT_CP0_SA 0 +#define XT_CP1_SA ALIGNUP(XCHAL_CP1_SA_ALIGN, XT_CP0_SA + XCHAL_CP0_SA_SIZE) +#define XT_CP2_SA ALIGNUP(XCHAL_CP2_SA_ALIGN, XT_CP1_SA + XCHAL_CP1_SA_SIZE) +#define XT_CP3_SA ALIGNUP(XCHAL_CP3_SA_ALIGN, XT_CP2_SA + XCHAL_CP2_SA_SIZE) +#define XT_CP4_SA ALIGNUP(XCHAL_CP4_SA_ALIGN, XT_CP3_SA + XCHAL_CP3_SA_SIZE) +#define XT_CP5_SA ALIGNUP(XCHAL_CP5_SA_ALIGN, XT_CP4_SA + XCHAL_CP4_SA_SIZE) +#define XT_CP6_SA ALIGNUP(XCHAL_CP6_SA_ALIGN, XT_CP5_SA + XCHAL_CP5_SA_SIZE) +#define XT_CP7_SA ALIGNUP(XCHAL_CP7_SA_ALIGN, XT_CP6_SA + XCHAL_CP6_SA_SIZE) +#define XT_CP_SA_SIZE ALIGNUP(16, XT_CP7_SA + XCHAL_CP7_SA_SIZE) + +/* Offsets within the overall save area: */ +#define XT_CPENABLE 0 /* (2 bytes) coprocessors active for this thread */ +#define XT_CPSTORED 2 /* (2 bytes) coprocessors saved for this thread */ +#define XT_CP_CS_ST 4 /* (2 bytes) coprocessor callee-saved regs stored for this thread */ +#define XT_CP_ASA 8 /* (4 bytes) ptr to aligned save area */ +/* Overall size allows for dynamic alignment: */ +#define XT_CP_SIZE (12 + XT_CP_SA_SIZE + XCHAL_TOTAL_SA_ALIGN) +#else +#define XT_CP_SIZE 0 +#endif + + +/* + Macro to get the current core ID. Only uses the reg given as an argument. + Reading PRID on the ESP108 architecture gives us 0xCDCD on the PRO processor + and 0xABAB on the APP CPU. We distinguish between the two by simply checking + bit 1: it's 1 on the APP and 0 on the PRO processor. +*/ + +#ifdef __ASSEMBLER__ + .macro getcoreid reg + rsr.prid \reg + bbci \reg,1,1f + movi \reg,1 + j 2f +1: + movi \reg,0 +2: + .endm +#endif + + + +/* +------------------------------------------------------------------------------- + MACROS TO HANDLE ABI SPECIFICS OF FUNCTION ENTRY AND RETURN + + Convenient where the frame size requirements are the same for both ABIs. + ENTRY(sz), RET(sz) are for framed functions (have locals or make calls). + ENTRY0, RET0 are for frameless functions (no locals, no calls). + + where size = size of stack frame in bytes (must be >0 and aligned to 16). + For framed functions the frame is created and the return address saved at + base of frame (Call0 ABI) or as determined by hardware (Windowed ABI). + For frameless functions, there is no frame and return address remains in a0. + Note: Because CPP macros expand to a single line, macros requiring multi-line + expansions are implemented as assembler macros. +------------------------------------------------------------------------------- +*/ + +#ifdef __ASSEMBLER__ +#ifdef __XTENSA_CALL0_ABI__ + /* Call0 */ + #define ENTRY(sz) entry1 sz + .macro entry1 size=0x10 + addi sp, sp, -\size + s32i a0, sp, 0 + .endm + #define ENTRY0 + #define RET(sz) ret1 sz + .macro ret1 size=0x10 + l32i a0, sp, 0 + addi sp, sp, \size + ret + .endm + #define RET0 ret +#else + /* Windowed */ + #define ENTRY(sz) entry sp, sz + #define ENTRY0 entry sp, 0x10 + #define RET(sz) retw + #define RET0 retw +#endif +#endif + + + + + +#endif /* XTENSA_CONTEXT_H */ + diff --git a/components/freertos/include/freertos/xtensa_rtos.h b/components/freertos/include/freertos/xtensa_rtos.h new file mode 100644 index 0000000000..980cc92e0d --- /dev/null +++ b/components/freertos/include/freertos/xtensa_rtos.h @@ -0,0 +1,233 @@ +/******************************************************************************* +// Copyright (c) 2003-2015 Cadence Design Systems, Inc. +// +// Permission is hereby granted, free of charge, to any person obtaining +// a copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to +// permit persons to whom the Software is furnished to do so, subject to +// the following conditions: +// +// The above copyright notice and this permission notice shall be included +// in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +// CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +// SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +-------------------------------------------------------------------------------- + + RTOS-SPECIFIC INFORMATION FOR XTENSA RTOS ASSEMBLER SOURCES + (FreeRTOS Port) + +This header is the primary glue between generic Xtensa RTOS support +sources and a specific RTOS port for Xtensa. It contains definitions +and macros for use primarily by Xtensa assembly coded source files. + +Macros in this header map callouts from generic Xtensa files to specific +RTOS functions. It may also be included in C source files. + +Xtensa RTOS ports support all RTOS-compatible configurations of the Xtensa +architecture, using the Xtensa hardware abstraction layer (HAL) to deal +with configuration specifics. + +Should be included by all Xtensa generic and RTOS port-specific sources. + +*******************************************************************************/ + +#ifndef XTENSA_RTOS_H +#define XTENSA_RTOS_H + +#ifdef __ASSEMBLER__ +#include +#else +#include +#endif + +#include +#include +#include + +/* +Include any RTOS specific definitions that are needed by this header. +*/ +#include + +/* +Convert FreeRTOSConfig definitions to XTENSA definitions. +However these can still be overridden from the command line. +*/ + +#ifndef XT_SIMULATOR + #if configXT_SIMULATOR + #define XT_SIMULATOR 1 /* Simulator mode */ + #endif +#endif + +#ifndef XT_BOARD + #if configXT_BOARD + #define XT_BOARD 1 /* Board mode */ + #endif +#endif + +#ifndef XT_TIMER_INDEX + #if defined configXT_TIMER_INDEX + #define XT_TIMER_INDEX configXT_TIMER_INDEX /* Index of hardware timer to be used */ + #endif +#endif + +#ifndef XT_INTEXC_HOOKS + #if configXT_INTEXC_HOOKS + #define XT_INTEXC_HOOKS 1 /* Enables exception hooks */ + #endif +#endif + +#if !defined(XT_SIMULATOR) && !defined(XT_BOARD) + #error Either XT_SIMULATOR or XT_BOARD must be defined. +#endif + + +/* +Name of RTOS (for messages). +*/ +#define XT_RTOS_NAME FreeRTOS + +/* +Check some Xtensa configuration requirements and report error if not met. +Error messages can be customize to the RTOS port. +*/ + +#if !XCHAL_HAVE_XEA2 +#error "FreeRTOS/Xtensa requires XEA2 (exception architecture 2)." +#endif + + +/******************************************************************************* + +RTOS CALLOUT MACROS MAPPED TO RTOS PORT-SPECIFIC FUNCTIONS. + +Define callout macros used in generic Xtensa code to interact with the RTOS. +The macros are simply the function names for use in calls from assembler code. +Some of these functions may call back to generic functions in xtensa_context.h . + +*******************************************************************************/ + +/* +Inform RTOS of entry into an interrupt handler that will affect it. +Allows RTOS to manage switch to any system stack and count nesting level. +Called after minimal context has been saved, with interrupts disabled. +RTOS port can call0 _xt_context_save to save the rest of the context. +May only be called from assembly code by the 'call0' instruction. +*/ +// void XT_RTOS_INT_ENTER(void) +#define XT_RTOS_INT_ENTER _frxt_int_enter + +/* +Inform RTOS of completion of an interrupt handler, and give control to +RTOS to perform thread/task scheduling, switch back from any system stack +and restore the context, and return to the exit dispatcher saved in the +stack frame at XT_STK_EXIT. RTOS port can call0 _xt_context_restore +to save the context saved in XT_RTOS_INT_ENTER via _xt_context_save, +leaving only a minimal part of the context to be restored by the exit +dispatcher. This function does not return to the place it was called from. +May only be called from assembly code by the 'call0' instruction. +*/ +// void XT_RTOS_INT_EXIT(void) +#define XT_RTOS_INT_EXIT _frxt_int_exit + +/* +Inform RTOS of the occurrence of a tick timer interrupt. +If RTOS has no tick timer, leave XT_RTOS_TIMER_INT undefined. +May be coded in or called from C or assembly, per ABI conventions. +RTOS may optionally define XT_TICK_PER_SEC in its own way (eg. macro). +*/ +// void XT_RTOS_TIMER_INT(void) +#define XT_RTOS_TIMER_INT _frxt_timer_int +#define XT_TICK_PER_SEC configTICK_RATE_HZ + +/* +Return in a15 the base address of the co-processor state save area for the +thread that triggered a co-processor exception, or 0 if no thread was running. +The state save area is structured as defined in xtensa_context.h and has size +XT_CP_SIZE. Co-processor instructions should only be used in thread code, never +in interrupt handlers or the RTOS kernel. May only be called from assembly code +and by the 'call0' instruction. A result of 0 indicates an unrecoverable error. +The implementation may use only a2-4, a15 (all other regs must be preserved). +*/ +// void* XT_RTOS_CP_STATE(void) +#define XT_RTOS_CP_STATE _frxt_task_coproc_state + + +/******************************************************************************* + +HOOKS TO DYNAMICALLY INSTALL INTERRUPT AND EXCEPTION HANDLERS PER LEVEL. + +This Xtensa RTOS port provides hooks for dynamically installing exception +and interrupt handlers to facilitate automated testing where each test +case can install its own handler for user exceptions and each interrupt +priority (level). This consists of an array of function pointers indexed +by interrupt priority, with index 0 being the user exception handler hook. +Each entry in the array is initially 0, and may be replaced by a function +pointer of type XT_INTEXC_HOOK. A handler may be uninstalled by installing 0. + +The handler for low and medium priority obeys ABI conventions so may be coded +in C. For the exception handler, the cause is the contents of the EXCCAUSE +reg, and the result is -1 if handled, else the cause (still needs handling). +For interrupt handlers, the cause is a mask of pending enabled interrupts at +that level, and the result is the same mask with the bits for the handled +interrupts cleared (those not cleared still need handling). This allows a test +case to either pre-handle or override the default handling for the exception +or interrupt level (see xtensa_vectors.S). + +High priority handlers (including NMI) must be coded in assembly, are always +called by 'call0' regardless of ABI, must preserve all registers except a0, +and must not use or modify the interrupted stack. The hook argument 'cause' +is not passed and the result is ignored, so as not to burden the caller with +saving and restoring a2 (it assumes only one interrupt per level - see the +discussion in high priority interrupts in xtensa_vectors.S). The handler +therefore should be coded to prototype 'void h(void)' even though it plugs +into an array of handlers of prototype 'unsigned h(unsigned)'. + +To enable interrupt/exception hooks, compile the RTOS with '-DXT_INTEXC_HOOKS'. + +*******************************************************************************/ + +#define XT_INTEXC_HOOK_NUM (1 + XCHAL_NUM_INTLEVELS + XCHAL_HAVE_NMI) + +#ifndef __ASSEMBLER__ +typedef unsigned (*XT_INTEXC_HOOK)(unsigned cause); +extern volatile XT_INTEXC_HOOK _xt_intexc_hooks[XT_INTEXC_HOOK_NUM]; +#endif + + +/******************************************************************************* + +CONVENIENCE INCLUSIONS. + +Ensures RTOS specific files need only include this one Xtensa-generic header. +These headers are included last so they can use the RTOS definitions above. + +*******************************************************************************/ + +#include "xtensa_context.h" + +#ifdef XT_RTOS_TIMER_INT +#include "xtensa_timer.h" +#endif + + +/******************************************************************************* + +Xtensa Port Version. + +*******************************************************************************/ + +#define XTENSA_PORT_VERSION 1.4.2 +#define XTENSA_PORT_VERSION_STRING "1.4.2" + +#endif /* XTENSA_RTOS_H */ + diff --git a/components/freertos/include/freertos/xtensa_timer.h b/components/freertos/include/freertos/xtensa_timer.h new file mode 100644 index 0000000000..9bb8648f69 --- /dev/null +++ b/components/freertos/include/freertos/xtensa_timer.h @@ -0,0 +1,159 @@ +/******************************************************************************* +// Copyright (c) 2003-2015 Cadence Design Systems, Inc. +// +// Permission is hereby granted, free of charge, to any person obtaining +// a copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to +// permit persons to whom the Software is furnished to do so, subject to +// the following conditions: +// +// The above copyright notice and this permission notice shall be included +// in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +// CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +// SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +-------------------------------------------------------------------------------- + + XTENSA INFORMATION FOR RTOS TICK TIMER AND CLOCK FREQUENCY + +This header contains definitions and macros for use primarily by Xtensa +RTOS assembly coded source files. It includes and uses the Xtensa hardware +abstraction layer (HAL) to deal with config specifics. It may also be +included in C source files. + +User may edit to modify timer selection and to specify clock frequency and +tick duration to match timer interrupt to the real-time tick duration. + +If the RTOS has no timer interrupt, then there is no tick timer and the +clock frequency is irrelevant, so all of these macros are left undefined +and the Xtensa core configuration need not have a timer. + +*******************************************************************************/ + +#ifndef XTENSA_TIMER_H +#define XTENSA_TIMER_H + +#ifdef __ASSEMBLER__ +#include +#endif + +#include +#include + +#include "xtensa_rtos.h" /* in case this wasn't included directly */ + +#include + +/* +Select timer to use for periodic tick, and determine its interrupt number +and priority. User may specify a timer by defining XT_TIMER_INDEX with -D, +in which case its validity is checked (it must exist in this core and must +not be on a high priority interrupt - an error will be reported in invalid). +Otherwise select the first low or medium priority interrupt timer available. +*/ +#if XCHAL_NUM_TIMERS == 0 + + #error "This Xtensa configuration is unsupported, it has no timers." + +#else + +#ifndef XT_TIMER_INDEX + #if XCHAL_TIMER3_INTERRUPT != XTHAL_TIMER_UNCONFIGURED + #if XCHAL_INT_LEVEL(XCHAL_TIMER3_INTERRUPT) <= XCHAL_EXCM_LEVEL + #undef XT_TIMER_INDEX + #define XT_TIMER_INDEX 3 + #endif + #endif + #if XCHAL_TIMER2_INTERRUPT != XTHAL_TIMER_UNCONFIGURED + #if XCHAL_INT_LEVEL(XCHAL_TIMER2_INTERRUPT) <= XCHAL_EXCM_LEVEL + #undef XT_TIMER_INDEX + #define XT_TIMER_INDEX 2 + #endif + #endif + #if XCHAL_TIMER1_INTERRUPT != XTHAL_TIMER_UNCONFIGURED + #if XCHAL_INT_LEVEL(XCHAL_TIMER1_INTERRUPT) <= XCHAL_EXCM_LEVEL + #undef XT_TIMER_INDEX + #define XT_TIMER_INDEX 1 + #endif + #endif + #if XCHAL_TIMER0_INTERRUPT != XTHAL_TIMER_UNCONFIGURED + #if XCHAL_INT_LEVEL(XCHAL_TIMER0_INTERRUPT) <= XCHAL_EXCM_LEVEL + #undef XT_TIMER_INDEX + #define XT_TIMER_INDEX 0 + #endif + #endif +#endif +#ifndef XT_TIMER_INDEX + #error "There is no suitable timer in this Xtensa configuration." +#endif + +#define XT_CCOMPARE (CCOMPARE + XT_TIMER_INDEX) +#define XT_TIMER_INTNUM XCHAL_TIMER_INTERRUPT(XT_TIMER_INDEX) +#define XT_TIMER_INTPRI XCHAL_INT_LEVEL(XT_TIMER_INTNUM) +#define XT_TIMER_INTEN (1 << XT_TIMER_INTNUM) + +#if XT_TIMER_INTNUM == XTHAL_TIMER_UNCONFIGURED + #error "The timer selected by XT_TIMER_INDEX does not exist in this core." +#elif XT_TIMER_INTPRI > XCHAL_EXCM_LEVEL + #error "The timer interrupt cannot be high priority (use medium or low)." +#endif + +#endif /* XCHAL_NUM_TIMERS */ + +/* +Set processor clock frequency, used to determine clock divisor for timer tick. +User should BE SURE TO ADJUST THIS for the Xtensa platform being used. +If using a supported board via the board-independent API defined in xtbsp.h, +this may be left undefined and frequency and tick divisor will be computed +and cached during run-time initialization. + +NOTE ON SIMULATOR: +Under the Xtensa instruction set simulator, the frequency can only be estimated +because it depends on the speed of the host and the version of the simulator. +Also because it runs much slower than hardware, it is not possible to achieve +real-time performance for most applications under the simulator. A frequency +too low does not allow enough time between timer interrupts, starving threads. +To obtain a more convenient but non-real-time tick duration on the simulator, +compile with xt-xcc option "-DXT_SIMULATOR". +Adjust this frequency to taste (it's not real-time anyway!). +*/ +#if defined(XT_SIMULATOR) && !defined(XT_CLOCK_FREQ) +#define XT_CLOCK_FREQ configCPU_CLOCK_HZ +#endif + +#if !defined(XT_CLOCK_FREQ) && !defined(XT_BOARD) + #error "XT_CLOCK_FREQ must be defined for the target platform." +#endif + +/* +Default number of timer "ticks" per second (default 100 for 10ms tick). +RTOS may define this in its own way (if applicable) in xtensa_rtos.h. +User may redefine this to an optimal value for the application, either by +editing this here or in xtensa_rtos.h, or compiling with xt-xcc option +"-DXT_TICK_PER_SEC=" where is a suitable number. +*/ +#ifndef XT_TICK_PER_SEC +#define XT_TICK_PER_SEC configTICK_RATE_HZ /* 10 ms tick = 100 ticks per second */ +#endif + +/* +Derivation of clock divisor for timer tick and interrupt (one per tick). +*/ +#ifdef XT_CLOCK_FREQ +#define XT_TICK_DIVISOR (XT_CLOCK_FREQ / XT_TICK_PER_SEC) +#endif + +#ifndef __ASSEMBLER__ +extern unsigned _xt_tick_divisor; +extern void _xt_tick_divisor_init(void); +#endif + +#endif /* XTENSA_TIMER_H */ + diff --git a/components/freertos/license.txt b/components/freertos/license.txt new file mode 100644 index 0000000000..e48ed809df --- /dev/null +++ b/components/freertos/license.txt @@ -0,0 +1,440 @@ +The FreeRTOS.org source code is licensed by the *modified* GNU General Public +License (GPL), text provided below. A special exception to the GPL is +included to allow you to distribute a combined work that includes FreeRTOS +without being obliged to provide the source code for any proprietary +components. See the licensing section of http://www.FreeRTOS.org for full +details. The exception text is also included at the bottom of this file. + +The FreeRTOS download also includes demo application source code, some of +which is provided by third parties AND IS LICENSED SEPARATELY FROM FREERTOS. + +For the avoidance of any doubt refer to the comment included at the top +of each source and header file for license and copyright information. + +This is a list of files for which Real Time Engineers Ltd are not the +copyright owner and are NOT COVERED BY THE GPL. + + +1) Various header files provided by silicon manufacturers and tool vendors + that define processor specific memory addresses and utility macros. + Permission has been granted by the various copyright holders for these + files to be included in the FreeRTOS download. Users must ensure license + conditions are adhered to for any use other than compilation of the + FreeRTOS demo applications. + +2) The uIP TCP/IP stack the copyright of which is held by Adam Dunkels. + Users must ensure the open source license conditions stated at the top + of each uIP source file is understood and adhered to. + +3) The lwIP TCP/IP stack the copyright of which is held by the Swedish + Institute of Computer Science. Users must ensure the open source license + conditions stated at the top of each lwIP source file is understood and + adhered to. + +4) Various peripheral driver source files and binaries provided by silicon + manufacturers and tool vendors. Permission has been granted by the + various copyright holders for these files to be included in the FreeRTOS + download. Users must ensure license conditions are adhered to for any + use other than compilation of the FreeRTOS demo applications. + +5) The files contained within FreeRTOS\Demo\WizNET_DEMO_TERN_186\tern_code, + which are slightly modified versions of code provided by and copyright to + Tern Inc. + +Errors and omissions should be reported to Richard Barry, contact details for +whom can be obtained from http://www.FreeRTOS.org. + + + + + +The GPL license text follows. + +A special exception to the GPL is included to allow you to distribute a +combined work that includes FreeRTOS without being obliged to provide +the source code for any proprietary components. See the licensing section +of http://www.FreeRTOS.org for full details. The exception text is also +included at the bottom of this file. + +-------------------------------------------------------------------- + + + + GNU GENERAL PUBLIC LICENSE + Version 2, June 1991 + + Copyright (C) 1989, 1991 Free Software Foundation, Inc. + 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +License is intended to guarantee your freedom to share and change free +software--to make sure the software is free for all its users. This +General Public License applies to most of the Free Software +Foundation's software and to any other program whose authors commit to +using it. (Some other Free Software Foundation software is covered by +the GNU Library General Public License instead.) You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +this service if you wish), that you receive source code or can get it +if you want it, that you can change the software or use pieces of it +in new free programs; and that you know you can do these things. + + To protect your rights, we need to make restrictions that forbid +anyone to deny you these rights or to ask you to surrender the rights. +These restrictions translate to certain responsibilities for you if you +distribute copies of the software, or if you modify it. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must give the recipients all the rights that +you have. You must make sure that they, too, receive or can get the +source code. And you must show them these terms so they know their +rights. + + We protect your rights with two steps: (1) copyright the software, and +(2) offer you this license which gives you legal permission to copy, +distribute and/or modify the software. + + Also, for each author's protection and ours, we want to make certain +that everyone understands that there is no warranty for this free +software. If the software is modified by someone else and passed on, we +want its recipients to know that what they have is not the original, so +that any problems introduced by others will not reflect on the original +authors' reputations. + + Finally, any free program is threatened constantly by software +patents. We wish to avoid the danger that redistributors of a free +program will individually obtain patent licenses, in effect making the +program proprietary. To prevent this, we have made it clear that any +patent must be licensed for everyone's free use or not licensed at all. + + The precise terms and conditions for copying, distribution and +modification follow. + + GNU GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License applies to any program or other work which contains +a notice placed by the copyright holder saying it may be distributed +under the terms of this General Public License. The "Program", below, +refers to any such program or work, and a "work based on the Program" +means either the Program or any derivative work under copyright law: +that is to say, a work containing the Program or a portion of it, +either verbatim or with modifications and/or translated into another +language. (Hereinafter, translation is included without limitation in +the term "modification".) Each licensee is addressed as "you". + +Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running the Program is not restricted, and the output from the Program +is covered only if its contents constitute a work based on the +Program (independent of having been made by running the Program). +Whether that is true depends on what the Program does. + + 1. You may copy and distribute verbatim copies of the Program's +source code as you receive it, in any medium, provided that you +conspicuously and appropriately publish on each copy an appropriate +copyright notice and disclaimer of warranty; keep intact all the +notices that refer to this License and to the absence of any warranty; +and give any other recipients of the Program a copy of this License +along with the Program. + +You may charge a fee for the physical act of transferring a copy, and +you may at your option offer warranty protection in exchange for a fee. + + 2. You may modify your copy or copies of the Program or any portion +of it, thus forming a work based on the Program, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) You must cause the modified files to carry prominent notices + stating that you changed the files and the date of any change. + + b) You must cause any work that you distribute or publish, that in + whole or in part contains or is derived from the Program or any + part thereof, to be licensed as a whole at no charge to all third + parties under the terms of this License. + + c) If the modified program normally reads commands interactively + when run, you must cause it, when started running for such + interactive use in the most ordinary way, to print or display an + announcement including an appropriate copyright notice and a + notice that there is no warranty (or else, saying that you provide + a warranty) and that users may redistribute the program under + these conditions, and telling the user how to view a copy of this + License. (Exception: if the Program itself is interactive but + does not normally print such an announcement, your work based on + the Program is not required to print an announcement.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Program, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Program, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Program. + +In addition, mere aggregation of another work not based on the Program +with the Program (or with a work based on the Program) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may copy and distribute the Program (or a work based on it, +under Section 2) in object code or executable form under the terms of +Sections 1 and 2 above provided that you also do one of the following: + + a) Accompany it with the complete corresponding machine-readable + source code, which must be distributed under the terms of Sections + 1 and 2 above on a medium customarily used for software interchange; or, + + b) Accompany it with a written offer, valid for at least three + years, to give any third party, for a charge no more than your + cost of physically performing source distribution, a complete + machine-readable copy of the corresponding source code, to be + distributed under the terms of Sections 1 and 2 above on a medium + customarily used for software interchange; or, + + c) Accompany it with the information you received as to the offer + to distribute corresponding source code. (This alternative is + allowed only for noncommercial distribution and only if you + received the program in object code or executable form with such + an offer, in accord with Subsection b above.) + +The source code for a work means the preferred form of the work for +making modifications to it. For an executable work, complete source +code means all the source code for all modules it contains, plus any +associated interface definition files, plus the scripts used to +control compilation and installation of the executable. However, as a +special exception, the source code distributed need not include +anything that is normally distributed (in either source or binary +form) with the major components (compiler, kernel, and so on) of the +operating system on which the executable runs, unless that component +itself accompanies the executable. + +If distribution of executable or object code is made by offering +access to copy from a designated place, then offering equivalent +access to copy the source code from the same place counts as +distribution of the source code, even though third parties are not +compelled to copy the source along with the object code. + + 4. You may not copy, modify, sublicense, or distribute the Program +except as expressly provided under this License. Any attempt +otherwise to copy, modify, sublicense or distribute the Program is +void, and will automatically terminate your rights under this License. +However, parties who have received copies, or rights, from you under +this License will not have their licenses terminated so long as such +parties remain in full compliance. + + 5. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Program or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Program (or any work based on the +Program), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Program or works based on it. + + 6. Each time you redistribute the Program (or any work based on the +Program), the recipient automatically receives a license from the +original licensor to copy, distribute or modify the Program subject to +these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties to +this License. + + 7. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Program at all. For example, if a patent +license would not permit royalty-free redistribution of the Program by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Program. + +If any portion of this section is held invalid or unenforceable under +any particular circumstance, the balance of the section is intended to +apply and the section as a whole is intended to apply in other +circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system, which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 8. If the distribution and/or use of the Program is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Program under this License +may add an explicit geographical distribution limitation excluding +those countries, so that distribution is permitted only in or among +countries not thus excluded. In such case, this License incorporates +the limitation as if written in the body of this License. + + 9. The Free Software Foundation may publish revised and/or new versions +of the General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + +Each version is given a distinguishing version number. If the Program +specifies a version number of this License which applies to it and "any +later version", you have the option of following the terms and conditions +either of that version or of any later version published by the Free +Software Foundation. If the Program does not specify a version number of +this License, you may choose any version ever published by the Free Software +Foundation. + + 10. If you wish to incorporate parts of the Program into other free +programs whose distribution conditions are different, write to the author +to ask for permission. For software which is copyrighted by the Free +Software Foundation, write to the Free Software Foundation; we sometimes +make exceptions for this. Our decision will be guided by the two goals +of preserving the free status of all derivatives of our free software and +of promoting the sharing and reuse of software generally. + + NO WARRANTY + + 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY +FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN +OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES +PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED +OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS +TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE +PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, +REPAIR OR CORRECTION. + + 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR +REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, +INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING +OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED +TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY +YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER +PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE +POSSIBILITY OF SUCH DAMAGES. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +convey the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + + Copyright (C) + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License** as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + +Also add information on how to contact you by electronic and paper mail. + +If the program is interactive, make it output a short notice like this +when it starts in an interactive mode: + + Gnomovision version 69, Copyright (C) year name of author + Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, the commands you use may +be called something other than `show w' and `show c'; they could even be +mouse-clicks or menu items--whatever suits your program. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the program, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the program + `Gnomovision' (which makes passes at compilers) written by James Hacker. + + , 1 April 1989 + Ty Coon, President of Vice + +This General Public License does not permit incorporating your program into +proprietary programs. If your program is a subroutine library, you may +consider it more useful to permit linking proprietary applications with the +library. If this is what you want to do, use the GNU Library General +Public License instead of this License. + +---------------------------------------------------------------------------- + +The FreeRTOS GPL Exception Text: + +Any FreeRTOS source code, whether modified or in it's original release form, +or whether in whole or in part, can only be distributed by you under the terms +of the GNU General Public License plus this exception. An independent module is +a module which is not derived from or based on FreeRTOS. + +Clause 1: + +Linking FreeRTOS statically or dynamically with other modules is making a +combined work based on FreeRTOS. Thus, the terms and conditions of the GNU +General Public License cover the whole combination. + +As a special exception, the copyright holder of FreeRTOS gives you permission +to link FreeRTOS with independent modules that communicate with FreeRTOS +solely through the FreeRTOS API interface, regardless of the license terms of +these independent modules, and to copy and distribute the resulting combined +work under terms of your choice, provided that + + + Every copy of the combined work is accompanied by a written statement that + details to the recipient the version of FreeRTOS used and an offer by yourself + to provide the FreeRTOS source code (including any modifications you may have + made) should the recipient request it. + + + The combined work is not itself an RTOS, scheduler, kernel or related product. + + + The independent modules add significant and primary functionality to FreeRTOS + and do not merely extend the existing functionality already present in FreeRTOS. + +Clause 2: + +FreeRTOS may not be used for any competitive or comparative purpose, including the +publication of any form of run time or compile time metric, without the express +permission of Real Time Engineers Ltd. (this is the norm within the industry and +is intended to ensure information accuracy). diff --git a/components/freertos/list.c b/components/freertos/list.c new file mode 100644 index 0000000000..03649295c2 --- /dev/null +++ b/components/freertos/list.c @@ -0,0 +1,233 @@ +/* + FreeRTOS V8.2.0 - Copyright (C) 2015 Real Time Engineers Ltd. + All rights reserved + + VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION. + + This file is part of the FreeRTOS distribution. + + FreeRTOS is free software; you can redistribute it and/or modify it under + the terms of the GNU General Public License (version 2) as published by the + Free Software Foundation >>!AND MODIFIED BY!<< the FreeRTOS exception. + + *************************************************************************** + >>! NOTE: The modification to the GPL is included to allow you to !<< + >>! distribute a combined work that includes FreeRTOS without being !<< + >>! obliged to provide the source code for proprietary components !<< + >>! outside of the FreeRTOS kernel. !<< + *************************************************************************** + + FreeRTOS is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + FOR A PARTICULAR PURPOSE. Full license text is available on the following + link: http://www.freertos.org/a00114.html + + *************************************************************************** + * * + * FreeRTOS provides completely free yet professionally developed, * + * robust, strictly quality controlled, supported, and cross * + * platform software that is more than just the market leader, it * + * is the industry's de facto standard. * + * * + * Help yourself get started quickly while simultaneously helping * + * to support the FreeRTOS project by purchasing a FreeRTOS * + * tutorial book, reference manual, or both: * + * http://www.FreeRTOS.org/Documentation * + * * + *************************************************************************** + + http://www.FreeRTOS.org/FAQHelp.html - Having a problem? Start by reading + the FAQ page "My application does not run, what could be wrong?". Have you + defined configASSERT()? + + http://www.FreeRTOS.org/support - In return for receiving this top quality + embedded software for free we request you assist our global community by + participating in the support forum. + + http://www.FreeRTOS.org/training - Investing in training allows your team to + be as productive as possible as early as possible. Now you can receive + FreeRTOS training directly from Richard Barry, CEO of Real Time Engineers + Ltd, and the world's leading authority on the world's leading RTOS. + + http://www.FreeRTOS.org/plus - A selection of FreeRTOS ecosystem products, + including FreeRTOS+Trace - an indispensable productivity tool, a DOS + compatible FAT file system, and our tiny thread aware UDP/IP stack. + + http://www.FreeRTOS.org/labs - Where new FreeRTOS products go to incubate. + Come and try FreeRTOS+TCP, our new open source TCP/IP stack for FreeRTOS. + + http://www.OpenRTOS.com - Real Time Engineers ltd. license FreeRTOS to High + Integrity Systems ltd. to sell under the OpenRTOS brand. Low cost OpenRTOS + licenses offer ticketed support, indemnification and commercial middleware. + + http://www.SafeRTOS.com - High Integrity Systems also provide a safety + engineered and independently SIL3 certified version for use in safety and + mission critical applications that require provable dependability. + + 1 tab == 4 spaces! +*/ + + +#include +#include "FreeRTOS.h" +#include "list.h" + +/*----------------------------------------------------------- + * PUBLIC LIST API documented in list.h + *----------------------------------------------------------*/ + +void vListInitialise( List_t * const pxList ) +{ + /* The list structure contains a list item which is used to mark the + end of the list. To initialise the list the list end is inserted + as the only list entry. */ + pxList->pxIndex = ( ListItem_t * ) &( pxList->xListEnd ); /*lint !e826 !e740 The mini list structure is used as the list end to save RAM. This is checked and valid. */ + + /* The list end value is the highest possible value in the list to + ensure it remains at the end of the list. */ + pxList->xListEnd.xItemValue = portMAX_DELAY; + + /* The list end next and previous pointers point to itself so we know + when the list is empty. */ + pxList->xListEnd.pxNext = ( ListItem_t * ) &( pxList->xListEnd ); /*lint !e826 !e740 The mini list structure is used as the list end to save RAM. This is checked and valid. */ + pxList->xListEnd.pxPrevious = ( ListItem_t * ) &( pxList->xListEnd );/*lint !e826 !e740 The mini list structure is used as the list end to save RAM. This is checked and valid. */ + + pxList->uxNumberOfItems = ( UBaseType_t ) 0U; + + /* Write known values into the list if + configUSE_LIST_DATA_INTEGRITY_CHECK_BYTES is set to 1. */ + listSET_LIST_INTEGRITY_CHECK_1_VALUE( pxList ); + listSET_LIST_INTEGRITY_CHECK_2_VALUE( pxList ); +} +/*-----------------------------------------------------------*/ + +void vListInitialiseItem( ListItem_t * const pxItem ) +{ + /* Make sure the list item is not recorded as being on a list. */ + pxItem->pvContainer = NULL; + + /* Write known values into the list item if + configUSE_LIST_DATA_INTEGRITY_CHECK_BYTES is set to 1. */ + listSET_FIRST_LIST_ITEM_INTEGRITY_CHECK_VALUE( pxItem ); + listSET_SECOND_LIST_ITEM_INTEGRITY_CHECK_VALUE( pxItem ); +} +/*-----------------------------------------------------------*/ + +void vListInsertEnd( List_t * const pxList, ListItem_t * const pxNewListItem ) +{ +ListItem_t * const pxIndex = pxList->pxIndex; + + /* Only effective when configASSERT() is also defined, these tests may catch + the list data structures being overwritten in memory. They will not catch + data errors caused by incorrect configuration or use of FreeRTOS. */ + listTEST_LIST_INTEGRITY( pxList ); + listTEST_LIST_ITEM_INTEGRITY( pxNewListItem ); + + /* Insert a new list item into pxList, but rather than sort the list, + makes the new list item the last item to be removed by a call to + listGET_OWNER_OF_NEXT_ENTRY(). */ + pxNewListItem->pxNext = pxIndex; + pxNewListItem->pxPrevious = pxIndex->pxPrevious; + pxIndex->pxPrevious->pxNext = pxNewListItem; + pxIndex->pxPrevious = pxNewListItem; + + /* Remember which list the item is in. */ + pxNewListItem->pvContainer = ( void * ) pxList; + + ( pxList->uxNumberOfItems )++; +} +/*-----------------------------------------------------------*/ + +void vListInsert( List_t * const pxList, ListItem_t * const pxNewListItem ) +{ +ListItem_t *pxIterator; +const TickType_t xValueOfInsertion = pxNewListItem->xItemValue; + + /* Only effective when configASSERT() is also defined, these tests may catch + the list data structures being overwritten in memory. They will not catch + data errors caused by incorrect configuration or use of FreeRTOS. */ + listTEST_LIST_INTEGRITY( pxList ); + listTEST_LIST_ITEM_INTEGRITY( pxNewListItem ); + + /* Insert the new list item into the list, sorted in xItemValue order. + + If the list already contains a list item with the same item value then the + new list item should be placed after it. This ensures that TCB's which are + stored in ready lists (all of which have the same xItemValue value) get a + share of the CPU. However, if the xItemValue is the same as the back marker + the iteration loop below will not end. Therefore the value is checked + first, and the algorithm slightly modified if necessary. */ + if( xValueOfInsertion == portMAX_DELAY ) + { + pxIterator = pxList->xListEnd.pxPrevious; + } + else + { + /* *** NOTE *********************************************************** + If you find your application is crashing here then likely causes are + listed below. In addition see http://www.freertos.org/FAQHelp.html for + more tips, and ensure configASSERT() is defined! + http://www.freertos.org/a00110.html#configASSERT + + 1) Stack overflow - + see http://www.freertos.org/Stacks-and-stack-overflow-checking.html + 2) Incorrect interrupt priority assignment, especially on Cortex-M + parts where numerically high priority values denote low actual + interrupt priorities, which can seem counter intuitive. See + http://www.freertos.org/RTOS-Cortex-M3-M4.html and the definition + of configMAX_SYSCALL_INTERRUPT_PRIORITY on + http://www.freertos.org/a00110.html + 3) Calling an API function from within a critical section or when + the scheduler is suspended, or calling an API function that does + not end in "FromISR" from an interrupt. + 4) Using a queue or semaphore before it has been initialised or + before the scheduler has been started (are interrupts firing + before vTaskStartScheduler() has been called?). + **********************************************************************/ + + for( pxIterator = ( ListItem_t * ) &( pxList->xListEnd ); pxIterator->pxNext->xItemValue <= xValueOfInsertion; pxIterator = pxIterator->pxNext ) /*lint !e826 !e740 The mini list structure is used as the list end to save RAM. This is checked and valid. */ + { + /* There is nothing to do here, just iterating to the wanted + insertion position. */ + } + } + + pxNewListItem->pxNext = pxIterator->pxNext; + pxNewListItem->pxNext->pxPrevious = pxNewListItem; + pxNewListItem->pxPrevious = pxIterator; + pxIterator->pxNext = pxNewListItem; + + /* Remember which list the item is in. This allows fast removal of the + item later. */ + pxNewListItem->pvContainer = ( void * ) pxList; + + ( pxList->uxNumberOfItems )++; +} +/*-----------------------------------------------------------*/ + +UBaseType_t uxListRemove( ListItem_t * const pxItemToRemove ) +{ +/* The list item knows which list it is in. Obtain the list from the list +item. */ +List_t * const pxList = ( List_t * ) pxItemToRemove->pvContainer; + + pxItemToRemove->pxNext->pxPrevious = pxItemToRemove->pxPrevious; + pxItemToRemove->pxPrevious->pxNext = pxItemToRemove->pxNext; + + /* Make sure the index is left pointing to a valid item. */ + if( pxList->pxIndex == pxItemToRemove ) + { + pxList->pxIndex = pxItemToRemove->pxPrevious; + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + + pxItemToRemove->pvContainer = NULL; + ( pxList->uxNumberOfItems )--; + + return pxList->uxNumberOfItems; +} +/*-----------------------------------------------------------*/ + diff --git a/components/freertos/panic.c b/components/freertos/panic.c new file mode 100644 index 0000000000..4711e9efe9 --- /dev/null +++ b/components/freertos/panic.c @@ -0,0 +1,211 @@ +// Copyright 2015-2016 Espressif Systems (Shanghai) PTE LTD +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at + +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +#include + +#include + +#include "rom/rtc.h" + +#include "freertos/FreeRTOS.h" +#include "freertos/task.h" +#include "freertos/xtensa_api.h" + +#include "soc/uart_register.h" +#include "soc/io_mux_reg.h" +#include "soc/dport_reg.h" +#include "soc/rtc_cntl_reg.h" + +#include "gdbstub.h" + +/* +Panic handlers; these get called when an unhandled exception occurs or the assembly-level +task switching / interrupt code runs into an unrecoverable error. The default task stack +overflow handler also is in here. +*/ + +#if !CONFIG_FREERTOS_PANIC_SILENT_REBOOT +//os_printf may be broken, so we fix our own printing fns... +inline static void panicPutchar(char c) { + while (((READ_PERI_REG(UART_STATUS_REG(0))>>UART_TXFIFO_CNT_S)&UART_TXFIFO_CNT)>=126) ; + WRITE_PERI_REG(UART_FIFO_REG(0), c); +} + +inline static void panicPutStr(const char *c) { + int x=0; + while (c[x]!=0) { + panicPutchar(c[x]); + x++; + } +} + +inline static void panicPutHex(int a) { + int x; + int c; + panicPutchar(' '); + for (x=0; x<8; x++) { + c=(a>>28)&0xf; + if (c<10) panicPutchar('0'+c); else panicPutchar('a'+c-10); + a<<=4; + } +} + +inline static void panicPutDec(int a) { + int n1, n2; + n1=a%10; + n2=a/10; + panicPutchar(' '); + if (n2==0) panicPutchar(' '); else panicPutchar(n2+'0'); + panicPutchar(n1+'0'); +} +#else +//No printing wanted. Stub out these functions. +inline static void panicPutchar(char c) { } +inline static void panicPutStr(const char *c) { } +inline static void panicPutHex(int a) { } +inline static void panicPutDec(int a) { } +#endif + +int xPortGetCoreID(); + +void __attribute__((weak)) vApplicationStackOverflowHook( TaskHandle_t xTask, signed char *pcTaskName ) { + panicPutStr("***ERROR*** A stack overflow in task"); + panicPutStr((char*)pcTaskName); + panicPutStr("has been detected.\n"); +} + +static const char *edesc[]={ + "IllegalInstruction", "Syscall", "InstructionFetchError", "LoadStoreError", + "Level1Interrupt", "Alloca", "IntegerDivideByZero", "PCValue", + "Privileged", "LoadStoreAlignment", "res", "res", + "InstrPDAddrError", "LoadStorePIFDataError", "InstrPIFAddrError", "LoadStorePIFAddrError", + "InstTLBMiss", "InstTLBMultiHit", "InstFetchPrivilege", "res", + "InstrFetchProhibited", "res", "res", "res", + "LoadStoreTLBMiss", "LoadStoreTLBMultihit", "LoadStorePrivilege", "res", + "LoadProhibited", "StoreProhibited", "res", "res", + "Cp0Dis", "Cp1Dis", "Cp2Dis", "Cp3Dis", + "Cp4Dis", "Cp5Dis", "Cp6Dis", "Cp7Dis" + }; + + +void commonErrorHandler(XtExcFrame *frame); + +//The fact that we've panic'ed probably means the other CPU is now running wild, possibly +//messing up the serial output, so we kill it here. +static void haltOtherCore() { + if (xPortGetCoreID()==0) { + //Kill app cpu + CLEAR_PERI_REG_MASK(RTC_OPTIONS0, RTC_CNTL_SW_STALL_APPCPU_C1<>!AND MODIFIED BY!<< the FreeRTOS exception. + + *************************************************************************** + >>! NOTE: The modification to the GPL is included to allow you to !<< + >>! distribute a combined work that includes FreeRTOS without being !<< + >>! obliged to provide the source code for proprietary components !<< + >>! outside of the FreeRTOS kernel. !<< + *************************************************************************** + + FreeRTOS is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + FOR A PARTICULAR PURPOSE. Full license text is available on the following + link: http://www.freertos.org/a00114.html + + *************************************************************************** + * * + * FreeRTOS provides completely free yet professionally developed, * + * robust, strictly quality controlled, supported, and cross * + * platform software that is more than just the market leader, it * + * is the industry's de facto standard. * + * * + * Help yourself get started quickly while simultaneously helping * + * to support the FreeRTOS project by purchasing a FreeRTOS * + * tutorial book, reference manual, or both: * + * http://www.FreeRTOS.org/Documentation * + * * + *************************************************************************** + + http://www.FreeRTOS.org/FAQHelp.html - Having a problem? Start by reading + the FAQ page "My application does not run, what could be wrong?". Have you + defined configASSERT()? + + http://www.FreeRTOS.org/support - In return for receiving this top quality + embedded software for free we request you assist our global community by + participating in the support forum. + + http://www.FreeRTOS.org/training - Investing in training allows your team to + be as productive as possible as early as possible. Now you can receive + FreeRTOS training directly from Richard Barry, CEO of Real Time Engineers + Ltd, and the world's leading authority on the world's leading RTOS. + + http://www.FreeRTOS.org/plus - A selection of FreeRTOS ecosystem products, + including FreeRTOS+Trace - an indispensable productivity tool, a DOS + compatible FAT file system, and our tiny thread aware UDP/IP stack. + + http://www.FreeRTOS.org/labs - Where new FreeRTOS products go to incubate. + Come and try FreeRTOS+TCP, our new open source TCP/IP stack for FreeRTOS. + + http://www.OpenRTOS.com - Real Time Engineers ltd. license FreeRTOS to High + Integrity Systems ltd. to sell under the OpenRTOS brand. Low cost OpenRTOS + licenses offer ticketed support, indemnification and commercial middleware. + + http://www.SafeRTOS.com - High Integrity Systems also provide a safety + engineered and independently SIL3 certified version for use in safety and + mission critical applications that require provable dependability. + + 1 tab == 4 spaces! +*/ + +/******************************************************************************* +// Copyright (c) 2003-2015 Cadence Design Systems, Inc. +// +// Permission is hereby granted, free of charge, to any person obtaining +// a copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to +// permit persons to whom the Software is furnished to do so, subject to +// the following conditions: +// +// The above copyright notice and this permission notice shall be included +// in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +// CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +// SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +-------------------------------------------------------------------------------- +*/ + +#include +#include + +#include "xtensa_rtos.h" + +#include "rom/ets_sys.h" + +#include "FreeRTOS.h" +#include "task.h" + +/* Defined in portasm.h */ +extern void _frxt_tick_timer_init(void); + +/* Defined in xtensa_context.S */ +extern void _xt_coproc_init(void); + + +/*-----------------------------------------------------------*/ + +unsigned port_xSchedulerRunning[portNUM_PROCESSORS] = {0}; // Duplicate of inaccessible xSchedulerRunning; needed at startup to avoid counting nesting +unsigned port_interruptNesting[portNUM_PROCESSORS] = {0}; // Interrupt nesting level + +/*-----------------------------------------------------------*/ + +// User exception dispatcher when exiting +void _xt_user_exit(void); + +/* + * Stack initialization + */ +#if portUSING_MPU_WRAPPERS +StackType_t *pxPortInitialiseStack( StackType_t *pxTopOfStack, TaskFunction_t pxCode, void *pvParameters, BaseType_t xRunPrivileged ) +#else +StackType_t *pxPortInitialiseStack( StackType_t *pxTopOfStack, TaskFunction_t pxCode, void *pvParameters ) +#endif +{ + StackType_t *sp, *tp; + XtExcFrame *frame; + #if XCHAL_CP_NUM > 0 + uint32_t *p; + #endif + + /* Create interrupt stack frame aligned to 16 byte boundary */ + sp = (StackType_t *) (((UBaseType_t)(pxTopOfStack + 1) - XT_CP_SIZE - XT_STK_FRMSZ) & ~0xf); + + /* Clear the entire frame (do not use memset() because we don't depend on C library) */ + for (tp = sp; tp <= pxTopOfStack; ++tp) + *tp = 0; + + frame = (XtExcFrame *) sp; + + /* Explicitly initialize certain saved registers */ + frame->pc = (UBaseType_t) pxCode; /* task entrypoint */ + frame->a0 = 0; /* to terminate GDB backtrace */ + frame->a1 = (UBaseType_t) sp + XT_STK_FRMSZ; /* physical top of stack frame */ + frame->exit = (UBaseType_t) _xt_user_exit; /* user exception exit dispatcher */ + + /* Set initial PS to int level 0, EXCM disabled ('rfe' will enable), user mode. */ + /* Also set entry point argument parameter. */ + #ifdef __XTENSA_CALL0_ABI__ + frame->a2 = (UBaseType_t) pvParameters; + frame->ps = PS_UM | PS_EXCM; + #else + /* + for windowed ABI also set WOE and CALLINC (pretend task was 'call4'd). */ + frame->a6 = (UBaseType_t) pvParameters; + frame->ps = PS_UM | PS_EXCM | PS_WOE | PS_CALLINC(1); + #endif + + #ifdef XT_USE_SWPRI + /* Set the initial virtual priority mask value to all 1's. */ + frame->vpri = 0xFFFFFFFF; + #endif + + #if XCHAL_CP_NUM > 0 + /* Init the coprocessor save area (see xtensa_context.h) */ + /* No access to TCB here, so derive indirectly. Stack growth is top to bottom. + * //p = (uint32_t *) xMPUSettings->coproc_area; + */ + p = (uint32_t *)(((uint32_t) pxTopOfStack - XT_CP_SIZE) & ~0xf); + p[0] = 0; + p[1] = 0; + p[2] = (((uint32_t) p) + 12 + XCHAL_TOTAL_SA_ALIGN - 1) & -XCHAL_TOTAL_SA_ALIGN; + #endif + + return sp; +} + +/*-----------------------------------------------------------*/ + +void vPortEndScheduler( void ) +{ + /* It is unlikely that the Xtensa port will get stopped. If required simply + disable the tick interrupt here. */ +} + +/*-----------------------------------------------------------*/ + +BaseType_t xPortStartScheduler( void ) +{ + // Interrupts are disabled at this point and stack contains PS with enabled interrupts when task context is restored + + #if XCHAL_CP_NUM > 0 + /* Initialize co-processor management for tasks. Leave CPENABLE alone. */ + _xt_coproc_init(); + #endif + + /* Init the tick divisor value */ + _xt_tick_divisor_init(); + + /* Setup the hardware to generate the tick. */ + _frxt_tick_timer_init(); + + port_xSchedulerRunning[xPortGetCoreID()] = 1; + + // Cannot be directly called from C; never returns + __asm__ volatile ("call0 _frxt_dispatch\n"); + + /* Should not get here. */ + return pdTRUE; +} +/*-----------------------------------------------------------*/ + +BaseType_t xPortSysTickHandler( void ) +{ + BaseType_t ret; + + portbenchmarkIntLatency(); + ret = xTaskIncrementTick(); + if( ret != pdFALSE ) + { + portYIELD_FROM_ISR(); + } + + return ret; +} +/*-----------------------------------------------------------*/ + +/* + * Used to set coprocessor area in stack. Current hack is to reuse MPU pointer for coprocessor area. + */ +#if portUSING_MPU_WRAPPERS +void vPortStoreTaskMPUSettings( xMPU_SETTINGS *xMPUSettings, const struct xMEMORY_REGION * const xRegions, StackType_t *pxBottomOfStack, uint16_t usStackDepth ) +{ + #if XCHAL_CP_NUM > 0 + xMPUSettings->coproc_area = (StackType_t*)((((uint32_t)(pxBottomOfStack + usStackDepth - 1)) - XT_CP_SIZE ) & ~0xf); + + + /* NOTE: we cannot initialize the coprocessor save area here because FreeRTOS is going to + * clear the stack area after we return. This is done in pxPortInitialiseStack(). + */ + #endif +} +#endif + + + +/* + * Wrapper for the Xtensa compare-and-set instruction. This subroutine will atomically compare + * *addr to compare, and if it's the same, will set *addr to set. It will return the old value + * of *addr. + * + * Note: the NOPs are needed on the ESP31 processor but superfluous on the ESP32. + * + * Warning: From the ISA docs: in some (unspecified) cases, the s32c1i instruction may return the + * *bitwise inverse* of the old mem if the mem wasn't written. This doesn't seem to happen on the + * ESP32, though. (Would show up directly if it did because the magic wouldn't match.) + */ +uint32_t uxPortCompareSet(volatile uint32_t *mux, uint32_t compare, uint32_t set) +{ + __asm__ __volatile__ ( + "WSR %2,SCOMPARE1 \n" //initialize SCOMPARE1 + "ISYNC \n" //wait sync + "S32C1I %0, %1, 0 \n" //store id into the lock, if the lock is the same as comparel. Otherwise, no write-access + :"=r"(set) \ + :"r"(mux), "r"(compare), "0"(set) \ + ); + return set; +} + +/* + * For kernel use: Initialize a per-CPU mux. Mux will be initialized unlocked. + */ +void vPortCPUInitializeMutex(portMUX_TYPE *mux) { +#ifdef portMUX_DEBUG + ets_printf("Initializing mux %p\n", mux); + mux->lastLockedFn="(never locked)"; + mux->lastLockedLine=-1; +#endif + mux->mux=portMUX_FREE_VAL; +} + + +/* + * For kernel use: Acquire a per-CPU mux. Spinlocks, so don't hold on to these muxes for too long. + */ +#ifdef portMUX_DEBUG +void vPortCPUAcquireMutex(portMUX_TYPE *mux, const char *fnName, int line) { +#else +void vPortCPUAcquireMutex(portMUX_TYPE *mux) { +#endif + uint32_t res; + uint32_t recCnt; + unsigned int irqStatus; +#ifdef portMUX_DEBUG + uint32_t cnt=(1<<16); + if ( (mux->mux & portMUX_MAGIC_MASK) != portMUX_MAGIC_VAL ) { + ets_printf("ERROR: vPortCPUAcquireMutex: mux %p is uninitialized (0x%X)!\n", mux, mux->mux); + mux->mux=portMUX_FREE_VAL; + } +#endif + + irqStatus=portENTER_CRITICAL_NESTED(); + do { + //Lock mux if it's currently unlocked + res=uxPortCompareSet(&mux->mux, portMUX_FREE_VAL, (xPortGetCoreID()<>portMUX_VAL_SHIFT) == xPortGetCoreID()) ) { + //Mux was already locked by us. Just bump the recurse count by one. + recCnt=(res&portMUX_CNT_MASK)>>portMUX_CNT_SHIFT; + recCnt++; +#ifdef portMUX_DEBUG_RECURSIVE + ets_printf("Recursive lock: recCnt=%d last non-recursive lock %s line %d, curr %s line %d\n", recCnt, mux->lastLockedFn, mux->lastLockedLine, fnName, line); +#endif + mux->mux=portMUX_MAGIC_VAL|(recCnt<lastLockedFn, mux->lastLockedLine, fnName, line); + ets_printf("Mux value %X\n", mux->mux); + } +#endif + } while (res!=portMUX_FREE_VAL); +#ifdef portMUX_DEBUG + if (res==portMUX_FREE_VAL) { //initial lock + mux->lastLockedFn=fnName; + mux->lastLockedLine=line; + } +#endif + portEXIT_CRITICAL_NESTED(irqStatus); +} + +/* + * For kernel use: Release a per-CPU mux. Returns true if everything is OK, false if mux + * was already unlocked or is locked by a different core. + */ +#ifdef portMUX_DEBUG +portBASE_TYPE vPortCPUReleaseMutex(portMUX_TYPE *mux, const char *fnName, int line) { +#else +portBASE_TYPE vPortCPUReleaseMutex(portMUX_TYPE *mux) { +#endif + uint32_t res=0; + uint32_t recCnt; + unsigned int irqStatus; + portBASE_TYPE ret=pdTRUE; +// ets_printf("Unlock %p\n", mux); + irqStatus=portENTER_CRITICAL_NESTED(); +#ifdef portMUX_DEBUG + const char *lastLockedFn=mux->lastLockedFn; + int lastLockedLine=mux->lastLockedLine; + mux->lastLockedFn=fnName; + mux->lastLockedLine=line; + if ( (mux->mux & portMUX_MAGIC_MASK) != portMUX_MAGIC_VAL ) ets_printf("ERROR: vPortCPUReleaseMutex: mux %p is uninitialized (0x%X)!\n", mux, mux->mux); +#endif + //Unlock mux if it's currently locked with a recurse count of 0 + res=uxPortCompareSet(&mux->mux, (xPortGetCoreID()<>portMUX_VAL_SHIFT) != xPortGetCoreID() ) { +#ifdef portMUX_DEBUG + ets_printf("ERROR: vPortCPUReleaseMutex: mux %p wasn't locked by this core (%d) but by core %d (ret=%x, mux=%x).\n", mux, xPortGetCoreID(), ((res&portMUX_VAL_MASK)>>portMUX_VAL_SHIFT), res, mux->mux); + ets_printf("Last non-recursive lock %s line %d\n", lastLockedFn, lastLockedLine); + ets_printf("Called by %s line %d\n", fnName, line); +#endif + ret=pdFALSE; + } else if ( ((res&portMUX_CNT_MASK)>>portMUX_CNT_SHIFT)!=0) { + //We locked this, but the reccount isn't zero. Decrease refcount and continue. + recCnt=(res&portMUX_CNT_MASK)>>portMUX_CNT_SHIFT; + recCnt--; +#ifdef portMUX_DEBUG_RECURSIVE + ets_printf("Recursive unlock: recCnt=%d last locked %s line %d, curr %s line %d\n", recCnt, lastLockedFn, lastLockedLine, fnName, line); +#endif + mux->mux=portMUX_MAGIC_VAL|(recCnt<pxTopOfStack = SP */ + movi a1, port_IntStackTop /* a1 = top of intr stack */ + movi a2, configISR_STACK_SIZE + getcoreid a3 + mull a2, a3, a2 + add a1, a1, a2 /* for current proc */ + +.Lnested: +1: + mov a0, a12 /* restore return addr and return */ + ret + +/* +******************************************************************************* +* _frxt_int_exit +* void _frxt_int_exit(void) +* +* Implements the Xtensa RTOS porting layer's XT_RTOS_INT_EXIT function for +* FreeRTOS. If required, calls vPortYieldFromInt() to perform task context +* switching, restore the (possibly) new task's context, and return to the +* exit dispatcher saved in the task's stack frame at XT_STK_EXIT. +* May only be called from assembly code by the 'call0' instruction. Does not +* return to caller. +* See the description of the XT_RTOS_ENTER macro in xtensa_rtos.h. +* +******************************************************************************* +*/ + .globl _frxt_int_exit + .type _frxt_int_exit,@function + .align 4 +_frxt_int_exit: + + getcoreid a3 + slli a4, a3, 2 /* a4 is core * 4 */ + movi a2, port_xSchedulerRunning + add a2, a2, a4 + movi a3, port_interruptNesting + add a3, a3, a4 + rsil a0, XCHAL_EXCM_LEVEL /* lock out interrupts */ + l32i a2, a2, 0 /* a2 = port_xSchedulerRunning */ + beqz a2, .Lnoswitch /* scheduler not running, no tasks */ + l32i a2, a3, 0 /* a2 = port_interruptNesting */ + addi a2, a2, -1 /* decrement nesting count */ + s32i a2, a3, 0 /* save nesting count */ + bnez a2, .Lnesting /* !=0 after decr so still nested */ + + movi a2, pxCurrentTCB + add a2, a2, a4 + l32i a2, a2, 0 /* a2 = current TCB */ + beqz a2, 1f /* no task ? go to dispatcher */ + l32i a1, a2, TOPOFSTACK_OFFS /* SP = pxCurrentTCB->pxTopOfStack */ + + movi a2, port_switch_flag /* address of switch flag */ + add a2, a2, a4 /* point to flag for this cpu */ + l32i a3, a2, 0 /* a3 = port_switch_flag */ + beqz a3, .Lnoswitch /* flag = 0 means no switch reqd */ + movi a3, 0 + s32i a3, a2, 0 /* zero out the flag for next time */ + +1: + /* + Call0 ABI callee-saved regs a12-15 need to be saved before possible preemption. + However a12-13 were already saved by _frxt_int_enter(). + */ + #ifdef __XTENSA_CALL0_ABI__ + s32i a14, a1, XT_STK_A14 + s32i a15, a1, XT_STK_A15 + #endif + + #ifdef __XTENSA_CALL0_ABI__ + call0 vPortYieldFromInt /* call dispatch inside the function; never returns */ + #else + call4 vPortYieldFromInt /* this one returns */ + call0 _frxt_dispatch /* tail-call dispatcher */ + /* Never returns here. */ + #endif + +.Lnoswitch: + /* + If we came here then about to resume the interrupted task. + */ + +.Lnesting: + /* + We come here only if there was no context switch, that is if this + is a nested interrupt, or the interrupted task was not preempted. + In either case there's no need to load the SP. + */ + + /* Restore full context from interrupt stack frame */ + call0 _xt_context_restore + + /* + Must return via the exit dispatcher corresponding to the entrypoint from which + this was called. Interruptee's A0, A1, PS, PC are restored and the interrupt + stack frame is deallocated in the exit dispatcher. + */ + l32i a0, a1, XT_STK_EXIT + ret + + +/* +********************************************************************************************************** +* _frxt_timer_int +* void _frxt_timer_int(void) +* +* Implements the Xtensa RTOS porting layer's XT_RTOS_TIMER_INT function for FreeRTOS. +* Called every timer interrupt. +* Manages the tick timer and calls xPortSysTickHandler() every tick. +* See the detailed description of the XT_RTOS_ENTER macro in xtensa_rtos.h. +* +* Callable from C (obeys ABI conventions). Implemented in assmebly code for performance. +* +********************************************************************************************************** +*/ + .globl _frxt_timer_int + .type _frxt_timer_int,@function + .align 4 +_frxt_timer_int: + + /* + Xtensa timers work by comparing a cycle counter with a preset value. Once the match occurs + an interrupt is generated, and the handler has to set a new cycle count into the comparator. + To avoid clock drift due to interrupt latency, the new cycle count is computed from the old, + not the time the interrupt was serviced. However if a timer interrupt is ever serviced more + than one tick late, it is necessary to process multiple ticks until the new cycle count is + in the future, otherwise the next timer interrupt would not occur until after the cycle + counter had wrapped (2^32 cycles later). + + do { + ticks++; + old_ccompare = read_ccompare_i(); + write_ccompare_i( old_ccompare + divisor ); + service one tick; + diff = read_ccount() - old_ccompare; + } while ( diff > divisor ); + */ + + ENTRY(16) + +.L_xt_timer_int_catchup: + + /* Update the timer comparator for the next tick. */ + #ifdef XT_CLOCK_FREQ + movi a2, XT_TICK_DIVISOR /* a2 = comparator increment */ + #else + movi a3, _xt_tick_divisor + l32i a2, a3, 0 /* a2 = comparator increment */ + #endif + rsr a3, XT_CCOMPARE /* a3 = old comparator value */ + add a4, a3, a2 /* a4 = new comparator value */ + wsr a4, XT_CCOMPARE /* update comp. and clear interrupt */ + esync + + #ifdef __XTENSA_CALL0_ABI__ + /* Preserve a2 and a3 across C calls. */ + s32i a2, sp, 4 + s32i a3, sp, 8 + #endif + + /* Call the FreeRTOS tick handler (see port.c). */ + #ifdef __XTENSA_CALL0_ABI__ + call0 xPortSysTickHandler + #else + call4 xPortSysTickHandler + #endif + + #ifdef __XTENSA_CALL0_ABI__ + /* Restore a2 and a3. */ + l32i a2, sp, 4 + l32i a3, sp, 8 + #endif + + /* Check if we need to process more ticks to catch up. */ + esync /* ensure comparator update complete */ + rsr a4, CCOUNT /* a4 = cycle count */ + sub a4, a4, a3 /* diff = ccount - old comparator */ + blt a2, a4, .L_xt_timer_int_catchup /* repeat while diff > divisor */ + + RET(16) + + /* +********************************************************************************************************** +* _frxt_tick_timer_init +* void _frxt_tick_timer_init(void) +* +* Initialize timer and timer interrrupt handler (_xt_tick_divisor_init() has already been been called). +* Callable from C (obeys ABI conventions on entry). +* +********************************************************************************************************** +*/ + .globl _frxt_tick_timer_init + .type _frxt_tick_timer_init,@function + .align 4 +_frxt_tick_timer_init: + + ENTRY(16) + + + /* Set up the periodic tick timer (assume enough time to complete init). */ + #ifdef XT_CLOCK_FREQ + movi a3, XT_TICK_DIVISOR + #else + movi a2, _xt_tick_divisor + l32i a3, a2, 0 + #endif + rsr a2, CCOUNT /* current cycle count */ + add a2, a2, a3 /* time of first timer interrupt */ + wsr a2, XT_CCOMPARE /* set the comparator */ + + /* + Enable the timer interrupt at the device level. Don't write directly + to the INTENABLE register because it may be virtualized. + */ + #ifdef __XTENSA_CALL0_ABI__ + movi a2, XT_TIMER_INTEN + call0 xt_ints_on + #else + movi a6, XT_TIMER_INTEN + call4 xt_ints_on + #endif + + RET(16) + +/* +********************************************************************************************************** +* DISPATCH THE HIGH READY TASK +* void _frxt_dispatch(void) +* +* Switch context to the highest priority ready task, restore its state and dispatch control to it. +* +* This is a common dispatcher that acts as a shared exit path for all the context switch functions +* including vPortYield() and vPortYieldFromInt(), all of which tail-call this dispatcher +* (for windowed ABI vPortYieldFromInt() calls it indirectly via _frxt_int_exit() ). +* +* The Xtensa port uses different stack frames for solicited and unsolicited task suspension (see +* comments on stack frames in xtensa_context.h). This function restores the state accordingly. +* If restoring a task that solicited entry, restores the minimal state and leaves CPENABLE clear. +* If restoring a task that was preempted, restores all state including the task's CPENABLE. +* +* Entry: +* pxCurrentTCB points to the TCB of the task to suspend, +* Because it is tail-called without a true function entrypoint, it needs no 'entry' instruction. +* +* Exit: +* If incoming task called vPortYield() (solicited), this function returns as if from vPortYield(). +* If incoming task was preempted by an interrupt, this function jumps to exit dispatcher. +* +********************************************************************************************************** +*/ + .globl _frxt_dispatch + .type _frxt_dispatch,@function + .align 4 +_frxt_dispatch: + + #ifdef __XTENSA_CALL0_ABI__ + call0 vTaskSwitchContext // Get next TCB to resume + movi a2, pxCurrentTCB + getcoreid a3 + slli a3, a3, 2 + add a2, a2, a3 + #else + call4 vTaskSwitchContext // Get next TCB to resume + movi a2, pxCurrentTCB + getcoreid a3 + slli a3, a3, 2 + add a2, a2, a3 + #endif + l32i a3, a2, 0 + l32i sp, a3, TOPOFSTACK_OFFS /* SP = next_TCB->pxTopOfStack; */ + s32i a3, a2, 0 + + /* Determine the type of stack frame. */ + l32i a2, sp, XT_STK_EXIT /* exit dispatcher or solicited flag */ + bnez a2, .L_frxt_dispatch_stk + +.L_frxt_dispatch_sol: + + /* Solicited stack frame. Restore minimal context and return from vPortYield(). */ + l32i a3, sp, XT_SOL_PS + #ifdef __XTENSA_CALL0_ABI__ + l32i a12, sp, XT_SOL_A12 + l32i a13, sp, XT_SOL_A13 + l32i a14, sp, XT_SOL_A14 + l32i a15, sp, XT_SOL_A15 + #endif + l32i a0, sp, XT_SOL_PC + #if XCHAL_CP_NUM > 0 + /* Ensure wsr.CPENABLE is complete (should be, it was cleared on entry). */ + rsync + #endif + /* As soons as PS is restored, interrupts can happen. No need to sync PS. */ + wsr a3, PS + #ifdef __XTENSA_CALL0_ABI__ + addi sp, sp, XT_SOL_FRMSZ + ret + #else + retw + #endif + +.L_frxt_dispatch_stk: + + #if XCHAL_CP_NUM > 0 + /* Restore CPENABLE from task's co-processor save area. */ + movi a3, pxCurrentTCB /* cp_state = */ + getcoreid a2 + slli a2, a2, 2 + add a3, a2, a3 + l32i a3, a3, 0 + l32i a2, a3, CP_TOPOFSTACK_OFFS /* StackType_t *pxStack; */ + l16ui a3, a2, XT_CPENABLE /* CPENABLE = cp_state->cpenable; */ + wsr a3, CPENABLE + #endif + + /* Interrupt stack frame. Restore full context and return to exit dispatcher. */ + call0 _xt_context_restore + + /* In Call0 ABI, restore callee-saved regs (A12, A13 already restored). */ + #ifdef __XTENSA_CALL0_ABI__ + l32i a14, sp, XT_STK_A14 + l32i a15, sp, XT_STK_A15 + #endif + + #if XCHAL_CP_NUM > 0 + /* Ensure wsr.CPENABLE has completed. */ + rsync + #endif + + /* + Must return via the exit dispatcher corresponding to the entrypoint from which + this was called. Interruptee's A0, A1, PS, PC are restored and the interrupt + stack frame is deallocated in the exit dispatcher. + */ + l32i a0, sp, XT_STK_EXIT + ret + + +/* +********************************************************************************************************** +* PERFORM A SOLICTED CONTEXT SWITCH (from a task) +* void vPortYield(void) +* +* This function saves the minimal state needed for a solicited task suspension, clears CPENABLE, +* then tail-calls the dispatcher _frxt_dispatch() to perform the actual context switch +* +* At Entry: +* pxCurrentTCB points to the TCB of the task to suspend +* Callable from C (obeys ABI conventions on entry). +* +* Does not return to caller. +* +********************************************************************************************************** +*/ + .globl vPortYield + .type vPortYield,@function + .align 4 +vPortYield: + + #ifdef __XTENSA_CALL0_ABI__ + addi sp, sp, -XT_SOL_FRMSZ + #else + entry sp, XT_SOL_FRMSZ + #endif + + rsr a2, PS + s32i a0, sp, XT_SOL_PC + s32i a2, sp, XT_SOL_PS + #ifdef __XTENSA_CALL0_ABI__ + s32i a12, sp, XT_SOL_A12 /* save callee-saved registers */ + s32i a13, sp, XT_SOL_A13 + s32i a14, sp, XT_SOL_A14 + s32i a15, sp, XT_SOL_A15 + #else + /* Spill register windows. Calling xthal_window_spill() causes extra */ + /* spills and reloads, so we will set things up to call the _nw version */ + /* instead to save cycles. */ + movi a6, ~(PS_WOE_MASK|PS_INTLEVEL_MASK) /* spills a4-a7 if needed */ + and a2, a2, a6 /* clear WOE, INTLEVEL */ + addi a2, a2, XCHAL_EXCM_LEVEL /* set INTLEVEL */ + wsr a2, PS + rsync + call0 xthal_window_spill_nw + l32i a2, sp, XT_SOL_PS /* restore PS */ + wsr a2, PS + #endif + + rsil a2, XCHAL_EXCM_LEVEL /* disable low/med interrupts */ + + #if XCHAL_CP_NUM > 0 + /* Save coprocessor callee-saved state (if any). At this point CPENABLE */ + /* should still reflect which CPs were in use (enabled). */ + call0 _xt_coproc_savecs + #endif + + movi a2, pxCurrentTCB + getcoreid a3 + slli a3, a3, 2 + add a2, a2, a3 + l32i a2, a2, 0 /* a2 = pxCurrentTCB */ + movi a3, 0 + s32i a3, sp, XT_SOL_EXIT /* 0 to flag as solicited frame */ + s32i sp, a2, TOPOFSTACK_OFFS /* pxCurrentTCB->pxTopOfStack = SP */ + + #if XCHAL_CP_NUM > 0 + /* Clear CPENABLE, also in task's co-processor state save area. */ + l32i a2, a2, CP_TOPOFSTACK_OFFS /* a2 = pxCurrentTCB->cp_state */ + movi a3, 0 + wsr a3, CPENABLE + beqz a2, 1f + s16i a3, a2, XT_CPENABLE /* clear saved cpenable */ +1: + #endif + + /* Tail-call dispatcher. */ + call0 _frxt_dispatch + /* Never reaches here. */ + + +/* +********************************************************************************************************** +* PERFORM AN UNSOLICITED CONTEXT SWITCH (from an interrupt) +* void vPortYieldFromInt(void) +* +* This calls the context switch hook (removed), saves and clears CPENABLE, then tail-calls the dispatcher +* _frxt_dispatch() to perform the actual context switch. +* +* At Entry: +* Interrupted task context has been saved in an interrupt stack frame at pxCurrentTCB->pxTopOfStack. +* pxCurrentTCB points to the TCB of the task to suspend, +* Callable from C (obeys ABI conventions on entry). +* +* At Exit: +* Windowed ABI defers the actual context switch until the stack is unwound to interrupt entry. +* Call0 ABI tail-calls the dispatcher directly (no need to unwind) so does not return to caller. +* +********************************************************************************************************** +*/ + .globl vPortYieldFromInt + .type vPortYieldFromInt,@function + .align 4 +vPortYieldFromInt: + + ENTRY(16) + + #if XCHAL_CP_NUM > 0 + /* Save CPENABLE in task's co-processor save area, and clear CPENABLE. */ + movi a3, pxCurrentTCB /* cp_state = */ + getcoreid a2 + slli a2, a2, 2 + add a3, a2, a3 + l32i a3, a3, 0 + + l32i a2, a3, CP_TOPOFSTACK_OFFS + + rsr a3, CPENABLE + s16i a3, a2, XT_CPENABLE /* cp_state->cpenable = CPENABLE; */ + movi a3, 0 + wsr a3, CPENABLE /* disable all co-processors */ + #endif + + #ifdef __XTENSA_CALL0_ABI__ + /* Tail-call dispatcher. */ + call0 _frxt_dispatch + /* Never reaches here. */ + #else + RET(16) + #endif + +/* +********************************************************************************************************** +* _frxt_task_coproc_state +* void _frxt_task_coproc_state(void) +* +* Implements the Xtensa RTOS porting layer's XT_RTOS_CP_STATE function for FreeRTOS. +* +* May only be called when a task is running, not within an interrupt handler (returns 0 in that case). +* May only be called from assembly code by the 'call0' instruction. Does NOT obey ABI conventions. +* Returns in A15 a pointer to the base of the co-processor state save area for the current task. +* See the detailed description of the XT_RTOS_ENTER macro in xtensa_rtos.h. +* +********************************************************************************************************** +*/ +#if XCHAL_CP_NUM > 0 + + .globl _frxt_task_coproc_state + .type _frxt_task_coproc_state,@function + .align 4 +_frxt_task_coproc_state: + + + /* We can use a3 as a scratchpad, the instances of code calling XT_RTOS_CP_STATE don't seem to need it saved. */ + getcoreid a3 + slli a3, a3, 2 /* a3=coreid*4 */ + movi a15, port_xSchedulerRunning /* if (port_xSchedulerRunning */ + add a15, a15, a3 + l32i a15, a15, 0 + beqz a15, 1f + movi a15, port_interruptNesting /* && port_interruptNesting == 0 */ + add a15, a15, a3 + l32i a15, a15, 0 + bnez a15, 1f + + movi a15, pxCurrentTCB + add a15, a3, a15 + l32i a15, a15, 0 /* && pxCurrentTCB != 0) { */ + + + beqz a15, 2f + l32i a15, a15, CP_TOPOFSTACK_OFFS + ret + +1: movi a15, 0 +2: ret + +#endif /* XCHAL_CP_NUM > 0 */ diff --git a/components/freertos/queue.c b/components/freertos/queue.c new file mode 100644 index 0000000000..337352fca8 --- /dev/null +++ b/components/freertos/queue.c @@ -0,0 +1,2642 @@ +/* + FreeRTOS V8.2.0 - Copyright (C) 2015 Real Time Engineers Ltd. + All rights reserved + + VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION. + + This file is part of the FreeRTOS distribution. + + FreeRTOS is free software; you can redistribute it and/or modify it under + the terms of the GNU General Public License (version 2) as published by the + Free Software Foundation >>!AND MODIFIED BY!<< the FreeRTOS exception. + + *************************************************************************** + >>! NOTE: The modification to the GPL is included to allow you to !<< + >>! distribute a combined work that includes FreeRTOS without being !<< + >>! obliged to provide the source code for proprietary components !<< + >>! outside of the FreeRTOS kernel. !<< + *************************************************************************** + + FreeRTOS is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + FOR A PARTICULAR PURPOSE. Full license text is available on the following + link: http://www.freertos.org/a00114.html + + *************************************************************************** + * * + * FreeRTOS provides completely free yet professionally developed, * + * robust, strictly quality controlled, supported, and cross * + * platform software that is more than just the market leader, it * + * is the industry's de facto standard. * + * * + * Help yourself get started quickly while simultaneously helping * + * to support the FreeRTOS project by purchasing a FreeRTOS * + * tutorial book, reference manual, or both: * + * http://www.FreeRTOS.org/Documentation * + * * + *************************************************************************** + + http://www.FreeRTOS.org/FAQHelp.html - Having a problem? Start by reading + the FAQ page "My application does not run, what could be wrong?". Have you + defined configASSERT()? + + http://www.FreeRTOS.org/support - In return for receiving this top quality + embedded software for free we request you assist our global community by + participating in the support forum. + + http://www.FreeRTOS.org/training - Investing in training allows your team to + be as productive as possible as early as possible. Now you can receive + FreeRTOS training directly from Richard Barry, CEO of Real Time Engineers + Ltd, and the world's leading authority on the world's leading RTOS. + + http://www.FreeRTOS.org/plus - A selection of FreeRTOS ecosystem products, + including FreeRTOS+Trace - an indispensable productivity tool, a DOS + compatible FAT file system, and our tiny thread aware UDP/IP stack. + + http://www.FreeRTOS.org/labs - Where new FreeRTOS products go to incubate. + Come and try FreeRTOS+TCP, our new open source TCP/IP stack for FreeRTOS. + + http://www.OpenRTOS.com - Real Time Engineers ltd. license FreeRTOS to High + Integrity Systems ltd. to sell under the OpenRTOS brand. Low cost OpenRTOS + licenses offer ticketed support, indemnification and commercial middleware. + + http://www.SafeRTOS.com - High Integrity Systems also provide a safety + engineered and independently SIL3 certified version for use in safety and + mission critical applications that require provable dependability. + + 1 tab == 4 spaces! +*/ + + + +/* + ToDo: The multicore implementation of this uses taskENTER_CRITICAL etc to make sure the + queue structures aren't accessed by another processor or core. It would be useful to have + IRQs be able to schedule stuff while doing task-related stuff, meaning we have to convert + the taskENTER_CRITICAL stuff to a lock + a scheduler suspend instead. +*/ + +#include +#include + +#include "rom/ets_sys.h" + +/* Defining MPU_WRAPPERS_INCLUDED_FROM_API_FILE prevents task.h from redefining +all the API functions to use the MPU wrappers. That should only be done when +task.h is included from an application file. */ +#define MPU_WRAPPERS_INCLUDED_FROM_API_FILE + +#include "FreeRTOS.h" +#include "task.h" +#include "queue.h" + +#if ( configUSE_CO_ROUTINES == 1 ) + #include "croutine.h" +#endif + +/* Lint e961 and e750 are suppressed as a MISRA exception justified because the +MPU ports require MPU_WRAPPERS_INCLUDED_FROM_API_FILE to be defined for the +header files above, but not in this file, in order to generate the correct +privileged Vs unprivileged linkage and placement. */ +#undef MPU_WRAPPERS_INCLUDED_FROM_API_FILE /*lint !e961 !e750. */ + + +/* Constants used with the xRxLock and xTxLock structure members. */ +#define queueUNLOCKED ( ( BaseType_t ) -1 ) +#define queueLOCKED_UNMODIFIED ( ( BaseType_t ) 0 ) + +/* When the Queue_t structure is used to represent a base queue its pcHead and +pcTail members are used as pointers into the queue storage area. When the +Queue_t structure is used to represent a mutex pcHead and pcTail pointers are +not necessary, and the pcHead pointer is set to NULL to indicate that the +pcTail pointer actually points to the mutex holder (if any). Map alternative +names to the pcHead and pcTail structure members to ensure the readability of +the code is maintained despite this dual use of two structure members. An +alternative implementation would be to use a union, but use of a union is +against the coding standard (although an exception to the standard has been +permitted where the dual use also significantly changes the type of the +structure member). */ +#define pxMutexHolder pcTail +#define uxQueueType pcHead +#define queueQUEUE_IS_MUTEX NULL + +/* Semaphores do not actually store or copy data, so have an item size of +zero. */ +#define queueSEMAPHORE_QUEUE_ITEM_LENGTH ( ( UBaseType_t ) 0 ) +#define queueMUTEX_GIVE_BLOCK_TIME ( ( TickType_t ) 0U ) + +#if( configUSE_PREEMPTION == 0 ) + /* If the cooperative scheduler is being used then a yield should not be + performed just because a higher priority task has been woken. */ + #define queueYIELD_IF_USING_PREEMPTION_MUX() + #define queueYIELD_IF_USING_PREEMPTION() +#else + #define queueYIELD_IF_USING_PREEMPTION() portYIELD_WITHIN_API() + #define queueYIELD_IF_USING_PREEMPTION_MUX(mux) { \ + taskEXIT_CRITICAL(mux); \ + portYIELD_WITHIN_API(); \ + taskENTER_CRITICAL(mux); \ + } while(0) +#endif + +/* + * Definition of the queue used by the scheduler. + * Items are queued by copy, not reference. See the following link for the + * rationale: http://www.freertos.org/Embedded-RTOS-Queues.html + */ +typedef struct QueueDefinition +{ + int8_t *pcHead; /*< Points to the beginning of the queue storage area. */ + int8_t *pcTail; /*< Points to the byte at the end of the queue storage area. Once more byte is allocated than necessary to store the queue items, this is used as a marker. */ + int8_t *pcWriteTo; /*< Points to the free next place in the storage area. */ + + union /* Use of a union is an exception to the coding standard to ensure two mutually exclusive structure members don't appear simultaneously (wasting RAM). */ + { + int8_t *pcReadFrom; /*< Points to the last place that a queued item was read from when the structure is used as a queue. */ + UBaseType_t uxRecursiveCallCount;/*< Maintains a count of the number of times a recursive mutex has been recursively 'taken' when the structure is used as a mutex. */ + } u; + + List_t xTasksWaitingToSend; /*< List of tasks that are blocked waiting to post onto this queue. Stored in priority order. */ + List_t xTasksWaitingToReceive; /*< List of tasks that are blocked waiting to read from this queue. Stored in priority order. */ + + volatile UBaseType_t uxMessagesWaiting;/*< The number of items currently in the queue. */ + UBaseType_t uxLength; /*< The length of the queue defined as the number of items it will hold, not the number of bytes. */ + UBaseType_t uxItemSize; /*< The size of each items that the queue will hold. */ + + volatile BaseType_t xRxLock; /*< Stores the number of items received from the queue (removed from the queue) while the queue was locked. Set to queueUNLOCKED when the queue is not locked. */ + volatile BaseType_t xTxLock; /*< Stores the number of items transmitted to the queue (added to the queue) while the queue was locked. Set to queueUNLOCKED when the queue is not locked. */ + + #if ( configUSE_TRACE_FACILITY == 1 ) + UBaseType_t uxQueueNumber; + uint8_t ucQueueType; + #endif + + #if ( configUSE_QUEUE_SETS == 1 ) + struct QueueDefinition *pxQueueSetContainer; + #endif + + portMUX_TYPE mux; + +} xQUEUE; + +/* The old xQUEUE name is maintained above then typedefed to the new Queue_t +name below to enable the use of older kernel aware debuggers. */ +typedef xQUEUE Queue_t; + +/*-----------------------------------------------------------*/ + +/* + * The queue registry is just a means for kernel aware debuggers to locate + * queue structures. It has no other purpose so is an optional component. + */ +#if ( configQUEUE_REGISTRY_SIZE > 0 ) + + /* The type stored within the queue registry array. This allows a name + to be assigned to each queue making kernel aware debugging a little + more user friendly. */ + typedef struct QUEUE_REGISTRY_ITEM + { + const char *pcQueueName; /*lint !e971 Unqualified char types are allowed for strings and single characters only. */ + QueueHandle_t xHandle; + } xQueueRegistryItem; + + /* The old xQueueRegistryItem name is maintained above then typedefed to the + new xQueueRegistryItem name below to enable the use of older kernel aware + debuggers. */ + typedef xQueueRegistryItem QueueRegistryItem_t; + + /* The queue registry is simply an array of QueueRegistryItem_t structures. + The pcQueueName member of a structure being NULL is indicative of the + array position being vacant. */ + QueueRegistryItem_t xQueueRegistry[ configQUEUE_REGISTRY_SIZE ]; + +#endif /* configQUEUE_REGISTRY_SIZE */ + +/* + * Unlocks a queue locked by a call to prvLockQueue. Locking a queue does not + * prevent an ISR from adding or removing items to the queue, but does prevent + * an ISR from removing tasks from the queue event lists. If an ISR finds a + * queue is locked it will instead increment the appropriate queue lock count + * to indicate that a task may require unblocking. When the queue in unlocked + * these lock counts are inspected, and the appropriate action taken. + */ +static void prvUnlockQueue( Queue_t * const pxQueue ) PRIVILEGED_FUNCTION; + +/* + * Uses a critical section to determine if there is any data in a queue. + * + * @return pdTRUE if the queue contains no items, otherwise pdFALSE. + */ +static BaseType_t prvIsQueueEmpty( Queue_t *pxQueue ) PRIVILEGED_FUNCTION; + +/* + * Uses a critical section to determine if there is any space in a queue. + * + * @return pdTRUE if there is no space, otherwise pdFALSE; + */ +static BaseType_t prvIsQueueFull( Queue_t *pxQueue ) PRIVILEGED_FUNCTION; + +/* + * Copies an item into the queue, either at the front of the queue or the + * back of the queue. + */ +static BaseType_t prvCopyDataToQueue( Queue_t * const pxQueue, const void *pvItemToQueue, const BaseType_t xPosition ) PRIVILEGED_FUNCTION; + +/* + * Copies an item out of a queue. + */ +static void prvCopyDataFromQueue( Queue_t * const pxQueue, void * const pvBuffer ) PRIVILEGED_FUNCTION; + +#if ( configUSE_QUEUE_SETS == 1 ) + /* + * Checks to see if a queue is a member of a queue set, and if so, notifies + * the queue set that the queue contains data. + */ + static BaseType_t prvNotifyQueueSetContainer( const Queue_t * const pxQueue, const BaseType_t xCopyPosition ) PRIVILEGED_FUNCTION; +#endif + +/*-----------------------------------------------------------*/ + +/* + * Macro to mark a queue as locked. Locking a queue prevents an ISR from + * accessing the queue event lists. + */ +#define prvLockQueue( pxQueue ) \ + taskENTER_CRITICAL(&pxQueue->mux); \ + { \ + if( ( pxQueue )->xRxLock == queueUNLOCKED ) \ + { \ + ( pxQueue )->xRxLock = queueLOCKED_UNMODIFIED; \ + } \ + if( ( pxQueue )->xTxLock == queueUNLOCKED ) \ + { \ + ( pxQueue )->xTxLock = queueLOCKED_UNMODIFIED; \ + } \ + } \ + taskEXIT_CRITICAL(&pxQueue->mux) +/*-----------------------------------------------------------*/ + +BaseType_t xQueueGenericReset( QueueHandle_t xQueue, BaseType_t xNewQueue ) +{ +Queue_t * const pxQueue = ( Queue_t * ) xQueue; + + configASSERT( pxQueue ); + + if ( xNewQueue == pdTRUE ) + { + vPortCPUInitializeMutex(&pxQueue->mux); + } + taskENTER_CRITICAL(&pxQueue->mux); + { + pxQueue->pcTail = pxQueue->pcHead + ( pxQueue->uxLength * pxQueue->uxItemSize ); + pxQueue->uxMessagesWaiting = ( UBaseType_t ) 0U; + pxQueue->pcWriteTo = pxQueue->pcHead; + pxQueue->u.pcReadFrom = pxQueue->pcHead + ( ( pxQueue->uxLength - ( UBaseType_t ) 1U ) * pxQueue->uxItemSize ); + pxQueue->xRxLock = queueUNLOCKED; + pxQueue->xTxLock = queueUNLOCKED; + + if( xNewQueue == pdFALSE ) + { + /* If there are tasks blocked waiting to read from the queue, then + the tasks will remain blocked as after this function exits the queue + will still be empty. If there are tasks blocked waiting to write to + the queue, then one should be unblocked as after this function exits + it will be possible to write to it. */ + if( listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToSend ) ) == pdFALSE ) + { + if( xTaskRemoveFromEventList( &( pxQueue->xTasksWaitingToSend ) ) == pdTRUE ) + { + queueYIELD_IF_USING_PREEMPTION_MUX(&pxQueue->mux); + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } + else + { + /* Ensure the event queues start in the correct state. */ + vListInitialise( &( pxQueue->xTasksWaitingToSend ) ); + vListInitialise( &( pxQueue->xTasksWaitingToReceive ) ); + } + } + taskEXIT_CRITICAL(&pxQueue->mux); + + /* A value is returned for calling semantic consistency with previous + versions. */ + return pdPASS; +} +/*-----------------------------------------------------------*/ + +QueueHandle_t xQueueGenericCreate( const UBaseType_t uxQueueLength, const UBaseType_t uxItemSize, const uint8_t ucQueueType ) +{ +Queue_t *pxNewQueue; +size_t xQueueSizeInBytes; +QueueHandle_t xReturn = NULL; +int8_t *pcAllocatedBuffer; + + /* Remove compiler warnings about unused parameters should + configUSE_TRACE_FACILITY not be set to 1. */ + ( void ) ucQueueType; + + configASSERT( uxQueueLength > ( UBaseType_t ) 0 ); + + if( uxItemSize == ( UBaseType_t ) 0 ) + { + /* There is not going to be a queue storage area. */ + xQueueSizeInBytes = ( size_t ) 0; + } + else + { + /* The queue is one byte longer than asked for to make wrap checking + easier/faster. */ + xQueueSizeInBytes = ( size_t ) ( uxQueueLength * uxItemSize ) + ( size_t ) 1; /*lint !e961 MISRA exception as the casts are only redundant for some ports. */ + } + + /* Allocate the new queue structure and storage area. */ + pcAllocatedBuffer = ( int8_t * ) pvPortMalloc( sizeof( Queue_t ) + xQueueSizeInBytes ); + + if( pcAllocatedBuffer != NULL ) + { + pxNewQueue = ( Queue_t * ) pcAllocatedBuffer; /*lint !e826 MISRA The buffer cannot be to small because it was dimensioned by sizeof( Queue_t ) + xQueueSizeInBytes. */ + + if( uxItemSize == ( UBaseType_t ) 0 ) + { + /* No RAM was allocated for the queue storage area, but PC head + cannot be set to NULL because NULL is used as a key to say the queue + is used as a mutex. Therefore just set pcHead to point to the queue + as a benign value that is known to be within the memory map. */ + pxNewQueue->pcHead = ( int8_t * ) pxNewQueue; + } + else + { + /* Jump past the queue structure to find the location of the queue + storage area - adding the padding bytes to get a better alignment. */ + pxNewQueue->pcHead = pcAllocatedBuffer + sizeof( Queue_t ); + } + + /* Initialise the queue members as described above where the queue type + is defined. */ + pxNewQueue->uxLength = uxQueueLength; + pxNewQueue->uxItemSize = uxItemSize; + ( void ) xQueueGenericReset( pxNewQueue, pdTRUE ); + + #if ( configUSE_TRACE_FACILITY == 1 ) + { + pxNewQueue->ucQueueType = ucQueueType; + } + #endif /* configUSE_TRACE_FACILITY */ + + #if( configUSE_QUEUE_SETS == 1 ) + { + pxNewQueue->pxQueueSetContainer = NULL; + } + #endif /* configUSE_QUEUE_SETS */ + + traceQUEUE_CREATE( pxNewQueue ); + xReturn = pxNewQueue; + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + + configASSERT( xReturn ); + + return xReturn; +} +/*-----------------------------------------------------------*/ + +#if ( configUSE_MUTEXES == 1 ) + + QueueHandle_t xQueueCreateMutex( const uint8_t ucQueueType ) + { + Queue_t *pxNewQueue; + + /* Prevent compiler warnings about unused parameters if + configUSE_TRACE_FACILITY does not equal 1. */ + ( void ) ucQueueType; + + /* Allocate the new queue structure. */ + pxNewQueue = ( Queue_t * ) pvPortMalloc( sizeof( Queue_t ) ); + if( pxNewQueue != NULL ) + { + /* Information required for priority inheritance. */ + pxNewQueue->pxMutexHolder = NULL; + pxNewQueue->uxQueueType = queueQUEUE_IS_MUTEX; + + /* Queues used as a mutex no data is actually copied into or out + of the queue. */ + pxNewQueue->pcWriteTo = NULL; + pxNewQueue->u.pcReadFrom = NULL; + + /* Each mutex has a length of 1 (like a binary semaphore) and + an item size of 0 as nothing is actually copied into or out + of the mutex. */ + pxNewQueue->uxMessagesWaiting = ( UBaseType_t ) 0U; + pxNewQueue->uxLength = ( UBaseType_t ) 1U; + pxNewQueue->uxItemSize = ( UBaseType_t ) 0U; + pxNewQueue->xRxLock = queueUNLOCKED; + pxNewQueue->xTxLock = queueUNLOCKED; + + #if ( configUSE_TRACE_FACILITY == 1 ) + { + pxNewQueue->ucQueueType = ucQueueType; + } + #endif + + #if ( configUSE_QUEUE_SETS == 1 ) + { + pxNewQueue->pxQueueSetContainer = NULL; + } + #endif + + /* Ensure the event queues start with the correct state. */ + vListInitialise( &( pxNewQueue->xTasksWaitingToSend ) ); + vListInitialise( &( pxNewQueue->xTasksWaitingToReceive ) ); + + traceCREATE_MUTEX( pxNewQueue ); + + /* Start with the semaphore in the expected state. */ + ( void ) xQueueGenericSend( pxNewQueue, NULL, ( TickType_t ) 0U, queueSEND_TO_BACK ); + } + else + { + traceCREATE_MUTEX_FAILED(); + } + + configASSERT( pxNewQueue ); + return pxNewQueue; + } + +#endif /* configUSE_MUTEXES */ +/*-----------------------------------------------------------*/ + +#if ( ( configUSE_MUTEXES == 1 ) && ( INCLUDE_xSemaphoreGetMutexHolder == 1 ) ) + + void* xQueueGetMutexHolder( QueueHandle_t xSemaphore ) + { + void *pxReturn; + + /* This function is called by xSemaphoreGetMutexHolder(), and should not + be called directly. Note: This is a good way of determining if the + calling task is the mutex holder, but not a good way of determining the + identity of the mutex holder, as the holder may change between the + following critical section exiting and the function returning. */ + taskENTER_CRITICAL(); + { + if( ( ( Queue_t * ) xSemaphore )->uxQueueType == queueQUEUE_IS_MUTEX ) + { + pxReturn = ( void * ) ( ( Queue_t * ) xSemaphore )->pxMutexHolder; + } + else + { + pxReturn = NULL; + } + } + taskEXIT_CRITICAL(); + + return pxReturn; + } /*lint !e818 xSemaphore cannot be a pointer to const because it is a typedef. */ + +#endif +/*-----------------------------------------------------------*/ + +#if ( configUSE_RECURSIVE_MUTEXES == 1 ) + + BaseType_t xQueueGiveMutexRecursive( QueueHandle_t xMutex ) + { + BaseType_t xReturn; + Queue_t * const pxMutex = ( Queue_t * ) xMutex; + + configASSERT( pxMutex ); + + /* If this is the task that holds the mutex then pxMutexHolder will not + change outside of this task. If this task does not hold the mutex then + pxMutexHolder can never coincidentally equal the tasks handle, and as + this is the only condition we are interested in it does not matter if + pxMutexHolder is accessed simultaneously by another task. Therefore no + mutual exclusion is required to test the pxMutexHolder variable. */ + if( pxMutex->pxMutexHolder == ( void * ) xTaskGetCurrentTaskHandle() ) /*lint !e961 Not a redundant cast as TaskHandle_t is a typedef. */ + { + traceGIVE_MUTEX_RECURSIVE( pxMutex ); + + /* uxRecursiveCallCount cannot be zero if pxMutexHolder is equal to + the task handle, therefore no underflow check is required. Also, + uxRecursiveCallCount is only modified by the mutex holder, and as + there can only be one, no mutual exclusion is required to modify the + uxRecursiveCallCount member. */ + ( pxMutex->u.uxRecursiveCallCount )--; + + /* Have we unwound the call count? */ + if( pxMutex->u.uxRecursiveCallCount == ( UBaseType_t ) 0 ) + { + /* Return the mutex. This will automatically unblock any other + task that might be waiting to access the mutex. */ + ( void ) xQueueGenericSend( pxMutex, NULL, queueMUTEX_GIVE_BLOCK_TIME, queueSEND_TO_BACK ); + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + + xReturn = pdPASS; + } + else + { + /* The mutex cannot be given because the calling task is not the + holder. */ + xReturn = pdFAIL; + + traceGIVE_MUTEX_RECURSIVE_FAILED( pxMutex ); + } + + return xReturn; + } + +#endif /* configUSE_RECURSIVE_MUTEXES */ +/*-----------------------------------------------------------*/ + +#if ( configUSE_RECURSIVE_MUTEXES == 1 ) + + BaseType_t xQueueTakeMutexRecursive( QueueHandle_t xMutex, TickType_t xTicksToWait ) + { + BaseType_t xReturn; + Queue_t * const pxMutex = ( Queue_t * ) xMutex; + + configASSERT( pxMutex ); + + /* Comments regarding mutual exclusion as per those within + xQueueGiveMutexRecursive(). */ + + traceTAKE_MUTEX_RECURSIVE( pxMutex ); + + if( pxMutex->pxMutexHolder == ( void * ) xTaskGetCurrentTaskHandle() ) /*lint !e961 Cast is not redundant as TaskHandle_t is a typedef. */ + { + ( pxMutex->u.uxRecursiveCallCount )++; + xReturn = pdPASS; + } + else + { + xReturn = xQueueGenericReceive( pxMutex, NULL, xTicksToWait, pdFALSE ); + + /* pdPASS will only be returned if the mutex was successfully + obtained. The calling task may have entered the Blocked state + before reaching here. */ + if( xReturn == pdPASS ) + { + ( pxMutex->u.uxRecursiveCallCount )++; + } + else + { + traceTAKE_MUTEX_RECURSIVE_FAILED( pxMutex ); + } + } + + return xReturn; + } + +#endif /* configUSE_RECURSIVE_MUTEXES */ +/*-----------------------------------------------------------*/ + +#if ( configUSE_COUNTING_SEMAPHORES == 1 ) + + QueueHandle_t xQueueCreateCountingSemaphore( const UBaseType_t uxMaxCount, const UBaseType_t uxInitialCount ) + { + QueueHandle_t xHandle; + + configASSERT( uxMaxCount != 0 ); + configASSERT( uxInitialCount <= uxMaxCount ); + + xHandle = xQueueGenericCreate( uxMaxCount, queueSEMAPHORE_QUEUE_ITEM_LENGTH, queueQUEUE_TYPE_COUNTING_SEMAPHORE ); + + if( xHandle != NULL ) + { + ( ( Queue_t * ) xHandle )->uxMessagesWaiting = uxInitialCount; + + traceCREATE_COUNTING_SEMAPHORE(); + } + else + { + traceCREATE_COUNTING_SEMAPHORE_FAILED(); + } + + configASSERT( xHandle ); + return xHandle; + } + +#endif /* configUSE_COUNTING_SEMAPHORES */ +/*-----------------------------------------------------------*/ + +BaseType_t xQueueGenericSend( QueueHandle_t xQueue, const void * const pvItemToQueue, TickType_t xTicksToWait, const BaseType_t xCopyPosition ) +{ +BaseType_t xEntryTimeSet = pdFALSE, xYieldRequired; +TimeOut_t xTimeOut; +Queue_t * const pxQueue = ( Queue_t * ) xQueue; + + configASSERT( pxQueue ); + configASSERT( !( ( pvItemToQueue == NULL ) && ( pxQueue->uxItemSize != ( UBaseType_t ) 0U ) ) ); + configASSERT( !( ( xCopyPosition == queueOVERWRITE ) && ( pxQueue->uxLength != 1 ) ) ); + #if ( ( INCLUDE_xTaskGetSchedulerState == 1 ) || ( configUSE_TIMERS == 1 ) ) + { + configASSERT( !( ( xTaskGetSchedulerState() == taskSCHEDULER_SUSPENDED ) && ( xTicksToWait != 0 ) ) ); + } + #endif + + + /* This function relaxes the coding standard somewhat to allow return + statements within the function itself. This is done in the interest + of execution time efficiency. */ + for( ;; ) + { + taskENTER_CRITICAL(&pxQueue->mux); + { + /* Is there room on the queue now? The running task must be + the highest priority task wanting to access the queue. If + the head item in the queue is to be overwritten then it does + not matter if the queue is full. */ + if( ( pxQueue->uxMessagesWaiting < pxQueue->uxLength ) || ( xCopyPosition == queueOVERWRITE ) ) + { + traceQUEUE_SEND( pxQueue ); + xYieldRequired = prvCopyDataToQueue( pxQueue, pvItemToQueue, xCopyPosition ); + + #if ( configUSE_QUEUE_SETS == 1 ) + { + if( pxQueue->pxQueueSetContainer != NULL ) + { + if( prvNotifyQueueSetContainer( pxQueue, xCopyPosition ) == pdTRUE ) + { + /* The queue is a member of a queue set, and posting + to the queue set caused a higher priority task to + unblock. A context switch is required. */ + queueYIELD_IF_USING_PREEMPTION_MUX(&pxQueue->mux); + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } + else + { + /* If there was a task waiting for data to arrive on the + queue then unblock it now. */ + if( listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToReceive ) ) == pdFALSE ) + { + if( xTaskRemoveFromEventList( &( pxQueue->xTasksWaitingToReceive ) ) == pdTRUE ) + { + /* The unblocked task has a priority higher than + our own so yield immediately. Yes it is ok to + do this from within the critical section - the + kernel takes care of that. */ + queueYIELD_IF_USING_PREEMPTION_MUX(&pxQueue->mux); + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } + else if( xYieldRequired != pdFALSE ) + { + /* This path is a special case that will only get + executed if the task was holding multiple mutexes + and the mutexes were given back in an order that is + different to that in which they were taken. */ + queueYIELD_IF_USING_PREEMPTION_MUX(&pxQueue->mux); + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } + } + #else /* configUSE_QUEUE_SETS */ + { + /* If there was a task waiting for data to arrive on the + queue then unblock it now. */ + if( listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToReceive ) ) == pdFALSE ) + { + if( xTaskRemoveFromEventList( &( pxQueue->xTasksWaitingToReceive ) ) == pdTRUE ) + { + /* The unblocked task has a priority higher than + our own so yield immediately. Yes it is ok to do + this from within the critical section - the kernel + takes care of that. */ + queueYIELD_IF_USING_PREEMPTION_MUX(&pxQueue->mux); + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } + else if( xYieldRequired != pdFALSE ) + { + /* This path is a special case that will only get + executed if the task was holding multiple mutexes and + the mutexes were given back in an order that is + different to that in which they were taken. */ + queueYIELD_IF_USING_PREEMPTION_MUX(&pxQueue->mux); + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } + #endif /* configUSE_QUEUE_SETS */ + + taskEXIT_CRITICAL(&pxQueue->mux); + return pdPASS; + } + else + { + if( xTicksToWait == ( TickType_t ) 0 ) + { + /* The queue was full and no block time is specified (or + the block time has expired) so leave now. */ + taskEXIT_CRITICAL(&pxQueue->mux); + + /* Return to the original privilege level before exiting + the function. */ + traceQUEUE_SEND_FAILED( pxQueue ); + return errQUEUE_FULL; + } + else if( xEntryTimeSet == pdFALSE ) + { + /* The queue was full and a block time was specified so + configure the timeout structure. */ + vTaskSetTimeOutState( &xTimeOut ); + xEntryTimeSet = pdTRUE; + } + else + { + /* Entry time was already set. */ + mtCOVERAGE_TEST_MARKER(); + } + } + } + taskEXIT_CRITICAL(&pxQueue->mux); + + /* Interrupts and other tasks can send to and receive from the queue + now the critical section has been exited. */ + + taskENTER_CRITICAL(&pxQueue->mux); +// prvLockQueue( pxQueue ); + + /* Update the timeout state to see if it has expired yet. */ + if( xTaskCheckForTimeOut( &xTimeOut, &xTicksToWait ) == pdFALSE ) + { + if( prvIsQueueFull( pxQueue ) != pdFALSE ) + { + traceBLOCKING_ON_QUEUE_SEND( pxQueue ); + vTaskPlaceOnEventList( &( pxQueue->xTasksWaitingToSend ), xTicksToWait ); + + /* Unlocking the queue means queue events can effect the + event list. It is possible that interrupts occurring now + remove this task from the event list again - but as the + scheduler is suspended the task will go onto the pending + ready last instead of the actual ready list. */ +// prvUnlockQueue( pxQueue ); + + + /* Resuming the scheduler will move tasks from the pending + ready list into the ready list - so it is feasible that this + task is already in a ready list before it yields - in which + case the yield will not cause a context switch unless there + is also a higher priority task in the pending ready list. */ + taskEXIT_CRITICAL(&pxQueue->mux); + portYIELD_WITHIN_API(); + } + else + { + /* Try again. */ +// prvUnlockQueue( pxQueue ); + taskEXIT_CRITICAL(&pxQueue->mux); + } + } + else + { + /* The timeout has expired. */ +// prvUnlockQueue( pxQueue ); + taskEXIT_CRITICAL(&pxQueue->mux); + + /* Return to the original privilege level before exiting the + function. */ + traceQUEUE_SEND_FAILED( pxQueue ); + return errQUEUE_FULL; + } + } +} +/*-----------------------------------------------------------*/ + +#if ( configUSE_ALTERNATIVE_API == 1 ) + + BaseType_t xQueueAltGenericSend( QueueHandle_t xQueue, const void * const pvItemToQueue, TickType_t xTicksToWait, BaseType_t xCopyPosition ) + { + BaseType_t xEntryTimeSet = pdFALSE; + TimeOut_t xTimeOut; + Queue_t * const pxQueue = ( Queue_t * ) xQueue; + + configASSERT( pxQueue ); + configASSERT( !( ( pvItemToQueue == NULL ) && ( pxQueue->uxItemSize != ( UBaseType_t ) 0U ) ) ); + + for( ;; ) + { + taskENTER_CRITICAL(&pxQueue->mux); + { + /* Is there room on the queue now? To be running we must be + the highest priority task wanting to access the queue. */ + if( pxQueue->uxMessagesWaiting < pxQueue->uxLength ) + { + traceQUEUE_SEND( pxQueue ); + prvCopyDataToQueue( pxQueue, pvItemToQueue, xCopyPosition ); + + /* If there was a task waiting for data to arrive on the + queue then unblock it now. */ + if( listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToReceive ) ) == pdFALSE ) + { + if( xTaskRemoveFromEventList( &( pxQueue->xTasksWaitingToReceive ) ) == pdTRUE ) + { + /* The unblocked task has a priority higher than + our own so yield immediately. */ + taskEXIT_CRITICAL(&pxQueue->mux); + portYIELD_WITHIN_API(); + taskENTER_CRITICAL(&pxQueue->mux); + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + + taskEXIT_CRITICAL(&pxQueue->mux); + return pdPASS; + } + else + { + if( xTicksToWait == ( TickType_t ) 0 ) + { + taskEXIT_CRITICAL(&pxQueue->mux); + return errQUEUE_FULL; + } + else if( xEntryTimeSet == pdFALSE ) + { + vTaskSetTimeOutState( &xTimeOut ); + xEntryTimeSet = pdTRUE; + } + } + } + taskEXIT_CRITICAL(&pxQueue->mux); + + taskENTER_CRITICAL(&pxQueue->mux); + { + if( xTaskCheckForTimeOut( &xTimeOut, &xTicksToWait ) == pdFALSE ) + { + if( prvIsQueueFull( pxQueue ) != pdFALSE ) + { + traceBLOCKING_ON_QUEUE_SEND( pxQueue ); + vTaskPlaceOnEventList( &( pxQueue->xTasksWaitingToSend ), xTicksToWait ); + taskEXIT_CRITICAL(&pxQueue->mux); + portYIELD_WITHIN_API(); + taskENTER_CRITICAL(&pxQueue->mux); + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } + else + { + taskEXIT_CRITICAL(&pxQueue->mux); + traceQUEUE_SEND_FAILED( pxQueue ); + return errQUEUE_FULL; + } + } + taskEXIT_CRITICAL(&pxQueue->mux); + } + } + +#endif /* configUSE_ALTERNATIVE_API */ +/*-----------------------------------------------------------*/ + +#if ( configUSE_ALTERNATIVE_API == 1 ) + + BaseType_t xQueueAltGenericReceive( QueueHandle_t xQueue, void * const pvBuffer, TickType_t xTicksToWait, BaseType_t xJustPeeking ) + { + BaseType_t xEntryTimeSet = pdFALSE; + TimeOut_t xTimeOut; + int8_t *pcOriginalReadPosition; + Queue_t * const pxQueue = ( Queue_t * ) xQueue; + + configASSERT( pxQueue ); + configASSERT( !( ( pvBuffer == NULL ) && ( pxQueue->uxItemSize != ( UBaseType_t ) 0U ) ) ); + ets_printf("Not Supported: %s\n", __FUNCTION__); + for( ;; ) + { + taskENTER_CRITICAL(); + { + if( pxQueue->uxMessagesWaiting > ( UBaseType_t ) 0 ) + { + /* Remember our read position in case we are just peeking. */ + pcOriginalReadPosition = pxQueue->u.pcReadFrom; + + prvCopyDataFromQueue( pxQueue, pvBuffer ); + + if( xJustPeeking == pdFALSE ) + { + traceQUEUE_RECEIVE( pxQueue ); + + /* Data is actually being removed (not just peeked). */ + --( pxQueue->uxMessagesWaiting ); + + #if ( configUSE_MUTEXES == 1 ) + { + if( pxQueue->uxQueueType == queueQUEUE_IS_MUTEX ) + { + /* Record the information required to implement + priority inheritance should it become necessary. */ + pxQueue->pxMutexHolder = ( int8_t * ) xTaskGetCurrentTaskHandle(); + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } + #endif + + if( listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToSend ) ) == pdFALSE ) + { + if( xTaskRemoveFromEventList( &( pxQueue->xTasksWaitingToSend ) ) == pdTRUE ) + { + portYIELD_WITHIN_API(); + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } + } + else + { + traceQUEUE_PEEK( pxQueue ); + + /* The data is not being removed, so reset our read + pointer. */ + pxQueue->u.pcReadFrom = pcOriginalReadPosition; + + /* The data is being left in the queue, so see if there are + any other tasks waiting for the data. */ + if( listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToReceive ) ) == pdFALSE ) + { + /* Tasks that are removed from the event list will get added to + the pending ready list as the scheduler is still suspended. */ + if( xTaskRemoveFromEventList( &( pxQueue->xTasksWaitingToReceive ) ) != pdFALSE ) + { + /* The task waiting has a higher priority than this task. */ + portYIELD_WITHIN_API(); + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } + + taskEXIT_CRITICAL(); + return pdPASS; + } + else + { + if( xTicksToWait == ( TickType_t ) 0 ) + { + taskEXIT_CRITICAL(); + traceQUEUE_RECEIVE_FAILED( pxQueue ); + return errQUEUE_EMPTY; + } + else if( xEntryTimeSet == pdFALSE ) + { + vTaskSetTimeOutState( &xTimeOut ); + xEntryTimeSet = pdTRUE; + } + } + } + taskEXIT_CRITICAL(); + + taskENTER_CRITICAL(); + { + if( xTaskCheckForTimeOut( &xTimeOut, &xTicksToWait ) == pdFALSE ) + { + if( prvIsQueueEmpty( pxQueue ) != pdFALSE ) + { + traceBLOCKING_ON_QUEUE_RECEIVE( pxQueue ); + + #if ( configUSE_MUTEXES == 1 ) + { + if( pxQueue->uxQueueType == queueQUEUE_IS_MUTEX ) + { + taskENTER_CRITICAL(); + { + vTaskPriorityInherit( ( void * ) pxQueue->pxMutexHolder ); + } + taskEXIT_CRITICAL(); + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } + #endif + + vTaskPlaceOnEventList( &( pxQueue->xTasksWaitingToReceive ), xTicksToWait ); + portYIELD_WITHIN_API(); + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } + else + { + taskEXIT_CRITICAL(); + traceQUEUE_RECEIVE_FAILED( pxQueue ); + return errQUEUE_EMPTY; + } + } + taskEXIT_CRITICAL(); + } + } + + +#endif /* configUSE_ALTERNATIVE_API */ +/*-----------------------------------------------------------*/ + +BaseType_t xQueueGenericSendFromISR( QueueHandle_t xQueue, const void * const pvItemToQueue, BaseType_t * const pxHigherPriorityTaskWoken, const BaseType_t xCopyPosition ) +{ +BaseType_t xReturn; +UBaseType_t uxSavedInterruptStatus; +Queue_t * const pxQueue = ( Queue_t * ) xQueue; + + configASSERT( pxQueue ); + configASSERT( !( ( pvItemToQueue == NULL ) && ( pxQueue->uxItemSize != ( UBaseType_t ) 0U ) ) ); + configASSERT( !( ( xCopyPosition == queueOVERWRITE ) && ( pxQueue->uxLength != 1 ) ) ); + + /* RTOS ports that support interrupt nesting have the concept of a maximum + system call (or maximum API call) interrupt priority. Interrupts that are + above the maximum system call priority are kept permanently enabled, even + when the RTOS kernel is in a critical section, but cannot make any calls to + FreeRTOS API functions. If configASSERT() is defined in FreeRTOSConfig.h + then portASSERT_IF_INTERRUPT_PRIORITY_INVALID() will result in an assertion + failure if a FreeRTOS API function is called from an interrupt that has been + assigned a priority above the configured maximum system call priority. + Only FreeRTOS functions that end in FromISR can be called from interrupts + that have been assigned a priority at or (logically) below the maximum + system call interrupt priority. FreeRTOS maintains a separate interrupt + safe API to ensure interrupt entry is as fast and as simple as possible. + More information (albeit Cortex-M specific) is provided on the following + link: http://www.freertos.org/RTOS-Cortex-M3-M4.html */ + portASSERT_IF_INTERRUPT_PRIORITY_INVALID(); + + /* Similar to xQueueGenericSend, except without blocking if there is no room + in the queue. Also don't directly wake a task that was blocked on a queue + read, instead return a flag to say whether a context switch is required or + not (i.e. has a task with a higher priority than us been woken by this + post). */ + uxSavedInterruptStatus = portSET_INTERRUPT_MASK_FROM_ISR(); + { + taskENTER_CRITICAL_ISR(&pxQueue->mux); + if( ( pxQueue->uxMessagesWaiting < pxQueue->uxLength ) || ( xCopyPosition == queueOVERWRITE ) ) + { + traceQUEUE_SEND_FROM_ISR( pxQueue ); + + /* A task can only have an inherited priority if it is a mutex + holder - and if there is a mutex holder then the mutex cannot be + given from an ISR. Therefore, unlike the xQueueGenericGive() + function, there is no need to determine the need for priority + disinheritance here or to clear the mutex holder TCB member. */ + ( void ) prvCopyDataToQueue( pxQueue, pvItemToQueue, xCopyPosition ); + + /* The event list is not altered if the queue is locked. This will + be done when the queue is unlocked later. */ + if( pxQueue->xTxLock == queueUNLOCKED ) + { + #if ( configUSE_QUEUE_SETS == 1 ) + { + if( pxQueue->pxQueueSetContainer != NULL ) + { + if( prvNotifyQueueSetContainer( pxQueue, xCopyPosition ) == pdTRUE ) + { + /* The queue is a member of a queue set, and posting + to the queue set caused a higher priority task to + unblock. A context switch is required. */ + if( pxHigherPriorityTaskWoken != NULL ) + { + *pxHigherPriorityTaskWoken = pdTRUE; + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } + else + { + if( listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToReceive ) ) == pdFALSE ) + { + if( xTaskRemoveFromEventList( &( pxQueue->xTasksWaitingToReceive ) ) != pdFALSE ) + { + /* The task waiting has a higher priority so + record that a context switch is required. */ + if( pxHigherPriorityTaskWoken != NULL ) + { + *pxHigherPriorityTaskWoken = pdTRUE; + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } + } + #else /* configUSE_QUEUE_SETS */ + { + if( listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToReceive ) ) == pdFALSE ) + { + if( xTaskRemoveFromEventList( &( pxQueue->xTasksWaitingToReceive ) ) != pdFALSE ) + { + /* The task waiting has a higher priority so record that a + context switch is required. */ + if( pxHigherPriorityTaskWoken != NULL ) + { + *pxHigherPriorityTaskWoken = pdTRUE; + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } + #endif /* configUSE_QUEUE_SETS */ + } + else + { + /* Increment the lock count so the task that unlocks the queue + knows that data was posted while it was locked. */ + ++( pxQueue->xTxLock ); + } + + xReturn = pdPASS; + } + else + { + traceQUEUE_SEND_FROM_ISR_FAILED( pxQueue ); + xReturn = errQUEUE_FULL; + } + taskEXIT_CRITICAL_ISR(&pxQueue->mux); + } + portCLEAR_INTERRUPT_MASK_FROM_ISR( uxSavedInterruptStatus ); + + return xReturn; +} +/*-----------------------------------------------------------*/ + +BaseType_t xQueueGiveFromISR( QueueHandle_t xQueue, BaseType_t * const pxHigherPriorityTaskWoken ) +{ +BaseType_t xReturn; +UBaseType_t uxSavedInterruptStatus; +Queue_t * const pxQueue = ( Queue_t * ) xQueue; + + configASSERT( pxQueue ); + + /* xQueueGenericSendFromISR() should be used in the item size is not 0. */ + configASSERT( pxQueue->uxItemSize == 0 ); + + /* RTOS ports that support interrupt nesting have the concept of a maximum + system call (or maximum API call) interrupt priority. Interrupts that are + above the maximum system call priority are kept permanently enabled, even + when the RTOS kernel is in a critical section, but cannot make any calls to + FreeRTOS API functions. If configASSERT() is defined in FreeRTOSConfig.h + then portASSERT_IF_INTERRUPT_PRIORITY_INVALID() will result in an assertion + failure if a FreeRTOS API function is called from an interrupt that has been + assigned a priority above the configured maximum system call priority. + Only FreeRTOS functions that end in FromISR can be called from interrupts + that have been assigned a priority at or (logically) below the maximum + system call interrupt priority. FreeRTOS maintains a separate interrupt + safe API to ensure interrupt entry is as fast and as simple as possible. + More information (albeit Cortex-M specific) is provided on the following + link: http://www.freertos.org/RTOS-Cortex-M3-M4.html */ + portASSERT_IF_INTERRUPT_PRIORITY_INVALID(); + + /* Similar to xQueueGenericSendFromISR() but used with semaphores where the + item size is 0. Don't directly wake a task that was blocked on a queue + read, instead return a flag to say whether a context switch is required or + not (i.e. has a task with a higher priority than us been woken by this + post). */ + uxSavedInterruptStatus = portSET_INTERRUPT_MASK_FROM_ISR(); + { + taskENTER_CRITICAL_ISR(&pxQueue->mux); + /* When the queue is used to implement a semaphore no data is ever + moved through the queue but it is still valid to see if the queue 'has + space'. */ + if( pxQueue->uxMessagesWaiting < pxQueue->uxLength ) + { + traceQUEUE_SEND_FROM_ISR( pxQueue ); + + /* A task can only have an inherited priority if it is a mutex + holder - and if there is a mutex holder then the mutex cannot be + given from an ISR. Therefore, unlike the xQueueGenericGive() + function, there is no need to determine the need for priority + disinheritance here or to clear the mutex holder TCB member. */ + + ++( pxQueue->uxMessagesWaiting ); + + /* The event list is not altered if the queue is locked. This will + be done when the queue is unlocked later. */ + if( pxQueue->xTxLock == queueUNLOCKED ) + { + #if ( configUSE_QUEUE_SETS == 1 ) + { + if( pxQueue->pxQueueSetContainer != NULL ) + { + if( prvNotifyQueueSetContainer( pxQueue, queueSEND_TO_BACK ) == pdTRUE ) + { + /* The semaphore is a member of a queue set, and + posting to the queue set caused a higher priority + task to unblock. A context switch is required. */ + if( pxHigherPriorityTaskWoken != NULL ) + { + *pxHigherPriorityTaskWoken = pdTRUE; + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } + else + { + if( listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToReceive ) ) == pdFALSE ) + { + if( xTaskRemoveFromEventList( &( pxQueue->xTasksWaitingToReceive ) ) != pdFALSE ) + { + /* The task waiting has a higher priority so + record that a context switch is required. */ + if( pxHigherPriorityTaskWoken != NULL ) + { + *pxHigherPriorityTaskWoken = pdTRUE; + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } + } + #else /* configUSE_QUEUE_SETS */ + { + if( listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToReceive ) ) == pdFALSE ) + { + if( xTaskRemoveFromEventList( &( pxQueue->xTasksWaitingToReceive ) ) != pdFALSE ) + { + /* The task waiting has a higher priority so record that a + context switch is required. */ + if( pxHigherPriorityTaskWoken != NULL ) + { + *pxHigherPriorityTaskWoken = pdTRUE; + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } + #endif /* configUSE_QUEUE_SETS */ + } + else + { + /* Increment the lock count so the task that unlocks the queue + knows that data was posted while it was locked. */ + ++( pxQueue->xTxLock ); + } + + xReturn = pdPASS; + } + else + { + traceQUEUE_SEND_FROM_ISR_FAILED( pxQueue ); + xReturn = errQUEUE_FULL; + } + taskEXIT_CRITICAL_ISR(&pxQueue->mux); + } + portCLEAR_INTERRUPT_MASK_FROM_ISR( uxSavedInterruptStatus ); + + return xReturn; +} +/*-----------------------------------------------------------*/ + +BaseType_t xQueueGenericReceive( QueueHandle_t xQueue, void * const pvBuffer, TickType_t xTicksToWait, const BaseType_t xJustPeeking ) +{ +BaseType_t xEntryTimeSet = pdFALSE; +TimeOut_t xTimeOut; +int8_t *pcOriginalReadPosition; +Queue_t * const pxQueue = ( Queue_t * ) xQueue; + + configASSERT( pxQueue ); + configASSERT( !( ( pvBuffer == NULL ) && ( pxQueue->uxItemSize != ( UBaseType_t ) 0U ) ) ); + #if ( ( INCLUDE_xTaskGetSchedulerState == 1 ) || ( configUSE_TIMERS == 1 ) ) + { + configASSERT( !( ( xTaskGetSchedulerState() == taskSCHEDULER_SUSPENDED ) && ( xTicksToWait != 0 ) ) ); + } + #endif + + /* This function relaxes the coding standard somewhat to allow return + statements within the function itself. This is done in the interest + of execution time efficiency. */ + + for( ;; ) + { + taskENTER_CRITICAL(&pxQueue->mux); + { + /* Is there data in the queue now? To be running the calling task + must be the highest priority task wanting to access the queue. */ + if( pxQueue->uxMessagesWaiting > ( UBaseType_t ) 0 ) + { + /* Remember the read position in case the queue is only being + peeked. */ + pcOriginalReadPosition = pxQueue->u.pcReadFrom; + + prvCopyDataFromQueue( pxQueue, pvBuffer ); + + if( xJustPeeking == pdFALSE ) + { + traceQUEUE_RECEIVE( pxQueue ); + + /* Actually removing data, not just peeking. */ + --( pxQueue->uxMessagesWaiting ); + + #if ( configUSE_MUTEXES == 1 ) + { + if( pxQueue->uxQueueType == queueQUEUE_IS_MUTEX ) + { + /* Record the information required to implement + priority inheritance should it become necessary. */ + pxQueue->pxMutexHolder = ( int8_t * ) pvTaskIncrementMutexHeldCount(); /*lint !e961 Cast is not redundant as TaskHandle_t is a typedef. */ + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } + #endif /* configUSE_MUTEXES */ + + if( listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToSend ) ) == pdFALSE ) + { + if( xTaskRemoveFromEventList( &( pxQueue->xTasksWaitingToSend ) ) == pdTRUE ) + { + queueYIELD_IF_USING_PREEMPTION_MUX(&pxQueue->mux); + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } + else + { + traceQUEUE_PEEK( pxQueue ); + + /* The data is not being removed, so reset the read + pointer. */ + pxQueue->u.pcReadFrom = pcOriginalReadPosition; + + /* The data is being left in the queue, so see if there are + any other tasks waiting for the data. */ + if( listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToReceive ) ) == pdFALSE ) + { + /* Tasks that are removed from the event list will get added to + the pending ready list as the scheduler is still suspended. */ + if( xTaskRemoveFromEventList( &( pxQueue->xTasksWaitingToReceive ) ) != pdFALSE ) + { + /* The task waiting has a higher priority than this task. */ + queueYIELD_IF_USING_PREEMPTION_MUX(&pxQueue->mux); + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } + + taskEXIT_CRITICAL(&pxQueue->mux); + return pdPASS; + } + else + { + if( xTicksToWait == ( TickType_t ) 0 ) + { + /* The queue was empty and no block time is specified (or + the block time has expired) so leave now. */ + traceQUEUE_RECEIVE_FAILED( pxQueue ); + taskEXIT_CRITICAL(&pxQueue->mux); + return errQUEUE_EMPTY; + } + else if( xEntryTimeSet == pdFALSE ) + { + /* The queue was empty and a block time was specified so + configure the timeout structure. */ + vTaskSetTimeOutState( &xTimeOut ); + xEntryTimeSet = pdTRUE; + } + else + { + /* Entry time was already set. */ + mtCOVERAGE_TEST_MARKER(); + } + } + } + taskEXIT_CRITICAL(&pxQueue->mux); + + /* Interrupts and other tasks can send to and receive from the queue + now the critical section has been exited. */ + + taskENTER_CRITICAL(&pxQueue->mux); +// prvLockQueue( pxQueue ); + + /* Update the timeout state to see if it has expired yet. */ + if( xTaskCheckForTimeOut( &xTimeOut, &xTicksToWait ) == pdFALSE ) + { + if( prvIsQueueEmpty( pxQueue ) != pdFALSE ) + { + traceBLOCKING_ON_QUEUE_RECEIVE( pxQueue ); + + #if ( configUSE_MUTEXES == 1 ) + { + if( pxQueue->uxQueueType == queueQUEUE_IS_MUTEX ) + { + vTaskPriorityInherit( ( void * ) pxQueue->pxMutexHolder ); + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } + #endif + + vTaskPlaceOnEventList( &( pxQueue->xTasksWaitingToReceive ), xTicksToWait ); +// prvUnlockQueue( pxQueue ); + taskEXIT_CRITICAL(&pxQueue->mux); + portYIELD_WITHIN_API(); + } + else + { + /* Try again. */ +// prvUnlockQueue( pxQueue ); + taskEXIT_CRITICAL(&pxQueue->mux); + } + } + else + { +// prvUnlockQueue( pxQueue ); + taskEXIT_CRITICAL(&pxQueue->mux); + traceQUEUE_RECEIVE_FAILED( pxQueue ); + return errQUEUE_EMPTY; + } + } +} +/*-----------------------------------------------------------*/ + +BaseType_t xQueueReceiveFromISR( QueueHandle_t xQueue, void * const pvBuffer, BaseType_t * const pxHigherPriorityTaskWoken ) +{ +BaseType_t xReturn; +UBaseType_t uxSavedInterruptStatus; +Queue_t * const pxQueue = ( Queue_t * ) xQueue; + + configASSERT( pxQueue ); + configASSERT( !( ( pvBuffer == NULL ) && ( pxQueue->uxItemSize != ( UBaseType_t ) 0U ) ) ); + + /* RTOS ports that support interrupt nesting have the concept of a maximum + system call (or maximum API call) interrupt priority. Interrupts that are + above the maximum system call priority are kept permanently enabled, even + when the RTOS kernel is in a critical section, but cannot make any calls to + FreeRTOS API functions. If configASSERT() is defined in FreeRTOSConfig.h + then portASSERT_IF_INTERRUPT_PRIORITY_INVALID() will result in an assertion + failure if a FreeRTOS API function is called from an interrupt that has been + assigned a priority above the configured maximum system call priority. + Only FreeRTOS functions that end in FromISR can be called from interrupts + that have been assigned a priority at or (logically) below the maximum + system call interrupt priority. FreeRTOS maintains a separate interrupt + safe API to ensure interrupt entry is as fast and as simple as possible. + More information (albeit Cortex-M specific) is provided on the following + link: http://www.freertos.org/RTOS-Cortex-M3-M4.html */ + portASSERT_IF_INTERRUPT_PRIORITY_INVALID(); + + uxSavedInterruptStatus = portSET_INTERRUPT_MASK_FROM_ISR(); + { + taskENTER_CRITICAL_ISR(&pxQueue->mux); + /* Cannot block in an ISR, so check there is data available. */ + if( pxQueue->uxMessagesWaiting > ( UBaseType_t ) 0 ) + { + traceQUEUE_RECEIVE_FROM_ISR( pxQueue ); + + prvCopyDataFromQueue( pxQueue, pvBuffer ); + --( pxQueue->uxMessagesWaiting ); + + /* If the queue is locked the event list will not be modified. + Instead update the lock count so the task that unlocks the queue + will know that an ISR has removed data while the queue was + locked. */ + if( pxQueue->xRxLock == queueUNLOCKED ) + { + if( listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToSend ) ) == pdFALSE ) + { + if( xTaskRemoveFromEventList( &( pxQueue->xTasksWaitingToSend ) ) != pdFALSE ) + { + /* The task waiting has a higher priority than us so + force a context switch. */ + if( pxHigherPriorityTaskWoken != NULL ) + { + *pxHigherPriorityTaskWoken = pdTRUE; + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } + else + { + /* Increment the lock count so the task that unlocks the queue + knows that data was removed while it was locked. */ + ++( pxQueue->xRxLock ); + } + + xReturn = pdPASS; + } + else + { + xReturn = pdFAIL; + traceQUEUE_RECEIVE_FROM_ISR_FAILED( pxQueue ); + } + taskEXIT_CRITICAL_ISR(&pxQueue->mux); + } + portCLEAR_INTERRUPT_MASK_FROM_ISR( uxSavedInterruptStatus ); + + return xReturn; +} +/*-----------------------------------------------------------*/ + +BaseType_t xQueuePeekFromISR( QueueHandle_t xQueue, void * const pvBuffer ) +{ +BaseType_t xReturn; +UBaseType_t uxSavedInterruptStatus; +int8_t *pcOriginalReadPosition; +Queue_t * const pxQueue = ( Queue_t * ) xQueue; + + configASSERT( pxQueue ); + configASSERT( !( ( pvBuffer == NULL ) && ( pxQueue->uxItemSize != ( UBaseType_t ) 0U ) ) ); + configASSERT( pxQueue->uxItemSize != 0 ); /* Can't peek a semaphore. */ + + /* RTOS ports that support interrupt nesting have the concept of a maximum + system call (or maximum API call) interrupt priority. Interrupts that are + above the maximum system call priority are kept permanently enabled, even + when the RTOS kernel is in a critical section, but cannot make any calls to + FreeRTOS API functions. If configASSERT() is defined in FreeRTOSConfig.h + then portASSERT_IF_INTERRUPT_PRIORITY_INVALID() will result in an assertion + failure if a FreeRTOS API function is called from an interrupt that has been + assigned a priority above the configured maximum system call priority. + Only FreeRTOS functions that end in FromISR can be called from interrupts + that have been assigned a priority at or (logically) below the maximum + system call interrupt priority. FreeRTOS maintains a separate interrupt + safe API to ensure interrupt entry is as fast and as simple as possible. + More information (albeit Cortex-M specific) is provided on the following + link: http://www.freertos.org/RTOS-Cortex-M3-M4.html */ + portASSERT_IF_INTERRUPT_PRIORITY_INVALID(); + + uxSavedInterruptStatus = portSET_INTERRUPT_MASK_FROM_ISR(); + taskENTER_CRITICAL_ISR(&pxQueue->mux); + { + /* Cannot block in an ISR, so check there is data available. */ + if( pxQueue->uxMessagesWaiting > ( UBaseType_t ) 0 ) + { + traceQUEUE_PEEK_FROM_ISR( pxQueue ); + + /* Remember the read position so it can be reset as nothing is + actually being removed from the queue. */ + pcOriginalReadPosition = pxQueue->u.pcReadFrom; + prvCopyDataFromQueue( pxQueue, pvBuffer ); + pxQueue->u.pcReadFrom = pcOriginalReadPosition; + + xReturn = pdPASS; + } + else + { + xReturn = pdFAIL; + traceQUEUE_PEEK_FROM_ISR_FAILED( pxQueue ); + } + } + taskEXIT_CRITICAL_ISR(&pxQueue->mux); + portCLEAR_INTERRUPT_MASK_FROM_ISR( uxSavedInterruptStatus ); + + return xReturn; +} +/*-----------------------------------------------------------*/ + +UBaseType_t uxQueueMessagesWaiting( const QueueHandle_t xQueue ) +{ +UBaseType_t uxReturn; +Queue_t * const pxQueue = ( Queue_t * ) xQueue; + + configASSERT( xQueue ); + + taskENTER_CRITICAL(&pxQueue->mux); + { + uxReturn = ( ( Queue_t * ) xQueue )->uxMessagesWaiting; + } + taskEXIT_CRITICAL(&pxQueue->mux); + + return uxReturn; +} /*lint !e818 Pointer cannot be declared const as xQueue is a typedef not pointer. */ +/*-----------------------------------------------------------*/ + +UBaseType_t uxQueueSpacesAvailable( const QueueHandle_t xQueue ) +{ +UBaseType_t uxReturn; +Queue_t *pxQueue; + + pxQueue = ( Queue_t * ) xQueue; + configASSERT( pxQueue ); + + taskENTER_CRITICAL(&pxQueue->mux); + { + uxReturn = pxQueue->uxLength - pxQueue->uxMessagesWaiting; + } + taskEXIT_CRITICAL(&pxQueue->mux); + + return uxReturn; +} /*lint !e818 Pointer cannot be declared const as xQueue is a typedef not pointer. */ +/*-----------------------------------------------------------*/ + +UBaseType_t uxQueueMessagesWaitingFromISR( const QueueHandle_t xQueue ) +{ +UBaseType_t uxReturn; +Queue_t * const pxQueue = ( Queue_t * ) xQueue; + + configASSERT( xQueue ); + + taskENTER_CRITICAL_ISR(&pxQueue->mux); + uxReturn = ( ( Queue_t * ) xQueue )->uxMessagesWaiting; + taskEXIT_CRITICAL_ISR(&pxQueue->mux); + + return uxReturn; +} /*lint !e818 Pointer cannot be declared const as xQueue is a typedef not pointer. */ +/*-----------------------------------------------------------*/ + +void vQueueDelete( QueueHandle_t xQueue ) +{ +Queue_t * const pxQueue = ( Queue_t * ) xQueue; + + configASSERT( pxQueue ); + + traceQUEUE_DELETE( pxQueue ); + #if ( configQUEUE_REGISTRY_SIZE > 0 ) + { + vQueueUnregisterQueue( pxQueue ); + } + #endif + vPortFree( pxQueue ); +} +/*-----------------------------------------------------------*/ + +#if ( configUSE_TRACE_FACILITY == 1 ) + + UBaseType_t uxQueueGetQueueNumber( QueueHandle_t xQueue ) + { + return ( ( Queue_t * ) xQueue )->uxQueueNumber; + } + +#endif /* configUSE_TRACE_FACILITY */ +/*-----------------------------------------------------------*/ + +#if ( configUSE_TRACE_FACILITY == 1 ) + + void vQueueSetQueueNumber( QueueHandle_t xQueue, UBaseType_t uxQueueNumber ) + { + ( ( Queue_t * ) xQueue )->uxQueueNumber = uxQueueNumber; + } + +#endif /* configUSE_TRACE_FACILITY */ +/*-----------------------------------------------------------*/ + +#if ( configUSE_TRACE_FACILITY == 1 ) + + uint8_t ucQueueGetQueueType( QueueHandle_t xQueue ) + { + return ( ( Queue_t * ) xQueue )->ucQueueType; + } + +#endif /* configUSE_TRACE_FACILITY */ +/*-----------------------------------------------------------*/ + +//This routine assumes the queue has already been locked. +static BaseType_t prvCopyDataToQueue( Queue_t * const pxQueue, const void *pvItemToQueue, const BaseType_t xPosition ) +{ +BaseType_t xReturn = pdFALSE; + + if( pxQueue->uxItemSize == ( UBaseType_t ) 0 ) + { + #if ( configUSE_MUTEXES == 1 ) + { + if( pxQueue->uxQueueType == queueQUEUE_IS_MUTEX ) + { + /* The mutex is no longer being held. */ + xReturn = xTaskPriorityDisinherit( ( void * ) pxQueue->pxMutexHolder ); + pxQueue->pxMutexHolder = NULL; + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } + #endif /* configUSE_MUTEXES */ + } + else if( xPosition == queueSEND_TO_BACK ) + { + ( void ) memcpy( ( void * ) pxQueue->pcWriteTo, pvItemToQueue, ( size_t ) pxQueue->uxItemSize ); /*lint !e961 !e418 MISRA exception as the casts are only redundant for some ports, plus previous logic ensures a null pointer can only be passed to memcpy() if the copy size is 0. */ + pxQueue->pcWriteTo += pxQueue->uxItemSize; + if( pxQueue->pcWriteTo >= pxQueue->pcTail ) /*lint !e946 MISRA exception justified as comparison of pointers is the cleanest solution. */ + { + pxQueue->pcWriteTo = pxQueue->pcHead; + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } + else + { + ( void ) memcpy( ( void * ) pxQueue->u.pcReadFrom, pvItemToQueue, ( size_t ) pxQueue->uxItemSize ); /*lint !e961 MISRA exception as the casts are only redundant for some ports. */ + pxQueue->u.pcReadFrom -= pxQueue->uxItemSize; + if( pxQueue->u.pcReadFrom < pxQueue->pcHead ) /*lint !e946 MISRA exception justified as comparison of pointers is the cleanest solution. */ + { + pxQueue->u.pcReadFrom = ( pxQueue->pcTail - pxQueue->uxItemSize ); + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + + if( xPosition == queueOVERWRITE ) + { + if( pxQueue->uxMessagesWaiting > ( UBaseType_t ) 0 ) + { + /* An item is not being added but overwritten, so subtract + one from the recorded number of items in the queue so when + one is added again below the number of recorded items remains + correct. */ + --( pxQueue->uxMessagesWaiting ); + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } + + ++( pxQueue->uxMessagesWaiting ); + + return xReturn; +} +/*-----------------------------------------------------------*/ + +static void prvCopyDataFromQueue( Queue_t * const pxQueue, void * const pvBuffer ) +{ + if( pxQueue->uxItemSize != ( UBaseType_t ) 0 ) + { + pxQueue->u.pcReadFrom += pxQueue->uxItemSize; + if( pxQueue->u.pcReadFrom >= pxQueue->pcTail ) /*lint !e946 MISRA exception justified as use of the relational operator is the cleanest solutions. */ + { + pxQueue->u.pcReadFrom = pxQueue->pcHead; + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + ( void ) memcpy( ( void * ) pvBuffer, ( void * ) pxQueue->u.pcReadFrom, ( size_t ) pxQueue->uxItemSize ); /*lint !e961 !e418 MISRA exception as the casts are only redundant for some ports. Also previous logic ensures a null pointer can only be passed to memcpy() when the count is 0. */ + } +} +/*-----------------------------------------------------------*/ + +static void prvUnlockQueue( Queue_t * const pxQueue ) +{ + /* THIS FUNCTION MUST BE CALLED WITH THE SCHEDULER SUSPENDED. */ + + /* The lock counts contains the number of extra data items placed or + removed from the queue while the queue was locked. When a queue is + locked items can be added or removed, but the event lists cannot be + updated. */ + taskENTER_CRITICAL(&pxQueue->mux); + { + /* See if data was added to the queue while it was locked. */ + while( pxQueue->xTxLock > queueLOCKED_UNMODIFIED ) + { + /* Data was posted while the queue was locked. Are any tasks + blocked waiting for data to become available? */ + #if ( configUSE_QUEUE_SETS == 1 ) + { + if( pxQueue->pxQueueSetContainer != NULL ) + { + if( prvNotifyQueueSetContainer( pxQueue, queueSEND_TO_BACK ) == pdTRUE ) + { + /* The queue is a member of a queue set, and posting to + the queue set caused a higher priority task to unblock. + A context switch is required. */ + taskEXIT_CRITICAL(&pxQueue->mux); //ToDo: Is aquire/release needed around any of the bTaskMissedYield calls? + vTaskMissedYield(); + taskENTER_CRITICAL(&pxQueue->mux); + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } + else + { + /* Tasks that are removed from the event list will get added to + the pending ready list as the scheduler is still suspended. */ + if( listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToReceive ) ) == pdFALSE ) + { + if( xTaskRemoveFromEventList( &( pxQueue->xTasksWaitingToReceive ) ) != pdFALSE ) + { + /* The task waiting has a higher priority so record that a + context switch is required. */ + taskEXIT_CRITICAL(&pxQueue->mux); + vTaskMissedYield(); + taskENTER_CRITICAL(&pxQueue->mux); + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } + else + { + break; + } + } + } + #else /* configUSE_QUEUE_SETS */ + { + /* Tasks that are removed from the event list will get added to + the pending ready list as the scheduler is still suspended. */ + if( listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToReceive ) ) == pdFALSE ) + { + if( xTaskRemoveFromEventList( &( pxQueue->xTasksWaitingToReceive ) ) != pdFALSE ) + { + /* The task waiting has a higher priority so record that a + context switch is required. */ + taskEXIT_CRITICAL(&pxQueue->mux); + vTaskMissedYield(); + taskENTER_CRITICAL(&pxQueue->mux); + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } + else + { + break; + } + } + #endif /* configUSE_QUEUE_SETS */ + + --( pxQueue->xTxLock ); + } + + pxQueue->xTxLock = queueUNLOCKED; + } + taskEXIT_CRITICAL(&pxQueue->mux); + + /* Do the same for the Rx lock. */ + taskENTER_CRITICAL(&pxQueue->mux); + { + while( pxQueue->xRxLock > queueLOCKED_UNMODIFIED ) + { + if( listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToSend ) ) == pdFALSE ) + { + if( xTaskRemoveFromEventList( &( pxQueue->xTasksWaitingToSend ) ) != pdFALSE ) + { + taskEXIT_CRITICAL(&pxQueue->mux); + vTaskMissedYield(); + taskENTER_CRITICAL(&pxQueue->mux); + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + + --( pxQueue->xRxLock ); + } + else + { + break; + } + } + + pxQueue->xRxLock = queueUNLOCKED; + } + taskEXIT_CRITICAL(&pxQueue->mux); +} +/*-----------------------------------------------------------*/ + +static BaseType_t prvIsQueueEmpty( Queue_t *pxQueue ) +{ +BaseType_t xReturn; + + //No lock needed: we read a base type. + { + if( pxQueue->uxMessagesWaiting == ( UBaseType_t ) 0 ) + { + xReturn = pdTRUE; + } + else + { + xReturn = pdFALSE; + } + } + + return xReturn; +} +/*-----------------------------------------------------------*/ + +BaseType_t xQueueIsQueueEmptyFromISR( QueueHandle_t xQueue ) +{ +BaseType_t xReturn; +Queue_t * const pxQueue = ( Queue_t * ) xQueue; + + configASSERT( xQueue ); + taskENTER_CRITICAL_ISR(&pxQueue->mux); + if( ( ( Queue_t * ) xQueue )->uxMessagesWaiting == ( UBaseType_t ) 0 ) + { + xReturn = pdTRUE; + } + else + { + xReturn = pdFALSE; + } + taskEXIT_CRITICAL_ISR(&pxQueue->mux); + + return xReturn; +} /*lint !e818 xQueue could not be pointer to const because it is a typedef. */ +/*-----------------------------------------------------------*/ + +static BaseType_t prvIsQueueFull( Queue_t *pxQueue ) +{ +BaseType_t xReturn; + + taskENTER_CRITICAL_ISR(&pxQueue->mux); + { + if( pxQueue->uxMessagesWaiting == pxQueue->uxLength ) + { + xReturn = pdTRUE; + } + else + { + xReturn = pdFALSE; + } + } + taskEXIT_CRITICAL_ISR(&pxQueue->mux); + + return xReturn; +} +/*-----------------------------------------------------------*/ + +BaseType_t xQueueIsQueueFullFromISR( QueueHandle_t xQueue ) +{ +BaseType_t xReturn; +Queue_t * const pxQueue = ( Queue_t * ) xQueue; + + configASSERT( xQueue ); + taskENTER_CRITICAL_ISR(&pxQueue->mux); + if( ( ( Queue_t * ) xQueue )->uxMessagesWaiting == ( ( Queue_t * ) xQueue )->uxLength ) + { + xReturn = pdTRUE; + } + else + { + xReturn = pdFALSE; + } + taskEXIT_CRITICAL_ISR(&pxQueue->mux); + + return xReturn; +} /*lint !e818 xQueue could not be pointer to const because it is a typedef. */ +/*-----------------------------------------------------------*/ + +#if ( configUSE_CO_ROUTINES == 1 ) + + BaseType_t xQueueCRSend( QueueHandle_t xQueue, const void *pvItemToQueue, TickType_t xTicksToWait ) + { + BaseType_t xReturn; + Queue_t * const pxQueue = ( Queue_t * ) xQueue; + + /* If the queue is already full we may have to block. A critical section + is required to prevent an interrupt removing something from the queue + between the check to see if the queue is full and blocking on the queue. */ + portDISABLE_INTERRUPTS(); + { + if( prvIsQueueFull( pxQueue ) != pdFALSE ) + { + /* The queue is full - do we want to block or just leave without + posting? */ + if( xTicksToWait > ( TickType_t ) 0 ) + { + /* As this is called from a coroutine we cannot block directly, but + return indicating that we need to block. */ + vCoRoutineAddToDelayedList( xTicksToWait, &( pxQueue->xTasksWaitingToSend ) ); + portENABLE_INTERRUPTS(); + return errQUEUE_BLOCKED; + } + else + { + portENABLE_INTERRUPTS(); + return errQUEUE_FULL; + } + } + } + portENABLE_INTERRUPTS(); + + portDISABLE_INTERRUPTS(); + { + if( pxQueue->uxMessagesWaiting < pxQueue->uxLength ) + { + /* There is room in the queue, copy the data into the queue. */ + prvCopyDataToQueue( pxQueue, pvItemToQueue, queueSEND_TO_BACK ); + xReturn = pdPASS; + + /* Were any co-routines waiting for data to become available? */ + if( listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToReceive ) ) == pdFALSE ) + { + /* In this instance the co-routine could be placed directly + into the ready list as we are within a critical section. + Instead the same pending ready list mechanism is used as if + the event were caused from within an interrupt. */ + if( xCoRoutineRemoveFromEventList( &( pxQueue->xTasksWaitingToReceive ) ) != pdFALSE ) + { + /* The co-routine waiting has a higher priority so record + that a yield might be appropriate. */ + xReturn = errQUEUE_YIELD; + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } + else + { + xReturn = errQUEUE_FULL; + } + } + portENABLE_INTERRUPTS(); + + return xReturn; + } + +#endif /* configUSE_CO_ROUTINES */ +/*-----------------------------------------------------------*/ + +#if ( configUSE_CO_ROUTINES == 1 ) + + BaseType_t xQueueCRReceive( QueueHandle_t xQueue, void *pvBuffer, TickType_t xTicksToWait ) + { + BaseType_t xReturn; + Queue_t * const pxQueue = ( Queue_t * ) xQueue; + + /* If the queue is already empty we may have to block. A critical section + is required to prevent an interrupt adding something to the queue + between the check to see if the queue is empty and blocking on the queue. */ + portDISABLE_INTERRUPTS(); + { + if( pxQueue->uxMessagesWaiting == ( UBaseType_t ) 0 ) + { + /* There are no messages in the queue, do we want to block or just + leave with nothing? */ + if( xTicksToWait > ( TickType_t ) 0 ) + { + /* As this is a co-routine we cannot block directly, but return + indicating that we need to block. */ + vCoRoutineAddToDelayedList( xTicksToWait, &( pxQueue->xTasksWaitingToReceive ) ); + portENABLE_INTERRUPTS(); + return errQUEUE_BLOCKED; + } + else + { + portENABLE_INTERRUPTS(); + return errQUEUE_FULL; + } + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } + portENABLE_INTERRUPTS(); + + portDISABLE_INTERRUPTS(); + { + if( pxQueue->uxMessagesWaiting > ( UBaseType_t ) 0 ) + { + /* Data is available from the queue. */ + pxQueue->u.pcReadFrom += pxQueue->uxItemSize; + if( pxQueue->u.pcReadFrom >= pxQueue->pcTail ) + { + pxQueue->u.pcReadFrom = pxQueue->pcHead; + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + --( pxQueue->uxMessagesWaiting ); + ( void ) memcpy( ( void * ) pvBuffer, ( void * ) pxQueue->u.pcReadFrom, ( unsigned ) pxQueue->uxItemSize ); + + xReturn = pdPASS; + + /* Were any co-routines waiting for space to become available? */ + if( listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToSend ) ) == pdFALSE ) + { + /* In this instance the co-routine could be placed directly + into the ready list as we are within a critical section. + Instead the same pending ready list mechanism is used as if + the event were caused from within an interrupt. */ + if( xCoRoutineRemoveFromEventList( &( pxQueue->xTasksWaitingToSend ) ) != pdFALSE ) + { + xReturn = errQUEUE_YIELD; + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } + else + { + xReturn = pdFAIL; + } + } + portENABLE_INTERRUPTS(); + + return xReturn; + } + +#endif /* configUSE_CO_ROUTINES */ +/*-----------------------------------------------------------*/ + +#if ( configUSE_CO_ROUTINES == 1 ) + + BaseType_t xQueueCRSendFromISR( QueueHandle_t xQueue, const void *pvItemToQueue, BaseType_t xCoRoutinePreviouslyWoken ) + { + Queue_t * const pxQueue = ( Queue_t * ) xQueue; + + /* Cannot block within an ISR so if there is no space on the queue then + exit without doing anything. */ + if( pxQueue->uxMessagesWaiting < pxQueue->uxLength ) + { + prvCopyDataToQueue( pxQueue, pvItemToQueue, queueSEND_TO_BACK ); + + /* We only want to wake one co-routine per ISR, so check that a + co-routine has not already been woken. */ + if( xCoRoutinePreviouslyWoken == pdFALSE ) + { + if( listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToReceive ) ) == pdFALSE ) + { + if( xCoRoutineRemoveFromEventList( &( pxQueue->xTasksWaitingToReceive ) ) != pdFALSE ) + { + return pdTRUE; + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + + return xCoRoutinePreviouslyWoken; + } + +#endif /* configUSE_CO_ROUTINES */ +/*-----------------------------------------------------------*/ + +#if ( configUSE_CO_ROUTINES == 1 ) + + BaseType_t xQueueCRReceiveFromISR( QueueHandle_t xQueue, void *pvBuffer, BaseType_t *pxCoRoutineWoken ) + { + BaseType_t xReturn; + Queue_t * const pxQueue = ( Queue_t * ) xQueue; + + /* We cannot block from an ISR, so check there is data available. If + not then just leave without doing anything. */ + if( pxQueue->uxMessagesWaiting > ( UBaseType_t ) 0 ) + { + /* Copy the data from the queue. */ + pxQueue->u.pcReadFrom += pxQueue->uxItemSize; + if( pxQueue->u.pcReadFrom >= pxQueue->pcTail ) + { + pxQueue->u.pcReadFrom = pxQueue->pcHead; + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + --( pxQueue->uxMessagesWaiting ); + ( void ) memcpy( ( void * ) pvBuffer, ( void * ) pxQueue->u.pcReadFrom, ( unsigned ) pxQueue->uxItemSize ); + + if( ( *pxCoRoutineWoken ) == pdFALSE ) + { + if( listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToSend ) ) == pdFALSE ) + { + if( xCoRoutineRemoveFromEventList( &( pxQueue->xTasksWaitingToSend ) ) != pdFALSE ) + { + *pxCoRoutineWoken = pdTRUE; + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + + xReturn = pdPASS; + } + else + { + xReturn = pdFAIL; + } + + return xReturn; + } + +#endif /* configUSE_CO_ROUTINES */ +/*-----------------------------------------------------------*/ + +#if ( configQUEUE_REGISTRY_SIZE > 0 ) + + void vQueueAddToRegistry( QueueHandle_t xQueue, const char *pcQueueName ) /*lint !e971 Unqualified char types are allowed for strings and single characters only. */ + { + UBaseType_t ux; + + /* See if there is an empty space in the registry. A NULL name denotes + a free slot. */ + for( ux = ( UBaseType_t ) 0U; ux < ( UBaseType_t ) configQUEUE_REGISTRY_SIZE; ux++ ) + { + if( xQueueRegistry[ ux ].pcQueueName == NULL ) + { + /* Store the information on this queue. */ + xQueueRegistry[ ux ].pcQueueName = pcQueueName; + xQueueRegistry[ ux ].xHandle = xQueue; + + traceQUEUE_REGISTRY_ADD( xQueue, pcQueueName ); + break; + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } + } + +#endif /* configQUEUE_REGISTRY_SIZE */ +/*-----------------------------------------------------------*/ + +#if ( configQUEUE_REGISTRY_SIZE > 0 ) + + void vQueueUnregisterQueue( QueueHandle_t xQueue ) + { + UBaseType_t ux; + + /* See if the handle of the queue being unregistered in actually in the + registry. */ + for( ux = ( UBaseType_t ) 0U; ux < ( UBaseType_t ) configQUEUE_REGISTRY_SIZE; ux++ ) + { + if( xQueueRegistry[ ux ].xHandle == xQueue ) + { + /* Set the name to NULL to show that this slot if free again. */ + xQueueRegistry[ ux ].pcQueueName = NULL; + break; + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } + + } /*lint !e818 xQueue could not be pointer to const because it is a typedef. */ + +#endif /* configQUEUE_REGISTRY_SIZE */ +/*-----------------------------------------------------------*/ + +#if ( configUSE_TIMERS == 1 ) + + void vQueueWaitForMessageRestricted( QueueHandle_t xQueue, TickType_t xTicksToWait ) + { + Queue_t * const pxQueue = ( Queue_t * ) xQueue; + + /* This function should not be called by application code hence the + 'Restricted' in its name. It is not part of the public API. It is + designed for use by kernel code, and has special calling requirements. + It can result in vListInsert() being called on a list that can only + possibly ever have one item in it, so the list will be fast, but even + so it should be called with the scheduler locked and not from a critical + section. */ + + /* Only do anything if there are no messages in the queue. This function + will not actually cause the task to block, just place it on a blocked + list. It will not block until the scheduler is unlocked - at which + time a yield will be performed. If an item is added to the queue while + the queue is locked, and the calling task blocks on the queue, then the + calling task will be immediately unblocked when the queue is unlocked. */ +// prvLockQueue( pxQueue ); + if( pxQueue->uxMessagesWaiting == ( UBaseType_t ) 0U ) + { + /* There is nothing in the queue, block for the specified period. */ + vTaskPlaceOnEventListRestricted( &( pxQueue->xTasksWaitingToReceive ), xTicksToWait ); + } + else + { + mtCOVERAGE_TEST_MARKER(); + } +// prvUnlockQueue( pxQueue ); + } + +#endif /* configUSE_TIMERS */ +/*-----------------------------------------------------------*/ + +#if ( configUSE_QUEUE_SETS == 1 ) + + QueueSetHandle_t xQueueCreateSet( const UBaseType_t uxEventQueueLength ) + { + QueueSetHandle_t pxQueue; + + pxQueue = xQueueGenericCreate( uxEventQueueLength, sizeof( Queue_t * ), queueQUEUE_TYPE_SET ); + + return pxQueue; + } + +#endif /* configUSE_QUEUE_SETS */ +/*-----------------------------------------------------------*/ + +#if ( configUSE_QUEUE_SETS == 1 ) + + BaseType_t xQueueAddToSet( QueueSetMemberHandle_t xQueueOrSemaphore, QueueSetHandle_t xQueueSet ) + { + BaseType_t xReturn; + +//ToDo: figure out locking +// taskENTER_CRITICAL(&pxQueue->mux); + { + if( ( ( Queue_t * ) xQueueOrSemaphore )->pxQueueSetContainer != NULL ) + { + /* Cannot add a queue/semaphore to more than one queue set. */ + xReturn = pdFAIL; + } + else if( ( ( Queue_t * ) xQueueOrSemaphore )->uxMessagesWaiting != ( UBaseType_t ) 0 ) + { + /* Cannot add a queue/semaphore to a queue set if there are already + items in the queue/semaphore. */ + xReturn = pdFAIL; + } + else + { + ( ( Queue_t * ) xQueueOrSemaphore )->pxQueueSetContainer = xQueueSet; + xReturn = pdPASS; + } + } +// taskEXIT_CRITICAL(&pxQueue->mux); + + return xReturn; + } + +#endif /* configUSE_QUEUE_SETS */ +/*-----------------------------------------------------------*/ + +#if ( configUSE_QUEUE_SETS == 1 ) + + BaseType_t xQueueRemoveFromSet( QueueSetMemberHandle_t xQueueOrSemaphore, QueueSetHandle_t xQueueSet ) + { + BaseType_t xReturn; + Queue_t * const pxQueueOrSemaphore = ( Queue_t * ) xQueueOrSemaphore; + + if( pxQueueOrSemaphore->pxQueueSetContainer != xQueueSet ) + { + /* The queue was not a member of the set. */ + xReturn = pdFAIL; + } + else if( pxQueueOrSemaphore->uxMessagesWaiting != ( UBaseType_t ) 0 ) + { + /* It is dangerous to remove a queue from a set when the queue is + not empty because the queue set will still hold pending events for + the queue. */ + xReturn = pdFAIL; + } + else + { +// taskENTER_CRITICAL(&pxQueue->mux); + { + /* The queue is no longer contained in the set. */ + pxQueueOrSemaphore->pxQueueSetContainer = NULL; + } +// taskEXIT_CRITICAL(&pxQueue->mux); + xReturn = pdPASS; + } + + return xReturn; + } /*lint !e818 xQueueSet could not be declared as pointing to const as it is a typedef. */ + +#endif /* configUSE_QUEUE_SETS */ +/*-----------------------------------------------------------*/ + +#if ( configUSE_QUEUE_SETS == 1 ) + + QueueSetMemberHandle_t xQueueSelectFromSet( QueueSetHandle_t xQueueSet, TickType_t const xTicksToWait ) + { + QueueSetMemberHandle_t xReturn = NULL; + + ( void ) xQueueGenericReceive( ( QueueHandle_t ) xQueueSet, &xReturn, xTicksToWait, pdFALSE ); /*lint !e961 Casting from one typedef to another is not redundant. */ + return xReturn; + } + +#endif /* configUSE_QUEUE_SETS */ +/*-----------------------------------------------------------*/ + +#if ( configUSE_QUEUE_SETS == 1 ) + + QueueSetMemberHandle_t xQueueSelectFromSetFromISR( QueueSetHandle_t xQueueSet ) + { + QueueSetMemberHandle_t xReturn = NULL; + + ( void ) xQueueReceiveFromISR( ( QueueHandle_t ) xQueueSet, &xReturn, NULL ); /*lint !e961 Casting from one typedef to another is not redundant. */ + return xReturn; + } + +#endif /* configUSE_QUEUE_SETS */ +/*-----------------------------------------------------------*/ + +#if ( configUSE_QUEUE_SETS == 1 ) + + static BaseType_t prvNotifyQueueSetContainer( const Queue_t * const pxQueue, const BaseType_t xCopyPosition ) + { + Queue_t *pxQueueSetContainer = pxQueue->pxQueueSetContainer; + BaseType_t xReturn = pdFALSE; + + /* This function must be called form a critical section. */ + + configASSERT( pxQueueSetContainer ); + configASSERT( pxQueueSetContainer->uxMessagesWaiting < pxQueueSetContainer->uxLength ); + + if( pxQueueSetContainer->uxMessagesWaiting < pxQueueSetContainer->uxLength ) + { + traceQUEUE_SEND( pxQueueSetContainer ); + /* The data copied is the handle of the queue that contains data. */ + xReturn = prvCopyDataToQueue( pxQueueSetContainer, &pxQueue, xCopyPosition ); + + if( listLIST_IS_EMPTY( &( pxQueueSetContainer->xTasksWaitingToReceive ) ) == pdFALSE ) + { + if( xTaskRemoveFromEventList( &( pxQueueSetContainer->xTasksWaitingToReceive ) ) != pdFALSE ) + { + /* The task waiting has a higher priority */ + xReturn = pdTRUE; + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + + return xReturn; + } + +#endif /* configUSE_QUEUE_SETS */ + + + + + + + + + + + + diff --git a/components/freertos/readme_smp.txt b/components/freertos/readme_smp.txt new file mode 100644 index 0000000000..0f7a66d74f --- /dev/null +++ b/components/freertos/readme_smp.txt @@ -0,0 +1,26 @@ +This version of FreeRTOS has been modified by Espressif to be SMP-aware. The +API is similar to the original FreeRTOS API, with the following changes: + +- The xTaskCreate() function now creates tasks that will run on the first +core only, for backwards compatibility. To schedule tasks on another core, +use xTaskCreatePinnedToCore(), which will accept a core ID as the last +argument. If this is the constant tskNO_AFFINITY, the task will be dynamically +scheduled on whichever core has time. + +- vTaskSuspendAll/vTaskResumeAll in non-SMP FreeRTOS will suspend the scheduler +so no other tasks than the current one will run. In this SMP version, it will +only suspend the scheduler ON THE CURRENT CORE. That is, tasks scheduled to +run on the other core(s) or without a specific CPU affinity, will still be +able to run. + +- Enabling and disabling interrupts will only affect the current core. +Disabling the interrupts will not disallow other tasks to run as +it would on a single-core system: the other core still will keep on +executing all it's own. Use a mux, queue or semaphore to protect your +structures instead. + +- While each core has individual interrupts, the handlers are shared. This +means that when you set a handler for an interrupt, it will get triggered if +the interrupt is triggered on both CPU0 as well as on CPU1. This is something +we may change in future FreeRTOS-esp32 releases. + diff --git a/components/freertos/readme_xtensa.txt b/components/freertos/readme_xtensa.txt new file mode 100644 index 0000000000..1d8d246dcf --- /dev/null +++ b/components/freertos/readme_xtensa.txt @@ -0,0 +1,769 @@ + FreeRTOS Port for Xtensa Configurable and Diamond Processors + ============================================================ + + FreeRTOS Version 8.2.0 + + +Introduction +------------ + +This document describes the Xtensa port for FreeRTOS multitasking RTOS. +For an introduction to FreeRTOS itself, please refer to FreeRTOS +documentation. + +This port currently works with version 8.2.0. + + +Xtensa Configuration Requirements and Restrictions +-------------------------------------------------- + +The Xtensa configurable architecture supports a vast space of processor +features. This port supports all of them, including custom processor +extensions defined in the TIE language, with certain minimum +requirements. You must use Xtensa Tools to compile and link FreeRTOS and +your application for your Xtensa configuration. The port uses the Xtensa +Hardware Abstraction Layer (HAL) to adapt to your Xtensa configuration. +NOTE: It may be possible to build and run this with the open-source +xtensa-linux tools provided you have the correct overlay for your Xtensa +configuration. However, this has not been tested and is currently not +supported by Cadence. + +This port includes optional reentrancy support for the 'newlib' C runtime +library that is distributed with Xtensa Tools, providing thread-safety on +a per task basis (for use in tasks only, not interrupt handlers). + +NOTE: At this time only the 'newlib' C library is supported for thread +safety. The 'xclib' and 'uclibc' libraries are not reentrant and do not +provide thread safety at this time. However, if you are not concerned +with reentrancy then you can use any of these libraries. + +This port also includes a simple example application that may run on +a supported board or the Xtensa instruction set simulator (ISS). There +are also a couple of test programs used in maintaining the port, which +serve as additional examples. + +FreeRTOS for Xtensa configurable processors requires the following minimum +processor configuration options: +- Timer interrupt option with at least one interruptible timer. +- Interrupt option (implied by the timer interrupt option). +- Exception Architecture 2 (XEA2). Please note that XEA1 is NOT supported. + All 'Diamond', 'Xtensa 6', 'Xtensa LX' and 'Xtensa LX2' processors and + most 'Xtensa T1050' processors are configured with XEA2. +All Diamond processor cores meet these requirements and are supported. + +Minimal support for certain evaluation boards is provided via a board +independent XTBSP API implemented by a board specific library distributed +with the Xtensa Tools. This provides the board clock frequency and basic +polled drivers for the display and console device. Note that XTBSP +is not a tradtional RTOS "board support package" with RTOS specific +interrupt-driven drivers - it is not specific to any RTOS. Note that +FreeRTOS can run on any Xtensa or Diamond board without this board support +(a "raw" platform), but you will have to provide the clock frequency +and drivers for any on-board devices you want to use. + + +Installation +------------ + +This port is downloaded in a ZIP file from FreeRTOS Web site. You will +also need to obtain the common FreeRTOS source package from FreeRTOS's +website in order to build the OS and applications. The Xtensa port files +are not currently included in the common package. + +All source is provided along with a Makefile that works for any host +platform supported by Xtensa Tools (Windows, Linux). These instructions +are written for Windows users, but can easily be understood and adapted +to other host platforms. + +First install the FreeRTOS common package in a directory of your choosing. +The structure of that package will look like this: + +FreeRTOS +|-- Demo +| |-- Common +| | |-- Minimal +| | `-- include +| | +| |-- Xtensa_XCC +| `-- ParTest +| +`-- Source + |-- include + `-- portable + |-- MemMang + `-- XCC + `-- Xtensa + +Since the Xtensa specific files are currently unavailable in the common +package, then you will need the separate zip file containing the Xtensa port +files. Extract from that zip file the Source/portable/XCC and Demo/Xtensa_XCC +folders and place them in the appropriate location under the common tree. + +The Xtensa Tools are available from Cadence as part of a processor +license. Be sure you have installed the Xtensa Tools and your processor +configuration. + + +Building FreeRTOS for Xtensa +---------------------------- + +The Makefiles are provided for your convenience and you do not need to +use them. Essentially you need to compile all the FreeRTOS common files, +the port files, and your application, and link them all. However all the +build instructions in this note use the Makefiles. + +By default, you will build for the Xtensa instruction set simulator. If +you have a supported emulation board, you can build to run on that. You +can also build to run on a raw Xtensa core with no board support, a +good starting point for supporting your own target platform. Cadence +recommends doing functional development on the simulator because it +is easier to debug with, then move to a board if/when you need to test +hardware drivers or real-time performance. + +The provided Makefile simplifies building FreeRTOS and the example +for your Xtensa configuration and platform (ISS, board, etc.). There +are detailed instructions in the comment at the top of the Makefile. +The test/Makefile provides similar support for building the tests, +and may be invoked directly from the top level Makefile. + +The Makefiles work on any host platform and support incremental builds. +The build for each Xtensa configuration and target platform is placed in +a subdirectory so several core and platform builds can co-exist even with +incremental rebuilds. You may specify the root of the build area (if tou +want it to be elsewhere than under the source tree) by defining BLDROOT +either in the make command or your shell environment. + +First, be sure you have installed Xtensa Tools and your processor +configuration, and be sure that Xtensa Tools are in your search path. +You can use xt-make, which comes with the Xtensa Tools, to run the +makefiles. + +Change directories to the Xtensa port directory: + +> cd FreeRTOS/Source/portable/XCC/Xtensa + +Now build the FreeRTOS RTOS as a library (libfreertos.a) as follows: + +> xt-make + +which by default builds for the simulator (TARGET=sim), or: + +> xt-make TARGET=board + +which builds for a supported board. Note that the board type does not +need to be specified when building the FreeRTOS library. + +If you are building for an Xtensa processor configuration that is not the +default you selected when you installed Xtensa Tools, you need to define the +environment variable XTENSA_CORE. If your configuration is not in the +default registry you selected when you installed Xtensa Tools, you also +need to define the environment variable XTENSA_SYSTEM. See tools manuals. +You can avoid defining these in your environment if you pass the variables +you need to redefine into xt-make as follows: + +> xt-make XTENSA_CORE= XTENSA_SYSTEM= ... + +There are more details about build options in the comment in the Makefile. + +After the library has been built, you must link your application with this +library in order to use FreeRTOS. + + +Building a FreeRTOS Application +------------------------------- + +The provided FreeRTOS example is designed to run on the Xtensa instruction +set simulator (ISS) or a supported evaluation board programmed with your +Xtensa processor configuration. + +To build the example for the default platform (simulator): + +> xt-make example + +which is the same as + +> xt-make example TARGET=sim + +The boards currently supported are the Xilinx ML605 and KC705 FPGA +development boards. To target these boards, type + +> xt-make example TARGET=ml605 + +or + +> xt-make example TARGET=kc705 + +To build in a location other than the default, specify the new location +using the BLDROOT variable. Note that this makefile will invoke the +FreeRTOS library build makefile automatically, passing on the relevant +parameters based on what you specified. + +You can override the default compilation options by specifying the new +options via CFLAGS. For example: + +> xt-make example TARGET=sim CFLAGS="-O2 -Os -g" + +This compiles example.c and links it with the FreeRTOS library +libfreertos.a and the appropriate linker-support package (LSP) for your +target platform (you can override the LSP by adding LSP= to the +xt-make command line). The resulting file example.exe is an ELF binary +file that can be downloaded and executed on the target. + +The example.exe binary appears in the platform specific subdirectory +described earlier. For the following commands, change to that directory +or prepend it as the path of example.exe. + +To build your application with thread-safe C library support using +the open-source 'newlib' library provided with the Xtensa Tools, you +need to make certain modifications to the application to plug in and +invoke the newlib reentrancy support. This allows each task to use +the library without interference with other tasks (it is not safe for +interrupt handlers to call the C library). + +First, you must define + + XT_USE_THREAD_SAFE_CLIB + +to a nonzero either in FreeRTOSConfig.h or in the compiler's command +line. + +Then, you must also make sure to allocate extra space on the stack for +each task that will use the C library reentrant functions. This extra +space is to be allocated over and above the actual stack space required +by the task itself. The define + + XT_STACK_EXTRA_CLIB + +specifies the amount of extra space to be added on to the stack to allow +saving the context for the C library as well as the coprocessors if any. +E.g. if your task requires 2000 bytes of stack space, you must allocate +(2000 + XT_STACK_EXTRA_CLIB) bytes for the stack. + +To build the example with thread-safe C library support: + +> xt-make CFLAGS="-O0 -DXT_USE_THREAD_SAFE_CLIB" example + +The "-O0" is necessary because you are overriding the default COPT=-O0. +You can specify any optimization level you require (if none, the compiler +defaults to -O2). + + +Running or Debugging an Application +----------------------------------- + +To execute the example application on the simulator: + +> xt-run [--turbo] example.exe + +The option --turbo provides much faster, but non-cycle-accurate simulation +(the --turbo option is only available with Xtensa Tools version 7 or later). + + +To execute on the simulator using the Xplorer GUI based debugger: + +> xplorer --debug example.exe + + +To execute on a supported evaluation board, download example.exe per +instructions in the tools manuals. Be sure the board has been programmed +with the correct configuration and is set up to boot from RAM and debug +a downloaded program! Optionally you may connect a terminal or terminal +emulator to the serial port on the board with settings as described in +the board user manual, and see the output of printf on the terminal. + +To obtain I/O on a "raw" platform such as an unsupported board, you need +to provide low level I/O drivers (eg. inbyte() and outbyte() for character +I/O if you want to use printf etc.). You can run "raw" executables on +any Xtensa platform, including simulator and any board, but you will not +see any behavior specific to the platform (eg. display, printed output, +stopping simulation at end of program). You can, while debugging, use a +debugger mechanism called GDBIO to obtain basic I/O. To use GDBIO, link +with the gdbio LSP. Refer to Xtensa tools documentation for details. + + +Task Stack Sizes +---------------- + +The application must ensure that every task has enough space for its +stack. Each task needs enough space for its own use, its own interrupt +stack frame (defined in xtensa_context.h) and space to save coprocessor +state, if any. Several factors influence the size of the stack required, +including the compiler optimization level and the use of the C library. +Calls to standard output functions such as printf() can use up a lot of +stack space. The tool xt-stack-usage is helpful in determining safe stack +sizes for your application. + +Some macros are provided in xtensa_config.h to help determine the stack +size for tasks that do and do not use the C library. Use these as the +basis for each task's stack size. They are minimum requirements taking +into account your configuration and use of the C library. In particular, +the define + + XT_STACK_MIN_SIZE + +defines the minimum stack size for any task. Be very careful if you try +to use a stack size smaller than this minimum. Stack overruns can cause +all kinds of hard-to-debug errors. It is recommended that you enable the +FreeRTOS stack checking features during development. + +WARNING: The newlib printf() function uses a lot of stack space. Be very +careful in using it. Optionally you can use the 'libxtutil' library for +output - it implements a subset of printf() that has smaller code size +and uses far less stack space. More information about this library is in +the Xtensa Tools documentation. + + +Interrupt Stack +--------------- + +Beginning with port version 1.2, the port uses a separate interrupt stack +for handling interrupts. Thus, it is no longer necessary for each task to +reserve space on its stack to handle interrupts. The size of the interrupt +stack is controlled by the parameter "configISR_STACK_SIZE" defined in +FreeRTOSConfig.h. Define this carefully to match your system requirements. + + +Assembler / Compiler Switches +----------------------------- + +The following are compiler switches are used by the provided +Makefile in building the FreeRTOS library and example application. +These can be modified by editing the Makefile or by overriding the +CFLAGS variable in the make command line, for example: + +> xt-make CFLAGS="-O2 -DXT_USE_THREAD_SAFE_CLIB" + + -g Specifies debug information. + -c Specifies object code generation. + -On Sets compiler optimization level n (default -O0). + -mlongcalls Allows assembler and linker to convert call + instructions to longer indirect call sequences + when target is out of range. + -x assembler-with-cpp Passes .s and .S files through C preprocessor. + -Dmacro Define a preprocessor macro with no value. + -Dmacro=value Define a preprocessor macro with a value. + +See the compiler / linker documentation for a full list of switches and +their use. + +Many definitions can be provided at compile-time via the -D option +without editing the source code. Here are some of the more useful ones: + + XT_USE_THREAD_SAFE_CLIB Enable support for the reentrancy to provide + thread-safety in the GNU newlib supplied with + Xtensa Tools. Default off. + + Note, the follwing defines are unique to the Xtensa port so have names + beginning with "XT_". + + XT_SIMULATOR Set this if building to run on the simulator. + Takes advantage of certain simulator control + and reporting facilities, and adjusts timing + of periodic tick to provide a more acceptable + performance in simulation (see XT_CLOCK_FREQ). + Set by default unless PLATFORM is overridden. + + XT_BOARD Set this if building for a supported board. + Be sure to specify the correct LSP for the + board. See the example makefile for usage. + + XT_CLOCK_FREQ=freq Specifies the target processor's clock + frequency in Hz. Used primarily to set the + timer that generates the periodic interrupt. + Defaults are provided and may be edited in + xtensa_timer.h (see comments there also). + Default for simulator provides more acceptable + performance, but cannot provide real-time + performance due to variation in simulation + speed per host platform and insufficient + cycles between interrupts to process them. + Supported board platforms by default leave + this undefined and compute the clock frequency + at initialization unless this is explicitly + defined. + + XT_TICK_PER_SEC=n Specifies the frequency of the periodic tick. + + XT_TIMER_INDEX=n Specifies which timer to use for periodic tick. + Set this if your Xtensa processor configuration + provides more than one suitable timer and you + want to override the default. See xtensa_timer.h . + + XT_INTEXC_HOOKS Enables hooks in interrupt vector handlers + to support dynamic installation of exception + and interrupt handlers. Disabled by default. + + XT_USE_OVLY Enable code overlay support. It uses a mutex, + hence configUSE_MUTEX must be enabled. This + option is currently unsupported. + + XT_USE_SWPRI Enable software prioritization of interrupts. + Enabling this will prioritize interrupts with + higher bit numbers over those with lower bit + numbers at the same level. This works only for + low and medium priority interrupts that can be + dispatched to C handlers. + + +Register Usage and Stack Frames +------------------------------- + +The Xtensa architecture specifies two ABIs that determine how the general +purpose registers a0-a15 are used: the standard windowed ABI use with +the Xtensa windowed register file architecture, and the optional and +more conventional Call0 ABI (required for Xtensa configurations without +a windowed register file). + +Xtensa processors may have other special registers (including co-processor +registers and other TIE "states") that are independent of this choice +of ABI. See Xtensa documentation for more details. + +In the windowed ABI the registers of the current window are used as follows: + a0 = return address + a1 = stack pointer (alias sp) + a2 = first argument and result of call (in simple cases) + a3-7 = second through sixth arguments of call (in simple cases). + Note that complex or large arguments are passed on the + stack. Details are in the Xtensa Tools manuals. + a8-a15 = available for use as temporaries. +There are no callee-save registers. The windowed hardware automatically +saves registers a0-a3 on a call4, a0-a8 on a call8, a0-a12 on a call12, +by rotating the register window. Hardware triggers window overflow and +underflow exceptions as necessary when registers outside the current +window need to be spilled to preallocated space in the stack frame, or +restored. Complete details are in the Xtensa manuals. The entire windowed +register file is saved and restored on interrupt or task context switch. + +The Call0 ABI does not make use of register windows, relying instead +on a fixed set of 16 registers without window rotation. +The Call0 ABI is more conventional and uses registers as follows: + a0 = return address + a1 = stack pointer (alias sp) + a2 = first argument and result of call (in simple cases) + a3-7 = second through sixth arguments of call (in simple cases). + Note that complex or large arguments are passed on the + stack. Details are in the Xtensa Tools manuals. + a8-a11 = scratch. + a12-a15 = callee-save (a function must preserve these for its caller). +On a FreeRTOS API call, callee-save registers are saved only when a task +context switch occurs, and other registers are not saved at all (the caller +does not expect them to be preserved). On an interrupt, callee-saved +registers might only be saved and restored when a task context-switch +occurs, but all other registers are always saved and restored. + +An Xtensa processor has other special registers independent of the ABI, +depending on the configuration (including co-processor registers and other +TIE state) that are part of the task context. FreeRTOS preserves all such +registers over an unsolicited context-switch triggered by an interrupt. +However it does NOT preserve these over a solicited context-switch during +a FreeRTOS API call. This bears some explanation. These special registers +are either ignored by the compiler or treated as caller-saved, meaning +that if kept "live" over a function call (ie. need to be preserved) +they must be saved and restored by the caller. Since solicited entry to +FreeRTOS is always made by a function call, FreeRTOS assumes the caller +has saved any of these registers that are "live". FreeRTOS avoids a lot +of overhead by not having to save and restore every special register +(there can be many) on every solicited context switch. + +As a consequence, the application developer should NOT assume that special +registers are preserved over a FreeRTOS API call such as vTaskDelay(). +If multiple tasks use a register, the caller must save and restore it. + +The saved context stack frames for context switches that occur as +a result of interrupt handling (interrupt frame) or from task-level +API calls (solicited frame) are described in human readable form in +xtensa_context.h . All suspended tasks have one of these two types +of stack frames. The top of the suspended task's stack is pointed to +by pxCurrentTCB->pxTopOfStack. A special location common to both stack +frames differentiates solicited and interrupt stack frames. + + +Improving Performance, Footprint, or Ease of Debugging +------------------------------------------------------ + +By default FreeRTOS for Xtensa is built with debug (-g) and without +compiler optimizations (-O0). This makes debugging easier. Of course, +-O0 costs performance and usually also increases stack usage. To make +FreeRTOS run faster you can change the Makefile to enable the desired +optimizations or set a predefined optimization level (-O) . + +Maximum performance is achieved with -O3 -ipa, but that might increase +the footprint substantially. A good compromise is -O2. See the compiler +manual for details. + +Minimal footprint is achieved by optimizing for space with -Os, at the +cost of some performance. See the compiler manual for details. + +The Xtensa architecture port-specific assembly files are coded with no +file-scope labels inside functions (all labels inside functions begin with +".L"). This allows a profiler to accurately associate an address with a +function, and also allows the debugger's stack trace to show the correct +function wherever the program counter is within that function. However +there are some tradeoffs in debugging. Local (".L") labels are not +visible to the debugger, so the following limitations may be observed +during debugging: +- You cannot set a breakpoint on a local label inside a function. +- Disassembly will show the entire function, but will get out of sync and + show incorrect opcodes if it crosses any padding before an aligned local + branch target (".L" label, not ".Ln"). Restart disassembly specifying an + address range explicitly between points where there is padding. +Since FreeRTOS is provided in source form, it is not difficult to remove +the ".L" and ".Ln" prefixes from local labels if you want them visible. +They can also be made visible by passing the '-L' option to the assembler +and linker (see the assembler and linker manuals for details). + + +Interrupt and Exception Handling +-------------------------------- + +FreeRTOS provides a complete set of efficient exception and first-level +interrupt handlers installed at the appropriate exception and interrupt +vector locations. The Xtensa architecture supports several different +classes of exceptions and interrupts. Being a configurable architecture, +many of these are optional, and the vector locations are determined by +your processor configuration. (Note that Diamond cores are pre-configured +with specific vector locations.) The handlers provided use conditional +compilation to adapt to your processor configuration and include only +the code that is needed. + +Xtensa vector locations may reside almost anywhere, including in ROM. +The amount of code space available at each of these locations is +often very small (e.g. due to following vectors). A small stub of +code installed at the vector jumps to the corresponding handler, +usually in RAM. The exception and interrupt handlers are defined in +xtensa_vectors.S. They are not specific to FreeRTOS, but call into +FreeRTOS where appropriate via macros defined in xtensa_rtos.h . + +The handlers provided for low and medium priority interrupts are just +dispatchers that save relevant state and call user-definable handlers. +See the files xtensa_vectors.S and xtensa_api.h for more details of how +to create and install application-specific user interrupt handlers. +Similarly, user-defined handlers can be installed for exceptions (other +than a few which are always handled by the OS). + +The high priority interrupt handlers provided may be considered templates +into which the application adds code to service specific interrupts. +The places where application handlers should be inserted are tagged with +the comment "USER_EDIT" in xtensa_vectors.S. + +This FreeRTOS port supports strict priority-based nesting of interrupts. +An interrupt may only nest on top of one of strictly lower priority. +Equal priority interrupts concurrently pending are handled in an +application-defined sequence before any lower priority interrupts +are handled. During interrupt and exception handling, the processor's +interrupt level (PS.INTLEVEL) is used to control the interrupt priority +level that can be accepted; interrupt sources are not controlled +individually by FreeRTOS (the application is free to access the INTENABLE +register directly to enable/disable individual interrupts, eg. using +Xtensa HAL services). This approach provides the most deterministic +bounds on interrupt latency (for a given priority) and stack depth. + +Software prioritization of interrupts at the same priority is controlled +by the definition of XT_USE_SWPRI. See above for a description of this +parameter. + +The following subsections describe the handling of each class of exception +and interrupt in more detail. Many have nothing to do with FreeRTOS but +are mentioned because there is code to handle them in xtensa_vectors.S. + +User Exception and Interrupt Handler (Low/Medium Priority): + + All Xtensa 'general exceptions' come to the user, kernel, or double + exception vector. The exception type is identified by the EXCCAUSE + special register (level 1 interrupts are one particular cause of a + general exception). This port sets up PS to direct all such exceptions + to the user vector. Exceptions taken at the other two vectors usually + indicate a kernel or application bug. + + Level 1 interrupts are identified at the beginning of the handler + and are dispatched to a dedicated handler. Then, syscall and alloca + exceptions are identified and dispatched to special handlers described + below. After this, coprocessor exceptions are identified and dispatched + to the coprocessor handler. + + Any remaining exceptions are processed as follows: + + Having allocated the exception stack frame, the user exception handler + saves the current task state and sets up a C environment and enables + the high-priority class of interrupts (which do not interact with + FreeRTOS), then reads EXCCAUSE and uses the cause (number) to index + into a table of user-specified handlers. The correct handler is then + called. If the handler returns, the context is restored and control is + returned to the code that caused the exception. The user-defined handler + may alter the saved context, or any other system state, that allows the + faulting instruction to be retried. + + If the cause is a level 1 (low-priority) or medium-priority interrupt, + the handler enables all interrupts above that priority level after + saving the task context. It then sets up the environment for C code + and then calls the handler (found in the handler table) for the + interrupt number. If the user has not specified a handler, then the + default handler will be called, which will terminate the program. + + If the interrupt is for the system timer, it calls a special interrupt + handler for the system timer tick, which calls _frxt_timer_int then + clears its bit from the mask. This interrupt cannot be hooked by the + user-defined handler. + + Finally, the handler calls _frxt_int_exit to allow FreeRTOS to perform + any scheduling necessary and return either to the interrupted task + or another. + + If software prioritization is enabled, the handler will re-enable all + interrupts at the same level that are numerically higher than the current + one, before calling the user handler. This allows a higher priority + interrupt to pre-empt the lower priority handler. + +Medium Priority Interrupt Handlers: + + Medium priority interrupts are those at levels 2 up to XCHAL_EXCM_LEVEL, + a configuration-specific maximum interrupt level affected by the global + 'exception mode' bit in the processor status word (PS.EXCM). + Interrupt levels above XCHAL_EXCM_LEVEL are of the high-priority class. + The Xtensa hardware documentation considers medium priority interrupts + to be a special case of high-priority interrupts, but from a software + perspective they are very different. + + Dispatch of medium-priority interrupts is discussed in the section + above. + +High Priority Interrupt Handlers: + + High priority interrupts are those strictly above XCHAL_EXCM_LEVEL, + a configuration-specific maximum interrupt level affected by the + global 'exception mode' bit in the processor status word (PS.EXCM). + High priority handlers may not directly interact with FreeRTOS at all, + and are described here only for the sake of completeness. They must + be coded in assembler (may not be coded in C) and are intended to be + used for handling extremely high frequency hardware events that need + to be handled in only a few cycles. A high priority interrupt handler + may trigger a software interrupt at a medium or low priority level to + occasionally signal FreeRTOS. Please see Xtensa documentation. + + There is a separate vector and a few special registers for each high + priority interrupt, providing for fast dispatch and efficient nesting + on top of lower priority interrupts. Handlers are templates included + only for the vectors that exist in your Xtensa processor configuration. + These templates are written for only one interrupt per high priority + level to minimize latency servicing very fast time-critical interrupts. + The vector code jumps to the corresponding first-level interrupt handler, + which then executes application-provided assembler code before returning + quickly to the interrupted task or lower priority handler. + +Kernel Exception Handler: + + Kernel mode is not used in this port of FreeRTOS, and therefore kernel + exceptions should not happen. A stub is provided for the vector that + triggers the debugger (if connected) or calls _xt_panic to freeze the + processor should a kernel exception occur. + +Alloca Exception Handler: + + Alloca exceptions are generated by the 'movsp' instruction, which + is used only in the windowed ABI. Its purpose is to allocate some + space on top of the stack. Because the window hardware may have + spilled some registers to the 16 byte "base save" area below the + stack pointer, it is necessary to protect those values. The alloca + handler accomplishes this quickly without setting up an interrupt + frame or entering FreeRTOS, by emulating a register underflow and + re-executing 'movsp'. + +Syscall Exception Handler: + + Syscall exceptions are generated by a 'syscall' instruction. + The windowed ABI specifies that executing this instruction with + a value of zero in register a2 must spill any unsaved registers + in the windowed register file to their pre-determined locations + on the caller's stack. The handler does exactly that, and skips + over the 'syscall' instruction before returning to the caller. + If a2 is non-zero, the handler returns a2 == -1 to the caller. + +Co-Processor Exception Handler: + + A co-processor exception is generated when a task accesses a + co-processor that it does not "own". Ownership represents which + task's state is currently in the co-processor. Co-processors are + context-switched "lazily" (on demand) only when a non-owning task + uses a co-processor instruction, otherwise a task retains ownership + even when it is preempted from the main processor. The co-processor + exception handler performs the context-switch and manages ownership. + + Co-processors may not be used by any code outside the context of a + task. A co-processor exception triggered by code that is not part + of a running task is a fatal error and FreeRTOS for Xtensa will panic. + This restriction is intended to reduce the overhead of saving and + restoring co-processor state (which can be quite large) and in + particular remove that overhead from interrupt handlers. + +Debug Exception Handler: + + A debug exception is caused as a result of running code, such as by + a 'break' instruction or hardware breakpoints and watchpoints, or + as a result of an external debug interrupt, such as from an OCD based + debugger or multiprocessor debug events ("breakin/breakout"). If the + processor is running in OCD mode under control of an OCD-based debugger, + the trigger event immediately halts the processor and gives control to + the OCD debugger. Otherwise control is transferred to the debug vector. + The debug vector handler calls the simulator if running on the ISS, + which then takes control and interacts with any attached debugger. + If running on hardware and not in OCD mode, debug exceptions are not + expected, so the debug handler calls _xt_panic to freeze the processor. + +Double Exception Handler: + + A double exception is a general exception that happens while the + processor is in exception mode (PS.EXCM set), and thus indicates a + bug in kernel code. The double exception vector handler triggers + the debugger (if connected) or calls _xt_panic to freeze the + processor. + +Window Overflow and Underflow Exception Handlers: + + Window overflow and underflow handlers are required for use of the + windowed ABI. Each has its own dedicated vector and highly optimized + code that is independent of OS. See Xtensa documentation for details. + +Hooks for Dynamic Installation of Handlers: + + Optional hooks are provided in the user exception and low level + interrupt handler and all medium and high priority interrupt handlers, + to dynamically install a handler function (which may be coded in C, + unless in a high-priority interrupt handler). These hooks are enabled + and used by automatic regression tests, they are not part of a normal + FreeRTOS build. However an application is free to take advantage of + them. The interrupt/exception hooks are described in xtensa_rtos.h . + + It is recommended that the application not make use of these hooks, but + rather use xt_set_interrupt_handler() and xt_set_exception_handler() + to install application-specific handlers. This method is more convenient + and allows arguments to be passed to the handlers. Software prioritization + of interrupts works only with this method. See xtensa_api.h for details. + +Overlay Support + + Code overlays are currently not supported for FreeRTOS. This will be + supported in a future release. Make sure that the option XT_USE_OVLY is + never defined when building. + + +Note on Porting Methodology and Copyrights +------------------------------------------ + +This port is based on a well-tested Cadence RTOS porting layer +that abstracts out Xtensa-generic aspects from the RTOS specifics +in the same way most RTOSes abstract out their generic code from the +architecture specific port code. This code is common to several RTOSes +ported by Cadence, and deals with highly Xtensa specific aspects such +as context save/restore, interrupt and exception dispatch, and handling +of co-processor, alloc and window over/underflow exceptions. + +The porting layer files are prefixed "xtensa_" and belong to Cadence +(they are provided freely as part of this port but are not subject to +FreeRTOS's copyright). The rest of the port is FreeRTOS specific and +are under FreeRTOS's copyright. + +The Makefiles are also provided by Cadence so have much in common with +other RTOS Makefiles provided by Cadence. + +-End- + diff --git a/components/freertos/stdint.readme b/components/freertos/stdint.readme new file mode 100644 index 0000000000..4414c29ed2 --- /dev/null +++ b/components/freertos/stdint.readme @@ -0,0 +1,27 @@ + +#ifndef FREERTOS_STDINT +#define FREERTOS_STDINT + +/******************************************************************************* + * THIS IS NOT A FULL stdint.h IMPLEMENTATION - It only contains the definitions + * necessary to build the FreeRTOS code. It is provided to allow FreeRTOS to be + * built using compilers that do not provide their own stdint.h definition. + * + * To use this file: + * + * 1) Copy this file into the directory that contains your FreeRTOSConfig.h + * header file, as that directory will already be in the compilers include + * path. + * + * 2) Rename the copied file stdint.h. + * + */ + +typedef signed char int8_t; +typedef unsigned char uint8_t; +typedef short int16_t; +typedef unsigned short uint16_t; +typedef long int32_t; +typedef unsigned long uint32_t; + +#endif /* FREERTOS_STDINT */ diff --git a/components/freertos/tasks.c b/components/freertos/tasks.c new file mode 100644 index 0000000000..d747708eb0 --- /dev/null +++ b/components/freertos/tasks.c @@ -0,0 +1,4535 @@ +/* + FreeRTOS V8.2.0 - Copyright (C) 2015 Real Time Engineers Ltd. + All rights reserved + + VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION. + + This file is part of the FreeRTOS distribution. + + FreeRTOS is free software; you can redistribute it and/or modify it under + the terms of the GNU General Public License (version 2) as published by the + Free Software Foundation >>!AND MODIFIED BY!<< the FreeRTOS exception. + + *************************************************************************** + >>! NOTE: The modification to the GPL is included to allow you to !<< + >>! distribute a combined work that includes FreeRTOS without being !<< + >>! obliged to provide the source code for proprietary components !<< + >>! outside of the FreeRTOS kernel. !<< + *************************************************************************** + + FreeRTOS is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + FOR A PARTICULAR PURPOSE. Full license text is available on the following + link: http://www.freertos.org/a00114.html + + *************************************************************************** + * * + * FreeRTOS provides completely free yet professionally developed, * + * robust, strictly quality controlled, supported, and cross * + * platform software that is more than just the market leader, it * + * is the industry's de facto standard. * + * * + * Help yourself get started quickly while simultaneously helping * + * to support the FreeRTOS project by purchasing a FreeRTOS * + * tutorial book, reference manual, or both: * + * http://www.FreeRTOS.org/Documentation * + * * + *************************************************************************** + + http://www.FreeRTOS.org/FAQHelp.html - Having a problem? Start by reading + the FAQ page "My application does not run, what could be wrong?". Have you + defined configASSERT()? + + http://www.FreeRTOS.org/support - In return for receiving this top quality + embedded software for free we request you assist our global community by + participating in the support forum. + + http://www.FreeRTOS.org/training - Investing in training allows your team to + be as productive as possible as early as possible. Now you can receive + FreeRTOS training directly from Richard Barry, CEO of Real Time Engineers + Ltd, and the world's leading authority on the world's leading RTOS. + + http://www.FreeRTOS.org/plus - A selection of FreeRTOS ecosystem products, + including FreeRTOS+Trace - an indispensable productivity tool, a DOS + compatible FAT file system, and our tiny thread aware UDP/IP stack. + + http://www.FreeRTOS.org/labs - Where new FreeRTOS products go to incubate. + Come and try FreeRTOS+TCP, our new open source TCP/IP stack for FreeRTOS. + + http://www.OpenRTOS.com - Real Time Engineers ltd. license FreeRTOS to High + Integrity Systems ltd. to sell under the OpenRTOS brand. Low cost OpenRTOS + licenses offer ticketed support, indemnification and commercial middleware. + + http://www.SafeRTOS.com - High Integrity Systems also provide a safety + engineered and independently SIL3 certified version for use in safety and + mission critical applications that require provable dependability. + + 1 tab == 4 spaces! +*/ + +/* Standard includes. */ +#include +#include + +/* Defining MPU_WRAPPERS_INCLUDED_FROM_API_FILE prevents task.h from redefining +all the API functions to use the MPU wrappers. That should only be done when +task.h is included from an application file. */ +#define MPU_WRAPPERS_INCLUDED_FROM_API_FILE + +#include "rom/ets_sys.h" + +/* FreeRTOS includes. */ +#include "FreeRTOS.h" +#include "task.h" +#include "timers.h" +#include "StackMacros.h" +#include "portmacro.h" + +/* Lint e961 and e750 are suppressed as a MISRA exception justified because the +MPU ports require MPU_WRAPPERS_INCLUDED_FROM_API_FILE to be defined for the +header files above, but not in this file, in order to generate the correct +privileged Vs unprivileged linkage and placement. */ +#undef MPU_WRAPPERS_INCLUDED_FROM_API_FILE /*lint !e961 !e750. */ + +/* Set configUSE_STATS_FORMATTING_FUNCTIONS to 2 to include the stats formatting +functions but without including stdio.h here. */ +#if ( configUSE_STATS_FORMATTING_FUNCTIONS == 1 ) + /* At the bottom of this file are two optional functions that can be used + to generate human readable text from the raw data generated by the + uxTaskGetSystemState() function. Note the formatting functions are provided + for convenience only, and are NOT considered part of the kernel. */ + #include +#endif /* configUSE_STATS_FORMATTING_FUNCTIONS == 1 ) */ + +/* Sanity check the configuration. */ +#if configUSE_TICKLESS_IDLE != 0 + #if INCLUDE_vTaskSuspend != 1 + #error INCLUDE_vTaskSuspend must be set to 1 if configUSE_TICKLESS_IDLE is not set to 0 + #endif /* INCLUDE_vTaskSuspend */ +#endif /* configUSE_TICKLESS_IDLE */ + +/* + * Defines the size, in words, of the stack allocated to the idle task. + */ +#define tskIDLE_STACK_SIZE configMINIMAL_STACK_SIZE + +#if( configUSE_PREEMPTION == 0 ) + /* If the cooperative scheduler is being used then a yield should not be + performed just because a higher priority task has been woken. */ + #define taskYIELD_IF_USING_PREEMPTION() + #define queueYIELD_IF_USING_PREEMPTION_MUX(mux) +#else + #define taskYIELD_IF_USING_PREEMPTION() portYIELD_WITHIN_API() + #define taskYIELD_IF_USING_PREEMPTION_MUX(mux) { \ + taskEXIT_CRITICAL(mux); \ + portYIELD_WITHIN_API(); \ + taskENTER_CRITICAL(mux); \ + } while(0) +#endif + +/* Value that can be assigned to the eNotifyState member of the TCB. */ +typedef enum +{ + eNotWaitingNotification = 0, + eWaitingNotification, + eNotified +} eNotifyValue; + +/* + * Task control block. A task control block (TCB) is allocated for each task, + * and stores task state information, including a pointer to the task's context + * (the task's run time environment, including register values) + */ +typedef struct tskTaskControlBlock +{ + volatile StackType_t *pxTopOfStack; /*< Points to the location of the last item placed on the tasks stack. THIS MUST BE THE FIRST MEMBER OF THE TCB STRUCT. */ + + #if ( portUSING_MPU_WRAPPERS == 1 ) + xMPU_SETTINGS xMPUSettings; /*< The MPU settings are defined as part of the port layer. THIS MUST BE THE SECOND MEMBER OF THE TCB STRUCT. */ + BaseType_t xUsingStaticallyAllocatedStack; /* Set to pdTRUE if the stack is a statically allocated array, and pdFALSE if the stack is dynamically allocated. */ + #endif + + ListItem_t xGenericListItem; /*< The list that the state list item of a task is reference from denotes the state of that task (Ready, Blocked, Suspended ). */ + ListItem_t xEventListItem; /*< Used to reference a task from an event list. */ + UBaseType_t uxPriority; /*< The priority of the task. 0 is the lowest priority. */ + StackType_t *pxStack; /*< Points to the start of the stack. */ + char pcTaskName[ configMAX_TASK_NAME_LEN ];/*< Descriptive name given to the task when created. Facilitates debugging only. */ /*lint !e971 Unqualified char types are allowed for strings and single characters only. */ + BaseType_t xCoreID; /*< Core this task is pinned to */ + + #if ( portSTACK_GROWTH > 0 ) + StackType_t *pxEndOfStack; /*< Points to the end of the stack on architectures where the stack grows up from low memory. */ + #endif + + #if ( portCRITICAL_NESTING_IN_TCB == 1 ) + UBaseType_t uxCriticalNesting; /*< Holds the critical section nesting depth for ports that do not maintain their own count in the port layer. */ + #endif + + #if ( configUSE_TRACE_FACILITY == 1 ) + UBaseType_t uxTCBNumber; /*< Stores a number that increments each time a TCB is created. It allows debuggers to determine when a task has been deleted and then recreated. */ + UBaseType_t uxTaskNumber; /*< Stores a number specifically for use by third party trace code. */ + #endif + + #if ( configUSE_MUTEXES == 1 ) + UBaseType_t uxBasePriority; /*< The priority last assigned to the task - used by the priority inheritance mechanism. */ + UBaseType_t uxMutexesHeld; + #endif + + #if ( configUSE_APPLICATION_TASK_TAG == 1 ) + TaskHookFunction_t pxTaskTag; + #endif + + #if( configNUM_THREAD_LOCAL_STORAGE_POINTERS > 0 ) + void *pvThreadLocalStoragePointers[ configNUM_THREAD_LOCAL_STORAGE_POINTERS ]; + #endif + + #if ( configGENERATE_RUN_TIME_STATS == 1 ) + uint32_t ulRunTimeCounter; /*< Stores the amount of time the task has spent in the Running state. */ + #endif + + #if ( configUSE_NEWLIB_REENTRANT == 1 ) + /* Allocate a Newlib reent structure that is specific to this task. + Note Newlib support has been included by popular demand, but is not + used by the FreeRTOS maintainers themselves. FreeRTOS is not + responsible for resulting newlib operation. User must be familiar with + newlib and must provide system-wide implementations of the necessary + stubs. Be warned that (at the time of writing) the current newlib design + implements a system-wide malloc() that must be provided with locks. */ + struct _reent xNewLib_reent; + #endif + + #if ( configUSE_TASK_NOTIFICATIONS == 1 ) + volatile uint32_t ulNotifiedValue; + volatile eNotifyValue eNotifyState; + #endif + +} tskTCB; + +/* The old tskTCB name is maintained above then typedefed to the new TCB_t name +below to enable the use of older kernel aware debuggers. */ +typedef tskTCB TCB_t; + +/* + * Some kernel aware debuggers require the data the debugger needs access to to + * be global, rather than file scope. + */ +#ifdef portREMOVE_STATIC_QUALIFIER + #define static +#endif + +/*lint -e956 A manual analysis and inspection has been used to determine which +static variables must be declared volatile. */ + +PRIVILEGED_DATA TCB_t * volatile pxCurrentTCB[ portNUM_PROCESSORS ] = { NULL }; + +/* Lists for ready and blocked tasks. --------------------*/ +PRIVILEGED_DATA static List_t pxReadyTasksLists[ configMAX_PRIORITIES ];/*< Prioritised ready tasks. */ +PRIVILEGED_DATA static List_t xDelayedTaskList1; /*< Delayed tasks. */ +PRIVILEGED_DATA static List_t xDelayedTaskList2; /*< Delayed tasks (two lists are used - one for delays that have overflowed the current tick count. */ +PRIVILEGED_DATA static List_t * volatile pxDelayedTaskList; /*< Points to the delayed task list currently being used. */ +PRIVILEGED_DATA static List_t * volatile pxOverflowDelayedTaskList; /*< Points to the delayed task list currently being used to hold tasks that have overflowed the current tick count. */ +PRIVILEGED_DATA static List_t xPendingReadyList; /*< Tasks that have been readied while the scheduler was suspended. They will be moved to the ready list when the scheduler is resumed. */ + +#if ( INCLUDE_vTaskDelete == 1 ) + + PRIVILEGED_DATA static List_t xTasksWaitingTermination; /*< Tasks that have been deleted - but their memory not yet freed. Protected by xTaskQueueMutex.*/ + PRIVILEGED_DATA static volatile UBaseType_t uxTasksDeleted = ( UBaseType_t ) 0U; + +#endif + +#if ( INCLUDE_vTaskSuspend == 1 ) + + PRIVILEGED_DATA static List_t xSuspendedTaskList; /*< Tasks that are currently suspended. */ + +#endif + +#if ( INCLUDE_xTaskGetIdleTaskHandle == 1 ) + + PRIVILEGED_DATA static TaskHandle_t xIdleTaskHandle = NULL; /*< Holds the handle of the idle task. The idle task is created automatically when the scheduler is started. */ + +#endif + +/* Other file private variables. --------------------------------*/ +PRIVILEGED_DATA static volatile UBaseType_t uxCurrentNumberOfTasks = ( UBaseType_t ) 0U; +PRIVILEGED_DATA static volatile TickType_t xTickCount = ( TickType_t ) 0U; +PRIVILEGED_DATA static volatile UBaseType_t uxTopReadyPriority = tskIDLE_PRIORITY; +PRIVILEGED_DATA static volatile BaseType_t xSchedulerRunning = pdFALSE; +PRIVILEGED_DATA static volatile UBaseType_t uxPendedTicks = ( UBaseType_t ) 0U; +PRIVILEGED_DATA static volatile BaseType_t xYieldPending = pdFALSE; +PRIVILEGED_DATA static volatile BaseType_t xNumOfOverflows = ( BaseType_t ) 0; +PRIVILEGED_DATA static UBaseType_t uxTaskNumber = ( UBaseType_t ) 0U; +PRIVILEGED_DATA static volatile TickType_t xNextTaskUnblockTime = portMAX_DELAY; + +/* Context switches are held pending while the scheduler is suspended. Also, +interrupts must not manipulate the xGenericListItem of a TCB, or any of the +lists the xGenericListItem can be referenced from, if the scheduler is suspended. +If an interrupt needs to unblock a task while the scheduler is suspended then it +moves the task's event list item into the xPendingReadyList, ready for the +kernel to move the task from the pending ready list into the real ready list +when the scheduler is unsuspended. The pending ready list itself can only be +accessed from a critical section. */ +PRIVILEGED_DATA static volatile UBaseType_t uxSchedulerSuspended[ portNUM_PROCESSORS ] = { ( UBaseType_t ) pdFALSE }; + +/* Muxes used in the task code */ +PRIVILEGED_DATA static portBASE_TYPE xMutexesInitialised = pdFALSE; +/* For now, we use just one mux for all the critical sections. ToDo: give evrything a bit more granularity; + that could improve performance by not needlessly spinning in spinlocks for unrelated resources. */ +PRIVILEGED_DATA static portMUX_TYPE xTaskQueueMutex; +PRIVILEGED_DATA static portMUX_TYPE xTickCountMutex; + +#if ( configGENERATE_RUN_TIME_STATS == 1 ) + + PRIVILEGED_DATA static uint32_t ulTaskSwitchedInTime = 0UL; /*< Holds the value of a timer/counter the last time a task was switched in. */ + PRIVILEGED_DATA static uint32_t ulTotalRunTime = 0UL; /*< Holds the total amount of execution time as defined by the run time counter clock. */ + +#endif + +/*lint +e956 */ + +/* Debugging and trace facilities private variables and macros. ------------*/ + +/* + * The value used to fill the stack of a task when the task is created. This + * is used purely for checking the high water mark for tasks. + */ +#define tskSTACK_FILL_BYTE ( 0xa5U ) + +/* + * Macros used by vListTask to indicate which state a task is in. + */ +#define tskBLOCKED_CHAR ( 'B' ) +#define tskREADY_CHAR ( 'R' ) +#define tskDELETED_CHAR ( 'D' ) +#define tskSUSPENDED_CHAR ( 'S' ) + +/*-----------------------------------------------------------*/ + + +#if ( configUSE_PORT_OPTIMISED_TASK_SELECTION == 0 ) + + /* If configUSE_PORT_OPTIMISED_TASK_SELECTION is 0 then task selection is + performed in a generic way that is not optimised to any particular + microcontroller architecture. */ + + /* uxTopReadyPriority holds the priority of the highest priority ready + state task. */ + #define taskRECORD_READY_PRIORITY( uxPriority ) \ + { \ + if( ( uxPriority ) > uxTopReadyPriority ) \ + { \ + uxTopReadyPriority = ( uxPriority ); \ + } \ + } /* taskRECORD_READY_PRIORITY */ + + /*-----------------------------------------------------------*/ + + #define taskSELECT_HIGHEST_PRIORITY_TASK() \ + { \ + /* Find the highest priority queue that contains ready tasks. */ \ + while( listLIST_IS_EMPTY( &( pxReadyTasksLists[ uxTopReadyPriority ] ) ) ) \ + { \ + configASSERT( uxTopReadyPriority ); \ + --uxTopReadyPriority; \ + } \ + \ + /* listGET_OWNER_OF_NEXT_ENTRY indexes through the list, so the tasks of \ + the same priority get an equal share of the processor time. */ \ + listGET_OWNER_OF_NEXT_ENTRY( pxCurrentTCB[ xPortGetCoreID() ], &( pxReadyTasksLists[ uxTopReadyPriority ] ) ); \ + } /* taskSELECT_HIGHEST_PRIORITY_TASK */ + + /*-----------------------------------------------------------*/ + + /* Define away taskRESET_READY_PRIORITY() and portRESET_READY_PRIORITY() as + they are only required when a port optimised method of task selection is + being used. */ + #define taskRESET_READY_PRIORITY( uxPriority ) + #define portRESET_READY_PRIORITY( uxPriority, uxTopReadyPriority ) + +#else /* configUSE_PORT_OPTIMISED_TASK_SELECTION */ + + /* If configUSE_PORT_OPTIMISED_TASK_SELECTION is 1 then task selection is + performed in a way that is tailored to the particular microcontroller + architecture being used. */ + + /* A port optimised version is provided. Call the port defined macros. */ + #define taskRECORD_READY_PRIORITY( uxPriority ) portRECORD_READY_PRIORITY( uxPriority, uxTopReadyPriority ) + + /*-----------------------------------------------------------*/ + + #define taskSELECT_HIGHEST_PRIORITY_TASK() \ + { \ + UBaseType_t uxTopPriority; \ + \ + /* Find the highest priority queue that contains ready tasks. */ \ + portGET_HIGHEST_PRIORITY( uxTopPriority, uxTopReadyPriority ); \ + configASSERT( listCURRENT_LIST_LENGTH( &( pxReadyTasksLists[ uxTopPriority ] ) ) > 0 ); \ + listGET_OWNER_OF_NEXT_ENTRY( pxCurrentTCB[ xPortGetCoreID() ], &( pxReadyTasksLists[ uxTopPriority ] ) ); \ + } /* taskSELECT_HIGHEST_PRIORITY_TASK() */ + + /*-----------------------------------------------------------*/ + + /* A port optimised version is provided, call it only if the TCB being reset + is being referenced from a ready list. If it is referenced from a delayed + or suspended list then it won't be in a ready list. */ + #define taskRESET_READY_PRIORITY( uxPriority ) \ + { \ + if( listCURRENT_LIST_LENGTH( &( pxReadyTasksLists[ ( uxPriority ) ] ) ) == ( UBaseType_t ) 0 ) \ + { \ + portRESET_READY_PRIORITY( ( uxPriority ), ( uxTopReadyPriority ) ); \ + } \ + } + +#endif /* configUSE_PORT_OPTIMISED_TASK_SELECTION */ + +/*-----------------------------------------------------------*/ + +/* pxDelayedTaskList and pxOverflowDelayedTaskList are switched when the tick +count overflows. */ +#define taskSWITCH_DELAYED_LISTS() \ +{ \ + List_t *pxTemp; \ + \ + /* The delayed tasks list should be empty when the lists are switched. */ \ + configASSERT( ( listLIST_IS_EMPTY( pxDelayedTaskList ) ) ); \ + \ + pxTemp = pxDelayedTaskList; \ + pxDelayedTaskList = pxOverflowDelayedTaskList; \ + pxOverflowDelayedTaskList = pxTemp; \ + xNumOfOverflows++; \ + prvResetNextTaskUnblockTime(); \ +} + +/*-----------------------------------------------------------*/ + +/* + * Place the task represented by pxTCB into the appropriate ready list for + * the task. It is inserted at the end of the list. + */ +#define prvAddTaskToReadyList( pxTCB ) \ + traceMOVED_TASK_TO_READY_STATE( pxTCB ) \ + taskRECORD_READY_PRIORITY( ( pxTCB )->uxPriority ); \ + vListInsertEnd( &( pxReadyTasksLists[ ( pxTCB )->uxPriority ] ), &( ( pxTCB )->xGenericListItem ) ) +/*-----------------------------------------------------------*/ + +/* + * Several functions take an TaskHandle_t parameter that can optionally be NULL, + * where NULL is used to indicate that the handle of the currently executing + * task should be used in place of the parameter. This macro simply checks to + * see if the parameter is NULL and returns a pointer to the appropriate TCB. + */ +/* ToDo: See if this still works for multicore. */ +#define prvGetTCBFromHandle( pxHandle ) ( ( ( pxHandle ) == NULL ) ? ( TCB_t * ) pxCurrentTCB[ xPortGetCoreID() ] : ( TCB_t * ) ( pxHandle ) ) + +/* The item value of the event list item is normally used to hold the priority +of the task to which it belongs (coded to allow it to be held in reverse +priority order). However, it is occasionally borrowed for other purposes. It +is important its value is not updated due to a task priority change while it is +being used for another purpose. The following bit definition is used to inform +the scheduler that the value should not be changed - in which case it is the +responsibility of whichever module is using the value to ensure it gets set back +to its original value when it is released. */ +#if configUSE_16_BIT_TICKS == 1 + #define taskEVENT_LIST_ITEM_VALUE_IN_USE 0x8000U +#else + #define taskEVENT_LIST_ITEM_VALUE_IN_USE 0x80000000UL +#endif + +/* Callback function prototypes. --------------------------*/ +#if configCHECK_FOR_STACK_OVERFLOW > 0 + extern void vApplicationStackOverflowHook( TaskHandle_t xTask, char *pcTaskName ); +#endif + +#if configUSE_TICK_HOOK > 0 + extern void vApplicationTickHook( void ); +#endif + +/* File private functions. --------------------------------*/ + +/* + * Utility to ready a TCB for a given task. Mainly just copies the parameters + * into the TCB structure. + */ +static void prvInitialiseTCBVariables( TCB_t * const pxTCB, const char * const pcName, UBaseType_t uxPriority, const MemoryRegion_t * const xRegions, const uint16_t usStackDepth, const BaseType_t xCoreID ) PRIVILEGED_FUNCTION; /*lint !e971 Unqualified char types are allowed for strings and single characters only. */ + +/** + * Utility task that simply returns pdTRUE if the task referenced by xTask is + * currently in the Suspended state, or pdFALSE if the task referenced by xTask + * is in any other state. + */ +#if ( INCLUDE_vTaskSuspend == 1 ) + static BaseType_t prvTaskIsTaskSuspended( const TaskHandle_t xTask ) PRIVILEGED_FUNCTION; +#endif /* INCLUDE_vTaskSuspend */ + +/* + * Utility to ready all the lists used by the scheduler. This is called + * automatically upon the creation of the first task. + */ +static void prvInitialiseTaskLists( void ) PRIVILEGED_FUNCTION; + +/* + * The idle task, which as all tasks is implemented as a never ending loop. + * The idle task is automatically created and added to the ready lists upon + * creation of the first user task. + * + * The portTASK_FUNCTION_PROTO() macro is used to allow port/compiler specific + * language extensions. The equivalent prototype for this function is: + * + * void prvIdleTask( void *pvParameters ); + * + */ +static portTASK_FUNCTION_PROTO( prvIdleTask, pvParameters ); + +/* + * Utility to free all memory allocated by the scheduler to hold a TCB, + * including the stack pointed to by the TCB. + * + * This does not free memory allocated by the task itself (i.e. memory + * allocated by calls to pvPortMalloc from within the tasks application code). + */ +#if ( INCLUDE_vTaskDelete == 1 ) + + static void prvDeleteTCB( TCB_t *pxTCB ) PRIVILEGED_FUNCTION; + +#endif + +/* + * Used only by the idle task. This checks to see if anything has been placed + * in the list of tasks waiting to be deleted. If so the task is cleaned up + * and its TCB deleted. + */ +static void prvCheckTasksWaitingTermination( void ) PRIVILEGED_FUNCTION; + +/* + * The currently executing task is entering the Blocked state. Add the task to + * either the current or the overflow delayed task list. + */ +static void prvAddCurrentTaskToDelayedList( const portBASE_TYPE xCoreID, const TickType_t xTimeToWake ) PRIVILEGED_FUNCTION; + +/* + * Allocates memory from the heap for a TCB and associated stack. Checks the + * allocation was successful. + */ +static TCB_t *prvAllocateTCBAndStack( const uint16_t usStackDepth, StackType_t * const puxStackBuffer ) PRIVILEGED_FUNCTION; + +/* + * Fills an TaskStatus_t structure with information on each task that is + * referenced from the pxList list (which may be a ready list, a delayed list, + * a suspended list, etc.). + * + * THIS FUNCTION IS INTENDED FOR DEBUGGING ONLY, AND SHOULD NOT BE CALLED FROM + * NORMAL APPLICATION CODE. + */ +#if ( configUSE_TRACE_FACILITY == 1 ) + + static UBaseType_t prvListTaskWithinSingleList( TaskStatus_t *pxTaskStatusArray, List_t *pxList, eTaskState eState ) PRIVILEGED_FUNCTION; + +#endif + +/* + * When a task is created, the stack of the task is filled with a known value. + * This function determines the 'high water mark' of the task stack by + * determining how much of the stack remains at the original preset value. + */ +#if ( ( configUSE_TRACE_FACILITY == 1 ) || ( INCLUDE_uxTaskGetStackHighWaterMark == 1 ) ) + + static uint16_t prvTaskCheckFreeStackSpace( const uint8_t * pucStackByte ) PRIVILEGED_FUNCTION; + +#endif + +/* + * Return the amount of time, in ticks, that will pass before the kernel will + * next move a task from the Blocked state to the Running state. + * + * This conditional compilation should use inequality to 0, not equality to 1. + * This is to ensure portSUPPRESS_TICKS_AND_SLEEP() can be called when user + * defined low power mode implementations require configUSE_TICKLESS_IDLE to be + * set to a value other than 1. + */ +#if ( configUSE_TICKLESS_IDLE != 0 ) + + static TickType_t prvGetExpectedIdleTime( void ) PRIVILEGED_FUNCTION; + +#endif + +/* + * Set xNextTaskUnblockTime to the time at which the next Blocked state task + * will exit the Blocked state. + */ +static void prvResetNextTaskUnblockTime( void ); + +#if ( ( configUSE_TRACE_FACILITY == 1 ) && ( configUSE_STATS_FORMATTING_FUNCTIONS > 0 ) ) + + /* + * Helper function used to pad task names with spaces when printing out + * human readable tables of task information. + */ + static char *prvWriteNameToBuffer( char *pcBuffer, const char *pcTaskName ); + +#endif + +/*-----------------------------------------------------------*/ + + +static void vTaskInitializeLocalMuxes( void ) +{ + vPortCPUInitializeMutex(&xTaskQueueMutex); + vPortCPUInitializeMutex(&xTickCountMutex); + xMutexesInitialised = pdTRUE; +} + +/*-----------------------------------------------------------*/ + +BaseType_t xTaskGenericCreate( TaskFunction_t pxTaskCode, const char * const pcName, const uint16_t usStackDepth, void * const pvParameters, UBaseType_t uxPriority, TaskHandle_t * const pxCreatedTask, StackType_t * const puxStackBuffer, const MemoryRegion_t * const xRegions, const BaseType_t xCoreID) /*lint !e971 Unqualified char types are allowed for strings and single characters only. */ +{ +BaseType_t xReturn; +TCB_t * pxNewTCB; +StackType_t *pxTopOfStack; +BaseType_t i; + + /* Initialize mutexes, if they're not already initialized. */ + if (xMutexesInitialised == pdFALSE) vTaskInitializeLocalMuxes(); + + configASSERT( pxTaskCode ); + configASSERT( ( ( uxPriority & ( ~portPRIVILEGE_BIT ) ) < configMAX_PRIORITIES ) ); + configASSERT( (xCoreID>=0 && xCoreIDxUsingStaticallyAllocatedStack = pdTRUE; + } + else + { + /* The stack was allocated dynamically. Note this so it can be + deleted again if the task is deleted. */ + pxNewTCB->xUsingStaticallyAllocatedStack = pdFALSE; + } + #endif /* portUSING_MPU_WRAPPERS == 1 */ + + /* Calculate the top of stack address. This depends on whether the + stack grows from high memory to low (as per the 80x86) or vice versa. + portSTACK_GROWTH is used to make the result positive or negative as + required by the port. */ + #if( portSTACK_GROWTH < 0 ) + { + pxTopOfStack = pxNewTCB->pxStack + ( usStackDepth - ( uint16_t ) 1 ); + pxTopOfStack = ( StackType_t * ) ( ( ( portPOINTER_SIZE_TYPE ) pxTopOfStack ) & ( ( portPOINTER_SIZE_TYPE ) ~portBYTE_ALIGNMENT_MASK ) ); /*lint !e923 MISRA exception. Avoiding casts between pointers and integers is not practical. Size differences accounted for using portPOINTER_SIZE_TYPE type. */ + + /* Check the alignment of the calculated top of stack is correct. */ + configASSERT( ( ( ( portPOINTER_SIZE_TYPE ) pxTopOfStack & ( portPOINTER_SIZE_TYPE ) portBYTE_ALIGNMENT_MASK ) == 0UL ) ); + } + #else /* portSTACK_GROWTH */ + { + pxTopOfStack = pxNewTCB->pxStack; + + /* Check the alignment of the stack buffer is correct. */ + configASSERT( ( ( ( portPOINTER_SIZE_TYPE ) pxNewTCB->pxStack & ( portPOINTER_SIZE_TYPE ) portBYTE_ALIGNMENT_MASK ) == 0UL ) ); + + /* If we want to use stack checking on architectures that use + a positive stack growth direction then we also need to store the + other extreme of the stack space. */ + pxNewTCB->pxEndOfStack = pxNewTCB->pxStack + ( usStackDepth - 1 ); + } + #endif /* portSTACK_GROWTH */ + + /* Setup the newly allocated TCB with the initial state of the task. */ + prvInitialiseTCBVariables( pxNewTCB, pcName, uxPriority, xRegions, usStackDepth, xCoreID ); + + /* Initialize the TCB stack to look as if the task was already running, + but had been interrupted by the scheduler. The return address is set + to the start of the task function. Once the stack has been initialised + the top of stack variable is updated. */ + #if( portUSING_MPU_WRAPPERS == 1 ) + { + pxNewTCB->pxTopOfStack = pxPortInitialiseStack( pxTopOfStack, pxTaskCode, pvParameters, xRunPrivileged ); + } + #else /* portUSING_MPU_WRAPPERS */ + { + pxNewTCB->pxTopOfStack = pxPortInitialiseStack( pxTopOfStack, pxTaskCode, pvParameters ); + } + #endif /* portUSING_MPU_WRAPPERS */ + + if( ( void * ) pxCreatedTask != NULL ) + { + /* Pass the TCB out - in an anonymous way. The calling function/ + task can use this as a handle to delete the task later if + required.*/ + *pxCreatedTask = ( TaskHandle_t ) pxNewTCB; + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + + /* Ensure interrupts don't access the task lists while they are being + updated. */ + taskENTER_CRITICAL(&xTaskQueueMutex); + { + uxCurrentNumberOfTasks++; + if( uxCurrentNumberOfTasks == ( UBaseType_t ) 1 ) + { + /* This is the first task to be created so do the preliminary + initialisation required. We will not recover if this call + fails, but we will report the failure. */ + prvInitialiseTaskLists(); + } + if( xSchedulerRunning == pdFALSE ) + { + /* Scheduler isn't running yet. We need to determine on which CPU to run this task. */ + for ( i=0; iuxPriority <= uxPriority ) + { + pxCurrentTCB[i] = pxNewTCB; + break; + } + } + } + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + + uxTaskNumber++; + + #if ( configUSE_TRACE_FACILITY == 1 ) + { + /* Add a counter into the TCB for tracing only. */ + pxNewTCB->uxTCBNumber = uxTaskNumber; + } + #endif /* configUSE_TRACE_FACILITY */ + traceTASK_CREATE( pxNewTCB ); + + prvAddTaskToReadyList( pxNewTCB ); + + xReturn = pdPASS; + portSETUP_TCB( pxNewTCB ); + } + taskEXIT_CRITICAL(&xTaskQueueMutex); + } + else + { + xReturn = errCOULD_NOT_ALLOCATE_REQUIRED_MEMORY; + traceTASK_CREATE_FAILED(); + } + + if( xReturn == pdPASS ) + { + if( xSchedulerRunning != pdFALSE ) + { + /* Scheduler is running. If the created task is of a higher priority than an executing task + then it should run now. + ToDo: This only works for the current core. If a task is scheduled on an other processor, + the other processor will keep running the task it's working on, and only switch to the newer + task on a timer interrupt. */ + //No mux here, uxPriority is mostly atomic and there's not really any harm if this check misfires. + if( pxCurrentTCB[ xPortGetCoreID() ]->uxPriority < uxPriority ) + { + taskYIELD_IF_USING_PREEMPTION(); + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } + + return xReturn; +} +/*-----------------------------------------------------------*/ + +#if ( INCLUDE_vTaskDelete == 1 ) + void vTaskDelete( TaskHandle_t xTaskToDelete ) + { + TCB_t *pxTCB; + taskENTER_CRITICAL(&xTaskQueueMutex); + { + /* If null is passed in here then it is the calling task that is + being deleted. */ + pxTCB = prvGetTCBFromHandle( xTaskToDelete ); + + /* Remove task from the ready list and place in the termination list. + This will stop the task from be scheduled. The idle task will check + the termination list and free up any memory allocated by the + scheduler for the TCB and stack. */ + if( uxListRemove( &( pxTCB->xGenericListItem ) ) == ( UBaseType_t ) 0 ) + { + taskRESET_READY_PRIORITY( pxTCB->uxPriority ); + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + + /* Is the task waiting on an event also? */ + if( listLIST_ITEM_CONTAINER( &( pxTCB->xEventListItem ) ) != NULL ) + { + ( void ) uxListRemove( &( pxTCB->xEventListItem ) ); + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + + vListInsertEnd( &xTasksWaitingTermination, &( pxTCB->xGenericListItem ) ); + + /* Increment the ucTasksDeleted variable so the idle task knows + there is a task that has been deleted and that it should therefore + check the xTasksWaitingTermination list. */ + ++uxTasksDeleted; + + /* Increment the uxTaskNumberVariable also so kernel aware debuggers + can detect that the task lists need re-generating. */ + uxTaskNumber++; + + traceTASK_DELETE( pxTCB ); + } + taskEXIT_CRITICAL(&xTaskQueueMutex); + + /* Force a reschedule if it is the currently running task that has just + been deleted. */ + if( xSchedulerRunning != pdFALSE ) + { + //No mux; no harm done if this misfires. The deleted task won't get scheduled anyway. + if( pxTCB == pxCurrentTCB[ xPortGetCoreID() ] ) + { + configASSERT( uxSchedulerSuspended[ xPortGetCoreID() ] == 0 ); + + /* The pre-delete hook is primarily for the Windows simulator, + in which Windows specific clean up operations are performed, + after which it is not possible to yield away from this task - + hence xYieldPending is used to latch that a context switch is + required. */ + portPRE_TASK_DELETE_HOOK( pxTCB, &xYieldPending ); + portYIELD_WITHIN_API(); + } + else + { + /* Reset the next expected unblock time in case it referred to + the task that has just been deleted. */ + taskENTER_CRITICAL(&xTaskQueueMutex); + { + prvResetNextTaskUnblockTime(); + } + taskEXIT_CRITICAL(&xTaskQueueMutex); + } + } + } + +#endif /* INCLUDE_vTaskDelete */ +/*-----------------------------------------------------------*/ + +#if ( INCLUDE_vTaskDelayUntil == 1 ) + +/* ToDo: Make this multicore-compatible. */ + void vTaskDelayUntil( TickType_t * const pxPreviousWakeTime, const TickType_t xTimeIncrement ) + { + TickType_t xTimeToWake; + BaseType_t xAlreadyYielded=pdFALSE, xShouldDelay = pdFALSE; + + ets_printf("ToDo %s\n", __FUNCTION__); + configASSERT( pxPreviousWakeTime ); + configASSERT( ( xTimeIncrement > 0U ) ); + configASSERT( uxSchedulerSuspended[ xPortGetCoreID() ] == 0 ); + + taskENTER_CRITICAL(&xTaskQueueMutex); +// vTaskSuspendAll(); + { + /* Minor optimisation. The tick count cannot change in this + block. */ +// portTICK_TYPE_ENTER_CRITICAL( &xTickCountMutex ); + const TickType_t xConstTickCount = xTickCount; +// portTICK_TYPE_EXIT_CRITICAL( &xTickCountMutex ); + + /* Generate the tick time at which the task wants to wake. */ + xTimeToWake = *pxPreviousWakeTime + xTimeIncrement; + + if( xConstTickCount < *pxPreviousWakeTime ) + { + /* The tick count has overflowed since this function was + lasted called. In this case the only time we should ever + actually delay is if the wake time has also overflowed, + and the wake time is greater than the tick time. When this + is the case it is as if neither time had overflowed. */ + if( ( xTimeToWake < *pxPreviousWakeTime ) && ( xTimeToWake > xConstTickCount ) ) + { + xShouldDelay = pdTRUE; + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } + else + { + /* The tick time has not overflowed. In this case we will + delay if either the wake time has overflowed, and/or the + tick time is less than the wake time. */ + if( ( xTimeToWake < *pxPreviousWakeTime ) || ( xTimeToWake > xConstTickCount ) ) + { + xShouldDelay = pdTRUE; + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } + + /* Update the wake time ready for the next call. */ + *pxPreviousWakeTime = xTimeToWake; + + if( xShouldDelay != pdFALSE ) + { + traceTASK_DELAY_UNTIL(); + + /* Remove the task from the ready list before adding it to the + blocked list as the same list item is used for both lists. */ + if( uxListRemove( &( pxCurrentTCB[ xPortGetCoreID() ]->xGenericListItem ) ) == ( UBaseType_t ) 0 ) + { + /* The current task must be in a ready list, so there is + no need to check, and the port reset macro can be called + directly. */ + portRESET_READY_PRIORITY( pxCurrentTCB[ xPortGetCoreID() ]->uxPriority, uxTopReadyPriority ); + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + + prvAddCurrentTaskToDelayedList( xPortGetCoreID(), xTimeToWake ); + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } +// xAlreadyYielded = xTaskResumeAll(); + taskEXIT_CRITICAL(&xTaskQueueMutex); + + /* Force a reschedule if xTaskResumeAll has not already done so, we may + have put ourselves to sleep. */ + if( xAlreadyYielded == pdFALSE ) + { + portYIELD_WITHIN_API(); + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } + +#endif /* INCLUDE_vTaskDelayUntil */ +/*-----------------------------------------------------------*/ + +#if ( INCLUDE_vTaskDelay == 1 ) + void vTaskDelay( const TickType_t xTicksToDelay ) + { + TickType_t xTimeToWake; + BaseType_t xAlreadyYielded = pdFALSE; + + /* A delay time of zero just forces a reschedule. */ + if( xTicksToDelay > ( TickType_t ) 0U ) + { + configASSERT( uxSchedulerSuspended[ xPortGetCoreID() ] == 0 ); + taskENTER_CRITICAL(&xTaskQueueMutex); +// vTaskSuspendAll(); + { + traceTASK_DELAY(); + + /* A task that is removed from the event list while the + scheduler is suspended will not get placed in the ready + list or removed from the blocked list until the scheduler + is resumed. + + This task cannot be in an event list as it is the currently + executing task. */ + + /* Calculate the time to wake - this may overflow but this is + not a problem. */ +// portTICK_TYPE_ENTER_CRITICAL( &xTickCountMutex ); + xTimeToWake = xTickCount + xTicksToDelay; +// portTICK_TYPE_EXIT_CRITICAL( &xTickCountMutex ); + + /* We must remove ourselves from the ready list before adding + ourselves to the blocked list as the same list item is used for + both lists. */ + if( uxListRemove( &( pxCurrentTCB[ xPortGetCoreID() ]->xGenericListItem ) ) == ( UBaseType_t ) 0 ) + { + /* The current task must be in a ready list, so there is + no need to check, and the port reset macro can be called + directly. */ + portRESET_READY_PRIORITY( pxCurrentTCB[ xPortGetCoreID() ]->uxPriority, uxTopReadyPriority ); + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + prvAddCurrentTaskToDelayedList( xPortGetCoreID(), xTimeToWake ); + } +// xAlreadyYielded = xTaskResumeAll(); + taskEXIT_CRITICAL(&xTaskQueueMutex); + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + + /* Force a reschedule if xTaskResumeAll has not already done so, we may + have put ourselves to sleep. */ + if( xAlreadyYielded == pdFALSE ) + { + portYIELD_WITHIN_API(); + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } + +#endif /* INCLUDE_vTaskDelay */ +/*-----------------------------------------------------------*/ + +#if ( INCLUDE_eTaskGetState == 1 ) +/* ToDo: Make this multicore-compatible. */ + eTaskState eTaskGetState( TaskHandle_t xTask ) + { + eTaskState eReturn; + List_t *pxStateList; + const TCB_t * const pxTCB = ( TCB_t * ) xTask; + + ets_printf("ToDo %s\n", __FUNCTION__); + configASSERT( pxTCB ); + + if( pxTCB == pxCurrentTCB[ xPortGetCoreID() ] ) + { + /* The task calling this function is querying its own state. */ + eReturn = eRunning; + } + else + { + taskENTER_CRITICAL(&xTaskQueueMutex); + { + pxStateList = ( List_t * ) listLIST_ITEM_CONTAINER( &( pxTCB->xGenericListItem ) ); + } + taskEXIT_CRITICAL(&xTaskQueueMutex); + + if( ( pxStateList == pxDelayedTaskList ) || ( pxStateList == pxOverflowDelayedTaskList ) ) + { + /* The task being queried is referenced from one of the Blocked + lists. */ + eReturn = eBlocked; + } + + #if ( INCLUDE_vTaskSuspend == 1 ) + else if( pxStateList == &xSuspendedTaskList ) + { + /* The task being queried is referenced from the suspended + list. Is it genuinely suspended or is it block + indefinitely? */ + if( listLIST_ITEM_CONTAINER( &( pxTCB->xEventListItem ) ) == NULL ) + { + eReturn = eSuspended; + } + else + { + eReturn = eBlocked; + } + } + #endif + + #if ( INCLUDE_vTaskDelete == 1 ) + else if( pxStateList == &xTasksWaitingTermination ) + { + /* The task being queried is referenced from the deleted + tasks list. */ + eReturn = eDeleted; + } + #endif + + else /*lint !e525 Negative indentation is intended to make use of pre-processor clearer. */ + { + /* If the task is not in any other state, it must be in the + Ready (including pending ready) state. */ + eReturn = eReady; + } + } + + return eReturn; + } /*lint !e818 xTask cannot be a pointer to const because it is a typedef. */ + +#endif /* INCLUDE_eTaskGetState */ +/*-----------------------------------------------------------*/ + +#if ( INCLUDE_uxTaskPriorityGet == 1 ) +/* ToDo: Make this multicore-compatible. */ + UBaseType_t uxTaskPriorityGet( TaskHandle_t xTask ) + { + TCB_t *pxTCB; + UBaseType_t uxReturn; + + ets_printf("ToDo %s\n", __FUNCTION__); + taskENTER_CRITICAL(&xTaskQueueMutex); + { + /* If null is passed in here then we are changing the + priority of the calling function. */ + pxTCB = prvGetTCBFromHandle( xTask ); + uxReturn = pxTCB->uxPriority; + } + taskEXIT_CRITICAL(&xTaskQueueMutex); + + return uxReturn; + } + +#endif /* INCLUDE_uxTaskPriorityGet */ +/*-----------------------------------------------------------*/ + +#if ( INCLUDE_uxTaskPriorityGet == 1 ) +/* ToDo: Make this multicore-compatible. */ + UBaseType_t uxTaskPriorityGetFromISR( TaskHandle_t xTask ) + { + TCB_t *pxTCB; + UBaseType_t uxReturn; + + taskENTER_CRITICAL_ISR(&xTaskQueueMutex); + { + /* If null is passed in here then it is the priority of the calling + task that is being queried. */ + pxTCB = prvGetTCBFromHandle( xTask ); + uxReturn = pxTCB->uxPriority; + } + taskEXIT_CRITICAL_ISR(&xTaskQueueMutex); + + return uxReturn; + } + +#endif /* INCLUDE_uxTaskPriorityGet */ +/*-----------------------------------------------------------*/ + +#if ( INCLUDE_vTaskPrioritySet == 1 ) + + void vTaskPrioritySet( TaskHandle_t xTask, UBaseType_t uxNewPriority ) + { + TCB_t *pxTCB; + UBaseType_t uxCurrentBasePriority, uxPriorityUsedOnEntry; + BaseType_t xYieldRequired = pdFALSE; + + configASSERT( ( uxNewPriority < configMAX_PRIORITIES ) ); + + /* Ensure the new priority is valid. */ + if( uxNewPriority >= ( UBaseType_t ) configMAX_PRIORITIES ) + { + uxNewPriority = ( UBaseType_t ) configMAX_PRIORITIES - ( UBaseType_t ) 1U; + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + + taskENTER_CRITICAL(&xTaskQueueMutex); + { + /* If null is passed in here then it is the priority of the calling + task that is being changed. */ + pxTCB = prvGetTCBFromHandle( xTask ); + + traceTASK_PRIORITY_SET( pxTCB, uxNewPriority ); + + #if ( configUSE_MUTEXES == 1 ) + { + uxCurrentBasePriority = pxTCB->uxBasePriority; + } + #else + { + uxCurrentBasePriority = pxTCB->uxPriority; + } + #endif + + if( uxCurrentBasePriority != uxNewPriority ) + { + /* The priority change may have readied a task of higher + priority than the calling task. */ + if( uxNewPriority > uxCurrentBasePriority ) + { + if( pxTCB != pxCurrentTCB[ xPortGetCoreID() ] ) + { + /* The priority of a task other than the currently + running task is being raised. Is the priority being + raised above that of the running task? */ + if( uxNewPriority >= pxCurrentTCB[ xPortGetCoreID() ]->uxPriority ) + { + xYieldRequired = pdTRUE; + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } + else + { + /* The priority of the running task is being raised, + but the running task must already be the highest + priority task able to run so no yield is required. */ + } + } + else if( pxTCB == pxCurrentTCB[ xPortGetCoreID() ] ) + { + /* Setting the priority of the running task down means + there may now be another task of higher priority that + is ready to execute. */ + xYieldRequired = pdTRUE; + } + else + { + /* Setting the priority of any other task down does not + require a yield as the running task must be above the + new priority of the task being modified. */ + } + + /* Remember the ready list the task might be referenced from + before its uxPriority member is changed so the + taskRESET_READY_PRIORITY() macro can function correctly. */ + uxPriorityUsedOnEntry = pxTCB->uxPriority; + + #if ( configUSE_MUTEXES == 1 ) + { + /* Only change the priority being used if the task is not + currently using an inherited priority. */ + if( pxTCB->uxBasePriority == pxTCB->uxPriority ) + { + pxTCB->uxPriority = uxNewPriority; + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + + /* The base priority gets set whatever. */ + pxTCB->uxBasePriority = uxNewPriority; + } + #else + { + pxTCB->uxPriority = uxNewPriority; + } + #endif + + /* Only reset the event list item value if the value is not + being used for anything else. */ + if( ( listGET_LIST_ITEM_VALUE( &( pxTCB->xEventListItem ) ) & taskEVENT_LIST_ITEM_VALUE_IN_USE ) == 0UL ) + { + listSET_LIST_ITEM_VALUE( &( pxTCB->xEventListItem ), ( ( TickType_t ) configMAX_PRIORITIES - ( TickType_t ) uxNewPriority ) ); /*lint !e961 MISRA exception as the casts are only redundant for some ports. */ + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + + /* If the task is in the blocked or suspended list we need do + nothing more than change it's priority variable. However, if + the task is in a ready list it needs to be removed and placed + in the list appropriate to its new priority. */ + if( listIS_CONTAINED_WITHIN( &( pxReadyTasksLists[ uxPriorityUsedOnEntry ] ), &( pxTCB->xGenericListItem ) ) != pdFALSE ) + { + /* The task is currently in its ready list - remove before adding + it to it's new ready list. As we are in a critical section we + can do this even if the scheduler is suspended. */ + if( uxListRemove( &( pxTCB->xGenericListItem ) ) == ( UBaseType_t ) 0 ) + { + /* It is known that the task is in its ready list so + there is no need to check again and the port level + reset macro can be called directly. */ + portRESET_READY_PRIORITY( uxPriorityUsedOnEntry, uxTopReadyPriority ); + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + prvAddTaskToReadyList( pxTCB ); + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + + if( xYieldRequired == pdTRUE ) + { + taskYIELD_IF_USING_PREEMPTION_MUX(&xTaskQueueMutex); + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + + /* Remove compiler warning about unused variables when the port + optimised task selection is not being used. */ + ( void ) uxPriorityUsedOnEntry; + } + } + taskEXIT_CRITICAL(&xTaskQueueMutex); + } + +#endif /* INCLUDE_vTaskPrioritySet */ +/*-----------------------------------------------------------*/ + +#if ( INCLUDE_vTaskSuspend == 1 ) +/* ToDo: Make this multicore-compatible. */ + void vTaskSuspend( TaskHandle_t xTaskToSuspend ) + { + TCB_t *pxTCB; + + ets_printf("ToDo %s\n", __FUNCTION__); + taskENTER_CRITICAL(&xTaskQueueMutex); + { + /* If null is passed in here then it is the running task that is + being suspended. */ + pxTCB = prvGetTCBFromHandle( xTaskToSuspend ); + + traceTASK_SUSPEND( pxTCB ); + + /* Remove task from the ready/delayed list and place in the + suspended list. */ + if( uxListRemove( &( pxTCB->xGenericListItem ) ) == ( UBaseType_t ) 0 ) + { + taskRESET_READY_PRIORITY( pxTCB->uxPriority ); + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + + /* Is the task waiting on an event also? */ + if( listLIST_ITEM_CONTAINER( &( pxTCB->xEventListItem ) ) != NULL ) + { + ( void ) uxListRemove( &( pxTCB->xEventListItem ) ); + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + + vListInsertEnd( &xSuspendedTaskList, &( pxTCB->xGenericListItem ) ); + } + taskEXIT_CRITICAL(&xTaskQueueMutex); + + if( pxTCB == pxCurrentTCB[ xPortGetCoreID() ] ) + { + if( xSchedulerRunning != pdFALSE ) + { + /* The current task has just been suspended. */ + configASSERT( uxSchedulerSuspended[ xPortGetCoreID() ] == 0 ); + portYIELD_WITHIN_API(); + } + else + { + /* The scheduler is not running, but the task that was pointed + to by pxCurrentTCB has just been suspended and pxCurrentTCB + must be adjusted to point to a different task. */ + if( listCURRENT_LIST_LENGTH( &xSuspendedTaskList ) == uxCurrentNumberOfTasks ) + { + /* No other tasks are ready, so set pxCurrentTCB back to + NULL so when the next task is created pxCurrentTCB will + be set to point to it no matter what its relative priority + is. */ + taskENTER_CRITICAL(&xTaskQueueMutex); + pxCurrentTCB[ xPortGetCoreID() ] = NULL; + taskEXIT_CRITICAL(&xTaskQueueMutex); + } + else + { + vTaskSwitchContext(); + } + } + } + else + { + if( xSchedulerRunning != pdFALSE ) + { + /* A task other than the currently running task was suspended, + reset the next expected unblock time in case it referred to the + task that is now in the Suspended state. */ + taskENTER_CRITICAL(&xTaskQueueMutex); + { + prvResetNextTaskUnblockTime(); + } + taskEXIT_CRITICAL(&xTaskQueueMutex); + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } + } + +#endif /* INCLUDE_vTaskSuspend */ +/*-----------------------------------------------------------*/ + +#if ( INCLUDE_vTaskSuspend == 1 ) + + static BaseType_t prvTaskIsTaskSuspended( const TaskHandle_t xTask ) + { + BaseType_t xReturn = pdFALSE; + const TCB_t * const pxTCB = ( TCB_t * ) xTask; + + /* Accesses xPendingReadyList so must be called from a critical + section. */ + taskENTER_CRITICAL(&xTaskQueueMutex); + + /* It does not make sense to check if the calling task is suspended. */ + configASSERT( xTask ); + + /* Is the task being resumed actually in the suspended list? */ + if( listIS_CONTAINED_WITHIN( &xSuspendedTaskList, &( pxTCB->xGenericListItem ) ) != pdFALSE ) + { + /* Has the task already been resumed from within an ISR? */ + if( listIS_CONTAINED_WITHIN( &xPendingReadyList, &( pxTCB->xEventListItem ) ) == pdFALSE ) + { + /* Is it in the suspended list because it is in the Suspended + state, or because is is blocked with no timeout? */ + if( listIS_CONTAINED_WITHIN( NULL, &( pxTCB->xEventListItem ) ) != pdFALSE ) + { + xReturn = pdTRUE; + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + taskEXIT_CRITICAL(&xTaskQueueMutex); + + return xReturn; + } /*lint !e818 xTask cannot be a pointer to const because it is a typedef. */ + +#endif /* INCLUDE_vTaskSuspend */ +/*-----------------------------------------------------------*/ + +#if ( INCLUDE_vTaskSuspend == 1 ) + +/* ToDo: Make this multicore-compatible. */ + void vTaskResume( TaskHandle_t xTaskToResume ) + { + TCB_t * const pxTCB = ( TCB_t * ) xTaskToResume; + + ets_printf("ToDo %s\n", __FUNCTION__); + /* It does not make sense to resume the calling task. */ + configASSERT( xTaskToResume ); + + taskENTER_CRITICAL(&xTaskQueueMutex); + /* The parameter cannot be NULL as it is impossible to resume the + currently executing task. */ + if( ( pxTCB != NULL ) && ( pxTCB != pxCurrentTCB[ xPortGetCoreID() ] ) ) + { + { + if( prvTaskIsTaskSuspended( pxTCB ) == pdTRUE ) + { + traceTASK_RESUME( pxTCB ); + + /* As we are in a critical section we can access the ready + lists even if the scheduler is suspended. */ + ( void ) uxListRemove( &( pxTCB->xGenericListItem ) ); + prvAddTaskToReadyList( pxTCB ); + + /* We may have just resumed a higher priority task. */ + if( pxTCB->uxPriority >= pxCurrentTCB[ xPortGetCoreID() ]->uxPriority ) + { + /* This yield may not cause the task just resumed to run, + but will leave the lists in the correct state for the + next yield. */ + taskYIELD_IF_USING_PREEMPTION_MUX(&xTaskQueueMutex); + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + taskEXIT_CRITICAL(&xTaskQueueMutex); + } + +#endif /* INCLUDE_vTaskSuspend */ + +/*-----------------------------------------------------------*/ + +#if ( ( INCLUDE_xTaskResumeFromISR == 1 ) && ( INCLUDE_vTaskSuspend == 1 ) ) + +/* ToDo: Make this multicore-compatible. */ + BaseType_t xTaskResumeFromISR( TaskHandle_t xTaskToResume ) + { + BaseType_t xYieldRequired = pdFALSE; + TCB_t * const pxTCB = ( TCB_t * ) xTaskToResume; + + configASSERT( xTaskToResume ); + + taskENTER_CRITICAL_ISR(&xTaskQueueMutex); + + { + if( prvTaskIsTaskSuspended( pxTCB ) == pdTRUE ) + { + traceTASK_RESUME_FROM_ISR( pxTCB ); + + /* Check the ready lists can be accessed. */ + if( uxSchedulerSuspended[ xPortGetCoreID() ] == ( UBaseType_t ) pdFALSE ) + { + /* Ready lists can be accessed so move the task from the + suspended list to the ready list directly. */ + if( pxTCB->uxPriority >= pxCurrentTCB[ xPortGetCoreID() ]->uxPriority ) + { + xYieldRequired = pdTRUE; + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + + ( void ) uxListRemove( &( pxTCB->xGenericListItem ) ); + prvAddTaskToReadyList( pxTCB ); + } + else + { + /* The delayed or ready lists cannot be accessed so the task + is held in the pending ready list until the scheduler is + unsuspended. */ + vListInsertEnd( &( xPendingReadyList ), &( pxTCB->xEventListItem ) ); + } + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } + taskEXIT_CRITICAL_ISR(&xTaskQueueMutex); + + return xYieldRequired; + } + +#endif /* ( ( INCLUDE_xTaskResumeFromISR == 1 ) && ( INCLUDE_vTaskSuspend == 1 ) ) */ +/*-----------------------------------------------------------*/ + +void vTaskStartScheduler( void ) +{ +BaseType_t xReturn; +BaseType_t i; + + /* Add the per-core idle tasks at the lowest priority. */ + for ( i=0; ixNewLib_reent; + } +} +#endif + + +void vTaskSuspendAll( void ) +{ + /* A critical section is not required as the variable is of type + BaseType_t. Please read Richard Barry's reply in the following link to a + post in the FreeRTOS support forum before reporting this as a bug! - + http://goo.gl/wu4acr */ + ++uxSchedulerSuspended[ xPortGetCoreID() ]; +} +/*----------------------------------------------------------*/ + +#if ( configUSE_TICKLESS_IDLE != 0 ) + + static TickType_t prvGetExpectedIdleTime( void ) + { + TickType_t xReturn; + + + taskENTER_CRITICAL(&xTaskQueueMutex); + if( pxCurrentTCB[ xPortGetCoreID() ]->uxPriority > tskIDLE_PRIORITY ) + { + xReturn = 0; + } + else if( listCURRENT_LIST_LENGTH( &( pxReadyTasksLists[ tskIDLE_PRIORITY ] ) ) > 1 ) + { + /* There are other idle priority tasks in the ready state. If + time slicing is used then the very next tick interrupt must be + processed. */ + xReturn = 0; + } + else + { + portTICK_TYPE_ENTER_CRITICAL( &xTickCountMutex ); + xReturn = xNextTaskUnblockTime - xTickCount; + portTICK_TYPE_EXIT_CRITICAL( &xTickCountMutex ); + } + taskEXIT_CRITICAL(&xTaskQueueMutex); + + return xReturn; + } + +#endif /* configUSE_TICKLESS_IDLE */ +/*----------------------------------------------------------*/ + +BaseType_t xTaskResumeAll( void ) +{ +TCB_t *pxTCB; +BaseType_t xAlreadyYielded = pdFALSE; + + /* If uxSchedulerSuspended[ xPortGetCoreID() ] is zero then this function does not match a + previous call to vTaskSuspendAll(). */ + configASSERT( uxSchedulerSuspended[ xPortGetCoreID() ] ); + /* It is possible that an ISR caused a task to be removed from an event + list while the scheduler was suspended. If this was the case then the + removed task will have been added to the xPendingReadyList. Once the + scheduler has been resumed it is safe to move all the pending ready + tasks from this list into their appropriate ready list. */ + + //This uses a mux, but can be called before tasks are scheduled. Make sure muxes are inited. + /* Initialize mutexes, if they're not already initialized. */ + if (xMutexesInitialised == pdFALSE) vTaskInitializeLocalMuxes(); + + taskENTER_CRITICAL(&xTaskQueueMutex); + { + --uxSchedulerSuspended[ xPortGetCoreID() ]; + + if( uxSchedulerSuspended[ xPortGetCoreID() ] == ( UBaseType_t ) pdFALSE ) + { + if( uxCurrentNumberOfTasks > ( UBaseType_t ) 0U ) + { + /* Move any readied tasks from the pending list into the + appropriate ready list. */ + while( listLIST_IS_EMPTY( &xPendingReadyList ) == pdFALSE ) + { + pxTCB = ( TCB_t * ) listGET_OWNER_OF_HEAD_ENTRY( ( &xPendingReadyList ) ); + ( void ) uxListRemove( &( pxTCB->xEventListItem ) ); + ( void ) uxListRemove( &( pxTCB->xGenericListItem ) ); + prvAddTaskToReadyList( pxTCB ); + + /* If the moved task has a priority higher than the current + task then a yield must be performed. */ + if( pxTCB->uxPriority >= pxCurrentTCB[ xPortGetCoreID() ]->uxPriority ) + { + xYieldPending = pdTRUE; + break; + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } + + /* If any ticks occurred while the scheduler was suspended then + they should be processed now. This ensures the tick count does + not slip, and that any delayed tasks are resumed at the correct + time. */ + if( uxPendedTicks > ( UBaseType_t ) 0U ) + { + while( uxPendedTicks > ( UBaseType_t ) 0U ) + { + if( xTaskIncrementTick() != pdFALSE ) + { + xYieldPending = pdTRUE; + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + --uxPendedTicks; + } + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + + if( xYieldPending == pdTRUE ) + { + #if( configUSE_PREEMPTION != 0 ) + { + xAlreadyYielded = pdTRUE; + } + #endif + taskYIELD_IF_USING_PREEMPTION_MUX(&xTaskQueueMutex); + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } + taskEXIT_CRITICAL(&xTaskQueueMutex); + + return xAlreadyYielded; +} +/*-----------------------------------------------------------*/ + +TickType_t xTaskGetTickCount( void ) +{ +TickType_t xTicks; + + /* Critical section required if running on a 16 bit processor. */ + portTICK_TYPE_ENTER_CRITICAL( &xTickCountMutex ); + { + xTicks = xTickCount; + } + portTICK_TYPE_EXIT_CRITICAL( &xTickCountMutex ); + + return xTicks; +} +/*-----------------------------------------------------------*/ + +TickType_t xTaskGetTickCountFromISR( void ) +{ +TickType_t xReturn; + + taskENTER_CRITICAL_ISR(&xTickCountMutex); + { + xReturn = xTickCount; +// vPortCPUReleaseMutex( &xTickCountMutex ); + } + taskEXIT_CRITICAL_ISR(&xTickCountMutex); + + return xReturn; +} +/*-----------------------------------------------------------*/ + +UBaseType_t uxTaskGetNumberOfTasks( void ) +{ + /* A critical section is not required because the variables are of type + BaseType_t. */ + return uxCurrentNumberOfTasks; +} +/*-----------------------------------------------------------*/ + +#if ( INCLUDE_pcTaskGetTaskName == 1 ) + + char *pcTaskGetTaskName( TaskHandle_t xTaskToQuery ) /*lint !e971 Unqualified char types are allowed for strings and single characters only. */ + { + TCB_t *pxTCB; + + /* If null is passed in here then the name of the calling task is being queried. */ + pxTCB = prvGetTCBFromHandle( xTaskToQuery ); + configASSERT( pxTCB ); + return &( pxTCB->pcTaskName[ 0 ] ); + } + +#endif /* INCLUDE_pcTaskGetTaskName */ +/*-----------------------------------------------------------*/ + +#if ( configUSE_TRACE_FACILITY == 1 ) + + UBaseType_t uxTaskGetSystemState( TaskStatus_t * const pxTaskStatusArray, const UBaseType_t uxArraySize, uint32_t * const pulTotalRunTime ) + { + UBaseType_t uxTask = 0, uxQueue = configMAX_PRIORITIES; + + ets_printf("ToDo %s\n", __FUNCTION__); + vTaskSuspendAll(); //WARNING: This only suspends one CPU. ToDo: suspend others as well. Mux using taskQueueMutex maybe? + { + /* Is there a space in the array for each task in the system? */ + if( uxArraySize >= uxCurrentNumberOfTasks ) + { + /* Fill in an TaskStatus_t structure with information on each + task in the Ready state. */ + do + { + uxQueue--; + uxTask += prvListTaskWithinSingleList( &( pxTaskStatusArray[ uxTask ] ), &( pxReadyTasksLists[ uxQueue ] ), eReady ); + + } while( uxQueue > ( UBaseType_t ) tskIDLE_PRIORITY ); /*lint !e961 MISRA exception as the casts are only redundant for some ports. */ + + /* Fill in an TaskStatus_t structure with information on each + task in the Blocked state. */ + uxTask += prvListTaskWithinSingleList( &( pxTaskStatusArray[ uxTask ] ), ( List_t * ) pxDelayedTaskList, eBlocked ); + uxTask += prvListTaskWithinSingleList( &( pxTaskStatusArray[ uxTask ] ), ( List_t * ) pxOverflowDelayedTaskList, eBlocked ); + + #if( INCLUDE_vTaskDelete == 1 ) + { + /* Fill in an TaskStatus_t structure with information on + each task that has been deleted but not yet cleaned up. */ + uxTask += prvListTaskWithinSingleList( &( pxTaskStatusArray[ uxTask ] ), &xTasksWaitingTermination, eDeleted ); + } + #endif + + #if ( INCLUDE_vTaskSuspend == 1 ) + { + /* Fill in an TaskStatus_t structure with information on + each task in the Suspended state. */ + uxTask += prvListTaskWithinSingleList( &( pxTaskStatusArray[ uxTask ] ), &xSuspendedTaskList, eSuspended ); + } + #endif + + #if ( configGENERATE_RUN_TIME_STATS == 1) + { + if( pulTotalRunTime != NULL ) + { + #ifdef portALT_GET_RUN_TIME_COUNTER_VALUE + portALT_GET_RUN_TIME_COUNTER_VALUE( ( *pulTotalRunTime ) ); + #else + *pulTotalRunTime = portGET_RUN_TIME_COUNTER_VALUE(); + #endif + } + } + #else + { + if( pulTotalRunTime != NULL ) + { + *pulTotalRunTime = 0; + } + } + #endif + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } + ( void ) xTaskResumeAll(); + + return uxTask; + } + +#endif /* configUSE_TRACE_FACILITY */ +/*----------------------------------------------------------*/ + +#if ( INCLUDE_xTaskGetIdleTaskHandle == 1 ) + + TaskHandle_t xTaskGetIdleTaskHandle( void ) + { + /* If xTaskGetIdleTaskHandle() is called before the scheduler has been + started, then xIdleTaskHandle will be NULL. */ + configASSERT( ( xIdleTaskHandle != NULL ) ); + return xIdleTaskHandle; + } + +#endif /* INCLUDE_xTaskGetIdleTaskHandle */ +/*----------------------------------------------------------*/ + +/* This conditional compilation should use inequality to 0, not equality to 1. +This is to ensure vTaskStepTick() is available when user defined low power mode +implementations require configUSE_TICKLESS_IDLE to be set to a value other than +1. */ +#if ( configUSE_TICKLESS_IDLE != 0 ) + + void vTaskStepTick( const TickType_t xTicksToJump ) + { + /* Correct the tick count value after a period during which the tick + was suppressed. Note this does *not* call the tick hook function for + each stepped tick. */ + portTICK_TYPE_ENTER_CRITICAL( &xTickCountMutex ); + configASSERT( ( xTickCount + xTicksToJump ) <= xNextTaskUnblockTime ); + xTickCount += xTicksToJump; + portTICK_TYPE_EXIT_CRITICAL( &xTickCountMutex ); + traceINCREASE_TICK_COUNT( xTicksToJump ); + } + +#endif /* configUSE_TICKLESS_IDLE */ +/*----------------------------------------------------------*/ + +BaseType_t xTaskIncrementTick( void ) +{ +TCB_t * pxTCB; +TickType_t xItemValue; +BaseType_t xSwitchRequired = pdFALSE; + + /* Called by the portable layer each time a tick interrupt occurs. + Increments the tick then checks to see if the new tick value will cause any + tasks to be unblocked. */ + + /* Only let core 0 increase the tick count, to keep accurate track of time. */ + /* ToDo: This doesn't really play nice with the logic below: it means when core 1 is + running a low-priority task, it will keep running it until there is a context + switch, even when this routine (running on core 0) unblocks a bunch of high-priority + tasks... this is less than optimal -- JD. */ + if ( xPortGetCoreID()!=0 ) { + /* + We can't really calculate what we need, that's done on core 0... just assume we need a switch. + ToDo: Make this more intelligent? -- JD + */ + return pdTRUE; + } + + + traceTASK_INCREMENT_TICK( xTickCount ); + + if( uxSchedulerSuspended[ xPortGetCoreID() ] == ( UBaseType_t ) pdFALSE ) + { + portTICK_TYPE_ENTER_CRITICAL( &xTickCountMutex ); + /* Increment the RTOS tick, switching the delayed and overflowed + delayed lists if it wraps to 0. */ + ++xTickCount; + portTICK_TYPE_EXIT_CRITICAL( &xTickCountMutex ); + + //The other CPU may decide to mess with the task queues, so this needs a mux. + taskENTER_CRITICAL_ISR(&xTaskQueueMutex); + { + /* Minor optimisation. The tick count cannot change in this + block. */ + const TickType_t xConstTickCount = xTickCount; + + if( xConstTickCount == ( TickType_t ) 0U ) + { + taskSWITCH_DELAYED_LISTS(); + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + + /* See if this tick has made a timeout expire. Tasks are stored in + the queue in the order of their wake time - meaning once one task + has been found whose block time has not expired there is no need to + look any further down the list. */ + if( xConstTickCount >= xNextTaskUnblockTime ) + { + for( ;; ) + { + if( listLIST_IS_EMPTY( pxDelayedTaskList ) != pdFALSE ) + { + /* The delayed list is empty. Set xNextTaskUnblockTime + to the maximum possible value so it is extremely + unlikely that the + if( xTickCount >= xNextTaskUnblockTime ) test will pass + next time through. */ + xNextTaskUnblockTime = portMAX_DELAY; + break; + } + else + { + /* The delayed list is not empty, get the value of the + item at the head of the delayed list. This is the time + at which the task at the head of the delayed list must + be removed from the Blocked state. */ + pxTCB = ( TCB_t * ) listGET_OWNER_OF_HEAD_ENTRY( pxDelayedTaskList ); + xItemValue = listGET_LIST_ITEM_VALUE( &( pxTCB->xGenericListItem ) ); + + if( xConstTickCount < xItemValue ) + { + /* It is not time to unblock this item yet, but the + item value is the time at which the task at the head + of the blocked list must be removed from the Blocked + state - so record the item value in + xNextTaskUnblockTime. */ + xNextTaskUnblockTime = xItemValue; + break; + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + + /* It is time to remove the item from the Blocked state. */ + ( void ) uxListRemove( &( pxTCB->xGenericListItem ) ); + + /* Is the task waiting on an event also? If so remove + it from the event list. */ + if( listLIST_ITEM_CONTAINER( &( pxTCB->xEventListItem ) ) != NULL ) + { + ( void ) uxListRemove( &( pxTCB->xEventListItem ) ); + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + + /* Place the unblocked task into the appropriate ready + list. */ + prvAddTaskToReadyList( pxTCB ); + + /* A task being unblocked cannot cause an immediate + context switch if preemption is turned off. */ + #if ( configUSE_PREEMPTION == 1 ) + { + /* Preemption is on, but a context switch should + only be performed if the unblocked task has a + priority that is equal to or higher than the + currently executing task. */ + if( pxTCB->uxPriority >= pxCurrentTCB[ xPortGetCoreID() ]->uxPriority ) + { + xSwitchRequired = pdTRUE; + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } + #endif /* configUSE_PREEMPTION */ + } + } + } + } + + /* Tasks of equal priority to the currently running task will share + processing time (time slice) if preemption is on, and the application + writer has not explicitly turned time slicing off. */ + #if ( ( configUSE_PREEMPTION == 1 ) && ( configUSE_TIME_SLICING == 1 ) ) + { + if( listCURRENT_LIST_LENGTH( &( pxReadyTasksLists[ pxCurrentTCB[ xPortGetCoreID() ]->uxPriority ] ) ) > ( UBaseType_t ) 1 ) + { + xSwitchRequired = pdTRUE; + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } + #endif /* ( ( configUSE_PREEMPTION == 1 ) && ( configUSE_TIME_SLICING == 1 ) ) */ + + #if ( configUSE_TICK_HOOK == 1 ) + { + /* Guard against the tick hook being called when the pended tick + count is being unwound (when the scheduler is being unlocked). */ + if( uxPendedTicks == ( UBaseType_t ) 0U ) + { + vApplicationTickHook(); + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } + #endif /* configUSE_TICK_HOOK */ + taskEXIT_CRITICAL_ISR(&xTaskQueueMutex); + } + else + { + ++uxPendedTicks; + + /* The tick hook gets called at regular intervals, even if the + scheduler is locked. */ + #if ( configUSE_TICK_HOOK == 1 ) + { + vApplicationTickHook(); + } + #endif + } + + #if ( configUSE_PREEMPTION == 1 ) + { + if( xYieldPending != pdFALSE ) + { + xSwitchRequired = pdTRUE; + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } + #endif /* configUSE_PREEMPTION */ + + return xSwitchRequired; +} +/*-----------------------------------------------------------*/ + +#if ( configUSE_APPLICATION_TASK_TAG == 1 ) + + void vTaskSetApplicationTaskTag( TaskHandle_t xTask, TaskHookFunction_t pxHookFunction ) + { + TCB_t *xTCB; + + /* If xTask is NULL then it is the task hook of the calling task that is + getting set. */ + if( xTask == NULL ) + { + xTCB = ( TCB_t * ) pxCurrentTCB[ xPortGetCoreID() ]; + } + else + { + xTCB = ( TCB_t * ) xTask; + } + + /* Save the hook function in the TCB. A critical section is required as + the value can be accessed from an interrupt. */ + taskENTER_CRITICAL(&xTaskQueueMutex); + xTCB->pxTaskTag = pxHookFunction; + taskEXIT_CRITICAL(&xTaskQueueMutex); + } + +#endif /* configUSE_APPLICATION_TASK_TAG */ +/*-----------------------------------------------------------*/ + +#if ( configUSE_APPLICATION_TASK_TAG == 1 ) + + TaskHookFunction_t xTaskGetApplicationTaskTag( TaskHandle_t xTask ) + { + TCB_t *xTCB; + TaskHookFunction_t xReturn; + + /* If xTask is NULL then we are setting our own task hook. */ + if( xTask == NULL ) + { + xTCB = ( TCB_t * ) pxCurrentTCB[ xPortGetCoreID() ]; + } + else + { + xTCB = ( TCB_t * ) xTask; + } + + /* Save the hook function in the TCB. A critical section is required as + the value can be accessed from an interrupt. */ + taskENTER_CRITICAL(&xTaskQueueMutex); + { + xReturn = xTCB->pxTaskTag; + } + taskEXIT_CRITICAL(&xTaskQueueMutex); + + return xReturn; + } + +#endif /* configUSE_APPLICATION_TASK_TAG */ +/*-----------------------------------------------------------*/ + +#if ( configUSE_APPLICATION_TASK_TAG == 1 ) + + BaseType_t xTaskCallApplicationTaskHook( TaskHandle_t xTask, void *pvParameter ) + { + TCB_t *xTCB; + BaseType_t xReturn; + + /* If xTask is NULL then we are calling our own task hook. */ + if( xTask == NULL ) + { + xTCB = ( TCB_t * ) pxCurrentTCB[ xPortGetCoreID() ]; + } + else + { + xTCB = ( TCB_t * ) xTask; + } + + if( xTCB->pxTaskTag != NULL ) + { + xReturn = xTCB->pxTaskTag( pvParameter ); + } + else + { + xReturn = pdFAIL; + } + + return xReturn; + } + +#endif /* configUSE_APPLICATION_TASK_TAG */ +/*-----------------------------------------------------------*/ + +void vTaskSwitchContext( void ) +{ + tskTCB * pxTCB; + //This can be called both from IRQ as well as normal context, so we can't + //use taskENTER_CRITICAL() here. Instead, save the irq status and disable + //IRQs, so we can use taskENTER_CRITICAL_ISR and friends. + int irqstate=portENTER_CRITICAL_NESTED(); + if( uxSchedulerSuspended[ xPortGetCoreID() ] != ( UBaseType_t ) pdFALSE ) + { + /* The scheduler is currently suspended - do not allow a context + switch. */ + xYieldPending = pdTRUE; + } + else + { + xYieldPending = pdFALSE; + traceTASK_SWITCHED_OUT(); + + #if ( configGENERATE_RUN_TIME_STATS == 1 ) + { + #ifdef portALT_GET_RUN_TIME_COUNTER_VALUE + portALT_GET_RUN_TIME_COUNTER_VALUE( ulTotalRunTime ); + #else + ulTotalRunTime = portGET_RUN_TIME_COUNTER_VALUE(); + #endif + + /* Add the amount of time the task has been running to the + accumulated time so far. The time the task started running was + stored in ulTaskSwitchedInTime. Note that there is no overflow + protection here so count values are only valid until the timer + overflows. The guard against negative values is to protect + against suspect run time stat counter implementations - which + are provided by the application, not the kernel. */ + taskENTER_CRITICAL_ISR(&xTaskQueueMutex); + if( ulTotalRunTime > ulTaskSwitchedInTime ) + { + pxCurrentTCB[ xPortGetCoreID() ]->ulRunTimeCounter += ( ulTotalRunTime - ulTaskSwitchedInTime ); + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + taskEXIT_CRITICAL_ISR(&xTaskQueueMutex); + ulTaskSwitchedInTime = ulTotalRunTime; + } + #endif /* configGENERATE_RUN_TIME_STATS */ + + /* Check for stack overflow, if configured. */ + taskFIRST_CHECK_FOR_STACK_OVERFLOW(); + taskSECOND_CHECK_FOR_STACK_OVERFLOW(); + + /* Select a new task to run using either the generic C or port + optimised asm code. */ + /* ToDo: either get rid of port-changable task switching stuff, or put all this inside the + taskSELECT_HIGHEST_PRIORITY_TASK macro, then replace this all with a taskSELECT_HIGHEST_PRIORITY_TASK(); + call */ + + taskENTER_CRITICAL_ISR(&xTaskQueueMutex); + + unsigned portBASE_TYPE foundNonExecutingWaiter = pdFALSE, ableToSchedule = pdFALSE, resetListHead; + unsigned portBASE_TYPE uxDynamicTopReady = uxTopReadyPriority; + unsigned portBASE_TYPE holdTop=pdFALSE; + + /* + * ToDo: This scheduler doesn't correctly implement the round-robin scheduling as done in the single-core + * FreeRTOS stack when multiple tasks have the same priority and are all ready; it just keeps grabbing the + * first one. ToDo: fix this. + * (Is this still true? if any, there's the issue with one core skipping over the processes for the other + * core, potentially not giving the skipped-over processes any time.) + */ + + while ( ableToSchedule == pdFALSE && uxDynamicTopReady >= 0 ) + { + configASSERT( uxTopReadyPriority>=0 ); + configASSERT( uxDynamicTopReady>=0 ); + resetListHead = pdFALSE; + // Nothing to do for empty lists + if (!listLIST_IS_EMPTY( &( pxReadyTasksLists[ uxDynamicTopReady ] ) )) { + + ableToSchedule = pdFALSE; + tskTCB * pxRefTCB; + + /* Remember the current list item so that we + can detect if all items have been inspected. + Once this happens, we move on to a lower + priority list (assuming nothing is suitable + for scheduling). Note: This can return NULL if + the list index is at the listItem */ + pxRefTCB = pxReadyTasksLists[ uxDynamicTopReady ].pxIndex->pvOwner; + + if ((void*)pxReadyTasksLists[ uxDynamicTopReady ].pxIndex==(void*)&pxReadyTasksLists[ uxDynamicTopReady ].xListEnd) { + //pxIndex points to the list end marker. Skip that and just get the next item. + listGET_OWNER_OF_NEXT_ENTRY( pxRefTCB, &( pxReadyTasksLists[ uxDynamicTopReady ] ) ); + } + + do { + listGET_OWNER_OF_NEXT_ENTRY( pxTCB, &( pxReadyTasksLists[ uxDynamicTopReady ] ) ); + /* Find out if the next task in the list is + already being executed by another core */ + foundNonExecutingWaiter = pdTRUE; + portBASE_TYPE i = 0; + for ( i=0; ixCoreID == tskNO_AFFINITY) { + pxCurrentTCB[xPortGetCoreID()] = pxTCB; + ableToSchedule = pdTRUE; + } else if (pxTCB->xCoreID == xPortGetCoreID()) { + pxCurrentTCB[xPortGetCoreID()] = pxTCB; + ableToSchedule = pdTRUE; + } else { + ableToSchedule = pdFALSE; + holdTop=pdTRUE; //keep this as the top prio, for the other CPU + } + } else { + ableToSchedule = pdFALSE; + } + + if (ableToSchedule == pdFALSE) { + resetListHead = pdTRUE; + } else if ((ableToSchedule == pdTRUE) && (resetListHead == pdTRUE)) { + tskTCB * pxResetTCB; + do { + listGET_OWNER_OF_NEXT_ENTRY( pxResetTCB, &( pxReadyTasksLists[ uxDynamicTopReady ] ) ); + } while(pxResetTCB != pxRefTCB); + } + } while ((ableToSchedule == pdFALSE) && (pxTCB != pxRefTCB)); + } else { + if (!holdTop) --uxTopReadyPriority; + } + --uxDynamicTopReady; + } + taskEXIT_CRITICAL_ISR(&xTaskQueueMutex); + + /* ToDo: taskSELECT_HIGHEST_PRIORITY_TASK replacement code ends here. */ + + traceTASK_SWITCHED_IN(); + + } + portEXIT_CRITICAL_NESTED(irqstate); +} +/*-----------------------------------------------------------*/ + +void vTaskPlaceOnEventList( List_t * const pxEventList, const TickType_t xTicksToWait ) +{ +TickType_t xTimeToWake; + + configASSERT( pxEventList ); + + taskENTER_CRITICAL(&xTaskQueueMutex); + + /* Place the event list item of the TCB in the appropriate event list. + This is placed in the list in priority order so the highest priority task + is the first to be woken by the event. The queue that contains the event + list is locked, preventing simultaneous access from interrupts. */ + vListInsert( pxEventList, &( pxCurrentTCB[ xPortGetCoreID() ]->xEventListItem ) ); + + /* The task must be removed from from the ready list before it is added to + the blocked list as the same list item is used for both lists. Exclusive + access to the ready lists guaranteed because the scheduler is locked. */ + if( uxListRemove( &( pxCurrentTCB[ xPortGetCoreID() ]->xGenericListItem ) ) == ( UBaseType_t ) 0 ) + { + /* The current task must be in a ready list, so there is no need to + check, and the port reset macro can be called directly. */ + portRESET_READY_PRIORITY( pxCurrentTCB[ xPortGetCoreID() ]->uxPriority, uxTopReadyPriority ); + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + + #if ( INCLUDE_vTaskSuspend == 1 ) + { + if( xTicksToWait == portMAX_DELAY ) + { + /* Add the task to the suspended task list instead of a delayed task + list to ensure the task is not woken by a timing event. It will + block indefinitely. */ + vListInsertEnd( &xSuspendedTaskList, &( pxCurrentTCB[ xPortGetCoreID() ]->xGenericListItem ) ); + } + else + { + /* Calculate the time at which the task should be woken if the event + does not occur. This may overflow but this doesn't matter, the + scheduler will handle it. */ + xTimeToWake = xTickCount + xTicksToWait; + prvAddCurrentTaskToDelayedList( xPortGetCoreID(), xTimeToWake ); + } + } + #else /* INCLUDE_vTaskSuspend */ + { + /* Calculate the time at which the task should be woken if the event does + not occur. This may overflow but this doesn't matter, the scheduler + will handle it. */ + xTimeToWake = xTickCount + xTicksToWait; + prvAddCurrentTaskToDelayedList( xTimeToWake ); + } + #endif /* INCLUDE_vTaskSuspend */ + + taskEXIT_CRITICAL(&xTaskQueueMutex); + +} +/*-----------------------------------------------------------*/ + +void vTaskPlaceOnUnorderedEventList( List_t * pxEventList, const TickType_t xItemValue, const TickType_t xTicksToWait ) +{ +TickType_t xTimeToWake; + + configASSERT( pxEventList ); + + taskENTER_CRITICAL(&xTaskQueueMutex); + + /* THIS FUNCTION MUST BE CALLED WITH THE SCHEDULER SUSPENDED. It is used by + the event groups implementation. */ + configASSERT( uxSchedulerSuspended[ xPortGetCoreID() ] != 0 ); + + /* Store the item value in the event list item. It is safe to access the + event list item here as interrupts won't access the event list item of a + task that is not in the Blocked state. */ + listSET_LIST_ITEM_VALUE( &( pxCurrentTCB[ xPortGetCoreID() ]->xEventListItem ), xItemValue | taskEVENT_LIST_ITEM_VALUE_IN_USE ); + + /* Place the event list item of the TCB at the end of the appropriate event + list. It is safe to access the event list here because it is part of an + event group implementation - and interrupts don't access event groups + directly (instead they access them indirectly by pending function calls to + the task level). */ + vListInsertEnd( pxEventList, &( pxCurrentTCB[ xPortGetCoreID() ]->xEventListItem ) ); + + /* The task must be removed from the ready list before it is added to the + blocked list. Exclusive access can be assured to the ready list as the + scheduler is locked. */ + if( uxListRemove( &( pxCurrentTCB[ xPortGetCoreID() ]->xGenericListItem ) ) == ( UBaseType_t ) 0 ) + { + /* The current task must be in a ready list, so there is no need to + check, and the port reset macro can be called directly. */ + portRESET_READY_PRIORITY( pxCurrentTCB[ xPortGetCoreID() ]->uxPriority, uxTopReadyPriority ); + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + + #if ( INCLUDE_vTaskSuspend == 1 ) + { + if( xTicksToWait == portMAX_DELAY ) + { + /* Add the task to the suspended task list instead of a delayed task + list to ensure it is not woken by a timing event. It will block + indefinitely. */ + vListInsertEnd( &xSuspendedTaskList, &( pxCurrentTCB[ xPortGetCoreID() ]->xGenericListItem ) ); + } + else + { + /* Calculate the time at which the task should be woken if the event + does not occur. This may overflow but this doesn't matter, the + kernel will manage it correctly. */ + xTimeToWake = xTickCount + xTicksToWait; + prvAddCurrentTaskToDelayedList( xPortGetCoreID(), xTimeToWake ); + } + } + #else /* INCLUDE_vTaskSuspend */ + { + /* Calculate the time at which the task should be woken if the event does + not occur. This may overflow but this doesn't matter, the kernel + will manage it correctly. */ + xTimeToWake = xTickCount + xTicksToWait; + prvAddCurrentTaskToDelayedList( xTimeToWake ); + } + #endif /* INCLUDE_vTaskSuspend */ + + taskEXIT_CRITICAL(&xTaskQueueMutex); +} +/*-----------------------------------------------------------*/ + +#if configUSE_TIMERS == 1 + + void vTaskPlaceOnEventListRestricted( List_t * const pxEventList, const TickType_t xTicksToWait ) + { + TickType_t xTimeToWake; + + taskENTER_CRITICAL(&xTaskQueueMutex); + configASSERT( pxEventList ); + + /* This function should not be called by application code hence the + 'Restricted' in its name. It is not part of the public API. It is + designed for use by kernel code, and has special calling requirements - + it should be called from a critical section. */ + + + /* Place the event list item of the TCB in the appropriate event list. + In this case it is assume that this is the only task that is going to + be waiting on this event list, so the faster vListInsertEnd() function + can be used in place of vListInsert. */ + vListInsertEnd( pxEventList, &( pxCurrentTCB[ xPortGetCoreID() ]->xEventListItem ) ); + + /* We must remove this task from the ready list before adding it to the + blocked list as the same list item is used for both lists. This + function is called form a critical section. */ + if( uxListRemove( &( pxCurrentTCB[ xPortGetCoreID() ]->xGenericListItem ) ) == ( UBaseType_t ) 0 ) + { + /* The current task must be in a ready list, so there is no need to + check, and the port reset macro can be called directly. */ + portRESET_READY_PRIORITY( pxCurrentTCB[ xPortGetCoreID() ]->uxPriority, uxTopReadyPriority ); + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + + /* Calculate the time at which the task should be woken if the event does + not occur. This may overflow but this doesn't matter. */ + xTimeToWake = xTickCount + xTicksToWait; + + traceTASK_DELAY_UNTIL(); + prvAddCurrentTaskToDelayedList( xPortGetCoreID(), xTimeToWake ); + taskEXIT_CRITICAL(&xTaskQueueMutex); + + } + +#endif /* configUSE_TIMERS */ +/*-----------------------------------------------------------*/ + +BaseType_t xTaskRemoveFromEventList( const List_t * const pxEventList ) +{ +TCB_t *pxUnblockedTCB; +BaseType_t xReturn; + + /* THIS FUNCTION MUST BE CALLED FROM A CRITICAL SECTION. It can also be + called from a critical section within an ISR. */ +//That makes the taskENTER_CRITICALs here unnecessary, right? -JD +// taskENTER_CRITICAL(&xTaskQueueMutex); + /* The event list is sorted in priority order, so the first in the list can + be removed as it is known to be the highest priority. Remove the TCB from + the delayed list, and add it to the ready list. + + If an event is for a queue that is locked then this function will never + get called - the lock count on the queue will get modified instead. This + means exclusive access to the event list is guaranteed here. + + This function assumes that a check has already been made to ensure that + pxEventList is not empty. */ + pxUnblockedTCB = ( TCB_t * ) listGET_OWNER_OF_HEAD_ENTRY( pxEventList ); + configASSERT( pxUnblockedTCB ); + ( void ) uxListRemove( &( pxUnblockedTCB->xEventListItem ) ); + + if( uxSchedulerSuspended[ xPortGetCoreID() ] == ( UBaseType_t ) pdFALSE ) + { + ( void ) uxListRemove( &( pxUnblockedTCB->xGenericListItem ) ); + prvAddTaskToReadyList( pxUnblockedTCB ); + } + else + { + /* The delayed and ready lists cannot be accessed, so hold this task + pending until the scheduler is resumed. */ + taskENTER_CRITICAL(&xTaskQueueMutex); + vListInsertEnd( &( xPendingReadyList ), &( pxUnblockedTCB->xEventListItem ) ); + taskEXIT_CRITICAL(&xTaskQueueMutex); + } + + if( pxUnblockedTCB->uxPriority > pxCurrentTCB[ xPortGetCoreID() ]->uxPriority ) + { + /* Return true if the task removed from the event list has a higher + priority than the calling task. This allows the calling task to know if + it should force a context switch now. */ + xReturn = pdTRUE; + + /* Mark that a yield is pending in case the user is not using the + "xHigherPriorityTaskWoken" parameter to an ISR safe FreeRTOS function. */ + xYieldPending = pdTRUE; + } + else + { + xReturn = pdFALSE; + } + + #if( configUSE_TICKLESS_IDLE == 1 ) + { + /* If a task is blocked on a kernel object then xNextTaskUnblockTime + might be set to the blocked task's time out time. If the task is + unblocked for a reason other than a timeout xNextTaskUnblockTime is + normally left unchanged, because it is automatically get reset to a new + value when the tick count equals xNextTaskUnblockTime. However if + tickless idling is used it might be more important to enter sleep mode + at the earliest possible time - so reset xNextTaskUnblockTime here to + ensure it is updated at the earliest possible time. */ + prvResetNextTaskUnblockTime(); + } + #endif +// taskEXIT_CRITICAL(&xTaskQueueMutex); + + return xReturn; +} +/*-----------------------------------------------------------*/ + +BaseType_t xTaskRemoveFromUnorderedEventList( ListItem_t * pxEventListItem, const TickType_t xItemValue ) +{ +TCB_t *pxUnblockedTCB; +BaseType_t xReturn; + + taskENTER_CRITICAL(&xTaskQueueMutex); + /* THIS FUNCTION MUST BE CALLED WITH THE SCHEDULER SUSPENDED. It is used by + the event flags implementation. */ + configASSERT( uxSchedulerSuspended[ xPortGetCoreID() ] != pdFALSE ); + + /* Store the new item value in the event list. */ + listSET_LIST_ITEM_VALUE( pxEventListItem, xItemValue | taskEVENT_LIST_ITEM_VALUE_IN_USE ); + + /* Remove the event list form the event flag. Interrupts do not access + event flags. */ + pxUnblockedTCB = ( TCB_t * ) listGET_LIST_ITEM_OWNER( pxEventListItem ); + configASSERT( pxUnblockedTCB ); + ( void ) uxListRemove( pxEventListItem ); + + /* Remove the task from the delayed list and add it to the ready list. The + scheduler is suspended so interrupts will not be accessing the ready + lists. */ + ( void ) uxListRemove( &( pxUnblockedTCB->xGenericListItem ) ); + prvAddTaskToReadyList( pxUnblockedTCB ); + + if( pxUnblockedTCB->uxPriority > pxCurrentTCB[ xPortGetCoreID() ]->uxPriority ) + { + /* Return true if the task removed from the event list has + a higher priority than the calling task. This allows + the calling task to know if it should force a context + switch now. */ + xReturn = pdTRUE; + + /* Mark that a yield is pending in case the user is not using the + "xHigherPriorityTaskWoken" parameter to an ISR safe FreeRTOS function. */ + xYieldPending = pdTRUE; + } + else + { + xReturn = pdFALSE; + } + + taskEXIT_CRITICAL(&xTaskQueueMutex); + return xReturn; +} +/*-----------------------------------------------------------*/ + +void vTaskSetTimeOutState( TimeOut_t * const pxTimeOut ) +{ + configASSERT( pxTimeOut ); + pxTimeOut->xOverflowCount = xNumOfOverflows; + pxTimeOut->xTimeOnEntering = xTickCount; +} +/*-----------------------------------------------------------*/ + +BaseType_t xTaskCheckForTimeOut( TimeOut_t * const pxTimeOut, TickType_t * const pxTicksToWait ) +{ +BaseType_t xReturn; + + configASSERT( pxTimeOut ); + configASSERT( pxTicksToWait ); + + taskENTER_CRITICAL(&xTickCountMutex); + { + /* Minor optimisation. The tick count cannot change in this block. */ + const TickType_t xConstTickCount = xTickCount; + + #if ( INCLUDE_vTaskSuspend == 1 ) + /* If INCLUDE_vTaskSuspend is set to 1 and the block time specified is + the maximum block time then the task should block indefinitely, and + therefore never time out. */ + if( *pxTicksToWait == portMAX_DELAY ) + { + xReturn = pdFALSE; + } + else /* We are not blocking indefinitely, perform the checks below. */ + #endif + + if( ( xNumOfOverflows != pxTimeOut->xOverflowCount ) && ( xConstTickCount >= pxTimeOut->xTimeOnEntering ) ) /*lint !e525 Indentation preferred as is to make code within pre-processor directives clearer. */ + { + /* The tick count is greater than the time at which vTaskSetTimeout() + was called, but has also overflowed since vTaskSetTimeOut() was called. + It must have wrapped all the way around and gone past us again. This + passed since vTaskSetTimeout() was called. */ + xReturn = pdTRUE; + } + else if( ( xConstTickCount - pxTimeOut->xTimeOnEntering ) < *pxTicksToWait ) + { + /* Not a genuine timeout. Adjust parameters for time remaining. */ + *pxTicksToWait -= ( xConstTickCount - pxTimeOut->xTimeOnEntering ); + vTaskSetTimeOutState( pxTimeOut ); + xReturn = pdFALSE; + } + else + { + xReturn = pdTRUE; + } + } + taskEXIT_CRITICAL(&xTickCountMutex); + + return xReturn; +} +/*-----------------------------------------------------------*/ + +void vTaskMissedYield( void ) +{ + xYieldPending = pdTRUE; +} +/*-----------------------------------------------------------*/ + +#if ( configUSE_TRACE_FACILITY == 1 ) + + UBaseType_t uxTaskGetTaskNumber( TaskHandle_t xTask ) + { + UBaseType_t uxReturn; + TCB_t *pxTCB; + + if( xTask != NULL ) + { + pxTCB = ( TCB_t * ) xTask; + uxReturn = pxTCB->uxTaskNumber; + } + else + { + uxReturn = 0U; + } + + return uxReturn; + } + +#endif /* configUSE_TRACE_FACILITY */ +/*-----------------------------------------------------------*/ + +#if ( configUSE_TRACE_FACILITY == 1 ) + + void vTaskSetTaskNumber( TaskHandle_t xTask, const UBaseType_t uxHandle ) + { + TCB_t *pxTCB; + + if( xTask != NULL ) + { + pxTCB = ( TCB_t * ) xTask; + pxTCB->uxTaskNumber = uxHandle; + } + } + +#endif /* configUSE_TRACE_FACILITY */ + +/* + * ----------------------------------------------------------- + * The Idle task. + * ---------------------------------------------------------- + * + * The portTASK_FUNCTION() macro is used to allow port/compiler specific + * language extensions. The equivalent prototype for this function is: + * + * void prvIdleTask( void *pvParameters ); + * + */ +static portTASK_FUNCTION( prvIdleTask, pvParameters ) +{ + /* Stop warnings. */ + ( void ) pvParameters; + + for( ;; ) + { + /* See if any tasks have been deleted. */ + prvCheckTasksWaitingTermination(); + + #if ( configUSE_PREEMPTION == 0 ) + { + /* If we are not using preemption we keep forcing a task switch to + see if any other task has become available. If we are using + preemption we don't need to do this as any task becoming available + will automatically get the processor anyway. */ + taskYIELD(); + } + #endif /* configUSE_PREEMPTION */ + + #if ( ( configUSE_PREEMPTION == 1 ) && ( configIDLE_SHOULD_YIELD == 1 ) ) + { + /* When using preemption tasks of equal priority will be + timesliced. If a task that is sharing the idle priority is ready + to run then the idle task should yield before the end of the + timeslice. + + A critical region is not required here as we are just reading from + the list, and an occasional incorrect value will not matter. If + the ready list at the idle priority contains more than one task + then a task other than the idle task is ready to execute. */ + if( listCURRENT_LIST_LENGTH( &( pxReadyTasksLists[ tskIDLE_PRIORITY ] ) ) > ( UBaseType_t ) 1 ) + { + taskYIELD(); + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } + #endif /* ( ( configUSE_PREEMPTION == 1 ) && ( configIDLE_SHOULD_YIELD == 1 ) ) */ + + #if ( configUSE_IDLE_HOOK == 1 ) + { + extern void vApplicationIdleHook( void ); + + /* Call the user defined function from within the idle task. This + allows the application designer to add background functionality + without the overhead of a separate task. + NOTE: vApplicationIdleHook() MUST NOT, UNDER ANY CIRCUMSTANCES, + CALL A FUNCTION THAT MIGHT BLOCK. */ + vApplicationIdleHook(); + } + #endif /* configUSE_IDLE_HOOK */ + + /* This conditional compilation should use inequality to 0, not equality + to 1. This is to ensure portSUPPRESS_TICKS_AND_SLEEP() is called when + user defined low power mode implementations require + configUSE_TICKLESS_IDLE to be set to a value other than 1. */ + #if ( configUSE_TICKLESS_IDLE != 0 ) + { + TickType_t xExpectedIdleTime; + + /* It is not desirable to suspend then resume the scheduler on + each iteration of the idle task. Therefore, a preliminary + test of the expected idle time is performed without the + scheduler suspended. The result here is not necessarily + valid. */ + xExpectedIdleTime = prvGetExpectedIdleTime(); + + if( xExpectedIdleTime >= configEXPECTED_IDLE_TIME_BEFORE_SLEEP ) + { +// vTaskSuspendAll(); + taskENTER_CRITICAL(&xTaskQueueMutex); + { + /* Now the scheduler is suspended, the expected idle + time can be sampled again, and this time its value can + be used. */ + configASSERT( xNextTaskUnblockTime >= xTickCount ); + xExpectedIdleTime = prvGetExpectedIdleTime(); + + if( xExpectedIdleTime >= configEXPECTED_IDLE_TIME_BEFORE_SLEEP ) + { + traceLOW_POWER_IDLE_BEGIN(); + portSUPPRESS_TICKS_AND_SLEEP( xExpectedIdleTime ); + traceLOW_POWER_IDLE_END(); + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } + taskEXIT_CRITICAL(&xTaskQueueMutex); +// ( void ) xTaskResumeAll(); + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } + #endif /* configUSE_TICKLESS_IDLE */ + } +} +/*-----------------------------------------------------------*/ + +#if configUSE_TICKLESS_IDLE != 0 + + eSleepModeStatus eTaskConfirmSleepModeStatus( void ) + { + eSleepModeStatus eReturn = eStandardSleep; + taskENTER_CRITICAL(&xTaskQueueMutex); + + if( listCURRENT_LIST_LENGTH( &xPendingReadyList ) != 0 ) + { + /* A task was made ready while the scheduler was suspended. */ + eReturn = eAbortSleep; + } + else if( xYieldPending != pdFALSE ) + { + /* A yield was pended while the scheduler was suspended. */ + eReturn = eAbortSleep; + } + else + { + #if configUSE_TIMERS == 0 + { + /* The idle task exists in addition to the application tasks. */ + const UBaseType_t uxNonApplicationTasks = 1; + + /* If timers are not being used and all the tasks are in the + suspended list (which might mean they have an infinite block + time rather than actually being suspended) then it is safe to + turn all clocks off and just wait for external interrupts. */ + if( listCURRENT_LIST_LENGTH( &xSuspendedTaskList ) == ( uxCurrentNumberOfTasks - uxNonApplicationTasks ) ) + { + eReturn = eNoTasksWaitingTimeout; + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } + #endif /* configUSE_TIMERS */ + } + taskEXIT_CRITICAL(&xTaskQueueMutex); + + return eReturn; + } +#endif /* configUSE_TICKLESS_IDLE */ +/*-----------------------------------------------------------*/ + +static void prvInitialiseTCBVariables( TCB_t * const pxTCB, const char * const pcName, UBaseType_t uxPriority, const MemoryRegion_t * const xRegions, const uint16_t usStackDepth, const BaseType_t xCoreID ) /*lint !e971 Unqualified char types are allowed for strings and single characters only. */ +{ +UBaseType_t x; + + /* Store the task name in the TCB. */ + for( x = ( UBaseType_t ) 0; x < ( UBaseType_t ) configMAX_TASK_NAME_LEN; x++ ) + { + pxTCB->pcTaskName[ x ] = pcName[ x ]; + + /* Don't copy all configMAX_TASK_NAME_LEN if the string is shorter than + configMAX_TASK_NAME_LEN characters just in case the memory after the + string is not accessible (extremely unlikely). */ + if( pcName[ x ] == 0x00 ) + { + break; + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } + + /* Ensure the name string is terminated in the case that the string length + was greater or equal to configMAX_TASK_NAME_LEN. */ + pxTCB->pcTaskName[ configMAX_TASK_NAME_LEN - 1 ] = '\0'; + + /* This is used as an array index so must ensure it's not too large. First + remove the privilege bit if one is present. */ + if( uxPriority >= ( UBaseType_t ) configMAX_PRIORITIES ) + { + uxPriority = ( UBaseType_t ) configMAX_PRIORITIES - ( UBaseType_t ) 1U; + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + + pxTCB->uxPriority = uxPriority; + pxTCB->xCoreID = xCoreID; + #if ( configUSE_MUTEXES == 1 ) + { + pxTCB->uxBasePriority = uxPriority; + pxTCB->uxMutexesHeld = 0; + } + #endif /* configUSE_MUTEXES */ + + vListInitialiseItem( &( pxTCB->xGenericListItem ) ); + vListInitialiseItem( &( pxTCB->xEventListItem ) ); + + /* Set the pxTCB as a link back from the ListItem_t. This is so we can get + back to the containing TCB from a generic item in a list. */ + listSET_LIST_ITEM_OWNER( &( pxTCB->xGenericListItem ), pxTCB ); + + /* Event lists are always in priority order. */ + listSET_LIST_ITEM_VALUE( &( pxTCB->xEventListItem ), ( TickType_t ) configMAX_PRIORITIES - ( TickType_t ) uxPriority ); /*lint !e961 MISRA exception as the casts are only redundant for some ports. */ + listSET_LIST_ITEM_OWNER( &( pxTCB->xEventListItem ), pxTCB ); + + #if ( portCRITICAL_NESTING_IN_TCB == 1 ) + { + pxTCB->uxCriticalNesting = ( UBaseType_t ) 0U; + } + #endif /* portCRITICAL_NESTING_IN_TCB */ + + #if ( configUSE_APPLICATION_TASK_TAG == 1 ) + { + pxTCB->pxTaskTag = NULL; + } + #endif /* configUSE_APPLICATION_TASK_TAG */ + + #if ( configGENERATE_RUN_TIME_STATS == 1 ) + { + pxTCB->ulRunTimeCounter = 0UL; + } + #endif /* configGENERATE_RUN_TIME_STATS */ + + #if ( portUSING_MPU_WRAPPERS == 1 ) + { + vPortStoreTaskMPUSettings( &( pxTCB->xMPUSettings ), xRegions, pxTCB->pxStack, usStackDepth ); + } + #else /* portUSING_MPU_WRAPPERS */ + { + ( void ) xRegions; + ( void ) usStackDepth; + } + #endif /* portUSING_MPU_WRAPPERS */ + + #if( configNUM_THREAD_LOCAL_STORAGE_POINTERS != 0 ) + { + for( x = 0; x < ( UBaseType_t ) configNUM_THREAD_LOCAL_STORAGE_POINTERS; x++ ) + { + pxNewTCB->pvThreadLocalStoragePointers[ x ] = NULL; + } + } + #endif + + + #if ( configUSE_TASK_NOTIFICATIONS == 1 ) + { + pxTCB->ulNotifiedValue = 0; + pxTCB->eNotifyState = eNotWaitingNotification; + } + #endif + + #if ( configUSE_NEWLIB_REENTRANT == 1 ) + { + /* Initialise this task's Newlib reent structure. */ + _REENT_INIT_PTR( ( &( pxTCB->xNewLib_reent ) ) ); + } + #endif /* configUSE_NEWLIB_REENTRANT */ +} +/*-----------------------------------------------------------*/ +#if ( configNUM_THREAD_LOCAL_STORAGE_POINTERS != 0 ) + + void vTaskSetThreadLocalStoragePointer( TaskHandle_t xTaskToSet, BaseType_t xIndex, void *pvValue ) + { + TCB_t *pxTCB; + + if( xIndex < configNUM_THREAD_LOCAL_STORAGE_POINTERS ) + { + pxTCB = prvGetTCBFromHandle( xTaskToSet ); + pxTCB->pvThreadLocalStoragePointers[ xIndex ] = pvValue; + } + } + +#endif /* configNUM_THREAD_LOCAL_STORAGE_POINTERS */ +/*-----------------------------------------------------------*/ + +#if ( configNUM_THREAD_LOCAL_STORAGE_POINTERS != 0 ) + + void *pvTaskGetThreadLocalStoragePointer( TaskHandle_t xTaskToQuery, BaseType_t xIndex ) + { + void *pvReturn = NULL; + TCB_t *pxTCB; + + if( xIndex < configNUM_THREAD_LOCAL_STORAGE_POINTERS ) + { + pxTCB = prvGetTCBFromHandle( xTaskToQuery ); + pvReturn = pxTCB->pvThreadLocalStoragePointers[ xIndex ]; + } + else + { + pvReturn = NULL; + } + + return pvReturn; + } + +#endif /* configNUM_THREAD_LOCAL_STORAGE_POINTERS */ + + +#if ( portUSING_MPU_WRAPPERS == 1 ) +/* ToDo: Check for multicore */ + void vTaskAllocateMPURegions( TaskHandle_t xTaskToModify, const MemoryRegion_t * const xRegions ) + { + TCB_t *pxTCB; + + ets_printf("ToDo %s\n", __FUNCTION__); + /* If null is passed in here then we are deleting ourselves. */ + pxTCB = prvGetTCBFromHandle( xTaskToModify ); + + vPortStoreTaskMPUSettings( &( pxTCB->xMPUSettings ), xRegions, NULL, 0 ); + } + +#endif /* portUSING_MPU_WRAPPERS */ +/*-----------------------------------------------------------*/ + +static void prvInitialiseTaskLists( void ) +{ +UBaseType_t uxPriority; + + for( uxPriority = ( UBaseType_t ) 0U; uxPriority < ( UBaseType_t ) configMAX_PRIORITIES; uxPriority++ ) + { + vListInitialise( &( pxReadyTasksLists[ uxPriority ] ) ); + } + + vListInitialise( &xDelayedTaskList1 ); + vListInitialise( &xDelayedTaskList2 ); + vListInitialise( &xPendingReadyList ); + + #if ( INCLUDE_vTaskDelete == 1 ) + { + vListInitialise( &xTasksWaitingTermination ); + } + #endif /* INCLUDE_vTaskDelete */ + + #if ( INCLUDE_vTaskSuspend == 1 ) + { + vListInitialise( &xSuspendedTaskList ); + } + #endif /* INCLUDE_vTaskSuspend */ + + /* Start with pxDelayedTaskList using list1 and the pxOverflowDelayedTaskList + using list2. */ + pxDelayedTaskList = &xDelayedTaskList1; + pxOverflowDelayedTaskList = &xDelayedTaskList2; +} +/*-----------------------------------------------------------*/ + +static void prvCheckTasksWaitingTermination( void ) +{ + #if ( INCLUDE_vTaskDelete == 1 ) + { + BaseType_t xListIsEmpty; + + /* ucTasksDeleted is used to prevent vTaskSuspendAll() being called + too often in the idle task. */ + while( uxTasksDeleted > ( UBaseType_t ) 0U ) + { + taskENTER_CRITICAL(&xTaskQueueMutex); + { + xListIsEmpty = listLIST_IS_EMPTY( &xTasksWaitingTermination ); + } + taskEXIT_CRITICAL(&xTaskQueueMutex); + + if( xListIsEmpty == pdFALSE ) + { + TCB_t *pxTCB; + + taskENTER_CRITICAL(&xTaskQueueMutex); + { + pxTCB = ( TCB_t * ) listGET_OWNER_OF_HEAD_ENTRY( ( &xTasksWaitingTermination ) ); + ( void ) uxListRemove( &( pxTCB->xGenericListItem ) ); + --uxCurrentNumberOfTasks; + --uxTasksDeleted; + } + taskEXIT_CRITICAL(&xTaskQueueMutex); + + prvDeleteTCB( pxTCB ); + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } + } + #endif /* vTaskDelete */ +} +/*-----------------------------------------------------------*/ + +//This should be called with the taskqueuemutex grabbed. -JD +static void prvAddCurrentTaskToDelayedList( const BaseType_t xCoreID, const TickType_t xTimeToWake ) +{ + /* The list item will be inserted in wake time order. */ + listSET_LIST_ITEM_VALUE( &( pxCurrentTCB[ xCoreID ]->xGenericListItem ), xTimeToWake ); + + if( xTimeToWake < xTickCount ) + { + /* Wake time has overflowed. Place this item in the overflow list. */ + vListInsert( pxOverflowDelayedTaskList, &( pxCurrentTCB[ xCoreID ]->xGenericListItem ) ); + } + else + { + /* The wake time has not overflowed, so the current block list is used. */ + vListInsert( pxDelayedTaskList, &( pxCurrentTCB[ xCoreID ]->xGenericListItem ) ); + + /* If the task entering the blocked state was placed at the head of the + list of blocked tasks then xNextTaskUnblockTime needs to be updated + too. */ + if( xTimeToWake < xNextTaskUnblockTime ) + { + xNextTaskUnblockTime = xTimeToWake; + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } +} +/*-----------------------------------------------------------*/ + +static TCB_t *prvAllocateTCBAndStack( const uint16_t usStackDepth, StackType_t * const puxStackBuffer ) +{ +TCB_t *pxNewTCB; + + /* If the stack grows down then allocate the stack then the TCB so the stack + does not grow into the TCB. Likewise if the stack grows up then allocate + the TCB then the stack. */ + #if( portSTACK_GROWTH > 0 ) + { + /* Allocate space for the TCB. Where the memory comes from depends on + the implementation of the port malloc function. */ + pxNewTCB = ( TCB_t * ) pvPortMalloc( sizeof( TCB_t ) ); + + if( pxNewTCB != NULL ) + { + /* Allocate space for the stack used by the task being created. + The base of the stack memory stored in the TCB so the task can + be deleted later if required. */ + pxNewTCB->pxStack = ( StackType_t * ) pvPortMallocAligned( ( ( ( size_t ) usStackDepth ) * sizeof( StackType_t ) ), puxStackBuffer ); /*lint !e961 MISRA exception as the casts are only redundant for some ports. */ + + if( pxNewTCB->pxStack == NULL ) + { + /* Could not allocate the stack. Delete the allocated TCB. */ + vPortFree( pxNewTCB ); + pxNewTCB = NULL; + } + } + } + #else /* portSTACK_GROWTH */ + { + StackType_t *pxStack; + + /* Allocate space for the stack used by the task being created. */ + pxStack = ( StackType_t * ) pvPortMallocAligned( ( ( ( size_t ) usStackDepth ) * sizeof( StackType_t ) ), puxStackBuffer ); /*lint !e961 MISRA exception as the casts are only redundant for some ports. */ + + if( pxStack != NULL ) + { + /* Allocate space for the TCB. Where the memory comes from depends + on the implementation of the port malloc function. */ + pxNewTCB = ( TCB_t * ) pvPortMalloc( sizeof( TCB_t ) ); + + if( pxNewTCB != NULL ) + { + /* Store the stack location in the TCB. */ + pxNewTCB->pxStack = pxStack; + } + else + { + /* The stack cannot be used as the TCB was not created. Free it + again. */ + vPortFree( pxStack ); + } + } + else + { + pxNewTCB = NULL; + } + } + #endif /* portSTACK_GROWTH */ + + if( pxNewTCB != NULL ) + { + /* Avoid dependency on memset() if it is not required. */ + #if( ( configCHECK_FOR_STACK_OVERFLOW > 1 ) || ( configUSE_TRACE_FACILITY == 1 ) || ( INCLUDE_uxTaskGetStackHighWaterMark == 1 ) ) + { + /* Just to help debugging. */ + ( void ) memset( pxNewTCB->pxStack, ( int ) tskSTACK_FILL_BYTE, ( size_t ) usStackDepth * sizeof( StackType_t ) ); + } + #endif /* ( ( configCHECK_FOR_STACK_OVERFLOW > 1 ) || ( ( configUSE_TRACE_FACILITY == 1 ) || ( INCLUDE_uxTaskGetStackHighWaterMark == 1 ) ) ) */ + } + + return pxNewTCB; +} +/*-----------------------------------------------------------*/ + +#if ( configUSE_TRACE_FACILITY == 1 ) + + static UBaseType_t prvListTaskWithinSingleList( TaskStatus_t *pxTaskStatusArray, List_t *pxList, eTaskState eState ) + { + volatile TCB_t *pxNextTCB, *pxFirstTCB; + UBaseType_t uxTask = 0; + + if( listCURRENT_LIST_LENGTH( pxList ) > ( UBaseType_t ) 0 ) + { + listGET_OWNER_OF_NEXT_ENTRY( pxFirstTCB, pxList ); + + /* Populate an TaskStatus_t structure within the + pxTaskStatusArray array for each task that is referenced from + pxList. See the definition of TaskStatus_t in task.h for the + meaning of each TaskStatus_t structure member. */ + do + { + listGET_OWNER_OF_NEXT_ENTRY( pxNextTCB, pxList ); + + pxTaskStatusArray[ uxTask ].xHandle = ( TaskHandle_t ) pxNextTCB; + pxTaskStatusArray[ uxTask ].pcTaskName = ( const char * ) &( pxNextTCB->pcTaskName [ 0 ] ); + pxTaskStatusArray[ uxTask ].xTaskNumber = pxNextTCB->uxTCBNumber; + pxTaskStatusArray[ uxTask ].eCurrentState = eState; + pxTaskStatusArray[ uxTask ].uxCurrentPriority = pxNextTCB->uxPriority; + + #if ( INCLUDE_vTaskSuspend == 1 ) + { + /* If the task is in the suspended list then there is a chance + it is actually just blocked indefinitely - so really it should + be reported as being in the Blocked state. */ + if( eState == eSuspended ) + { + if( listLIST_ITEM_CONTAINER( &( pxNextTCB->xEventListItem ) ) != NULL ) + { + pxTaskStatusArray[ uxTask ].eCurrentState = eBlocked; + } + } + } + #endif /* INCLUDE_vTaskSuspend */ + + #if ( configUSE_MUTEXES == 1 ) + { + pxTaskStatusArray[ uxTask ].uxBasePriority = pxNextTCB->uxBasePriority; + } + #else + { + pxTaskStatusArray[ uxTask ].uxBasePriority = 0; + } + #endif + + #if ( configGENERATE_RUN_TIME_STATS == 1 ) + { + pxTaskStatusArray[ uxTask ].ulRunTimeCounter = pxNextTCB->ulRunTimeCounter; + } + #else + { + pxTaskStatusArray[ uxTask ].ulRunTimeCounter = 0; + } + #endif + + #if ( portSTACK_GROWTH > 0 ) + { + pxTaskStatusArray[ uxTask ].usStackHighWaterMark = prvTaskCheckFreeStackSpace( ( uint8_t * ) pxNextTCB->pxEndOfStack ); + } + #else + { + pxTaskStatusArray[ uxTask ].usStackHighWaterMark = prvTaskCheckFreeStackSpace( ( uint8_t * ) pxNextTCB->pxStack ); + } + #endif + + uxTask++; + + } while( pxNextTCB != pxFirstTCB ); + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + + return uxTask; + } + +#endif /* configUSE_TRACE_FACILITY */ +/*-----------------------------------------------------------*/ + +#if ( ( configUSE_TRACE_FACILITY == 1 ) || ( INCLUDE_uxTaskGetStackHighWaterMark == 1 ) ) + + static uint16_t prvTaskCheckFreeStackSpace( const uint8_t * pucStackByte ) + { + uint32_t ulCount = 0U; + + while( *pucStackByte == ( uint8_t ) tskSTACK_FILL_BYTE ) + { + pucStackByte -= portSTACK_GROWTH; + ulCount++; + } + + ulCount /= ( uint32_t ) sizeof( StackType_t ); /*lint !e961 Casting is not redundant on smaller architectures. */ + + return ( uint16_t ) ulCount; + } + +#endif /* ( ( configUSE_TRACE_FACILITY == 1 ) || ( INCLUDE_uxTaskGetStackHighWaterMark == 1 ) ) */ +/*-----------------------------------------------------------*/ + +#if ( INCLUDE_uxTaskGetStackHighWaterMark == 1 ) + + UBaseType_t uxTaskGetStackHighWaterMark( TaskHandle_t xTask ) + { + TCB_t *pxTCB; + uint8_t *pucEndOfStack; + UBaseType_t uxReturn; + + pxTCB = prvGetTCBFromHandle( xTask ); + + #if portSTACK_GROWTH < 0 + { + pucEndOfStack = ( uint8_t * ) pxTCB->pxStack; + } + #else + { + pucEndOfStack = ( uint8_t * ) pxTCB->pxEndOfStack; + } + #endif + + uxReturn = ( UBaseType_t ) prvTaskCheckFreeStackSpace( pucEndOfStack ); + + return uxReturn; + } + +#endif /* INCLUDE_uxTaskGetStackHighWaterMark */ +/*-----------------------------------------------------------*/ + +#if ( INCLUDE_vTaskDelete == 1 ) + + static void prvDeleteTCB( TCB_t *pxTCB ) + { + /* This call is required specifically for the TriCore port. It must be + above the vPortFree() calls. The call is also used by ports/demos that + want to allocate and clean RAM statically. */ + portCLEAN_UP_TCB( pxTCB ); + + /* Free up the memory allocated by the scheduler for the task. It is up + to the task to free any memory allocated at the application level. */ + #if ( configUSE_NEWLIB_REENTRANT == 1 ) + { + _reclaim_reent( &( pxTCB->xNewLib_reent ) ); + } + #endif /* configUSE_NEWLIB_REENTRANT */ + + #if( portUSING_MPU_WRAPPERS == 1 ) + { + /* Only free the stack if it was allocated dynamically in the first + place. */ + if( pxTCB->xUsingStaticallyAllocatedStack == pdFALSE ) + { + vPortFreeAligned( pxTCB->pxStack ); + } + } + #else + { + vPortFreeAligned( pxTCB->pxStack ); + } + #endif + + vPortFree( pxTCB ); + } + +#endif /* INCLUDE_vTaskDelete */ +/*-----------------------------------------------------------*/ + +static void prvResetNextTaskUnblockTime( void ) +{ +TCB_t *pxTCB; + + if( listLIST_IS_EMPTY( pxDelayedTaskList ) != pdFALSE ) + { + /* The new current delayed list is empty. Set + xNextTaskUnblockTime to the maximum possible value so it is + extremely unlikely that the + if( xTickCount >= xNextTaskUnblockTime ) test will pass until + there is an item in the delayed list. */ + xNextTaskUnblockTime = portMAX_DELAY; + } + else + { + /* The new current delayed list is not empty, get the value of + the item at the head of the delayed list. This is the time at + which the task at the head of the delayed list should be removed + from the Blocked state. */ + ( pxTCB ) = ( TCB_t * ) listGET_OWNER_OF_HEAD_ENTRY( pxDelayedTaskList ); + xNextTaskUnblockTime = listGET_LIST_ITEM_VALUE( &( ( pxTCB )->xGenericListItem ) ); + } +} +/*-----------------------------------------------------------*/ + +#if ( ( INCLUDE_xTaskGetCurrentTaskHandle == 1 ) || ( configUSE_MUTEXES == 1 ) ) + + TaskHandle_t xTaskGetCurrentTaskHandle( void ) + { + TaskHandle_t xReturn; + + /* A critical section is not required as this is not called from + an interrupt and the current TCB will always be the same for any + individual execution thread. */ + xReturn = pxCurrentTCB[ xPortGetCoreID() ]; + + return xReturn; + } + +#endif /* ( ( INCLUDE_xTaskGetCurrentTaskHandle == 1 ) || ( configUSE_MUTEXES == 1 ) ) */ +/*-----------------------------------------------------------*/ + +#if ( ( INCLUDE_xTaskGetSchedulerState == 1 ) || ( configUSE_TIMERS == 1 ) ) + + BaseType_t xTaskGetSchedulerState( void ) + { + BaseType_t xReturn; + + if( xSchedulerRunning == pdFALSE ) + { + xReturn = taskSCHEDULER_NOT_STARTED; + } + else + { + if( uxSchedulerSuspended[ xPortGetCoreID() ] == ( UBaseType_t ) pdFALSE ) + { + xReturn = taskSCHEDULER_RUNNING; + } + else + { + xReturn = taskSCHEDULER_SUSPENDED; + } + } + + return xReturn; + } + +#endif /* ( ( INCLUDE_xTaskGetSchedulerState == 1 ) || ( configUSE_TIMERS == 1 ) ) */ +/*-----------------------------------------------------------*/ + +/* +ToDo: Mutexes haven't been tested or adapted to multicore at all. + +In fact, nothing below this line has/is. +*/ + +#if ( configUSE_MUTEXES == 1 ) + + void vTaskPriorityInherit( TaskHandle_t const pxMutexHolder ) + { + TCB_t * const pxTCB = ( TCB_t * ) pxMutexHolder; + + taskENTER_CRITICAL(&xTickCountMutex); + /* If the mutex was given back by an interrupt while the queue was + locked then the mutex holder might now be NULL. */ + if( pxMutexHolder != NULL ) + { + if( pxTCB->uxPriority < pxCurrentTCB[ xPortGetCoreID() ]->uxPriority ) + { + /* Adjust the mutex holder state to account for its new + priority. Only reset the event list item value if the value is + not being used for anything else. */ + if( ( listGET_LIST_ITEM_VALUE( &( pxTCB->xEventListItem ) ) & taskEVENT_LIST_ITEM_VALUE_IN_USE ) == 0UL ) + { + listSET_LIST_ITEM_VALUE( &( pxTCB->xEventListItem ), ( TickType_t ) configMAX_PRIORITIES - ( TickType_t ) pxCurrentTCB[ xPortGetCoreID() ]->uxPriority ); /*lint !e961 MISRA exception as the casts are only redundant for some ports. */ + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + + /* If the task being modified is in the ready state it will need to + be moved into a new list. */ + if( listIS_CONTAINED_WITHIN( &( pxReadyTasksLists[ pxTCB->uxPriority ] ), &( pxTCB->xGenericListItem ) ) != pdFALSE ) + { + if( uxListRemove( &( pxTCB->xGenericListItem ) ) == ( UBaseType_t ) 0 ) + { + taskRESET_READY_PRIORITY( pxTCB->uxPriority ); + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + + /* Inherit the priority before being moved into the new list. */ + pxTCB->uxPriority = pxCurrentTCB[ xPortGetCoreID() ]->uxPriority; + prvAddTaskToReadyList( pxTCB ); + } + else + { + /* Just inherit the priority. */ + pxTCB->uxPriority = pxCurrentTCB[ xPortGetCoreID() ]->uxPriority; + } + + traceTASK_PRIORITY_INHERIT( pxTCB, pxCurrentTCB[ xPortGetCoreID() ]->uxPriority ); + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + + taskEXIT_CRITICAL(&xTickCountMutex); + + } + +#endif /* configUSE_MUTEXES */ +/*-----------------------------------------------------------*/ + +#if ( configUSE_MUTEXES == 1 ) + + BaseType_t xTaskPriorityDisinherit( TaskHandle_t const pxMutexHolder ) + { + TCB_t * const pxTCB = ( TCB_t * ) pxMutexHolder; + BaseType_t xReturn = pdFALSE; + taskENTER_CRITICAL(&xTickCountMutex); + + if( pxMutexHolder != NULL ) + { + configASSERT( pxTCB->uxMutexesHeld ); + ( pxTCB->uxMutexesHeld )--; + + if( pxTCB->uxPriority != pxTCB->uxBasePriority ) + { + /* Only disinherit if no other mutexes are held. */ + if( pxTCB->uxMutexesHeld == ( UBaseType_t ) 0 ) + { + /* A task can only have an inhertied priority if it holds + the mutex. If the mutex is held by a task then it cannot be + given from an interrupt, and if a mutex is given by the + holding task then it must be the running state task. Remove + the holding task from the ready list. */ + if( uxListRemove( &( pxTCB->xGenericListItem ) ) == ( UBaseType_t ) 0 ) + { + taskRESET_READY_PRIORITY( pxTCB->uxPriority ); + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + + /* Disinherit the priority before adding the task into the + new ready list. */ + traceTASK_PRIORITY_DISINHERIT( pxTCB, pxTCB->uxBasePriority ); + pxTCB->uxPriority = pxTCB->uxBasePriority; + + /* Reset the event list item value. It cannot be in use for + any other purpose if this task is running, and it must be + running to give back the mutex. */ + listSET_LIST_ITEM_VALUE( &( pxTCB->xEventListItem ), ( TickType_t ) configMAX_PRIORITIES - ( TickType_t ) pxTCB->uxPriority ); /*lint !e961 MISRA exception as the casts are only redundant for some ports. */ + prvAddTaskToReadyList( pxTCB ); + + /* Return true to indicate that a context switch is required. + This is only actually required in the corner case whereby + multiple mutexes were held and the mutexes were given back + in an order different to that in which they were taken. + If a context switch did not occur when the first mutex was + returned, even if a task was waiting on it, then a context + switch should occur when the last mutex is returned whether + a task is waiting on it or not. */ + xReturn = pdTRUE; + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + + taskEXIT_CRITICAL(&xTickCountMutex); + return xReturn; + } + +#endif /* configUSE_MUTEXES */ +/*-----------------------------------------------------------*/ + +/* For multicore, this assumes the vPortCPUAquireMutex is recursive, that is, it can be called multiple + times and the release call will have to be called as many times for the mux to unlock. */ + +/* Gotcha (which seems to be deliberate in FreeRTOS, according to +http://www.freertos.org/FreeRTOS_Support_Forum_Archive/December_2012/freertos_PIC32_Bug_-_vTaskEnterCritical_6400806.html +) is that calling vTaskEnterCritical followed by vTaskExitCritical will leave the interrupts DISABLED! Re-enabling the +scheduler will re-enable the interrupts instead. */ + + +#if ( portCRITICAL_NESTING_IN_TCB == 1 ) + + +#ifdef portMUX_DEBUG + void vTaskEnterCritical( portMUX_TYPE *mux, const char *function, int line ) +#else + void vTaskEnterCritical( portMUX_TYPE *mux ) +#endif + { + portDISABLE_INTERRUPTS(); +#ifdef portMUX_DEBUG + vPortCPUAcquireMutex( mux, function, line ); +#else + vPortCPUAcquireMutex( mux ); +#endif + + if( xSchedulerRunning != pdFALSE ) + { + ( pxCurrentTCB[ xPortGetCoreID() ]->uxCriticalNesting )++; + + /* This is not the interrupt safe version of the enter critical + function so assert() if it is being called from an interrupt + context. Only API functions that end in "FromISR" can be used in an + interrupt. Only assert if the critical nesting count is 1 to + protect against recursive calls if the assert function also uses a + critical section. */ + if( pxCurrentTCB[ xPortGetCoreID() ]->uxCriticalNesting == 1 ) + { + portASSERT_IF_IN_ISR(); + } + + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } + +#endif /* portCRITICAL_NESTING_IN_TCB */ +/*-----------------------------------------------------------*/ + +#if ( portCRITICAL_NESTING_IN_TCB == 1 ) + +#ifdef portMUX_DEBUG + void vTaskExitCritical( portMUX_TYPE *mux, const char *function, int line ) +#else + void vTaskExitCritical( portMUX_TYPE *mux ) +#endif + { +#ifdef portMUX_DEBUG + vPortCPUReleaseMutex( mux, function, line ); +#else + vPortCPUReleaseMutex( mux ); +#endif + if( xSchedulerRunning != pdFALSE ) + { + if( pxCurrentTCB[ xPortGetCoreID() ]->uxCriticalNesting > 0U ) + { + ( pxCurrentTCB[ xPortGetCoreID() ]->uxCriticalNesting )--; + + if( pxCurrentTCB[ xPortGetCoreID() ]->uxCriticalNesting == 0U ) + { + portENABLE_INTERRUPTS(); + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } + +#endif /* portCRITICAL_NESTING_IN_TCB */ +/*-----------------------------------------------------------*/ + +#if ( ( configUSE_TRACE_FACILITY == 1 ) && ( configUSE_STATS_FORMATTING_FUNCTIONS > 0 ) ) + + static char *prvWriteNameToBuffer( char *pcBuffer, const char *pcTaskName ) + { + BaseType_t x; + + /* Start by copying the entire string. */ + strcpy( pcBuffer, pcTaskName ); + + /* Pad the end of the string with spaces to ensure columns line up when + printed out. */ + for( x = strlen( pcBuffer ); x < ( configMAX_TASK_NAME_LEN - 1 ); x++ ) + { + pcBuffer[ x ] = ' '; + } + + /* Terminate. */ + pcBuffer[ x ] = 0x00; + + /* Return the new end of string. */ + return &( pcBuffer[ x ] ); + } + +#endif /* ( configUSE_TRACE_FACILITY == 1 ) && ( configUSE_STATS_FORMATTING_FUNCTIONS > 0 ) */ +/*-----------------------------------------------------------*/ + +#if ( ( configUSE_TRACE_FACILITY == 1 ) && ( configUSE_STATS_FORMATTING_FUNCTIONS > 0 ) ) + + void vTaskList( char * pcWriteBuffer ) + { + TaskStatus_t *pxTaskStatusArray; + volatile UBaseType_t uxArraySize, x; + char cStatus; + + /* + * PLEASE NOTE: + * + * This function is provided for convenience only, and is used by many + * of the demo applications. Do not consider it to be part of the + * scheduler. + * + * vTaskList() calls uxTaskGetSystemState(), then formats part of the + * uxTaskGetSystemState() output into a human readable table that + * displays task names, states and stack usage. + * + * vTaskList() has a dependency on the sprintf() C library function that + * might bloat the code size, use a lot of stack, and provide different + * results on different platforms. An alternative, tiny, third party, + * and limited functionality implementation of sprintf() is provided in + * many of the FreeRTOS/Demo sub-directories in a file called + * printf-stdarg.c (note printf-stdarg.c does not provide a full + * snprintf() implementation!). + * + * It is recommended that production systems call uxTaskGetSystemState() + * directly to get access to raw stats data, rather than indirectly + * through a call to vTaskList(). + */ + + + /* Make sure the write buffer does not contain a string. */ + *pcWriteBuffer = 0x00; + + /* Take a snapshot of the number of tasks in case it changes while this + function is executing. */ + uxArraySize = uxCurrentNumberOfTasks; + + /* Allocate an array index for each task. */ + pxTaskStatusArray = pvPortMalloc( uxCurrentNumberOfTasks * sizeof( TaskStatus_t ) ); + + if( pxTaskStatusArray != NULL ) + { + /* Generate the (binary) data. */ + uxArraySize = uxTaskGetSystemState( pxTaskStatusArray, uxArraySize, NULL ); + + /* Create a human readable table from the binary data. */ + for( x = 0; x < uxArraySize; x++ ) + { + switch( pxTaskStatusArray[ x ].eCurrentState ) + { + case eReady: cStatus = tskREADY_CHAR; + break; + + case eBlocked: cStatus = tskBLOCKED_CHAR; + break; + + case eSuspended: cStatus = tskSUSPENDED_CHAR; + break; + + case eDeleted: cStatus = tskDELETED_CHAR; + break; + + default: /* Should not get here, but it is included + to prevent static checking errors. */ + cStatus = 0x00; + break; + } + + /* Write the task name to the string, padding with spaces so it + can be printed in tabular form more easily. */ + pcWriteBuffer = prvWriteNameToBuffer( pcWriteBuffer, pxTaskStatusArray[ x ].pcTaskName ); + + /* Write the rest of the string. */ + sprintf( pcWriteBuffer, "\t%c\t%u\t%u\t%u\r\n", cStatus, ( unsigned int ) pxTaskStatusArray[ x ].uxCurrentPriority, ( unsigned int ) pxTaskStatusArray[ x ].usStackHighWaterMark, ( unsigned int ) pxTaskStatusArray[ x ].xTaskNumber ); + pcWriteBuffer += strlen( pcWriteBuffer ); + } + + /* Free the array again. */ + vPortFree( pxTaskStatusArray ); + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } + +#endif /* ( ( configUSE_TRACE_FACILITY == 1 ) && ( configUSE_STATS_FORMATTING_FUNCTIONS > 0 ) ) */ +/*----------------------------------------------------------*/ + +#if ( ( configGENERATE_RUN_TIME_STATS == 1 ) && ( configUSE_STATS_FORMATTING_FUNCTIONS > 0 ) ) + + void vTaskGetRunTimeStats( char *pcWriteBuffer ) + { + TaskStatus_t *pxTaskStatusArray; + volatile UBaseType_t uxArraySize, x; + uint32_t ulTotalTime, ulStatsAsPercentage; + + #if( configUSE_TRACE_FACILITY != 1 ) + { + #error configUSE_TRACE_FACILITY must also be set to 1 in FreeRTOSConfig.h to use vTaskGetRunTimeStats(). + } + #endif + + /* + * PLEASE NOTE: + * + * This function is provided for convenience only, and is used by many + * of the demo applications. Do not consider it to be part of the + * scheduler. + * + * vTaskGetRunTimeStats() calls uxTaskGetSystemState(), then formats part + * of the uxTaskGetSystemState() output into a human readable table that + * displays the amount of time each task has spent in the Running state + * in both absolute and percentage terms. + * + * vTaskGetRunTimeStats() has a dependency on the sprintf() C library + * function that might bloat the code size, use a lot of stack, and + * provide different results on different platforms. An alternative, + * tiny, third party, and limited functionality implementation of + * sprintf() is provided in many of the FreeRTOS/Demo sub-directories in + * a file called printf-stdarg.c (note printf-stdarg.c does not provide + * a full snprintf() implementation!). + * + * It is recommended that production systems call uxTaskGetSystemState() + * directly to get access to raw stats data, rather than indirectly + * through a call to vTaskGetRunTimeStats(). + */ + + /* Make sure the write buffer does not contain a string. */ + *pcWriteBuffer = 0x00; + + /* Take a snapshot of the number of tasks in case it changes while this + function is executing. */ + uxArraySize = uxCurrentNumberOfTasks; + + /* Allocate an array index for each task. */ + pxTaskStatusArray = pvPortMalloc( uxCurrentNumberOfTasks * sizeof( TaskStatus_t ) ); + + if( pxTaskStatusArray != NULL ) + { + /* Generate the (binary) data. */ + uxArraySize = uxTaskGetSystemState( pxTaskStatusArray, uxArraySize, &ulTotalTime ); + + /* For percentage calculations. */ + ulTotalTime /= 100UL; + + /* Avoid divide by zero errors. */ + if( ulTotalTime > 0 ) + { + /* Create a human readable table from the binary data. */ + for( x = 0; x < uxArraySize; x++ ) + { + /* What percentage of the total run time has the task used? + This will always be rounded down to the nearest integer. + ulTotalRunTimeDiv100 has already been divided by 100. */ + ulStatsAsPercentage = pxTaskStatusArray[ x ].ulRunTimeCounter / ulTotalTime; + + /* Write the task name to the string, padding with + spaces so it can be printed in tabular form more + easily. */ + pcWriteBuffer = prvWriteNameToBuffer( pcWriteBuffer, pxTaskStatusArray[ x ].pcTaskName ); + + if( ulStatsAsPercentage > 0UL ) + { + #ifdef portLU_PRINTF_SPECIFIER_REQUIRED + { + sprintf( pcWriteBuffer, "\t%lu\t\t%lu%%\r\n", pxTaskStatusArray[ x ].ulRunTimeCounter, ulStatsAsPercentage ); + } + #else + { + /* sizeof( int ) == sizeof( long ) so a smaller + printf() library can be used. */ + sprintf( pcWriteBuffer, "\t%u\t\t%u%%\r\n", ( unsigned int ) pxTaskStatusArray[ x ].ulRunTimeCounter, ( unsigned int ) ulStatsAsPercentage ); + } + #endif + } + else + { + /* If the percentage is zero here then the task has + consumed less than 1% of the total run time. */ + #ifdef portLU_PRINTF_SPECIFIER_REQUIRED + { + sprintf( pcWriteBuffer, "\t%lu\t\t<1%%\r\n", pxTaskStatusArray[ x ].ulRunTimeCounter ); + } + #else + { + /* sizeof( int ) == sizeof( long ) so a smaller + printf() library can be used. */ + sprintf( pcWriteBuffer, "\t%u\t\t<1%%\r\n", ( unsigned int ) pxTaskStatusArray[ x ].ulRunTimeCounter ); + } + #endif + } + + pcWriteBuffer += strlen( pcWriteBuffer ); + } + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + + /* Free the array again. */ + vPortFree( pxTaskStatusArray ); + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } + +#endif /* ( ( configGENERATE_RUN_TIME_STATS == 1 ) && ( configUSE_STATS_FORMATTING_FUNCTIONS > 0 ) ) */ +/*-----------------------------------------------------------*/ + +TickType_t uxTaskResetEventItemValue( void ) +{ +TickType_t uxReturn; + taskENTER_CRITICAL(&xTaskQueueMutex); + uxReturn = listGET_LIST_ITEM_VALUE( &( pxCurrentTCB[ xPortGetCoreID() ]->xEventListItem ) ); + + /* Reset the event list item to its normal value - so it can be used with + queues and semaphores. */ + listSET_LIST_ITEM_VALUE( &( pxCurrentTCB[ xPortGetCoreID() ]->xEventListItem ), ( ( TickType_t ) configMAX_PRIORITIES - ( TickType_t ) pxCurrentTCB[ xPortGetCoreID() ]->uxPriority ) ); /*lint !e961 MISRA exception as the casts are only redundant for some ports. */ + taskEXIT_CRITICAL(&xTaskQueueMutex); + + return uxReturn; +} +/*-----------------------------------------------------------*/ + +#if ( configUSE_MUTEXES == 1 ) + + void *pvTaskIncrementMutexHeldCount( void ) + { + /* If xSemaphoreCreateMutex() is called before any tasks have been created + then pxCurrentTCB will be NULL. */ + taskENTER_CRITICAL(&xTaskQueueMutex); + if( pxCurrentTCB[ xPortGetCoreID() ] != NULL ) + { + ( pxCurrentTCB[ xPortGetCoreID() ]->uxMutexesHeld )++; + } + taskEXIT_CRITICAL(&xTaskQueueMutex); + + return pxCurrentTCB[ xPortGetCoreID() ]; + } + +#endif /* configUSE_MUTEXES */ +/*-----------------------------------------------------------*/ + +#if( configUSE_TASK_NOTIFICATIONS == 1 ) + + uint32_t ulTaskNotifyTake( BaseType_t xClearCountOnExit, TickType_t xTicksToWait ) + { + TickType_t xTimeToWake; + uint32_t ulReturn; + + taskENTER_CRITICAL(&xTaskQueueMutex); + { + /* Only block if the notification count is not already non-zero. */ + if( pxCurrentTCB[ xPortGetCoreID() ]->ulNotifiedValue == 0UL ) + { + /* Mark this task as waiting for a notification. */ + pxCurrentTCB[ xPortGetCoreID() ]->eNotifyState = eWaitingNotification; + + if( xTicksToWait > ( TickType_t ) 0 ) + { + /* The task is going to block. First it must be removed + from the ready list. */ + if( uxListRemove( &( pxCurrentTCB[ xPortGetCoreID() ]->xGenericListItem ) ) == ( UBaseType_t ) 0 ) + { + /* The current task must be in a ready list, so there is + no need to check, and the port reset macro can be called + directly. */ + portRESET_READY_PRIORITY( pxCurrentTCB[ xPortGetCoreID() ]->uxPriority, uxTopReadyPriority ); + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + + #if ( INCLUDE_vTaskSuspend == 1 ) + { + if( xTicksToWait == portMAX_DELAY ) + { + /* Add the task to the suspended task list instead + of a delayed task list to ensure the task is not + woken by a timing event. It will block + indefinitely. */ + vListInsertEnd( &xSuspendedTaskList, &( pxCurrentTCB[ xPortGetCoreID() ]->xGenericListItem ) ); + } + else + { + /* Calculate the time at which the task should be + woken if no notification events occur. This may + overflow but this doesn't matter, the scheduler will + handle it. */ + xTimeToWake = xTickCount + xTicksToWait; + prvAddCurrentTaskToDelayedList( xPortGetCoreID(), xTimeToWake ); + } + } + #else /* INCLUDE_vTaskSuspend */ + { + /* Calculate the time at which the task should be + woken if the event does not occur. This may + overflow but this doesn't matter, the scheduler will + handle it. */ + xTimeToWake = xTickCount + xTicksToWait; + prvAddCurrentTaskToDelayedList( xTimeToWake ); + } + #endif /* INCLUDE_vTaskSuspend */ + + /* All ports are written to allow a yield in a critical + section (some will yield immediately, others wait until the + critical section exits) - but it is not something that + application code should ever do. */ + portYIELD_WITHIN_API(); + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } + taskEXIT_CRITICAL(&xTaskQueueMutex); + + taskENTER_CRITICAL(&xTaskQueueMutex); + { + ulReturn = pxCurrentTCB[ xPortGetCoreID() ]->ulNotifiedValue; + + if( ulReturn != 0UL ) + { + if( xClearCountOnExit != pdFALSE ) + { + pxCurrentTCB[ xPortGetCoreID() ]->ulNotifiedValue = 0UL; + } + else + { + ( pxCurrentTCB[ xPortGetCoreID() ]->ulNotifiedValue )--; + } + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + + pxCurrentTCB[ xPortGetCoreID() ]->eNotifyState = eNotWaitingNotification; + } + taskEXIT_CRITICAL(&xTaskQueueMutex); + + return ulReturn; + } + +#endif /* configUSE_TASK_NOTIFICATIONS */ +/*-----------------------------------------------------------*/ + +#if( configUSE_TASK_NOTIFICATIONS == 1 ) + + BaseType_t xTaskNotifyWait( uint32_t ulBitsToClearOnEntry, uint32_t ulBitsToClearOnExit, uint32_t *pulNotificationValue, TickType_t xTicksToWait ) + { + TickType_t xTimeToWake; + BaseType_t xReturn; + + taskENTER_CRITICAL(&xTaskQueueMutex); + { + /* Only block if a notification is not already pending. */ + if( pxCurrentTCB[ xPortGetCoreID() ]->eNotifyState != eNotified ) + { + /* Clear bits in the task's notification value as bits may get + set by the notifying task or interrupt. This can be used to + clear the value to zero. */ + pxCurrentTCB[ xPortGetCoreID() ]->ulNotifiedValue &= ~ulBitsToClearOnEntry; + + /* Mark this task as waiting for a notification. */ + pxCurrentTCB[ xPortGetCoreID() ]->eNotifyState = eWaitingNotification; + + if( xTicksToWait > ( TickType_t ) 0 ) + { + /* The task is going to block. First it must be removed + from the ready list. */ + if( uxListRemove( &( pxCurrentTCB[ xPortGetCoreID() ]->xGenericListItem ) ) == ( UBaseType_t ) 0 ) + { + /* The current task must be in a ready list, so there is + no need to check, and the port reset macro can be called + directly. */ + portRESET_READY_PRIORITY( pxCurrentTCB[ xPortGetCoreID() ]->uxPriority, uxTopReadyPriority ); + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + + #if ( INCLUDE_vTaskSuspend == 1 ) + { + if( xTicksToWait == portMAX_DELAY ) + { + /* Add the task to the suspended task list instead + of a delayed task list to ensure the task is not + woken by a timing event. It will block + indefinitely. */ + vListInsertEnd( &xSuspendedTaskList, &( pxCurrentTCB[ xPortGetCoreID() ]->xGenericListItem ) ); + } + else + { + /* Calculate the time at which the task should be + woken if no notification events occur. This may + overflow but this doesn't matter, the scheduler will + handle it. */ + xTimeToWake = xTickCount + xTicksToWait; + prvAddCurrentTaskToDelayedList( xPortGetCoreID(), xTimeToWake ); + } + } + #else /* INCLUDE_vTaskSuspend */ + { + /* Calculate the time at which the task should be + woken if the event does not occur. This may + overflow but this doesn't matter, the scheduler will + handle it. */ + xTimeToWake = xTickCount + xTicksToWait; + prvAddCurrentTaskToDelayedList( xTimeToWake ); + } + #endif /* INCLUDE_vTaskSuspend */ + + /* All ports are written to allow a yield in a critical + section (some will yield immediately, others wait until the + critical section exits) - but it is not something that + application code should ever do. */ + portYIELD_WITHIN_API(); + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } + taskEXIT_CRITICAL(&xTaskQueueMutex); + + taskENTER_CRITICAL(&xTaskQueueMutex); + { + if( pulNotificationValue != NULL ) + { + /* Output the current notification value, which may or may not + have changed. */ + *pulNotificationValue = pxCurrentTCB[ xPortGetCoreID() ]->ulNotifiedValue; + } + + /* If eNotifyValue is set then either the task never entered the + blocked state (because a notification was already pending) or the + task unblocked because of a notification. Otherwise the task + unblocked because of a timeout. */ + if( pxCurrentTCB[ xPortGetCoreID() ]->eNotifyState == eWaitingNotification ) + { + /* A notification was not received. */ + xReturn = pdFALSE; + } + else + { + /* A notification was already pending or a notification was + received while the task was waiting. */ + pxCurrentTCB[ xPortGetCoreID() ]->ulNotifiedValue &= ~ulBitsToClearOnExit; + xReturn = pdTRUE; + } + + pxCurrentTCB[ xPortGetCoreID() ]->eNotifyState = eNotWaitingNotification; + } + taskEXIT_CRITICAL(&xTaskQueueMutex); + + return xReturn; + } + +#endif /* configUSE_TASK_NOTIFICATIONS */ +/*-----------------------------------------------------------*/ + +#if( configUSE_TASK_NOTIFICATIONS == 1 ) + + BaseType_t xTaskNotify( TaskHandle_t xTaskToNotify, uint32_t ulValue, eNotifyAction eAction ) + { + TCB_t * pxTCB; + eNotifyValue eOriginalNotifyState; + BaseType_t xReturn = pdPASS; + + configASSERT( xTaskToNotify ); + pxTCB = ( TCB_t * ) xTaskToNotify; + + taskENTER_CRITICAL(&xTaskQueueMutex); + { + eOriginalNotifyState = pxTCB->eNotifyState; + + pxTCB->eNotifyState = eNotified; + + switch( eAction ) + { + case eSetBits : + pxTCB->ulNotifiedValue |= ulValue; + break; + + case eIncrement : + ( pxTCB->ulNotifiedValue )++; + break; + + case eSetValueWithOverwrite : + pxTCB->ulNotifiedValue = ulValue; + break; + + case eSetValueWithoutOverwrite : + if( eOriginalNotifyState != eNotified ) + { + pxTCB->ulNotifiedValue = ulValue; + } + else + { + /* The value could not be written to the task. */ + xReturn = pdFAIL; + } + break; + + case eNoAction: + /* The task is being notified without its notify value being + updated. */ + break; + } + + + /* If the task is in the blocked state specifically to wait for a + notification then unblock it now. */ + if( eOriginalNotifyState == eWaitingNotification ) + { + ( void ) uxListRemove( &( pxTCB->xGenericListItem ) ); + prvAddTaskToReadyList( pxTCB ); + + /* The task should not have been on an event list. */ + configASSERT( listLIST_ITEM_CONTAINER( &( pxTCB->xEventListItem ) ) == NULL ); + + if( pxTCB->uxPriority > pxCurrentTCB[ xPortGetCoreID() ]->uxPriority ) + { + /* The notified task has a priority above the currently + executing task so a yield is required. */ + portYIELD_WITHIN_API(); + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } + taskEXIT_CRITICAL(&xTaskQueueMutex); + + return xReturn; + } + +#endif /* configUSE_TASK_NOTIFICATIONS */ +/*-----------------------------------------------------------*/ + +#if( configUSE_TASK_NOTIFICATIONS == 1 ) + + BaseType_t xTaskNotifyFromISR( TaskHandle_t xTaskToNotify, uint32_t ulValue, eNotifyAction eAction, BaseType_t *pxHigherPriorityTaskWoken ) + { + TCB_t * pxTCB; + eNotifyValue eOriginalNotifyState; + BaseType_t xReturn = pdPASS; + + configASSERT( xTaskToNotify ); + + pxTCB = ( TCB_t * ) xTaskToNotify; + + taskENTER_CRITICAL_ISR(&xTaskQueueMutex); + + { + eOriginalNotifyState = pxTCB->eNotifyState; + + pxTCB->eNotifyState = eNotified; + + switch( eAction ) + { + case eSetBits : + pxTCB->ulNotifiedValue |= ulValue; + break; + + case eIncrement : + ( pxTCB->ulNotifiedValue )++; + break; + + case eSetValueWithOverwrite : + pxTCB->ulNotifiedValue = ulValue; + break; + + case eSetValueWithoutOverwrite : + if( eOriginalNotifyState != eNotified ) + { + pxTCB->ulNotifiedValue = ulValue; + } + else + { + /* The value could not be written to the task. */ + xReturn = pdFAIL; + } + break; + + case eNoAction : + /* The task is being notified without its notify value being + updated. */ + break; + } + + + /* If the task is in the blocked state specifically to wait for a + notification then unblock it now. */ + if( eOriginalNotifyState == eWaitingNotification ) + { + /* The task should not have been on an event list. */ + configASSERT( listLIST_ITEM_CONTAINER( &( pxTCB->xEventListItem ) ) == NULL ); + + if( uxSchedulerSuspended[ xPortGetCoreID() ] == ( UBaseType_t ) pdFALSE ) + { + ( void ) uxListRemove( &( pxTCB->xGenericListItem ) ); + prvAddTaskToReadyList( pxTCB ); + } + else + { + /* The delayed and ready lists cannot be accessed, so hold + this task pending until the scheduler is resumed. */ + vListInsertEnd( &( xPendingReadyList ), &( pxTCB->xEventListItem ) ); + } + + if( pxTCB->uxPriority > pxCurrentTCB[ xPortGetCoreID() ]->uxPriority ) + { + /* The notified task has a priority above the currently + executing task so a yield is required. */ + if( pxHigherPriorityTaskWoken != NULL ) + { + *pxHigherPriorityTaskWoken = pdTRUE; + } + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } + } + taskEXIT_CRITICAL_ISR(&xTaskQueueMutex); + + return xReturn; + } + +#endif /* configUSE_TASK_NOTIFICATIONS */ +/*-----------------------------------------------------------*/ + +#if( configUSE_TASK_NOTIFICATIONS == 1 ) + + void vTaskNotifyGiveFromISR( TaskHandle_t xTaskToNotify, BaseType_t *pxHigherPriorityTaskWoken ) + { + TCB_t * pxTCB; + eNotifyValue eOriginalNotifyState; + + configASSERT( xTaskToNotify ); + + + pxTCB = ( TCB_t * ) xTaskToNotify; + + taskENTER_CRITICAL_ISR(&xTaskQueueMutex); + { + eOriginalNotifyState = pxTCB->eNotifyState; + pxTCB->eNotifyState = eNotified; + + /* 'Giving' is equivalent to incrementing a count in a counting + semaphore. */ + ( pxTCB->ulNotifiedValue )++; + + /* If the task is in the blocked state specifically to wait for a + notification then unblock it now. */ + if( eOriginalNotifyState == eWaitingNotification ) + { + /* The task should not have been on an event list. */ + configASSERT( listLIST_ITEM_CONTAINER( &( pxTCB->xEventListItem ) ) == NULL ); + + if( uxSchedulerSuspended[ xPortGetCoreID() ] == ( UBaseType_t ) pdFALSE ) + { + ( void ) uxListRemove( &( pxTCB->xGenericListItem ) ); + prvAddTaskToReadyList( pxTCB ); + } + else + { + /* The delayed and ready lists cannot be accessed, so hold + this task pending until the scheduler is resumed. */ + vListInsertEnd( &( xPendingReadyList ), &( pxTCB->xEventListItem ) ); + } + + if( pxTCB->uxPriority > pxCurrentTCB[ xPortGetCoreID() ]->uxPriority ) + { + /* The notified task has a priority above the currently + executing task so a yield is required. */ + if( pxHigherPriorityTaskWoken != NULL ) + { + *pxHigherPriorityTaskWoken = pdTRUE; + } + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } + } + taskEXIT_CRITICAL_ISR(&xTaskQueueMutex); + } + +#endif /* configUSE_TASK_NOTIFICATIONS */ + +/*-----------------------------------------------------------*/ + + +#ifdef FREERTOS_MODULE_TEST + #include "tasks_test_access_functions.h" +#endif + diff --git a/components/freertos/timers.c b/components/freertos/timers.c new file mode 100644 index 0000000000..7c0ba5bd9a --- /dev/null +++ b/components/freertos/timers.c @@ -0,0 +1,909 @@ +/* + FreeRTOS V8.2.0 - Copyright (C) 2015 Real Time Engineers Ltd. + All rights reserved + + VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION. + + This file is part of the FreeRTOS distribution. + + FreeRTOS is free software; you can redistribute it and/or modify it under + the terms of the GNU General Public License (version 2) as published by the + Free Software Foundation >>!AND MODIFIED BY!<< the FreeRTOS exception. + + *************************************************************************** + >>! NOTE: The modification to the GPL is included to allow you to !<< + >>! distribute a combined work that includes FreeRTOS without being !<< + >>! obliged to provide the source code for proprietary components !<< + >>! outside of the FreeRTOS kernel. !<< + *************************************************************************** + + FreeRTOS is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + FOR A PARTICULAR PURPOSE. Full license text is available on the following + link: http://www.freertos.org/a00114.html + + *************************************************************************** + * * + * FreeRTOS provides completely free yet professionally developed, * + * robust, strictly quality controlled, supported, and cross * + * platform software that is more than just the market leader, it * + * is the industry's de facto standard. * + * * + * Help yourself get started quickly while simultaneously helping * + * to support the FreeRTOS project by purchasing a FreeRTOS * + * tutorial book, reference manual, or both: * + * http://www.FreeRTOS.org/Documentation * + * * + *************************************************************************** + + http://www.FreeRTOS.org/FAQHelp.html - Having a problem? Start by reading + the FAQ page "My application does not run, what could be wrong?". Have you + defined configASSERT()? + + http://www.FreeRTOS.org/support - In return for receiving this top quality + embedded software for free we request you assist our global community by + participating in the support forum. + + http://www.FreeRTOS.org/training - Investing in training allows your team to + be as productive as possible as early as possible. Now you can receive + FreeRTOS training directly from Richard Barry, CEO of Real Time Engineers + Ltd, and the world's leading authority on the world's leading RTOS. + + http://www.FreeRTOS.org/plus - A selection of FreeRTOS ecosystem products, + including FreeRTOS+Trace - an indispensable productivity tool, a DOS + compatible FAT file system, and our tiny thread aware UDP/IP stack. + + http://www.FreeRTOS.org/labs - Where new FreeRTOS products go to incubate. + Come and try FreeRTOS+TCP, our new open source TCP/IP stack for FreeRTOS. + + http://www.OpenRTOS.com - Real Time Engineers ltd. license FreeRTOS to High + Integrity Systems ltd. to sell under the OpenRTOS brand. Low cost OpenRTOS + licenses offer ticketed support, indemnification and commercial middleware. + + http://www.SafeRTOS.com - High Integrity Systems also provide a safety + engineered and independently SIL3 certified version for use in safety and + mission critical applications that require provable dependability. + + 1 tab == 4 spaces! +*/ + +/* Standard includes. */ +#include + +/* Defining MPU_WRAPPERS_INCLUDED_FROM_API_FILE prevents task.h from redefining +all the API functions to use the MPU wrappers. That should only be done when +task.h is included from an application file. */ +#define MPU_WRAPPERS_INCLUDED_FROM_API_FILE + +#include "FreeRTOS.h" +#include "task.h" +#include "queue.h" +#include "timers.h" +#include "portmacro.h" + +#if ( INCLUDE_xTimerPendFunctionCall == 1 ) && ( configUSE_TIMERS == 0 ) + #error configUSE_TIMERS must be set to 1 to make the xTimerPendFunctionCall() function available. +#endif + +/* Lint e961 and e750 are suppressed as a MISRA exception justified because the +MPU ports require MPU_WRAPPERS_INCLUDED_FROM_API_FILE to be defined for the +header files above, but not in this file, in order to generate the correct +privileged Vs unprivileged linkage and placement. */ +#undef MPU_WRAPPERS_INCLUDED_FROM_API_FILE /*lint !e961 !e750. */ + + +/* This entire source file will be skipped if the application is not configured +to include software timer functionality. This #if is closed at the very bottom +of this file. If you want to include software timer functionality then ensure +configUSE_TIMERS is set to 1 in FreeRTOSConfig.h. */ +#if ( configUSE_TIMERS == 1 ) + +/* Misc definitions. */ +#define tmrNO_DELAY ( TickType_t ) 0U + +/* The definition of the timers themselves. */ +typedef struct tmrTimerControl +{ + const char *pcTimerName; /*<< Text name. This is not used by the kernel, it is included simply to make debugging easier. */ /*lint !e971 Unqualified char types are allowed for strings and single characters only. */ + ListItem_t xTimerListItem; /*<< Standard linked list item as used by all kernel features for event management. */ + TickType_t xTimerPeriodInTicks;/*<< How quickly and often the timer expires. */ + UBaseType_t uxAutoReload; /*<< Set to pdTRUE if the timer should be automatically restarted once expired. Set to pdFALSE if the timer is, in effect, a one-shot timer. */ + void *pvTimerID; /*<< An ID to identify the timer. This allows the timer to be identified when the same callback is used for multiple timers. */ + TimerCallbackFunction_t pxCallbackFunction; /*<< The function that will be called when the timer expires. */ + #if( configUSE_TRACE_FACILITY == 1 ) + UBaseType_t uxTimerNumber; /*<< An ID assigned by trace tools such as FreeRTOS+Trace */ + #endif +} xTIMER; + +/* The old xTIMER name is maintained above then typedefed to the new Timer_t +name below to enable the use of older kernel aware debuggers. */ +typedef xTIMER Timer_t; + +/* The definition of messages that can be sent and received on the timer queue. +Two types of message can be queued - messages that manipulate a software timer, +and messages that request the execution of a non-timer related callback. The +two message types are defined in two separate structures, xTimerParametersType +and xCallbackParametersType respectively. */ +typedef struct tmrTimerParameters +{ + TickType_t xMessageValue; /*<< An optional value used by a subset of commands, for example, when changing the period of a timer. */ + Timer_t * pxTimer; /*<< The timer to which the command will be applied. */ +} TimerParameter_t; + + +typedef struct tmrCallbackParameters +{ + PendedFunction_t pxCallbackFunction; /* << The callback function to execute. */ + void *pvParameter1; /* << The value that will be used as the callback functions first parameter. */ + uint32_t ulParameter2; /* << The value that will be used as the callback functions second parameter. */ +} CallbackParameters_t; + +/* The structure that contains the two message types, along with an identifier +that is used to determine which message type is valid. */ +typedef struct tmrTimerQueueMessage +{ + BaseType_t xMessageID; /*<< The command being sent to the timer service task. */ + union + { + TimerParameter_t xTimerParameters; + + /* Don't include xCallbackParameters if it is not going to be used as + it makes the structure (and therefore the timer queue) larger. */ + #if ( INCLUDE_xTimerPendFunctionCall == 1 ) + CallbackParameters_t xCallbackParameters; + #endif /* INCLUDE_xTimerPendFunctionCall */ + } u; +} DaemonTaskMessage_t; + +/*lint -e956 A manual analysis and inspection has been used to determine which +static variables must be declared volatile. */ + +/* The list in which active timers are stored. Timers are referenced in expire +time order, with the nearest expiry time at the front of the list. Only the +timer service task is allowed to access these lists. */ +PRIVILEGED_DATA static List_t xActiveTimerList1; +PRIVILEGED_DATA static List_t xActiveTimerList2; +PRIVILEGED_DATA static List_t *pxCurrentTimerList; +PRIVILEGED_DATA static List_t *pxOverflowTimerList; + +/* A queue that is used to send commands to the timer service task. */ +PRIVILEGED_DATA static QueueHandle_t xTimerQueue = NULL; + +/* Mux. We use a single mux for all the timers for now. ToDo: maybe increase granularity here? */ +PRIVILEGED_DATA portMUX_TYPE xTimerMux; + +#if ( INCLUDE_xTimerGetTimerDaemonTaskHandle == 1 ) + + PRIVILEGED_DATA static TaskHandle_t xTimerTaskHandle = NULL; + +#endif + +/*lint +e956 */ + +/*-----------------------------------------------------------*/ + +/* + * Initialise the infrastructure used by the timer service task if it has not + * been initialised already. + */ +static void prvCheckForValidListAndQueue( void ) PRIVILEGED_FUNCTION; + +/* + * The timer service task (daemon). Timer functionality is controlled by this + * task. Other tasks communicate with the timer service task using the + * xTimerQueue queue. + */ +static void prvTimerTask( void *pvParameters ) PRIVILEGED_FUNCTION; + +/* + * Called by the timer service task to interpret and process a command it + * received on the timer queue. + */ +static void prvProcessReceivedCommands( void ) PRIVILEGED_FUNCTION; + +/* + * Insert the timer into either xActiveTimerList1, or xActiveTimerList2, + * depending on if the expire time causes a timer counter overflow. + */ +static BaseType_t prvInsertTimerInActiveList( Timer_t * const pxTimer, const TickType_t xNextExpiryTime, const TickType_t xTimeNow, const TickType_t xCommandTime ) PRIVILEGED_FUNCTION; + +/* + * An active timer has reached its expire time. Reload the timer if it is an + * auto reload timer, then call its callback. + */ +static void prvProcessExpiredTimer( const TickType_t xNextExpireTime, const TickType_t xTimeNow ) PRIVILEGED_FUNCTION; + +/* + * The tick count has overflowed. Switch the timer lists after ensuring the + * current timer list does not still reference some timers. + */ +static void prvSwitchTimerLists( void ) PRIVILEGED_FUNCTION; + +/* + * Obtain the current tick count, setting *pxTimerListsWereSwitched to pdTRUE + * if a tick count overflow occurred since prvSampleTimeNow() was last called. + */ +static TickType_t prvSampleTimeNow( BaseType_t * const pxTimerListsWereSwitched ) PRIVILEGED_FUNCTION; + +/* + * If the timer list contains any active timers then return the expire time of + * the timer that will expire first and set *pxListWasEmpty to false. If the + * timer list does not contain any timers then return 0 and set *pxListWasEmpty + * to pdTRUE. + */ +static TickType_t prvGetNextExpireTime( BaseType_t * const pxListWasEmpty ) PRIVILEGED_FUNCTION; + +/* + * If a timer has expired, process it. Otherwise, block the timer service task + * until either a timer does expire or a command is received. + */ +static void prvProcessTimerOrBlockTask( const TickType_t xNextExpireTime, const BaseType_t xListWasEmpty ) PRIVILEGED_FUNCTION; + +/*-----------------------------------------------------------*/ + +BaseType_t xTimerCreateTimerTask( void ) +{ +BaseType_t xReturn = pdFAIL; + + /* This function is called when the scheduler is started if + configUSE_TIMERS is set to 1. Check that the infrastructure used by the + timer service task has been created/initialised. If timers have already + been created then the initialisation will already have been performed. */ + + /* For now, the timer task will be fixed to core 0. This means whatever process + running on whatever core schedules the timer, the timer callback function + will *ALWAYS* run on core 0. */ + prvCheckForValidListAndQueue(); + + if( xTimerQueue != NULL ) + { + #if ( INCLUDE_xTimerGetTimerDaemonTaskHandle == 1 ) + { + /* Create the timer task, storing its handle in xTimerTaskHandle so + it can be returned by the xTimerGetTimerDaemonTaskHandle() function. */ + xReturn = xTaskCreatePinnedToCore( prvTimerTask, "Tmr Svc", ( uint16_t ) configTIMER_TASK_STACK_DEPTH, NULL, ( ( UBaseType_t ) configTIMER_TASK_PRIORITY ) | portPRIVILEGE_BIT, &xTimerTaskHandle, 0 ); + } + #else + { + /* Create the timer task without storing its handle. */ + xReturn = xTaskCreatePinnedToCore( prvTimerTask, "Tmr Svc", ( uint16_t ) configTIMER_TASK_STACK_DEPTH, NULL, ( ( UBaseType_t ) configTIMER_TASK_PRIORITY ) | portPRIVILEGE_BIT, NULL, 0 ); + } + #endif + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + + configASSERT( xReturn ); + return xReturn; +} +/*-----------------------------------------------------------*/ + +TimerHandle_t xTimerCreate( const char * const pcTimerName, const TickType_t xTimerPeriodInTicks, const UBaseType_t uxAutoReload, void * const pvTimerID, TimerCallbackFunction_t pxCallbackFunction ) /*lint !e971 Unqualified char types are allowed for strings and single characters only. */ +{ +Timer_t *pxNewTimer; + + /* Allocate the timer structure. */ + if( xTimerPeriodInTicks == ( TickType_t ) 0U ) + { + pxNewTimer = NULL; + } + else + { + pxNewTimer = ( Timer_t * ) pvPortMalloc( sizeof( Timer_t ) ); + if( pxNewTimer != NULL ) + { + /* Ensure the infrastructure used by the timer service task has been + created/initialised. */ + prvCheckForValidListAndQueue(); + + /* Initialise the timer structure members using the function parameters. */ + pxNewTimer->pcTimerName = pcTimerName; + pxNewTimer->xTimerPeriodInTicks = xTimerPeriodInTicks; + pxNewTimer->uxAutoReload = uxAutoReload; + pxNewTimer->pvTimerID = pvTimerID; + pxNewTimer->pxCallbackFunction = pxCallbackFunction; + vListInitialiseItem( &( pxNewTimer->xTimerListItem ) ); + + traceTIMER_CREATE( pxNewTimer ); + } + else + { + traceTIMER_CREATE_FAILED(); + } + } + + /* 0 is not a valid value for xTimerPeriodInTicks. */ + configASSERT( ( xTimerPeriodInTicks > 0 ) ); + + return ( TimerHandle_t ) pxNewTimer; +} +/*-----------------------------------------------------------*/ + +BaseType_t xTimerGenericCommand( TimerHandle_t xTimer, const BaseType_t xCommandID, const TickType_t xOptionalValue, BaseType_t * const pxHigherPriorityTaskWoken, const TickType_t xTicksToWait ) +{ +BaseType_t xReturn = pdFAIL; +DaemonTaskMessage_t xMessage; + + /* Send a message to the timer service task to perform a particular action + on a particular timer definition. */ + if( xTimerQueue != NULL ) + { + /* Send a command to the timer service task to start the xTimer timer. */ + xMessage.xMessageID = xCommandID; + xMessage.u.xTimerParameters.xMessageValue = xOptionalValue; + xMessage.u.xTimerParameters.pxTimer = ( Timer_t * ) xTimer; + + if( xCommandID < tmrFIRST_FROM_ISR_COMMAND ) + { + if( xTaskGetSchedulerState() == taskSCHEDULER_RUNNING ) + { + xReturn = xQueueSendToBack( xTimerQueue, &xMessage, xTicksToWait ); + } + else + { + xReturn = xQueueSendToBack( xTimerQueue, &xMessage, tmrNO_DELAY ); + } + } + else + { + xReturn = xQueueSendToBackFromISR( xTimerQueue, &xMessage, pxHigherPriorityTaskWoken ); + } + + traceTIMER_COMMAND_SEND( xTimer, xCommandID, xOptionalValue, xReturn ); + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + + return xReturn; +} +/*-----------------------------------------------------------*/ + +#if ( INCLUDE_xTimerGetTimerDaemonTaskHandle == 1 ) + + TaskHandle_t xTimerGetTimerDaemonTaskHandle( void ) + { + /* If xTimerGetTimerDaemonTaskHandle() is called before the scheduler has been + started, then xTimerTaskHandle will be NULL. */ + configASSERT( ( xTimerTaskHandle != NULL ) ); + return xTimerTaskHandle; + } + +#endif +/*-----------------------------------------------------------*/ + +const char * pcTimerGetTimerName( TimerHandle_t xTimer ) +{ +Timer_t *pxTimer = ( Timer_t * ) xTimer; + + return pxTimer->pcTimerName; +} +/*-----------------------------------------------------------*/ + +static void prvProcessExpiredTimer( const TickType_t xNextExpireTime, const TickType_t xTimeNow ) +{ +BaseType_t xResult; +Timer_t * const pxTimer = ( Timer_t * ) listGET_OWNER_OF_HEAD_ENTRY( pxCurrentTimerList ); + + /* Remove the timer from the list of active timers. A check has already + been performed to ensure the list is not empty. */ + ( void ) uxListRemove( &( pxTimer->xTimerListItem ) ); + traceTIMER_EXPIRED( pxTimer ); + + /* If the timer is an auto reload timer then calculate the next + expiry time and re-insert the timer in the list of active timers. */ + if( pxTimer->uxAutoReload == ( UBaseType_t ) pdTRUE ) + { + /* The timer is inserted into a list using a time relative to anything + other than the current time. It will therefore be inserted into the + correct list relative to the time this task thinks it is now. */ + if( prvInsertTimerInActiveList( pxTimer, ( xNextExpireTime + pxTimer->xTimerPeriodInTicks ), xTimeNow, xNextExpireTime ) == pdTRUE ) + { + /* The timer expired before it was added to the active timer + list. Reload it now. */ + xResult = xTimerGenericCommand( pxTimer, tmrCOMMAND_START_DONT_TRACE, xNextExpireTime, NULL, tmrNO_DELAY ); + configASSERT( xResult ); + ( void ) xResult; + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + + /* Call the timer callback. */ + pxTimer->pxCallbackFunction( ( TimerHandle_t ) pxTimer ); +} +/*-----------------------------------------------------------*/ + +static void prvTimerTask( void *pvParameters ) +{ +TickType_t xNextExpireTime; +BaseType_t xListWasEmpty; + + /* Just to avoid compiler warnings. */ + ( void ) pvParameters; + + for( ;; ) + { + /* Query the timers list to see if it contains any timers, and if so, + obtain the time at which the next timer will expire. */ + xNextExpireTime = prvGetNextExpireTime( &xListWasEmpty ); + + /* If a timer has expired, process it. Otherwise, block this task + until either a timer does expire, or a command is received. */ + prvProcessTimerOrBlockTask( xNextExpireTime, xListWasEmpty ); + + /* Empty the command queue. */ + prvProcessReceivedCommands(); + } +} +/*-----------------------------------------------------------*/ + +static void prvProcessTimerOrBlockTask( const TickType_t xNextExpireTime, const BaseType_t xListWasEmpty ) +{ +TickType_t xTimeNow; +BaseType_t xTimerListsWereSwitched; + + vTaskSuspendAll(); + { + /* Obtain the time now to make an assessment as to whether the timer + has expired or not. If obtaining the time causes the lists to switch + then don't process this timer as any timers that remained in the list + when the lists were switched will have been processed within the + prvSampleTimeNow() function. */ + xTimeNow = prvSampleTimeNow( &xTimerListsWereSwitched ); + if( xTimerListsWereSwitched == pdFALSE ) + { + /* The tick count has not overflowed, has the timer expired? */ + if( ( xListWasEmpty == pdFALSE ) && ( xNextExpireTime <= xTimeNow ) ) + { + ( void ) xTaskResumeAll(); + prvProcessExpiredTimer( xNextExpireTime, xTimeNow ); + } + else + { + /* The tick count has not overflowed, and the next expire + time has not been reached yet. This task should therefore + block to wait for the next expire time or a command to be + received - whichever comes first. The following line cannot + be reached unless xNextExpireTime > xTimeNow, except in the + case when the current timer list is empty. */ + vQueueWaitForMessageRestricted( xTimerQueue, ( xNextExpireTime - xTimeNow ) ); + + if( xTaskResumeAll() == pdFALSE ) + { + /* Yield to wait for either a command to arrive, or the + block time to expire. If a command arrived between the + critical section being exited and this yield then the yield + will not cause the task to block. */ + portYIELD_WITHIN_API(); + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } + } + else + { + ( void ) xTaskResumeAll(); + } + } +} +/*-----------------------------------------------------------*/ + +static TickType_t prvGetNextExpireTime( BaseType_t * const pxListWasEmpty ) +{ +TickType_t xNextExpireTime; + + /* Timers are listed in expiry time order, with the head of the list + referencing the task that will expire first. Obtain the time at which + the timer with the nearest expiry time will expire. If there are no + active timers then just set the next expire time to 0. That will cause + this task to unblock when the tick count overflows, at which point the + timer lists will be switched and the next expiry time can be + re-assessed. */ + *pxListWasEmpty = listLIST_IS_EMPTY( pxCurrentTimerList ); + if( *pxListWasEmpty == pdFALSE ) + { + xNextExpireTime = listGET_ITEM_VALUE_OF_HEAD_ENTRY( pxCurrentTimerList ); + } + else + { + /* Ensure the task unblocks when the tick count rolls over. */ + xNextExpireTime = ( TickType_t ) 0U; + } + + return xNextExpireTime; +} +/*-----------------------------------------------------------*/ + +static TickType_t prvSampleTimeNow( BaseType_t * const pxTimerListsWereSwitched ) +{ +TickType_t xTimeNow; +PRIVILEGED_DATA static TickType_t xLastTime = ( TickType_t ) 0U; /*lint !e956 Variable is only accessible to one task. */ + + xTimeNow = xTaskGetTickCount(); + + if( xTimeNow < xLastTime ) + { + prvSwitchTimerLists(); + *pxTimerListsWereSwitched = pdTRUE; + } + else + { + *pxTimerListsWereSwitched = pdFALSE; + } + + xLastTime = xTimeNow; + + return xTimeNow; +} +/*-----------------------------------------------------------*/ + +static BaseType_t prvInsertTimerInActiveList( Timer_t * const pxTimer, const TickType_t xNextExpiryTime, const TickType_t xTimeNow, const TickType_t xCommandTime ) +{ +BaseType_t xProcessTimerNow = pdFALSE; + + listSET_LIST_ITEM_VALUE( &( pxTimer->xTimerListItem ), xNextExpiryTime ); + listSET_LIST_ITEM_OWNER( &( pxTimer->xTimerListItem ), pxTimer ); + + if( xNextExpiryTime <= xTimeNow ) + { + /* Has the expiry time elapsed between the command to start/reset a + timer was issued, and the time the command was processed? */ + if( ( xTimeNow - xCommandTime ) >= pxTimer->xTimerPeriodInTicks ) + { + /* The time between a command being issued and the command being + processed actually exceeds the timers period. */ + xProcessTimerNow = pdTRUE; + } + else + { + vListInsert( pxOverflowTimerList, &( pxTimer->xTimerListItem ) ); + } + } + else + { + if( ( xTimeNow < xCommandTime ) && ( xNextExpiryTime >= xCommandTime ) ) + { + /* If, since the command was issued, the tick count has overflowed + but the expiry time has not, then the timer must have already passed + its expiry time and should be processed immediately. */ + xProcessTimerNow = pdTRUE; + } + else + { + vListInsert( pxCurrentTimerList, &( pxTimer->xTimerListItem ) ); + } + } + + return xProcessTimerNow; +} +/*-----------------------------------------------------------*/ + +static void prvProcessReceivedCommands( void ) +{ +DaemonTaskMessage_t xMessage; +Timer_t *pxTimer; +BaseType_t xTimerListsWereSwitched, xResult; +TickType_t xTimeNow; + + while( xQueueReceive( xTimerQueue, &xMessage, tmrNO_DELAY ) != pdFAIL ) /*lint !e603 xMessage does not have to be initialised as it is passed out, not in, and it is not used unless xQueueReceive() returns pdTRUE. */ + { + #if ( INCLUDE_xTimerPendFunctionCall == 1 ) + { + /* Negative commands are pended function calls rather than timer + commands. */ + if( xMessage.xMessageID < ( BaseType_t ) 0 ) + { + const CallbackParameters_t * const pxCallback = &( xMessage.u.xCallbackParameters ); + + /* The timer uses the xCallbackParameters member to request a + callback be executed. Check the callback is not NULL. */ + configASSERT( pxCallback ); + + /* Call the function. */ + pxCallback->pxCallbackFunction( pxCallback->pvParameter1, pxCallback->ulParameter2 ); + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } + #endif /* INCLUDE_xTimerPendFunctionCall */ + + /* Commands that are positive are timer commands rather than pended + function calls. */ + if( xMessage.xMessageID >= ( BaseType_t ) 0 ) + { + /* The messages uses the xTimerParameters member to work on a + software timer. */ + pxTimer = xMessage.u.xTimerParameters.pxTimer; + + if( listIS_CONTAINED_WITHIN( NULL, &( pxTimer->xTimerListItem ) ) == pdFALSE ) + { + /* The timer is in a list, remove it. */ + ( void ) uxListRemove( &( pxTimer->xTimerListItem ) ); + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + + traceTIMER_COMMAND_RECEIVED( pxTimer, xMessage.xMessageID, xMessage.u.xTimerParameters.xMessageValue ); + + /* In this case the xTimerListsWereSwitched parameter is not used, but + it must be present in the function call. prvSampleTimeNow() must be + called after the message is received from xTimerQueue so there is no + possibility of a higher priority task adding a message to the message + queue with a time that is ahead of the timer daemon task (because it + pre-empted the timer daemon task after the xTimeNow value was set). */ + xTimeNow = prvSampleTimeNow( &xTimerListsWereSwitched ); + + switch( xMessage.xMessageID ) + { + case tmrCOMMAND_START : + case tmrCOMMAND_START_FROM_ISR : + case tmrCOMMAND_RESET : + case tmrCOMMAND_RESET_FROM_ISR : + case tmrCOMMAND_START_DONT_TRACE : + /* Start or restart a timer. */ + if( prvInsertTimerInActiveList( pxTimer, xMessage.u.xTimerParameters.xMessageValue + pxTimer->xTimerPeriodInTicks, xTimeNow, xMessage.u.xTimerParameters.xMessageValue ) == pdTRUE ) + { + /* The timer expired before it was added to the active + timer list. Process it now. */ + pxTimer->pxCallbackFunction( ( TimerHandle_t ) pxTimer ); + traceTIMER_EXPIRED( pxTimer ); + + if( pxTimer->uxAutoReload == ( UBaseType_t ) pdTRUE ) + { + xResult = xTimerGenericCommand( pxTimer, tmrCOMMAND_START_DONT_TRACE, xMessage.u.xTimerParameters.xMessageValue + pxTimer->xTimerPeriodInTicks, NULL, tmrNO_DELAY ); + configASSERT( xResult ); + ( void ) xResult; + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + break; + + case tmrCOMMAND_STOP : + case tmrCOMMAND_STOP_FROM_ISR : + /* The timer has already been removed from the active list. + There is nothing to do here. */ + break; + + case tmrCOMMAND_CHANGE_PERIOD : + case tmrCOMMAND_CHANGE_PERIOD_FROM_ISR : + pxTimer->xTimerPeriodInTicks = xMessage.u.xTimerParameters.xMessageValue; + configASSERT( ( pxTimer->xTimerPeriodInTicks > 0 ) ); + + /* The new period does not really have a reference, and can be + longer or shorter than the old one. The command time is + therefore set to the current time, and as the period cannot be + zero the next expiry time can only be in the future, meaning + (unlike for the xTimerStart() case above) there is no fail case + that needs to be handled here. */ + ( void ) prvInsertTimerInActiveList( pxTimer, ( xTimeNow + pxTimer->xTimerPeriodInTicks ), xTimeNow, xTimeNow ); + break; + + case tmrCOMMAND_DELETE : + /* The timer has already been removed from the active list, + just free up the memory. */ + vPortFree( pxTimer ); + break; + + default : + /* Don't expect to get here. */ + break; + } + } + } +} +/*-----------------------------------------------------------*/ + +static void prvSwitchTimerLists( void ) +{ +TickType_t xNextExpireTime, xReloadTime; +List_t *pxTemp; +Timer_t *pxTimer; +BaseType_t xResult; + + /* The tick count has overflowed. The timer lists must be switched. + If there are any timers still referenced from the current timer list + then they must have expired and should be processed before the lists + are switched. */ + while( listLIST_IS_EMPTY( pxCurrentTimerList ) == pdFALSE ) + { + xNextExpireTime = listGET_ITEM_VALUE_OF_HEAD_ENTRY( pxCurrentTimerList ); + + /* Remove the timer from the list. */ + pxTimer = ( Timer_t * ) listGET_OWNER_OF_HEAD_ENTRY( pxCurrentTimerList ); + ( void ) uxListRemove( &( pxTimer->xTimerListItem ) ); + traceTIMER_EXPIRED( pxTimer ); + + /* Execute its callback, then send a command to restart the timer if + it is an auto-reload timer. It cannot be restarted here as the lists + have not yet been switched. */ + pxTimer->pxCallbackFunction( ( TimerHandle_t ) pxTimer ); + + if( pxTimer->uxAutoReload == ( UBaseType_t ) pdTRUE ) + { + /* Calculate the reload value, and if the reload value results in + the timer going into the same timer list then it has already expired + and the timer should be re-inserted into the current list so it is + processed again within this loop. Otherwise a command should be sent + to restart the timer to ensure it is only inserted into a list after + the lists have been swapped. */ + xReloadTime = ( xNextExpireTime + pxTimer->xTimerPeriodInTicks ); + if( xReloadTime > xNextExpireTime ) + { + listSET_LIST_ITEM_VALUE( &( pxTimer->xTimerListItem ), xReloadTime ); + listSET_LIST_ITEM_OWNER( &( pxTimer->xTimerListItem ), pxTimer ); + vListInsert( pxCurrentTimerList, &( pxTimer->xTimerListItem ) ); + } + else + { + xResult = xTimerGenericCommand( pxTimer, tmrCOMMAND_START_DONT_TRACE, xNextExpireTime, NULL, tmrNO_DELAY ); + configASSERT( xResult ); + ( void ) xResult; + } + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } + + pxTemp = pxCurrentTimerList; + pxCurrentTimerList = pxOverflowTimerList; + pxOverflowTimerList = pxTemp; +} +/*-----------------------------------------------------------*/ + +static void prvCheckForValidListAndQueue( void ) +{ + /* Check that the list from which active timers are referenced, and the + queue used to communicate with the timer service, have been + initialised. */ + + /* Erm, yes, this is a problem. We can't lock until the lock is initialized, and we can't initialize the lock + atomically because we don't have a lock yet... I'm pretty sure doubly-initializing a lock on 2 cpus + is no problem in the current implementation, but this is not a nice way to solve things. ToDo - improve. */ + + if( xTimerQueue == NULL ) vPortCPUInitializeMutex( &xTimerMux ); + + taskENTER_CRITICAL( &xTimerMux ); + { + if( xTimerQueue == NULL ) + { + vListInitialise( &xActiveTimerList1 ); + vListInitialise( &xActiveTimerList2 ); + pxCurrentTimerList = &xActiveTimerList1; + pxOverflowTimerList = &xActiveTimerList2; + xTimerQueue = xQueueCreate( ( UBaseType_t ) configTIMER_QUEUE_LENGTH, sizeof( DaemonTaskMessage_t ) ); + configASSERT( xTimerQueue ); + + #if ( configQUEUE_REGISTRY_SIZE > 0 ) + { + if( xTimerQueue != NULL ) + { + vQueueAddToRegistry( xTimerQueue, "TmrQ" ); + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } + #endif /* configQUEUE_REGISTRY_SIZE */ + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } + taskEXIT_CRITICAL( &xTimerMux ); +} +/*-----------------------------------------------------------*/ + +BaseType_t xTimerIsTimerActive( TimerHandle_t xTimer ) +{ +BaseType_t xTimerIsInActiveList; +Timer_t *pxTimer = ( Timer_t * ) xTimer; + + /* Is the timer in the list of active timers? */ + taskENTER_CRITICAL( &xTimerMux ); + { + /* Checking to see if it is in the NULL list in effect checks to see if + it is referenced from either the current or the overflow timer lists in + one go, but the logic has to be reversed, hence the '!'. */ + xTimerIsInActiveList = ( BaseType_t ) !( listIS_CONTAINED_WITHIN( NULL, &( pxTimer->xTimerListItem ) ) ); + } + taskEXIT_CRITICAL( &xTimerMux ); + + return xTimerIsInActiveList; +} /*lint !e818 Can't be pointer to const due to the typedef. */ +/*-----------------------------------------------------------*/ + +void *pvTimerGetTimerID( const TimerHandle_t xTimer ) +{ +Timer_t * const pxTimer = ( Timer_t * ) xTimer; + + return pxTimer->pvTimerID; +} +/*-----------------------------------------------------------*/ + +#if( INCLUDE_xTimerPendFunctionCall == 1 ) + + BaseType_t xTimerPendFunctionCallFromISR( PendedFunction_t xFunctionToPend, void *pvParameter1, uint32_t ulParameter2, BaseType_t *pxHigherPriorityTaskWoken ) + { + DaemonTaskMessage_t xMessage; + BaseType_t xReturn; + + /* Complete the message with the function parameters and post it to the + daemon task. */ + xMessage.xMessageID = tmrCOMMAND_EXECUTE_CALLBACK_FROM_ISR; + xMessage.u.xCallbackParameters.pxCallbackFunction = xFunctionToPend; + xMessage.u.xCallbackParameters.pvParameter1 = pvParameter1; + xMessage.u.xCallbackParameters.ulParameter2 = ulParameter2; + + xReturn = xQueueSendFromISR( xTimerQueue, &xMessage, pxHigherPriorityTaskWoken ); + + tracePEND_FUNC_CALL_FROM_ISR( xFunctionToPend, pvParameter1, ulParameter2, xReturn ); + + return xReturn; + } + +#endif /* INCLUDE_xTimerPendFunctionCall */ +/*-----------------------------------------------------------*/ + +#if( INCLUDE_xTimerPendFunctionCall == 1 ) + + BaseType_t xTimerPendFunctionCall( PendedFunction_t xFunctionToPend, void *pvParameter1, uint32_t ulParameter2, TickType_t xTicksToWait ) + { + DaemonTaskMessage_t xMessage; + BaseType_t xReturn; + + /* This function can only be called after a timer has been created or + after the scheduler has been started because, until then, the timer + queue does not exist. */ + configASSERT( xTimerQueue ); + + /* Complete the message with the function parameters and post it to the + daemon task. */ + xMessage.xMessageID = tmrCOMMAND_EXECUTE_CALLBACK; + xMessage.u.xCallbackParameters.pxCallbackFunction = xFunctionToPend; + xMessage.u.xCallbackParameters.pvParameter1 = pvParameter1; + xMessage.u.xCallbackParameters.ulParameter2 = ulParameter2; + + xReturn = xQueueSendToBack( xTimerQueue, &xMessage, xTicksToWait ); + + tracePEND_FUNC_CALL( xFunctionToPend, pvParameter1, ulParameter2, xReturn ); + + return xReturn; + } + +#endif /* INCLUDE_xTimerPendFunctionCall */ +/*-----------------------------------------------------------*/ + +/* This entire source file will be skipped if the application is not configured +to include software timer functionality. If you want to include software timer +functionality then ensure configUSE_TIMERS is set to 1 in FreeRTOSConfig.h. */ +#endif /* configUSE_TIMERS == 1 */ + + + diff --git a/components/freertos/xtensa_context.S b/components/freertos/xtensa_context.S new file mode 100644 index 0000000000..9e1c434f22 --- /dev/null +++ b/components/freertos/xtensa_context.S @@ -0,0 +1,645 @@ +/******************************************************************************* +Copyright (c) 2006-2015 Cadence Design Systems Inc. + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be included +in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +-------------------------------------------------------------------------------- + + XTENSA CONTEXT SAVE AND RESTORE ROUTINES + +Low-level Call0 functions for handling generic context save and restore of +registers not specifically addressed by the interrupt vectors and handlers. +Those registers (not handled by these functions) are PC, PS, A0, A1 (SP). +Except for the calls to RTOS functions, this code is generic to Xtensa. + +Note that in Call0 ABI, interrupt handlers are expected to preserve the callee- +save regs (A12-A15), which is always the case if the handlers are coded in C. +However A12, A13 are made available as scratch registers for interrupt dispatch +code, so are presumed saved anyway, and are always restored even in Call0 ABI. +Only A14, A15 are truly handled as callee-save regs. + +Because Xtensa is a configurable architecture, this port supports all user +generated configurations (except restrictions stated in the release notes). +This is accomplished by conditional compilation using macros and functions +defined in the Xtensa HAL (hardware adaptation layer) for your configuration. +Only the processor state included in your configuration is saved and restored, +including any processor state added by user configuration options or TIE. + +*******************************************************************************/ + +/* Warn nicely if this file gets named with a lowercase .s instead of .S: */ +#define NOERROR # +NOERROR: .error "C preprocessor needed for this file: make sure its filename\ + ends in uppercase .S, or use xt-xcc's -x assembler-with-cpp option." + + +#include "xtensa_rtos.h" +#include "xtensa_context.h" + +#ifdef XT_USE_OVLY +#include +#endif + + .text + + + +/******************************************************************************* + +_xt_context_save + + !! MUST BE CALLED ONLY BY 'CALL0' INSTRUCTION !! + +Saves all Xtensa processor state except PC, PS, A0, A1 (SP), A12, A13, in the +interrupt stack frame defined in xtensa_rtos.h. +Its counterpart is _xt_context_restore (which also restores A12, A13). + +Caller is expected to have saved PC, PS, A0, A1 (SP), A12, A13 in the frame. +This function preserves A12 & A13 in order to provide the caller with 2 scratch +regs that need not be saved over the call to this function. The choice of which +2 regs to provide is governed by xthal_window_spill_nw and xthal_save_extra_nw, +to avoid moving data more than necessary. Caller can assign regs accordingly. + +Entry Conditions: + A0 = Return address in caller. + A1 = Stack pointer of interrupted thread or handler ("interruptee"). + Original A12, A13 have already been saved in the interrupt stack frame. + Other processor state except PC, PS, A0, A1 (SP), A12, A13, is as at the + point of interruption. + If windowed ABI, PS.EXCM = 1 (exceptions disabled). + +Exit conditions: + A0 = Return address in caller. + A1 = Stack pointer of interrupted thread or handler ("interruptee"). + A12, A13 as at entry (preserved). + If windowed ABI, PS.EXCM = 1 (exceptions disabled). + +*******************************************************************************/ + + .global _xt_context_save + .type _xt_context_save,@function + .align 4 + .literal_position + .align 4 +_xt_context_save: + + s32i a2, sp, XT_STK_A2 + s32i a3, sp, XT_STK_A3 + s32i a4, sp, XT_STK_A4 + s32i a5, sp, XT_STK_A5 + s32i a6, sp, XT_STK_A6 + s32i a7, sp, XT_STK_A7 + s32i a8, sp, XT_STK_A8 + s32i a9, sp, XT_STK_A9 + s32i a10, sp, XT_STK_A10 + s32i a11, sp, XT_STK_A11 + + /* + Call0 ABI callee-saved regs a12-15 do not need to be saved here. + a12-13 are the caller's responsibility so it can use them as scratch. + So only need to save a14-a15 here for Windowed ABI (not Call0). + */ + #ifndef __XTENSA_CALL0_ABI__ + s32i a14, sp, XT_STK_A14 + s32i a15, sp, XT_STK_A15 + #endif + + rsr a3, SAR + s32i a3, sp, XT_STK_SAR + + #if XCHAL_HAVE_LOOPS + rsr a3, LBEG + s32i a3, sp, XT_STK_LBEG + rsr a3, LEND + s32i a3, sp, XT_STK_LEND + rsr a3, LCOUNT + s32i a3, sp, XT_STK_LCOUNT + #endif + + #ifdef XT_USE_SWPRI + /* Save virtual priority mask */ + movi a3, _xt_vpri_mask + l32i a3, a3, 0 + s32i a3, sp, XT_STK_VPRI + #endif + + #if XCHAL_EXTRA_SA_SIZE > 0 || !defined(__XTENSA_CALL0_ABI__) + mov a9, a0 /* preserve ret addr */ + #endif + + #ifndef __XTENSA_CALL0_ABI__ + /* + To spill the reg windows, temp. need pre-interrupt stack ptr and a4-15. + Need to save a9,12,13 temporarily (in frame temps) and recover originals. + Interrupts need to be disabled below XCHAL_EXCM_LEVEL and window overflow + and underflow exceptions disabled (assured by PS.EXCM == 1). + */ + s32i a12, sp, XT_STK_TMP0 /* temp. save stuff in stack frame */ + s32i a13, sp, XT_STK_TMP1 + s32i a9, sp, XT_STK_TMP2 + + /* + Save the overlay state if we are supporting overlays. Since we just saved + three registers, we can conveniently use them here. Note that as of now, + overlays only work for windowed calling ABI. + */ + #ifdef XT_USE_OVLY + l32i a9, sp, XT_STK_PC /* recover saved PC */ + _xt_overlay_get_state a9, a12, a13 + s32i a9, sp, XT_STK_OVLY /* save overlay state */ + #endif + + l32i a12, sp, XT_STK_A12 /* recover original a9,12,13 */ + l32i a13, sp, XT_STK_A13 + l32i a9, sp, XT_STK_A9 + addi sp, sp, XT_STK_FRMSZ /* restore the interruptee's SP */ + call0 xthal_window_spill_nw /* preserves only a4,5,8,9,12,13 */ + addi sp, sp, -XT_STK_FRMSZ + l32i a12, sp, XT_STK_TMP0 /* recover stuff from stack frame */ + l32i a13, sp, XT_STK_TMP1 + l32i a9, sp, XT_STK_TMP2 + #endif + + #if XCHAL_EXTRA_SA_SIZE > 0 + /* + NOTE: Normally the xthal_save_extra_nw macro only affects address + registers a2-a5. It is theoretically possible for Xtensa processor + designers to write TIE that causes more address registers to be + affected, but it is generally unlikely. If that ever happens, + more registers need to be saved/restored around this macro invocation. + Here we assume a9,12,13 are preserved. + Future Xtensa tools releases might limit the regs that can be affected. + */ + addi a2, sp, XT_STK_EXTRA /* where to save it */ + # if XCHAL_EXTRA_SA_ALIGN > 16 + movi a3, -XCHAL_EXTRA_SA_ALIGN + and a2, a2, a3 /* align dynamically >16 bytes */ + # endif + call0 xthal_save_extra_nw /* destroys a0,2,3,4,5 */ + #endif + + #if XCHAL_EXTRA_SA_SIZE > 0 || !defined(__XTENSA_CALL0_ABI__) + mov a0, a9 /* retrieve ret addr */ + #endif + + ret + +/******************************************************************************* + +_xt_context_restore + + !! MUST BE CALLED ONLY BY 'CALL0' INSTRUCTION !! + +Restores all Xtensa processor state except PC, PS, A0, A1 (SP) (and in Call0 +ABI, A14, A15 which are preserved by all interrupt handlers) from an interrupt +stack frame defined in xtensa_rtos.h . +Its counterpart is _xt_context_save (whose caller saved A12, A13). + +Caller is responsible to restore PC, PS, A0, A1 (SP). + +Entry Conditions: + A0 = Return address in caller. + A1 = Stack pointer of interrupted thread or handler ("interruptee"). + +Exit conditions: + A0 = Return address in caller. + A1 = Stack pointer of interrupted thread or handler ("interruptee"). + Other processor state except PC, PS, A0, A1 (SP), is as at the point + of interruption. + +*******************************************************************************/ + + .global _xt_context_restore + .type _xt_context_restore,@function + .align 4 + .literal_position + .align 4 +_xt_context_restore: + + #if XCHAL_EXTRA_SA_SIZE > 0 + /* + NOTE: Normally the xthal_restore_extra_nw macro only affects address + registers a2-a5. It is theoretically possible for Xtensa processor + designers to write TIE that causes more address registers to be + affected, but it is generally unlikely. If that ever happens, + more registers need to be saved/restored around this macro invocation. + Here we only assume a13 is preserved. + Future Xtensa tools releases might limit the regs that can be affected. + */ + mov a13, a0 /* preserve ret addr */ + addi a2, sp, XT_STK_EXTRA /* where to find it */ + # if XCHAL_EXTRA_SA_ALIGN > 16 + movi a3, -XCHAL_EXTRA_SA_ALIGN + and a2, a2, a3 /* align dynamically >16 bytes */ + # endif + call0 xthal_restore_extra_nw /* destroys a0,2,3,4,5 */ + mov a0, a13 /* retrieve ret addr */ + #endif + + #if XCHAL_HAVE_LOOPS + l32i a2, sp, XT_STK_LBEG + l32i a3, sp, XT_STK_LEND + wsr a2, LBEG + l32i a2, sp, XT_STK_LCOUNT + wsr a3, LEND + wsr a2, LCOUNT + #endif + + #ifdef XT_USE_OVLY + /* + If we are using overlays, this is a good spot to check if we need + to restore an overlay for the incoming task. Here we have a bunch + of registers to spare. Note that this step is going to use a few + bytes of storage below SP (SP-20 to SP-32) if an overlay is going + to be restored. + */ + l32i a2, sp, XT_STK_PC /* retrieve PC */ + l32i a3, sp, XT_STK_PS /* retrieve PS */ + l32i a4, sp, XT_STK_OVLY /* retrieve overlay state */ + l32i a5, sp, XT_STK_A1 /* retrieve stack ptr */ + _xt_overlay_check_map a2, a3, a4, a5, a6 + s32i a2, sp, XT_STK_PC /* save updated PC */ + s32i a3, sp, XT_STK_PS /* save updated PS */ + #endif + + #ifdef XT_USE_SWPRI + /* Restore virtual interrupt priority and interrupt enable */ + movi a3, _xt_intdata + l32i a4, a3, 0 /* a4 = _xt_intenable */ + l32i a5, sp, XT_STK_VPRI /* a5 = saved _xt_vpri_mask */ + and a4, a4, a5 + wsr a4, INTENABLE /* update INTENABLE */ + s32i a5, a3, 4 /* restore _xt_vpri_mask */ + #endif + + l32i a3, sp, XT_STK_SAR + l32i a2, sp, XT_STK_A2 + wsr a3, SAR + l32i a3, sp, XT_STK_A3 + l32i a4, sp, XT_STK_A4 + l32i a5, sp, XT_STK_A5 + l32i a6, sp, XT_STK_A6 + l32i a7, sp, XT_STK_A7 + l32i a8, sp, XT_STK_A8 + l32i a9, sp, XT_STK_A9 + l32i a10, sp, XT_STK_A10 + l32i a11, sp, XT_STK_A11 + + /* + Call0 ABI callee-saved regs a12-15 do not need to be restored here. + However a12-13 were saved for scratch before XT_RTOS_INT_ENTER(), + so need to be restored anyway, despite being callee-saved in Call0. + */ + l32i a12, sp, XT_STK_A12 + l32i a13, sp, XT_STK_A13 + #ifndef __XTENSA_CALL0_ABI__ + l32i a14, sp, XT_STK_A14 + l32i a15, sp, XT_STK_A15 + #endif + + ret + + +/******************************************************************************* + +_xt_coproc_init + +Initializes global co-processor management data, setting all co-processors +to "unowned". Leaves CPENABLE as it found it (does NOT clear it). + +Called during initialization of the RTOS, before any threads run. + +This may be called from normal Xtensa single-threaded application code which +might use co-processors. The Xtensa run-time initialization enables all +co-processors. They must remain enabled here, else a co-processor exception +might occur outside of a thread, which the exception handler doesn't expect. + +Entry Conditions: + Xtensa single-threaded run-time environment is in effect. + No thread is yet running. + +Exit conditions: + None. + +Obeys ABI conventions per prototype: + void _xt_coproc_init(void) + +*******************************************************************************/ + +#if XCHAL_CP_NUM > 0 + + .global _xt_coproc_init + .type _xt_coproc_init,@function + .align 4 + .literal_position + .align 4 +_xt_coproc_init: + ENTRY0 + + /* Initialize thread co-processor ownerships to 0 (unowned). */ + movi a2, _xt_coproc_owner_sa /* a2 = base of owner array */ + addi a3, a2, (XCHAL_CP_MAX*portNUM_PROCESSORS) << 2 /* a3 = top+1 of owner array */ + movi a4, 0 /* a4 = 0 (unowned) */ +1: s32i a4, a2, 0 + addi a2, a2, 4 + bltu a2, a3, 1b + + RET0 + +#endif + + +/******************************************************************************* + +_xt_coproc_release + +Releases any and all co-processors owned by a given thread. The thread is +identified by it's co-processor state save area defined in xtensa_context.h . + +Must be called before a thread's co-proc save area is deleted to avoid +memory corruption when the exception handler tries to save the state. +May be called when a thread terminates or completes but does not delete +the co-proc save area, to avoid the exception handler having to save the +thread's co-proc state before another thread can use it (optimization). + +Entry Conditions: + A2 = Pointer to base of co-processor state save area. + +Exit conditions: + None. + +Obeys ABI conventions per prototype: + void _xt_coproc_release(void * coproc_sa_base) + +*******************************************************************************/ + +#if XCHAL_CP_NUM > 0 + + .global _xt_coproc_release + .type _xt_coproc_release,@function + .align 4 + .literal_position + .align 4 +_xt_coproc_release: + ENTRY0 /* a2 = base of save area */ + + getcoreid a5 + movi a3, XCHAL_CP_MAX << 2 + mull a5, a5, a3 + movi a3, _xt_coproc_owner_sa /* a3 = base of owner array */ + add a3, a3, a5 + + addi a4, a3, XCHAL_CP_MAX << 2 /* a4 = top+1 of owner array */ + movi a5, 0 /* a5 = 0 (unowned) */ + + rsil a6, XCHAL_EXCM_LEVEL /* lock interrupts */ + +1: l32i a7, a3, 0 /* a7 = owner at a3 */ + bne a2, a7, 2f /* if (coproc_sa_base == owner) */ + s32i a5, a3, 0 /* owner = unowned */ +2: addi a3, a3, 1<<2 /* a3 = next entry in owner array */ + bltu a3, a4, 1b /* repeat until end of array */ + +3: wsr a6, PS /* restore interrupts */ + + RET0 + +#endif + + +/******************************************************************************* +_xt_coproc_savecs + +If there is a current thread and it has a coprocessor state save area, then +save all callee-saved state into this area. This function is called from the +solicited context switch handler. It calls a system-specific function to get +the coprocessor save area base address. + +Entry conditions: + - The thread being switched out is still the current thread. + - CPENABLE state reflects which coprocessors are active. + - Registers have been saved/spilled already. + +Exit conditions: + - All necessary CP callee-saved state has been saved. + - Registers a2-a7, a13-a15 have been trashed. + +Must be called from assembly code only, using CALL0. +*******************************************************************************/ +#if XCHAL_CP_NUM > 0 + + .extern _xt_coproc_sa_offset /* external reference */ + + .global _xt_coproc_savecs + .type _xt_coproc_savecs,@function + .align 4 + .literal_position + .align 4 +_xt_coproc_savecs: + + /* At entry, CPENABLE should be showing which CPs are enabled. */ + + rsr a2, CPENABLE /* a2 = which CPs are enabled */ + beqz a2, .Ldone /* quick exit if none */ + mov a14, a0 /* save return address */ + call0 XT_RTOS_CP_STATE /* get address of CP save area */ + mov a0, a14 /* restore return address */ + beqz a15, .Ldone /* if none then nothing to do */ + s16i a2, a15, XT_CP_CS_ST /* save mask of CPs being stored */ + movi a13, _xt_coproc_sa_offset /* array of CP save offsets */ + l32i a15, a15, XT_CP_ASA /* a15 = base of aligned save area */ + +#if XCHAL_CP0_SA_SIZE + bbci.l a2, 0, 2f /* CP 0 not enabled */ + l32i a14, a13, 0 /* a14 = _xt_coproc_sa_offset[0] */ + add a3, a14, a15 /* a3 = save area for CP 0 */ + xchal_cp0_store a3, a4, a5, a6, a7 continue=0 ofs=-1 select=XTHAL_SAS_TIE|XTHAL_SAS_NOCC|XTHAL_SAS_CALE alloc=XTHAL_SAS_ALL +2: +#endif + +#if XCHAL_CP1_SA_SIZE + bbci.l a2, 1, 2f /* CP 1 not enabled */ + l32i a14, a13, 4 /* a14 = _xt_coproc_sa_offset[1] */ + add a3, a14, a15 /* a3 = save area for CP 1 */ + xchal_cp1_store a3, a4, a5, a6, a7 continue=0 ofs=-1 select=XTHAL_SAS_TIE|XTHAL_SAS_NOCC|XTHAL_SAS_CALE alloc=XTHAL_SAS_ALL +2: +#endif + +#if XCHAL_CP2_SA_SIZE + bbci.l a2, 2, 2f + l32i a14, a13, 8 + add a3, a14, a15 + xchal_cp2_store a3, a4, a5, a6, a7 continue=0 ofs=-1 select=XTHAL_SAS_TIE|XTHAL_SAS_NOCC|XTHAL_SAS_CALE alloc=XTHAL_SAS_ALL +2: +#endif + +#if XCHAL_CP3_SA_SIZE + bbci.l a2, 3, 2f + l32i a14, a13, 12 + add a3, a14, a15 + xchal_cp3_store a3, a4, a5, a6, a7 continue=0 ofs=-1 select=XTHAL_SAS_TIE|XTHAL_SAS_NOCC|XTHAL_SAS_CALE alloc=XTHAL_SAS_ALL +2: +#endif + +#if XCHAL_CP4_SA_SIZE + bbci.l a2, 4, 2f + l32i a14, a13, 16 + add a3, a14, a15 + xchal_cp4_store a3, a4, a5, a6, a7 continue=0 ofs=-1 select=XTHAL_SAS_TIE|XTHAL_SAS_NOCC|XTHAL_SAS_CALE alloc=XTHAL_SAS_ALL +2: +#endif + +#if XCHAL_CP5_SA_SIZE + bbci.l a2, 5, 2f + l32i a14, a13, 20 + add a3, a14, a15 + xchal_cp5_store a3, a4, a5, a6, a7 continue=0 ofs=-1 select=XTHAL_SAS_TIE|XTHAL_SAS_NOCC|XTHAL_SAS_CALE alloc=XTHAL_SAS_ALL +2: +#endif + +#if XCHAL_CP6_SA_SIZE + bbci.l a2, 6, 2f + l32i a14, a13, 24 + add a3, a14, a15 + xchal_cp6_store a3, a4, a5, a6, a7 continue=0 ofs=-1 select=XTHAL_SAS_TIE|XTHAL_SAS_NOCC|XTHAL_SAS_CALE alloc=XTHAL_SAS_ALL +2: +#endif + +#if XCHAL_CP7_SA_SIZE + bbci.l a2, 7, 2f + l32i a14, a13, 28 + add a3, a14, a15 + xchal_cp7_store a3, a4, a5, a6, a7 continue=0 ofs=-1 select=XTHAL_SAS_TIE|XTHAL_SAS_NOCC|XTHAL_SAS_CALE alloc=XTHAL_SAS_ALL +2: +#endif + +.Ldone: + ret +#endif + + +/******************************************************************************* +_xt_coproc_restorecs + +Restore any callee-saved coprocessor state for the incoming thread. +This function is called from coprocessor exception handling, when giving +ownership to a thread that solicited a context switch earlier. It calls a +system-specific function to get the coprocessor save area base address. + +Entry conditions: + - The incoming thread is set as the current thread. + - CPENABLE is set up correctly for all required coprocessors. + - a2 = mask of coprocessors to be restored. + +Exit conditions: + - All necessary CP callee-saved state has been restored. + - CPENABLE - unchanged. + - Registers a2-a7, a13-a15 have been trashed. + +Must be called from assembly code only, using CALL0. +*******************************************************************************/ +#if XCHAL_CP_NUM > 0 + + .global _xt_coproc_restorecs + .type _xt_coproc_restorecs,@function + .align 4 + .literal_position + .align 4 +_xt_coproc_restorecs: + + mov a14, a0 /* save return address */ + call0 XT_RTOS_CP_STATE /* get address of CP save area */ + mov a0, a14 /* restore return address */ + beqz a15, .Ldone2 /* if none then nothing to do */ + l16ui a3, a15, XT_CP_CS_ST /* a3 = which CPs have been saved */ + xor a3, a3, a2 /* clear the ones being restored */ + s32i a3, a15, XT_CP_CS_ST /* update saved CP mask */ + movi a13, _xt_coproc_sa_offset /* array of CP save offsets */ + l32i a15, a15, XT_CP_ASA /* a15 = base of aligned save area */ + +#if XCHAL_CP0_SA_SIZE + bbci.l a2, 0, 2f /* CP 0 not enabled */ + l32i a14, a13, 0 /* a14 = _xt_coproc_sa_offset[0] */ + add a3, a14, a15 /* a3 = save area for CP 0 */ + xchal_cp0_load a3, a4, a5, a6, a7 continue=0 ofs=-1 select=XTHAL_SAS_TIE|XTHAL_SAS_NOCC|XTHAL_SAS_CALE alloc=XTHAL_SAS_ALL +2: +#endif + +#if XCHAL_CP1_SA_SIZE + bbci.l a2, 1, 2f /* CP 1 not enabled */ + l32i a14, a13, 4 /* a14 = _xt_coproc_sa_offset[1] */ + add a3, a14, a15 /* a3 = save area for CP 1 */ + xchal_cp1_load a3, a4, a5, a6, a7 continue=0 ofs=-1 select=XTHAL_SAS_TIE|XTHAL_SAS_NOCC|XTHAL_SAS_CALE alloc=XTHAL_SAS_ALL +2: +#endif + +#if XCHAL_CP2_SA_SIZE + bbci.l a2, 2, 2f + l32i a14, a13, 8 + add a3, a14, a15 + xchal_cp2_load a3, a4, a5, a6, a7 continue=0 ofs=-1 select=XTHAL_SAS_TIE|XTHAL_SAS_NOCC|XTHAL_SAS_CALE alloc=XTHAL_SAS_ALL +2: +#endif + +#if XCHAL_CP3_SA_SIZE + bbci.l a2, 3, 2f + l32i a14, a13, 12 + add a3, a14, a15 + xchal_cp3_load a3, a4, a5, a6, a7 continue=0 ofs=-1 select=XTHAL_SAS_TIE|XTHAL_SAS_NOCC|XTHAL_SAS_CALE alloc=XTHAL_SAS_ALL +2: +#endif + +#if XCHAL_CP4_SA_SIZE + bbci.l a2, 4, 2f + l32i a14, a13, 16 + add a3, a14, a15 + xchal_cp4_load a3, a4, a5, a6, a7 continue=0 ofs=-1 select=XTHAL_SAS_TIE|XTHAL_SAS_NOCC|XTHAL_SAS_CALE alloc=XTHAL_SAS_ALL +2: +#endif + +#if XCHAL_CP5_SA_SIZE + bbci.l a2, 5, 2f + l32i a14, a13, 20 + add a3, a14, a15 + xchal_cp5_load a3, a4, a5, a6, a7 continue=0 ofs=-1 select=XTHAL_SAS_TIE|XTHAL_SAS_NOCC|XTHAL_SAS_CALE alloc=XTHAL_SAS_ALL +2: +#endif + +#if XCHAL_CP6_SA_SIZE + bbci.l a2, 6, 2f + l32i a14, a13, 24 + add a3, a14, a15 + xchal_cp6_load a3, a4, a5, a6, a7 continue=0 ofs=-1 select=XTHAL_SAS_TIE|XTHAL_SAS_NOCC|XTHAL_SAS_CALE alloc=XTHAL_SAS_ALL +2: +#endif + +#if XCHAL_CP7_SA_SIZE + bbci.l a2, 7, 2f + l32i a14, a13, 28 + add a3, a14, a15 + xchal_cp7_load a3, a4, a5, a6, a7 continue=0 ofs=-1 select=XTHAL_SAS_TIE|XTHAL_SAS_NOCC|XTHAL_SAS_CALE alloc=XTHAL_SAS_ALL +2: +#endif + +.Ldone2: + ret + +#endif + + diff --git a/components/freertos/xtensa_init.c b/components/freertos/xtensa_init.c new file mode 100644 index 0000000000..ded8df1098 --- /dev/null +++ b/components/freertos/xtensa_init.c @@ -0,0 +1,65 @@ +/******************************************************************************* +// Copyright (c) 2003-2015 Cadence Design Systems, Inc. +// +// Permission is hereby granted, free of charge, to any person obtaining +// a copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to +// permit persons to whom the Software is furnished to do so, subject to +// the following conditions: +// +// The above copyright notice and this permission notice shall be included +// in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +// CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +// SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +-------------------------------------------------------------------------------- + + XTENSA INITIALIZATION ROUTINES CODED IN C + +This file contains miscellaneous Xtensa RTOS-generic initialization functions +that are implemented in C. + +*******************************************************************************/ + + +#ifdef XT_BOARD +#include +#endif + +#include "xtensa_rtos.h" + +#ifdef XT_RTOS_TIMER_INT + +unsigned _xt_tick_divisor = 0; /* cached number of cycles per tick */ + +/* +Compute and initialize at run-time the tick divisor (the number of +processor clock cycles in an RTOS tick, used to set the tick timer). +Called when the processor clock frequency is not known at compile-time. +*/ +void _xt_tick_divisor_init(void) +{ +#ifdef XT_CLOCK_FREQ + + _xt_tick_divisor = (XT_CLOCK_FREQ / XT_TICK_PER_SEC); + +#else + + #ifdef XT_BOARD + _xt_tick_divisor = xtbsp_clock_freq_hz() / XT_TICK_PER_SEC; + #else + #error "No way to obtain processor clock frequency" + #endif /* XT_BOARD */ + +#endif /* XT_CLOCK_FREQ */ +} + +#endif /* XT_RTOS_TIMER_INT */ + diff --git a/components/freertos/xtensa_intr.c b/components/freertos/xtensa_intr.c new file mode 100644 index 0000000000..f5ca7d151f --- /dev/null +++ b/components/freertos/xtensa_intr.c @@ -0,0 +1,138 @@ +/******************************************************************************* +Copyright (c) 2006-2015 Cadence Design Systems Inc. + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be included +in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +******************************************************************************/ + +/****************************************************************************** + Xtensa-specific interrupt and exception functions for RTOS ports. + Also see xtensa_intr_asm.S. +******************************************************************************/ + +#include + +#include + +#include "freertos/xtensa_api.h" + +#include "rom/ets_sys.h" + +#if XCHAL_HAVE_EXCEPTIONS + +/* Handler table is in xtensa_intr_asm.S */ +// Todo: Make multicore - JD + +extern xt_exc_handler _xt_exception_table[XCHAL_EXCCAUSE_NUM]; + + +/* + Default handler for unhandled exceptions. + CHANGED: We do this in panic.c now +*/ + +//void xt_unhandled_exception(XtExcFrame *frame) +//{ + //exit(-1); +//} +extern void xt_unhandled_exception(XtExcFrame *frame); + + +/* + This function registers a handler for the specified exception. + The function returns the address of the previous handler. + On error, it returns 0. +*/ +xt_exc_handler xt_set_exception_handler(int n, xt_exc_handler f) +{ + xt_exc_handler old; + + if( n < 0 || n >= XCHAL_EXCCAUSE_NUM ) + return 0; /* invalid exception number */ + + old = _xt_exception_table[n]; + + if (f) { + _xt_exception_table[n] = f; + } + else { + _xt_exception_table[n] = &xt_unhandled_exception; + } + + return ((old == &xt_unhandled_exception) ? 0 : old); +} + +#endif + +#if XCHAL_HAVE_INTERRUPTS + +/* Handler table is in xtensa_intr_asm.S */ + +typedef struct xt_handler_table_entry { + void * handler; + void * arg; +} xt_handler_table_entry; + +extern xt_handler_table_entry _xt_interrupt_table[XCHAL_NUM_INTERRUPTS]; + + +/* + Default handler for unhandled interrupts. +*/ +void xt_unhandled_interrupt(void * arg) +{ + ets_printf("Unhandled interrupt!\n"); + //exit(-1); +} + + +/* + This function registers a handler for the specified interrupt. The "arg" + parameter specifies the argument to be passed to the handler when it is + invoked. The function returns the address of the previous handler. + On error, it returns 0. +*/ +xt_handler xt_set_interrupt_handler(int n, xt_handler f, void * arg) +{ + xt_handler_table_entry * entry; + xt_handler old; + + if( n < 0 || n >= XCHAL_NUM_INTERRUPTS ) + return 0; /* invalid interrupt number */ + if( Xthal_intlevel[n] > XCHAL_EXCM_LEVEL ) + return 0; /* priority level too high to safely handle in C */ + + entry = _xt_interrupt_table + n; + old = entry->handler; + + if (f) { + entry->handler = f; + entry->arg = arg; + } + else { + entry->handler = &xt_unhandled_interrupt; + entry->arg = (void*)n; + } + + return ((old == &xt_unhandled_interrupt) ? 0 : old); +} + + +#endif /* XCHAL_HAVE_INTERRUPTS */ + diff --git a/components/freertos/xtensa_intr_asm.S b/components/freertos/xtensa_intr_asm.S new file mode 100644 index 0000000000..5f9890dfe4 --- /dev/null +++ b/components/freertos/xtensa_intr_asm.S @@ -0,0 +1,179 @@ +/******************************************************************************* +Copyright (c) 2006-2015 Cadence Design Systems Inc. + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be included +in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +******************************************************************************/ + +/****************************************************************************** + Xtensa interrupt handling data and assembly routines. + Also see xtensa_intr.c and xtensa_vectors.S. +******************************************************************************/ + +#include +#include + +#include "xtensa_context.h" + +#if XCHAL_HAVE_INTERRUPTS + +/* +------------------------------------------------------------------------------- + INTENABLE virtualization information. +------------------------------------------------------------------------------- +*/ + + .data + .global _xt_intdata + .align 8 +_xt_intdata: + .global _xt_intenable + .type _xt_intenable,@object + .size _xt_intenable,4 + .global _xt_vpri_mask + .type _xt_vpri_mask,@object + .size _xt_vpri_mask,4 + +_xt_intenable: .word 0 /* Virtual INTENABLE */ +_xt_vpri_mask: .word 0xFFFFFFFF /* Virtual priority mask */ + + +/* +------------------------------------------------------------------------------- + Table of C-callable interrupt handlers for each interrupt. Note that not all + slots can be filled, because interrupts at level > EXCM_LEVEL will not be + dispatched to a C handler by default. +------------------------------------------------------------------------------- +*/ + + .data + .global _xt_interrupt_table + .align 8 + +_xt_interrupt_table: + + .set i, 0 + .rept XCHAL_NUM_INTERRUPTS + .word xt_unhandled_interrupt /* handler address */ + .word i /* handler arg (default: intnum) */ + .set i, i+1 + .endr + +#endif /* XCHAL_HAVE_INTERRUPTS */ + + +#if XCHAL_HAVE_EXCEPTIONS + +/* +------------------------------------------------------------------------------- + Table of C-callable exception handlers for each exception. Note that not all + slots will be active, because some exceptions (e.g. coprocessor exceptions) + are always handled by the OS and cannot be hooked by user handlers. +------------------------------------------------------------------------------- +*/ + + .data + .global _xt_exception_table + .align 4 + +_xt_exception_table: + .rept XCHAL_EXCCAUSE_NUM + .word xt_unhandled_exception /* handler address */ + .endr + +#endif + + +/* +------------------------------------------------------------------------------- + unsigned int xt_ints_on ( unsigned int mask ) + + Enables a set of interrupts. Does not simply set INTENABLE directly, but + computes it as a function of the current virtual priority. + Can be called from interrupt handlers. +------------------------------------------------------------------------------- +*/ + + .text + .align 4 + .global xt_ints_on + .type xt_ints_on,@function + +xt_ints_on: + + ENTRY0 +#if XCHAL_HAVE_INTERRUPTS + movi a3, 0 + movi a4, _xt_intdata + xsr a3, INTENABLE /* Disables all interrupts */ + rsync + l32i a3, a4, 0 /* a3 = _xt_intenable */ + l32i a6, a4, 4 /* a6 = _xt_vpri_mask */ + or a5, a3, a2 /* a5 = _xt_intenable | mask */ + s32i a5, a4, 0 /* _xt_intenable |= mask */ + and a5, a5, a6 /* a5 = _xt_intenable & _xt_vpri_mask */ + wsr a5, INTENABLE /* Reenable interrupts */ + mov a2, a3 /* Previous mask */ +#else + movi a2, 0 /* Return zero */ +#endif + RET0 + + .size xt_ints_on, . - xt_ints_on + + +/* +------------------------------------------------------------------------------- + unsigned int xt_ints_off ( unsigned int mask ) + + Disables a set of interrupts. Does not simply set INTENABLE directly, + but computes it as a function of the current virtual priority. + Can be called from interrupt handlers. +------------------------------------------------------------------------------- +*/ + + .text + .align 4 + .global xt_ints_off + .type xt_ints_off,@function + +xt_ints_off: + + ENTRY0 +#if XCHAL_HAVE_INTERRUPTS + movi a3, 0 + movi a4, _xt_intdata + xsr a3, INTENABLE /* Disables all interrupts */ + rsync + l32i a3, a4, 0 /* a3 = _xt_intenable */ + l32i a6, a4, 4 /* a6 = _xt_vpri_mask */ + or a5, a3, a2 /* a5 = _xt_intenable | mask */ + xor a5, a5, a2 /* a5 = _xt_intenable & ~mask */ + s32i a5, a4, 0 /* _xt_intenable &= ~mask */ + and a5, a5, a6 /* a5 = _xt_intenable & _xt_vpri_mask */ + wsr a5, INTENABLE /* Reenable interrupts */ + mov a2, a3 /* Previous mask */ +#else + movi a2, 0 /* return zero */ +#endif + RET0 + + .size xt_ints_off, . - xt_ints_off + + diff --git a/components/freertos/xtensa_overlay_os_hook.c b/components/freertos/xtensa_overlay_os_hook.c new file mode 100644 index 0000000000..a5ca23ceef --- /dev/null +++ b/components/freertos/xtensa_overlay_os_hook.c @@ -0,0 +1,67 @@ +// xtensa_overlay_os_hook.c -- Overlay manager OS hooks for FreeRTOS. + +// Copyright (c) 2015-2015 Cadence Design Systems Inc. +// +// Permission is hereby granted, free of charge, to any person obtaining +// a copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to +// permit persons to whom the Software is furnished to do so, subject to +// the following conditions: +// +// The above copyright notice and this permission notice shall be included +// in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +// CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +// SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + + +#include "FreeRTOS.h" +#include "semphr.h" + +#if configUSE_MUTEX + +/* Mutex object that controls access to the overlay. Currently only one + * overlay region is supported so one mutex suffices. + */ +static SemaphoreHandle_t xt_overlay_mutex; + + +/* This function should be overridden to provide OS specific init such + * as the creation of a mutex lock that can be used for overlay locking. + * Typically this mutex would be set up with priority inheritance. See + * overlay manager documentation for more details. + */ +void xt_overlay_init_os(void) +{ + /* Create the mutex for overlay access. Priority inheritance is + * required. + */ + xt_overlay_mutex = xSemaphoreCreateMutex(); +} + + +/* This function locks access to shared overlay resources, typically + * by acquiring a mutex. + */ +void xt_overlay_lock(void) +{ + xSemaphoreTake(xt_overlay_mutex, 0); +} + + +/* This function releases access to shared overlay resources, typically + * by unlocking a mutex. + */ +void xt_overlay_unlock(void) +{ + xSemaphoreGive(xt_overlay_mutex); +} + +#endif diff --git a/components/freertos/xtensa_vectors.S b/components/freertos/xtensa_vectors.S new file mode 100644 index 0000000000..0ff6c4c19b --- /dev/null +++ b/components/freertos/xtensa_vectors.S @@ -0,0 +1,1980 @@ +/******************************************************************************* +Copyright (c) 2006-2015 Cadence Design Systems Inc. + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be included +in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +-------------------------------------------------------------------------------- + + XTENSA VECTORS AND LOW LEVEL HANDLERS FOR AN RTOS + + Xtensa low level exception and interrupt vectors and handlers for an RTOS. + + Interrupt handlers and user exception handlers support interaction with + the RTOS by calling XT_RTOS_INT_ENTER and XT_RTOS_INT_EXIT before and + after user's specific interrupt handlers. These macros are defined in + xtensa_.h to call suitable functions in a specific RTOS. + + Users can install application-specific interrupt handlers for low and + medium level interrupts, by calling xt_set_interrupt_handler(). These + handlers can be written in C, and must obey C calling convention. The + handler table is indexed by the interrupt number. Each handler may be + provided with an argument. + + Note that the system timer interrupt is handled specially, and is + dispatched to the RTOS-specific handler. This timer cannot be hooked + by application code. + + Optional hooks are also provided to install a handler per level at + run-time, made available by compiling this source file with + '-DXT_INTEXC_HOOKS' (useful for automated testing). + +!! This file is a template that usually needs to be modified to handle !! +!! application specific interrupts. Search USER_EDIT for helpful comments !! +!! on where to insert handlers and how to write them. !! + + Users can also install application-specific exception handlers in the + same way, by calling xt_set_exception_handler(). One handler slot is + provided for each exception type. Note that some exceptions are handled + by the porting layer itself, and cannot be taken over by application + code in this manner. These are the alloca, syscall, and coprocessor + exceptions. + + The exception handlers can be written in C, and must follow C calling + convention. Each handler is passed a pointer to an exception frame as + its single argument. The exception frame is created on the stack, and + holds the saved context of the thread that took the exception. If the + handler returns, the context will be restored and the instruction that + caused the exception will be retried. If the handler makes any changes + to the saved state in the exception frame, the changes will be applied + when restoring the context. + + Because Xtensa is a configurable architecture, this port supports all user + generated configurations (except restrictions stated in the release notes). + This is accomplished by conditional compilation using macros and functions + defined in the Xtensa HAL (hardware adaptation layer) for your configuration. + Only the relevant parts of this file will be included in your RTOS build. + For example, this file provides interrupt vector templates for all types and + all priority levels, but only the ones in your configuration are built. + + NOTES on the use of 'call0' for long jumps instead of 'j': + 1. This file should be assembled with the -mlongcalls option to xt-xcc. + 2. The -mlongcalls compiler option causes 'call0 dest' to be expanded to + a sequence 'l32r a0, dest' 'callx0 a0' which works regardless of the + distance from the call to the destination. The linker then relaxes + it back to 'call0 dest' if it determines that dest is within range. + This allows more flexibility in locating code without the performance + overhead of the 'l32r' literal data load in cases where the destination + is in range of 'call0'. There is an additional benefit in that 'call0' + has a longer range than 'j' due to the target being word-aligned, so + the 'l32r' sequence is less likely needed. + 3. The use of 'call0' with -mlongcalls requires that register a0 not be + live at the time of the call, which is always the case for a function + call but needs to be ensured if 'call0' is used as a jump in lieu of 'j'. + 4. This use of 'call0' is independent of the C function call ABI. + +*******************************************************************************/ + +#include "xtensa_rtos.h" + + +/* Enable stack backtrace across exception/interrupt - see below */ +#define XT_DEBUG_BACKTRACE 0 + + +/* +-------------------------------------------------------------------------------- + Defines used to access _xtos_interrupt_table. +-------------------------------------------------------------------------------- +*/ +#define XIE_HANDLER 0 +#define XIE_ARG 4 +#define XIE_SIZE 8 + +/* +-------------------------------------------------------------------------------- + Macro extract_msb - return the input with only the highest bit set. + + Input : "ain" - Input value, clobbered. + Output : "aout" - Output value, has only one bit set, MSB of "ain". + The two arguments must be different AR registers. +-------------------------------------------------------------------------------- +*/ + + .macro extract_msb aout ain +1: + addi \aout, \ain, -1 /* aout = ain - 1 */ + and \ain, \ain, \aout /* ain = ain & aout */ + bnez \ain, 1b /* repeat until ain == 0 */ + addi \aout, \aout, 1 /* return aout + 1 */ + .endm + +/* +-------------------------------------------------------------------------------- + Macro dispatch_c_isr - dispatch interrupts to user ISRs. + This will dispatch to user handlers (if any) that are registered in the + XTOS dispatch table (_xtos_interrupt_table). These handlers would have + been registered by calling _xtos_set_interrupt_handler(). There is one + exception - the timer interrupt used by the OS will not be dispatched + to a user handler - this must be handled by the caller of this macro. + + Level triggered and software interrupts are automatically deasserted by + this code. + + ASSUMPTIONS: + -- PS.INTLEVEL is set to "level" at entry + -- PS.EXCM = 0, C calling enabled + + NOTE: For CALL0 ABI, a12-a15 have not yet been saved. + + NOTE: This macro will use registers a0 and a2-a6. The arguments are: + level -- interrupt level + mask -- interrupt bitmask for this level +-------------------------------------------------------------------------------- +*/ + + .macro dispatch_c_isr level mask + + /* Get mask of pending, enabled interrupts at this level into a2. */ + +.L_xt_user_int_&level&: + rsr a2, INTENABLE + rsr a3, INTERRUPT + movi a4, \mask + and a2, a2, a3 + and a2, a2, a4 + beqz a2, 9f /* nothing to do */ + + /* This bit of code provides a nice debug backtrace in the debugger. + It does take a few more instructions, so undef XT_DEBUG_BACKTRACE + if you want to save the cycles. + */ + #if XT_DEBUG_BACKTRACE + #ifndef __XTENSA_CALL0_ABI__ + rsr a0, EPC_1 + \level - 1 /* return address */ + movi a4, 0xC0000000 /* constant with top 2 bits set (call size) */ + or a0, a0, a4 /* set top 2 bits */ + addx2 a0, a4, a0 /* clear top bit -- simulating call4 size */ + #endif + #endif + + #ifdef XT_INTEXC_HOOKS + /* Call interrupt hook if present to (pre)handle interrupts. */ + movi a4, _xt_intexc_hooks + l32i a4, a4, \level << 2 + beqz a4, 2f + #ifdef __XTENSA_CALL0_ABI__ + callx0 a4 + beqz a2, 9f + #else + mov a6, a2 + callx4 a4 + beqz a6, 9f + mov a2, a6 + #endif +2: + #endif + + /* Now look up in the dispatch table and call user ISR if any. */ + /* If multiple bits are set then MSB has highest priority. */ + + extract_msb a4, a2 /* a4 = MSB of a2, a2 trashed */ + + #ifdef XT_USE_SWPRI + /* Enable all interrupts at this level that are numerically higher + than the one we just selected, since they are treated as higher + priority. + */ + movi a3, \mask /* a3 = all interrupts at this level */ + add a2, a4, a4 /* a2 = a4 << 1 */ + addi a2, a2, -1 /* a2 = mask of 1's <= a4 bit */ + and a2, a2, a3 /* a2 = mask of all bits <= a4 at this level */ + movi a3, _xt_intdata + l32i a6, a3, 4 /* a6 = _xt_vpri_mask */ + neg a2, a2 + addi a2, a2, -1 /* a2 = mask to apply */ + and a5, a6, a2 /* mask off all bits <= a4 bit */ + s32i a5, a3, 4 /* update _xt_vpri_mask */ + rsr a3, INTENABLE + and a3, a3, a2 /* mask off all bits <= a4 bit */ + wsr a3, INTENABLE + rsil a3, \level - 1 /* lower interrupt level by 1 */ + #endif + + movi a3, XT_TIMER_INTEN /* a3 = timer interrupt bit */ + wsr a4, INTCLEAR /* clear sw or edge-triggered interrupt */ + beq a3, a4, 7f /* if timer interrupt then skip table */ + + find_ms_setbit a3, a4, a3, 0 /* a3 = interrupt number */ + + movi a4, _xt_interrupt_table + addx8 a3, a3, a4 /* a3 = address of interrupt table entry */ + l32i a4, a3, XIE_HANDLER /* a4 = handler address */ + #ifdef __XTENSA_CALL0_ABI__ + mov a12, a6 /* save in callee-saved reg */ + l32i a2, a3, XIE_ARG /* a2 = handler arg */ + callx0 a4 /* call handler */ + mov a2, a12 + #else + mov a2, a6 /* save in windowed reg */ + l32i a6, a3, XIE_ARG /* a6 = handler arg */ + callx4 a4 /* call handler */ + #endif + + #ifdef XT_USE_SWPRI + j 8f + #else + j .L_xt_user_int_&level& /* check for more interrupts */ + #endif + +7: + + .ifeq XT_TIMER_INTPRI - \level +.L_xt_user_int_timer_&level&: + /* + Interrupt handler for the RTOS tick timer if at this level. + We'll be reading the interrupt state again after this call + so no need to preserve any registers except a6 (vpri_mask). + */ + + #ifdef __XTENSA_CALL0_ABI__ + mov a12, a6 + call0 XT_RTOS_TIMER_INT + mov a2, a12 + #else + mov a2, a6 + call4 XT_RTOS_TIMER_INT + #endif + .endif + + #ifdef XT_USE_SWPRI + j 8f + #else + j .L_xt_user_int_&level& /* check for more interrupts */ + #endif + + #ifdef XT_USE_SWPRI +8: + /* Restore old value of _xt_vpri_mask from a2. Also update INTENABLE from + virtual _xt_intenable which _could_ have changed during interrupt + processing. */ + + movi a3, _xt_intdata + l32i a4, a3, 0 /* a4 = _xt_intenable */ + s32i a2, a3, 4 /* update _xt_vpri_mask */ + and a4, a4, a2 /* a4 = masked intenable */ + wsr a4, INTENABLE /* update INTENABLE */ + #endif + +9: + /* done */ + + .endm + + +/* +-------------------------------------------------------------------------------- + Panic handler. + Should be reached by call0 (preferable) or jump only. If call0, a0 says where + from. If on simulator, display panic message and abort, else loop indefinitely. +-------------------------------------------------------------------------------- +*/ + + .section .iram1,"ax" + .global panicHandler + + .global _xt_panic + .type _xt_panic,@function + .align 4 + .literal_position + .align 4 + +_xt_panic: + /* Allocate exception frame and save minimal context. */ + mov a0, sp + addi sp, sp, -XT_STK_FRMSZ + s32i a0, sp, XT_STK_A1 + #if XCHAL_HAVE_WINDOWED + s32e a0, sp, -12 /* for debug backtrace */ + #endif + rsr a0, PS /* save interruptee's PS */ + s32i a0, sp, XT_STK_PS + rsr a0, EPC_1 /* save interruptee's PC */ + s32i a0, sp, XT_STK_PC + #if XCHAL_HAVE_WINDOWED + s32e a0, sp, -16 /* for debug backtrace */ + #endif + s32i a12, sp, XT_STK_A12 /* _xt_context_save requires A12- */ + s32i a13, sp, XT_STK_A13 /* A13 to have already been saved */ + call0 _xt_context_save + + /* Save exc cause and vaddr into exception frame */ + rsr a0, EXCCAUSE + s32i a0, sp, XT_STK_EXCCAUSE + rsr a0, EXCVADDR + s32i a0, sp, XT_STK_EXCVADDR + + /* _xt_context_save seems to save the current a0, but we need the interuptees a0. Fix this. */ + rsr a0, EXCSAVE_1 /* save interruptee's a0 */ + s32i a0, sp, XT_STK_A0 + + /* Set up PS for C, reenable hi-pri interrupts, and clear EXCM. */ + movi a0, PS_INTLEVEL(XCHAL_EXCM_LEVEL) | PS_UM | PS_WOE + wsr a0, PS + + //Call panic handler + mov a2,sp + call4 panicHandler + +1: j 1b /* loop infinitely */ + + retw + + + .align 4 +//Call using call0. Prints the hex char in a2. Kills a3, a4, a5 +panic_print_hex: + movi a3,0x60000000 + movi a4,8 +panic_print_hex_loop: + l32i a5, a3, 0x1c + extui a5, a5, 16, 8 + bgei a5,64,panic_print_hex_loop + + srli a5,a2,28 + bgei a5,10,panic_print_hex_a + addi a5,a5,'0' + j panic_print_hex_ok +panic_print_hex_a: + addi a5,a5,'A'-10 +panic_print_hex_ok: + s32i a5,a3,0 + slli a2,a2,4 + + addi a4,a4,-1 + bnei a4,0,panic_print_hex_loop + movi a5,' ' + s32i a5,a3,0 + + ret + + + + .section .rodata, "a" + .align 4 + + + +/* +-------------------------------------------------------------------------------- + Hooks to dynamically install handlers for exceptions and interrupts. + Allows automated regression frameworks to install handlers per test. + Consists of an array of function pointers indexed by interrupt level, + with index 0 containing the entry for user exceptions. + Initialized with all 0s, meaning no handler is installed at each level. + See comment in xtensa_rtos.h for more details. +-------------------------------------------------------------------------------- +*/ + + #ifdef XT_INTEXC_HOOKS + .data + .global _xt_intexc_hooks + .type _xt_intexc_hooks,@object + .align 4 + +_xt_intexc_hooks: + .fill XT_INTEXC_HOOK_NUM, 4, 0 + #endif + + +/* +-------------------------------------------------------------------------------- + EXCEPTION AND LEVEL 1 INTERRUPT VECTORS AND LOW LEVEL HANDLERS + (except window exception vectors). + + Each vector goes at a predetermined location according to the Xtensa + hardware configuration, which is ensured by its placement in a special + section known to the Xtensa linker support package (LSP). It performs + the minimum necessary before jumping to the handler in the .text section. + + The corresponding handler goes in the normal .text section. It sets up + the appropriate stack frame, saves a few vector-specific registers and + calls XT_RTOS_INT_ENTER to save the rest of the interrupted context + and enter the RTOS, then sets up a C environment. It then calls the + user's interrupt handler code (which may be coded in C) and finally + calls XT_RTOS_INT_EXIT to transfer control to the RTOS for scheduling. + + While XT_RTOS_INT_EXIT does not return directly to the interruptee, + eventually the RTOS scheduler will want to dispatch the interrupted + task or handler. The scheduler will return to the exit point that was + saved in the interrupt stack frame at XT_STK_EXIT. +-------------------------------------------------------------------------------- +*/ + + +/* +-------------------------------------------------------------------------------- +Debug Exception. +-------------------------------------------------------------------------------- +*/ + +#if XCHAL_HAVE_DEBUG + + .begin literal_prefix .DebugExceptionVector + .section .DebugExceptionVector.text, "ax" + .global _DebugExceptionVector + .align 4 + +_DebugExceptionVector: + + #ifdef XT_SIMULATOR + /* + In the simulator, let the debugger (if any) handle the debug exception, + or simply stop the simulation: + */ + wsr a2, EXCSAVE+XCHAL_DEBUGLEVEL /* save a2 where sim expects it */ + movi a2, SYS_gdb_enter_sktloop + simcall /* have ISS handle debug exc. */ + #elif 0 /* change condition to 1 to use the HAL minimal debug handler */ + wsr a3, EXCSAVE+XCHAL_DEBUGLEVEL + movi a3, xthal_debugexc_defhndlr_nw /* use default debug handler */ + jx a3 + #else + wsr a0, EXCSAVE+XCHAL_DEBUGLEVEL /* save original a0 somewhere */ + call0 _xt_panic /* does not return */ + rfi XCHAL_DEBUGLEVEL /* make a0 point here not later */ + #endif + + .end literal_prefix + +#endif + +/* +-------------------------------------------------------------------------------- +Double Exception. +Double exceptions are not a normal occurrence. They indicate a bug of some kind. +-------------------------------------------------------------------------------- +*/ + +#ifdef XCHAL_DOUBLEEXC_VECTOR_VADDR + + .begin literal_prefix .DoubleExceptionVector + .section .DoubleExceptionVector.text, "ax" + .global _DoubleExceptionVector + .align 4 + +_DoubleExceptionVector: + + #if XCHAL_HAVE_DEBUG + break 1, 4 /* unhandled double exception */ + #endif + call0 _xt_panic /* does not return */ + rfde /* make a0 point here not later */ + + .end literal_prefix + +#endif /* XCHAL_DOUBLEEXC_VECTOR_VADDR */ + +/* +-------------------------------------------------------------------------------- +Kernel Exception (including Level 1 Interrupt from kernel mode). +-------------------------------------------------------------------------------- +*/ + + .begin literal_prefix .KernelExceptionVector + .section .KernelExceptionVector.text, "ax" + .global _KernelExceptionVector + .align 4 + +_KernelExceptionVector: + + wsr a0, EXCSAVE_1 /* preserve a0 */ + call0 _xt_kernel_exc /* kernel exception handler */ + /* never returns here - call0 is used as a jump (see note at top) */ + + .end literal_prefix + + .section .iram1,"ax" + .align 4 + +_xt_kernel_exc: + #if XCHAL_HAVE_DEBUG + break 1, 0 /* unhandled kernel exception */ + #endif + call0 _xt_panic /* does not return */ + rfe /* make a0 point here not there */ + + +/* +-------------------------------------------------------------------------------- +User Exception (including Level 1 Interrupt from user mode). +-------------------------------------------------------------------------------- +*/ + + .begin literal_prefix .UserExceptionVector + .section .UserExceptionVector.text, "ax" + .global _UserExceptionVector + .type _UserExceptionVector,@function + .align 4 + +_UserExceptionVector: + + wsr a0, EXCSAVE_1 /* preserve a0 */ + call0 _xt_user_exc /* user exception handler */ + /* never returns here - call0 is used as a jump (see note at top) */ + + .end literal_prefix + +/* +-------------------------------------------------------------------------------- + Insert some waypoints for jumping beyond the signed 8-bit range of + conditional branch instructions, so the conditional branchces to specific + exception handlers are not taken in the mainline. Saves some cycles in the + mainline. +-------------------------------------------------------------------------------- +*/ + + .section .iram1,"ax" + + #if XCHAL_HAVE_WINDOWED + .align 4 +_xt_to_alloca_exc: + call0 _xt_alloca_exc /* in window vectors section */ + /* never returns here - call0 is used as a jump (see note at top) */ + #endif + + .align 4 +_xt_to_syscall_exc: + call0 _xt_syscall_exc + /* never returns here - call0 is used as a jump (see note at top) */ + + #if XCHAL_CP_NUM > 0 + .align 4 +_xt_to_coproc_exc: + call0 _xt_coproc_exc + /* never returns here - call0 is used as a jump (see note at top) */ + #endif + + +/* +-------------------------------------------------------------------------------- + User exception handler. +-------------------------------------------------------------------------------- +*/ + + .type _xt_user_exc,@function + .align 4 + +_xt_user_exc: + + /* If level 1 interrupt then jump to the dispatcher */ + rsr a0, EXCCAUSE + beqi a0, EXCCAUSE_LEVEL1INTERRUPT, _xt_lowint1 + + /* Handle any coprocessor exceptions. Rely on the fact that exception + numbers above EXCCAUSE_CP0_DISABLED all relate to the coprocessors. + */ + #if XCHAL_CP_NUM > 0 + bgeui a0, EXCCAUSE_CP0_DISABLED, _xt_to_coproc_exc + #endif + + /* Handle alloca and syscall exceptions */ + #if XCHAL_HAVE_WINDOWED + beqi a0, EXCCAUSE_ALLOCA, _xt_to_alloca_exc + #endif + beqi a0, EXCCAUSE_SYSCALL, _xt_to_syscall_exc + + /* Handle all other exceptions. All can have user-defined handlers. */ + /* NOTE: we'll stay on the user stack for exception handling. */ + + /* Allocate exception frame and save minimal context. */ + mov a0, sp + addi sp, sp, -XT_STK_FRMSZ + s32i a0, sp, XT_STK_A1 + #if XCHAL_HAVE_WINDOWED + s32e a0, sp, -12 /* for debug backtrace */ + #endif + rsr a0, PS /* save interruptee's PS */ + s32i a0, sp, XT_STK_PS + rsr a0, EPC_1 /* save interruptee's PC */ + s32i a0, sp, XT_STK_PC + #if XCHAL_HAVE_WINDOWED + s32e a0, sp, -16 /* for debug backtrace */ + #endif + s32i a12, sp, XT_STK_A12 /* _xt_context_save requires A12- */ + s32i a13, sp, XT_STK_A13 /* A13 to have already been saved */ + call0 _xt_context_save + + /* Save exc cause and vaddr into exception frame */ + rsr a0, EXCCAUSE + s32i a0, sp, XT_STK_EXCCAUSE + rsr a0, EXCVADDR + s32i a0, sp, XT_STK_EXCVADDR + + /* _xt_context_save seems to save the current a0, but we need the interuptees a0. Fix this. */ + rsr a0, EXCSAVE_1 /* save interruptee's a0 */ + s32i a0, sp, XT_STK_A0 + + /* Set up PS for C, reenable hi-pri interrupts, and clear EXCM. */ + #ifdef __XTENSA_CALL0_ABI__ + movi a0, PS_INTLEVEL(XCHAL_EXCM_LEVEL) | PS_UM + #else + movi a0, PS_INTLEVEL(XCHAL_EXCM_LEVEL) | PS_UM | PS_WOE + #endif + wsr a0, PS + + #ifdef XT_DEBUG_BACKTRACE + #ifndef __XTENSA_CALL0_ABI__ + rsr a0, EPC_1 /* return address for debug backtrace */ + movi a5, 0xC0000000 /* constant with top 2 bits set (call size) */ + rsync /* wait for WSR.PS to complete */ + or a0, a0, a5 /* set top 2 bits */ + addx2 a0, a5, a0 /* clear top bit -- thus simulating call4 size */ + #else + rsync /* wait for WSR.PS to complete */ + #endif + #endif + + rsr a2, EXCCAUSE /* recover exc cause */ + + #ifdef XT_INTEXC_HOOKS + /* + Call exception hook to pre-handle exceptions (if installed). + Pass EXCCAUSE in a2, and check result in a2 (if -1, skip default handling). + */ + movi a4, _xt_intexc_hooks + l32i a4, a4, 0 /* user exception hook index 0 */ + beqz a4, 1f +.Ln_xt_user_exc_call_hook: + #ifdef __XTENSA_CALL0_ABI__ + callx0 a4 + beqi a2, -1, .L_xt_user_done + #else + mov a6, a2 + callx4 a4 + beqi a6, -1, .L_xt_user_done + mov a2, a6 + #endif +1: + #endif + + rsr a2, EXCCAUSE /* recover exc cause */ + movi a3, _xt_exception_table + addx4 a4, a2, a3 /* a4 = address of exception table entry */ + l32i a4, a4, 0 /* a4 = handler address */ + #ifdef __XTENSA_CALL0_ABI__ + mov a2, sp /* a2 = pointer to exc frame */ + callx0 a4 /* call handler */ + #else + mov a6, sp /* a6 = pointer to exc frame */ + callx4 a4 /* call handler */ + #endif + +.L_xt_user_done: + + /* Restore context and return */ + call0 _xt_context_restore + l32i a0, sp, XT_STK_PS /* retrieve interruptee's PS */ + wsr a0, PS + l32i a0, sp, XT_STK_PC /* retrieve interruptee's PC */ + wsr a0, EPC_1 + l32i a0, sp, XT_STK_A0 /* retrieve interruptee's A0 */ + l32i sp, sp, XT_STK_A1 /* remove exception frame */ + rsync /* ensure PS and EPC written */ + rfe /* PS.EXCM is cleared */ + + +/* +-------------------------------------------------------------------------------- + Exit point for dispatch. Saved in interrupt stack frame at XT_STK_EXIT + on entry and used to return to a thread or interrupted interrupt handler. +-------------------------------------------------------------------------------- +*/ + + .global _xt_user_exit + .type _xt_user_exit,@function + .align 4 +_xt_user_exit: + l32i a0, sp, XT_STK_PS /* retrieve interruptee's PS */ + wsr a0, PS + l32i a0, sp, XT_STK_PC /* retrieve interruptee's PC */ + wsr a0, EPC_1 + l32i a0, sp, XT_STK_A0 /* retrieve interruptee's A0 */ + l32i sp, sp, XT_STK_A1 /* remove interrupt stack frame */ + rsync /* ensure PS and EPC written */ + rfe /* PS.EXCM is cleared */ + + +/* + +-------------------------------------------------------------------------------- +Syscall Exception Handler (jumped to from User Exception Handler). +Syscall 0 is required to spill the register windows (no-op in Call 0 ABI). +Only syscall 0 is handled here. Other syscalls return -1 to caller in a2. +-------------------------------------------------------------------------------- +*/ + + .section .iram1,"ax" + .type _xt_syscall_exc,@function + .align 4 +_xt_syscall_exc: + + #ifdef __XTENSA_CALL0_ABI__ + /* + Save minimal regs for scratch. Syscall 0 does nothing in Call0 ABI. + Use a minimal stack frame (16B) to save A2 & A3 for scratch. + PS.EXCM could be cleared here, but unlikely to improve worst-case latency. + rsr a0, PS + addi a0, a0, -PS_EXCM_MASK + wsr a0, PS + */ + addi sp, sp, -16 + s32i a2, sp, 8 + s32i a3, sp, 12 + #else /* Windowed ABI */ + /* + Save necessary context and spill the register windows. + PS.EXCM is still set and must remain set until after the spill. + Reuse context save function though it saves more than necessary. + For this reason, a full interrupt stack frame is allocated. + */ + addi sp, sp, -XT_STK_FRMSZ /* allocate interrupt stack frame */ + s32i a12, sp, XT_STK_A12 /* _xt_context_save requires A12- */ + s32i a13, sp, XT_STK_A13 /* A13 to have already been saved */ + call0 _xt_context_save + #endif + + /* + Grab the interruptee's PC and skip over the 'syscall' instruction. + If it's at the end of a zero-overhead loop and it's not on the last + iteration, decrement loop counter and skip to beginning of loop. + */ + rsr a2, EPC_1 /* a2 = PC of 'syscall' */ + addi a3, a2, 3 /* ++PC */ + #if XCHAL_HAVE_LOOPS + rsr a0, LEND /* if (PC == LEND */ + bne a3, a0, 1f + rsr a0, LCOUNT /* && LCOUNT != 0) */ + beqz a0, 1f /* { */ + addi a0, a0, -1 /* --LCOUNT */ + rsr a3, LBEG /* PC = LBEG */ + wsr a0, LCOUNT /* } */ + #endif +1: wsr a3, EPC_1 /* update PC */ + + /* Restore interruptee's context and return from exception. */ + #ifdef __XTENSA_CALL0_ABI__ + l32i a2, sp, 8 + l32i a3, sp, 12 + addi sp, sp, 16 + #else + call0 _xt_context_restore + addi sp, sp, XT_STK_FRMSZ + #endif + movi a0, -1 + movnez a2, a0, a2 /* return -1 if not syscall 0 */ + rsr a0, EXCSAVE_1 + rfe + +/* +-------------------------------------------------------------------------------- +Co-Processor Exception Handler (jumped to from User Exception Handler). +These exceptions are generated by co-processor instructions, which are only +allowed in thread code (not in interrupts or kernel code). This restriction is +deliberately imposed to reduce the burden of state-save/restore in interrupts. +-------------------------------------------------------------------------------- +*/ +#if XCHAL_CP_NUM > 0 + + .section .rodata, "a" + +/* Offset to CP n save area in thread's CP save area. */ + .global _xt_coproc_sa_offset + .type _xt_coproc_sa_offset,@object + .align 16 /* minimize crossing cache boundaries */ +_xt_coproc_sa_offset: + .word XT_CP0_SA, XT_CP1_SA, XT_CP2_SA, XT_CP3_SA + .word XT_CP4_SA, XT_CP5_SA, XT_CP6_SA, XT_CP7_SA + +/* Bitmask for CP n's CPENABLE bit. */ + .type _xt_coproc_mask,@object + .align 16,,8 /* try to keep it all in one cache line */ + .set i, 0 +_xt_coproc_mask: + .rept XCHAL_CP_MAX + .long (i<<16) | (1<= 2 + + .begin literal_prefix .Level2InterruptVector + .section .Level2InterruptVector.text, "ax" + .global _Level2Vector + .type _Level2Vector,@function + .align 4 +_Level2Vector: + wsr a0, EXCSAVE_2 /* preserve a0 */ + call0 _xt_medint2 /* load interrupt handler */ + /* never returns here - call0 is used as a jump (see note at top) */ + + .end literal_prefix + + .section .iram1,"ax" + .type _xt_medint2,@function + .align 4 +_xt_medint2: + mov a0, sp /* sp == a1 */ + addi sp, sp, -XT_STK_FRMSZ /* allocate interrupt stack frame */ + s32i a0, sp, XT_STK_A1 /* save pre-interrupt SP */ + rsr a0, EPS_2 /* save interruptee's PS */ + s32i a0, sp, XT_STK_PS + rsr a0, EPC_2 /* save interruptee's PC */ + s32i a0, sp, XT_STK_PC + rsr a0, EXCSAVE_2 /* save interruptee's a0 */ + s32i a0, sp, XT_STK_A0 + movi a0, _xt_medint2_exit /* save exit point for dispatch */ + s32i a0, sp, XT_STK_EXIT + + /* Save rest of interrupt context and enter RTOS. */ + call0 XT_RTOS_INT_ENTER /* common RTOS interrupt entry */ + + /* !! We are now on the RTOS system stack !! */ + + /* Set up PS for C, enable interrupts above this level and clear EXCM. */ + #ifdef __XTENSA_CALL0_ABI__ + movi a0, PS_INTLEVEL(2) | PS_UM + #else + movi a0, PS_INTLEVEL(2) | PS_UM | PS_WOE + #endif + wsr a0, PS + rsync + + /* OK to call C code at this point, dispatch user ISRs */ + + dispatch_c_isr 2 XCHAL_INTLEVEL2_MASK + + /* Done handling interrupts, transfer control to OS */ + call0 XT_RTOS_INT_EXIT /* does not return directly here */ + + /* + Exit point for dispatch. Saved in interrupt stack frame at XT_STK_EXIT + on entry and used to return to a thread or interrupted interrupt handler. + */ + .global _xt_medint2_exit + .type _xt_medint2_exit,@function + .align 4 +_xt_medint2_exit: + /* Restore only level-specific regs (the rest were already restored) */ + l32i a0, sp, XT_STK_PS /* retrieve interruptee's PS */ + wsr a0, EPS_2 + l32i a0, sp, XT_STK_PC /* retrieve interruptee's PC */ + wsr a0, EPC_2 + l32i a0, sp, XT_STK_A0 /* retrieve interruptee's A0 */ + l32i sp, sp, XT_STK_A1 /* remove interrupt stack frame */ + rsync /* ensure EPS and EPC written */ + rfi 2 + +#endif /* Level 2 */ + +#if XCHAL_EXCM_LEVEL >= 3 + + .begin literal_prefix .Level3InterruptVector + .section .Level3InterruptVector.text, "ax" + .global _Level3Vector + .type _Level3Vector,@function + .align 4 +_Level3Vector: + wsr a0, EXCSAVE_3 /* preserve a0 */ + call0 _xt_medint3 /* load interrupt handler */ + /* never returns here - call0 is used as a jump (see note at top) */ + + .end literal_prefix + + .section .iram1,"ax" + .type _xt_medint3,@function + .align 4 +_xt_medint3: + mov a0, sp /* sp == a1 */ + addi sp, sp, -XT_STK_FRMSZ /* allocate interrupt stack frame */ + s32i a0, sp, XT_STK_A1 /* save pre-interrupt SP */ + rsr a0, EPS_3 /* save interruptee's PS */ + s32i a0, sp, XT_STK_PS + rsr a0, EPC_3 /* save interruptee's PC */ + s32i a0, sp, XT_STK_PC + rsr a0, EXCSAVE_3 /* save interruptee's a0 */ + s32i a0, sp, XT_STK_A0 + movi a0, _xt_medint3_exit /* save exit point for dispatch */ + s32i a0, sp, XT_STK_EXIT + + /* Save rest of interrupt context and enter RTOS. */ + call0 XT_RTOS_INT_ENTER /* common RTOS interrupt entry */ + + /* !! We are now on the RTOS system stack !! */ + + /* Set up PS for C, enable interrupts above this level and clear EXCM. */ + #ifdef __XTENSA_CALL0_ABI__ + movi a0, PS_INTLEVEL(3) | PS_UM + #else + movi a0, PS_INTLEVEL(3) | PS_UM | PS_WOE + #endif + wsr a0, PS + rsync + + /* OK to call C code at this point, dispatch user ISRs */ + + dispatch_c_isr 3 XCHAL_INTLEVEL3_MASK + + /* Done handling interrupts, transfer control to OS */ + call0 XT_RTOS_INT_EXIT /* does not return directly here */ + + /* + Exit point for dispatch. Saved in interrupt stack frame at XT_STK_EXIT + on entry and used to return to a thread or interrupted interrupt handler. + */ + .global _xt_medint3_exit + .type _xt_medint3_exit,@function + .align 4 +_xt_medint3_exit: + /* Restore only level-specific regs (the rest were already restored) */ + l32i a0, sp, XT_STK_PS /* retrieve interruptee's PS */ + wsr a0, EPS_3 + l32i a0, sp, XT_STK_PC /* retrieve interruptee's PC */ + wsr a0, EPC_3 + l32i a0, sp, XT_STK_A0 /* retrieve interruptee's A0 */ + l32i sp, sp, XT_STK_A1 /* remove interrupt stack frame */ + rsync /* ensure EPS and EPC written */ + rfi 3 + +#endif /* Level 3 */ + +#if XCHAL_EXCM_LEVEL >= 4 + + .begin literal_prefix .Level4InterruptVector + .section .Level4InterruptVector.text, "ax" + .global _Level4Vector + .type _Level4Vector,@function + .align 4 +_Level4Vector: + wsr a0, EXCSAVE_4 /* preserve a0 */ + call0 _xt_medint4 /* load interrupt handler */ + + .end literal_prefix + + .section .iram1,"ax" + .type _xt_medint4,@function + .align 4 +_xt_medint4: + mov a0, sp /* sp == a1 */ + addi sp, sp, -XT_STK_FRMSZ /* allocate interrupt stack frame */ + s32i a0, sp, XT_STK_A1 /* save pre-interrupt SP */ + rsr a0, EPS_4 /* save interruptee's PS */ + s32i a0, sp, XT_STK_PS + rsr a0, EPC_4 /* save interruptee's PC */ + s32i a0, sp, XT_STK_PC + rsr a0, EXCSAVE_4 /* save interruptee's a0 */ + s32i a0, sp, XT_STK_A0 + movi a0, _xt_medint4_exit /* save exit point for dispatch */ + s32i a0, sp, XT_STK_EXIT + + /* Save rest of interrupt context and enter RTOS. */ + call0 XT_RTOS_INT_ENTER /* common RTOS interrupt entry */ + + /* !! We are now on the RTOS system stack !! */ + + /* Set up PS for C, enable interrupts above this level and clear EXCM. */ + #ifdef __XTENSA_CALL0_ABI__ + movi a0, PS_INTLEVEL(4) | PS_UM + #else + movi a0, PS_INTLEVEL(4) | PS_UM | PS_WOE + #endif + wsr a0, PS + rsync + + /* OK to call C code at this point, dispatch user ISRs */ + + dispatch_c_isr 4 XCHAL_INTLEVEL4_MASK + + /* Done handling interrupts, transfer control to OS */ + call0 XT_RTOS_INT_EXIT /* does not return directly here */ + + /* + Exit point for dispatch. Saved in interrupt stack frame at XT_STK_EXIT + on entry and used to return to a thread or interrupted interrupt handler. + */ + .global _xt_medint4_exit + .type _xt_medint4_exit,@function + .align 4 +_xt_medint4_exit: + /* Restore only level-specific regs (the rest were already restored) */ + l32i a0, sp, XT_STK_PS /* retrieve interruptee's PS */ + wsr a0, EPS_4 + l32i a0, sp, XT_STK_PC /* retrieve interruptee's PC */ + wsr a0, EPC_4 + l32i a0, sp, XT_STK_A0 /* retrieve interruptee's A0 */ + l32i sp, sp, XT_STK_A1 /* remove interrupt stack frame */ + rsync /* ensure EPS and EPC written */ + rfi 4 + +#endif /* Level 4 */ + +#if XCHAL_EXCM_LEVEL >= 5 + + .begin literal_prefix .Level5InterruptVector + .section .Level5InterruptVector.text, "ax" + .global _Level5Vector + .type _Level5Vector,@function + .align 4 +_Level5Vector: + wsr a0, EXCSAVE_5 /* preserve a0 */ + call0 _xt_medint5 /* load interrupt handler */ + + .end literal_prefix + + .section .iram1,"ax" + .type _xt_medint5,@function + .align 4 +_xt_medint5: + mov a0, sp /* sp == a1 */ + addi sp, sp, -XT_STK_FRMSZ /* allocate interrupt stack frame */ + s32i a0, sp, XT_STK_A1 /* save pre-interrupt SP */ + rsr a0, EPS_5 /* save interruptee's PS */ + s32i a0, sp, XT_STK_PS + rsr a0, EPC_5 /* save interruptee's PC */ + s32i a0, sp, XT_STK_PC + rsr a0, EXCSAVE_5 /* save interruptee's a0 */ + s32i a0, sp, XT_STK_A0 + movi a0, _xt_medint5_exit /* save exit point for dispatch */ + s32i a0, sp, XT_STK_EXIT + + /* Save rest of interrupt context and enter RTOS. */ + call0 XT_RTOS_INT_ENTER /* common RTOS interrupt entry */ + + /* !! We are now on the RTOS system stack !! */ + + /* Set up PS for C, enable interrupts above this level and clear EXCM. */ + #ifdef __XTENSA_CALL0_ABI__ + movi a0, PS_INTLEVEL(5) | PS_UM + #else + movi a0, PS_INTLEVEL(5) | PS_UM | PS_WOE + #endif + wsr a0, PS + rsync + + /* OK to call C code at this point, dispatch user ISRs */ + + dispatch_c_isr 5 XCHAL_INTLEVEL5_MASK + + /* Done handling interrupts, transfer control to OS */ + call0 XT_RTOS_INT_EXIT /* does not return directly here */ + + /* + Exit point for dispatch. Saved in interrupt stack frame at XT_STK_EXIT + on entry and used to return to a thread or interrupted interrupt handler. + */ + .global _xt_medint5_exit + .type _xt_medint5_exit,@function + .align 4 +_xt_medint5_exit: + /* Restore only level-specific regs (the rest were already restored) */ + l32i a0, sp, XT_STK_PS /* retrieve interruptee's PS */ + wsr a0, EPS_5 + l32i a0, sp, XT_STK_PC /* retrieve interruptee's PC */ + wsr a0, EPC_5 + l32i a0, sp, XT_STK_A0 /* retrieve interruptee's A0 */ + l32i sp, sp, XT_STK_A1 /* remove interrupt stack frame */ + rsync /* ensure EPS and EPC written */ + rfi 5 + +#endif /* Level 5 */ + +#if XCHAL_EXCM_LEVEL >= 6 + + .begin literal_prefix .Level6InterruptVector + .section .Level6InterruptVector.text, "ax" + .global _Level6Vector + .type _Level6Vector,@function + .align 4 +_Level6Vector: + wsr a0, EXCSAVE_6 /* preserve a0 */ + call0 _xt_medint6 /* load interrupt handler */ + + .end literal_prefix + + .section .iram1,"ax" + .type _xt_medint6,@function + .align 4 +_xt_medint6: + mov a0, sp /* sp == a1 */ + addi sp, sp, -XT_STK_FRMSZ /* allocate interrupt stack frame */ + s32i a0, sp, XT_STK_A1 /* save pre-interrupt SP */ + rsr a0, EPS_6 /* save interruptee's PS */ + s32i a0, sp, XT_STK_PS + rsr a0, EPC_6 /* save interruptee's PC */ + s32i a0, sp, XT_STK_PC + rsr a0, EXCSAVE_6 /* save interruptee's a0 */ + s32i a0, sp, XT_STK_A0 + movi a0, _xt_medint6_exit /* save exit point for dispatch */ + s32i a0, sp, XT_STK_EXIT + + /* Save rest of interrupt context and enter RTOS. */ + call0 XT_RTOS_INT_ENTER /* common RTOS interrupt entry */ + + /* !! We are now on the RTOS system stack !! */ + + /* Set up PS for C, enable interrupts above this level and clear EXCM. */ + #ifdef __XTENSA_CALL0_ABI__ + movi a0, PS_INTLEVEL(6) | PS_UM + #else + movi a0, PS_INTLEVEL(6) | PS_UM | PS_WOE + #endif + wsr a0, PS + rsync + + /* OK to call C code at this point, dispatch user ISRs */ + + dispatch_c_isr 6 XCHAL_INTLEVEL6_MASK + + /* Done handling interrupts, transfer control to OS */ + call0 XT_RTOS_INT_EXIT /* does not return directly here */ + + /* + Exit point for dispatch. Saved in interrupt stack frame at XT_STK_EXIT + on entry and used to return to a thread or interrupted interrupt handler. + */ + .global _xt_medint6_exit + .type _xt_medint6_exit,@function + .align 4 +_xt_medint6_exit: + /* Restore only level-specific regs (the rest were already restored) */ + l32i a0, sp, XT_STK_PS /* retrieve interruptee's PS */ + wsr a0, EPS_6 + l32i a0, sp, XT_STK_PC /* retrieve interruptee's PC */ + wsr a0, EPC_6 + l32i a0, sp, XT_STK_A0 /* retrieve interruptee's A0 */ + l32i sp, sp, XT_STK_A1 /* remove interrupt stack frame */ + rsync /* ensure EPS and EPC written */ + rfi 6 + +#endif /* Level 6 */ + + +/******************************************************************************* + +HIGH PRIORITY (LEVEL > XCHAL_EXCM_LEVEL) INTERRUPT VECTORS AND HANDLERS + +High priority interrupts are by definition those with priorities greater +than XCHAL_EXCM_LEVEL. This includes non-maskable (NMI). High priority +interrupts cannot interact with the RTOS, that is they must save all regs +they use and not call any RTOS function. + +A further restriction imposed by the Xtensa windowed architecture is that +high priority interrupts must not modify the stack area even logically +"above" the top of the interrupted stack (they need to provide their +own stack or static save area). + +Cadence Design Systems recommends high priority interrupt handlers be coded in assembly +and used for purposes requiring very short service times. + +Here are templates for high priority (level 2+) interrupt vectors. +They assume only one interrupt per level to avoid the burden of identifying +which interrupts at this level are pending and enabled. This allows for +minimum latency and avoids having to save/restore a2 in addition to a0. +If more than one interrupt per high priority level is configured, this burden +is on the handler which in any case must provide a way to save and restore +registers it uses without touching the interrupted stack. + +Each vector goes at a predetermined location according to the Xtensa +hardware configuration, which is ensured by its placement in a special +section known to the Xtensa linker support package (LSP). It performs +the minimum necessary before jumping to the handler in the .text section. + +*******************************************************************************/ + +/* +Currently only shells for high priority interrupt handlers are provided +here. However a template and example can be found in the Cadence Design Systems tools +documentation: "Microprocessor Programmer's Guide". +*/ + +#if XCHAL_NUM_INTLEVELS >=2 && XCHAL_EXCM_LEVEL <2 && XCHAL_DEBUGLEVEL !=2 + + .begin literal_prefix .Level2InterruptVector + .section .Level2InterruptVector.text, "ax" + .global _Level2Vector + .type _Level2Vector,@function + .align 4 +_Level2Vector: + wsr a0, EXCSAVE_2 /* preserve a0 */ + call0 _xt_highint2 /* load interrupt handler */ + + .end literal_prefix + + .section .iram1,"ax" + .type _xt_highint2,@function + .align 4 +_xt_highint2: + + #ifdef XT_INTEXC_HOOKS + /* Call interrupt hook if present to (pre)handle interrupts. */ + movi a0, _xt_intexc_hooks + l32i a0, a0, 2<<2 + beqz a0, 1f +.Ln_xt_highint2_call_hook: + callx0 a0 /* must NOT disturb stack! */ +1: + #endif + + /* USER_EDIT: + ADD HIGH PRIORITY LEVEL 2 INTERRUPT HANDLER CODE HERE. + */ + + .align 4 +.L_xt_highint2_exit: + rsr a0, EXCSAVE_2 /* restore a0 */ + rfi 2 + +#endif /* Level 2 */ + +#if XCHAL_NUM_INTLEVELS >=3 && XCHAL_EXCM_LEVEL <3 && XCHAL_DEBUGLEVEL !=3 + + .begin literal_prefix .Level3InterruptVector + .section .Level3InterruptVector.text, "ax" + .global _Level3Vector + .type _Level3Vector,@function + .align 4 +_Level3Vector: + wsr a0, EXCSAVE_3 /* preserve a0 */ + call0 _xt_highint3 /* load interrupt handler */ + /* never returns here - call0 is used as a jump (see note at top) */ + + .end literal_prefix + + .section .iram1,"ax" + .type _xt_highint3,@function + .align 4 +_xt_highint3: + + #ifdef XT_INTEXC_HOOKS + /* Call interrupt hook if present to (pre)handle interrupts. */ + movi a0, _xt_intexc_hooks + l32i a0, a0, 3<<2 + beqz a0, 1f +.Ln_xt_highint3_call_hook: + callx0 a0 /* must NOT disturb stack! */ +1: + #endif + + /* USER_EDIT: + ADD HIGH PRIORITY LEVEL 3 INTERRUPT HANDLER CODE HERE. + */ + + .align 4 +.L_xt_highint3_exit: + rsr a0, EXCSAVE_3 /* restore a0 */ + rfi 3 + +#endif /* Level 3 */ + +#if XCHAL_NUM_INTLEVELS >=4 && XCHAL_EXCM_LEVEL <4 && XCHAL_DEBUGLEVEL !=4 + + .begin literal_prefix .Level4InterruptVector + .section .Level4InterruptVector.text, "ax" + .global _Level4Vector + .type _Level4Vector,@function + .align 4 +_Level4Vector: + wsr a0, EXCSAVE_4 /* preserve a0 */ + call0 _xt_highint4 /* load interrupt handler */ + /* never returns here - call0 is used as a jump (see note at top) */ + + .end literal_prefix + + .section .iram1,"ax" + .type _xt_highint4,@function + .align 4 +_xt_highint4: + + #ifdef XT_INTEXC_HOOKS + /* Call interrupt hook if present to (pre)handle interrupts. */ + movi a0, _xt_intexc_hooks + l32i a0, a0, 4<<2 + beqz a0, 1f +.Ln_xt_highint4_call_hook: + callx0 a0 /* must NOT disturb stack! */ +1: + #endif + + /* USER_EDIT: + ADD HIGH PRIORITY LEVEL 4 INTERRUPT HANDLER CODE HERE. + */ + + .align 4 +.L_xt_highint4_exit: + rsr a0, EXCSAVE_4 /* restore a0 */ + rfi 4 + +#endif /* Level 4 */ + +#if XCHAL_NUM_INTLEVELS >=5 && XCHAL_EXCM_LEVEL <5 && XCHAL_DEBUGLEVEL !=5 + + .begin literal_prefix .Level5InterruptVector + .section .Level5InterruptVector.text, "ax" + .global _Level5Vector + .type _Level5Vector,@function + .align 4 +_Level5Vector: + wsr a0, EXCSAVE_5 /* preserve a0 */ + call0 _xt_highint5 /* load interrupt handler */ + /* never returns here - call0 is used as a jump (see note at top) */ + + .end literal_prefix + + .section .iram1,"ax" + .type _xt_highint5,@function + .align 4 +_xt_highint5: + + #ifdef XT_INTEXC_HOOKS + /* Call interrupt hook if present to (pre)handle interrupts. */ + movi a0, _xt_intexc_hooks + l32i a0, a0, 5<<2 + beqz a0, 1f +.Ln_xt_highint5_call_hook: + callx0 a0 /* must NOT disturb stack! */ +1: + #endif + + /* USER_EDIT: + ADD HIGH PRIORITY LEVEL 5 INTERRUPT HANDLER CODE HERE. + */ + + .align 4 +.L_xt_highint5_exit: + rsr a0, EXCSAVE_5 /* restore a0 */ + rfi 5 + +#endif /* Level 5 */ + +#if XCHAL_NUM_INTLEVELS >=6 && XCHAL_EXCM_LEVEL <6 && XCHAL_DEBUGLEVEL !=6 + + .begin literal_prefix .Level6InterruptVector + .section .Level6InterruptVector.text, "ax" + .global _Level6Vector + .type _Level6Vector,@function + .align 4 +_Level6Vector: + wsr a0, EXCSAVE_6 /* preserve a0 */ + call0 _xt_highint6 /* load interrupt handler */ + /* never returns here - call0 is used as a jump (see note at top) */ + + .end literal_prefix + + .section .iram1,"ax" + .type _xt_highint6,@function + .align 4 +_xt_highint6: + + #ifdef XT_INTEXC_HOOKS + /* Call interrupt hook if present to (pre)handle interrupts. */ + movi a0, _xt_intexc_hooks + l32i a0, a0, 6<<2 + beqz a0, 1f +.Ln_xt_highint6_call_hook: + callx0 a0 /* must NOT disturb stack! */ +1: + #endif + + /* USER_EDIT: + ADD HIGH PRIORITY LEVEL 6 INTERRUPT HANDLER CODE HERE. + */ + + .align 4 +.L_xt_highint6_exit: + rsr a0, EXCSAVE_6 /* restore a0 */ + rfi 6 + +#endif /* Level 6 */ + +#if XCHAL_HAVE_NMI + + .begin literal_prefix .NMIExceptionVector + .section .NMIExceptionVector.text, "ax" + .global _NMIExceptionVector + .type _NMIExceptionVector,@function + .align 4 +_NMIExceptionVector: + wsr a0, EXCSAVE + XCHAL_NMILEVEL _ /* preserve a0 */ + call0 _xt_nmi /* load interrupt handler */ + /* never returns here - call0 is used as a jump (see note at top) */ + + .end literal_prefix + + .section .iram1,"ax" + .type _xt_nmi,@function + .align 4 +_xt_nmi: + + #ifdef XT_INTEXC_HOOKS + /* Call interrupt hook if present to (pre)handle interrupts. */ + movi a0, _xt_intexc_hooks + l32i a0, a0, XCHAL_NMILEVEL<<2 + beqz a0, 1f +.Ln_xt_nmi_call_hook: + callx0 a0 /* must NOT disturb stack! */ +1: + #endif + + /* USER_EDIT: + ADD HIGH PRIORITY NON-MASKABLE INTERRUPT (NMI) HANDLER CODE HERE. + */ + + .align 4 +.L_xt_nmi_exit: + rsr a0, EXCSAVE + XCHAL_NMILEVEL /* restore a0 */ + rfi XCHAL_NMILEVEL + +#endif /* NMI */ + + +/******************************************************************************* + +WINDOW OVERFLOW AND UNDERFLOW EXCEPTION VECTORS AND ALLOCA EXCEPTION HANDLER + +Here is the code for each window overflow/underflow exception vector and +(interspersed) efficient code for handling the alloca exception cause. +Window exceptions are handled entirely in the vector area and are very +tight for performance. The alloca exception is also handled entirely in +the window vector area so comes at essentially no cost in code size. +Users should never need to modify them and Cadence Design Systems recommends +they do not. + +Window handlers go at predetermined vector locations according to the +Xtensa hardware configuration, which is ensured by their placement in a +special section known to the Xtensa linker support package (LSP). Since +their offsets in that section are always the same, the LSPs do not define +a section per vector. + +These things are coded for XEA2 only (XEA1 is not supported). + +Note on Underflow Handlers: +The underflow handler for returning from call[i+1] to call[i] +must preserve all the registers from call[i+1]'s window. +In particular, a0 and a1 must be preserved because the RETW instruction +will be reexecuted (and may even underflow if an intervening exception +has flushed call[i]'s registers). +Registers a2 and up may contain return values. + +*******************************************************************************/ + +#if XCHAL_HAVE_WINDOWED + + .section .WindowVectors.text, "ax" + +/* +-------------------------------------------------------------------------------- +Window Overflow Exception for Call4. + +Invoked if a call[i] referenced a register (a4-a15) +that contains data from ancestor call[j]; +call[j] had done a call4 to call[j+1]. +On entry here: + window rotated to call[j] start point; + a0-a3 are registers to be saved; + a4-a15 must be preserved; + a5 is call[j+1]'s stack pointer. +-------------------------------------------------------------------------------- +*/ + + .org 0x0 + .global _WindowOverflow4 +_WindowOverflow4: + + s32e a0, a5, -16 /* save a0 to call[j+1]'s stack frame */ + s32e a1, a5, -12 /* save a1 to call[j+1]'s stack frame */ + s32e a2, a5, -8 /* save a2 to call[j+1]'s stack frame */ + s32e a3, a5, -4 /* save a3 to call[j+1]'s stack frame */ + rfwo /* rotates back to call[i] position */ + +/* +-------------------------------------------------------------------------------- +Window Underflow Exception for Call4 + +Invoked by RETW returning from call[i+1] to call[i] +where call[i]'s registers must be reloaded (not live in ARs); +where call[i] had done a call4 to call[i+1]. +On entry here: + window rotated to call[i] start point; + a0-a3 are undefined, must be reloaded with call[i].reg[0..3]; + a4-a15 must be preserved (they are call[i+1].reg[0..11]); + a5 is call[i+1]'s stack pointer. +-------------------------------------------------------------------------------- +*/ + + .org 0x40 + .global _WindowUnderflow4 +_WindowUnderflow4: + + l32e a0, a5, -16 /* restore a0 from call[i+1]'s stack frame */ + l32e a1, a5, -12 /* restore a1 from call[i+1]'s stack frame */ + l32e a2, a5, -8 /* restore a2 from call[i+1]'s stack frame */ + l32e a3, a5, -4 /* restore a3 from call[i+1]'s stack frame */ + rfwu + +/* +-------------------------------------------------------------------------------- +Handle alloca exception generated by interruptee executing 'movsp'. +This uses space between the window vectors, so is essentially "free". +All interruptee's regs are intact except a0 which is saved in EXCSAVE_1, +and PS.EXCM has been set by the exception hardware (can't be interrupted). +The fact the alloca exception was taken means the registers associated with +the base-save area have been spilled and will be restored by the underflow +handler, so those 4 registers are available for scratch. +The code is optimized to avoid unaligned branches and minimize cache misses. +-------------------------------------------------------------------------------- +*/ + + .align 4 + .global _xt_alloca_exc +_xt_alloca_exc: + + rsr a0, WINDOWBASE /* grab WINDOWBASE before rotw changes it */ + rotw -1 /* WINDOWBASE goes to a4, new a0-a3 are scratch */ + rsr a2, PS + extui a3, a2, XCHAL_PS_OWB_SHIFT, XCHAL_PS_OWB_BITS + xor a3, a3, a4 /* bits changed from old to current windowbase */ + rsr a4, EXCSAVE_1 /* restore original a0 (now in a4) */ + slli a3, a3, XCHAL_PS_OWB_SHIFT + xor a2, a2, a3 /* flip changed bits in old window base */ + wsr a2, PS /* update PS.OWB to new window base */ + rsync + + _bbci.l a4, 31, _WindowUnderflow4 + rotw -1 /* original a0 goes to a8 */ + _bbci.l a8, 30, _WindowUnderflow8 + rotw -1 + j _WindowUnderflow12 + +/* +-------------------------------------------------------------------------------- +Window Overflow Exception for Call8 + +Invoked if a call[i] referenced a register (a4-a15) +that contains data from ancestor call[j]; +call[j] had done a call8 to call[j+1]. +On entry here: + window rotated to call[j] start point; + a0-a7 are registers to be saved; + a8-a15 must be preserved; + a9 is call[j+1]'s stack pointer. +-------------------------------------------------------------------------------- +*/ + + .org 0x80 + .global _WindowOverflow8 +_WindowOverflow8: + + s32e a0, a9, -16 /* save a0 to call[j+1]'s stack frame */ + l32e a0, a1, -12 /* a0 <- call[j-1]'s sp + (used to find end of call[j]'s frame) */ + s32e a1, a9, -12 /* save a1 to call[j+1]'s stack frame */ + s32e a2, a9, -8 /* save a2 to call[j+1]'s stack frame */ + s32e a3, a9, -4 /* save a3 to call[j+1]'s stack frame */ + s32e a4, a0, -32 /* save a4 to call[j]'s stack frame */ + s32e a5, a0, -28 /* save a5 to call[j]'s stack frame */ + s32e a6, a0, -24 /* save a6 to call[j]'s stack frame */ + s32e a7, a0, -20 /* save a7 to call[j]'s stack frame */ + rfwo /* rotates back to call[i] position */ + +/* +-------------------------------------------------------------------------------- +Window Underflow Exception for Call8 + +Invoked by RETW returning from call[i+1] to call[i] +where call[i]'s registers must be reloaded (not live in ARs); +where call[i] had done a call8 to call[i+1]. +On entry here: + window rotated to call[i] start point; + a0-a7 are undefined, must be reloaded with call[i].reg[0..7]; + a8-a15 must be preserved (they are call[i+1].reg[0..7]); + a9 is call[i+1]'s stack pointer. +-------------------------------------------------------------------------------- +*/ + + .org 0xC0 + .global _WindowUnderflow8 +_WindowUnderflow8: + + l32e a0, a9, -16 /* restore a0 from call[i+1]'s stack frame */ + l32e a1, a9, -12 /* restore a1 from call[i+1]'s stack frame */ + l32e a2, a9, -8 /* restore a2 from call[i+1]'s stack frame */ + l32e a7, a1, -12 /* a7 <- call[i-1]'s sp + (used to find end of call[i]'s frame) */ + l32e a3, a9, -4 /* restore a3 from call[i+1]'s stack frame */ + l32e a4, a7, -32 /* restore a4 from call[i]'s stack frame */ + l32e a5, a7, -28 /* restore a5 from call[i]'s stack frame */ + l32e a6, a7, -24 /* restore a6 from call[i]'s stack frame */ + l32e a7, a7, -20 /* restore a7 from call[i]'s stack frame */ + rfwu + +/* +-------------------------------------------------------------------------------- +Window Overflow Exception for Call12 + +Invoked if a call[i] referenced a register (a4-a15) +that contains data from ancestor call[j]; +call[j] had done a call12 to call[j+1]. +On entry here: + window rotated to call[j] start point; + a0-a11 are registers to be saved; + a12-a15 must be preserved; + a13 is call[j+1]'s stack pointer. +-------------------------------------------------------------------------------- +*/ + + .org 0x100 + .global _WindowOverflow12 +_WindowOverflow12: + + s32e a0, a13, -16 /* save a0 to call[j+1]'s stack frame */ + l32e a0, a1, -12 /* a0 <- call[j-1]'s sp + (used to find end of call[j]'s frame) */ + s32e a1, a13, -12 /* save a1 to call[j+1]'s stack frame */ + s32e a2, a13, -8 /* save a2 to call[j+1]'s stack frame */ + s32e a3, a13, -4 /* save a3 to call[j+1]'s stack frame */ + s32e a4, a0, -48 /* save a4 to end of call[j]'s stack frame */ + s32e a5, a0, -44 /* save a5 to end of call[j]'s stack frame */ + s32e a6, a0, -40 /* save a6 to end of call[j]'s stack frame */ + s32e a7, a0, -36 /* save a7 to end of call[j]'s stack frame */ + s32e a8, a0, -32 /* save a8 to end of call[j]'s stack frame */ + s32e a9, a0, -28 /* save a9 to end of call[j]'s stack frame */ + s32e a10, a0, -24 /* save a10 to end of call[j]'s stack frame */ + s32e a11, a0, -20 /* save a11 to end of call[j]'s stack frame */ + rfwo /* rotates back to call[i] position */ + +/* +-------------------------------------------------------------------------------- +Window Underflow Exception for Call12 + +Invoked by RETW returning from call[i+1] to call[i] +where call[i]'s registers must be reloaded (not live in ARs); +where call[i] had done a call12 to call[i+1]. +On entry here: + window rotated to call[i] start point; + a0-a11 are undefined, must be reloaded with call[i].reg[0..11]; + a12-a15 must be preserved (they are call[i+1].reg[0..3]); + a13 is call[i+1]'s stack pointer. +-------------------------------------------------------------------------------- +*/ + + .org 0x140 + .global _WindowUnderflow12 +_WindowUnderflow12: + + l32e a0, a13, -16 /* restore a0 from call[i+1]'s stack frame */ + l32e a1, a13, -12 /* restore a1 from call[i+1]'s stack frame */ + l32e a2, a13, -8 /* restore a2 from call[i+1]'s stack frame */ + l32e a11, a1, -12 /* a11 <- call[i-1]'s sp + (used to find end of call[i]'s frame) */ + l32e a3, a13, -4 /* restore a3 from call[i+1]'s stack frame */ + l32e a4, a11, -48 /* restore a4 from end of call[i]'s stack frame */ + l32e a5, a11, -44 /* restore a5 from end of call[i]'s stack frame */ + l32e a6, a11, -40 /* restore a6 from end of call[i]'s stack frame */ + l32e a7, a11, -36 /* restore a7 from end of call[i]'s stack frame */ + l32e a8, a11, -32 /* restore a8 from end of call[i]'s stack frame */ + l32e a9, a11, -28 /* restore a9 from end of call[i]'s stack frame */ + l32e a10, a11, -24 /* restore a10 from end of call[i]'s stack frame */ + l32e a11, a11, -20 /* restore a11 from end of call[i]'s stack frame */ + rfwu + +#endif /* XCHAL_HAVE_WINDOWED */ + + .section .UserEnter.text, "ax" + .global call_user_start + .type call_user_start,@function + .align 4 + .literal_position + + + diff --git a/components/freertos/xtensa_vectors.S-new b/components/freertos/xtensa_vectors.S-new new file mode 100644 index 0000000000..88349eee9f --- /dev/null +++ b/components/freertos/xtensa_vectors.S-new @@ -0,0 +1,1915 @@ +/******************************************************************************* +Copyright (c) 2006-2015 Cadence Design Systems Inc. + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be included +in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +-------------------------------------------------------------------------------- + + XTENSA VECTORS AND LOW LEVEL HANDLERS FOR AN RTOS + + Xtensa low level exception and interrupt vectors and handlers for an RTOS. + + Interrupt handlers and user exception handlers support interaction with + the RTOS by calling XT_RTOS_INT_ENTER and XT_RTOS_INT_EXIT before and + after user's specific interrupt handlers. These macros are defined in + xtensa_.h to call suitable functions in a specific RTOS. + + Users can install application-specific interrupt handlers for low and + medium level interrupts, by calling xt_set_interrupt_handler(). These + handlers can be written in C, and must obey C calling convention. The + handler table is indexed by the interrupt number. Each handler may be + provided with an argument. + + Note that the system timer interrupt is handled specially, and is + dispatched to the RTOS-specific handler. This timer cannot be hooked + by application code. + + Optional hooks are also provided to install a handler per level at + run-time, made available by compiling this source file with + '-DXT_INTEXC_HOOKS' (useful for automated testing). + +!! This file is a template that usually needs to be modified to handle !! +!! application specific interrupts. Search USER_EDIT for helpful comments !! +!! on where to insert handlers and how to write them. !! + + Users can also install application-specific exception handlers in the + same way, by calling xt_set_exception_handler(). One handler slot is + provided for each exception type. Note that some exceptions are handled + by the porting layer itself, and cannot be taken over by application + code in this manner. These are the alloca, syscall, and coprocessor + exceptions. + + The exception handlers can be written in C, and must follow C calling + convention. Each handler is passed a pointer to an exception frame as + its single argument. The exception frame is created on the stack, and + holds the saved context of the thread that took the exception. If the + handler returns, the context will be restored and the instruction that + caused the exception will be retried. If the handler makes any changes + to the saved state in the exception frame, the changes will be applied + when restoring the context. + + Because Xtensa is a configurable architecture, this port supports all user + generated configurations (except restrictions stated in the release notes). + This is accomplished by conditional compilation using macros and functions + defined in the Xtensa HAL (hardware adaptation layer) for your configuration. + Only the relevant parts of this file will be included in your RTOS build. + For example, this file provides interrupt vector templates for all types and + all priority levels, but only the ones in your configuration are built. + + NOTES on the use of 'call0' for long jumps instead of 'j': + 1. This file should be assembled with the -mlongcalls option to xt-xcc. + 2. The -mlongcalls compiler option causes 'call0 dest' to be expanded to + a sequence 'l32r a0, dest' 'callx0 a0' which works regardless of the + distance from the call to the destination. The linker then relaxes + it back to 'call0 dest' if it determines that dest is within range. + This allows more flexibility in locating code without the performance + overhead of the 'l32r' literal data load in cases where the destination + is in range of 'call0'. There is an additional benefit in that 'call0' + has a longer range than 'j' due to the target being word-aligned, so + the 'l32r' sequence is less likely needed. + 3. The use of 'call0' with -mlongcalls requires that register a0 not be + live at the time of the call, which is always the case for a function + call but needs to be ensured if 'call0' is used as a jump in lieu of 'j'. + 4. This use of 'call0' is independent of the C function call ABI. + +*******************************************************************************/ + +#include "xtensa_rtos.h" + + +/* Enable stack backtrace across exception/interrupt - see below */ +#define XT_DEBUG_BACKTRACE 1 + + +/* +-------------------------------------------------------------------------------- + Defines used to access _xtos_interrupt_table. +-------------------------------------------------------------------------------- +*/ +#define XIE_HANDLER 0 +#define XIE_ARG 4 +#define XIE_SIZE 8 + +/* +-------------------------------------------------------------------------------- + Macro extract_msb - return the input with only the highest bit set. + + Input : "ain" - Input value, clobbered. + Output : "aout" - Output value, has only one bit set, MSB of "ain". + The two arguments must be different AR registers. +-------------------------------------------------------------------------------- +*/ + + .macro extract_msb aout ain +1: + addi \aout, \ain, -1 /* aout = ain - 1 */ + and \ain, \ain, \aout /* ain = ain & aout */ + bnez \ain, 1b /* repeat until ain == 0 */ + addi \aout, \aout, 1 /* return aout + 1 */ + .endm + +/* +-------------------------------------------------------------------------------- + Macro dispatch_c_isr - dispatch interrupts to user ISRs. + This will dispatch to user handlers (if any) that are registered in the + XTOS dispatch table (_xtos_interrupt_table). These handlers would have + been registered by calling _xtos_set_interrupt_handler(). There is one + exception - the timer interrupt used by the OS will not be dispatched + to a user handler - this must be handled by the caller of this macro. + + Level triggered and software interrupts are automatically deasserted by + this code. + + ASSUMPTIONS: + -- PS.INTLEVEL is set to "level" at entry + -- PS.EXCM = 0, C calling enabled + + NOTE: For CALL0 ABI, a12-a15 have not yet been saved. + + NOTE: This macro will use registers a0 and a2-a6. The arguments are: + level -- interrupt level + mask -- interrupt bitmask for this level +-------------------------------------------------------------------------------- +*/ + + .macro dispatch_c_isr level mask + + /* Get mask of pending, enabled interrupts at this level into a2. */ + +.L_xt_user_int_&level&: + rsr a2, INTENABLE + rsr a3, INTERRUPT + movi a4, \mask + and a2, a2, a3 + and a2, a2, a4 + beqz a2, 9f /* nothing to do */ + + /* This bit of code provides a nice debug backtrace in the debugger. + It does take a few more instructions, so undef XT_DEBUG_BACKTRACE + if you want to save the cycles. + */ + #if XT_DEBUG_BACKTRACE + #ifndef __XTENSA_CALL0_ABI__ + rsr a0, EPC_1 + \level - 1 /* return address */ + movi a4, 0xC0000000 /* constant with top 2 bits set (call size) */ + or a0, a0, a4 /* set top 2 bits */ + addx2 a0, a4, a0 /* clear top bit -- simulating call4 size */ + #endif + #endif + + #ifdef XT_INTEXC_HOOKS + /* Call interrupt hook if present to (pre)handle interrupts. */ + movi a4, _xt_intexc_hooks + l32i a4, a4, \level << 2 + beqz a4, 2f + #ifdef __XTENSA_CALL0_ABI__ + callx0 a4 + beqz a2, 9f + #else + mov a6, a2 + callx4 a4 + beqz a6, 9f + mov a2, a6 + #endif +2: + #endif + + /* Now look up in the dispatch table and call user ISR if any. */ + /* If multiple bits are set then MSB has highest priority. */ + + extract_msb a4, a2 /* a4 = MSB of a2, a2 trashed */ + + #ifdef XT_USE_SWPRI + /* Enable all interrupts at this level that are numerically higher + than the one we just selected, since they are treated as higher + priority. + */ + movi a3, \mask /* a3 = all interrupts at this level */ + add a2, a4, a4 /* a2 = a4 << 1 */ + addi a2, a2, -1 /* a2 = mask of 1's <= a4 bit */ + and a2, a2, a3 /* a2 = mask of all bits <= a4 at this level */ + movi a3, _xt_intdata + l32i a6, a3, 4 /* a6 = _xt_vpri_mask */ + neg a2, a2 + addi a2, a2, -1 /* a2 = mask to apply */ + and a5, a6, a2 /* mask off all bits <= a4 bit */ + s32i a5, a3, 4 /* update _xt_vpri_mask */ + rsr a3, INTENABLE + and a3, a3, a2 /* mask off all bits <= a4 bit */ + wsr a3, INTENABLE + rsil a3, \level - 1 /* lower interrupt level by 1 */ + #endif + + movi a3, XT_TIMER_INTEN /* a3 = timer interrupt bit */ + wsr a4, INTCLEAR /* clear sw or edge-triggered interrupt */ + beq a3, a4, 7f /* if timer interrupt then skip table */ + + find_ms_setbit a3, a4, a3, 0 /* a3 = interrupt number */ + + movi a4, _xt_interrupt_table + addx8 a3, a3, a4 /* a3 = address of interrupt table entry */ + l32i a4, a3, XIE_HANDLER /* a4 = handler address */ + #ifdef __XTENSA_CALL0_ABI__ + mov a12, a6 /* save in callee-saved reg */ + l32i a2, a3, XIE_ARG /* a2 = handler arg */ + callx0 a4 /* call handler */ + mov a2, a12 + #else + mov a2, a6 /* save in windowed reg */ + l32i a6, a3, XIE_ARG /* a6 = handler arg */ + callx4 a4 /* call handler */ + #endif + + #ifdef XT_USE_SWPRI + j 8f + #else + j .L_xt_user_int_&level& /* check for more interrupts */ + #endif + +7: + + .ifeq XT_TIMER_INTPRI - \level +.L_xt_user_int_timer_&level&: + /* + Interrupt handler for the RTOS tick timer if at this level. + We'll be reading the interrupt state again after this call + so no need to preserve any registers except a6 (vpri_mask). + */ + + #ifdef __XTENSA_CALL0_ABI__ + mov a12, a6 + call0 XT_RTOS_TIMER_INT + mov a2, a12 + #else + mov a2, a6 + call4 XT_RTOS_TIMER_INT + #endif + .endif + + #ifdef XT_USE_SWPRI + j 8f + #else + j .L_xt_user_int_&level& /* check for more interrupts */ + #endif + + #ifdef XT_USE_SWPRI +8: + /* Restore old value of _xt_vpri_mask from a2. Also update INTENABLE from + virtual _xt_intenable which _could_ have changed during interrupt + processing. */ + + movi a3, _xt_intdata + l32i a4, a3, 0 /* a4 = _xt_intenable */ + s32i a2, a3, 4 /* update _xt_vpri_mask */ + and a4, a4, a2 /* a4 = masked intenable */ + wsr a4, INTENABLE /* update INTENABLE */ + #endif + +9: + /* done */ + + .endm + + +/* +-------------------------------------------------------------------------------- + Panic handler. + Should be reached by call0 (preferable) or jump only. If call0, a0 says where + from. If on simulator, display panic message and abort, else loop indefinitely. +-------------------------------------------------------------------------------- +*/ + + .text + .global _xt_panic + .type _xt_panic,@function + .align 4 + +_xt_panic: + #ifdef XT_SIMULATOR + addi a4, a0, -3 /* point to call0 */ + movi a3, _xt_panic_message + movi a2, SYS_log_msg + simcall + movi a2, SYS_gdb_abort + simcall + #else + rsil a2, XCHAL_EXCM_LEVEL /* disable all low & med ints */ +1: j 1b /* loop infinitely */ + #endif + + .section .rodata, "a" + .align 4 + +_xt_panic_message: + .string "\n*** _xt_panic() was called from 0x%08x or jumped to. ***\n" + + +/* +-------------------------------------------------------------------------------- + Hooks to dynamically install handlers for exceptions and interrupts. + Allows automated regression frameworks to install handlers per test. + Consists of an array of function pointers indexed by interrupt level, + with index 0 containing the entry for user exceptions. + Initialized with all 0s, meaning no handler is installed at each level. + See comment in xtensa_rtos.h for more details. +-------------------------------------------------------------------------------- +*/ + + #ifdef XT_INTEXC_HOOKS + .data + .global _xt_intexc_hooks + .type _xt_intexc_hooks,@object + .align 4 + +_xt_intexc_hooks: + .fill XT_INTEXC_HOOK_NUM, 4, 0 + #endif + + +/* +-------------------------------------------------------------------------------- + EXCEPTION AND LEVEL 1 INTERRUPT VECTORS AND LOW LEVEL HANDLERS + (except window exception vectors). + + Each vector goes at a predetermined location according to the Xtensa + hardware configuration, which is ensured by its placement in a special + section known to the Xtensa linker support package (LSP). It performs + the minimum necessary before jumping to the handler in the .text section. + + The corresponding handler goes in the normal .text section. It sets up + the appropriate stack frame, saves a few vector-specific registers and + calls XT_RTOS_INT_ENTER to save the rest of the interrupted context + and enter the RTOS, then sets up a C environment. It then calls the + user's interrupt handler code (which may be coded in C) and finally + calls XT_RTOS_INT_EXIT to transfer control to the RTOS for scheduling. + + While XT_RTOS_INT_EXIT does not return directly to the interruptee, + eventually the RTOS scheduler will want to dispatch the interrupted + task or handler. The scheduler will return to the exit point that was + saved in the interrupt stack frame at XT_STK_EXIT. +-------------------------------------------------------------------------------- +*/ + + +/* +-------------------------------------------------------------------------------- +Debug Exception. +-------------------------------------------------------------------------------- +*/ + +#if XCHAL_HAVE_DEBUG + + .begin literal_prefix .DebugExceptionVector + .section .DebugExceptionVector.text, "ax" + .global _DebugExceptionVector + .align 4 + +_DebugExceptionVector: + + #ifdef XT_SIMULATOR + /* + In the simulator, let the debugger (if any) handle the debug exception, + or simply stop the simulation: + */ + wsr a2, EXCSAVE+XCHAL_DEBUGLEVEL /* save a2 where sim expects it */ + movi a2, SYS_gdb_enter_sktloop + simcall /* have ISS handle debug exc. */ + #elif 0 /* change condition to 1 to use the HAL minimal debug handler */ + wsr a3, EXCSAVE+XCHAL_DEBUGLEVEL + movi a3, xthal_debugexc_defhndlr_nw /* use default debug handler */ + jx a3 + #else + wsr a0, EXCSAVE+XCHAL_DEBUGLEVEL /* save original a0 somewhere */ + call0 _xt_panic /* does not return */ + rfi XCHAL_DEBUGLEVEL /* make a0 point here not later */ + #endif + + .end literal_prefix + +#endif + +/* +-------------------------------------------------------------------------------- +Double Exception. +Double exceptions are not a normal occurrence. They indicate a bug of some kind. +-------------------------------------------------------------------------------- +*/ + +#ifdef XCHAL_DOUBLEEXC_VECTOR_VADDR + + .begin literal_prefix .DoubleExceptionVector + .section .DoubleExceptionVector.text, "ax" + .global _DoubleExceptionVector + .align 4 + +_DoubleExceptionVector: + + #if XCHAL_HAVE_DEBUG + break 1, 4 /* unhandled double exception */ + #endif + call0 _xt_panic /* does not return */ + rfde /* make a0 point here not later */ + + .end literal_prefix + +#endif /* XCHAL_DOUBLEEXC_VECTOR_VADDR */ + +/* +-------------------------------------------------------------------------------- +Kernel Exception (including Level 1 Interrupt from kernel mode). +-------------------------------------------------------------------------------- +*/ + + .begin literal_prefix .KernelExceptionVector + .section .KernelExceptionVector.text, "ax" + .global _KernelExceptionVector + .align 4 + +_KernelExceptionVector: + + wsr a0, EXCSAVE_1 /* preserve a0 */ + call0 _xt_kernel_exc /* kernel exception handler */ + /* never returns here - call0 is used as a jump (see note at top) */ + + .end literal_prefix + + .text + .align 4 + +_xt_kernel_exc: + #if XCHAL_HAVE_DEBUG + break 1, 0 /* unhandled kernel exception */ + #endif + call0 _xt_panic /* does not return */ + rfe /* make a0 point here not there */ + + +/* +-------------------------------------------------------------------------------- +User Exception (including Level 1 Interrupt from user mode). +-------------------------------------------------------------------------------- +*/ + + .begin literal_prefix .UserExceptionVector + .section .UserExceptionVector.text, "ax" + .global _UserExceptionVector + .type _UserExceptionVector,@function + .align 4 + +_UserExceptionVector: + + wsr a0, EXCSAVE_1 /* preserve a0 */ + call0 _xt_user_exc /* user exception handler */ + /* never returns here - call0 is used as a jump (see note at top) */ + + .end literal_prefix + +/* +-------------------------------------------------------------------------------- + Insert some waypoints for jumping beyond the signed 8-bit range of + conditional branch instructions, so the conditional branchces to specific + exception handlers are not taken in the mainline. Saves some cycles in the + mainline. +-------------------------------------------------------------------------------- +*/ + + .text + + #if XCHAL_HAVE_WINDOWED + .align 4 +_xt_to_alloca_exc: + call0 _xt_alloca_exc /* in window vectors section */ + /* never returns here - call0 is used as a jump (see note at top) */ + #endif + + .align 4 +_xt_to_syscall_exc: + call0 _xt_syscall_exc + /* never returns here - call0 is used as a jump (see note at top) */ + + #if XCHAL_CP_NUM > 0 + .align 4 +_xt_to_coproc_exc: + call0 _xt_coproc_exc + /* never returns here - call0 is used as a jump (see note at top) */ + #endif + + +/* +-------------------------------------------------------------------------------- + User exception handler. +-------------------------------------------------------------------------------- +*/ + + .type _xt_user_exc,@function + .align 4 + +_xt_user_exc: + + /* If level 1 interrupt then jump to the dispatcher */ + rsr a0, EXCCAUSE + beqi a0, EXCCAUSE_LEVEL1INTERRUPT, _xt_lowint1 + + /* Handle any coprocessor exceptions. Rely on the fact that exception + numbers above EXCCAUSE_CP0_DISABLED all relate to the coprocessors. + */ + #if XCHAL_CP_NUM > 0 + bgeui a0, EXCCAUSE_CP0_DISABLED, _xt_to_coproc_exc + #endif + + /* Handle alloca and syscall exceptions */ + #if XCHAL_HAVE_WINDOWED + beqi a0, EXCCAUSE_ALLOCA, _xt_to_alloca_exc + #endif + beqi a0, EXCCAUSE_SYSCALL, _xt_to_syscall_exc + + /* Handle all other exceptions. All can have user-defined handlers. */ + /* NOTE: we'll stay on the user stack for exception handling. */ + + /* Allocate exception frame and save minimal context. */ + mov a0, sp + addi sp, sp, -XT_STK_FRMSZ + s32i a0, sp, XT_STK_A1 + #if XCHAL_HAVE_WINDOWED + s32e a0, sp, -12 /* for debug backtrace */ + #endif + rsr a0, PS /* save interruptee's PS */ + s32i a0, sp, XT_STK_PS + rsr a0, EPC_1 /* save interruptee's PC */ + s32i a0, sp, XT_STK_PC + rsr a0, EXCSAVE_1 /* save interruptee's a0 */ + s32i a0, sp, XT_STK_A0 + #if XCHAL_HAVE_WINDOWED + s32e a0, sp, -16 /* for debug backtrace */ + #endif + s32i a12, sp, XT_STK_A12 /* _xt_context_save requires A12- */ + s32i a13, sp, XT_STK_A13 /* A13 to have already been saved */ + call0 _xt_context_save + + /* Save exc cause and vaddr into exception frame */ + rsr a0, EXCCAUSE + s32i a0, sp, XT_STK_EXCCAUSE + rsr a0, EXCVADDR + s32i a0, sp, XT_STK_EXCVADDR + + /* Set up PS for C, reenable hi-pri interrupts, and clear EXCM. */ + #ifdef __XTENSA_CALL0_ABI__ + movi a0, PS_INTLEVEL(XCHAL_EXCM_LEVEL) | PS_UM + #else + movi a0, PS_INTLEVEL(XCHAL_EXCM_LEVEL) | PS_UM | PS_WOE + #endif + wsr a0, PS + + #ifdef XT_DEBUG_BACKTRACE + #ifndef __XTENSA_CALL0_ABI__ + rsr a0, EPC_1 /* return address for debug backtrace */ + movi a5, 0xC0000000 /* constant with top 2 bits set (call size) */ + rsync /* wait for WSR.PS to complete */ + or a0, a0, a5 /* set top 2 bits */ + addx2 a0, a5, a0 /* clear top bit -- thus simulating call4 size */ + #else + rsync /* wait for WSR.PS to complete */ + #endif + #endif + + rsr a2, EXCCAUSE /* recover exc cause */ + + #ifdef XT_INTEXC_HOOKS + /* + Call exception hook to pre-handle exceptions (if installed). + Pass EXCCAUSE in a2, and check result in a2 (if -1, skip default handling). + */ + movi a4, _xt_intexc_hooks + l32i a4, a4, 0 /* user exception hook index 0 */ + beqz a4, 1f +.Ln_xt_user_exc_call_hook: + #ifdef __XTENSA_CALL0_ABI__ + callx0 a4 + beqi a2, -1, .L_xt_user_done + #else + mov a6, a2 + callx4 a4 + beqi a6, -1, .L_xt_user_done + mov a2, a6 + #endif +1: + #endif + + rsr a2, EXCCAUSE /* recover exc cause */ + movi a3, _xt_exception_table + addx4 a4, a2, a3 /* a4 = address of exception table entry */ + l32i a4, a4, 0 /* a4 = handler address */ + #ifdef __XTENSA_CALL0_ABI__ + mov a2, sp /* a2 = pointer to exc frame */ + callx0 a4 /* call handler */ + #else + mov a6, sp /* a6 = pointer to exc frame */ + callx4 a4 /* call handler */ + #endif + +.L_xt_user_done: + + /* Restore context and return */ + call0 _xt_context_restore + l32i a0, sp, XT_STK_PS /* retrieve interruptee's PS */ + wsr a0, PS + l32i a0, sp, XT_STK_PC /* retrieve interruptee's PC */ + wsr a0, EPC_1 + l32i a0, sp, XT_STK_A0 /* retrieve interruptee's A0 */ + l32i sp, sp, XT_STK_A1 /* remove exception frame */ + rsync /* ensure PS and EPC written */ + rfe /* PS.EXCM is cleared */ + + +/* +-------------------------------------------------------------------------------- + Exit point for dispatch. Saved in interrupt stack frame at XT_STK_EXIT + on entry and used to return to a thread or interrupted interrupt handler. +-------------------------------------------------------------------------------- +*/ + + .global _xt_user_exit + .type _xt_user_exit,@function + .align 4 +_xt_user_exit: + l32i a0, sp, XT_STK_PS /* retrieve interruptee's PS */ + wsr a0, PS + l32i a0, sp, XT_STK_PC /* retrieve interruptee's PC */ + wsr a0, EPC_1 + l32i a0, sp, XT_STK_A0 /* retrieve interruptee's A0 */ + l32i sp, sp, XT_STK_A1 /* remove interrupt stack frame */ + rsync /* ensure PS and EPC written */ + rfe /* PS.EXCM is cleared */ + + +/* +-------------------------------------------------------------------------------- +Syscall Exception Handler (jumped to from User Exception Handler). +Syscall 0 is required to spill the register windows (no-op in Call 0 ABI). +Only syscall 0 is handled here. Other syscalls return -1 to caller in a2. +-------------------------------------------------------------------------------- +*/ + + .text + .type _xt_syscall_exc,@function + .align 4 +_xt_syscall_exc: + + #ifdef __XTENSA_CALL0_ABI__ + /* + Save minimal regs for scratch. Syscall 0 does nothing in Call0 ABI. + Use a minimal stack frame (16B) to save A2 & A3 for scratch. + PS.EXCM could be cleared here, but unlikely to improve worst-case latency. + rsr a0, PS + addi a0, a0, -PS_EXCM_MASK + wsr a0, PS + */ + addi sp, sp, -16 + s32i a2, sp, 8 + s32i a3, sp, 12 + #else /* Windowed ABI */ + /* + Save necessary context and spill the register windows. + PS.EXCM is still set and must remain set until after the spill. + Reuse context save function though it saves more than necessary. + For this reason, a full interrupt stack frame is allocated. + */ + addi sp, sp, -XT_STK_FRMSZ /* allocate interrupt stack frame */ + s32i a12, sp, XT_STK_A12 /* _xt_context_save requires A12- */ + s32i a13, sp, XT_STK_A13 /* A13 to have already been saved */ + call0 _xt_context_save + #endif + + /* + Grab the interruptee's PC and skip over the 'syscall' instruction. + If it's at the end of a zero-overhead loop and it's not on the last + iteration, decrement loop counter and skip to beginning of loop. + */ + rsr a2, EPC_1 /* a2 = PC of 'syscall' */ + addi a3, a2, 3 /* ++PC */ + #if XCHAL_HAVE_LOOPS + rsr a0, LEND /* if (PC == LEND */ + bne a3, a0, 1f + rsr a0, LCOUNT /* && LCOUNT != 0) */ + beqz a0, 1f /* { */ + addi a0, a0, -1 /* --LCOUNT */ + rsr a3, LBEG /* PC = LBEG */ + wsr a0, LCOUNT /* } */ + #endif +1: wsr a3, EPC_1 /* update PC */ + + /* Restore interruptee's context and return from exception. */ + #ifdef __XTENSA_CALL0_ABI__ + l32i a2, sp, 8 + l32i a3, sp, 12 + addi sp, sp, 16 + #else + call0 _xt_context_restore + addi sp, sp, XT_STK_FRMSZ + #endif + movi a0, -1 + movnez a2, a0, a2 /* return -1 if not syscall 0 */ + rsr a0, EXCSAVE_1 + rfe + +/* +-------------------------------------------------------------------------------- +Co-Processor Exception Handler (jumped to from User Exception Handler). +These exceptions are generated by co-processor instructions, which are only +allowed in thread code (not in interrupts or kernel code). This restriction is +deliberately imposed to reduce the burden of state-save/restore in interrupts. +-------------------------------------------------------------------------------- +*/ +#if XCHAL_CP_NUM > 0 + + .section .rodata, "a" + +/* Offset to CP n save area in thread's CP save area. */ + .global _xt_coproc_sa_offset + .type _xt_coproc_sa_offset,@object + .align 16 /* minimize crossing cache boundaries */ +_xt_coproc_sa_offset: + .word XT_CP0_SA, XT_CP1_SA, XT_CP2_SA, XT_CP3_SA + .word XT_CP4_SA, XT_CP5_SA, XT_CP6_SA, XT_CP7_SA + +/* Bitmask for CP n's CPENABLE bit. */ + .type _xt_coproc_mask,@object + .align 16,,8 /* try to keep it all in one cache line */ + .set i, 0 +_xt_coproc_mask: + .rept XCHAL_CP_MAX + .long (i<<16) | (1<= 2 + + .begin literal_prefix .Level2InterruptVector + .section .Level2InterruptVector.text, "ax" + .global _Level2Vector + .type _Level2Vector,@function + .align 4 +_Level2Vector: + wsr a0, EXCSAVE_2 /* preserve a0 */ + call0 _xt_medint2 /* load interrupt handler */ + /* never returns here - call0 is used as a jump (see note at top) */ + + .end literal_prefix + + .text + .type _xt_medint2,@function + .align 4 +_xt_medint2: + mov a0, sp /* sp == a1 */ + addi sp, sp, -XT_STK_FRMSZ /* allocate interrupt stack frame */ + s32i a0, sp, XT_STK_A1 /* save pre-interrupt SP */ + rsr a0, EPS_2 /* save interruptee's PS */ + s32i a0, sp, XT_STK_PS + rsr a0, EPC_2 /* save interruptee's PC */ + s32i a0, sp, XT_STK_PC + rsr a0, EXCSAVE_2 /* save interruptee's a0 */ + s32i a0, sp, XT_STK_A0 + movi a0, _xt_medint2_exit /* save exit point for dispatch */ + s32i a0, sp, XT_STK_EXIT + + /* Save rest of interrupt context and enter RTOS. */ + call0 XT_RTOS_INT_ENTER /* common RTOS interrupt entry */ + + /* !! We are now on the RTOS system stack !! */ + + /* Set up PS for C, enable interrupts above this level and clear EXCM. */ + #ifdef __XTENSA_CALL0_ABI__ + movi a0, PS_INTLEVEL(2) | PS_UM + #else + movi a0, PS_INTLEVEL(2) | PS_UM | PS_WOE + #endif + wsr a0, PS + rsync + + /* OK to call C code at this point, dispatch user ISRs */ + + dispatch_c_isr 2 XCHAL_INTLEVEL2_MASK + + /* Done handling interrupts, transfer control to OS */ + call0 XT_RTOS_INT_EXIT /* does not return directly here */ + + /* + Exit point for dispatch. Saved in interrupt stack frame at XT_STK_EXIT + on entry and used to return to a thread or interrupted interrupt handler. + */ + .global _xt_medint2_exit + .type _xt_medint2_exit,@function + .align 4 +_xt_medint2_exit: + /* Restore only level-specific regs (the rest were already restored) */ + l32i a0, sp, XT_STK_PS /* retrieve interruptee's PS */ + wsr a0, EPS_2 + l32i a0, sp, XT_STK_PC /* retrieve interruptee's PC */ + wsr a0, EPC_2 + l32i a0, sp, XT_STK_A0 /* retrieve interruptee's A0 */ + l32i sp, sp, XT_STK_A1 /* remove interrupt stack frame */ + rsync /* ensure EPS and EPC written */ + rfi 2 + +#endif /* Level 2 */ + +#if XCHAL_EXCM_LEVEL >= 3 + + .begin literal_prefix .Level3InterruptVector + .section .Level3InterruptVector.text, "ax" + .global _Level3Vector + .type _Level3Vector,@function + .align 4 +_Level3Vector: + wsr a0, EXCSAVE_3 /* preserve a0 */ + call0 _xt_medint3 /* load interrupt handler */ + /* never returns here - call0 is used as a jump (see note at top) */ + + .end literal_prefix + + .text + .type _xt_medint3,@function + .align 4 +_xt_medint3: + mov a0, sp /* sp == a1 */ + addi sp, sp, -XT_STK_FRMSZ /* allocate interrupt stack frame */ + s32i a0, sp, XT_STK_A1 /* save pre-interrupt SP */ + rsr a0, EPS_3 /* save interruptee's PS */ + s32i a0, sp, XT_STK_PS + rsr a0, EPC_3 /* save interruptee's PC */ + s32i a0, sp, XT_STK_PC + rsr a0, EXCSAVE_3 /* save interruptee's a0 */ + s32i a0, sp, XT_STK_A0 + movi a0, _xt_medint3_exit /* save exit point for dispatch */ + s32i a0, sp, XT_STK_EXIT + + /* Save rest of interrupt context and enter RTOS. */ + call0 XT_RTOS_INT_ENTER /* common RTOS interrupt entry */ + + /* !! We are now on the RTOS system stack !! */ + + /* Set up PS for C, enable interrupts above this level and clear EXCM. */ + #ifdef __XTENSA_CALL0_ABI__ + movi a0, PS_INTLEVEL(3) | PS_UM + #else + movi a0, PS_INTLEVEL(3) | PS_UM | PS_WOE + #endif + wsr a0, PS + rsync + + /* OK to call C code at this point, dispatch user ISRs */ + + dispatch_c_isr 3 XCHAL_INTLEVEL3_MASK + + /* Done handling interrupts, transfer control to OS */ + call0 XT_RTOS_INT_EXIT /* does not return directly here */ + + /* + Exit point for dispatch. Saved in interrupt stack frame at XT_STK_EXIT + on entry and used to return to a thread or interrupted interrupt handler. + */ + .global _xt_medint3_exit + .type _xt_medint3_exit,@function + .align 4 +_xt_medint3_exit: + /* Restore only level-specific regs (the rest were already restored) */ + l32i a0, sp, XT_STK_PS /* retrieve interruptee's PS */ + wsr a0, EPS_3 + l32i a0, sp, XT_STK_PC /* retrieve interruptee's PC */ + wsr a0, EPC_3 + l32i a0, sp, XT_STK_A0 /* retrieve interruptee's A0 */ + l32i sp, sp, XT_STK_A1 /* remove interrupt stack frame */ + rsync /* ensure EPS and EPC written */ + rfi 3 + +#endif /* Level 3 */ + +#if XCHAL_EXCM_LEVEL >= 4 + + .begin literal_prefix .Level4InterruptVector + .section .Level4InterruptVector.text, "ax" + .global _Level4Vector + .type _Level4Vector,@function + .align 4 +_Level4Vector: + wsr a0, EXCSAVE_4 /* preserve a0 */ + call0 _xt_medint4 /* load interrupt handler */ + + .end literal_prefix + + .text + .type _xt_medint4,@function + .align 4 +_xt_medint4: + mov a0, sp /* sp == a1 */ + addi sp, sp, -XT_STK_FRMSZ /* allocate interrupt stack frame */ + s32i a0, sp, XT_STK_A1 /* save pre-interrupt SP */ + rsr a0, EPS_4 /* save interruptee's PS */ + s32i a0, sp, XT_STK_PS + rsr a0, EPC_4 /* save interruptee's PC */ + s32i a0, sp, XT_STK_PC + rsr a0, EXCSAVE_4 /* save interruptee's a0 */ + s32i a0, sp, XT_STK_A0 + movi a0, _xt_medint4_exit /* save exit point for dispatch */ + s32i a0, sp, XT_STK_EXIT + + /* Save rest of interrupt context and enter RTOS. */ + call0 XT_RTOS_INT_ENTER /* common RTOS interrupt entry */ + + /* !! We are now on the RTOS system stack !! */ + + /* Set up PS for C, enable interrupts above this level and clear EXCM. */ + #ifdef __XTENSA_CALL0_ABI__ + movi a0, PS_INTLEVEL(4) | PS_UM + #else + movi a0, PS_INTLEVEL(4) | PS_UM | PS_WOE + #endif + wsr a0, PS + rsync + + /* OK to call C code at this point, dispatch user ISRs */ + + dispatch_c_isr 4 XCHAL_INTLEVEL4_MASK + + /* Done handling interrupts, transfer control to OS */ + call0 XT_RTOS_INT_EXIT /* does not return directly here */ + + /* + Exit point for dispatch. Saved in interrupt stack frame at XT_STK_EXIT + on entry and used to return to a thread or interrupted interrupt handler. + */ + .global _xt_medint4_exit + .type _xt_medint4_exit,@function + .align 4 +_xt_medint4_exit: + /* Restore only level-specific regs (the rest were already restored) */ + l32i a0, sp, XT_STK_PS /* retrieve interruptee's PS */ + wsr a0, EPS_4 + l32i a0, sp, XT_STK_PC /* retrieve interruptee's PC */ + wsr a0, EPC_4 + l32i a0, sp, XT_STK_A0 /* retrieve interruptee's A0 */ + l32i sp, sp, XT_STK_A1 /* remove interrupt stack frame */ + rsync /* ensure EPS and EPC written */ + rfi 4 + +#endif /* Level 4 */ + +#if XCHAL_EXCM_LEVEL >= 5 + + .begin literal_prefix .Level5InterruptVector + .section .Level5InterruptVector.text, "ax" + .global _Level5Vector + .type _Level5Vector,@function + .align 4 +_Level5Vector: + wsr a0, EXCSAVE_5 /* preserve a0 */ + call0 _xt_medint5 /* load interrupt handler */ + + .end literal_prefix + + .text + .type _xt_medint5,@function + .align 4 +_xt_medint5: + mov a0, sp /* sp == a1 */ + addi sp, sp, -XT_STK_FRMSZ /* allocate interrupt stack frame */ + s32i a0, sp, XT_STK_A1 /* save pre-interrupt SP */ + rsr a0, EPS_5 /* save interruptee's PS */ + s32i a0, sp, XT_STK_PS + rsr a0, EPC_5 /* save interruptee's PC */ + s32i a0, sp, XT_STK_PC + rsr a0, EXCSAVE_5 /* save interruptee's a0 */ + s32i a0, sp, XT_STK_A0 + movi a0, _xt_medint5_exit /* save exit point for dispatch */ + s32i a0, sp, XT_STK_EXIT + + /* Save rest of interrupt context and enter RTOS. */ + call0 XT_RTOS_INT_ENTER /* common RTOS interrupt entry */ + + /* !! We are now on the RTOS system stack !! */ + + /* Set up PS for C, enable interrupts above this level and clear EXCM. */ + #ifdef __XTENSA_CALL0_ABI__ + movi a0, PS_INTLEVEL(5) | PS_UM + #else + movi a0, PS_INTLEVEL(5) | PS_UM | PS_WOE + #endif + wsr a0, PS + rsync + + /* OK to call C code at this point, dispatch user ISRs */ + + dispatch_c_isr 5 XCHAL_INTLEVEL5_MASK + + /* Done handling interrupts, transfer control to OS */ + call0 XT_RTOS_INT_EXIT /* does not return directly here */ + + /* + Exit point for dispatch. Saved in interrupt stack frame at XT_STK_EXIT + on entry and used to return to a thread or interrupted interrupt handler. + */ + .global _xt_medint5_exit + .type _xt_medint5_exit,@function + .align 4 +_xt_medint5_exit: + /* Restore only level-specific regs (the rest were already restored) */ + l32i a0, sp, XT_STK_PS /* retrieve interruptee's PS */ + wsr a0, EPS_5 + l32i a0, sp, XT_STK_PC /* retrieve interruptee's PC */ + wsr a0, EPC_5 + l32i a0, sp, XT_STK_A0 /* retrieve interruptee's A0 */ + l32i sp, sp, XT_STK_A1 /* remove interrupt stack frame */ + rsync /* ensure EPS and EPC written */ + rfi 5 + +#endif /* Level 5 */ + +#if XCHAL_EXCM_LEVEL >= 6 + + .begin literal_prefix .Level6InterruptVector + .section .Level6InterruptVector.text, "ax" + .global _Level6Vector + .type _Level6Vector,@function + .align 4 +_Level6Vector: + wsr a0, EXCSAVE_6 /* preserve a0 */ + call0 _xt_medint6 /* load interrupt handler */ + + .end literal_prefix + + .text + .type _xt_medint6,@function + .align 4 +_xt_medint6: + mov a0, sp /* sp == a1 */ + addi sp, sp, -XT_STK_FRMSZ /* allocate interrupt stack frame */ + s32i a0, sp, XT_STK_A1 /* save pre-interrupt SP */ + rsr a0, EPS_6 /* save interruptee's PS */ + s32i a0, sp, XT_STK_PS + rsr a0, EPC_6 /* save interruptee's PC */ + s32i a0, sp, XT_STK_PC + rsr a0, EXCSAVE_6 /* save interruptee's a0 */ + s32i a0, sp, XT_STK_A0 + movi a0, _xt_medint6_exit /* save exit point for dispatch */ + s32i a0, sp, XT_STK_EXIT + + /* Save rest of interrupt context and enter RTOS. */ + call0 XT_RTOS_INT_ENTER /* common RTOS interrupt entry */ + + /* !! We are now on the RTOS system stack !! */ + + /* Set up PS for C, enable interrupts above this level and clear EXCM. */ + #ifdef __XTENSA_CALL0_ABI__ + movi a0, PS_INTLEVEL(6) | PS_UM + #else + movi a0, PS_INTLEVEL(6) | PS_UM | PS_WOE + #endif + wsr a0, PS + rsync + + /* OK to call C code at this point, dispatch user ISRs */ + + dispatch_c_isr 6 XCHAL_INTLEVEL6_MASK + + /* Done handling interrupts, transfer control to OS */ + call0 XT_RTOS_INT_EXIT /* does not return directly here */ + + /* + Exit point for dispatch. Saved in interrupt stack frame at XT_STK_EXIT + on entry and used to return to a thread or interrupted interrupt handler. + */ + .global _xt_medint6_exit + .type _xt_medint6_exit,@function + .align 4 +_xt_medint6_exit: + /* Restore only level-specific regs (the rest were already restored) */ + l32i a0, sp, XT_STK_PS /* retrieve interruptee's PS */ + wsr a0, EPS_6 + l32i a0, sp, XT_STK_PC /* retrieve interruptee's PC */ + wsr a0, EPC_6 + l32i a0, sp, XT_STK_A0 /* retrieve interruptee's A0 */ + l32i sp, sp, XT_STK_A1 /* remove interrupt stack frame */ + rsync /* ensure EPS and EPC written */ + rfi 6 + +#endif /* Level 6 */ + + +/******************************************************************************* + +HIGH PRIORITY (LEVEL > XCHAL_EXCM_LEVEL) INTERRUPT VECTORS AND HANDLERS + +High priority interrupts are by definition those with priorities greater +than XCHAL_EXCM_LEVEL. This includes non-maskable (NMI). High priority +interrupts cannot interact with the RTOS, that is they must save all regs +they use and not call any RTOS function. + +A further restriction imposed by the Xtensa windowed architecture is that +high priority interrupts must not modify the stack area even logically +"above" the top of the interrupted stack (they need to provide their +own stack or static save area). + +Cadence Design Systems recommends high priority interrupt handlers be coded in assembly +and used for purposes requiring very short service times. + +Here are templates for high priority (level 2+) interrupt vectors. +They assume only one interrupt per level to avoid the burden of identifying +which interrupts at this level are pending and enabled. This allows for +minimum latency and avoids having to save/restore a2 in addition to a0. +If more than one interrupt per high priority level is configured, this burden +is on the handler which in any case must provide a way to save and restore +registers it uses without touching the interrupted stack. + +Each vector goes at a predetermined location according to the Xtensa +hardware configuration, which is ensured by its placement in a special +section known to the Xtensa linker support package (LSP). It performs +the minimum necessary before jumping to the handler in the .text section. + +*******************************************************************************/ + +/* +Currently only shells for high priority interrupt handlers are provided +here. However a template and example can be found in the Cadence Design Systems tools +documentation: "Microprocessor Programmer's Guide". +*/ + +#if XCHAL_NUM_INTLEVELS >=2 && XCHAL_EXCM_LEVEL <2 && XCHAL_DEBUGLEVEL !=2 + + .begin literal_prefix .Level2InterruptVector + .section .Level2InterruptVector.text, "ax" + .global _Level2Vector + .type _Level2Vector,@function + .align 4 +_Level2Vector: + wsr a0, EXCSAVE_2 /* preserve a0 */ + call0 _xt_highint2 /* load interrupt handler */ + + .end literal_prefix + + .text + .type _xt_highint2,@function + .align 4 +_xt_highint2: + + #ifdef XT_INTEXC_HOOKS + /* Call interrupt hook if present to (pre)handle interrupts. */ + movi a0, _xt_intexc_hooks + l32i a0, a0, 2<<2 + beqz a0, 1f +.Ln_xt_highint2_call_hook: + callx0 a0 /* must NOT disturb stack! */ +1: + #endif + + /* USER_EDIT: + ADD HIGH PRIORITY LEVEL 2 INTERRUPT HANDLER CODE HERE. + */ + + .align 4 +.L_xt_highint2_exit: + rsr a0, EXCSAVE_2 /* restore a0 */ + rfi 2 + +#endif /* Level 2 */ + +#if XCHAL_NUM_INTLEVELS >=3 && XCHAL_EXCM_LEVEL <3 && XCHAL_DEBUGLEVEL !=3 + + .begin literal_prefix .Level3InterruptVector + .section .Level3InterruptVector.text, "ax" + .global _Level3Vector + .type _Level3Vector,@function + .align 4 +_Level3Vector: + wsr a0, EXCSAVE_3 /* preserve a0 */ + call0 _xt_highint3 /* load interrupt handler */ + /* never returns here - call0 is used as a jump (see note at top) */ + + .end literal_prefix + + .text + .type _xt_highint3,@function + .align 4 +_xt_highint3: + + #ifdef XT_INTEXC_HOOKS + /* Call interrupt hook if present to (pre)handle interrupts. */ + movi a0, _xt_intexc_hooks + l32i a0, a0, 3<<2 + beqz a0, 1f +.Ln_xt_highint3_call_hook: + callx0 a0 /* must NOT disturb stack! */ +1: + #endif + + /* USER_EDIT: + ADD HIGH PRIORITY LEVEL 3 INTERRUPT HANDLER CODE HERE. + */ + + .align 4 +.L_xt_highint3_exit: + rsr a0, EXCSAVE_3 /* restore a0 */ + rfi 3 + +#endif /* Level 3 */ + +#if XCHAL_NUM_INTLEVELS >=4 && XCHAL_EXCM_LEVEL <4 && XCHAL_DEBUGLEVEL !=4 + + .begin literal_prefix .Level4InterruptVector + .section .Level4InterruptVector.text, "ax" + .global _Level4Vector + .type _Level4Vector,@function + .align 4 +_Level4Vector: + wsr a0, EXCSAVE_4 /* preserve a0 */ + call0 _xt_highint4 /* load interrupt handler */ + /* never returns here - call0 is used as a jump (see note at top) */ + + .end literal_prefix + + .text + .type _xt_highint4,@function + .align 4 +_xt_highint4: + + #ifdef XT_INTEXC_HOOKS + /* Call interrupt hook if present to (pre)handle interrupts. */ + movi a0, _xt_intexc_hooks + l32i a0, a0, 4<<2 + beqz a0, 1f +.Ln_xt_highint4_call_hook: + callx0 a0 /* must NOT disturb stack! */ +1: + #endif + + /* USER_EDIT: + ADD HIGH PRIORITY LEVEL 4 INTERRUPT HANDLER CODE HERE. + */ + + .align 4 +.L_xt_highint4_exit: + rsr a0, EXCSAVE_4 /* restore a0 */ + rfi 4 + +#endif /* Level 4 */ + +#if XCHAL_NUM_INTLEVELS >=5 && XCHAL_EXCM_LEVEL <5 && XCHAL_DEBUGLEVEL !=5 + + .begin literal_prefix .Level5InterruptVector + .section .Level5InterruptVector.text, "ax" + .global _Level5Vector + .type _Level5Vector,@function + .align 4 +_Level5Vector: + wsr a0, EXCSAVE_5 /* preserve a0 */ + call0 _xt_highint5 /* load interrupt handler */ + /* never returns here - call0 is used as a jump (see note at top) */ + + .end literal_prefix + + .text + .type _xt_highint5,@function + .align 4 +_xt_highint5: + + #ifdef XT_INTEXC_HOOKS + /* Call interrupt hook if present to (pre)handle interrupts. */ + movi a0, _xt_intexc_hooks + l32i a0, a0, 5<<2 + beqz a0, 1f +.Ln_xt_highint5_call_hook: + callx0 a0 /* must NOT disturb stack! */ +1: + #endif + + /* USER_EDIT: + ADD HIGH PRIORITY LEVEL 5 INTERRUPT HANDLER CODE HERE. + */ + + .align 4 +.L_xt_highint5_exit: + rsr a0, EXCSAVE_5 /* restore a0 */ + rfi 5 + +#endif /* Level 5 */ + +#if XCHAL_NUM_INTLEVELS >=6 && XCHAL_EXCM_LEVEL <6 && XCHAL_DEBUGLEVEL !=6 + + .begin literal_prefix .Level6InterruptVector + .section .Level6InterruptVector.text, "ax" + .global _Level6Vector + .type _Level6Vector,@function + .align 4 +_Level6Vector: + wsr a0, EXCSAVE_6 /* preserve a0 */ + call0 _xt_highint6 /* load interrupt handler */ + /* never returns here - call0 is used as a jump (see note at top) */ + + .end literal_prefix + + .text + .type _xt_highint6,@function + .align 4 +_xt_highint6: + + #ifdef XT_INTEXC_HOOKS + /* Call interrupt hook if present to (pre)handle interrupts. */ + movi a0, _xt_intexc_hooks + l32i a0, a0, 6<<2 + beqz a0, 1f +.Ln_xt_highint6_call_hook: + callx0 a0 /* must NOT disturb stack! */ +1: + #endif + + /* USER_EDIT: + ADD HIGH PRIORITY LEVEL 6 INTERRUPT HANDLER CODE HERE. + */ + + .align 4 +.L_xt_highint6_exit: + rsr a0, EXCSAVE_6 /* restore a0 */ + rfi 6 + +#endif /* Level 6 */ + +#if XCHAL_HAVE_NMI + + .begin literal_prefix .NMIExceptionVector + .section .NMIExceptionVector.text, "ax" + .global _NMIExceptionVector + .type _NMIExceptionVector,@function + .align 4 +_NMIExceptionVector: + wsr a0, EXCSAVE + XCHAL_NMILEVEL _ /* preserve a0 */ + call0 _xt_nmi /* load interrupt handler */ + /* never returns here - call0 is used as a jump (see note at top) */ + + .end literal_prefix + + .text + .type _xt_nmi,@function + .align 4 +_xt_nmi: + + #ifdef XT_INTEXC_HOOKS + /* Call interrupt hook if present to (pre)handle interrupts. */ + movi a0, _xt_intexc_hooks + l32i a0, a0, XCHAL_NMILEVEL<<2 + beqz a0, 1f +.Ln_xt_nmi_call_hook: + callx0 a0 /* must NOT disturb stack! */ +1: + #endif + + /* USER_EDIT: + ADD HIGH PRIORITY NON-MASKABLE INTERRUPT (NMI) HANDLER CODE HERE. + */ + + .align 4 +.L_xt_nmi_exit: + rsr a0, EXCSAVE + XCHAL_NMILEVEL /* restore a0 */ + rfi XCHAL_NMILEVEL + +#endif /* NMI */ + + +/******************************************************************************* + +WINDOW OVERFLOW AND UNDERFLOW EXCEPTION VECTORS AND ALLOCA EXCEPTION HANDLER + +Here is the code for each window overflow/underflow exception vector and +(interspersed) efficient code for handling the alloca exception cause. +Window exceptions are handled entirely in the vector area and are very +tight for performance. The alloca exception is also handled entirely in +the window vector area so comes at essentially no cost in code size. +Users should never need to modify them and Cadence Design Systems recommends +they do not. + +Window handlers go at predetermined vector locations according to the +Xtensa hardware configuration, which is ensured by their placement in a +special section known to the Xtensa linker support package (LSP). Since +their offsets in that section are always the same, the LSPs do not define +a section per vector. + +These things are coded for XEA2 only (XEA1 is not supported). + +Note on Underflow Handlers: +The underflow handler for returning from call[i+1] to call[i] +must preserve all the registers from call[i+1]'s window. +In particular, a0 and a1 must be preserved because the RETW instruction +will be reexecuted (and may even underflow if an intervening exception +has flushed call[i]'s registers). +Registers a2 and up may contain return values. + +*******************************************************************************/ + +#if XCHAL_HAVE_WINDOWED + + .section .WindowVectors.text, "ax" + +/* +-------------------------------------------------------------------------------- +Window Overflow Exception for Call4. + +Invoked if a call[i] referenced a register (a4-a15) +that contains data from ancestor call[j]; +call[j] had done a call4 to call[j+1]. +On entry here: + window rotated to call[j] start point; + a0-a3 are registers to be saved; + a4-a15 must be preserved; + a5 is call[j+1]'s stack pointer. +-------------------------------------------------------------------------------- +*/ + + .org 0x0 + .global _WindowOverflow4 +_WindowOverflow4: + + s32e a0, a5, -16 /* save a0 to call[j+1]'s stack frame */ + s32e a1, a5, -12 /* save a1 to call[j+1]'s stack frame */ + s32e a2, a5, -8 /* save a2 to call[j+1]'s stack frame */ + s32e a3, a5, -4 /* save a3 to call[j+1]'s stack frame */ + rfwo /* rotates back to call[i] position */ + +/* +-------------------------------------------------------------------------------- +Window Underflow Exception for Call4 + +Invoked by RETW returning from call[i+1] to call[i] +where call[i]'s registers must be reloaded (not live in ARs); +where call[i] had done a call4 to call[i+1]. +On entry here: + window rotated to call[i] start point; + a0-a3 are undefined, must be reloaded with call[i].reg[0..3]; + a4-a15 must be preserved (they are call[i+1].reg[0..11]); + a5 is call[i+1]'s stack pointer. +-------------------------------------------------------------------------------- +*/ + + .org 0x40 + .global _WindowUnderflow4 +_WindowUnderflow4: + + l32e a0, a5, -16 /* restore a0 from call[i+1]'s stack frame */ + l32e a1, a5, -12 /* restore a1 from call[i+1]'s stack frame */ + l32e a2, a5, -8 /* restore a2 from call[i+1]'s stack frame */ + l32e a3, a5, -4 /* restore a3 from call[i+1]'s stack frame */ + rfwu + +/* +-------------------------------------------------------------------------------- +Handle alloca exception generated by interruptee executing 'movsp'. +This uses space between the window vectors, so is essentially "free". +All interruptee's regs are intact except a0 which is saved in EXCSAVE_1, +and PS.EXCM has been set by the exception hardware (can't be interrupted). +The fact the alloca exception was taken means the registers associated with +the base-save area have been spilled and will be restored by the underflow +handler, so those 4 registers are available for scratch. +The code is optimized to avoid unaligned branches and minimize cache misses. +-------------------------------------------------------------------------------- +*/ + + .align 4 + .global _xt_alloca_exc +_xt_alloca_exc: + + rsr a0, WINDOWBASE /* grab WINDOWBASE before rotw changes it */ + rotw -1 /* WINDOWBASE goes to a4, new a0-a3 are scratch */ + rsr a2, PS + extui a3, a2, XCHAL_PS_OWB_SHIFT, XCHAL_PS_OWB_BITS + xor a3, a3, a4 /* bits changed from old to current windowbase */ + rsr a4, EXCSAVE_1 /* restore original a0 (now in a4) */ + slli a3, a3, XCHAL_PS_OWB_SHIFT + xor a2, a2, a3 /* flip changed bits in old window base */ + wsr a2, PS /* update PS.OWB to new window base */ + rsync + + _bbci.l a4, 31, _WindowUnderflow4 + rotw -1 /* original a0 goes to a8 */ + _bbci.l a8, 30, _WindowUnderflow8 + rotw -1 + j _WindowUnderflow12 + +/* +-------------------------------------------------------------------------------- +Window Overflow Exception for Call8 + +Invoked if a call[i] referenced a register (a4-a15) +that contains data from ancestor call[j]; +call[j] had done a call8 to call[j+1]. +On entry here: + window rotated to call[j] start point; + a0-a7 are registers to be saved; + a8-a15 must be preserved; + a9 is call[j+1]'s stack pointer. +-------------------------------------------------------------------------------- +*/ + + .org 0x80 + .global _WindowOverflow8 +_WindowOverflow8: + + s32e a0, a9, -16 /* save a0 to call[j+1]'s stack frame */ + l32e a0, a1, -12 /* a0 <- call[j-1]'s sp + (used to find end of call[j]'s frame) */ + s32e a1, a9, -12 /* save a1 to call[j+1]'s stack frame */ + s32e a2, a9, -8 /* save a2 to call[j+1]'s stack frame */ + s32e a3, a9, -4 /* save a3 to call[j+1]'s stack frame */ + s32e a4, a0, -32 /* save a4 to call[j]'s stack frame */ + s32e a5, a0, -28 /* save a5 to call[j]'s stack frame */ + s32e a6, a0, -24 /* save a6 to call[j]'s stack frame */ + s32e a7, a0, -20 /* save a7 to call[j]'s stack frame */ + rfwo /* rotates back to call[i] position */ + +/* +-------------------------------------------------------------------------------- +Window Underflow Exception for Call8 + +Invoked by RETW returning from call[i+1] to call[i] +where call[i]'s registers must be reloaded (not live in ARs); +where call[i] had done a call8 to call[i+1]. +On entry here: + window rotated to call[i] start point; + a0-a7 are undefined, must be reloaded with call[i].reg[0..7]; + a8-a15 must be preserved (they are call[i+1].reg[0..7]); + a9 is call[i+1]'s stack pointer. +-------------------------------------------------------------------------------- +*/ + + .org 0xC0 + .global _WindowUnderflow8 +_WindowUnderflow8: + + l32e a0, a9, -16 /* restore a0 from call[i+1]'s stack frame */ + l32e a1, a9, -12 /* restore a1 from call[i+1]'s stack frame */ + l32e a2, a9, -8 /* restore a2 from call[i+1]'s stack frame */ + l32e a7, a1, -12 /* a7 <- call[i-1]'s sp + (used to find end of call[i]'s frame) */ + l32e a3, a9, -4 /* restore a3 from call[i+1]'s stack frame */ + l32e a4, a7, -32 /* restore a4 from call[i]'s stack frame */ + l32e a5, a7, -28 /* restore a5 from call[i]'s stack frame */ + l32e a6, a7, -24 /* restore a6 from call[i]'s stack frame */ + l32e a7, a7, -20 /* restore a7 from call[i]'s stack frame */ + rfwu + +/* +-------------------------------------------------------------------------------- +Window Overflow Exception for Call12 + +Invoked if a call[i] referenced a register (a4-a15) +that contains data from ancestor call[j]; +call[j] had done a call12 to call[j+1]. +On entry here: + window rotated to call[j] start point; + a0-a11 are registers to be saved; + a12-a15 must be preserved; + a13 is call[j+1]'s stack pointer. +-------------------------------------------------------------------------------- +*/ + + .org 0x100 + .global _WindowOverflow12 +_WindowOverflow12: + + s32e a0, a13, -16 /* save a0 to call[j+1]'s stack frame */ + l32e a0, a1, -12 /* a0 <- call[j-1]'s sp + (used to find end of call[j]'s frame) */ + s32e a1, a13, -12 /* save a1 to call[j+1]'s stack frame */ + s32e a2, a13, -8 /* save a2 to call[j+1]'s stack frame */ + s32e a3, a13, -4 /* save a3 to call[j+1]'s stack frame */ + s32e a4, a0, -48 /* save a4 to end of call[j]'s stack frame */ + s32e a5, a0, -44 /* save a5 to end of call[j]'s stack frame */ + s32e a6, a0, -40 /* save a6 to end of call[j]'s stack frame */ + s32e a7, a0, -36 /* save a7 to end of call[j]'s stack frame */ + s32e a8, a0, -32 /* save a8 to end of call[j]'s stack frame */ + s32e a9, a0, -28 /* save a9 to end of call[j]'s stack frame */ + s32e a10, a0, -24 /* save a10 to end of call[j]'s stack frame */ + s32e a11, a0, -20 /* save a11 to end of call[j]'s stack frame */ + rfwo /* rotates back to call[i] position */ + +/* +-------------------------------------------------------------------------------- +Window Underflow Exception for Call12 + +Invoked by RETW returning from call[i+1] to call[i] +where call[i]'s registers must be reloaded (not live in ARs); +where call[i] had done a call12 to call[i+1]. +On entry here: + window rotated to call[i] start point; + a0-a11 are undefined, must be reloaded with call[i].reg[0..11]; + a12-a15 must be preserved (they are call[i+1].reg[0..3]); + a13 is call[i+1]'s stack pointer. +-------------------------------------------------------------------------------- +*/ + + .org 0x140 + .global _WindowUnderflow12 +_WindowUnderflow12: + + l32e a0, a13, -16 /* restore a0 from call[i+1]'s stack frame */ + l32e a1, a13, -12 /* restore a1 from call[i+1]'s stack frame */ + l32e a2, a13, -8 /* restore a2 from call[i+1]'s stack frame */ + l32e a11, a1, -12 /* a11 <- call[i-1]'s sp + (used to find end of call[i]'s frame) */ + l32e a3, a13, -4 /* restore a3 from call[i+1]'s stack frame */ + l32e a4, a11, -48 /* restore a4 from end of call[i]'s stack frame */ + l32e a5, a11, -44 /* restore a5 from end of call[i]'s stack frame */ + l32e a6, a11, -40 /* restore a6 from end of call[i]'s stack frame */ + l32e a7, a11, -36 /* restore a7 from end of call[i]'s stack frame */ + l32e a8, a11, -32 /* restore a8 from end of call[i]'s stack frame */ + l32e a9, a11, -28 /* restore a9 from end of call[i]'s stack frame */ + l32e a10, a11, -24 /* restore a10 from end of call[i]'s stack frame */ + l32e a11, a11, -20 /* restore a11 from end of call[i]'s stack frame */ + rfwu + +#endif /* XCHAL_HAVE_WINDOWED */ + + .section .UserEnter.text, "ax" + .global call_user_start + .type call_user_start,@function + .align 4 + .literal_position + + +call_user_start: + + movi a2, 0x40040000 /* note: absolute symbol, not a ptr */ + wsr a2, vecbase + call0 user_start /* user exception handler */ diff --git a/components/freertos/xtensa_vectors.S-old b/components/freertos/xtensa_vectors.S-old new file mode 100644 index 0000000000..2d0f7a99d2 --- /dev/null +++ b/components/freertos/xtensa_vectors.S-old @@ -0,0 +1,2064 @@ +/******************************************************************************* +Copyright (c) 2006-2015 Cadence Design Systems Inc. + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be included +in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +-------------------------------------------------------------------------------- + + XTENSA VECTORS AND LOW LEVEL HANDLERS FOR AN RTOS + + Xtensa low level exception and interrupt vectors and handlers for an RTOS. + + Interrupt handlers and user exception handlers support interaction with + the RTOS by calling XT_RTOS_INT_ENTER and XT_RTOS_INT_EXIT before and + after user's specific interrupt handlers. These macros are defined in + xtensa_.h to call suitable functions in a specific RTOS. + + Users can install application-specific interrupt handlers for low and + medium level interrupts, by calling xt_set_interrupt_handler(). These + handlers can be written in C, and must obey C calling convention. The + handler table is indexed by the interrupt number. Each handler may be + provided with an argument. + + Note that the system timer interrupt is handled specially, and is + dispatched to the RTOS-specific handler. This timer cannot be hooked + by application code. + + Optional hooks are also provided to install a handler per level at + run-time, made available by compiling this source file with + '-DXT_INTEXC_HOOKS' (useful for automated testing). + +!! This file is a template that usually needs to be modified to handle !! +!! application specific interrupts. Search USER_EDIT for helpful comments !! +!! on where to insert handlers and how to write them. !! + + Users can also install application-specific exception handlers in the + same way, by calling xt_set_exception_handler(). One handler slot is + provided for each exception type. Note that some exceptions are handled + by the porting layer itself, and cannot be taken over by application + code in this manner. These are the alloca, syscall, and coprocessor + exceptions. + + The exception handlers can be written in C, and must follow C calling + convention. Each handler is passed a pointer to an exception frame as + its single argument. The exception frame is created on the stack, and + holds the saved context of the thread that took the exception. If the + handler returns, the context will be restored and the instruction that + caused the exception will be retried. If the handler makes any changes + to the saved state in the exception frame, the changes will be applied + when restoring the context. + + Because Xtensa is a configurable architecture, this port supports all user + generated configurations (except restrictions stated in the release notes). + This is accomplished by conditional compilation using macros and functions + defined in the Xtensa HAL (hardware adaptation layer) for your configuration. + Only the relevant parts of this file will be included in your RTOS build. + For example, this file provides interrupt vector templates for all types and + all priority levels, but only the ones in your configuration are built. + + NOTES on the use of 'call0' for long jumps instead of 'j': + 1. This file should be assembled with the -mlongcalls option to xt-xcc. + 2. The -mlongcalls compiler option causes 'call0 dest' to be expanded to + a sequence 'l32r a0, dest' 'callx0 a0' which works regardless of the + distance from the call to the destination. The linker then relaxes + it back to 'call0 dest' if it determines that dest is within range. + This allows more flexibility in locating code without the performance + overhead of the 'l32r' literal data load in cases where the destination + is in range of 'call0'. There is an additional benefit in that 'call0' + has a longer range than 'j' due to the target being word-aligned, so + the 'l32r' sequence is less likely needed. + 3. The use of 'call0' with -mlongcalls requires that register a0 not be + live at the time of the call, which is always the case for a function + call but needs to be ensured if 'call0' is used as a jump in lieu of 'j'. + 4. This use of 'call0' is independent of the C function call ABI. + +*******************************************************************************/ + +#include "xtensa_rtos.h" + + +/* Enable stack backtrace across exception/interrupt - see below */ +#define XT_DEBUG_BACKTRACE 0 + + +/* +-------------------------------------------------------------------------------- + Defines used to access _xtos_interrupt_table. +-------------------------------------------------------------------------------- +*/ +#define XIE_HANDLER 0 +#define XIE_ARG 4 +#define XIE_SIZE 8 + +/* +-------------------------------------------------------------------------------- + Macro extract_msb - return the input with only the highest bit set. + + Input : "ain" - Input value, clobbered. + Output : "aout" - Output value, has only one bit set, MSB of "ain". + The two arguments must be different AR registers. +-------------------------------------------------------------------------------- +*/ + + .macro extract_msb aout ain +1: + addi \aout, \ain, -1 /* aout = ain - 1 */ + and \ain, \ain, \aout /* ain = ain & aout */ + bnez \ain, 1b /* repeat until ain == 0 */ + addi \aout, \aout, 1 /* return aout + 1 */ + .endm + +/* +-------------------------------------------------------------------------------- + Macro dispatch_c_isr - dispatch interrupts to user ISRs. + This will dispatch to user handlers (if any) that are registered in the + XTOS dispatch table (_xtos_interrupt_table). These handlers would have + been registered by calling _xtos_set_interrupt_handler(). There is one + exception - the timer interrupt used by the OS will not be dispatched + to a user handler - this must be handled by the caller of this macro. + + Level triggered and software interrupts are automatically deasserted by + this code. + + ASSUMPTIONS: + -- PS.INTLEVEL is set to "level" at entry + -- PS.EXCM = 0, C calling enabled + + NOTE: For CALL0 ABI, a12-a15 have not yet been saved. + + NOTE: This macro will use registers a0 and a2-a6. The arguments are: + level -- interrupt level + mask -- interrupt bitmask for this level +-------------------------------------------------------------------------------- +*/ + + .macro dispatch_c_isr level mask + + /* Get mask of pending, enabled interrupts at this level into a2. */ + +.L_xt_user_int_&level&: + rsr a2, INTENABLE + rsr a3, INTERRUPT + movi a4, \mask + and a2, a2, a3 + and a2, a2, a4 + beqz a2, 9f /* nothing to do */ + + /* This bit of code provides a nice debug backtrace in the debugger. + It does take a few more instructions, so undef XT_DEBUG_BACKTRACE + if you want to save the cycles. + */ + #if XT_DEBUG_BACKTRACE + #ifndef __XTENSA_CALL0_ABI__ + rsr a0, EPC_1 + \level - 1 /* return address */ + movi a4, 0xC0000000 /* constant with top 2 bits set (call size) */ + or a0, a0, a4 /* set top 2 bits */ + addx2 a0, a4, a0 /* clear top bit -- simulating call4 size */ + #endif + #endif + + #ifdef XT_INTEXC_HOOKS + /* Call interrupt hook if present to (pre)handle interrupts. */ + movi a4, _xt_intexc_hooks + l32i a4, a4, \level << 2 + beqz a4, 2f + #ifdef __XTENSA_CALL0_ABI__ + callx0 a4 + beqz a2, 9f + #else + mov a6, a2 + callx4 a4 + beqz a6, 9f + mov a2, a6 + #endif +2: + #endif + + /* Now look up in the dispatch table and call user ISR if any. */ + /* If multiple bits are set then MSB has highest priority. */ + + extract_msb a4, a2 /* a4 = MSB of a2, a2 trashed */ + + #ifdef XT_USE_SWPRI + /* Enable all interrupts at this level that are numerically higher + than the one we just selected, since they are treated as higher + priority. + */ + movi a3, \mask /* a3 = all interrupts at this level */ + add a2, a4, a4 /* a2 = a4 << 1 */ + addi a2, a2, -1 /* a2 = mask of 1's <= a4 bit */ + and a2, a2, a3 /* a2 = mask of all bits <= a4 at this level */ + movi a3, _xt_intdata + l32i a6, a3, 4 /* a6 = _xt_vpri_mask */ + neg a2, a2 + addi a2, a2, -1 /* a2 = mask to apply */ + and a5, a6, a2 /* mask off all bits <= a4 bit */ + s32i a5, a3, 4 /* update _xt_vpri_mask */ + rsr a3, INTENABLE + and a3, a3, a2 /* mask off all bits <= a4 bit */ + wsr a3, INTENABLE + rsil a3, \level - 1 /* lower interrupt level by 1 */ + #endif + + movi a3, XT_TIMER_INTEN /* a3 = timer interrupt bit */ + wsr a4, INTCLEAR /* clear sw or edge-triggered interrupt */ + beq a3, a4, 7f /* if timer interrupt then skip table */ + + find_ms_setbit a3, a4, a3, 0 /* a3 = interrupt number */ + + movi a4, _xt_interrupt_table + addx8 a3, a3, a4 /* a3 = address of interrupt table entry */ + l32i a4, a3, XIE_HANDLER /* a4 = handler address */ + #ifdef __XTENSA_CALL0_ABI__ + mov a12, a6 /* save in callee-saved reg */ + l32i a2, a3, XIE_ARG /* a2 = handler arg */ + callx0 a4 /* call handler */ + mov a2, a12 + #else + mov a2, a6 /* save in windowed reg */ + l32i a6, a3, XIE_ARG /* a6 = handler arg */ + callx4 a4 /* call handler */ + #endif + + #ifdef XT_USE_SWPRI + j 8f + #else + j .L_xt_user_int_&level& /* check for more interrupts */ + #endif + +7: + + .ifeq XT_TIMER_INTPRI - \level +.L_xt_user_int_timer_&level&: + /* + Interrupt handler for the RTOS tick timer if at this level. + We'll be reading the interrupt state again after this call + so no need to preserve any registers except a6 (vpri_mask). + */ + + #ifdef __XTENSA_CALL0_ABI__ + mov a12, a6 + call0 XT_RTOS_TIMER_INT + mov a2, a12 + #else + mov a2, a6 + call4 XT_RTOS_TIMER_INT + #endif + .endif + + #ifdef XT_USE_SWPRI + j 8f + #else + j .L_xt_user_int_&level& /* check for more interrupts */ + #endif + + #ifdef XT_USE_SWPRI +8: + /* Restore old value of _xt_vpri_mask from a2. Also update INTENABLE from + virtual _xt_intenable which _could_ have changed during interrupt + processing. */ + + movi a3, _xt_intdata + l32i a4, a3, 0 /* a4 = _xt_intenable */ + s32i a2, a3, 4 /* update _xt_vpri_mask */ + and a4, a4, a2 /* a4 = masked intenable */ + wsr a4, INTENABLE /* update INTENABLE */ + #endif + +9: + /* done */ + + .endm + + +/* +-------------------------------------------------------------------------------- + Panic handler. + Should be reached by call0 (preferable) or jump only. If call0, a0 says where + from. If on simulator, display panic message and abort, else loop indefinitely. +-------------------------------------------------------------------------------- +*/ + + .text + .global panicHandlerRegs + .global panicHandler + .global panicStack + + .global _xt_panic + .type _xt_panic,@function + .align 4 + +_xt_panic: + //ToDo: save registers + movi a2, panicHandlerRegs + s32i a0,a2,0 + s32i a1,a2,4 + s32i a2,a2,8 + s32i a3,a2,12 + s32i a4,a2,16 + s32i a5,a2,20 + s32i a6,a2,24 + s32i a7,a2,28 + s32i a8,a2,32 + s32i a9,a2,36 + s32i a10,a2,40 + s32i a11,a2,44 + s32i a12,a2,48 + s32i a13,a2,52 + s32i a14,a2,56 + s32i a15,a2,60 + + rsr a3, EXCSAVE + s32i a3,a2,64 + rsr a3, EXCSAVE+1 + s32i a3,a2,68 + rsr a3, EXCSAVE+2 + s32i a3,a2,72 + rsr a3, EXCSAVE+3 + s32i a3,a2,76 + rsr a3, EXCSAVE+4 + s32i a3,a2,80 + rsr a3, EXCSAVE+5 + s32i a3,a2,84 + rsr a3, EXCSAVE+6 + s32i a3,a2,88 + rsr a3, EXCSAVE+7 + s32i a3,a2,92 + + rsr a3, EPC + s32i a3,a2,96 + rsr a3, EPC+1 + s32i a3,a2,100 + rsr a3, EPC+2 + s32i a3,a2,104 + rsr a3, EPC+3 + s32i a3,a2,108 + rsr a3, EPC+4 + s32i a3,a2,112 + rsr a3, EPC+5 + s32i a3,a2,116 + rsr a3, EPC+6 + s32i a3,a2,120 + rsr a3, EPC+7 + s32i a3,a2,124 + + rsr a3, DEPC + s32i a3,a2,128 + rsr a3, EXCVADDR + s32i a3,a2,132 + + //Reset window start / base to 0 + movi a2, 1 + wsr a2, windowstart + movi a2, 0 + wsr a2, windowbase + rsync + + //Clear EXCM, set WOE flags + rsr a2, ps + movi a3, ~(PS_EXCM_MASK) + and a2, a2, a3 + movi a3, PS_WOE_MASK + or a2, a2, a3 + wsr a2, ps + rsync + + //Switch to private stack + movi a1,panicStack+(255*4) + rsil a2, XCHAL_EXCM_LEVEL /* disable all low & med ints */ + + + // Debug: output '!' on serport + movi a2,0x60000000 + movi a3,'!' + s32i a3,a2,0 + + movi a3, panicHandlerRegs + l32i a2,a3,0 + call0 panic_print_hex + rsr a2, EXCCAUSE + call0 panic_print_hex + rsr a2, EXCVADDR + call0 panic_print_hex + rsr a2,EPC+1 + call0 panic_print_hex + rsr a2,EPC+2 + call0 panic_print_hex + rsr a2,EPC+3 + call0 panic_print_hex + rsr a2,EPC+6 + call0 panic_print_hex + rsr a2,EXCSAVE_1 + call0 panic_print_hex + rsr a2,DEPC + call0 panic_print_hex + + //Call panic handler +// movi a4, panicHandler +// callx4 a4 + call4 panicHandler + + movi a2,0x60000000 + movi a3,'d' + s32i a3,a2,0 + + +1: j 1b /* loop infinitely */ + + .align 4 +panicHandlerz: + entry a1,32 + movi a2,0x60000000 + movi a3,'h' + memw + s32i a3,a2,0 + + retw + + + .align 4 +//Call using call0. Prints the hex char in a2. Kills a3, a4, a5 +panic_print_hex: + movi a3,0x60000000 + movi a4,8 +panic_print_hex_loop: + l32i a5, a3, 0x1c + extui a5, a5, 16, 8 + bgei a5,64,panic_print_hex_loop + + srli a5,a2,28 + bgei a5,10,panic_print_hex_a + addi a5,a5,'0' + j panic_print_hex_ok +panic_print_hex_a: + addi a5,a5,'A'-10 +panic_print_hex_ok: + s32i a5,a3,0 + slli a2,a2,4 + + addi a4,a4,-1 + bnei a4,0,panic_print_hex_loop + movi a5,' ' + s32i a5,a3,0 + + ret + + + + .section .rodata, "a" + .align 4 + + + +/* +-------------------------------------------------------------------------------- + Hooks to dynamically install handlers for exceptions and interrupts. + Allows automated regression frameworks to install handlers per test. + Consists of an array of function pointers indexed by interrupt level, + with index 0 containing the entry for user exceptions. + Initialized with all 0s, meaning no handler is installed at each level. + See comment in xtensa_rtos.h for more details. +-------------------------------------------------------------------------------- +*/ + + #ifdef XT_INTEXC_HOOKS + .data + .global _xt_intexc_hooks + .type _xt_intexc_hooks,@object + .align 4 + +_xt_intexc_hooks: + .fill XT_INTEXC_HOOK_NUM, 4, 0 + #endif + + +/* +-------------------------------------------------------------------------------- + EXCEPTION AND LEVEL 1 INTERRUPT VECTORS AND LOW LEVEL HANDLERS + (except window exception vectors). + + Each vector goes at a predetermined location according to the Xtensa + hardware configuration, which is ensured by its placement in a special + section known to the Xtensa linker support package (LSP). It performs + the minimum necessary before jumping to the handler in the .text section. + + The corresponding handler goes in the normal .text section. It sets up + the appropriate stack frame, saves a few vector-specific registers and + calls XT_RTOS_INT_ENTER to save the rest of the interrupted context + and enter the RTOS, then sets up a C environment. It then calls the + user's interrupt handler code (which may be coded in C) and finally + calls XT_RTOS_INT_EXIT to transfer control to the RTOS for scheduling. + + While XT_RTOS_INT_EXIT does not return directly to the interruptee, + eventually the RTOS scheduler will want to dispatch the interrupted + task or handler. The scheduler will return to the exit point that was + saved in the interrupt stack frame at XT_STK_EXIT. +-------------------------------------------------------------------------------- +*/ + + +/* +-------------------------------------------------------------------------------- +Debug Exception. +-------------------------------------------------------------------------------- +*/ + +#if XCHAL_HAVE_DEBUG + + .begin literal_prefix .DebugExceptionVector + .section .DebugExceptionVector.text, "ax" + .global _DebugExceptionVector + .align 4 + +_DebugExceptionVector: + + #ifdef XT_SIMULATOR + /* + In the simulator, let the debugger (if any) handle the debug exception, + or simply stop the simulation: + */ + wsr a2, EXCSAVE+XCHAL_DEBUGLEVEL /* save a2 where sim expects it */ + movi a2, SYS_gdb_enter_sktloop + simcall /* have ISS handle debug exc. */ + #elif 0 /* change condition to 1 to use the HAL minimal debug handler */ + wsr a3, EXCSAVE+XCHAL_DEBUGLEVEL + movi a3, xthal_debugexc_defhndlr_nw /* use default debug handler */ + jx a3 + #else + wsr a0, EXCSAVE+XCHAL_DEBUGLEVEL /* save original a0 somewhere */ + call0 _xt_panic /* does not return */ + rfi XCHAL_DEBUGLEVEL /* make a0 point here not later */ + #endif + + .end literal_prefix + +#endif + +/* +-------------------------------------------------------------------------------- +Double Exception. +Double exceptions are not a normal occurrence. They indicate a bug of some kind. +-------------------------------------------------------------------------------- +*/ + +#ifdef XCHAL_DOUBLEEXC_VECTOR_VADDR + + .begin literal_prefix .DoubleExceptionVector + .section .DoubleExceptionVector.text, "ax" + .global _DoubleExceptionVector + .align 4 + +_DoubleExceptionVector: + + #if XCHAL_HAVE_DEBUG + break 1, 4 /* unhandled double exception */ + #endif + call0 _xt_panic /* does not return */ + rfde /* make a0 point here not later */ + + .end literal_prefix + +#endif /* XCHAL_DOUBLEEXC_VECTOR_VADDR */ + +/* +-------------------------------------------------------------------------------- +Kernel Exception (including Level 1 Interrupt from kernel mode). +-------------------------------------------------------------------------------- +*/ + + .begin literal_prefix .KernelExceptionVector + .section .KernelExceptionVector.text, "ax" + .global _KernelExceptionVector + .align 4 + +_KernelExceptionVector: + + wsr a0, EXCSAVE_1 /* preserve a0 */ + call0 _xt_kernel_exc /* kernel exception handler */ + /* never returns here - call0 is used as a jump (see note at top) */ + + .end literal_prefix + + .text + .align 4 + +_xt_kernel_exc: + #if XCHAL_HAVE_DEBUG + break 1, 0 /* unhandled kernel exception */ + #endif + call0 _xt_panic /* does not return */ + rfe /* make a0 point here not there */ + + +/* +-------------------------------------------------------------------------------- +User Exception (including Level 1 Interrupt from user mode). +-------------------------------------------------------------------------------- +*/ + + .begin literal_prefix .UserExceptionVector + .section .UserExceptionVector.text, "ax" + .global _UserExceptionVector + .type _UserExceptionVector,@function + .align 4 + +_UserExceptionVector: + + wsr a0, EXCSAVE_1 /* preserve a0 */ + call0 _xt_user_exc /* user exception handler */ + /* never returns here - call0 is used as a jump (see note at top) */ + + .end literal_prefix + +/* +-------------------------------------------------------------------------------- + Insert some waypoints for jumping beyond the signed 8-bit range of + conditional branch instructions, so the conditional branchces to specific + exception handlers are not taken in the mainline. Saves some cycles in the + mainline. +-------------------------------------------------------------------------------- +*/ + + .text + + #if XCHAL_HAVE_WINDOWED + .align 4 +_xt_to_alloca_exc: + call0 _xt_alloca_exc /* in window vectors section */ + /* never returns here - call0 is used as a jump (see note at top) */ + #endif + + .align 4 +_xt_to_syscall_exc: + call0 _xt_syscall_exc + /* never returns here - call0 is used as a jump (see note at top) */ + + #if XCHAL_CP_NUM > 0 + .align 4 +_xt_to_coproc_exc: + call0 _xt_coproc_exc + /* never returns here - call0 is used as a jump (see note at top) */ + #endif + + +/* +-------------------------------------------------------------------------------- + User exception handler. +-------------------------------------------------------------------------------- +*/ + + .type _xt_user_exc,@function + .align 4 + +_xt_user_exc: + + /* If level 1 interrupt then jump to the dispatcher */ + rsr a0, EXCCAUSE + beqi a0, EXCCAUSE_LEVEL1INTERRUPT, _xt_lowint1 + + /* Handle any coprocessor exceptions. Rely on the fact that exception + numbers above EXCCAUSE_CP0_DISABLED all relate to the coprocessors. + */ + #if XCHAL_CP_NUM > 0 + bgeui a0, EXCCAUSE_CP0_DISABLED, _xt_to_coproc_exc + #endif + + /* Handle alloca and syscall exceptions */ + #if XCHAL_HAVE_WINDOWED + beqi a0, EXCCAUSE_ALLOCA, _xt_to_alloca_exc + #endif + beqi a0, EXCCAUSE_SYSCALL, _xt_to_syscall_exc + + //HACK! No custom vector stuff, just call panic handler directly. ToDo: remove this when possible. -JD + call0 _xt_panic + + /* Handle all other exceptions. All can have user-defined handlers. */ + /* NOTE: we'll stay on the user stack for exception handling. */ + + /* Allocate exception frame and save minimal context. */ + mov a0, sp + addi sp, sp, -XT_STK_FRMSZ + s32i a0, sp, XT_STK_A1 + #if XCHAL_HAVE_WINDOWED + s32e a0, sp, -12 /* for debug backtrace */ + #endif + rsr a0, PS /* save interruptee's PS */ + s32i a0, sp, XT_STK_PS + rsr a0, EPC_1 /* save interruptee's PC */ + s32i a0, sp, XT_STK_PC + rsr a0, EXCSAVE_1 /* save interruptee's a0 */ + s32i a0, sp, XT_STK_A0 + #if XCHAL_HAVE_WINDOWED + s32e a0, sp, -16 /* for debug backtrace */ + #endif + s32i a12, sp, XT_STK_A12 /* _xt_context_save requires A12- */ + s32i a13, sp, XT_STK_A13 /* A13 to have already been saved */ + call0 _xt_context_save + + /* Save exc cause and vaddr into exception frame */ + rsr a0, EXCCAUSE + s32i a0, sp, XT_STK_EXCCAUSE + rsr a0, EXCVADDR + s32i a0, sp, XT_STK_EXCVADDR + + /* Set up PS for C, reenable hi-pri interrupts, and clear EXCM. */ + #ifdef __XTENSA_CALL0_ABI__ + movi a0, PS_INTLEVEL(XCHAL_EXCM_LEVEL) | PS_UM + #else + movi a0, PS_INTLEVEL(XCHAL_EXCM_LEVEL) | PS_UM | PS_WOE + #endif + wsr a0, PS + + #ifdef XT_DEBUG_BACKTRACE + #ifndef __XTENSA_CALL0_ABI__ + rsr a0, EPC_1 /* return address for debug backtrace */ + movi a5, 0xC0000000 /* constant with top 2 bits set (call size) */ + rsync /* wait for WSR.PS to complete */ + or a0, a0, a5 /* set top 2 bits */ + addx2 a0, a5, a0 /* clear top bit -- thus simulating call4 size */ + #else + rsync /* wait for WSR.PS to complete */ + #endif + #endif + + rsr a2, EXCCAUSE /* recover exc cause */ + + #ifdef XT_INTEXC_HOOKS + /* + Call exception hook to pre-handle exceptions (if installed). + Pass EXCCAUSE in a2, and check result in a2 (if -1, skip default handling). + */ + movi a4, _xt_intexc_hooks + l32i a4, a4, 0 /* user exception hook index 0 */ + beqz a4, 1f +.Ln_xt_user_exc_call_hook: + #ifdef __XTENSA_CALL0_ABI__ + callx0 a4 + beqi a2, -1, .L_xt_user_done + #else + mov a6, a2 + callx4 a4 + beqi a6, -1, .L_xt_user_done + mov a2, a6 + #endif +1: + #endif + + rsr a2, EXCCAUSE /* recover exc cause */ + movi a3, _xt_exception_table + addx4 a4, a2, a3 /* a4 = address of exception table entry */ + l32i a4, a4, 0 /* a4 = handler address */ + #ifdef __XTENSA_CALL0_ABI__ + mov a2, sp /* a2 = pointer to exc frame */ + callx0 a4 /* call handler */ + #else + mov a6, sp /* a6 = pointer to exc frame */ + callx4 a4 /* call handler */ + #endif + +.L_xt_user_done: + + /* Restore context and return */ + call0 _xt_context_restore + l32i a0, sp, XT_STK_PS /* retrieve interruptee's PS */ + wsr a0, PS + l32i a0, sp, XT_STK_PC /* retrieve interruptee's PC */ + wsr a0, EPC_1 + l32i a0, sp, XT_STK_A0 /* retrieve interruptee's A0 */ + l32i sp, sp, XT_STK_A1 /* remove exception frame */ + rsync /* ensure PS and EPC written */ + rfe /* PS.EXCM is cleared */ + + +/* +-------------------------------------------------------------------------------- + Exit point for dispatch. Saved in interrupt stack frame at XT_STK_EXIT + on entry and used to return to a thread or interrupted interrupt handler. +-------------------------------------------------------------------------------- +*/ + + .global _xt_user_exit + .type _xt_user_exit,@function + .align 4 +_xt_user_exit: + l32i a0, sp, XT_STK_PS /* retrieve interruptee's PS */ + wsr a0, PS + l32i a0, sp, XT_STK_PC /* retrieve interruptee's PC */ + wsr a0, EPC_1 + l32i a0, sp, XT_STK_A0 /* retrieve interruptee's A0 */ + l32i sp, sp, XT_STK_A1 /* remove interrupt stack frame */ + rsync /* ensure PS and EPC written */ + rfe /* PS.EXCM is cleared */ + + +/* +-------------------------------------------------------------------------------- +Syscall Exception Handler (jumped to from User Exception Handler). +Syscall 0 is required to spill the register windows (no-op in Call 0 ABI). +Only syscall 0 is handled here. Other syscalls return -1 to caller in a2. +-------------------------------------------------------------------------------- +*/ + + .text + .type _xt_syscall_exc,@function + .align 4 +_xt_syscall_exc: + + #ifdef __XTENSA_CALL0_ABI__ + /* + Save minimal regs for scratch. Syscall 0 does nothing in Call0 ABI. + Use a minimal stack frame (16B) to save A2 & A3 for scratch. + PS.EXCM could be cleared here, but unlikely to improve worst-case latency. + rsr a0, PS + addi a0, a0, -PS_EXCM_MASK + wsr a0, PS + */ + addi sp, sp, -16 + s32i a2, sp, 8 + s32i a3, sp, 12 + #else /* Windowed ABI */ + /* + Save necessary context and spill the register windows. + PS.EXCM is still set and must remain set until after the spill. + Reuse context save function though it saves more than necessary. + For this reason, a full interrupt stack frame is allocated. + */ + addi sp, sp, -XT_STK_FRMSZ /* allocate interrupt stack frame */ + s32i a12, sp, XT_STK_A12 /* _xt_context_save requires A12- */ + s32i a13, sp, XT_STK_A13 /* A13 to have already been saved */ + call0 _xt_context_save + #endif + + /* + Grab the interruptee's PC and skip over the 'syscall' instruction. + If it's at the end of a zero-overhead loop and it's not on the last + iteration, decrement loop counter and skip to beginning of loop. + */ + rsr a2, EPC_1 /* a2 = PC of 'syscall' */ + addi a3, a2, 3 /* ++PC */ + #if XCHAL_HAVE_LOOPS + rsr a0, LEND /* if (PC == LEND */ + bne a3, a0, 1f + rsr a0, LCOUNT /* && LCOUNT != 0) */ + beqz a0, 1f /* { */ + addi a0, a0, -1 /* --LCOUNT */ + rsr a3, LBEG /* PC = LBEG */ + wsr a0, LCOUNT /* } */ + #endif +1: wsr a3, EPC_1 /* update PC */ + + /* Restore interruptee's context and return from exception. */ + #ifdef __XTENSA_CALL0_ABI__ + l32i a2, sp, 8 + l32i a3, sp, 12 + addi sp, sp, 16 + #else + call0 _xt_context_restore + addi sp, sp, XT_STK_FRMSZ + #endif + movi a0, -1 + movnez a2, a0, a2 /* return -1 if not syscall 0 */ + rsr a0, EXCSAVE_1 + rfe + +/* +-------------------------------------------------------------------------------- +Co-Processor Exception Handler (jumped to from User Exception Handler). +These exceptions are generated by co-processor instructions, which are only +allowed in thread code (not in interrupts or kernel code). This restriction is +deliberately imposed to reduce the burden of state-save/restore in interrupts. +-------------------------------------------------------------------------------- +*/ +#if XCHAL_CP_NUM > 0 + + .section .rodata, "a" + +/* Offset to CP n save area in thread's CP save area. */ + .global _xt_coproc_sa_offset + .type _xt_coproc_sa_offset,@object + .align 16 /* minimize crossing cache boundaries */ +_xt_coproc_sa_offset: + .word XT_CP0_SA, XT_CP1_SA, XT_CP2_SA, XT_CP3_SA + .word XT_CP4_SA, XT_CP5_SA, XT_CP6_SA, XT_CP7_SA + +/* Bitmask for CP n's CPENABLE bit. */ + .type _xt_coproc_mask,@object + .align 16,,8 /* try to keep it all in one cache line */ + .set i, 0 +_xt_coproc_mask: + .rept XCHAL_CP_MAX + .long (i<<16) | (1<= 2 + + .begin literal_prefix .Level2InterruptVector + .section .Level2InterruptVector.text, "ax" + .global _Level2Vector + .type _Level2Vector,@function + .align 4 +_Level2Vector: + wsr a0, EXCSAVE_2 /* preserve a0 */ + call0 _xt_medint2 /* load interrupt handler */ + /* never returns here - call0 is used as a jump (see note at top) */ + + .end literal_prefix + + .text + .type _xt_medint2,@function + .align 4 +_xt_medint2: + mov a0, sp /* sp == a1 */ + addi sp, sp, -XT_STK_FRMSZ /* allocate interrupt stack frame */ + s32i a0, sp, XT_STK_A1 /* save pre-interrupt SP */ + rsr a0, EPS_2 /* save interruptee's PS */ + s32i a0, sp, XT_STK_PS + rsr a0, EPC_2 /* save interruptee's PC */ + s32i a0, sp, XT_STK_PC + rsr a0, EXCSAVE_2 /* save interruptee's a0 */ + s32i a0, sp, XT_STK_A0 + movi a0, _xt_medint2_exit /* save exit point for dispatch */ + s32i a0, sp, XT_STK_EXIT + + /* Save rest of interrupt context and enter RTOS. */ + call0 XT_RTOS_INT_ENTER /* common RTOS interrupt entry */ + + /* !! We are now on the RTOS system stack !! */ + + /* Set up PS for C, enable interrupts above this level and clear EXCM. */ + #ifdef __XTENSA_CALL0_ABI__ + movi a0, PS_INTLEVEL(2) | PS_UM + #else + movi a0, PS_INTLEVEL(2) | PS_UM | PS_WOE + #endif + wsr a0, PS + rsync + + /* OK to call C code at this point, dispatch user ISRs */ + + dispatch_c_isr 2 XCHAL_INTLEVEL2_MASK + + /* Done handling interrupts, transfer control to OS */ + call0 XT_RTOS_INT_EXIT /* does not return directly here */ + + /* + Exit point for dispatch. Saved in interrupt stack frame at XT_STK_EXIT + on entry and used to return to a thread or interrupted interrupt handler. + */ + .global _xt_medint2_exit + .type _xt_medint2_exit,@function + .align 4 +_xt_medint2_exit: + /* Restore only level-specific regs (the rest were already restored) */ + l32i a0, sp, XT_STK_PS /* retrieve interruptee's PS */ + wsr a0, EPS_2 + l32i a0, sp, XT_STK_PC /* retrieve interruptee's PC */ + wsr a0, EPC_2 + l32i a0, sp, XT_STK_A0 /* retrieve interruptee's A0 */ + l32i sp, sp, XT_STK_A1 /* remove interrupt stack frame */ + rsync /* ensure EPS and EPC written */ + rfi 2 + +#endif /* Level 2 */ + +#if XCHAL_EXCM_LEVEL >= 3 + + .begin literal_prefix .Level3InterruptVector + .section .Level3InterruptVector.text, "ax" + .global _Level3Vector + .type _Level3Vector,@function + .align 4 +_Level3Vector: + wsr a0, EXCSAVE_3 /* preserve a0 */ + call0 _xt_medint3 /* load interrupt handler */ + /* never returns here - call0 is used as a jump (see note at top) */ + + .end literal_prefix + + .text + .type _xt_medint3,@function + .align 4 +_xt_medint3: + mov a0, sp /* sp == a1 */ + addi sp, sp, -XT_STK_FRMSZ /* allocate interrupt stack frame */ + s32i a0, sp, XT_STK_A1 /* save pre-interrupt SP */ + rsr a0, EPS_3 /* save interruptee's PS */ + s32i a0, sp, XT_STK_PS + rsr a0, EPC_3 /* save interruptee's PC */ + s32i a0, sp, XT_STK_PC + rsr a0, EXCSAVE_3 /* save interruptee's a0 */ + s32i a0, sp, XT_STK_A0 + movi a0, _xt_medint3_exit /* save exit point for dispatch */ + s32i a0, sp, XT_STK_EXIT + + /* Save rest of interrupt context and enter RTOS. */ + call0 XT_RTOS_INT_ENTER /* common RTOS interrupt entry */ + + /* !! We are now on the RTOS system stack !! */ + + /* Set up PS for C, enable interrupts above this level and clear EXCM. */ + #ifdef __XTENSA_CALL0_ABI__ + movi a0, PS_INTLEVEL(3) | PS_UM + #else + movi a0, PS_INTLEVEL(3) | PS_UM | PS_WOE + #endif + wsr a0, PS + rsync + + /* OK to call C code at this point, dispatch user ISRs */ + + dispatch_c_isr 3 XCHAL_INTLEVEL3_MASK + + /* Done handling interrupts, transfer control to OS */ + call0 XT_RTOS_INT_EXIT /* does not return directly here */ + + /* + Exit point for dispatch. Saved in interrupt stack frame at XT_STK_EXIT + on entry and used to return to a thread or interrupted interrupt handler. + */ + .global _xt_medint3_exit + .type _xt_medint3_exit,@function + .align 4 +_xt_medint3_exit: + /* Restore only level-specific regs (the rest were already restored) */ + l32i a0, sp, XT_STK_PS /* retrieve interruptee's PS */ + wsr a0, EPS_3 + l32i a0, sp, XT_STK_PC /* retrieve interruptee's PC */ + wsr a0, EPC_3 + l32i a0, sp, XT_STK_A0 /* retrieve interruptee's A0 */ + l32i sp, sp, XT_STK_A1 /* remove interrupt stack frame */ + rsync /* ensure EPS and EPC written */ + rfi 3 + +#endif /* Level 3 */ + +#if XCHAL_EXCM_LEVEL >= 4 + + .begin literal_prefix .Level4InterruptVector + .section .Level4InterruptVector.text, "ax" + .global _Level4Vector + .type _Level4Vector,@function + .align 4 +_Level4Vector: + wsr a0, EXCSAVE_4 /* preserve a0 */ + call0 _xt_medint4 /* load interrupt handler */ + + .end literal_prefix + + .text + .type _xt_medint4,@function + .align 4 +_xt_medint4: + mov a0, sp /* sp == a1 */ + addi sp, sp, -XT_STK_FRMSZ /* allocate interrupt stack frame */ + s32i a0, sp, XT_STK_A1 /* save pre-interrupt SP */ + rsr a0, EPS_4 /* save interruptee's PS */ + s32i a0, sp, XT_STK_PS + rsr a0, EPC_4 /* save interruptee's PC */ + s32i a0, sp, XT_STK_PC + rsr a0, EXCSAVE_4 /* save interruptee's a0 */ + s32i a0, sp, XT_STK_A0 + movi a0, _xt_medint4_exit /* save exit point for dispatch */ + s32i a0, sp, XT_STK_EXIT + + /* Save rest of interrupt context and enter RTOS. */ + call0 XT_RTOS_INT_ENTER /* common RTOS interrupt entry */ + + /* !! We are now on the RTOS system stack !! */ + + /* Set up PS for C, enable interrupts above this level and clear EXCM. */ + #ifdef __XTENSA_CALL0_ABI__ + movi a0, PS_INTLEVEL(4) | PS_UM + #else + movi a0, PS_INTLEVEL(4) | PS_UM | PS_WOE + #endif + wsr a0, PS + rsync + + /* OK to call C code at this point, dispatch user ISRs */ + + dispatch_c_isr 4 XCHAL_INTLEVEL4_MASK + + /* Done handling interrupts, transfer control to OS */ + call0 XT_RTOS_INT_EXIT /* does not return directly here */ + + /* + Exit point for dispatch. Saved in interrupt stack frame at XT_STK_EXIT + on entry and used to return to a thread or interrupted interrupt handler. + */ + .global _xt_medint4_exit + .type _xt_medint4_exit,@function + .align 4 +_xt_medint4_exit: + /* Restore only level-specific regs (the rest were already restored) */ + l32i a0, sp, XT_STK_PS /* retrieve interruptee's PS */ + wsr a0, EPS_4 + l32i a0, sp, XT_STK_PC /* retrieve interruptee's PC */ + wsr a0, EPC_4 + l32i a0, sp, XT_STK_A0 /* retrieve interruptee's A0 */ + l32i sp, sp, XT_STK_A1 /* remove interrupt stack frame */ + rsync /* ensure EPS and EPC written */ + rfi 4 + +#endif /* Level 4 */ + +#if XCHAL_EXCM_LEVEL >= 5 + + .begin literal_prefix .Level5InterruptVector + .section .Level5InterruptVector.text, "ax" + .global _Level5Vector + .type _Level5Vector,@function + .align 4 +_Level5Vector: + wsr a0, EXCSAVE_5 /* preserve a0 */ + call0 _xt_medint5 /* load interrupt handler */ + + .end literal_prefix + + .text + .type _xt_medint5,@function + .align 4 +_xt_medint5: + mov a0, sp /* sp == a1 */ + addi sp, sp, -XT_STK_FRMSZ /* allocate interrupt stack frame */ + s32i a0, sp, XT_STK_A1 /* save pre-interrupt SP */ + rsr a0, EPS_5 /* save interruptee's PS */ + s32i a0, sp, XT_STK_PS + rsr a0, EPC_5 /* save interruptee's PC */ + s32i a0, sp, XT_STK_PC + rsr a0, EXCSAVE_5 /* save interruptee's a0 */ + s32i a0, sp, XT_STK_A0 + movi a0, _xt_medint5_exit /* save exit point for dispatch */ + s32i a0, sp, XT_STK_EXIT + + /* Save rest of interrupt context and enter RTOS. */ + call0 XT_RTOS_INT_ENTER /* common RTOS interrupt entry */ + + /* !! We are now on the RTOS system stack !! */ + + /* Set up PS for C, enable interrupts above this level and clear EXCM. */ + #ifdef __XTENSA_CALL0_ABI__ + movi a0, PS_INTLEVEL(5) | PS_UM + #else + movi a0, PS_INTLEVEL(5) | PS_UM | PS_WOE + #endif + wsr a0, PS + rsync + + /* OK to call C code at this point, dispatch user ISRs */ + + dispatch_c_isr 5 XCHAL_INTLEVEL5_MASK + + /* Done handling interrupts, transfer control to OS */ + call0 XT_RTOS_INT_EXIT /* does not return directly here */ + + /* + Exit point for dispatch. Saved in interrupt stack frame at XT_STK_EXIT + on entry and used to return to a thread or interrupted interrupt handler. + */ + .global _xt_medint5_exit + .type _xt_medint5_exit,@function + .align 4 +_xt_medint5_exit: + /* Restore only level-specific regs (the rest were already restored) */ + l32i a0, sp, XT_STK_PS /* retrieve interruptee's PS */ + wsr a0, EPS_5 + l32i a0, sp, XT_STK_PC /* retrieve interruptee's PC */ + wsr a0, EPC_5 + l32i a0, sp, XT_STK_A0 /* retrieve interruptee's A0 */ + l32i sp, sp, XT_STK_A1 /* remove interrupt stack frame */ + rsync /* ensure EPS and EPC written */ + rfi 5 + +#endif /* Level 5 */ + +#if XCHAL_EXCM_LEVEL >= 6 + + .begin literal_prefix .Level6InterruptVector + .section .Level6InterruptVector.text, "ax" + .global _Level6Vector + .type _Level6Vector,@function + .align 4 +_Level6Vector: + wsr a0, EXCSAVE_6 /* preserve a0 */ + call0 _xt_medint6 /* load interrupt handler */ + + .end literal_prefix + + .text + .type _xt_medint6,@function + .align 4 +_xt_medint6: + mov a0, sp /* sp == a1 */ + addi sp, sp, -XT_STK_FRMSZ /* allocate interrupt stack frame */ + s32i a0, sp, XT_STK_A1 /* save pre-interrupt SP */ + rsr a0, EPS_6 /* save interruptee's PS */ + s32i a0, sp, XT_STK_PS + rsr a0, EPC_6 /* save interruptee's PC */ + s32i a0, sp, XT_STK_PC + rsr a0, EXCSAVE_6 /* save interruptee's a0 */ + s32i a0, sp, XT_STK_A0 + movi a0, _xt_medint6_exit /* save exit point for dispatch */ + s32i a0, sp, XT_STK_EXIT + + /* Save rest of interrupt context and enter RTOS. */ + call0 XT_RTOS_INT_ENTER /* common RTOS interrupt entry */ + + /* !! We are now on the RTOS system stack !! */ + + /* Set up PS for C, enable interrupts above this level and clear EXCM. */ + #ifdef __XTENSA_CALL0_ABI__ + movi a0, PS_INTLEVEL(6) | PS_UM + #else + movi a0, PS_INTLEVEL(6) | PS_UM | PS_WOE + #endif + wsr a0, PS + rsync + + /* OK to call C code at this point, dispatch user ISRs */ + + dispatch_c_isr 6 XCHAL_INTLEVEL6_MASK + + /* Done handling interrupts, transfer control to OS */ + call0 XT_RTOS_INT_EXIT /* does not return directly here */ + + /* + Exit point for dispatch. Saved in interrupt stack frame at XT_STK_EXIT + on entry and used to return to a thread or interrupted interrupt handler. + */ + .global _xt_medint6_exit + .type _xt_medint6_exit,@function + .align 4 +_xt_medint6_exit: + /* Restore only level-specific regs (the rest were already restored) */ + l32i a0, sp, XT_STK_PS /* retrieve interruptee's PS */ + wsr a0, EPS_6 + l32i a0, sp, XT_STK_PC /* retrieve interruptee's PC */ + wsr a0, EPC_6 + l32i a0, sp, XT_STK_A0 /* retrieve interruptee's A0 */ + l32i sp, sp, XT_STK_A1 /* remove interrupt stack frame */ + rsync /* ensure EPS and EPC written */ + rfi 6 + +#endif /* Level 6 */ + + +/******************************************************************************* + +HIGH PRIORITY (LEVEL > XCHAL_EXCM_LEVEL) INTERRUPT VECTORS AND HANDLERS + +High priority interrupts are by definition those with priorities greater +than XCHAL_EXCM_LEVEL. This includes non-maskable (NMI). High priority +interrupts cannot interact with the RTOS, that is they must save all regs +they use and not call any RTOS function. + +A further restriction imposed by the Xtensa windowed architecture is that +high priority interrupts must not modify the stack area even logically +"above" the top of the interrupted stack (they need to provide their +own stack or static save area). + +Cadence Design Systems recommends high priority interrupt handlers be coded in assembly +and used for purposes requiring very short service times. + +Here are templates for high priority (level 2+) interrupt vectors. +They assume only one interrupt per level to avoid the burden of identifying +which interrupts at this level are pending and enabled. This allows for +minimum latency and avoids having to save/restore a2 in addition to a0. +If more than one interrupt per high priority level is configured, this burden +is on the handler which in any case must provide a way to save and restore +registers it uses without touching the interrupted stack. + +Each vector goes at a predetermined location according to the Xtensa +hardware configuration, which is ensured by its placement in a special +section known to the Xtensa linker support package (LSP). It performs +the minimum necessary before jumping to the handler in the .text section. + +*******************************************************************************/ + +/* +Currently only shells for high priority interrupt handlers are provided +here. However a template and example can be found in the Cadence Design Systems tools +documentation: "Microprocessor Programmer's Guide". +*/ + +#if XCHAL_NUM_INTLEVELS >=2 && XCHAL_EXCM_LEVEL <2 && XCHAL_DEBUGLEVEL !=2 + + .begin literal_prefix .Level2InterruptVector + .section .Level2InterruptVector.text, "ax" + .global _Level2Vector + .type _Level2Vector,@function + .align 4 +_Level2Vector: + wsr a0, EXCSAVE_2 /* preserve a0 */ + call0 _xt_highint2 /* load interrupt handler */ + + .end literal_prefix + + .text + .type _xt_highint2,@function + .align 4 +_xt_highint2: + + #ifdef XT_INTEXC_HOOKS + /* Call interrupt hook if present to (pre)handle interrupts. */ + movi a0, _xt_intexc_hooks + l32i a0, a0, 2<<2 + beqz a0, 1f +.Ln_xt_highint2_call_hook: + callx0 a0 /* must NOT disturb stack! */ +1: + #endif + + /* USER_EDIT: + ADD HIGH PRIORITY LEVEL 2 INTERRUPT HANDLER CODE HERE. + */ + + .align 4 +.L_xt_highint2_exit: + rsr a0, EXCSAVE_2 /* restore a0 */ + rfi 2 + +#endif /* Level 2 */ + +#if XCHAL_NUM_INTLEVELS >=3 && XCHAL_EXCM_LEVEL <3 && XCHAL_DEBUGLEVEL !=3 + + .begin literal_prefix .Level3InterruptVector + .section .Level3InterruptVector.text, "ax" + .global _Level3Vector + .type _Level3Vector,@function + .align 4 +_Level3Vector: + wsr a0, EXCSAVE_3 /* preserve a0 */ + call0 _xt_highint3 /* load interrupt handler */ + /* never returns here - call0 is used as a jump (see note at top) */ + + .end literal_prefix + + .text + .type _xt_highint3,@function + .align 4 +_xt_highint3: + + #ifdef XT_INTEXC_HOOKS + /* Call interrupt hook if present to (pre)handle interrupts. */ + movi a0, _xt_intexc_hooks + l32i a0, a0, 3<<2 + beqz a0, 1f +.Ln_xt_highint3_call_hook: + callx0 a0 /* must NOT disturb stack! */ +1: + #endif + + /* USER_EDIT: + ADD HIGH PRIORITY LEVEL 3 INTERRUPT HANDLER CODE HERE. + */ + + .align 4 +.L_xt_highint3_exit: + rsr a0, EXCSAVE_3 /* restore a0 */ + rfi 3 + +#endif /* Level 3 */ + +#if XCHAL_NUM_INTLEVELS >=4 && XCHAL_EXCM_LEVEL <4 && XCHAL_DEBUGLEVEL !=4 + + .begin literal_prefix .Level4InterruptVector + .section .Level4InterruptVector.text, "ax" + .global _Level4Vector + .type _Level4Vector,@function + .align 4 +_Level4Vector: + wsr a0, EXCSAVE_4 /* preserve a0 */ + call0 _xt_highint4 /* load interrupt handler */ + /* never returns here - call0 is used as a jump (see note at top) */ + + .end literal_prefix + + .text + .type _xt_highint4,@function + .align 4 +_xt_highint4: + + #ifdef XT_INTEXC_HOOKS + /* Call interrupt hook if present to (pre)handle interrupts. */ + movi a0, _xt_intexc_hooks + l32i a0, a0, 4<<2 + beqz a0, 1f +.Ln_xt_highint4_call_hook: + callx0 a0 /* must NOT disturb stack! */ +1: + #endif + + /* USER_EDIT: + ADD HIGH PRIORITY LEVEL 4 INTERRUPT HANDLER CODE HERE. + */ + + .align 4 +.L_xt_highint4_exit: + rsr a0, EXCSAVE_4 /* restore a0 */ + rfi 4 + +#endif /* Level 4 */ + +#if XCHAL_NUM_INTLEVELS >=5 && XCHAL_EXCM_LEVEL <5 && XCHAL_DEBUGLEVEL !=5 + + .begin literal_prefix .Level5InterruptVector + .section .Level5InterruptVector.text, "ax" + .global _Level5Vector + .type _Level5Vector,@function + .align 4 +_Level5Vector: + wsr a0, EXCSAVE_5 /* preserve a0 */ + call0 _xt_highint5 /* load interrupt handler */ + /* never returns here - call0 is used as a jump (see note at top) */ + + .end literal_prefix + + .text + .type _xt_highint5,@function + .align 4 +_xt_highint5: + + #ifdef XT_INTEXC_HOOKS + /* Call interrupt hook if present to (pre)handle interrupts. */ + movi a0, _xt_intexc_hooks + l32i a0, a0, 5<<2 + beqz a0, 1f +.Ln_xt_highint5_call_hook: + callx0 a0 /* must NOT disturb stack! */ +1: + #endif + + /* USER_EDIT: + ADD HIGH PRIORITY LEVEL 5 INTERRUPT HANDLER CODE HERE. + */ + + .align 4 +.L_xt_highint5_exit: + rsr a0, EXCSAVE_5 /* restore a0 */ + rfi 5 + +#endif /* Level 5 */ + +#if XCHAL_NUM_INTLEVELS >=6 && XCHAL_EXCM_LEVEL <6 && XCHAL_DEBUGLEVEL !=6 + + .begin literal_prefix .Level6InterruptVector + .section .Level6InterruptVector.text, "ax" + .global _Level6Vector + .type _Level6Vector,@function + .align 4 +_Level6Vector: + wsr a0, EXCSAVE_6 /* preserve a0 */ + call0 _xt_highint6 /* load interrupt handler */ + /* never returns here - call0 is used as a jump (see note at top) */ + + .end literal_prefix + + .text + .type _xt_highint6,@function + .align 4 +_xt_highint6: + + #ifdef XT_INTEXC_HOOKS + /* Call interrupt hook if present to (pre)handle interrupts. */ + movi a0, _xt_intexc_hooks + l32i a0, a0, 6<<2 + beqz a0, 1f +.Ln_xt_highint6_call_hook: + callx0 a0 /* must NOT disturb stack! */ +1: + #endif + + /* USER_EDIT: + ADD HIGH PRIORITY LEVEL 6 INTERRUPT HANDLER CODE HERE. + */ + + .align 4 +.L_xt_highint6_exit: + rsr a0, EXCSAVE_6 /* restore a0 */ + rfi 6 + +#endif /* Level 6 */ + +#if XCHAL_HAVE_NMI + + .begin literal_prefix .NMIExceptionVector + .section .NMIExceptionVector.text, "ax" + .global _NMIExceptionVector + .type _NMIExceptionVector,@function + .align 4 +_NMIExceptionVector: + wsr a0, EXCSAVE + XCHAL_NMILEVEL _ /* preserve a0 */ + call0 _xt_nmi /* load interrupt handler */ + /* never returns here - call0 is used as a jump (see note at top) */ + + .end literal_prefix + + .text + .type _xt_nmi,@function + .align 4 +_xt_nmi: + + #ifdef XT_INTEXC_HOOKS + /* Call interrupt hook if present to (pre)handle interrupts. */ + movi a0, _xt_intexc_hooks + l32i a0, a0, XCHAL_NMILEVEL<<2 + beqz a0, 1f +.Ln_xt_nmi_call_hook: + callx0 a0 /* must NOT disturb stack! */ +1: + #endif + + /* USER_EDIT: + ADD HIGH PRIORITY NON-MASKABLE INTERRUPT (NMI) HANDLER CODE HERE. + */ + + .align 4 +.L_xt_nmi_exit: + rsr a0, EXCSAVE + XCHAL_NMILEVEL /* restore a0 */ + rfi XCHAL_NMILEVEL + +#endif /* NMI */ + + +/******************************************************************************* + +WINDOW OVERFLOW AND UNDERFLOW EXCEPTION VECTORS AND ALLOCA EXCEPTION HANDLER + +Here is the code for each window overflow/underflow exception vector and +(interspersed) efficient code for handling the alloca exception cause. +Window exceptions are handled entirely in the vector area and are very +tight for performance. The alloca exception is also handled entirely in +the window vector area so comes at essentially no cost in code size. +Users should never need to modify them and Cadence Design Systems recommends +they do not. + +Window handlers go at predetermined vector locations according to the +Xtensa hardware configuration, which is ensured by their placement in a +special section known to the Xtensa linker support package (LSP). Since +their offsets in that section are always the same, the LSPs do not define +a section per vector. + +These things are coded for XEA2 only (XEA1 is not supported). + +Note on Underflow Handlers: +The underflow handler for returning from call[i+1] to call[i] +must preserve all the registers from call[i+1]'s window. +In particular, a0 and a1 must be preserved because the RETW instruction +will be reexecuted (and may even underflow if an intervening exception +has flushed call[i]'s registers). +Registers a2 and up may contain return values. + +*******************************************************************************/ + +#if XCHAL_HAVE_WINDOWED + + .section .WindowVectors.text, "ax" + +/* +-------------------------------------------------------------------------------- +Window Overflow Exception for Call4. + +Invoked if a call[i] referenced a register (a4-a15) +that contains data from ancestor call[j]; +call[j] had done a call4 to call[j+1]. +On entry here: + window rotated to call[j] start point; + a0-a3 are registers to be saved; + a4-a15 must be preserved; + a5 is call[j+1]'s stack pointer. +-------------------------------------------------------------------------------- +*/ + + .org 0x0 + .global _WindowOverflow4 +_WindowOverflow4: + + s32e a0, a5, -16 /* save a0 to call[j+1]'s stack frame */ + s32e a1, a5, -12 /* save a1 to call[j+1]'s stack frame */ + s32e a2, a5, -8 /* save a2 to call[j+1]'s stack frame */ + s32e a3, a5, -4 /* save a3 to call[j+1]'s stack frame */ + rfwo /* rotates back to call[i] position */ + +/* +-------------------------------------------------------------------------------- +Window Underflow Exception for Call4 + +Invoked by RETW returning from call[i+1] to call[i] +where call[i]'s registers must be reloaded (not live in ARs); +where call[i] had done a call4 to call[i+1]. +On entry here: + window rotated to call[i] start point; + a0-a3 are undefined, must be reloaded with call[i].reg[0..3]; + a4-a15 must be preserved (they are call[i+1].reg[0..11]); + a5 is call[i+1]'s stack pointer. +-------------------------------------------------------------------------------- +*/ + + .org 0x40 + .global _WindowUnderflow4 +_WindowUnderflow4: + + l32e a0, a5, -16 /* restore a0 from call[i+1]'s stack frame */ + l32e a1, a5, -12 /* restore a1 from call[i+1]'s stack frame */ + l32e a2, a5, -8 /* restore a2 from call[i+1]'s stack frame */ + l32e a3, a5, -4 /* restore a3 from call[i+1]'s stack frame */ + rfwu + +/* +-------------------------------------------------------------------------------- +Handle alloca exception generated by interruptee executing 'movsp'. +This uses space between the window vectors, so is essentially "free". +All interruptee's regs are intact except a0 which is saved in EXCSAVE_1, +and PS.EXCM has been set by the exception hardware (can't be interrupted). +The fact the alloca exception was taken means the registers associated with +the base-save area have been spilled and will be restored by the underflow +handler, so those 4 registers are available for scratch. +The code is optimized to avoid unaligned branches and minimize cache misses. +-------------------------------------------------------------------------------- +*/ + + .align 4 + .global _xt_alloca_exc +_xt_alloca_exc: + + rsr a0, WINDOWBASE /* grab WINDOWBASE before rotw changes it */ + rotw -1 /* WINDOWBASE goes to a4, new a0-a3 are scratch */ + rsr a2, PS + extui a3, a2, XCHAL_PS_OWB_SHIFT, XCHAL_PS_OWB_BITS + xor a3, a3, a4 /* bits changed from old to current windowbase */ + rsr a4, EXCSAVE_1 /* restore original a0 (now in a4) */ + slli a3, a3, XCHAL_PS_OWB_SHIFT + xor a2, a2, a3 /* flip changed bits in old window base */ + wsr a2, PS /* update PS.OWB to new window base */ + rsync + + _bbci.l a4, 31, _WindowUnderflow4 + rotw -1 /* original a0 goes to a8 */ + _bbci.l a8, 30, _WindowUnderflow8 + rotw -1 + j _WindowUnderflow12 + +/* +-------------------------------------------------------------------------------- +Window Overflow Exception for Call8 + +Invoked if a call[i] referenced a register (a4-a15) +that contains data from ancestor call[j]; +call[j] had done a call8 to call[j+1]. +On entry here: + window rotated to call[j] start point; + a0-a7 are registers to be saved; + a8-a15 must be preserved; + a9 is call[j+1]'s stack pointer. +-------------------------------------------------------------------------------- +*/ + + .org 0x80 + .global _WindowOverflow8 +_WindowOverflow8: + + s32e a0, a9, -16 /* save a0 to call[j+1]'s stack frame */ + l32e a0, a1, -12 /* a0 <- call[j-1]'s sp + (used to find end of call[j]'s frame) */ + s32e a1, a9, -12 /* save a1 to call[j+1]'s stack frame */ + s32e a2, a9, -8 /* save a2 to call[j+1]'s stack frame */ + s32e a3, a9, -4 /* save a3 to call[j+1]'s stack frame */ + s32e a4, a0, -32 /* save a4 to call[j]'s stack frame */ + s32e a5, a0, -28 /* save a5 to call[j]'s stack frame */ + s32e a6, a0, -24 /* save a6 to call[j]'s stack frame */ + s32e a7, a0, -20 /* save a7 to call[j]'s stack frame */ + rfwo /* rotates back to call[i] position */ + +/* +-------------------------------------------------------------------------------- +Window Underflow Exception for Call8 + +Invoked by RETW returning from call[i+1] to call[i] +where call[i]'s registers must be reloaded (not live in ARs); +where call[i] had done a call8 to call[i+1]. +On entry here: + window rotated to call[i] start point; + a0-a7 are undefined, must be reloaded with call[i].reg[0..7]; + a8-a15 must be preserved (they are call[i+1].reg[0..7]); + a9 is call[i+1]'s stack pointer. +-------------------------------------------------------------------------------- +*/ + + .org 0xC0 + .global _WindowUnderflow8 +_WindowUnderflow8: + + l32e a0, a9, -16 /* restore a0 from call[i+1]'s stack frame */ + l32e a1, a9, -12 /* restore a1 from call[i+1]'s stack frame */ + l32e a2, a9, -8 /* restore a2 from call[i+1]'s stack frame */ + l32e a7, a1, -12 /* a7 <- call[i-1]'s sp + (used to find end of call[i]'s frame) */ + l32e a3, a9, -4 /* restore a3 from call[i+1]'s stack frame */ + l32e a4, a7, -32 /* restore a4 from call[i]'s stack frame */ + l32e a5, a7, -28 /* restore a5 from call[i]'s stack frame */ + l32e a6, a7, -24 /* restore a6 from call[i]'s stack frame */ + l32e a7, a7, -20 /* restore a7 from call[i]'s stack frame */ + rfwu + +/* +-------------------------------------------------------------------------------- +Window Overflow Exception for Call12 + +Invoked if a call[i] referenced a register (a4-a15) +that contains data from ancestor call[j]; +call[j] had done a call12 to call[j+1]. +On entry here: + window rotated to call[j] start point; + a0-a11 are registers to be saved; + a12-a15 must be preserved; + a13 is call[j+1]'s stack pointer. +-------------------------------------------------------------------------------- +*/ + + .org 0x100 + .global _WindowOverflow12 +_WindowOverflow12: + + s32e a0, a13, -16 /* save a0 to call[j+1]'s stack frame */ + l32e a0, a1, -12 /* a0 <- call[j-1]'s sp + (used to find end of call[j]'s frame) */ + s32e a1, a13, -12 /* save a1 to call[j+1]'s stack frame */ + s32e a2, a13, -8 /* save a2 to call[j+1]'s stack frame */ + s32e a3, a13, -4 /* save a3 to call[j+1]'s stack frame */ + s32e a4, a0, -48 /* save a4 to end of call[j]'s stack frame */ + s32e a5, a0, -44 /* save a5 to end of call[j]'s stack frame */ + s32e a6, a0, -40 /* save a6 to end of call[j]'s stack frame */ + s32e a7, a0, -36 /* save a7 to end of call[j]'s stack frame */ + s32e a8, a0, -32 /* save a8 to end of call[j]'s stack frame */ + s32e a9, a0, -28 /* save a9 to end of call[j]'s stack frame */ + s32e a10, a0, -24 /* save a10 to end of call[j]'s stack frame */ + s32e a11, a0, -20 /* save a11 to end of call[j]'s stack frame */ + rfwo /* rotates back to call[i] position */ + +/* +-------------------------------------------------------------------------------- +Window Underflow Exception for Call12 + +Invoked by RETW returning from call[i+1] to call[i] +where call[i]'s registers must be reloaded (not live in ARs); +where call[i] had done a call12 to call[i+1]. +On entry here: + window rotated to call[i] start point; + a0-a11 are undefined, must be reloaded with call[i].reg[0..11]; + a12-a15 must be preserved (they are call[i+1].reg[0..3]); + a13 is call[i+1]'s stack pointer. +-------------------------------------------------------------------------------- +*/ + + .org 0x140 + .global _WindowUnderflow12 +_WindowUnderflow12: + + l32e a0, a13, -16 /* restore a0 from call[i+1]'s stack frame */ + l32e a1, a13, -12 /* restore a1 from call[i+1]'s stack frame */ + l32e a2, a13, -8 /* restore a2 from call[i+1]'s stack frame */ + l32e a11, a1, -12 /* a11 <- call[i-1]'s sp + (used to find end of call[i]'s frame) */ + l32e a3, a13, -4 /* restore a3 from call[i+1]'s stack frame */ + l32e a4, a11, -48 /* restore a4 from end of call[i]'s stack frame */ + l32e a5, a11, -44 /* restore a5 from end of call[i]'s stack frame */ + l32e a6, a11, -40 /* restore a6 from end of call[i]'s stack frame */ + l32e a7, a11, -36 /* restore a7 from end of call[i]'s stack frame */ + l32e a8, a11, -32 /* restore a8 from end of call[i]'s stack frame */ + l32e a9, a11, -28 /* restore a9 from end of call[i]'s stack frame */ + l32e a10, a11, -24 /* restore a10 from end of call[i]'s stack frame */ + l32e a11, a11, -20 /* restore a11 from end of call[i]'s stack frame */ + rfwu + +#endif /* XCHAL_HAVE_WINDOWED */ + + .section .UserEnter.text, "ax" + .global call_user_start + .type call_user_start,@function + .align 4 + .literal_position + + +call_user_start: + + movi a2, 0x40040000 /* note: absolute symbol, not a ptr */ + wsr a2, vecbase + call0 user_start /* user exception handler */ diff --git a/components/lwip/CHANGELOG b/components/lwip/CHANGELOG new file mode 100755 index 0000000000..21a85c94c3 --- /dev/null +++ b/components/lwip/CHANGELOG @@ -0,0 +1,4044 @@ +HISTORY + +(git master) + + * [Enter new changes just after this line - do not remove this line] + + ++ New features: + + 2016-02-22: Ivan Delamer: + * Initial 6LoWPAN support + + 2015-12-26: Martin Hentschel and Dirk Ziegelmeier + * Rewrite SNMP agent + + 2015-11-12: Dirk Ziegelmeier + * Decouple SNMP stack from lwIP core and move stack to apps/ directory. + Breaking change: Users have to call snmp_init() now! + + 2015-11-12: Dirk Ziegelmeier + * Implement possibility to declare private memory pools. This is useful to + decouple some apps from the core (SNMP stack) or make contrib app useage + simpler (httpserver_raw) + + 2015-10-09: Simon Goldschmidt + * started to move "private" header files containing implementation details to + "lwip/priv/" include directory to seperate the API from the implementation. + + 2015-10-07: Simon Goldschmidt + * added sntp client as first "supported" application layer protocol implementation + added 'apps' folder + + 2015-09-30: Dirk Ziegelmeier + * snmp_structs.h, mib_structs.c, mib2.c: snmp: fixed ugly inheritance + implementation by aggregating the "base class" (struct mib_node) in all + derived node classes to get more type-safe code + + 2015-09-23: Simon Goldschmidt + * netif.h/.c, nd6.c: task #13729: Convert netif addresses (IPv4 & IPv6) to + ip_addr_t (so they can be used without conversion/temporary storage) + + 2015-09-08: Dirk Ziegelmeier + * snmp: Separate mib2 counter/table callbacks from snmp agent. This both cleans + up the code and should allow integration of a 3rd party agent/mib2. Simple + counters are kept in MIB2_STATS, tree/table change function prototypes moved to + snmp_mib2.h. + + 2015-09-03: Simon Goldschmidt + * opt.h, dns.h/.c: DNS/IPv6: added support for AAAA records + + 2015-09-01: Simon Goldschmidt + * task #12178: hardware checksum capabilities can be configured per netif + (use NETIF_SET_CHECKSUM_CTRL() in your netif's init function) + + 2015-08-30: Simon Goldschmidt + * PBUF_REF with "custom" pbufs is now supported for RX pbufs (see pcapif in + contrib for an example, LWIP_SUPPORT_CUSTOM_PBUF is required) + + 2015-08-30: Simon Goldschmidt + * support IPv4 source based routing: define LWIP_HOOK_IP4_ROUTE_SRC to point + to a routing function + + 2015-08-05: Simon Goldschmidt + * many files: allow multicast socket options IP_MULTICAST_TTL, IP_MULTICAST_IF + and IP_MULTICAST_LOOP to be used without IGMP + + 2015-04-24: Simon Goldschmidt + * dhcp.h/c, autoip.h/.c: added functions dhcp/autoip_supplied_address() to + check for the source of address assignment (replacement for NETIF_FLAG_DHCP) + + 2015-04-10: Simon Goldschmidt + * many files: task #13480: added LWIP_IPV4 define - IPv4 can be disabled, + leaving an IPv6-only stack + + 2015-04-09: Simon Goldschmidt + * nearly all files: task #12722 (improve IPv4/v6 address handling): renamed + ip_addr_t to ip4_addr_t, renamed ipX_addr_t to ip_addr_t and added IP + version; ip_addr_t is used for all generic IP addresses for the API, + ip(4/6)_addr_t are only used internally or when initializing netifs or when + calling version-related functions + + 2015-03-24: Simon Goldschmidt + * opt.h, ip4_addr.h, ip4.c, ip6.c: loopif is not required for loopback traffic + any more but passed through any netif (ENABLE_LOOPBACK has to be enabled) + + 2015-03-23: Simon Goldschmidt + * opt.h, etharp.c: with ETHARP_TABLE_MATCH_NETIF== 1, duplicate (Auto)-IP + addresses on multiple netifs should now be working correctly (if correctly + addressed by routing, that is) + + 2015-03-23: Simon Goldschmidt + * etharp.c: Stable etharp entries that are about to expire are now refreshed + using unicast to prevent unnecessary broadcast. Only if no answer is received + after 15 seconds, broadcast is used. + + 2015-03-06: Philip Gladstone + * netif.h/.c: patch #8359 (Provide utility function to add an IPv6 address to + an interface) + + 2015-03-05: Simon Goldschmidt + * netif.c, ip4.c, dhcp.c, autoip.c: fixed bug #37068 (netif up/down handling + is unclear): correclty separated administrative status of a netif (up/down) + from 'valid address' status + ATTENTION: netif_set_up() now always has to be called, even when dhcp/autoip + is used! + + 2015-02-26: patch by TabascoEye + * netif.c, udp.h/.c: fixed bug #40753 (re-bind UDP pcbs on change of IP address) + + 2015-02-22: chrysn, Simon Goldschmidt + * *.*: Changed nearly all functions taking 'ip(X)_addr_t' pointer to take + const pointers (changed user callbacks: raw_recv_fn, udp_recv_fn; changed + port callbacks: netif_output_fn, netif_igmp_mac_filter_fn) + + 2015-02-19: Ivan Delamer + * netif.h, dhcp.c: Removed unused netif flag for DHCP. The preferred way to evaluate + if DHCP is active is through netif->dhcp field. + + 2015-02-19: Ivan Delamer + * netif.h, slipif.c, ppp.c: Removed unused netif flag for point to point connections + + 2015-02-18: Simon Goldschmidt + * api_lib.c: fixed bug #37958 "netconn API doesn't handle correctly + connections half-closed by peer" + + 2015-02-18: Simon Goldschmidt + * tcp.c: tcp_alloc() prefers killing CLOSING/LAST_ACK over active connections + (see bug #39565) + + 2015-02-16: Claudius Zingerli, Sergio Caprile + * opt.h, dhcp.h/.c: patch #8361 "Add support for NTP option in DHCP" + + 2015-02-14: Simon Goldschmidt + * opt.h, snmp*: added support for write-access community and dedicated + community for sending traps + + 2015-02-13: Simon Goldschmidt + * opt.h, memp.c: added hook LWIP_HOOK_MEMP_AVAILABLE() to get informed when + a memp pool was empty and an item is now available + + 2015-02-13: Simon Goldschmidt + * opt.h, pbuf.h/.c, etharp.c: Added the option PBUF_LINK_ENCAPSULATION_HLEN to + allocate additional header space for TX on netifs requiring additional headers + + 2015-02-12: chrysn + * timers.h/.c: introduce sys_timeouts_sleeptime (returns the time left before + the next timeout is due, for NO_SYS==1) + + 2015-02-11: Nick van Ijzendoorn + * opt.h, sockets.h/c: patch #7702 "Include ability to increase the socket number + with defined offset" + + 2015-02-11: Frederick Baksik + * opt.h, def.h, others: patch #8423 "arch/perf.h" should be made an optional item + + 2015-02-11: Simon Goldschmidt + * api_msg.c, opt.h: started to implement fullduplex sockets/netconns + (note that this is highly unstable yet!) + + 2015-01-17: Simon Goldschmidt + * api: allow enabling socket API without (public) netconn API - netconn API is + still used by sockets, but keeping it private (static) should allow better + compiler optimizations + + 2015-01-16: Simon Goldschmidt + * tcp_in.c: fixed bug #20506 "Initial congestion window is very small" again + by implementing the calculation formula from RFC3390 + + 2014-12-10: Simon Goldschmidt + * api: added option LWIP_NETCONN_SEM_PER_THREAD to use a semaphore per thread + instead of using one per netconn and per select call + + 2014-12-08: Simon Goldschmidt + * ip6.h: fixed bug #43778: IPv6 header version not set on 16-bit platform + (macro IP6H_VTCFL_SET()) + + 2014-12-08: Simon Goldschmidt + * icmp.c, ip4.c, pbuf.c, udp.c, pbuf.h: task #11472 Support PBUF_REF for RX + (IPv6 and IPv4/v6 reassembly might not work yet) + + 2014-11-06: Simon Goldschmidt + * sockets.c/.h, init.c: lwip_socket_init() is not needed any more + -> compatibility define + + 2014-09-16: Simon Goldschmidt + * dns.c, opt.h: reduced ram usage by parsing DNS responses in place + + 2014-09-16: Simon Goldschmidt + * pbuf.h/.c: added pbuf_take_at() and pbuf_put_at() + + 2014-09-15: Simon Goldschmidt + * dns.c: added source port randomization to make the DNS client more robust + (see bug #43144) + + 2013-09-02: Simon Goldschmidt + * arch.h and many other files: added optional macros PACK_STRUCT_FLD_8() and + PACK_STRUCT_FLD_S() to prevent gcc 4 from warning about struct members that + do not need packing + + 2013-08-19: Simon Goldschmidt + * netif.h: bug #42998: made NETIF_MAX_HWADDR_LEN overridable for some special + networks + + 2013-03-17: Simon Goldschmidt (patch by Ghobad Emadi) + * opt.h, etharp.c: Added LWIP_HOOK_ETHARP_GET_GW to implement IPv4 routing with + multiple gateways + + 2013-04-20: Fatih Asici + * opt.h, etharp.h/.c: patch #7993: Added support for transmitting packets + with VLAN headers via hook function LWIP_HOOK_VLAN_SET and to check them + via hook function LWIP_HOOK_VLAN_CHECK + + 2014-02-20: Simon Goldschmidt (based on patch by Artem Pisarenko) + * patch #7885: modification of api modules to support FreeRTOS-MPU + (don't pass stack-pointers to other threads) + + 2014-02-05: Simon Goldschmidt (patch by "xtian" and "alex_ab") + * patch #6537/#7858: TCP window scaling support + + 2014-01-17: Jiri Engelthaler + * icmp, icmp6, opt.h: patch #8027: Completed HW checksuming for IPv4 and + IPv6 ICMP's + + 2012-08-22: Sylvain Rochet + * New PPP stack for lwIP, developed in ppp-new branch. + Based from pppd 2.4.5, released 2009-11-17, with huge changes to match + code size and memory requirements for embedded devices, including: + - Gluing together the previous low-level PPP code in lwIP to pppd 2.4.5, which + is more or less what pppd sys-* files are, so that we get something working + using the unix port. + - Merged some patchs from lwIP Git repository which add interesting features + or fix bugs. + - Merged some patchs from Debian pppd package which add interesting features + or fix bugs. + - Ported PPP timeout handling to the lwIP timers system + - Disabled all the PPP code using filesystem access, replaced in necessary cases + to configuration variables. + - Disabled all the PPP code forking processes. + - Removed IPX support, lwIP does not support IPX. + - Ported and improved random module from the previous PPP port. + - Removed samba TDB (file-driven database) usage, because it needs a filesystem. + - MS-CHAP required a DES implementation, we added the latest PolarSSL DES + implementation which is under a BSD-ish license. + - Also switched to PolarSSL MD4,MD5,SHA1 implementations, which are meant to be + used in embedded devices with reduced memory footprint. + - Removed PPP configuration file parsing support. + - Added macro definition EAP_SUPPORT to make EAP support optional. + - Added macro definition CHAP_SUPPORT to make CHAP support optional. + - Added macro definition MSCHAP_SUPPORT to make MSCHAP support optional. + - Added macro definition PAP_SUPPORT to make PAP support optional. + - Cleared all Linux syscall calls. + - Disabled demand support using a macro, so that it can be ported later. + - Disabled ECP support using a macro, so that it can be ported later. + - Disabled CCP support using a macro, so that it can be ported later. + - Disabled CBCP support using a macro, so that it can be ported later. + - Disabled LQR support using a macro, so that it can be ported later. + - Print packet debug feature optional, through PRINTPKT_SUPPORT + - Removed POSIX signal usage. + - Fully ported PPPoS code from the previous port. + - Fully ported PPPoE code from the previous port. + - Fully ported VJ compression protocol code from the previous port. + - Removed all malloc()/free() use from PPP, replaced by stack usage or PBUF. + - Disabled PPP server support using a macro, so that it can be ported later. + - Switched all PPP debug to lwIP debug system. + - Created PPP Control Block (PPP PCB), removed PPP unit integer everywhere, + removed all global variables everywhere, did everything necessary for + the PPP stack to support more than one PPP session (pppd only support + one session per process). + - Removed the statically allocated output buffer, now using PBUF. + - Improved structure size of all PPP modules, deep analyze of code to reduce + variables size to the bare minimum. Switched all boolean type (char type in + most architecture) to compiler generated bitfields. + - Added PPP IPv6 support, glued lwIP IPv6 support to PPP. + - Now using a persistent netif interface which can then be used in lwIP + functions requiring a netif. + - Now initializing PPP in lwip_init() function. + - Reworked completely the PPP state machine, so that we don't end up in + anymore in inconsistent state, especially with PPPoE. + - Improved the way we handle PPP reconnection after disconnect, cleaning + everything required so that we start the PPP connection again from a + clean state. + - Added PPP holdoff support, allow the lwIP user to wait a little bit before + reconnecting, prevents connection flood, especially when using PPPoL2TP. + - Added PPPoL2TP LAC support (a.k.a. UDP tunnels), adding a VPN client + feature to lwIP, L2TP being a widely used tunnel protocol. + - Switched all used PPP types to lwIP types (u8t, u16t, u32t, ...) + - Added PPP API "sequential" thread-safe API, based from NETIFAPI. + + 2011-07-21: Simon Goldschmidt + * sockets.c, opt.h: (bug #30185): added LWIP_FIONREAD_LINUXMODE that makes + ioctl/FIONREAD return the size of the next pending datagram. + + 2011-05-25: Simon Goldschmidt + * again nearly the whole stack, renamed ip.c to ip4.c, ip_addr.c to ip4_addr.c, + combined ipv4/ipv6 inet_chksum.c, added ip.h, ip_addr.h: Combined IPv4 + and IPv6 code where possible, added defines to access IPv4/IPv6 in non-IP + code so that the code is more readable. + + 2011-05-17: Patch by Ivan Delamer (only checked in by Simon Goldschmidt) + * nearly the whole stack: Finally, we got decent IPv6 support, big thanks to + Ivan! (this is work in progress: we're just post release anyway :-) + + + ++ Bugfixes: + + 2016-03-05: Simon Goldschmidt + * err.h/.c, sockets.c: ERR_IF is not necessarily a fatal error + + 2015-11-19: fix by Kerem Hadimli + * sockets.c: fixed bug #46471: lwip_accept() leaks socket descriptors if new + netconn was already closed because of peer behavior + + 2015-11-12: fix by Valery Ushakov + * tcp_in.c: fixed bug #46365 tcp_accept_null() should call tcp_abort() + + 2015-10-02: Dirk Ziegelmeier/Simon Goldschmidt + * snmp: cleaned up snmp structs API (fixed race conditions from bug #46089, + reduce ram/rom usage of tables): incompatible change for private MIBs + + 2015-09-30: Simon Goldschmidt + * ip4_addr.c: fixed bug #46072: ip4addr_aton() does not check the number range + of all address parts + + 2015-08-28: Simon Goldschmidt + * tcp.c, tcp_in.c: fixed bug #44023: TCP ssthresh value is unclear: ssthresh + is set to the full send window for active open, too, and is updated once + after SYN to ensure the correct send window is used + + 2015-08-28: Simon Goldschmidt + * tcp: fixed bug #45559: Window scaling casts u32_t to u16_t without checks + + 2015-08-26: Simon Goldschmidt + * ip6_frag.h/.c: fixed bug bug #41009: IPv6 reassembly broken on 64-bit platforms: + define IPV6_FRAG_COPYHEADER==1 on these platforms to copy the IPv6 header + instead of referencing it, which gives more room for struct ip6_reass_helper + + 2015-08-25: Simon Goldschmidt + * sockets.c: fixed bug #45827: recvfrom: TCP window is updated with MSG_PEEK + + 2015-08-20: Manoj Kumar + * snmp_msg.h, msg_in.c: fixed bug #43790: Sending octet string of Length >255 + from SNMP agent + + 2015-08-19: Jens Nielsen + * icmp.c, ip4.c, tcp_in.c, udp.c, raw.c: fixed bug #45120: Broadcast & multiple + interfaces handling + + 2015-08-19: Simon Goldschmidt (patch by "Sandra") + * dns.c: fixed bug #45004: dns response without answer might be discarded + + 2015-08-18: Chrysn + * timers.c: patch #8704 fix sys_timeouts_sleeptime function + + 2015-07-01: Erik Ekman + * puf.c: fixed bug #45454 (pbuf_take_at() skips write and returns OK if offset + is at start of pbuf in chain) + + 2015-05-19: Simon Goldschmidt + * dhcp.h/.c: fixed bugs #45140 and #45141 (dhcp was not stopped correctly after + fixing bug #38204) + + 2015-03-21: Simon Goldschmidt (patch by Homyak) + * tcp_in.c: fixed bug #44766 (LWIP_WND_SCALE: tcphdr->wnd was not scaled in + two places) + + 2015-03-21: Simon Goldschmidt + * tcp_impl.h, tcp.c, tcp_in.c: fixed bug #41318 (Bad memory ref in tcp_input() + after tcp_close()) + + 2015-03-21: Simon Goldschmidt + * tcp_in.c: fixed bug #38468 (tcp_sent() not called on half-open connection for + data ACKed with the same ack as FIN) + + 2015-03-21: Simon Goldschmidt (patch by Christoffer Lind) + * dhcp.h/.c: fixed bug #38204 (DHCP lease time not handled correctly) + + 2015-03-20: Simon Goldschmidt + * dhcp.c: fixed bug #38714 (Missing option and client address in DHCPRELEASE message) + + 2015-03-19: Simon Goldschmidt + * api.h, tcpip.h, api_lib.c, api_msg.c: fixed race conditions in assigning + netconn->last_err (fixed bugs #38121 and #37676) + + 2015-03-09: Simon Goldschmidt + * ip4.c: fixed the IPv4 part of bug #43904 (ip_route() must detect linkup status) + + 2015-03-04: Simon Goldschmidt + * nd6.c: fixed bug #43784 (a host should send at least one Router Solicitation) + + 2015-03-04: Valery Ushakov + * ip6.c: fixed bug #41094 (Byte-order bug in IPv6 fragmentation header test) + + 2015-03-04: Zach Smith + * nd6.c: fixed bug #38153 (nd6_input() byte order issues) + + 2015-02-26: Simon Goldschmidt + * netif.c, tcp.h/.c: fixed bug #44378 (TCP connections are not aborted on netif + remove) + + 2015-02-25: Simon Goldschmidt + * ip4.c, etharp.c: fixed bug #40177 (System hangs when dealing with corrupted + packets), implemented task #12357 (Ensure that malicious packets don't + assert-fail): improved some pbuf_header calls to not assert-fail. + + 2015-02-25: patch by Joel Cunningham + * udp.h/.c, sockets.c: fixed bug #43028 (IP_MULTICAST_TTL affects unicast + datagrams) + + 2015-02-25: patch by Greg Renda + * ip4_frag.c: fixed bug #38210 (ip reassembly while remove oldest datagram) + + 2015-02-25: Simon Goldschmidt + * sockets.c: fixed bug #38165 (socket with mulicast): ensure igmp membership + are dropped when socket (not netconn!) is closed. + + 2015-02-25: Simon Goldschmidt + * ip4.h/.c, udp.c: fixed bug #38061 (wrong multicast routing in IPv4) by + adding an optional default netif for multicast routing + + 2015-02-25: Simon Goldschmidt + * netconn API: fixed that netconn_connect still used message passing for + LWIP_TCPIP_CORE_LOCKING==1 + + 2015-02-22: patch by Jens Nielsen + * icmp.c: fixed bug #38803 (Source address in broadcast ping reply) + + 2015-02-22: Simon Goldschmidt + * udp.h, sockets.c: added proper accessor functions for pcb->multicast_ip + (previously used by get/setsockopt only) + + 2015-02-18: Simon Goldschmidt + * sockets.c: Fixed select not reporting received FIN as 'readable' in certain + rare cases (bug #43779: select(), close(), and TCP retransmission error) + + 2015-02-17: Simon Goldschmidt + * err.h, sockets.c, api_msg.c: fixed bug #38853 "connect() use a wrong errno": + return ERR_ALREADY/EALRADY during connect, ERR_ISCONN/EISCONN when already + connected + + 2015-02-17: Simon Goldschmidt + * tcp_impl.h, tcp_out.c, tcp.c, api_msg.c: fixed bug #37614 "Errors from + ipX_output are not processed". Now tcp_output(_segment) checks for the return + value of ipX_output and does not try to send more on error. A netif driver + can call tcp_txnow() (from tcpip_thread!) to try to send again if TX buffers + are available again. + + 2015-02-14: patches by Freddie Chopin + * snmp*: made community writable, fixed some const pointers + + 2015-02-13: Simon Goldschmidt + * msg_in.c: fixed bug #22070 "MIB_OBJECT_WRITE_ONLY not implemented in SNMP" + + 2015-02-12: Simon Goldschmidt + * ip.h, ip4.c, ip6.c: fixed bug #36403 "ip4_input() and ip6_input() always pass + inp to higher layers": now the accepting netif is passed up, but the input + netif is available through ip_current_input_netif() if required. + + 2015-02-11: patch by hichard + * tcpip.c: fixed bug #43094 "The function tcpip_input() forget to handle IPv6" + + 2015-02-10: Simon Goldschmidt + * netconn API: fixed that netconn_close/netconn_delete still used message passing + for LWIP_TCPIP_CORE_LOCKING==1 + + 2015-02-10: Simon Goldschmidt + * netconn/socket api: fixed bug #44225 "closing TCP socket should time out + eventually", implemented task #6930 "Implement SO_LINGER": closing TCP sockets + times out after 20 seconds or after the configured SND_TIMEOUT or depending + on the linger settings. + + 2015-01-27: Simon Goldschmidt + * api_msg.c: fixed that SHUT_RD followed by SHUT_WR was different to SHUT_RDWR, + fixed return value of lwip_netconn_do_close on unconnected netconns + + 2015-01-17: Simon Goldschmidt + * sockets.c: fixed bug #43361 select() crashes with stale FDs + + 2015-01-17: Simon Goldschmidt + * sockets.c/.h, memp_std.h: fixed bug #40788 "lwip_setsockopt_internal() crashes" + by rewriting set/getsockopt functions to combine checks with the actual code + and add more NULL checks; this also fixes that CORE_LOCKING used message + passing for set/getsockopt. + + 2014-12-19: Simon Goldschmidt + * opt.h, dhcp.h/.c: prevent dhcp from starting when netif link is down (only + when LWIP_DHCP_CHECK_LINK_UP==1, which is disabled by default for + compatibility reasons) + + 2014-12-17: Simon Goldschmidt + * tcp_out.c: fixed bug #43840 Checksum error for TCP_CHECKSUM_ON_COPY==1 for + no-copy data with odd length + + 2014-12-10: Simon Goldschmidt + * sockets.c, tcp.c, others: fixed bug #43797 set/getsockopt: SO_SNDTIMEO/SO_RCVTIMEO + take int as option but should take timeval (LWIP_SO_SNDRCVTIMEO_STANDARD==0 can + be used to revert to the old 'winsock' style behaviour) + Fixed implementation of SO_ACCEPTCONN to just look at the pcb state + + 2014-12-09: Simon Goldschmidt + * ip4.c: fixed bug #43596 IGMP queries from 0.0.0.0 are discarded + + 2014-10-21: Simon Goldschmidt (patch by Joel Cunningham and Albert Huitsing) + * sockts.c: fixed bugs #41495 Possible threading issue in select() and #43278 + event_callback() handle context switch when calling sys_sem_signal() + + 2014-10-21: Simon Goldschmidt + * api_msg.c: fixed bug #38219 Assert on TCP netconn_write with sndtimeout set + + 2014-09-16: Kevin Cernekee + * dns.c: patch #8480 Fix handling of dns_seqno wraparound + + 2014-09-16: Simon Goldschmidt + * tcp_out.c: fixed bug #43192 tcp_enqueue_flags() should not check TCP_SND_QUEUELEN + when sending FIN + + 2014-09-03: Simon Goldschmidt + * msg_in.c: fixed bug #39355 SNMP Memory Leak in case of error + + 2014-09-02: Simon Goldschmidt + * err.h/.c, sockets.c, api_msg.c: fixed bug #43110 call getpeername() before + listen() will cause a error + + 2014-09-02: Simon Goldschmidt + * sockets.c: fixed bug #42117 lwip_fcntl does not set errno + + 2014-09-02: Simon Goldschmidt + * tcp.c: fixed bug #42299 tcp_abort() leaves freed pcb on tcp_bound_pcbs list + + 2014-08-20: Simon Goldschmidt + * dns.c: fixed bug #42987 lwIP is vulnerable to DNS cache poisoning due to + non-randomized TXIDs + + 2014-06-03: Simon Goldschmidt + * tcp_impl.h, tcp_in.c: fixed bug #37969 SYN packet dropped as short packet in + tcp_input function + + 2014-05-20: Simon Goldschmidt + * tcp_out.c: fixed bug #37184 tcp_write problem for pcbs in the SYN_SENT state + + 2014-05-19: Simon Goldschmidt + * *.h: Fixed bug #35874 reserved identifier violation (removed leading underscores + from header include guards) + + 2014-04-08: Simon Goldschmidt + * tcp.c: Fixed bug #36167 tcp server crash when client closes (maximum window) + + 2014-04-06: Simon Goldschmidt + * tcp_in.c: Fixed bug #36210 lwIP does not elicit an empty ACK when received + unacceptable ACK + + 2014-04-06: Simon Goldschmidt + * dhcp.c, ip4.c/.h, ip6.c/.h, udp.c/.h, ip.h: Fixed bug #41787 DHCP Discovery + is invalid when an IP is set to thet netif. + + 2014-03-14: Simon Goldschmidt + * tcp_out.c: Fixed bug #36153 TCP Cheksum error if LWIP_CHECKSUM_ON_COPY=1 + + 2014-03-11: Simon Goldschmidt (patch by Mason) + * opt.h, sockets.c: fixed bug #35928 BSD sockets functions must set errno for + POSIX-compliance + + 2014-02-27: Simon Goldschmidt + * dhcp.c: fixed bug #40303 DHCP xid renewed when sending a DHCPREQUEST + + 2014-02-27: Simon Goldschmidt + * raw.c: fixed bug #41680 raw socket can not receive IPv6 packet when + IP_SOF_BROADCAST_RECV==1 + + 2014-02-27: Simon Goldschmidt + * api_msg.c, sockets.c: fixed bug #38404 getpeeraddr returns success on + unconnected/listening TCP sockets + + 2014-02-27: Simon Goldschmidt + * sockets.c: fixed bug #41729 Some socket functions return Exyz instead of -1 + + 2014-02-25: Simon Goldschmidt + * ip4.c: fixed bug #39514 ip_route() may return an IPv6-only interface + + 2014-02-25: Simon Goldschmidt, patch by Fatih Asici + * pbuf.c: fixed bug #39356 Wrong increment in pbuf_memfind() + + 2014-02-25: Simon Goldschmidt + * netif.c/.h, udp.c: fixed bug #39225 udp.c uses netif_matches_ip6_addr() incorrectly; + renamed function netif_matches_ip6_addr() to netif_get_ip6_addr_match() + + 2014-02-25: Simon Goldschmidt + * igmp.c: fixed bug #39145 IGMP membership report for 224.0.0.1 + + 2014-02-22: Simon Goldschmidt (patch by Amir Shalem) + * etharp.c, opt.h: fixed bug #34681 Limit ARP queue length by ARP_QUEUE_LEN (=3) + + 2014-02-22: Simon Goldschmidt (patch by Amir Shalem) + * etharp.h/.c: fixed bug #34682 Limit ARP request flood for unresolved entry + + 2014-02-20: Simon Goldschmidt + * tcp_out.c: fixed bug #39683 Assertion "seg->tcphdr not aligned" failed with + MEM_ALIGNMENT = 8 + + 2014-02-20: Simon Goldschmidt + * sockets.c: fixed bug #39882 No function shall set errno to 0 + + 2014-02-20: Simon Goldschmidt + * mib_structs.c: fixed bug #40050 SNMP problem with MIB arrays > 255 + + 2014-02-20: Simon Goldschmidt + * api.h, sockets.c: fixed bug #41499 netconn::recv_avail can overflow + + 2014-01-08: Stathis Voukelatos + * memp_std.h: patch #7928 Fixed size calculation in MALLOC memory pool + creation macro + + 2014-01-18: Brian Fahs + * tcp_out.c: patch #8237: tcp_rexmit_rto fails to update pcb->unsent_oversize + when necessary + + 2014-01-17: Grant Erickson, Jay Logue, Simon Goldschmidt + * ipv6.c, netif.c: patch #7913 Enable Support for IPv6 Loopback + + 2014-01-16: Stathis Voukelatos + * netif.c: patch #7902 Fixed netif_poll() operation when LWIP_LOOPBACK_MAX_PBUFS > 0 + + 2014-01-14: "Freddie Chopin" + * snmp.h, mib2.c: fixed constness and spelling of sysdescr + + 2014-01-14: Simon Goldschmidt (patch by Thomas Faber) + * tcpip.c: patch #8241: Fix implicit declaration of ip_input with + LWIP_TCPIP_CORE_LOCKING_INPUT disabled + + 2014-01-14: chrysn + * timers.c: patch #8244 make timeouts usable reliably from outside of the + timeout routine + + 2014-01-10: Simon Goldschmidt + * ip_frag.c, ip6_frag.c: fixed bug #41041 Potential use-after-free in IPv6 reassembly + + 2014-01-10: Simon Goldschmidt + * memp.c: fixed bug #41188 Alignment error in memp_init() when MEMP_SEPARATE_POOLS==1 + + 2014-01-10: Simon Goldschmidt + * tcp.c: fixed bug #39898 tcp_fasttmr() possible lock due to infinte queue process loop + + 2013-06-29: Simon Goldschmidt + * inet.h, sockets.h: partially fixed bug #37585: IPv6 compatibility (in socket structs) + + 2013-06-29: Simon Goldschmidt + * inet6.h: bug #37585/task #12600: fixed struct in6_addr.s6_addr to conform to spec + + 2013-04-24: patch by Liam + * api_msg.c: patch #8008 Fix a potential null pointer dereference in assert + + 2013-04-24: Simon Goldschmidt + * igmp.c: fixed possible division by zero + + 2013-04-24: Simon Goldschmidt + * ip6.h, some ipv6 C files: fixed bug #38526 Coverity: Recursive Header Inclusion in ip6.h + + 2013-04-24: Simon Goldschmidt (patch by Emil Ljungdahl): + * netif.c: fixed bug #38586 netif_loop_output() "deadlocks" + + 2013-01-15: Simon Goldschmidt + * ip4.c: fixed bug #37665 ip_canforward operates on address in wrong byte order + + 2013-01-15: Simon Goldschmidt + * pbuf.h: fixed bug #38097 pbuf_free_ooseq() warning + + 2013-01-14: Simon Goldschmidt + * dns.c: fixed bug #37705 Possible memory corruption in DNS query + + 2013-01-11: Simon Goldschmidt + * raw.c: fixed bug #38066 Raw pcbs can alter packet without eating it + + 2012-08-22: Simon Goldschmidt + * memp.c: fixed bug #37166: memp_sanity check loops itself + + 2012-08-13: Simon Goldschmidt + * dhcp.c: fixed bug #36645: Calling dhcp_release before dhcp_start + dereferences NULL + + 2012-08-13: Simon Goldschmidt + * msg_out.c: fixed bug #36840 snmp_send_trap() NULL de-reference if traps + configured but no interfaces available + + 2012-08-13: Simon Goldschmidt + * dns.c: fixed bug #36899 DNS TTL 0 is cached for a long time + + 2012-05-11: Simon Goldschmidt (patch by Marty) + * memp.c: fixed bug #36412: memp.c does not compile when + MEMP_OVERFLOW_CHECK > zero and MEMP_SEPARATE_POOLS == 1 + + 2012-05-03: Simon Goldschmidt (patch by Sylvain Rochet) + * ppp.c: fixed bug #36283 (PPP struct used on header size computation and + not packed) + + 2012-05-03: Simon Goldschmidt (patch by David Empson) + * ppp.c: fixed bug #36388 (PPP: checksum-only in last pbuf leads to pbuf with + zero length) + + 2012-03-25: Simon Goldschmidt + * api_msg.c: Fixed bug #35817: do_connect() invalidly signals op_completed + for UDP/RAW with LWIP_TCPIP_CORE_LOCKING==1 + + 2012-03-25: Simon Goldschmidt + * api_msg.h, api_lib.c, api_msg.c, netifapi.c: fixed bug #35931: Name space + pollution in api_msg.c and netifapi.c + + 2011-08-24: Simon Goldschmidt + * inet6.h: fixed bug #34124 struct in6_addr does not conform to the standard + + + +(STABLE-1.4.1) + + ++ New features: + + 2012-03-25: Simon Goldschmidt (idea by Mason) + * posix/*: added posix-compatibility include files posix/netdb.h and posix/sys/socket.h + which are a simple wrapper to the correct lwIP include files. + + 2012-01-16: Simon Goldschmidt + * opt.h, icmp.c: Added option CHECKSUM_GEN_ICMP + + 2011-12-17: Simon Goldschmidt + * ip.h: implemented API functions to access so_options of IP pcbs (UDP, TCP, RAW) + (fixes bug #35061) + + 2011-09-27: Simon Goldschmidt + * opt.h, tcp.c, tcp_in.c: Implemented limiting data on ooseq queue (task #9989) + (define TCP_OOSEQ_MAX_BYTES / TCP_OOSEQ_MAX_PBUFS in lwipopts.h) + + 2011-09-21: Simon Goldschmidt + * opt.h, api.h, api_lib.c, api_msg.h/.c, sockets.c: Implemented timeout on + send (TCP only, bug #33820) + + 2011-09-21: Simon Goldschmidt + * init.c: Converted runtime-sanity-checks into compile-time checks that can + be disabled (since runtime checks can often not be seen on embedded targets) + + 2011-09-11: Simon Goldschmidt + * ppp.h, ppp_impl.h: splitted ppp.h to an internal and external header file + to get a clear separation of which functions an application or port may use + (task #11281) + + 2011-09-11: Simon Goldschmidt + * opt.h, tcp_impl.h, tcp.c, udp.h/.c: Added a config option to randomize + initial local TCP/UDP ports (so that different port ranges are used after + a reboot; bug #33818; this one added tcp_init/udp_init functions again) + + 2011-09-03: Simon Goldschmidt + * dhcp.c: DHCP uses LWIP_RAND() for xid's (bug #30302) + + 2011-08-24: Simon Goldschmidt + * opt.h, netif.h/.c: added netif remove callback (bug #32397) + + 2011-07-26: Simon Goldschmidt + * etharp.c: ETHARP_SUPPORT_VLAN: add support for an external VLAN filter + function instead of only checking for one VLAN (define ETHARP_VLAN_CHECK_FN) + + 2011-07-21: Simon Goldschmidt (patch by hanhui) + * ip4.c, etharp.c, pbuf.h: bug #33634 ip_forward() have a faulty behaviour: + Added pbuf flags to mark incoming packets as link-layer broadcast/multicast. + Also added code to allow ip_forward() to forward non-broadcast packets to + the input netif (set IP_FORWARD_ALLOW_TX_ON_RX_NETIF==1). + + 2011-06-26: Simon Goldschmidt (patch by Cameron Gutman) + * tcp.c, tcp_out.c: bug #33604: added some more asserts to check that + pcb->state != LISTEN + + 2011-05-14: Simon Goldschmidt (patch by Stéphane Lesage) + * tcpip.c/.h: patch #7449 allow tcpip callback from interrupt with static + memory message + + + ++ Bugfixes: + + 2012-09-26: Simon Goldschmidt + * api_msg.c: fixed bug #37405 'err_tcp()' uses already freed 'netconn' object + + 2012-09-26: patch by Henrik Persson + * dhcp.c: patch #7843 Fix corner case with dhcp timeouts + + 2012-09-26: patch by Henrik Persson + * dhcp.c: patch #7840 Segfault in dhcp_parse_reply if no end marker in dhcp packet + + 2012-08-22: Simon Goldschmidt + * memp.c: fixed bug #37166: memp_sanity check loops itself + + 2012-05-08: Simon Goldschmidt + * tcp_out.c: fixed bug: #36380 unsent_oversize mismatch in 1.4.1RC1 (this was + a debug-check issue only) + + 2012-03-27: Simon Goldschmidt + * vj.c: fixed bug #35756 header length calculation problem in ppp/vj.c + + 2012-03-27: Simon Goldschmidt (patch by Mason) + * tcp_out.c: fixed bug #35945: SYN packet should provide the recv MSS not the + send MSS + + 2012-03-22: Simon Goldschmidt + * ip4.c: fixed bug #35927: missing refragmentaion in ip_forward + + 2012-03-20: Simon Goldschmidt (patch by Mason) + * netdb.c: fixed bug #35907: lwip_gethostbyname_r returns an invalid h_addr_list + + 2012-03-12: Simon Goldschmidt (patch by Bostjan Meglic) + * ppp.c: fixed bug #35809: PPP GetMask(): Compiler warning on big endian, + possible bug on little endian system + + 2012-02-23: Simon Goldschmidt + * etharp.c: fixed bug #35595: Impossible to send broadcast without a gateway + (introduced when fixing bug# 33551) + + 2012-02-16: Simon Goldschmidt + * ppp.c: fixed pbuf leak when PPP session is aborted through pppSigHUP() + (bug #35541: PPP Memory Leak) + + 2012-02-16: Simon Goldschmidt + * etharp.c: fixed bug #35531: Impossible to send multicast without a gateway + (introduced when fixing bug# 33551) + + 2012-02-16: Simon Goldschmidt (patch by Stéphane Lesage) + * msg_in.c, msg_out.c: fixed bug #35536 SNMP: error too big response is malformed + + 2012-02-15: Simon Goldschmidt + * init.c: fixed bug #35537: MEMP_NUM_* sanity checks should be disabled with + MEMP_MEM_MALLOC==1 + + 2012-02-12: Simon Goldschmidt + * tcp.h, tcp_in.c, tcp_out.c: partly fixed bug #25882: TCP hangs on + MSS > pcb->snd_wnd (by not creating segments bigger than half the window) + + 2012-02-11: Simon Goldschmidt + * tcp.c: fixed bug #35435: No pcb state check before adding it to time-wait + queue while closing + + 2012-01-22: Simon Goldschmidt + * tcp.c, tcp_in.c: fixed bug #35305: pcb may be freed too early on shutdown(WR) + + 2012-01-21: Simon Goldschmidt + * tcp.c: fixed bug #34636: FIN_WAIT_2 - Incorrect shutdown of TCP pcb + + 2012-01-20: Simon Goldschmidt + * dhcp.c: fixed bug #35151: DHCP asserts on incoming option lengths + + 2012-01-20: Simon Goldschmidt + * pbuf.c: fixed bug #35291: NULL pointer in pbuf_copy + + 2011-11-25: Simon Goldschmidt + * tcp.h/.c, tcp_impl.h, tcp_in.c: fixed bug #31177: tcp timers can corrupt + tcp_active_pcbs in some cases + + 2011-11-23: Simon Goldschmidt + * sys.c: fixed bug #34884: sys_msleep() body needs to be surrounded with + '#ifndef sys_msleep' + + 2011-11-22: Simon Goldschmidt + * netif.c, etharp.h/.c: fixed bug #34684: Clear the arp table cache when + netif is brought down + + 2011-10-28: Simon Goldschmidt + * tcp_in.c: fixed bug #34638: Dead code in tcp_receive - pcb->dupacks + + 2011-10-23: Simon Goldschmidt + * mem.c: fixed bug #34429: possible memory corruption with + LWIP_ALLOW_MEM_FREE_FROM_OTHER_CONTEXT set to 1 + + 2011-10-18: Simon Goldschmidt + * arch.h, netdb.c: fixed bug #34592: lwip_gethostbyname_r uses nonstandard + error value + + 2011-10-18: Simon Goldschmidt + * opt.h: fixed default values of TCP_SNDLOWAT and TCP_SNDQUEUELOWAT for small + windows (bug #34176 select after non-blocking send times out) + + 2011-10-18: Simon Goldschmidt + * tcp_impl.h, tcp_out.c: fixed bug #34587: TCP_BUILD_MSS_OPTION doesn't + consider netif->mtu, causes slow network + + 2011-10-18: Simon Goldschmidt + * sockets.c: fixed bug #34581 missing parentheses in udplite sockets code + + 2011-10-18: Simon Goldschmidt + * sockets.h: fixed bug #34580 fcntl() is missing in LWIP_COMPAT_SOCKETS + + 2011-10-17: Simon Goldschmidt + * api_msg.c: fixed bug #34569: shutdown(SHUT_WR) crashes netconn/socket api + + 2011-10-13: Simon Goldschmidt + * tcp_in.c, tcp_out.c: fixed bug #34517 (persist timer is started although no + zero window is received) by starting the persist timer when a zero window is + received, not when we have more data queued for sending than fits into the + window + + 2011-10-13: Simon Goldschmidt + * def.h, timers.c: fixed bug #34541: LWIP_U32_DIFF is unnecessarily complex + + 2011-10-13: Simon Goldschmidt + * sockets.c, api_lib.c: fixed bug #34540: compiler error when CORE_LOCKING is + used and not all protocols are enabled + + 2011-10-12: Simon Goldschmidt + * pbuf.c: fixed bug #34534: Error in sending fragmented IP if MEM_ALIGNMENT > 4 + + 2011-10-09: Simon Goldschmidt + * tcp_out.c: fixed bug #34426: tcp_zero_window_probe() transmits incorrect + byte value when pcb->unacked != NULL + + 2011-10-09: Simon Goldschmidt + * ip4.c: fixed bug #34447 LWIP_IP_ACCEPT_UDP_PORT(dst_port) wrong + + 2011-09-27: Simon Goldschmidt + * tcp_in.c, tcp_out.c: Reset pcb->unsent_oversize in 2 more places... + + 2011-09-27: Simon Goldschmidt + * tcp_in.c: fixed bug #28288: Data after FIN in oos queue + + 2011-09-27: Simon Goldschmidt + * dhcp.c: fixed bug #34406 dhcp_option_hostname() can overflow the pbuf + + 2011-09-24: Simon Goldschmidt + * mem.h: fixed bug #34377 MEM_SIZE_F is not defined if MEM_LIBC_MALLOC==1 + + 2011-09-23: Simon Goldschmidt + * pbuf.h, tcp.c, tcp_in.c: fixed bug #33871: rejecting TCP_EVENT_RECV() for + the last packet including FIN can lose data + + 2011-09-22: Simon Goldschmidt + * tcp_impl.h: fixed bug #34355: nagle does not take snd_buf/snd_queuelen into + account + + 2011-09-21: Simon Goldschmidt + * opt.h: fixed default value of TCP_SND_BUF to not violate the sanity checks + in init.c + + 2011-09-20: Simon Goldschmidt + * timers.c: fixed bug #34337 (possible NULL pointer in sys_check_timeouts) + + 2011-09-11: Simon Goldschmidt + * tcp_out.c: use pcb->mss instead of TCP_MSS for preallocate mss-sized pbufs + (bug #34019) + + 2011-09-09: Simon Goldschmidt + * udp.c: fixed bug #34072: UDP broadcast is received from wrong UDP pcb if + udp port matches + + 2011-09-03: Simon Goldschmidt + * tcp_in.c: fixed bug #33952 PUSH flag in incoming packet is lost when packet + is aggregated and sent to application + + 2011-09-01: Simon Goldschmidt + * opt.h: fixed bug #31809 LWIP_EVENT_API in opts.h is inconsistent compared + to other options + + 2011-09-01: Simon Goldschmidt + * tcp_in.c: fixed bug #34111 RST for ACK to listening pcb has wrong seqno + + 2011-08-24: Simon Goldschmidt + * api_msg.c, sockets.c: fixed bug #33956 Wrong error returned when calling + accept() on UDP connections + + 2011-08-24: Simon Goldschmidt + * sockets.h: fixed bug #34057 socklen_t should be a typedef + + 2011-08-24: Simon Goldschmidt + * pbuf.c: fixed bug #34112 Odd check in pbuf_alloced_custom (typo) + + 2011-08-24: Simon Goldschmidt + * dhcp.c: fixed bug #34122 dhcp: hostname can overflow + + 2011-08-24: Simon Goldschmidt + * netif.c: fixed bug #34121 netif_add/netif_set_ipaddr fail on NULL ipaddr + + 2011-08-22: Simon Goldschmidt + * tcp_out.c: fixed bug #33962 TF_FIN not always set after FIN is sent. (This + merely prevents nagle from not transmitting fast after closing.) + + 2011-07-22: Simon Goldschmidt + * api_lib.c, api_msg.c, sockets.c, api.h: fixed bug #31084 (socket API returns + always EMSGSIZE on non-blocking sockets if data size > send buffers) -> now + lwip_send() sends as much as possible for non-blocking sockets + + 2011-07-22: Simon Goldschmidt + * pbuf.c/.h, timers.c: freeing ooseq pbufs when the pbuf pool is empty implemented + for NO_SYS==1: when not using sys_check_timeouts(), call PBUF_CHECK_FREE_OOSEQ() + at regular intervals from main level. + + 2011-07-21: Simon Goldschmidt + * etharp.c: fixed bug #33551 (ARP entries may time out although in use) by + sending an ARP request when an ARP entry is used in the last minute before + it would time out. + + 2011-07-04: Simon Goldschmidt + * sys_arch.txt: Fixed documentation after changing sys arch prototypes for 1.4.0. + + 2011-06-26: Simon Goldschmidt + * tcp.c: fixed bug #31723 (tcp_kill_prio() kills pcbs with the same prio) by + updating its documentation only. + + 2011-06-26: Simon Goldschmidt + * mem.c: fixed bug #33545: With MEM_USE_POOLS==1, mem_malloc can return an + unaligned pointer. + + 2011-06-26: Simon Goldschmidt + * mem.c: fixed bug #33544 "warning in mem.c in lwip 1.4.0 with NO_SYS=1" + + 2011-05-25: Simon Goldschmidt + * tcp.c: fixed bug #33398 (pointless conversion when checking TCP port range) + + + +(STABLE-1.4.0) + + ++ New features: + + 2011-03-27: Simon Goldschmidt + * tcp_impl.h, tcp_in.c, tcp_out.c: Removed 'dataptr' from 'struct tcp_seg' and + calculate it in tcp_zero_window_probe (the only place where it was used). + + 2010-11-21: Simon Goldschmidt + * dhcp.c/.h: Added a function to deallocate the struct dhcp from a netif + (fixes bug #31525). + + 2010-07-12: Simon Goldschmidt (patch by Stephane Lesage) + * ip.c, udp.c/.h, pbuf.h, sockets.c: task #10495: Added support for + IP_MULTICAST_LOOP at socket- and raw-API level. + + 2010-06-16: Simon Goldschmidt + * ip.c: Added an optional define (LWIP_IP_ACCEPT_UDP_PORT) that can allow + link-layer-addressed UDP traffic to be received while a netif is down (just + like DHCP during configuration) + + 2010-05-22: Simon Goldschmidt + * many many files: bug #27352: removed packing from ip_addr_t, the packed + version is now only used in protocol headers. Added global storage for + current src/dest IP address while in input functions. + + 2010-05-16: Simon Goldschmidt + * def.h: task #10391: Add preprocessor-macros for compile-time htonl + calculation (and use them throughout the stack where applicable) + + 2010-05-16: Simon Goldschmidt + * opt.h, memp_std.h, memp.c, ppp_oe.h/.c: PPPoE now uses its own MEMP pool + instead of the heap (moved struct pppoe_softc from ppp_oe.c to ppp_oe.h) + + 2010-05-16: Simon Goldschmidt + * opt.h, memp_std.h, dns.h/.c: DNS_LOCAL_HOSTLIST_IS_DYNAMIC uses its own + MEMP pool instead of the heap + + 2010-05-13: Simon Goldschmidt + * tcp.c, udp.c: task #6995: Implement SO_REUSEADDR (correctly), added + new option SO_REUSE_RXTOALL to pass received UDP broadcast/multicast + packets to more than one pcb. + + 2010-05-02: Simon Goldschmidt + * netbuf.h/.c, sockets.c, api_msg.c: use checksum-on-copy for sending + UDP data for LWIP_NETIF_TX_SINGLE_PBUF==1 + + 2010-04-30: Simon Goldschmidt + * udp.h/.c, pbuf.h/.c: task #6849: added udp_send(_to/_if) functions that + take a precalculated checksum, added pbuf_fill_chksum() to copy data + into a pbuf and at the same time calculating the checksum for that data + + 2010-04-29: Simon Goldschmidt + * ip_addr.h, etharp.h/.c, autoip.c: Create overridable macros for copying + 2-byte-aligned IP addresses and MAC addresses + + 2010-04-28: Patch by Bill Auerbach + * ip.c: Inline generating IP checksum to save a function call + + 2010-04-14: Simon Goldschmidt + * tcpip.h/.c, timers.c: Added an overridable define to get informed when the + tcpip_thread processes messages or timeouts to implement a watchdog. + + 2010-03-28: Simon Goldschmidt + * ip_frag.c: create a new (contiguous) PBUF_RAM for every outgoing + fragment if LWIP_NETIF_TX_SINGLE_PBUF==1 + + 2010-03-27: Simon Goldschmidt + * etharp.c: Speedup TX by moving code from find_entry to etharp_output/ + etharp_query to prevent unnecessary function calls (inspired by + patch #7135). + + 2010-03-20: Simon Goldschmidt + * opt.h, tcpip.c/.h: Added an option to disable tcpip_(un)timeout code + since the linker cannot do this automatically to save space. + + 2010-03-20: Simon Goldschmidt + * opt.h, etharp.c/.h: Added support for static ARP table entries + + 2010-03-14: Simon Goldschmidt + * tcp_impl.h, tcp_out.c, inet_chksum.h/.c: task #6849: Calculate checksum + when creating TCP segments, not when (re-)transmitting them. + + 2010-03-07: Simon Goldschmidt + * sockets.c: bug #28775 (select/event_callback: only check select_cb_list + on change) plus use SYS_LIGHTWEIGHT_PROT to protect the select code. + This should speed up receiving data on sockets as the select code in + event_callback is only executed when select is waiting. + + 2010-03-06: Simon Goldschmidt + * tcp_out.c: task #7013 (Create option to have all packets delivered to + netif->output in one piece): Always copy to try to create single pbufs + in tcp_write. + + 2010-03-06: Simon Goldschmidt + * api.h, api_lib.c, sockets.c: task #10167 (sockets: speed up TCP recv + by not allocating a netbuf): added function netconn_recv_tcp_pbuf() + for tcp netconns to receive pbufs, not netbufs; use that function + for tcp sockets. + + 2010-03-05: Jakob Ole Stoklundsen / Simon Goldschmidt + * opt.h, tcp.h, tcp_impl.h, tcp.c, tcp_in.c, tcp_out.c: task #7040: + Work on tcp_enqueue: Don't waste memory when chaining segments, + added option TCP_OVERSIZE to prevent creating many small pbufs when + calling tcp_write with many small blocks of data. Instead, pbufs are + allocated larger than needed and the space is used for later calls to + tcp_write. + + 2010-02-21: Simon Goldschmidt + * stats.c/.h: Added const char* name to mem- and memp-stats for easier + debugging. + + 2010-02-21: Simon Goldschmidt + * tcp.h (and usages), added tcp_impl.h: Splitted API and internal + implementation of tcp to make API usage cleare to application programmers + + 2010-02-14: Simon Goldschmidt/Stephane Lesage + * ip_addr.h: Improved some defines working on ip addresses, added faster + macro to copy addresses that cannot be NULL + + 2010-02-13: Simon Goldschmidt + * api.h, api_lib.c, api_msg.c, sockets.c: task #7865 (implement non- + blocking send operation) + + 2010-02-12: Simon Goldschmidt + * sockets.c/.h: Added a minimal version of posix fctl() to have a + standardised way to set O_NONBLOCK for nonblocking sockets. + + 2010-02-12: Simon Goldschmidt + * dhcp.c/.h, autoip.c/.h: task #10139 (Prefer statically allocated + memory): added autoip_set_struct() and dhcp_set_struct() to let autoip + and dhcp work with user-allocated structs instead of callin mem_malloc + + 2010-02-12: Simon Goldschmidt/Jeff Barber + * tcp.c/h: patch #6865 (SO_REUSEADDR for TCP): if pcb.so_options has + SOF_REUSEADDR set, allow binding to endpoint in TIME_WAIT + + 2010-02-12: Simon Goldschmidt + * sys layer: task #10139 (Prefer statically allocated memory): converted + mbox and semaphore functions to take pointers to sys_mbox_t/sys_sem_t; + converted sys_mbox_new/sys_sem_new to take pointers and return err_t; + task #7212: Add Mutex concept in sys_arch (define LWIP_COMPAT_MUTEX + to let sys.h use binary semaphores instead of mutexes - as before) + + 2010-02-09: Simon Goldschmidt (Simon Kallweit) + * timers.c/.h: Added function sys_restart_timeouts() from patch #7085 + (Restart system timeout handling) + + 2010-02-09: Simon Goldschmidt + * netif.c/.h, removed loopif.c/.h: task #10153 (Integrate loopif into + netif.c) - loopif does not have to be created by the port any more, + just define LWIP_HAVE_LOOPIF to 1. + + 2010-02-08: Simon Goldschmidt + * inet.h, ip_addr.c/.h: Added reentrant versions of inet_ntoa/ipaddr_ntoa + inet_ntoa_r/ipaddr_ntoa_r + + 2010-02-08: Simon Goldschmidt + * netif.h: Added netif_s/get_igmp_mac_filter() macros + + 2010-02-05: Simon Goldschmidt + * netif.h: Added function-like macros to get/set the hostname on a netif + + 2010-02-04: Simon Goldschmidt + * nearly every file: Replaced struct ip_addr by typedef ip_addr_t to + make changing the actual implementation behind the typedef easier. + + 2010-02-01: Simon Goldschmidt + * opt.h, memp_std.h, dns.h, netdb.c, memp.c: Let netdb use a memp pool + for allocating memory when getaddrinfo() is called. + + 2010-01-31: Simon Goldschmidt + * dhcp.h, dhcp.c: Reworked the code that parses DHCP options: parse + them once instead of parsing for every option. This also removes + the need for mem_malloc from dhcp_recv and makes it possible to + correctly retrieve the BOOTP file. + + 2010-01-30: simon Goldschmidt + * sockets.c: Use SYS_LIGHTWEIGHT_PROT instead of a semaphore to protect + the sockets array. + + 2010-01-29: Simon Goldschmidt (patch by Laura Garrett) + * api.h, api_msg.c, sockets.c: Added except set support in select + (patch #6860) + + 2010-01-29: Simon Goldschmidt (patch by Laura Garrett) + * api.h, sockets.h, err.h, api_lib.c, api_msg.c, sockets.c, err.c: + Add non-blocking support for connect (partly from patch #6860), + plus many cleanups in socket & netconn API. + + 2010-01-27: Simon Goldschmidt + * opt.h, tcp.h, init.c, api_msg.c: Added TCP_SNDQUEUELOWAT corresponding + to TCP_SNDLOWAT and added tcp_sndqueuelen() - this fixes bug #28605 + + 2010-01-26: Simon Goldschmidt + * snmp: Use memp pools for snmp instead of the heap; added 4 new pools. + + 2010-01-14: Simon Goldschmidt + * ppp.c/.h: Fixed bug #27856: PPP: Set netif link- and status-callback + by adding ppp_set_netif_statuscallback()/ppp_set_netif_linkcallback() + + 2010-01-13: Simon Goldschmidt + * mem.c: The heap now may be moved to user-defined memory by defining + LWIP_RAM_HEAP_POINTER as a void pointer to that memory's address + (patch #6966 and bug #26133) + + 2010-01-10: Simon Goldschmidt (Bill Auerbach) + * opt.h, memp.c: patch #6822 (Add option to place memory pools in + separate arrays) + + 2010-01-10: Simon Goldschmidt + * init.c, igmp.c: patch #6463 (IGMP - Adding Random Delay): added define + LWIP_RAND() for lwip-wide randomization (to be defined in cc.h) + + 2009-12-31: Simon Goldschmidt + * tcpip.c, init.c, memp.c, sys.c, memp_std.h, sys.h, tcpip.h + added timers.c/.h: Separated timer implementation from semaphore/mbox + implementation, moved timer implementation to timers.c/.h, timers are + now only called from tcpip_thread or by explicitly checking them. + (TASK#7235) + + 2009-12-27: Simon Goldschmidt + * opt.h, etharp.h/.c, init.c, tcpip.c: Added an additional option + LWIP_ETHERNET to support ethernet without ARP (necessary for pure PPPoE) + + + ++ Bugfixes: + + 2011-04-20: Simon Goldschmidt + * sys_arch.txt: sys_arch_timeouts() is not needed any more. + + 2011-04-13: Simon Goldschmidt + * tcp.c, udp.c: Fixed bug #33048 (Bad range for IP source port numbers) by + using ports in the IANA private/dynamic range (49152 through 65535). + + 2011-03-29: Simon Goldschmidt, patch by Emil Lhungdahl: + * etharp.h/.c: Fixed broken VLAN support. + + 2011-03-27: Simon Goldschmidt + * tcp.c: Fixed bug #32926 (TCP_RMV(&tcp_bound_pcbs) is called on unbound tcp + pcbs) by checking if the pcb was bound (local_port != 0). + + 2011-03-27: Simon Goldschmidt + * ppp.c: Fixed bug #32280 (ppp: a pbuf is freed twice) + + 2011-03-27: Simon Goldschmidt + * sockets.c: Fixed bug #32906: lwip_connect+lwip_send did not work for udp and + raw pcbs with LWIP_TCPIP_CORE_LOCKING==1. + + 2011-03-27: Simon Goldschmidt + * tcp_out.c: Fixed bug #32820 (Outgoing TCP connections created before route + is present never times out) by starting retransmission timer before checking + route. + + 2011-03-22: Simon Goldschmidt + * ppp.c: Fixed bug #32648 (PPP code crashes when terminating a link) by only + calling sio_read_abort() if the file descriptor is valid. + + 2011-03-14: Simon Goldschmidt + * err.h/.c, sockets.c, api_msg.c: fixed bug #31748 (Calling non-blocking connect + more than once can render a socket useless) since it mainly involves changing + "FATAL" classification of error codes: ERR_USE and ERR_ISCONN just aren't fatal. + + 2011-03-13: Simon Goldschmidt + * sockets.c: fixed bug #32769 (ESHUTDOWN is linux-specific) by fixing + err_to_errno_table (ERR_CLSD: ENOTCONN instead of ESHUTDOWN), ERR_ISCONN: + use EALRADY instead of -1 + + 2011-03-13: Simon Goldschmidt + * api_lib.c: netconn_accept: return ERR_ABRT instead of ERR_CLSD if the + connection has been aborted by err_tcp (since this is not a normal closing + procedure). + + 2011-03-13: Simon Goldschmidt + * tcp.c: tcp_bind: return ERR_VAL instead of ERR_ISCONN when trying to bind + with pcb->state != CLOSED + + 2011-02-17: Simon Goldschmidt + * rawapi.txt: Fixed bug #32561 tcp_poll argument definition out-of-order in + documentation + + 2011-02-17: Simon Goldschmidt + * many files: Added missing U/UL modifiers to fix 16-bit-arch portability. + + 2011-01-24: Simon Goldschmidt + * sockets.c: Fixed bug #31741: lwip_select seems to have threading problems + + 2010-12-02: Simon Goldschmidt + * err.h: Fixed ERR_IS_FATAL so that ERR_WOULDBLOCK is not fatal. + + 2010-11-23: Simon Goldschmidt + * api.h, api_lib.c, api_msg.c, sockets.c: netconn.recv_avail is only used for + LWIP_SO_RCVBUF and ioctl/FIONREAD. + + 2010-11-23: Simon Goldschmidt + * etharp.c: Fixed bug #31720: ARP-queueing: RFC 1122 recommends to queue at + least 1 packet -> ARP_QUEUEING==0 now queues the most recent packet. + + 2010-11-23: Simon Goldschmidt + * tcp_in.c: Fixed bug #30577: tcp_input: don't discard ACK-only packets after + refusing 'refused_data' again. + + 2010-11-22: Simon Goldschmidt + * sockets.c: Fixed bug #31590: getsockopt(... SO_ERROR ...) gives EINPROGRESS + after a successful nonblocking connection. + + 2010-11-22: Simon Goldschmidt + * etharp.c: Fixed bug #31722: IP packets sent with an AutoIP source addr + must be sent link-local + + 2010-11-22: Simon Goldschmidt + * timers.c: patch #7329: tcp_timer_needed prototype was ifdef'ed out for + LWIP_TIMERS==0 + + 2010-11-20: Simon Goldschmidt + * sockets.c: Fixed bug #31170: lwip_setsockopt() does not set socket number + + 2010-11-20: Simon Goldschmidt + * sockets.h: Fixed bug #31304: Changed SHUT_RD, SHUT_WR and SHUT_RDWR to + resemble other stacks. + + 2010-11-20: Simon Goldschmidt + * dns.c: Fixed bug #31535: TCP_SND_QUEUELEN must be at least 2 or else + no-copy TCP writes will never succeed. + + 2010-11-20: Simon Goldschmidt + * dns.c: Fixed bug #31701: Error return value from dns_gethostbyname() does + not match documentation: return ERR_ARG instead of ERR_VAL if not + initialized or wrong argument. + + 2010-10-20: Simon Goldschmidt + * sockets.h: Fixed bug #31385: sizeof(struct sockaddr) is 30 but should be 16 + + 2010-10-05: Simon Goldschmidt + * dhcp.c: Once again fixed #30038: DHCP/AutoIP cooperation failed when + replugging the network cable after an AutoIP address was assigned. + + 2010-08-10: Simon Goldschmidt + * tcp.c: Fixed bug #30728: tcp_new_port() did not check listen pcbs + + 2010-08-03: Simon Goldschmidt + * udp.c, raw.c: Don't chain empty pbufs when sending them (fixes bug #30625) + + 2010-08-01: Simon Goldschmidt (patch by Greg Renda) + * ppp.c: Applied patch #7264 (PPP protocols are rejected incorrectly on big + endian architectures) + + 2010-07-28: Simon Goldschmidt + * api_lib.c, api_msg.c, sockets.c, mib2.c: Fixed compilation with TCP or UDP + disabled. + + 2010-07-27: Simon Goldschmidt + * tcp.c: Fixed bug #30565 (tcp_connect() check bound list): that check did no + harm but never did anything + + 2010-07-21: Simon Goldschmidt + * ip.c: Fixed invalid fix for bug #30402 (CHECKSUM_GEN_IP_INLINE does not + add IP options) + + 2010-07-16: Kieran Mansley + * msg_in.c: Fixed SNMP ASN constant defines to not use ! operator + + 2010-07-10: Simon Goldschmidt + * ip.c: Fixed bug #30402: CHECKSUM_GEN_IP_INLINE does not add IP options + + 2010-06-30: Simon Goldschmidt + * api_msg.c: fixed bug #30300 (shutdown parameter was not initialized in + netconn_delete) + + 2010-06-28: Kieran Mansley + * timers.c remove unportable printing of C function pointers + + 2010-06-24: Simon Goldschmidt + * init.c, timers.c/.h, opt.h, memp_std.h: From patch #7221: added flag + NO_SYS_NO_TIMERS to drop timer support for NO_SYS==1 for easier upgrading + + 2010-06-24: Simon Goldschmidt + * api(_lib).c/.h, api_msg.c/.h, sockets.c/.h: Fixed bug #10088: Correctly + implemented shutdown at socket level. + + 2010-06-21: Simon Goldschmidt + * pbuf.c/.h, ip_frag.c/.h, opt.h, memp_std.h: Fixed bug #29361 (ip_frag has + problems with zero-copy DMA MACs) by adding custom pbufs and implementing + custom pbufs that reference other (original) pbufs. Additionally set + IP_FRAG_USES_STATIC_BUF=0 as default to be on the safe side. + + 2010-06-15: Simon Goldschmidt + * dhcp.c: Fixed bug #29970: DHCP endian issue parsing option responses + + 2010-06-14: Simon Goldschmidt + * autoip.c: Fixed bug #30039: AutoIP does not reuse previous addresses + + 2010-06-12: Simon Goldschmidt + * dhcp.c: Fixed bug #30038: dhcp_network_changed doesn't reset AUTOIP coop + state + + 2010-05-17: Simon Goldschmidt + * netdb.c: Correctly NULL-terminate h_addr_list + + 2010-05-16: Simon Goldschmidt + * def.h/.c: changed the semantics of LWIP_PREFIX_BYTEORDER_FUNCS to prevent + "symbol already defined" i.e. when linking to winsock + + 2010-05-05: Simon Goldschmidt + * def.h, timers.c: Fixed bug #29769 (sys_check_timeouts: sys_now() may + overflow) + + 2010-04-21: Simon Goldschmidt + * api_msg.c: Fixed bug #29617 (sometime cause stall on delete listening + connection) + + 2010-03-28: Luca Ceresoli + * ip_addr.c/.h: patch #7143: Add a few missing const qualifiers + + 2010-03-27: Luca Ceresoli + * mib2.c: patch #7130: remove meaningless const qualifiers + + 2010-03-26: Simon Goldschmidt + * tcp_out.c: Make LWIP_NETIF_TX_SINGLE_PBUF work for TCP, too + + 2010-03-26: Simon Goldschmidt + * various files: Fixed compiling with different options disabled (TCP/UDP), + triggered by bug #29345; don't allocate acceptmbox if LWIP_TCP is disabled + + 2010-03-25: Simon Goldschmidt + * sockets.c: Fixed bug #29332: lwip_select() processes readset incorrectly + + 2010-03-25: Simon Goldschmidt + * tcp_in.c, test_tcp_oos.c: Fixed bug #29080: Correctly handle remote side + overrunning our rcv_wnd in ooseq case. + + 2010-03-22: Simon Goldschmidt + * tcp.c: tcp_listen() did not copy the pcb's prio. + + 2010-03-19: Simon Goldschmidt + * snmp_msg.c: Fixed bug #29256: SNMP Trap address was not correctly set + + 2010-03-14: Simon Goldschmidt + * opt.h, etharp.h: Fixed bug #29148 (Incorrect PBUF_POOL_BUFSIZE for ports + where ETH_PAD_SIZE > 0) by moving definition of ETH_PAD_SIZE to opt.h + and basing PBUF_LINK_HLEN on it. + + 2010-03-08: Simon Goldschmidt + * netif.c, ipv4/ip.c: task #10241 (AutoIP: don't break existing connections + when assiging routable address): when checking incoming packets and + aborting existing connection on address change, filter out link-local + addresses. + + 2010-03-06: Simon Goldschmidt + * sockets.c: Fixed LWIP_NETIF_TX_SINGLE_PBUF for LWIP_TCPIP_CORE_LOCKING + + 2010-03-06: Simon Goldschmidt + * ipv4/ip.c: Don't try to forward link-local addresses + + 2010-03-06: Simon Goldschmidt + * etharp.c: Fixed bug #29087: etharp: don't send packets for LinkLocal- + addresses to gw + + 2010-03-05: Simon Goldschmidt + * dhcp.c: Fixed bug #29072: Correctly set ciaddr based on message-type + and state. + + 2010-03-05: Simon Goldschmidt + * api_msg.c: Correctly set TCP_WRITE_FLAG_MORE when netconn_write is split + into multiple calls to tcp_write. + + 2010-02-21: Simon Goldschmidt + * opt.h, mem.h, dns.c: task #10140: Remove DNS_USES_STATIC_BUF (keep + the implementation of DNS_USES_STATIC_BUF==1) + + 2010-02-20: Simon Goldschmidt + * tcp.h, tcp.c, tcp_in.c, tcp_out.c: Task #10088: Correctly implement + close() vs. shutdown(). Now the application does not get any more + recv callbacks after calling tcp_close(). Added tcp_shutdown(). + + 2010-02-19: Simon Goldschmidt + * mem.c/.h, pbuf.c: Renamed mem_realloc() to mem_trim() to prevent + confusion with realloc() + + 2010-02-15: Simon Goldschmidt/Stephane Lesage + * netif.c/.h: Link status does not depend on LWIP_NETIF_LINK_CALLBACK + (fixes bug #28899) + + 2010-02-14: Simon Goldschmidt + * netif.c: Fixed bug #28877 (Duplicate ARP gratuitous packet with + LWIP_NETIF_LINK_CALLBACK set on) by only sending if both link- and + admin-status of a netif are up + + 2010-02-14: Simon Goldschmidt + * opt.h: Disable ETHARP_TRUST_IP_MAC by default since it slows down packet + reception and is not really necessary + + 2010-02-14: Simon Goldschmidt + * etharp.c/.h: Fixed ARP input processing: only add a new entry if a + request was directed as us (RFC 826, Packet Reception), otherwise + only update existing entries; internalized some functions + + 2010-02-14: Simon Goldschmidt + * netif.h, etharp.c, tcpip.c: Fixed bug #28183 (ARP and TCP/IP cannot be + disabled on netif used for PPPoE) by adding a new netif flag + (NETIF_FLAG_ETHERNET) that tells the stack the device is an ethernet + device but prevents usage of ARP (so that ethernet_input can be used + for PPPoE). + + 2010-02-12: Simon Goldschmidt + * netif.c: netif_set_link_up/down: only do something if the link state + actually changes + + 2010-02-12: Simon Goldschmidt/Stephane Lesage + * api_msg.c: Fixed bug #28865 (Cannot close socket/netconn in non-blocking + connect) + + 2010-02-12: Simon Goldschmidt + * mem.h: Fixed bug #28866 (mem_realloc function defined in mem.h) + + 2010-02-09: Simon Goldschmidt + * api_lib.c, api_msg.c, sockets.c, api.h, api_msg.h: Fixed bug #22110 + (recv() makes receive window update for data that wasn't received by + application) + + 2010-02-09: Simon Goldschmidt/Stephane Lesage + * sockets.c: Fixed bug #28853 (lwip_recvfrom() returns 0 on receive time-out + or any netconn_recv() error) + + 2010-02-09: Simon Goldschmidt + * ppp.c: task #10154 (PPP: Update snmp in/out counters for tx/rx packets) + + 2010-02-09: Simon Goldschmidt + * netif.c: For loopback packets, adjust the stats- and snmp-counters + for the loopback netif. + + 2010-02-08: Simon Goldschmidt + * igmp.c/.h, ip.h: Moved most defines from igmp.h to igmp.c for clarity + since they are not used anywhere else. + + 2010-02-08: Simon Goldschmidt (Stéphane Lesage) + * igmp.c, igmp.h, stats.c, stats.h: Improved IGMP stats + (patch from bug #28798) + + 2010-02-08: Simon Goldschmidt (Stéphane Lesage) + * igmp.c: Fixed bug #28798 (Error in "Max Response Time" processing) and + another bug when LWIP_RAND() returns zero. + + 2010-02-04: Simon Goldschmidt + * nearly every file: Use macros defined in ip_addr.h (some of them new) + to work with IP addresses (preparation for bug #27352 - Change ip_addr + from struct to typedef (u32_t) - and better code). + + 2010-01-31: Simon Goldschmidt + * netif.c: Don't call the link-callback from netif_set_up/down() since + this invalidly retriggers DHCP. + + 2010-01-29: Simon Goldschmidt + * ip_addr.h, inet.h, def.h, inet.c, def.c, more: Cleanly separate the + portability file inet.h and its contents from the stack: moved htonX- + functions to def.h (and the new def.c - they are not ipv4 dependent), + let inet.h depend on ip_addr.h and not the other way round. + This fixes bug #28732. + + 2010-01-28: Kieran Mansley + * tcp.c: Ensure ssthresh >= 2*MSS + + 2010-01-27: Simon Goldschmidt + * tcp.h, tcp.c, tcp_in.c: Fixed bug #27871: Calling tcp_abort() in recv + callback can lead to accessing unallocated memory. As a consequence, + ERR_ABRT means the application has called tcp_abort()! + + 2010-01-25: Simon Goldschmidt + * snmp_structs.h, msg_in.c: Partly fixed bug #22070 (MIB_OBJECT_WRITE_ONLY + not implemented in SNMP): write-only or not-accessible are still + returned by getnext (though not by get) + + 2010-01-24: Simon Goldschmidt + * snmp: Renamed the private mib node from 'private' to 'mib_private' to + not use reserved C/C++ keywords + + 2010-01-23: Simon Goldschmidt + * sockets.c: Fixed bug #28716: select() returns 0 after waiting for less + than 1 ms + + 2010-01-21: Simon Goldschmidt + * tcp.c, api_msg.c: Fixed bug #28651 (tcp_connect: no callbacks called + if tcp_enqueue fails) both in raw- and netconn-API + + 2010-01-19: Simon Goldschmidt + * api_msg.c: Fixed bug #27316: netconn: Possible deadlock in err_tcp + + 2010-01-18: Iordan Neshev/Simon Goldschmidt + * src/netif/ppp: reorganised PPP sourcecode to 2.3.11 including some + bugfix backports from 2.4.x. + + 2010-01-18: Simon Goldschmidt + * mem.c: Fixed bug #28679: mem_realloc calculates mem_stats wrong + + 2010-01-17: Simon Goldschmidt + * api_lib.c, api_msg.c, (api_msg.h, api.h, sockets.c, tcpip.c): + task #10102: "netconn: clean up conn->err threading issues" by adding + error return value to struct api_msg_msg + + 2010-01-17: Simon Goldschmidt + * api.h, api_lib.c, sockets.c: Changed netconn_recv() and netconn_accept() + to return err_t (bugs #27709 and #28087) + + 2010-01-14: Simon Goldschmidt + * ...: Use typedef for function prototypes throughout the stack. + + 2010-01-13: Simon Goldschmidt + * api_msg.h/.c, api_lib.c: Fixed bug #26672 (close connection when receive + window = 0) by correctly draining recvmbox/acceptmbox + + 2010-01-11: Simon Goldschmidt + * pap.c: Fixed bug #13315 (PPP PAP authentication can result in + erroneous callbacks) by copying the code from recent pppd + + 2010-01-10: Simon Goldschmidt + * raw.c: Fixed bug #28506 (raw_bind should filter received packets) + + 2010-01-10: Simon Goldschmidt + * tcp.h/.c: bug #28127 (remove call to tcp_output() from tcp_ack(_now)()) + + 2010-01-08: Simon Goldschmidt + * sockets.c: Fixed bug #28519 (lwip_recvfrom bug with len > 65535) + + 2010-01-08: Simon Goldschmidt + * dns.c: Copy hostname for DNS_LOCAL_HOSTLIST_IS_DYNAMIC==1 since string + passed to dns_local_addhost() might be volatile + + 2010-01-07: Simon Goldschmidt + * timers.c, tcp.h: Call tcp_timer_needed() with NO_SYS==1, too + + 2010-01-06: Simon Goldschmidt + * netdb.h: Fixed bug #28496: missing include guards in netdb.h + + 2009-12-31: Simon Goldschmidt + * many ppp files: Reorganised PPP source code from ucip structure to pppd + structure to easily compare our code against the pppd code (around v2.3.1) + + 2009-12-27: Simon Goldschmidt + * tcp_in.c: Another fix for bug #28241 (ooseq processing) and adapted + unit test + + +(STABLE-1.3.2) + + ++ New features: + + 2009-10-27 Simon Goldschmidt/Stephan Lesage + * netifapi.c/.h: Added netifapi_netif_set_addr() + + 2009-10-07 Simon Goldschmidt/Fabian Koch + * api_msg.c, netbuf.c/.h, opt.h: patch #6888: Patch for UDP Netbufs to + support dest-addr and dest-port (optional: LWIP_NETBUF_RECVINFO) + + 2009-08-26 Simon Goldschmidt/Simon Kallweit + * slipif.c/.h: bug #26397: SLIP polling support + + 2009-08-25 Simon Goldschmidt + * opt.h, etharp.h/.c: task #9033: Support IEEE 802.1q tagged frame (VLAN), + New configuration options ETHARP_SUPPORT_VLAN and ETHARP_VLAN_CHECK. + + 2009-08-25 Simon Goldschmidt + * ip_addr.h, netdb.c: patch #6900: added define ip_ntoa(struct ip_addr*) + + 2009-08-24 Jakob Stoklund Olesen + * autoip.c, dhcp.c, netif.c: patch #6725: Teach AutoIP and DHCP to respond + to netif_set_link_up(). + + 2009-08-23 Simon Goldschmidt + * tcp.h/.c: Added function tcp_debug_state_str() to convert a tcp state + to a human-readable string. + + ++ Bugfixes: + + 2009-12-24: Kieran Mansley + * tcp_in.c Apply patches from Oleg Tyshev to improve OOS processing + (BUG#28241) + + 2009-12-06: Simon Goldschmidt + * ppp.h/.c: Fixed bug #27079 (Yet another leak in PPP): outpacket_buf can + be statically allocated (like in ucip) + + 2009-12-04: Simon Goldschmidt (patch by Ioardan Neshev) + * pap.c: patch #6969: PPP: missing PAP authentication UNTIMEOUT + + 2009-12-03: Simon Goldschmidt + * tcp.h, tcp_in.c, tcp_out.c: Fixed bug #28106: dup ack for fast retransmit + could have non-zero length + + 2009-12-02: Simon Goldschmidt + * tcp_in.c: Fixed bug #27904: TCP sends too many ACKs: delay resetting + tcp_input_pcb until after calling the pcb's callbacks + + 2009-11-29: Simon Goldschmidt + * tcp_in.c: Fixed bug #28054: Two segments with FIN flag on the out-of- + sequence queue, also fixed PBUF_POOL leak in the out-of-sequence code + + 2009-11-29: Simon Goldschmidt + * pbuf.c: Fixed bug #28064: pbuf_alloc(PBUF_POOL) is not thread-safe by + queueing a call into tcpip_thread to free ooseq-bufs if the pool is empty + + 2009-11-26: Simon Goldschmidt + * tcp.h: Fixed bug #28098: Nagle can prevent fast retransmit from sending + segment + + 2009-11-26: Simon Goldschmidt + * tcp.h, sockets.c: Fixed bug #28099: API required to disable Nagle + algorithm at PCB level + + 2009-11-22: Simon Goldschmidt + * tcp_out.c: Fixed bug #27905: FIN isn't combined with data on unsent + + 2009-11-22: Simon Goldschmidt (suggested by Bill Auerbach) + * tcp.c: tcp_alloc: prevent increasing stats.err for MEMP_TCP_PCB when + reusing time-wait pcb + + 2009-11-20: Simon Goldschmidt (patch by Albert Bartel) + * sockets.c: Fixed bug #28062: Data received directly after accepting + does not wake up select + + 2009-11-11: Simon Goldschmidt + * netdb.h: Fixed bug #27994: incorrect define for freeaddrinfo(addrinfo) + + 2009-10-30: Simon Goldschmidt + * opt.h: Increased default value for TCP_MSS to 536, updated default + value for TCP_WND to 4*TCP_MSS to keep delayed ACK working. + + 2009-10-28: Kieran Mansley + * tcp_in.c, tcp_out.c, tcp.h: re-work the fast retransmission code + to follow algorithm from TCP/IP Illustrated + + 2009-10-27: Kieran Mansley + * tcp_in.c: fix BUG#27445: grow cwnd with every duplicate ACK + + 2009-10-25: Simon Goldschmidt + * tcp.h: bug-fix in the TCP_EVENT_RECV macro (has to call tcp_recved if + pcb->recv is NULL to keep rcv_wnd correct) + + 2009-10-25: Simon Goldschmidt + * tcp_in.c: Fixed bug #26251: RST process in TIME_WAIT TCP state + + 2009-10-23: Simon Goldschmidt (David Empson) + * tcp.c: Fixed bug #27783: Silly window avoidance for small window sizes + + 2009-10-21: Simon Goldschmidt + * tcp_in.c: Fixed bug #27215: TCP sent() callback gives leading and + trailing 1 byte len (SYN/FIN) + + 2009-10-21: Simon Goldschmidt + * tcp_out.c: Fixed bug #27315: zero window probe and FIN + + 2009-10-19: Simon Goldschmidt + * dhcp.c/.h: Minor code simplification (don't store received pbuf, change + conditional code to assert where applicable), check pbuf length before + testing for valid reply + + 2009-10-19: Simon Goldschmidt + * dhcp.c: Removed most calls to udp_connect since they aren't necessary + when using udp_sendto_if() - always stay connected to IP_ADDR_ANY. + + 2009-10-16: Simon Goldschmidt + * ip.c: Fixed bug #27390: Source IP check in ip_input() causes it to drop + valid DHCP packets -> allow 0.0.0.0 as source address when LWIP_DHCP is + enabled + + 2009-10-15: Simon Goldschmidt (Oleg Tyshev) + * tcp_in.c: Fixed bug #27329: dupacks by unidirectional data transmit + + 2009-10-15: Simon Goldschmidt + * api_lib.c: Fixed bug #27709: conn->err race condition on netconn_recv() + timeout + + 2009-10-15: Simon Goldschmidt + * autoip.c: Fixed bug #27704: autoip starts with wrong address + LWIP_AUTOIP_CREATE_SEED_ADDR() returned address in host byte order instead + of network byte order + + 2009-10-11 Simon Goldschmidt (Jörg Kesten) + * tcp_out.c: Fixed bug #27504: tcp_enqueue wrongly concatenates segments + which are not consecutive when retransmitting unacked segments + + 2009-10-09 Simon Goldschmidt + * opt.h: Fixed default values of some stats to only be enabled if used + Fixes bug #27338: sys_stats is defined when NO_SYS = 1 + + 2009-08-30 Simon Goldschmidt + * ip.c: Fixed bug bug #27345: "ip_frag() does not use the LWIP_NETIF_LOOPBACK + function" by checking for loopback before calling ip_frag + + 2009-08-25 Simon Goldschmidt + * dhcp.c: fixed invalid dependency to etharp_query if DHCP_DOES_ARP_CHECK==0 + + 2009-08-23 Simon Goldschmidt + * ppp.c: bug #27078: Possible memory leak in pppInit() + + 2009-08-23 Simon Goldschmidt + * netdb.c, dns.c: bug #26657: DNS, if host name is "localhost", result + is error. + + 2009-08-23 Simon Goldschmidt + * opt.h, init.c: bug #26649: TCP fails when TCP_MSS > TCP_SND_BUF + Fixed wrong parenthesis, added check in init.c + + 2009-08-23 Simon Goldschmidt + * ppp.c: bug #27266: wait-state debug message in pppMain occurs every ms + + 2009-08-23 Simon Goldschmidt + * many ppp files: bug #27267: Added include to string.h where needed + + 2009-08-23 Simon Goldschmidt + * tcp.h: patch #6843: tcp.h macro optimization patch (for little endian) + + +(STABLE-1.3.1) + + ++ New features: + + 2009-05-10 Simon Goldschmidt + * opt.h, sockets.c, pbuf.c, netbuf.h, pbuf.h: task #7013: Added option + LWIP_NETIF_TX_SINGLE_PBUF to try to create transmit packets from only + one pbuf to help MACs that don't support scatter-gather DMA. + + 2009-05-09 Simon Goldschmidt + * icmp.h, icmp.c: Shrinked ICMP code, added option to NOT check icoming + ECHO pbuf for size (just use it): LWIP_ICMP_ECHO_CHECK_INPUT_PBUF_LEN + + 2009-05-05 Simon Goldschmidt, Jakob Stoklund Olesen + * ip.h, ip.c: Added ip_current_netif() & ip_current_header() to receive + extended info about the currently received packet. + + 2009-04-27 Simon Goldschmidt + * sys.h: Made SYS_LIGHTWEIGHT_PROT and sys_now() work with NO_SYS=1 + + 2009-04-25 Simon Goldschmidt + * mem.c, opt.h: Added option MEM_USE_POOLS_TRY_BIGGER_POOL to try the next + bigger malloc pool if one is empty (only usable with MEM_USE_POOLS). + + 2009-04-21 Simon Goldschmidt + * dns.c, init.c, dns.h, opt.h: task #7507, patch #6786: DNS supports static + hosts table. New configuration options DNS_LOCAL_HOSTLIST and + DNS_LOCAL_HOSTLIST_IS_DYNAMIC. Also, DNS_LOOKUP_LOCAL_EXTERN() can be defined + as an external function for lookup. + + 2009-04-15 Simon Goldschmidt + * dhcp.c: patch #6763: Global DHCP XID can be redefined to something more unique + + 2009-03-31 Kieran Mansley + * tcp.c, tcp_out.c, tcp_in.c, sys.h, tcp.h, opts.h: add support for + TCP timestamp options, off by default. Rework tcp_enqueue() to + take option flags rather than specified option data + + 2009-02-18 Simon Goldschmidt + * cc.h: Added printf formatter for size_t: SZT_F + + 2009-02-16 Simon Goldschmidt (patch by Rishi Khan) + * icmp.c, opt.h: patch #6539: (configurable) response to broadcast- and multicast + pings + + 2009-02-12 Simon Goldschmidt + * init.h: Added LWIP_VERSION to get the current version of the stack + + 2009-02-11 Simon Goldschmidt (suggested by Gottfried Spitaler) + * opt.h, memp.h/.c: added MEMP_MEM_MALLOC to use mem_malloc/mem_free instead + of the pool allocator (can save code size with MEM_LIBC_MALLOC if libc-malloc + is otherwise used) + + 2009-01-28 Jonathan Larmour (suggested by Bill Bauerbach) + * ipv4/inet_chksum.c, ipv4/lwip/inet_chksum.h: inet_chksum_pseudo_partial() + is only used by UDPLITE at present, so conditionalise it. + + 2008-12-03 Simon Goldschmidt (base on patch from Luca Ceresoli) + * autoip.c: checked in (slightly modified) patch #6683: Customizable AUTOIP + "seed" address. This should reduce AUTOIP conflicts if + LWIP_AUTOIP_CREATE_SEED_ADDR is overridden. + + 2008-10-02 Jonathan Larmour and Rishi Khan + * sockets.c (lwip_accept): Return EWOULDBLOCK if would block on non-blocking + socket. + + 2008-06-30 Simon Goldschmidt + * mem.c, opt.h, stats.h: fixed bug #21433: Calling mem_free/pbuf_free from + interrupt context isn't safe: LWIP_ALLOW_MEM_FREE_FROM_OTHER_CONTEXT allows + mem_free to run between mem_malloc iterations. Added illegal counter for + mem stats. + + 2008-06-27 Simon Goldschmidt + * stats.h/.c, some other files: patch #6483: stats module improvement: + Added defines to display each module's statistic individually, added stats + defines for MEM, MEMP and SYS modules, removed (unused) rexmit counter. + + 2008-06-17 Simon Goldschmidt + * err.h: patch #6459: Made err_t overridable to use a more efficient type + (define LWIP_ERR_T in cc.h) + + 2008-06-17 Simon Goldschmidt + * slipif.c: patch #6480: Added a configuration option for slipif for symmetry + to loopif + + 2008-06-17 Simon Goldschmidt (patch by Luca Ceresoli) + * netif.c, loopif.c, ip.c, netif.h, loopif.h, opt.h: Checked in slightly + modified version of patch # 6370: Moved loopif code to netif.c so that + loopback traffic is supported on all netifs (all local IPs). + Added option to limit loopback packets for each netifs. + + + ++ Bugfixes: + 2009-08-12 Kieran Mansley + * tcp_in.c, tcp.c: Fix bug #27209: handle trimming of segments when + out of window or out of order properly + + 2009-08-12 Kieran Mansley + * tcp_in.c: Fix bug #27199: use snd_wl2 instead of snd_wl1 + + 2009-07-28 Simon Goldschmidt + * mem.h: Fixed bug #27105: "realloc() cannot replace mem_realloc()"s + + 2009-07-27 Kieran Mansley + * api.h api_msg.h netdb.h sockets.h: add missing #include directives + + 2009-07-09 Kieran Mansley + * api_msg.c, sockets.c, api.h: BUG23240 use signed counters for + recv_avail and don't increment counters until message successfully + sent to mbox + + 2009-06-25 Kieran Mansley + * api_msg.c api.h: BUG26722: initialise netconn write variables + in netconn_alloc + + 2009-06-25 Kieran Mansley + * tcp.h: BUG26879: set ret value in TCP_EVENT macros when function is not set + + 2009-06-25 Kieran Mansley + * tcp.c, tcp_in.c, tcp_out.c, tcp.h: BUG26301 and BUG26267: correct + simultaneous close behaviour, and make snd_nxt have the same meaning + as in the RFCs. + + 2009-05-12 Simon Goldschmidt + * etharp.h, etharp.c, netif.c: fixed bug #26507: "Gratuitous ARP depends on + arp_table / uses etharp_query" by adding etharp_gratuitous() + + 2009-05-12 Simon Goldschmidt + * ip.h, ip.c, igmp.c: bug #26487: Added ip_output_if_opt that can add IP options + to the IP header (used by igmp_ip_output_if) + + 2009-05-06 Simon Goldschmidt + * inet_chksum.c: On little endian architectures, use LWIP_PLATFORM_HTONS (if + defined) for SWAP_BYTES_IN_WORD to speed up checksumming. + + 2009-05-05 Simon Goldschmidt + * sockets.c: bug #26405: Prematurely released semaphore causes lwip_select() + to crash + + 2009-05-04 Simon Goldschmidt + * init.c: snmp was not initialized in lwip_init() + + 2009-05-04 Frédéric Bernon + * dhcp.c, netbios.c: Changes if IP_SOF_BROADCAST is enabled. + + 2009-05-03 Simon Goldschmidt + * tcp.h: bug #26349: Nagle algorithm doesn't send although segment is full + (and unsent->next == NULL) + + 2009-05-02 Simon Goldschmidt + * tcpip.h, tcpip.c: fixed tcpip_untimeout (does not need the time, broken after + 1.3.0 in CVS only) - fixes compilation of ppp_oe.c + + 2009-05-02 Simon Goldschmidt + * msg_in.c: fixed bug #25636: SNMPSET value is ignored for integer fields + + 2009-05-01 Simon Goldschmidt + * pap.c: bug #21680: PPP upap_rauthnak() drops legal NAK packets + + 2009-05-01 Simon Goldschmidt + * ppp.c: bug #24228: Memory corruption with PPP and DHCP + + 2009-04-29 Frédéric Bernon + * raw.c, udp.c, init.c, opt.h, ip.h, sockets.h: bug #26309: Implement the + SO(F)_BROADCAST filter for all API layers. Avoid the unindented reception + of broadcast packets even when this option wasn't set. Port maintainers + which want to enable this filter have to set IP_SOF_BROADCAST=1 in opt.h. + If you want this option also filter broadcast on recv operations, you also + have to set IP_SOF_BROADCAST_RECV=1 in opt.h. + + 2009-04-28 Simon Goldschmidt, Jakob Stoklund Olesen + * dhcp.c: patch #6721, bugs #25575, #25576: Some small fixes to DHCP and + DHCP/AUTOIP cooperation + + 2009-04-25 Simon Goldschmidt, Oleg Tyshev + * tcp_out.c: bug #24212: Deadlocked tcp_retransmit due to exceeded pcb->cwnd + Fixed by sorting the unsent and unacked queues (segments are inserted at the + right place in tcp_output and tcp_rexmit). + + 2009-04-25 Simon Goldschmidt + * memp.c, mem.c, memp.h, mem_std.h: bug #26213 "Problem with memory allocation + when debugging": memp_sizes contained the wrong sizes (including sanity + regions); memp pools for MEM_USE_POOLS were too small + + 2009-04-24 Simon Goldschmidt, Frédéric Bernon + * inet.c: patch #6765: Fix a small problem with the last changes (incorrect + behavior, with with ip address string not ended by a '\0', a space or a + end of line) + + 2009-04-19 Simon Goldschmidt + * rawapi.txt: Fixed bug #26069: Corrected documentation: if tcp_connect fails, + pcb->err is called, not pcb->connected (with an error code). + + 2009-04-19 Simon Goldschmidt + * tcp_out.c: Fixed bug #26236: "TCP options (timestamp) don't work with + no-copy-tcpwrite": deallocate option data, only concat segments with same flags + + 2009-04-19 Simon Goldschmidt + * tcp_out.c: Fixed bug #25094: "Zero-length pbuf" (options are now allocated + in the header pbuf, not the data pbuf) + + 2009-04-18 Simon Goldschmidt + * api_msg.c: fixed bug #25695: Segmentation fault in do_writemore() + + 2009-04-15 Simon Goldschmidt + * sockets.c: tried to fix bug #23559: lwip_recvfrom problem with tcp + + 2009-04-15 Simon Goldschmidt + * dhcp.c: task #9192: mem_free of dhcp->options_in and dhcp->msg_in + + 2009-04-15 Simon Goldschmidt + * ip.c, ip6.c, tcp_out.c, ip.h: patch #6808: Add a utility function + ip_hinted_output() (for smaller code mainly) + + 2009-04-15 Simon Goldschmidt + * inet.c: patch #6765: Supporting new line characters in inet_aton() + + 2009-04-15 Simon Goldschmidt + * dhcp.c: patch #6764: DHCP rebind and renew did not send hostnam option; + Converted constant OPTION_MAX_MSG_SIZE to netif->mtu, check if netif->mtu + is big enough in dhcp_start + + 2009-04-15 Simon Goldschmidt + * netbuf.c: bug #26027: netbuf_chain resulted in pbuf memory leak + + 2009-04-15 Simon Goldschmidt + * sockets.c, ppp.c: bug #25763: corrected 4 occurrences of SMEMCPY to MEMCPY + + 2009-04-15 Simon Goldschmidt + * sockets.c: bug #26121: set_errno can be overridden + + 2009-04-09 Kieran Mansley (patch from Luca Ceresoli ) + * init.c, opt.h: Patch#6774 TCP_QUEUE_OOSEQ breaks compilation when + LWIP_TCP==0 + + 2009-04-09 Kieran Mansley (patch from Roy Lee ) + * tcp.h: Patch#6802 Add do-while-clauses to those function like + macros in tcp.h + + 2009-03-31 Kieran Mansley + * tcp.c, tcp_in.c, tcp_out.c, tcp.h, opt.h: Rework the way window + updates are calculated and sent (BUG20515) + + * tcp_in.c: cope with SYN packets received during established states, + and retransmission of initial SYN. + + * tcp_out.c: set push bit correctly when tcp segments are merged + + 2009-03-27 Kieran Mansley + * tcp_out.c set window correctly on probes (correcting change made + yesterday) + + 2009-03-26 Kieran Mansley + * tcp.c, tcp_in.c, tcp.h: add tcp_abandon() to cope with dropping + connections where no reset required (bug #25622) + + * tcp_out.c: set TCP_ACK flag on keepalive and zero window probes + (bug #20779) + + 2009-02-18 Simon Goldschmidt (Jonathan Larmour and Bill Auerbach) + * ip_frag.c: patch #6528: the buffer used for IP_FRAG_USES_STATIC_BUF could be + too small depending on MEM_ALIGNMENT + + 2009-02-16 Simon Goldschmidt + * sockets.h/.c, api_*.h/.c: fixed arguments of socket functions to match the standard; + converted size argument of netconn_write to 'size_t' + + 2009-02-16 Simon Goldschmidt + * tcp.h, tcp.c: fixed bug #24440: TCP connection close problem on 64-bit host + by moving accept callback function pointer to TCP_PCB_COMMON + + 2009-02-12 Simon Goldschmidt + * dhcp.c: fixed bug #25345 (DHCPDECLINE is sent with "Maximum message size" + option) + + 2009-02-11 Simon Goldschmidt + * dhcp.c: fixed bug #24480 (releasing old udp_pdb and pbuf in dhcp_start) + + 2009-02-11 Simon Goldschmidt + * opt.h, api_msg.c: added configurable default valud for netconn->recv_bufsize: + RECV_BUFSIZE_DEFAULT (fixes bug #23726: pbuf pool exhaustion on slow recv()) + + 2009-02-10 Simon Goldschmidt + * tcp.c: fixed bug #25467: Listen backlog is not reset on timeout in SYN_RCVD: + Accepts_pending is decrease on a corresponding listen pcb when a connection + in state SYN_RCVD is close. + + 2009-01-28 Jonathan Larmour + * pbuf.c: reclaim pbufs from TCP out-of-sequence segments if we run + out of pool pbufs. + + 2008-12-19 Simon Goldschmidt + * many files: patch #6699: fixed some warnings on platform where sizeof(int) == 2 + + 2008-12-10 Tamas Somogyi, Frédéric Bernon + * sockets.c: fixed bug #25051: lwip_recvfrom problem with udp: fromaddr and + port uses deleted netbuf. + + 2008-10-18 Simon Goldschmidt + * tcp_in.c: fixed bug ##24596: Vulnerability on faulty TCP options length + in tcp_parseopt + + 2008-10-15 Simon Goldschmidt + * ip_frag.c: fixed bug #24517: IP reassembly crashes on unaligned IP headers + by packing the struct ip_reass_helper. + + 2008-10-03 David Woodhouse, Jonathan Larmour + * etharp.c (etharp_arp_input): Fix type aliasing problem copying ip address. + + 2008-10-02 Jonathan Larmour + * dns.c: Hard-code structure sizes, to avoid issues on some compilers where + padding is included. + + 2008-09-30 Jonathan Larmour + * sockets.c (lwip_accept): check addr isn't NULL. If it's valid, do an + assertion check that addrlen isn't NULL. + + 2008-09-30 Jonathan Larmour + * tcp.c: Fix bug #24227, wrong error message in tcp_bind. + + 2008-08-26 Simon Goldschmidt + * inet.h, ip_addr.h: fixed bug #24132: Cross-dependency between ip_addr.h and + inet.h -> moved declaration of struct in_addr from ip_addr.h to inet.h + + 2008-08-14 Simon Goldschmidt + * api_msg.c: fixed bug #23847: do_close_internal references freed memory (when + tcp_close returns != ERR_OK) + + 2008-07-08 Frédéric Bernon + * stats.h: Fix some build bugs introduced with patch #6483 (missing some parameters + in macros, mainly if MEM_STATS=0 and MEMP_STATS=0). + + 2008-06-24 Jonathan Larmour + * tcp_in.c: Fix for bug #23693 as suggested by Art R. Ensure cseg is unused + if tcp_seg_copy fails. + + 2008-06-17 Simon Goldschmidt + * inet_chksum.c: Checked in some ideas of patch #6460 (loop optimizations) + and created defines for swapping bytes and folding u32 to u16. + + 2008-05-30 Kieran Mansley + * tcp_in.c Remove redundant "if" statement, and use real rcv_wnd + rather than rcv_ann_wnd when deciding if packets are in-window. + Contributed by + + 2008-05-30 Kieran Mansley + * mem.h: Fix BUG#23254. Change macro definition of mem_* to allow + passing as function pointers when MEM_LIBC_MALLOC is defined. + + 2008-05-09 Jonathan Larmour + * err.h, err.c, sockets.c: Fix bug #23119: Reorder timeout error code to + stop it being treated as a fatal error. + + 2008-04-15 Simon Goldschmidt + * dhcp.c: fixed bug #22804: dhcp_stop doesn't clear NETIF_FLAG_DHCP + (flag now cleared) + + 2008-03-27 Simon Goldschmidt + * mem.c, tcpip.c, tcpip.h, opt.h: fixed bug #21433 (Calling mem_free/pbuf_free + from interrupt context isn't safe): set LWIP_USE_HEAP_FROM_INTERRUPT to 1 + in lwipopts.h or use pbuf_free_callback(p)/mem_free_callback(m) to free pbufs + or heap memory from interrupt context + + 2008-03-26 Simon Goldschmidt + * tcp_in.c, tcp.c: fixed bug #22249: division by zero could occur if a remote + host sent a zero mss as TCP option. + + +(STABLE-1.3.0) + + ++ New features: + + 2008-03-10 Jonathan Larmour + * inet_chksum.c: Allow choice of one of the sample algorithms to be + made from lwipopts.h. Fix comment on how to override LWIP_CHKSUM. + + 2008-01-22 Frédéric Bernon + * tcp.c, tcp_in.c, tcp.h, opt.h: Rename LWIP_CALCULATE_EFF_SEND_MSS in + TCP_CALCULATE_EFF_SEND_MSS to have coherent TCP options names. + + 2008-01-14 Frédéric Bernon + * rawapi.txt, api_msg.c, tcp.c, tcp_in.c, tcp.h: changes for task #7675 "Enable + to refuse data on a TCP_EVENT_RECV call". Important, behavior changes for the + tcp_recv callback (see rawapi.txt). + + 2008-01-14 Frédéric Bernon, Marc Chaland + * ip.c: Integrate patch #6369" ip_input : checking before realloc". + + 2008-01-12 Frédéric Bernon + * tcpip.h, tcpip.c, api.h, api_lib.c, api_msg.c, sockets.c: replace the field + netconn::sem per netconn::op_completed like suggested for the task #7490 + "Add return value to sys_mbox_post". + + 2008-01-12 Frédéric Bernon + * api_msg.c, opt.h: replace DEFAULT_RECVMBOX_SIZE per DEFAULT_TCP_RECVMBOX_SIZE, + DEFAULT_UDP_RECVMBOX_SIZE and DEFAULT_RAW_RECVMBOX_SIZE (to optimize queues + sizes), like suggested for the task #7490 "Add return value to sys_mbox_post". + + 2008-01-10 Frédéric Bernon + * tcpip.h, tcpip.c: add tcpip_callback_with_block function for the task #7490 + "Add return value to sys_mbox_post". tcpip_callback is always defined as + "blocking" ("block" parameter = 1). + + 2008-01-10 Frédéric Bernon + * tcpip.h, tcpip.c, api.h, api_lib.c, api_msg.c, sockets.c: replace the field + netconn::mbox (sys_mbox_t) per netconn::sem (sys_sem_t) for the task #7490 + "Add return value to sys_mbox_post". + + 2008-01-05 Frédéric Bernon + * sys_arch.txt, api.h, api_lib.c, api_msg.h, api_msg.c, tcpip.c, sys.h, opt.h: + Introduce changes for task #7490 "Add return value to sys_mbox_post" with some + modifications in the sys_mbox api: sys_mbox_new take a "size" parameters which + indicate the number of pointers query by the mailbox. There is three defines + in opt.h to indicate sizes for tcpip::mbox, netconn::recvmbox, and for the + netconn::acceptmbox. Port maintainers, you can decide to just add this new + parameter in your implementation, but to ignore it to keep the previous behavior. + The new sys_mbox_trypost function return a value to know if the mailbox is + full or if the message is posted. Take a look to sys_arch.txt for more details. + This new function is used in tcpip_input (so, can be called in an interrupt + context since the function is not blocking), and in recv_udp and recv_raw. + + 2008-01-04 Frédéric Bernon, Simon Goldschmidt, Jonathan Larmour + * rawapi.txt, api.h, api_lib.c, api_msg.h, api_msg.c, sockets.c, tcp.h, tcp.c, + tcp_in.c, init.c, opt.h: rename backlog options with TCP_ prefix, limit the + "backlog" parameter in an u8_t, 0 is interpreted as "smallest queue", add + documentation in the rawapi.txt file. + + 2007-12-31 Kieran Mansley (based on patch from Per-Henrik Lundbolm) + * tcp.c, tcp_in.c, tcp_out.c, tcp.h: Add TCP persist timer + + 2007-12-31 Frédéric Bernon, Luca Ceresoli + * autoip.c, etharp.c: ip_addr.h: Integrate patch #6348: "Broadcast ARP packets + in autoip". The change in etharp_raw could be removed, since all calls to + etharp_raw use ethbroadcast for the "ethdst_addr" parameter. But it could be + wrong in the future. + + 2007-12-30 Frédéric Bernon, Tom Evans + * ip.c: Fix bug #21846 "LwIP doesn't appear to perform any IP Source Address + Filtering" reported by Tom Evans. + + 2007-12-21 Frédéric Bernon, Simon Goldschmidt, Jonathan Larmour + * tcp.h, opt.h, api.h, api_msg.h, tcp.c, tcp_in.c, api_lib.c, api_msg.c, + sockets.c, init.c: task #7252: Implement TCP listen backlog: Warning: raw API + applications have to call 'tcp_accepted(pcb)' in their accept callback to + keep accepting new connections. + + 2007-12-13 Frédéric Bernon + * api_msg.c, err.h, err.c, sockets.c, dns.c, dns.h: replace "enum dns_result" + by err_t type. Add a new err_t code "ERR_INPROGRESS". + + 2007-12-12 Frédéric Bernon + * dns.h, dns.c, opt.h: move DNS options to the "right" place. Most visibles + are the one which have ram usage. + + 2007-12-05 Frédéric Bernon + * netdb.c: add a LWIP_DNS_API_HOSTENT_STORAGE option to decide to use a static + set of variables (=0) or a local one (=1). In this last case, your port should + provide a function "struct hostent* sys_thread_hostent( struct hostent* h)" + which have to do a copy of "h" and return a pointer ont the "per-thread" copy. + + 2007-12-03 Simon Goldschmidt + * ip.c: ip_input: check if a packet is for inp first before checking all other + netifs on netif_list (speeds up packet receiving in most cases) + + 2007-11-30 Simon Goldschmidt + * udp.c, raw.c: task #7497: Sort lists (pcb, netif, ...) for faster access + UDP: move a (connected) pcb selected for input to the front of the list of + pcbs so that it is found faster next time. Same for RAW pcbs that have eaten + a packet. + + 2007-11-28 Simon Goldschmidt + * etharp.c, stats.c, stats.h, opt.h: Introduced ETHARP_STATS + + 2007-11-25 Simon Goldschmidt + * dhcp.c: dhcp_unfold_reply() uses pbuf_copy_partial instead of its own copy + algorithm. + + 2007-11-24 Simon Goldschmidt + * netdb.h, netdb.c, sockets.h/.c: Moved lwip_gethostbyname from sockets.c + to the new file netdb.c; included lwip_getaddrinfo. + + 2007-11-21 Simon Goldschmidt + * tcp.h, opt.h, tcp.c, tcp_in.c: implemented calculating the effective send-mss + based on the MTU of the netif used to send. Enabled by default. Disable by + setting LWIP_CALCULATE_EFF_SEND_MSS to 0. This fixes bug #21492. + + 2007-11-19 Frédéric Bernon + * api_msg.c, dns.h, dns.c: Implement DNS_DOES_NAME_CHECK option (check if name + received match the name query), implement DNS_USES_STATIC_BUF (the place where + copy dns payload to parse the response), return an error if there is no place + for a new query, and fix some minor problems. + + 2007-11-16 Simon Goldschmidt + * new files: ipv4/inet.c, ipv4/inet_chksum.c, ipv6/inet6.c + removed files: core/inet.c, core/inet6.c + Moved inet files into ipv4/ipv6 directory; splitted inet.c/inet.h into + inet and chksum part; changed includes in all lwIP files as appropriate + + 2007-11-16 Simon Goldschmidt + * api.h, api_msg.h, api_lib.c, api_msg.c, socket.h, socket.c: Added sequential + dns resolver function for netconn api (netconn_gethostbyname) and socket api + (gethostbyname/gethostbyname_r). + + 2007-11-15 Jim Pettinato, Frédéric Bernon + * opt.h, init.c, tcpip.c, dhcp.c, dns.h, dns.c: add DNS client for simple name + requests with RAW api interface. Initialization is done in lwip_init() with + build time options. DNS timer is added in tcpip_thread context. DHCP can set + DNS server ip addresses when options are received. You need to set LWIP_DNS=1 + in your lwipopts.h file (LWIP_DNS=0 in opt.h). DNS_DEBUG can be set to get + some traces with LWIP_DEBUGF. Sanity check have been added. There is a "todo" + list with points to improve. + + 2007-11-06 Simon Goldschmidt + * opt.h, mib2.c: Patch #6215: added ifAdminStatus write support (if explicitly + enabled by defining SNMP_SAFE_REQUESTS to 0); added code to check link status + for ifOperStatus if LWIP_NETIF_LINK_CALLBACK is defined. + + 2007-11-06 Simon Goldschmidt + * api.h, api_msg.h and dependent files: Task #7410: Removed the need to include + core header files in api.h (ip/tcp/udp/raw.h) to hide the internal + implementation from netconn api applications. + + 2007-11-03 Frédéric Bernon + * api.h, api_lib.c, api_msg.c, sockets.c, opt.h: add SO_RCVBUF option for UDP & + RAW netconn. You need to set LWIP_SO_RCVBUF=1 in your lwipopts.h (it's disabled + by default). Netconn API users can use the netconn_recv_bufsize macro to access + it. This is a first release which have to be improve for TCP. Note it used the + netconn::recv_avail which need to be more "thread-safe" (note there is already + the problem for FIONREAD with lwip_ioctl/ioctlsocket). + + 2007-11-01 Frédéric Bernon, Marc Chaland + * sockets.h, sockets.c, api.h, api_lib.c, api_msg.h, api_msg.c, tcp.h, tcp_out.c: + Integrate "patch #6250 : MSG_MORE flag for send". MSG_MORE is used at socket api + layer, NETCONN_MORE at netconn api layer, and TCP_WRITE_FLAG_MORE at raw api + layer. This option enable to delayed TCP PUSH flag on multiple "write" calls. + Note that previous "copy" parameter for "write" APIs is now called "apiflags". + + 2007-10-24 Frédéric Bernon + * api.h, api_lib.c, api_msg.c: Add macro API_EVENT in the same spirit than + TCP_EVENT_xxx macros to get a code more readable. It could also help to remove + some code (like we have talk in "patch #5919 : Create compile switch to remove + select code"), but it could be done later. + + 2007-10-08 Simon Goldschmidt + * many files: Changed initialization: many init functions are not needed any + more since we now rely on the compiler initializing global and static + variables to zero! + + 2007-10-06 Simon Goldschmidt + * ip_frag.c, memp.c, mib2.c, ip_frag.h, memp_std.h, opt.h: Changed IP_REASSEMBLY + to enqueue the received pbufs so that multiple packets can be reassembled + simultaneously and no static reassembly buffer is needed. + + 2007-10-05 Simon Goldschmidt + * tcpip.c, etharp.h, etharp.c: moved ethernet_input from tcpip.c to etharp.c so + all netifs (or ports) can use it. + + 2007-10-05 Frédéric Bernon + * netifapi.h, netifapi.c: add function netifapi_netif_set_default. Change the + common function to reduce a little bit the footprint (for all functions using + only the "netif" parameter). + + 2007-10-03 Frédéric Bernon + * netifapi.h, netifapi.c: add functions netifapi_netif_set_up, netifapi_netif_set_down, + netifapi_autoip_start and netifapi_autoip_stop. Use a common function to reduce + a little bit the footprint (for all functions using only the "netif" parameter). + + 2007-09-15 Frédéric Bernon + * udp.h, udp.c, sockets.c: Changes for "#20503 IGMP Improvement". Add IP_MULTICAST_IF + option in socket API, and a new field "multicast_ip" in "struct udp_pcb" (for + netconn and raw API users), only if LWIP_IGMP=1. Add getsockopt processing for + IP_MULTICAST_TTL and IP_MULTICAST_IF. + + 2007-09-10 Frédéric Bernon + * snmp.h, mib2.c: enable to remove SNMP timer (which consumne several cycles + even when it's not necessary). snmp_agent.txt tell to call snmp_inc_sysuptime() + each 10ms (but, it's intrusive if you use sys_timeout feature). Now, you can + decide to call snmp_add_sysuptime(100) each 1000ms (which is bigger "step", but + call to a lower frequency). Or, you can decide to not call snmp_inc_sysuptime() + or snmp_add_sysuptime(), and to define the SNMP_GET_SYSUPTIME(sysuptime) macro. + This one is undefined by default in mib2.c. SNMP_GET_SYSUPTIME is called inside + snmp_get_sysuptime(u32_t *value), and enable to change "sysuptime" value only + when it's queried (any direct call to "sysuptime" is changed by a call to + snmp_get_sysuptime). + + 2007-09-09 Frédéric Bernon, Bill Florac + * igmp.h, igmp.c, netif.h, netif.c, ip.c: To enable to have interfaces with IGMP, + and others without it, there is a new NETIF_FLAG_IGMP flag to set in netif->flags + if you want IGMP on an interface. igmp_stop() is now called inside netif_remove(). + igmp_report_groups() is now called inside netif_set_link_up() (need to have + LWIP_NETIF_LINK_CALLBACK=1) to resend reports once the link is up (avoid to wait + the next query message to receive the matching multicast streams). + + 2007-09-08 Frédéric Bernon + * sockets.c, ip.h, api.h, tcp.h: declare a "struct ip_pcb" which only contains + IP_PCB. Add in the netconn's "pcb" union a "struct ip_pcb *ip;" (no size change). + Use this new field to access to common pcb fields (ttl, tos, so_options, etc...). + Enable to access to these fields with LWIP_TCP=0. + + 2007-09-05 Frédéric Bernon + * udp.c, ipv4/icmp.c, ipv4/ip.c, ipv6/icmp.c, ipv6/ip6.c, ipv4/icmp.h, + ipv6/icmp.h, opt.h: Integrate "task #7272 : LWIP_ICMP option". The new option + LWIP_ICMP enable/disable ICMP module inside the IP stack (enable per default). + Be careful, disabling ICMP make your product non-compliant to RFC1122, but + help to reduce footprint, and to reduce "visibility" on the Internet. + + 2007-09-05 Frédéric Bernon, Bill Florac + * opt.h, sys.h, tcpip.c, slipif.c, ppp.c, sys_arch.txt: Change parameters list + for sys_thread_new (see "task #7252 : Create sys_thread_new_ex()"). Two new + parameters have to be provided: a task name, and a task stack size. For this + one, since it's platform dependant, you could define the best one for you in + your lwipopts.h. For port maintainers, you can just add these new parameters + in your sys_arch.c file, and but it's not mandatory, use them in your OS + specific functions. + + 2007-09-05 Frédéric Bernon + * inet.c, autoip.c, msg_in.c, msg_out.c, init.c: Move some build time checkings + inside init.c for task #7142 "Sanity check user-configurable values". + + 2007-09-04 Frédéric Bernon, Bill Florac + * igmp.h, igmp.c, memp_std.h, memp.c, init.c, opt.h: Replace mem_malloc call by + memp_malloc, and use a new MEMP_NUM_IGMP_GROUP option (see opt.h to define the + value). It will avoid potential fragmentation problems, use a counter to know + how many times a group is used on an netif, and free it when all applications + leave it. MEMP_NUM_IGMP_GROUP got 8 as default value (and init.c got a sanity + check if LWIP_IGMP!=0). + + 2007-09-03 Frédéric Bernon + * igmp.h, igmp.c, sockets.c, api_msg.c: Changes for "#20503 IGMP Improvement". + Initialize igmp_mac_filter to NULL in netif_add (this field should be set in + the netif's "init" function). Use the "imr_interface" field (for socket layer) + and/or the "interface" field (for netconn layer), for join/leave operations. + The igmp_join/leavegroup first parameter change from a netif to an ipaddr. + This field could be a netif's ipaddr, or "any" (same meaning than ip_addr_isany). + + 2007-08-30 Frédéric Bernon + * Add netbuf.h, netbuf.c, Change api.h, api_lib.c: #7249 "Split netbuf functions + from api/api_lib". Now netbuf API is independant of netconn, and can be used + with other API (application based on raw API, or future "socket2" API). Ports + maintainers just have to add src/api/netbuf.c in their makefile/projects. + + 2007-08-30 Frédéric Bernon, Jonathan Larmour + * init.c: Add first version of lwip_sanity_check for task #7142 "Sanity check + user-configurable values". + + 2007-08-29 Frédéric Bernon + * igmp.h, igmp.c, tcpip.c, init.c, netif.c: change igmp_init and add igmp_start. + igmp_start is call inside netif_add. Now, igmp initialization is in the same + spirit than the others modules. Modify some IGMP debug traces. + + 2007-08-29 Frédéric Bernon + * Add init.h, init.c, Change opt.h, tcpip.c: Task #7213 "Add a lwip_init function" + Add lwip_init function to regroup all modules initializations, and to provide + a place to add code for task #7142 "Sanity check user-configurable values". + Ports maintainers should remove direct initializations calls from their code, + and add init.c in their makefiles. Note that lwip_init() function is called + inside tcpip_init, but can also be used by raw api users since all calls are + disabled when matching options are disabled. Also note that their is new options + in opt.h, you should configure in your lwipopts.h (they are enabled per default). + + 2007-08-26 Marc Boucher + * api_msg.c: do_close_internal(): Reset the callbacks and arg (conn) to NULL + since they can under certain circumstances be called with an invalid conn + pointer after the connection has been closed (and conn has been freed). + + 2007-08-25 Frédéric Bernon (Artem Migaev's Patch) + * netif.h, netif.c: Integrate "patch #6163 : Function to check if link layer is up". + Add a netif_is_link_up() function if LWIP_NETIF_LINK_CALLBACK option is set. + + 2007-08-22 Frédéric Bernon + * netif.h, netif.c, opt.h: Rename LWIP_NETIF_CALLBACK in LWIP_NETIF_STATUS_CALLBACK + to be coherent with new LWIP_NETIF_LINK_CALLBACK option before next release. + + 2007-08-22 Frédéric Bernon + * tcpip.h, tcpip.c, ethernetif.c, opt.h: remove options ETHARP_TCPIP_INPUT & + ETHARP_TCPIP_ETHINPUT, now, only "ethinput" code is supported, even if the + name is tcpip_input (we keep the name of 1.2.0 function). + + 2007-08-17 Jared Grubb + * memp_std.h, memp.h, memp.c, mem.c, stats.c: (Task #7136) Centralize mempool + settings into new memp_std.h and optional user file lwippools.h. This adds + more dynamic mempools, and allows the user to create an arbitrary number of + mempools for mem_malloc. + + 2007-08-16 Marc Boucher + * api_msg.c: Initialize newconn->state to NETCONN_NONE in accept_function; + otherwise it was left to NETCONN_CLOSE and sent_tcp() could prematurely + close the connection. + + 2007-08-16 Marc Boucher + * sockets.c: lwip_accept(): check netconn_peer() error return. + + 2007-08-16 Marc Boucher + * mem.c, mem.h: Added mem_calloc(). + + 2007-08-16 Marc Boucher + * tcpip.c, tcpip.h memp.c, memp.h: Added distinct memp (MEMP_TCPIP_MSG_INPKT) + for input packets to prevent floods from consuming all of MEMP_TCPIP_MSG + and starving other message types. + Renamed MEMP_TCPIP_MSG to MEMP_TCPIP_MSG_API + + 2007-08-16 Marc Boucher + * pbuf.c, pbuf.h, etharp.c, tcp_in.c, sockets.c: Split pbuf flags in pbuf + type and flgs (later renamed to flags). + Use enum pbuf_flag as pbuf_type. Renumber PBUF_FLAG_*. + Improved lwip_recvfrom(). TCP push now propagated. + + 2007-08-16 Marc Boucher + * ethernetif.c, contrib/ports/various: ethbroadcast now a shared global + provided by etharp. + + 2007-08-16 Marc Boucher + * ppp_oe.c ppp_oe.h, auth.c chap.c fsm.c lcp.c ppp.c ppp.h, + etharp.c ethernetif.c, etharp.h, opt.h tcpip.h, tcpip.c: + Added PPPoE support and various PPP improvements. + + 2007-07-25 Simon Goldschmidt + * api_lib.c, ip_frag.c, pbuf.c, api.h, pbuf.h: Introduced pbuf_copy_partial, + making netbuf_copy_partial use this function. + + 2007-07-25 Simon Goldschmidt + * tcp_in.c: Fix bug #20506: Slow start / initial congestion window starts with + 2 * mss (instead of 1 * mss previously) to comply with some newer RFCs and + other stacks. + + 2007-07-13 Jared Grubb (integrated by Frédéric Bernon) + * opt.h, netif.h, netif.c, ethernetif.c: Add new configuration option to add + a link callback in the netif struct, and functions to handle it. Be carefull + for port maintainers to add the NETIF_FLAG_LINK_UP flag (like in ethernetif.c) + if you want to be sure to be compatible with future changes... + + 2007-06-30 Frédéric Bernon + * sockets.h, sockets.c: Implement MSG_PEEK flag for recv/recvfrom functions. + + 2007-06-21 Simon Goldschmidt + * etharp.h, etharp.c: Combined etharp_request with etharp_raw for both + LWIP_AUTOIP =0 and =1 to remove redundant code. + + 2007-06-21 Simon Goldschmidt + * mem.c, memp.c, mem.h, memp.h, opt.h: task #6863: Introduced the option + MEM_USE_POOLS to use 4 pools with different sized elements instead of a + heap. This both prevents memory fragmentation and gives a higher speed + at the cost of more memory consumption. Turned off by default. + + 2007-06-21 Simon Goldschmidt + * api_lib.c, api_msg.c, api.h, api_msg.h: Converted the length argument of + netconn_write (and therefore also api_msg_msg.msg.w.len) from u16_t into + int to be able to send a bigger buffer than 64K with one time (mainly + used from lwip_send). + + 2007-06-21 Simon Goldschmidt + * tcp.h, api_msg.c: Moved the nagle algorithm from netconn_write/do_write + into a define (tcp_output_nagle) in tcp.h to provide it to raw api users, too. + + 2007-06-21 Simon Goldschmidt + * api.h, api_lib.c, api_msg.c: Fixed bug #20021: Moved sendbuf-processing in + netconn_write from api_lib.c to api_msg.c to also prevent multiple context- + changes on low memory or empty send-buffer. + + 2007-06-18 Simon Goldschmidt + * etharp.c, etharp.h: Changed etharp to use a defined hardware address length + of 6 to avoid loading netif->hwaddr_len every time (since this file is only + used for ethernet and struct eth_addr already had a defined length of 6). + + 2007-06-17 Simon Goldschmidt + * sockets.c, sockets.h: Implemented socket options SO_NO_CHECK for UDP sockets + to disable UDP checksum generation on transmit. + + 2007-06-13 Frédéric Bernon, Simon Goldschmidt + * debug.h, api_msg.c: change LWIP_ERROR to use it to check errors like invalid + pointers or parameters, and let the possibility to redefined it in cc.h. Use + this macro to check "conn" parameter in api_msg.c functions. + + 2007-06-11 Simon Goldschmidt + * sockets.c, sockets.h: Added UDP lite support for sockets + + 2007-06-10 Simon Goldschmidt + * udp.h, opt.h, api_msg.c, ip.c, udp.c: Included switch LWIP_UDPLITE (enabled + by default) to switch off UDP-Lite support if not needed (reduces udp.c code + size) + + 2007-06-09 Dominik Spies (integrated by Frédéric Bernon) + * autoip.h, autoip.c, dhcp.h, dhcp.c, netif.h, netif.c, etharp.h, etharp.c, opt.h: + AutoIP implementation available for IPv4, with new options LWIP_AUTOIP and + LWIP_DHCP_AUTOIP_COOP if you want to cooperate with DHCP. Some tips to adapt + (see TODO mark in the source code). + + 2007-06-09 Simon Goldschmidt + * etharp.h, etharp.c, ethernetif.c: Modified order of parameters for + etharp_output() to match netif->output so etharp_output() can be used + directly as netif->output to save one function call. + + 2007-06-08 Simon Goldschmidt + * netif.h, ethernetif.c, slipif.c, loopif.c: Added define + NETIF_INIT_SNMP(netif, type, speed) to initialize per-netif snmp variables, + added initialization of those to ethernetif, slipif and loopif. + + 2007-05-18 Simon Goldschmidt + * opt.h, ip_frag.c, ip_frag.h, ip.c: Added option IP_FRAG_USES_STATIC_BUF + (defaulting to off for now) that can be set to 0 to send fragmented + packets by passing PBUF_REFs down the stack. + + 2007-05-23 Frédéric Bernon + * api_lib.c: Implement SO_RCVTIMEO for accept and recv on TCP + connections, such present in patch #5959. + + 2007-05-23 Frédéric Bernon + * api.h, api_lib.c, api_msg.c, sockets.c: group the different NETCONN_UDPxxx + code in only one part... + + 2007-05-18 Simon Goldschmidt + * opt.h, memp.h, memp.c: Added option MEMP_OVERFLOW_CHECK to check for memp + elements to overflow. This is achieved by adding some bytes before and after + each pool element (increasing their size, of course), filling them with a + prominent value and checking them on freeing the element. + Set it to 2 to also check every element in every pool each time memp_malloc() + or memp_free() is called (slower but more helpful). + + 2007-05-10 Simon Goldschmidt + * opt.h, memp.h, memp.c, pbuf.c (see task #6831): use a new memp pool for + PBUF_POOL pbufs instead of the old pool implementation in pbuf.c to reduce + code size. + + 2007-05-11 Frédéric Bernon + * sockets.c, api_lib.c, api_msg.h, api_msg.c, netifapi.h, netifapi.c, tcpip.c: + Include a function pointer instead of a table index in the message to reduce + footprint. Disable some part of lwip_send and lwip_sendto if some options are + not set (LWIP_TCP, LWIP_UDP, LWIP_RAW). + + 2007-05-10 Simon Goldschmidt + * *.h (except netif/ppp/*.h): Included patch #5448: include '#ifdef __cplusplus + \ extern "C" {' in all header files. Now you can write your application using + the lwIP stack in C++ and simply #include the core files. Note I have left + out the netif/ppp/*h header files for now, since I don't know which files are + included by applications and which are for internal use only. + + 2007-05-09 Simon Goldschmidt + * opt.h, *.c/*.h: Included patch #5920: Create define to override C-library + memcpy. 2 Defines are created: MEMCPY() for normal memcpy, SMEMCPY() for + situations where some compilers might inline the copy and save a function + call. Also replaced all calls to memcpy() with calls to (S)MEMCPY(). + + 2007-05-08 Simon Goldschmidt + * mem.h: If MEM_LIBC_MALLOC==1, allow the defines (e.g. mem_malloc() -> malloc()) + to be overriden in case the C-library malloc implementation is not protected + against concurrent access. + + 2007-05-04 Simon Goldschmidt (Atte Kojo) + * etharp.c: Introduced fast one-entry-cache to speed up ARP lookup when sending + multiple packets to the same host. + + 2007-05-04 Frédéric Bernon, Jonathan Larmour + * sockets.c, api.h, api_lib.c, api_msg.h, api_msg.c: Fix bug #19162 "lwip_sento: a possible + to corrupt remote addr/port connection state". Reduce problems "not enought memory" with + netbuf (if we receive lot of datagrams). Improve lwip_sendto (only one exchange between + sockets api and api_msg which run in tcpip_thread context). Add netconn_sento function. + Warning, if you directly access to "fromaddr" & "fromport" field from netbuf struct, + these fields are now renamed "addr" & "port". + + 2007-04-11 Jonathan Larmour + * sys.h, api_lib.c: Provide new sys_mbox_tryfetch function. Require ports to provide new + sys_arch_mbox_tryfetch function to get a message if one is there, otherwise return + with SYS_MBOX_EMPTY. sys_arch_mbox_tryfetch can be implemented as a function-like macro + by the port in sys_arch.h if desired. + + 2007-04-06 Frédéric Bernon, Simon Goldschmidt + * opt.h, tcpip.h, tcpip.c, netifapi.h, netifapi.c: New configuration option LWIP_NETIF_API + allow to use thread-safe functions to add/remove netif in list, and to start/stop dhcp + clients, using new functions from netifapi.h. Disable as default (no port change to do). + + 2007-04-05 Frédéric Bernon + * sockets.c: remplace ENOBUFS errors on alloc_socket by ENFILE to be more BSD compliant. + + 2007-04-04 Simon Goldschmidt + * arch.h, api_msg.c, dhcp.c, msg_in.c, sockets.c: Introduced #define LWIP_UNUSED_ARG(x) + use this for and architecture-independent form to tell the compiler you intentionally + are not using this variable. Can be overriden in cc.h. + + 2007-03-28 Frédéric Bernon + * opt.h, netif.h, dhcp.h, dhcp.c: New configuration option LWIP_NETIF_HOSTNAME allow to + define a hostname in netif struct (this is just a pointer, so, you can use a hardcoded + string, point on one of your's ethernetif field, or alloc a string you will free yourself). + It will be used by DHCP to register a client hostname, but can also be use when you call + snmp_set_sysname. + + 2007-03-28 Frédéric Bernon + * netif.h, netif.c: A new NETIF_FLAG_ETHARP flag is defined in netif.h, to allow to + initialize a network interface's flag with. It tell this interface is an ethernet + device, and we can use ARP with it to do a "gratuitous ARP" (RFC 3220 "IP Mobility + Support for IPv4" section 4.6) when interface is "up" with netif_set_up(). + + 2007-03-26 Frédéric Bernon, Jonathan Larmour + * opt.h, tcpip.c: New configuration option LWIP_ARP allow to disable ARP init at build + time if you only use PPP or SLIP. The default is enable. Note we don't have to call + etharp_init in your port's initilization sequence if you use tcpip.c, because this call + is done in tcpip_init function. + + 2007-03-22 Frédéric Bernon + * stats.h, stats.c, msg_in.c: Stats counters can be change to u32_t if necessary with the + new option LWIP_STATS_LARGE. If you need this option, define LWIP_STATS_LARGE to 1 in + your lwipopts.h. More, unused counters are not defined in the stats structs, and not + display by stats_display(). Note that some options (SYS_STATS and RAW_STATS) are defined + but never used. Fix msg_in.c with the correct #if test for a stat display. + + 2007-03-21 Kieran Mansley + * netif.c, netif.h: Apply patch#4197 with some changes (originator: rireland@hmgsl.com). + Provides callback on netif up/down state change. + + 2007-03-11 Frédéric Bernon, Mace Gael, Steve Reynolds + * sockets.h, sockets.c, api.h, api_lib.c, api_msg.h, api_msg.c, igmp.h, igmp.c, + ip.c, netif.h, tcpip.c, opt.h: + New configuration option LWIP_IGMP to enable IGMP processing. Based on only one + filter per all network interfaces. Declare a new function in netif to enable to + control the MAC filter (to reduce lwIP traffic processing). + + 2007-03-11 Frédéric Bernon + * tcp.h, tcp.c, sockets.c, tcp_out.c, tcp_in.c, opt.h: Keepalive values can + be configured at run time with LWIP_TCP_KEEPALIVE, but don't change this + unless you know what you're doing (default are RFC1122 compliant). Note + that TCP_KEEPIDLE and TCP_KEEPINTVL have to be set in seconds. + + 2007-03-08 Frédéric Bernon + * tcp.h: Keepalive values can be configured at compile time, but don't change + this unless you know what you're doing (default are RFC1122 compliant). + + 2007-03-08 Frédéric Bernon + * sockets.c, api.h, api_lib.c, tcpip.c, sys.h, sys.c, err.c, opt.h: + Implement LWIP_SO_RCVTIMEO configuration option to enable/disable SO_RCVTIMEO + on UDP sockets/netconn. + + 2007-03-08 Simon Goldschmidt + * snmp_msg.h, msg_in.c: SNMP UDP ports can be configured at compile time. + + 2007-03-06 Frédéric Bernon + * api.h, api_lib.c, sockets.h, sockets.c, tcpip.c, sys.h, sys.c, err.h: + Implement SO_RCVTIMEO on UDP sockets/netconn. + + 2007-02-28 Kieran Mansley (based on patch from Simon Goldschmidt) + * api_lib.c, tcpip.c, memp.c, memp.h: make API msg structs allocated + on the stack and remove the API msg type from memp + + 2007-02-26 Jonathan Larmour (based on patch from Simon Goldschmidt) + * sockets.h, sockets.c: Move socket initialization to new + lwip_socket_init() function. + NOTE: this changes the API with ports. Ports will have to be + updated to call lwip_socket_init() now. + + 2007-02-26 Jonathan Larmour (based on patch from Simon Goldschmidt) + * api_lib.c: Use memcpy in netbuf_copy_partial. + + + ++ Bug fixes: + + 2008-03-17 Frédéric Bernon, Ed Kerekes + * igmp.h, igmp.c: Fix bug #22613 "IGMP iphdr problem" (could have + some problems to fill the IP header on some targets, use now the + ip.h macros to do it). + + 2008-03-13 Frédéric Bernon + * sockets.c: Fix bug #22435 "lwip_recvfrom with TCP break;". Using + (lwip_)recvfrom with valid "from" and "fromlen" parameters, on a + TCP connection caused a crash. Note that using (lwip_)recvfrom + like this is a bit slow and that using (lwip)getpeername is the + good lwip way to do it (so, using recv is faster on tcp sockets). + + 2008-03-12 Frédéric Bernon, Jonathan Larmour + * api_msg.c, contrib/apps/ping.c: Fix bug #22530 "api_msg.c's + recv_raw() does not consume data", and the ping sample (with + LWIP_SOCKET=1, the code did the wrong supposition that lwip_recvfrom + returned the IP payload, without the IP header). + + 2008-03-04 Jonathan Larmour + * mem.c, stats.c, mem.h: apply patch #6414 to avoid compiler errors + and/or warnings on some systems where mem_size_t and size_t differ. + * pbuf.c, ppp.c: Fix warnings on some systems with mem_malloc. + + 2008-03-04 Kieran Mansley (contributions by others) + * Numerous small compiler error/warning fixes from contributions to + mailing list after 1.3.0 release candidate made. + + 2008-01-25 Cui hengbin (integrated by Frédéric Bernon) + * dns.c: Fix bug #22108 "DNS problem" caused by unaligned structures. + + 2008-01-15 Kieran Mansley + * tcp_out.c: BUG20511. Modify persist timer to start when we are + prevented from sending by a small send window, not just a zero + send window. + + 2008-01-09 Jonathan Larmour + * opt.h, ip.c: Rename IP_OPTIONS define to IP_OPTIONS_ALLOWED to avoid + conflict with Linux system headers. + + 2008-01-06 Jonathan Larmour + * dhcp.c: fix bug #19927: "DHCP NACK problem" by clearing any existing set IP + address entirely on receiving a DHCPNAK, and restarting discovery. + + 2007-12-21 Simon Goldschmidt + * sys.h, api_lib.c, api_msg.c, sockets.c: fix bug #21698: "netconn->recv_avail + is not protected" by using new macros for interlocked access to modify/test + netconn->recv_avail. + + 2007-12-20 Kieran Mansley (based on patch from Oleg Tyshev) + * tcp_in.c: fix bug# 21535 (nrtx not reset correctly in SYN_SENT state) + + 2007-12-20 Kieran Mansley (based on patch from Per-Henrik Lundbolm) + * tcp.c, tcp_in.c, tcp_out.c, tcp.h: fix bug #20199 (better handling + of silly window avoidance and prevent lwIP from shrinking the window) + + 2007-12-04 Simon Goldschmidt + * tcp.c, tcp_in.c: fix bug #21699 (segment leak in ooseq processing when last + data packet was lost): add assert that all segment lists are empty in + tcp_pcb_remove before setting pcb to CLOSED state; don't directly set CLOSED + state from LAST_ACK in tcp_process + + 2007-12-02 Simon Goldschmidt + * sockets.h: fix bug #21654: exclude definition of struct timeval from #ifndef FD_SET + If including for system-struct timeval, LWIP_TIMEVAL_PRIVATE now + has to be set to 0 in lwipopts.h + + 2007-12-02 Simon Goldschmidt + * api_msg.c, api_lib.c: fix bug #21656 (recvmbox problem in netconn API): always + allocate a recvmbox in netconn_new_with_proto_and_callback. For a tcp-listen + netconn, this recvmbox is later freed and a new mbox is allocated for acceptmbox. + This is a fix for thread-safety and allocates all items needed for a netconn + when the netconn is created. + + 2007-11-30 Simon Goldschmidt + * udp.c: first attempt to fix bug #21655 (DHCP doesn't work reliably with multiple + netifs): if LWIP_DHCP is enabled, UDP packets to DHCP_CLIENT_PORT are passed + to netif->dhcp->pcb only (if that exists) and not to any other pcb for the same + port (only solution to let UDP pcbs 'bind' to a netif instead of an IP address) + + 2007-11-27 Simon Goldschmidt + * ip.c: fixed bug #21643 (udp_send/raw_send don't fail if netif is down) by + letting ip_route only use netifs that are up. + + 2007-11-27 Simon Goldschmidt + * err.h, api_lib.c, api_msg.c, sockets.c: Changed error handling: ERR_MEM, ERR_BUF + and ERR_RTE are seen as non-fatal, all other errors are fatal. netconns and + sockets block most operations once they have seen a fatal error. + + 2007-11-27 Simon Goldschmidt + * udp.h, udp.c, dhcp.c: Implemented new function udp_sendto_if which takes the + netif to send as an argument (to be able to send on netifs that are down). + + 2007-11-26 Simon Goldschmidt + * tcp_in.c: Fixed bug #21582: pcb->acked accounting can be wrong when ACKs + arrive out-of-order + + 2007-11-21 Simon Goldschmidt + * tcp.h, tcp_out.c, api_msg.c: Fixed bug #20287: tcp_output_nagle sends too early + Fixed the nagle algorithm; nagle now also works for all raw API applications + and has to be explicitly disabled with 'tcp_pcb->flags |= TF_NODELAY' + + 2007-11-12 Frédéric Bernon + * sockets.c, api.h, api_lib.c, api_msg.h, api_msg.c: Fixed bug #20900. Now, most + of the netconn_peer and netconn_addr processing is done inside tcpip_thread + context in do_getaddr. + + 2007-11-10 Simon Goldschmidt + * etharp.c: Fixed bug: assert fired when MEMP_ARP_QUEUE was empty (which can + happen any time). Now the packet simply isn't enqueued when out of memory. + + 2007-11-01 Simon Goldschmidt + * tcp.c, tcp_in.c: Fixed bug #21494: The send mss (pcb->mss) is set to 536 (or + TCP_MSS if that is smaller) as long as no MSS option is received from the + remote host. + + 2007-11-01 Simon Goldschmidt + * tcp.h, tcp.c, tcp_in.c: Fixed bug #21491: The MSS option sent (with SYN) + is now based on TCP_MSS instead of pcb->mss (on passive open now effectively + sending our configured TCP_MSS instead of the one received). + + 2007-11-01 Simon Goldschmidt + * tcp_in.c: Fixed bug #21181: On active open, the initial congestion window was + calculated based on the configured TCP_MSS, not on the MSS option received + with SYN+ACK. + + 2007-10-09 Simon Goldschmidt + * udp.c, inet.c, inet.h: Fixed UDPLite: send: Checksum was always generated too + short and also was generated wrong if checksum coverage != tot_len; + receive: checksum was calculated wrong if checksum coverage != tot_len + + 2007-10-08 Simon Goldschmidt + * mem.c: lfree was not updated in mem_realloc! + + 2007-10-07 Frédéric Bernon + * sockets.c, api.h, api_lib.c: First step to fix "bug #20900 : Potential + crash error problem with netconn_peer & netconn_addr". VERY IMPORTANT: + this change cause an API breakage for netconn_addr, since a parameter + type change. Any compiler should cause an error without any changes in + yours netconn_peer calls (so, it can't be a "silent change"). It also + reduce a little bit the footprint for socket layer (lwip_getpeername & + lwip_getsockname use now a common lwip_getaddrname function since + netconn_peer & netconn_addr have the same parameters). + + 2007-09-20 Simon Goldschmidt + * tcp.c: Fixed bug #21080 (tcp_bind without check pcbs in TIME_WAIT state) + by checking tcp_tw_pcbs also + + 2007-09-19 Simon Goldschmidt + * icmp.c: Fixed bug #21107 (didn't reset IP TTL in ICMP echo replies) + + 2007-09-15 Mike Kleshov + * mem.c: Fixed bug #21077 (inaccuracy in calculation of lwip_stat.mem.used) + + 2007-09-06 Frédéric Bernon + * several-files: replace some #include "arch/cc.h" by "lwip/arch.h", or simply remove + it as long as "lwip/opt.h" is included before (this one include "lwip/debug.h" which + already include "lwip/arch.h"). Like that, default defines are provided by "lwip/arch.h" + if they are not defined in cc.h, in the same spirit than "lwip/opt.h" for lwipopts.h. + + 2007-08-30 Frédéric Bernon + * igmp.h, igmp.c: Some changes to remove some redundant code, add some traces, + and fix some coding style. + + 2007-08-28 Frédéric Bernon + * tcpip.c: Fix TCPIP_MSG_INPKT processing: now, tcpip_input can be used for any + kind of packets. These packets are considered like Ethernet packets (payload + pointing to ethhdr) if the netif got the NETIF_FLAG_ETHARP flag. Else, packets + are considered like IP packets (payload pointing to iphdr). + + 2007-08-27 Frédéric Bernon + * api.h, api_lib.c, api_msg.c: First fix for "bug #20900 : Potential crash error + problem with netconn_peer & netconn_addr". Introduce NETCONN_LISTEN netconn_state + and remove obsolete ones (NETCONN_RECV & NETCONN_ACCEPT). + + 2007-08-24 Kieran Mansley + * inet.c Modify (acc >> 16) test to ((acc >> 16) != 0) to help buggy + compiler (Paradigm C++) + + 2007-08-09 Frédéric Bernon, Bill Florac + * stats.h, stats.c, igmp.h, igmp.c, opt.h: Fix for bug #20503 : IGMP Improvement. + Introduce IGMP_STATS to centralize statistics management. + + 2007-08-09 Frédéric Bernon, Bill Florac + * udp.c: Fix for bug #20503 : IGMP Improvement. Enable to receive a multicast + packet on a udp pcb binded on an netif's IP address, and not on "any". + + 2007-08-09 Frédéric Bernon, Bill Florac + * igmp.h, igmp.c, ip.c: Fix minor changes from bug #20503 : IGMP Improvement. + This is mainly on using lookup/lookfor, and some coding styles... + + 2007-07-26 Frédéric Bernon (and "thedoctor") + * igmp.c: Fix bug #20595 to accept IGMPv3 "Query" messages. + + 2007-07-25 Simon Goldschmidt + * api_msg.c, tcp.c: Another fix for bug #20021: by not returning an error if + tcp_output fails in tcp_close, the code in do_close_internal gets simpler + (tcp_output is called again later from tcp timers). + + 2007-07-25 Simon Goldschmidt + * ip_frag.c: Fixed bug #20429: use the new pbuf_copy_partial instead of the old + copy_from_pbuf, which illegally modified the given pbuf. + + 2007-07-25 Simon Goldschmidt + * tcp_out.c: tcp_enqueue: pcb->snd_queuelen didn't work for chaine PBUF_RAMs: + changed snd_queuelen++ to snd_queuelen += pbuf_clen(p). + + 2007-07-24 Simon Goldschmidt + * api_msg.c, tcp.c: Fix bug #20480: Check the pcb passed to tcp_listen() for the + correct state (must be CLOSED). + + 2007-07-13 Thomas Taranowski (commited by Jared Grubb) + * memp.c: Fix bug #20478: memp_malloc returned NULL+MEMP_SIZE on failed + allocation. It now returns NULL. + + 2007-07-13 Frédéric Bernon + * api_msg.c: Fix bug #20318: api_msg "recv" callbacks don't call pbuf_free in + all error cases. + + 2007-07-13 Frédéric Bernon + * api_msg.c: Fix bug #20315: possible memory leak problem if tcp_listen failed, + because current code doesn't follow rawapi.txt documentation. + + 2007-07-13 Kieran Mansley + * src/core/tcp_in.c Apply patch#5741 from Oleg Tyshev to fix bug in + out of sequence processing of received packets + + 2007-07-03 Simon Goldschmidt + * nearly-all-files: Added assertions where PBUF_RAM pbufs are used and an + assumption is made that this pbuf is in one piece (i.e. not chained). These + assumptions clash with the possibility of converting to fully pool-based + pbuf implementations, where PBUF_RAM pbufs might be chained. + + 2007-07-03 Simon Goldschmidt + * api.h, api_lib.c, api_msg.c: Final fix for bug #20021 and some other problems + when closing tcp netconns: removed conn->sem, less context switches when + closing, both netconn_close and netconn_delete should safely close tcp + connections. + + 2007-07-02 Simon Goldschmidt + * ipv4/ip.h, ipv6/ip.h, opt.h, netif.h, etharp.h, ipv4/ip.c, netif.c, raw.c, + tcp_out.c, udp.c, etharp.c: Added option LWIP_NETIF_HWADDRHINT (default=off) + to cache ARP table indices with each pcb instead of single-entry cache for + the complete stack. + + 2007-07-02 Simon Goldschmidt + * tcp.h, tcp.c, tcp_in.c, tcp_out.c: Added some ASSERTS and casts to prevent + warnings when assigning to smaller types. + + 2007-06-28 Simon Goldschmidt + * tcp_out.c: Added check to prevent tcp_pcb->snd_queuelen from overflowing. + + 2007-06-28 Simon Goldschmidt + * tcp.h: Fixed bug #20287: Fixed nagle algorithm (sending was done too early if + a segment contained chained pbufs) + + 2007-06-28 Frédéric Bernon + * autoip.c: replace most of rand() calls by a macro LWIP_AUTOIP_RAND which compute + a "pseudo-random" value based on netif's MAC and some autoip fields. It's always + possible to define this macro in your own lwipopts.h to always use C library's + rand(). Note that autoip_create_rand_addr doesn't use this macro. + + 2007-06-28 Frédéric Bernon + * netifapi.h, netifapi.c, tcpip.h, tcpip.c: Update code to handle the option + LWIP_TCPIP_CORE_LOCKING, and do some changes to be coherent with last modifications + in api_lib/api_msg (use pointers and not type with table, etc...) + + 2007-06-26 Simon Goldschmidt + * udp.h: Fixed bug #20259: struct udp_hdr was lacking the packin defines. + + 2007-06-25 Simon Goldschmidt + * udp.c: Fixed bug #20253: icmp_dest_unreach was called with a wrong p->payload + for udp packets with no matching pcb. + + 2007-06-25 Simon Goldschmidt + * udp.c: Fixed bug #20220: UDP PCB search in udp_input(): a non-local match + could get udp input packets if the remote side matched. + + 2007-06-13 Simon Goldschmidt + * netif.c: Fixed bug #20180 (TCP pcbs listening on IP_ADDR_ANY could get + changed in netif_set_ipaddr if previous netif->ip_addr.addr was 0. + + 2007-06-13 Simon Goldschmidt + * api_msg.c: pcb_new sets conn->err if protocol is not implemented + -> netconn_new_..() does not allocate a new connection for unsupported + protocols. + + 2007-06-13 Frédéric Bernon, Simon Goldschmidt + * api_lib.c: change return expression in netconn_addr and netconn_peer, because + conn->err was reset to ERR_OK without any reasons (and error was lost)... + + 2007-06-13 Frédéric Bernon, Matthias Weisser + * opt.h, mem.h, mem.c, memp.c, pbuf.c, ip_frag.c, vj.c: Fix bug #20162. Rename + MEM_ALIGN in LWIP_MEM_ALIGN and MEM_ALIGN_SIZE in LWIP_MEM_ALIGN_SIZE to avoid + some macro names collision with some OS macros. + + 2007-06-11 Simon Goldschmidt + * udp.c: UDP Lite: corrected the use of chksum_len (based on RFC3828: if it's 0, + create checksum over the complete packet. On RX, if it's < 8 (and not 0), + discard the packet. Also removed the duplicate 'udphdr->chksum = 0' for both + UDP & UDP Lite. + + 2007-06-11 Srinivas Gollakota & Oleg Tyshev + * tcp_out.c: Fix for bug #20075 : "A problem with keep-alive timer and TCP flags" + where TCP flags wasn't initialized in tcp_keepalive. + + 2007-06-03 Simon Goldschmidt + * udp.c: udp_input(): Input pbuf was not freed if pcb had no recv function + registered, p->payload was modified without modifying p->len if sending + icmp_dest_unreach() (had no negative effect but was definitively wrong). + + 2007-06-03 Simon Goldschmidt + * icmp.c: Corrected bug #19937: For responding to an icmp echo request, icmp + re-used the input pbuf even if that didn't have enough space to include the + link headers. Now the space is tested and a new pbuf is allocated for the + echo response packet if the echo request pbuf isn't big enough. + + 2007-06-01 Simon Goldschmidt + * sockets.c: Checked in patch #5914: Moved sockopt processing into tcpip_thread. + + 2007-05-23 Frédéric Bernon + * api_lib.c, sockets.c: Fixed bug #5958 for netconn_listen (acceptmbox only + allocated by do_listen if success) and netconn_accept errors handling. In + most of api_lib functions, we replace some errors checkings like "if (conn==NULL)" + by ASSERT, except for netconn_delete. + + 2007-05-23 Frédéric Bernon + * api_lib.c: Fixed bug #5957 "Safe-thread problem inside netconn_recv" to return + an error code if it's impossible to fetch a pbuf on a TCP connection (and not + directly close the recvmbox). + + 2007-05-22 Simon Goldschmidt + * tcp.c: Fixed bug #1895 (tcp_bind not correct) by introducing a list of + bound but unconnected (and non-listening) tcp_pcbs. + + 2007-05-22 Frédéric Bernon + * sys.h, sys.c, api_lib.c, tcpip.c: remove sys_mbox_fetch_timeout() (was only + used for LWIP_SO_RCVTIMEO option) and use sys_arch_mbox_fetch() instead of + sys_mbox_fetch() in api files. Now, users SHOULD NOT use internal lwIP features + like "sys_timeout" in their application threads. + + 2007-05-22 Frédéric Bernon + * api.h, api_lib.c, api_msg.h, api_msg.c: change the struct api_msg_msg to see + which parameters are used by which do_xxx function, and to avoid "misusing" + parameters (patch #5938). + + 2007-05-22 Simon Goldschmidt + * api_lib.c, api_msg.c, raw.c, api.h, api_msg.h, raw.h: Included patch #5938: + changed raw_pcb.protocol from u16_t to u8_t since for IPv4 and IPv6, proto + is only 8 bits wide. This affects the api, as there, the protocol was + u16_t, too. + + 2007-05-18 Simon Goldschmidt + * memp.c: addition to patch #5913: smaller pointer was returned but + memp_memory was the same size -> did not save memory. + + 2007-05-16 Simon Goldschmidt + * loopif.c, slipif.c: Fix bug #19729: free pbuf if netif->input() returns + != ERR_OK. + + 2007-05-16 Simon Goldschmidt + * api_msg.c, udp.c: If a udp_pcb has a local_ip set, check if it is the same + as the one of the netif used for sending to prevent sending from old + addresses after a netif address gets changed (partly fixes bug #3168). + + 2007-05-16 Frédéric Bernon + * tcpip.c, igmp.h, igmp.c: Fixed bug "#19800 : IGMP: igmp_tick() will not work + with NO_SYS=1". Note that igmp_init is always in tcpip_thread (and not in + tcpip_init) because we have to be sure that network interfaces are already + added (mac filter is updated only in igmp_init for the moment). + + 2007-05-16 Simon Goldschmidt + * mem.c, memp.c: Removed semaphores from memp, changed sys_sem_wait calls + into sys_arch_sem_wait calls to prevent timers from running while waiting + for the heap. This fixes bug #19167. + + 2007-05-13 Simon Goldschmidt + * tcp.h, sockets.h, sockets.c: Fixed bug from patch #5865 by moving the defines + for socket options (lwip_set/-getsockopt) used with level IPPROTO_TCP from + tcp.h to sockets.h. + + 2007-05-07 Simon Goldschmidt + * mem.c: Another attempt to fix bug #17922. + + 2007-05-04 Simon Goldschmidt + * pbuf.c, pbuf.h, etharp.c: Further update to ARP queueing: Changed pbuf_copy() + implementation so that it can be reused (don't allocate the target + pbuf inside pbuf_copy()). + + 2007-05-04 Simon Goldschmidt + * memp.c: checked in patch #5913: in memp_malloc() we can return memp as mem + to save a little RAM (next pointer of memp is not used while not in pool). + + 2007-05-03 "maq" + * sockets.c: Fix ioctl FIONREAD when some data remains from last recv. + (patch #3574). + + 2007-04-23 Simon Goldschmidt + * loopif.c, loopif.h, opt.h, src/netif/FILES: fix bug #2595: "loopif results + in NULL reference for incoming TCP packets". Loopif has to be configured + (using LWIP_LOOPIF_MULTITHREADING) to directly call netif->input() + (multithreading environments, e.g. netif->input() = tcpip_input()) or + putting packets on a list that is fed to the stack by calling loopif_poll() + (single-thread / NO_SYS / polling environment where e.g. + netif->input() = ip_input). + + 2007-04-17 Jonathan Larmour + * pbuf.c: Use s32_t in pbuf_realloc(), as an s16_t can't reliably hold + the difference between two u16_t's. + * sockets.h: FD_SETSIZE needs to match number of sockets, which is + MEMP_NUM_NETCONN in sockets.c right now. + + 2007-04-12 Jonathan Larmour + * icmp.c: Reset IP header TTL in ICMP ECHO responses (bug #19580). + + 2007-04-12 Kieran Mansley + * tcp.c, tcp_in.c, tcp_out.c, tcp.h: Modify way the retransmission + timer is reset to fix bug#19434, with help from Oleg Tyshev. + + 2007-04-11 Simon Goldschmidt + * etharp.c, pbuf.c, pbuf.h: 3rd fix for bug #11400 (arp-queuing): More pbufs than + previously thought need to be copied (everything but PBUF_ROM!). Cleaned up + pbuf.c: removed functions no needed any more (by etharp). + + 2007-04-11 Kieran Mansley + * inet.c, ip_addr.h, sockets.h, sys.h, tcp.h: Apply patch #5745: Fix + "Constant is long" warnings with 16bit compilers. Contributed by + avatar@mmlab.cse.yzu.edu.tw + + 2007-04-05 Frédéric Bernon, Jonathan Larmour + * api_msg.c: Fix bug #16830: "err_tcp() posts to connection mailbox when no pend on + the mailbox is active". Now, the post is only done during a connect, and do_send, + do_write and do_join_leave_group don't do anything if a previous error was signaled. + + 2007-04-03 Frédéric Bernon + * ip.c: Don't set the IP_DF ("Don't fragment") flag in the IP header in IP output + packets. See patch #5834. + + 2007-03-30 Frédéric Bernon + * api_msg.c: add a "pcb_new" helper function to avoid redundant code, and to add + missing pcb allocations checking (in do_bind, and for each raw_new). Fix style. + + 2007-03-30 Frédéric Bernon + * most of files: prefix all debug.h define with "LWIP_" to avoid any conflict with + others environment defines (these were too "generic"). + + 2007-03-28 Frédéric Bernon + * api.h, api_lib.c, sockets.c: netbuf_ref doesn't check its internal pbuf_alloc call + result and can cause a crash. lwip_send now check netbuf_ref result. + + 2007-03-28 Simon Goldschmidt + * sockets.c Remove "#include " from sockets.c to avoid multiple + definition of macros (in errno.h and lwip/arch.h) if LWIP_PROVIDE_ERRNO is + defined. This is the way it should have been already (looking at + doc/sys_arch.txt) + + 2007-03-28 Kieran Mansley + * opt.h Change default PBUF_POOL_BUFSIZE (again) to accomodate default MSS + + IP and TCP headers *and* physical link headers + + 2007-03-26 Frédéric Bernon (based on patch from Dmitry Potapov) + * api_lib.c: patch for netconn_write(), fixes a possible race condition which cause + to send some garbage. It is not a definitive solution, but the patch does solve + the problem for most cases. + + 2007-03-22 Frédéric Bernon + * api_msg.h, api_msg.c: Remove obsolete API_MSG_ACCEPT and do_accept (never used). + + 2007-03-22 Frédéric Bernon + * api_lib.c: somes resources couldn't be freed if there was errors during + netconn_new_with_proto_and_callback. + + 2007-03-22 Frédéric Bernon + * ethernetif.c: update netif->input calls to check return value. In older ports, + it's a good idea to upgrade them, even if before, there could be another problem + (access to an uninitialized mailbox). + + 2007-03-21 Simon Goldschmidt + * sockets.c: fixed bug #5067 (essentialy a signed/unsigned warning fixed + by casting to unsigned). + + 2007-03-21 Frédéric Bernon + * api_lib.c, api_msg.c, tcpip.c: integrate sys_mbox_fetch(conn->mbox, NULL) calls from + api_lib.c to tcpip.c's tcpip_apimsg(). Now, use a local variable and not a + dynamic one from memp to send tcpip_msg to tcpip_thread in a synchrone call. + Free tcpip_msg from tcpip_apimsg is not done in tcpip_thread. This give a + faster and more reliable communication between api_lib and tcpip. + + 2007-03-21 Frédéric Bernon + * opt.h: Add LWIP_NETIF_CALLBACK (to avoid compiler warning) and set it to 0. + + 2007-03-21 Frédéric Bernon + * api_msg.c, igmp.c, igmp.h: Fix C++ style comments + + 2007-03-21 Kieran Mansley + * opt.h Change default PBUF_POOL_BUFSIZE to accomodate default MSS + + IP and TCP headers + + 2007-03-21 Kieran Mansley + * Fix all uses of pbuf_header to check the return value. In some + cases just assert if it fails as I'm not sure how to fix them, but + this is no worse than before when they would carry on regardless + of the failure. + + 2007-03-21 Kieran Mansley + * sockets.c, igmp.c, igmp.h, memp.h: Fix C++ style comments and + comment out missing header include in icmp.c + + 2007-03-20 Frédéric Bernon + * memp.h, stats.c: Fix stats_display function where memp_names table wasn't + synchronized with memp.h. + + 2007-03-20 Frédéric Bernon + * tcpip.c: Initialize tcpip's mbox, and verify if initialized in tcpip_input, + tcpip_ethinput, tcpip_callback, tcpip_apimsg, to fix a init problem with + network interfaces. Also fix a compiler warning. + + 2007-03-20 Kieran Mansley + * udp.c: Only try and use pbuf_header() to make space for headers if + not a ROM or REF pbuf. + + 2007-03-19 Frédéric Bernon + * api_msg.h, api_msg.c, tcpip.h, tcpip.c: Add return types to tcpip_apimsg() + and api_msg_post(). + + 2007-03-19 Frédéric Bernon + * Remove unimplemented "memp_realloc" function from memp.h. + + 2007-03-11 Simon Goldschmidt + * pbuf.c: checked in patch #5796: pbuf_alloc: len field claculation caused + memory corruption. + + 2007-03-11 Simon Goldschmidt (based on patch from Dmitry Potapov) + * api_lib.c, sockets.c, api.h, api_msg.h, sockets.h: Fixed bug #19251 + (missing `const' qualifier in socket functions), to get more compatible to + standard POSIX sockets. + + 2007-03-11 Frédéric Bernon (based on patch from Dmitry Potapov) + * sockets.c: Add asserts inside bind, connect and sendto to check input + parameters. Remove excessive set_errno() calls after get_socket(), because + errno is set inside of get_socket(). Move last sock_set_errno() inside + lwip_close. + + 2007-03-09 Simon Goldschmidt + * memp.c: Fixed bug #11400: New etharp queueing introduced bug: memp_memory + was allocated too small. + + 2007-03-06 Simon Goldschmidt + * tcpip.c: Initialize dhcp timers in tcpip_thread (if LWIP_DHCP) to protect + the stack from concurrent access. + + 2007-03-06 Frédéric Bernon, Dmitry Potapov + * tcpip.c, ip_frag.c, ethernetif.c: Fix some build problems, and a redundancy + call to "lwip_stats.link.recv++;" in low_level_input() & ethernetif_input(). + + 2007-03-06 Simon Goldschmidt + * ip_frag.c, ip_frag.h: Reduce code size: don't include code in those files + if IP_FRAG == 0 and IP_REASSEMBLY == 0 + + 2007-03-06 Frédéric Bernon, Simon Goldschmidt + * opt.h, ip_frag.h, tcpip.h, tcpip.c, ethernetif.c: add new configuration + option named ETHARP_TCPIP_ETHINPUT, which enable the new tcpip_ethinput. + Allow to do ARP processing for incoming packets inside tcpip_thread + (protecting ARP layer against concurrent access). You can also disable + old code using tcp_input with new define ETHARP_TCPIP_INPUT set to 0. + Older ports have to use tcpip_ethinput. + + 2007-03-06 Simon Goldschmidt (based on patch from Dmitry Potapov) + * err.h, err.c: fixed compiler warning "initialization dircards qualifiers + from pointer target type" + + 2007-03-05 Frédéric Bernon + * opt.h, sockets.h: add new configuration options (LWIP_POSIX_SOCKETS_IO_NAMES, + ETHARP_TRUST_IP_MAC, review SO_REUSE) + + 2007-03-04 Frédéric Bernon + * api_msg.c: Remove some compiler warnings : parameter "pcb" was never + referenced. + + 2007-03-04 Frédéric Bernon + * api_lib.c: Fix "[patch #5764] api_lib.c cleanup: after patch #5687" (from + Dmitry Potapov). + The api_msg struct stay on the stack (not moved to netconn struct). + + 2007-03-04 Simon Goldschmidt (based on patch from Dmitry Potapov) + * pbuf.c: Fix BUG#19168 - pbuf_free can cause deadlock (if + SYS_LIGHTWEIGHT_PROT=1 & freeing PBUF_RAM when mem_sem is not available) + Also fixed cast warning in pbuf_alloc() + + 2007-03-04 Simon Goldschmidt + * etharp.c, etharp.h, memp.c, memp.h, opt.h: Fix BUG#11400 - don't corrupt + existing pbuf chain when enqueuing multiple pbufs to a pending ARP request + + 2007-03-03 Frédéric Bernon + * udp.c: remove obsolete line "static struct udp_pcb *pcb_cache = NULL;" + It is static, and never used in udp.c except udp_init(). + + 2007-03-02 Simon Goldschmidt + * tcpip.c: Moved call to ip_init(), udp_init() and tcp_init() from + tcpip_thread() to tcpip_init(). This way, raw API connections can be + initialized before tcpip_thread is running (e.g. before OS is started) + + 2007-03-02 Frédéric Bernon + * rawapi.txt: Fix documentation mismatch with etharp.h about etharp_tmr's call + interval. + + 2007-02-28 Kieran Mansley + * pbuf.c: Fix BUG#17645 - ensure pbuf payload pointer is not moved + outside the region of the pbuf by pbuf_header() + + 2007-02-28 Kieran Mansley + * sockets.c: Fix BUG#19161 - ensure milliseconds timeout is non-zero + when supplied timeout is also non-zero + +(STABLE-1.2.0) + + 2006-12-05 Leon Woestenberg + * CHANGELOG: Mention STABLE-1.2.0 release. + + ++ New features: + + 2006-12-01 Christiaan Simons + * mem.h, opt.h: Added MEM_LIBC_MALLOC option. + Note this is a workaround. Currently I have no other options left. + + 2006-10-26 Christiaan Simons (accepted patch by Jonathan Larmour) + * ipv4/ip_frag.c: rename MAX_MTU to IP_FRAG_MAX_MTU and move define + to include/lwip/opt.h. + * ipv4/lwip/ip_frag.h: Remove unused IP_REASS_INTERVAL. + Move IP_REASS_MAXAGE and IP_REASS_BUFSIZE to include/lwip/opt.h. + * opt.h: Add above new options. + + 2006-08-18 Christiaan Simons + * tcp_{in,out}.c: added SNMP counters. + * ipv4/ip.c: added SNMP counters. + * ipv4/ip_frag.c: added SNMP counters. + + 2006-08-08 Christiaan Simons + * etharp.{c,h}: added etharp_find_addr() to read + (stable) ethernet/IP address pair from ARP table + + 2006-07-14 Christiaan Simons + * mib_structs.c: added + * include/lwip/snmp_structs.h: added + * netif.{c,h}, netif/ethernetif.c: added SNMP statistics to netif struct + + 2006-07-06 Christiaan Simons + * snmp/asn1_{enc,dec}.c added + * snmp/mib2.c added + * snmp/msg_{in,out}.c added + * include/lwip/snmp_asn1.h added + * include/lwip/snmp_msg.h added + * doc/snmp_agent.txt added + + 2006-03-29 Christiaan Simons + * inet.c, inet.h: Added platform byteswap support. + Added LWIP_PLATFORM_BYTESWAP define (defaults to 0) and + optional LWIP_PLATFORM_HTONS(), LWIP_PLATFORM_HTONL() macros. + + ++ Bug fixes: + + 2006-11-30 Christiaan Simons + * dhcp.c: Fixed false triggers of request_timeout. + + 2006-11-28 Christiaan Simons + * netif.c: In netif_add() fixed missing clear of ip_addr, netmask, gw and flags. + + 2006-10-11 Christiaan Simons + * api_lib.c etharp.c, ip.c, memp.c, stats.c, sys.{c,h} tcp.h: + Partially accepted patch #5449 for ANSI C compatibility / build fixes. + * ipv4/lwip/ip.h ipv6/lwip/ip.h: Corrected UDP-Lite protocol + identifier from 170 to 136 (bug #17574). + + 2006-10-10 Christiaan Simons + * api_msg.c: Fixed Nagle algorithm as reported by Bob Grice. + + 2006-08-17 Christiaan Simons + * udp.c: Fixed bug #17200, added check for broadcast + destinations for PCBs bound to a unicast address. + + 2006-08-07 Christiaan Simons + * api_msg.c: Flushing TCP output in do_close() (bug #15926). + + 2006-06-27 Christiaan Simons + * api_msg.c: Applied patch for cold case (bug #11135). + In accept_function() ensure newconn->callback is always initialized. + + 2006-06-15 Christiaan Simons + * mem.h: added MEM_SIZE_F alias to fix an ancient cold case (bug #1748), + facilitate printing of mem_size_t and u16_t statistics. + + 2006-06-14 Christiaan Simons + * api_msg.c: Applied patch #5146 to handle allocation failures + in accept() by Kevin Lawson. + + 2006-05-26 Christiaan Simons + * api_lib.c: Removed conn->sem creation and destruction + from netconn_write() and added sys_sem_new to netconn_new_*. + +(STABLE-1_1_1) + + 2006-03-03 Christiaan Simons + * ipv4/ip_frag.c: Added bound-checking assertions on ip_reassbitmap + access and added pbuf_alloc() return value checks. + + 2006-01-01 Leon Woestenberg + * tcp_{in,out}.c, tcp_out.c: Removed 'even sndbuf' fix in TCP, which is + now handled by the checksum routine properly. + + 2006-02-27 Leon Woestenberg + * pbuf.c: Fix alignment; pbuf_init() would not work unless + pbuf_pool_memory[] was properly aligned. (Patch by Curt McDowell.) + + 2005-12-20 Leon Woestenberg + * tcp.c: Remove PCBs which stay in LAST_ACK state too long. Patch + submitted by Mitrani Hiroshi. + + 2005-12-15 Christiaan Simons + * inet.c: Disabled the added summing routine to preserve code space. + + 2005-12-14 Leon Woestenberg + * tcp_in.c: Duplicate FIN ACK race condition fix by Kelvin Lawson. + Added Curt McDowell's optimized checksumming routine for future + inclusion. Need to create test case for unaliged, aligned, odd, + even length combination of cases on various endianess machines. + + 2005-12-09 Christiaan Simons + * inet.c: Rewrote standard checksum routine in proper portable C. + + 2005-11-25 Christiaan Simons + * udp.c tcp.c: Removed SO_REUSE hack. Should reside in socket code only. + * *.c: introduced cc.h LWIP_DEBUG formatters matching the u16_t, s16_t, + u32_t, s32_t typedefs. This solves most debug word-length assumes. + + 2005-07-17 Leon Woestenberg + * inet.c: Fixed unaligned 16-bit access in the standard checksum + routine by Peter Jolasson. + * slipif.c: Fixed implementation assumption of single-pbuf datagrams. + + 2005-02-04 Leon Woestenberg + * tcp_out.c: Fixed uninitialized 'queue' referenced in memerr branch. + * tcp_{out|in}.c: Applied patch fixing unaligned access. + + 2005-01-04 Leon Woestenberg + * pbuf.c: Fixed missing semicolon after LWIP_DEBUG statement. + + 2005-01-03 Leon Woestenberg + * udp.c: UDP pcb->recv() was called even when it was NULL. + +(STABLE-1_1_0) + + 2004-12-28 Leon Woestenberg + * etharp.*: Disabled multiple packets on the ARP queue. + This clashes with TCP queueing. + + 2004-11-28 Leon Woestenberg + * etharp.*: Fixed race condition from ARP request to ARP timeout. + Halved the ARP period, doubled the period counts. + ETHARP_MAX_PENDING now should be at least 2. This prevents + the counter from reaching 0 right away (which would allow + too little time for ARP responses to be received). + + 2004-11-25 Leon Woestenberg + * dhcp.c: Decline messages were not multicast but unicast. + * etharp.c: ETHARP_CREATE is renamed to ETHARP_TRY_HARD. + Do not try hard to insert arbitrary packet's source address, + etharp_ip_input() now calls etharp_update() without ETHARP_TRY_HARD. + etharp_query() now always DOES call ETHARP_TRY_HARD so that users + querying an address will see it appear in the cache (DHCP could + suffer from this when a server invalidly gave an in-use address.) + * ipv4/ip_addr.h: Renamed ip_addr_maskcmp() to _netcmp() as we are + comparing network addresses (identifiers), not the network masks + themselves. + * ipv4/ip_addr.c: ip_addr_isbroadcast() now checks that the given + IP address actually belongs to the network of the given interface. + + 2004-11-24 Kieran Mansley + * tcp.c: Increment pcb->snd_buf when ACK is received in SYN_SENT state. + +(STABLE-1_1_0-RC1) + + 2004-10-16 Kieran Mansley + * tcp.c: Add code to tcp_recved() to send an ACK (window update) immediately, + even if one is already pending, if the rcv_wnd is above a threshold + (currently TCP_WND/2). This avoids waiting for a timer to expire to send a + delayed ACK in order to open the window if the stack is only receiving data. + + 2004-09-12 Kieran Mansley + * tcp*.*: Retransmit time-out handling improvement by Sam Jansen. + + 2004-08-20 Tony Mountifield + * etharp.c: Make sure the first pbuf queued on an ARP entry + is properly ref counted. + + 2004-07-27 Tony Mountifield + * debug.h: Added (int) cast in LWIP_DEBUGF() to avoid compiler + warnings about comparison. + * pbuf.c: Stopped compiler complaining of empty if statement + when LWIP_DEBUGF() empty. Closed an unclosed comment. + * tcp.c: Stopped compiler complaining of empty if statement + when LWIP_DEBUGF() empty. + * ip.h Corrected IPH_TOS() macro: returns a byte, so doesn't need htons(). + * inet.c: Added a couple of casts to quiet the compiler. + No need to test isascii(c) before isdigit(c) or isxdigit(c). + + 2004-07-22 Tony Mountifield + * inet.c: Made data types consistent in inet_ntoa(). + Added casts for return values of checksum routines, to pacify compiler. + * ip_frag.c, tcp_out.c, sockets.c, pbuf.c + Small corrections to some debugging statements, to pacify compiler. + + 2004-07-21 Tony Mountifield + * etharp.c: Removed spurious semicolon and added missing end-of-comment. + * ethernetif.c Updated low_level_output() to match prototype for + netif->linkoutput and changed low_level_input() similarly for consistency. + * api_msg.c: Changed recv_raw() from int to u8_t, to match prototype + of raw_recv() in raw.h and so avoid compiler error. + * sockets.c: Added trivial (int) cast to keep compiler happier. + * ip.c, netif.c Changed debug statements to use the tidier ip4_addrN() macros. + +(STABLE-1_0_0) + + ++ Changes: + + 2004-07-05 Leon Woestenberg + * sockets.*: Restructured LWIP_PRIVATE_TIMEVAL. Make sure + your cc.h file defines this either 1 or 0. If non-defined, + defaults to 1. + * .c: Added and includes where used. + * etharp.c: Made some array indices unsigned. + + 2004-06-27 Leon Woestenberg + * netif.*: Added netif_set_up()/down(). + * dhcp.c: Changes to restart program flow. + + 2004-05-07 Leon Woestenberg + * etharp.c: In find_entry(), instead of a list traversal per candidate, do a + single-pass lookup for different candidates. Should exploit locality. + + 2004-04-29 Leon Woestenberg + * tcp*.c: Cleaned up source comment documentation for Doxygen processing. + * opt.h: ETHARP_ALWAYS_INSERT option removed to comply with ARP RFC. + * etharp.c: update_arp_entry() only adds new ARP entries when adviced to by + the caller. This deprecates the ETHARP_ALWAYS_INSERT overrule option. + + ++ Bug fixes: + + 2004-04-27 Leon Woestenberg + * etharp.c: Applied patch of bug #8708 by Toni Mountifield with a solution + suggested by Timmy Brolin. Fix for 32-bit processors that cannot access + non-aligned 32-bit words, such as soms 32-bit TCP/IP header fields. Fix + is to prefix the 14-bit Ethernet headers with two padding bytes. + + 2004-04-23 Leon Woestenberg + * ip_addr.c: Fix in the ip_addr_isbroadcast() check. + * etharp.c: Fixed the case where the packet that initiates the ARP request + is not queued, and gets lost. Fixed the case where the packets destination + address is already known; we now always queue the packet and perform an ARP + request. + +(STABLE-0_7_0) + + ++ Bug fixes: + + * Fixed TCP bug for SYN_SENT to ESTABLISHED state transition. + * Fixed TCP bug in dequeueing of FIN from out of order segment queue. + * Fixed two possible NULL references in rare cases. + +(STABLE-0_6_6) + + ++ Bug fixes: + + * Fixed DHCP which did not include the IP address in DECLINE messages. + + ++ Changes: + + * etharp.c has been hauled over a bit. + +(STABLE-0_6_5) + + ++ Bug fixes: + + * Fixed TCP bug induced by bad window resizing with unidirectional TCP traffic. + * Packets sent from ARP queue had invalid source hardware address. + + ++ Changes: + + * Pass-by ARP requests do now update the cache. + + ++ New features: + + * No longer dependent on ctype.h. + * New socket options. + * Raw IP pcb support. + +(STABLE-0_6_4) + + ++ Bug fixes: + + * Some debug formatters and casts fixed. + * Numereous fixes in PPP. + + ++ Changes: + + * DEBUGF now is LWIP_DEBUGF + * pbuf_dechain() has been re-enabled. + * Mentioned the changed use of CVS branches in README. + +(STABLE-0_6_3) + + ++ Bug fixes: + + * Fixed pool pbuf memory leak in pbuf_alloc(). + Occured if not enough PBUF_POOL pbufs for a packet pbuf chain. + Reported by Savin Zlobec. + + * PBUF_POOL chains had their tot_len field not set for non-first + pbufs. Fixed in pbuf_alloc(). + + ++ New features: + + * Added PPP stack contributed by Marc Boucher + + ++ Changes: + + * Now drops short packets for ICMP/UDP/TCP protocols. More robust. + + * ARP queueuing now queues the latest packet instead of the first. + This is the RFC recommended behaviour, but can be overridden in + lwipopts.h. + +(0.6.2) + + ++ Bugfixes: + + * TCP has been fixed to deal with the new use of the pbuf->ref + counter. + + * DHCP dhcp_inform() crash bug fixed. + + ++ Changes: + + * Removed pbuf_pool_free_cache and pbuf_pool_alloc_cache. Also removed + pbuf_refresh(). This has sped up pbuf pool operations considerably. + Implemented by David Haas. + +(0.6.1) + + ++ New features: + + * The packet buffer implementation has been enhanced to support + zero-copy and copy-on-demand for packet buffers which have their + payloads in application-managed memory. + Implemented by David Haas. + + Use PBUF_REF to make a pbuf refer to RAM. lwIP will use zero-copy + if an outgoing packet can be directly sent on the link, or perform + a copy-on-demand when necessary. + + The application can safely assume the packet is sent, and the RAM + is available to the application directly after calling udp_send() + or similar function. + + ++ Bugfixes: + + * ARP_QUEUEING should now correctly work for all cases, including + PBUF_REF. + Implemented by Leon Woestenberg. + + ++ Changes: + + * IP_ADDR_ANY is no longer a NULL pointer. Instead, it is a pointer + to a '0.0.0.0' IP address. + + * The packet buffer implementation is changed. The pbuf->ref counter + meaning has changed, and several pbuf functions have been + adapted accordingly. + + * netif drivers have to be changed to set the hardware address length field + that must be initialized correctly by the driver (hint: 6 for Ethernet MAC). + See the contrib/ports/c16x cs8900 driver as a driver example. + + * netif's have a dhcp field that must be initialized to NULL by the driver. + See the contrib/ports/c16x cs8900 driver as a driver example. + +(0.5.x) This file has been unmaintained up to 0.6.1. All changes are + logged in CVS but have not been explained here. + +(0.5.3) Changes since version 0.5.2 + + ++ Bugfixes: + + * memp_malloc(MEMP_API_MSG) could fail with multiple application + threads because it wasn't protected by semaphores. + + ++ Other changes: + + * struct ip_addr now packed. + + * The name of the time variable in arp.c has been changed to ctime + to avoid conflicts with the time() function. + +(0.5.2) Changes since version 0.5.1 + + ++ New features: + + * A new TCP function, tcp_tmr(), now handles both TCP timers. + + ++ Bugfixes: + + * A bug in tcp_parseopt() could cause the stack to hang because of a + malformed TCP option. + + * The address of new connections in the accept() function in the BSD + socket library was not handled correctly. + + * pbuf_dechain() did not update the ->tot_len field of the tail. + + * Aborted TCP connections were not handled correctly in all + situations. + + ++ Other changes: + + * All protocol header structs are now packed. + + * The ->len field in the tcp_seg structure now counts the actual + amount of data, and does not add one for SYN and FIN segments. + +(0.5.1) Changes since version 0.5.0 + + ++ New features: + + * Possible to run as a user process under Linux. + + * Preliminary support for cross platform packed structs. + + * ARP timer now implemented. + + ++ Bugfixes: + + * TCP output queue length was badly initialized when opening + connections. + + * TCP delayed ACKs were not sent correctly. + + * Explicit initialization of BSS segment variables. + + * read() in BSD socket library could drop data. + + * Problems with memory alignment. + + * Situations when all TCP buffers were used could lead to + starvation. + + * TCP MSS option wasn't parsed correctly. + + * Problems with UDP checksum calculation. + + * IP multicast address tests had endianess problems. + + * ARP requests had wrong destination hardware address. + + ++ Other changes: + + * struct eth_addr changed from u16_t[3] array to u8_t[6]. + + * A ->linkoutput() member was added to struct netif. + + * TCP and UDP ->dest_* struct members where changed to ->remote_*. + + * ntoh* macros are now null definitions for big endian CPUs. + +(0.5.0) Changes since version 0.4.2 + + ++ New features: + + * Redesigned operating system emulation layer to make porting easier. + + * Better control over TCP output buffers. + + * Documenation added. + + ++ Bugfixes: + + * Locking issues in buffer management. + + * Bugfixes in the sequential API. + + * IP forwarding could cause memory leakage. This has been fixed. + + ++ Other changes: + + * Directory structure somewhat changed; the core/ tree has been + collapsed. + +(0.4.2) Changes since version 0.4.1 + + ++ New features: + + * Experimental ARP implementation added. + + * Skeleton Ethernet driver added. + + * Experimental BSD socket API library added. + + ++ Bugfixes: + + * In very intense situations, memory leakage could occur. This has + been fixed. + + ++ Other changes: + + * Variables named "data" and "code" have been renamed in order to + avoid name conflicts in certain compilers. + + * Variable++ have in appliciable cases been translated to ++variable + since some compilers generate better code in the latter case. + +(0.4.1) Changes since version 0.4 + + ++ New features: + + * TCP: Connection attempts time out earlier than data + transmissions. Nagle algorithm implemented. Push flag set on the + last segment in a burst. + + * UDP: experimental support for UDP-Lite extensions. + + ++ Bugfixes: + + * TCP: out of order segments were in some cases handled incorrectly, + and this has now been fixed. Delayed acknowledgements was broken + in 0.4, has now been fixed. Binding to an address that is in use + now results in an error. Reset connections sometimes hung an + application; this has been fixed. + + * Checksum calculation sometimes failed for chained pbufs with odd + lengths. This has been fixed. + + * API: a lot of bug fixes in the API. The UDP API has been improved + and tested. Error reporting and handling has been + improved. Logical flaws and race conditions for incoming TCP + connections has been found and removed. + + * Memory manager: alignment issues. Reallocating memory sometimes + failed, this has been fixed. + + * Generic library: bcopy was flawed and has been fixed. + + ++ Other changes: + + * API: all datatypes has been changed from generic ones such as + ints, to specified ones such as u16_t. Functions that return + errors now have the correct type (err_t). + + * General: A lot of code cleaned up and debugging code removed. Many + portability issues have been fixed. + + * The license was changed; the advertising clause was removed. + + * C64 port added. + + * Thanks: Huge thanks go to Dagan Galarneau, Horst Garnetzke, Petri + Kosunen, Mikael Caleres, and Frits Wilmink for reporting and + fixing bugs! + +(0.4) Changes since version 0.3.1 + + * Memory management has been radically changed; instead of + allocating memory from a shared heap, memory for objects that are + rapidly allocated and deallocated is now kept in pools. Allocation + and deallocation from those memory pools is very fast. The shared + heap is still present but is used less frequently. + + * The memory, memory pool, and packet buffer subsystems now support + 4-, 2-, or 1-byte alignment. + + * "Out of memory" situations are handled in a more robust way. + + * Stack usage has been reduced. + + * Easier configuration of lwIP parameters such as memory usage, + TTLs, statistics gathering, etc. All configuration parameters are + now kept in a single header file "lwipopts.h". + + * The directory structure has been changed slightly so that all + architecture specific files are kept under the src/arch + hierarchy. + + * Error propagation has been improved, both in the protocol modules + and in the API. + + * The code for the RTXC architecture has been implemented, tested + and put to use. + + * Bugs have been found and corrected in the TCP, UDP, IP, API, and + the Internet checksum modules. + + * Bugs related to porting between a 32-bit and a 16-bit architecture + have been found and corrected. + + * The license has been changed slightly to conform more with the + original BSD license, including the advertisement clause. + +(0.3.1) Changes since version 0.3 + + * Fix of a fatal bug in the buffer management. Pbufs with allocated + RAM never returned the RAM when the pbuf was deallocated. + + * TCP congestion control, window updates and retransmissions did not + work correctly. This has now been fixed. + + * Bugfixes in the API. + +(0.3) Changes since version 0.2 + + * New and improved directory structure. All include files are now + kept in a dedicated include/ directory. + + * The API now has proper error handling. A new function, + netconn_err(), now returns an error code for the connection in + case of errors. + + * Improvements in the memory management subsystem. The system now + keeps a pointer to the lowest free memory block. A new function, + mem_malloc2() tries to allocate memory once, and if it fails tries + to free some memory and retry the allocation. + + * Much testing has been done with limited memory + configurations. lwIP now does a better job when overloaded. + + * Some bugfixes and improvements to the buffer (pbuf) subsystem. + + * Many bugfixes in the TCP code: + + - Fixed a bug in tcp_close(). + + - The TCP receive window was incorrectly closed when out of + sequence segments was received. This has been fixed. + + - Connections are now timed-out of the FIN-WAIT-2 state. + + - The initial congestion window could in some cases be too + large. This has been fixed. + + - The retransmission queue could in some cases be screwed up. This + has been fixed. + + - TCP RST flag now handled correctly. + + - Out of sequence data was in some cases never delivered to the + application. This has been fixed. + + - Retransmitted segments now contain the correct acknowledgment + number and advertised window. + + - TCP retransmission timeout backoffs are not correctly computed + (ala BSD). After a number of retransmissions, TCP now gives up + the connection. + + * TCP connections now are kept on three lists, one for active + connections, one for listening connections, and one for + connections that are in TIME-WAIT. This greatly speeds up the fast + timeout processing for sending delayed ACKs. + + * TCP now provides proper feedback to the application when a + connection has been successfully set up. + + * More comments have been added to the code. The code has also been + somewhat cleaned up. + +(0.2) Initial public release. diff --git a/components/lwip/COPYING b/components/lwip/COPYING new file mode 100755 index 0000000000..e23898b5e8 --- /dev/null +++ b/components/lwip/COPYING @@ -0,0 +1,33 @@ +/* + * Copyright (c) 2001, 2002 Swedish Institute of Computer Science. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + * + */ + + diff --git a/components/lwip/Kconfig b/components/lwip/Kconfig new file mode 100644 index 0000000000..ee6511e00c --- /dev/null +++ b/components/lwip/Kconfig @@ -0,0 +1,14 @@ +menu "LWIP" + +config LWIP_MAX_SOCKETS + int "Max number of open sockets" + range 1 16 + default 4 + help + Sockets take up a certain amount of memory, and allowing fewer + sockets to be open at the same time conserves memory. Specify + the maximum amount of sockets here. + +endmenu + + diff --git a/components/lwip/Makefile b/components/lwip/Makefile new file mode 100755 index 0000000000..b2de346b21 --- /dev/null +++ b/components/lwip/Makefile @@ -0,0 +1,16 @@ +# +# Component Makefile +# +# This Makefile should, at the very least, just include $(SDK_PATH)/make/component.mk. By default, +# this will take the sources in this directory, compile them and link them into +# lib(subdirectory_name).a in the build directory. This behaviour is entirely configurable, +# please read the SDK documents if you need to do this. +# + +COMPONENT_ADD_INCLUDEDIRS := include/lwip include/lwip/port + +COMPONENT_SRCDIRS := api apps core/ipv4 core/ipv6 core netif port/freertos port/netif port + +EXTRA_CFLAGS := -Wno-error=address -Waddress -DLWIP_ESP8266 + +include $(SDK_PATH)/make/component.mk diff --git a/components/lwip/README b/components/lwip/README new file mode 100755 index 0000000000..495556ef2c --- /dev/null +++ b/components/lwip/README @@ -0,0 +1,86 @@ +INTRODUCTION + +lwIP is a small independent implementation of the TCP/IP protocol +suite that has been developed by Adam Dunkels at the Computer and +Networks Architectures (CNA) lab at the Swedish Institute of Computer +Science (SICS). + +The focus of the lwIP TCP/IP implementation is to reduce the RAM usage +while still having a full scale TCP. This making lwIP suitable for use +in embedded systems with tens of kilobytes of free RAM and room for +around 40 kilobytes of code ROM. + +FEATURES + + * IP (Internet Protocol) including packet forwarding over multiple network + interfaces + * ICMP (Internet Control Message Protocol) for network maintenance and debugging + * IGMP (Internet Group Management Protocol) for multicast traffic management + * UDP (User Datagram Protocol) including experimental UDP-lite extensions + * TCP (Transmission Control Protocol) with congestion control, RTT estimation + and fast recovery/fast retransmit + * Specialized raw/native API for enhanced performance + * Optional Berkeley-like socket API + * DNS (Domain names resolver) + * SNMP (Simple Network Management Protocol) + * DHCP (Dynamic Host Configuration Protocol) + * AUTOIP (for IPv4, conform with RFC 3927) + * PPP (Point-to-Point Protocol) + * ARP (Address Resolution Protocol) for Ethernet + +LICENSE + +lwIP is freely available under a BSD license. + +DEVELOPMENT + +lwIP has grown into an excellent TCP/IP stack for embedded devices, +and developers using the stack often submit bug fixes, improvements, +and additions to the stack to further increase its usefulness. + +Development of lwIP is hosted on Savannah, a central point for +software development, maintenance and distribution. Everyone can +help improve lwIP by use of Savannah's interface, Git and the +mailing list. A core team of developers will commit changes to the +Git source tree. + +The lwIP TCP/IP stack is maintained in the 'lwip' Git module and +contributions (such as platform ports) are in the 'contrib' Git module. + +See doc/savannah.txt for details on Git server access for users and +developers. + +The current Git trees are web-browsable: + http://git.savannah.gnu.org/cgit/lwip.git + http://git.savannah.gnu.org/cgit/lwip/lwip-contrib.git + +Submit patches and bugs via the lwIP project page: + http://savannah.nongnu.org/projects/lwip/ + + +DOCUMENTATION + +The original out-dated homepage of lwIP and Adam Dunkels' papers on +lwIP are at the official lwIP home page: + http://www.sics.se/~adam/lwip/ + +Self documentation of the source code is regularly extracted from the +current Git sources and is available from this web page: + http://www.nongnu.org/lwip/ + +There is now a constantly growin wiki about lwIP at + http://lwip.wikia.com/wiki/LwIP_Wiki + +Also, there are mailing lists you can subscribe at + http://savannah.nongnu.org/mail/?group=lwip +plus searchable archives: + http://lists.nongnu.org/archive/html/lwip-users/ + http://lists.nongnu.org/archive/html/lwip-devel/ + +Reading Adam's papers, the files in docs/, browsing the source code +documentation and browsing the mailing list archives is a good way to +become familiar with the design of lwIP. + +Adam Dunkels +Leon Woestenberg + diff --git a/components/lwip/VERSION b/components/lwip/VERSION new file mode 100644 index 0000000000..4276fd51ac --- /dev/null +++ b/components/lwip/VERSION @@ -0,0 +1 @@ +bf7fc41e \ No newline at end of file diff --git a/components/lwip/api/api_lib.c b/components/lwip/api/api_lib.c new file mode 100755 index 0000000000..c38c760811 --- /dev/null +++ b/components/lwip/api/api_lib.c @@ -0,0 +1,979 @@ +/** + * @file + * Sequential API External module + * + */ + +/* + * Copyright (c) 2001-2004 Swedish Institute of Computer Science. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + * + */ + +/* This is the part of the API that is linked with + the application */ + +#include "lwip/opt.h" + +#if LWIP_NETCONN /* don't build if not configured for use in lwipopts.h */ + +#include "lwip/api.h" +#include "lwip/memp.h" + +#include "lwip/ip.h" +#include "lwip/raw.h" +#include "lwip/udp.h" +#include "lwip/priv/api_msg.h" +#include "lwip/priv/tcp_priv.h" +#include "lwip/priv/tcpip_priv.h" + +#include + +#ifdef MEMLEAK_DEBUG +static const char mem_debug_file[] ICACHE_RODATA_ATTR STORE_ATTR = __FILE__; +#endif + + +#define API_MSG_VAR_REF(name) API_VAR_REF(name) +#define API_MSG_VAR_DECLARE(name) API_VAR_DECLARE(struct api_msg, name) +#define API_MSG_VAR_ALLOC(name) API_VAR_ALLOC(struct api_msg, MEMP_API_MSG, name) +#define API_MSG_VAR_ALLOC_DONTFAIL(name) API_VAR_ALLOC_DONTFAIL(struct api_msg, MEMP_API_MSG, name) +#define API_MSG_VAR_FREE(name) API_VAR_FREE(MEMP_API_MSG, name) + +static err_t netconn_close_shutdown(struct netconn *conn, u8_t how); + +#if !LWIP_TCPIP_CORE_LOCKING +/** + * Call the lower part of a netconn_* function + * This function is then running in the thread context + * of tcpip_thread and has exclusive access to lwIP core code. + * + * @param apimsg a struct containing the function to call and its parameters + * @return ERR_OK if the function was called, another err_t if not + */ +static err_t +tcpip_apimsg(struct api_msg *apimsg) +{ +#ifdef LWIP_DEBUG + /* catch functions that don't set err */ + apimsg->msg.err = ERR_VAL; +#endif +#if LWIP_NETCONN_SEM_PER_THREAD + apimsg->msg.op_completed_sem = LWIP_NETCONN_THREAD_SEM_GET(); + LWIP_ASSERT("netconn semaphore not initialized", + sys_sem_valid(apimsg->msg.op_completed_sem)); +#endif + + if (tcpip_send_api_msg(apimsg->function, &apimsg->msg, LWIP_API_MSG_SEM(&apimsg->msg)) == ERR_OK) { + return apimsg->msg.err; + } + + return ERR_VAL; +} +#endif /* !LWIP_TCPIP_CORE_LOCKING */ + +/** + * Create a new netconn (of a specific type) that has a callback function. + * The corresponding pcb is also created. + * + * @param t the type of 'connection' to create (@see enum netconn_type) + * @param proto the IP protocol for RAW IP pcbs + * @param callback a function to call on status changes (RX available, TX'ed) + * @return a newly allocated struct netconn or + * NULL on memory error + */ +struct netconn* +netconn_new_with_proto_and_callback(enum netconn_type t, u8_t proto, netconn_callback callback) +{ + struct netconn *conn; + API_MSG_VAR_DECLARE(msg); + + conn = netconn_alloc(t, callback); + if (conn != NULL) { + err_t err; + API_MSG_VAR_ALLOC_DONTFAIL(msg); + API_MSG_VAR_REF(msg).msg.msg.n.proto = proto; + API_MSG_VAR_REF(msg).msg.conn = conn; + TCPIP_APIMSG(&API_MSG_VAR_REF(msg), lwip_netconn_do_newconn, err); + API_MSG_VAR_FREE(msg); + if (err != ERR_OK) { + LWIP_ASSERT("freeing conn without freeing pcb", conn->pcb.tcp == NULL); + LWIP_ASSERT("conn has no recvmbox", sys_mbox_valid(&conn->recvmbox)); +#if LWIP_TCP + LWIP_ASSERT("conn->acceptmbox shouldn't exist", !sys_mbox_valid(&conn->acceptmbox)); +#endif /* LWIP_TCP */ +#if !LWIP_NETCONN_SEM_PER_THREAD + LWIP_ASSERT("conn has no op_completed", sys_sem_valid(&conn->op_completed)); + sys_sem_free(&conn->op_completed); +#endif /* !LWIP_NETCONN_SEM_PER_THREAD */ + sys_mbox_free(&conn->recvmbox); + memp_free(MEMP_NETCONN, conn); + return NULL; + } + } + return conn; +} + +/** + * Close a netconn 'connection' and free its resources. + * UDP and RAW connection are completely closed, TCP pcbs might still be in a waitstate + * after this returns. + * + * @param conn the netconn to delete + * @return ERR_OK if the connection was deleted + */ +err_t +netconn_delete(struct netconn *conn) +{ + err_t err; + API_MSG_VAR_DECLARE(msg); + + /* No ASSERT here because possible to get a (conn == NULL) if we got an accept error */ + if (conn == NULL) { + return ERR_OK; + } + + API_MSG_VAR_ALLOC(msg); + API_MSG_VAR_REF(msg).msg.conn = conn; +#if LWIP_SO_SNDTIMEO || LWIP_SO_LINGER + /* get the time we started, which is later compared to + sys_now() + conn->send_timeout */ + API_MSG_VAR_REF(msg).msg.msg.sd.time_started = sys_now(); +#else /* LWIP_SO_SNDTIMEO || LWIP_SO_LINGER */ +#if LWIP_TCP + API_MSG_VAR_REF(msg).msg.msg.sd.polls_left = + ((LWIP_TCP_CLOSE_TIMEOUT_MS_DEFAULT + TCP_SLOW_INTERVAL - 1) / TCP_SLOW_INTERVAL) + 1; +#endif /* LWIP_TCP */ +#endif /* LWIP_SO_SNDTIMEO || LWIP_SO_LINGER */ + TCPIP_APIMSG(&API_MSG_VAR_REF(msg), lwip_netconn_do_delconn, err); + API_MSG_VAR_FREE(msg); + + if (err != ERR_OK) { + return err; + } + +#if !LWIP_THREAD_SAFE + LWIP_DEBUGF(THREAD_SAFE_DEBUG, ("netconn_delete - free conn\n")); + netconn_free(conn); +#endif + + return ERR_OK; +} + +/** + * Get the local or remote IP address and port of a netconn. + * For RAW netconns, this returns the protocol instead of a port! + * + * @param conn the netconn to query + * @param addr a pointer to which to save the IP address + * @param port a pointer to which to save the port (or protocol for RAW) + * @param local 1 to get the local IP address, 0 to get the remote one + * @return ERR_CONN for invalid connections + * ERR_OK if the information was retrieved + */ +err_t +netconn_getaddr(struct netconn *conn, ip_addr_t *addr, u16_t *port, u8_t local) +{ + API_MSG_VAR_DECLARE(msg); + err_t err; + + LWIP_ERROR("netconn_getaddr: invalid conn", (conn != NULL), return ERR_ARG;); + LWIP_ERROR("netconn_getaddr: invalid addr", (addr != NULL), return ERR_ARG;); + LWIP_ERROR("netconn_getaddr: invalid port", (port != NULL), return ERR_ARG;); + + API_MSG_VAR_ALLOC(msg); + API_MSG_VAR_REF(msg).msg.conn = conn; + API_MSG_VAR_REF(msg).msg.msg.ad.local = local; +#if LWIP_MPU_COMPATIBLE + TCPIP_APIMSG(msg, lwip_netconn_do_getaddr, err); + *addr = msg->msg.msg.ad.ipaddr; + *port = msg->msg.msg.ad.port; +#else /* LWIP_MPU_COMPATIBLE */ + msg.msg.msg.ad.ipaddr = addr; + msg.msg.msg.ad.port = port; + TCPIP_APIMSG(&msg, lwip_netconn_do_getaddr, err); +#endif /* LWIP_MPU_COMPATIBLE */ + API_MSG_VAR_FREE(msg); + + return err; +} + +/** + * Bind a netconn to a specific local IP address and port. + * Binding one netconn twice might not always be checked correctly! + * + * @param conn the netconn to bind + * @param addr the local IP address to bind the netconn to (use IP_ADDR_ANY + * to bind to all addresses) + * @param port the local port to bind the netconn to (not used for RAW) + * @return ERR_OK if bound, any other err_t on failure + */ +err_t +netconn_bind(struct netconn *conn, const ip_addr_t *addr, u16_t port) +{ + API_MSG_VAR_DECLARE(msg); + err_t err; + + LWIP_ERROR("netconn_bind: invalid conn", (conn != NULL), return ERR_ARG;); + + /* Don't propagate NULL pointer (IP_ADDR_ANY alias) to subsequent functions */ + if (addr == NULL) { + addr = IP_ADDR_ANY; + } + + API_MSG_VAR_ALLOC(msg); + API_MSG_VAR_REF(msg).msg.conn = conn; + API_MSG_VAR_REF(msg).msg.msg.bc.ipaddr = API_MSG_VAR_REF(addr); + API_MSG_VAR_REF(msg).msg.msg.bc.port = port; + TCPIP_APIMSG(&API_MSG_VAR_REF(msg), lwip_netconn_do_bind, err); + API_MSG_VAR_FREE(msg); + + return err; +} + +/** + * Connect a netconn to a specific remote IP address and port. + * + * @param conn the netconn to connect + * @param addr the remote IP address to connect to + * @param port the remote port to connect to (no used for RAW) + * @return ERR_OK if connected, return value of tcp_/udp_/raw_connect otherwise + */ +err_t +netconn_connect(struct netconn *conn, const ip_addr_t *addr, u16_t port) +{ + API_MSG_VAR_DECLARE(msg); + err_t err; + + LWIP_ERROR("netconn_connect: invalid conn", (conn != NULL), return ERR_ARG;); + + /* Don't propagate NULL pointer (IP_ADDR_ANY alias) to subsequent functions */ + if (addr == NULL) { + addr = IP_ADDR_ANY; + } + + API_MSG_VAR_ALLOC(msg); + API_MSG_VAR_REF(msg).msg.conn = conn; + API_MSG_VAR_REF(msg).msg.msg.bc.ipaddr = API_MSG_VAR_REF(addr); + API_MSG_VAR_REF(msg).msg.msg.bc.port = port; + TCPIP_APIMSG(&API_MSG_VAR_REF(msg), lwip_netconn_do_connect, err); + API_MSG_VAR_FREE(msg); + + return err; +} + +/** + * Disconnect a netconn from its current peer (only valid for UDP netconns). + * + * @param conn the netconn to disconnect + * @return TODO: return value is not set here... + */ +err_t +netconn_disconnect(struct netconn *conn) +{ + API_MSG_VAR_DECLARE(msg); + err_t err; + + LWIP_ERROR("netconn_disconnect: invalid conn", (conn != NULL), return ERR_ARG;); + + API_MSG_VAR_ALLOC(msg); + API_MSG_VAR_REF(msg).msg.conn = conn; + TCPIP_APIMSG(&API_MSG_VAR_REF(msg), lwip_netconn_do_disconnect, err); + API_MSG_VAR_FREE(msg); + + return err; +} + +/** + * Set a TCP netconn into listen mode + * + * @param conn the tcp netconn to set to listen mode + * @param backlog the listen backlog, only used if TCP_LISTEN_BACKLOG==1 + * @return ERR_OK if the netconn was set to listen (UDP and RAW netconns + * don't return any error (yet?)) + */ +err_t +netconn_listen_with_backlog(struct netconn *conn, u8_t backlog) +{ +#if LWIP_TCP + API_MSG_VAR_DECLARE(msg); + err_t err; + + /* This does no harm. If TCP_LISTEN_BACKLOG is off, backlog is unused. */ + LWIP_UNUSED_ARG(backlog); + + LWIP_ERROR("netconn_listen: invalid conn", (conn != NULL), return ERR_ARG;); + + API_MSG_VAR_ALLOC(msg); + API_MSG_VAR_REF(msg).msg.conn = conn; +#if TCP_LISTEN_BACKLOG + API_MSG_VAR_REF(msg).msg.msg.lb.backlog = backlog; +#endif /* TCP_LISTEN_BACKLOG */ + TCPIP_APIMSG(&API_MSG_VAR_REF(msg), lwip_netconn_do_listen, err); + API_MSG_VAR_FREE(msg); + + return err; +#else /* LWIP_TCP */ + LWIP_UNUSED_ARG(conn); + LWIP_UNUSED_ARG(backlog); + return ERR_ARG; +#endif /* LWIP_TCP */ +} + +/** + * Accept a new connection on a TCP listening netconn. + * + * @param conn the TCP listen netconn + * @param new_conn pointer where the new connection is stored + * @return ERR_OK if a new connection has been received or an error + * code otherwise + */ +err_t +netconn_accept(struct netconn *conn, struct netconn **new_conn) +{ +#if LWIP_TCP + struct netconn *newconn; + err_t err; +#if TCP_LISTEN_BACKLOG + API_MSG_VAR_DECLARE(msg); +#endif /* TCP_LISTEN_BACKLOG */ + + LWIP_ERROR("netconn_accept: invalid pointer", (new_conn != NULL), return ERR_ARG;); + *new_conn = NULL; + LWIP_ERROR("netconn_accept: invalid conn", (conn != NULL), return ERR_ARG;); + LWIP_ERROR("netconn_accept: invalid acceptmbox", sys_mbox_valid(&conn->acceptmbox), return ERR_ARG;); + + err = conn->last_err; + if (ERR_IS_FATAL(err)) { + /* don't recv on fatal errors: this might block the application task + waiting on acceptmbox forever! */ + return err; + } + +#if LWIP_SO_RCVTIMEO + if (sys_arch_mbox_fetch(&conn->acceptmbox, (void **)&newconn, conn->recv_timeout) == SYS_ARCH_TIMEOUT) { + return ERR_TIMEOUT; + } +#else + sys_arch_mbox_fetch(&conn->acceptmbox, (void **)&newconn, 0); +#endif /* LWIP_SO_RCVTIMEO*/ + /* Register event with callback */ + API_EVENT(conn, NETCONN_EVT_RCVMINUS, 0); + + if (newconn == NULL) { + /* connection has been aborted */ + /* in this special case, we set the netconn error from application thread, as + on a ready-to-accept listening netconn, there should not be anything running + in tcpip_thread */ + NETCONN_SET_SAFE_ERR(conn, ERR_ABRT); + return ERR_ABRT; + } +#if TCP_LISTEN_BACKLOG + /* Let the stack know that we have accepted the connection. */ + API_MSG_VAR_ALLOC_DONTFAIL(msg); + API_MSG_VAR_REF(msg).msg.conn = conn; + /* don't care for the return value of lwip_netconn_do_recv */ + TCPIP_APIMSG_NOERR(&API_MSG_VAR_REF(msg), lwip_netconn_do_recv); + API_MSG_VAR_FREE(msg); +#endif /* TCP_LISTEN_BACKLOG */ + + *new_conn = newconn; + /* don't set conn->last_err: it's only ERR_OK, anyway */ + return ERR_OK; +#else /* LWIP_TCP */ + LWIP_UNUSED_ARG(conn); + LWIP_UNUSED_ARG(new_conn); + return ERR_ARG; +#endif /* LWIP_TCP */ +} + +/** + * Receive data: actual implementation that doesn't care whether pbuf or netbuf + * is received + * + * @param conn the netconn from which to receive data + * @param new_buf pointer where a new pbuf/netbuf is stored when received data + * @return ERR_OK if data has been received, an error code otherwise (timeout, + * memory error or another error) + */ +static err_t +netconn_recv_data(struct netconn *conn, void **new_buf) +{ + void *buf = NULL; + u16_t len; + err_t err; +#if LWIP_TCP + API_MSG_VAR_DECLARE(msg); +#endif /* LWIP_TCP */ + + LWIP_ERROR("netconn_recv: invalid pointer", (new_buf != NULL), return ERR_ARG;); + *new_buf = NULL; + LWIP_ERROR("netconn_recv: invalid conn", (conn != NULL), return ERR_ARG;); +#if LWIP_TCP +#if (LWIP_UDP || LWIP_RAW) + if (NETCONNTYPE_GROUP(conn->type) == NETCONN_TCP) +#endif /* (LWIP_UDP || LWIP_RAW) */ + { + if (!sys_mbox_valid(&conn->recvmbox)) { + /* This happens when calling this function after receiving FIN */ + return sys_mbox_valid(&conn->acceptmbox) ? ERR_CONN : ERR_CLSD; + } + } +#endif /* LWIP_TCP */ + LWIP_ERROR("netconn_recv: invalid recvmbox", sys_mbox_valid(&conn->recvmbox), return ERR_CONN;); + + err = conn->last_err; + if (ERR_IS_FATAL(err)) { + /* don't recv on fatal errors: this might block the application task + waiting on recvmbox forever! */ + /* @todo: this does not allow us to fetch data that has been put into recvmbox + before the fatal error occurred - is that a problem? */ + return err; + } + +#if LWIP_SO_RCVTIMEO + if (sys_arch_mbox_fetch(&conn->recvmbox, &buf, conn->recv_timeout) == SYS_ARCH_TIMEOUT) { + return ERR_TIMEOUT; + } +#else + sys_arch_mbox_fetch(&conn->recvmbox, &buf, 0); +#endif /* LWIP_SO_RCVTIMEO*/ + +#if LWIP_TCP +#if (LWIP_UDP || LWIP_RAW) + if (NETCONNTYPE_GROUP(conn->type) == NETCONN_TCP) +#endif /* (LWIP_UDP || LWIP_RAW) */ + { + if (!netconn_get_noautorecved(conn) || (buf == NULL)) { + /* Let the stack know that we have taken the data. */ + /* TODO: Speedup: Don't block and wait for the answer here + (to prevent multiple thread-switches). */ + API_MSG_VAR_ALLOC_DONTFAIL(msg); + API_MSG_VAR_REF(msg).msg.conn = conn; + if (buf != NULL) { + API_MSG_VAR_REF(msg).msg.msg.r.len = ((struct pbuf *)buf)->tot_len; + } else { + API_MSG_VAR_REF(msg).msg.msg.r.len = 1; + } + /* don't care for the return value of lwip_netconn_do_recv */ + TCPIP_APIMSG_NOERR(&API_MSG_VAR_REF(msg), lwip_netconn_do_recv); + API_MSG_VAR_FREE(msg); + } + + /* If we are closed, we indicate that we no longer wish to use the socket */ + if (buf == NULL) { + API_EVENT(conn, NETCONN_EVT_RCVMINUS, 0); + /* RX side is closed, so deallocate the recvmbox */ + netconn_close_shutdown(conn, NETCONN_SHUT_RD); + /* Don' store ERR_CLSD as conn->err since we are only half-closed */ + return ERR_CLSD; + } + len = ((struct pbuf *)buf)->tot_len; + } +#endif /* LWIP_TCP */ +#if LWIP_TCP && (LWIP_UDP || LWIP_RAW) + else +#endif /* LWIP_TCP && (LWIP_UDP || LWIP_RAW) */ +#if (LWIP_UDP || LWIP_RAW) + { +#if LWIP_THREAD_SAFE + if (buf == NULL){ + API_EVENT(conn, NETCONN_EVT_RCVMINUS, 0); + return ERR_CLSD; + } +#endif + LWIP_ASSERT("buf != NULL", buf != NULL); + len = netbuf_len((struct netbuf *)buf); + } +#endif /* (LWIP_UDP || LWIP_RAW) */ + +#if LWIP_SO_RCVBUF + SYS_ARCH_DEC(conn->recv_avail, len); +#endif /* LWIP_SO_RCVBUF */ + /* Register event with callback */ + API_EVENT(conn, NETCONN_EVT_RCVMINUS, len); + + LWIP_DEBUGF(API_LIB_DEBUG, ("netconn_recv_data: received %p, len=%"U16_F"\n", buf, len)); + + *new_buf = buf; + /* don't set conn->last_err: it's only ERR_OK, anyway */ + return ERR_OK; +} + +/** + * Receive data (in form of a pbuf) from a TCP netconn + * + * @param conn the netconn from which to receive data + * @param new_buf pointer where a new pbuf is stored when received data + * @return ERR_OK if data has been received, an error code otherwise (timeout, + * memory error or another error) + * ERR_ARG if conn is not a TCP netconn + */ +err_t +netconn_recv_tcp_pbuf(struct netconn *conn, struct pbuf **new_buf) +{ + LWIP_ERROR("netconn_recv: invalid conn", (conn != NULL) && + NETCONNTYPE_GROUP(netconn_type(conn)) == NETCONN_TCP, return ERR_ARG;); + + return netconn_recv_data(conn, (void **)new_buf); +} + +/** + * Receive data (in form of a netbuf containing a packet buffer) from a netconn + * + * @param conn the netconn from which to receive data + * @param new_buf pointer where a new netbuf is stored when received data + * @return ERR_OK if data has been received, an error code otherwise (timeout, + * memory error or another error) + */ +err_t +netconn_recv(struct netconn *conn, struct netbuf **new_buf) +{ +#if LWIP_TCP + struct netbuf *buf = NULL; + err_t err; +#endif /* LWIP_TCP */ + + LWIP_ERROR("netconn_recv: invalid pointer", (new_buf != NULL), return ERR_ARG;); + *new_buf = NULL; + LWIP_ERROR("netconn_recv: invalid conn", (conn != NULL), return ERR_ARG;); + +#if LWIP_TCP +#if (LWIP_UDP || LWIP_RAW) + if (NETCONNTYPE_GROUP(conn->type) == NETCONN_TCP) +#endif /* (LWIP_UDP || LWIP_RAW) */ + { + struct pbuf *p = NULL; + /* This is not a listening netconn, since recvmbox is set */ + + buf = (struct netbuf *)memp_malloc(MEMP_NETBUF); + if (buf == NULL) { + return ERR_MEM; + } + + err = netconn_recv_data(conn, (void **)&p); + if (err != ERR_OK) { + memp_free(MEMP_NETBUF, buf); + return err; + } + LWIP_ASSERT("p != NULL", p != NULL); + + buf->p = p; + buf->ptr = p; + buf->port = 0; + ip_addr_set_zero(&buf->addr); + *new_buf = buf; + /* don't set conn->last_err: it's only ERR_OK, anyway */ + return ERR_OK; + } +#endif /* LWIP_TCP */ +#if LWIP_TCP && (LWIP_UDP || LWIP_RAW) + else +#endif /* LWIP_TCP && (LWIP_UDP || LWIP_RAW) */ + { +#if (LWIP_UDP || LWIP_RAW) + return netconn_recv_data(conn, (void **)new_buf); +#endif /* (LWIP_UDP || LWIP_RAW) */ + } +} + +/** + * TCP: update the receive window: by calling this, the application + * tells the stack that it has processed data and is able to accept + * new data. + * ATTENTION: use with care, this is mainly used for sockets! + * Can only be used when calling netconn_set_noautorecved(conn, 1) before. + * + * @param conn the netconn for which to update the receive window + * @param length amount of data processed (ATTENTION: this must be accurate!) + */ +void +netconn_recved(struct netconn *conn, u32_t length) +{ +#if LWIP_TCP + if ((conn != NULL) && (NETCONNTYPE_GROUP(conn->type) == NETCONN_TCP) && + (netconn_get_noautorecved(conn))) { + API_MSG_VAR_DECLARE(msg); + /* Let the stack know that we have taken the data. */ + /* TODO: Speedup: Don't block and wait for the answer here + (to prevent multiple thread-switches). */ + API_MSG_VAR_ALLOC_DONTFAIL(msg); + API_MSG_VAR_REF(msg).msg.conn = conn; + API_MSG_VAR_REF(msg).msg.msg.r.len = length; + /* don't care for the return value of lwip_netconn_do_recv */ + TCPIP_APIMSG_NOERR(&API_MSG_VAR_REF(msg), lwip_netconn_do_recv); + API_MSG_VAR_FREE(msg); + } +#else /* LWIP_TCP */ + LWIP_UNUSED_ARG(conn); + LWIP_UNUSED_ARG(length); +#endif /* LWIP_TCP */ +} + +/** + * Send data (in form of a netbuf) to a specific remote IP address and port. + * Only to be used for UDP and RAW netconns (not TCP). + * + * @param conn the netconn over which to send data + * @param buf a netbuf containing the data to send + * @param addr the remote IP address to which to send the data + * @param port the remote port to which to send the data + * @return ERR_OK if data was sent, any other err_t on error + */ +err_t +netconn_sendto(struct netconn *conn, struct netbuf *buf, const ip_addr_t *addr, u16_t port) +{ + if (buf != NULL) { + ip_addr_set(&buf->addr, addr); + buf->port = port; + return netconn_send(conn, buf); + } + return ERR_VAL; +} + +/** + * Send data over a UDP or RAW netconn (that is already connected). + * + * @param conn the UDP or RAW netconn over which to send data + * @param buf a netbuf containing the data to send + * @return ERR_OK if data was sent, any other err_t on error + */ +err_t +netconn_send(struct netconn *conn, struct netbuf *buf) +{ + API_MSG_VAR_DECLARE(msg); + err_t err; + + LWIP_ERROR("netconn_send: invalid conn", (conn != NULL), return ERR_ARG;); + + LWIP_DEBUGF(API_LIB_DEBUG, ("netconn_send: sending %"U16_F" bytes\n", buf->p->tot_len)); + API_MSG_VAR_ALLOC(msg); + API_MSG_VAR_REF(msg).msg.conn = conn; + API_MSG_VAR_REF(msg).msg.msg.b = buf; + TCPIP_APIMSG(&API_MSG_VAR_REF(msg), lwip_netconn_do_send, err); + API_MSG_VAR_FREE(msg); + + return err; +} + +/** + * Send data over a TCP netconn. + * + * @param conn the TCP netconn over which to send data + * @param dataptr pointer to the application buffer that contains the data to send + * @param size size of the application data to send + * @param apiflags combination of following flags : + * - NETCONN_COPY: data will be copied into memory belonging to the stack + * - NETCONN_MORE: for TCP connection, PSH flag will be set on last segment sent + * - NETCONN_DONTBLOCK: only write the data if all data can be written at once + * @param bytes_written pointer to a location that receives the number of written bytes + * @return ERR_OK if data was sent, any other err_t on error + */ +err_t +netconn_write_partly(struct netconn *conn, const void *dataptr, size_t size, + u8_t apiflags, size_t *bytes_written) +{ + API_MSG_VAR_DECLARE(msg); + err_t err; + u8_t dontblock; + + LWIP_ERROR("netconn_write: invalid conn", (conn != NULL), return ERR_ARG;); + LWIP_ERROR("netconn_write: invalid conn->type", (NETCONNTYPE_GROUP(conn->type)== NETCONN_TCP), return ERR_VAL;); + if (size == 0) { + return ERR_OK; + } + dontblock = netconn_is_nonblocking(conn) || (apiflags & NETCONN_DONTBLOCK); + +#ifdef LWIP_ESP8266 + +#ifdef FOR_XIAOMI + if (dontblock && bytes_written) { +#else + if (dontblock && !bytes_written) { +#endif + +#else + if (dontblock && !bytes_written) { +#endif + /* This implies netconn_write() cannot be used for non-blocking send, since + it has no way to return the number of bytes written. */ + return ERR_VAL; + } + + API_MSG_VAR_ALLOC(msg); + /* non-blocking write sends as much */ + API_MSG_VAR_REF(msg).msg.conn = conn; + API_MSG_VAR_REF(msg).msg.msg.w.dataptr = dataptr; + API_MSG_VAR_REF(msg).msg.msg.w.apiflags = apiflags; + API_MSG_VAR_REF(msg).msg.msg.w.len = size; +#if LWIP_SO_SNDTIMEO + if (conn->send_timeout != 0) { + /* get the time we started, which is later compared to + sys_now() + conn->send_timeout */ + API_MSG_VAR_REF(msg).msg.msg.w.time_started = sys_now(); + } else { + API_MSG_VAR_REF(msg).msg.msg.w.time_started = 0; + } +#endif /* LWIP_SO_SNDTIMEO */ + + /* For locking the core: this _can_ be delayed on low memory/low send buffer, + but if it is, this is done inside api_msg.c:do_write(), so we can use the + non-blocking version here. */ + TCPIP_APIMSG(&API_MSG_VAR_REF(msg), lwip_netconn_do_write, err); + if ((err == ERR_OK) && (bytes_written != NULL)) { + if (dontblock +#if LWIP_SO_SNDTIMEO + || (conn->send_timeout != 0) +#endif /* LWIP_SO_SNDTIMEO */ + ) { + /* nonblocking write: maybe the data has been sent partly */ + *bytes_written = API_MSG_VAR_REF(msg).msg.msg.w.len; + } else { + /* blocking call succeeded: all data has been sent if it */ + *bytes_written = size; + } + } + API_MSG_VAR_FREE(msg); + + return err; +} + +/** + * Close or shutdown a TCP netconn (doesn't delete it). + * + * @param conn the TCP netconn to close or shutdown + * @param how fully close or only shutdown one side? + * @return ERR_OK if the netconn was closed, any other err_t on error + */ +static err_t +netconn_close_shutdown(struct netconn *conn, u8_t how) +{ + API_MSG_VAR_DECLARE(msg); + err_t err; + LWIP_UNUSED_ARG(how); + + LWIP_ERROR("netconn_close: invalid conn", (conn != NULL), return ERR_ARG;); + + API_MSG_VAR_ALLOC(msg); + API_MSG_VAR_REF(msg).msg.conn = conn; +#if LWIP_TCP + /* shutting down both ends is the same as closing */ + API_MSG_VAR_REF(msg).msg.msg.sd.shut = how; +#if LWIP_SO_SNDTIMEO || LWIP_SO_LINGER + /* get the time we started, which is later compared to + sys_now() + conn->send_timeout */ + API_MSG_VAR_REF(msg).msg.msg.sd.time_started = sys_now(); +#else /* LWIP_SO_SNDTIMEO || LWIP_SO_LINGER */ + API_MSG_VAR_REF(msg).msg.msg.sd.polls_left = + ((LWIP_TCP_CLOSE_TIMEOUT_MS_DEFAULT + TCP_SLOW_INTERVAL - 1) / TCP_SLOW_INTERVAL) + 1; +#endif /* LWIP_SO_SNDTIMEO || LWIP_SO_LINGER */ +#endif /* LWIP_TCP */ + TCPIP_APIMSG(&API_MSG_VAR_REF(msg), lwip_netconn_do_close, err); + API_MSG_VAR_FREE(msg); + + return err; +} + +/** + * Close a TCP netconn (doesn't delete it). + * + * @param conn the TCP netconn to close + * @return ERR_OK if the netconn was closed, any other err_t on error + */ +err_t +netconn_close(struct netconn *conn) +{ + /* shutting down both ends is the same as closing */ + return netconn_close_shutdown(conn, NETCONN_SHUT_RDWR); +} + +/** + * Shut down one or both sides of a TCP netconn (doesn't delete it). + * + * @param conn the TCP netconn to shut down + * @return ERR_OK if the netconn was closed, any other err_t on error + */ +err_t +netconn_shutdown(struct netconn *conn, u8_t shut_rx, u8_t shut_tx) +{ + return netconn_close_shutdown(conn, (shut_rx ? NETCONN_SHUT_RD : 0) | (shut_tx ? NETCONN_SHUT_WR : 0)); +} + +#if LWIP_IGMP || (LWIP_IPV6 && LWIP_IPV6_MLD) +/** + * Join multicast groups for UDP netconns. + * + * @param conn the UDP netconn for which to change multicast addresses + * @param multiaddr IP address of the multicast group to join or leave + * @param netif_addr the IP address of the network interface on which to send + * the igmp message + * @param join_or_leave flag whether to send a join- or leave-message + * @return ERR_OK if the action was taken, any err_t on error + */ +err_t +netconn_join_leave_group(struct netconn *conn, + const ip_addr_t *multiaddr, + const ip_addr_t *netif_addr, + enum netconn_igmp join_or_leave) +{ + API_MSG_VAR_DECLARE(msg); + err_t err; + + LWIP_ERROR("netconn_join_leave_group: invalid conn", (conn != NULL), return ERR_ARG;); + + API_MSG_VAR_ALLOC(msg); + + /* Don't propagate NULL pointer (IP_ADDR_ANY alias) to subsequent functions */ + if (multiaddr == NULL) { + multiaddr = IP_ADDR_ANY; + } + if (netif_addr == NULL) { + netif_addr = IP_ADDR_ANY; + } + + API_MSG_VAR_REF(msg).msg.conn = conn; + API_MSG_VAR_REF(msg).msg.msg.jl.multiaddr = API_MSG_VAR_REF(multiaddr); + API_MSG_VAR_REF(msg).msg.msg.jl.netif_addr = API_MSG_VAR_REF(netif_addr); + API_MSG_VAR_REF(msg).msg.msg.jl.join_or_leave = join_or_leave; + TCPIP_APIMSG(&API_MSG_VAR_REF(msg), lwip_netconn_do_join_leave_group, err); + API_MSG_VAR_FREE(msg); + + return err; +} +#endif /* LWIP_IGMP || (LWIP_IPV6 && LWIP_IPV6_MLD) */ + +#if LWIP_DNS +/** + * Execute a DNS query, only one IP address is returned + * + * @param name a string representation of the DNS host name to query + * @param addr a preallocated ip_addr_t where to store the resolved IP address + * @return ERR_OK: resolving succeeded + * ERR_MEM: memory error, try again later + * ERR_ARG: dns client not initialized or invalid hostname + * ERR_VAL: dns server response was invalid + */ +#if LWIP_IPV4 && LWIP_IPV6 +err_t +netconn_gethostbyname_addrtype(const char *name, ip_addr_t *addr, u8_t dns_addrtype) +#else +err_t +netconn_gethostbyname(const char *name, ip_addr_t *addr) +#endif +{ + + API_VAR_DECLARE(struct dns_api_msg, msg); +#if !LWIP_MPU_COMPATIBLE + sys_sem_t sem; +#endif /* LWIP_MPU_COMPATIBLE */ + err_t err; + + LWIP_ERROR("netconn_gethostbyname: invalid name", (name != NULL), return ERR_ARG;); + LWIP_ERROR("netconn_gethostbyname: invalid addr", (addr != NULL), return ERR_ARG;); +#if LWIP_MPU_COMPATIBLE + if (strlen(name) >= DNS_MAX_NAME_LENGTH) { + return ERR_ARG; + } +#endif + + API_VAR_ALLOC(struct dns_api_msg, MEMP_DNS_API_MSG, msg); +#if LWIP_MPU_COMPATIBLE + strncpy(API_VAR_REF(msg).name, name, DNS_MAX_NAME_LENGTH-1); + API_VAR_REF(msg).name[DNS_MAX_NAME_LENGTH-1] = 0; +#else /* LWIP_MPU_COMPATIBLE */ + msg.err = &err; + msg.sem = &sem; + API_VAR_REF(msg).addr = API_VAR_REF(addr); + API_VAR_REF(msg).name = name; +#endif /* LWIP_MPU_COMPATIBLE */ +#if LWIP_IPV4 && LWIP_IPV6 + API_VAR_REF(msg).dns_addrtype = dns_addrtype; +#endif /* LWIP_IPV4 && LWIP_IPV6 */ + + +#if LWIP_NETCONN_SEM_PER_THREAD + API_VAR_REF(msg).sem = LWIP_NETCONN_THREAD_SEM_GET(); +#else /* LWIP_NETCONN_SEM_PER_THREAD*/ + err = sys_sem_new(API_EXPR_REF(API_VAR_REF(msg).sem), 0); + if (err != ERR_OK) { + API_VAR_FREE(MEMP_DNS_API_MSG, msg); + return err; + } +#endif /* LWIP_NETCONN_SEM_PER_THREAD */ + + err = tcpip_callback(lwip_netconn_do_gethostbyname, &API_VAR_REF(msg)); + if (err != ERR_OK) { +#if !LWIP_NETCONN_SEM_PER_THREAD + sys_sem_free(API_EXPR_REF(API_VAR_REF(msg).sem)); +#endif /* !LWIP_NETCONN_SEM_PER_THREAD */ + + API_VAR_FREE(MEMP_DNS_API_MSG, msg); + return err; + } + + sys_sem_wait(API_EXPR_REF_SEM(API_VAR_REF(msg).sem)); +#if !LWIP_NETCONN_SEM_PER_THREAD + sys_sem_free(API_EXPR_REF(API_VAR_REF(msg).sem)); +#endif /* !LWIP_NETCONN_SEM_PER_THREAD */ + +#if LWIP_MPU_COMPATIBLE + *addr = msg->addr; + err = msg->err; +#endif /* LWIP_MPU_COMPATIBLE */ + + API_VAR_FREE(MEMP_DNS_API_MSG, msg); + + return err; +} +#endif /* LWIP_DNS*/ + +#if LWIP_NETCONN_SEM_PER_THREAD +void +netconn_thread_init(void) +{ + sys_sem_t *sem = LWIP_NETCONN_THREAD_SEM_GET(); + if ((sem == NULL) || !sys_sem_valid(sem)) { + /* call alloc only once */ + LWIP_NETCONN_THREAD_SEM_ALLOC(); + LWIP_ASSERT("LWIP_NETCONN_THREAD_SEM_ALLOC() failed", sys_sem_valid(LWIP_NETCONN_THREAD_SEM_GET())); + } +} + +void +netconn_thread_cleanup(void) +{ + sys_sem_t *sem = LWIP_NETCONN_THREAD_SEM_GET(); + if ((sem != NULL) && sys_sem_valid(sem)) { + /* call free only once */ + LWIP_NETCONN_THREAD_SEM_FREE(); + } +} +#endif /* LWIP_NETCONN_SEM_PER_THREAD */ + +#endif /* LWIP_NETCONN */ diff --git a/components/lwip/api/api_msg.c b/components/lwip/api/api_msg.c new file mode 100755 index 0000000000..e8e967ef40 --- /dev/null +++ b/components/lwip/api/api_msg.c @@ -0,0 +1,1930 @@ +/** + * @file + * Sequential API Internal module + * + */ + +/* + * Copyright (c) 2001-2004 Swedish Institute of Computer Science. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + * + */ + +#include "lwip/opt.h" + +#if LWIP_NETCONN /* don't build if not configured for use in lwipopts.h */ + +#include "lwip/priv/api_msg.h" + +#include "lwip/ip.h" +#include "lwip/udp.h" +#include "lwip/tcp.h" +#include "lwip/raw.h" + +#include "lwip/memp.h" +#include "lwip/igmp.h" +#include "lwip/dns.h" +#include "lwip/mld6.h" +#include "lwip/priv/tcpip_priv.h" + +#include + +#ifdef MEMLEAK_DEBUG +static const char mem_debug_file[] ICACHE_RODATA_ATTR STORE_ATTR = __FILE__; +#endif + +/* netconns are polled once per second (e.g. continue write on memory error) */ +#define NETCONN_TCP_POLL_INTERVAL 2 + +#define SET_NONBLOCKING_CONNECT(conn, val) do { if (val) { \ + (conn)->flags |= NETCONN_FLAG_IN_NONBLOCKING_CONNECT; \ +} else { \ + (conn)->flags &= ~ NETCONN_FLAG_IN_NONBLOCKING_CONNECT; }} while(0) +#define IN_NONBLOCKING_CONNECT(conn) (((conn)->flags & NETCONN_FLAG_IN_NONBLOCKING_CONNECT) != 0) + +/* forward declarations */ +#if LWIP_TCP +#if LWIP_TCPIP_CORE_LOCKING +#define WRITE_DELAYED , 1 +#define WRITE_DELAYED_PARAM , u8_t delayed +#else /* LWIP_TCPIP_CORE_LOCKING */ +#define WRITE_DELAYED +#define WRITE_DELAYED_PARAM +#endif /* LWIP_TCPIP_CORE_LOCKING */ +static err_t lwip_netconn_do_writemore(struct netconn *conn WRITE_DELAYED_PARAM); +static err_t lwip_netconn_do_close_internal(struct netconn *conn WRITE_DELAYED_PARAM); +#endif + +#if LWIP_RAW +/** + * Receive callback function for RAW netconns. + * Doesn't 'eat' the packet, only copies it and sends it to + * conn->recvmbox + * + * @see raw.h (struct raw_pcb.recv) for parameters and return value + */ +static u8_t +recv_raw(void *arg, struct raw_pcb *pcb, struct pbuf *p, + const ip_addr_t *addr) +{ + struct pbuf *q; + struct netbuf *buf; + struct netconn *conn; + + LWIP_UNUSED_ARG(addr); + conn = (struct netconn *)arg; + + if ((conn != NULL) && sys_mbox_valid(&conn->recvmbox)) { +#if LWIP_SO_RCVBUF + int recv_avail; + SYS_ARCH_GET(conn->recv_avail, recv_avail); + if ((recv_avail + (int)(p->tot_len)) > conn->recv_bufsize) { + return 0; + } +#endif /* LWIP_SO_RCVBUF */ + /* copy the whole packet into new pbufs */ + q = pbuf_alloc(PBUF_RAW, p->tot_len, PBUF_RAM); + if (q != NULL) { + if (pbuf_copy(q, p) != ERR_OK) { + pbuf_free(q); + q = NULL; + } + } + + if (q != NULL) { + u16_t len; + buf = (struct netbuf *)memp_malloc(MEMP_NETBUF); + if (buf == NULL) { + pbuf_free(q); + return 0; + } + + buf->p = q; + buf->ptr = q; + ip_addr_copy(buf->addr, *ip_current_src_addr()); + buf->port = pcb->protocol; + + len = q->tot_len; + if (sys_mbox_trypost(&conn->recvmbox, buf) != ERR_OK) { + netbuf_delete(buf); + return 0; + } else { +#if LWIP_SO_RCVBUF + SYS_ARCH_INC(conn->recv_avail, len); +#endif /* LWIP_SO_RCVBUF */ + /* Register event with callback */ + API_EVENT(conn, NETCONN_EVT_RCVPLUS, len); + } + } + } + + return 0; /* do not eat the packet */ +} +#endif /* LWIP_RAW*/ + +#if LWIP_UDP +/** + * Receive callback function for UDP netconns. + * Posts the packet to conn->recvmbox or deletes it on memory error. + * + * @see udp.h (struct udp_pcb.recv) for parameters + */ +static void +recv_udp(void *arg, struct udp_pcb *pcb, struct pbuf *p, + const ip_addr_t *addr, u16_t port) +{ + struct netbuf *buf; + struct netconn *conn; + u16_t len; +#if LWIP_SO_RCVBUF + int recv_avail; +#endif /* LWIP_SO_RCVBUF */ + + LWIP_UNUSED_ARG(pcb); /* only used for asserts... */ + LWIP_ASSERT("recv_udp must have a pcb argument", pcb != NULL); + LWIP_ASSERT("recv_udp must have an argument", arg != NULL); + conn = (struct netconn *)arg; + LWIP_ASSERT("recv_udp: recv for wrong pcb!", conn->pcb.udp == pcb); + +#if LWIP_SO_RCVBUF + SYS_ARCH_GET(conn->recv_avail, recv_avail); + if ((conn == NULL) || !sys_mbox_valid(&conn->recvmbox) || + ((recv_avail + (int)(p->tot_len)) > conn->recv_bufsize)) { +#else /* LWIP_SO_RCVBUF */ + if ((conn == NULL) || !sys_mbox_valid(&conn->recvmbox)) { +#endif /* LWIP_SO_RCVBUF */ + pbuf_free(p); + return; + } + + buf = (struct netbuf *)memp_malloc(MEMP_NETBUF); + if (buf == NULL) { + pbuf_free(p); + return; + } else { + buf->p = p; + buf->ptr = p; + ip_addr_set(&buf->addr, addr); + buf->port = port; +#if LWIP_NETBUF_RECVINFO + { + /* get the UDP header - always in the first pbuf, ensured by udp_input */ + const struct udp_hdr* udphdr = (const struct udp_hdr*)ip_next_header_ptr(); +#if LWIP_CHECKSUM_ON_COPY + buf->flags = NETBUF_FLAG_DESTADDR; +#endif /* LWIP_CHECKSUM_ON_COPY */ + ip_addr_set(&buf->toaddr, ip_current_dest_addr()); + buf->toport_chksum = udphdr->dest; + } +#endif /* LWIP_NETBUF_RECVINFO */ + } + + len = p->tot_len; + if (sys_mbox_trypost(&conn->recvmbox, buf) != ERR_OK) { + netbuf_delete(buf); + return; + } else { +#if LWIP_SO_RCVBUF + SYS_ARCH_INC(conn->recv_avail, len); +#endif /* LWIP_SO_RCVBUF */ + /* Register event with callback */ + API_EVENT(conn, NETCONN_EVT_RCVPLUS, len); + } +} +#endif /* LWIP_UDP */ + +#if LWIP_TCP +/** + * Receive callback function for TCP netconns. + * Posts the packet to conn->recvmbox, but doesn't delete it on errors. + * + * @see tcp.h (struct tcp_pcb.recv) for parameters and return value + */ +static err_t +recv_tcp(void *arg, struct tcp_pcb *pcb, struct pbuf *p, err_t err) +{ + struct netconn *conn; + u16_t len; + + LWIP_UNUSED_ARG(pcb); + LWIP_ASSERT("recv_tcp must have a pcb argument", pcb != NULL); + LWIP_ASSERT("recv_tcp must have an argument", arg != NULL); + conn = (struct netconn *)arg; + + if (conn == NULL) { + return ERR_VAL; + } + LWIP_ASSERT("recv_tcp: recv for wrong pcb!", conn->pcb.tcp == pcb); + + if (!sys_mbox_valid(&conn->recvmbox)) { + /* recvmbox already deleted */ + if (p != NULL) { + tcp_recved(pcb, p->tot_len); + pbuf_free(p); + } + return ERR_OK; + } + /* Unlike for UDP or RAW pcbs, don't check for available space + using recv_avail since that could break the connection + (data is already ACKed) */ + + /* don't overwrite fatal errors! */ + if (err != ERR_OK) { + NETCONN_SET_SAFE_ERR(conn, err); + } + + if (p != NULL) { + len = p->tot_len; + } else { + len = 0; + } + + if (sys_mbox_trypost(&conn->recvmbox, p) != ERR_OK) { + /* don't deallocate p: it is presented to us later again from tcp_fasttmr! */ + return ERR_MEM; + } else { +#if LWIP_SO_RCVBUF + SYS_ARCH_INC(conn->recv_avail, len); +#endif /* LWIP_SO_RCVBUF */ + /* Register event with callback */ + API_EVENT(conn, NETCONN_EVT_RCVPLUS, len); + } + + return ERR_OK; +} + +/** + * Poll callback function for TCP netconns. + * Wakes up an application thread that waits for a connection to close + * or data to be sent. The application thread then takes the + * appropriate action to go on. + * + * Signals the conn->sem. + * netconn_close waits for conn->sem if closing failed. + * + * @see tcp.h (struct tcp_pcb.poll) for parameters and return value + */ +static err_t +poll_tcp(void *arg, struct tcp_pcb *pcb) +{ + struct netconn *conn = (struct netconn *)arg; + + LWIP_UNUSED_ARG(pcb); + LWIP_ASSERT("conn != NULL", (conn != NULL)); + + if (conn->state == NETCONN_WRITE) { + lwip_netconn_do_writemore(conn WRITE_DELAYED); + } else if (conn->state == NETCONN_CLOSE) { +#if !LWIP_SO_SNDTIMEO && !LWIP_SO_LINGER + if (conn->current_msg && conn->current_msg->msg.sd.polls_left) { + conn->current_msg->msg.sd.polls_left--; + } +#endif /* !LWIP_SO_SNDTIMEO && !LWIP_SO_LINGER */ + lwip_netconn_do_close_internal(conn WRITE_DELAYED); + } + /* @todo: implement connect timeout here? */ + + /* Did a nonblocking write fail before? Then check available write-space. */ + if (conn->flags & NETCONN_FLAG_CHECK_WRITESPACE) { + /* If the queued byte- or pbuf-count drops below the configured low-water limit, + let select mark this pcb as writable again. */ + if ((conn->pcb.tcp != NULL) && (tcp_sndbuf(conn->pcb.tcp) > TCP_SNDLOWAT) && + (tcp_sndqueuelen(conn->pcb.tcp) < TCP_SNDQUEUELOWAT)) { + conn->flags &= ~NETCONN_FLAG_CHECK_WRITESPACE; + API_EVENT(conn, NETCONN_EVT_SENDPLUS, 0); + } + } + + return ERR_OK; +} + +/** + * Sent callback function for TCP netconns. + * Signals the conn->sem and calls API_EVENT. + * netconn_write waits for conn->sem if send buffer is low. + * + * @see tcp.h (struct tcp_pcb.sent) for parameters and return value + */ +static err_t +sent_tcp(void *arg, struct tcp_pcb *pcb, u16_t len) +{ + struct netconn *conn = (struct netconn *)arg; + + LWIP_UNUSED_ARG(pcb); + LWIP_ASSERT("conn != NULL", (conn != NULL)); + + if (conn) { + if (conn->state == NETCONN_WRITE) { + lwip_netconn_do_writemore(conn WRITE_DELAYED); + } else if (conn->state == NETCONN_CLOSE) { + lwip_netconn_do_close_internal(conn WRITE_DELAYED); + } + + /* If the queued byte- or pbuf-count drops below the configured low-water limit, + let select mark this pcb as writable again. */ + if ((conn->pcb.tcp != NULL) && (tcp_sndbuf(conn->pcb.tcp) > TCP_SNDLOWAT) && + (tcp_sndqueuelen(conn->pcb.tcp) < TCP_SNDQUEUELOWAT)) { + conn->flags &= ~NETCONN_FLAG_CHECK_WRITESPACE; + API_EVENT(conn, NETCONN_EVT_SENDPLUS, len); + } + } + + return ERR_OK; +} + +/** + * Error callback function for TCP netconns. + * Signals conn->sem, posts to all conn mboxes and calls API_EVENT. + * The application thread has then to decide what to do. + * + * @see tcp.h (struct tcp_pcb.err) for parameters + */ +static void +err_tcp(void *arg, err_t err) +{ + struct netconn *conn; + enum netconn_state old_state; + + conn = (struct netconn *)arg; + LWIP_ASSERT("conn != NULL", (conn != NULL)); + + conn->pcb.tcp = NULL; + + /* no check since this is always fatal! */ + SYS_ARCH_SET(conn->last_err, err); + + /* reset conn->state now before waking up other threads */ + old_state = conn->state; + conn->state = NETCONN_NONE; + + /* @todo: the type of NETCONN_EVT created should depend on 'old_state' */ + + /* Notify the user layer about a connection error. Used to signal select. */ + API_EVENT(conn, NETCONN_EVT_ERROR, 0); + /* Try to release selects pending on 'read' or 'write', too. + They will get an error if they actually try to read or write. */ + API_EVENT(conn, NETCONN_EVT_RCVPLUS, 0); + API_EVENT(conn, NETCONN_EVT_SENDPLUS, 0); + + /* pass NULL-message to recvmbox to wake up pending recv */ + if (sys_mbox_valid(&conn->recvmbox)) { + /* use trypost to prevent deadlock */ + sys_mbox_trypost(&conn->recvmbox, NULL); + } + /* pass NULL-message to acceptmbox to wake up pending accept */ + if (sys_mbox_valid(&conn->acceptmbox)) { + /* use trypost to preven deadlock */ + sys_mbox_trypost(&conn->acceptmbox, NULL); + } + + if ((old_state == NETCONN_WRITE) || (old_state == NETCONN_CLOSE) || + (old_state == NETCONN_CONNECT)) { + /* calling lwip_netconn_do_writemore/lwip_netconn_do_close_internal is not necessary + since the pcb has already been deleted! */ + int was_nonblocking_connect = IN_NONBLOCKING_CONNECT(conn); + SET_NONBLOCKING_CONNECT(conn, 0); + + if (!was_nonblocking_connect) { + sys_sem_t* op_completed_sem; + /* set error return code */ + LWIP_ASSERT("conn->current_msg != NULL", conn->current_msg != NULL); + conn->current_msg->err = err; + op_completed_sem = LWIP_API_MSG_SEM(conn->current_msg); + + LWIP_ASSERT("inavlid op_completed_sem", sys_sem_valid(op_completed_sem)); + conn->current_msg = NULL; + /* wake up the waiting task */ + NETCONN_SET_SAFE_ERR(conn, err); + + sys_sem_signal(op_completed_sem); + } + } else { + LWIP_ASSERT("conn->current_msg == NULL", conn->current_msg == NULL); + } +} + +/** + * Setup a tcp_pcb with the correct callback function pointers + * and their arguments. + * + * @param conn the TCP netconn to setup + */ +static void +setup_tcp(struct netconn *conn) +{ + struct tcp_pcb *pcb; + + pcb = conn->pcb.tcp; + tcp_arg(pcb, conn); + tcp_recv(pcb, recv_tcp); + tcp_sent(pcb, sent_tcp); + tcp_poll(pcb, poll_tcp, NETCONN_TCP_POLL_INTERVAL); + tcp_err(pcb, err_tcp); +} + +/** + * Accept callback function for TCP netconns. + * Allocates a new netconn and posts that to conn->acceptmbox. + * + * @see tcp.h (struct tcp_pcb_listen.accept) for parameters and return value + */ +static err_t +accept_function(void *arg, struct tcp_pcb *newpcb, err_t err) +{ + struct netconn *newconn; + struct netconn *conn = (struct netconn *)arg; + + LWIP_DEBUGF(API_MSG_DEBUG, ("accept_function: newpcb->tate: %s\n", tcp_debug_state_str(newpcb->state))); + + if (!sys_mbox_valid(&conn->acceptmbox)) { + LWIP_DEBUGF(API_MSG_DEBUG, ("accept_function: acceptmbox already deleted\n")); + return ERR_VAL; + } + + /* We have to set the callback here even though + * the new socket is unknown. conn->socket is marked as -1. */ + newconn = netconn_alloc(conn->type, conn->callback); + if (newconn == NULL) { + return ERR_MEM; + } + newconn->pcb.tcp = newpcb; + setup_tcp(newconn); + /* no protection: when creating the pcb, the netconn is not yet known + to the application thread */ + newconn->last_err = err; + + if (sys_mbox_trypost(&conn->acceptmbox, newconn) != ERR_OK) { + /* When returning != ERR_OK, the pcb is aborted in tcp_process(), + so do nothing here! */ + /* remove all references to this netconn from the pcb */ + struct tcp_pcb* pcb = newconn->pcb.tcp; + tcp_arg(pcb, NULL); + tcp_recv(pcb, NULL); + tcp_sent(pcb, NULL); + tcp_poll(pcb, NULL, 0); + tcp_err(pcb, NULL); + /* remove reference from to the pcb from this netconn */ + newconn->pcb.tcp = NULL; + /* no need to drain since we know the recvmbox is empty. */ + sys_mbox_free(&newconn->recvmbox); + sys_mbox_set_invalid(&newconn->recvmbox); + netconn_free(newconn); + return ERR_MEM; + } else { + /* Register event with callback */ + API_EVENT(conn, NETCONN_EVT_RCVPLUS, 0); + } + + return ERR_OK; +} +#endif /* LWIP_TCP */ + +/** + * Create a new pcb of a specific type. + * Called from lwip_netconn_do_newconn(). + * + * @param msg the api_msg_msg describing the connection type + * @return msg->conn->err, but the return value is currently ignored + */ +static void +pcb_new(struct api_msg_msg *msg) +{ + LWIP_ASSERT("pcb_new: pcb already allocated", msg->conn->pcb.tcp == NULL); + + /* Allocate a PCB for this connection */ + switch(NETCONNTYPE_GROUP(msg->conn->type)) { +#if LWIP_RAW + case NETCONN_RAW: + msg->conn->pcb.raw = raw_new(msg->msg.n.proto); + if (msg->conn->pcb.raw != NULL) { + raw_recv(msg->conn->pcb.raw, recv_raw, msg->conn); + } + break; +#endif /* LWIP_RAW */ +#if LWIP_UDP + case NETCONN_UDP: + msg->conn->pcb.udp = udp_new(); + if (msg->conn->pcb.udp != NULL) { +#if LWIP_UDPLITE + if (NETCONNTYPE_ISUDPLITE(msg->conn->type)) { + udp_setflags(msg->conn->pcb.udp, UDP_FLAGS_UDPLITE); + } +#endif /* LWIP_UDPLITE */ + if (NETCONNTYPE_ISUDPNOCHKSUM(msg->conn->type)) { + udp_setflags(msg->conn->pcb.udp, UDP_FLAGS_NOCHKSUM); + } + udp_recv(msg->conn->pcb.udp, recv_udp, msg->conn); + } + break; +#endif /* LWIP_UDP */ +#if LWIP_TCP + case NETCONN_TCP: + msg->conn->pcb.tcp = tcp_new(); + if (msg->conn->pcb.tcp != NULL) { + setup_tcp(msg->conn); + } + break; +#endif /* LWIP_TCP */ + default: + /* Unsupported netconn type, e.g. protocol disabled */ + msg->err = ERR_VAL; + return; + } + if (msg->conn->pcb.ip == NULL) { + msg->err = ERR_MEM; + } +#if LWIP_IPV4 && LWIP_IPV6 + else { + if (NETCONNTYPE_ISIPV6(msg->conn->type)) { + /* Convert IPv4 PCB manually to an IPv6 PCB */ + IP_SET_TYPE_VAL(msg->conn->pcb.ip->local_ip, IPADDR_TYPE_V6); + IP_SET_TYPE_VAL(msg->conn->pcb.ip->remote_ip, IPADDR_TYPE_V6); + } + } +#endif /* LWIP_IPV4 && LWIP_IPV6 */ +} + +/** + * Create a new pcb of a specific type inside a netconn. + * Called from netconn_new_with_proto_and_callback. + * + * @param msg the api_msg_msg describing the connection type + */ +void +lwip_netconn_do_newconn(void *m) +{ + struct api_msg_msg *msg = (struct api_msg_msg*)m; + + msg->err = ERR_OK; + if (msg->conn->pcb.tcp == NULL) { + pcb_new(msg); + } + /* Else? This "new" connection already has a PCB allocated. */ + /* Is this an error condition? Should it be deleted? */ + /* We currently just are happy and return. */ + + TCPIP_APIMSG_ACK(msg); +} + +/** + * Create a new netconn (of a specific type) that has a callback function. + * The corresponding pcb is NOT created! + * + * @param t the type of 'connection' to create (@see enum netconn_type) + * @param proto the IP protocol for RAW IP pcbs + * @param callback a function to call on status changes (RX available, TX'ed) + * @return a newly allocated struct netconn or + * NULL on memory error + */ +struct netconn* +netconn_alloc(enum netconn_type t, netconn_callback callback) +{ + struct netconn *conn; + int size; + + conn = (struct netconn *)memp_malloc(MEMP_NETCONN); + if (conn == NULL) { + return NULL; + } + + conn->last_err = ERR_OK; + conn->type = t; + conn->pcb.tcp = NULL; + + /* If all sizes are the same, every compiler should optimize this switch to nothing */ + switch(NETCONNTYPE_GROUP(t)) { +#if LWIP_RAW + case NETCONN_RAW: + size = DEFAULT_RAW_RECVMBOX_SIZE; + break; +#endif /* LWIP_RAW */ +#if LWIP_UDP + case NETCONN_UDP: + size = DEFAULT_UDP_RECVMBOX_SIZE; + break; +#endif /* LWIP_UDP */ +#if LWIP_TCP + case NETCONN_TCP: + size = DEFAULT_TCP_RECVMBOX_SIZE; + break; +#endif /* LWIP_TCP */ + default: + LWIP_ASSERT("netconn_alloc: undefined netconn_type", 0); + goto free_and_return; + } + + if (sys_mbox_new(&conn->recvmbox, size) != ERR_OK) { + goto free_and_return; + } +#if !LWIP_NETCONN_SEM_PER_THREAD + if (sys_sem_new(&conn->op_completed, 0) != ERR_OK) { + sys_mbox_free(&conn->recvmbox); + goto free_and_return; + } +#endif + +#if LWIP_TCP + sys_mbox_set_invalid(&conn->acceptmbox); +#endif + conn->state = NETCONN_NONE; +#if LWIP_SOCKET + /* initialize socket to -1 since 0 is a valid socket */ + conn->socket = -1; +#endif /* LWIP_SOCKET */ + conn->callback = callback; +#if LWIP_TCP + conn->current_msg = NULL; + conn->write_offset = 0; +#endif /* LWIP_TCP */ +#if LWIP_SO_SNDTIMEO + conn->send_timeout = 0; +#endif /* LWIP_SO_SNDTIMEO */ +#if LWIP_SO_RCVTIMEO + conn->recv_timeout = 0; +#endif /* LWIP_SO_RCVTIMEO */ +#if LWIP_SO_RCVBUF + conn->recv_bufsize = RECV_BUFSIZE_DEFAULT; + conn->recv_avail = 0; +#endif /* LWIP_SO_RCVBUF */ +#if LWIP_SO_LINGER + conn->linger = -1; +#endif /* LWIP_SO_LINGER */ + conn->flags = 0; + return conn; +free_and_return: + memp_free(MEMP_NETCONN, conn); + return NULL; +} + +/** + * Delete a netconn and all its resources. + * The pcb is NOT freed (since we might not be in the right thread context do this). + * + * @param conn the netconn to free + */ +void +netconn_free(struct netconn *conn) +{ + LWIP_ASSERT("PCB must be deallocated outside this function", conn->pcb.tcp == NULL); + LWIP_ASSERT("recvmbox must be deallocated before calling this function", + !sys_mbox_valid(&conn->recvmbox)); +#if LWIP_TCP + LWIP_ASSERT("acceptmbox must be deallocated before calling this function", + !sys_mbox_valid(&conn->acceptmbox)); +#endif /* LWIP_TCP */ + +#if !LWIP_NETCONN_SEM_PER_THREAD + sys_sem_free(&conn->op_completed); + sys_sem_set_invalid(&conn->op_completed); +#endif + + memp_free(MEMP_NETCONN, conn); +} + +/** + * Delete rcvmbox and acceptmbox of a netconn and free the left-over data in + * these mboxes + * + * @param conn the netconn to free + * @bytes_drained bytes drained from recvmbox + * @accepts_drained pending connections drained from acceptmbox + */ +static void +netconn_drain(struct netconn *conn) +{ + void *mem; +#if LWIP_TCP + struct pbuf *p; +#endif /* LWIP_TCP */ + + /* This runs in tcpip_thread, so we don't need to lock against rx packets */ + + /* Delete and drain the recvmbox. */ + if (sys_mbox_valid(&conn->recvmbox)) { + while (sys_mbox_tryfetch(&conn->recvmbox, &mem) != SYS_MBOX_EMPTY) { +#if LWIP_TCP + if (NETCONNTYPE_GROUP(conn->type) == NETCONN_TCP) { + if (mem != NULL) { + p = (struct pbuf*)mem; + /* pcb might be set to NULL already by err_tcp() */ + if (conn->pcb.tcp != NULL) { + tcp_recved(conn->pcb.tcp, p->tot_len); + } + pbuf_free(p); + } + } else +#endif /* LWIP_TCP */ + { + netbuf_delete((struct netbuf *)mem); + } + } + sys_mbox_free(&conn->recvmbox); + sys_mbox_set_invalid(&conn->recvmbox); + } + + /* Delete and drain the acceptmbox. */ +#if LWIP_TCP + if (sys_mbox_valid(&conn->acceptmbox)) { + while (sys_mbox_tryfetch(&conn->acceptmbox, &mem) != SYS_MBOX_EMPTY) { + struct netconn *newconn = (struct netconn *)mem; + /* Only tcp pcbs have an acceptmbox, so no need to check conn->type */ + /* pcb might be set to NULL already by err_tcp() */ + if (conn->pcb.tcp != NULL) { + tcp_accepted(conn->pcb.tcp); + } + /* drain recvmbox */ + netconn_drain(newconn); + if (newconn->pcb.tcp != NULL) { + tcp_abort(newconn->pcb.tcp); + newconn->pcb.tcp = NULL; + } + netconn_free(newconn); + } + sys_mbox_free(&conn->acceptmbox); + sys_mbox_set_invalid(&conn->acceptmbox); + } +#endif /* LWIP_TCP */ +} + +#if LWIP_TCP +/** + * Internal helper function to close a TCP netconn: since this sometimes + * doesn't work at the first attempt, this function is called from multiple + * places. + * + * @param conn the TCP netconn to close + * [@param delay 1 if called from sent/poll (wake up calling thread on end)] + */ +static err_t +lwip_netconn_do_close_internal(struct netconn *conn WRITE_DELAYED_PARAM) +{ + err_t err; + u8_t shut, shut_rx, shut_tx, close; + u8_t close_finished = 0; + struct tcp_pcb* tpcb; +#if LWIP_SO_LINGER + u8_t linger_wait_required = 0; +#endif /* LWIP_SO_LINGER */ + + LWIP_ASSERT("invalid conn", (conn != NULL)); + LWIP_ASSERT("this is for tcp netconns only", (NETCONNTYPE_GROUP(conn->type) == NETCONN_TCP)); + LWIP_ASSERT("conn must be in state NETCONN_CLOSE", (conn->state == NETCONN_CLOSE)); + LWIP_ASSERT("pcb already closed", (conn->pcb.tcp != NULL)); + LWIP_ASSERT("conn->current_msg != NULL", conn->current_msg != NULL); + + tpcb = conn->pcb.tcp; + shut = conn->current_msg->msg.sd.shut; + shut_rx = shut & NETCONN_SHUT_RD; + shut_tx = shut & NETCONN_SHUT_WR; + /* shutting down both ends is the same as closing + (also if RD or WR side was shut down before already) */ + if (shut == NETCONN_SHUT_RDWR) { + close = 1; + } else if (shut_rx && + ((tpcb->state == FIN_WAIT_1) || + (tpcb->state == FIN_WAIT_2) || + (tpcb->state == CLOSING))) { + close = 1; + } else if (shut_tx && ((tpcb->flags & TF_RXCLOSED) != 0)) { + close = 1; + } else { + close = 0; + } + + /* Set back some callback pointers */ + if (close) { + tcp_arg(tpcb, NULL); + } + if (tpcb->state == LISTEN) { + tcp_accept(tpcb, NULL); + } else { + /* some callbacks have to be reset if tcp_close is not successful */ + if (shut_rx) { + tcp_recv(tpcb, NULL); + tcp_accept(tpcb, NULL); + } + if (shut_tx) { + tcp_sent(tpcb, NULL); + } + if (close) { + tcp_poll(tpcb, NULL, 0); + tcp_err(tpcb, NULL); + } + } + /* Try to close the connection */ + if (close) { +#if LWIP_SO_LINGER + /* check linger possibilites before calling tcp_close */ + err = ERR_OK; + /* linger enabled/required at all? (i.e. is there untransmitted data left?) */ + if ((conn->linger >= 0) && (conn->pcb.tcp->unsent || conn->pcb.tcp->unacked)) { + if ((conn->linger == 0)) { + /* data left but linger prevents waiting */ + tcp_abort(tpcb); + tpcb = NULL; + } else if (conn->linger > 0) { + /* data left and linger says we should wait */ + if (netconn_is_nonblocking(conn)) { + /* data left on a nonblocking netconn -> cannot linger */ + err = ERR_WOULDBLOCK; + } else if ((s32_t)(sys_now() - conn->current_msg->msg.sd.time_started) >= + (conn->linger * 1000)) { + /* data left but linger timeout has expired (this happens on further + calls to this function through poll_tcp */ + tcp_abort(tpcb); + tpcb = NULL; + } else { + /* data left -> need to wait for ACK after successful close */ + linger_wait_required = 1; + } + } + } + if ((err == ERR_OK) && (tpcb != NULL)) +#endif /* LWIP_SO_LINGER */ + { + err = tcp_close(tpcb); + } + } else { + err = tcp_shutdown(tpcb, shut_rx, shut_tx); + } + if (err == ERR_OK) { + close_finished = 1; +#if LWIP_SO_LINGER + if (linger_wait_required) { + /* wait for ACK of all unsent/unacked data by just getting called again */ + close_finished = 0; + err = ERR_INPROGRESS; + } +#endif /* LWIP_SO_LINGER */ + } else { + if (err == ERR_MEM) { + /* Closing failed because of memory shortage */ + if (netconn_is_nonblocking(conn)) { + /* Nonblocking close failed */ + close_finished = 1; + err = ERR_WOULDBLOCK; + } else { + /* Blocking close, check the timeout */ +#if LWIP_SO_SNDTIMEO || LWIP_SO_LINGER + s32_t close_timeout = LWIP_TCP_CLOSE_TIMEOUT_MS_DEFAULT; + /* this is kind of an lwip addition to the standard sockets: we wait + for some time when failing to allocate a segment for the FIN */ +#if LWIP_SO_SNDTIMEO + if (conn->send_timeout > 0) { + close_timeout = conn->send_timeout; + } +#endif /* LWIP_SO_SNDTIMEO */ +#if LWIP_SO_LINGER + if (conn->linger >= 0) { + /* use linger timeout (seconds) */ + close_timeout = conn->linger * 1000U; + } +#endif + if ((s32_t)(sys_now() - conn->current_msg->msg.sd.time_started) >= close_timeout) { +#else /* LWIP_SO_SNDTIMEO || LWIP_SO_LINGER */ + if (conn->current_msg->msg.sd.polls_left == 0) { +#endif /* LWIP_SO_SNDTIMEO || LWIP_SO_LINGER */ + close_finished = 1; + if (close) { + /* in this case, we want to RST the connection */ + tcp_abort(tpcb); + err = ERR_OK; + } + } + } + } else { + /* Closing failed for a non-memory error: give up */ + close_finished = 1; + } + } + if (close_finished) { + /* Closing done (succeeded, non-memory error, nonblocking error or timeout) */ + sys_sem_t* op_completed_sem = LWIP_API_MSG_SEM(conn->current_msg); + conn->current_msg->err = err; + conn->current_msg = NULL; + conn->state = NETCONN_NONE; + if (err == ERR_OK) { + if (close) { + /* Set back some callback pointers as conn is going away */ + conn->pcb.tcp = NULL; + /* Trigger select() in socket layer. Make sure everybody notices activity + on the connection, error first! */ + API_EVENT(conn, NETCONN_EVT_ERROR, 0); + } + if (shut_rx) { + API_EVENT(conn, NETCONN_EVT_RCVPLUS, 0); + } + if (shut_tx) { + API_EVENT(conn, NETCONN_EVT_SENDPLUS, 0); + } + } + NETCONN_SET_SAFE_ERR(conn, err); +#if LWIP_TCPIP_CORE_LOCKING + if (delayed) +#endif + { + /* wake up the application task */ + sys_sem_signal(op_completed_sem); + } + return ERR_OK; + } + if (!close_finished) { + /* Closing failed and we want to wait: restore some of the callbacks */ + /* Closing of listen pcb will never fail! */ + LWIP_ASSERT("Closing a listen pcb may not fail!", (tpcb->state != LISTEN)); + if (shut_tx) { + tcp_sent(tpcb, sent_tcp); + } + /* when waiting for close, set up poll interval to 500ms */ + tcp_poll(tpcb, poll_tcp, 1); + tcp_err(tpcb, err_tcp); + tcp_arg(tpcb, conn); + /* don't restore recv callback: we don't want to receive any more data */ + } + /* If closing didn't succeed, we get called again either + from poll_tcp or from sent_tcp */ + LWIP_ASSERT("err != ERR_OK", err != ERR_OK); + return err; +} +#endif /* LWIP_TCP */ + +/** + * Delete the pcb inside a netconn. + * Called from netconn_delete. + * + * @param msg the api_msg_msg pointing to the connection + */ +void +lwip_netconn_do_delconn(void *m) +{ + struct api_msg_msg *msg = (struct api_msg_msg*)m; + + enum netconn_state state = msg->conn->state; + LWIP_ASSERT("netconn state error", /* this only happens for TCP netconns */ + (state == NETCONN_NONE) || (NETCONNTYPE_GROUP(msg->conn->type) == NETCONN_TCP)); +#if LWIP_NETCONN_FULLDUPLEX + /* In full duplex mode, blocking write/connect is aborted with ERR_CLSD */ + if (state != NETCONN_NONE) { + if ((state == NETCONN_WRITE) || + ((state == NETCONN_CONNECT) && !IN_NONBLOCKING_CONNECT(msg->conn))) { + /* close requested, abort running write/connect */ + sys_sem_t* op_completed_sem; + LWIP_ASSERT("msg->conn->current_msg != NULL", msg->conn->current_msg != NULL); + op_completed_sem = LWIP_API_MSG_SEM(msg->conn->current_msg); + msg->conn->current_msg->err = ERR_CLSD; + msg->conn->current_msg = NULL; + msg->conn->write_offset = 0; + msg->conn->state = NETCONN_NONE; + NETCONN_SET_SAFE_ERR(msg->conn, ERR_CLSD); + sys_sem_signal(op_completed_sem); + } + } +#else /* LWIP_NETCONN_FULLDUPLEX */ + if (((state != NETCONN_NONE) && + (state != NETCONN_LISTEN) && + (state != NETCONN_CONNECT)) || + ((state == NETCONN_CONNECT) && !IN_NONBLOCKING_CONNECT(msg->conn))) { + /* This means either a blocking write or blocking connect is running + (nonblocking write returns and sets state to NONE) */ + msg->err = ERR_INPROGRESS; + } else +#endif /* LWIP_NETCONN_FULLDUPLEX */ + { + LWIP_ASSERT("blocking connect in progress", + (state != NETCONN_CONNECT) || IN_NONBLOCKING_CONNECT(msg->conn)); + msg->err = ERR_OK; + /* Drain and delete mboxes */ + netconn_drain(msg->conn); + + if (msg->conn->pcb.tcp != NULL) { + + switch (NETCONNTYPE_GROUP(msg->conn->type)) { +#if LWIP_RAW + case NETCONN_RAW: + raw_remove(msg->conn->pcb.raw); + break; +#endif /* LWIP_RAW */ +#if LWIP_UDP + case NETCONN_UDP: + msg->conn->pcb.udp->recv_arg = NULL; + udp_remove(msg->conn->pcb.udp); + break; +#endif /* LWIP_UDP */ +#if LWIP_TCP + case NETCONN_TCP: + LWIP_ASSERT("already writing or closing", msg->conn->current_msg == NULL && + msg->conn->write_offset == 0); + msg->conn->state = NETCONN_CLOSE; + msg->msg.sd.shut = NETCONN_SHUT_RDWR; + msg->conn->current_msg = msg; +#if LWIP_TCPIP_CORE_LOCKING + if (lwip_netconn_do_close_internal(msg->conn, 0) != ERR_OK) { + LWIP_ASSERT("state!", msg->conn->state == NETCONN_CLOSE); + UNLOCK_TCPIP_CORE(); + sys_arch_sem_wait(LWIP_API_MSG_SEM(msg), 0); + LOCK_TCPIP_CORE(); + LWIP_ASSERT("state!", msg->conn->state == NETCONN_NONE); + } +#else /* LWIP_TCPIP_CORE_LOCKING */ + lwip_netconn_do_close_internal(msg->conn); +#endif /* LWIP_TCPIP_CORE_LOCKING */ + /* API_EVENT is called inside lwip_netconn_do_close_internal, before releasing + the application thread, so we can return at this point! */ + return; +#endif /* LWIP_TCP */ + default: + break; + } + msg->conn->pcb.tcp = NULL; + } + /* tcp netconns don't come here! */ + + /* @todo: this lets select make the socket readable and writable, + which is wrong! errfd instead? */ + API_EVENT(msg->conn, NETCONN_EVT_RCVPLUS, 0); + API_EVENT(msg->conn, NETCONN_EVT_SENDPLUS, 0); + } + if (sys_sem_valid(LWIP_API_MSG_SEM(msg))) { + TCPIP_APIMSG_ACK(msg); + } +} + +/** + * Bind a pcb contained in a netconn + * Called from netconn_bind. + * + * @param msg the api_msg_msg pointing to the connection and containing + * the IP address and port to bind to + */ +void +lwip_netconn_do_bind(void *m) +{ + struct api_msg_msg *msg = (struct api_msg_msg*)m; + + if (ERR_IS_FATAL(msg->conn->last_err)) { + msg->err = msg->conn->last_err; + } else { + msg->err = ERR_VAL; + if (msg->conn->pcb.tcp != NULL) { + const ip_addr_t *ipaddr = API_EXPR_REF(msg->msg.bc.ipaddr); + +#if LWIP_IPV4 && LWIP_IPV6 + /* "Socket API like" dual-stack support: If IP to bind to is IP6_ADDR_ANY, + * and NETCONN_FLAG_IPV6_V6ONLY is NOT set, use IP_ANY_TYPE to bind + */ + if (ip_addr_cmp(ipaddr, IP6_ADDR_ANY) && + (netconn_get_ipv6only(msg->conn) == 0)) { + /* change PCB type to IPADDR_TYPE_ANY */ + IP_SET_TYPE_VAL(msg->conn->pcb.ip->local_ip, IPADDR_TYPE_ANY); + IP_SET_TYPE_VAL(msg->conn->pcb.ip->remote_ip, IPADDR_TYPE_ANY); + + /* bind to IPADDR_TYPE_ANY */ + ipaddr = IP_ANY_TYPE; + } +#endif /* LWIP_IPV4 && LWIP_IPV6 */ + + switch (NETCONNTYPE_GROUP(msg->conn->type)) { +#if LWIP_RAW + case NETCONN_RAW: + msg->err = raw_bind(msg->conn->pcb.raw, ipaddr); + break; +#endif /* LWIP_RAW */ +#if LWIP_UDP + case NETCONN_UDP: + msg->err = udp_bind(msg->conn->pcb.udp, ipaddr, msg->msg.bc.port); + break; +#endif /* LWIP_UDP */ +#if LWIP_TCP + case NETCONN_TCP: + msg->err = tcp_bind(msg->conn->pcb.tcp, ipaddr, msg->msg.bc.port); + break; +#endif /* LWIP_TCP */ + default: + break; + } + } + } + TCPIP_APIMSG_ACK(msg); +} + +#if LWIP_TCP +/** + * TCP callback function if a connection (opened by tcp_connect/lwip_netconn_do_connect) has + * been established (or reset by the remote host). + * + * @see tcp.h (struct tcp_pcb.connected) for parameters and return values + */ +static err_t +lwip_netconn_do_connected(void *arg, struct tcp_pcb *pcb, err_t err) +{ + struct netconn *conn; + int was_blocking; + sys_sem_t* op_completed_sem = NULL; + + LWIP_UNUSED_ARG(pcb); + + conn = (struct netconn *)arg; + + if (conn == NULL) { + return ERR_VAL; + } + + LWIP_ASSERT("conn->state == NETCONN_CONNECT", conn->state == NETCONN_CONNECT); + LWIP_ASSERT("(conn->current_msg != NULL) || conn->in_non_blocking_connect", + (conn->current_msg != NULL) || IN_NONBLOCKING_CONNECT(conn)); + + if (conn->current_msg != NULL) { + conn->current_msg->err = err; + op_completed_sem = LWIP_API_MSG_SEM(conn->current_msg); + } + if ((NETCONNTYPE_GROUP(conn->type) == NETCONN_TCP) && (err == ERR_OK)) { + setup_tcp(conn); + } + was_blocking = !IN_NONBLOCKING_CONNECT(conn); + SET_NONBLOCKING_CONNECT(conn, 0); + LWIP_ASSERT("blocking connect state error", + (was_blocking && op_completed_sem != NULL) || + (!was_blocking && op_completed_sem == NULL)); + conn->current_msg = NULL; + conn->state = NETCONN_NONE; + NETCONN_SET_SAFE_ERR(conn, ERR_OK); + API_EVENT(conn, NETCONN_EVT_SENDPLUS, 0); + + if (was_blocking) { + sys_sem_signal(op_completed_sem); + } + return ERR_OK; +} +#endif /* LWIP_TCP */ + +/** + * Connect a pcb contained inside a netconn + * Called from netconn_connect. + * + * @param msg the api_msg_msg pointing to the connection and containing + * the IP address and port to connect to + */ +void +lwip_netconn_do_connect(void *m) +{ + struct api_msg_msg *msg = (struct api_msg_msg*)m; + + if (msg->conn->pcb.tcp == NULL) { + /* This may happen when calling netconn_connect() a second time */ + msg->err = ERR_CLSD; + } else { + switch (NETCONNTYPE_GROUP(msg->conn->type)) { +#if LWIP_RAW + case NETCONN_RAW: + msg->err = raw_connect(msg->conn->pcb.raw, API_EXPR_REF(msg->msg.bc.ipaddr)); + break; +#endif /* LWIP_RAW */ +#if LWIP_UDP + case NETCONN_UDP: + msg->err = udp_connect(msg->conn->pcb.udp, API_EXPR_REF(msg->msg.bc.ipaddr), msg->msg.bc.port); + break; +#endif /* LWIP_UDP */ +#if LWIP_TCP + case NETCONN_TCP: + /* Prevent connect while doing any other action. */ + if (msg->conn->state == NETCONN_CONNECT) { + msg->err = ERR_ALREADY; + } else if (msg->conn->state != NETCONN_NONE) { + +#ifdef LWIP_ESP8266 + if( msg->conn->pcb.tcp->state == ESTABLISHED ) + msg->err = ERR_ISCONN; + else + msg->err = ERR_ALREADY; +#else + msg->err = ERR_ISCONN; +#endif + + } else { + setup_tcp(msg->conn); + msg->err = tcp_connect(msg->conn->pcb.tcp, API_EXPR_REF(msg->msg.bc.ipaddr), + msg->msg.bc.port, lwip_netconn_do_connected); + if (msg->err == ERR_OK) { + u8_t non_blocking = netconn_is_nonblocking(msg->conn); + msg->conn->state = NETCONN_CONNECT; + SET_NONBLOCKING_CONNECT(msg->conn, non_blocking); + if (non_blocking) { + msg->err = ERR_INPROGRESS; + } else { + msg->conn->current_msg = msg; + /* sys_sem_signal() is called from lwip_netconn_do_connected (or err_tcp()), + when the connection is established! */ +#if LWIP_TCPIP_CORE_LOCKING + LWIP_ASSERT("state!", msg->conn->state == NETCONN_CONNECT); + UNLOCK_TCPIP_CORE(); + sys_arch_sem_wait(LWIP_API_MSG_SEM(msg), 0); + LOCK_TCPIP_CORE(); + LWIP_ASSERT("state!", msg->conn->state != NETCONN_CONNECT); +#endif /* LWIP_TCPIP_CORE_LOCKING */ + return; + } + } + } + break; +#endif /* LWIP_TCP */ + default: + LWIP_ERROR("Invalid netconn type", 0, do{ msg->err = ERR_VAL; }while(0)); + break; + } + } + /* For all other protocols, netconn_connect() calls TCPIP_APIMSG(), + so use TCPIP_APIMSG_ACK() here. */ + TCPIP_APIMSG_ACK(msg); +} + +/** + * Disconnect a pcb contained inside a netconn + * Only used for UDP netconns. + * Called from netconn_disconnect. + * + * @param msg the api_msg_msg pointing to the connection to disconnect + */ +void +lwip_netconn_do_disconnect(void *m) +{ + struct api_msg_msg *msg = (struct api_msg_msg*)m; + +#if LWIP_UDP + if (NETCONNTYPE_GROUP(msg->conn->type) == NETCONN_UDP) { + udp_disconnect(msg->conn->pcb.udp); + msg->err = ERR_OK; + } else +#endif /* LWIP_UDP */ + { + msg->err = ERR_VAL; + } + TCPIP_APIMSG_ACK(msg); +} + +#if LWIP_TCP +/** + * Set a TCP pcb contained in a netconn into listen mode + * Called from netconn_listen. + * + * @param msg the api_msg_msg pointing to the connection + */ +void +lwip_netconn_do_listen(void *m) +{ + struct api_msg_msg *msg = (struct api_msg_msg*)m; + + if (ERR_IS_FATAL(msg->conn->last_err)) { + msg->err = msg->conn->last_err; + } else { + msg->err = ERR_CONN; + if (msg->conn->pcb.tcp != NULL) { + if (NETCONNTYPE_GROUP(msg->conn->type) == NETCONN_TCP) { + if (msg->conn->state == NETCONN_NONE) { + struct tcp_pcb* lpcb; + if (msg->conn->pcb.tcp->state != CLOSED) { + /* connection is not closed, cannot listen */ + msg->err = ERR_VAL; + } else { +#if LWIP_IPV4 && LWIP_IPV6 + /* "Socket API like" dual-stack support: If IP to listen to is IP6_ADDR_ANY, + * and NETCONN_FLAG_IPV6_V6ONLY is NOT set, use IP_ANY_TYPE to listen + */ + if (ip_addr_cmp(&msg->conn->pcb.ip->local_ip, IP6_ADDR_ANY) && + (netconn_get_ipv6only(msg->conn) == 0)) { + /* change PCB type to IPADDR_TYPE_ANY */ + IP_SET_TYPE_VAL(msg->conn->pcb.tcp->local_ip, IPADDR_TYPE_ANY); + IP_SET_TYPE_VAL(msg->conn->pcb.tcp->remote_ip, IPADDR_TYPE_ANY); + } +#endif /* LWIP_IPV4 && LWIP_IPV6 */ + +#if TCP_LISTEN_BACKLOG + lpcb = tcp_listen_with_backlog(msg->conn->pcb.tcp, msg->msg.lb.backlog); +#else /* TCP_LISTEN_BACKLOG */ + lpcb = tcp_listen(msg->conn->pcb.tcp); +#endif /* TCP_LISTEN_BACKLOG */ + + if (lpcb == NULL) { + /* in this case, the old pcb is still allocated */ + msg->err = ERR_MEM; + } else { + /* delete the recvmbox and allocate the acceptmbox */ + if (sys_mbox_valid(&msg->conn->recvmbox)) { + /** @todo: should we drain the recvmbox here? */ + sys_mbox_free(&msg->conn->recvmbox); + sys_mbox_set_invalid(&msg->conn->recvmbox); + } + msg->err = ERR_OK; + if (!sys_mbox_valid(&msg->conn->acceptmbox)) { + msg->err = sys_mbox_new(&msg->conn->acceptmbox, DEFAULT_ACCEPTMBOX_SIZE); + } + if (msg->err == ERR_OK) { + msg->conn->state = NETCONN_LISTEN; + msg->conn->pcb.tcp = lpcb; + tcp_arg(msg->conn->pcb.tcp, msg->conn); + tcp_accept(msg->conn->pcb.tcp, accept_function); + } else { + /* since the old pcb is already deallocated, free lpcb now */ + tcp_close(lpcb); + msg->conn->pcb.tcp = NULL; + } + } + } + } else if (msg->conn->state == NETCONN_LISTEN) { + /* already listening, allow updating of the backlog */ + msg->err = ERR_OK; +#if TCP_LISTEN_BACKLOG + tcp_backlog_set(msg->conn->pcb.tcp, msg->msg.lb.backlog); +#endif /* TCP_LISTEN_BACKLOG */ + } + } else { + msg->err = ERR_ARG; + } + } + } + TCPIP_APIMSG_ACK(msg); +} +#endif /* LWIP_TCP */ + +/** + * Send some data on a RAW or UDP pcb contained in a netconn + * Called from netconn_send + * + * @param msg the api_msg_msg pointing to the connection + */ +void +lwip_netconn_do_send(void *m) +{ + struct api_msg_msg *msg = (struct api_msg_msg*)m; + + if (ERR_IS_FATAL(msg->conn->last_err)) { + msg->err = msg->conn->last_err; + } else { + msg->err = ERR_CONN; + if (msg->conn->pcb.tcp != NULL) { + switch (NETCONNTYPE_GROUP(msg->conn->type)) { +#if LWIP_RAW + case NETCONN_RAW: + if (ip_addr_isany(&msg->msg.b->addr)) { + msg->err = raw_send(msg->conn->pcb.raw, msg->msg.b->p); + } else { + msg->err = raw_sendto(msg->conn->pcb.raw, msg->msg.b->p, &msg->msg.b->addr); + } + break; +#endif +#if LWIP_UDP + case NETCONN_UDP: +#if LWIP_CHECKSUM_ON_COPY + if (ip_addr_isany(&msg->msg.b->addr) || IP_IS_ANY_TYPE_VAL(msg->msg.b->addr)) { + msg->err = udp_send_chksum(msg->conn->pcb.udp, msg->msg.b->p, + msg->msg.b->flags & NETBUF_FLAG_CHKSUM, msg->msg.b->toport_chksum); + } else { + msg->err = udp_sendto_chksum(msg->conn->pcb.udp, msg->msg.b->p, + &msg->msg.b->addr, msg->msg.b->port, + msg->msg.b->flags & NETBUF_FLAG_CHKSUM, msg->msg.b->toport_chksum); + } +#else /* LWIP_CHECKSUM_ON_COPY */ + if (ip_addr_isany_val(msg->msg.b->addr) || IP_IS_ANY_TYPE_VAL(msg->msg.b->addr)) { + msg->err = udp_send(msg->conn->pcb.udp, msg->msg.b->p); + } else { + msg->err = udp_sendto(msg->conn->pcb.udp, msg->msg.b->p, &msg->msg.b->addr, msg->msg.b->port); + } +#endif /* LWIP_CHECKSUM_ON_COPY */ + break; +#endif /* LWIP_UDP */ + default: + break; + } + } + } + TCPIP_APIMSG_ACK(msg); +} + +#if LWIP_TCP +/** + * Indicate data has been received from a TCP pcb contained in a netconn + * Called from netconn_recv + * + * @param msg the api_msg_msg pointing to the connection + */ +void +lwip_netconn_do_recv(void *m) +{ + struct api_msg_msg *msg = (struct api_msg_msg*)m; + + msg->err = ERR_OK; + if (msg->conn->pcb.tcp != NULL) { + if (NETCONNTYPE_GROUP(msg->conn->type) == NETCONN_TCP) { +#if TCP_LISTEN_BACKLOG + if (msg->conn->pcb.tcp->state == LISTEN) { + tcp_accepted(msg->conn->pcb.tcp); + } else +#endif /* TCP_LISTEN_BACKLOG */ + { + u32_t remaining = msg->msg.r.len; + do { + u16_t recved = (remaining > 0xffff) ? 0xffff : (u16_t)remaining; + tcp_recved(msg->conn->pcb.tcp, recved); + remaining -= recved; + } while (remaining != 0); + } + } + } + TCPIP_APIMSG_ACK(msg); +} + +/** + * See if more data needs to be written from a previous call to netconn_write. + * Called initially from lwip_netconn_do_write. If the first call can't send all data + * (because of low memory or empty send-buffer), this function is called again + * from sent_tcp() or poll_tcp() to send more data. If all data is sent, the + * blocking application thread (waiting in netconn_write) is released. + * + * @param conn netconn (that is currently in state NETCONN_WRITE) to process + * [@param delay 1 if called from sent/poll (wake up calling thread on end)] + * @return ERR_OK + * ERR_MEM if LWIP_TCPIP_CORE_LOCKING=1 and sending hasn't yet finished + */ +static err_t +lwip_netconn_do_writemore(struct netconn *conn WRITE_DELAYED_PARAM) +{ + err_t err; + const void *dataptr; + u16_t len, available; + u8_t write_finished = 0; + size_t diff; + u8_t dontblock; + u8_t apiflags; + + LWIP_ASSERT("conn != NULL", conn != NULL); + LWIP_ASSERT("conn->state == NETCONN_WRITE", (conn->state == NETCONN_WRITE)); + LWIP_ASSERT("conn->current_msg != NULL", conn->current_msg != NULL); + LWIP_ASSERT("conn->pcb.tcp != NULL", conn->pcb.tcp != NULL); + LWIP_ASSERT("conn->write_offset < conn->current_msg->msg.w.len", + conn->write_offset < conn->current_msg->msg.w.len); + + dontblock = netconn_is_nonblocking(conn) || + (conn->current_msg->msg.w.apiflags & NETCONN_DONTBLOCK); + apiflags = conn->current_msg->msg.w.apiflags; + +#if LWIP_SO_SNDTIMEO + if ((conn->send_timeout != 0) && + ((s32_t)(sys_now() - conn->current_msg->msg.w.time_started) >= conn->send_timeout)) { + write_finished = 1; + if (conn->write_offset == 0) { + /* nothing has been written */ + err = ERR_WOULDBLOCK; + conn->current_msg->msg.w.len = 0; + } else { + /* partial write */ + err = ERR_OK; + conn->current_msg->msg.w.len = conn->write_offset; + conn->write_offset = 0; + } + } else +#endif /* LWIP_SO_SNDTIMEO */ + { + dataptr = (const u8_t*)conn->current_msg->msg.w.dataptr + conn->write_offset; + diff = conn->current_msg->msg.w.len - conn->write_offset; + if (diff > 0xffffUL) { /* max_u16_t */ + len = 0xffff; + apiflags |= TCP_WRITE_FLAG_MORE; + } else { + len = (u16_t)diff; + } + available = tcp_sndbuf(conn->pcb.tcp); + if (available < len) { + /* don't try to write more than sendbuf */ + len = available; + if (dontblock) { + if (!len) { + err = ERR_WOULDBLOCK; + goto err_mem; + } + } else { + apiflags |= TCP_WRITE_FLAG_MORE; + } + } + LWIP_ASSERT("lwip_netconn_do_writemore: invalid length!", ((conn->write_offset + len) <= conn->current_msg->msg.w.len)); + err = tcp_write(conn->pcb.tcp, dataptr, len, apiflags); + /* if OK or memory error, check available space */ + if ((err == ERR_OK) || (err == ERR_MEM)) { +err_mem: + if (dontblock && (len < conn->current_msg->msg.w.len)) { + /* non-blocking write did not write everything: mark the pcb non-writable + and let poll_tcp check writable space to mark the pcb writable again */ + API_EVENT(conn, NETCONN_EVT_SENDMINUS, len); + conn->flags |= NETCONN_FLAG_CHECK_WRITESPACE; + } else if ((tcp_sndbuf(conn->pcb.tcp) <= TCP_SNDLOWAT) || + (tcp_sndqueuelen(conn->pcb.tcp) >= TCP_SNDQUEUELOWAT)) { + /* The queued byte- or pbuf-count exceeds the configured low-water limit, + let select mark this pcb as non-writable. */ + API_EVENT(conn, NETCONN_EVT_SENDMINUS, len); + } + } + + if (err == ERR_OK) { + err_t out_err; + conn->write_offset += len; + if ((conn->write_offset == conn->current_msg->msg.w.len) || dontblock) { + /* return sent length */ + conn->current_msg->msg.w.len = conn->write_offset; + /* everything was written */ + write_finished = 1; + } + out_err = tcp_output(conn->pcb.tcp); + if (ERR_IS_FATAL(out_err) || (out_err == ERR_RTE)) { + /* If tcp_output fails with fatal error or no route is found, + don't try writing any more but return the error + to the application thread. */ + err = out_err; + write_finished = 1; + conn->current_msg->msg.w.len = 0; + } + } else if ((err == ERR_MEM) && !dontblock) { + /* If ERR_MEM, we wait for sent_tcp or poll_tcp to be called + we do NOT return to the application thread, since ERR_MEM is + only a temporary error! */ + + /* tcp_write returned ERR_MEM, try tcp_output anyway */ + err_t out_err = tcp_output(conn->pcb.tcp); + if (ERR_IS_FATAL(out_err) || (out_err == ERR_RTE)) { + /* If tcp_output fails with fatal error or no route is found, + don't try writing any more but return the error + to the application thread. */ + err = out_err; + write_finished = 1; + conn->current_msg->msg.w.len = 0; + } else { + } + } else { + /* On errors != ERR_MEM, we don't try writing any more but return + the error to the application thread. */ + write_finished = 1; + conn->current_msg->msg.w.len = 0; + } + } + if (write_finished) { + /* everything was written: set back connection state + and back to application task */ + sys_sem_t* op_completed_sem = LWIP_API_MSG_SEM(conn->current_msg); + + conn->current_msg->err = err; + conn->current_msg = NULL; + conn->write_offset = 0; + conn->state = NETCONN_NONE; + NETCONN_SET_SAFE_ERR(conn, err); +#if LWIP_TCPIP_CORE_LOCKING + if (delayed) +#endif + { + sys_sem_signal(op_completed_sem); + } + } +#if LWIP_TCPIP_CORE_LOCKING + else { + return ERR_MEM; + } +#endif + return ERR_OK; +} +#endif /* LWIP_TCP */ + +/** + * Send some data on a TCP pcb contained in a netconn + * Called from netconn_write + * + * @param msg the api_msg_msg pointing to the connection + */ +void +lwip_netconn_do_write(void *m) +{ + struct api_msg_msg *msg = (struct api_msg_msg*)m; + + if (ERR_IS_FATAL(msg->conn->last_err)) { + msg->err = msg->conn->last_err; + } else { + if (NETCONNTYPE_GROUP(msg->conn->type) == NETCONN_TCP) { +#if LWIP_TCP + if (msg->conn->state != NETCONN_NONE) { + /* netconn is connecting, closing or in blocking write */ + msg->err = ERR_INPROGRESS; + } else if (msg->conn->pcb.tcp != NULL) { + msg->conn->state = NETCONN_WRITE; + /* set all the variables used by lwip_netconn_do_writemore */ + LWIP_ASSERT("already writing or closing", msg->conn->current_msg == NULL && + msg->conn->write_offset == 0); + LWIP_ASSERT("msg->msg.w.len != 0", msg->msg.w.len != 0); + msg->conn->current_msg = msg; + msg->conn->write_offset = 0; +#if LWIP_TCPIP_CORE_LOCKING + if (lwip_netconn_do_writemore(msg->conn, 0) != ERR_OK) { + LWIP_ASSERT("state!", msg->conn->state == NETCONN_WRITE); + UNLOCK_TCPIP_CORE(); + +#ifdef LWIP_ESP8266 +//#if 0 + sys_arch_sem_wait( LWIP_API_MSG_SND_SEM(msg), 0); +#else + sys_arch_sem_wait(LWIP_API_MSG_SEM(msg), 0); +#endif + + LOCK_TCPIP_CORE(); + LWIP_ASSERT("state!", msg->conn->state != NETCONN_WRITE); + } +#else /* LWIP_TCPIP_CORE_LOCKING */ + lwip_netconn_do_writemore(msg->conn); +#endif /* LWIP_TCPIP_CORE_LOCKING */ + /* for both cases: if lwip_netconn_do_writemore was called, don't ACK the APIMSG + since lwip_netconn_do_writemore ACKs it! */ + return; + } else { + msg->err = ERR_CONN; + } +#else /* LWIP_TCP */ + msg->err = ERR_VAL; +#endif /* LWIP_TCP */ +#if (LWIP_UDP || LWIP_RAW) + } else { + msg->err = ERR_VAL; +#endif /* (LWIP_UDP || LWIP_RAW) */ + } + } + TCPIP_APIMSG_ACK(msg); +} + +/** + * Return a connection's local or remote address + * Called from netconn_getaddr + * + * @param msg the api_msg_msg pointing to the connection + */ +void +lwip_netconn_do_getaddr(void *m) +{ + struct api_msg_msg *msg = (struct api_msg_msg*)m; + + if (msg->conn->pcb.ip != NULL) { + if (msg->msg.ad.local) { + ip_addr_copy(API_EXPR_DEREF(msg->msg.ad.ipaddr), + msg->conn->pcb.ip->local_ip); + } else { + ip_addr_copy(API_EXPR_DEREF(msg->msg.ad.ipaddr), + msg->conn->pcb.ip->remote_ip); + } + msg->err = ERR_OK; + switch (NETCONNTYPE_GROUP(msg->conn->type)) { +#if LWIP_RAW + case NETCONN_RAW: + if (msg->msg.ad.local) { + API_EXPR_DEREF(msg->msg.ad.port) = msg->conn->pcb.raw->protocol; + } else { + /* return an error as connecting is only a helper for upper layers */ + msg->err = ERR_CONN; + } + break; +#endif /* LWIP_RAW */ +#if LWIP_UDP + case NETCONN_UDP: + if (msg->msg.ad.local) { + API_EXPR_DEREF(msg->msg.ad.port) = msg->conn->pcb.udp->local_port; + } else { + if ((msg->conn->pcb.udp->flags & UDP_FLAGS_CONNECTED) == 0) { + msg->err = ERR_CONN; + } else { + API_EXPR_DEREF(msg->msg.ad.port) = msg->conn->pcb.udp->remote_port; + } + } + break; +#endif /* LWIP_UDP */ +#if LWIP_TCP + case NETCONN_TCP: + if ((msg->msg.ad.local == 0) && + ((msg->conn->pcb.tcp->state == CLOSED) || (msg->conn->pcb.tcp->state == LISTEN))) { + /* pcb is not connected and remote name is requested */ + msg->err = ERR_CONN; + } else { + API_EXPR_DEREF(msg->msg.ad.port) = (msg->msg.ad.local ? msg->conn->pcb.tcp->local_port : msg->conn->pcb.tcp->remote_port); + } + break; +#endif /* LWIP_TCP */ + default: + LWIP_ASSERT("invalid netconn_type", 0); + break; + } + } else { + msg->err = ERR_CONN; + } + TCPIP_APIMSG_ACK(msg); +} + +/** + * Close or half-shutdown a TCP pcb contained in a netconn + * Called from netconn_close + * In contrast to closing sockets, the netconn is not deallocated. + * + * @param msg the api_msg_msg pointing to the connection + */ +void +lwip_netconn_do_close(void *m) +{ + struct api_msg_msg *msg = (struct api_msg_msg*)m; + +#if LWIP_TCP + enum netconn_state state = msg->conn->state; + /* First check if this is a TCP netconn and if it is in a correct state + (LISTEN doesn't support half shutdown) */ + if ((msg->conn->pcb.tcp != NULL) && + (NETCONNTYPE_GROUP(msg->conn->type) == NETCONN_TCP) && + ((msg->msg.sd.shut == NETCONN_SHUT_RDWR) || (state != NETCONN_LISTEN))) { + /* Check if we are in a connected state */ + if (state == NETCONN_CONNECT) { + /* TCP connect in progress: cannot shutdown */ + msg->err = ERR_CONN; + } else if (state == NETCONN_WRITE) { +#if LWIP_NETCONN_FULLDUPLEX + if (msg->msg.sd.shut & NETCONN_SHUT_WR) { + /* close requested, abort running write */ + sys_sem_t* op_completed_sem; + LWIP_ASSERT("msg->conn->current_msg != NULL", msg->conn->current_msg != NULL); + op_completed_sem = LWIP_API_MSG_SEM(msg->conn->current_msg); + msg->conn->current_msg->err = ERR_CLSD; + msg->conn->current_msg = NULL; + msg->conn->write_offset = 0; + msg->conn->state = NETCONN_NONE; + NETCONN_SET_SAFE_ERR(msg->conn, ERR_CLSD); + sys_sem_signal(op_completed_sem); + } else { + LWIP_ASSERT("msg->msg.sd.shut == NETCONN_SHUT_RD", msg->msg.sd.shut == NETCONN_SHUT_RD); + /* In this case, let the write continue and do not interfere with + conn->current_msg or conn->state! */ + msg->err = tcp_shutdown(msg->conn->pcb.tcp, 1, 0); + } +#else /* LWIP_NETCONN_FULLDUPLEX */ + msg->err = ERR_INPROGRESS; +#endif /* LWIP_NETCONN_FULLDUPLEX */ + } else { + if (msg->msg.sd.shut & NETCONN_SHUT_RD) { + /* Drain and delete mboxes */ + netconn_drain(msg->conn); + } + LWIP_ASSERT("already writing or closing", msg->conn->current_msg == NULL && + msg->conn->write_offset == 0); + msg->conn->state = NETCONN_CLOSE; + msg->conn->current_msg = msg; +#if LWIP_TCPIP_CORE_LOCKING + if (lwip_netconn_do_close_internal(msg->conn, 0) != ERR_OK) { + LWIP_ASSERT("state!", msg->conn->state == NETCONN_CLOSE); + UNLOCK_TCPIP_CORE(); + sys_arch_sem_wait(LWIP_API_MSG_SEM(msg), 0); + LOCK_TCPIP_CORE(); + LWIP_ASSERT("state!", msg->conn->state == NETCONN_NONE); + } +#else /* LWIP_TCPIP_CORE_LOCKING */ + lwip_netconn_do_close_internal(msg->conn); +#endif /* LWIP_TCPIP_CORE_LOCKING */ + /* for tcp netconns, lwip_netconn_do_close_internal ACKs the message */ + return; + } + } else +#endif /* LWIP_TCP */ + { + msg->err = ERR_CONN; + } + TCPIP_APIMSG_ACK(msg); +} + +#if LWIP_IGMP || (LWIP_IPV6 && LWIP_IPV6_MLD) +/** + * Join multicast groups for UDP netconns. + * Called from netconn_join_leave_group + * + * @param msg the api_msg_msg pointing to the connection + */ +void +lwip_netconn_do_join_leave_group(void *m) +{ + struct api_msg_msg *msg = (struct api_msg_msg*)m; + + if (ERR_IS_FATAL(msg->conn->last_err)) { + msg->err = msg->conn->last_err; + } else { + if (msg->conn->pcb.tcp != NULL) { + if (NETCONNTYPE_GROUP(msg->conn->type) == NETCONN_UDP) { +#if LWIP_UDP +#if LWIP_IPV6 && LWIP_IPV6_MLD + if (NETCONNTYPE_ISIPV6(msg->conn->type)) { + if (msg->msg.jl.join_or_leave == NETCONN_JOIN) { + msg->err = mld6_joingroup(ip_2_ip6(API_EXPR_REF(msg->msg.jl.netif_addr)), + ip_2_ip6(API_EXPR_REF(msg->msg.jl.multiaddr))); + } else { + msg->err = mld6_leavegroup(ip_2_ip6(API_EXPR_REF(msg->msg.jl.netif_addr)), + ip_2_ip6(API_EXPR_REF(msg->msg.jl.multiaddr))); + } + } + else +#endif /* LWIP_IPV6 && LWIP_IPV6_MLD */ + { +#if LWIP_IGMP + if (msg->msg.jl.join_or_leave == NETCONN_JOIN) { + msg->err = igmp_joingroup(ip_2_ip4(API_EXPR_REF(msg->msg.jl.netif_addr)), + ip_2_ip4(API_EXPR_REF(msg->msg.jl.multiaddr))); + } else { + msg->err = igmp_leavegroup(ip_2_ip4(API_EXPR_REF(msg->msg.jl.netif_addr)), + ip_2_ip4(API_EXPR_REF(msg->msg.jl.multiaddr))); + } +#endif /* LWIP_IGMP */ + } +#endif /* LWIP_UDP */ +#if (LWIP_TCP || LWIP_RAW) + } else { + msg->err = ERR_VAL; +#endif /* (LWIP_TCP || LWIP_RAW) */ + } + } else { + msg->err = ERR_CONN; + } + } + TCPIP_APIMSG_ACK(msg); +} +#endif /* LWIP_IGMP || (LWIP_IPV6 && LWIP_IPV6_MLD) */ + +#if LWIP_DNS +/** + * Callback function that is called when DNS name is resolved + * (or on timeout). A waiting application thread is waked up by + * signaling the semaphore. + */ +static void +lwip_netconn_do_dns_found(const char *name, const ip_addr_t *ipaddr, void *arg) +{ + struct dns_api_msg *msg = (struct dns_api_msg*)arg; + + /* we trust the internal implementation to be correct :-) */ + LWIP_UNUSED_ARG(name); + + if (ipaddr == NULL) { + /* timeout or memory error */ + API_EXPR_DEREF(msg->err) = ERR_VAL; + } else { + /* address was resolved */ + API_EXPR_DEREF(msg->err) = ERR_OK; + API_EXPR_DEREF(msg->addr) = *ipaddr; + } + /* wake up the application task waiting in netconn_gethostbyname */ + sys_sem_signal(API_EXPR_REF_SEM(msg->sem)); +} + +/** + * Execute a DNS query + * Called from netconn_gethostbyname + * + * @param arg the dns_api_msg pointing to the query + */ +void +lwip_netconn_do_gethostbyname(void *arg) +{ + struct dns_api_msg *msg = (struct dns_api_msg*)arg; + u8_t addrtype = +#if LWIP_IPV4 && LWIP_IPV6 + msg->dns_addrtype; +#else + LWIP_DNS_ADDRTYPE_DEFAULT; +#endif + + API_EXPR_DEREF(msg->err) = dns_gethostbyname_addrtype(msg->name, + API_EXPR_REF(msg->addr), lwip_netconn_do_dns_found, msg, addrtype); + if (API_EXPR_DEREF(msg->err) != ERR_INPROGRESS) { + /* on error or immediate success, wake up the application + * task waiting in netconn_gethostbyname */ + sys_sem_signal(API_EXPR_REF_SEM(msg->sem)); + } +} +#endif /* LWIP_DNS */ + +#endif /* LWIP_NETCONN */ diff --git a/components/lwip/api/err.c b/components/lwip/api/err.c new file mode 100755 index 0000000000..f3650f4cac --- /dev/null +++ b/components/lwip/api/err.c @@ -0,0 +1,75 @@ +/** + * @file + * Error Management module + * + */ + +/* + * Copyright (c) 2001-2004 Swedish Institute of Computer Science. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + * + */ + +#include "lwip/err.h" + +#ifdef LWIP_DEBUG + +static const char *err_strerr[] = { + "Ok.", /* ERR_OK 0 */ + "Out of memory error.", /* ERR_MEM -1 */ + "Buffer error.", /* ERR_BUF -2 */ + "Timeout.", /* ERR_TIMEOUT -3 */ + "Routing problem.", /* ERR_RTE -4 */ + "Operation in progress.", /* ERR_INPROGRESS -5 */ + "Illegal value.", /* ERR_VAL -6 */ + "Operation would block.", /* ERR_WOULDBLOCK -7 */ + "Address in use.", /* ERR_USE -8 */ + "Already connecting.", /* ERR_ALREADY -9 */ + "Already connected.", /* ERR_ISCONN -10 */ + "Not connected.", /* ERR_CONN -11 */ + "Low-level netif error.", /* ERR_IF -12 */ + "Connection aborted.", /* ERR_ABRT -13 */ + "Connection reset.", /* ERR_RST -14 */ + "Connection closed.", /* ERR_CLSD -15 */ + "Illegal argument." /* ERR_ARG -16 */ +}; + +/** + * Convert an lwip internal error to a string representation. + * + * @param err an lwip internal err_t + * @return a string representation for err + */ +const char * +lwip_strerr(err_t err) +{ + return err_strerr[-err]; +} + +#endif /* LWIP_DEBUG */ diff --git a/components/lwip/api/netbuf.c b/components/lwip/api/netbuf.c new file mode 100755 index 0000000000..6c6dc69ccd --- /dev/null +++ b/components/lwip/api/netbuf.c @@ -0,0 +1,250 @@ +/** + * @file + * Network buffer management + * + */ + +/* + * Copyright (c) 2001-2004 Swedish Institute of Computer Science. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + * + */ + +#include "lwip/opt.h" + +#if LWIP_NETCONN /* don't build if not configured for use in lwipopts.h */ + +#include "lwip/netbuf.h" +#include "lwip/memp.h" + +#include + +#ifdef MEMLEAK_DEBUG +static const char mem_debug_file[] ICACHE_RODATA_ATTR STORE_ATTR = __FILE__; +#endif + + +/** + * Create (allocate) and initialize a new netbuf. + * The netbuf doesn't yet contain a packet buffer! + * + * @return a pointer to a new netbuf + * NULL on lack of memory + */ +struct +netbuf *netbuf_new(void) +{ + struct netbuf *buf; + + buf = (struct netbuf *)memp_malloc(MEMP_NETBUF); + if (buf != NULL) { + buf->p = NULL; + buf->ptr = NULL; + ip_addr_set_zero(&buf->addr); + buf->port = 0; +#if LWIP_NETBUF_RECVINFO || LWIP_CHECKSUM_ON_COPY +#if LWIP_CHECKSUM_ON_COPY + buf->flags = 0; +#endif /* LWIP_CHECKSUM_ON_COPY */ + buf->toport_chksum = 0; +#if LWIP_NETBUF_RECVINFO + ip_addr_set_zero(&buf->toaddr); +#endif /* LWIP_NETBUF_RECVINFO */ +#endif /* LWIP_NETBUF_RECVINFO || LWIP_CHECKSUM_ON_COPY */ + return buf; + } else { + return NULL; + } +} + +/** + * Deallocate a netbuf allocated by netbuf_new(). + * + * @param buf pointer to a netbuf allocated by netbuf_new() + */ +void +netbuf_delete(struct netbuf *buf) +{ + if (buf != NULL) { + if (buf->p != NULL) { + pbuf_free(buf->p); + buf->p = buf->ptr = NULL; + } + memp_free(MEMP_NETBUF, buf); + } +} + +/** + * Allocate memory for a packet buffer for a given netbuf. + * + * @param buf the netbuf for which to allocate a packet buffer + * @param size the size of the packet buffer to allocate + * @return pointer to the allocated memory + * NULL if no memory could be allocated + */ +void * +netbuf_alloc(struct netbuf *buf, u16_t size) +{ + LWIP_ERROR("netbuf_alloc: invalid buf", (buf != NULL), return NULL;); + + /* Deallocate any previously allocated memory. */ + if (buf->p != NULL) { + pbuf_free(buf->p); + } + buf->p = pbuf_alloc(PBUF_TRANSPORT, size, PBUF_RAM); + if (buf->p == NULL) { + return NULL; + } + LWIP_ASSERT("check that first pbuf can hold size", + (buf->p->len >= size)); + buf->ptr = buf->p; + return buf->p->payload; +} + +/** + * Free the packet buffer included in a netbuf + * + * @param buf pointer to the netbuf which contains the packet buffer to free + */ +void +netbuf_free(struct netbuf *buf) +{ + LWIP_ERROR("netbuf_free: invalid buf", (buf != NULL), return;); + if (buf->p != NULL) { + pbuf_free(buf->p); + } + buf->p = buf->ptr = NULL; +} + +/** + * Let a netbuf reference existing (non-volatile) data. + * + * @param buf netbuf which should reference the data + * @param dataptr pointer to the data to reference + * @param size size of the data + * @return ERR_OK if data is referenced + * ERR_MEM if data couldn't be referenced due to lack of memory + */ +err_t +netbuf_ref(struct netbuf *buf, const void *dataptr, u16_t size) +{ + LWIP_ERROR("netbuf_ref: invalid buf", (buf != NULL), return ERR_ARG;); + if (buf->p != NULL) { + pbuf_free(buf->p); + } + buf->p = pbuf_alloc(PBUF_TRANSPORT, 0, PBUF_REF); + if (buf->p == NULL) { + buf->ptr = NULL; + return ERR_MEM; + } + ((struct pbuf_rom*)buf->p)->payload = dataptr; + buf->p->len = buf->p->tot_len = size; + buf->ptr = buf->p; + return ERR_OK; +} + +/** + * Chain one netbuf to another (@see pbuf_chain) + * + * @param head the first netbuf + * @param tail netbuf to chain after head, freed by this function, may not be reference after returning + */ +void +netbuf_chain(struct netbuf *head, struct netbuf *tail) +{ + LWIP_ERROR("netbuf_ref: invalid head", (head != NULL), return;); + LWIP_ERROR("netbuf_chain: invalid tail", (tail != NULL), return;); + pbuf_cat(head->p, tail->p); + head->ptr = head->p; + memp_free(MEMP_NETBUF, tail); +} + +/** + * Get the data pointer and length of the data inside a netbuf. + * + * @param buf netbuf to get the data from + * @param dataptr pointer to a void pointer where to store the data pointer + * @param len pointer to an u16_t where the length of the data is stored + * @return ERR_OK if the information was retrieved, + * ERR_BUF on error. + */ +err_t +netbuf_data(struct netbuf *buf, void **dataptr, u16_t *len) +{ + LWIP_ERROR("netbuf_data: invalid buf", (buf != NULL), return ERR_ARG;); + LWIP_ERROR("netbuf_data: invalid dataptr", (dataptr != NULL), return ERR_ARG;); + LWIP_ERROR("netbuf_data: invalid len", (len != NULL), return ERR_ARG;); + + if (buf->ptr == NULL) { + return ERR_BUF; + } + *dataptr = buf->ptr->payload; + *len = buf->ptr->len; + return ERR_OK; +} + +/** + * Move the current data pointer of a packet buffer contained in a netbuf + * to the next part. + * The packet buffer itself is not modified. + * + * @param buf the netbuf to modify + * @return -1 if there is no next part + * 1 if moved to the next part but now there is no next part + * 0 if moved to the next part and there are still more parts + */ +s8_t +netbuf_next(struct netbuf *buf) +{ + LWIP_ERROR("netbuf_free: invalid buf", (buf != NULL), return -1;); + if (buf->ptr->next == NULL) { + return -1; + } + buf->ptr = buf->ptr->next; + if (buf->ptr->next == NULL) { + return 1; + } + return 0; +} + +/** + * Move the current data pointer of a packet buffer contained in a netbuf + * to the beginning of the packet. + * The packet buffer itself is not modified. + * + * @param buf the netbuf to modify + */ +void +netbuf_first(struct netbuf *buf) +{ + LWIP_ERROR("netbuf_free: invalid buf", (buf != NULL), return;); + buf->ptr = buf->p; +} + +#endif /* LWIP_NETCONN */ diff --git a/components/lwip/api/netdb.c b/components/lwip/api/netdb.c new file mode 100755 index 0000000000..8fd3f41861 --- /dev/null +++ b/components/lwip/api/netdb.c @@ -0,0 +1,415 @@ +/** + * @file + * API functions for name resolving + * + */ + +/* + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Simon Goldschmidt + * + */ + +#include "lwip/netdb.h" + +#if LWIP_DNS && LWIP_SOCKET + +#include "lwip/err.h" +#include "lwip/mem.h" +#include "lwip/memp.h" +#include "lwip/ip_addr.h" +#include "lwip/api.h" +#include "lwip/dns.h" + +#include +#include + +#ifdef MEMLEAK_DEBUG +static const char mem_debug_file[] ICACHE_RODATA_ATTR STORE_ATTR = __FILE__; +#endif + + +/** helper struct for gethostbyname_r to access the char* buffer */ +struct gethostbyname_r_helper { + ip_addr_t *addr_list[2]; + ip_addr_t addr; + char *aliases; +}; + +/** h_errno is exported in netdb.h for access by applications. */ +#if LWIP_DNS_API_DECLARE_H_ERRNO +int h_errno; +#endif /* LWIP_DNS_API_DECLARE_H_ERRNO */ + +/** define "hostent" variables storage: 0 if we use a static (but unprotected) + * set of variables for lwip_gethostbyname, 1 if we use a local storage */ +#ifndef LWIP_DNS_API_HOSTENT_STORAGE +#define LWIP_DNS_API_HOSTENT_STORAGE 0 +#endif + +/** define "hostent" variables storage */ +#if LWIP_DNS_API_HOSTENT_STORAGE +#define HOSTENT_STORAGE +#else +#define HOSTENT_STORAGE static +#endif /* LWIP_DNS_API_STATIC_HOSTENT */ + +/** + * Returns an entry containing addresses of address family AF_INET + * for the host with name name. + * Due to dns_gethostbyname limitations, only one address is returned. + * + * @param name the hostname to resolve + * @return an entry containing addresses of address family AF_INET + * for the host with name name + */ +struct hostent* +lwip_gethostbyname(const char *name) +{ + err_t err; + ip_addr_t addr; + + /* buffer variables for lwip_gethostbyname() */ + HOSTENT_STORAGE struct hostent s_hostent; + HOSTENT_STORAGE char *s_aliases; + HOSTENT_STORAGE ip_addr_t s_hostent_addr; + HOSTENT_STORAGE ip_addr_t *s_phostent_addr[2]; + HOSTENT_STORAGE char s_hostname[DNS_MAX_NAME_LENGTH + 1]; + + /* query host IP address */ + err = netconn_gethostbyname(name, &addr); + if (err != ERR_OK) { + LWIP_DEBUGF(DNS_DEBUG, ("lwip_gethostbyname(%s) failed, err=%d\n", name, err)); + h_errno = HOST_NOT_FOUND; + return NULL; + } + + /* fill hostent */ + s_hostent_addr = addr; + s_phostent_addr[0] = &s_hostent_addr; + s_phostent_addr[1] = NULL; + strncpy(s_hostname, name, DNS_MAX_NAME_LENGTH); + s_hostname[DNS_MAX_NAME_LENGTH] = 0; + s_hostent.h_name = s_hostname; + s_aliases = NULL; + s_hostent.h_aliases = &s_aliases; + s_hostent.h_addrtype = AF_INET; + s_hostent.h_length = sizeof(ip_addr_t); + s_hostent.h_addr_list = (char**)&s_phostent_addr; + +#if DNS_DEBUG + /* dump hostent */ + LWIP_DEBUGF(DNS_DEBUG, ("hostent.h_name == %s\n", s_hostent.h_name)); + LWIP_DEBUGF(DNS_DEBUG, ("hostent.h_aliases == %p\n", (void*)s_hostent.h_aliases)); + /* h_aliases are always empty */ + LWIP_DEBUGF(DNS_DEBUG, ("hostent.h_addrtype == %d\n", s_hostent.h_addrtype)); + LWIP_DEBUGF(DNS_DEBUG, ("hostent.h_length == %d\n", s_hostent.h_length)); + LWIP_DEBUGF(DNS_DEBUG, ("hostent.h_addr_list == %p\n", (void*)s_hostent.h_addr_list)); + if (s_hostent.h_addr_list != NULL) { + u8_t idx; + for (idx=0; s_hostent.h_addr_list[idx]; idx++) { + LWIP_DEBUGF(DNS_DEBUG, ("hostent.h_addr_list[%i] == %p\n", idx, s_hostent.h_addr_list[idx])); + LWIP_DEBUGF(DNS_DEBUG, ("hostent.h_addr_list[%i]-> == %s\n", idx, ipaddr_ntoa((ip_addr_t*)s_hostent.h_addr_list[idx]))); + } + } +#endif /* DNS_DEBUG */ + +#if LWIP_DNS_API_HOSTENT_STORAGE + /* this function should return the "per-thread" hostent after copy from s_hostent */ + return sys_thread_hostent(&s_hostent); +#else + return &s_hostent; +#endif /* LWIP_DNS_API_HOSTENT_STORAGE */ +} + +/** + * Thread-safe variant of lwip_gethostbyname: instead of using a static + * buffer, this function takes buffer and errno pointers as arguments + * and uses these for the result. + * + * @param name the hostname to resolve + * @param ret pre-allocated struct where to store the result + * @param buf pre-allocated buffer where to store additional data + * @param buflen the size of buf + * @param result pointer to a hostent pointer that is set to ret on success + * and set to zero on error + * @param h_errnop pointer to an int where to store errors (instead of modifying + * the global h_errno) + * @return 0 on success, non-zero on error, additional error information + * is stored in *h_errnop instead of h_errno to be thread-safe + */ +int +lwip_gethostbyname_r(const char *name, struct hostent *ret, char *buf, + size_t buflen, struct hostent **result, int *h_errnop) +{ + err_t err; + struct gethostbyname_r_helper *h; + char *hostname; + size_t namelen; + int lh_errno; + + if (h_errnop == NULL) { + /* ensure h_errnop is never NULL */ + h_errnop = &lh_errno; + } + + if (result == NULL) { + /* not all arguments given */ + *h_errnop = EINVAL; + return -1; + } + /* first thing to do: set *result to nothing */ + *result = NULL; + if ((name == NULL) || (ret == NULL) || (buf == NULL)) { + /* not all arguments given */ + *h_errnop = EINVAL; + return -1; + } + + namelen = strlen(name); + if (buflen < (sizeof(struct gethostbyname_r_helper) + namelen + 1 + (MEM_ALIGNMENT - 1))) { + /* buf can't hold the data needed + a copy of name */ + *h_errnop = ERANGE; + return -1; + } + + h = (struct gethostbyname_r_helper*)LWIP_MEM_ALIGN(buf); + hostname = ((char*)h) + sizeof(struct gethostbyname_r_helper); + + /* query host IP address */ + err = netconn_gethostbyname(name, &h->addr); + if (err != ERR_OK) { + LWIP_DEBUGF(DNS_DEBUG, ("lwip_gethostbyname(%s) failed, err=%d\n", name, err)); + *h_errnop = HOST_NOT_FOUND; + return -1; + } + + /* copy the hostname into buf */ + MEMCPY(hostname, name, namelen); + hostname[namelen] = 0; + + /* fill hostent */ + h->addr_list[0] = &h->addr; + h->addr_list[1] = NULL; + h->aliases = NULL; + ret->h_name = hostname; + ret->h_aliases = &h->aliases; + ret->h_addrtype = AF_INET; + ret->h_length = sizeof(ip_addr_t); + ret->h_addr_list = (char**)&h->addr_list; + + /* set result != NULL */ + *result = ret; + + /* return success */ + return 0; +} + +/** + * Frees one or more addrinfo structures returned by getaddrinfo(), along with + * any additional storage associated with those structures. If the ai_next field + * of the structure is not null, the entire list of structures is freed. + * + * @param ai struct addrinfo to free + */ +void +lwip_freeaddrinfo(struct addrinfo *ai) +{ + struct addrinfo *next; + + while (ai != NULL) { + next = ai->ai_next; + memp_free(MEMP_NETDB, ai); + ai = next; + } +} + +/** + * Translates the name of a service location (for example, a host name) and/or + * a service name and returns a set of socket addresses and associated + * information to be used in creating a socket with which to address the + * specified service. + * Memory for the result is allocated internally and must be freed by calling + * lwip_freeaddrinfo()! + * + * Due to a limitation in dns_gethostbyname, only the first address of a + * host is returned. + * Also, service names are not supported (only port numbers)! + * + * @param nodename descriptive name or address string of the host + * (may be NULL -> local address) + * @param servname port number as string of NULL + * @param hints structure containing input values that set socktype and protocol + * @param res pointer to a pointer where to store the result (set to NULL on failure) + * @return 0 on success, non-zero on failure + * + * @todo: implement AI_V4MAPPED, AI_ADDRCONFIG + */ +int +lwip_getaddrinfo(const char *nodename, const char *servname, + const struct addrinfo *hints, struct addrinfo **res) +{ + err_t err; + ip_addr_t addr; + struct addrinfo *ai; + struct sockaddr_storage *sa = NULL; + int port_nr = 0; + size_t total_size; + size_t namelen = 0; + int ai_family; + + if (res == NULL) { + return EAI_FAIL; + } + *res = NULL; + if ((nodename == NULL) && (servname == NULL)) { + return EAI_NONAME; + } + + if (hints != NULL) { + ai_family = hints->ai_family; + if ((ai_family != AF_UNSPEC) +#if LWIP_IPV4 + && (ai_family != AF_INET) +#endif /* LWIP_IPV4 */ +#if LWIP_IPV6 + && (ai_family != AF_INET6) +#endif /* LWIP_IPV6 */ + ) { + return EAI_FAMILY; + } + } else { + ai_family = AF_UNSPEC; + } + + if (servname != NULL) { + /* service name specified: convert to port number + * @todo?: currently, only ASCII integers (port numbers) are supported (AI_NUMERICSERV)! */ + port_nr = atoi(servname); + if ((port_nr <= 0) || (port_nr > 0xffff)) { + return EAI_SERVICE; + } + } + + if (nodename != NULL) { + /* service location specified, try to resolve */ + if ((hints != NULL) && (hints->ai_flags & AI_NUMERICHOST)) { + /* no DNS lookup, just parse for an address string */ + if (!ipaddr_aton(nodename, &addr)) { + return EAI_NONAME; + } +#if LWIP_IPV4 && LWIP_IPV6 + if ((IP_IS_V6_VAL(addr) && ai_family == AF_INET) || + (!IP_IS_V6_VAL(addr) && ai_family == AF_INET6)) { + return EAI_NONAME; + } +#endif /* LWIP_IPV4 && LWIP_IPV6 */ + } else { +#if LWIP_IPV4 && LWIP_IPV6 + /* AF_UNSPEC: prefer IPv4 */ + u8_t type = NETCONN_DNS_IPV4_IPV6; + if (ai_family == AF_INET) { + type = NETCONN_DNS_IPV4; + } else if (ai_family == AF_INET6) { + type = NETCONN_DNS_IPV6; + } +#endif /* LWIP_IPV4 && LWIP_IPV6 */ + err = netconn_gethostbyname_addrtype(nodename, &addr, type); + if (err != ERR_OK) { + return EAI_FAIL; + } + } + } else { + /* service location specified, use loopback address */ + if ((hints != NULL) && (hints->ai_flags & AI_PASSIVE)) { + ip_addr_set_any(ai_family == AF_INET6, &addr); + } else { + ip_addr_set_loopback(ai_family == AF_INET6, &addr); + } + } + + total_size = sizeof(struct addrinfo) + sizeof(struct sockaddr_storage); + if (nodename != NULL) { + namelen = strlen(nodename); + if (namelen > DNS_MAX_NAME_LENGTH) { + /* invalid name length */ + return EAI_FAIL; + } + LWIP_ASSERT("namelen is too long", total_size + namelen + 1 > total_size); + total_size += namelen + 1; + } + /* If this fails, please report to lwip-devel! :-) */ + LWIP_ASSERT("total_size <= NETDB_ELEM_SIZE: please report this!", + total_size <= NETDB_ELEM_SIZE); + ai = (struct addrinfo *)memp_malloc(MEMP_NETDB); + if (ai == NULL) { + return EAI_MEMORY; + } + memset(ai, 0, total_size); + sa = (struct sockaddr_storage *)(void*)((u8_t*)ai + sizeof(struct addrinfo)); + if (IP_IS_V6_VAL(addr)) { +#if LWIP_IPV6 + struct sockaddr_in6 *sa6 = (struct sockaddr_in6*)sa; + /* set up sockaddr */ + inet6_addr_from_ip6addr(&sa6->sin6_addr, ip_2_ip6(&addr)); + sa6->sin6_family = AF_INET6; + sa6->sin6_len = sizeof(struct sockaddr_in6); + sa6->sin6_port = htons((u16_t)port_nr); + ai->ai_family = AF_INET6; +#endif /* LWIP_IPV6 */ + } else { +#if LWIP_IPV4 + struct sockaddr_in *sa4 = (struct sockaddr_in*)sa; + /* set up sockaddr */ + inet_addr_from_ipaddr(&sa4->sin_addr, ip_2_ip4(&addr)); + sa4->sin_family = AF_INET; + sa4->sin_len = sizeof(struct sockaddr_in); + sa4->sin_port = htons((u16_t)port_nr); + ai->ai_family = AF_INET; +#endif /* LWIP_IPV4 */ + } + + /* set up addrinfo */ + if (hints != NULL) { + /* copy socktype & protocol from hints if specified */ + ai->ai_socktype = hints->ai_socktype; + ai->ai_protocol = hints->ai_protocol; + } + if (nodename != NULL) { + /* copy nodename to canonname if specified */ + ai->ai_canonname = ((char*)ai + sizeof(struct addrinfo) + sizeof(struct sockaddr_storage)); + MEMCPY(ai->ai_canonname, nodename, namelen); + ai->ai_canonname[namelen] = 0; + } + ai->ai_addrlen = sizeof(struct sockaddr_storage); + ai->ai_addr = (struct sockaddr*)sa; + + *res = ai; + + return 0; +} + +#endif /* LWIP_DNS && LWIP_SOCKET */ diff --git a/components/lwip/api/netifapi.c b/components/lwip/api/netifapi.c new file mode 100755 index 0000000000..3ddb9f546b --- /dev/null +++ b/components/lwip/api/netifapi.c @@ -0,0 +1,206 @@ +/** + * @file + * Network Interface Sequential API module + * + */ + +/* + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + */ + +#include "lwip/opt.h" + +#if LWIP_NETIF_API /* don't build if not configured for use in lwipopts.h */ + +#include "lwip/netifapi.h" +#include "lwip/memp.h" +#include "lwip/priv/tcpip_priv.h" + +#define NETIFAPI_VAR_REF(name) API_VAR_REF(name) +#define NETIFAPI_VAR_DECLARE(name) API_VAR_DECLARE(struct netifapi_msg, name) +#define NETIFAPI_VAR_ALLOC(name) API_VAR_ALLOC(struct netifapi_msg, MEMP_NETIFAPI_MSG, name) +#define NETIFAPI_VAR_FREE(name) API_VAR_FREE(MEMP_NETIFAPI_MSG, name) + +/** + * Call netif_add() inside the tcpip_thread context. + */ +static err_t +netifapi_do_netif_add(struct tcpip_api_call *m) +{ + struct netifapi_msg *msg = (struct netifapi_msg*)m; + + if (!netif_add( msg->netif, +#if LWIP_IPV4 + API_EXPR_REF(msg->msg.add.ipaddr), + API_EXPR_REF(msg->msg.add.netmask), + API_EXPR_REF(msg->msg.add.gw), +#endif /* LWIP_IPV4 */ + msg->msg.add.state, + msg->msg.add.init, + msg->msg.add.input)) { + return ERR_IF; + } else { + return ERR_OK; + } +} + +#if LWIP_IPV4 +/** + * Call netif_set_addr() inside the tcpip_thread context. + */ +static err_t +netifapi_do_netif_set_addr(struct tcpip_api_call *m) +{ + struct netifapi_msg *msg = (struct netifapi_msg*)m; + + netif_set_addr( msg->netif, + API_EXPR_REF(msg->msg.add.ipaddr), + API_EXPR_REF(msg->msg.add.netmask), + API_EXPR_REF(msg->msg.add.gw)); + return ERR_OK; +} +#endif /* LWIP_IPV4 */ + +/** + * Call the "errtfunc" (or the "voidfunc" if "errtfunc" is NULL) inside the + * tcpip_thread context. + */ +static err_t +netifapi_do_netif_common(struct tcpip_api_call *m) +{ + struct netifapi_msg *msg = (struct netifapi_msg*)m; + + if (msg->msg.common.errtfunc != NULL) { + return msg->msg.common.errtfunc(msg->netif); + } else { + msg->msg.common.voidfunc(msg->netif); + return ERR_OK; + } +} + +/** + * Call netif_add() in a thread-safe way by running that function inside the + * tcpip_thread context. + * + * @note for params @see netif_add() + */ +err_t +netifapi_netif_add(struct netif *netif, +#if LWIP_IPV4 + const ip4_addr_t *ipaddr, const ip4_addr_t *netmask, const ip4_addr_t *gw, +#endif /* LWIP_IPV4 */ + void *state, netif_init_fn init, netif_input_fn input) +{ + err_t err; + NETIFAPI_VAR_DECLARE(msg); + NETIFAPI_VAR_ALLOC(msg); + +#if LWIP_IPV4 + if (ipaddr == NULL) { + ipaddr = IP4_ADDR_ANY; + } + if (netmask == NULL) { + netmask = IP4_ADDR_ANY; + } + if (gw == NULL) { + gw = IP4_ADDR_ANY; + } +#endif /* LWIP_IPV4 */ + + NETIFAPI_VAR_REF(msg).netif = netif; +#if LWIP_IPV4 + NETIFAPI_VAR_REF(msg).msg.add.ipaddr = NETIFAPI_VAR_REF(ipaddr); + NETIFAPI_VAR_REF(msg).msg.add.netmask = NETIFAPI_VAR_REF(netmask); + NETIFAPI_VAR_REF(msg).msg.add.gw = NETIFAPI_VAR_REF(gw); +#endif /* LWIP_IPV4 */ + NETIFAPI_VAR_REF(msg).msg.add.state = state; + NETIFAPI_VAR_REF(msg).msg.add.init = init; + NETIFAPI_VAR_REF(msg).msg.add.input = input; + err = tcpip_api_call(netifapi_do_netif_add, &API_VAR_REF(msg).call); + NETIFAPI_VAR_FREE(msg); + return err; +} + +#if LWIP_IPV4 +/** + * Call netif_set_addr() in a thread-safe way by running that function inside the + * tcpip_thread context. + * + * @note for params @see netif_set_addr() + */ +err_t +netifapi_netif_set_addr(struct netif *netif, + const ip4_addr_t *ipaddr, + const ip4_addr_t *netmask, + const ip4_addr_t *gw) +{ + err_t err; + NETIFAPI_VAR_DECLARE(msg); + NETIFAPI_VAR_ALLOC(msg); + + if (ipaddr == NULL) { + ipaddr = IP4_ADDR_ANY; + } + if (netmask == NULL) { + netmask = IP4_ADDR_ANY; + } + if (gw == NULL) { + gw = IP4_ADDR_ANY; + } + + NETIFAPI_VAR_REF(msg).netif = netif; + NETIFAPI_VAR_REF(msg).msg.add.ipaddr = NETIFAPI_VAR_REF(ipaddr); + NETIFAPI_VAR_REF(msg).msg.add.netmask = NETIFAPI_VAR_REF(netmask); + NETIFAPI_VAR_REF(msg).msg.add.gw = NETIFAPI_VAR_REF(gw); + err = tcpip_api_call(netifapi_do_netif_set_addr, &API_VAR_REF(msg).call); + NETIFAPI_VAR_FREE(msg); + return err; +} +#endif /* LWIP_IPV4 */ + +/** + * call the "errtfunc" (or the "voidfunc" if "errtfunc" is NULL) in a thread-safe + * way by running that function inside the tcpip_thread context. + * + * @note use only for functions where there is only "netif" parameter. + */ +err_t +netifapi_netif_common(struct netif *netif, netifapi_void_fn voidfunc, + netifapi_errt_fn errtfunc) +{ + err_t err; + NETIFAPI_VAR_DECLARE(msg); + NETIFAPI_VAR_ALLOC(msg); + + NETIFAPI_VAR_REF(msg).netif = netif; + NETIFAPI_VAR_REF(msg).msg.common.voidfunc = voidfunc; + NETIFAPI_VAR_REF(msg).msg.common.errtfunc = errtfunc; + err = tcpip_api_call(netifapi_do_netif_common, &API_VAR_REF(msg).call); + NETIFAPI_VAR_FREE(msg); + return err; +} + +#endif /* LWIP_NETIF_API */ diff --git a/components/lwip/api/pppapi.c b/components/lwip/api/pppapi.c new file mode 100755 index 0000000000..b5dcd144b4 --- /dev/null +++ b/components/lwip/api/pppapi.c @@ -0,0 +1,371 @@ +/** + * @file + * Point To Point Protocol Sequential API module + * + */ + +/* + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + */ + +#include "lwip/opt.h" + +#if LWIP_PPP_API /* don't build if not configured for use in lwipopts.h */ + +#include "lwip/pppapi.h" +#include "lwip/priv/tcpip_priv.h" +#include "netif/ppp/pppoe.h" +#include "netif/ppp/pppol2tp.h" +#include "netif/ppp/pppos.h" + + +/** + * Call ppp_set_default() inside the tcpip_thread context. + */ +static err_t +pppapi_do_ppp_set_default(struct tcpip_api_call *m) +{ + struct pppapi_msg_msg *msg = (struct pppapi_msg_msg *)m; + + ppp_set_default(msg->ppp); + return ERR_OK; +} + +/** + * Call ppp_set_default() in a thread-safe way by running that function inside the + * tcpip_thread context. + */ +void +pppapi_set_default(ppp_pcb *pcb) +{ + struct pppapi_msg msg; + msg.msg.ppp = pcb; + tcpip_api_call(pppapi_do_ppp_set_default, &msg.call); +} + + +/** + * Call ppp_set_auth() inside the tcpip_thread context. + */ +static err_t +pppapi_do_ppp_set_auth(struct tcpip_api_call *m) +{ + struct pppapi_msg_msg *msg = (struct pppapi_msg_msg *)m; + + ppp_set_auth(msg->ppp, msg->msg.setauth.authtype, + msg->msg.setauth.user, msg->msg.setauth.passwd); + return ERR_OK; +} + +/** + * Call ppp_set_auth() in a thread-safe way by running that function inside the + * tcpip_thread context. + */ +void +pppapi_set_auth(ppp_pcb *pcb, u8_t authtype, const char *user, const char *passwd) +{ + struct pppapi_msg msg; + msg.msg.ppp = pcb; + msg.msg.msg.setauth.authtype = authtype; + msg.msg.msg.setauth.user = user; + msg.msg.msg.setauth.passwd = passwd; + tcpip_api_call(pppapi_do_ppp_set_auth, &msg.call); +} + + +#if PPP_NOTIFY_PHASE +/** + * Call ppp_set_notify_phase_callback() inside the tcpip_thread context. + */ +static err_t +pppapi_do_ppp_set_notify_phase_callback(struct tcpip_api_call *m) +{ + struct pppapi_msg_msg *msg = (struct pppapi_msg_msg *)m; + ppp_set_notify_phase_callback(msg->ppp, msg->msg.setnotifyphasecb.notify_phase_cb); + return ERR_OK; +} + +/** + * Call ppp_set_notify_phase_callback() in a thread-safe way by running that function inside the + * tcpip_thread context. + */ +void +pppapi_set_notify_phase_callback(ppp_pcb *pcb, ppp_notify_phase_cb_fn notify_phase_cb) +{ + struct pppapi_msg msg; + msg.function = pppapi_do_ppp_set_notify_phase_callback; + msg.msg.ppp = pcb; + msg.msg.msg.setnotifyphasecb.notify_phase_cb = notify_phase_cb; + tcpip_api_call(pppapi_do_ppp_set_notify_phase_callback, &msg.call); +} +#endif /* PPP_NOTIFY_PHASE */ + + +#if PPPOS_SUPPORT +/** + * Call pppos_create() inside the tcpip_thread context. + */ +static err_t +pppapi_do_pppos_create(struct tcpip_api_call *m) +{ + struct pppapi_msg_msg *msg = (struct pppapi_msg_msg *)m; + + msg->ppp = pppos_create(msg->msg.serialcreate.pppif, msg->msg.serialcreate.output_cb, + msg->msg.serialcreate.link_status_cb, msg->msg.serialcreate.ctx_cb); + return ERR_OK; +} + +/** + * Call pppos_create() in a thread-safe way by running that function inside the + * tcpip_thread context. + */ +ppp_pcb* +pppapi_pppos_create(struct netif *pppif, pppos_output_cb_fn output_cb, + ppp_link_status_cb_fn link_status_cb, void *ctx_cb) +{ + struct pppapi_msg msg; + msg.msg.msg.serialcreate.pppif = pppif; + msg.msg.msg.serialcreate.output_cb = output_cb; + msg.msg.msg.serialcreate.link_status_cb = link_status_cb; + msg.msg.msg.serialcreate.ctx_cb = ctx_cb; + tcpip_api_call(pppapi_do_pppos_create, &msg.call); + return msg.msg.ppp; +} +#endif /* PPPOS_SUPPORT */ + + +#if PPPOE_SUPPORT +/** + * Call pppoe_create() inside the tcpip_thread context. + */ +static err_t +pppapi_do_pppoe_create(struct tcpip_api_call *m) +{ + struct pppapi_msg_msg *msg = (struct pppapi_msg_msg *)m; + + msg->ppp = pppoe_create(msg->msg.ethernetcreate.pppif, msg->msg.ethernetcreate.ethif, + msg->msg.ethernetcreate.service_name, msg->msg.ethernetcreate.concentrator_name, + msg->msg.ethernetcreate.link_status_cb, msg->msg.ethernetcreate.ctx_cb); + return ERR_OK; +} + +/** + * Call pppoe_create() in a thread-safe way by running that function inside the + * tcpip_thread context. + */ +ppp_pcb* +pppapi_pppoe_create(struct netif *pppif, struct netif *ethif, const char *service_name, + const char *concentrator_name, ppp_link_status_cb_fn link_status_cb, + void *ctx_cb) +{ + struct pppapi_msg msg; + msg.msg.msg.ethernetcreate.pppif = pppif; + msg.msg.msg.ethernetcreate.ethif = ethif; + msg.msg.msg.ethernetcreate.service_name = service_name; + msg.msg.msg.ethernetcreate.concentrator_name = concentrator_name; + msg.msg.msg.ethernetcreate.link_status_cb = link_status_cb; + msg.msg.msg.ethernetcreate.ctx_cb = ctx_cb; + tcpip_api_call(pppapi_do_pppoe_create, &msg.call); + return msg.msg.ppp; +} +#endif /* PPPOE_SUPPORT */ + + +#if PPPOL2TP_SUPPORT +/** + * Call pppol2tp_create() inside the tcpip_thread context. + */ +static err_t +pppapi_do_pppol2tp_create(struct tcpip_api_call *m) +{ + struct pppapi_msg_msg *msg = (struct pppapi_msg_msg *)m; + + msg->ppp = pppol2tp_create(msg->msg.l2tpcreate.pppif, + msg->msg.l2tpcreate.netif, msg->msg.l2tpcreate.ipaddr, msg->msg.l2tpcreate.port, +#if PPPOL2TP_AUTH_SUPPORT + msg->msg.l2tpcreate.secret, + msg->msg.l2tpcreate.secret_len, +#else /* PPPOL2TP_AUTH_SUPPORT */ + NULL, +#endif /* PPPOL2TP_AUTH_SUPPORT */ + msg->msg.l2tpcreate.link_status_cb, msg->msg.l2tpcreate.ctx_cb); + return ERR_OK; +} + +/** + * Call pppol2tp_create() in a thread-safe way by running that function inside the + * tcpip_thread context. + */ +ppp_pcb* +pppapi_pppol2tp_create(struct netif *pppif, struct netif *netif, ip_addr_t *ipaddr, u16_t port, + const u8_t *secret, u8_t secret_len, + ppp_link_status_cb_fn link_status_cb, void *ctx_cb) +{ + struct pppapi_msg msg; + msg.msg.msg.l2tpcreate.pppif = pppif; + msg.msg.msg.l2tpcreate.netif = netif; + msg.msg.msg.l2tpcreate.ipaddr = ipaddr; + msg.msg.msg.l2tpcreate.port = port; +#if PPPOL2TP_AUTH_SUPPORT + msg.msg.msg.l2tpcreate.secret = secret; + msg.msg.msg.l2tpcreate.secret_len = secret_len; +#endif /* PPPOL2TP_AUTH_SUPPORT */ + msg.msg.msg.l2tpcreate.link_status_cb = link_status_cb; + msg.msg.msg.l2tpcreate.ctx_cb = ctx_cb; + tcpip_api_call(pppapi_do_pppol2tp_create, &msg.call); + return msg.msg.ppp; +} +#endif /* PPPOL2TP_SUPPORT */ + + +/** + * Call ppp_connect() inside the tcpip_thread context. + */ +static err_t +pppapi_do_ppp_connect(struct tcpip_api_call *m) +{ + struct pppapi_msg_msg *msg = (struct pppapi_msg_msg *)m; + + return ppp_connect(msg->ppp, msg->msg.connect.holdoff); +} + +/** + * Call ppp_connect() in a thread-safe way by running that function inside the + * tcpip_thread context. + */ +err_t +pppapi_connect(ppp_pcb *pcb, u16_t holdoff) +{ + struct pppapi_msg msg; + msg.msg.ppp = pcb; + msg.msg.msg.connect.holdoff = holdoff; + return tcpip_api_call(pppapi_do_ppp_connect, &msg.call); +} + + +#if PPP_SERVER +/** + * Call ppp_listen() inside the tcpip_thread context. + */ +static void +pppapi_do_ppp_listen(struct pppapi_msg_msg *msg) +{ + msg->err = ppp_listen(msg->ppp, msg->msg.listen.addrs); + TCPIP_PPPAPI_ACK(msg); +} + +/** + * Call ppp_listen() in a thread-safe way by running that function inside the + * tcpip_thread context. + */ +err_t +pppapi_listen(ppp_pcb *pcb, struct ppp_addrs *addrs) +{ + struct pppapi_msg msg; + msg.function = pppapi_do_ppp_listen; + msg.msg.ppp = pcb; + msg.msg.msg.listen.addrs = addrs; + TCPIP_PPPAPI(&msg); + return msg.msg.err; +} +#endif /* PPP_SERVER */ + + +/** + * Call ppp_close() inside the tcpip_thread context. + */ +static err_t +pppapi_do_ppp_close(struct tcpip_api_call *m) +{ + struct pppapi_msg_msg *msg = (struct pppapi_msg_msg *)m; + + return ppp_close(msg->ppp, msg->msg.close.nocarrier); +} + +/** + * Call ppp_close() in a thread-safe way by running that function inside the + * tcpip_thread context. + */ +err_t +pppapi_close(ppp_pcb *pcb, u8_t nocarrier) +{ + struct pppapi_msg msg; + msg.msg.ppp = pcb; + msg.msg.msg.close.nocarrier = nocarrier; + return tcpip_api_call(pppapi_do_ppp_close, &msg.call); +} + + +/** + * Call ppp_free() inside the tcpip_thread context. + */ +static err_t +pppapi_do_ppp_free(struct tcpip_api_call *m) +{ + struct pppapi_msg_msg *msg = (struct pppapi_msg_msg *)m; + + return ppp_free(msg->ppp); +} + +/** + * Call ppp_free() in a thread-safe way by running that function inside the + * tcpip_thread context. + */ +err_t +pppapi_free(ppp_pcb *pcb) +{ + struct pppapi_msg msg; + msg.msg.ppp = pcb; + return tcpip_api_call(pppapi_do_ppp_free, &msg.call); +} + + +/** + * Call ppp_ioctl() inside the tcpip_thread context. + */ +static err_t +pppapi_do_ppp_ioctl(struct tcpip_api_call *m) +{ + struct pppapi_msg_msg *msg = (struct pppapi_msg_msg *)m; + + return ppp_ioctl(msg->ppp, msg->msg.ioctl.cmd, msg->msg.ioctl.arg); +} + +/** + * Call ppp_ioctl() in a thread-safe way by running that function inside the + * tcpip_thread context. + */ +err_t +pppapi_ioctl(ppp_pcb *pcb, u8_t cmd, void *arg) +{ + struct pppapi_msg msg; + msg.msg.ppp = pcb; + msg.msg.msg.ioctl.cmd = cmd; + msg.msg.msg.ioctl.arg = arg; + return tcpip_api_call(pppapi_do_ppp_ioctl, &msg.call); +} + +#endif /* LWIP_PPP_API */ diff --git a/components/lwip/api/sockets.c b/components/lwip/api/sockets.c new file mode 100755 index 0000000000..ee1c9216b3 --- /dev/null +++ b/components/lwip/api/sockets.c @@ -0,0 +1,3263 @@ +/** + * @file + * Sockets BSD-Like API module + * + */ + +/* + * Copyright (c) 2001-2004 Swedish Institute of Computer Science. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + * + * Improved by Marc Boucher and David Haas + * + */ + +#include "lwip/opt.h" + +#if LWIP_SOCKET /* don't build if not configured for use in lwipopts.h */ + +#include "lwip/sockets.h" +#include "lwip/api.h" +#include "lwip/sys.h" +#include "lwip/igmp.h" +#include "lwip/inet.h" +#include "lwip/tcp.h" +#include "lwip/raw.h" +#include "lwip/udp.h" +#include "lwip/memp.h" +#include "lwip/pbuf.h" +#include "lwip/priv/tcpip_priv.h" +#include "lwip/priv/api_msg.h" +//#include "esp_common.h" +#if LWIP_CHECKSUM_ON_COPY +#include "lwip/inet_chksum.h" +#endif + +#include + +#ifdef MEMLEAK_DEBUG +static const char mem_debug_file[] ICACHE_RODATA_ATTR STORE_ATTR = __FILE__; +#endif + + +/* If the netconn API is not required publicly, then we include the necessary + files here to get the implementation */ +#if !LWIP_NETCONN +#undef LWIP_NETCONN +#define LWIP_NETCONN 1 +#include "api_msg.c" +#include "api_lib.c" +#include "netbuf.c" +#undef LWIP_NETCONN +#define LWIP_NETCONN 0 +#endif + +#if LWIP_IPV4 +#define IP4ADDR_PORT_TO_SOCKADDR(sin, ipaddr, port) do { \ + (sin)->sin_len = sizeof(struct sockaddr_in); \ + (sin)->sin_family = AF_INET; \ + (sin)->sin_port = htons((port)); \ + inet_addr_from_ipaddr(&(sin)->sin_addr, ipaddr); \ + memset((sin)->sin_zero, 0, SIN_ZERO_LEN); }while(0) +#define SOCKADDR4_TO_IP4ADDR_PORT(sin, ipaddr, port) do { \ + inet_addr_to_ipaddr(ip_2_ip4(ipaddr), &((sin)->sin_addr)); \ + (port) = ntohs((sin)->sin_port); }while(0) +#endif /* LWIP_IPV4 */ + +#if LWIP_IPV6 +#define IP6ADDR_PORT_TO_SOCKADDR(sin6, ipaddr, port) do { \ + (sin6)->sin6_len = sizeof(struct sockaddr_in6); \ + (sin6)->sin6_family = AF_INET6; \ + (sin6)->sin6_port = htons((port)); \ + (sin6)->sin6_flowinfo = 0; \ + inet6_addr_from_ip6addr(&(sin6)->sin6_addr, ipaddr); \ + (sin6)->sin6_scope_id = 0; }while(0) +#define SOCKADDR6_TO_IP6ADDR_PORT(sin6, ipaddr, port) do { \ + inet6_addr_to_ip6addr(ip_2_ip6(ipaddr), &((sin6)->sin6_addr)); \ + (port) = ntohs((sin6)->sin6_port); }while(0) +#endif /* LWIP_IPV6 */ + +#if LWIP_IPV4 && LWIP_IPV6 +static void sockaddr_to_ipaddr_port(const struct sockaddr* sockaddr, ip_addr_t* ipaddr, u16_t* port); + +#define IS_SOCK_ADDR_LEN_VALID(namelen) (((namelen) == sizeof(struct sockaddr_in)) || \ + ((namelen) == sizeof(struct sockaddr_in6))) +#define IS_SOCK_ADDR_TYPE_VALID(name) (((name)->sa_family == AF_INET) || \ + ((name)->sa_family == AF_INET6)) +#define SOCK_ADDR_TYPE_MATCH(name, sock) \ + ((((name)->sa_family == AF_INET) && !(NETCONNTYPE_ISIPV6((sock)->conn->type))) || \ + (((name)->sa_family == AF_INET6) && (NETCONNTYPE_ISIPV6((sock)->conn->type)))) +#define IPADDR_PORT_TO_SOCKADDR(sockaddr, ipaddr, port) do { \ + if (IP_IS_V6(ipaddr)) { \ + IP6ADDR_PORT_TO_SOCKADDR((struct sockaddr_in6*)(void*)(sockaddr), ip_2_ip6(ipaddr), port); \ + } else { \ + IP4ADDR_PORT_TO_SOCKADDR((struct sockaddr_in*)(void*)(sockaddr), ip_2_ip4(ipaddr), port); \ + } } while(0) +#define SOCKADDR_TO_IPADDR_PORT(sockaddr, ipaddr, port) sockaddr_to_ipaddr_port(sockaddr, ipaddr, &(port)) +#define DOMAIN_TO_NETCONN_TYPE(domain, type) (((domain) == AF_INET) ? \ + (type) : (enum netconn_type)((type) | NETCONN_TYPE_IPV6)) +#elif LWIP_IPV6 /* LWIP_IPV4 && LWIP_IPV6 */ +#define IS_SOCK_ADDR_LEN_VALID(namelen) ((namelen) == sizeof(struct sockaddr_in6)) +#define IS_SOCK_ADDR_TYPE_VALID(name) ((name)->sa_family == AF_INET6) +#define SOCK_ADDR_TYPE_MATCH(name, sock) 1 +#define IPADDR_PORT_TO_SOCKADDR(sockaddr, ipaddr, port) \ + IP6ADDR_PORT_TO_SOCKADDR((struct sockaddr_in6*)(void*)(sockaddr), ip_2_ip6(ipaddr), port) +#define SOCKADDR_TO_IPADDR_PORT(sockaddr, ipaddr, port) \ + SOCKADDR6_TO_IP6ADDR_PORT((const struct sockaddr_in6*)(const void*)(sockaddr), ipaddr, port) +#define DOMAIN_TO_NETCONN_TYPE(domain, netconn_type) (netconn_type) +#else /*-> LWIP_IPV4: LWIP_IPV4 && LWIP_IPV6 */ +#define IS_SOCK_ADDR_LEN_VALID(namelen) ((namelen) == sizeof(struct sockaddr_in)) +#define IS_SOCK_ADDR_TYPE_VALID(name) ((name)->sa_family == AF_INET) +#define SOCK_ADDR_TYPE_MATCH(name, sock) 1 +#define IPADDR_PORT_TO_SOCKADDR(sockaddr, ipaddr, port) \ + IP4ADDR_PORT_TO_SOCKADDR((struct sockaddr_in*)(void*)(sockaddr), ip_2_ip4(ipaddr), port) +#define SOCKADDR_TO_IPADDR_PORT(sockaddr, ipaddr, port) \ + SOCKADDR4_TO_IP4ADDR_PORT((const struct sockaddr_in*)(const void*)(sockaddr), ipaddr, port) +#define DOMAIN_TO_NETCONN_TYPE(domain, netconn_type) (netconn_type) +#endif /* LWIP_IPV6 */ + +#define IS_SOCK_ADDR_TYPE_VALID_OR_UNSPEC(name) (((name)->sa_family == AF_UNSPEC) || \ + IS_SOCK_ADDR_TYPE_VALID(name)) +#define SOCK_ADDR_TYPE_MATCH_OR_UNSPEC(name, sock) (((name)->sa_family == AF_UNSPEC) || \ + SOCK_ADDR_TYPE_MATCH(name, sock)) +#define IS_SOCK_ADDR_ALIGNED(name) ((((mem_ptr_t)(name)) % 4) == 0) + + +#define LWIP_SOCKOPT_CHECK_OPTLEN(optlen, opttype) do { if ((optlen) < sizeof(opttype)) { return EINVAL; }}while(0) +#define LWIP_SOCKOPT_CHECK_OPTLEN_CONN(sock, optlen, opttype) do { \ + LWIP_SOCKOPT_CHECK_OPTLEN(optlen, opttype); \ + if ((sock)->conn == NULL) { return EINVAL; } }while(0) +#define LWIP_SOCKOPT_CHECK_OPTLEN_CONN_PCB(sock, optlen, opttype) do { \ + LWIP_SOCKOPT_CHECK_OPTLEN(optlen, opttype); \ + if (((sock)->conn == NULL) || ((sock)->conn->pcb.tcp == NULL)) { return EINVAL; } }while(0) +#define LWIP_SOCKOPT_CHECK_OPTLEN_CONN_PCB_TYPE(sock, optlen, opttype, netconntype) do { \ + LWIP_SOCKOPT_CHECK_OPTLEN_CONN_PCB(sock, optlen, opttype); \ + if (NETCONNTYPE_GROUP(netconn_type((sock)->conn)) != netconntype) { return ENOPROTOOPT; } }while(0) + + +#define LWIP_SETGETSOCKOPT_DATA_VAR_REF(name) API_VAR_REF(name) +#define LWIP_SETGETSOCKOPT_DATA_VAR_DECLARE(name) API_VAR_DECLARE(struct lwip_setgetsockopt_data, name) +#define LWIP_SETGETSOCKOPT_DATA_VAR_FREE(name) API_VAR_FREE(MEMP_SOCKET_SETGETSOCKOPT_DATA, name) +#if LWIP_MPU_COMPATIBLE +#define LWIP_SETGETSOCKOPT_DATA_VAR_ALLOC(name, sock) do { \ + name = (struct lwip_setgetsockopt_data *)memp_malloc(MEMP_SOCKET_SETGETSOCKOPT_DATA); \ + if (name == NULL) { \ + sock_set_errno(sock, ENOMEM); \ + return -1; \ + } }while(0) +#else /* LWIP_MPU_COMPATIBLE */ +#define LWIP_SETGETSOCKOPT_DATA_VAR_ALLOC(name, sock) +#endif /* LWIP_MPU_COMPATIBLE */ + +#if LWIP_SO_SNDRCVTIMEO_NONSTANDARD +#define LWIP_SO_SNDRCVTIMEO_OPTTYPE int +#define LWIP_SO_SNDRCVTIMEO_SET(optval, val) (*(int *)(optval) = (val)) +#define LWIP_SO_SNDRCVTIMEO_GET_MS(optval) ((s32_t)*(const int*)(optval)) +#else +#define LWIP_SO_SNDRCVTIMEO_OPTTYPE struct timeval +#define LWIP_SO_SNDRCVTIMEO_SET(optval, val) do { \ + s32_t loc = (val); \ + ((struct timeval *)(optval))->tv_sec = (loc) / 1000U; \ + ((struct timeval *)(optval))->tv_usec = ((loc) % 1000U) * 1000U; }while(0) +#define LWIP_SO_SNDRCVTIMEO_GET_MS(optval) ((((const struct timeval *)(optval))->tv_sec * 1000U) + (((const struct timeval *)(optval))->tv_usec / 1000U)) +#endif + +#define NUM_SOCKETS MEMP_NUM_NETCONN + +/** This is overridable for the rare case where more than 255 threads + * select on the same socket... + */ +#ifndef SELWAIT_T +#define SELWAIT_T u8_t +#endif + +/** Contains all internal pointers and states used for a socket */ +struct lwip_sock { + /** sockets currently are built on netconns, each socket has one netconn */ + struct netconn *conn; + /** data that was left from the previous read */ + void *lastdata; + /** offset in the data that was left from the previous read */ + u16_t lastoffset; + /** number of times data was received, set by event_callback(), + tested by the receive and select functions */ + s16_t rcvevent; + /** number of times data was ACKed (free send buffer), set by event_callback(), + tested by select */ + u16_t sendevent; + /** error happened for this socket, set by event_callback(), tested by select */ + u16_t errevent; + /** last error that occurred on this socket (in fact, all our errnos fit into an u8_t) */ + u8_t err; + +#if LWIP_THREAD_SAFE + /* lock is used to protect state/ref field, however this lock is not a perfect lock, e.g + * taskA and taskB can access sock X, then taskA freed sock X, before taskB detect + * this, taskC reuse sock X, then when taskB try to access sock X, problem may happen. + * A mitigation solution may be, when allocate a socket, alloc the least frequently used + * socket. + */ + sys_mutex_t lock; + + /* can be LWIP_SOCK_OPEN/LWIP_SOCK_CLOSING/LWIP_SOCK_CLOSED */ + u8_t state; + + /* if ref is 0, the sock need/can to be freed */ + s8_t ref; + + /* indicate how long the sock is in LWIP_SOCK_CLOSED status */ + u8_t age; +#endif + + /** counter of how many threads are waiting for this socket using select */ + SELWAIT_T select_waiting; +}; + +#if LWIP_THREAD_SAFE + +#define LWIP_SOCK_OPEN 0 +#define LWIP_SOCK_CLOSING 1 +#define LWIP_SOCK_CLOSED 2 + +#define LWIP_SOCK_LOCK(sock) \ +do{\ + /*LWIP_DEBUGF(THREAD_SAFE_DEBUG, ("l\n"));*/\ + sys_mutex_lock(&sock->lock);\ + /*LWIP_DEBUGF(THREAD_SAFE_DEBUG, ("l ok\n"));*/\ +}while(0) + + +#define LWIP_SOCK_UNLOCK(sock) \ +do{\ + sys_mutex_unlock(&sock->lock);\ + /*LWIP_DEBUGF(THREAD_SAFE_DEBUG1, ("unl\n"));*/\ +}while(0) + +#define LWIP_FREE_SOCK(sock) \ +do{\ + if(sock->conn && NETCONNTYPE_GROUP(netconn_type(sock->conn)) == NETCONN_TCP){\ + LWIP_DEBUGF(THREAD_SAFE_DEBUG, ("LWIP_FREE_SOCK:free tcp sock\n"));\ + free_socket(sock, 1);\ + } else {\ + LWIP_DEBUGF(THREAD_SAFE_DEBUG, ("LWIP_FREE_SOCK:free non-tcp sock\n"));\ + free_socket(sock, 0);\ + }\ +}while(0) + +#define LWIP_SET_CLOSE_FLAG() \ +do{\ + LWIP_SOCK_LOCK(__sock);\ + LWIP_DEBUGF(THREAD_SAFE_DEBUG, ("mark sock closing\n"));\ + __sock->state = LWIP_SOCK_CLOSING;\ + LWIP_SOCK_UNLOCK(__sock);\ +}while(0) + +#define LWIP_API_LOCK() \ + struct lwip_sock *__sock;\ + int __ret;\ +\ + __sock = get_socket(s);\ + if (!__sock) {\ + return -1;\ + }\ +\ +do{\ + LWIP_SOCK_LOCK(__sock);\ + __sock->ref ++;\ + if (__sock->state != LWIP_SOCK_OPEN) {\ + LWIP_DEBUGF(THREAD_SAFE_DEBUG, ("LWIP_API_LOCK:soc is %d, return\n", __sock->state));\ + __sock->ref --;\ + LWIP_SOCK_UNLOCK(__sock);\ + return -1;\ + }\ +\ + LWIP_SOCK_UNLOCK(__sock);\ +}while(0) + +#define LWIP_API_UNLOCK() \ +do{\ + LWIP_SOCK_LOCK(__sock);\ + __sock->ref --;\ + if (__sock->state == LWIP_SOCK_CLOSING) {\ + if (__sock->ref == 0){\ + LWIP_DEBUGF(THREAD_SAFE_DEBUG, ("LWIP_API_UNLOCK:ref 0, free __sock\n"));\ + LWIP_FREE_SOCK(__sock);\ + LWIP_SOCK_UNLOCK(__sock);\ + return __ret;\ + }\ + LWIP_DEBUGF(THREAD_SAFE_DEBUG, ("LWIP_API_UNLOCK: soc state is closing, return\n"));\ + LWIP_SOCK_UNLOCK(__sock);\ + return __ret;\ + }\ +\ + LWIP_SOCK_UNLOCK(__sock);\ + return __ret;\ +}while(0) + +#endif + + + +#if LWIP_NETCONN_SEM_PER_THREAD +#define SELECT_SEM_T sys_sem_t* +#define SELECT_SEM_PTR(sem) (sem) +#else /* LWIP_NETCONN_SEM_PER_THREAD */ +#define SELECT_SEM_T sys_sem_t +#define SELECT_SEM_PTR(sem) (&(sem)) +#endif /* LWIP_NETCONN_SEM_PER_THREAD */ + +/** Description for a task waiting in select */ +struct lwip_select_cb { + /** Pointer to the next waiting task */ + struct lwip_select_cb *next; + /** Pointer to the previous waiting task */ + struct lwip_select_cb *prev; + /** readset passed to select */ + fd_set *readset; + /** writeset passed to select */ + fd_set *writeset; + /** unimplemented: exceptset passed to select */ + fd_set *exceptset; + /** don't signal the same semaphore twice: set to 1 when signalled */ + int sem_signalled; + /** semaphore to wake up a task waiting for select */ + SELECT_SEM_T sem; +}; + +/** A struct sockaddr replacement that has the same alignment as sockaddr_in/ + * sockaddr_in6 if instantiated. + */ +union sockaddr_aligned { + struct sockaddr sa; +#if LWIP_IPV6 + struct sockaddr_in6 sin6; +#endif /* LWIP_IPV6 */ +#if LWIP_IPV4 + struct sockaddr_in sin; +#endif /* LWIP_IPV4 */ +}; + +#if LWIP_IGMP +/* Define the number of IPv4 multicast memberships, default is one per socket */ +#ifndef LWIP_SOCKET_MAX_MEMBERSHIPS +#define LWIP_SOCKET_MAX_MEMBERSHIPS NUM_SOCKETS +#endif + +/* This is to keep track of IP_ADD_MEMBERSHIP calls to drop the membership when + a socket is closed */ +struct lwip_socket_multicast_pair { + /** the socket (+1 to not require initialization) */ + int sa; + /** the interface address */ + ip4_addr_t if_addr; + /** the group address */ + ip4_addr_t multi_addr; +}; + +struct lwip_socket_multicast_pair socket_ipv4_multicast_memberships[LWIP_SOCKET_MAX_MEMBERSHIPS]; + +static int lwip_socket_register_membership(int s, const ip4_addr_t *if_addr, const ip4_addr_t *multi_addr); +static void lwip_socket_unregister_membership(int s, const ip4_addr_t *if_addr, const ip4_addr_t *multi_addr); +static void lwip_socket_drop_registered_memberships(int s); +#endif /* LWIP_IGMP */ + +#ifdef LWIP_ESP8266 +extern size_t system_get_free_heap_size(void); + +#define DELAY_WHEN_MEMORY_NOT_ENOUGH() \ +do{\ + uint8_t _wait_delay = 0;\ + while (system_get_free_heap_size() < HEAP_HIGHWAT){\ + vTaskDelay(_wait_delay/portTICK_RATE_MS);\ + if (_wait_delay < 64) _wait_delay *= 2;\ + }\ +}while(0) + +#else +#define DELAY_WHEN_MEMORY_NOT_ENOUGH() +#endif + +/** The global array of available sockets */ +static struct lwip_sock sockets[NUM_SOCKETS]; +#ifdef LWIP_THREAD_SAFE +static bool sockets_init_flag = false; +#endif +/** The global list of tasks waiting for select */ +static struct lwip_select_cb *select_cb_list; +/** This counter is increased from lwip_select when the list is changed + and checked in event_callback to see if it has changed. */ +static volatile int select_cb_ctr; + +/** Table to quickly map an lwIP error (err_t) to a socket error + * by using -err as an index */ +#ifdef LWIP_ESP8266 +//TO_DO +//static const int err_to_errno_table[] ICACHE_RODATA_ATTR STORE_ATTR = { +static const int err_to_errno_table[] = { +#else +static const int err_to_errno_table[] = { +#endif + 0, /* ERR_OK 0 No error, everything OK. */ + ENOMEM, /* ERR_MEM -1 Out of memory error. */ + ENOBUFS, /* ERR_BUF -2 Buffer error. */ + EWOULDBLOCK, /* ERR_TIMEOUT -3 Timeout */ + EHOSTUNREACH, /* ERR_RTE -4 Routing problem. */ + EINPROGRESS, /* ERR_INPROGRESS -5 Operation in progress */ + EINVAL, /* ERR_VAL -6 Illegal value. */ + EWOULDBLOCK, /* ERR_WOULDBLOCK -7 Operation would block. */ + EADDRINUSE, /* ERR_USE -8 Address in use. */ + +#ifdef LWIP_ESP8266 + EALREADY, /* ERR_ALREADY -9 Already connected. */ + EISCONN, /* ERR_ISCONN -10 Conn already established */ + ECONNABORTED, /* ERR_ABRT -11 Connection aborted. */ + ECONNRESET, /* ERR_RST -12 Connection reset. */ + ENOTCONN, /* ERR_CLSD -13 Connection closed. */ + ENOTCONN, /* ERR_CONN -14 Not connected. */ + EIO, /* ERR_ARG -15 Illegal argument. */ + -1, /* ERR_IF -16 Low-level netif error */ +#else + EALREADY, /* ERR_ALREADY -9 Already connecting. */ + EISCONN, /* ERR_ISCONN -10 Conn already established.*/ + ENOTCONN, /* ERR_CONN -11 Not connected. */ + -1, /* ERR_IF -12 Low-level netif error */ + ECONNABORTED, /* ERR_ABRT -13 Connection aborted. */ + ECONNRESET, /* ERR_RST -14 Connection reset. */ + ENOTCONN, /* ERR_CLSD -15 Connection closed. */ + EIO /* ERR_ARG -16 Illegal argument. */ +#endif +}; + +#define ERR_TO_ERRNO_TABLE_SIZE LWIP_ARRAYSIZE(err_to_errno_table) + +#define err_to_errno(err) \ + ((unsigned)(-(signed)(err)) < ERR_TO_ERRNO_TABLE_SIZE ? \ + err_to_errno_table[-(signed)(err)] : EIO) + +#if LWIP_SOCKET_SET_ERRNO +#ifndef set_errno +#define set_errno(err) do { if (err) { errno = (err); } } while(0) +#endif +#else /* LWIP_SOCKET_SET_ERRNO */ +#define set_errno(err) +#endif /* LWIP_SOCKET_SET_ERRNO */ + +#define sock_set_errno(sk, e) do { \ + const int sockerr = (e); \ + sk->err = (u8_t)sockerr; \ + set_errno(sockerr); \ +} while (0) + +/* Forward declaration of some functions */ +static void event_callback(struct netconn *conn, enum netconn_evt evt, u16_t len); +#if !LWIP_TCPIP_CORE_LOCKING +static void lwip_getsockopt_callback(void *arg); +static void lwip_setsockopt_callback(void *arg); +#endif +static u8_t lwip_getsockopt_impl(int s, int level, int optname, void *optval, socklen_t *optlen); +static u8_t lwip_setsockopt_impl(int s, int level, int optname, const void *optval, socklen_t optlen); + +#if LWIP_IPV4 && LWIP_IPV6 +static void +sockaddr_to_ipaddr_port(const struct sockaddr* sockaddr, ip_addr_t* ipaddr, u16_t* port) +{ + if ((sockaddr->sa_family) == AF_INET6) { + SOCKADDR6_TO_IP6ADDR_PORT((const struct sockaddr_in6*)(const void*)(sockaddr), ipaddr, *port); + ipaddr->type = IPADDR_TYPE_V6; + } else { + SOCKADDR4_TO_IP4ADDR_PORT((const struct sockaddr_in*)(const void*)(sockaddr), ipaddr, *port); + ipaddr->type = IPADDR_TYPE_V4; + } +} +#endif /* LWIP_IPV4 && LWIP_IPV6 */ + +/** LWIP_NETCONN_SEM_PER_THREAD==1: initialize thread-local semaphore */ +void +lwip_socket_thread_init(void) +{ + netconn_thread_init(); +} + +/** LWIP_NETCONN_SEM_PER_THREAD==1: destroy thread-local semaphore */ +void +lwip_socket_thread_cleanup(void) +{ + netconn_thread_cleanup(); +} + +/** + * Map a externally used socket index to the internal socket representation. + * + * @param s externally used socket index + * @return struct lwip_sock for the socket or NULL if not found + */ +static struct lwip_sock * +get_socket(int s) +{ + struct lwip_sock *sock; + + s -= LWIP_SOCKET_OFFSET; + + if ((s < 0) || (s >= NUM_SOCKETS)) { + LWIP_DEBUGF(SOCKETS_DEBUG, ("get_socket(%d): invalid\n", s + LWIP_SOCKET_OFFSET)); + set_errno(EBADF); + return NULL; + } + + sock = &sockets[s]; + + if (!sock->conn) { + LWIP_DEBUGF(SOCKETS_DEBUG, ("get_socket(%d): not active\n", s + LWIP_SOCKET_OFFSET)); + set_errno(EBADF); + return NULL; + } + + return sock; +} + +/** + * Same as get_socket but doesn't set errno + * + * @param s externally used socket index + * @return struct lwip_sock for the socket or NULL if not found + */ +static struct lwip_sock * +tryget_socket(int s) +{ + s -= LWIP_SOCKET_OFFSET; + if ((s < 0) || (s >= NUM_SOCKETS)) { + return NULL; + } + if (!sockets[s].conn) { + return NULL; + } + return &sockets[s]; +} + +/** + * Allocate a new socket for a given netconn. + * + * @param newconn the netconn for which to allocate a socket + * @param accepted 1 if socket has been created by accept(), + * 0 if socket has been created by socket() + * @return the index of the new socket; -1 on error + */ +static int +alloc_socket(struct netconn *newconn, int accepted) +{ + int i; + SYS_ARCH_DECL_PROTECT(lev); + +#if LWIP_THREAD_SAFE + bool found = false; + int oldest = -1; + + SYS_ARCH_PROTECT(lev); + + if (sockets_init_flag == false){ + sockets_init_flag = true; + memset(sockets, 0, sizeof(sockets)); + } + + for (i = 0; i < NUM_SOCKETS; ++i) { + sockets[i].age ++; + + if (found == true){ + continue; + } + + if (!sockets[i].conn && (sockets[i].state == LWIP_SOCK_OPEN)) { + found = true; + oldest = i; + continue; + } + + if (!sockets[i].conn){ + if (oldest == -1 || sockets[i].age > sockets[oldest].age){ + oldest = i; + } + } + } + + if ((oldest != -1) && !sockets[oldest].conn) { + found = true; + sockets[oldest].conn = newconn; + } + + SYS_ARCH_UNPROTECT(lev); + + if (found == true) { + sockets[oldest].lastdata = NULL; + sockets[oldest].lastoffset = 0; + sockets[oldest].rcvevent = 0; + + /* TCP sendbuf is empty, but the socket is not yet writable until connected + * (unless it has been created by accept()). */ + sockets[oldest].sendevent = (NETCONNTYPE_GROUP(newconn->type) == NETCONN_TCP ? (accepted != 0) : 1); + sockets[oldest].errevent = 0; + sockets[oldest].err = 0; + sockets[oldest].select_waiting = 0; + + sockets[oldest].state = LWIP_SOCK_OPEN; + sockets[oldest].age = 0; + sockets[oldest].ref = 0; + if (!sockets[oldest].lock){ + /* one time init and never free */ + if (sys_mutex_new(&sockets[oldest].lock) != ERR_OK){ + LWIP_DEBUGF(THREAD_SAFE_DEBUG, ("new sock lock fail\n")); + return -1; + } + } + LWIP_DEBUGF(THREAD_SAFE_DEBUG, ("alloc_socket: alloc %d ok\n", oldest)); + + return oldest + LWIP_SOCKET_OFFSET; + } + + LWIP_DEBUGF(THREAD_SAFE_DEBUG, ("alloc_socket: failed\n")); + +#else + + /* allocate a new socket identifier */ + for (i = 0; i < NUM_SOCKETS; ++i) { + /* Protect socket array */ + SYS_ARCH_PROTECT(lev); + if (!sockets[i].conn) { + sockets[i].conn = newconn; + /* The socket is not yet known to anyone, so no need to protect + after having marked it as used. */ + SYS_ARCH_UNPROTECT(lev); + sockets[i].lastdata = NULL; + sockets[i].lastoffset = 0; + sockets[i].rcvevent = 0; + /* TCP sendbuf is empty, but the socket is not yet writable until connected + * (unless it has been created by accept()). */ + sockets[i].sendevent = (NETCONNTYPE_GROUP(newconn->type) == NETCONN_TCP ? (accepted != 0) : 1); + sockets[i].errevent = 0; + sockets[i].err = 0; + sockets[i].select_waiting = 0; + + return i + LWIP_SOCKET_OFFSET; + } + SYS_ARCH_UNPROTECT(lev); + } + +#endif + + return -1; +} + +/** Free a socket. The socket's netconn must have been + * delete before! + * + * @param sock the socket to free + * @param is_tcp != 0 for TCP sockets, used to free lastdata + */ +static void +free_socket(struct lwip_sock *sock, int is_tcp) +{ + void *lastdata; + SYS_ARCH_DECL_PROTECT(lev); + + LWIP_DEBUGF(THREAD_SAFE_DEBUG, ("free_sockset:free socket s=%p is_tcp=%d\n", sock, is_tcp)); + lastdata = sock->lastdata; + sock->lastdata = NULL; + sock->lastoffset = 0; + sock->err = 0; +#if LWIP_THREAD_SAFE + if (sock->conn){ + netconn_free(sock->conn); + } + + SYS_ARCH_PROTECT(lev); + sock->age = 0; + sock->conn = NULL; + sock->state = LWIP_SOCK_CLOSED; + SYS_ARCH_UNPROTECT(lev); +#endif + + /* Protect socket array */ + SYS_ARCH_SET(sock->conn, NULL); + /* don't use 'sock' after this line, as another task might have allocated it */ + + if (lastdata != NULL) { + if (is_tcp) { + LWIP_DEBUGF(THREAD_SAFE_DEBUG, ("free_sockset:free lastdata pbuf=%p\n", lastdata)); + pbuf_free((struct pbuf *)lastdata); + } else { + LWIP_DEBUGF(THREAD_SAFE_DEBUG, ("free_sockset:free lastdata, netbuf=%p\n", lastdata)); + netbuf_delete((struct netbuf *)lastdata); + } + } +} + +/* Below this, the well-known socket functions are implemented. + * Use google.com or opengroup.org to get a good description :-) + * + * Exceptions are documented! + */ + +int +lwip_accept(int s, struct sockaddr *addr, socklen_t *addrlen) +{ + struct lwip_sock *sock, *nsock; + struct netconn *newconn; + ip_addr_t naddr; + u16_t port = 0; + int newsock; + err_t err; + SYS_ARCH_DECL_PROTECT(lev); + + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_accept(%d)...\n", s)); + sock = get_socket(s); + if (!sock) { + return -1; + } + + if (netconn_is_nonblocking(sock->conn) && (sock->rcvevent <= 0)) { + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_accept(%d): returning EWOULDBLOCK\n", s)); + sock_set_errno(sock, EWOULDBLOCK); + return -1; + } + + /* wait for a new connection */ + err = netconn_accept(sock->conn, &newconn); + if (err != ERR_OK) { + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_accept(%d): netconn_acept failed, err=%d\n", s, err)); + if (NETCONNTYPE_GROUP(netconn_type(sock->conn)) != NETCONN_TCP) { + sock_set_errno(sock, EOPNOTSUPP); + return EOPNOTSUPP; + } + sock_set_errno(sock, err_to_errno(err)); + return -1; + } + LWIP_ASSERT("newconn != NULL", newconn != NULL); + /* Prevent automatic window updates, we do this on our own! */ + netconn_set_noautorecved(newconn, 1); + + newsock = alloc_socket(newconn, 1); + if (newsock == -1) { + netconn_delete(newconn); + sock_set_errno(sock, ENFILE); + return -1; + } + LWIP_ASSERT("invalid socket index", (newsock >= LWIP_SOCKET_OFFSET) && (newsock < NUM_SOCKETS + LWIP_SOCKET_OFFSET)); + LWIP_ASSERT("newconn->callback == event_callback", newconn->callback == event_callback); + nsock = &sockets[newsock - LWIP_SOCKET_OFFSET]; + + /* See event_callback: If data comes in right away after an accept, even + * though the server task might not have created a new socket yet. + * In that case, newconn->socket is counted down (newconn->socket--), + * so nsock->rcvevent is >= 1 here! + */ + SYS_ARCH_PROTECT(lev); + nsock->rcvevent += (s16_t)(-1 - newconn->socket); + newconn->socket = newsock; + SYS_ARCH_UNPROTECT(lev); + + /* Note that POSIX only requires us to check addr is non-NULL. addrlen must + * not be NULL if addr is valid. + */ + if (addr != NULL) { + union sockaddr_aligned tempaddr; + /* get the IP address and port of the remote host */ + err = netconn_peer(newconn, &naddr, &port); + if (err != ERR_OK) { + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_accept(%d): netconn_peer failed, err=%d\n", s, err)); + netconn_delete(newconn); + free_socket(nsock, 1); + sock_set_errno(sock, err_to_errno(err)); + return -1; + } + LWIP_ASSERT("addr valid but addrlen NULL", addrlen != NULL); + + IPADDR_PORT_TO_SOCKADDR(&tempaddr, &naddr, port); + if (*addrlen > tempaddr.sa.sa_len) { + *addrlen = tempaddr.sa.sa_len; + } + MEMCPY(addr, &tempaddr, *addrlen); + + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_accept(%d) returning new sock=%d addr=", s, newsock)); + ip_addr_debug_print_val(SOCKETS_DEBUG, naddr); + LWIP_DEBUGF(SOCKETS_DEBUG, (" port=%"U16_F"\n", port)); + } else { + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_accept(%d) returning new sock=%d", s, newsock)); + } + + sock_set_errno(sock, 0); + return newsock; +} + +int +lwip_bind(int s, const struct sockaddr *name, socklen_t namelen) +{ + struct lwip_sock *sock; + ip_addr_t local_addr; + u16_t local_port; + err_t err; + + sock = get_socket(s); + if (!sock) { + return -1; + } + + if (!SOCK_ADDR_TYPE_MATCH(name, sock)) { + /* sockaddr does not match socket type (IPv4/IPv6) */ + sock_set_errno(sock, err_to_errno(ERR_VAL)); + return -1; + } + + /* check size, family and alignment of 'name' */ + LWIP_ERROR("lwip_bind: invalid address", (IS_SOCK_ADDR_LEN_VALID(namelen) && + IS_SOCK_ADDR_TYPE_VALID(name) && IS_SOCK_ADDR_ALIGNED(name)), + sock_set_errno(sock, err_to_errno(ERR_ARG)); return -1;); + LWIP_UNUSED_ARG(namelen); + + SOCKADDR_TO_IPADDR_PORT(name, &local_addr, local_port); + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_bind(%d, addr=", s)); + ip_addr_debug_print_val(SOCKETS_DEBUG, local_addr); + LWIP_DEBUGF(SOCKETS_DEBUG, (" port=%"U16_F")\n", local_port)); + + err = netconn_bind(sock->conn, &local_addr, local_port); + + if (err != ERR_OK) { + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_bind(%d) failed, err=%d\n", s, err)); + sock_set_errno(sock, err_to_errno(err)); + return -1; + } + + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_bind(%d) succeeded\n", s)); + sock_set_errno(sock, 0); + return 0; +} + +int +lwip_close(int s) +{ + struct lwip_sock *sock; + int is_tcp = 0; + err_t err; + + LWIP_DEBUGF(SOCKETS_DEBUG|THREAD_SAFE_DEBUG, ("lwip_close: (%d)\n", s)); + + sock = get_socket(s); + if (!sock) { + LWIP_DEBUGF(SOCKETS_DEBUG|THREAD_SAFE_DEBUG, ("lwip_close: sock is null, return -1\n")); + return -1; + } + + if (sock->conn != NULL) { + is_tcp = NETCONNTYPE_GROUP(netconn_type(sock->conn)) == NETCONN_TCP; + LWIP_DEBUGF(SOCKETS_DEBUG|THREAD_SAFE_DEBUG, ("lwip_close: is_tcp=%d\n", is_tcp)); + } else { + LWIP_DEBUGF(SOCKETS_DEBUG|THREAD_SAFE_DEBUG, ("conn is null\n")); + LWIP_ASSERT("lwip_close: sock->lastdata == NULL", sock->lastdata == NULL); + } + +#if LWIP_IGMP + /* drop all possibly joined IGMP memberships */ + lwip_socket_drop_registered_memberships(s); +#endif /* LWIP_IGMP */ + + err = netconn_delete(sock->conn); + if (err != ERR_OK) { + LWIP_DEBUGF(SOCKETS_DEBUG|THREAD_SAFE_DEBUG, ("netconn_delete fail, ret=%d\n", err)); + sock_set_errno(sock, err_to_errno(err)); + return -1; + } + +#if !LWIP_THREAD_SAFE + free_socket(sock, is_tcp); +#endif + + set_errno(0); + return 0; +} + +int +lwip_connect(int s, const struct sockaddr *name, socklen_t namelen) +{ + struct lwip_sock *sock; + err_t err; + + sock = get_socket(s); + if (!sock) { + return -1; + } + + if (!SOCK_ADDR_TYPE_MATCH_OR_UNSPEC(name, sock)) { + /* sockaddr does not match socket type (IPv4/IPv6) */ + sock_set_errno(sock, err_to_errno(ERR_VAL)); + return -1; + } + + LWIP_UNUSED_ARG(namelen); + if (name->sa_family == AF_UNSPEC) { + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_connect(%d, AF_UNSPEC)\n", s)); + err = netconn_disconnect(sock->conn); + } else { + ip_addr_t remote_addr; + u16_t remote_port; + + /* check size, family and alignment of 'name' */ + LWIP_ERROR("lwip_connect: invalid address", IS_SOCK_ADDR_LEN_VALID(namelen) && + IS_SOCK_ADDR_TYPE_VALID_OR_UNSPEC(name) && IS_SOCK_ADDR_ALIGNED(name), + sock_set_errno(sock, err_to_errno(ERR_ARG)); return -1;); + + SOCKADDR_TO_IPADDR_PORT(name, &remote_addr, remote_port); + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_connect(%d, addr=", s)); + ip_addr_debug_print_val(SOCKETS_DEBUG, remote_addr); + LWIP_DEBUGF(SOCKETS_DEBUG, (" port=%"U16_F")\n", remote_port)); + + err = netconn_connect(sock->conn, &remote_addr, remote_port); + } + + if (err != ERR_OK) { + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_connect(%d) failed, err=%d\n", s, err)); + sock_set_errno(sock, err_to_errno(err)); + return -1; + } + + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_connect(%d) succeeded\n", s)); + sock_set_errno(sock, 0); + return 0; +} + +/** + * Set a socket into listen mode. + * The socket may not have been used for another connection previously. + * + * @param s the socket to set to listening mode + * @param backlog (ATTENTION: needs TCP_LISTEN_BACKLOG=1) + * @return 0 on success, non-zero on failure + */ +int +lwip_listen(int s, int backlog) +{ + struct lwip_sock *sock; + err_t err; + + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_listen(%d, backlog=%d)\n", s, backlog)); + + sock = get_socket(s); + if (!sock) { + return -1; + } + + /* limit the "backlog" parameter to fit in an u8_t */ + backlog = LWIP_MIN(LWIP_MAX(backlog, 0), 0xff); + + err = netconn_listen_with_backlog(sock->conn, (u8_t)backlog); + + if (err != ERR_OK) { + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_listen(%d) failed, err=%d\n", s, err)); + if (NETCONNTYPE_GROUP(netconn_type(sock->conn)) != NETCONN_TCP) { + sock_set_errno(sock, EOPNOTSUPP); + return -1; + } + sock_set_errno(sock, err_to_errno(err)); + return -1; + } + + sock_set_errno(sock, 0); + return 0; +} + +int +lwip_recvfrom(int s, void *mem, size_t len, int flags, + struct sockaddr *from, socklen_t *fromlen) +{ + struct lwip_sock *sock; + void *buf = NULL; + struct pbuf *p; + u16_t buflen, copylen; + int off = 0; + u8_t done = 0; + err_t err; + + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_recvfrom(%d, %p, %"SZT_F", 0x%x, ..)\n", s, mem, len, flags)); + sock = get_socket(s); + if (!sock) { + return -1; + } + + do { + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_recvfrom: top while sock->lastdata=%p\n", sock->lastdata)); + /* Check if there is data left from the last recv operation. */ + if (sock->lastdata) { + buf = sock->lastdata; + } else { + /* If this is non-blocking call, then check first */ + if (((flags & MSG_DONTWAIT) || netconn_is_nonblocking(sock->conn)) && + (sock->rcvevent <= 0)) { + if (off > 0) { + /* update receive window */ + netconn_recved(sock->conn, (u32_t)off); + /* already received data, return that */ + sock_set_errno(sock, 0); + return off; + } + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_recvfrom(%d): returning EWOULDBLOCK\n", s)); + sock_set_errno(sock, EWOULDBLOCK); + return -1; + } + + /* No data was left from the previous operation, so we try to get + some from the network. */ + if (NETCONNTYPE_GROUP(netconn_type(sock->conn)) == NETCONN_TCP) { + err = netconn_recv_tcp_pbuf(sock->conn, (struct pbuf **)&buf); + } else { + err = netconn_recv(sock->conn, (struct netbuf **)&buf); + } + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_recvfrom: netconn_recv err=%d, netbuf=%p\n", + err, buf)); + + if (err != ERR_OK) { + if (off > 0) { + /* update receive window */ + netconn_recved(sock->conn, (u32_t)off); + if (err == ERR_CLSD) { + /* closed but already received data, ensure select gets the FIN, too */ + event_callback(sock->conn, NETCONN_EVT_RCVPLUS, 0); + } + /* already received data, return that */ + sock_set_errno(sock, 0); + return off; + } + /* We should really do some error checking here. */ + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_recvfrom(%d): buf == NULL, error is \"%s\"!\n", + s, lwip_strerr(err))); + sock_set_errno(sock, err_to_errno(err)); + if (err == ERR_CLSD) { + return 0; + } else { + return -1; + } + } + LWIP_ASSERT("buf != NULL", buf != NULL); + sock->lastdata = buf; + } + + if (NETCONNTYPE_GROUP(netconn_type(sock->conn)) == NETCONN_TCP) { + p = (struct pbuf *)buf; + } else { + p = ((struct netbuf *)buf)->p; + } + buflen = p->tot_len; + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_recvfrom: buflen=%"U16_F" len=%"SZT_F" off=%d sock->lastoffset=%"U16_F"\n", + buflen, len, off, sock->lastoffset)); + + buflen -= sock->lastoffset; + + if (len > buflen) { + copylen = buflen; + } else { + copylen = (u16_t)len; + } + + /* copy the contents of the received buffer into + the supplied memory pointer mem */ + pbuf_copy_partial(p, (u8_t*)mem + off, copylen, sock->lastoffset); + + off += copylen; + + if (NETCONNTYPE_GROUP(netconn_type(sock->conn)) == NETCONN_TCP) { + LWIP_ASSERT("invalid copylen, len would underflow", len >= copylen); + len -= copylen; + if ((len <= 0) || + (p->flags & PBUF_FLAG_PUSH) || + (sock->rcvevent <= 0) || + ((flags & MSG_PEEK) != 0)) { + done = 1; + } + } else { + done = 1; + } + + /* Check to see from where the data was.*/ + if (done) { +#if !SOCKETS_DEBUG + if (from && fromlen) +#endif /* !SOCKETS_DEBUG */ + { + u16_t port; + ip_addr_t tmpaddr; + ip_addr_t *fromaddr; + union sockaddr_aligned saddr; + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_recvfrom(%d): addr=", s)); + if (NETCONNTYPE_GROUP(netconn_type(sock->conn)) == NETCONN_TCP) { + fromaddr = &tmpaddr; + netconn_getaddr(sock->conn, fromaddr, &port, 0); + } else { + port = netbuf_fromport((struct netbuf *)buf); + fromaddr = netbuf_fromaddr((struct netbuf *)buf); + } + IPADDR_PORT_TO_SOCKADDR(&saddr, fromaddr, port); + ip_addr_debug_print(SOCKETS_DEBUG, fromaddr); + LWIP_DEBUGF(SOCKETS_DEBUG, (" port=%"U16_F" len=%d\n", port, off)); + +#ifdef LWIP_ESP8266 + if (from && fromlen) +#else + +#if SOCKETS_DEBUG + if (from && fromlen) +#endif /* SOCKETS_DEBUG */ + +#endif + { + if (*fromlen > saddr.sa.sa_len) { + *fromlen = saddr.sa.sa_len; + } + MEMCPY(from, &saddr, *fromlen); + +#ifdef LWIP_ESP8266 + } else { + /*fix the code for setting the UDP PROTO's remote infomation by liuh at 2014.8.27*/ + if (NETCONNTYPE_GROUP(netconn_type(sock->conn)) == NETCONN_UDP){ + sock->conn->pcb.udp->remote_ip.u_addr.ip4.addr = fromaddr->u_addr.ip4.addr; + sock->conn->pcb.udp->remote_port = port; + } +#endif + + } + } + } + + /* If we don't peek the incoming message... */ + if ((flags & MSG_PEEK) == 0) { + /* If this is a TCP socket, check if there is data left in the + buffer. If so, it should be saved in the sock structure for next + time around. */ + if ((NETCONNTYPE_GROUP(netconn_type(sock->conn)) == NETCONN_TCP) && (buflen - copylen > 0)) { + sock->lastdata = buf; + sock->lastoffset += copylen; + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_recvfrom: lastdata now netbuf=%p\n", buf)); + } else { + sock->lastdata = NULL; + sock->lastoffset = 0; + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_recvfrom: deleting netbuf=%p\n", buf)); + if (NETCONNTYPE_GROUP(netconn_type(sock->conn)) == NETCONN_TCP) { + pbuf_free((struct pbuf *)buf); + } else { + netbuf_delete((struct netbuf *)buf); + } + buf = NULL; + } + } + } while (!done); + + if ((off > 0) && (NETCONNTYPE_GROUP(netconn_type(sock->conn)) == NETCONN_TCP) && + ((flags & MSG_PEEK) == 0)) { + /* update receive window */ + netconn_recved(sock->conn, (u32_t)off); + } + sock_set_errno(sock, 0); + return off; +} + + +int +lwip_read(int s, void *mem, size_t len) +{ + return lwip_recvfrom(s, mem, len, 0, NULL, NULL); +} + +int +lwip_recv(int s, void *mem, size_t len, int flags) +{ + return lwip_recvfrom(s, mem, len, flags, NULL, NULL); +} + +int +lwip_send(int s, const void *data, size_t size, int flags) +{ + struct lwip_sock *sock; + err_t err; + u8_t write_flags; + size_t written; + + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_send(%d, data=%p, size=%"SZT_F", flags=0x%x)\n", + s, data, size, flags)); + + sock = get_socket(s); + if (!sock) { + return -1; + } + + if (NETCONNTYPE_GROUP(netconn_type(sock->conn)) != NETCONN_TCP) { +#if (LWIP_UDP || LWIP_RAW) + return lwip_sendto(s, data, size, flags, NULL, 0); +#else /* (LWIP_UDP || LWIP_RAW) */ + sock_set_errno(sock, err_to_errno(ERR_ARG)); + return -1; +#endif /* (LWIP_UDP || LWIP_RAW) */ + } + + DELAY_WHEN_MEMORY_NOT_ENOUGH(); + + write_flags = NETCONN_COPY | + ((flags & MSG_MORE) ? NETCONN_MORE : 0) | + ((flags & MSG_DONTWAIT) ? NETCONN_DONTBLOCK : 0); + written = 0; + err = netconn_write_partly(sock->conn, data, size, write_flags, &written); + + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_send(%d) err=%d written=%"SZT_F"\n", s, err, written)); + sock_set_errno(sock, err_to_errno(err)); + + return (err == ERR_OK ? (int)written : -1); +} + +int +lwip_sendmsg(int s, const struct msghdr *msg, int flags) +{ + struct lwip_sock *sock; + struct netbuf *chain_buf; + u16_t remote_port; + int i; +#if LWIP_TCP + u8_t write_flags; + size_t written; +#endif + int size = 0; + err_t err = ERR_OK; + + sock = get_socket(s); + if (!sock) { + return -1; + } + + LWIP_ERROR("lwip_sendmsg: invalid msghdr", msg != NULL, + sock_set_errno(sock, err_to_errno(ERR_ARG)); return -1;); + + LWIP_UNUSED_ARG(msg->msg_control); + LWIP_UNUSED_ARG(msg->msg_controllen); + LWIP_UNUSED_ARG(msg->msg_flags); + LWIP_ERROR("lwip_sendmsg: invalid msghdr iov", (msg->msg_iov != NULL && msg->msg_iovlen != 0), + sock_set_errno(sock, err_to_errno(ERR_ARG)); return -1;); + + if (NETCONNTYPE_GROUP(netconn_type(sock->conn)) == NETCONN_TCP) { +#if LWIP_TCP + write_flags = NETCONN_COPY | + ((flags & MSG_MORE) ? NETCONN_MORE : 0) | + ((flags & MSG_DONTWAIT) ? NETCONN_DONTBLOCK : 0); + + for (i = 0; i < msg->msg_iovlen; i++) { + written = 0; + err = netconn_write_partly(sock->conn, msg->msg_iov[i].iov_base, msg->msg_iov[i].iov_len, write_flags, &written); + if (err == ERR_OK) { + size += written; + /* check that the entire IO vector was accepected, if not return a partial write */ + if (written != msg->msg_iov[i].iov_len) + break; + } + /* none of this IO vector was accepted, but previous was, return partial write and conceal ERR_WOULDBLOCK */ + else if (err == ERR_WOULDBLOCK && size > 0) { + err = ERR_OK; + /* let ERR_WOULDBLOCK persist on the netconn since we are returning ERR_OK */ + break; + } else { + size = -1; + break; + } + } + sock_set_errno(sock, err_to_errno(err)); + return size; +#else /* LWIP_TCP */ + sock_set_errno(sock, err_to_errno(ERR_ARG)); + return -1; +#endif /* LWIP_TCP */ + } + /* else, UDP and RAW NETCONNs */ +#if LWIP_UDP || LWIP_RAW + + LWIP_UNUSED_ARG(flags); + LWIP_ERROR("lwip_sendmsg: invalid msghdr name", (((msg->msg_name == NULL) && (msg->msg_namelen == 0)) || + IS_SOCK_ADDR_LEN_VALID(msg->msg_namelen)) , + sock_set_errno(sock, err_to_errno(ERR_ARG)); return -1;); + + /* initialize chain buffer with destination */ + chain_buf = netbuf_new(); + if (!chain_buf) { + sock_set_errno(sock, err_to_errno(ERR_MEM)); + return -1; + } + if (msg->msg_name) { + SOCKADDR_TO_IPADDR_PORT((const struct sockaddr *)msg->msg_name, &chain_buf->addr, remote_port); + netbuf_fromport(chain_buf) = remote_port; + } +#if LWIP_NETIF_TX_SINGLE_PBUF + for (i = 0; i < msg->msg_iovlen; i++) { + size += msg->msg_iov[i].iov_len; + } + /* Allocate a new netbuf and copy the data into it. */ + if (netbuf_alloc(chain_buf, (u16_t)size) == NULL) { + err = ERR_MEM; + } + else { + /* flatten the IO vectors */ + size_t offset = 0; + for (i = 0; i < msg->msg_iovlen; i++) { + MEMCPY(&((u8_t*)chain_buf->p->payload)[offset], msg->msg_iov[i].iov_base, msg->msg_iov[i].iov_len); + offset += msg->msg_iov[i].iov_len; + } +#if LWIP_CHECKSUM_ON_COPY + { + /* This can be improved by using LWIP_CHKSUM_COPY() and aggregating the checksum for each IO vector */ + u16_t chksum = ~inet_chksum_pbuf(chain_buf->p); + netbuf_set_chksum(chain_buf, chksum); + } +#endif /* LWIP_CHECKSUM_ON_COPY */ + err = ERR_OK; + } +#else /* LWIP_NETIF_TX_SINGLE_PBUF */ + /* create a chained netbuf from the IO vectors. NOTE: we assemble a pbuf chain + manually to avoid having to allocate, chain, and delete a netbuf for each iov */ + for (i = 0; i < msg->msg_iovlen; i++) { + struct pbuf *p = pbuf_alloc(PBUF_TRANSPORT, 0, PBUF_REF); + if (p == NULL) { + err = ERR_MEM; /* let netbuf_delete() cleanup chain_buf */ + break; + } + p->payload = msg->msg_iov[i].iov_base; + LWIP_ASSERT("iov_len < u16_t", msg->msg_iov[i].iov_len <= 0xFFFF); + p->len = p->tot_len = (u16_t)msg->msg_iov[i].iov_len; + /* netbuf empty, add new pbuf */ + if (chain_buf->p == NULL) { + chain_buf->p = chain_buf->ptr = p; + /* add pbuf to existing pbuf chain */ + } else { + pbuf_cat(chain_buf->p, p); + } + } + /* save size of total chain */ + if (err == ERR_OK) { + size = netbuf_len(chain_buf); + } +#endif /* LWIP_NETIF_TX_SINGLE_PBUF */ + + if (err == ERR_OK) { + /* send the data */ + err = netconn_send(sock->conn, chain_buf); + } + + /* deallocated the buffer */ + netbuf_delete(chain_buf); + + sock_set_errno(sock, err_to_errno(err)); + return (err == ERR_OK ? size : -1); +#else /* LWIP_UDP || LWIP_RAW */ + sock_set_errno(sock, err_to_errno(ERR_ARG)); + return -1; +#endif /* LWIP_UDP || LWIP_RAW */ +} + +int +lwip_sendto(int s, const void *data, size_t size, int flags, + const struct sockaddr *to, socklen_t tolen) +{ + struct lwip_sock *sock; + err_t err; + u16_t short_size; + u16_t remote_port; + struct netbuf buf; + + sock = get_socket(s); + if (!sock) { + return -1; + } + + if (NETCONNTYPE_GROUP(netconn_type(sock->conn)) == NETCONN_TCP) { +#if LWIP_TCP + return lwip_send(s, data, size, flags); +#else /* LWIP_TCP */ + LWIP_UNUSED_ARG(flags); + sock_set_errno(sock, err_to_errno(ERR_ARG)); + return -1; +#endif /* LWIP_TCP */ + } + + DELAY_WHEN_MEMORY_NOT_ENOUGH(); + + if ((to != NULL) && !SOCK_ADDR_TYPE_MATCH(to, sock)) { + /* sockaddr does not match socket type (IPv4/IPv6) */ + sock_set_errno(sock, err_to_errno(ERR_VAL)); + return -1; + } + + /* @todo: split into multiple sendto's? */ + LWIP_ASSERT("lwip_sendto: size must fit in u16_t", size <= 0xffff); + short_size = (u16_t)size; + LWIP_ERROR("lwip_sendto: invalid address", (((to == NULL) && (tolen == 0)) || + (IS_SOCK_ADDR_LEN_VALID(tolen) && + IS_SOCK_ADDR_TYPE_VALID(to) && IS_SOCK_ADDR_ALIGNED(to))), + sock_set_errno(sock, err_to_errno(ERR_ARG)); return -1;); + LWIP_UNUSED_ARG(tolen); + + /* initialize a buffer */ + buf.p = buf.ptr = NULL; +#if LWIP_CHECKSUM_ON_COPY + buf.flags = 0; +#endif /* LWIP_CHECKSUM_ON_COPY */ + if (to) { + SOCKADDR_TO_IPADDR_PORT(to, &buf.addr, remote_port); + } else { + +#ifdef LWIP_ESP8266 + /*fix the code for getting the UDP proto's remote information by liuh at 2014.8.27*/ + if (NETCONNTYPE_GROUP(netconn_type(sock->conn)) == NETCONN_UDP){ + buf.addr.u_addr.ip4.addr = sock->conn->pcb.udp->remote_ip.u_addr.ip4.addr; + remote_port = sock->conn->pcb.udp->remote_port; + } else { +#endif + remote_port = 0; + ip_addr_set_any(NETCONNTYPE_ISIPV6(netconn_type(sock->conn)), &buf.addr); +#ifdef LWIP_ESP8266 + } +#endif + + } + netbuf_fromport(&buf) = remote_port; + + + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_sendto(%d, data=%p, short_size=%"U16_F", flags=0x%x to=", + s, data, short_size, flags)); + ip_addr_debug_print(SOCKETS_DEBUG, &buf.addr); + LWIP_DEBUGF(SOCKETS_DEBUG, (" port=%"U16_F"\n", remote_port)); + + /* make the buffer point to the data that should be sent */ +#if LWIP_NETIF_TX_SINGLE_PBUF + /* Allocate a new netbuf and copy the data into it. */ + if (netbuf_alloc(&buf, short_size) == NULL) { + err = ERR_MEM; + } else { +#if LWIP_CHECKSUM_ON_COPY + if (NETCONNTYPE_GROUP(netconn_type(sock->conn)) != NETCONN_RAW) { + u16_t chksum = LWIP_CHKSUM_COPY(buf.p->payload, data, short_size); + netbuf_set_chksum(&buf, chksum); + } else +#endif /* LWIP_CHECKSUM_ON_COPY */ + { + MEMCPY(buf.p->payload, data, short_size); + } + err = ERR_OK; + } +#else /* LWIP_NETIF_TX_SINGLE_PBUF */ + err = netbuf_ref(&buf, data, short_size); +#endif /* LWIP_NETIF_TX_SINGLE_PBUF */ + if (err == ERR_OK) { + /* send the data */ + err = netconn_send(sock->conn, &buf); + } + + /* deallocated the buffer */ + netbuf_free(&buf); + + sock_set_errno(sock, err_to_errno(err)); + return (err == ERR_OK ? short_size : -1); +} + +int +lwip_socket(int domain, int type, int protocol) +{ + struct netconn *conn; + int i; + +#if !LWIP_IPV6 + LWIP_UNUSED_ARG(domain); /* @todo: check this */ +#endif /* LWIP_IPV6 */ + + /* create a netconn */ + switch (type) { + case SOCK_RAW: + conn = netconn_new_with_proto_and_callback(DOMAIN_TO_NETCONN_TYPE(domain, NETCONN_RAW), + (u8_t)protocol, event_callback); + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_socket(%s, SOCK_RAW, %d) = ", + domain == PF_INET ? "PF_INET" : "UNKNOWN", protocol)); + break; + case SOCK_DGRAM: + conn = netconn_new_with_callback(DOMAIN_TO_NETCONN_TYPE(domain, + ((protocol == IPPROTO_UDPLITE) ? NETCONN_UDPLITE : NETCONN_UDP)) , + event_callback); + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_socket(%s, SOCK_DGRAM, %d) = ", + domain == PF_INET ? "PF_INET" : "UNKNOWN", protocol)); + break; + case SOCK_STREAM: + conn = netconn_new_with_callback(DOMAIN_TO_NETCONN_TYPE(domain, NETCONN_TCP), event_callback); + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_socket(%s, SOCK_STREAM, %d) = ", + domain == PF_INET ? "PF_INET" : "UNKNOWN", protocol)); + if (conn != NULL) { + /* Prevent automatic window updates, we do this on our own! */ + netconn_set_noautorecved(conn, 1); + } + break; + default: + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_socket(%d, %d/UNKNOWN, %d) = -1\n", + domain, type, protocol)); + set_errno(EINVAL); + return -1; + } + + if (!conn) { + LWIP_DEBUGF(SOCKETS_DEBUG, ("-1 / ENOBUFS (could not create netconn)\n")); + set_errno(ENOBUFS); + return -1; + } + + i = alloc_socket(conn, 0); + + if (i == -1) { + netconn_delete(conn); + set_errno(ENFILE); + return -1; + } + conn->socket = i; + LWIP_DEBUGF(SOCKETS_DEBUG, ("%d\n", i)); + set_errno(0); + return i; +} + +int +lwip_write(int s, const void *data, size_t size) +{ + return lwip_send(s, data, size, 0); +} + +int +lwip_writev(int s, const struct iovec *iov, int iovcnt) +{ + struct msghdr msg; + + msg.msg_name = NULL; + msg.msg_namelen = 0; + /* Hack: we have to cast via number to cast from 'const' pointer to non-const. + Blame the opengroup standard for this inconsistency. */ + msg.msg_iov = (struct iovec *)(size_t)iov; + msg.msg_iovlen = iovcnt; + msg.msg_control = NULL; + msg.msg_controllen = 0; + msg.msg_flags = 0; + return lwip_sendmsg(s, &msg, 0); +} + +/** + * Go through the readset and writeset lists and see which socket of the sockets + * set in the sets has events. On return, readset, writeset and exceptset have + * the sockets enabled that had events. + * + * @param maxfdp1 the highest socket index in the sets + * @param readset_in: set of sockets to check for read events + * @param writeset_in: set of sockets to check for write events + * @param exceptset_in: set of sockets to check for error events + * @param readset_out: set of sockets that had read events + * @param writeset_out: set of sockets that had write events + * @param exceptset_out: set os sockets that had error events + * @return number of sockets that had events (read/write/exception) (>= 0) + */ +static int +lwip_selscan(int maxfdp1, fd_set *readset_in, fd_set *writeset_in, fd_set *exceptset_in, + fd_set *readset_out, fd_set *writeset_out, fd_set *exceptset_out) +{ + int i, nready = 0; + fd_set lreadset, lwriteset, lexceptset; + struct lwip_sock *sock; + SYS_ARCH_DECL_PROTECT(lev); + + FD_ZERO(&lreadset); + FD_ZERO(&lwriteset); + FD_ZERO(&lexceptset); + + /* Go through each socket in each list to count number of sockets which + currently match */ + for (i = LWIP_SOCKET_OFFSET; i < maxfdp1; i++) { + /* if this FD is not in the set, continue */ + if (!(readset_in && FD_ISSET(i, readset_in)) && + !(writeset_in && FD_ISSET(i, writeset_in)) && + !(exceptset_in && FD_ISSET(i, exceptset_in))) { + continue; + } + /* First get the socket's status (protected)... */ + SYS_ARCH_PROTECT(lev); + sock = tryget_socket(i); + if (sock != NULL) { + void* lastdata = sock->lastdata; + s16_t rcvevent = sock->rcvevent; + u16_t sendevent = sock->sendevent; + u16_t errevent = sock->errevent; + SYS_ARCH_UNPROTECT(lev); + + /* ... then examine it: */ + /* See if netconn of this socket is ready for read */ + if (readset_in && FD_ISSET(i, readset_in) && ((lastdata != NULL) || (rcvevent > 0))) { + FD_SET(i, &lreadset); + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_selscan: fd=%d ready for reading\n", i)); + nready++; + } + /* See if netconn of this socket is ready for write */ + if (writeset_in && FD_ISSET(i, writeset_in) && (sendevent != 0)) { + FD_SET(i, &lwriteset); + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_selscan: fd=%d ready for writing\n", i)); + nready++; + } + /* See if netconn of this socket had an error */ + if (exceptset_in && FD_ISSET(i, exceptset_in) && (errevent != 0)) { + FD_SET(i, &lexceptset); + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_selscan: fd=%d ready for exception\n", i)); + nready++; + } + } else { + SYS_ARCH_UNPROTECT(lev); + /* continue on to next FD in list */ + } + } + /* copy local sets to the ones provided as arguments */ + *readset_out = lreadset; + *writeset_out = lwriteset; + *exceptset_out = lexceptset; + + LWIP_ASSERT("nready >= 0", nready >= 0); + return nready; +} + +int +lwip_select(int maxfdp1, fd_set *readset, fd_set *writeset, fd_set *exceptset, + struct timeval *timeout) +{ + u32_t waitres = 0; + int nready; + fd_set lreadset, lwriteset, lexceptset; + u32_t msectimeout; + struct lwip_select_cb select_cb; + int i; + int maxfdp2; +#if LWIP_NETCONN_SEM_PER_THREAD + int waited = 0; +#endif + SYS_ARCH_DECL_PROTECT(lev); + + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_select(%d, %p, %p, %p, tvsec=%"S32_F" tvusec=%"S32_F")\n", + maxfdp1, (void *)readset, (void *) writeset, (void *) exceptset, + timeout ? (s32_t)timeout->tv_sec : (s32_t)-1, + timeout ? (s32_t)timeout->tv_usec : (s32_t)-1)); + + /* Go through each socket in each list to count number of sockets which + currently match */ + nready = lwip_selscan(maxfdp1, readset, writeset, exceptset, &lreadset, &lwriteset, &lexceptset); + + /* If we don't have any current events, then suspend if we are supposed to */ + if (!nready) { + if (timeout && timeout->tv_sec == 0 && timeout->tv_usec == 0) { + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_select: no timeout, returning 0\n")); + /* This is OK as the local fdsets are empty and nready is zero, + or we would have returned earlier. */ + goto return_copy_fdsets; + } + + /* None ready: add our semaphore to list: + We don't actually need any dynamic memory. Our entry on the + list is only valid while we are in this function, so it's ok + to use local variables. */ + + select_cb.next = NULL; + select_cb.prev = NULL; + select_cb.readset = readset; + select_cb.writeset = writeset; + select_cb.exceptset = exceptset; + select_cb.sem_signalled = 0; +#if LWIP_NETCONN_SEM_PER_THREAD + select_cb.sem = LWIP_NETCONN_THREAD_SEM_GET(); +#else /* LWIP_NETCONN_SEM_PER_THREAD */ + if (sys_sem_new(&select_cb.sem, 0) != ERR_OK) { + /* failed to create semaphore */ + set_errno(ENOMEM); + return -1; + } +#endif /* LWIP_NETCONN_SEM_PER_THREAD */ + + /* Protect the select_cb_list */ + SYS_ARCH_PROTECT(lev); + + /* Put this select_cb on top of list */ + select_cb.next = select_cb_list; + if (select_cb_list != NULL) { + select_cb_list->prev = &select_cb; + } + select_cb_list = &select_cb; + /* Increasing this counter tells event_callback that the list has changed. */ + select_cb_ctr++; + + /* Now we can safely unprotect */ + SYS_ARCH_UNPROTECT(lev); + + /* Increase select_waiting for each socket we are interested in */ + maxfdp2 = maxfdp1; + for (i = LWIP_SOCKET_OFFSET; i < maxfdp1; i++) { + if ((readset && FD_ISSET(i, readset)) || + (writeset && FD_ISSET(i, writeset)) || + (exceptset && FD_ISSET(i, exceptset))) { + struct lwip_sock *sock; + SYS_ARCH_PROTECT(lev); + sock = tryget_socket(i); + if (sock != NULL) { + sock->select_waiting++; + LWIP_ASSERT("sock->select_waiting > 0", sock->select_waiting > 0); + } else { + /* Not a valid socket */ + nready = -1; + maxfdp2 = i; + SYS_ARCH_UNPROTECT(lev); + break; + } + SYS_ARCH_UNPROTECT(lev); + } + } + + if (nready >= 0) { + /* Call lwip_selscan again: there could have been events between + the last scan (without us on the list) and putting us on the list! */ + nready = lwip_selscan(maxfdp1, readset, writeset, exceptset, &lreadset, &lwriteset, &lexceptset); + if (!nready) { + /* Still none ready, just wait to be woken */ + if (timeout == 0) { + /* Wait forever */ + msectimeout = 0; + } else { + msectimeout = ((timeout->tv_sec * 1000) + ((timeout->tv_usec + 500)/1000)); + if (msectimeout == 0) { + /* Wait 1ms at least (0 means wait forever) */ + msectimeout = 1; + } + } + + waitres = sys_arch_sem_wait(SELECT_SEM_PTR(select_cb.sem), msectimeout); +#if LWIP_NETCONN_SEM_PER_THREAD + waited = 1; +#endif + } + } + + /* Decrease select_waiting for each socket we are interested in */ + for (i = LWIP_SOCKET_OFFSET; i < maxfdp2; i++) { + if ((readset && FD_ISSET(i, readset)) || + (writeset && FD_ISSET(i, writeset)) || + (exceptset && FD_ISSET(i, exceptset))) { + struct lwip_sock *sock; + SYS_ARCH_PROTECT(lev); + sock = tryget_socket(i); + if (sock != NULL) { + /* @todo: what if this is a new socket (reallocated?) in this case, + select_waiting-- would be wrong (a global 'sockalloc' counter, + stored per socket could help) */ + LWIP_ASSERT("sock->select_waiting > 0", sock->select_waiting > 0); + if (sock->select_waiting > 0) { + sock->select_waiting--; + } + } else { + /* Not a valid socket */ + nready = -1; + } + SYS_ARCH_UNPROTECT(lev); + } + } + /* Take us off the list */ + SYS_ARCH_PROTECT(lev); + if (select_cb.next != NULL) { + select_cb.next->prev = select_cb.prev; + } + if (select_cb_list == &select_cb) { + LWIP_ASSERT("select_cb.prev == NULL", select_cb.prev == NULL); + select_cb_list = select_cb.next; + } else { + LWIP_ASSERT("select_cb.prev != NULL", select_cb.prev != NULL); + select_cb.prev->next = select_cb.next; + } + /* Increasing this counter tells event_callback that the list has changed. */ + select_cb_ctr++; + SYS_ARCH_UNPROTECT(lev); + +#if LWIP_NETCONN_SEM_PER_THREAD + if (select_cb.sem_signalled && (!waited || (waitres == SYS_ARCH_TIMEOUT))) { + /* don't leave the thread-local semaphore signalled */ + sys_arch_sem_wait(select_cb.sem, 1); + } +#else /* LWIP_NETCONN_SEM_PER_THREAD */ + sys_sem_free(&select_cb.sem); +#endif /* LWIP_NETCONN_SEM_PER_THREAD */ + + if (nready < 0) { + /* This happens when a socket got closed while waiting */ + set_errno(EBADF); + return -1; + } + + if (waitres == SYS_ARCH_TIMEOUT) { + /* Timeout */ + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_select: timeout expired\n")); + /* This is OK as the local fdsets are empty and nready is zero, + or we would have returned earlier. */ + goto return_copy_fdsets; + } + + /* See what's set */ + nready = lwip_selscan(maxfdp1, readset, writeset, exceptset, &lreadset, &lwriteset, &lexceptset); + } + + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_select: nready=%d\n", nready)); +return_copy_fdsets: + set_errno(0); + if (readset) { + *readset = lreadset; + } + if (writeset) { + *writeset = lwriteset; + } + if (exceptset) { + *exceptset = lexceptset; + } + return nready; +} + +/** + * Callback registered in the netconn layer for each socket-netconn. + * Processes recvevent (data available) and wakes up tasks waiting for select. + */ +static void +event_callback(struct netconn *conn, enum netconn_evt evt, u16_t len) +{ + int s; + struct lwip_sock *sock; + struct lwip_select_cb *scb; + int last_select_cb_ctr; + SYS_ARCH_DECL_PROTECT(lev); + + LWIP_UNUSED_ARG(len); + + /* Get socket */ + if (conn) { + s = conn->socket; + if (s < 0) { + /* Data comes in right away after an accept, even though + * the server task might not have created a new socket yet. + * Just count down (or up) if that's the case and we + * will use the data later. Note that only receive events + * can happen before the new socket is set up. */ + SYS_ARCH_PROTECT(lev); + if (conn->socket < 0) { + if (evt == NETCONN_EVT_RCVPLUS) { + conn->socket--; + } + SYS_ARCH_UNPROTECT(lev); + return; + } + s = conn->socket; + SYS_ARCH_UNPROTECT(lev); + } + + sock = get_socket(s); + if (!sock) { + return; + } + } else { + return; + } + + SYS_ARCH_PROTECT(lev); + /* Set event as required */ + switch (evt) { + case NETCONN_EVT_RCVPLUS: + sock->rcvevent++; + break; + case NETCONN_EVT_RCVMINUS: + sock->rcvevent--; + break; + case NETCONN_EVT_SENDPLUS: + sock->sendevent = 1; + break; + case NETCONN_EVT_SENDMINUS: + sock->sendevent = 0; + break; + case NETCONN_EVT_ERROR: + sock->errevent = 1; + break; + default: + LWIP_ASSERT("unknown event", 0); + break; + } + + if (sock->select_waiting == 0) { + /* noone is waiting for this socket, no need to check select_cb_list */ + SYS_ARCH_UNPROTECT(lev); + return; + } + + /* Now decide if anyone is waiting for this socket */ + /* NOTE: This code goes through the select_cb_list list multiple times + ONLY IF a select was actually waiting. We go through the list the number + of waiting select calls + 1. This list is expected to be small. */ + + /* At this point, SYS_ARCH is still protected! */ +again: + for (scb = select_cb_list; scb != NULL; scb = scb->next) { + /* remember the state of select_cb_list to detect changes */ + last_select_cb_ctr = select_cb_ctr; + if (scb->sem_signalled == 0) { + /* semaphore not signalled yet */ + int do_signal = 0; + /* Test this select call for our socket */ + if (sock->rcvevent > 0) { + if (scb->readset && FD_ISSET(s, scb->readset)) { + do_signal = 1; + } + } + if (sock->sendevent != 0) { + if (!do_signal && scb->writeset && FD_ISSET(s, scb->writeset)) { + do_signal = 1; + } + } + if (sock->errevent != 0) { + if (!do_signal && scb->exceptset && FD_ISSET(s, scb->exceptset)) { + do_signal = 1; + } + } + if (do_signal) { + scb->sem_signalled = 1; + /* Don't call SYS_ARCH_UNPROTECT() before signaling the semaphore, as this might + lead to the select thread taking itself off the list, invalidating the semaphore. */ + sys_sem_signal(SELECT_SEM_PTR(scb->sem)); + } + } + /* unlock interrupts with each step */ + SYS_ARCH_UNPROTECT(lev); + /* this makes sure interrupt protection time is short */ + SYS_ARCH_PROTECT(lev); + if (last_select_cb_ctr != select_cb_ctr) { + /* someone has changed select_cb_list, restart at the beginning */ + goto again; + } + } + SYS_ARCH_UNPROTECT(lev); +} + +/** + * Unimplemented: Close one end of a full-duplex connection. + * Currently, the full connection is closed. + */ +int +lwip_shutdown(int s, int how) +{ +#ifndef LWIP_ESP8266 + + struct lwip_sock *sock; + err_t err; + u8_t shut_rx = 0, shut_tx = 0; + + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_shutdown(%d, how=%d)\n", s, how)); + + sock = get_socket(s); + if (!sock) { + return -1; + } + + if (sock->conn != NULL) { + if (NETCONNTYPE_GROUP(netconn_type(sock->conn)) != NETCONN_TCP) { + sock_set_errno(sock, EOPNOTSUPP); + return -1; + } + } else { + sock_set_errno(sock, ENOTCONN); + return -1; + } + + if (how == SHUT_RD) { + shut_rx = 1; + } else if (how == SHUT_WR) { + shut_tx = 1; + } else if (how == SHUT_RDWR) { + shut_rx = 1; + shut_tx = 1; + } else { + sock_set_errno(sock, EINVAL); + return -1; + } + err = netconn_shutdown(sock->conn, shut_rx, shut_tx); + + sock_set_errno(sock, err_to_errno(err)); + return (err == ERR_OK ? 0 : -1); +#else + return ERR_OK; +#endif + +} + +static int +lwip_getaddrname(int s, struct sockaddr *name, socklen_t *namelen, u8_t local) +{ + struct lwip_sock *sock; + union sockaddr_aligned saddr; + ip_addr_t naddr; + u16_t port; + err_t err; + + sock = get_socket(s); + if (!sock) { + return -1; + } + + /* get the IP address and port */ + /* @todo: this does not work for IPv6, yet */ + err = netconn_getaddr(sock->conn, &naddr, &port, local); + if (err != ERR_OK) { + sock_set_errno(sock, err_to_errno(err)); + return -1; + } + IPADDR_PORT_TO_SOCKADDR(&saddr, &naddr, port); + + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getaddrname(%d, addr=", s)); + ip_addr_debug_print_val(SOCKETS_DEBUG, naddr); + LWIP_DEBUGF(SOCKETS_DEBUG, (" port=%"U16_F")\n", port)); + + if (*namelen > saddr.sa.sa_len) { + *namelen = saddr.sa.sa_len; + } + MEMCPY(name, &saddr, *namelen); + + sock_set_errno(sock, 0); + return 0; +} + +int +lwip_getpeername(int s, struct sockaddr *name, socklen_t *namelen) +{ + return lwip_getaddrname(s, name, namelen, 0); +} + +int +lwip_getsockname(int s, struct sockaddr *name, socklen_t *namelen) +{ + return lwip_getaddrname(s, name, namelen, 1); +} + +int +lwip_getsockopt(int s, int level, int optname, void *optval, socklen_t *optlen) +{ + u8_t err; + struct lwip_sock *sock = get_socket(s); +#if !LWIP_TCPIP_CORE_LOCKING + LWIP_SETGETSOCKOPT_DATA_VAR_DECLARE(data); +#endif /* !LWIP_TCPIP_CORE_LOCKING */ + + if (!sock) { + return -1; + } + + if ((NULL == optval) || (NULL == optlen)) { + sock_set_errno(sock, EFAULT); + return -1; + } + +#if LWIP_TCPIP_CORE_LOCKING + /* core-locking can just call the -impl function */ + LOCK_TCPIP_CORE(); + err = lwip_getsockopt_impl(s, level, optname, optval, optlen); + UNLOCK_TCPIP_CORE(); + +#else /* LWIP_TCPIP_CORE_LOCKING */ + +#if LWIP_MPU_COMPATIBLE + /* MPU_COMPATIBLE copies the optval data, so check for max size here */ + if (*optlen > LWIP_SETGETSOCKOPT_MAXOPTLEN) { + sock_set_errno(sock, ENOBUFS); + return -1; + } +#endif /* LWIP_MPU_COMPATIBLE */ + + LWIP_SETGETSOCKOPT_DATA_VAR_ALLOC(data, sock); + LWIP_SETGETSOCKOPT_DATA_VAR_REF(data).s = s; + LWIP_SETGETSOCKOPT_DATA_VAR_REF(data).level = level; + LWIP_SETGETSOCKOPT_DATA_VAR_REF(data).optname = optname; + LWIP_SETGETSOCKOPT_DATA_VAR_REF(data).optlen = *optlen; +#if !LWIP_MPU_COMPATIBLE + LWIP_SETGETSOCKOPT_DATA_VAR_REF(data).optval.p = optval; +#endif /* !LWIP_MPU_COMPATIBLE */ + LWIP_SETGETSOCKOPT_DATA_VAR_REF(data).err = 0; +#if LWIP_NETCONN_SEM_PER_THREAD + LWIP_SETGETSOCKOPT_DATA_VAR_REF(data).completed_sem = LWIP_NETCONN_THREAD_SEM_GET(); +#else + LWIP_SETGETSOCKOPT_DATA_VAR_REF(data).completed_sem = &sock->conn->op_completed; +#endif + err = tcpip_callback(lwip_getsockopt_callback, &LWIP_SETGETSOCKOPT_DATA_VAR_REF(data)); + if (err != ERR_OK) { + LWIP_SETGETSOCKOPT_DATA_VAR_FREE(data); + sock_set_errno(sock, err_to_errno(err)); + return -1; + } + sys_arch_sem_wait((sys_sem_t*)(LWIP_SETGETSOCKOPT_DATA_VAR_REF(data).completed_sem), 0); + + /* write back optlen and optval */ + *optlen = LWIP_SETGETSOCKOPT_DATA_VAR_REF(data).optlen; +#if LWIP_MPU_COMPATIBLE + memcpy(optval, LWIP_SETGETSOCKOPT_DATA_VAR_REF(data).optval, + LWIP_SETGETSOCKOPT_DATA_VAR_REF(data).optlen); +#endif /* LWIP_MPU_COMPATIBLE */ + + /* maybe lwip_getsockopt_internal has changed err */ + err = LWIP_SETGETSOCKOPT_DATA_VAR_REF(data).err; + LWIP_SETGETSOCKOPT_DATA_VAR_FREE(data); +#endif /* LWIP_TCPIP_CORE_LOCKING */ + + sock_set_errno(sock, err); + return err ? -1 : 0; +} + +#if !LWIP_TCPIP_CORE_LOCKING +/** lwip_getsockopt_callback: only used without CORE_LOCKING + * to get into the tcpip_thread + */ +static void +lwip_getsockopt_callback(void *arg) +{ + struct lwip_setgetsockopt_data *data; + LWIP_ASSERT("arg != NULL", arg != NULL); + data = (struct lwip_setgetsockopt_data*)arg; + + data->err = lwip_getsockopt_impl(data->s, data->level, data->optname, +#if LWIP_MPU_COMPATIBLE + data->optval, +#else /* LWIP_MPU_COMPATIBLE */ + data->optval.p, +#endif /* LWIP_MPU_COMPATIBLE */ + &data->optlen); + + sys_sem_signal((sys_sem_t*)(data->completed_sem)); +} +#endif /* LWIP_TCPIP_CORE_LOCKING */ + +/** lwip_getsockopt_impl: the actual implementation of getsockopt: + * same argument as lwip_getsockopt, either called directly or through callback + */ +static u8_t +lwip_getsockopt_impl(int s, int level, int optname, void *optval, socklen_t *optlen) +{ + u8_t err = 0; + struct lwip_sock *sock = tryget_socket(s); + if (!sock) { + return EBADF; + } + + switch (level) { + +/* Level: SOL_SOCKET */ + case SOL_SOCKET: + switch (optname) { + +#if LWIP_TCP + case SO_ACCEPTCONN: + LWIP_SOCKOPT_CHECK_OPTLEN_CONN_PCB(sock, *optlen, int); + if (NETCONNTYPE_GROUP(sock->conn->type) != NETCONN_TCP) { + return ENOPROTOOPT; + } + if ((sock->conn->pcb.tcp != NULL) && (sock->conn->pcb.tcp->state == LISTEN)) { + *(int*)optval = 1; + } else { + *(int*)optval = 0; + } + break; +#endif /* LWIP_TCP */ + + /* The option flags */ + case SO_BROADCAST: + case SO_KEEPALIVE: +#if SO_REUSE + case SO_REUSEADDR: +#endif /* SO_REUSE */ + LWIP_SOCKOPT_CHECK_OPTLEN_CONN_PCB(sock, *optlen, int); + *(int*)optval = ip_get_option(sock->conn->pcb.ip, optname); + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, SOL_SOCKET, optname=0x%x, ..) = %s\n", + s, optname, (*(int*)optval?"on":"off"))); + break; + + case SO_TYPE: + LWIP_SOCKOPT_CHECK_OPTLEN_CONN(sock, *optlen, int); + switch (NETCONNTYPE_GROUP(netconn_type(sock->conn))) { + case NETCONN_RAW: + *(int*)optval = SOCK_RAW; + break; + case NETCONN_TCP: + *(int*)optval = SOCK_STREAM; + break; + case NETCONN_UDP: + *(int*)optval = SOCK_DGRAM; + break; + default: /* unrecognized socket type */ + *(int*)optval = netconn_type(sock->conn); + LWIP_DEBUGF(SOCKETS_DEBUG, + ("lwip_getsockopt(%d, SOL_SOCKET, SO_TYPE): unrecognized socket type %d\n", + s, *(int *)optval)); + } /* switch (netconn_type(sock->conn)) */ + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, SOL_SOCKET, SO_TYPE) = %d\n", + s, *(int *)optval)); + break; + + case SO_ERROR: + LWIP_SOCKOPT_CHECK_OPTLEN(*optlen, int); + /* only overwrite ERR_OK or temporary errors */ + if (((sock->err == 0) || (sock->err == EINPROGRESS)) && (sock->conn != NULL)) { + sock_set_errno(sock, err_to_errno(sock->conn->last_err)); + } + *(int *)optval = (sock->err == 0xFF ? (int)-1 : (int)sock->err); + sock->err = 0; + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, SOL_SOCKET, SO_ERROR) = %d\n", + s, *(int *)optval)); + break; + +#if LWIP_SO_SNDTIMEO + case SO_SNDTIMEO: + LWIP_SOCKOPT_CHECK_OPTLEN_CONN(sock, *optlen, LWIP_SO_SNDRCVTIMEO_OPTTYPE); + LWIP_SO_SNDRCVTIMEO_SET(optval, netconn_get_sendtimeout(sock->conn)); + break; +#endif /* LWIP_SO_SNDTIMEO */ +#if LWIP_SO_RCVTIMEO + case SO_RCVTIMEO: + LWIP_SOCKOPT_CHECK_OPTLEN_CONN(sock, *optlen, LWIP_SO_SNDRCVTIMEO_OPTTYPE); + LWIP_SO_SNDRCVTIMEO_SET(optval, netconn_get_recvtimeout(sock->conn)); + break; +#endif /* LWIP_SO_RCVTIMEO */ +#if LWIP_SO_RCVBUF + case SO_RCVBUF: + LWIP_SOCKOPT_CHECK_OPTLEN_CONN(sock, *optlen, int); + *(int *)optval = netconn_get_recvbufsize(sock->conn); + break; +#endif /* LWIP_SO_RCVBUF */ +#if LWIP_SO_LINGER + case SO_LINGER: + { + s16_t conn_linger; + struct linger* linger = (struct linger*)optval; + LWIP_SOCKOPT_CHECK_OPTLEN_CONN(sock, *optlen, struct linger); + conn_linger = sock->conn->linger; + if (conn_linger >= 0) { + linger->l_onoff = 1; + linger->l_linger = (int)conn_linger; + } else { + linger->l_onoff = 0; + linger->l_linger = 0; + } + } + break; +#endif /* LWIP_SO_LINGER */ +#if LWIP_UDP + case SO_NO_CHECK: + LWIP_SOCKOPT_CHECK_OPTLEN_CONN_PCB_TYPE(sock, *optlen, int, NETCONN_UDP); +#if LWIP_UDPLITE + if ((udp_flags(sock->conn->pcb.udp) & UDP_FLAGS_UDPLITE) != 0) { + /* this flag is only available for UDP, not for UDP lite */ + return EAFNOSUPPORT; + } +#endif /* LWIP_UDPLITE */ + *(int*)optval = (udp_flags(sock->conn->pcb.udp) & UDP_FLAGS_NOCHKSUM) ? 1 : 0; + break; +#endif /* LWIP_UDP*/ + default: + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, SOL_SOCKET, UNIMPL: optname=0x%x, ..)\n", + s, optname)); + err = ENOPROTOOPT; + break; + } /* switch (optname) */ + break; + +/* Level: IPPROTO_IP */ + case IPPROTO_IP: + switch (optname) { + case IP_TTL: + LWIP_SOCKOPT_CHECK_OPTLEN_CONN_PCB(sock, *optlen, int); + *(int*)optval = sock->conn->pcb.ip->ttl; + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, IPPROTO_IP, IP_TTL) = %d\n", + s, *(int *)optval)); + break; + case IP_TOS: + LWIP_SOCKOPT_CHECK_OPTLEN_CONN_PCB(sock, *optlen, int); + *(int*)optval = sock->conn->pcb.ip->tos; + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, IPPROTO_IP, IP_TOS) = %d\n", + s, *(int *)optval)); + break; +#if LWIP_MULTICAST_TX_OPTIONS + case IP_MULTICAST_TTL: + LWIP_SOCKOPT_CHECK_OPTLEN_CONN_PCB(sock, *optlen, u8_t); + if (NETCONNTYPE_GROUP(netconn_type(sock->conn)) != NETCONN_UDP) { + return ENOPROTOOPT; + } + *(u8_t*)optval = sock->conn->pcb.udp->mcast_ttl; + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, IPPROTO_IP, IP_MULTICAST_TTL) = %d\n", + s, *(int *)optval)); + break; + case IP_MULTICAST_IF: + LWIP_SOCKOPT_CHECK_OPTLEN_CONN_PCB(sock, *optlen, struct in_addr); + if (NETCONNTYPE_GROUP(netconn_type(sock->conn)) != NETCONN_UDP) { + return ENOPROTOOPT; + } + inet_addr_from_ipaddr((struct in_addr*)optval, udp_get_multicast_netif_addr(sock->conn->pcb.udp)); + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, IPPROTO_IP, IP_MULTICAST_IF) = 0x%"X32_F"\n", + s, *(u32_t *)optval)); + break; + case IP_MULTICAST_LOOP: + LWIP_SOCKOPT_CHECK_OPTLEN_CONN_PCB(sock, *optlen, u8_t); + if ((sock->conn->pcb.udp->flags & UDP_FLAGS_MULTICAST_LOOP) != 0) { + *(u8_t*)optval = 1; + } else { + *(u8_t*)optval = 0; + } + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, IPPROTO_IP, IP_MULTICAST_LOOP) = %d\n", + s, *(int *)optval)); + break; +#endif /* LWIP_MULTICAST_TX_OPTIONS */ + default: + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, IPPROTO_IP, UNIMPL: optname=0x%x, ..)\n", + s, optname)); + err = ENOPROTOOPT; + break; + } /* switch (optname) */ + break; + +#if LWIP_TCP +/* Level: IPPROTO_TCP */ + case IPPROTO_TCP: + /* Special case: all IPPROTO_TCP option take an int */ + LWIP_SOCKOPT_CHECK_OPTLEN_CONN_PCB_TYPE(sock, *optlen, int, NETCONN_TCP); + switch (optname) { + case TCP_NODELAY: + *(int*)optval = tcp_nagle_disabled(sock->conn->pcb.tcp); + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, IPPROTO_TCP, TCP_NODELAY) = %s\n", + s, (*(int*)optval)?"on":"off") ); + break; + case TCP_KEEPALIVE: + *(int*)optval = (int)sock->conn->pcb.tcp->keep_idle; + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, IPPROTO_TCP, TCP_KEEPALIVE) = %d\n", + s, *(int *)optval)); + break; + +#if LWIP_TCP_KEEPALIVE + case TCP_KEEPIDLE: + *(int*)optval = (int)(sock->conn->pcb.tcp->keep_idle/1000); + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, IPPROTO_TCP, TCP_KEEPIDLE) = %d\n", + s, *(int *)optval)); + break; + case TCP_KEEPINTVL: + *(int*)optval = (int)(sock->conn->pcb.tcp->keep_intvl/1000); + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, IPPROTO_TCP, TCP_KEEPINTVL) = %d\n", + s, *(int *)optval)); + break; + case TCP_KEEPCNT: + *(int*)optval = (int)sock->conn->pcb.tcp->keep_cnt; + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, IPPROTO_TCP, TCP_KEEPCNT) = %d\n", + s, *(int *)optval)); + break; +#endif /* LWIP_TCP_KEEPALIVE */ + default: + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, IPPROTO_TCP, UNIMPL: optname=0x%x, ..)\n", + s, optname)); + err = ENOPROTOOPT; + break; + } /* switch (optname) */ + break; +#endif /* LWIP_TCP */ + +#if LWIP_IPV6 +/* Level: IPPROTO_IPV6 */ + case IPPROTO_IPV6: + switch (optname) { + case IPV6_V6ONLY: + LWIP_SOCKOPT_CHECK_OPTLEN_CONN(sock, *optlen, int); + /* @todo: this does not work for datagram sockets, yet */ + if (NETCONNTYPE_GROUP(netconn_type(sock->conn)) != NETCONN_TCP) { + return ENOPROTOOPT; + } + *(int*)optval = (netconn_get_ipv6only(sock->conn) ? 1 : 0); + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, IPPROTO_IPV6, IPV6_V6ONLY) = %d\n", + s, *(int *)optval)); + break; + default: + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, IPPROTO_IPV6, UNIMPL: optname=0x%x, ..)\n", + s, optname)); + err = ENOPROTOOPT; + break; + } /* switch (optname) */ + break; +#endif /* LWIP_IPV6 */ + +#if LWIP_UDP && LWIP_UDPLITE + /* Level: IPPROTO_UDPLITE */ + case IPPROTO_UDPLITE: + /* Special case: all IPPROTO_UDPLITE option take an int */ + LWIP_SOCKOPT_CHECK_OPTLEN_CONN_PCB(sock, *optlen, int); + /* If this is no UDP lite socket, ignore any options. */ + if (!NETCONNTYPE_ISUDPLITE(netconn_type(sock->conn))) { + return ENOPROTOOPT; + } + switch (optname) { + case UDPLITE_SEND_CSCOV: + *(int*)optval = sock->conn->pcb.udp->chksum_len_tx; + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, IPPROTO_UDPLITE, UDPLITE_SEND_CSCOV) = %d\n", + s, (*(int*)optval)) ); + break; + case UDPLITE_RECV_CSCOV: + *(int*)optval = sock->conn->pcb.udp->chksum_len_rx; + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, IPPROTO_UDPLITE, UDPLITE_RECV_CSCOV) = %d\n", + s, (*(int*)optval)) ); + break; + default: + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, IPPROTO_UDPLITE, UNIMPL: optname=0x%x, ..)\n", + s, optname)); + err = ENOPROTOOPT; + break; + } /* switch (optname) */ + break; +#endif /* LWIP_UDP */ + /* Level: IPPROTO_RAW */ + case IPPROTO_RAW: + switch (optname) { +#if LWIP_IPV6 && LWIP_RAW + case IPV6_CHECKSUM: + LWIP_SOCKOPT_CHECK_OPTLEN_CONN_PCB_TYPE(sock, *optlen, int, NETCONN_RAW); + if (sock->conn->pcb.raw->chksum_reqd == 0) { + *(int *)optval = -1; + } else { + *(int *)optval = sock->conn->pcb.raw->chksum_offset; + } + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, IPPROTO_RAW, IPV6_CHECKSUM) = %d\n", + s, (*(int*)optval)) ); + break; +#endif /* LWIP_IPV6 && LWIP_RAW */ + default: + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, IPPROTO_RAW, UNIMPL: optname=0x%x, ..)\n", + s, optname)); + err = ENOPROTOOPT; + break; + } /* switch (optname) */ + break; + default: + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, level=0x%x, UNIMPL: optname=0x%x, ..)\n", + s, level, optname)); + err = ENOPROTOOPT; + break; + } /* switch (level) */ + + return err; +} + +int +lwip_setsockopt(int s, int level, int optname, const void *optval, socklen_t optlen) +{ + u8_t err = 0; + struct lwip_sock *sock = get_socket(s); +#if !LWIP_TCPIP_CORE_LOCKING + LWIP_SETGETSOCKOPT_DATA_VAR_DECLARE(data); +#endif /* !LWIP_TCPIP_CORE_LOCKING */ + + if (!sock) { + return -1; + } + + if (NULL == optval) { + sock_set_errno(sock, EFAULT); + return -1; + } + +#if LWIP_TCPIP_CORE_LOCKING + /* core-locking can just call the -impl function */ + LOCK_TCPIP_CORE(); + err = lwip_setsockopt_impl(s, level, optname, optval, optlen); + UNLOCK_TCPIP_CORE(); + +#else /* LWIP_TCPIP_CORE_LOCKING */ + +#if LWIP_MPU_COMPATIBLE + /* MPU_COMPATIBLE copies the optval data, so check for max size here */ + if (optlen > LWIP_SETGETSOCKOPT_MAXOPTLEN) { + sock_set_errno(sock, ENOBUFS); + return -1; + } +#endif /* LWIP_MPU_COMPATIBLE */ + + LWIP_SETGETSOCKOPT_DATA_VAR_ALLOC(data, sock); + LWIP_SETGETSOCKOPT_DATA_VAR_REF(data).s = s; + LWIP_SETGETSOCKOPT_DATA_VAR_REF(data).level = level; + LWIP_SETGETSOCKOPT_DATA_VAR_REF(data).optname = optname; + LWIP_SETGETSOCKOPT_DATA_VAR_REF(data).optlen = optlen; +#if LWIP_MPU_COMPATIBLE + memcpy(LWIP_SETGETSOCKOPT_DATA_VAR_REF(data).optval, optval, optlen); +#else /* LWIP_MPU_COMPATIBLE */ + LWIP_SETGETSOCKOPT_DATA_VAR_REF(data).optval.pc = (const void*)optval; +#endif /* LWIP_MPU_COMPATIBLE */ + LWIP_SETGETSOCKOPT_DATA_VAR_REF(data).err = 0; +#if LWIP_NETCONN_SEM_PER_THREAD + LWIP_SETGETSOCKOPT_DATA_VAR_REF(data).completed_sem = LWIP_NETCONN_THREAD_SEM_GET(); +#else + LWIP_SETGETSOCKOPT_DATA_VAR_REF(data).completed_sem = &sock->conn->op_completed; +#endif + err = tcpip_callback(lwip_setsockopt_callback, &LWIP_SETGETSOCKOPT_DATA_VAR_REF(data)); + if (err != ERR_OK) { + LWIP_SETGETSOCKOPT_DATA_VAR_FREE(data); + sock_set_errno(sock, err_to_errno(err)); + return -1; + } + sys_arch_sem_wait((sys_sem_t*)(LWIP_SETGETSOCKOPT_DATA_VAR_REF(data).completed_sem), 0); + + /* maybe lwip_getsockopt_internal has changed err */ + err = LWIP_SETGETSOCKOPT_DATA_VAR_REF(data).err; + LWIP_SETGETSOCKOPT_DATA_VAR_FREE(data); +#endif /* LWIP_TCPIP_CORE_LOCKING */ + + sock_set_errno(sock, err); + return err ? -1 : 0; +} + +#if !LWIP_TCPIP_CORE_LOCKING +/** lwip_setsockopt_callback: only used without CORE_LOCKING + * to get into the tcpip_thread + */ +static void +lwip_setsockopt_callback(void *arg) +{ + struct lwip_setgetsockopt_data *data; + LWIP_ASSERT("arg != NULL", arg != NULL); + data = (struct lwip_setgetsockopt_data*)arg; + + data->err = lwip_setsockopt_impl(data->s, data->level, data->optname, +#if LWIP_MPU_COMPATIBLE + data->optval, +#else /* LWIP_MPU_COMPATIBLE */ + data->optval.pc, +#endif /* LWIP_MPU_COMPATIBLE */ + data->optlen); + + sys_sem_signal((sys_sem_t*)(data->completed_sem)); +} +#endif /* LWIP_TCPIP_CORE_LOCKING */ + +/** lwip_setsockopt_impl: the actual implementation of setsockopt: + * same argument as lwip_setsockopt, either called directly or through callback + */ +static u8_t +lwip_setsockopt_impl(int s, int level, int optname, const void *optval, socklen_t optlen) +{ + u8_t err = 0; + struct lwip_sock *sock = tryget_socket(s); + if (!sock) { + return EBADF; + } + + switch (level) { + +/* Level: SOL_SOCKET */ + case SOL_SOCKET: + switch (optname) { + + /* SO_ACCEPTCONN is get-only */ + + /* The option flags */ + case SO_BROADCAST: + case SO_KEEPALIVE: +#if SO_REUSE + case SO_REUSEADDR: +#endif /* SO_REUSE */ + LWIP_SOCKOPT_CHECK_OPTLEN_CONN_PCB(sock, optlen, int); + if (*(const int*)optval) { + ip_set_option(sock->conn->pcb.ip, optname); + } else { + ip_reset_option(sock->conn->pcb.ip, optname); + } + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_setsockopt(%d, SOL_SOCKET, optname=0x%x, ..) -> %s\n", + s, optname, (*(const int*)optval?"on":"off"))); + break; + + /* SO_TYPE is get-only */ + /* SO_ERROR is get-only */ + +#if LWIP_SO_SNDTIMEO + case SO_SNDTIMEO: + LWIP_SOCKOPT_CHECK_OPTLEN_CONN(sock, optlen, LWIP_SO_SNDRCVTIMEO_OPTTYPE); + netconn_set_sendtimeout(sock->conn, LWIP_SO_SNDRCVTIMEO_GET_MS(optval)); + break; +#endif /* LWIP_SO_SNDTIMEO */ +#if LWIP_SO_RCVTIMEO + case SO_RCVTIMEO: + LWIP_SOCKOPT_CHECK_OPTLEN_CONN(sock, optlen, LWIP_SO_SNDRCVTIMEO_OPTTYPE); + netconn_set_recvtimeout(sock->conn, (int)LWIP_SO_SNDRCVTIMEO_GET_MS(optval)); + break; +#endif /* LWIP_SO_RCVTIMEO */ +#if LWIP_SO_RCVBUF + case SO_RCVBUF: + LWIP_SOCKOPT_CHECK_OPTLEN_CONN(sock, optlen, int); + netconn_set_recvbufsize(sock->conn, *(const int*)optval); + break; +#endif /* LWIP_SO_RCVBUF */ +#if LWIP_SO_LINGER + case SO_LINGER: + { + const struct linger* linger = (const struct linger*)optval; + LWIP_SOCKOPT_CHECK_OPTLEN_CONN(sock, optlen, struct linger); + if (linger->l_onoff) { + int lingersec = linger->l_linger; + if (lingersec < 0) { + return EINVAL; + } + if (lingersec > 0xFFFF) { + lingersec = 0xFFFF; + } + sock->conn->linger = (s16_t)lingersec; + } else { + sock->conn->linger = -1; + } + } + break; +#endif /* LWIP_SO_LINGER */ +#if LWIP_UDP + case SO_NO_CHECK: + LWIP_SOCKOPT_CHECK_OPTLEN_CONN_PCB_TYPE(sock, optlen, int, NETCONN_UDP); +#if LWIP_UDPLITE + if ((udp_flags(sock->conn->pcb.udp) & UDP_FLAGS_UDPLITE) != 0) { + /* this flag is only available for UDP, not for UDP lite */ + return EAFNOSUPPORT; + } +#endif /* LWIP_UDPLITE */ + if (*(const int*)optval) { + udp_setflags(sock->conn->pcb.udp, udp_flags(sock->conn->pcb.udp) | UDP_FLAGS_NOCHKSUM); + } else { + udp_setflags(sock->conn->pcb.udp, udp_flags(sock->conn->pcb.udp) & ~UDP_FLAGS_NOCHKSUM); + } + break; +#endif /* LWIP_UDP */ + default: + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_setsockopt(%d, SOL_SOCKET, UNIMPL: optname=0x%x, ..)\n", + s, optname)); + err = ENOPROTOOPT; + break; + } /* switch (optname) */ + break; + +/* Level: IPPROTO_IP */ + case IPPROTO_IP: + switch (optname) { + case IP_TTL: + LWIP_SOCKOPT_CHECK_OPTLEN_CONN_PCB(sock, optlen, int); + sock->conn->pcb.ip->ttl = (u8_t)(*(const int*)optval); + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_setsockopt(%d, IPPROTO_IP, IP_TTL, ..) -> %d\n", + s, sock->conn->pcb.ip->ttl)); + break; + case IP_TOS: + LWIP_SOCKOPT_CHECK_OPTLEN_CONN_PCB(sock, optlen, int); + sock->conn->pcb.ip->tos = (u8_t)(*(const int*)optval); + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_setsockopt(%d, IPPROTO_IP, IP_TOS, ..)-> %d\n", + s, sock->conn->pcb.ip->tos)); + break; +#if LWIP_MULTICAST_TX_OPTIONS + case IP_MULTICAST_TTL: + LWIP_SOCKOPT_CHECK_OPTLEN_CONN_PCB_TYPE(sock, optlen, u8_t, NETCONN_UDP); + sock->conn->pcb.udp->mcast_ttl = (u8_t)(*(const u8_t*)optval); + break; + case IP_MULTICAST_IF: + { + ip4_addr_t if_addr; + LWIP_SOCKOPT_CHECK_OPTLEN_CONN_PCB_TYPE(sock, optlen, struct in_addr, NETCONN_UDP); + inet_addr_to_ipaddr(&if_addr, (const struct in_addr*)optval); + udp_set_multicast_netif_addr(sock->conn->pcb.udp, &if_addr); + } + break; + case IP_MULTICAST_LOOP: + LWIP_SOCKOPT_CHECK_OPTLEN_CONN_PCB_TYPE(sock, optlen, u8_t, NETCONN_UDP); + if (*(const u8_t*)optval) { + udp_setflags(sock->conn->pcb.udp, udp_flags(sock->conn->pcb.udp) | UDP_FLAGS_MULTICAST_LOOP); + } else { + udp_setflags(sock->conn->pcb.udp, udp_flags(sock->conn->pcb.udp) & ~UDP_FLAGS_MULTICAST_LOOP); + } + break; +#endif /* LWIP_MULTICAST_TX_OPTIONS */ +#if LWIP_IGMP + case IP_ADD_MEMBERSHIP: + case IP_DROP_MEMBERSHIP: + { + /* If this is a TCP or a RAW socket, ignore these options. */ + /* @todo: assign membership to this socket so that it is dropped when state the socket */ + err_t igmp_err; + const struct ip_mreq *imr = (const struct ip_mreq *)optval; + ip4_addr_t if_addr; + ip4_addr_t multi_addr; + LWIP_SOCKOPT_CHECK_OPTLEN_CONN_PCB_TYPE(sock, optlen, struct ip_mreq, NETCONN_UDP); + inet_addr_to_ipaddr(&if_addr, &imr->imr_interface); + inet_addr_to_ipaddr(&multi_addr, &imr->imr_multiaddr); + if (optname == IP_ADD_MEMBERSHIP) { + if (!lwip_socket_register_membership(s, &if_addr, &multi_addr)) { + /* cannot track membership (out of memory) */ + err = ENOMEM; + igmp_err = ERR_OK; + } else { + igmp_err = igmp_joingroup(&if_addr, &multi_addr); + } + } else { + igmp_err = igmp_leavegroup(&if_addr, &multi_addr); + lwip_socket_unregister_membership(s, &if_addr, &multi_addr); + } + if (igmp_err != ERR_OK) { + err = EADDRNOTAVAIL; + } + } + break; +#endif /* LWIP_IGMP */ + default: + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_setsockopt(%d, IPPROTO_IP, UNIMPL: optname=0x%x, ..)\n", + s, optname)); + err = ENOPROTOOPT; + break; + } /* switch (optname) */ + break; + +#if LWIP_TCP +/* Level: IPPROTO_TCP */ + case IPPROTO_TCP: + /* Special case: all IPPROTO_TCP option take an int */ + LWIP_SOCKOPT_CHECK_OPTLEN_CONN_PCB_TYPE(sock, optlen, int, NETCONN_TCP); + switch (optname) { + case TCP_NODELAY: + if (*(const int*)optval) { + tcp_nagle_disable(sock->conn->pcb.tcp); + } else { + tcp_nagle_enable(sock->conn->pcb.tcp); + } + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_setsockopt(%d, IPPROTO_TCP, TCP_NODELAY) -> %s\n", + s, (*(const int *)optval)?"on":"off") ); + break; + case TCP_KEEPALIVE: + sock->conn->pcb.tcp->keep_idle = (u32_t)(*(const int*)optval); + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_setsockopt(%d, IPPROTO_TCP, TCP_KEEPALIVE) -> %"U32_F"\n", + s, sock->conn->pcb.tcp->keep_idle)); + break; + +#if LWIP_TCP_KEEPALIVE + case TCP_KEEPIDLE: + sock->conn->pcb.tcp->keep_idle = 1000*(u32_t)(*(const int*)optval); + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_setsockopt(%d, IPPROTO_TCP, TCP_KEEPIDLE) -> %"U32_F"\n", + s, sock->conn->pcb.tcp->keep_idle)); + break; + case TCP_KEEPINTVL: + sock->conn->pcb.tcp->keep_intvl = 1000*(u32_t)(*(const int*)optval); + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_setsockopt(%d, IPPROTO_TCP, TCP_KEEPINTVL) -> %"U32_F"\n", + s, sock->conn->pcb.tcp->keep_intvl)); + break; + case TCP_KEEPCNT: + sock->conn->pcb.tcp->keep_cnt = (u32_t)(*(const int*)optval); + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_setsockopt(%d, IPPROTO_TCP, TCP_KEEPCNT) -> %"U32_F"\n", + s, sock->conn->pcb.tcp->keep_cnt)); + break; +#endif /* LWIP_TCP_KEEPALIVE */ + default: + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_setsockopt(%d, IPPROTO_TCP, UNIMPL: optname=0x%x, ..)\n", + s, optname)); + err = ENOPROTOOPT; + break; + } /* switch (optname) */ + break; +#endif /* LWIP_TCP*/ + +#if LWIP_IPV6 +/* Level: IPPROTO_IPV6 */ + case IPPROTO_IPV6: + switch (optname) { + case IPV6_V6ONLY: + /* @todo: this does not work for datagram sockets, yet */ + LWIP_SOCKOPT_CHECK_OPTLEN_CONN_PCB_TYPE(sock, optlen, int, NETCONN_TCP); + if (*(const int*)optval) { + netconn_set_ipv6only(sock->conn, 1); + } else { + netconn_set_ipv6only(sock->conn, 0); + } + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_setsockopt(%d, IPPROTO_IPV6, IPV6_V6ONLY, ..) -> %d\n", + s, (netconn_get_ipv6only(sock->conn) ? 1 : 0))); + break; + default: + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_setsockopt(%d, IPPROTO_IPV6, UNIMPL: optname=0x%x, ..)\n", + s, optname)); + err = ENOPROTOOPT; + break; + } /* switch (optname) */ + break; +#endif /* LWIP_IPV6 */ + +#if LWIP_UDP && LWIP_UDPLITE + /* Level: IPPROTO_UDPLITE */ + case IPPROTO_UDPLITE: + /* Special case: all IPPROTO_UDPLITE option take an int */ + LWIP_SOCKOPT_CHECK_OPTLEN_CONN_PCB(sock, optlen, int); + /* If this is no UDP lite socket, ignore any options. */ + if (!NETCONNTYPE_ISUDPLITE(netconn_type(sock->conn))) { + return ENOPROTOOPT; + } + switch (optname) { + case UDPLITE_SEND_CSCOV: + if ((*(const int*)optval != 0) && ((*(const int*)optval < 8) || (*(const int*)optval > 0xffff))) { + /* don't allow illegal values! */ + sock->conn->pcb.udp->chksum_len_tx = 8; + } else { + sock->conn->pcb.udp->chksum_len_tx = (u16_t)*(const int*)optval; + } + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_setsockopt(%d, IPPROTO_UDPLITE, UDPLITE_SEND_CSCOV) -> %d\n", + s, (*(const int*)optval)) ); + break; + case UDPLITE_RECV_CSCOV: + if ((*(const int*)optval != 0) && ((*(const int*)optval < 8) || (*(const int*)optval > 0xffff))) { + /* don't allow illegal values! */ + sock->conn->pcb.udp->chksum_len_rx = 8; + } else { + sock->conn->pcb.udp->chksum_len_rx = (u16_t)*(const int*)optval; + } + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_setsockopt(%d, IPPROTO_UDPLITE, UDPLITE_RECV_CSCOV) -> %d\n", + s, (*(const int*)optval)) ); + break; + default: + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_setsockopt(%d, IPPROTO_UDPLITE, UNIMPL: optname=0x%x, ..)\n", + s, optname)); + err = ENOPROTOOPT; + break; + } /* switch (optname) */ + break; +#endif /* LWIP_UDP */ + /* Level: IPPROTO_RAW */ + case IPPROTO_RAW: + switch (optname) { +#if LWIP_IPV6 && LWIP_RAW + case IPV6_CHECKSUM: + LWIP_SOCKOPT_CHECK_OPTLEN_CONN_PCB_TYPE(sock, optlen, int, NETCONN_RAW); + if (*(const int *)optval < 0) { + sock->conn->pcb.raw->chksum_reqd = 0; + } else if (*(const int *)optval & 1) { + /* Per RFC3542, odd offsets are not allowed */ + return EINVAL; + } else { + sock->conn->pcb.raw->chksum_reqd = 1; + sock->conn->pcb.raw->chksum_offset = (u16_t)*(const int *)optval; + } + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_setsockopt(%d, IPPROTO_RAW, IPV6_CHECKSUM, ..) -> %d\n", + s, sock->conn->pcb.raw->chksum_reqd)); + break; +#endif /* LWIP_IPV6 && LWIP_RAW */ + default: + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_setsockopt(%d, IPPROTO_RAW, UNIMPL: optname=0x%x, ..)\n", + s, optname)); + err = ENOPROTOOPT; + break; + } /* switch (optname) */ + break; + default: + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_setsockopt(%d, level=0x%x, UNIMPL: optname=0x%x, ..)\n", + s, level, optname)); + err = ENOPROTOOPT; + break; + } /* switch (level) */ + + return err; +} + +int +lwip_ioctl(int s, long cmd, void *argp) +{ + struct lwip_sock *sock = get_socket(s); + u8_t val; +#if LWIP_SO_RCVBUF + u16_t buflen = 0; + int recv_avail; +#endif /* LWIP_SO_RCVBUF */ + + if (!sock) { + return -1; + } + + switch (cmd) { +#if LWIP_SO_RCVBUF || LWIP_FIONREAD_LINUXMODE + case FIONREAD: + if (!argp) { + sock_set_errno(sock, EINVAL); + return -1; + } +#if LWIP_FIONREAD_LINUXMODE + if (NETCONNTYPE_GROUP(netconn_type(sock->conn)) != NETCONN_TCP) { + struct pbuf *p; + if (sock->lastdata) { + p = ((struct netbuf *)sock->lastdata)->p; + *((int*)argp) = p->tot_len - sock->lastoffset; + } else { + struct netbuf *rxbuf; + err_t err; + if (sock->rcvevent <= 0) { + *((int*)argp) = 0; + } else { + err = netconn_recv(sock->conn, &rxbuf); + if (err != ERR_OK) { + *((int*)argp) = 0; + } else { + sock->lastdata = rxbuf; + sock->lastoffset = 0; + *((int*)argp) = rxbuf->p->tot_len; + } + } + } + return 0; + } +#endif /* LWIP_FIONREAD_LINUXMODE */ + +#if LWIP_SO_RCVBUF + /* we come here if either LWIP_FIONREAD_LINUXMODE==0 or this is a TCP socket */ + SYS_ARCH_GET(sock->conn->recv_avail, recv_avail); + if (recv_avail < 0) { + recv_avail = 0; + } + *((int*)argp) = recv_avail; + + /* Check if there is data left from the last recv operation. /maq 041215 */ + if (sock->lastdata) { + struct pbuf *p = (struct pbuf *)sock->lastdata; + if (NETCONNTYPE_GROUP(netconn_type(sock->conn)) != NETCONN_TCP) { + p = ((struct netbuf *)p)->p; + } + buflen = p->tot_len; + buflen -= sock->lastoffset; + + *((int*)argp) += buflen; + } + + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_ioctl(%d, FIONREAD, %p) = %"U16_F"\n", s, argp, *((u16_t*)argp))); + sock_set_errno(sock, 0); + return 0; +#else /* LWIP_SO_RCVBUF */ + break; +#endif /* LWIP_SO_RCVBUF */ +#endif /* LWIP_SO_RCVBUF || LWIP_FIONREAD_LINUXMODE */ + + case (long)FIONBIO: + val = 0; + if (argp && *(u32_t*)argp) { + val = 1; + } + netconn_set_nonblocking(sock->conn, val); + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_ioctl(%d, FIONBIO, %d)\n", s, val)); + sock_set_errno(sock, 0); + return 0; + + default: + break; + } /* switch (cmd) */ + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_ioctl(%d, UNIMPL: 0x%lx, %p)\n", s, cmd, argp)); + sock_set_errno(sock, ENOSYS); /* not yet implemented */ + return -1; +} + +/** A minimal implementation of fcntl. + * Currently only the commands F_GETFL and F_SETFL are implemented. + * Only the flag O_NONBLOCK is implemented. + */ +int +lwip_fcntl(int s, int cmd, int val) +{ + struct lwip_sock *sock = get_socket(s); + int ret = -1; + + if (!sock) { + return -1; + } + + switch (cmd) { + case F_GETFL: + ret = netconn_is_nonblocking(sock->conn) ? O_NONBLOCK : 0; + sock_set_errno(sock, 0); + break; + case F_SETFL: + if ((val & ~O_NONBLOCK) == 0) { + /* only O_NONBLOCK, all other bits are zero */ + netconn_set_nonblocking(sock->conn, val & O_NONBLOCK); + ret = 0; + sock_set_errno(sock, 0); + } else { + sock_set_errno(sock, ENOSYS); /* not yet implemented */ + } + break; + default: + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_fcntl(%d, UNIMPL: %d, %d)\n", s, cmd, val)); + sock_set_errno(sock, ENOSYS); /* not yet implemented */ + break; + } + return ret; +} + +#if LWIP_IGMP +/** Register a new IGMP membership. On socket close, the membership is dropped automatically. + * + * ATTENTION: this function is called from tcpip_thread (or under CORE_LOCK). + * + * @return 1 on success, 0 on failure + */ +static int +lwip_socket_register_membership(int s, const ip4_addr_t *if_addr, const ip4_addr_t *multi_addr) +{ + /* s+1 is stored in the array to prevent having to initialize the array + (default initialization is to 0) */ + int sa = s + 1; + int i; + + for (i = 0; i < LWIP_SOCKET_MAX_MEMBERSHIPS; i++) { + if (socket_ipv4_multicast_memberships[i].sa == 0) { + socket_ipv4_multicast_memberships[i].sa = sa; + ip4_addr_copy(socket_ipv4_multicast_memberships[i].if_addr, *if_addr); + ip4_addr_copy(socket_ipv4_multicast_memberships[i].multi_addr, *multi_addr); + return 1; + } + } + return 0; +} + +/** Unregister a previously registered membership. This prevents dropping the membership + * on socket close. + * + * ATTENTION: this function is called from tcpip_thread (or under CORE_LOCK). + */ +static void +lwip_socket_unregister_membership(int s, const ip4_addr_t *if_addr, const ip4_addr_t *multi_addr) +{ + /* s+1 is stored in the array to prevent having to initialize the array + (default initialization is to 0) */ + int sa = s + 1; + int i; + + for (i = 0; i < LWIP_SOCKET_MAX_MEMBERSHIPS; i++) { + if ((socket_ipv4_multicast_memberships[i].sa == sa) && + ip4_addr_cmp(&socket_ipv4_multicast_memberships[i].if_addr, if_addr) && + ip4_addr_cmp(&socket_ipv4_multicast_memberships[i].multi_addr, multi_addr)) { + socket_ipv4_multicast_memberships[i].sa = 0; + ip4_addr_set_zero(&socket_ipv4_multicast_memberships[i].if_addr); + ip4_addr_set_zero(&socket_ipv4_multicast_memberships[i].multi_addr); + return; + } + } +} + +/** Drop all memberships of a socket that were not dropped explicitly via setsockopt. + * + * ATTENTION: this function is NOT called from tcpip_thread (or under CORE_LOCK). + */ +static void lwip_socket_drop_registered_memberships(int s) +{ + /* s+1 is stored in the array to prevent having to initialize the array + (default initialization is to 0) */ + int sa = s + 1; + int i; + + LWIP_ASSERT("socket has no netconn", sockets[s].conn != NULL); + + for (i = 0; i < LWIP_SOCKET_MAX_MEMBERSHIPS; i++) { + if (socket_ipv4_multicast_memberships[i].sa == sa) { + ip_addr_t multi_addr, if_addr; + ip_addr_copy_from_ip4(multi_addr, socket_ipv4_multicast_memberships[i].multi_addr); + ip_addr_copy_from_ip4(if_addr, socket_ipv4_multicast_memberships[i].if_addr); + socket_ipv4_multicast_memberships[i].sa = 0; + ip4_addr_set_zero(&socket_ipv4_multicast_memberships[i].if_addr); + ip4_addr_set_zero(&socket_ipv4_multicast_memberships[i].multi_addr); + + netconn_join_leave_group(sockets[s].conn, &multi_addr, &if_addr, NETCONN_LEAVE); + } + } +} +#endif /* LWIP_IGMP */ + +#if LWIP_THREAD_SAFE + +int +lwip_sendto_r(int s, const void *data, size_t size, int flags, + const struct sockaddr *to, socklen_t tolen) +{ + LWIP_API_LOCK(); + __ret = lwip_sendto(s, data, size, flags, to, tolen); + LWIP_API_UNLOCK(); +} + +int +lwip_send_r(int s, const void *data, size_t size, int flags) +{ + LWIP_API_LOCK(); + __ret = lwip_send(s, data, size, flags); + LWIP_API_UNLOCK(); +} + +int +lwip_recvfrom_r(int s, void *mem, size_t len, int flags, + struct sockaddr *from, socklen_t *fromlen) +{ + LWIP_API_LOCK(); + __ret = lwip_recvfrom(s, mem, len, flags, from, fromlen); + LWIP_API_UNLOCK(); +} + +int +lwip_recv_r(int s, void *mem, size_t len, int flags) +{ + return lwip_recvfrom_r(s, mem, len, flags, NULL, NULL); +} + +int +lwip_read_r(int s, void *mem, size_t len) +{ + return lwip_recvfrom_r(s, mem, len, 0, NULL, NULL); +} + +int +lwip_sendmsg_r(int s, const struct msghdr *msg, int flags) +{ + LWIP_API_LOCK(); + __ret = lwip_sendmsg(s, msg, flags); + LWIP_API_UNLOCK(); +} + +int +lwip_write_r(int s, const void *data, size_t size) +{ + return lwip_send_r(s, data, size, 0); +} + +int +lwip_writev_r(int s, const struct iovec *iov, int iovcnt) +{ + struct msghdr msg; + + msg.msg_name = NULL; + msg.msg_namelen = 0; + /* Hack: we have to cast via number to cast from 'const' pointer to non-const. + Blame the opengroup standard for this inconsistency. */ + msg.msg_iov = (struct iovec *)(size_t)iov; + msg.msg_iovlen = iovcnt; + msg.msg_control = NULL; + msg.msg_controllen = 0; + msg.msg_flags = 0; + return lwip_sendmsg_r(s, &msg, 0); +} + +int +lwip_connect_r(int s, const struct sockaddr *name, socklen_t namelen) +{ + LWIP_API_LOCK(); + __ret = lwip_connect(s, name, namelen); + LWIP_API_UNLOCK(); +} + +int +lwip_listen_r(int s, int backlog) +{ + LWIP_API_LOCK(); + __ret = lwip_listen(s, backlog); + LWIP_API_UNLOCK(); +} + +int +lwip_bind_r(int s, const struct sockaddr *name, socklen_t namelen) +{ + LWIP_API_LOCK(); + __ret = lwip_bind(s, name, namelen); + LWIP_API_UNLOCK(); +} + +int +lwip_accept_r(int s, struct sockaddr *addr, socklen_t *addrlen) +{ + LWIP_API_LOCK(); + __ret = lwip_accept(s, addr, addrlen); + LWIP_API_UNLOCK(); +} + +int +lwip_ioctl_r(int s, long cmd, void *argp) +{ + LWIP_API_LOCK(); + __ret = lwip_ioctl(s, cmd, argp); + LWIP_API_UNLOCK(); +} + +int +lwip_fcntl_r(int s, int cmd, int val) +{ + LWIP_API_LOCK(); + __ret = lwip_fcntl(s, cmd, val); + LWIP_API_UNLOCK(); +} + +int +lwip_setsockopt_r(int s, int level, int optname, const void *optval, socklen_t optlen) +{ + LWIP_API_LOCK(); + __ret = lwip_setsockopt(s, level, optname, optval, optlen); + LWIP_API_UNLOCK(); +} + +int +lwip_getsockopt_r(int s, int level, int optname, void *optval, socklen_t *optlen) +{ + LWIP_API_LOCK(); + __ret = lwip_getsockopt(s, level, optname, optval, optlen); + LWIP_API_UNLOCK(); +} + +int +lwip_getpeername_r(int s, struct sockaddr *name, socklen_t *namelen) +{ + LWIP_API_LOCK(); + __ret = lwip_getpeername(s, name, namelen); + LWIP_API_UNLOCK(); +} + +int +lwip_getsockname_r(int s, struct sockaddr *name, socklen_t *namelen) +{ + LWIP_API_LOCK(); + __ret = lwip_getsockname(s, name, namelen); + LWIP_API_UNLOCK(); +} + +int +lwip_close_r(int s) +{ + LWIP_API_LOCK(); + LWIP_SET_CLOSE_FLAG(); + __ret = lwip_close(s); + LWIP_API_UNLOCK(); +} + +int +lwip_shutdown_r(int s, int how) +{ + LWIP_API_LOCK(); + __ret = lwip_shutdown(s, how); + LWIP_API_UNLOCK(); +} + +#endif + +#endif /* LWIP_SOCKET */ diff --git a/components/lwip/api/tcpip.c b/components/lwip/api/tcpip.c new file mode 100755 index 0000000000..f0c4c476e7 --- /dev/null +++ b/components/lwip/api/tcpip.c @@ -0,0 +1,569 @@ +/** + * @file + * Sequential API Main thread module + * + */ + +/* + * Copyright (c) 2001-2004 Swedish Institute of Computer Science. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + * + */ + +#include "lwip/opt.h" + +#if !NO_SYS /* don't build if not configured for use in lwipopts.h */ + +#include "lwip/priv/tcpip_priv.h" +#include "lwip/priv/api_msg.h" +#include "lwip/sys.h" +#include "lwip/memp.h" +#include "lwip/mem.h" +#include "lwip/init.h" +#include "lwip/ip.h" +#include "lwip/pbuf.h" +#include "netif/etharp.h" + +#ifdef MEMLEAK_DEBUG +static const char mem_debug_file[] ICACHE_RODATA_ATTR STORE_ATTR = __FILE__; +#endif + + +#define TCPIP_MSG_VAR_REF(name) API_VAR_REF(name) +#define TCPIP_MSG_VAR_DECLARE(name) API_VAR_DECLARE(struct tcpip_msg, name) +#define TCPIP_MSG_VAR_ALLOC(name) API_VAR_ALLOC(struct tcpip_msg, MEMP_TCPIP_MSG_API, name) +#define TCPIP_MSG_VAR_FREE(name) API_VAR_FREE(MEMP_TCPIP_MSG_API, name) + +/* global variables */ +#ifdef PERF +uint32 g_rx_post_mbox_fail_cnt = 0; +#endif +static tcpip_init_done_fn tcpip_init_done; +static void *tcpip_init_done_arg; +static sys_mbox_t mbox; + +#if LWIP_TCPIP_CORE_LOCKING +/** The global semaphore to lock the stack. */ +sys_mutex_t lock_tcpip_core; +#endif /* LWIP_TCPIP_CORE_LOCKING */ + + +/** + * The main lwIP thread. This thread has exclusive access to lwIP core functions + * (unless access to them is not locked). Other threads communicate with this + * thread using message boxes. + * + * It also starts all the timers to make sure they are running in the right + * thread context. + * + * @param arg unused argument + */ +static void +tcpip_thread(void *arg) +{ + + + struct tcpip_msg *msg; + LWIP_UNUSED_ARG(arg); + + if (tcpip_init_done != NULL) { + tcpip_init_done(tcpip_init_done_arg); + } + + + + LOCK_TCPIP_CORE(); + while (1) { + + + /* MAIN Loop */ + UNLOCK_TCPIP_CORE(); + LWIP_TCPIP_THREAD_ALIVE(); + /* wait for a message, timeouts are processed while waiting */ + sys_timeouts_mbox_fetch(&mbox, (void **)&msg); + LOCK_TCPIP_CORE(); + + + + if (msg == NULL) { + LWIP_DEBUGF(TCPIP_DEBUG, ("tcpip_thread: invalid message: NULL\n")); + LWIP_ASSERT("tcpip_thread: invalid message", 0); + + continue; + } + + + + + switch (msg->type) { +#if !LWIP_TCPIP_CORE_LOCKING + case TCPIP_MSG_API: + + LWIP_DEBUGF(TCPIP_DEBUG, ("tcpip_thread: API message %p\n", (void *)msg)); + msg->msg.api.function(msg->msg.api.msg); + break; + case TCPIP_MSG_API_CALL: + + LWIP_DEBUGF(TCPIP_DEBUG, ("tcpip_thread: API CALL message %p\n", (void *)msg)); + msg->msg.api_call->err = msg->msg.api_call->function(msg->msg.api_call); +#if LWIP_NETCONN_SEM_PER_THREAD + sys_sem_signal(msg->msg.api_call->sem); +#else /* LWIP_NETCONN_SEM_PER_THREAD */ + sys_sem_signal(&msg->msg.api_call->sem); +#endif /* LWIP_NETCONN_SEM_PER_THREAD */ + break; +#endif /* LWIP_TCPIP_CORE_LOCKING */ + +#if !LWIP_TCPIP_CORE_LOCKING_INPUT + case TCPIP_MSG_INPKT: + LWIP_DEBUGF(TCPIP_DEBUG, ("tcpip_thread: PACKET %p\n", (void *)msg)); + +#ifdef LWIP_ESP8266 +//#if 0 + if(msg->msg.inp.p != NULL && msg->msg.inp.netif != NULL) { +#endif + msg->msg.inp.input_fn(msg->msg.inp.p, msg->msg.inp.netif); +#ifdef LWIP_ESP8266 +//#if 0 + } +#endif + + memp_free(MEMP_TCPIP_MSG_INPKT, msg); + + break; +#endif /* LWIP_TCPIP_CORE_LOCKING_INPUT */ + +#if LWIP_TCPIP_TIMEOUT + case TCPIP_MSG_TIMEOUT: + + LWIP_DEBUGF(TCPIP_DEBUG, ("tcpip_thread: TIMEOUT %p\n", (void *)msg)); + sys_timeout(msg->msg.tmo.msecs, msg->msg.tmo.h, msg->msg.tmo.arg); + memp_free(MEMP_TCPIP_MSG_API, msg); + break; + case TCPIP_MSG_UNTIMEOUT: + + LWIP_DEBUGF(TCPIP_DEBUG, ("tcpip_thread: UNTIMEOUT %p\n", (void *)msg)); + sys_untimeout(msg->msg.tmo.h, msg->msg.tmo.arg); + memp_free(MEMP_TCPIP_MSG_API, msg); + break; +#endif /* LWIP_TCPIP_TIMEOUT */ + + case TCPIP_MSG_CALLBACK: + + LWIP_DEBUGF(TCPIP_DEBUG, ("tcpip_thread: CALLBACK %p\n", (void *)msg)); + msg->msg.cb.function(msg->msg.cb.ctx); + memp_free(MEMP_TCPIP_MSG_API, msg); + break; + + case TCPIP_MSG_CALLBACK_STATIC: + + LWIP_DEBUGF(TCPIP_DEBUG, ("tcpip_thread: CALLBACK_STATIC %p\n", (void *)msg)); + msg->msg.cb.function(msg->msg.cb.ctx); + break; + + default: + + LWIP_DEBUGF(TCPIP_DEBUG, ("tcpip_thread: invalid message: %d\n", msg->type)); + LWIP_ASSERT("tcpip_thread: invalid message", 0); + break; + } + + } +} + +/** + * Pass a received packet to tcpip_thread for input processing + * + * @param p the received packet + * @param inp the network interface on which the packet was received + * @param input_fn input function to call + */ +err_t +tcpip_inpkt(struct pbuf *p, struct netif *inp, netif_input_fn input_fn) +{ +#if LWIP_TCPIP_CORE_LOCKING_INPUT + err_t ret; + LWIP_DEBUGF(TCPIP_DEBUG, ("tcpip_inpkt: PACKET %p/%p\n", (void *)p, (void *)inp)); + LOCK_TCPIP_CORE(); + ret = input_fn(p, inp); + UNLOCK_TCPIP_CORE(); + return ret; +#else /* LWIP_TCPIP_CORE_LOCKING_INPUT */ + struct tcpip_msg *msg; + + if (!sys_mbox_valid_val(mbox)) { + return ERR_VAL; + } + msg = (struct tcpip_msg *)memp_malloc(MEMP_TCPIP_MSG_INPKT); + if (msg == NULL) { + return ERR_MEM; + } + + msg->type = TCPIP_MSG_INPKT; + msg->msg.inp.p = p; + msg->msg.inp.netif = inp; + msg->msg.inp.input_fn = input_fn; + if (sys_mbox_trypost(&mbox, msg) != ERR_OK) { +#ifdef PERF + g_rx_post_mbox_fail_cnt ++; +#endif + memp_free(MEMP_TCPIP_MSG_INPKT, msg); + return ERR_MEM; + } + return ERR_OK; +#endif /* LWIP_TCPIP_CORE_LOCKING_INPUT */ +} + +/** + * Pass a received packet to tcpip_thread for input processing with + * ethernet_input or ip_input + * + * @param p the received packet, p->payload pointing to the Ethernet header or + * to an IP header (if inp doesn't have NETIF_FLAG_ETHARP or + * NETIF_FLAG_ETHERNET flags) + * @param inp the network interface on which the packet was received + */ +err_t +tcpip_input(struct pbuf *p, struct netif *inp) +{ +#if LWIP_ETHERNET + if (inp->flags & (NETIF_FLAG_ETHARP | NETIF_FLAG_ETHERNET)) { + return tcpip_inpkt(p, inp, ethernet_input); + } else +#endif /* LWIP_ETHERNET */ + return tcpip_inpkt(p, inp, ip_input); +} + +/** + * Call a specific function in the thread context of + * tcpip_thread for easy access synchronization. + * A function called in that way may access lwIP core code + * without fearing concurrent access. + * + * @param f the function to call + * @param ctx parameter passed to f + * @param block 1 to block until the request is posted, 0 to non-blocking mode + * @return ERR_OK if the function was called, another err_t if not + */ +err_t +tcpip_callback_with_block(tcpip_callback_fn function, void *ctx, u8_t block) +{ + struct tcpip_msg *msg; + + if (sys_mbox_valid_val(mbox)) { + msg = (struct tcpip_msg *)memp_malloc(MEMP_TCPIP_MSG_API); + if (msg == NULL) { + return ERR_MEM; + } + + msg->type = TCPIP_MSG_CALLBACK; + msg->msg.cb.function = function; + msg->msg.cb.ctx = ctx; + if (block) { + sys_mbox_post(&mbox, msg); + } else { + if (sys_mbox_trypost(&mbox, msg) != ERR_OK) { + memp_free(MEMP_TCPIP_MSG_API, msg); + return ERR_MEM; + } + } + return ERR_OK; + } + return ERR_VAL; +} + +#if LWIP_TCPIP_TIMEOUT +/** + * call sys_timeout in tcpip_thread + * + * @param msec time in milliseconds for timeout + * @param h function to be called on timeout + * @param arg argument to pass to timeout function h + * @return ERR_MEM on memory error, ERR_OK otherwise + */ +err_t +tcpip_timeout(u32_t msecs, sys_timeout_handler h, void *arg) +{ + struct tcpip_msg *msg; + + if (sys_mbox_valid_val(mbox)) { + msg = (struct tcpip_msg *)memp_malloc(MEMP_TCPIP_MSG_API); + if (msg == NULL) { + return ERR_MEM; + } + + msg->type = TCPIP_MSG_TIMEOUT; + msg->msg.tmo.msecs = msecs; + msg->msg.tmo.h = h; + msg->msg.tmo.arg = arg; + sys_mbox_post(&mbox, msg); + return ERR_OK; + } + return ERR_VAL; +} + +/** + * call sys_untimeout in tcpip_thread + * + * @param msec time in milliseconds for timeout + * @param h function to be called on timeout + * @param arg argument to pass to timeout function h + * @return ERR_MEM on memory error, ERR_OK otherwise + */ +err_t +tcpip_untimeout(sys_timeout_handler h, void *arg) +{ + struct tcpip_msg *msg; + + if (sys_mbox_valid_val(mbox)) { + msg = (struct tcpip_msg *)memp_malloc(MEMP_TCPIP_MSG_API); + if (msg == NULL) { + return ERR_MEM; + } + + msg->type = TCPIP_MSG_UNTIMEOUT; + msg->msg.tmo.h = h; + msg->msg.tmo.arg = arg; + sys_mbox_post(&mbox, msg); + return ERR_OK; + } + return ERR_VAL; +} +#endif /* LWIP_TCPIP_TIMEOUT */ + + +#if !LWIP_TCPIP_CORE_LOCKING +/** + * Generic way to dispatch an API message in TCPIP thread. + * + * @param fn function to be called from TCPIP thread + * @param apimsg argument to API function + * @param sem semaphore to wait on + * @return ERR_OK if the function was called, another err_t if not + */ +err_t +tcpip_send_api_msg(tcpip_callback_fn fn, void *apimsg, sys_sem_t* sem) +{ + LWIP_ASSERT("semaphore not initialized", sys_sem_valid(sem)); + + if (sys_mbox_valid_val(mbox)) { + TCPIP_MSG_VAR_DECLARE(msg); + + TCPIP_MSG_VAR_ALLOC(msg); + TCPIP_MSG_VAR_REF(msg).type = TCPIP_MSG_API; + TCPIP_MSG_VAR_REF(msg).msg.api.function = fn; + TCPIP_MSG_VAR_REF(msg).msg.api.msg = apimsg; + sys_mbox_post(&mbox, &TCPIP_MSG_VAR_REF(msg)); + sys_arch_sem_wait(sem, 0); + TCPIP_MSG_VAR_FREE(msg); + + return ERR_OK; + } + return ERR_VAL; +} +#endif /* !LWIP_TCPIP_CORE_LOCKING */ + +err_t tcpip_api_call(tcpip_api_call_fn fn, struct tcpip_api_call *call) +{ +#if LWIP_TCPIP_CORE_LOCKING + err_t err; + LOCK_TCPIP_CORE(); + err = fn(call); + UNLOCK_TCPIP_CORE(); + return err; +#else + if (sys_mbox_valid_val(mbox)) { + TCPIP_MSG_VAR_DECLARE(msg); + err_t err; + +#if LWIP_NETCONN_SEM_PER_THREAD + call->sem = LWIP_NETCONN_THREAD_SEM_GET(); +#else /* LWIP_NETCONN_SEM_PER_THREAD */ + err = sys_sem_new(&call->sem, 0); + if (err != ERR_OK) { + return err; + } +#endif /* LWIP_NETCONN_SEM_PER_THREAD */ + + TCPIP_MSG_VAR_ALLOC(msg); + TCPIP_MSG_VAR_REF(msg).type = TCPIP_MSG_API_CALL; + TCPIP_MSG_VAR_REF(msg).msg.api_call = call; + TCPIP_MSG_VAR_REF(msg).msg.api_call->function = fn; + sys_mbox_post(&mbox, &TCPIP_MSG_VAR_REF(msg)); +#if LWIP_NETCONN_SEM_PER_THREAD + sys_arch_sem_wait(call->sem, 0); +#else /* LWIP_NETCONN_SEM_PER_THREAD */ + sys_arch_sem_wait(&call->sem, 0); + sys_sem_free(&call->sem); +#endif /* LWIP_NETCONN_SEM_PER_THREAD */ + TCPIP_MSG_VAR_FREE(msg); + return ERR_OK; + } + return ERR_VAL; +#endif +} + +/** + * Allocate a structure for a static callback message and initialize it. + * This is intended to be used to send "static" messages from interrupt context. + * + * @param function the function to call + * @param ctx parameter passed to function + * @return a struct pointer to pass to tcpip_trycallback(). + */ +struct tcpip_callback_msg* +tcpip_callbackmsg_new(tcpip_callback_fn function, void *ctx) +{ + struct tcpip_msg *msg = (struct tcpip_msg *)memp_malloc(MEMP_TCPIP_MSG_API); + if (msg == NULL) { + return NULL; + } + msg->type = TCPIP_MSG_CALLBACK_STATIC; + msg->msg.cb.function = function; + msg->msg.cb.ctx = ctx; + return (struct tcpip_callback_msg*)msg; +} + +/** + * Free a callback message allocated by tcpip_callbackmsg_new(). + * + * @param msg the message to free + */ +void +tcpip_callbackmsg_delete(struct tcpip_callback_msg* msg) +{ + memp_free(MEMP_TCPIP_MSG_API, msg); +} + +/** + * Try to post a callback-message to the tcpip_thread mbox + * This is intended to be used to send "static" messages from interrupt context. + * + * @param msg pointer to the message to post + * @return sys_mbox_trypost() return code + */ +err_t +tcpip_trycallback(struct tcpip_callback_msg* msg) +{ + if (!sys_mbox_valid_val(mbox)) { + return ERR_VAL; + } + return sys_mbox_trypost(&mbox, msg); +} + +/** + * Initialize this module: + * - initialize all sub modules + * - start the tcpip_thread + * + * @param initfunc a function to call when tcpip_thread is running and finished initializing + * @param arg argument to pass to initfunc + */ +void +tcpip_init(tcpip_init_done_fn initfunc, void *arg) +{ + + lwip_init(); + + tcpip_init_done = initfunc; + tcpip_init_done_arg = arg; + if (sys_mbox_new(&mbox, TCPIP_MBOX_SIZE) != ERR_OK) { + LWIP_ASSERT("failed to create tcpip_thread mbox", 0); + } +#if LWIP_TCPIP_CORE_LOCKING + if (sys_mutex_new(&lock_tcpip_core) != ERR_OK) { + LWIP_ASSERT("failed to create lock_tcpip_core", 0); + } +#endif /* LWIP_TCPIP_CORE_LOCKING */ + + +#ifdef LWIP_ESP8266 + sys_thread_t xLwipTaskHandle = sys_thread_new(TCPIP_THREAD_NAME + , tcpip_thread, NULL, TCPIP_THREAD_STACKSIZE, TCPIP_THREAD_PRIO); + + printf("tcpip_task_hdlxxx : %x, prio:%d,stack:%d\n", + (u32_t)xLwipTaskHandle,TCPIP_THREAD_PRIO,TCPIP_THREAD_STACKSIZE); +#else + sys_thread_new(TCPIP_THREAD_NAME, tcpip_thread, NULL, TCPIP_THREAD_STACKSIZE, TCPIP_THREAD_PRIO); +#endif + +} + +/** + * Simple callback function used with tcpip_callback to free a pbuf + * (pbuf_free has a wrong signature for tcpip_callback) + * + * @param p The pbuf (chain) to be dereferenced. + */ +static void +pbuf_free_int(void *p) +{ + struct pbuf *q = (struct pbuf *)p; + pbuf_free(q); +} + +/** + * A simple wrapper function that allows you to free a pbuf from interrupt context. + * + * @param p The pbuf (chain) to be dereferenced. + * @return ERR_OK if callback could be enqueued, an err_t if not + */ +err_t +pbuf_free_callback(struct pbuf *p) +{ + return tcpip_callback_with_block(pbuf_free_int, p, 0); +} + +/** + * A simple wrapper function that allows you to free heap memory from + * interrupt context. + * + * @param m the heap memory to free + * @return ERR_OK if callback could be enqueued, an err_t if not + */ + +#ifdef LWIP_ESP8266 +//#if 0 +static void mem_free_local(void *arg) +{ + mem_free(arg); +} +err_t mem_free_callback(void *m) +{ + return tcpip_callback_with_block(mem_free_local, m, 0); + +#else +err_t mem_free_callback(void *m) +{ +#endif + + return tcpip_callback_with_block(mem_free, m, 0); +} + +#endif /* !NO_SYS */ diff --git a/components/lwip/apps/dhcpserver.c b/components/lwip/apps/dhcpserver.c new file mode 100644 index 0000000000..3b9795c5ad --- /dev/null +++ b/components/lwip/apps/dhcpserver.c @@ -0,0 +1,2485 @@ +// Copyright 2015-2016 Espressif Systems (Shanghai) PTE LTD +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at + +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +//#include "esp_common.h" +#include +#include +#include "lwip/inet.h" +#include "lwip/err.h" +#include "lwip/pbuf.h" +#include "lwip/udp.h" +#include "lwip/mem.h" +#include "lwip/ip_addr.h" +#include "apps/dhcpserver.h" + +#include "tcpip_adapter.h" + +#ifdef LWIP_ESP8266 + +enum dyc_dhcps_flags{ + DHCPS_STARTED = 0x00, + DHCPS_STOP = 0x01, + _END +} DhcpsFlags = DHCPS_STOP; + +#define DHCPS_MAX_LEASE 0x64 +#define BOOTP_BROADCAST 0x8000 + +#define DHCP_REQUEST 1 +#define DHCP_REPLY 2 +#define DHCP_HTYPE_ETHERNET 1 +#define DHCP_HLEN_ETHERNET 6 +#define DHCP_MSG_LEN 236 + +#define DHCPS_SERVER_PORT 67 +#define DHCPS_CLIENT_PORT 68 + +#define DHCPDISCOVER 1 +#define DHCPOFFER 2 +#define DHCPREQUEST 3 +#define DHCPDECLINE 4 +#define DHCPACK 5 +#define DHCPNAK 6 +#define DHCPRELEASE 7 + +#define DHCP_OPTION_SUBNET_MASK 1 +#define DHCP_OPTION_ROUTER 3 +#define DHCP_OPTION_DNS_SERVER 6 +#define DHCP_OPTION_REQ_IPADDR 50 +#define DHCP_OPTION_LEASE_TIME 51 +#define DHCP_OPTION_MSG_TYPE 53 +#define DHCP_OPTION_SERVER_ID 54 +#define DHCP_OPTION_INTERFACE_MTU 26 +#define DHCP_OPTION_PERFORM_ROUTER_DISCOVERY 31 +#define DHCP_OPTION_BROADCAST_ADDRESS 28 +#define DHCP_OPTION_REQ_LIST 55 +#define DHCP_OPTION_END 255 + +//#define USE_CLASS_B_NET 1 +#define DHCPS_DEBUG 0 +#define DHCPS_LOG printf + +#define DYC_DHCP_CRASH //os_printf + + +#define MAX_STATION_NUM 8 + +#define DHCPS_STATE_OFFER 1 +#define DHCPS_STATE_DECLINE 2 +#define DHCPS_STATE_ACK 3 +#define DHCPS_STATE_NAK 4 +#define DHCPS_STATE_IDLE 5 +#define DHCPS_STATE_RELEASE 6 + + + +#ifdef MEMLEAK_DEBUG +static const char mem_debug_file[] ICACHE_RODATA_ATTR STORE_ATTR = __FILE__; +#endif + +//////////////////////////////////////////////////////////////////////////////////// +//static const uint8_t xid[4] = {0xad, 0xde, 0x12, 0x23}; +//static u8_t old_xid[4] = {0}; +static const u32_t magic_cookie = 0x63538263; +//static const u32_t magic_cookie = 0x63538263; +//static const char magic_cookie[] = {0x63,0x82,0x53,0x63}; +//static const u32_t magic_cookie = 0x63538263; +//static const u32_t magic_cookie_temp = 0x63538263; + +/* +ip_2_ip4(ipaddr) +IP_IS_V6(dest) +IP_SET_TYPE(ipaddr, IPADDR_TYPE_V4) +*/ + + +static struct udp_pcb *pcb_dhcps = NULL; +static ip4_addr_t broadcast_dhcps; +static ip4_addr_t server_address; +static ip4_addr_t client_address; //added +static ip4_addr_t client_address_plus; + +static struct dhcps_lease dhcps_lease; +//static bool dhcps_lease_flag = true; +static list_node *plist = NULL; +static u8_t offer = 0xFF; +static bool renew = false; +#define DHCPS_LEASE_TIME_DEF (120) +u32_t dhcps_lease_time = DHCPS_LEASE_TIME_DEF; //minute + + + +static enum dyc_dhcps_flags get_dhcps_status(void ) +{ + return DhcpsFlags; +} +/****************************************************************************** + * FunctionName : node_insert_to_list + * Description : insert the node to the list + * Parameters : arg -- Additional argument to pass to the callback function + * Returns : none +*******************************************************************************/ +void node_insert_to_list(list_node **phead, list_node* pinsert) +{ + list_node *plist = NULL; + struct dhcps_pool *pdhcps_pool = NULL; + struct dhcps_pool *pdhcps_node = NULL; + if (*phead == NULL) + *phead = pinsert; + else { + plist = *phead; + pdhcps_node = pinsert->pnode; + pdhcps_pool = plist->pnode; + + if(pdhcps_node->ip.addr < pdhcps_pool->ip.addr) { + pinsert->pnext = plist; + *phead = pinsert; + } else { + while (plist->pnext != NULL) { + pdhcps_pool = plist->pnext->pnode; + if (pdhcps_node->ip.addr < pdhcps_pool->ip.addr) { + pinsert->pnext = plist->pnext; + plist->pnext = pinsert; + break; + } + plist = plist->pnext; + } + + if(plist->pnext == NULL) { + plist->pnext = pinsert; + } + } + } +// pinsert->pnext = NULL; +} + +/****************************************************************************** + * FunctionName : node_delete_from_list + * Description : remove the node from list + * Parameters : arg -- Additional argument to pass to the callback function + * Returns : none +*******************************************************************************/ +void node_remove_from_list(list_node **phead, list_node* pdelete) +{ + list_node *plist = NULL; + + plist = *phead; + if (plist == NULL){ + *phead = NULL; + } else { + if (plist == pdelete){ + *phead = plist->pnext; + pdelete->pnext = NULL; + } else { + while (plist != NULL) { + if (plist->pnext == pdelete){ + plist->pnext = pdelete->pnext; + pdelete->pnext = NULL; + } + plist = plist->pnext; + } + } + } +} +/////////////////////////////////////////////////////////////////////////////////// +/* + * ��DHCP msg��Ϣ�ṹ���������� + * + * @param optptr -- DHCP msg��Ϣλ�� + * @param type -- Ҫ��ӵ�����option + * + * @return uint8_t* ����DHCP msgƫ�Ƶ�ַ + */ +/////////////////////////////////////////////////////////////////////////////////// +static u8_t* add_msg_type(u8_t *optptr, u8_t type) +{ + *optptr++ = DHCP_OPTION_MSG_TYPE; + *optptr++ = 1; + *optptr++ = type; + return optptr; +} +/////////////////////////////////////////////////////////////////////////////////// +/* + * ��DHCP msg�ṹ������offerӦ������ + * + * @param optptr -- DHCP msg��Ϣλ�� + * + * @return uint8_t* ����DHCP msgƫ�Ƶ�ַ + */ +/////////////////////////////////////////////////////////////////////////////////// +static u8_t* add_offer_options(u8_t *optptr) +{ + ip4_addr_t ipadd; + + ipadd.addr = *( (u32_t *) &server_address); + +#ifdef USE_CLASS_B_NET + *optptr++ = DHCP_OPTION_SUBNET_MASK; + *optptr++ = 4; //length + *optptr++ = 255; + *optptr++ = 240; + *optptr++ = 0; + *optptr++ = 0; +#else + *optptr++ = DHCP_OPTION_SUBNET_MASK; + *optptr++ = 4; + *optptr++ = 255; + *optptr++ = 255; + *optptr++ = 255; + *optptr++ = 0; +#endif + + *optptr++ = DHCP_OPTION_LEASE_TIME; + *optptr++ = 4; + *optptr++ = ((DHCPS_LEASE_TIMER * 60) >> 24) & 0xFF; + *optptr++ = ((DHCPS_LEASE_TIMER * 60) >> 16) & 0xFF; + *optptr++ = ((DHCPS_LEASE_TIMER * 60) >> 8) & 0xFF; + *optptr++ = ((DHCPS_LEASE_TIMER * 60) >> 0) & 0xFF; + + *optptr++ = DHCP_OPTION_SERVER_ID; + *optptr++ = 4; + *optptr++ = ip4_addr1( &ipadd); + *optptr++ = ip4_addr2( &ipadd); + *optptr++ = ip4_addr3( &ipadd); + *optptr++ = ip4_addr4( &ipadd); + + if (dhcps_router_enabled(offer)){ + struct ip_info if_ip; + //bzero(&if_ip, sizeof(struct ip_info)); + memset(&if_ip ,0x00, sizeof(struct ip_info)); + + tcpip_adapter_get_ip_info(WIFI_IF_AP, &if_ip); + + *optptr++ = DHCP_OPTION_ROUTER; + *optptr++ = 4; + *optptr++ = ip4_addr1( &if_ip.gw); + *optptr++ = ip4_addr2( &if_ip.gw); + *optptr++ = ip4_addr3( &if_ip.gw); + *optptr++ = ip4_addr4( &if_ip.gw); + } + +#ifdef USE_DNS + *optptr++ = DHCP_OPTION_DNS_SERVER; + *optptr++ = 4; + *optptr++ = ip4_addr1( &ipadd); + *optptr++ = ip4_addr2( &ipadd); + *optptr++ = ip4_addr3( &ipadd); + *optptr++ = ip4_addr4( &ipadd); +#endif + +#ifdef CLASS_B_NET + *optptr++ = DHCP_OPTION_BROADCAST_ADDRESS; + *optptr++ = 4; + *optptr++ = ip4_addr1( &ipadd); + *optptr++ = 255; + *optptr++ = 255; + *optptr++ = 255; +#else + *optptr++ = DHCP_OPTION_BROADCAST_ADDRESS; + *optptr++ = 4; + *optptr++ = ip4_addr1( &ipadd); + *optptr++ = ip4_addr2( &ipadd); + *optptr++ = ip4_addr3( &ipadd); + *optptr++ = 255; +#endif + + *optptr++ = DHCP_OPTION_INTERFACE_MTU; + *optptr++ = 2; +#ifdef CLASS_B_NET + *optptr++ = 0x05; + *optptr++ = 0xdc; +#else + *optptr++ = 0x02; + *optptr++ = 0x40; +#endif + + *optptr++ = DHCP_OPTION_PERFORM_ROUTER_DISCOVERY; + *optptr++ = 1; + *optptr++ = 0x00; + + *optptr++ = 43; + *optptr++ = 6; + + *optptr++ = 0x01; + *optptr++ = 4; + *optptr++ = 0x00; + *optptr++ = 0x00; + *optptr++ = 0x00; + *optptr++ = 0x02; + + return optptr; +} +/////////////////////////////////////////////////////////////////////////////////// +/* + * ��DHCP msg�ṹ����ӽ����־���� + * + * @param optptr -- DHCP msg��Ϣλ�� + * + * @return uint8_t* ����DHCP msgƫ�Ƶ�ַ + */ +/////////////////////////////////////////////////////////////////////////////////// +static u8_t* add_end(u8_t *optptr) +{ + + *optptr++ = DHCP_OPTION_END; + return optptr; +} +/////////////////////////////////////////////////////////////////////////////////// +/////////////////////////////////////////////////////////////////////////////////// +static void create_msg(struct dhcps_msg *m) +{ + ip4_addr_t client; + + + client.addr = *( (uint32_t *) &client_address); + + m->op = DHCP_REPLY; + + m->htype = DHCP_HTYPE_ETHERNET; + + m->hlen = 6; + + m->hops = 0; +// os_memcpy((char *) xid, (char *) m->xid, sizeof(m->xid)); + m->secs = 0; + m->flags = htons(BOOTP_BROADCAST); + + memcpy((char *) m->yiaddr, (char *) &client.addr, sizeof(m->yiaddr)); + + memset((char *) m->ciaddr, 0, sizeof(m->ciaddr)); + + memset((char *) m->siaddr, 0, sizeof(m->siaddr)); + + memset((char *) m->giaddr, 0, sizeof(m->giaddr)); + + memset((char *) m->sname, 0, sizeof(m->sname)); + + memset((char *) m->file, 0, sizeof(m->file)); + + memset((char *) m->options, 0, sizeof(m->options)); + +// u32_t temp = 0x63538263; + // u8 *log_temp = (u8 *)&temp; +//DYC_DHCP_CRASH("l:%0x,%0x,%0x,%0x,",log_temp[0],log_temp[1],log_temp[2],log_temp[3]); + +u32_t magic_cookie_temp = magic_cookie; + +//extern bool system_get_string_from_flash(void *flash_str, void* ram_str,uint8 ram_str_len); +//system_get_string_from_flash((void *)(&magic_cookie), (void *)(&magic_cookie_temp),4); +//os_printf("ck_tmp3:%08X\n",magic_cookie_temp); + + //memcpy((char *) m->options, &magic_cookie, sizeof(magic_cookie)); + memcpy((char *) m->options, &magic_cookie_temp, sizeof(magic_cookie_temp)); +// DYC_DHCP_CRASH("m,"); +} +/////////////////////////////////////////////////////////////////////////////////// +/* + * ����һ��OFFER + * + * @param -- m ָ����Ҫ���͵�DHCP msg���� + */ +/////////////////////////////////////////////////////////////////////////////////// +static void send_offer(struct dhcps_msg *m) +{ + u8_t *end; + struct pbuf *p, *q; + u8_t *data; + u16_t cnt=0; + u16_t i; + err_t SendOffer_err_t; + create_msg(m); + + end = add_msg_type(&m->options[4], DHCPOFFER); + end = add_offer_options(end); + end = add_end(end); + + p = pbuf_alloc(PBUF_TRANSPORT, sizeof(struct dhcps_msg), PBUF_RAM); +#if DHCPS_DEBUG + DHCPS_LOG("udhcp: send_offer>>p->ref = %d\n", p->ref); +#endif + if(p != NULL){ + +#if DHCPS_DEBUG + DHCPS_LOG("dhcps: send_offer>>pbuf_alloc succeed\n"); + DHCPS_LOG("dhcps: send_offer>>p->tot_len = %d\n", p->tot_len); + DHCPS_LOG("dhcps: send_offer>>p->len = %d\n", p->len); +#endif + q = p; + while(q != NULL){ + data = (u8_t *)q->payload; + for(i=0; ilen; i++) + { + data[i] = ((u8_t *) m)[cnt++]; +#if DHCPS_DEBUG + DHCPS_LOG("%02x ",data[i]); + if((i+1)%16 == 0){ + DHCPS_LOG("\n"); + } +#endif + } + + q = q->next; + } + }else{ + +#if DHCPS_DEBUG + DHCPS_LOG("dhcps: send_offer>>pbuf_alloc failed\n"); +#endif + return; + } + + ip_addr_t ip_temp = IPADDR4_INIT(0x0); + ip4_addr_set(ip_2_ip4(&ip_temp), &broadcast_dhcps); + SendOffer_err_t = udp_sendto( pcb_dhcps, p, &ip_temp, DHCPS_CLIENT_PORT ); +#if DHCPS_DEBUG + DHCPS_LOG("dhcps: send_offer>>udp_sendto result %x\n",SendOffer_err_t); +#endif + if(p->ref != 0){ +#if DHCPS_DEBUG + DHCPS_LOG("udhcp: send_offer>>free pbuf\n"); +#endif + pbuf_free(p); + } +} +/////////////////////////////////////////////////////////////////////////////////// +/* + * ����һ��NAK��Ϣ + * + * @param m ָ����Ҫ���͵�DHCP msg���� + */ +/////////////////////////////////////////////////////////////////////////////////// +static void send_nak(struct dhcps_msg *m) +{ + u8_t *end; + struct pbuf *p, *q; + u8_t *data; + u16_t cnt=0; + u16_t i; + err_t SendNak_err_t; + create_msg(m); + + end = add_msg_type(&m->options[4], DHCPNAK); + end = add_end(end); + + p = pbuf_alloc(PBUF_TRANSPORT, sizeof(struct dhcps_msg), PBUF_RAM); +#if DHCPS_DEBUG + DHCPS_LOG("udhcp: send_nak>>p->ref = %d\n", p->ref); +#endif + if(p != NULL){ + +#if DHCPS_DEBUG + DHCPS_LOG("dhcps: send_nak>>pbuf_alloc succeed\n"); + DHCPS_LOG("dhcps: send_nak>>p->tot_len = %d\n", p->tot_len); + DHCPS_LOG("dhcps: send_nak>>p->len = %d\n", p->len); +#endif + q = p; + while(q != NULL){ + data = (u8_t *)q->payload; + for(i=0; ilen; i++) + { + data[i] = ((u8_t *) m)[cnt++]; +#if DHCPS_DEBUG + DHCPS_LOG("%02x ",data[i]); + if((i+1)%16 == 0){ + DHCPS_LOG("\n"); + } +#endif + } + + q = q->next; + } + }else{ + +#if DHCPS_DEBUG + DHCPS_LOG("dhcps: send_nak>>pbuf_alloc failed\n"); +#endif + return; + } + + ip_addr_t ip_temp = IPADDR4_INIT(0x0); + ip4_addr_set(ip_2_ip4(&ip_temp), &broadcast_dhcps); + SendNak_err_t = udp_sendto( pcb_dhcps, p, &ip_temp, DHCPS_CLIENT_PORT ); +#if DHCPS_DEBUG + DHCPS_LOG("dhcps: send_nak>>udp_sendto result %x\n",SendNak_err_t); +#endif + if(p->ref != 0){ +#if DHCPS_DEBUG + DHCPS_LOG("udhcp: send_nak>>free pbuf\n"); +#endif + pbuf_free(p); + } +} +/////////////////////////////////////////////////////////////////////////////////// +/* + * ����һ��ACK��DHCP�ͻ��� + * + * @param m ָ����Ҫ���͵�DHCP msg���� + */ +/////////////////////////////////////////////////////////////////////////////////// +static void send_ack(struct dhcps_msg *m) +{ + u8_t *end; + struct pbuf *p, *q; + u8_t *data; + u16_t cnt=0; + u16_t i; + err_t SendAck_err_t; + create_msg(m); + + end = add_msg_type(&m->options[4], DHCPACK); + end = add_offer_options(end); + end = add_end(end); + + p = pbuf_alloc(PBUF_TRANSPORT, sizeof(struct dhcps_msg), PBUF_RAM); +#if DHCPS_DEBUG + DHCPS_LOG("udhcp: send_ack>>p->ref = %d\n", p->ref); +#endif + if(p != NULL){ + +#if DHCPS_DEBUG + DHCPS_LOG("dhcps: send_ack>>pbuf_alloc succeed\n"); + DHCPS_LOG("dhcps: send_ack>>p->tot_len = %d\n", p->tot_len); + DHCPS_LOG("dhcps: send_ack>>p->len = %d\n", p->len); +#endif + q = p; + while(q != NULL){ + data = (u8_t *)q->payload; + for(i=0; ilen; i++) + { + data[i] = ((u8_t *) m)[cnt++]; +#if DHCPS_DEBUG + DHCPS_LOG("%02x ",data[i]); + if((i+1)%16 == 0){ + DHCPS_LOG("\n"); + } +#endif + } + + q = q->next; + } + }else{ + +#if DHCPS_DEBUG + DHCPS_LOG("dhcps: send_ack>>pbuf_alloc failed\n"); +#endif + return; + } + + ip_addr_t ip_temp = IPADDR4_INIT(0x0); + ip4_addr_set(ip_2_ip4(&ip_temp), &broadcast_dhcps); + SendAck_err_t = udp_sendto( pcb_dhcps, p, &ip_temp, DHCPS_CLIENT_PORT ); +#if DHCPS_DEBUG + DHCPS_LOG("dhcps: send_ack>>udp_sendto result %x\n",SendAck_err_t); +#endif + + if(p->ref != 0){ +#if DHCPS_DEBUG + DHCPS_LOG("udhcp: send_ack>>free pbuf\n"); +#endif + pbuf_free(p); + } +} +/////////////////////////////////////////////////////////////////////////////////// +/* + * ����DHCP�ͻ��˷�����DHCP����������Ϣ�����Բ�ͬ��DHCP��������������Ӧ��Ӧ�� + * + * @param optptr DHCP msg��������� + * @param len ��������Ĵ��?(byte) + * + * @return uint8_t ���ش�����DHCP Server״ֵ̬ + */ +/////////////////////////////////////////////////////////////////////////////////// +static u8_t parse_options(u8_t *optptr, s16_t len) +{ + ip4_addr_t client; + bool is_dhcp_parse_end = false; + struct dhcps_state s; + + client.addr = *( (uint32_t *) &client_address);// Ҫ�����DHCP�ͻ��˵�IP + + u8_t *end = optptr + len; + u16_t type = 0; + + s.state = DHCPS_STATE_IDLE; + + while (optptr < end) { +#if DHCPS_DEBUG + DHCPS_LOG("dhcps: (s16_t)*optptr = %d\n", (s16_t)*optptr); +#endif + switch ((s16_t) *optptr) { + + case DHCP_OPTION_MSG_TYPE: //53 + type = *(optptr + 2); + break; + + case DHCP_OPTION_REQ_IPADDR://50 + if( memcmp( (char *) &client.addr, (char *) optptr+2,4)==0 ) { +#if DHCPS_DEBUG + DHCPS_LOG("dhcps: DHCP_OPTION_REQ_IPADDR = 0 ok\n"); +#endif + s.state = DHCPS_STATE_ACK; + }else { +#if DHCPS_DEBUG + DHCPS_LOG("dhcps: DHCP_OPTION_REQ_IPADDR != 0 err\n"); +#endif + s.state = DHCPS_STATE_NAK; + } + break; + case DHCP_OPTION_END: + { + is_dhcp_parse_end = true; + } + break; + } + + if(is_dhcp_parse_end){ + break; + } + + optptr += optptr[1] + 2; + } + + switch (type){ + + case DHCPDISCOVER://1 + s.state = DHCPS_STATE_OFFER; +#if DHCPS_DEBUG + DHCPS_LOG("dhcps: DHCPD_STATE_OFFER\n"); +#endif + break; + + case DHCPREQUEST://3 + if ( !(s.state == DHCPS_STATE_ACK || s.state == DHCPS_STATE_NAK) ) { + if(renew == true) { + s.state = DHCPS_STATE_ACK; + } else { + s.state = DHCPS_STATE_NAK; + } +#if DHCPS_DEBUG + DHCPS_LOG("dhcps: DHCPD_STATE_NAK\n"); +#endif + } + break; + + case DHCPDECLINE://4 + s.state = DHCPS_STATE_IDLE; +#if DHCPS_DEBUG + DHCPS_LOG("dhcps: DHCPD_STATE_IDLE\n"); +#endif + break; + + case DHCPRELEASE://7 + s.state = DHCPS_STATE_RELEASE; +#if DHCPS_DEBUG + DHCPS_LOG("dhcps: DHCPD_STATE_IDLE\n"); +#endif + break; + } +#if DHCPS_DEBUG + DHCPS_LOG("dhcps: return s.state = %d\n", s.state); +#endif + return s.state; +} +/////////////////////////////////////////////////////////////////////////////////// +/////////////////////////////////////////////////////////////////////////////////// +static s16_t parse_msg(struct dhcps_msg *m, u16_t len) +{ + +//u32 magic_cookie_temp = magic_cookie; +//extern bool system_get_string_from_flash(void *flash_str, void* ram_str,uint8 ram_str_len); +//system_get_string_from_flash((void *)(&magic_cookie), (void *)(&magic_cookie_temp),4); +//os_printf("ck_tmp4:%08X\n",magic_cookie_temp); + + if(memcmp((char *)m->options, + &magic_cookie, + sizeof(magic_cookie)) == 0){ +#if DHCPS_DEBUG + DHCPS_LOG("dhcps: len = %d\n", len); +#endif + + ip4_addr_t addr_tmp; +// memcpy((char *)old_xid, (char *)m->xid, sizeof(m->xid)); + + struct dhcps_pool *pdhcps_pool = NULL; + list_node *pnode = NULL; + list_node *pback_node = NULL; + ip4_addr_t first_address; + bool flag = false; + +// POOL_START: + first_address.addr = dhcps_lease.start_ip.addr; + client_address.addr = client_address_plus.addr; + renew = false; +// addr_tmp.addr = htonl(client_address_plus.addr); +// addr_tmp.addr++; +// client_address_plus.addr = htonl(addr_tmp.addr); + for (pback_node = plist; pback_node != NULL;pback_node = pback_node->pnext) { + pdhcps_pool = pback_node->pnode; + if (memcmp(pdhcps_pool->mac, m->chaddr, sizeof(pdhcps_pool->mac)) == 0){ +// os_printf("the same device request ip\n"); + if (memcmp(&pdhcps_pool->ip.addr, m->ciaddr, sizeof(pdhcps_pool->ip.addr)) == 0) { + renew = true; + } + client_address.addr = pdhcps_pool->ip.addr; + pdhcps_pool->lease_timer = DHCPS_LEASE_TIMER; + pnode = pback_node; + goto POOL_CHECK; + } else if (pdhcps_pool->ip.addr == client_address_plus.addr){ +// client_address.addr = client_address_plus.addr; +// os_printf("the ip addr has been request\n"); + addr_tmp.addr = htonl(client_address_plus.addr); + addr_tmp.addr++; + client_address_plus.addr = htonl(addr_tmp.addr); + client_address.addr = client_address_plus.addr; + } + + if(flag == false) { // search the fisrt unused ip + if(first_address.addr < pdhcps_pool->ip.addr) { + flag = true; + } else { + addr_tmp.addr = htonl(first_address.addr); + addr_tmp.addr++; + first_address.addr = htonl(addr_tmp.addr); + } + } + } + if (client_address_plus.addr > dhcps_lease.end_ip.addr) { + client_address.addr = first_address.addr; + } + if (client_address.addr > dhcps_lease.end_ip.addr) { + client_address_plus.addr = dhcps_lease.start_ip.addr; + pdhcps_pool = NULL; + pnode = NULL; + } else { + pdhcps_pool = (struct dhcps_pool *)malloc(sizeof(struct dhcps_pool)); + memset(pdhcps_pool ,0x00 ,sizeof(struct dhcps_pool)); + + pdhcps_pool->ip.addr = client_address.addr; + memcpy(pdhcps_pool->mac, m->chaddr, sizeof(pdhcps_pool->mac)); + pdhcps_pool->lease_timer = DHCPS_LEASE_TIMER; + pnode = (list_node *)malloc(sizeof(list_node )); + memset(pnode ,0x00 ,sizeof(list_node)); + + pnode->pnode = pdhcps_pool; + pnode->pnext = NULL; + node_insert_to_list(&plist,pnode); + if (client_address.addr == dhcps_lease.end_ip.addr) { + client_address_plus.addr = dhcps_lease.start_ip.addr; + } else { + addr_tmp.addr = htonl(client_address.addr); + addr_tmp.addr++; + client_address_plus.addr = htonl(addr_tmp.addr); + } + } + + POOL_CHECK: + if ((client_address.addr > dhcps_lease.end_ip.addr) || (ip4_addr_isany(&client_address))){ + if(pnode != NULL) { + node_remove_from_list(&plist,pnode); + free(pnode); + pnode = NULL; + } + + if (pdhcps_pool != NULL) { + free(pdhcps_pool); + pdhcps_pool = NULL; + } +// client_address_plus.addr = dhcps_lease.start_ip.addr; + return 4; + } + + s16_t ret = parse_options(&m->options[4], len);; + + if(ret == DHCPS_STATE_RELEASE) { + if(pnode != NULL) { + node_remove_from_list(&plist,pnode); + free(pnode); + pnode = NULL; + } + + if (pdhcps_pool != NULL) { + free(pdhcps_pool); + pdhcps_pool = NULL; + } + memset(&client_address,0x0,sizeof(client_address)); + } + +//TO_DO , set (ap-> sta) ip_addr no use. +//if ( tcpip_dep_set_ip_info(STATION_IF, struct ip_info *if_ip) == false ) + //return 0; +//if (wifi_softap_set_station_info(m->chaddr, &client_address) == false) { + // return 0; + +#if DHCPS_DEBUG + DHCPS_LOG("dhcps: xid changed\n"); + DHCPS_LOG("dhcps: client_address.addr = %x\n", client_address.addr); +#endif + return ret; + } + return 0; +} + + +static void handle_dhcp(void *arg, + struct udp_pcb *pcb, + struct pbuf *p, + const ip_addr_t *addr, + u16_t port) +{ + struct dhcps_msg *pmsg_dhcps = NULL; + s16_t tlen; + u16_t i; + u16_t dhcps_msg_cnt=0; + u8_t *p_dhcps_msg = NULL; + u8_t *data; + +#if DHCPS_DEBUG + DHCPS_LOG("dhcps: handle_dhcp-> receive a packet\n"); +#endif + if (p==NULL) return; + + pmsg_dhcps = (struct dhcps_msg *)malloc(sizeof(struct dhcps_msg)); + memset(pmsg_dhcps ,0x00 ,sizeof(struct dhcps_msg)); + + if (NULL == pmsg_dhcps){ + pbuf_free(p); + return; + } + p_dhcps_msg = (u8_t *)pmsg_dhcps; + tlen = p->tot_len; + data = p->payload; + +#if DHCPS_DEBUG + DHCPS_LOG("dhcps: handle_dhcp-> p->tot_len = %d\n", tlen); + DHCPS_LOG("dhcps: handle_dhcp-> p->len = %d\n", p->len); +#endif + + for(i=0; ilen; i++){ + p_dhcps_msg[dhcps_msg_cnt++] = data[i]; +#if DHCPS_DEBUG + DHCPS_LOG("%02x ",data[i]); + if((i+1)%16 == 0){ + DHCPS_LOG("\n"); + } +#endif + } + + if(p->next != NULL) { +#if DHCPS_DEBUG + DHCPS_LOG("dhcps: handle_dhcp-> p->next != NULL\n"); + DHCPS_LOG("dhcps: handle_dhcp-> p->next->tot_len = %d\n",p->next->tot_len); + DHCPS_LOG("dhcps: handle_dhcp-> p->next->len = %d\n",p->next->len); +#endif + + data = p->next->payload; + for(i=0; inext->len; i++){ + p_dhcps_msg[dhcps_msg_cnt++] = data[i]; +#if DHCPS_DEBUG + DHCPS_LOG("%02x ",data[i]); + if((i+1)%16 == 0){ + DHCPS_LOG("\n"); + } +#endif + } + } + + /* + * DHCP �ͻ���������Ϣ���� + */ +#if DHCPS_DEBUG + DHCPS_LOG("dhcps: handle_dhcp-> parse_msg(p)\n"); +#endif + + switch(parse_msg(pmsg_dhcps, tlen - 240)) { + case DHCPS_STATE_OFFER://1 +#if DHCPS_DEBUG + DHCPS_LOG("dhcps: handle_dhcp-> DHCPD_STATE_OFFER\n"); +#endif + send_offer(pmsg_dhcps); + break; + case DHCPS_STATE_ACK://3 +#if DHCPS_DEBUG + DHCPS_LOG("dhcps: handle_dhcp-> DHCPD_STATE_ACK\n"); +#endif + send_ack(pmsg_dhcps); + break; + case DHCPS_STATE_NAK://4 +#if DHCPS_DEBUG + DHCPS_LOG("dhcps: handle_dhcp-> DHCPD_STATE_NAK\n"); +#endif + send_nak(pmsg_dhcps); + break; + default : + break; + } +#if DHCPS_DEBUG + DHCPS_LOG("dhcps: handle_dhcp-> pbuf_free(p)\n"); +#endif + pbuf_free(p); + free(pmsg_dhcps); + pmsg_dhcps = NULL; +} +/////////////////////////////////////////////////////////////////////////////////// +static void wifi_softap_init_dhcps_lease(u32_t ip) +{ + u32_t softap_ip = 0,local_ip = 0; + u32_t start_ip = 0; + u32_t end_ip = 0; + if (dhcps_lease.enable == true) { + softap_ip = htonl(ip); + start_ip = htonl(dhcps_lease.start_ip.addr); + end_ip = htonl(dhcps_lease.end_ip.addr); + /*config ip information can't contain local ip*/ + if ((start_ip <= softap_ip) && (softap_ip <= end_ip)) { + dhcps_lease.enable = false; + } else { + /*config ip information must be in the same segment as the local ip*/ + softap_ip >>= 8; + if (((start_ip >> 8 != softap_ip) || (end_ip >> 8 != softap_ip)) + || (end_ip - start_ip > DHCPS_MAX_LEASE)) { + dhcps_lease.enable = false; + } + } + } + + if (dhcps_lease.enable == false) { + local_ip = softap_ip = htonl(ip); + softap_ip &= 0xFFFFFF00; + local_ip &= 0xFF; + if (local_ip >= 0x80) + local_ip -= DHCPS_MAX_LEASE; + else + local_ip ++; + + bzero(&dhcps_lease, sizeof(dhcps_lease)); + dhcps_lease.start_ip.addr = softap_ip | local_ip; + dhcps_lease.end_ip.addr = softap_ip | (local_ip + DHCPS_MAX_LEASE - 1); + dhcps_lease.start_ip.addr = htonl(dhcps_lease.start_ip.addr); + dhcps_lease.end_ip.addr= htonl(dhcps_lease.end_ip.addr); + } +// os_printf("start_ip = 0x%x, end_ip = 0x%x\n",dhcps_lease.start_ip, dhcps_lease.end_ip); +} + + +/////////////////////////////////////////////////////////////////////////////////// +void dhcps_start(struct netif *netif) +{ + struct netif * apnetif =netif; + + + if(apnetif->dhcps_pcb != NULL) { + udp_remove(apnetif->dhcps_pcb); + } + pcb_dhcps = udp_new(); + if (pcb_dhcps == NULL) { + printf("dhcps_start(): could not obtain pcb\n"); + } + apnetif->dhcps_pcb = pcb_dhcps; + + IP4_ADDR(&broadcast_dhcps, 255, 255, 255, 255); + + server_address = netif->ip_addr.u_addr.ip4; + wifi_softap_init_dhcps_lease( server_address.addr ); + + client_address_plus.addr = dhcps_lease.start_ip.addr; + + udp_bind(pcb_dhcps, IP_ADDR_ANY, DHCPS_SERVER_PORT); + udp_recv(pcb_dhcps, handle_dhcp, NULL); +#if DHCPS_DEBUG + DHCPS_LOG("dhcps:dhcps_start->udp_recv function Set a receive callback handle_dhcp for UDP_PCB pcb_dhcps\n"); +#endif + DhcpsFlags = DHCPS_STARTED; + +} + +void dhcps_stop(struct netif *netif ) +{ + struct netif * apnetif = netif; + if(apnetif == NULL) + { + printf("dhcps_stop: apnetif == NULL\n"); + return; + } + udp_disconnect(pcb_dhcps); +// dhcps_lease_flag = true; + if(apnetif->dhcps_pcb != NULL) { + udp_remove(apnetif->dhcps_pcb); + apnetif->dhcps_pcb = NULL; + } + + list_node *pnode = NULL; + list_node *pback_node = NULL; + pnode = plist; + while (pnode != NULL) { + pback_node = pnode; + pnode = pback_node->pnext; + node_remove_from_list(&plist, pback_node); + free(pback_node->pnode); + pback_node->pnode = NULL; + free(pback_node); + pback_node = NULL; + } + DhcpsFlags = DHCPS_STOP; +} + +bool wifi_softap_set_dhcps_lease(struct dhcps_lease *please) +{ + +// NOT USE + struct ip_info info; + u32_t softap_ip = 0; + u32_t start_ip = 0; + u32_t end_ip = 0; + + //uint8 opmode = wifi_get_opmode(); + //uint8 opmode = 0; + //if (opmode == STATION_MODE || opmode == NULL_MODE) { + //return false; + //} + if (please == NULL || get_dhcps_status() == DHCPS_STARTED) + return false; + + if(please->enable) { + struct ip_info ip_info; + memset(&ip_info, 0x00, sizeof(struct ip_info)); + tcpip_adapter_get_ip_info(WIFI_IF_AP, &info); + + softap_ip = htonl(info.ip.addr); + start_ip = htonl(please->start_ip.addr); + end_ip = htonl(please->end_ip.addr); + + /*config ip information can't contain local ip*/ + if ((start_ip <= softap_ip) && (softap_ip <= end_ip)) + return false; + + /*config ip information must be in the same segment as the local ip*/ + softap_ip >>= 8; + if ((start_ip >> 8 != softap_ip) + || (end_ip >> 8 != softap_ip)) { + return false; + } + + if (end_ip - start_ip > DHCPS_MAX_LEASE) + return false; + + memset(&dhcps_lease, 0x00, sizeof(dhcps_lease)); + // dhcps_lease.start_ip.addr = start_ip; + // dhcps_lease.end_ip.addr = end_ip; + dhcps_lease.start_ip.addr = please->start_ip.addr; + dhcps_lease.end_ip.addr = please->end_ip.addr; + } + dhcps_lease.enable = please->enable; +// dhcps_lease_flag = false; + return true; +} + +/****************************************************************************** + * FunctionName : wifi_softap_get_dhcps_lease + * Description : get the lease information of DHCP server + * Parameters : please -- Additional argument to get the lease information, + * Little-Endian. + * Returns : true or false +*******************************************************************************/ +bool wifi_softap_get_dhcps_lease(struct dhcps_lease *please) +{ + + if (NULL == please) + return false; + if (dhcps_lease.enable == false){ + if (get_dhcps_status() == DHCPS_STOP) + return false; + } else { + ; + } + please->start_ip.addr = dhcps_lease.start_ip.addr; + please->end_ip.addr = dhcps_lease.end_ip.addr; + return true; +} + +static void kill_oldest_dhcps_pool(void) +{ + list_node *pre = NULL, *p = NULL; + list_node *minpre = NULL, *minp = NULL; + struct dhcps_pool *pdhcps_pool = NULL, *pmin_pool = NULL; + pre = plist; + p = pre->pnext; + minpre = pre; + minp = p; + while (p != NULL){ + pdhcps_pool = p->pnode; + pmin_pool = minp->pnode; + if (pdhcps_pool->lease_timer < pmin_pool->lease_timer){ + minp = p; + minpre = pre; + } + pre = p; + p = p->pnext; + } + minpre->pnext = minp->pnext; + free(minp->pnode); + minp->pnode = NULL; + free(minp); + minp = NULL; +} + +void dhcps_coarse_tmr(void) +{ + u8_t num_dhcps_pool = 0; + list_node *pback_node = NULL; + list_node *pnode = NULL; + struct dhcps_pool *pdhcps_pool = NULL; + pnode = plist; + while (pnode != NULL) { + pdhcps_pool = pnode->pnode; + pdhcps_pool->lease_timer --; + if (pdhcps_pool->lease_timer == 0){ + pback_node = pnode; + pnode = pback_node->pnext; + node_remove_from_list(&plist,pback_node); + free(pback_node->pnode); + pback_node->pnode = NULL; + free(pback_node); + pback_node = NULL; + } else { + pnode = pnode ->pnext; + num_dhcps_pool ++; + } + } + + if (num_dhcps_pool >= MAX_STATION_NUM) + kill_oldest_dhcps_pool(); +} + +bool wifi_softap_set_dhcps_offer_option(u8_t level, void* optarg) +{ + bool offer_flag = true; + u8_t option = 0; + + if (optarg == NULL && get_dhcps_status() == false) + return false; + + if (level <= OFFER_START || level >= OFFER_END) + return false; + + switch (level){ + case OFFER_ROUTER: + offer = (*(u8_t *)optarg) & 0x01; + offer_flag = true; + break; + default : + offer_flag = false; + break; + } + return offer_flag; +} + +bool wifi_softap_set_dhcps_lease_time(u32_t minute) +{ + + if (get_dhcps_status() == DHCPS_STARTED) { + return false; + } + + if(minute == 0) { + return false; + } + dhcps_lease_time = minute; + return true; +} + +bool wifi_softap_reset_dhcps_lease_time(void) +{ + + if (get_dhcps_status() == DHCPS_STARTED) { + return false; + } + dhcps_lease_time = DHCPS_LEASE_TIME_DEF; + return true; +} + +u32_t wifi_softap_get_dhcps_lease_time(void) // minute +{ + return dhcps_lease_time; +} +#else +#include +#include +#include +#include "lwip/sys.h" +#include +#include +static os_timer_t micros_overflow_timer; +static uint32_t micros_at_last_overflow_tick = 0; +static uint32_t micros_overflow_count = 0; + +void micros_overflow_tick(void* arg) +{ + uint32_t m = system_get_time(); + if(m < micros_at_last_overflow_tick) + ++micros_overflow_count; + micros_at_last_overflow_tick = m; +} + +unsigned long millis() +{ + uint32_t m = system_get_time(); + uint32_t c = micros_overflow_count + ((m < micros_at_last_overflow_tick) ? 1 : 0); + return c * 4294967 + m / 1000; +} + +unsigned long micros() +{ + return system_get_time(); +} + +void dhcps_set_default_time(void) +{ + os_timer_disarm(µs_overflow_timer); + os_timer_setfn(µs_overflow_timer, (os_timer_func_t*) µs_overflow_tick, 0); + os_timer_arm(µs_overflow_timer, 60000, 1); +} + +time_t time(time_t * t) +{ + time_t seconds = millis(); + if (t) + { + *t = seconds; + } + return seconds; +} + +/* + * Initialize the binding list. + */ + +void +dhcp_binding_list_init (binding_list *list) +{ + STAILQ_INIT(list); +} + +/* + * Create a new binding + * + * The binding is added to the binding list, + * and a pointer to the binding is returned for further manipulations. + */ + +address_binding * +dhcp_binding_add (binding_list *list, uint32_t address, uint8_t *cident, uint8_t cident_len, int is_static) +{ + // fill binding + address_binding *binding = calloc(1, sizeof(*binding)); + + binding->address = address; + binding->cident_len = cident_len; + memcpy(binding->cident, cident, cident_len); + + binding->is_static = is_static; + + // add to binding list + STAILQ_INSERT_HEAD(list, binding, pointers); + + return binding; +} + +/* + * Updated bindings status, i.e. set to EXPIRED the status of the + * expired bindings. + */ + +void +dhcp_binding_statuses_update (binding_list *list) +{ + address_binding *binding, *binding_temp; + + STAILQ_FOREACH_SAFE(binding, list, pointers, binding_temp) + { + if(binding->binding_time + binding->lease_time < time(NULL)) + { + binding->status = EXPIRED; + } + } +} + +/* + * Search a static or dynamic binding having the given client identifier. + * + * If the is_static option is true a static binding will be searched, + * otherwise a dynamic one. If status is not zero, an binding with that + * status will be searched. + */ + +address_binding * +dhcp_binding_search (binding_list *list, uint8_t *cident, uint8_t cident_len, int is_static, int status) +{ + address_binding *binding, *binding_temp; + + STAILQ_FOREACH_SAFE(binding, list, pointers, binding_temp) + { + if((binding->is_static == is_static || is_static == STATIC_OR_DYNAMIC) && + binding->cident_len == cident_len && + memcmp(binding->cident, cident, cident_len) == 0) + { + if(status == 0) + return binding; + else if(status == binding->status) + return binding; + } + } + + return NULL; +} + +/* + * Get an available free address + * + * If a zero address is returned, no more address are available. + */ + +static uint32_t +dhcp_binding_take_free_address (pool_indexes *indexes) +{ + if(indexes->current <= indexes->last) + { + uint32_t address = indexes->current; + indexes->current = htonl(ntohl(indexes->current) + 1); + return address; + + } + else + return 0; +} + +/* + * Create a new dynamic binding or reuse an expired one. + * + * An attemp will be made to assign to the client the requested IP address + * contained in the address option. An address equals to zero means that no + * specific address has been requested. + * + * If the dynamic pool of addresses is full a NULL pointer will be returned. + */ + +address_binding * +dhcp_binding_new_dynamic (binding_list *list, pool_indexes *indexes, uint32_t address, uint8_t *cident, uint8_t cident_len) +{ + address_binding *binding, *binding_temp; + address_binding *found_binding = NULL; + + if (address != 0) + { + + STAILQ_FOREACH_SAFE(binding, list, pointers, binding_temp) + { + // search a previous binding using the requested IP address + + if(binding->address == address) + { + found_binding = binding; + break; + } + } + } + + if(found_binding != NULL && + !found_binding->is_static && + found_binding->status != PENDING && + found_binding->status != ASSOCIATED) + { + + // the requested IP address is available (reuse an expired association) + return found_binding; + + } + else + { + + /* the requested IP address is already in use, or no address has been + requested, or the address requested has never been allocated + (we do not support this last case and just return the next + available address!). */ + + uint32_t address = dhcp_binding_take_free_address(indexes); + + if(address != 0) + return dhcp_binding_add(list, address, cident, cident_len, 0); + + else // search any previously assigned address which is expired + { + + STAILQ_FOREACH_SAFE(binding, list, pointers, binding_temp) + { + if(!binding->is_static && + found_binding->status != PENDING && + found_binding->status != ASSOCIATED) + return binding; + } + + // if executions reach here no more addresses are available + return NULL; + } + } +} + +/* + * Delete an binding list and deallocate its memory. + * Deallocate even the list elements. + */ + +static void +dhcp_binding_list_delete (binding_list *list) +{ + address_binding *opt = STAILQ_FIRST(list); + address_binding *tmp; + + while (opt != NULL) + { + tmp = STAILQ_NEXT(opt, pointers); + free(opt); + opt = tmp; + } + + STAILQ_INIT(list); +} + +/* Value parsing functions: + * + * Parse the string pointed by s, and allocate the + * pointer p to contain the parsed data. + * + * On success return the size of the parsed data, + * on error return zero. + */ + +static int dhcp_option_byte (char *s, void **p); +static int dhcp_option_byte_list (char *s, void **p); +static int dhcp_option_short (char *s, void **p); +static int dhcp_option_short_list (char *s, void **p); +static int dhcp_option_long (char *s, void **p); +static int dhcp_option_string (char *s, void **p); +static int dhcp_option_ip (char *s, void **p); +static int dhcp_option_ip_list (char *s, void **p); + +/* Global pool */ +static const uint8_t dhcp_option_magic[4] = {0x63, 0x82, 0x53, 0x63}; +static address_pool dhcp_address_pool = {0}; + +/* + * Mapping table between DHCP options and + * functions that parse their value. + */ +static struct +{ + char *name; + int (*f) (char *, void **); +} dhcp_option_info [256] = +{ + [PAD] { "PAD", NULL }, + [END] { "END", NULL }, + [SUBNET_MASK] { "SUBNET_MASK", dhcp_option_ip }, + [TIME_OFFSET] { "TIME_OFFSET", dhcp_option_long }, + [ROUTER] { "ROUTER", dhcp_option_ip_list }, + [TIME_SERVER] { "TIME_SERVER", dhcp_option_ip_list }, + [NAME_SERVER] { "NAME_SERVER", dhcp_option_ip_list }, + [DOMAIN_NAME_SERVER] { "DOMAIN_NAME_SERVER", dhcp_option_ip_list }, + [LOG_SERVER] { "LOG_SERVER", dhcp_option_ip_list }, + [COOKIE_SERVER] { "COOKIE_SERVER", dhcp_option_ip_list }, + [LPR_SERVER] { "LPR_SERVER", dhcp_option_ip_list }, + [IMPRESS_SERVER] { "IMPRESS_SERVER", dhcp_option_ip_list }, + [RESOURCE_LOCATION_SERVER] { "RESOURCE_LOCATION_SERVER", dhcp_option_ip_list }, + [HOST_NAME] { "HOST_NAME", dhcp_option_string }, + [BOOT_FILE_SIZE] { "BOOT_FILE_SIZE", dhcp_option_short }, + [MERIT_DUMP_FILE] { "MERIT_DUMP_FILE", dhcp_option_string }, + [DOMAIN_NAME] { "DOMAIN_NAME", dhcp_option_string }, + [SWAP_SERVER] { "SWAP_SERVER", dhcp_option_ip }, + [ROOT_PATH] { "ROOT_PATH", dhcp_option_string }, + [EXTENSIONS_PATH] { "EXTENSIONS_PATH", dhcp_option_string }, + [IP_FORWARDING] { "IP_FORWARDING", dhcp_option_byte }, + [NON_LOCAL_SOURCE_ROUTING] { "NON_LOCAL_SOURCE_ROUTING", dhcp_option_byte }, + [POLICY_FILTER] { "POLICY_FILTER", dhcp_option_ip_list }, + [MAXIMUM_DATAGRAM_REASSEMBLY_SIZE] { "MAXIMUM_DATAGRAM_REASSEMBLY_SIZE", dhcp_option_short }, + [DEFAULT_IP_TIME_TO_LIVE] { "DEFAULT_IP_TIME_TO_LIVE", dhcp_option_byte }, + [PATH_MTU_AGING_TIMEOUT] { "PATH_MTU_AGING_TIMEOUT", dhcp_option_long }, + [PATH_MTU_PLATEAU_TABLE] { "PATH_MTU_PLATEAU_TABLE", dhcp_option_short_list }, + [INTERFACE_MTU] { "INTERFACE_MTU", dhcp_option_short }, + [ALL_SUBNETS_ARE_LOCAL] { "ALL_SUBNETS_ARE_LOCAL", dhcp_option_byte }, + [BROADCAST_ADDRESS] { "BROADCAST_ADDRESS", dhcp_option_ip }, + [PERFORM_MASK_DISCOVERY] { "PERFORM_MASK_DISCOVERY", dhcp_option_byte }, + [MASK_SUPPLIER] { "MASK_SUPPLIER", dhcp_option_byte }, + [PERFORM_ROUTER_DISCOVERY] { "PERFORM_ROUTER_DISCOVERY", dhcp_option_byte }, + [ROUTER_SOLICITATION_ADDRESS] { "ROUTER_SOLICITATION_ADDRESS", dhcp_option_ip }, + [STATIC_ROUTE] { "STATIC_ROUTE", dhcp_option_ip_list }, + [TRAILER_ENCAPSULATION] { "TRAILER_ENCAPSULATION", dhcp_option_byte }, + [ARP_CACHE_TIMEOUT] { "ARP_CACHE_TIMEOUT", dhcp_option_long }, + [ETHERNET_ENCAPSULATION] { "ETHERNET_ENCAPSULATION", dhcp_option_byte }, + [TCP_DEFAULT_TTL] { "TCP_DEFAULT_TTL", dhcp_option_byte }, + [TCP_KEEPALIVE_INTERVAL] { "TCP_KEEPALIVE_INTERVAL", dhcp_option_long }, + [TCP_KEEPALIVE_GARBAGE] { "TCP_KEEPALIVE_GARBAGE", dhcp_option_byte }, + [NETWORK_INFORMATION_SERVICE_DOMAIN] { "NETWORK_INFORMATION_SERVICE_DOMAIN", dhcp_option_string }, + [NETWORK_INFORMATION_SERVERS] { "NETWORK_INFORMATION_SERVERS", dhcp_option_ip_list }, + [NETWORK_TIME_PROTOCOL_SERVERS] { "NETWORK_TIME_PROTOCOL_SERVERS", dhcp_option_ip_list }, + [VENDOR_SPECIFIC_INFORMATION] { "VENDOR_SPECIFIC_INFORMATION", dhcp_option_byte_list }, + [NETBIOS_OVER_TCP_IP_NAME_SERVER] { "NETBIOS_OVER_TCP_IP_NAME_SERVER", dhcp_option_ip_list }, + [NETBIOS_OVER_TCP_IP_DATAGRAM_DISTRIBUTION_SERVER] { "NETBIOS_OVER_TCP_IP_DATAGRAM_DISTRIBUTION_SERVER", dhcp_option_ip_list }, + [NETBIOS_OVER_TCP_IP_NODE_TYPE] { "NETBIOS_OVER_TCP_IP_NODE_TYPE", dhcp_option_byte }, + [NETBIOS_OVER_TCP_IP_SCOPE] { "NETBIOS_OVER_TCP_IP_SCOPE", dhcp_option_string }, + [X_WINDOW_SYSTEM_FONT_SERVER] { "X_WINDOW_SYSTEM_FONT_SERVER", dhcp_option_ip_list }, + [X_WINDOW_SYSTEM_DISPLAY_MANAGER] { "X_WINDOW_SYSTEM_DISPLAY_MANAGER", dhcp_option_ip_list }, + [NETWORK_INFORMATION_SERVICE_PLUS_DOMAIN] { "NETWORK_INFORMATION_SERVICE_PLUS_DOMAIN", dhcp_option_string }, + [NETWORK_INFORMATION_SERVICE_PLUS_SERVERS] { "NETWORK_INFORMATION_SERVICE_PLUS_SERVERS", dhcp_option_ip_list }, + [MOBILE_IP_HOME_AGENT] { "MOBILE_IP_HOME_AGENT", dhcp_option_ip_list }, + [SMTP_SERVER] { "SMTP_SERVER", dhcp_option_ip_list }, + [POP3_SERVER] { "POP3_SERVER", dhcp_option_ip_list }, + [NNTP_SERVER] { "NNTP_SERVER", dhcp_option_ip_list }, + [DEFAULT_WWW_SERVER] { "DEFAULT_WWW_SERVER", dhcp_option_ip_list }, + [DEFAULT_FINGER_SERVER] { "DEFAULT_FINGER_SERVER", dhcp_option_ip_list }, + [DEFAULT_IRC_SERVER] { "DEFAULT_IRC_SERVER", dhcp_option_ip_list }, + [STREETTALK_SERVER] { "STREETTALK_SERVER", dhcp_option_ip_list }, + [STREETTALK_DIRECTORY_ASSISTANCE_SERVER] { "STREETTALK_DIRECTORY_ASSISTANCE_SERVER", dhcp_option_ip_list }, + [REQUESTED_IP_ADDRESS] { "REQUESTED_IP_ADDRESS", NULL }, + [IP_ADDRESS_LEASE_TIME] { "IP_ADDRESS_LEASE_TIME", dhcp_option_long }, + [OPTION_OVERLOAD] { "OPTION_OVERLOAD", dhcp_option_byte }, + [TFTP_SERVER_NAME] { "TFTP_SERVER_NAME", dhcp_option_string }, + [BOOTFILE_NAME] { "BOOTFILE_NAME", dhcp_option_string }, + [DHCP_MESSAGE_TYPE] { "DHCP_MESSAGE_TYPE", NULL }, + [SERVER_IDENTIFIER] { "SERVER_IDENTIFIER", dhcp_option_ip }, + [PARAMETER_REQUEST_LIST] { "PARAMETER_REQUEST_LIST", NULL }, + [MESSAGE] { "MESSAGE", NULL }, + [MAXIMUM_DHCP_MESSAGE_SIZE] { "MAXIMUM_DHCP_MESSAGE_SIZE", NULL }, + [RENEWAL_T1_TIME_VALUE] { "RENEWAL_T1_TIME_VALUE", dhcp_option_long }, + [REBINDING_T2_TIME_VALUE] { "REBINDING_T2_TIME_VALUE", dhcp_option_long }, + [VENDOR_CLASS_IDENTIFIER] { "VENDOR_CLASS_IDENTIFIER", NULL }, + [CLIENT_IDENTIFIER] { "CLIENT_IDENTIFIER", NULL }, + + [USER_CLASS] { "USER_CLASS", NULL }, + [FQDN] { "FQDN", NULL }, + [DHCP_AGENT_OPTIONS] { "DHCP_AGENT_OPTIONS", NULL }, + [NDS_SERVERS] { "NDS_SERVERS", NULL }, + [NDS_TREE_NAME] { "NDS_TREE_NAME", NULL }, + [NDS_CONTEXT] { "NDS_CONTEXT", NULL }, + [CLIENT_LAST_TRANSACTION_TIME] { "CLIENT_LAST_TRANSACTION_TIME", NULL }, + [ASSOCIATED_IP] { "ASSOCIATED_IP", NULL }, + [USER_AUTHENTICATION_PROTOCOL] { "USER_AUTHENTICATION_PROTOCOL", NULL }, + [AUTO_CONFIGURE] { "AUTO_CONFIGURE", NULL }, + [NAME_SERVICE_SEARCH] { "NAME_SERVICE_SEARCH", dhcp_option_string }, + [SUBNET_SELECTION] { "SUBNET_SELECTION", NULL }, + [DOMAIN_SEARCH] { "DOMAIN_SEARCH", dhcp_option_string }, + [CLASSLESS_ROUTE] { "CLASSLESS_ROUTE", dhcp_option_string }, +}; + +/* Value parsing functions */ + +static int +dhcp_option_byte (char *s, void **p) +{ + *p = malloc(sizeof(uint8_t)); + uint8_t n = ((uint8_t) strtol(s, NULL, 0)); + memcpy(*p, &n, sizeof(n)); + + return sizeof(uint8_t); +} + +static int +dhcp_option_byte_list (char *s, void **p) +{ + *p = malloc(strlen(s) * sizeof(uint8_t)); // slightly over the strictly requested size + + int count = 0; + + char *s2 = strdup(s); + char *s3 = strtok(s2, ", "); + + while(s3 != NULL) + { + + uint8_t n = ((uint8_t) strtol(s3, NULL, 0)); + + memcpy(((uint8_t *) *p) + count, &n, sizeof(uint8_t)); + + count += sizeof(uint8_t); + s3 = strtok(NULL, " "); + } + + free(s2); + + return count; +} + +static int +dhcp_option_short (char *s, void **p) +{ + *p = malloc(sizeof(uint16_t)); + uint16_t n = ((uint16_t) strtol(s, NULL, 0)); + memcpy(*p, &n, sizeof(n)); + + return sizeof(uint16_t); +} + +static int +dhcp_option_short_list (char *s, void **p) +{ + *p = malloc(strlen(s) * sizeof(uint16_t)); // slightly over the strictly requested size + + int count = 0; + + char *s2 = strdup(s); + char *s3 = strtok(s2, ", "); + + while(s3 != NULL) + { + + uint16_t n = ((uint16_t) strtol(s3, NULL, 0)); + + memcpy(((uint8_t *) *p) + count, &n, sizeof(uint16_t)); + + count += sizeof(uint16_t); + s3 = strtok(NULL, " "); + } + + free(s2); + + return count; +} + +static int +dhcp_option_long (char *s, void **p) +{ + *p = malloc(sizeof(uint32_t)); + uint32_t n = strtol(s, NULL, 0); + memcpy(*p, &n, sizeof(n)); + + return sizeof(uint32_t); +} + +static int +dhcp_option_string (char *s, void **p) +{ + *p = strdup(s); + + return strlen(s); +} + +static int +dhcp_option_ip (char *s, void **p) +{ + struct sockaddr_in ip; + + *p = malloc(sizeof(uint32_t)); + + if (inet_aton(s, &ip.sin_addr) == 0) // error: invalid IP address + { + free(*p); + return 0; + } + + memcpy(*p, &ip.sin_addr, sizeof(uint32_t)); + + return sizeof(uint32_t); +} + +static int +dhcp_option_ip_list (char *s, void **p) +{ + *p = malloc(strlen(s) * sizeof(uint32_t) / 4); // slightly over the strictly required size + + int count = 0; + + char *s2 = strdup(s); + char *s3 = strtok(s2, ", "); + + while(s3 != NULL) + { + struct sockaddr_in ip; + + if (inet_aton(s3, &ip.sin_addr) == 0) // error: invalid IP address + { + free(*p); + return 0; + } + + memcpy(((uint8_t *) *p) + count, &ip.sin_addr, sizeof(uint32_t)); + + count += sizeof(uint32_t); + s3 = strtok(NULL, " "); + } + + free(s2); + + return count; +} + +/* Option-related functions */ + +/* + * Given the name of the option and its value as strings, + * fill the dhcp_option structure pointed by opt. + * + * On success return the parsed option id, + * otherwise return zero. + */ +static uint8_t +dhcp_option_parse (dhcp_option *opt, char *name, char *value) +{ + int (*f) (char *, void **); + int id; + + uint8_t len; + uint8_t *p; + + for (id = 0; id < 256; id++) // search the option by name + { + if (dhcp_option_info[id].name && + strcmp(dhcp_option_info[id].name, name) == 0) break; + } + + if (id == 256) // not found + { + log_info("Unsupported DHCP option '%s'", name); + return 0; + } + + f = dhcp_option_info[id].f; + + if (f == NULL) // no parsing function available + { + log_info("Unsupported DHCP option '%s'", name); + return 0; + } + + len = f(value, (void **)&p); // parse the value + + if(len == 0) // error parsing the value + return 0; + + // structure filling + opt->id = id; + opt->len = len; + memcpy(opt->data, p, len); + + free(p); + + return opt->id; +} + +/* + * Initialize an option list. + */ + +static void +dhcp_option_list_init (dhcp_option_list *list) +{ + STAILQ_INIT(list); +} + +/* + * Given a list of options search an option having + * the passed option id, and returns a pointer to it. + * + * If the option is not present the function returns NULL. + */ + +static dhcp_option * +dhcp_option_search (dhcp_option_list *list, uint8_t id) +{ + dhcp_option *opt, *opt_temp; + + STAILQ_FOREACH_SAFE(opt, list, pointers, opt_temp) + { + + if(opt->id == id) + return opt; + + } + + return NULL; +} + +/* + * Print options in list. + */ + +static void +dhcp_option_print (dhcp_option_list *list) +{ + dhcp_option *opt, *opt_temp; + int i=0; + + STAILQ_FOREACH_SAFE(opt, list, pointers, opt_temp) + { + + printf("options[%d]=%d (%s)\n", i++, opt->id, + dhcp_option_info[opt->id].name); + + } +} + + +/* + * Append the provided option to the list. + * + * Always allocate new memory, that must be freed later... + */ + +static void +dhcp_option_append (dhcp_option_list *list, dhcp_option *opt) +{ + dhcp_option *nopt = calloc(1, sizeof(*nopt)); + memcpy(nopt, opt, 2 + opt->len); + + STAILQ_INSERT_TAIL(list, nopt, pointers); +} + +/* + * Parse the options contained in a DHCP message into a list. + * + * Return 1 on success, 0 if the options are malformed. + */ + +static int +dhcp_option_parse_to_list (dhcp_option_list *list, dhcp_option *opts, size_t len) +{ + dhcp_option *opt, *end; + + opt = opts; + end = (dhcp_option *)(((uint8_t *)opts) + len); + + if (len < 4 || + memcmp(opt, dhcp_option_magic, sizeof(dhcp_option_magic)) != 0) + return 0; + + opt = (dhcp_option *)(((uint8_t *) opt) + 4); + + while (opt < end && + opt->id != END) // TODO: check also valid option sizes + { + + if ((dhcp_option *)(((uint8_t *) opt) + 2 + opt->len) >= end) + return 0; // the len field is too long + + dhcp_option_append(list, opt); + + opt = (dhcp_option *)(((uint8_t *) opt) + 2 + opt->len); + } + + if (opt < end && opt->id == END) + return 1; + + return 0; +} + +/* + * Serialize a list of options, to be inserted directly inside + * the options section of a DHCP message. + * + * Return 0 on error, the total serialized len on success. + */ + +static size_t +dhcp_option_list_serialize (dhcp_option_list *list, uint8_t *buf, size_t len) +{ + uint8_t *p = buf; + + if (len < 4) + return 0; + + memcpy(p, dhcp_option_magic, sizeof(dhcp_option_magic)); + p += 4; + len -= 4; + + dhcp_option *opt, *opt_temp; + + STAILQ_FOREACH_SAFE(opt, list, pointers, opt_temp) + { + + if (len <= 2 + opt->len) + return 0; + + memcpy(p, opt, 2 + opt->len); + p += 2 + opt->len; + len -= 2 + opt->len; + + } + + if (len < 1) + return 0; + + *p = END; + + p++; + len--; + + return p - buf; +} + +/* + * Delete an option list and deallocate its memory. + * Deallocate even the list elements. + */ + +static void +dhcp_option_list_delete (dhcp_option_list *list) +{ + dhcp_option *opt = STAILQ_FIRST(list); + dhcp_option *tmp; + + while (opt != NULL) + { + tmp = STAILQ_NEXT(opt, pointers); + free(opt); + opt = tmp; + } + + STAILQ_INIT(list); +} + +static void dhcp_options_default_fill(dhcp_option_list *list, dhcp_option_list *reply_opts) +{ + dhcp_option *opt, *opt_temp; + int i = 0; + + STAILQ_FOREACH_SAFE(opt, list, pointers, opt_temp) + { + log_info("options[%d]=%d (%s)\n", i++, opt->id, dhcp_option_info[opt->id].name); + + if (opt != NULL) + dhcp_option_append(reply_opts, opt); + } +} + +static void +dhcp_options_requested_fill (dhcp_option *requested_opts, dhcp_option_list *reply_opts) +{ + uint8_t len = requested_opts->len; + uint8_t *id = requested_opts->data; + + int i = 0; + for (i = 0; i < len; i++) + { + if(id[i] != 0) + { + dhcp_option *opt = dhcp_option_search(&dhcp_address_pool.options, id[i]); + + if(opt != NULL) + dhcp_option_append(reply_opts, opt); + } + } + dhcp_option_print(reply_opts); +} + +static bool dhcp_options_add(char* name, char* value) +{ + uint8_t id = 0; + bool flags = true; + REQUIRE_ACTION(name, add_error, flags = false); + REQUIRE_ACTION(value, add_error, flags = false); + dhcp_option *option = calloc(1, sizeof(*option)); + REQUIRE_ACTION(option, add_error, flags = false); + id = dhcp_option_parse(option, name, value); + if (id == 0) + { + log_info( "error: invalid dhcp option specified: %s,%s",name, value); + REQUIRE_ACTION(option, add_error, flags = false); + } + + dhcp_option_append(&dhcp_address_pool.options, option); + + if(option->id == IP_ADDRESS_LEASE_TIME) + dhcp_address_pool.lease_time = ntohl(*((uint32_t *)option->data)); + +add_error: + free(option); + return flags; +} + +/* + * Message handling routines. + */ + +static uint8_t dhcp_request_expand (dhcps_msg *request, size_t len) +{ + dhcp_option_list_init(&request->opts); + + if (request->hdr.hlen < 1 || request->hdr.hlen > 16) + return 0; + + if (dhcp_option_parse_to_list(&request->opts, (dhcp_option *)request->hdr.options, len - DHCP_HEADER_SIZE) == 0) + return 0; + + dhcp_option *type_opt = dhcp_option_search(&request->opts, DHCP_MESSAGE_TYPE); + + if (type_opt == NULL) + return 0; + + uint8_t type = type_opt->data[0]; + + return type; +} + +static int +dhcp_reply_init (dhcps_msg *request, dhcps_msg *reply) +{ + memset(&reply->hdr, 0, sizeof(reply->hdr)); + + dhcp_option_list_init(&reply->opts); + + reply->hdr.op = BOOTREPLY; + + reply->hdr.htype = request->hdr.htype; + reply->hdr.hlen = request->hdr.hlen; + + reply->hdr.xid = request->hdr.xid; + reply->hdr.flags = request->hdr.flags; + + reply->hdr.giaddr = request->hdr.giaddr; + + memcpy(reply->hdr.chaddr, request->hdr.chaddr, request->hdr.hlen); + + return 1; +} + +static int dhcp_reply_send(struct udp_pcb *pcb, ip_addr_t *addr, dhcps_msg *reply) +{ + size_t len = 0, ret = 0; + struct pbuf *p = NULL, *q = NULL; + u8_t *data = NULL; + u16_t cnt = 0; + u16_t i = 0; + + len = dhcp_option_list_serialize(&reply->opts, reply->hdr.options, sizeof(reply->hdr) - DHCP_HEADER_SIZE); + len += DHCP_HEADER_SIZE; + + dhcp_option *type_opt = dhcp_option_search(&reply->opts, DHCP_MESSAGE_TYPE); + if (type_opt == NULL) + return -1; + +// if (type_opt->data[0] == DHCP_OFFER) + addr->u_addr.ip4.addr = INADDR_BROADCAST; +// else +// ip4_addr_set(ip_2_ip4(addr), &reply->hdr.yiaddr); // use the address assigned by us + + if (reply->hdr.yiaddr.addr != 0) + { + log_info("send_dhcp_reply %s\n", inet_ntoa(*addr)); + } + + p = pbuf_alloc(PBUF_TRANSPORT, len, PBUF_RAM); + + if (p != NULL) + { + q = p; + while (q != NULL) + { + data = (u8_t *)q->payload; + for (i = 0; i< q->len; i++) + { + data[i] = ((u8_t *) reply)[cnt++]; + } + + q = q->next; + } + } + else + { + return 0; + } + + ret = udp_sendto(pcb, p, addr, BOOTPC); + log_info("dhcp_send %d %d\n", ret, p->ref); + if(p->ref != 0) + { + pbuf_free(p); + } + + return ret; +} + +static int +dhcp_reply_fill (dhcps_msg *request, dhcps_msg *reply, + address_binding *binding, uint8_t type) +{ + static dhcp_option type_opt, server_id_opt; + + type_opt.id = DHCP_MESSAGE_TYPE; + type_opt.len = 1; + type_opt.data[0] = type; + dhcp_option_append(&reply->opts, &type_opt); + + server_id_opt.id = SERVER_IDENTIFIER; + server_id_opt.len = 4; + memcpy(server_id_opt.data, &dhcp_address_pool.server_id, sizeof(dhcp_address_pool.server_id)); + dhcp_option_append(&reply->opts, &server_id_opt); + + if(binding != NULL) + { + reply->hdr.yiaddr.addr = binding->address; + } + + if (type != DHCPS_NAK) + { + dhcp_option *requested_opts = dhcp_option_search(&request->opts, PARAMETER_REQUEST_LIST); + + if (requested_opts) + dhcp_options_default_fill(&dhcp_address_pool.options, &reply->opts); + } + + return type; +} + +static int +dhcp_discover (dhcps_msg *request, dhcps_msg *reply) +{ + address_binding *binding = NULL; + binding = dhcp_binding_search(&dhcp_address_pool.bindings, request->hdr.chaddr, request->hdr.hlen, STATIC, EMPTY); + + if (binding) + { + /* a static binding has been configured for this client */ + log_info("%s %d %p",__FILE__, __LINE__, binding); + } + else + { + /* use dynamic pool */ + /* If an address is available, the new address SHOULD be chosen as follows: */ + binding = dhcp_binding_search(&dhcp_address_pool.bindings, request->hdr.chaddr,request->hdr.hlen, DYNAMIC, EMPTY); + + if (binding) + { + /* The client's current address as recorded in the client's current + binding, ELSE */ + + /* The client's previous address as recorded in the client's (now + expired or released) binding, if that address is in the server's + pool of available addresses and not already allocated, ELSE */ + log_info("%s %d %p",__FILE__, __LINE__, binding); + } + else + { + /* The address requested in the 'Requested IP Address' option, if that + address is valid and not already allocated, ELSE */ + + /* A new address allocated from the server's pool of available + addresses; the address is selected based on the subnet from which + the message was received (if 'giaddr' is 0) or on the address of + the relay agent that forwarded the message ('giaddr' when not 0). */ + + /* extract requested IP address */ + uint32_t address = 0; + dhcp_option *address_opt = dhcp_option_search(&request->opts, REQUESTED_IP_ADDRESS); + + if (address_opt != NULL) + memcpy(&address, address_opt->data, sizeof(address)); + + binding = dhcp_binding_new_dynamic(&dhcp_address_pool.bindings, &dhcp_address_pool.indexes, address, request->hdr.chaddr, request->hdr.hlen); + + if (binding == NULL) + { + log_info("Can not offer an address, no address available."); + return 0; + } + } + } + + if (binding->binding_time + binding->lease_time < time(NULL)) + { + log_info("%s %d %p",__FILE__, __LINE__, binding); + binding->status = PENDING; + binding->binding_time = time(NULL); + binding->lease_time = dhcp_address_pool.pending_time; + } + + return dhcp_reply_fill(request, reply, binding, DHCPS_OFFER); +} + +static int +dhcp_request (dhcps_msg *request, dhcps_msg *reply) +{ + address_binding *binding = dhcp_binding_search(&dhcp_address_pool.bindings, request->hdr.chaddr, request->hdr.hlen, STATIC_OR_DYNAMIC, PENDING); + + uint32_t server_id = 0; + dhcp_option *server_id_opt = dhcp_option_search(&request->opts, SERVER_IDENTIFIER); + + if (server_id_opt != NULL) + memcpy(&server_id, server_id_opt->data, sizeof(server_id)); + + if (server_id == dhcp_address_pool.server_id) + { + /* this request is an answer to our offer */ + if (binding != NULL) + { + log_info("Ack, associated"); + + binding->status = ASSOCIATED; + binding->lease_time = dhcp_address_pool.lease_time; + + return dhcp_reply_fill(request, reply, binding, DHCPS_ACK); + } + else + { + log_info("Nak, not associated"); + + return dhcp_reply_fill(request, reply, NULL, DHCPS_NAK); + } + + } + else if (server_id != 0) + { + /* this request is an answer to another offer */ + + binding->status = EMPTY; + binding->lease_time = 0; + + return 0; + } + + return 0; +} + +static int +dhcp_decline (dhcps_msg *request, dhcps_msg *reply) +{ + address_binding *binding = NULL; + binding = dhcp_binding_search(&dhcp_address_pool.bindings, request->hdr.chaddr, request->hdr.hlen, STATIC_OR_DYNAMIC, PENDING); + if(binding != NULL) + { + binding->status = EMPTY; + } + + return 0; +} + +static int +dhcp_release (dhcps_msg *request, dhcps_msg *reply) +{ + address_binding *binding = NULL; + binding = dhcp_binding_search(&dhcp_address_pool.bindings, request->hdr.chaddr, request->hdr.hlen, STATIC_OR_DYNAMIC, ASSOCIATED); + if(binding != NULL) + { + binding->status = RELEASED; + } + + return 0; +} + +static int +dhcp_inform (dhcps_msg *request, dhcps_msg *reply) +{ + return dhcp_reply_fill(request, reply, NULL, DHCPS_ACK); +} + +/** + * If an incoming DHCP message is in response to us, then trigger the state machine. + * + * Dispatch client DHCP messages to the correct handling routines + * + */ +static void dhcp_recv(void *arg, struct udp_pcb *pcb, struct pbuf *p, const ip_addr_t *addr, u16_t port) +{ + struct netif *netif = ip_current_input_netif(); + + struct pbuf *pthis = NULL; + + LWIP_UNUSED_ARG(arg); + LWIP_ASSERT("invalid server address type", !IP_IS_V6(addr)); + /* prevent warnings about unused arguments */ + LWIP_UNUSED_ARG(pcb); + LWIP_UNUSED_ARG(addr); + LWIP_UNUSED_ARG(port); + uint8_t type = 0; + dhcps_msg *request = calloc(1, sizeof(dhcps_msg)); + REQUIRE_ACTION(request, free_pbuf_and_return, 0); + dhcps_msg *reply = calloc(1, sizeof(dhcps_msg)); + REQUIRE_ACTION(reply, free_pbuf_and_return, 0); + size_t len = 0; + len = pbuf_copy_partial(p, &request->hdr, p->tot_len, 0); + if (len < DHCP_HEADER_SIZE + 5) + { + goto free_pbuf_and_return; + } + else + { + if (request->hdr.op != BOOTREQUEST) + { + goto free_pbuf_and_return; + } + else + { + type = dhcp_request_expand(request, len); + dhcp_reply_init(request, reply); + switch (type) + { + case DHCPS_DISCOVER: + type = dhcp_discover(request, reply); + break; + + case DHCPS_REQUEST: + type = dhcp_request(request, reply); + break; + + case DHCPS_DECLINE: + type = dhcp_decline(request, reply); + break; + + case DHCPS_RELEASE: + type = dhcp_release(request, reply); + break; + + case DHCPS_INFORM: + type = dhcp_inform(request, reply); + break; + + default: + log_info("%s.%u: request with invalid DHCP message type option",inet_ntoa(addr), port); + break; + } + + if (type != DHCP_NONE) + dhcp_reply_send(pcb, (ip_addr_t *)addr, reply); + + dhcp_option_list_delete(&request->opts); + dhcp_option_list_delete(&reply->opts); + } + } + +free_pbuf_and_return: + if (request != NULL) + free(request); + + if (reply != NULL) + free(reply); + pbuf_free(p); +} + +void dhcps_set_default_option(struct dhcps_lease *pool_addr) +{ + ip4_addr_t server_ip, broadcast, dns; + REQUIRE_ASSERT(pool_addr); + address_pool *dhcps_addr_pool = &dhcp_address_pool; + + if (dhcps_addr_pool->flags){ + + } else{ + dhcp_option_list_init(&dhcps_addr_pool->options); + dhcps_addr_pool->flags = true; + } + + /* Load configuration */ + dhcps_option_set(IP_ADDRESS_LEASE_TIME, "36000"); + dhcps_option_set(SUBNET_MASK, inet_ntoa(pool_addr->net_mask)); + + server_ip.addr = dhcps_addr_pool->server_id; + dhcps_option_set(ROUTER, inet_ntoa(server_ip)); + + broadcast.addr = server_ip.addr | ~(pool_addr->net_mask.addr); + dhcps_option_set(BROADCAST_ADDRESS,inet_ntoa(broadcast)); + + dns.addr = DHCP_SERVER_OPENDNS; + dhcps_option_set(DOMAIN_NAME_SERVER, inet_ntoa(dns)); +} + +static void dhcps_set_default_binding(address_pool *pool_addr) +{ + REQUIRE_ASSERT(pool_addr); + dhcp_binding_list_init(&pool_addr->bindings); +} + +static address_pool* dhcps_try_open_socket(address_pool *pool_addr) +{ + REQUIRE_ASSERT(pool_addr); + pool_addr->socket = udp_new(); + REQUIRE_ASSERT(pool_addr->socket); + udp_bind(pool_addr->socket, IP_ADDR_ANY, BOOTPS); + udp_recv(pool_addr->socket, dhcp_recv, pool_addr); + return pool_addr; +} + +void dhcps_start(struct netif *netif, struct dhcps_lease *lease_pool) +{ + REQUIRE_ASSERT(netif); + REQUIRE_ASSERT(lease_pool); + + dhcp_address_pool.server_id = netif->ip_addr.u_addr.ip4.addr; + dhcps_set_default_time(); + dhcps_set_default_binding(&dhcp_address_pool); + dhcps_set_default_option(lease_pool); + dhcps_try_open_socket(&dhcp_address_pool); +} + +void dhcps_stop(struct netif *netif ) +{ + dhcp_binding_list_delete(&dhcp_address_pool.bindings); + dhcp_option_list_delete(&dhcp_address_pool.options); + udp_remove(dhcp_address_pool.socket); + dhcp_address_pool.flags = false; +// memset(&dhcp_address_pool, 0, sizeof(address_pool)); +} + +bool dhcps_lease_set(struct dhcps_lease *please) +{ + REQUIRE_ASSERT(please); + + dhcp_address_pool.indexes.first = please->start_ip.addr; + dhcp_address_pool.indexes.last = please->end_ip.addr; + dhcp_address_pool.indexes.current = please->start_ip.addr; + + return true; +} + +bool dhcps_lease_get(struct dhcps_lease *please) +{ + REQUIRE_ASSERT(please); + please->start_ip.addr = dhcp_address_pool.indexes.first; + please->end_ip.addr = dhcp_address_pool.indexes.last; + please->net_mask.addr = inet_addr("255.255.255.0"); + return true; +} + +bool dhcps_option_set(u8_t opt_id, void* optarg) +{ + if (dhcp_address_pool.flags){ + dhcp_option *opt = dhcp_option_search(&dhcp_address_pool.options, opt_id); + if (opt) + { + opt->len = strlen(optarg); + memset(opt->data, 0, sizeof(opt->data)); + memcpy(opt->data, optarg, opt->len); + return true; + } + else + { + return dhcp_options_add(dhcp_option_info[opt_id].name, optarg); + } + } else{ + dhcp_option_list_init(&dhcp_address_pool.options); + dhcp_address_pool.flags = true; + return dhcp_options_add(dhcp_option_info[opt_id].name, optarg); + } +} + +bool wifi_softap_set_dhcps_lease(struct dhcps_lease *please) +{ + return false; +} + +bool wifi_softap_set_dhcps_lease_time(u32_t minute) +{ + return false; +} + +#endif /*ifdef LWIP_ESP8266*/ + + + + + diff --git a/components/lwip/core/def.c b/components/lwip/core/def.c new file mode 100755 index 0000000000..bb4b8e01fc --- /dev/null +++ b/components/lwip/core/def.c @@ -0,0 +1,108 @@ +/** + * @file + * Common functions used throughout the stack. + * + */ + +/* + * Copyright (c) 2001-2004 Swedish Institute of Computer Science. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Simon Goldschmidt + * + */ + +#include "lwip/opt.h" +#include "lwip/def.h" + +/** + * These are reference implementations of the byte swapping functions. + * Again with the aim of being simple, correct and fully portable. + * Byte swapping is the second thing you would want to optimize. You will + * need to port it to your architecture and in your cc.h: + * + * #define LWIP_PLATFORM_BYTESWAP 1 + * #define LWIP_PLATFORM_HTONS(x) + * #define LWIP_PLATFORM_HTONL(x) + * + * Note ntohs() and ntohl() are merely references to the htonx counterparts. + */ + +#if (LWIP_PLATFORM_BYTESWAP == 0) && (BYTE_ORDER == LITTLE_ENDIAN) + +/** + * Convert an u16_t from host- to network byte order. + * + * @param n u16_t in host byte order + * @return n in network byte order + */ +u16_t +lwip_htons(u16_t n) +{ + return ((n & 0xff) << 8) | ((n & 0xff00) >> 8); +} + +/** + * Convert an u16_t from network- to host byte order. + * + * @param n u16_t in network byte order + * @return n in host byte order + */ +u16_t +lwip_ntohs(u16_t n) +{ + return lwip_htons(n); +} + +/** + * Convert an u32_t from host- to network byte order. + * + * @param n u32_t in host byte order + * @return n in network byte order + */ +u32_t +lwip_htonl(u32_t n) +{ + return ((n & 0xff) << 24) | + ((n & 0xff00) << 8) | + ((n & 0xff0000UL) >> 8) | + ((n & 0xff000000UL) >> 24); +} + +/** + * Convert an u32_t from network- to host byte order. + * + * @param n u32_t in network byte order + * @return n in host byte order + */ +u32_t +lwip_ntohl(u32_t n) +{ + return lwip_htonl(n); +} + +#endif /* (LWIP_PLATFORM_BYTESWAP == 0) && (BYTE_ORDER == LITTLE_ENDIAN) */ diff --git a/components/lwip/core/dns.c b/components/lwip/core/dns.c new file mode 100755 index 0000000000..da8ac95b8d --- /dev/null +++ b/components/lwip/core/dns.c @@ -0,0 +1,1500 @@ +/** + * @file + * DNS - host name to IP address resolver. + * + */ + +/** + + * This file implements a DNS host name to IP address resolver. + + * Port to lwIP from uIP + * by Jim Pettinato April 2007 + + * security fixes and more by Simon Goldschmidt + + * uIP version Copyright (c) 2002-2003, Adam Dunkels. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote + * products derived from this software without specific prior + * written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * + * DNS.C + * + * The lwIP DNS resolver functions are used to lookup a host name and + * map it to a numerical IP address. It maintains a list of resolved + * hostnames that can be queried with the dns_lookup() function. + * New hostnames can be resolved using the dns_query() function. + * + * The lwIP version of the resolver also adds a non-blocking version of + * gethostbyname() that will work with a raw API application. This function + * checks for an IP address string first and converts it if it is valid. + * gethostbyname() then does a dns_lookup() to see if the name is + * already in the table. If so, the IP is returned. If not, a query is + * issued and the function returns with a ERR_INPROGRESS status. The app + * using the dns client must then go into a waiting state. + * + * Once a hostname has been resolved (or found to be non-existent), + * the resolver code calls a specified callback function (which + * must be implemented by the module that uses the resolver). + */ + +/*----------------------------------------------------------------------------- + * RFC 1035 - Domain names - implementation and specification + * RFC 2181 - Clarifications to the DNS Specification + *----------------------------------------------------------------------------*/ + +/** @todo: define good default values (rfc compliance) */ +/** @todo: improve answer parsing, more checkings... */ +/** @todo: check RFC1035 - 7.3. Processing responses */ + +/*----------------------------------------------------------------------------- + * Includes + *----------------------------------------------------------------------------*/ + +#include "lwip/opt.h" + +#if LWIP_DNS /* don't build if not configured for use in lwipopts.h */ + +#include "lwip/udp.h" +#include "lwip/mem.h" +#include "lwip/memp.h" +#include "lwip/dns.h" + +#include + +#ifdef MEMLEAK_DEBUG +static const char mem_debug_file[] ICACHE_RODATA_ATTR STORE_ATTR = __FILE__; +#endif + +/** Random generator function to create random TXIDs and source ports for queries */ +#ifndef DNS_RAND_TXID +#if ((LWIP_DNS_SECURE & LWIP_DNS_SECURE_RAND_XID) != 0) +#define DNS_RAND_TXID LWIP_RAND +#else +static u16_t dns_txid; +#define DNS_RAND_TXID() (++dns_txid) +#endif +#endif + +/** Limits the source port to be >= 1024 by default */ +#ifndef DNS_PORT_ALLOWED +#define DNS_PORT_ALLOWED(port) ((port) >= 1024) +#endif + +/** DNS server port address */ +#ifndef DNS_SERVER_PORT +#define DNS_SERVER_PORT 53 +#endif + +/** DNS maximum number of retries when asking for a name, before "timeout". */ +#ifndef DNS_MAX_RETRIES +#define DNS_MAX_RETRIES 4 +#endif + +/** DNS resource record max. TTL (one week as default) */ +#ifndef DNS_MAX_TTL +#define DNS_MAX_TTL 604800 +#endif + +/* The number of parallel requests (i.e. calls to dns_gethostbyname + * that cannot be answered from the DNS table. + * This is set to the table size by default. + */ +#if ((LWIP_DNS_SECURE & LWIP_DNS_SECURE_NO_MULTIPLE_OUTSTANDING) != 0) +#ifndef DNS_MAX_REQUESTS +#define DNS_MAX_REQUESTS DNS_TABLE_SIZE +#endif +#else +/* In this configuration, both arrays have to have the same size and are used + * like one entry (used/free) */ +#define DNS_MAX_REQUESTS DNS_TABLE_SIZE +#endif + +/* The number of UDP source ports used in parallel */ +#if ((LWIP_DNS_SECURE & LWIP_DNS_SECURE_RAND_SRC_PORT) != 0) +#ifndef DNS_MAX_SOURCE_PORTS +#define DNS_MAX_SOURCE_PORTS DNS_MAX_REQUESTS +#endif +#else +#ifdef DNS_MAX_SOURCE_PORTS +#undef DNS_MAX_SOURCE_PORTS +#endif +#define DNS_MAX_SOURCE_PORTS 1 +#endif + +#if LWIP_IPV4 && LWIP_IPV6 +#define LWIP_DNS_ADDRTYPE_IS_IPV6(t) (((t) == LWIP_DNS_ADDRTYPE_IPV6_IPV4) || ((t) == LWIP_DNS_ADDRTYPE_IPV6)) +#define LWIP_DNS_ADDRTYPE_MATCH_IP(t, ip) (IP_IS_V6_VAL(ip) ? LWIP_DNS_ADDRTYPE_IS_IPV6(t) : (!LWIP_DNS_ADDRTYPE_IS_IPV6(t))) +#define LWIP_DNS_ADDRTYPE_ARG(x) , x +#define LWIP_DNS_ADDRTYPE_ARG_OR_ZERO(x) x +#define LWIP_DNS_SET_ADDRTYPE(x, y) do { x = y; } while(0) +#else +#if LWIP_IPV6 +#define LWIP_DNS_ADDRTYPE_IS_IPV6(t) 1 +#else +#define LWIP_DNS_ADDRTYPE_IS_IPV6(t) 0 +#endif +#define LWIP_DNS_ADDRTYPE_MATCH_IP(t, ip) 1 +#define LWIP_DNS_ADDRTYPE_ARG(x) +#define LWIP_DNS_ADDRTYPE_ARG_OR_ZERO(x) 0 +#define LWIP_DNS_SET_ADDRTYPE(x, y) +#endif /* LWIP_IPV4 && LWIP_IPV6 */ + +/** DNS field TYPE used for "Resource Records" */ +#define DNS_RRTYPE_A 1 /* a host address */ +#define DNS_RRTYPE_NS 2 /* an authoritative name server */ +#define DNS_RRTYPE_MD 3 /* a mail destination (Obsolete - use MX) */ +#define DNS_RRTYPE_MF 4 /* a mail forwarder (Obsolete - use MX) */ +#define DNS_RRTYPE_CNAME 5 /* the canonical name for an alias */ +#define DNS_RRTYPE_SOA 6 /* marks the start of a zone of authority */ +#define DNS_RRTYPE_MB 7 /* a mailbox domain name (EXPERIMENTAL) */ +#define DNS_RRTYPE_MG 8 /* a mail group member (EXPERIMENTAL) */ +#define DNS_RRTYPE_MR 9 /* a mail rename domain name (EXPERIMENTAL) */ +#define DNS_RRTYPE_NULL 10 /* a null RR (EXPERIMENTAL) */ +#define DNS_RRTYPE_WKS 11 /* a well known service description */ +#define DNS_RRTYPE_PTR 12 /* a domain name pointer */ +#define DNS_RRTYPE_HINFO 13 /* host information */ +#define DNS_RRTYPE_MINFO 14 /* mailbox or mail list information */ +#define DNS_RRTYPE_MX 15 /* mail exchange */ +#define DNS_RRTYPE_TXT 16 /* text strings */ +#define DNS_RRTYPE_AAAA 28 /* IPv6 address */ + +/** DNS field CLASS used for "Resource Records" */ +#define DNS_RRCLASS_IN 1 /* the Internet */ +#define DNS_RRCLASS_CS 2 /* the CSNET class (Obsolete - used only for examples in some obsolete RFCs) */ +#define DNS_RRCLASS_CH 3 /* the CHAOS class */ +#define DNS_RRCLASS_HS 4 /* Hesiod [Dyer 87] */ +#define DNS_RRCLASS_FLUSH 0x800 /* Flush bit */ + +/* DNS protocol flags */ +#define DNS_FLAG1_RESPONSE 0x80 +#define DNS_FLAG1_OPCODE_STATUS 0x10 +#define DNS_FLAG1_OPCODE_INVERSE 0x08 +#define DNS_FLAG1_OPCODE_STANDARD 0x00 +#define DNS_FLAG1_AUTHORATIVE 0x04 +#define DNS_FLAG1_TRUNC 0x02 +#define DNS_FLAG1_RD 0x01 +#define DNS_FLAG2_RA 0x80 +#define DNS_FLAG2_ERR_MASK 0x0f +#define DNS_FLAG2_ERR_NONE 0x00 +#define DNS_FLAG2_ERR_NAME 0x03 + +/* DNS protocol states */ +#define DNS_STATE_UNUSED 0 +#define DNS_STATE_NEW 1 +#define DNS_STATE_ASKING 2 +#define DNS_STATE_DONE 3 + +#ifdef PACK_STRUCT_USE_INCLUDES +# include "arch/bpstruct.h" +#endif +PACK_STRUCT_BEGIN +/** DNS message header */ +struct dns_hdr { + PACK_STRUCT_FIELD(u16_t id); + PACK_STRUCT_FLD_8(u8_t flags1); + PACK_STRUCT_FLD_8(u8_t flags2); + PACK_STRUCT_FIELD(u16_t numquestions); + PACK_STRUCT_FIELD(u16_t numanswers); + PACK_STRUCT_FIELD(u16_t numauthrr); + PACK_STRUCT_FIELD(u16_t numextrarr); +} PACK_STRUCT_STRUCT; +PACK_STRUCT_END +#ifdef PACK_STRUCT_USE_INCLUDES +# include "arch/epstruct.h" +#endif +#define SIZEOF_DNS_HDR 12 + +/** DNS query message structure. + No packing needed: only used locally on the stack. */ +struct dns_query { + /* DNS query record starts with either a domain name or a pointer + to a name already present somewhere in the packet. */ + u16_t type; + u16_t cls; +}; +#define SIZEOF_DNS_QUERY 4 + +/** DNS answer message structure. + No packing needed: only used locally on the stack. */ +struct dns_answer { + /* DNS answer record starts with either a domain name or a pointer + to a name already present somewhere in the packet. */ + u16_t type; + u16_t cls; + u32_t ttl; + u16_t len; +}; +#define SIZEOF_DNS_ANSWER 10 +/* maximum allowed size for the struct due to non-packed */ +#define SIZEOF_DNS_ANSWER_ASSERT 12 + +/** DNS table entry */ +struct dns_table_entry { + u32_t ttl; + ip_addr_t ipaddr; + u16_t txid; + u8_t state; + u8_t server_idx; + u8_t tmr; + u8_t retries; + u8_t seqno; +#if ((LWIP_DNS_SECURE & LWIP_DNS_SECURE_RAND_SRC_PORT) != 0) + u8_t pcb_idx; +#endif + char name[DNS_MAX_NAME_LENGTH]; +#if LWIP_IPV4 && LWIP_IPV6 + u8_t reqaddrtype; +#endif /* LWIP_IPV4 && LWIP_IPV6 */ +}; + +/** DNS request table entry: used when dns_gehostbyname cannot answer the + * request from the DNS table */ +struct dns_req_entry { + /* pointer to callback on DNS query done */ + dns_found_callback found; + /* argument passed to the callback function */ + void *arg; +#if ((LWIP_DNS_SECURE & LWIP_DNS_SECURE_NO_MULTIPLE_OUTSTANDING) != 0) + u8_t dns_table_idx; +#endif +#if LWIP_IPV4 && LWIP_IPV6 + u8_t reqaddrtype; +#endif /* LWIP_IPV4 && LWIP_IPV6 */ +}; + +#if DNS_LOCAL_HOSTLIST + +#if DNS_LOCAL_HOSTLIST_IS_DYNAMIC +/** Local host-list. For hostnames in this list, no + * external name resolution is performed */ +static struct local_hostlist_entry *local_hostlist_dynamic; +#else /* DNS_LOCAL_HOSTLIST_IS_DYNAMIC */ + +/** Defining this allows the local_hostlist_static to be placed in a different + * linker section (e.g. FLASH) */ +#ifndef DNS_LOCAL_HOSTLIST_STORAGE_PRE +#define DNS_LOCAL_HOSTLIST_STORAGE_PRE static +#endif /* DNS_LOCAL_HOSTLIST_STORAGE_PRE */ +/** Defining this allows the local_hostlist_static to be placed in a different + * linker section (e.g. FLASH) */ +#ifndef DNS_LOCAL_HOSTLIST_STORAGE_POST +#define DNS_LOCAL_HOSTLIST_STORAGE_POST +#endif /* DNS_LOCAL_HOSTLIST_STORAGE_POST */ +DNS_LOCAL_HOSTLIST_STORAGE_PRE struct local_hostlist_entry local_hostlist_static[] + DNS_LOCAL_HOSTLIST_STORAGE_POST = DNS_LOCAL_HOSTLIST_INIT; + +#endif /* DNS_LOCAL_HOSTLIST_IS_DYNAMIC */ + +static void dns_init_local(void); +#endif /* DNS_LOCAL_HOSTLIST */ + + +/* forward declarations */ +static void dns_recv(void *s, struct udp_pcb *pcb, struct pbuf *p, const ip_addr_t *addr, u16_t port); +static void dns_check_entries(void); +static void dns_call_found(u8_t idx, ip_addr_t* addr); + +/*----------------------------------------------------------------------------- + * Globals + *----------------------------------------------------------------------------*/ + +/* DNS variables */ +static struct udp_pcb *dns_pcbs[DNS_MAX_SOURCE_PORTS]; +#if ((LWIP_DNS_SECURE & LWIP_DNS_SECURE_RAND_SRC_PORT) != 0) +static u8_t dns_last_pcb_idx; +#endif +static u8_t dns_seqno; +static struct dns_table_entry dns_table[DNS_TABLE_SIZE]; +static struct dns_req_entry dns_requests[DNS_MAX_REQUESTS]; +static ip_addr_t dns_servers[DNS_MAX_SERVERS]; + +#ifndef LWIP_DNS_STRICMP +#define LWIP_DNS_STRICMP(str1, str2) dns_stricmp(str1, str2) +/** + * A small but sufficient implementation for case insensitive strcmp. + * This can be defined to e.g. stricmp for windows or strcasecmp for linux. */ +static int +dns_stricmp(const char* str1, const char* str2) +{ + char c1, c2; + + do { + c1 = *str1++; + c2 = *str2++; + if (c1 != c2) { + char c1_upc = c1 | 0x20; + if ((c1_upc >= 'a') && (c1_upc <= 'z')) { + /* characters are not equal an one is in the alphabet range: + downcase both chars and check again */ + char c2_upc = c2 | 0x20; + if (c1_upc != c2_upc) { + /* still not equal */ + /* don't care for < or > */ + return 1; + } + } else { + /* characters are not equal but none is in the alphabet range */ + return 1; + } + } + } while (c1 != 0); + return 0; +} +#endif /* LWIP_DNS_STRICMP */ + +/** + * Initialize the resolver: set up the UDP pcb and configure the default server + * (if DNS_SERVER_ADDRESS is set). + */ +void +dns_init(void) +{ +#ifdef DNS_SERVER_ADDRESS + /* initialize default DNS server address */ + ip_addr_t dnsserver; + DNS_SERVER_ADDRESS(&dnsserver); + dns_setserver(0, &dnsserver); +#endif /* DNS_SERVER_ADDRESS */ + + LWIP_ASSERT("sanity check SIZEOF_DNS_QUERY", + sizeof(struct dns_query) == SIZEOF_DNS_QUERY); + LWIP_ASSERT("sanity check SIZEOF_DNS_ANSWER", + sizeof(struct dns_answer) <= SIZEOF_DNS_ANSWER_ASSERT); + + LWIP_DEBUGF(DNS_DEBUG, ("dns_init: initializing\n")); + + /* if dns client not yet initialized... */ +#if ((LWIP_DNS_SECURE & LWIP_DNS_SECURE_RAND_SRC_PORT) == 0) + if (dns_pcbs[0] == NULL) { + dns_pcbs[0] = udp_new_ip_type(IPADDR_TYPE_ANY); + LWIP_ASSERT("dns_pcbs[0] != NULL", dns_pcbs[0] != NULL); + + /* initialize DNS table not needed (initialized to zero since it is a + * global variable) */ + LWIP_ASSERT("For implicit initialization to work, DNS_STATE_UNUSED needs to be 0", + DNS_STATE_UNUSED == 0); + + /* initialize DNS client */ + udp_bind(dns_pcbs[0], IP_ANY_TYPE, 0); + udp_recv(dns_pcbs[0], dns_recv, NULL); + } +#endif + +#if DNS_LOCAL_HOSTLIST + dns_init_local(); +#endif +} + +/** + * Initialize one of the DNS servers. + * + * @param numdns the index of the DNS server to set must be < DNS_MAX_SERVERS + * @param dnsserver IP address of the DNS server to set + */ +void +dns_setserver(u8_t numdns, const ip_addr_t *dnsserver) +{ + if (numdns < DNS_MAX_SERVERS) { + if (dnsserver != NULL) { + dns_servers[numdns] = (*dnsserver); + } else { + dns_servers[numdns] = *IP_ADDR_ANY; + } + } +} + +/** + * Obtain one of the currently configured DNS server. + * + * @param numdns the index of the DNS server + * @return IP address of the indexed DNS server or "ip_addr_any" if the DNS + * server has not been configured. + */ +ip_addr_t +dns_getserver(u8_t numdns) +{ + if (numdns < DNS_MAX_SERVERS) { + return dns_servers[numdns]; + } else { + return *IP_ADDR_ANY; + } +} + +/** + * The DNS resolver client timer - handle retries and timeouts and should + * be called every DNS_TMR_INTERVAL milliseconds (every second by default). + */ +void +dns_tmr(void) +{ + LWIP_DEBUGF(DNS_DEBUG, ("dns_tmr: dns_check_entries\n")); + dns_check_entries(); +} + +#if DNS_LOCAL_HOSTLIST +static void +dns_init_local(void) +{ +#if DNS_LOCAL_HOSTLIST_IS_DYNAMIC && defined(DNS_LOCAL_HOSTLIST_INIT) + size_t i; + struct local_hostlist_entry *entry; + /* Dynamic: copy entries from DNS_LOCAL_HOSTLIST_INIT to list */ + struct local_hostlist_entry local_hostlist_init[] = DNS_LOCAL_HOSTLIST_INIT; + size_t namelen; + for (i = 0; i < sizeof(local_hostlist_init) / sizeof(struct local_hostlist_entry); i++) { + struct local_hostlist_entry *init_entry = &local_hostlist_init[i]; + LWIP_ASSERT("invalid host name (NULL)", init_entry->name != NULL); + namelen = strlen(init_entry->name); + LWIP_ASSERT("namelen <= DNS_LOCAL_HOSTLIST_MAX_NAMELEN", namelen <= DNS_LOCAL_HOSTLIST_MAX_NAMELEN); + entry = (struct local_hostlist_entry *)memp_malloc(MEMP_LOCALHOSTLIST); + LWIP_ASSERT("mem-error in dns_init_local", entry != NULL); + if (entry != NULL) { + char* entry_name = (char*)entry + sizeof(struct local_hostlist_entry); + MEMCPY(entry_name, init_entry->name, namelen); + entry_name[namelen] = 0; + entry->name = entry_name; + entry->addr = init_entry->addr; + entry->next = local_hostlist_dynamic; + local_hostlist_dynamic = entry; + } + } +#endif /* DNS_LOCAL_HOSTLIST_IS_DYNAMIC && defined(DNS_LOCAL_HOSTLIST_INIT) */ +} + +/** + * Scans the local host-list for a hostname. + * + * @param hostname Hostname to look for in the local host-list + * @param addr the first IP address for the hostname in the local host-list or + * IPADDR_NONE if not found. + * @return ERR_OK if found, ERR_ARG if not found + */ +static err_t +dns_lookup_local(const char *hostname, ip_addr_t *addr LWIP_DNS_ADDRTYPE_ARG(u8_t dns_addrtype)) +{ +#if DNS_LOCAL_HOSTLIST_IS_DYNAMIC + struct local_hostlist_entry *entry = local_hostlist_dynamic; + while (entry != NULL) { + if ((LWIP_DNS_STRICMP(entry->name, hostname) == 0) && + LWIP_DNS_ADDRTYPE_MATCH_IP(dns_addrtype, entry->addr)) { + if (addr) { + ip_addr_copy(*addr, entry->addr); + } + return ERR_OK; + } + entry = entry->next; + } +#else /* DNS_LOCAL_HOSTLIST_IS_DYNAMIC */ + size_t i; + for (i = 0; i < sizeof(local_hostlist_static) / sizeof(struct local_hostlist_entry); i++) { + if ((LWIP_DNS_STRICMP(local_hostlist_static[i].name, hostname) == 0) && + LWIP_DNS_ADDRTYPE_MATCH_IP(dns_addrtype, local_hostlist_static[i].addr)) { + if (addr) { + ip_addr_copy(*addr, local_hostlist_static[i].addr); + } + return ERR_OK; + } + } +#endif /* DNS_LOCAL_HOSTLIST_IS_DYNAMIC */ + return ERR_ARG; +} + +#if DNS_LOCAL_HOSTLIST_IS_DYNAMIC +/** Remove all entries from the local host-list for a specific hostname + * and/or IP address + * + * @param hostname hostname for which entries shall be removed from the local + * host-list + * @param addr address for which entries shall be removed from the local host-list + * @return the number of removed entries + */ +int +dns_local_removehost(const char *hostname, const ip_addr_t *addr) +{ + int removed = 0; + struct local_hostlist_entry *entry = local_hostlist_dynamic; + struct local_hostlist_entry *last_entry = NULL; + while (entry != NULL) { + if (((hostname == NULL) || !LWIP_DNS_STRICMP(entry->name, hostname)) && + ((addr == NULL) || ip_addr_cmp(&entry->addr, addr))) { + struct local_hostlist_entry *free_entry; + if (last_entry != NULL) { + last_entry->next = entry->next; + } else { + local_hostlist_dynamic = entry->next; + } + free_entry = entry; + entry = entry->next; + memp_free(MEMP_LOCALHOSTLIST, free_entry); + removed++; + } else { + last_entry = entry; + entry = entry->next; + } + } + return removed; +} + +/** + * Add a hostname/IP address pair to the local host-list. + * Duplicates are not checked. + * + * @param hostname hostname of the new entry + * @param addr IP address of the new entry + * @return ERR_OK if succeeded or ERR_MEM on memory error + */ +err_t +dns_local_addhost(const char *hostname, const ip_addr_t *addr) +{ + struct local_hostlist_entry *entry; + size_t namelen; + char* entry_name; + LWIP_ASSERT("invalid host name (NULL)", hostname != NULL); + namelen = strlen(hostname); + LWIP_ASSERT("namelen <= DNS_LOCAL_HOSTLIST_MAX_NAMELEN", namelen <= DNS_LOCAL_HOSTLIST_MAX_NAMELEN); + entry = (struct local_hostlist_entry *)memp_malloc(MEMP_LOCALHOSTLIST); + if (entry == NULL) { + return ERR_MEM; + } + entry_name = (char*)entry + sizeof(struct local_hostlist_entry); + MEMCPY(entry_name, hostname, namelen); + entry_name[namelen] = 0; + entry->name = entry_name; + ip_addr_copy(entry->addr, *addr); + entry->next = local_hostlist_dynamic; + local_hostlist_dynamic = entry; + return ERR_OK; +} +#endif /* DNS_LOCAL_HOSTLIST_IS_DYNAMIC*/ +#endif /* DNS_LOCAL_HOSTLIST */ + +/** + * Look up a hostname in the array of known hostnames. + * + * @note This function only looks in the internal array of known + * hostnames, it does not send out a query for the hostname if none + * was found. The function dns_enqueue() can be used to send a query + * for a hostname. + * + * @param name the hostname to look up + * @param addr the hostname's IP address, as u32_t (instead of ip_addr_t to + * better check for failure: != IPADDR_NONE) or IPADDR_NONE if the hostname + * was not found in the cached dns_table. + * @return ERR_OK if found, ERR_ARG if not found + */ +static err_t +dns_lookup(const char *name, ip_addr_t *addr LWIP_DNS_ADDRTYPE_ARG(u8_t dns_addrtype)) +{ + u8_t i; +#if DNS_LOCAL_HOSTLIST || defined(DNS_LOOKUP_LOCAL_EXTERN) +#endif /* DNS_LOCAL_HOSTLIST || defined(DNS_LOOKUP_LOCAL_EXTERN) */ +#if DNS_LOCAL_HOSTLIST + if (dns_lookup_local(name, addr LWIP_DNS_ADDRTYPE_ARG(dns_addrtype)) == ERR_OK) { + return ERR_OK; + } +#endif /* DNS_LOCAL_HOSTLIST */ +#ifdef DNS_LOOKUP_LOCAL_EXTERN + if (DNS_LOOKUP_LOCAL_EXTERN(name, addr, LWIP_DNS_ADDRTYPE_ARG_OR_ZERO(dns_addrtype))) { + return ERR_OK; + } +#endif /* DNS_LOOKUP_LOCAL_EXTERN */ + + /* Walk through name list, return entry if found. If not, return NULL. */ + for (i = 0; i < DNS_TABLE_SIZE; ++i) { + if ((dns_table[i].state == DNS_STATE_DONE) && + (LWIP_DNS_STRICMP(name, dns_table[i].name) == 0) && + LWIP_DNS_ADDRTYPE_MATCH_IP(dns_addrtype, dns_table[i].ipaddr)) { + LWIP_DEBUGF(DNS_DEBUG, ("dns_lookup: \"%s\": found = ", name)); + ip_addr_debug_print(DNS_DEBUG, &(dns_table[i].ipaddr)); + LWIP_DEBUGF(DNS_DEBUG, ("\n")); + if (addr) { + ip_addr_copy(*addr, dns_table[i].ipaddr); + } + return ERR_OK; + } + } + + return ERR_ARG; +} + +/** + * Compare the "dotted" name "query" with the encoded name "response" + * to make sure an answer from the DNS server matches the current dns_table + * entry (otherwise, answers might arrive late for hostname not on the list + * any more). + * + * @param query hostname (not encoded) from the dns_table + * @param p pbuf containing the encoded hostname in the DNS response + * @param start_offset offset into p where the name starts + * @return 0xFFFF: names differ, other: names equal -> offset behind name + */ +static u16_t +dns_compare_name(char *query, struct pbuf* p, u16_t start_offset) +{ + unsigned char n; + u16_t response_offset = start_offset; + + do { + n = pbuf_get_at(p, response_offset++); + /** @see RFC 1035 - 4.1.4. Message compression */ + if ((n & 0xc0) == 0xc0) { + /* Compressed name: cannot be equal since we don't send them */ + return 0xFFFF; + } else { + /* Not compressed name */ + while (n > 0) { + if ((*query) != pbuf_get_at(p, response_offset)) { + return 0xFFFF; + } + ++response_offset; + ++query; + --n; + } + ++query; + } + } while (pbuf_get_at(p, response_offset) != 0); + + return response_offset + 1; +} + +/** + * Walk through a compact encoded DNS name and return the end of the name. + * + * @param p pbuf containing the name + * @param query_idx start index into p pointing to encoded DNS name in the DNS server response + * @return index to end of the name + */ +static u16_t +dns_parse_name(struct pbuf* p, u16_t query_idx) +{ + unsigned char n; + + do { + n = pbuf_get_at(p, query_idx++); + /** @see RFC 1035 - 4.1.4. Message compression */ + if ((n & 0xc0) == 0xc0) { + /* Compressed name */ + break; + } else { + /* Not compressed name */ + while (n > 0) { + ++query_idx; + --n; + } + } + } while (pbuf_get_at(p, query_idx) != 0); + + return query_idx + 1; +} + +/** + * Send a DNS query packet. + * + * @param idx the DNS table entry index for which to send a request + * @return ERR_OK if packet is sent; an err_t indicating the problem otherwise + */ +static err_t +dns_send(u8_t idx) +{ + err_t err; + struct dns_hdr hdr; + struct dns_query qry; + struct pbuf *p; + u16_t query_idx, copy_len; + const char *hostname, *hostname_part; + u8_t n; + u8_t pcb_idx; + struct dns_table_entry* entry = &dns_table[idx]; + + LWIP_DEBUGF(DNS_DEBUG, ("dns_send: dns_servers[%"U16_F"] \"%s\": request\n", + (u16_t)(entry->server_idx), entry->name)); + LWIP_ASSERT("dns server out of array", entry->server_idx < DNS_MAX_SERVERS); + if (ip_addr_isany_val(dns_servers[entry->server_idx])) { + /* DNS server not valid anymore, e.g. PPP netif has been shut down */ + /* call specified callback function if provided */ + dns_call_found(idx, NULL); + /* flush this entry */ + entry->state = DNS_STATE_UNUSED; + return ERR_OK; + } + + /* if here, we have either a new query or a retry on a previous query to process */ + p = pbuf_alloc(PBUF_TRANSPORT, (u16_t)(SIZEOF_DNS_HDR + strlen(entry->name) + 2 + + SIZEOF_DNS_QUERY), PBUF_RAM); + if (p != NULL) { + /* fill dns header */ + memset(&hdr, 0, SIZEOF_DNS_HDR); + hdr.id = htons(entry->txid); + hdr.flags1 = DNS_FLAG1_RD; + hdr.numquestions = PP_HTONS(1); + pbuf_take(p, &hdr, SIZEOF_DNS_HDR); + hostname = entry->name; + --hostname; + + /* convert hostname into suitable query format. */ + query_idx = SIZEOF_DNS_HDR; + do { + ++hostname; + hostname_part = hostname; + for (n = 0; *hostname != '.' && *hostname != 0; ++hostname) { + ++n; + } + copy_len = (u16_t)(hostname - hostname_part); + pbuf_put_at(p, query_idx, n); + pbuf_take_at(p, hostname_part, copy_len, query_idx + 1); + query_idx += n + 1; + } while (*hostname != 0); + pbuf_put_at(p, query_idx, 0); + query_idx++; + + /* fill dns query */ + if (LWIP_DNS_ADDRTYPE_IS_IPV6(entry->reqaddrtype)) { + qry.type = PP_HTONS(DNS_RRTYPE_AAAA); + } else { + qry.type = PP_HTONS(DNS_RRTYPE_A); + } + qry.cls = PP_HTONS(DNS_RRCLASS_IN); + pbuf_take_at(p, &qry, SIZEOF_DNS_QUERY, query_idx); + +#if ((LWIP_DNS_SECURE & LWIP_DNS_SECURE_RAND_SRC_PORT) != 0) + pcb_idx = entry->pcb_idx; +#else + pcb_idx = 0; +#endif + /* send dns packet */ + LWIP_DEBUGF(DNS_DEBUG, ("sending DNS request ID %d for name \"%s\" to server %d\r\n", + entry->txid, entry->name, entry->server_idx)); + err = udp_sendto(dns_pcbs[pcb_idx], p, &dns_servers[entry->server_idx], DNS_SERVER_PORT); + + /* free pbuf */ + pbuf_free(p); + } else { + err = ERR_MEM; + } + + return err; +} + +#if ((LWIP_DNS_SECURE & LWIP_DNS_SECURE_RAND_SRC_PORT) != 0) +static struct udp_pcb* +dns_alloc_random_port(void) +{ + err_t err; + struct udp_pcb* ret; + + ret = udp_new_ip_type(IPADDR_TYPE_ANY); + if (ret == NULL) { + /* out of memory, have to reuse an existing pcb */ + return NULL; + } + do { + u16_t port = (u16_t)DNS_RAND_TXID(); + if (!DNS_PORT_ALLOWED(port)) { + /* this port is not allowed, try again */ + err = ERR_USE; + continue; + } + err = udp_bind(ret, IP_ANY_TYPE, port); + } while (err == ERR_USE); + if (err != ERR_OK) { + udp_remove(ret); + return NULL; + } + udp_recv(ret, dns_recv, NULL); + return ret; +} + +/** + * dns_alloc_pcb() - allocates a new pcb (or reuses an existing one) to be used + * for sending a request + * + * @return an index into dns_pcbs + */ +static u8_t +dns_alloc_pcb(void) +{ + u8_t i; + u8_t idx; + + for (i = 0; i < DNS_MAX_SOURCE_PORTS; i++) { + if (dns_pcbs[i] == NULL) { + break; + } + } + if (i < DNS_MAX_SOURCE_PORTS) { + dns_pcbs[i] = dns_alloc_random_port(); + if (dns_pcbs[i] != NULL) { + /* succeeded */ + dns_last_pcb_idx = i; + return i; + } + } + /* if we come here, creating a new UDP pcb failed, so we have to use + an already existing one */ + for (i = 0, idx = dns_last_pcb_idx + 1; i < DNS_MAX_SOURCE_PORTS; i++, idx++) { + if (idx >= DNS_MAX_SOURCE_PORTS) { + idx = 0; + } + if (dns_pcbs[idx] != NULL) { + dns_last_pcb_idx = idx; + return idx; + } + } + return DNS_MAX_SOURCE_PORTS; +} +#endif /* ((LWIP_DNS_SECURE & LWIP_DNS_SECURE_RAND_SRC_PORT) != 0) */ + +/** + * dns_call_found() - call the found callback and check if there are duplicate + * entries for the given hostname. If there are any, their found callback will + * be called and they will be removed. + * + * @param idx dns table index of the entry that is resolved or removed + * @param addr IP address for the hostname (or NULL on error or memory shortage) + */ +static void +dns_call_found(u8_t idx, ip_addr_t* addr) +{ +#if ((LWIP_DNS_SECURE & (LWIP_DNS_SECURE_NO_MULTIPLE_OUTSTANDING | LWIP_DNS_SECURE_RAND_SRC_PORT)) != 0) + u8_t i; +#endif + +#if LWIP_IPV4 && LWIP_IPV6 + if (addr != NULL) { + /* check that address type matches the request and adapt the table entry */ + if (IP_IS_V6_VAL(*addr)) { + LWIP_ASSERT("invalid response", LWIP_DNS_ADDRTYPE_IS_IPV6(dns_table[idx].reqaddrtype)); + dns_table[idx].reqaddrtype = LWIP_DNS_ADDRTYPE_IPV6; + } else { + LWIP_ASSERT("invalid response", !LWIP_DNS_ADDRTYPE_IS_IPV6(dns_table[idx].reqaddrtype)); + dns_table[idx].reqaddrtype = LWIP_DNS_ADDRTYPE_IPV4; + } + } +#endif /* LWIP_IPV4 && LWIP_IPV6 */ + +#if ((LWIP_DNS_SECURE & LWIP_DNS_SECURE_NO_MULTIPLE_OUTSTANDING) != 0) + for (i = 0; i < DNS_MAX_REQUESTS; i++) { + if (dns_requests[i].found && (dns_requests[i].dns_table_idx == idx)) { + (*dns_requests[i].found)(dns_table[idx].name, addr, dns_requests[i].arg); + /* flush this entry */ + dns_requests[i].found = NULL; + } + } +#else + if (dns_requests[idx].found) { + (*dns_requests[idx].found)(dns_table[idx].name, addr, dns_requests[idx].arg); + } + dns_requests[idx].found = NULL; +#endif +#if ((LWIP_DNS_SECURE & LWIP_DNS_SECURE_RAND_SRC_PORT) != 0) + /* close the pcb used unless other request are using it */ + for (i = 0; i < DNS_MAX_REQUESTS; i++) { + if (i == idx) { + continue; /* only check other requests */ + } + if (dns_table[i].state == DNS_STATE_ASKING) { + if (dns_table[i].pcb_idx == dns_table[idx].pcb_idx) { + /* another request is still using the same pcb */ + dns_table[idx].pcb_idx = DNS_MAX_SOURCE_PORTS; + break; + } + } + } + if (dns_table[idx].pcb_idx < DNS_MAX_SOURCE_PORTS) { + /* if we come here, the pcb is not used any more and can be removed */ + udp_remove(dns_pcbs[dns_table[idx].pcb_idx]); + dns_pcbs[dns_table[idx].pcb_idx] = NULL; + dns_table[idx].pcb_idx = DNS_MAX_SOURCE_PORTS; + } +#endif +} + +/* Create a query transmission ID that is unique for all outstanding queries */ +static u16_t +dns_create_txid(void) +{ + u16_t txid; + u8_t i; + +again: + txid = (u16_t)DNS_RAND_TXID(); + + /* check whether the ID is unique */ + for (i = 0; i < DNS_TABLE_SIZE; i++) { + if ((dns_table[i].state == DNS_STATE_ASKING) && + (dns_table[i].txid == txid)) { + /* ID already used by another pending query */ + goto again; + } + } + + return txid; +} + +/** + * dns_check_entry() - see if entry has not yet been queried and, if so, sends out a query. + * Check an entry in the dns_table: + * - send out query for new entries + * - retry old pending entries on timeout (also with different servers) + * - remove completed entries from the table if their TTL has expired + * + * @param i index of the dns_table entry to check + */ +static void +dns_check_entry(u8_t i) +{ + err_t err; + struct dns_table_entry *entry = &dns_table[i]; + + LWIP_ASSERT("array index out of bounds", i < DNS_TABLE_SIZE); + + switch (entry->state) { + + case DNS_STATE_NEW: { + u16_t txid; + /* initialize new entry */ + txid = dns_create_txid(); + entry->txid = txid; + entry->state = DNS_STATE_ASKING; + entry->server_idx = 0; + entry->tmr = 1; + entry->retries = 0; + + /* send DNS packet for this entry */ + err = dns_send(i); + if (err != ERR_OK) { + LWIP_DEBUGF(DNS_DEBUG | LWIP_DBG_LEVEL_WARNING, + ("dns_send returned error: %s\n", lwip_strerr(err))); + } + break; + } + + case DNS_STATE_ASKING: + if (--entry->tmr == 0) { + if (++entry->retries == DNS_MAX_RETRIES) { + if ((entry->server_idx + 1 < DNS_MAX_SERVERS) && !ip_addr_isany_val(dns_servers[entry->server_idx + 1])) { + /* change of server */ + entry->server_idx++; + entry->tmr = 1; + entry->retries = 0; + } else { + LWIP_DEBUGF(DNS_DEBUG, ("dns_check_entry: \"%s\": timeout\n", entry->name)); + /* call specified callback function if provided */ + dns_call_found(i, NULL); + /* flush this entry */ + entry->state = DNS_STATE_UNUSED; + break; + } + } else { + /* wait longer for the next retry */ + entry->tmr = entry->retries; + } + + /* send DNS packet for this entry */ + err = dns_send(i); + if (err != ERR_OK) { + LWIP_DEBUGF(DNS_DEBUG | LWIP_DBG_LEVEL_WARNING, + ("dns_send returned error: %s\n", lwip_strerr(err))); + } + } + break; + case DNS_STATE_DONE: + /* if the time to live is nul */ + if ((entry->ttl == 0) || (--entry->ttl == 0)) { + LWIP_DEBUGF(DNS_DEBUG, ("dns_check_entry: \"%s\": flush\n", entry->name)); + /* flush this entry, there cannot be any related pending entries in this state */ + entry->state = DNS_STATE_UNUSED; + } + break; + case DNS_STATE_UNUSED: + /* nothing to do */ + break; + default: + LWIP_ASSERT("unknown dns_table entry state:", 0); + break; + } +} + +/** + * Call dns_check_entry for each entry in dns_table - check all entries. + */ +static void +dns_check_entries(void) +{ + u8_t i; + + for (i = 0; i < DNS_TABLE_SIZE; ++i) { + dns_check_entry(i); + } +} + +/** + * Receive input function for DNS response packets arriving for the dns UDP pcb. + * + * @params see udp.h + */ +static void +dns_recv(void *arg, struct udp_pcb *pcb, struct pbuf *p, const ip_addr_t *addr, u16_t port) +{ + u8_t i, entry_idx = DNS_TABLE_SIZE; + u16_t txid; + u16_t res_idx; + struct dns_hdr hdr; + struct dns_answer ans; + struct dns_query qry; + u16_t nquestions, nanswers; + + LWIP_UNUSED_ARG(arg); + LWIP_UNUSED_ARG(pcb); + LWIP_UNUSED_ARG(port); + + /* is the dns message big enough ? */ + if (p->tot_len < (SIZEOF_DNS_HDR + SIZEOF_DNS_QUERY)) { + LWIP_DEBUGF(DNS_DEBUG, ("dns_recv: pbuf too small\n")); + /* free pbuf and return */ + goto memerr; + } + + /* copy dns payload inside static buffer for processing */ + if (pbuf_copy_partial(p, &hdr, SIZEOF_DNS_HDR, 0) == SIZEOF_DNS_HDR) { + /* Match the ID in the DNS header with the name table. */ + txid = htons(hdr.id); + for (i = 0; i < DNS_TABLE_SIZE; i++) { + struct dns_table_entry *entry = &dns_table[i]; + entry_idx = i; + if ((entry->state == DNS_STATE_ASKING) && + (entry->txid == txid)) { + u8_t dns_err; + /* This entry is now completed. */ + +#ifndef LWIP_ESP8266 + entry->state = DNS_STATE_DONE; +#endif + dns_err = hdr.flags2 & DNS_FLAG2_ERR_MASK; + + /* We only care about the question(s) and the answers. The authrr + and the extrarr are simply discarded. */ + nquestions = htons(hdr.numquestions); + nanswers = htons(hdr.numanswers); + + /* Check for error. If so, call callback to inform. */ + if (((hdr.flags1 & DNS_FLAG1_RESPONSE) == 0) || (dns_err != 0) || (nquestions != 1)) { + LWIP_DEBUGF(DNS_DEBUG, ("dns_recv: \"%s\": error in flags\n", entry->name)); + /* call callback to indicate error, clean up memory and return */ +#ifndef LWIP_ESP8266 + goto responseerr; + } +#else + goto memerr; + } + entry->state = DNS_STATE_DONE; +#endif + + + /* Check whether response comes from the same network address to which the + question was sent. (RFC 5452) */ + if (!ip_addr_cmp(addr, &dns_servers[entry->server_idx])) { + /* call callback to indicate error, clean up memory and return */ + goto responseerr; + } + + /* Check if the name in the "question" part match with the name in the entry and + skip it if equal. */ + res_idx = dns_compare_name(entry->name, p, SIZEOF_DNS_HDR); + if (res_idx == 0xFFFF) { + LWIP_DEBUGF(DNS_DEBUG, ("dns_recv: \"%s\": response not match to query\n", entry->name)); + /* call callback to indicate error, clean up memory and return */ + goto responseerr; + } + + /* check if "question" part matches the request */ + pbuf_copy_partial(p, &qry, SIZEOF_DNS_QUERY, res_idx); + if ((qry.cls != PP_HTONS(DNS_RRCLASS_IN)) || + (LWIP_DNS_ADDRTYPE_IS_IPV6(entry->reqaddrtype) && (qry.type != PP_HTONS(DNS_RRTYPE_AAAA))) || + (!LWIP_DNS_ADDRTYPE_IS_IPV6(entry->reqaddrtype) && (qry.type != PP_HTONS(DNS_RRTYPE_A)))) { + LWIP_DEBUGF(DNS_DEBUG, ("dns_recv: \"%s\": response not match to query\n", entry->name)); + /* call callback to indicate error, clean up memory and return */ + goto responseerr; + } + /* skip the rest of the "question" part */ + res_idx += SIZEOF_DNS_QUERY; + + while ((nanswers > 0) && (res_idx < p->tot_len)) { + /* skip answer resource record's host name */ + res_idx = dns_parse_name(p, res_idx); + + /* Check for IP address type and Internet class. Others are discarded. */ + pbuf_copy_partial(p, &ans, SIZEOF_DNS_ANSWER, res_idx); + if (ans.cls == PP_HTONS(DNS_RRCLASS_IN)) { +#if LWIP_IPV4 + if ((ans.type == PP_HTONS(DNS_RRTYPE_A)) && (ans.len == PP_HTONS(sizeof(ip4_addr_t)))) { +#if LWIP_IPV4 && LWIP_IPV6 + if (!LWIP_DNS_ADDRTYPE_IS_IPV6(entry->reqaddrtype)) +#endif /* LWIP_IPV4 && LWIP_IPV6 */ + { + ip4_addr_t ip4addr; + res_idx += SIZEOF_DNS_ANSWER; + /* read the answer resource record's TTL, and maximize it if needed */ + entry->ttl = ntohl(ans.ttl); + if (entry->ttl > DNS_MAX_TTL) { + entry->ttl = DNS_MAX_TTL; + } + /* read the IP address after answer resource record's header */ + pbuf_copy_partial(p, &ip4addr, sizeof(ip4_addr_t), res_idx); + ip_addr_copy_from_ip4(entry->ipaddr, ip4addr); + LWIP_DEBUGF(DNS_DEBUG, ("dns_recv: \"%s\": response = ", entry->name)); + ip_addr_debug_print(DNS_DEBUG, (&(entry->ipaddr))); + LWIP_DEBUGF(DNS_DEBUG, ("\n")); + /* call specified callback function if provided */ + dns_call_found(entry_idx, &entry->ipaddr); + if (entry->ttl == 0) { + /* RFC 883, page 29: "Zero values are + interpreted to mean that the RR can only be used for the + transaction in progress, and should not be cached." + -> flush this entry now */ + goto flushentry; + } + /* deallocate memory and return */ + goto memerr; + } + } +#endif /* LWIP_IPV4 */ +#if LWIP_IPV6 + if ((ans.type == PP_HTONS(DNS_RRTYPE_AAAA)) && (ans.len == PP_HTONS(sizeof(ip6_addr_t)))) { +#if LWIP_IPV4 && LWIP_IPV6 + if (LWIP_DNS_ADDRTYPE_IS_IPV6(entry->reqaddrtype)) +#endif /* LWIP_IPV4 && LWIP_IPV6 */ + { + ip6_addr_t ip6addr; + res_idx += SIZEOF_DNS_ANSWER; + /* read the answer resource record's TTL, and maximize it if needed */ + entry->ttl = ntohl(ans.ttl); + if (entry->ttl > DNS_MAX_TTL) { + entry->ttl = DNS_MAX_TTL; + } + /* read the IP address after answer resource record's header */ + pbuf_copy_partial(p, &ip6addr, sizeof(ip6_addr_t), res_idx); + ip_addr_copy_from_ip6(entry->ipaddr, ip6addr); + LWIP_DEBUGF(DNS_DEBUG, ("dns_recv: \"%s\": response = ", entry->name)); + ip_addr_debug_print(DNS_DEBUG, (&(entry->ipaddr))); + LWIP_DEBUGF(DNS_DEBUG, (" AAAA\n")); + /* call specified callback function if provided */ + dns_call_found(entry_idx, &entry->ipaddr); + if (entry->ttl == 0) { + /* RFC 883, page 29: "Zero values are + interpreted to mean that the RR can only be used for the + transaction in progress, and should not be cached." + -> flush this entry now */ + goto flushentry; + } + /* deallocate memory and return */ + goto memerr; + } + } +#endif /* LWIP_IPV6 */ + } + /* skip this answer */ + res_idx += SIZEOF_DNS_ANSWER + htons(ans.len); + --nanswers; + } +#if LWIP_IPV4 && LWIP_IPV6 + if ((entry->reqaddrtype == LWIP_DNS_ADDRTYPE_IPV4_IPV6) || + (entry->reqaddrtype == LWIP_DNS_ADDRTYPE_IPV6_IPV4)) { + if (entry->reqaddrtype == LWIP_DNS_ADDRTYPE_IPV4_IPV6) { + /* IPv4 failed, try IPv6 */ + entry->reqaddrtype = LWIP_DNS_ADDRTYPE_IPV6; + } else { + /* IPv6 failed, try IPv4 */ + entry->reqaddrtype = LWIP_DNS_ADDRTYPE_IPV4; + } + pbuf_free(p); + entry->state = DNS_STATE_NEW; + dns_check_entry(entry_idx); + return; + } +#endif /* LWIP_IPV4 && LWIP_IPV6 */ + LWIP_DEBUGF(DNS_DEBUG, ("dns_recv: \"%s\": error in response\n", entry->name)); + /* call callback to indicate error, clean up memory and return */ + goto responseerr; + } + } + } + + /* deallocate memory and return */ + goto memerr; + +responseerr: + /* ERROR: call specified callback function with NULL as name to indicate an error */ + dns_call_found(entry_idx, NULL); +flushentry: + /* flush this entry */ + dns_table[entry_idx].state = DNS_STATE_UNUSED; + +memerr: + /* free pbuf */ + pbuf_free(p); + return; +} + +/** + * Queues a new hostname to resolve and sends out a DNS query for that hostname + * + * @param name the hostname that is to be queried + * @param hostnamelen length of the hostname + * @param found a callback function to be called on success, failure or timeout + * @param callback_arg argument to pass to the callback function + * @return @return a err_t return code. + */ +static err_t +dns_enqueue(const char *name, size_t hostnamelen, dns_found_callback found, + void *callback_arg LWIP_DNS_ADDRTYPE_ARG(u8_t dns_addrtype)) +{ + u8_t i; + u8_t lseq, lseqi; + struct dns_table_entry *entry = NULL; + size_t namelen; + struct dns_req_entry* req; + +#if ((LWIP_DNS_SECURE & LWIP_DNS_SECURE_NO_MULTIPLE_OUTSTANDING) != 0) + u8_t r; + /* check for duplicate entries */ + for (i = 0; i < DNS_TABLE_SIZE; i++) { + if ((dns_table[i].state == DNS_STATE_ASKING) && + (LWIP_DNS_STRICMP(name, dns_table[i].name) == 0)) { +#if LWIP_IPV4 && LWIP_IPV6 + if (dns_table[i].reqaddrtype != dns_addrtype) { + /* requested address types don't match + this can lead to 2 concurrent requests, but mixing the address types + for the same host should not be that common */ + continue; + } +#endif /* LWIP_IPV4 && LWIP_IPV6 */ + /* this is a duplicate entry, find a free request entry */ + for (r = 0; r < DNS_MAX_REQUESTS; r++) { + if (dns_requests[r].found == 0) { + dns_requests[r].found = found; + dns_requests[r].arg = callback_arg; + dns_requests[r].dns_table_idx = i; + LWIP_DNS_SET_ADDRTYPE(dns_requests[r].reqaddrtype, dns_addrtype); + LWIP_DEBUGF(DNS_DEBUG, ("dns_enqueue: \"%s\": duplicate request\n", name)); + return ERR_INPROGRESS; + } + } + } + } + /* no duplicate entries found */ +#endif + + /* search an unused entry, or the oldest one */ + lseq = 0; + lseqi = DNS_TABLE_SIZE; + for (i = 0; i < DNS_TABLE_SIZE; ++i) { + entry = &dns_table[i]; + /* is it an unused entry ? */ + if (entry->state == DNS_STATE_UNUSED) { + break; + } + /* check if this is the oldest completed entry */ + if (entry->state == DNS_STATE_DONE) { + if ((u8_t)(dns_seqno - entry->seqno) > lseq) { + lseq = dns_seqno - entry->seqno; + lseqi = i; + } + } + } + + /* if we don't have found an unused entry, use the oldest completed one */ + if (i == DNS_TABLE_SIZE) { + if ((lseqi >= DNS_TABLE_SIZE) || (dns_table[lseqi].state != DNS_STATE_DONE)) { + /* no entry can be used now, table is full */ + LWIP_DEBUGF(DNS_DEBUG, ("dns_enqueue: \"%s\": DNS entries table is full\n", name)); + return ERR_MEM; + } else { + /* use the oldest completed one */ + i = lseqi; + entry = &dns_table[i]; + } + } + +#if ((LWIP_DNS_SECURE & LWIP_DNS_SECURE_NO_MULTIPLE_OUTSTANDING) != 0) + /* find a free request entry */ + req = NULL; + for (r = 0; r < DNS_MAX_REQUESTS; r++) { + if (dns_requests[r].found == NULL) { + req = &dns_requests[r]; + break; + } + } + if (req == NULL) { + /* no request entry can be used now, table is full */ + LWIP_DEBUGF(DNS_DEBUG, ("dns_enqueue: \"%s\": DNS request entries table is full\n", name)); + return ERR_MEM; + } + req->dns_table_idx = i; +#else + /* in this configuration, the entry index is the same as the request index */ + req = &dns_requests[i]; +#endif + + /* use this entry */ + LWIP_DEBUGF(DNS_DEBUG, ("dns_enqueue: \"%s\": use DNS entry %"U16_F"\n", name, (u16_t)(i))); + + /* fill the entry */ + entry->state = DNS_STATE_NEW; + entry->seqno = dns_seqno; + LWIP_DNS_SET_ADDRTYPE(entry->reqaddrtype, dns_addrtype); + LWIP_DNS_SET_ADDRTYPE(req->reqaddrtype, dns_addrtype); + req->found = found; + req->arg = callback_arg; + namelen = LWIP_MIN(hostnamelen, DNS_MAX_NAME_LENGTH-1); + MEMCPY(entry->name, name, namelen); + entry->name[namelen] = 0; + +#if ((LWIP_DNS_SECURE & LWIP_DNS_SECURE_RAND_SRC_PORT) != 0) + entry->pcb_idx = dns_alloc_pcb(); + if (entry->pcb_idx >= DNS_MAX_SOURCE_PORTS) { + /* failed to get a UDP pcb */ + LWIP_DEBUGF(DNS_DEBUG, ("dns_enqueue: \"%s\": failed to allocate a pcb\n", name)); + entry->state = DNS_STATE_UNUSED; + req->found = NULL; + return ERR_MEM; + } + LWIP_DEBUGF(DNS_DEBUG, ("dns_enqueue: \"%s\": use DNS pcb %"U16_F"\n", name, (u16_t)(entry->pcb_idx))); +#endif + + dns_seqno++; + + /* force to send query without waiting timer */ + dns_check_entry(i); + + /* dns query is enqueued */ + return ERR_INPROGRESS; +} + +/** + * Resolve a hostname (string) into an IP address. + * NON-BLOCKING callback version for use with raw API!!! + * + * Returns immediately with one of err_t return codes: + * - ERR_OK if hostname is a valid IP address string or the host + * name is already in the local names table. + * - ERR_INPROGRESS enqueue a request to be sent to the DNS server + * for resolution if no errors are present. + * - ERR_ARG: dns client not initialized or invalid hostname + * + * @param hostname the hostname that is to be queried + * @param addr pointer to a ip_addr_t where to store the address if it is already + * cached in the dns_table (only valid if ERR_OK is returned!) + * @param found a callback function to be called on success, failure or timeout (only if + * ERR_INPROGRESS is returned!) + * @param callback_arg argument to pass to the callback function + * @return a err_t return code. + */ +err_t +dns_gethostbyname(const char *hostname, ip_addr_t *addr, dns_found_callback found, + void *callback_arg) +{ + return dns_gethostbyname_addrtype(hostname, addr, found, callback_arg, LWIP_DNS_ADDRTYPE_DEFAULT); +} + +/** Like dns_gethostbyname, but returned address type can be controlled: + * @param dns_addrtype: - LWIP_DNS_ADDRTYPE_IPV4_IPV6: try to resolve IPv4 first, try IPv6 if IPv4 fails only + * - LWIP_DNS_ADDRTYPE_IPV6_IPV4: try to resolve IPv6 first, try IPv4 if IPv6 fails only + * - LWIP_DNS_ADDRTYPE_IPV4: try to resolve IPv4 only + * - LWIP_DNS_ADDRTYPE_IPV6: try to resolve IPv6 only + */ +err_t +dns_gethostbyname_addrtype(const char *hostname, ip_addr_t *addr, dns_found_callback found, + void *callback_arg, u8_t dns_addrtype) +{ + size_t hostnamelen; + /* not initialized or no valid server yet, or invalid addr pointer + * or invalid hostname or invalid hostname length */ + if ((addr == NULL) || + (!hostname) || (!hostname[0])) { + return ERR_ARG; + } +#if ((LWIP_DNS_SECURE & LWIP_DNS_SECURE_RAND_SRC_PORT) == 0) + if (dns_pcbs[0] == NULL) { + return ERR_ARG; + } +#endif + hostnamelen = strlen(hostname); + if (hostnamelen >= DNS_MAX_NAME_LENGTH) { + LWIP_DEBUGF(DNS_DEBUG, ("dns_gethostbyname: name too long to resolve")); + return ERR_ARG; + } + + +#if LWIP_HAVE_LOOPIF + if (strcmp(hostname, "localhost") == 0) { + ip_addr_set_loopback(LWIP_DNS_ADDRTYPE_IS_IPV6(dns_addrtype), addr); + return ERR_OK; + } +#endif /* LWIP_HAVE_LOOPIF */ + + /* host name already in octet notation? set ip addr and return ERR_OK */ + if (ipaddr_aton(hostname, addr)) { +#if LWIP_IPV4 && LWIP_IPV6 + if ((IP_IS_V6(addr) && (dns_addrtype != LWIP_DNS_ADDRTYPE_IPV4)) || + (!IP_IS_V6(addr) && (dns_addrtype != LWIP_DNS_ADDRTYPE_IPV6))) +#endif /* LWIP_IPV4 && LWIP_IPV6 */ + { + return ERR_OK; + } + } + /* already have this address cached? */ + if (dns_lookup(hostname, addr LWIP_DNS_ADDRTYPE_ARG(dns_addrtype)) == ERR_OK) { + return ERR_OK; + } +#if LWIP_IPV4 && LWIP_IPV6 + if ((dns_addrtype == LWIP_DNS_ADDRTYPE_IPV4_IPV6) || (dns_addrtype == LWIP_DNS_ADDRTYPE_IPV6_IPV4)) { + /* fallback to 2nd IP type and try again to lookup */ + u8_t fallback; + if (dns_addrtype == LWIP_DNS_ADDRTYPE_IPV4_IPV6) { + fallback = LWIP_DNS_ADDRTYPE_IPV6; + } else { + fallback = LWIP_DNS_ADDRTYPE_IPV4; + } + if (dns_lookup(hostname, addr LWIP_DNS_ADDRTYPE_ARG(fallback)) == ERR_OK) { + return ERR_OK; + } + } +#else /* LWIP_IPV4 && LWIP_IPV6 */ + LWIP_UNUSED_ARG(dns_addrtype); +#endif /* LWIP_IPV4 && LWIP_IPV6 */ + + /* prevent calling found callback if no server is set, return error instead */ + if (ip_addr_isany_val(dns_servers[0])) { + return ERR_VAL; + } + + /* queue query with specified callback */ + return dns_enqueue(hostname, hostnamelen, found, callback_arg LWIP_DNS_ADDRTYPE_ARG(dns_addrtype)); +} + +#endif /* LWIP_DNS */ diff --git a/components/lwip/core/inet_chksum.c b/components/lwip/core/inet_chksum.c new file mode 100755 index 0000000000..bcaa3dc827 --- /dev/null +++ b/components/lwip/core/inet_chksum.c @@ -0,0 +1,612 @@ +/** + * @file + * Incluse internet checksum functions. + * + */ + +/* + * Copyright (c) 2001-2004 Swedish Institute of Computer Science. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + * + */ + +#include "lwip/opt.h" + +#include "lwip/inet_chksum.h" +#include "lwip/def.h" +#include "lwip/ip_addr.h" + +#include +#include + +/* These are some reference implementations of the checksum algorithm, with the + * aim of being simple, correct and fully portable. Checksumming is the + * first thing you would want to optimize for your platform. If you create + * your own version, link it in and in your cc.h put: + * + * #define LWIP_CHKSUM + * + * Or you can select from the implementations below by defining + * LWIP_CHKSUM_ALGORITHM to 1, 2 or 3. + */ + +#ifndef LWIP_CHKSUM +# define LWIP_CHKSUM lwip_standard_chksum +# ifndef LWIP_CHKSUM_ALGORITHM +# define LWIP_CHKSUM_ALGORITHM 2 +# endif +u16_t lwip_standard_chksum(const void *dataptr, int len); +#endif +/* If none set: */ +#ifndef LWIP_CHKSUM_ALGORITHM +# define LWIP_CHKSUM_ALGORITHM 0 +#endif + +#if (LWIP_CHKSUM_ALGORITHM == 1) /* Version #1 */ +/** + * lwip checksum + * + * @param dataptr points to start of data to be summed at any boundary + * @param len length of data to be summed + * @return host order (!) lwip checksum (non-inverted Internet sum) + * + * @note accumulator size limits summable length to 64k + * @note host endianess is irrelevant (p3 RFC1071) + */ +u16_t +lwip_standard_chksum(const void *dataptr, int len) +{ + u32_t acc; + u16_t src; + const u8_t *octetptr; + + acc = 0; + /* dataptr may be at odd or even addresses */ + octetptr = (const u8_t*)dataptr; + while (len > 1) { + /* declare first octet as most significant + thus assume network order, ignoring host order */ + src = (*octetptr) << 8; + octetptr++; + /* declare second octet as least significant */ + src |= (*octetptr); + octetptr++; + acc += src; + len -= 2; + } + if (len > 0) { + /* accumulate remaining octet */ + src = (*octetptr) << 8; + acc += src; + } + /* add deferred carry bits */ + acc = (acc >> 16) + (acc & 0x0000ffffUL); + if ((acc & 0xffff0000UL) != 0) { + acc = (acc >> 16) + (acc & 0x0000ffffUL); + } + /* This maybe a little confusing: reorder sum using htons() + instead of ntohs() since it has a little less call overhead. + The caller must invert bits for Internet sum ! */ + return htons((u16_t)acc); +} +#endif + +#if (LWIP_CHKSUM_ALGORITHM == 2) /* Alternative version #2 */ +/* + * Curt McDowell + * Broadcom Corp. + * csm@broadcom.com + * + * IP checksum two bytes at a time with support for + * unaligned buffer. + * Works for len up to and including 0x20000. + * by Curt McDowell, Broadcom Corp. 12/08/2005 + * + * @param dataptr points to start of data to be summed at any boundary + * @param len length of data to be summed + * @return host order (!) lwip checksum (non-inverted Internet sum) + */ +u16_t +lwip_standard_chksum(const void *dataptr, int len) +{ + const u8_t *pb = (const u8_t *)dataptr; + const u16_t *ps; + u16_t t = 0; + u32_t sum = 0; + int odd = ((mem_ptr_t)pb & 1); + + /* Get aligned to u16_t */ + if (odd && len > 0) { + ((u8_t *)&t)[1] = *pb++; + len--; + } + + /* Add the bulk of the data */ + ps = (const u16_t *)(const void *)pb; + while (len > 1) { + sum += *ps++; + len -= 2; + } + + /* Consume left-over byte, if any */ + if (len > 0) { + ((u8_t *)&t)[0] = *(const u8_t *)ps; + } + + /* Add end bytes */ + sum += t; + + /* Fold 32-bit sum to 16 bits + calling this twice is probably faster than if statements... */ + sum = FOLD_U32T(sum); + sum = FOLD_U32T(sum); + + /* Swap if alignment was odd */ + if (odd) { + sum = SWAP_BYTES_IN_WORD(sum); + } + + return (u16_t)sum; +} +#endif + +#if (LWIP_CHKSUM_ALGORITHM == 3) /* Alternative version #3 */ +/** + * An optimized checksum routine. Basically, it uses loop-unrolling on + * the checksum loop, treating the head and tail bytes specially, whereas + * the inner loop acts on 8 bytes at a time. + * + * @arg start of buffer to be checksummed. May be an odd byte address. + * @len number of bytes in the buffer to be checksummed. + * @return host order (!) lwip checksum (non-inverted Internet sum) + * + * by Curt McDowell, Broadcom Corp. December 8th, 2005 + */ +u16_t +lwip_standard_chksum(const void *dataptr, int len) +{ + const u8_t *pb = (const u8_t *)dataptr; + const u16_t *ps; + u16_t t = 0; + const u32_t *pl; + u32_t sum = 0, tmp; + /* starts at odd byte address? */ + int odd = ((mem_ptr_t)pb & 1); + + if (odd && len > 0) { + ((u8_t *)&t)[1] = *pb++; + len--; + } + + ps = (const u16_t *)(const void*)pb; + + if (((mem_ptr_t)ps & 3) && len > 1) { + sum += *ps++; + len -= 2; + } + + pl = (const u32_t *)(const void*)ps; + + while (len > 7) { + tmp = sum + *pl++; /* ping */ + if (tmp < sum) { + tmp++; /* add back carry */ + } + + sum = tmp + *pl++; /* pong */ + if (sum < tmp) { + sum++; /* add back carry */ + } + + len -= 8; + } + + /* make room in upper bits */ + sum = FOLD_U32T(sum); + + ps = (const u16_t *)pl; + + /* 16-bit aligned word remaining? */ + while (len > 1) { + sum += *ps++; + len -= 2; + } + + /* dangling tail byte remaining? */ + if (len > 0) { /* include odd byte */ + ((u8_t *)&t)[0] = *(const u8_t *)ps; + } + + sum += t; /* add end bytes */ + + /* Fold 32-bit sum to 16 bits + calling this twice is probably faster than if statements... */ + sum = FOLD_U32T(sum); + sum = FOLD_U32T(sum); + + if (odd) { + sum = SWAP_BYTES_IN_WORD(sum); + } + + return (u16_t)sum; +} +#endif + +/** Parts of the pseudo checksum which are common to IPv4 and IPv6 */ +static u16_t +inet_cksum_pseudo_base(struct pbuf *p, u8_t proto, u16_t proto_len, u32_t acc) +{ + struct pbuf *q; + u8_t swapped = 0; + + /* iterate through all pbuf in chain */ + for (q = p; q != NULL; q = q->next) { + LWIP_DEBUGF(INET_DEBUG, ("inet_chksum_pseudo(): checksumming pbuf %p (has next %p) \n", + (void *)q, (void *)q->next)); + acc += LWIP_CHKSUM(q->payload, q->len); + /*LWIP_DEBUGF(INET_DEBUG, ("inet_chksum_pseudo(): unwrapped lwip_chksum()=%"X32_F" \n", acc));*/ + /* just executing this next line is probably faster that the if statement needed + to check whether we really need to execute it, and does no harm */ + acc = FOLD_U32T(acc); + if (q->len % 2 != 0) { + swapped = 1 - swapped; + acc = SWAP_BYTES_IN_WORD(acc); + } + /*LWIP_DEBUGF(INET_DEBUG, ("inet_chksum_pseudo(): wrapped lwip_chksum()=%"X32_F" \n", acc));*/ + } + + if (swapped) { + acc = SWAP_BYTES_IN_WORD(acc); + } + + acc += (u32_t)htons((u16_t)proto); + acc += (u32_t)htons(proto_len); + + /* Fold 32-bit sum to 16 bits + calling this twice is probably faster than if statements... */ + acc = FOLD_U32T(acc); + acc = FOLD_U32T(acc); + LWIP_DEBUGF(INET_DEBUG, ("inet_chksum_pseudo(): pbuf chain lwip_chksum()=%"X32_F"\n", acc)); + return (u16_t)~(acc & 0xffffUL); +} + +#if LWIP_IPV4 +/* inet_chksum_pseudo: + * + * Calculates the IPv4 pseudo Internet checksum used by TCP and UDP for a pbuf chain. + * IP addresses are expected to be in network byte order. + * + * @param p chain of pbufs over that a checksum should be calculated (ip data part) + * @param src source ip address (used for checksum of pseudo header) + * @param dst destination ip address (used for checksum of pseudo header) + * @param proto ip protocol (used for checksum of pseudo header) + * @param proto_len length of the ip data part (used for checksum of pseudo header) + * @return checksum (as u16_t) to be saved directly in the protocol header + */ +u16_t +inet_chksum_pseudo(struct pbuf *p, u8_t proto, u16_t proto_len, + const ip4_addr_t *src, const ip4_addr_t *dest) +{ + u32_t acc; + u32_t addr; + + addr = ip4_addr_get_u32(src); + acc = (addr & 0xffffUL); + acc += ((addr >> 16) & 0xffffUL); + addr = ip4_addr_get_u32(dest); + acc += (addr & 0xffffUL); + acc += ((addr >> 16) & 0xffffUL); + /* fold down to 16 bits */ + acc = FOLD_U32T(acc); + acc = FOLD_U32T(acc); + + return inet_cksum_pseudo_base(p, proto, proto_len, acc); +} +#endif /* LWIP_IPV4 */ + +#if LWIP_IPV6 +/** + * Calculates the checksum with IPv6 pseudo header used by TCP and UDP for a pbuf chain. + * IPv6 addresses are expected to be in network byte order. + * + * @param p chain of pbufs over that a checksum should be calculated (ip data part) + * @param src source ipv6 address (used for checksum of pseudo header) + * @param dst destination ipv6 address (used for checksum of pseudo header) + * @param proto ipv6 protocol/next header (used for checksum of pseudo header) + * @param proto_len length of the ipv6 payload (used for checksum of pseudo header) + * @return checksum (as u16_t) to be saved directly in the protocol header + */ +u16_t +ip6_chksum_pseudo(struct pbuf *p, u8_t proto, u16_t proto_len, + const ip6_addr_t *src, const ip6_addr_t *dest) +{ + u32_t acc = 0; + u32_t addr; + u8_t addr_part; + + for (addr_part = 0; addr_part < 4; addr_part++) { + addr = src->addr[addr_part]; + acc += (addr & 0xffffUL); + acc += ((addr >> 16) & 0xffffUL); + addr = dest->addr[addr_part]; + acc += (addr & 0xffffUL); + acc += ((addr >> 16) & 0xffffUL); + } + /* fold down to 16 bits */ + acc = FOLD_U32T(acc); + acc = FOLD_U32T(acc); + + return inet_cksum_pseudo_base(p, proto, proto_len, acc); +} +#endif /* LWIP_IPV6 */ + +/* ip_chksum_pseudo: + * + * Calculates the IPv4 or IPv6 pseudo Internet checksum used by TCP and UDP for a pbuf chain. + * IP addresses are expected to be in network byte order. + * + * @param p chain of pbufs over that a checksum should be calculated (ip data part) + * @param src source ip address (used for checksum of pseudo header) + * @param dst destination ip address (used for checksum of pseudo header) + * @param proto ip protocol (used for checksum of pseudo header) + * @param proto_len length of the ip data part (used for checksum of pseudo header) + * @return checksum (as u16_t) to be saved directly in the protocol header + */ +u16_t +ip_chksum_pseudo(struct pbuf *p, u8_t proto, u16_t proto_len, + const ip_addr_t *src, const ip_addr_t *dest) +{ +#if LWIP_IPV6 + if (IP_IS_V6(dest)) { + return ip6_chksum_pseudo(p, proto, proto_len, ip_2_ip6(src), ip_2_ip6(dest)); + } +#endif /* LWIP_IPV6 */ +#if LWIP_IPV4 && LWIP_IPV6 + else +#endif /* LWIP_IPV4 && LWIP_IPV6 */ +#if LWIP_IPV4 + { + return inet_chksum_pseudo(p, proto, proto_len, ip_2_ip4(src), ip_2_ip4(dest)); + } +#endif /* LWIP_IPV4 */ +} + +/** Parts of the pseudo checksum which are common to IPv4 and IPv6 */ +static u16_t +inet_cksum_pseudo_partial_base(struct pbuf *p, u8_t proto, u16_t proto_len, + u16_t chksum_len, u32_t acc) +{ + struct pbuf *q; + u8_t swapped = 0; + u16_t chklen; + + /* iterate through all pbuf in chain */ + for (q = p; (q != NULL) && (chksum_len > 0); q = q->next) { + LWIP_DEBUGF(INET_DEBUG, ("inet_chksum_pseudo(): checksumming pbuf %p (has next %p) \n", + (void *)q, (void *)q->next)); + chklen = q->len; + if (chklen > chksum_len) { + chklen = chksum_len; + } + acc += LWIP_CHKSUM(q->payload, chklen); + chksum_len -= chklen; + LWIP_ASSERT("delete me", chksum_len < 0x7fff); + /*LWIP_DEBUGF(INET_DEBUG, ("inet_chksum_pseudo(): unwrapped lwip_chksum()=%"X32_F" \n", acc));*/ + /* fold the upper bit down */ + acc = FOLD_U32T(acc); + if (q->len % 2 != 0) { + swapped = 1 - swapped; + acc = SWAP_BYTES_IN_WORD(acc); + } + /*LWIP_DEBUGF(INET_DEBUG, ("inet_chksum_pseudo(): wrapped lwip_chksum()=%"X32_F" \n", acc));*/ + } + + if (swapped) { + acc = SWAP_BYTES_IN_WORD(acc); + } + + acc += (u32_t)htons((u16_t)proto); + acc += (u32_t)htons(proto_len); + + /* Fold 32-bit sum to 16 bits + calling this twice is probably faster than if statements... */ + acc = FOLD_U32T(acc); + acc = FOLD_U32T(acc); + LWIP_DEBUGF(INET_DEBUG, ("inet_chksum_pseudo(): pbuf chain lwip_chksum()=%"X32_F"\n", acc)); + return (u16_t)~(acc & 0xffffUL); +} + +#if LWIP_IPV4 +/* inet_chksum_pseudo_partial: + * + * Calculates the IPv4 pseudo Internet checksum used by TCP and UDP for a pbuf chain. + * IP addresses are expected to be in network byte order. + * + * @param p chain of pbufs over that a checksum should be calculated (ip data part) + * @param src source ip address (used for checksum of pseudo header) + * @param dst destination ip address (used for checksum of pseudo header) + * @param proto ip protocol (used for checksum of pseudo header) + * @param proto_len length of the ip data part (used for checksum of pseudo header) + * @return checksum (as u16_t) to be saved directly in the protocol header + */ +u16_t +inet_chksum_pseudo_partial(struct pbuf *p, u8_t proto, u16_t proto_len, + u16_t chksum_len, const ip4_addr_t *src, const ip4_addr_t *dest) +{ + u32_t acc; + u32_t addr; + + addr = ip4_addr_get_u32(src); + acc = (addr & 0xffffUL); + acc += ((addr >> 16) & 0xffffUL); + addr = ip4_addr_get_u32(dest); + acc += (addr & 0xffffUL); + acc += ((addr >> 16) & 0xffffUL); + /* fold down to 16 bits */ + acc = FOLD_U32T(acc); + acc = FOLD_U32T(acc); + + return inet_cksum_pseudo_partial_base(p, proto, proto_len, chksum_len, acc); +} +#endif /* LWIP_IPV4 */ + +#if LWIP_IPV6 +/** + * Calculates the checksum with IPv6 pseudo header used by TCP and UDP for a pbuf chain. + * IPv6 addresses are expected to be in network byte order. Will only compute for a + * portion of the payload. + * + * @param p chain of pbufs over that a checksum should be calculated (ip data part) + * @param src source ipv6 address (used for checksum of pseudo header) + * @param dst destination ipv6 address (used for checksum of pseudo header) + * @param proto ipv6 protocol/next header (used for checksum of pseudo header) + * @param proto_len length of the ipv6 payload (used for checksum of pseudo header) + * @param chksum_len number of payload bytes used to compute chksum + * @return checksum (as u16_t) to be saved directly in the protocol header + */ +u16_t +ip6_chksum_pseudo_partial(struct pbuf *p, u8_t proto, u16_t proto_len, + u16_t chksum_len, const ip6_addr_t *src, const ip6_addr_t *dest) +{ + u32_t acc = 0; + u32_t addr; + u8_t addr_part; + + for (addr_part = 0; addr_part < 4; addr_part++) { + addr = src->addr[addr_part]; + acc += (addr & 0xffffUL); + acc += ((addr >> 16) & 0xffffUL); + addr = dest->addr[addr_part]; + acc += (addr & 0xffffUL); + acc += ((addr >> 16) & 0xffffUL); + } + /* fold down to 16 bits */ + acc = FOLD_U32T(acc); + acc = FOLD_U32T(acc); + + return inet_cksum_pseudo_partial_base(p, proto, proto_len, chksum_len, acc); +} +#endif /* LWIP_IPV6 */ + +/* ip_chksum_pseudo_partial: + * + * Calculates the IPv4 or IPv6 pseudo Internet checksum used by TCP and UDP for a pbuf chain. + * + * @param p chain of pbufs over that a checksum should be calculated (ip data part) + * @param src source ip address (used for checksum of pseudo header) + * @param dst destination ip address (used for checksum of pseudo header) + * @param proto ip protocol (used for checksum of pseudo header) + * @param proto_len length of the ip data part (used for checksum of pseudo header) + * @return checksum (as u16_t) to be saved directly in the protocol header + */ +u16_t +ip_chksum_pseudo_partial(struct pbuf *p, u8_t proto, u16_t proto_len, + u16_t chksum_len, const ip_addr_t *src, const ip_addr_t *dest) +{ +#if LWIP_IPV6 + if (IP_IS_V6(dest)) { + return ip6_chksum_pseudo_partial(p, proto, proto_len, chksum_len, ip_2_ip6(src), ip_2_ip6(dest)); + } +#endif /* LWIP_IPV6 */ +#if LWIP_IPV4 && LWIP_IPV6 + else +#endif /* LWIP_IPV4 && LWIP_IPV6 */ +#if LWIP_IPV4 + { + return inet_chksum_pseudo_partial(p, proto, proto_len, chksum_len, ip_2_ip4(src), ip_2_ip4(dest)); + } +#endif /* LWIP_IPV4 */ +} + +/* inet_chksum: + * + * Calculates the Internet checksum over a portion of memory. Used primarily for IP + * and ICMP. + * + * @param dataptr start of the buffer to calculate the checksum (no alignment needed) + * @param len length of the buffer to calculate the checksum + * @return checksum (as u16_t) to be saved directly in the protocol header + */ + +u16_t +inet_chksum(const void *dataptr, u16_t len) +{ + return (u16_t)~(unsigned int)LWIP_CHKSUM(dataptr, len); +} + +/** + * Calculate a checksum over a chain of pbufs (without pseudo-header, much like + * inet_chksum only pbufs are used). + * + * @param p pbuf chain over that the checksum should be calculated + * @return checksum (as u16_t) to be saved directly in the protocol header + */ +u16_t +inet_chksum_pbuf(struct pbuf *p) +{ + u32_t acc; + struct pbuf *q; + u8_t swapped; + + acc = 0; + swapped = 0; + for (q = p; q != NULL; q = q->next) { + acc += LWIP_CHKSUM(q->payload, q->len); + acc = FOLD_U32T(acc); + if (q->len % 2 != 0) { + swapped = 1 - swapped; + acc = SWAP_BYTES_IN_WORD(acc); + } + } + + if (swapped) { + acc = SWAP_BYTES_IN_WORD(acc); + } + return (u16_t)~(acc & 0xffffUL); +} + +/* These are some implementations for LWIP_CHKSUM_COPY, which copies data + * like MEMCPY but generates a checksum at the same time. Since this is a + * performance-sensitive function, you might want to create your own version + * in assembly targeted at your hardware by defining it in lwipopts.h: + * #define LWIP_CHKSUM_COPY(dst, src, len) your_chksum_copy(dst, src, len) + */ + +#if (LWIP_CHKSUM_COPY_ALGORITHM == 1) /* Version #1 */ +/** Safe but slow: first call MEMCPY, then call LWIP_CHKSUM. + * For architectures with big caches, data might still be in cache when + * generating the checksum after copying. + */ +u16_t +lwip_chksum_copy(void *dst, const void *src, u16_t len) +{ + MEMCPY(dst, src, len); + return LWIP_CHKSUM(dst, len); +} +#endif /* (LWIP_CHKSUM_COPY_ALGORITHM == 1) */ diff --git a/components/lwip/core/init.c b/components/lwip/core/init.c new file mode 100755 index 0000000000..2a410d0e46 --- /dev/null +++ b/components/lwip/core/init.c @@ -0,0 +1,378 @@ +/** + * @file + * Modules initialization + * + */ + +/* + * Copyright (c) 2001-2004 Swedish Institute of Computer Science. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + * + */ + +#include "lwip/opt.h" + +#include "lwip/init.h" +#include "lwip/stats.h" +#include "lwip/sys.h" +#include "lwip/mem.h" +#include "lwip/memp.h" +#include "lwip/pbuf.h" +#include "lwip/netif.h" +#include "lwip/sockets.h" +#include "lwip/ip.h" +#include "lwip/raw.h" +#include "lwip/udp.h" +#include "lwip/priv/tcp_priv.h" +#include "lwip/autoip.h" +#include "lwip/igmp.h" +#include "lwip/dns.h" +#include "lwip/timers.h" +#include "netif/etharp.h" +#include "lwip/ip6.h" +#include "lwip/nd6.h" +#include "lwip/mld6.h" +#include "lwip/api.h" +#include "netif/ppp/ppp_impl.h" + +#ifndef PERF +/* Compile-time sanity checks for configuration errors. + * These can be done independently of LWIP_DEBUG, without penalty. + */ +#ifndef BYTE_ORDER + #error "BYTE_ORDER is not defined, you have to define it in your cc.h" +#endif +#if (!IP_SOF_BROADCAST && IP_SOF_BROADCAST_RECV) + #error "If you want to use broadcast filter per pcb on recv operations, you have to define IP_SOF_BROADCAST=1 in your lwipopts.h" +#endif +#if (!LWIP_UDP && LWIP_UDPLITE) + #error "If you want to use UDP Lite, you have to define LWIP_UDP=1 in your lwipopts.h" +#endif +#if (!LWIP_UDP && LWIP_DHCP) + #error "If you want to use DHCP, you have to define LWIP_UDP=1 in your lwipopts.h" +#endif +#if (!LWIP_UDP && LWIP_MULTICAST_TX_OPTIONS) + #error "If you want to use IGMP/LWIP_MULTICAST_TX_OPTIONS, you have to define LWIP_UDP=1 in your lwipopts.h" +#endif +#if (!LWIP_UDP && LWIP_DNS) + #error "If you want to use DNS, you have to define LWIP_UDP=1 in your lwipopts.h" +#endif +#if !MEMP_MEM_MALLOC /* MEMP_NUM_* checks are disabled when not using the pool allocator */ +#if (LWIP_ARP && ARP_QUEUEING && (MEMP_NUM_ARP_QUEUE<=0)) + #error "If you want to use ARP Queueing, you have to define MEMP_NUM_ARP_QUEUE>=1 in your lwipopts.h" +#endif +#if (LWIP_RAW && (MEMP_NUM_RAW_PCB<=0)) + #error "If you want to use RAW, you have to define MEMP_NUM_RAW_PCB>=1 in your lwipopts.h" +#endif +#if (LWIP_UDP && (MEMP_NUM_UDP_PCB<=0)) + #error "If you want to use UDP, you have to define MEMP_NUM_UDP_PCB>=1 in your lwipopts.h" +#endif +#if (LWIP_TCP && (MEMP_NUM_TCP_PCB<=0)) + #error "If you want to use TCP, you have to define MEMP_NUM_TCP_PCB>=1 in your lwipopts.h" +#endif +#if (LWIP_IGMP && (MEMP_NUM_IGMP_GROUP<=1)) + #error "If you want to use IGMP, you have to define MEMP_NUM_IGMP_GROUP>1 in your lwipopts.h" +#endif +#if (LWIP_IGMP && !LWIP_MULTICAST_TX_OPTIONS) + #error "If you want to use IGMP, you have to define LWIP_MULTICAST_TX_OPTIONS==1 in your lwipopts.h" +#endif +#if (LWIP_IGMP && !LWIP_IPV4) + #error "IGMP needs LWIP_IPV4 enabled in your lwipopts.h" +#endif +#if (LWIP_MULTICAST_TX_OPTIONS && !LWIP_IPV4) + #error "LWIP_MULTICAST_TX_OPTIONS needs LWIP_IPV4 enabled in your lwipopts.h" +#endif +#if ((LWIP_NETCONN || LWIP_SOCKET) && (MEMP_NUM_TCPIP_MSG_API<=0)) + #error "If you want to use Sequential API, you have to define MEMP_NUM_TCPIP_MSG_API>=1 in your lwipopts.h" +#endif +/* There must be sufficient timeouts, taking into account requirements of the subsystems. */ +#if LWIP_TIMERS && (MEMP_NUM_SYS_TIMEOUT < (LWIP_TCP + IP_REASSEMBLY + LWIP_ARP + (2*LWIP_DHCP) + LWIP_AUTOIP + LWIP_IGMP + LWIP_DNS + PPP_SUPPORT + (LWIP_IPV6 ? (1 + LWIP_IPV6_REASS + LWIP_IPV6_MLD) : 0))) + #error "MEMP_NUM_SYS_TIMEOUT is too low to accomodate all required timeouts" +#endif +#if (IP_REASSEMBLY && (MEMP_NUM_REASSDATA > IP_REASS_MAX_PBUFS)) + #error "MEMP_NUM_REASSDATA > IP_REASS_MAX_PBUFS doesn't make sense since each struct ip_reassdata must hold 2 pbufs at least!" +#endif +#endif /* !MEMP_MEM_MALLOC */ + +#if LWIP_WND_SCALE +//#if (LWIP_TCP && (TCP_WND > 0xffffffff)) + //#error "If you want to use TCP, TCP_WND must fit in an u32_t, so, you have to reduce it in your lwipopts.h" +//#endif +#if (LWIP_TCP && LWIP_WND_SCALE && (TCP_RCV_SCALE > 14)) + #error "The maximum valid window scale value is 14!" +#endif +//#if (LWIP_TCP && (TCP_WND > (0xFFFFU << TCP_RCV_SCALE))) + //#error "TCP_WND is bigger than the configured LWIP_WND_SCALE allows!" +//#endif +//#if (LWIP_TCP && ((TCP_WND >> TCP_RCV_SCALE) == 0)) + //#error "TCP_WND is too small for the configured LWIP_WND_SCALE (results in zero window)!" +//#endif +#else /* LWIP_WND_SCALE */ + +#ifndef LWIP_ESP8266 +#if (LWIP_TCP && (TCP_WND > 0xffff)) + #error "If you want to use TCP, TCP_WND must fit in an u16_t, so, you have to reduce it in your lwipopts.h (or enable window scaling)" +#endif +#endif + +#endif /* LWIP_WND_SCALE */ +#if (LWIP_TCP && (TCP_SND_QUEUELEN > 0xffff)) + #error "If you want to use TCP, TCP_SND_QUEUELEN must fit in an u16_t, so, you have to reduce it in your lwipopts.h" +#endif +#if (LWIP_TCP && (TCP_SND_QUEUELEN < 2)) + #error "TCP_SND_QUEUELEN must be at least 2 for no-copy TCP writes to work" +#endif + +#ifndef LWIP_ESP8266 +#if (LWIP_TCP && ((TCP_MAXRTX > 12) || (TCP_SYNMAXRTX > 12))) + #error "If you want to use TCP, TCP_MAXRTX and TCP_SYNMAXRTX must less or equal to 12 (due to tcp_backoff table), so, you have to reduce them in your lwipopts.h" +#endif +#endif + +#if (LWIP_TCP && TCP_LISTEN_BACKLOG && ((TCP_DEFAULT_LISTEN_BACKLOG < 0) || (TCP_DEFAULT_LISTEN_BACKLOG > 0xff))) + #error "If you want to use TCP backlog, TCP_DEFAULT_LISTEN_BACKLOG must fit into an u8_t" +#endif +#if (LWIP_NETIF_API && (NO_SYS==1)) + #error "If you want to use NETIF API, you have to define NO_SYS=0 in your lwipopts.h" +#endif +#if ((LWIP_SOCKET || LWIP_NETCONN) && (NO_SYS==1)) + #error "If you want to use Sequential API, you have to define NO_SYS=0 in your lwipopts.h" +#endif +#if (LWIP_PPP_API && (NO_SYS==1)) + #error "If you want to use PPP API, you have to define NO_SYS=0 in your lwipopts.h" +#endif +#if (LWIP_PPP_API && (PPP_SUPPORT==0)) + #error "If you want to use PPP API, you have to enable PPP_SUPPORT in your lwipopts.h" +#endif +#if (((!LWIP_DHCP) || (!LWIP_AUTOIP)) && LWIP_DHCP_AUTOIP_COOP) + #error "If you want to use DHCP/AUTOIP cooperation mode, you have to define LWIP_DHCP=1 and LWIP_AUTOIP=1 in your lwipopts.h" +#endif +#if (((!LWIP_DHCP) || (!LWIP_ARP)) && DHCP_DOES_ARP_CHECK) + #error "If you want to use DHCP ARP checking, you have to define LWIP_DHCP=1 and LWIP_ARP=1 in your lwipopts.h" +#endif +#if (!LWIP_ARP && LWIP_AUTOIP) + #error "If you want to use AUTOIP, you have to define LWIP_ARP=1 in your lwipopts.h" +#endif +#if (LWIP_TCP && ((LWIP_EVENT_API && LWIP_CALLBACK_API) || (!LWIP_EVENT_API && !LWIP_CALLBACK_API))) + #error "One and exactly one of LWIP_EVENT_API and LWIP_CALLBACK_API has to be enabled in your lwipopts.h" +#endif +#if (MEM_LIBC_MALLOC && MEM_USE_POOLS) + #error "MEM_LIBC_MALLOC and MEM_USE_POOLS may not both be simultaneously enabled in your lwipopts.h" +#endif +#if (MEM_USE_POOLS && !MEMP_USE_CUSTOM_POOLS) + #error "MEM_USE_POOLS requires custom pools (MEMP_USE_CUSTOM_POOLS) to be enabled in your lwipopts.h" +#endif +#if (PBUF_POOL_BUFSIZE <= MEM_ALIGNMENT) + #error "PBUF_POOL_BUFSIZE must be greater than MEM_ALIGNMENT or the offset may take the full first pbuf" +#endif +#if (DNS_LOCAL_HOSTLIST && !DNS_LOCAL_HOSTLIST_IS_DYNAMIC && !(defined(DNS_LOCAL_HOSTLIST_INIT))) + #error "you have to define define DNS_LOCAL_HOSTLIST_INIT {{'host1', 0x123}, {'host2', 0x234}} to initialize DNS_LOCAL_HOSTLIST" +#endif +#if PPP_SUPPORT && !PPPOS_SUPPORT && !PPPOE_SUPPORT && !PPPOL2TP_SUPPORT + #error "PPP_SUPPORT needs at least one of PPPOS_SUPPORT, PPPOE_SUPPORT or PPPOL2TP_SUPPORT turned on" +#endif +#if PPP_SUPPORT && !PPP_IPV4_SUPPORT && !PPP_IPV6_SUPPORT + #error "PPP_SUPPORT needs PPP_IPV4_SUPPORT and/or PPP_IPV6_SUPPORT turned on" +#endif +#if PPP_SUPPORT && PPP_IPV4_SUPPORT && !LWIP_IPV4 + #error "PPP_IPV4_SUPPORT needs LWIP_IPV4 turned on" +#endif +#if PPP_SUPPORT && PPP_IPV6_SUPPORT && !LWIP_IPV6 + #error "PPP_IPV6_SUPPORT needs LWIP_IPV6 turned on" +#endif +#if !LWIP_ETHERNET && (LWIP_ARP || PPPOE_SUPPORT) + #error "LWIP_ETHERNET needs to be turned on for LWIP_ARP or PPPOE_SUPPORT" +#endif +#if (LWIP_IGMP || LWIP_IPV6) && !defined(LWIP_RAND) + #error "When using IGMP or IPv6, LWIP_RAND() needs to be defined to a random-function returning an u32_t random value" +#endif +#if LWIP_TCPIP_CORE_LOCKING_INPUT && !LWIP_TCPIP_CORE_LOCKING + #error "When using LWIP_TCPIP_CORE_LOCKING_INPUT, LWIP_TCPIP_CORE_LOCKING must be enabled, too" +#endif +#if LWIP_TCP && LWIP_NETIF_TX_SINGLE_PBUF && !TCP_OVERSIZE + #error "LWIP_NETIF_TX_SINGLE_PBUF needs TCP_OVERSIZE enabled to create single-pbuf TCP packets" +#endif +#if IP_FRAG && IP_FRAG_USES_STATIC_BUF && LWIP_NETIF_TX_SINGLE_PBUF + #error "LWIP_NETIF_TX_SINGLE_PBUF does not work with IP_FRAG_USES_STATIC_BUF==1 as that creates pbuf queues" +#endif +#if LWIP_NETCONN && LWIP_TCP +#if NETCONN_COPY != TCP_WRITE_FLAG_COPY + #error "NETCONN_COPY != TCP_WRITE_FLAG_COPY" +#endif +#if NETCONN_MORE != TCP_WRITE_FLAG_MORE + #error "NETCONN_MORE != TCP_WRITE_FLAG_MORE" +#endif +#endif /* LWIP_NETCONN && LWIP_TCP */ +#if LWIP_SOCKET +/* Check that the SO_* socket options and SOF_* lwIP-internal flags match */ +#if SO_REUSEADDR != SOF_REUSEADDR + #error "WARNING: SO_REUSEADDR != SOF_REUSEADDR" +#endif +#if SO_KEEPALIVE != SOF_KEEPALIVE + #error "WARNING: SO_KEEPALIVE != SOF_KEEPALIVE" +#endif +#if SO_BROADCAST != SOF_BROADCAST + #error "WARNING: SO_BROADCAST != SOF_BROADCAST" +#endif +#endif /* LWIP_SOCKET */ + + +/* Compile-time checks for deprecated options. + */ +#ifdef MEMP_NUM_TCPIP_MSG + #error "MEMP_NUM_TCPIP_MSG option is deprecated. Remove it from your lwipopts.h." +#endif +#ifdef TCP_REXMIT_DEBUG + #error "TCP_REXMIT_DEBUG option is deprecated. Remove it from your lwipopts.h." +#endif +#ifdef RAW_STATS + #error "RAW_STATS option is deprecated. Remove it from your lwipopts.h." +#endif +#ifdef ETHARP_QUEUE_FIRST + #error "ETHARP_QUEUE_FIRST option is deprecated. Remove it from your lwipopts.h." +#endif +#ifdef ETHARP_ALWAYS_INSERT + #error "ETHARP_ALWAYS_INSERT option is deprecated. Remove it from your lwipopts.h." +#endif + +#ifndef LWIP_DISABLE_TCP_SANITY_CHECKS +#define LWIP_DISABLE_TCP_SANITY_CHECKS 0 +#endif +#ifndef LWIP_DISABLE_MEMP_SANITY_CHECKS +#define LWIP_DISABLE_MEMP_SANITY_CHECKS 0 +#endif + +/* MEMP sanity checks */ +#if !LWIP_DISABLE_MEMP_SANITY_CHECKS +#if LWIP_NETCONN +#if MEMP_MEM_MALLOC +#if !MEMP_NUM_NETCONN && LWIP_SOCKET +#error "lwip_sanity_check: WARNING: MEMP_NUM_NETCONN cannot be 0 when using sockets!" +#endif +#else /* MEMP_MEM_MALLOC */ +#if MEMP_NUM_NETCONN > (MEMP_NUM_TCP_PCB+MEMP_NUM_TCP_PCB_LISTEN+MEMP_NUM_UDP_PCB+MEMP_NUM_RAW_PCB) +#error "lwip_sanity_check: WARNING: MEMP_NUM_NETCONN should be less than the sum of MEMP_NUM_{TCP,RAW,UDP}_PCB+MEMP_NUM_TCP_PCB_LISTEN. If you know what you are doing, define LWIP_DISABLE_MEMP_SANITY_CHECKS to 1 to disable this error." +#endif +#endif /* MEMP_MEM_MALLOC */ +#endif /* LWIP_NETCONN */ +#endif /* !LWIP_DISABLE_MEMP_SANITY_CHECKS */ + +/* TCP sanity checks */ +#if !LWIP_DISABLE_TCP_SANITY_CHECKS +#if LWIP_TCP +#if !MEMP_MEM_MALLOC && (MEMP_NUM_TCP_SEG < TCP_SND_QUEUELEN) + #error "lwip_sanity_check: WARNING: MEMP_NUM_TCP_SEG should be at least as big as TCP_SND_QUEUELEN. If you know what you are doing, define LWIP_DISABLE_TCP_SANITY_CHECKS to 1 to disable this error." +#endif +#if TCP_SND_BUF < (2 * TCP_MSS) + #error "lwip_sanity_check: WARNING: TCP_SND_BUF must be at least as much as (2 * TCP_MSS) for things to work smoothly. If you know what you are doing, define LWIP_DISABLE_TCP_SANITY_CHECKS to 1 to disable this error." +#endif +#if TCP_SND_QUEUELEN < (2 * (TCP_SND_BUF / TCP_MSS)) + #error "lwip_sanity_check: WARNING: TCP_SND_QUEUELEN must be at least as much as (2 * TCP_SND_BUF/TCP_MSS) for things to work. If you know what you are doing, define LWIP_DISABLE_TCP_SANITY_CHECKS to 1 to disable this error." +#endif +#if TCP_SNDLOWAT >= TCP_SND_BUF + #error "lwip_sanity_check: WARNING: TCP_SNDLOWAT must be less than TCP_SND_BUF. If you know what you are doing, define LWIP_DISABLE_TCP_SANITY_CHECKS to 1 to disable this error." +#endif +#if TCP_SNDLOWAT >= (0xFFFF - (4 * TCP_MSS)) + #error "lwip_sanity_check: WARNING: TCP_SNDLOWAT must at least be 4*MSS below u16_t overflow!" +#endif +#if TCP_SNDQUEUELOWAT >= TCP_SND_QUEUELEN + #error "lwip_sanity_check: WARNING: TCP_SNDQUEUELOWAT must be less than TCP_SND_QUEUELEN. If you know what you are doing, define LWIP_DISABLE_TCP_SANITY_CHECKS to 1 to disable this error." +#endif +#if !MEMP_MEM_MALLOC && (PBUF_POOL_BUFSIZE <= (PBUF_LINK_ENCAPSULATION_HLEN + PBUF_LINK_HLEN + PBUF_IP_HLEN + PBUF_TRANSPORT_HLEN)) + #error "lwip_sanity_check: WARNING: PBUF_POOL_BUFSIZE does not provide enough space for protocol headers. If you know what you are doing, define LWIP_DISABLE_TCP_SANITY_CHECKS to 1 to disable this error." +#endif + +#ifndef LWIP_ESP8266 +#if !MEMP_MEM_MALLOC && (TCP_WND > (PBUF_POOL_SIZE * (PBUF_POOL_BUFSIZE - (PBUF_LINK_ENCAPSULATION_HLEN + PBUF_LINK_HLEN + PBUF_IP_HLEN + PBUF_TRANSPORT_HLEN)))) + #error "lwip_sanity_check: WARNING: TCP_WND is larger than space provided by PBUF_POOL_SIZE * (PBUF_POOL_BUFSIZE - protocol headers). If you know what you are doing, define LWIP_DISABLE_TCP_SANITY_CHECKS to 1 to disable this error." +#endif + +#if TCP_WND < TCP_MSS + #error "lwip_sanity_check: WARNING: TCP_WND is smaller than MSS. If you know what you are doing, define LWIP_DISABLE_TCP_SANITY_CHECKS to 1 to disable this error." +#endif +#endif + +#endif /* LWIP_TCP */ +#endif /* !LWIP_DISABLE_TCP_SANITY_CHECKS */ +#endif + +/** + * Initialize all modules. + */ +void +lwip_init(void) +{ +#ifdef LWIP_ESP8266 +// MEMP_NUM_TCP_PCB = 5; +// TCP_WND = (4 * TCP_MSS); +// TCP_MAXRTX = 12; +// TCP_SYNMAXRTX = 6; +#endif + + /* Modules initialization */ + stats_init(); +#if !NO_SYS + sys_init(); +#endif /* !NO_SYS */ + mem_init(); + memp_init(); + pbuf_init(); + netif_init(); +#if LWIP_IPV4 + ip_init(); +#if LWIP_ARP + etharp_init(); +#endif /* LWIP_ARP */ +#endif /* LWIP_IPV4 */ +#if LWIP_RAW + raw_init(); +#endif /* LWIP_RAW */ +#if LWIP_UDP + udp_init(); +#endif /* LWIP_UDP */ +#if LWIP_TCP + tcp_init(); +#endif /* LWIP_TCP */ +#if LWIP_AUTOIP + autoip_init(); +#endif /* LWIP_AUTOIP */ +#if LWIP_IGMP + igmp_init(); +#endif /* LWIP_IGMP */ +#if LWIP_DNS + dns_init(); +#endif /* LWIP_DNS */ +#if PPP_SUPPORT + ppp_init(); +#endif + +#if LWIP_TIMERS + sys_timeouts_init(); +#endif /* LWIP_TIMERS */ +} diff --git a/components/lwip/core/ip.c b/components/lwip/core/ip.c new file mode 100755 index 0000000000..aa42fba763 --- /dev/null +++ b/components/lwip/core/ip.c @@ -0,0 +1,101 @@ +/** + * @file ip.c + * Common IPv4 and IPv6 code + * + */ + +/* + * Copyright (c) 2001-2004 Swedish Institute of Computer Science. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + * + */ + +#include "lwip/opt.h" + +#if LWIP_IPV4 || LWIP_IPV6 + +#include "lwip/ip_addr.h" +#include "lwip/ip.h" + +/** Global data for both IPv4 and IPv6 */ +struct ip_globals ip_data; + +#if LWIP_IPV4 && LWIP_IPV6 + +const ip_addr_t ip_addr_any_type = IPADDR_ANY_TYPE_INIT; + +/** Convert IP address string (both versions) to numeric. + * The version is auto-detected from the string. + * + * @param cp IP address string to convert + * @param addr conversion result is stored here + * @return 1 on success, 0 on error + */ +int +ipaddr_aton(const char *cp, ip_addr_t *addr) +{ + if (cp != NULL) { + const char* c; + for (c = cp; *c != 0; c++) { + if (*c == ':') { + /* contains a colon: IPv6 address */ + if (addr) { + IP_SET_TYPE_VAL(*addr, IPADDR_TYPE_V6); + } + return ip6addr_aton(cp, ip_2_ip6(addr)); + } else if (*c == '.') { + /* contains a dot: IPv4 address */ + break; + } + } + /* call ip4addr_aton as fallback or if IPv4 was found */ + if (addr) { + IP_SET_TYPE_VAL(*addr, IPADDR_TYPE_V4); + } + return ip4addr_aton(cp, ip_2_ip4(addr)); + } + return 0; +} + +/* If both IP versions are enabled, this function can dispatch packets to the correct one. */ +err_t +ip_input(struct pbuf *p, struct netif *inp) +{ + if (p != NULL) { + if (IP_HDR_GET_VERSION(p->payload) == 6) { + return ip6_input(p, inp); + } + return ip4_input(p, inp); + } + return ERR_VAL; +} + +#endif /* LWIP_IPV4 && LWIP_IPV6 */ + +#endif /* LWIP_IPV4 || LWIP_IPV6 */ diff --git a/components/lwip/core/ipv4/autoip.c b/components/lwip/core/ipv4/autoip.c new file mode 100755 index 0000000000..391e8eeaed --- /dev/null +++ b/components/lwip/core/ipv4/autoip.c @@ -0,0 +1,549 @@ +/** + * @file + * AutoIP Automatic LinkLocal IP Configuration + * + */ + +/* + * + * Copyright (c) 2007 Dominik Spies + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * Author: Dominik Spies + * + * This is a AutoIP implementation for the lwIP TCP/IP stack. It aims to conform + * with RFC 3927. + * + * + * Please coordinate changes and requests with Dominik Spies + * + */ + +/******************************************************************************* + * USAGE: + * + * define LWIP_AUTOIP 1 in your lwipopts.h + * + * If you don't use tcpip.c (so, don't call, you don't call tcpip_init): + * - First, call autoip_init(). + * - call autoip_tmr() all AUTOIP_TMR_INTERVAL msces, + * that should be defined in autoip.h. + * I recommend a value of 100. The value must divide 1000 with a remainder almost 0. + * Possible values are 1000, 500, 333, 250, 200, 166, 142, 125, 111, 100 .... + * + * Without DHCP: + * - Call autoip_start() after netif_add(). + * + * With DHCP: + * - define LWIP_DHCP_AUTOIP_COOP 1 in your lwipopts.h. + * - Configure your DHCP Client. + * + */ + +#include "lwip/opt.h" + +#if LWIP_IPV4 && LWIP_AUTOIP /* don't build if not configured for use in lwipopts.h */ + +#include "lwip/mem.h" +/* #include "lwip/udp.h" */ +#include "lwip/ip_addr.h" +#include "lwip/netif.h" +#include "lwip/autoip.h" +#include "netif/etharp.h" + +#include +#include + +#ifdef MEMLEAK_DEBUG +static const char mem_debug_file[] ICACHE_RODATA_ATTR STORE_ATTR = __FILE__; +#endif + + +/* 169.254.0.0 */ +#define AUTOIP_NET 0xA9FE0000 +/* 169.254.1.0 */ +#define AUTOIP_RANGE_START (AUTOIP_NET | 0x0100) +/* 169.254.254.255 */ +#define AUTOIP_RANGE_END (AUTOIP_NET | 0xFEFF) + + +/** Pseudo random macro based on netif informations. + * You could use "rand()" from the C Library if you define LWIP_AUTOIP_RAND in lwipopts.h */ +#ifndef LWIP_AUTOIP_RAND +#define LWIP_AUTOIP_RAND(netif) ( (((u32_t)((netif->hwaddr[5]) & 0xff) << 24) | \ + ((u32_t)((netif->hwaddr[3]) & 0xff) << 16) | \ + ((u32_t)((netif->hwaddr[2]) & 0xff) << 8) | \ + ((u32_t)((netif->hwaddr[4]) & 0xff))) + \ + (netif->autoip?netif->autoip->tried_llipaddr:0)) +#endif /* LWIP_AUTOIP_RAND */ + +/** + * Macro that generates the initial IP address to be tried by AUTOIP. + * If you want to override this, define it to something else in lwipopts.h. + */ +#ifndef LWIP_AUTOIP_CREATE_SEED_ADDR +#define LWIP_AUTOIP_CREATE_SEED_ADDR(netif) \ + htonl(AUTOIP_RANGE_START + ((u32_t)(((u8_t)(netif->hwaddr[4])) | \ + ((u32_t)((u8_t)(netif->hwaddr[5]))) << 8))) +#endif /* LWIP_AUTOIP_CREATE_SEED_ADDR */ + +/* static functions */ +static void autoip_handle_arp_conflict(struct netif *netif); + +/* creates a pseudo random LL IP-Address for a network interface */ +static void autoip_create_addr(struct netif *netif, ip4_addr_t *ipaddr); + +/* sends an ARP probe */ +static err_t autoip_arp_probe(struct netif *netif); + +/* sends an ARP announce */ +static err_t autoip_arp_announce(struct netif *netif); + +/* configure interface for use with current LL IP-Address */ +static err_t autoip_bind(struct netif *netif); + +/* start sending probes for llipaddr */ +static void autoip_start_probing(struct netif *netif); + + +/** Set a statically allocated struct autoip to work with. + * Using this prevents autoip_start to allocate it using mem_malloc. + * + * @param netif the netif for which to set the struct autoip + * @param dhcp (uninitialised) dhcp struct allocated by the application + */ +void +autoip_set_struct(struct netif *netif, struct autoip *autoip) +{ + LWIP_ASSERT("netif != NULL", netif != NULL); + LWIP_ASSERT("autoip != NULL", autoip != NULL); + LWIP_ASSERT("netif already has a struct autoip set", netif->autoip == NULL); + + /* clear data structure */ + memset(autoip, 0, sizeof(struct autoip)); + /* autoip->state = AUTOIP_STATE_OFF; */ + netif->autoip = autoip; +} + +/** Restart AutoIP client and check the next address (conflict detected) + * + * @param netif The netif under AutoIP control + */ +static void +autoip_restart(struct netif *netif) +{ + netif->autoip->tried_llipaddr++; + autoip_start(netif); +} + +/** + * Handle a IP address conflict after an ARP conflict detection + */ +static void +autoip_handle_arp_conflict(struct netif *netif) +{ + /* Somehow detect if we are defending or retreating */ + unsigned char defend = 1; /* tbd */ + + if (defend) { + if (netif->autoip->lastconflict > 0) { + /* retreat, there was a conflicting ARP in the last + * DEFEND_INTERVAL seconds + */ + LWIP_DEBUGF(AUTOIP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, + ("autoip_handle_arp_conflict(): we are defending, but in DEFEND_INTERVAL, retreating\n")); + + /* TODO: close all TCP sessions */ + autoip_restart(netif); + } else { + LWIP_DEBUGF(AUTOIP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, + ("autoip_handle_arp_conflict(): we are defend, send ARP Announce\n")); + autoip_arp_announce(netif); + netif->autoip->lastconflict = DEFEND_INTERVAL * AUTOIP_TICKS_PER_SECOND; + } + } else { + LWIP_DEBUGF(AUTOIP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, + ("autoip_handle_arp_conflict(): we do not defend, retreating\n")); + /* TODO: close all TCP sessions */ + autoip_restart(netif); + } +} + +/** + * Create an IP-Address out of range 169.254.1.0 to 169.254.254.255 + * + * @param netif network interface on which create the IP-Address + * @param ipaddr ip address to initialize + */ +static void +autoip_create_addr(struct netif *netif, ip4_addr_t *ipaddr) +{ + /* Here we create an IP-Address out of range 169.254.1.0 to 169.254.254.255 + * compliant to RFC 3927 Section 2.1 + * We have 254 * 256 possibilities */ + + u32_t addr = ntohl(LWIP_AUTOIP_CREATE_SEED_ADDR(netif)); + addr += netif->autoip->tried_llipaddr; + addr = AUTOIP_NET | (addr & 0xffff); + /* Now, 169.254.0.0 <= addr <= 169.254.255.255 */ + + if (addr < AUTOIP_RANGE_START) { + addr += AUTOIP_RANGE_END - AUTOIP_RANGE_START + 1; + } + if (addr > AUTOIP_RANGE_END) { + addr -= AUTOIP_RANGE_END - AUTOIP_RANGE_START + 1; + } + LWIP_ASSERT("AUTOIP address not in range", (addr >= AUTOIP_RANGE_START) && + (addr <= AUTOIP_RANGE_END)); + ip4_addr_set_u32(ipaddr, htonl(addr)); + + LWIP_DEBUGF(AUTOIP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, + ("autoip_create_addr(): tried_llipaddr=%"U16_F", %"U16_F".%"U16_F".%"U16_F".%"U16_F"\n", + (u16_t)(netif->autoip->tried_llipaddr), ip4_addr1_16(ipaddr), ip4_addr2_16(ipaddr), + ip4_addr3_16(ipaddr), ip4_addr4_16(ipaddr))); +} + +/** + * Sends an ARP probe from a network interface + * + * @param netif network interface used to send the probe + */ +static err_t +autoip_arp_probe(struct netif *netif) +{ + return etharp_raw(netif, (struct eth_addr *)netif->hwaddr, ðbroadcast, + (struct eth_addr *)netif->hwaddr, IP4_ADDR_ANY, ðzero, + &netif->autoip->llipaddr, ARP_REQUEST); +} + +/** + * Sends an ARP announce from a network interface + * + * @param netif network interface used to send the announce + */ +static err_t +autoip_arp_announce(struct netif *netif) +{ + return etharp_raw(netif, (struct eth_addr *)netif->hwaddr, ðbroadcast, + (struct eth_addr *)netif->hwaddr, &netif->autoip->llipaddr, ðzero, + &netif->autoip->llipaddr, ARP_REQUEST); +} + +/** + * Configure interface for use with current LL IP-Address + * + * @param netif network interface to configure with current LL IP-Address + */ +static err_t +autoip_bind(struct netif *netif) +{ + struct autoip *autoip = netif->autoip; + ip4_addr_t sn_mask, gw_addr; + + LWIP_DEBUGF(AUTOIP_DEBUG | LWIP_DBG_TRACE, + ("autoip_bind(netif=%p) %c%c%"U16_F" %"U16_F".%"U16_F".%"U16_F".%"U16_F"\n", + (void*)netif, netif->name[0], netif->name[1], (u16_t)netif->num, + ip4_addr1_16(&autoip->llipaddr), ip4_addr2_16(&autoip->llipaddr), + ip4_addr3_16(&autoip->llipaddr), ip4_addr4_16(&autoip->llipaddr))); + + IP4_ADDR(&sn_mask, 255, 255, 0, 0); + IP4_ADDR(&gw_addr, 0, 0, 0, 0); + + netif_set_addr(netif, &autoip->llipaddr, &sn_mask, &gw_addr); + /* interface is used by routing now that an address is set */ + + return ERR_OK; +} + +/** + * Start AutoIP client + * + * @param netif network interface on which start the AutoIP client + */ +err_t +autoip_start(struct netif *netif) +{ + struct autoip *autoip = netif->autoip; + err_t result = ERR_OK; + + LWIP_ERROR("netif is not up, old style port?", netif_is_up(netif), return ERR_ARG;); + + /* Set IP-Address, Netmask and Gateway to 0 to make sure that + * ARP Packets are formed correctly + */ + netif_set_addr(netif, IP4_ADDR_ANY, IP4_ADDR_ANY, IP4_ADDR_ANY); + + LWIP_DEBUGF(AUTOIP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, + ("autoip_start(netif=%p) %c%c%"U16_F"\n", (void*)netif, netif->name[0], + netif->name[1], (u16_t)netif->num)); + if (autoip == NULL) { + /* no AutoIP client attached yet? */ + LWIP_DEBUGF(AUTOIP_DEBUG | LWIP_DBG_TRACE, + ("autoip_start(): starting new AUTOIP client\n")); + autoip = (struct autoip *)mem_malloc(sizeof(struct autoip)); + if (autoip == NULL) { + LWIP_DEBUGF(AUTOIP_DEBUG | LWIP_DBG_TRACE, + ("autoip_start(): could not allocate autoip\n")); + return ERR_MEM; + } + memset(autoip, 0, sizeof(struct autoip)); + /* store this AutoIP client in the netif */ + netif->autoip = autoip; + LWIP_DEBUGF(AUTOIP_DEBUG | LWIP_DBG_TRACE, ("autoip_start(): allocated autoip")); + } else { + autoip->state = AUTOIP_STATE_OFF; + autoip->ttw = 0; + autoip->sent_num = 0; + ip4_addr_set_zero(&autoip->llipaddr); + autoip->lastconflict = 0; + } + + autoip_create_addr(netif, &(autoip->llipaddr)); + autoip_start_probing(netif); + + return result; +} + +static void +autoip_start_probing(struct netif *netif) +{ + struct autoip *autoip = netif->autoip; + + autoip->state = AUTOIP_STATE_PROBING; + autoip->sent_num = 0; + LWIP_DEBUGF(AUTOIP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, + ("autoip_start_probing(): changing state to PROBING: %"U16_F".%"U16_F".%"U16_F".%"U16_F"\n", + ip4_addr1_16(&netif->autoip->llipaddr), ip4_addr2_16(&netif->autoip->llipaddr), + ip4_addr3_16(&netif->autoip->llipaddr), ip4_addr4_16(&netif->autoip->llipaddr))); + + /* time to wait to first probe, this is randomly + * chosen out of 0 to PROBE_WAIT seconds. + * compliant to RFC 3927 Section 2.2.1 + */ + autoip->ttw = (u16_t)(LWIP_AUTOIP_RAND(netif) % (PROBE_WAIT * AUTOIP_TICKS_PER_SECOND)); + + /* + * if we tried more then MAX_CONFLICTS we must limit our rate for + * acquiring and probing address + * compliant to RFC 3927 Section 2.2.1 + */ + if (autoip->tried_llipaddr > MAX_CONFLICTS) { + autoip->ttw = RATE_LIMIT_INTERVAL * AUTOIP_TICKS_PER_SECOND; + } +} + +/** + * Handle a possible change in the network configuration. + * + * If there is an AutoIP address configured, take the interface down + * and begin probing with the same address. + */ +void +autoip_network_changed(struct netif *netif) +{ + if (netif->autoip && netif->autoip->state != AUTOIP_STATE_OFF) { + autoip_start_probing(netif); + } +} + +/** + * Stop AutoIP client + * + * @param netif network interface on which stop the AutoIP client + */ +err_t +autoip_stop(struct netif *netif) +{ + if (netif->autoip) { + netif->autoip->state = AUTOIP_STATE_OFF; + if (ip4_addr_islinklocal(netif_ip4_addr(netif))) { + netif_set_addr(netif, IP4_ADDR_ANY, IP4_ADDR_ANY, IP4_ADDR_ANY); + } + } + return ERR_OK; +} + +/** + * Has to be called in loop every AUTOIP_TMR_INTERVAL milliseconds + */ +void +autoip_tmr(void) +{ + struct netif *netif = netif_list; + /* loop through netif's */ + while (netif != NULL) { + /* only act on AutoIP configured interfaces */ + if (netif->autoip != NULL) { + if (netif->autoip->lastconflict > 0) { + netif->autoip->lastconflict--; + } + + LWIP_DEBUGF(AUTOIP_DEBUG | LWIP_DBG_TRACE, + ("autoip_tmr() AutoIP-State: %"U16_F", ttw=%"U16_F"\n", + (u16_t)(netif->autoip->state), netif->autoip->ttw)); + + switch(netif->autoip->state) { + case AUTOIP_STATE_PROBING: + if (netif->autoip->ttw > 0) { + netif->autoip->ttw--; + } else { + if (netif->autoip->sent_num >= PROBE_NUM) { + netif->autoip->state = AUTOIP_STATE_ANNOUNCING; + netif->autoip->sent_num = 0; + netif->autoip->ttw = ANNOUNCE_WAIT * AUTOIP_TICKS_PER_SECOND; + LWIP_DEBUGF(AUTOIP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, + ("autoip_tmr(): changing state to ANNOUNCING: %"U16_F".%"U16_F".%"U16_F".%"U16_F"\n", + ip4_addr1_16(&netif->autoip->llipaddr), ip4_addr2_16(&netif->autoip->llipaddr), + ip4_addr3_16(&netif->autoip->llipaddr), ip4_addr4_16(&netif->autoip->llipaddr))); + } else { + autoip_arp_probe(netif); + LWIP_DEBUGF(AUTOIP_DEBUG | LWIP_DBG_TRACE, + ("autoip_tmr() PROBING Sent Probe\n")); + netif->autoip->sent_num++; + /* calculate time to wait to next probe */ + netif->autoip->ttw = (u16_t)((LWIP_AUTOIP_RAND(netif) % + ((PROBE_MAX - PROBE_MIN) * AUTOIP_TICKS_PER_SECOND) ) + + PROBE_MIN * AUTOIP_TICKS_PER_SECOND); + } + } + break; + + case AUTOIP_STATE_ANNOUNCING: + if (netif->autoip->ttw > 0) { + netif->autoip->ttw--; + } else { + if (netif->autoip->sent_num == 0) { + /* We are here the first time, so we waited ANNOUNCE_WAIT seconds + * Now we can bind to an IP address and use it. + * + * autoip_bind calls netif_set_addr. This triggers a gratuitous ARP + * which counts as an announcement. + */ + autoip_bind(netif); + } else { + autoip_arp_announce(netif); + LWIP_DEBUGF(AUTOIP_DEBUG | LWIP_DBG_TRACE, + ("autoip_tmr() ANNOUNCING Sent Announce\n")); + } + netif->autoip->ttw = ANNOUNCE_INTERVAL * AUTOIP_TICKS_PER_SECOND; + netif->autoip->sent_num++; + + if (netif->autoip->sent_num >= ANNOUNCE_NUM) { + netif->autoip->state = AUTOIP_STATE_BOUND; + netif->autoip->sent_num = 0; + netif->autoip->ttw = 0; + LWIP_DEBUGF(AUTOIP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, + ("autoip_tmr(): changing state to BOUND: %"U16_F".%"U16_F".%"U16_F".%"U16_F"\n", + ip4_addr1_16(&netif->autoip->llipaddr), ip4_addr2_16(&netif->autoip->llipaddr), + ip4_addr3_16(&netif->autoip->llipaddr), ip4_addr4_16(&netif->autoip->llipaddr))); + } + } + break; + + default: + /* nothing to do in other states */ + break; + } + } + /* proceed to next network interface */ + netif = netif->next; + } +} + +/** + * Handles every incoming ARP Packet, called by etharp_arp_input. + * + * @param netif network interface to use for autoip processing + * @param hdr Incoming ARP packet + */ +void +autoip_arp_reply(struct netif *netif, struct etharp_hdr *hdr) +{ + LWIP_DEBUGF(AUTOIP_DEBUG | LWIP_DBG_TRACE, ("autoip_arp_reply()\n")); + if ((netif->autoip != NULL) && (netif->autoip->state != AUTOIP_STATE_OFF)) { + /* when ip.src == llipaddr && hw.src != netif->hwaddr + * + * when probing ip.dst == llipaddr && hw.src != netif->hwaddr + * we have a conflict and must solve it + */ + ip4_addr_t sipaddr, dipaddr; + struct eth_addr netifaddr; + ETHADDR16_COPY(netifaddr.addr, netif->hwaddr); + + /* Copy struct ip4_addr2 to aligned ip4_addr, to support compilers without + * structure packing (not using structure copy which breaks strict-aliasing rules). + */ + IPADDR2_COPY(&sipaddr, &hdr->sipaddr); + IPADDR2_COPY(&dipaddr, &hdr->dipaddr); + + if ((netif->autoip->state == AUTOIP_STATE_PROBING) || + ((netif->autoip->state == AUTOIP_STATE_ANNOUNCING) && + (netif->autoip->sent_num == 0))) { + /* RFC 3927 Section 2.2.1: + * from beginning to after ANNOUNCE_WAIT + * seconds we have a conflict if + * ip.src == llipaddr OR + * ip.dst == llipaddr && hw.src != own hwaddr + */ + if ((ip4_addr_cmp(&sipaddr, &netif->autoip->llipaddr)) || + (ip4_addr_cmp(&dipaddr, &netif->autoip->llipaddr) && + !eth_addr_cmp(&netifaddr, &hdr->shwaddr))) { + LWIP_DEBUGF(AUTOIP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE | LWIP_DBG_LEVEL_WARNING, + ("autoip_arp_reply(): Probe Conflict detected\n")); + autoip_restart(netif); + } + } else { + /* RFC 3927 Section 2.5: + * in any state we have a conflict if + * ip.src == llipaddr && hw.src != own hwaddr + */ + if (ip4_addr_cmp(&sipaddr, &netif->autoip->llipaddr) && + !eth_addr_cmp(&netifaddr, &hdr->shwaddr)) { + LWIP_DEBUGF(AUTOIP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE | LWIP_DBG_LEVEL_WARNING, + ("autoip_arp_reply(): Conflicting ARP-Packet detected\n")); + autoip_handle_arp_conflict(netif); + } + } + } +} + +/** check if AutoIP supplied netif->ip_addr + * + * @param netif the netif to check + * @return 1 if AutoIP supplied netif->ip_addr (state BOUND), + * 0 otherwise + */ +u8_t +autoip_supplied_address(struct netif *netif) +{ + if ((netif != NULL) && (netif->autoip != NULL)) { + if (netif->autoip->state == AUTOIP_STATE_BOUND) { + return 1; + } + } + return 0; +} + +#endif /* LWIP_IPV4 && LWIP_AUTOIP */ diff --git a/components/lwip/core/ipv4/dhcp.c b/components/lwip/core/ipv4/dhcp.c new file mode 100755 index 0000000000..d13b557108 --- /dev/null +++ b/components/lwip/core/ipv4/dhcp.c @@ -0,0 +1,1941 @@ +/** + * @file + * Dynamic Host Configuration Protocol client + * + */ + +/* + * Copyright (c) 2001-2004 Leon Woestenberg + * Copyright (c) 2001-2004 Axon Digital Design B.V., The Netherlands. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * The Swedish Institute of Computer Science and Adam Dunkels + * are specifically granted permission to redistribute this + * source code. + * + * Author: Leon Woestenberg + * + * This is a DHCP client for the lwIP TCP/IP stack. It aims to conform + * with RFC 2131 and RFC 2132. + * + * TODO: + * - Support for interfaces other than Ethernet (SLIP, PPP, ...) + * + * Please coordinate changes and requests with Leon Woestenberg + * + * + * Integration with your code: + * + * In lwip/dhcp.h + * #define DHCP_COARSE_TIMER_SECS (recommended 60 which is a minute) + * #define DHCP_FINE_TIMER_MSECS (recommended 500 which equals TCP coarse timer) + * + * Then have your application call dhcp_coarse_tmr() and + * dhcp_fine_tmr() on the defined intervals. + * + * dhcp_start(struct netif *netif); + * starts a DHCP client instance which configures the interface by + * obtaining an IP address lease and maintaining it. + * + * Use dhcp_release(netif) to end the lease and use dhcp_stop(netif) + * to remove the DHCP client. + * + */ + +#include "lwip/opt.h" + +#if LWIP_IPV4 && LWIP_DHCP /* don't build if not configured for use in lwipopts.h */ + +#include "lwip/stats.h" +#include "lwip/mem.h" +#include "lwip/udp.h" +#include "lwip/ip_addr.h" +#include "lwip/netif.h" +#include "lwip/def.h" +#include "lwip/dhcp.h" +#include "lwip/autoip.h" +#include "lwip/dns.h" +#include "netif/etharp.h" + +#include + +#ifdef MEMLEAK_DEBUG +static const char mem_debug_file[] ICACHE_RODATA_ATTR STORE_ATTR = __FILE__; +#endif + +/** DHCP_CREATE_RAND_XID: if this is set to 1, the xid is created using + * LWIP_RAND() (this overrides DHCP_GLOBAL_XID) + */ +#ifndef DHCP_CREATE_RAND_XID +#define DHCP_CREATE_RAND_XID 1 +#endif + +/** Default for DHCP_GLOBAL_XID is 0xABCD0000 + * This can be changed by defining DHCP_GLOBAL_XID and DHCP_GLOBAL_XID_HEADER, e.g. + * #define DHCP_GLOBAL_XID_HEADER "stdlib.h" + * #define DHCP_GLOBAL_XID rand() + */ +#ifdef DHCP_GLOBAL_XID_HEADER +#include DHCP_GLOBAL_XID_HEADER /* include optional starting XID generation prototypes */ +#endif + +/** DHCP_OPTION_MAX_MSG_SIZE is set to the MTU + * MTU is checked to be big enough in dhcp_start */ +#define DHCP_MAX_MSG_LEN(netif) (netif->mtu) +#define DHCP_MAX_MSG_LEN_MIN_REQUIRED 576 +/** Minimum length for reply before packet is parsed */ +#define DHCP_MIN_REPLY_LEN 44 + +#define REBOOT_TRIES 2 + +/** Option handling: options are parsed in dhcp_parse_reply + * and saved in an array where other functions can load them from. + * This might be moved into the struct dhcp (not necessarily since + * lwIP is single-threaded and the array is only used while in recv + * callback). */ +#define DHCP_OPTION_IDX_OVERLOAD 0 +#define DHCP_OPTION_IDX_MSG_TYPE 1 +#define DHCP_OPTION_IDX_SERVER_ID 2 +#define DHCP_OPTION_IDX_LEASE_TIME 3 +#define DHCP_OPTION_IDX_T1 4 +#define DHCP_OPTION_IDX_T2 5 +#define DHCP_OPTION_IDX_SUBNET_MASK 6 +#define DHCP_OPTION_IDX_ROUTER 7 +#define DHCP_OPTION_IDX_DNS_SERVER 8 +#if LWIP_DHCP_GET_NTP_SRV +#define DHCP_OPTION_IDX_NTP_SERVER (DHCP_OPTION_IDX_DNS_SERVER + DNS_MAX_SERVERS) +#define DHCP_OPTION_IDX_MAX (DHCP_OPTION_IDX_NTP_SERVER + LWIP_DHCP_MAX_NTP_SERVERS) +#else /* LWIP_DHCP_GET_NTP_SRV */ +#define DHCP_OPTION_IDX_MAX (DHCP_OPTION_IDX_DNS_SERVER + DNS_MAX_SERVERS) +#endif /* LWIP_DHCP_GET_NTP_SRV */ + +/** Holds the decoded option values, only valid while in dhcp_recv. + @todo: move this into struct dhcp? */ +u32_t dhcp_rx_options_val[DHCP_OPTION_IDX_MAX]; +/** Holds a flag which option was received and is contained in dhcp_rx_options_val, + only valid while in dhcp_recv. + @todo: move this into struct dhcp? */ +u8_t dhcp_rx_options_given[DHCP_OPTION_IDX_MAX]; + +static u8_t dhcp_discover_select_options[] = { + DHCP_OPTION_SUBNET_MASK, + DHCP_OPTION_ROUTER, + DHCP_OPTION_BROADCAST, + DHCP_OPTION_DNS_SERVER + +#ifdef LWIP_ESP8266 +/**add options for support more router by liuHan**/ + , DHCP_OPTION_DOMAIN_NAME, + DHCP_OPTION_NB_TINS, + DHCP_OPTION_NB_TINT, + DHCP_OPTION_NB_TIS, + DHCP_OPTION_PRD, + DHCP_OPTION_STATIC_ROUTER, + DHCP_OPTION_CLASSLESS_STATIC_ROUTER, + DHCP_OPTION_VSN +#endif + +#if LWIP_DHCP_GET_NTP_SRV + , DHCP_OPTION_NTP +#endif /* LWIP_DHCP_GET_NTP_SRV */ + }; + +#ifdef DHCP_GLOBAL_XID +static u32_t xid; +static u8_t xid_initialised; +#endif /* DHCP_GLOBAL_XID */ + +#define dhcp_option_given(dhcp, idx) (dhcp_rx_options_given[idx] != 0) +#define dhcp_got_option(dhcp, idx) (dhcp_rx_options_given[idx] = 1) +#define dhcp_clear_option(dhcp, idx) (dhcp_rx_options_given[idx] = 0) +#define dhcp_clear_all_options(dhcp) (memset(dhcp_rx_options_given, 0, sizeof(dhcp_rx_options_given))) +#define dhcp_get_option_value(dhcp, idx) (dhcp_rx_options_val[idx]) +#define dhcp_set_option_value(dhcp, idx, val) (dhcp_rx_options_val[idx] = (val)) + +static struct udp_pcb *dhcp_pcb; +static u8_t dhcp_pcb_refcount; + +/* DHCP client state machine functions */ +static err_t dhcp_discover(struct netif *netif); +static err_t dhcp_select(struct netif *netif); +static void dhcp_bind(struct netif *netif); +#if DHCP_DOES_ARP_CHECK +static err_t dhcp_decline(struct netif *netif); +#endif /* DHCP_DOES_ARP_CHECK */ +static err_t dhcp_rebind(struct netif *netif); +static err_t dhcp_reboot(struct netif *netif); +static void dhcp_set_state(struct dhcp *dhcp, u8_t new_state); + +/* receive, unfold, parse and free incoming messages */ +static void dhcp_recv(void *arg, struct udp_pcb *pcb, struct pbuf *p, const ip_addr_t *addr, u16_t port); + +/* set the DHCP timers */ +static void dhcp_timeout(struct netif *netif); +static void dhcp_t1_timeout(struct netif *netif); +static void dhcp_t2_timeout(struct netif *netif); + +/* build outgoing messages */ +/* create a DHCP message, fill in common headers */ +static err_t dhcp_create_msg(struct netif *netif, struct dhcp *dhcp, u8_t message_type); +/* free a DHCP request */ +static void dhcp_delete_msg(struct dhcp *dhcp); +/* add a DHCP option (type, then length in bytes) */ +static void dhcp_option(struct dhcp *dhcp, u8_t option_type, u8_t option_len); +/* add option values */ +static void dhcp_option_byte(struct dhcp *dhcp, u8_t value); +static void dhcp_option_short(struct dhcp *dhcp, u16_t value); +static void dhcp_option_long(struct dhcp *dhcp, u32_t value); +#if LWIP_NETIF_HOSTNAME +static void dhcp_option_hostname(struct dhcp *dhcp, struct netif *netif); +#endif /* LWIP_NETIF_HOSTNAME */ +/* always add the DHCP options trailer to end and pad */ +static void dhcp_option_trailer(struct dhcp *dhcp); + +/** Ensure DHCP PCB is allocated and bound */ +static err_t +dhcp_inc_pcb_refcount(void) +{ + if(dhcp_pcb_refcount == 0) { + LWIP_ASSERT("dhcp_inc_pcb_refcount(): memory leak", dhcp_pcb == NULL); + + /* allocate UDP PCB */ + dhcp_pcb = udp_new(); + + if(dhcp_pcb == NULL) { + return ERR_MEM; + } + + ip_set_option(dhcp_pcb, SOF_BROADCAST); + + /* set up local and remote port for the pcb -> listen on all interfaces on all src/dest IPs */ + udp_bind(dhcp_pcb, IP_ADDR_ANY, DHCP_CLIENT_PORT); + udp_connect(dhcp_pcb, IP_ADDR_ANY, DHCP_SERVER_PORT); + udp_recv(dhcp_pcb, dhcp_recv, NULL); + } + + dhcp_pcb_refcount++; + + return ERR_OK; +} + +/** Free DHCP PCB if the last netif stops using it */ +static void +dhcp_dec_pcb_refcount(void) +{ + LWIP_ASSERT("dhcp_pcb_refcount(): refcount error", (dhcp_pcb_refcount > 0)); + dhcp_pcb_refcount--; + + if(dhcp_pcb_refcount == 0) { + udp_remove(dhcp_pcb); + dhcp_pcb = NULL; + } +} + +/** + * Back-off the DHCP client (because of a received NAK response). + * + * Back-off the DHCP client because of a received NAK. Receiving a + * NAK means the client asked for something non-sensible, for + * example when it tries to renew a lease obtained on another network. + * + * We clear any existing set IP address and restart DHCP negotiation + * afresh (as per RFC2131 3.2.3). + * + * @param netif the netif under DHCP control + */ +static void +dhcp_handle_nak(struct netif *netif) +{ + struct dhcp *dhcp = netif->dhcp; + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_handle_nak(netif=%p) %c%c%"U16_F"\n", + (void*)netif, netif->name[0], netif->name[1], (u16_t)netif->num)); + /* remove IP address from interface (must no longer be used, as per RFC2131) */ + netif_set_addr(netif, IP4_ADDR_ANY, IP4_ADDR_ANY, IP4_ADDR_ANY); + /* Change to a defined state */ + dhcp_set_state(dhcp, DHCP_STATE_BACKING_OFF); + /* We can immediately restart discovery */ + dhcp_discover(netif); +} + +#if DHCP_DOES_ARP_CHECK +/** + * Checks if the offered IP address is already in use. + * + * It does so by sending an ARP request for the offered address and + * entering CHECKING state. If no ARP reply is received within a small + * interval, the address is assumed to be free for use by us. + * + * @param netif the netif under DHCP control + */ +static void +dhcp_check(struct netif *netif) +{ + struct dhcp *dhcp = netif->dhcp; + err_t result; + u16_t msecs; + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_check(netif=%p) %c%c\n", (void *)netif, (s16_t)netif->name[0], + (s16_t)netif->name[1])); + dhcp_set_state(dhcp, DHCP_STATE_CHECKING); + /* create an ARP query for the offered IP address, expecting that no host + responds, as the IP address should not be in use. */ + result = etharp_query(netif, &dhcp->offered_ip_addr, NULL); + if (result != ERR_OK) { + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_WARNING, ("dhcp_check: could not perform ARP query\n")); + } + if (dhcp->tries < 255) { + dhcp->tries++; + } + msecs = 500; + dhcp->request_timeout = (msecs + DHCP_FINE_TIMER_MSECS - 1) / DHCP_FINE_TIMER_MSECS; + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("dhcp_check(): set request timeout %"U16_F" msecs\n", msecs)); +} +#endif /* DHCP_DOES_ARP_CHECK */ + +/** + * Remember the configuration offered by a DHCP server. + * + * @param netif the netif under DHCP control + */ +static void +dhcp_handle_offer(struct netif *netif) +{ + struct dhcp *dhcp = netif->dhcp; + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_handle_offer(netif=%p) %c%c%"U16_F"\n", + (void*)netif, netif->name[0], netif->name[1], (u16_t)netif->num)); + /* obtain the server address */ + if (dhcp_option_given(dhcp, DHCP_OPTION_IDX_SERVER_ID)) { + ip_addr_set_ip4_u32(&dhcp->server_ip_addr, htonl(dhcp_get_option_value(dhcp, DHCP_OPTION_IDX_SERVER_ID))); + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_STATE, ("dhcp_handle_offer(): server 0x%08"X32_F"\n", + ip4_addr_get_u32(ip_2_ip4(&dhcp->server_ip_addr)))); + /* remember offered address */ + ip4_addr_copy(dhcp->offered_ip_addr, dhcp->msg_in->yiaddr); + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_STATE, ("dhcp_handle_offer(): offer for 0x%08"X32_F"\n", + ip4_addr_get_u32(&dhcp->offered_ip_addr))); + + dhcp_select(netif); + } else { + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_SERIOUS, + ("dhcp_handle_offer(netif=%p) did not get server ID!\n", (void*)netif)); + } +} + +/** + * Select a DHCP server offer out of all offers. + * + * Simply select the first offer received. + * + * @param netif the netif under DHCP control + * @return lwIP specific error (see error.h) + */ +static err_t +dhcp_select(struct netif *netif) +{ + struct dhcp *dhcp = netif->dhcp; + err_t result; + u16_t msecs; + u8_t i; + + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_select(netif=%p) %c%c%"U16_F"\n", (void*)netif, netif->name[0], netif->name[1], (u16_t)netif->num)); + dhcp_set_state(dhcp, DHCP_STATE_REQUESTING); + + /* create and initialize the DHCP message header */ + result = dhcp_create_msg(netif, dhcp, DHCP_REQUEST); + if (result == ERR_OK) { + dhcp_option(dhcp, DHCP_OPTION_MAX_MSG_SIZE, DHCP_OPTION_MAX_MSG_SIZE_LEN); + dhcp_option_short(dhcp, DHCP_MAX_MSG_LEN(netif)); + + /* MUST request the offered IP address */ + dhcp_option(dhcp, DHCP_OPTION_REQUESTED_IP, 4); + dhcp_option_long(dhcp, ntohl(ip4_addr_get_u32(&dhcp->offered_ip_addr))); + + dhcp_option(dhcp, DHCP_OPTION_SERVER_ID, 4); + dhcp_option_long(dhcp, ntohl(ip4_addr_get_u32(ip_2_ip4(&dhcp->server_ip_addr)))); + + dhcp_option(dhcp, DHCP_OPTION_PARAMETER_REQUEST_LIST, sizeof(dhcp_discover_select_options)); + for (i = 0; i < sizeof(dhcp_discover_select_options); i++) { + dhcp_option_byte(dhcp, dhcp_discover_select_options[i]); + } + +#if LWIP_NETIF_HOSTNAME + dhcp_option_hostname(dhcp, netif); +#endif /* LWIP_NETIF_HOSTNAME */ + + dhcp_option_trailer(dhcp); + /* shrink the pbuf to the actual content length */ + pbuf_realloc(dhcp->p_out, sizeof(struct dhcp_msg) - DHCP_OPTIONS_LEN + dhcp->options_out_len); + + /* send broadcast to any DHCP server */ + udp_sendto_if_src(dhcp_pcb, dhcp->p_out, IP_ADDR_BROADCAST, DHCP_SERVER_PORT, netif, IP_ADDR_ANY); + dhcp_delete_msg(dhcp); + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("dhcp_select: REQUESTING\n")); + } else { + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_WARNING, ("dhcp_select: could not allocate DHCP request\n")); + } + if (dhcp->tries < 255) { + dhcp->tries++; + } + msecs = (dhcp->tries < 6 ? 1 << dhcp->tries : 60) * 1000; + dhcp->request_timeout = (msecs + DHCP_FINE_TIMER_MSECS - 1) / DHCP_FINE_TIMER_MSECS; + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_STATE, ("dhcp_select(): set request timeout %"U16_F" msecs\n", msecs)); + return result; +} + +/** + * The DHCP timer that checks for lease renewal/rebind timeouts. + */ +void +dhcp_coarse_tmr(void) +{ + struct netif *netif = netif_list; + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_coarse_tmr()\n")); + /* iterate through all network interfaces */ + while (netif != NULL) { + /* only act on DHCP configured interfaces */ + struct dhcp* dhcp = netif->dhcp; + if ((dhcp != NULL) && (dhcp->state != DHCP_STATE_OFF)) { + /* compare lease time to expire timeout */ + if (dhcp->t0_timeout && (++dhcp->lease_used == dhcp->t0_timeout)) { + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("dhcp_coarse_tmr(): t0 timeout\n")); + /* this clients' lease time has expired */ + dhcp_release(netif); + dhcp_discover(netif); + /* timer is active (non zero), and triggers (zeroes) now? */ + } else if (dhcp->t2_rebind_time && (dhcp->t2_rebind_time-- == 1)) { + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("dhcp_coarse_tmr(): t2 timeout\n")); + /* this clients' rebind timeout triggered */ + dhcp_t2_timeout(netif); + /* timer is active (non zero), and triggers (zeroes) now */ + } else if (dhcp->t1_renew_time && (dhcp->t1_renew_time-- == 1)) { + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("dhcp_coarse_tmr(): t1 timeout\n")); + /* this clients' renewal timeout triggered */ + dhcp_t1_timeout(netif); + } + } + /* proceed to next netif */ + netif = netif->next; + } +} + +/** + * DHCP transaction timeout handling + * + * A DHCP server is expected to respond within a short period of time. + * This timer checks whether an outstanding DHCP request is timed out. + */ +void +dhcp_fine_tmr(void) +{ + struct netif *netif = netif_list; + /* loop through netif's */ + while (netif != NULL) { + /* only act on DHCP configured interfaces */ + if (netif->dhcp != NULL) { + +//#ifdef LWIP_ESP8266 + /*add DHCP retries processing by LiuHan*/ +#if 0 + if (DHCP_MAXRTX != 0) { + if (netif->dhcp->tries >= DHCP_MAXRTX){ + //os_printf("DHCP timeout\n"); + if (netif->dhcp_event != NULL) + netif->dhcp_event(); + break; + } + } + +#endif + + /* timer is active (non zero), and is about to trigger now */ + if (netif->dhcp->request_timeout > 1) { + netif->dhcp->request_timeout--; + } + else if (netif->dhcp->request_timeout == 1) { + netif->dhcp->request_timeout--; + /* { netif->dhcp->request_timeout == 0 } */ + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("dhcp_fine_tmr(): request timeout\n")); + /* this client's request timeout triggered */ + dhcp_timeout(netif); + } + } + /* proceed to next network interface */ + netif = netif->next; + } +} + +/** + * A DHCP negotiation transaction, or ARP request, has timed out. + * + * The timer that was started with the DHCP or ARP request has + * timed out, indicating no response was received in time. + * + * @param netif the netif under DHCP control + */ +static void +dhcp_timeout(struct netif *netif) +{ + struct dhcp *dhcp = netif->dhcp; + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_timeout()\n")); + /* back-off period has passed, or server selection timed out */ + if ((dhcp->state == DHCP_STATE_BACKING_OFF) || (dhcp->state == DHCP_STATE_SELECTING)) { + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_timeout(): restarting discovery\n")); + dhcp_discover(netif); + /* receiving the requested lease timed out */ + } else if (dhcp->state == DHCP_STATE_REQUESTING) { + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("dhcp_timeout(): REQUESTING, DHCP request timed out\n")); + if (dhcp->tries <= 5) { + dhcp_select(netif); + } else { + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("dhcp_timeout(): REQUESTING, releasing, restarting\n")); + dhcp_release(netif); + dhcp_discover(netif); + } +#if DHCP_DOES_ARP_CHECK + /* received no ARP reply for the offered address (which is good) */ + } else if (dhcp->state == DHCP_STATE_CHECKING) { + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("dhcp_timeout(): CHECKING, ARP request timed out\n")); + if (dhcp->tries <= 1) { + dhcp_check(netif); + /* no ARP replies on the offered address, + looks like the IP address is indeed free */ + } else { + /* bind the interface to the offered address */ + dhcp_bind(netif); + } +#endif /* DHCP_DOES_ARP_CHECK */ + } else if (dhcp->state == DHCP_STATE_REBOOTING) { + if (dhcp->tries < REBOOT_TRIES) { + dhcp_reboot(netif); + } else { + dhcp_discover(netif); + } + } +} + +/** + * The renewal period has timed out. + * + * @param netif the netif under DHCP control + */ +static void +dhcp_t1_timeout(struct netif *netif) +{ + struct dhcp *dhcp = netif->dhcp; + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_STATE, ("dhcp_t1_timeout()\n")); + if ((dhcp->state == DHCP_STATE_REQUESTING) || (dhcp->state == DHCP_STATE_BOUND) || + (dhcp->state == DHCP_STATE_RENEWING)) { + /* just retry to renew - note that the rebind timer (t2) will + * eventually time-out if renew tries fail. */ + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, + ("dhcp_t1_timeout(): must renew\n")); + /* This slightly different to RFC2131: DHCPREQUEST will be sent from state + DHCP_STATE_RENEWING, not DHCP_STATE_BOUND */ + dhcp_renew(netif); + /* Calculate next timeout */ + if (((netif->dhcp->t2_timeout - dhcp->lease_used) / 2) >= ((60 + DHCP_COARSE_TIMER_SECS / 2) / DHCP_COARSE_TIMER_SECS)) + { + netif->dhcp->t1_renew_time = ((netif->dhcp->t2_timeout - dhcp->lease_used) / 2); + } + } +} + +/** + * The rebind period has timed out. + * + * @param netif the netif under DHCP control + */ +static void +dhcp_t2_timeout(struct netif *netif) +{ + struct dhcp *dhcp = netif->dhcp; + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("dhcp_t2_timeout()\n")); + if ((dhcp->state == DHCP_STATE_REQUESTING) || (dhcp->state == DHCP_STATE_BOUND) || + (dhcp->state == DHCP_STATE_RENEWING) || (dhcp->state == DHCP_STATE_REBINDING)) { + /* just retry to rebind */ + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, + ("dhcp_t2_timeout(): must rebind\n")); + /* This slightly different to RFC2131: DHCPREQUEST will be sent from state + DHCP_STATE_REBINDING, not DHCP_STATE_BOUND */ + dhcp_rebind(netif); + /* Calculate next timeout */ + if (((netif->dhcp->t0_timeout - dhcp->lease_used) / 2) >= ((60 + DHCP_COARSE_TIMER_SECS / 2) / DHCP_COARSE_TIMER_SECS)) + { + netif->dhcp->t2_rebind_time = ((netif->dhcp->t0_timeout - dhcp->lease_used) / 2); + } + } +} + +/** + * Handle a DHCP ACK packet + * + * @param netif the netif under DHCP control + */ +static void +dhcp_handle_ack(struct netif *netif) +{ + struct dhcp *dhcp = netif->dhcp; +#if LWIP_DNS || LWIP_DHCP_GET_NTP_SRV + u8_t n; +#endif /* LWIP_DNS || LWIP_DHCP_GET_NTP_SRV */ +#if LWIP_DHCP_GET_NTP_SRV + ip4_addr_t ntp_server_addrs[LWIP_DHCP_MAX_NTP_SERVERS]; +#endif + + /* clear options we might not get from the ACK */ + ip4_addr_set_zero(&dhcp->offered_sn_mask); + ip4_addr_set_zero(&dhcp->offered_gw_addr); +#if LWIP_DHCP_BOOTP_FILE + ip4_addr_set_zero(&dhcp->offered_si_addr); +#endif /* LWIP_DHCP_BOOTP_FILE */ + + /* lease time given? */ + if (dhcp_option_given(dhcp, DHCP_OPTION_IDX_LEASE_TIME)) { + /* remember offered lease time */ + dhcp->offered_t0_lease = dhcp_get_option_value(dhcp, DHCP_OPTION_IDX_LEASE_TIME); + } + /* renewal period given? */ + if (dhcp_option_given(dhcp, DHCP_OPTION_IDX_T1)) { + /* remember given renewal period */ + dhcp->offered_t1_renew = dhcp_get_option_value(dhcp, DHCP_OPTION_IDX_T1); + } else { + /* calculate safe periods for renewal */ + dhcp->offered_t1_renew = dhcp->offered_t0_lease / 2; + } + + /* renewal period given? */ + if (dhcp_option_given(dhcp, DHCP_OPTION_IDX_T2)) { + /* remember given rebind period */ + dhcp->offered_t2_rebind = dhcp_get_option_value(dhcp, DHCP_OPTION_IDX_T2); + } else { + /* calculate safe periods for rebinding (offered_t0_lease * 0.875 -> 87.5%)*/ + dhcp->offered_t2_rebind = (dhcp->offered_t0_lease * 7U) / 8U; + } + + /* (y)our internet address */ + ip4_addr_copy(dhcp->offered_ip_addr, dhcp->msg_in->yiaddr); + +#if LWIP_DHCP_BOOTP_FILE + /* copy boot server address, + boot file name copied in dhcp_parse_reply if not overloaded */ + ip_addr_copy(dhcp->offered_si_addr, dhcp->msg_in->siaddr); +#endif /* LWIP_DHCP_BOOTP_FILE */ + + /* subnet mask given? */ + if (dhcp_option_given(dhcp, DHCP_OPTION_IDX_SUBNET_MASK)) { + /* remember given subnet mask */ + ip4_addr_set_u32(&dhcp->offered_sn_mask, htonl(dhcp_get_option_value(dhcp, DHCP_OPTION_IDX_SUBNET_MASK))); + dhcp->subnet_mask_given = 1; + } else { + dhcp->subnet_mask_given = 0; + } + + /* gateway router */ + if (dhcp_option_given(dhcp, DHCP_OPTION_IDX_ROUTER)) { + ip4_addr_set_u32(&dhcp->offered_gw_addr, htonl(dhcp_get_option_value(dhcp, DHCP_OPTION_IDX_ROUTER))); + } + +#if LWIP_DHCP_GET_NTP_SRV + /* NTP servers */ + for (n = 0; (n < LWIP_DHCP_MAX_NTP_SERVERS) && dhcp_option_given(dhcp, DHCP_OPTION_IDX_NTP_SERVER + n); n++) { + ip4_addr_set_u32(&ntp_server_addrs[n], htonl(dhcp_get_option_value(dhcp, DHCP_OPTION_IDX_NTP_SERVER + n))); + } + dhcp_set_ntp_servers(n, ntp_server_addrs); +#endif /* LWIP_DHCP_GET_NTP_SRV */ + +#if LWIP_DNS + /* DNS servers */ + for (n = 0; (n < DNS_MAX_SERVERS) && dhcp_option_given(dhcp, DHCP_OPTION_IDX_DNS_SERVER + n); n++) { + ip_addr_t dns_addr; + ip_addr_set_ip4_u32(&dns_addr, htonl(dhcp_get_option_value(dhcp, DHCP_OPTION_IDX_DNS_SERVER + n))); + dns_setserver(n, &dns_addr); + } +#endif /* LWIP_DNS */ +} + +/** Set a statically allocated struct dhcp to work with. + * Using this prevents dhcp_start to allocate it using mem_malloc. + * + * @param netif the netif for which to set the struct dhcp + * @param dhcp (uninitialised) dhcp struct allocated by the application + */ +void +dhcp_set_struct(struct netif *netif, struct dhcp *dhcp) +{ + LWIP_ASSERT("netif != NULL", netif != NULL); + LWIP_ASSERT("dhcp != NULL", dhcp != NULL); + LWIP_ASSERT("netif already has a struct dhcp set", netif->dhcp == NULL); + + /* clear data structure */ + memset(dhcp, 0, sizeof(struct dhcp)); + /* dhcp_set_state(&dhcp, DHCP_STATE_OFF); */ + netif->dhcp = dhcp; +} + +/** Removes a struct dhcp from a netif. + * + * ATTENTION: Only use this when not using dhcp_set_struct() to allocate the + * struct dhcp since the memory is passed back to the heap. + * + * @param netif the netif from which to remove the struct dhcp + */ +void dhcp_cleanup(struct netif *netif) +{ + LWIP_ASSERT("netif != NULL", netif != NULL); + + if (netif->dhcp != NULL) { + mem_free(netif->dhcp); + netif->dhcp = NULL; + } +} + +/** + * Start DHCP negotiation for a network interface. + * + * If no DHCP client instance was attached to this interface, + * a new client is created first. If a DHCP client instance + * was already present, it restarts negotiation. + * + * @param netif The lwIP network interface + * @return lwIP error code + * - ERR_OK - No error + * - ERR_MEM - Out of memory + */ +err_t +dhcp_start(struct netif *netif) +{ + struct dhcp *dhcp; + err_t result; + + LWIP_ERROR("netif != NULL", (netif != NULL), return ERR_ARG;); + LWIP_ERROR("netif is not up, old style port?", netif_is_up(netif), return ERR_ARG;); + dhcp = netif->dhcp; + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("dhcp_start(netif=%p) %c%c%"U16_F"\n", (void*)netif, netif->name[0], netif->name[1], (u16_t)netif->num)); + + /* check hwtype of the netif */ + if ((netif->flags & NETIF_FLAG_ETHARP) == 0) { + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_start(): No ETHARP netif\n")); + return ERR_ARG; + } + + /* check MTU of the netif */ + if (netif->mtu < DHCP_MAX_MSG_LEN_MIN_REQUIRED) { + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_start(): Cannot use this netif with DHCP: MTU is too small\n")); + return ERR_MEM; + } + + /* no DHCP client attached yet? */ + if (dhcp == NULL) { + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_start(): starting new DHCP client\n")); + dhcp = (struct dhcp *)mem_malloc(sizeof(struct dhcp)); + if (dhcp == NULL) { + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_start(): could not allocate dhcp\n")); + return ERR_MEM; + } + + /* store this dhcp client in the netif */ + netif->dhcp = dhcp; + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_start(): allocated dhcp")); + /* already has DHCP client attached */ + } else { + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("dhcp_start(): restarting DHCP configuration\n")); + LWIP_ASSERT("pbuf p_out wasn't freed", dhcp->p_out == NULL); + LWIP_ASSERT("reply wasn't freed", dhcp->msg_in == NULL ); + + if(dhcp->pcb_allocated != 0) { + dhcp_dec_pcb_refcount(); /* free DHCP PCB if not needed any more */ + } + /* dhcp is cleared below, no need to reset flag*/ + } + + /* clear data structure */ + memset(dhcp, 0, sizeof(struct dhcp)); + /* dhcp_set_state(&dhcp, DHCP_STATE_OFF); */ + + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_start(): starting DHCP configuration\n")); + + if(dhcp_inc_pcb_refcount() != ERR_OK) { /* ensure DHCP PCB is allocated */ + return ERR_MEM; + } + dhcp->pcb_allocated = 1; + +#if LWIP_DHCP_CHECK_LINK_UP + if (!netif_is_link_up(netif)) { + /* set state INIT and wait for dhcp_network_changed() to call dhcp_discover() */ + dhcp_set_state(dhcp, DHCP_STATE_INIT); + return ERR_OK; + } +#endif /* LWIP_DHCP_CHECK_LINK_UP */ + + + /* (re)start the DHCP negotiation */ + result = dhcp_discover(netif); + if (result != ERR_OK) { + /* free resources allocated above */ + dhcp_stop(netif); + return ERR_MEM; + } + return result; +} + +/** + * Inform a DHCP server of our manual configuration. + * + * This informs DHCP servers of our fixed IP address configuration + * by sending an INFORM message. It does not involve DHCP address + * configuration, it is just here to be nice to the network. + * + * @param netif The lwIP network interface + */ +void +dhcp_inform(struct netif *netif) +{ + struct dhcp dhcp; + err_t result = ERR_OK; + + LWIP_ERROR("netif != NULL", (netif != NULL), return;); + + if(dhcp_inc_pcb_refcount() != ERR_OK) { /* ensure DHCP PCB is allocated */ + return; + } + + memset(&dhcp, 0, sizeof(struct dhcp)); + dhcp_set_state(&dhcp, DHCP_STATE_INFORMING); + + /* create and initialize the DHCP message header */ + result = dhcp_create_msg(netif, &dhcp, DHCP_INFORM); + if (result == ERR_OK) { + dhcp_option(&dhcp, DHCP_OPTION_MAX_MSG_SIZE, DHCP_OPTION_MAX_MSG_SIZE_LEN); + dhcp_option_short(&dhcp, DHCP_MAX_MSG_LEN(netif)); + + dhcp_option_trailer(&dhcp); + + pbuf_realloc(dhcp.p_out, sizeof(struct dhcp_msg) - DHCP_OPTIONS_LEN + dhcp.options_out_len); + + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("dhcp_inform: INFORMING\n")); + + udp_sendto_if(dhcp_pcb, dhcp.p_out, IP_ADDR_BROADCAST, DHCP_SERVER_PORT, netif); + + dhcp_delete_msg(&dhcp); + } else { + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_SERIOUS, ("dhcp_inform: could not allocate DHCP request\n")); + } + + dhcp_dec_pcb_refcount(); /* delete DHCP PCB if not needed any more */ +} + +/** Handle a possible change in the network configuration. + * + * This enters the REBOOTING state to verify that the currently bound + * address is still valid. + */ +void +dhcp_network_changed(struct netif *netif) +{ + struct dhcp *dhcp = netif->dhcp; + if (!dhcp) + return; + switch (dhcp->state) { + case DHCP_STATE_REBINDING: + case DHCP_STATE_RENEWING: + case DHCP_STATE_BOUND: + case DHCP_STATE_REBOOTING: + dhcp->tries = 0; + dhcp_reboot(netif); + break; + case DHCP_STATE_OFF: + /* stay off */ + break; + default: + /* INIT/REQUESTING/CHECKING/BACKING_OFF restart with new 'rid' because the + state changes, SELECTING: continue with current 'rid' as we stay in the + same state */ +#if LWIP_DHCP_AUTOIP_COOP + if (dhcp->autoip_coop_state == DHCP_AUTOIP_COOP_STATE_ON) { + autoip_stop(netif); + dhcp->autoip_coop_state = DHCP_AUTOIP_COOP_STATE_OFF; + } +#endif /* LWIP_DHCP_AUTOIP_COOP */ + /* ensure we start with short timeouts, even if already discovering */ + dhcp->tries = 0; + dhcp_discover(netif); + break; + } +} + +#if DHCP_DOES_ARP_CHECK +/** + * Match an ARP reply with the offered IP address. + * + * @param netif the network interface on which the reply was received + * @param addr The IP address we received a reply from + */ +void dhcp_arp_reply(struct netif *netif, const ip4_addr_t *addr) +{ + LWIP_ERROR("netif != NULL", (netif != NULL), return;); + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_arp_reply()\n")); + /* is a DHCP client doing an ARP check? */ + if ((netif->dhcp != NULL) && (netif->dhcp->state == DHCP_STATE_CHECKING)) { + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("dhcp_arp_reply(): CHECKING, arp reply for 0x%08"X32_F"\n", + ip4_addr_get_u32(addr))); + /* did a host respond with the address we + were offered by the DHCP server? */ + if (ip4_addr_cmp(addr, &netif->dhcp->offered_ip_addr)) { + /* we will not accept the offered address */ + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE | LWIP_DBG_LEVEL_WARNING, + ("dhcp_arp_reply(): arp reply matched with offered address, declining\n")); + dhcp_decline(netif); + } + } +} + +/** + * Decline an offered lease. + * + * Tell the DHCP server we do not accept the offered address. + * One reason to decline the lease is when we find out the address + * is already in use by another host (through ARP). + * + * @param netif the netif under DHCP control + */ +static err_t +dhcp_decline(struct netif *netif) +{ + struct dhcp *dhcp = netif->dhcp; + err_t result = ERR_OK; + u16_t msecs; + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_decline()\n")); + dhcp_set_state(dhcp, DHCP_STATE_BACKING_OFF); + /* create and initialize the DHCP message header */ + result = dhcp_create_msg(netif, dhcp, DHCP_DECLINE); + if (result == ERR_OK) { + dhcp_option(dhcp, DHCP_OPTION_REQUESTED_IP, 4); + dhcp_option_long(dhcp, ntohl(ip4_addr_get_u32(&dhcp->offered_ip_addr))); + + dhcp_option_trailer(dhcp); + /* resize pbuf to reflect true size of options */ + pbuf_realloc(dhcp->p_out, sizeof(struct dhcp_msg) - DHCP_OPTIONS_LEN + dhcp->options_out_len); + + /* per section 4.4.4, broadcast DECLINE messages */ + udp_sendto_if_src(dhcp_pcb, dhcp->p_out, IP_ADDR_BROADCAST, DHCP_SERVER_PORT, netif, IP_ADDR_ANY); + dhcp_delete_msg(dhcp); + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("dhcp_decline: BACKING OFF\n")); + } else { + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_SERIOUS, + ("dhcp_decline: could not allocate DHCP request\n")); + } + if (dhcp->tries < 255) { + dhcp->tries++; + } + msecs = 10*1000; + dhcp->request_timeout = (msecs + DHCP_FINE_TIMER_MSECS - 1) / DHCP_FINE_TIMER_MSECS; + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_decline(): set request timeout %"U16_F" msecs\n", msecs)); + return result; +} +#endif /* DHCP_DOES_ARP_CHECK */ + + +/** + * Start the DHCP process, discover a DHCP server. + * + * @param netif the netif under DHCP control + */ +static err_t +dhcp_discover(struct netif *netif) +{ + struct dhcp *dhcp = netif->dhcp; + err_t result = ERR_OK; + u16_t msecs; + u8_t i; + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_discover()\n")); + ip4_addr_set_any(&dhcp->offered_ip_addr); + dhcp_set_state(dhcp, DHCP_STATE_SELECTING); + /* create and initialize the DHCP message header */ + result = dhcp_create_msg(netif, dhcp, DHCP_DISCOVER); + if (result == ERR_OK) { + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_discover: making request\n")); + + dhcp_option(dhcp, DHCP_OPTION_MAX_MSG_SIZE, DHCP_OPTION_MAX_MSG_SIZE_LEN); + dhcp_option_short(dhcp, DHCP_MAX_MSG_LEN(netif)); + +#ifdef LWIP_ESP8266 +#if LWIP_NETIF_HOSTNAME + dhcp_option_hostname(dhcp, netif); +#endif /* LWIP_NETIF_HOSTNAME */ +#endif + + dhcp_option(dhcp, DHCP_OPTION_PARAMETER_REQUEST_LIST, sizeof(dhcp_discover_select_options)); + for (i = 0; i < sizeof(dhcp_discover_select_options); i++) { + dhcp_option_byte(dhcp, dhcp_discover_select_options[i]); + } + dhcp_option_trailer(dhcp); + + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_discover: realloc()ing\n")); + pbuf_realloc(dhcp->p_out, sizeof(struct dhcp_msg) - DHCP_OPTIONS_LEN + dhcp->options_out_len); + + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_discover: sendto(DISCOVER, IP_ADDR_BROADCAST, DHCP_SERVER_PORT)\n")); + udp_sendto_if_src(dhcp_pcb, dhcp->p_out, IP_ADDR_BROADCAST, DHCP_SERVER_PORT, netif, IP_ADDR_ANY); + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_discover: deleting()ing\n")); + dhcp_delete_msg(dhcp); + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("dhcp_discover: SELECTING\n")); + } else { + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_SERIOUS, ("dhcp_discover: could not allocate DHCP request\n")); + } + if (dhcp->tries < 255) { + dhcp->tries++; + } +#if LWIP_DHCP_AUTOIP_COOP + if (dhcp->tries >= LWIP_DHCP_AUTOIP_COOP_TRIES && dhcp->autoip_coop_state == DHCP_AUTOIP_COOP_STATE_OFF) { + dhcp->autoip_coop_state = DHCP_AUTOIP_COOP_STATE_ON; + autoip_start(netif); + } +#endif /* LWIP_DHCP_AUTOIP_COOP */ + msecs = (dhcp->tries < 6 ? 1 << dhcp->tries : 60) * 1000; + dhcp->request_timeout = (msecs + DHCP_FINE_TIMER_MSECS - 1) / DHCP_FINE_TIMER_MSECS; + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("dhcp_discover(): set request timeout %"U16_F" msecs\n", msecs)); + return result; +} + + +/** + * Bind the interface to the offered IP address. + * + * @param netif network interface to bind to the offered address + */ +static void +dhcp_bind(struct netif *netif) +{ + u32_t timeout; + struct dhcp *dhcp; + ip4_addr_t sn_mask, gw_addr; + LWIP_ERROR("dhcp_bind: netif != NULL", (netif != NULL), return;); + dhcp = netif->dhcp; + LWIP_ERROR("dhcp_bind: dhcp != NULL", (dhcp != NULL), return;); + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_bind(netif=%p) %c%c%"U16_F"\n", (void*)netif, netif->name[0], netif->name[1], (u16_t)netif->num)); + + /* reset time used of lease */ + dhcp->lease_used = 0; + + if (dhcp->offered_t0_lease != 0xffffffffUL) { + /* set renewal period timer */ + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_bind(): t0 renewal timer %"U32_F" secs\n", dhcp->offered_t0_lease)); + timeout = (dhcp->offered_t0_lease + DHCP_COARSE_TIMER_SECS / 2) / DHCP_COARSE_TIMER_SECS; + if (timeout > 0xffff) { + timeout = 0xffff; + } + dhcp->t0_timeout = (u16_t)timeout; + if (dhcp->t0_timeout == 0) { + dhcp->t0_timeout = 1; + } + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("dhcp_bind(): set request timeout %"U32_F" msecs\n", dhcp->offered_t0_lease*1000)); + } + + /* temporary DHCP lease? */ + if (dhcp->offered_t1_renew != 0xffffffffUL) { + /* set renewal period timer */ + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_bind(): t1 renewal timer %"U32_F" secs\n", dhcp->offered_t1_renew)); + timeout = (dhcp->offered_t1_renew + DHCP_COARSE_TIMER_SECS / 2) / DHCP_COARSE_TIMER_SECS; + if (timeout > 0xffff) { + timeout = 0xffff; + } + dhcp->t1_timeout = (u16_t)timeout; + if (dhcp->t1_timeout == 0) { + dhcp->t1_timeout = 1; + } + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("dhcp_bind(): set request timeout %"U32_F" msecs\n", dhcp->offered_t1_renew*1000)); + dhcp->t1_renew_time = dhcp->t1_timeout; + } + /* set renewal period timer */ + if (dhcp->offered_t2_rebind != 0xffffffffUL) { + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_bind(): t2 rebind timer %"U32_F" secs\n", dhcp->offered_t2_rebind)); + timeout = (dhcp->offered_t2_rebind + DHCP_COARSE_TIMER_SECS / 2) / DHCP_COARSE_TIMER_SECS; + if (timeout > 0xffff) { + timeout = 0xffff; + } + dhcp->t2_timeout = (u16_t)timeout; + if (dhcp->t2_timeout == 0) { + dhcp->t2_timeout = 1; + } + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("dhcp_bind(): set request timeout %"U32_F" msecs\n", dhcp->offered_t2_rebind*1000)); + dhcp->t2_rebind_time = dhcp->t2_timeout; + } + + /* If we have sub 1 minute lease, t2 and t1 will kick in at the same time. */ + if ((dhcp->t1_timeout >= dhcp->t2_timeout) && (dhcp->t2_timeout > 0)) { + dhcp->t1_timeout = 0; + } + + if (dhcp->subnet_mask_given) { + /* copy offered network mask */ + ip4_addr_copy(sn_mask, dhcp->offered_sn_mask); + } else { + /* subnet mask not given, choose a safe subnet mask given the network class */ + u8_t first_octet = ip4_addr1(&dhcp->offered_ip_addr); + if (first_octet <= 127) { + ip4_addr_set_u32(&sn_mask, PP_HTONL(0xff000000UL)); + } else if (first_octet >= 192) { + ip4_addr_set_u32(&sn_mask, PP_HTONL(0xffffff00UL)); + } else { + ip4_addr_set_u32(&sn_mask, PP_HTONL(0xffff0000UL)); + } + } + + ip4_addr_copy(gw_addr, dhcp->offered_gw_addr); + /* gateway address not given? */ + if (ip4_addr_isany_val(gw_addr)) { + /* copy network address */ + ip4_addr_get_network(&gw_addr, &dhcp->offered_ip_addr, &sn_mask); + /* use first host address on network as gateway */ + ip4_addr_set_u32(&gw_addr, ip4_addr_get_u32(&gw_addr) | PP_HTONL(0x00000001UL)); + } + +#if LWIP_DHCP_AUTOIP_COOP + if (dhcp->autoip_coop_state == DHCP_AUTOIP_COOP_STATE_ON) { + autoip_stop(netif); + dhcp->autoip_coop_state = DHCP_AUTOIP_COOP_STATE_OFF; + } +#endif /* LWIP_DHCP_AUTOIP_COOP */ + + /* Espressif add start. */ + /* back up old ip/netmask/gw */ + ip4_addr_t ip, mask, gw; + ip4_addr_set(&ip, ip_2_ip4(&netif->ip_addr)); + ip4_addr_set(&mask, ip_2_ip4(&netif->netmask)); + ip4_addr_set(&gw, ip_2_ip4(&netif->gw)); + /* Espressif add end. */ + + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_STATE, ("dhcp_bind(): IP: 0x%08"X32_F" SN: 0x%08"X32_F" GW: 0x%08"X32_F"\n", + ip4_addr_get_u32(&dhcp->offered_ip_addr), ip4_addr_get_u32(&sn_mask), ip4_addr_get_u32(&gw_addr))); + netif_set_addr(netif, &dhcp->offered_ip_addr, &sn_mask, &gw_addr); + /* interface is used by routing now that an address is set */ + +#ifdef LWIP_ESP8266 + /* use old ip/mask/gw to check whether ip/mask/gw changed */ +// extern void system_station_got_ip_set(ip4_addr_t *ip, ip4_addr_t *mask, ip4_addr_t *gw); +// system_station_got_ip_set(&ip, &mask, &gw); +#endif + + /* use old ip/mask/gw to check whether ip/mask/gw changed */ +// extern void system_station_got_ip_set(ip4_addr_t *ip, ip4_addr_t *mask, ip4_addr_t *gw); +// system_station_got_ip_set(&ip, &mask, &gw); + + /* netif is now bound to DHCP leased address */ + dhcp_set_state(dhcp, DHCP_STATE_BOUND); + +} + +/** + * Renew an existing DHCP lease at the involved DHCP server. + * + * @param netif network interface which must renew its lease + */ +err_t +dhcp_renew(struct netif *netif) +{ + struct dhcp *dhcp = netif->dhcp; + err_t result; + u16_t msecs; + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_renew()\n")); + dhcp_set_state(dhcp, DHCP_STATE_RENEWING); + + /* create and initialize the DHCP message header */ + result = dhcp_create_msg(netif, dhcp, DHCP_REQUEST); + if (result == ERR_OK) { + dhcp_option(dhcp, DHCP_OPTION_MAX_MSG_SIZE, DHCP_OPTION_MAX_MSG_SIZE_LEN); + dhcp_option_short(dhcp, DHCP_MAX_MSG_LEN(netif)); + +#if LWIP_NETIF_HOSTNAME + dhcp_option_hostname(dhcp, netif); +#endif /* LWIP_NETIF_HOSTNAME */ + + /* append DHCP message trailer */ + dhcp_option_trailer(dhcp); + + pbuf_realloc(dhcp->p_out, sizeof(struct dhcp_msg) - DHCP_OPTIONS_LEN + dhcp->options_out_len); + + udp_sendto_if(dhcp_pcb, dhcp->p_out, &dhcp->server_ip_addr, DHCP_SERVER_PORT, netif); + dhcp_delete_msg(dhcp); + + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("dhcp_renew: RENEWING\n")); + } else { + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_SERIOUS, ("dhcp_renew: could not allocate DHCP request\n")); + } + if (dhcp->tries < 255) { + dhcp->tries++; + } + /* back-off on retries, but to a maximum of 20 seconds */ + msecs = dhcp->tries < 10 ? dhcp->tries * 2000 : 20 * 1000; + dhcp->request_timeout = (msecs + DHCP_FINE_TIMER_MSECS - 1) / DHCP_FINE_TIMER_MSECS; + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("dhcp_renew(): set request timeout %"U16_F" msecs\n", msecs)); + return result; +} + +/** + * Rebind with a DHCP server for an existing DHCP lease. + * + * @param netif network interface which must rebind with a DHCP server + */ +static err_t +dhcp_rebind(struct netif *netif) +{ + struct dhcp *dhcp = netif->dhcp; + err_t result; + u16_t msecs; + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("dhcp_rebind()\n")); + dhcp_set_state(dhcp, DHCP_STATE_REBINDING); + + /* create and initialize the DHCP message header */ + result = dhcp_create_msg(netif, dhcp, DHCP_REQUEST); + if (result == ERR_OK) { + dhcp_option(dhcp, DHCP_OPTION_MAX_MSG_SIZE, DHCP_OPTION_MAX_MSG_SIZE_LEN); + dhcp_option_short(dhcp, DHCP_MAX_MSG_LEN(netif)); + +#if LWIP_NETIF_HOSTNAME + dhcp_option_hostname(dhcp, netif); +#endif /* LWIP_NETIF_HOSTNAME */ + + dhcp_option_trailer(dhcp); + + pbuf_realloc(dhcp->p_out, sizeof(struct dhcp_msg) - DHCP_OPTIONS_LEN + dhcp->options_out_len); + + /* broadcast to server */ + udp_sendto_if(dhcp_pcb, dhcp->p_out, IP_ADDR_BROADCAST, DHCP_SERVER_PORT, netif); + dhcp_delete_msg(dhcp); + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("dhcp_rebind: REBINDING\n")); + } else { + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_SERIOUS, ("dhcp_rebind: could not allocate DHCP request\n")); + } + if (dhcp->tries < 255) { + dhcp->tries++; + } + msecs = dhcp->tries < 10 ? dhcp->tries * 1000 : 10 * 1000; + dhcp->request_timeout = (msecs + DHCP_FINE_TIMER_MSECS - 1) / DHCP_FINE_TIMER_MSECS; + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("dhcp_rebind(): set request timeout %"U16_F" msecs\n", msecs)); + return result; +} + +/** + * Enter REBOOTING state to verify an existing lease + * + * @param netif network interface which must reboot + */ +static err_t +dhcp_reboot(struct netif *netif) +{ + struct dhcp *dhcp = netif->dhcp; + err_t result; + u16_t msecs; + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("dhcp_reboot()\n")); + dhcp_set_state(dhcp, DHCP_STATE_REBOOTING); + + /* create and initialize the DHCP message header */ + result = dhcp_create_msg(netif, dhcp, DHCP_REQUEST); + if (result == ERR_OK) { + dhcp_option(dhcp, DHCP_OPTION_MAX_MSG_SIZE, DHCP_OPTION_MAX_MSG_SIZE_LEN); + dhcp_option_short(dhcp, 576); + + dhcp_option(dhcp, DHCP_OPTION_REQUESTED_IP, 4); + dhcp_option_long(dhcp, ntohl(ip4_addr_get_u32(&dhcp->offered_ip_addr))); + + dhcp_option_trailer(dhcp); + + pbuf_realloc(dhcp->p_out, sizeof(struct dhcp_msg) - DHCP_OPTIONS_LEN + dhcp->options_out_len); + + /* broadcast to server */ + udp_sendto_if(dhcp_pcb, dhcp->p_out, IP_ADDR_BROADCAST, DHCP_SERVER_PORT, netif); + dhcp_delete_msg(dhcp); + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("dhcp_reboot: REBOOTING\n")); + } else { + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_SERIOUS, ("dhcp_reboot: could not allocate DHCP request\n")); + } + if (dhcp->tries < 255) { + dhcp->tries++; + } + msecs = dhcp->tries < 10 ? dhcp->tries * 1000 : 10 * 1000; + dhcp->request_timeout = (msecs + DHCP_FINE_TIMER_MSECS - 1) / DHCP_FINE_TIMER_MSECS; + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("dhcp_reboot(): set request timeout %"U16_F" msecs\n", msecs)); + return result; +} + + +/** + * Release a DHCP lease. + * + * @param netif network interface which must release its lease + */ +err_t +dhcp_release(struct netif *netif) +{ + struct dhcp *dhcp = netif->dhcp; + err_t result; + ip_addr_t server_ip_addr; + u8_t is_dhcp_supplied_address; + + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_release()\n")); + if (dhcp == NULL) { + return ERR_ARG; + } + ip_addr_copy(server_ip_addr, dhcp->server_ip_addr); + + is_dhcp_supplied_address = dhcp_supplied_address(netif); + + /* idle DHCP client */ + dhcp_set_state(dhcp, DHCP_STATE_OFF); + /* clean old DHCP offer */ + ip_addr_set_zero_ip4(&dhcp->server_ip_addr); + ip4_addr_set_zero(&dhcp->offered_ip_addr); + ip4_addr_set_zero(&dhcp->offered_sn_mask); + ip4_addr_set_zero(&dhcp->offered_gw_addr); +#if LWIP_DHCP_BOOTP_FILE + ip4_addr_set_zero(&dhcp->offered_si_addr); +#endif /* LWIP_DHCP_BOOTP_FILE */ + dhcp->offered_t0_lease = dhcp->offered_t1_renew = dhcp->offered_t2_rebind = 0; + dhcp->t1_renew_time = dhcp->t2_rebind_time = dhcp->lease_used = dhcp->t0_timeout = 0; + + if (!is_dhcp_supplied_address) { + /* don't issue release message when address is not dhcp-assigned */ + return ERR_OK; + } + + /* create and initialize the DHCP message header */ + result = dhcp_create_msg(netif, dhcp, DHCP_RELEASE); + if (result == ERR_OK) { + dhcp_option(dhcp, DHCP_OPTION_SERVER_ID, 4); + dhcp_option_long(dhcp, ntohl(ip4_addr_get_u32(ip_2_ip4(&server_ip_addr)))); + + dhcp_option_trailer(dhcp); + + pbuf_realloc(dhcp->p_out, sizeof(struct dhcp_msg) - DHCP_OPTIONS_LEN + dhcp->options_out_len); + + udp_sendto_if(dhcp_pcb, dhcp->p_out, &server_ip_addr, DHCP_SERVER_PORT, netif); + dhcp_delete_msg(dhcp); + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("dhcp_release: RELEASED, DHCP_STATE_OFF\n")); + } else { + /* sending release failed, but that's not a problem since the correct behaviour of dhcp does not rely on release */ + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_SERIOUS, ("dhcp_release: could not allocate DHCP request\n")); + } + /* remove IP address from interface (prevents routing from selecting this interface) */ + netif_set_addr(netif, IP4_ADDR_ANY, IP4_ADDR_ANY, IP4_ADDR_ANY); + + return result; +} + +/** + * Remove the DHCP client from the interface. + * + * @param netif The network interface to stop DHCP on + */ +void +dhcp_stop(struct netif *netif) +{ + struct dhcp *dhcp; + LWIP_ERROR("dhcp_stop: netif != NULL", (netif != NULL), return;); + dhcp = netif->dhcp; + + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_stop()\n")); + /* netif is DHCP configured? */ + if (dhcp != NULL) { +#if LWIP_DHCP_AUTOIP_COOP + if (dhcp->autoip_coop_state == DHCP_AUTOIP_COOP_STATE_ON) { + autoip_stop(netif); + dhcp->autoip_coop_state = DHCP_AUTOIP_COOP_STATE_OFF; + } +#endif /* LWIP_DHCP_AUTOIP_COOP */ + + LWIP_ASSERT("reply wasn't freed", dhcp->msg_in == NULL); + dhcp_set_state(dhcp, DHCP_STATE_OFF); + + if(dhcp->pcb_allocated != 0) { + dhcp_dec_pcb_refcount(); /* free DHCP PCB if not needed any more */ + dhcp->pcb_allocated = 0; + } + } +} + +/* + * Set the DHCP state of a DHCP client. + * + * If the state changed, reset the number of tries. + */ +static void +dhcp_set_state(struct dhcp *dhcp, u8_t new_state) +{ + if (new_state != dhcp->state) { + dhcp->state = new_state; + dhcp->tries = 0; + dhcp->request_timeout = 0; + } +} + +/* + * Concatenate an option type and length field to the outgoing + * DHCP message. + * + */ +static void +dhcp_option(struct dhcp *dhcp, u8_t option_type, u8_t option_len) +{ + LWIP_ASSERT("dhcp_option: dhcp->options_out_len + 2 + option_len <= DHCP_OPTIONS_LEN", dhcp->options_out_len + 2U + option_len <= DHCP_OPTIONS_LEN); + dhcp->msg_out->options[dhcp->options_out_len++] = option_type; + dhcp->msg_out->options[dhcp->options_out_len++] = option_len; +} +/* + * Concatenate a single byte to the outgoing DHCP message. + * + */ +static void +dhcp_option_byte(struct dhcp *dhcp, u8_t value) +{ + LWIP_ASSERT("dhcp_option_byte: dhcp->options_out_len < DHCP_OPTIONS_LEN", dhcp->options_out_len < DHCP_OPTIONS_LEN); + dhcp->msg_out->options[dhcp->options_out_len++] = value; +} + +static void +dhcp_option_short(struct dhcp *dhcp, u16_t value) +{ + LWIP_ASSERT("dhcp_option_short: dhcp->options_out_len + 2 <= DHCP_OPTIONS_LEN", dhcp->options_out_len + 2U <= DHCP_OPTIONS_LEN); + dhcp->msg_out->options[dhcp->options_out_len++] = (u8_t)((value & 0xff00U) >> 8); + dhcp->msg_out->options[dhcp->options_out_len++] = (u8_t) (value & 0x00ffU); +} + +static void +dhcp_option_long(struct dhcp *dhcp, u32_t value) +{ + LWIP_ASSERT("dhcp_option_long: dhcp->options_out_len + 4 <= DHCP_OPTIONS_LEN", dhcp->options_out_len + 4U <= DHCP_OPTIONS_LEN); + dhcp->msg_out->options[dhcp->options_out_len++] = (u8_t)((value & 0xff000000UL) >> 24); + dhcp->msg_out->options[dhcp->options_out_len++] = (u8_t)((value & 0x00ff0000UL) >> 16); + dhcp->msg_out->options[dhcp->options_out_len++] = (u8_t)((value & 0x0000ff00UL) >> 8); + dhcp->msg_out->options[dhcp->options_out_len++] = (u8_t)((value & 0x000000ffUL)); +} + +#if LWIP_NETIF_HOSTNAME +static void +dhcp_option_hostname(struct dhcp *dhcp, struct netif *netif) +{ + if (netif->hostname != NULL) { + size_t namelen = strlen(netif->hostname); + if (namelen > 0) { + u8_t len; + const char *p = netif->hostname; + /* Shrink len to available bytes (need 2 bytes for OPTION_HOSTNAME + and 1 byte for trailer) */ + size_t available = DHCP_OPTIONS_LEN - dhcp->options_out_len - 3; + LWIP_ASSERT("DHCP: hostname is too long!", namelen <= available); + len = LWIP_MIN(namelen, available); + dhcp_option(dhcp, DHCP_OPTION_HOSTNAME, len); + while (len--) { + dhcp_option_byte(dhcp, *p++); + } + } + } +} +#endif /* LWIP_NETIF_HOSTNAME */ + +/** + * Extract the DHCP message and the DHCP options. + * + * Extract the DHCP message and the DHCP options, each into a contiguous + * piece of memory. As a DHCP message is variable sized by its options, + * and also allows overriding some fields for options, the easy approach + * is to first unfold the options into a contiguous piece of memory, and + * use that further on. + * + */ +static err_t +dhcp_parse_reply(struct dhcp *dhcp, struct pbuf *p) +{ + u8_t *options; + u16_t offset; + u16_t offset_max; + u16_t options_idx; + u16_t options_idx_max; + struct pbuf *q; + int parse_file_as_options = 0; + int parse_sname_as_options = 0; + + /* clear received options */ + dhcp_clear_all_options(dhcp); + /* check that beginning of dhcp_msg (up to and including chaddr) is in first pbuf */ + if (p->len < DHCP_SNAME_OFS) { + return ERR_BUF; + } + dhcp->msg_in = (struct dhcp_msg *)p->payload; +#if LWIP_DHCP_BOOTP_FILE + /* clear boot file name */ + dhcp->boot_file_name[0] = 0; +#endif /* LWIP_DHCP_BOOTP_FILE */ + + /* parse options */ + + /* start with options field */ + options_idx = DHCP_OPTIONS_OFS; + /* parse options to the end of the received packet */ + options_idx_max = p->tot_len; +again: + q = p; + while ((q != NULL) && (options_idx >= q->len)) { + options_idx -= q->len; + options_idx_max -= q->len; + q = q->next; + } + if (q == NULL) { + return ERR_BUF; + } + offset = options_idx; + offset_max = options_idx_max; + options = (u8_t*)q->payload; + /* at least 1 byte to read and no end marker, then at least 3 bytes to read? */ + while ((q != NULL) && (options[offset] != DHCP_OPTION_END) && (offset < offset_max)) { + u8_t op = options[offset]; + u8_t len; + u8_t decode_len = 0; + int decode_idx = -1; + u16_t val_offset = offset + 2; + /* len byte might be in the next pbuf */ + if (offset + 1 < q->len) { + len = options[offset + 1]; + } else { + len = (q->next != NULL ? ((u8_t*)q->next->payload)[0] : 0); + } + /* LWIP_DEBUGF(DHCP_DEBUG, ("msg_offset=%"U16_F", q->len=%"U16_F, msg_offset, q->len)); */ + decode_len = len; + switch(op) { + /* case(DHCP_OPTION_END): handled above */ + case(DHCP_OPTION_PAD): + /* special option: no len encoded */ + decode_len = len = 0; + /* will be increased below */ + offset--; + break; + case(DHCP_OPTION_SUBNET_MASK): + LWIP_ERROR("len == 4", len == 4, return ERR_VAL;); + decode_idx = DHCP_OPTION_IDX_SUBNET_MASK; + break; + case(DHCP_OPTION_ROUTER): + decode_len = 4; /* only copy the first given router */ + LWIP_ERROR("len >= decode_len", len >= decode_len, return ERR_VAL;); + decode_idx = DHCP_OPTION_IDX_ROUTER; + break; + case(DHCP_OPTION_DNS_SERVER): + /* special case: there might be more than one server */ + LWIP_ERROR("len % 4 == 0", len % 4 == 0, return ERR_VAL;); + /* limit number of DNS servers */ + decode_len = LWIP_MIN(len, 4 * DNS_MAX_SERVERS); + LWIP_ERROR("len >= decode_len", len >= decode_len, return ERR_VAL;); + decode_idx = DHCP_OPTION_IDX_DNS_SERVER; + break; + case(DHCP_OPTION_LEASE_TIME): + LWIP_ERROR("len == 4", len == 4, return ERR_VAL;); + decode_idx = DHCP_OPTION_IDX_LEASE_TIME; + break; +#if LWIP_DHCP_GET_NTP_SRV + case(DHCP_OPTION_NTP): + /* special case: there might be more than one server */ + LWIP_ERROR("len % 4 == 0", len % 4 == 0, return ERR_VAL;); + /* limit number of NTP servers */ + decode_len = LWIP_MIN(len, 4 * LWIP_DHCP_MAX_NTP_SERVERS); + LWIP_ERROR("len >= decode_len", len >= decode_len, return ERR_VAL;); + decode_idx = DHCP_OPTION_IDX_NTP_SERVER; + break; +#endif /* LWIP_DHCP_GET_NTP_SRV*/ + case(DHCP_OPTION_OVERLOAD): + LWIP_ERROR("len == 1", len == 1, return ERR_VAL;); + decode_idx = DHCP_OPTION_IDX_OVERLOAD; + break; + case(DHCP_OPTION_MESSAGE_TYPE): + LWIP_ERROR("len == 1", len == 1, return ERR_VAL;); + decode_idx = DHCP_OPTION_IDX_MSG_TYPE; + break; + case(DHCP_OPTION_SERVER_ID): + LWIP_ERROR("len == 4", len == 4, return ERR_VAL;); + decode_idx = DHCP_OPTION_IDX_SERVER_ID; + break; + case(DHCP_OPTION_T1): + LWIP_ERROR("len == 4", len == 4, return ERR_VAL;); + decode_idx = DHCP_OPTION_IDX_T1; + break; + case(DHCP_OPTION_T2): + LWIP_ERROR("len == 4", len == 4, return ERR_VAL;); + decode_idx = DHCP_OPTION_IDX_T2; + break; + default: + decode_len = 0; + LWIP_DEBUGF(DHCP_DEBUG, ("skipping option %"U16_F" in options\n", op)); + break; + } + offset += len + 2; + if (decode_len > 0) { + u32_t value = 0; + u16_t copy_len; +decode_next: + LWIP_ASSERT("check decode_idx", decode_idx >= 0 && decode_idx < DHCP_OPTION_IDX_MAX); + if (!dhcp_option_given(dhcp, decode_idx)) { + copy_len = LWIP_MIN(decode_len, 4); + pbuf_copy_partial(q, &value, copy_len, val_offset); + if (decode_len > 4) { + /* decode more than one u32_t */ + LWIP_ERROR("decode_len % 4 == 0", decode_len % 4 == 0, return ERR_VAL;); + dhcp_got_option(dhcp, decode_idx); + dhcp_set_option_value(dhcp, decode_idx, htonl(value)); + decode_len -= 4; + val_offset += 4; + decode_idx++; + goto decode_next; + } else if (decode_len == 4) { + value = ntohl(value); + } else { + LWIP_ERROR("invalid decode_len", decode_len == 1, return ERR_VAL;); + value = ((u8_t*)&value)[0]; + } + dhcp_got_option(dhcp, decode_idx); + dhcp_set_option_value(dhcp, decode_idx, value); + } + } + if (offset >= q->len) { + offset -= q->len; + offset_max -= q->len; + if ((offset < offset_max) && offset_max) { + q = q->next; + LWIP_ASSERT("next pbuf was null", q); + options = (u8_t*)q->payload; + } else { + /* We've run out of bytes, probably no end marker. Don't proceed. */ + break; + } + } + } + /* is this an overloaded message? */ + if (dhcp_option_given(dhcp, DHCP_OPTION_IDX_OVERLOAD)) { + u32_t overload = dhcp_get_option_value(dhcp, DHCP_OPTION_IDX_OVERLOAD); + dhcp_clear_option(dhcp, DHCP_OPTION_IDX_OVERLOAD); + if (overload == DHCP_OVERLOAD_FILE) { + parse_file_as_options = 1; + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("overloaded file field\n")); + } else if (overload == DHCP_OVERLOAD_SNAME) { + parse_sname_as_options = 1; + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("overloaded sname field\n")); + } else if (overload == DHCP_OVERLOAD_SNAME_FILE) { + parse_sname_as_options = 1; + parse_file_as_options = 1; + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("overloaded sname and file field\n")); + } else { + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("invalid overload option: %d\n", (int)overload)); + } +#if LWIP_DHCP_BOOTP_FILE + if (!parse_file_as_options) { + /* only do this for ACK messages */ + if (dhcp_option_given(dhcp, DHCP_OPTION_IDX_MSG_TYPE) && + (dhcp_get_option_value(dhcp, DHCP_OPTION_IDX_MSG_TYPE) == DHCP_ACK)) + /* copy bootp file name, don't care for sname (server hostname) */ + pbuf_copy_partial(p, dhcp->boot_file_name, DHCP_FILE_LEN-1, DHCP_FILE_OFS); + /* make sure the string is really NULL-terminated */ + dhcp->boot_file_name[DHCP_FILE_LEN-1] = 0; + } +#endif /* LWIP_DHCP_BOOTP_FILE */ + } + if (parse_file_as_options) { + /* if both are overloaded, parse file first and then sname (RFC 2131 ch. 4.1) */ + parse_file_as_options = 0; + options_idx = DHCP_FILE_OFS; + options_idx_max = DHCP_FILE_OFS + DHCP_FILE_LEN; + goto again; + } else if (parse_sname_as_options) { + parse_sname_as_options = 0; + options_idx = DHCP_SNAME_OFS; + options_idx_max = DHCP_SNAME_OFS + DHCP_SNAME_LEN; + goto again; + } + return ERR_OK; +} + +/** + * If an incoming DHCP message is in response to us, then trigger the state machine + */ +static void +dhcp_recv(void *arg, struct udp_pcb *pcb, struct pbuf *p, const ip_addr_t *addr, u16_t port) +{ + struct netif *netif = ip_current_input_netif(); + struct dhcp *dhcp = netif->dhcp; + struct dhcp_msg *reply_msg = (struct dhcp_msg *)p->payload; + u8_t msg_type; + u8_t i; + + LWIP_UNUSED_ARG(arg); + + /* Caught DHCP message from netif that does not have DHCP enabled? -> not interested */ + if((dhcp == NULL) || (dhcp->pcb_allocated == 0)) { + goto free_pbuf_and_return; + } + + LWIP_ASSERT("invalid server address type", !IP_IS_V6(addr)); + + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_recv(pbuf = %p) from DHCP server %"U16_F".%"U16_F".%"U16_F".%"U16_F" port %"U16_F"\n", (void*)p, + ip4_addr1_16(ip_2_ip4(addr)), ip4_addr2_16(ip_2_ip4(addr)), ip4_addr3_16(ip_2_ip4(addr)), ip4_addr4_16(ip_2_ip4(addr)), port)); + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("pbuf->len = %"U16_F"\n", p->len)); + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("pbuf->tot_len = %"U16_F"\n", p->tot_len)); + /* prevent warnings about unused arguments */ + LWIP_UNUSED_ARG(pcb); + LWIP_UNUSED_ARG(addr); + LWIP_UNUSED_ARG(port); + + LWIP_ASSERT("reply wasn't freed", dhcp->msg_in == NULL); + + if (p->len < DHCP_MIN_REPLY_LEN) { + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_WARNING, ("DHCP reply message or pbuf too short\n")); + goto free_pbuf_and_return; + } + + if (reply_msg->op != DHCP_BOOTREPLY) { + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_WARNING, ("not a DHCP reply message, but type %"U16_F"\n", (u16_t)reply_msg->op)); + goto free_pbuf_and_return; + } + /* iterate through hardware address and match against DHCP message */ + for (i = 0; i < netif->hwaddr_len && i < NETIF_MAX_HWADDR_LEN && i < DHCP_CHADDR_LEN; i++) { + if (netif->hwaddr[i] != reply_msg->chaddr[i]) { + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_WARNING, + ("netif->hwaddr[%"U16_F"]==%02"X16_F" != reply_msg->chaddr[%"U16_F"]==%02"X16_F"\n", + (u16_t)i, (u16_t)netif->hwaddr[i], (u16_t)i, (u16_t)reply_msg->chaddr[i])); + goto free_pbuf_and_return; + } + } + /* match transaction ID against what we expected */ + if (ntohl(reply_msg->xid) != dhcp->xid) { + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_WARNING, + ("transaction id mismatch reply_msg->xid(%"X32_F")!=dhcp->xid(%"X32_F")\n",ntohl(reply_msg->xid),dhcp->xid)); + goto free_pbuf_and_return; + } + /* option fields could be unfold? */ + if (dhcp_parse_reply(dhcp, p) != ERR_OK) { + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_SERIOUS, + ("problem unfolding DHCP message - too short on memory?\n")); + goto free_pbuf_and_return; + } + + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("searching DHCP_OPTION_MESSAGE_TYPE\n")); + /* obtain pointer to DHCP message type */ + if (!dhcp_option_given(dhcp, DHCP_OPTION_IDX_MSG_TYPE)) { + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_WARNING, ("DHCP_OPTION_MESSAGE_TYPE option not found\n")); + goto free_pbuf_and_return; + } + + /* read DHCP message type */ + msg_type = (u8_t)dhcp_get_option_value(dhcp, DHCP_OPTION_IDX_MSG_TYPE); + /* message type is DHCP ACK? */ + if (msg_type == DHCP_ACK) { + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("DHCP_ACK received\n")); + /* in requesting state? */ + if (dhcp->state == DHCP_STATE_REQUESTING) { + dhcp_handle_ack(netif); +#if DHCP_DOES_ARP_CHECK + /* check if the acknowledged lease address is already in use */ + dhcp_check(netif); +#else + /* bind interface to the acknowledged lease address */ + dhcp_bind(netif); +#endif + } + /* already bound to the given lease address? */ + else if ((dhcp->state == DHCP_STATE_REBOOTING) || (dhcp->state == DHCP_STATE_REBINDING) || + (dhcp->state == DHCP_STATE_RENEWING)) { + dhcp_bind(netif); + } + } + /* received a DHCP_NAK in appropriate state? */ + else if ((msg_type == DHCP_NAK) && + ((dhcp->state == DHCP_STATE_REBOOTING) || (dhcp->state == DHCP_STATE_REQUESTING) || + (dhcp->state == DHCP_STATE_REBINDING) || (dhcp->state == DHCP_STATE_RENEWING ))) { + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("DHCP_NAK received\n")); + dhcp_handle_nak(netif); + } + /* received a DHCP_OFFER in DHCP_STATE_SELECTING state? */ + else if ((msg_type == DHCP_OFFER) && (dhcp->state == DHCP_STATE_SELECTING)) { + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("DHCP_OFFER received in DHCP_STATE_SELECTING state\n")); + dhcp->request_timeout = 0; + /* remember offered lease */ + dhcp_handle_offer(netif); + } +free_pbuf_and_return: + dhcp->msg_in = NULL; + pbuf_free(p); +} + +/** + * Create a DHCP request, fill in common headers + * + * @param netif the netif under DHCP control + * @param dhcp dhcp control struct + * @param message_type message type of the request + */ +static err_t +dhcp_create_msg(struct netif *netif, struct dhcp *dhcp, u8_t message_type) +{ + u16_t i; +#ifndef DHCP_GLOBAL_XID + /** default global transaction identifier starting value (easy to match + * with a packet analyser). We simply increment for each new request. + * Predefine DHCP_GLOBAL_XID to a better value or a function call to generate one + * at runtime, any supporting function prototypes can be defined in DHCP_GLOBAL_XID_HEADER */ +#if DHCP_CREATE_RAND_XID && defined(LWIP_RAND) + static u32_t xid; +#else /* DHCP_CREATE_RAND_XID && defined(LWIP_RAND) */ + static u32_t xid = 0xABCD0000; +#endif /* DHCP_CREATE_RAND_XID && defined(LWIP_RAND) */ +#else + if (!xid_initialised) { + xid = DHCP_GLOBAL_XID; + xid_initialised = !xid_initialised; + } +#endif + LWIP_ERROR("dhcp_create_msg: netif != NULL", (netif != NULL), return ERR_ARG;); + LWIP_ERROR("dhcp_create_msg: dhcp != NULL", (dhcp != NULL), return ERR_VAL;); + LWIP_ASSERT("dhcp_create_msg: dhcp->p_out == NULL", dhcp->p_out == NULL); + LWIP_ASSERT("dhcp_create_msg: dhcp->msg_out == NULL", dhcp->msg_out == NULL); + dhcp->p_out = pbuf_alloc(PBUF_TRANSPORT, sizeof(struct dhcp_msg), PBUF_RAM); + if (dhcp->p_out == NULL) { + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_SERIOUS, + ("dhcp_create_msg(): could not allocate pbuf\n")); + return ERR_MEM; + } + LWIP_ASSERT("dhcp_create_msg: check that first pbuf can hold struct dhcp_msg", + (dhcp->p_out->len >= sizeof(struct dhcp_msg))); + + /* DHCP_REQUEST should reuse 'xid' from DHCPOFFER */ + if (message_type != DHCP_REQUEST) { + /* reuse transaction identifier in retransmissions */ + if (dhcp->tries == 0) { +#if DHCP_CREATE_RAND_XID && defined(LWIP_RAND) + xid = LWIP_RAND(); +#else /* DHCP_CREATE_RAND_XID && defined(LWIP_RAND) */ + xid++; +#endif /* DHCP_CREATE_RAND_XID && defined(LWIP_RAND) */ + } + dhcp->xid = xid; + } + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, + ("transaction id xid(%"X32_F")\n", xid)); + + dhcp->msg_out = (struct dhcp_msg *)dhcp->p_out->payload; + + dhcp->msg_out->op = DHCP_BOOTREQUEST; + /* TODO: make link layer independent */ + dhcp->msg_out->htype = DHCP_HTYPE_ETH; + dhcp->msg_out->hlen = netif->hwaddr_len; + dhcp->msg_out->hops = 0; + dhcp->msg_out->xid = htonl(dhcp->xid); + dhcp->msg_out->secs = 0; + /* we don't need the broadcast flag since we can receive unicast traffic + before being fully configured! */ + dhcp->msg_out->flags = 0; + ip4_addr_set_zero(&dhcp->msg_out->ciaddr); + /* set ciaddr to netif->ip_addr based on message_type and state */ + if ((message_type == DHCP_INFORM) || (message_type == DHCP_DECLINE) || (message_type == DHCP_RELEASE) || + ((message_type == DHCP_REQUEST) && /* DHCP_STATE_BOUND not used for sending! */ + ((dhcp->state== DHCP_STATE_RENEWING) || dhcp->state== DHCP_STATE_REBINDING))) { + ip4_addr_copy(dhcp->msg_out->ciaddr, *netif_ip4_addr(netif)); + } + ip4_addr_set_zero(&dhcp->msg_out->yiaddr); + ip4_addr_set_zero(&dhcp->msg_out->siaddr); + ip4_addr_set_zero(&dhcp->msg_out->giaddr); + for (i = 0; i < DHCP_CHADDR_LEN; i++) { + /* copy netif hardware address, pad with zeroes */ + dhcp->msg_out->chaddr[i] = (i < netif->hwaddr_len && i < NETIF_MAX_HWADDR_LEN) ? netif->hwaddr[i] : 0/* pad byte*/; + } + for (i = 0; i < DHCP_SNAME_LEN; i++) { + dhcp->msg_out->sname[i] = 0; + } + for (i = 0; i < DHCP_FILE_LEN; i++) { + dhcp->msg_out->file[i] = 0; + } + dhcp->msg_out->cookie = PP_HTONL(DHCP_MAGIC_COOKIE); + dhcp->options_out_len = 0; + /* fill options field with an incrementing array (for debugging purposes) */ + for (i = 0; i < DHCP_OPTIONS_LEN; i++) { + dhcp->msg_out->options[i] = (u8_t)i; /* for debugging only, no matter if truncated */ + } + /* Add option MESSAGE_TYPE */ + dhcp_option(dhcp, DHCP_OPTION_MESSAGE_TYPE, DHCP_OPTION_MESSAGE_TYPE_LEN); + dhcp_option_byte(dhcp, message_type); + return ERR_OK; +} + +/** + * Free previously allocated memory used to send a DHCP request. + * + * @param dhcp the dhcp struct to free the request from + */ +static void +dhcp_delete_msg(struct dhcp *dhcp) +{ + LWIP_ERROR("dhcp_delete_msg: dhcp != NULL", (dhcp != NULL), return;); + LWIP_ASSERT("dhcp_delete_msg: dhcp->p_out != NULL", dhcp->p_out != NULL); + LWIP_ASSERT("dhcp_delete_msg: dhcp->msg_out != NULL", dhcp->msg_out != NULL); + if (dhcp->p_out != NULL) { + pbuf_free(dhcp->p_out); + } + dhcp->p_out = NULL; + dhcp->msg_out = NULL; +} + +/** + * Add a DHCP message trailer + * + * Adds the END option to the DHCP message, and if + * necessary, up to three padding bytes. + * + * @param dhcp DHCP state structure + */ +static void +dhcp_option_trailer(struct dhcp *dhcp) +{ + LWIP_ERROR("dhcp_option_trailer: dhcp != NULL", (dhcp != NULL), return;); + LWIP_ASSERT("dhcp_option_trailer: dhcp->msg_out != NULL\n", dhcp->msg_out != NULL); + LWIP_ASSERT("dhcp_option_trailer: dhcp->options_out_len < DHCP_OPTIONS_LEN\n", dhcp->options_out_len < DHCP_OPTIONS_LEN); + dhcp->msg_out->options[dhcp->options_out_len++] = DHCP_OPTION_END; + /* packet is too small, or not 4 byte aligned? */ + while (((dhcp->options_out_len < DHCP_MIN_OPTIONS_LEN) || (dhcp->options_out_len & 3)) && + (dhcp->options_out_len < DHCP_OPTIONS_LEN)) { + /* add a fill/padding byte */ + dhcp->msg_out->options[dhcp->options_out_len++] = 0; + } +} + +/** check if DHCP supplied netif->ip_addr + * + * @param netif the netif to check + * @return 1 if DHCP supplied netif->ip_addr (states BOUND or RENEWING), + * 0 otherwise + */ +u8_t +dhcp_supplied_address(struct netif *netif) +{ + if ((netif != NULL) && (netif->dhcp != NULL)) { + if ((netif->dhcp->state == DHCP_STATE_BOUND) || + (netif->dhcp->state == DHCP_STATE_RENEWING)) { + return 1; + } + } + return 0; +} + +#endif /* LWIP_IPV4 && LWIP_DHCP */ diff --git a/components/lwip/core/ipv4/icmp.c b/components/lwip/core/ipv4/icmp.c new file mode 100755 index 0000000000..c492ed75fe --- /dev/null +++ b/components/lwip/core/ipv4/icmp.c @@ -0,0 +1,391 @@ +/** + * @file + * ICMP - Internet Control Message Protocol + * + */ + +/* + * Copyright (c) 2001-2004 Swedish Institute of Computer Science. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + * + */ + +/* Some ICMP messages should be passed to the transport protocols. This + is not implemented. */ + +#include "lwip/opt.h" + +#if LWIP_IPV4 && LWIP_ICMP /* don't build if not configured for use in lwipopts.h */ + +#include "lwip/icmp.h" +#include "lwip/inet_chksum.h" +#include "lwip/ip.h" +#include "lwip/def.h" +#include "lwip/stats.h" + +#include + +#ifdef MEMLEAK_DEBUG +static const char mem_debug_file[] ICACHE_RODATA_ATTR STORE_ATTR = __FILE__; +#endif + + +/** Small optimization: set to 0 if incoming PBUF_POOL pbuf always can be + * used to modify and send a response packet (and to 1 if this is not the case, + * e.g. when link header is stripped of when receiving) */ +#ifndef LWIP_ICMP_ECHO_CHECK_INPUT_PBUF_LEN +#define LWIP_ICMP_ECHO_CHECK_INPUT_PBUF_LEN 1 +#endif /* LWIP_ICMP_ECHO_CHECK_INPUT_PBUF_LEN */ + +/* The amount of data from the original packet to return in a dest-unreachable */ +#define ICMP_DEST_UNREACH_DATASIZE 8 + +static void icmp_send_response(struct pbuf *p, u8_t type, u8_t code); + +/** + * Processes ICMP input packets, called from ip_input(). + * + * Currently only processes icmp echo requests and sends + * out the echo response. + * + * @param p the icmp echo request packet, p->payload pointing to the icmp header + * @param inp the netif on which this packet was received + */ +void +icmp_input(struct pbuf *p, struct netif *inp) +{ + u8_t type; +#ifdef LWIP_DEBUG + u8_t code; +#endif /* LWIP_DEBUG */ + struct icmp_echo_hdr *iecho; + const struct ip_hdr *iphdr_in; + s16_t hlen; + const ip4_addr_t* src; + + ICMP_STATS_INC(icmp.recv); + MIB2_STATS_INC(mib2.icmpinmsgs); + + iphdr_in = ip4_current_header(); + hlen = IPH_HL(iphdr_in) * 4; + if (p->len < sizeof(u16_t)*2) { + LWIP_DEBUGF(ICMP_DEBUG, ("icmp_input: short ICMP (%"U16_F" bytes) received\n", p->tot_len)); + goto lenerr; + } + + type = *((u8_t *)p->payload); +#ifdef LWIP_DEBUG + code = *(((u8_t *)p->payload)+1); +#endif /* LWIP_DEBUG */ + switch (type) { + case ICMP_ER: + /* This is OK, echo reply might have been parsed by a raw PCB + (as obviously, an echo request has been sent, too). */ + MIB2_STATS_INC(mib2.icmpinechoreps); + break; + case ICMP_ECHO: + MIB2_STATS_INC(mib2.icmpinechos); + src = ip4_current_dest_addr(); + /* multicast destination address? */ + if (ip4_addr_ismulticast(ip4_current_dest_addr())) { +#if LWIP_MULTICAST_PING + /* For multicast, use address of receiving interface as source address */ + src = netif_ip4_addr(inp); +#else /* LWIP_MULTICAST_PING */ + LWIP_DEBUGF(ICMP_DEBUG, ("icmp_input: Not echoing to multicast pings\n")); + goto icmperr; +#endif /* LWIP_MULTICAST_PING */ + } + /* broadcast destination address? */ + if (ip4_addr_isbroadcast(ip4_current_dest_addr(), ip_current_netif())) { +#if LWIP_BROADCAST_PING + /* For broadcast, use address of receiving interface as source address */ + src = netif_ip4_addr(inp); +#else /* LWIP_BROADCAST_PING */ + LWIP_DEBUGF(ICMP_DEBUG, ("icmp_input: Not echoing to broadcast pings\n")); + goto icmperr; +#endif /* LWIP_BROADCAST_PING */ + } + LWIP_DEBUGF(ICMP_DEBUG, ("icmp_input: ping\n")); + if (p->tot_len < sizeof(struct icmp_echo_hdr)) { + LWIP_DEBUGF(ICMP_DEBUG, ("icmp_input: bad ICMP echo received\n")); + goto lenerr; + } +#if CHECKSUM_CHECK_ICMP + IF__NETIF_CHECKSUM_ENABLED(inp, NETIF_CHECKSUM_CHECK_ICMP) { + if (inet_chksum_pbuf(p) != 0) { + LWIP_DEBUGF(ICMP_DEBUG, ("icmp_input: checksum failed for received ICMP echo\n")); + pbuf_free(p); + ICMP_STATS_INC(icmp.chkerr); + MIB2_STATS_INC(mib2.icmpinerrors); + return; + } + } +#endif +#if LWIP_ICMP_ECHO_CHECK_INPUT_PBUF_LEN + if (pbuf_header(p, (PBUF_IP_HLEN + PBUF_LINK_HLEN + PBUF_LINK_ENCAPSULATION_HLEN))) { + /* p is not big enough to contain link headers + * allocate a new one and copy p into it + */ + struct pbuf *r; + /* allocate new packet buffer with space for link headers */ + r = pbuf_alloc(PBUF_LINK, p->tot_len + hlen, PBUF_RAM); + if (r == NULL) { + LWIP_DEBUGF(ICMP_DEBUG, ("icmp_input: allocating new pbuf failed\n")); + goto icmperr; + } + LWIP_ASSERT("check that first pbuf can hold struct the ICMP header", + (r->len >= hlen + sizeof(struct icmp_echo_hdr))); + /* copy the ip header */ + MEMCPY(r->payload, iphdr_in, hlen); + /* switch r->payload back to icmp header */ + if (pbuf_header(r, -hlen)) { + LWIP_ASSERT("icmp_input: moving r->payload to icmp header failed\n", 0); + pbuf_free(r); + goto icmperr; + } + /* copy the rest of the packet without ip header */ + if (pbuf_copy(r, p) != ERR_OK) { + LWIP_ASSERT("icmp_input: copying to new pbuf failed\n", 0); + pbuf_free(r); + goto icmperr; + } + /* free the original p */ + pbuf_free(p); + /* we now have an identical copy of p that has room for link headers */ + p = r; + } else { + /* restore p->payload to point to icmp header */ + if (pbuf_header(p, -(s16_t)(PBUF_IP_HLEN + PBUF_LINK_HLEN + PBUF_LINK_ENCAPSULATION_HLEN))) { + LWIP_ASSERT("icmp_input: restoring original p->payload failed\n", 0); + goto icmperr; + } + } +#endif /* LWIP_ICMP_ECHO_CHECK_INPUT_PBUF_LEN */ + /* At this point, all checks are OK. */ + /* We generate an answer by switching the dest and src ip addresses, + * setting the icmp type to ECHO_RESPONSE and updating the checksum. */ + iecho = (struct icmp_echo_hdr *)p->payload; + if (pbuf_header(p, hlen)) { + LWIP_ASSERT("Can't move over header in packet", 0); + } else { + err_t ret; + struct ip_hdr *iphdr = (struct ip_hdr*)p->payload; + ip4_addr_copy(iphdr->src, *src); + ip4_addr_copy(iphdr->dest, *ip4_current_src_addr()); + ICMPH_TYPE_SET(iecho, ICMP_ER); +#if CHECKSUM_GEN_ICMP + IF__NETIF_CHECKSUM_ENABLED(inp, NETIF_CHECKSUM_GEN_ICMP) { + /* adjust the checksum */ + if (iecho->chksum > PP_HTONS(0xffffU - (ICMP_ECHO << 8))) { + iecho->chksum += PP_HTONS(ICMP_ECHO << 8) + 1; + } else { + iecho->chksum += PP_HTONS(ICMP_ECHO << 8); + } + } +#if LWIP_CHECKSUM_CTRL_PER_NETIF + else { + iecho->chksum = 0; + } +#endif /* LWIP_CHECKSUM_CTRL_PER_NETIF */ +#else /* CHECKSUM_GEN_ICMP */ + iecho->chksum = 0; +#endif /* CHECKSUM_GEN_ICMP */ + + /* Set the correct TTL and recalculate the header checksum. */ + IPH_TTL_SET(iphdr, ICMP_TTL); + IPH_CHKSUM_SET(iphdr, 0); +#if CHECKSUM_GEN_IP + IF__NETIF_CHECKSUM_ENABLED(inp, NETIF_CHECKSUM_GEN_IP) { + IPH_CHKSUM_SET(iphdr, inet_chksum(iphdr, IP_HLEN)); + } +#endif /* CHECKSUM_GEN_IP */ + + ICMP_STATS_INC(icmp.xmit); + /* increase number of messages attempted to send */ + MIB2_STATS_INC(mib2.icmpoutmsgs); + /* increase number of echo replies attempted to send */ + MIB2_STATS_INC(mib2.icmpoutechoreps); + + /* send an ICMP packet */ + ret = ip4_output_if(p, src, IP_HDRINCL, + ICMP_TTL, 0, IP_PROTO_ICMP, inp); + if (ret != ERR_OK) { + LWIP_DEBUGF(ICMP_DEBUG, ("icmp_input: ip_output_if returned an error: %s\n", lwip_strerr(ret))); + } + } + break; + default: + if (type == ICMP_DUR) { + MIB2_STATS_INC(mib2.icmpindestunreachs); + } else if (type == ICMP_TE) { + MIB2_STATS_INC(mib2.icmpindestunreachs); + } else if (type == ICMP_PP) { + MIB2_STATS_INC(mib2.icmpinparmprobs); + } else if (type == ICMP_SQ) { + MIB2_STATS_INC(mib2.icmpinsrcquenchs); + } else if (type == ICMP_RD) { + MIB2_STATS_INC(mib2.icmpinredirects); + } else if (type == ICMP_TS) { + MIB2_STATS_INC(mib2.icmpintimestamps); + } else if (type == ICMP_TSR) { + MIB2_STATS_INC(mib2.icmpintimestampreps); + } else if (type == ICMP_AM) { + MIB2_STATS_INC(mib2.icmpinaddrmasks); + } else if (type == ICMP_AMR) { + MIB2_STATS_INC(mib2.icmpinaddrmaskreps); + } + LWIP_DEBUGF(ICMP_DEBUG, ("icmp_input: ICMP type %"S16_F" code %"S16_F" not supported.\n", + (s16_t)type, (s16_t)code)); + ICMP_STATS_INC(icmp.proterr); + ICMP_STATS_INC(icmp.drop); + } + pbuf_free(p); + return; +lenerr: + pbuf_free(p); + ICMP_STATS_INC(icmp.lenerr); + MIB2_STATS_INC(mib2.icmpinerrors); + return; +#if LWIP_ICMP_ECHO_CHECK_INPUT_PBUF_LEN || !LWIP_MULTICAST_PING || !LWIP_BROADCAST_PING +icmperr: + pbuf_free(p); + ICMP_STATS_INC(icmp.err); + MIB2_STATS_INC(mib2.icmpinerrors); + return; +#endif /* LWIP_ICMP_ECHO_CHECK_INPUT_PBUF_LEN || !LWIP_MULTICAST_PING || !LWIP_BROADCAST_PING */ +} + +/** + * Send an icmp 'destination unreachable' packet, called from ip_input() if + * the transport layer protocol is unknown and from udp_input() if the local + * port is not bound. + * + * @param p the input packet for which the 'unreachable' should be sent, + * p->payload pointing to the IP header + * @param t type of the 'unreachable' packet + */ +void +icmp_dest_unreach(struct pbuf *p, enum icmp_dur_type t) +{ + MIB2_STATS_INC(mib2.icmpoutdestunreachs); + icmp_send_response(p, ICMP_DUR, t); +} + +#if IP_FORWARD || IP_REASSEMBLY +/** + * Send a 'time exceeded' packet, called from ip_forward() if TTL is 0. + * + * @param p the input packet for which the 'time exceeded' should be sent, + * p->payload pointing to the IP header + * @param t type of the 'time exceeded' packet + */ +void +icmp_time_exceeded(struct pbuf *p, enum icmp_te_type t) +{ + MIB2_STATS_INC(mib2.icmpouttimeexcds); + icmp_send_response(p, ICMP_TE, t); +} + +#endif /* IP_FORWARD || IP_REASSEMBLY */ + +/** + * Send an icmp packet in response to an incoming packet. + * + * @param p the input packet for which the 'unreachable' should be sent, + * p->payload pointing to the IP header + * @param type Type of the ICMP header + * @param code Code of the ICMP header + */ +static void +icmp_send_response(struct pbuf *p, u8_t type, u8_t code) +{ + struct pbuf *q; + struct ip_hdr *iphdr; + /* we can use the echo header here */ + struct icmp_echo_hdr *icmphdr; + ip4_addr_t iphdr_src; + struct netif *netif; + + /* increase number of messages attempted to send */ + MIB2_STATS_INC(mib2.icmpoutmsgs); + + /* ICMP header + IP header + 8 bytes of data */ + q = pbuf_alloc(PBUF_IP, sizeof(struct icmp_echo_hdr) + IP_HLEN + ICMP_DEST_UNREACH_DATASIZE, + PBUF_RAM); + if (q == NULL) { + LWIP_DEBUGF(ICMP_DEBUG, ("icmp_time_exceeded: failed to allocate pbuf for ICMP packet.\n")); + MIB2_STATS_INC(mib2.icmpouterrors); + return; + } + LWIP_ASSERT("check that first pbuf can hold icmp message", + (q->len >= (sizeof(struct icmp_echo_hdr) + IP_HLEN + ICMP_DEST_UNREACH_DATASIZE))); + + iphdr = (struct ip_hdr *)p->payload; + LWIP_DEBUGF(ICMP_DEBUG, ("icmp_time_exceeded from ")); + ip4_addr_debug_print_val(ICMP_DEBUG, iphdr->src); + LWIP_DEBUGF(ICMP_DEBUG, (" to ")); + ip4_addr_debug_print_val(ICMP_DEBUG, iphdr->dest); + LWIP_DEBUGF(ICMP_DEBUG, ("\n")); + + icmphdr = (struct icmp_echo_hdr *)q->payload; + icmphdr->type = type; + icmphdr->code = code; + icmphdr->id = 0; + icmphdr->seqno = 0; + + /* copy fields from original packet */ + SMEMCPY((u8_t *)q->payload + sizeof(struct icmp_echo_hdr), (u8_t *)p->payload, + IP_HLEN + ICMP_DEST_UNREACH_DATASIZE); + + ip4_addr_copy(iphdr_src, iphdr->src); +#ifdef LWIP_HOOK_IP4_ROUTE_SRC + { + ip4_addr_t iphdr_dst; + ip4_addr_copy(iphdr_dst, iphdr->dest); + netif = ip4_route_src(&iphdr_src, &iphdr_dst); + } +#else + netif = ip4_route(&iphdr_src); +#endif + if (netif != NULL) { + /* calculate checksum */ + icmphdr->chksum = 0; +#if CHECKSUM_GEN_ICMP + IF__NETIF_CHECKSUM_ENABLED(netif, NETIF_CHECKSUM_GEN_ICMP) { + icmphdr->chksum = inet_chksum(icmphdr, q->len); + } +#endif + ICMP_STATS_INC(icmp.xmit); + ip4_output_if(q, NULL, &iphdr_src, ICMP_TTL, 0, IP_PROTO_ICMP, netif); + } + pbuf_free(q); +} + +#endif /* LWIP_IPV4 && LWIP_ICMP */ diff --git a/components/lwip/core/ipv4/igmp.c b/components/lwip/core/ipv4/igmp.c new file mode 100755 index 0000000000..d75fe15fd0 --- /dev/null +++ b/components/lwip/core/ipv4/igmp.c @@ -0,0 +1,832 @@ +/** + * @file + * IGMP - Internet Group Management Protocol + * + */ + +/* + * Copyright (c) 2002 CITEL Technologies Ltd. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of CITEL Technologies Ltd nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY CITEL TECHNOLOGIES AND CONTRIBUTORS ``AS IS'' + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL CITEL TECHNOLOGIES OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * This file is a contribution to the lwIP TCP/IP stack. + * The Swedish Institute of Computer Science and Adam Dunkels + * are specifically granted permission to redistribute this + * source code. +*/ + +/*------------------------------------------------------------- +Note 1) +Although the rfc requires V1 AND V2 capability +we will only support v2 since now V1 is very old (August 1989) +V1 can be added if required + +a debug print and statistic have been implemented to +show this up. +------------------------------------------------------------- +------------------------------------------------------------- +Note 2) +A query for a specific group address (as opposed to ALLHOSTS) +has now been implemented as I am unsure if it is required + +a debug print and statistic have been implemented to +show this up. +------------------------------------------------------------- +------------------------------------------------------------- +Note 3) +The router alert rfc 2113 is implemented in outgoing packets +but not checked rigorously incoming +------------------------------------------------------------- +Steve Reynolds +------------------------------------------------------------*/ + +/*----------------------------------------------------------------------------- + * RFC 988 - Host extensions for IP multicasting - V0 + * RFC 1054 - Host extensions for IP multicasting - + * RFC 1112 - Host extensions for IP multicasting - V1 + * RFC 2236 - Internet Group Management Protocol, Version 2 - V2 <- this code is based on this RFC (it's the "de facto" standard) + * RFC 3376 - Internet Group Management Protocol, Version 3 - V3 + * RFC 4604 - Using Internet Group Management Protocol Version 3... - V3+ + * RFC 2113 - IP Router Alert Option - + *----------------------------------------------------------------------------*/ + +/*----------------------------------------------------------------------------- + * Includes + *----------------------------------------------------------------------------*/ + +#include "lwip/opt.h" + +#if LWIP_IPV4 && LWIP_IGMP /* don't build if not configured for use in lwipopts.h */ + +#include "lwip/igmp.h" +#include "lwip/debug.h" +#include "lwip/def.h" +#include "lwip/mem.h" +#include "lwip/ip.h" +#include "lwip/inet_chksum.h" +#include "lwip/netif.h" +#include "lwip/stats.h" + +#include "string.h" + +#ifdef MEMLEAK_DEBUG +static const char mem_debug_file[] ICACHE_RODATA_ATTR STORE_ATTR = __FILE__; +#endif + + +/* + * IGMP constants + */ +#define IGMP_TTL 1 +#define IGMP_MINLEN 8 +#define ROUTER_ALERT 0x9404U +#define ROUTER_ALERTLEN 4 + +/* + * IGMP message types, including version number. + */ +#define IGMP_MEMB_QUERY 0x11 /* Membership query */ +#define IGMP_V1_MEMB_REPORT 0x12 /* Ver. 1 membership report */ +#define IGMP_V2_MEMB_REPORT 0x16 /* Ver. 2 membership report */ +#define IGMP_LEAVE_GROUP 0x17 /* Leave-group message */ + +/* Group membership states */ +#define IGMP_GROUP_NON_MEMBER 0 +#define IGMP_GROUP_DELAYING_MEMBER 1 +#define IGMP_GROUP_IDLE_MEMBER 2 + +/** + * IGMP packet format. + */ +#ifdef PACK_STRUCT_USE_INCLUDES +# include "arch/bpstruct.h" +#endif +PACK_STRUCT_BEGIN +struct igmp_msg { + PACK_STRUCT_FLD_8(u8_t igmp_msgtype); + PACK_STRUCT_FLD_8(u8_t igmp_maxresp); + PACK_STRUCT_FIELD(u16_t igmp_checksum); + PACK_STRUCT_FLD_S(ip4_addr_p_t igmp_group_address); +} PACK_STRUCT_STRUCT; +PACK_STRUCT_END +#ifdef PACK_STRUCT_USE_INCLUDES +# include "arch/epstruct.h" +#endif + + +static struct igmp_group *igmp_lookup_group(struct netif *ifp, const ip4_addr_t *addr); +static err_t igmp_remove_group(struct igmp_group *group); +static void igmp_timeout( struct igmp_group *group); +static void igmp_start_timer(struct igmp_group *group, u8_t max_time); +static void igmp_delaying_member(struct igmp_group *group, u8_t maxresp); +static err_t igmp_ip_output_if(struct pbuf *p, const ip4_addr_t *src, const ip4_addr_t *dest, struct netif *netif); +static void igmp_send(struct igmp_group *group, u8_t type); + + +static struct igmp_group* igmp_group_list; +static ip4_addr_t allsystems; +static ip4_addr_t allrouters; + + +/** + * Initialize the IGMP module + */ +void +igmp_init(void) +{ + LWIP_DEBUGF(IGMP_DEBUG, ("igmp_init: initializing\n")); + + IP4_ADDR(&allsystems, 224, 0, 0, 1); + IP4_ADDR(&allrouters, 224, 0, 0, 2); +} + +/** + * Start IGMP processing on interface + * + * @param netif network interface on which start IGMP processing + */ +err_t +igmp_start(struct netif *netif) +{ + struct igmp_group* group; + LWIP_DEBUGF(IGMP_DEBUG, ("igmp_start: starting IGMP processing on if %p\n", (void*)netif)); + group = igmp_lookup_group(netif, &allsystems); + + if (group != NULL) { + group->group_state = IGMP_GROUP_IDLE_MEMBER; + group->use++; + + /* Allow the igmp messages at the MAC level */ + if (netif->igmp_mac_filter != NULL) { + LWIP_DEBUGF(IGMP_DEBUG, ("igmp_start: igmp_mac_filter(ADD ")); + ip4_addr_debug_print_val(IGMP_DEBUG, allsystems); + LWIP_DEBUGF(IGMP_DEBUG, (") on if %p\n", (void*)netif)); + netif->igmp_mac_filter(netif, &allsystems, IGMP_ADD_MAC_FILTER); + } + return ERR_OK; + } + return ERR_MEM; +} + +/** + * Stop IGMP processing on interface + * + * @param netif network interface on which stop IGMP processing + */ +err_t +igmp_stop(struct netif *netif) +{ + struct igmp_group *group = igmp_group_list; + struct igmp_group *prev = NULL; + struct igmp_group *next; + + /* look for groups joined on this interface further down the list */ + while (group != NULL) { + next = group->next; + /* is it a group joined on this interface? */ + if (group->netif == netif) { + /* is it the first group of the list? */ + if (group == igmp_group_list) { + igmp_group_list = next; + } + /* is there a "previous" group defined? */ + if (prev != NULL) { + prev->next = next; + } + /* disable the group at the MAC level */ + if (netif->igmp_mac_filter != NULL) { + LWIP_DEBUGF(IGMP_DEBUG, ("igmp_stop: igmp_mac_filter(DEL ")); + ip4_addr_debug_print(IGMP_DEBUG, &group->group_address); + LWIP_DEBUGF(IGMP_DEBUG, (") on if %p\n", (void*)netif)); + netif->igmp_mac_filter(netif, &(group->group_address), IGMP_DEL_MAC_FILTER); + } + /* free group */ + memp_free(MEMP_IGMP_GROUP, group); + } else { + /* change the "previous" */ + prev = group; + } + /* move to "next" */ + group = next; + } + return ERR_OK; +} + +/** + * Report IGMP memberships for this interface + * + * @param netif network interface on which report IGMP memberships + */ +void +igmp_report_groups(struct netif *netif) +{ + struct igmp_group *group = igmp_group_list; + + LWIP_DEBUGF(IGMP_DEBUG, ("igmp_report_groups: sending IGMP reports on if %p\n", (void*)netif)); + + while (group != NULL) { + if ((group->netif == netif) && (!(ip4_addr_cmp(&(group->group_address), &allsystems)))) { + igmp_delaying_member(group, IGMP_JOIN_DELAYING_MEMBER_TMR); + } + group = group->next; + } +} + +/** + * Search for a group in the global igmp_group_list + * + * @param ifp the network interface for which to look + * @param addr the group ip address to search for + * @return a struct igmp_group* if the group has been found, + * NULL if the group wasn't found. + */ +struct igmp_group * +igmp_lookfor_group(struct netif *ifp, const ip4_addr_t *addr) +{ + struct igmp_group *group = igmp_group_list; + + while (group != NULL) { + if ((group->netif == ifp) && (ip4_addr_cmp(&(group->group_address), addr))) { + return group; + } + group = group->next; + } + + /* to be clearer, we return NULL here instead of + * 'group' (which is also NULL at this point). + */ + return NULL; +} + +/** + * Search for a specific igmp group and create a new one if not found- + * + * @param ifp the network interface for which to look + * @param addr the group ip address to search + * @return a struct igmp_group*, + * NULL on memory error. + */ +struct igmp_group * +igmp_lookup_group(struct netif *ifp, const ip4_addr_t *addr) +{ + struct igmp_group *group; + /* Search if the group already exists */ + group = igmp_lookfor_group(ifp, addr); + + if (group != NULL) { + /* Group already exists. */ + return group; + } + + /* Group doesn't exist yet, create a new one */ + group = (struct igmp_group *)memp_malloc(MEMP_IGMP_GROUP); + if (group != NULL) { + group->netif = ifp; + ip4_addr_set(&(group->group_address), addr); + group->timer = 0; /* Not running */ + group->group_state = IGMP_GROUP_NON_MEMBER; + group->last_reporter_flag = 0; + group->use = 0; + group->next = igmp_group_list; + + igmp_group_list = group; + } + + LWIP_DEBUGF(IGMP_DEBUG, ("igmp_lookup_group: %sallocated a new group with address ", (group?"":"impossible to "))); + ip4_addr_debug_print(IGMP_DEBUG, addr); + LWIP_DEBUGF(IGMP_DEBUG, (" on if %p\n", (void*)ifp)); + + return group; +} + +/** + * Remove a group in the global igmp_group_list + * + * @param group the group to remove from the global igmp_group_list + * @return ERR_OK if group was removed from the list, an err_t otherwise + */ +static err_t +igmp_remove_group(struct igmp_group *group) +{ + err_t err = ERR_OK; + + /* Is it the first group? */ + if (igmp_group_list == group) { + igmp_group_list = group->next; + } else { + /* look for group further down the list */ + struct igmp_group *tmpGroup; + for (tmpGroup = igmp_group_list; tmpGroup != NULL; tmpGroup = tmpGroup->next) { + if (tmpGroup->next == group) { + tmpGroup->next = group->next; + break; + } + } + /* Group not found in the global igmp_group_list */ + if (tmpGroup == NULL) { + err = ERR_ARG; + } + } + /* free group */ + memp_free(MEMP_IGMP_GROUP, group); + + return err; +} + +/** + * Called from ip_input() if a new IGMP packet is received. + * + * @param p received igmp packet, p->payload pointing to the igmp header + * @param inp network interface on which the packet was received + * @param dest destination ip address of the igmp packet + */ +void +igmp_input(struct pbuf *p, struct netif *inp, const ip4_addr_t *dest) +{ + struct igmp_msg* igmp; + struct igmp_group* group; + struct igmp_group* groupref; + + IGMP_STATS_INC(igmp.recv); + + /* Note that the length CAN be greater than 8 but only 8 are used - All are included in the checksum */ + if (p->len < IGMP_MINLEN) { + pbuf_free(p); + IGMP_STATS_INC(igmp.lenerr); + LWIP_DEBUGF(IGMP_DEBUG, ("igmp_input: length error\n")); + return; + } + + LWIP_DEBUGF(IGMP_DEBUG, ("igmp_input: message from ")); + ip4_addr_debug_print(IGMP_DEBUG, &(ip4_current_header()->src)); + LWIP_DEBUGF(IGMP_DEBUG, (" to address ")); + ip4_addr_debug_print(IGMP_DEBUG, &(ip4_current_header()->dest)); + LWIP_DEBUGF(IGMP_DEBUG, (" on if %p\n", (void*)inp)); + + /* Now calculate and check the checksum */ + igmp = (struct igmp_msg *)p->payload; + if (inet_chksum(igmp, p->len)) { + pbuf_free(p); + IGMP_STATS_INC(igmp.chkerr); + LWIP_DEBUGF(IGMP_DEBUG, ("igmp_input: checksum error\n")); + return; + } + + /* Packet is ok so find an existing group */ + group = igmp_lookfor_group(inp, dest); /* use the destination IP address of incoming packet */ + + /* If group can be found or create... */ + if (!group) { + pbuf_free(p); + IGMP_STATS_INC(igmp.drop); + LWIP_DEBUGF(IGMP_DEBUG, ("igmp_input: IGMP frame not for us\n")); + return; + } + + /* NOW ACT ON THE INCOMING MESSAGE TYPE... */ + switch (igmp->igmp_msgtype) { + case IGMP_MEMB_QUERY: + /* IGMP_MEMB_QUERY to the "all systems" address ? */ + if ((ip4_addr_cmp(dest, &allsystems)) && ip4_addr_isany(&igmp->igmp_group_address)) { + /* THIS IS THE GENERAL QUERY */ + LWIP_DEBUGF(IGMP_DEBUG, ("igmp_input: General IGMP_MEMB_QUERY on \"ALL SYSTEMS\" address (224.0.0.1) [igmp_maxresp=%i]\n", (int)(igmp->igmp_maxresp))); + + if (igmp->igmp_maxresp == 0) { + IGMP_STATS_INC(igmp.rx_v1); + LWIP_DEBUGF(IGMP_DEBUG, ("igmp_input: got an all hosts query with time== 0 - this is V1 and not implemented - treat as v2\n")); + igmp->igmp_maxresp = IGMP_V1_DELAYING_MEMBER_TMR; + } else { + IGMP_STATS_INC(igmp.rx_general); + } + + groupref = igmp_group_list; + while (groupref) { + /* Do not send messages on the all systems group address! */ + if ((groupref->netif == inp) && (!(ip4_addr_cmp(&(groupref->group_address), &allsystems)))) { + igmp_delaying_member(groupref, igmp->igmp_maxresp); + } + groupref = groupref->next; + } + } else { + /* IGMP_MEMB_QUERY to a specific group ? */ + if (!ip4_addr_isany(&igmp->igmp_group_address)) { + LWIP_DEBUGF(IGMP_DEBUG, ("igmp_input: IGMP_MEMB_QUERY to a specific group ")); + ip4_addr_debug_print(IGMP_DEBUG, &igmp->igmp_group_address); + if (ip4_addr_cmp(dest, &allsystems)) { + ip4_addr_t groupaddr; + LWIP_DEBUGF(IGMP_DEBUG, (" using \"ALL SYSTEMS\" address (224.0.0.1) [igmp_maxresp=%i]\n", (int)(igmp->igmp_maxresp))); + /* we first need to re-look for the group since we used dest last time */ + ip4_addr_copy(groupaddr, igmp->igmp_group_address); + group = igmp_lookfor_group(inp, &groupaddr); + } else { + LWIP_DEBUGF(IGMP_DEBUG, (" with the group address as destination [igmp_maxresp=%i]\n", (int)(igmp->igmp_maxresp))); + } + + if (group != NULL) { + IGMP_STATS_INC(igmp.rx_group); + igmp_delaying_member(group, igmp->igmp_maxresp); + } else { + IGMP_STATS_INC(igmp.drop); + } + } else { + IGMP_STATS_INC(igmp.proterr); + } + } + break; + case IGMP_V2_MEMB_REPORT: + LWIP_DEBUGF(IGMP_DEBUG, ("igmp_input: IGMP_V2_MEMB_REPORT\n")); + IGMP_STATS_INC(igmp.rx_report); + if (group->group_state == IGMP_GROUP_DELAYING_MEMBER) { + /* This is on a specific group we have already looked up */ + group->timer = 0; /* stopped */ + group->group_state = IGMP_GROUP_IDLE_MEMBER; + group->last_reporter_flag = 0; + } + break; + default: + LWIP_DEBUGF(IGMP_DEBUG, ("igmp_input: unexpected msg %d in state %d on group %p on if %p\n", + igmp->igmp_msgtype, group->group_state, (void*)&group, (void*)group->netif)); + IGMP_STATS_INC(igmp.proterr); + break; + } + + pbuf_free(p); + return; +} + +/** + * Join a group on one network interface. + * + * @param ifaddr ip address of the network interface which should join a new group + * @param groupaddr the ip address of the group which to join + * @return ERR_OK if group was joined on the netif(s), an err_t otherwise + */ +err_t +igmp_joingroup(const ip4_addr_t *ifaddr, const ip4_addr_t *groupaddr) +{ + err_t err = ERR_VAL; /* no matching interface */ + struct netif *netif; + + /* make sure it is multicast address */ + LWIP_ERROR("igmp_joingroup: attempt to join non-multicast address", ip4_addr_ismulticast(groupaddr), return ERR_VAL;); + LWIP_ERROR("igmp_joingroup: attempt to join allsystems address", (!ip4_addr_cmp(groupaddr, &allsystems)), return ERR_VAL;); + + /* loop through netif's */ + netif = netif_list; + while (netif != NULL) { + /* Should we join this interface ? */ + if ((netif->flags & NETIF_FLAG_IGMP) && ((ip4_addr_isany(ifaddr) || ip4_addr_cmp(netif_ip4_addr(netif), ifaddr)))) { + err = igmp_joingroup_netif(netif, groupaddr); + if (err != ERR_OK) { + /* Return an error even if some network interfaces are joined */ + /** @todo undo any other netif already joined */ + return err; + } + } + /* proceed to next network interface */ + netif = netif->next; + } + + return err; +} + +/** + * Join a group on one network interface. + * + * @param netif the network interface which should join a new group + * @param groupaddr the ip address of the group which to join + * @return ERR_OK if group was joined on the netif, an err_t otherwise + */ +err_t +igmp_joingroup_netif(struct netif *netif, const ip4_addr_t *groupaddr) +{ + struct igmp_group *group; + + /* make sure it is multicast address */ + LWIP_ERROR("igmp_joingroup_netif: attempt to join non-multicast address", ip4_addr_ismulticast(groupaddr), return ERR_VAL;); + LWIP_ERROR("igmp_joingroup_netif: attempt to join allsystems address", (!ip4_addr_cmp(groupaddr, &allsystems)), return ERR_VAL;); + + /* make sure it is an igmp-enabled netif */ + LWIP_ERROR("igmp_joingroup_netif: attempt to join on non-IGMP netif", netif->flags & NETIF_FLAG_IGMP, return ERR_VAL;); + + /* find group or create a new one if not found */ + group = igmp_lookup_group(netif, groupaddr); + + if (group != NULL) { + /* This should create a new group, check the state to make sure */ + if (group->group_state != IGMP_GROUP_NON_MEMBER) { + LWIP_DEBUGF(IGMP_DEBUG, ("igmp_joingroup_netif: join to group not in state IGMP_GROUP_NON_MEMBER\n")); + } else { + /* OK - it was new group */ + LWIP_DEBUGF(IGMP_DEBUG, ("igmp_joingroup_netif: join to new group: ")); + ip4_addr_debug_print(IGMP_DEBUG, groupaddr); + LWIP_DEBUGF(IGMP_DEBUG, ("\n")); + + /* If first use of the group, allow the group at the MAC level */ + if ((group->use==0) && (netif->igmp_mac_filter != NULL)) { + LWIP_DEBUGF(IGMP_DEBUG, ("igmp_joingroup_netif: igmp_mac_filter(ADD ")); + ip4_addr_debug_print(IGMP_DEBUG, groupaddr); + LWIP_DEBUGF(IGMP_DEBUG, (") on if %p\n", (void*)netif)); + netif->igmp_mac_filter(netif, groupaddr, IGMP_ADD_MAC_FILTER); + } + + IGMP_STATS_INC(igmp.tx_join); + igmp_send(group, IGMP_V2_MEMB_REPORT); + + igmp_start_timer(group, IGMP_JOIN_DELAYING_MEMBER_TMR); + + /* Need to work out where this timer comes from */ + group->group_state = IGMP_GROUP_DELAYING_MEMBER; + } + /* Increment group use */ + group->use++; + /* Join on this interface */ + return ERR_OK; + } else { + LWIP_DEBUGF(IGMP_DEBUG, ("igmp_joingroup_netif: Not enough memory to join to group\n")); + return ERR_MEM; + } +} + +/** + * Leave a group on one network interface. + * + * @param ifaddr ip address of the network interface which should leave a group + * @param groupaddr the ip address of the group which to leave + * @return ERR_OK if group was left on the netif(s), an err_t otherwise + */ +err_t +igmp_leavegroup(const ip4_addr_t *ifaddr, const ip4_addr_t *groupaddr) +{ + err_t err = ERR_VAL; /* no matching interface */ + struct netif *netif; + + /* make sure it is multicast address */ + LWIP_ERROR("igmp_leavegroup: attempt to leave non-multicast address", ip4_addr_ismulticast(groupaddr), return ERR_VAL;); + LWIP_ERROR("igmp_leavegroup: attempt to leave allsystems address", (!ip4_addr_cmp(groupaddr, &allsystems)), return ERR_VAL;); + + /* loop through netif's */ + netif = netif_list; + while (netif != NULL) { + /* Should we leave this interface ? */ + if ((netif->flags & NETIF_FLAG_IGMP) && ((ip4_addr_isany(ifaddr) || ip4_addr_cmp(netif_ip4_addr(netif), ifaddr)))) { + err_t res = igmp_leavegroup_netif(netif, groupaddr); + if (err != ERR_OK) { + /* Store this result if we have not yet gotten a success */ + err = res; + } + } + /* proceed to next network interface */ + netif = netif->next; + } + + return err; +} + +/** + * Leave a group on one network interface. + * + * @param netif the network interface which should leave a group + * @param groupaddr the ip address of the group which to leave + * @return ERR_OK if group was left on the netif, an err_t otherwise + */ +err_t +igmp_leavegroup_netif(struct netif *netif, const ip4_addr_t *groupaddr) +{ + struct igmp_group *group; + + /* make sure it is multicast address */ + LWIP_ERROR("igmp_leavegroup_netif: attempt to leave non-multicast address", ip4_addr_ismulticast(groupaddr), return ERR_VAL;); + LWIP_ERROR("igmp_leavegroup_netif: attempt to leave allsystems address", (!ip4_addr_cmp(groupaddr, &allsystems)), return ERR_VAL;); + + /* make sure it is an igmp-enabled netif */ + LWIP_ERROR("igmp_leavegroup_netif: attempt to leave on non-IGMP netif", netif->flags & NETIF_FLAG_IGMP, return ERR_VAL;); + + /* find group */ + group = igmp_lookfor_group(netif, groupaddr); + + if (group != NULL) { + /* Only send a leave if the flag is set according to the state diagram */ + LWIP_DEBUGF(IGMP_DEBUG, ("igmp_leavegroup_netif: Leaving group: ")); + ip4_addr_debug_print(IGMP_DEBUG, groupaddr); + LWIP_DEBUGF(IGMP_DEBUG, ("\n")); + + /* If there is no other use of the group */ + if (group->use <= 1) { + /* If we are the last reporter for this group */ + if (group->last_reporter_flag) { + LWIP_DEBUGF(IGMP_DEBUG, ("igmp_leavegroup_netif: sending leaving group\n")); + IGMP_STATS_INC(igmp.tx_leave); + igmp_send(group, IGMP_LEAVE_GROUP); + } + + /* Disable the group at the MAC level */ + if (netif->igmp_mac_filter != NULL) { + LWIP_DEBUGF(IGMP_DEBUG, ("igmp_leavegroup_netif: igmp_mac_filter(DEL ")); + ip4_addr_debug_print(IGMP_DEBUG, groupaddr); + LWIP_DEBUGF(IGMP_DEBUG, (") on if %p\n", (void*)netif)); + netif->igmp_mac_filter(netif, groupaddr, IGMP_DEL_MAC_FILTER); + } + + LWIP_DEBUGF(IGMP_DEBUG, ("igmp_leavegroup_netif: remove group: ")); + ip4_addr_debug_print(IGMP_DEBUG, groupaddr); + LWIP_DEBUGF(IGMP_DEBUG, ("\n")); + + /* Free the group */ + igmp_remove_group(group); + } else { + /* Decrement group use */ + group->use--; + } + return ERR_OK; + } else { + LWIP_DEBUGF(IGMP_DEBUG, ("igmp_leavegroup_netif: not member of group\n")); + return ERR_VAL; + } +} + +/** + * The igmp timer function (both for NO_SYS=1 and =0) + * Should be called every IGMP_TMR_INTERVAL milliseconds (100 ms is default). + */ +void +igmp_tmr(void) +{ + struct igmp_group *group = igmp_group_list; + + while (group != NULL) { + if (group->timer > 0) { + group->timer--; + if (group->timer == 0) { + igmp_timeout(group); + } + } + group = group->next; + } +} + +/** + * Called if a timeout for one group is reached. + * Sends a report for this group. + * + * @param group an igmp_group for which a timeout is reached + */ +static void +igmp_timeout(struct igmp_group *group) +{ + /* If the state is IGMP_GROUP_DELAYING_MEMBER then we send a report for this group + (unless it is the allsystems group) */ + if ((group->group_state == IGMP_GROUP_DELAYING_MEMBER) && + (!(ip4_addr_cmp(&(group->group_address), &allsystems)))) { + LWIP_DEBUGF(IGMP_DEBUG, ("igmp_timeout: report membership for group with address ")); + ip4_addr_debug_print(IGMP_DEBUG, &(group->group_address)); + LWIP_DEBUGF(IGMP_DEBUG, (" on if %p\n", (void*)group->netif)); + + IGMP_STATS_INC(igmp.tx_report); + igmp_send(group, IGMP_V2_MEMB_REPORT); + } +} + +/** + * Start a timer for an igmp group + * + * @param group the igmp_group for which to start a timer + * @param max_time the time in multiples of IGMP_TMR_INTERVAL (decrease with + * every call to igmp_tmr()) + */ +static void +igmp_start_timer(struct igmp_group *group, u8_t max_time) +{ +#ifdef LWIP_RAND + group->timer = max_time > 2 ? (LWIP_RAND() % max_time) : 1; +#else /* LWIP_RAND */ + /* ATTENTION: use this only if absolutely necessary! */ + group->timer = max_time / 2; +#endif /* LWIP_RAND */ + + if (group->timer == 0) { + group->timer = 1; + } +} + +/** + * Delaying membership report for a group if necessary + * + * @param group the igmp_group for which "delaying" membership report + * @param maxresp query delay + */ +static void +igmp_delaying_member(struct igmp_group *group, u8_t maxresp) +{ + if ((group->group_state == IGMP_GROUP_IDLE_MEMBER) || + ((group->group_state == IGMP_GROUP_DELAYING_MEMBER) && + ((group->timer == 0) || (maxresp < group->timer)))) { + igmp_start_timer(group, maxresp); + group->group_state = IGMP_GROUP_DELAYING_MEMBER; + } +} + + +/** + * Sends an IP packet on a network interface. This function constructs the IP header + * and calculates the IP header checksum. If the source IP address is NULL, + * the IP address of the outgoing network interface is filled in as source address. + * + * @param p the packet to send (p->payload points to the data, e.g. next + protocol header; if dest == IP_HDRINCL, p already includes an IP + header and p->payload points to that IP header) + * @param src the source IP address to send from (if src == IP_ADDR_ANY, the + * IP address of the netif used to send is used as source address) + * @param dest the destination IP address to send the packet to + * @param ttl the TTL value to be set in the IP header + * @param proto the PROTOCOL to be set in the IP header + * @param netif the netif on which to send this packet + * @return ERR_OK if the packet was sent OK + * ERR_BUF if p doesn't have enough space for IP/LINK headers + * returns errors returned by netif->output + */ +static err_t +igmp_ip_output_if(struct pbuf *p, const ip4_addr_t *src, const ip4_addr_t *dest, struct netif *netif) +{ + /* This is the "router alert" option */ + u16_t ra[2]; + ra[0] = PP_HTONS(ROUTER_ALERT); + ra[1] = 0x0000; /* Router shall examine packet */ + IGMP_STATS_INC(igmp.xmit); + return ip4_output_if_opt(p, src, dest, IGMP_TTL, 0, IP_PROTO_IGMP, netif, ra, ROUTER_ALERTLEN); +} + +/** + * Send an igmp packet to a specific group. + * + * @param group the group to which to send the packet + * @param type the type of igmp packet to send + */ +static void +igmp_send(struct igmp_group *group, u8_t type) +{ + struct pbuf* p = NULL; + struct igmp_msg* igmp = NULL; + ip4_addr_t src = *IP4_ADDR_ANY; + ip4_addr_t* dest = NULL; + + /* IP header + "router alert" option + IGMP header */ + p = pbuf_alloc(PBUF_TRANSPORT, IGMP_MINLEN, PBUF_RAM); + + if (p) { + igmp = (struct igmp_msg *)p->payload; + LWIP_ASSERT("igmp_send: check that first pbuf can hold struct igmp_msg", + (p->len >= sizeof(struct igmp_msg))); + ip4_addr_copy(src, *netif_ip4_addr(group->netif)); + + if (type == IGMP_V2_MEMB_REPORT) { + dest = &(group->group_address); + ip4_addr_copy(igmp->igmp_group_address, group->group_address); + group->last_reporter_flag = 1; /* Remember we were the last to report */ + } else { + if (type == IGMP_LEAVE_GROUP) { + dest = &allrouters; + ip4_addr_copy(igmp->igmp_group_address, group->group_address); + } + } + + if ((type == IGMP_V2_MEMB_REPORT) || (type == IGMP_LEAVE_GROUP)) { + igmp->igmp_msgtype = type; + igmp->igmp_maxresp = 0; + igmp->igmp_checksum = 0; + igmp->igmp_checksum = inet_chksum(igmp, IGMP_MINLEN); + + igmp_ip_output_if(p, &src, dest, group->netif); + } + + pbuf_free(p); + } else { + LWIP_DEBUGF(IGMP_DEBUG, ("igmp_send: not enough memory for igmp_send\n")); + IGMP_STATS_INC(igmp.memerr); + } +} + +#endif /* LWIP_IPV4 && LWIP_IGMP */ diff --git a/components/lwip/core/ipv4/ip4.c b/components/lwip/core/ipv4/ip4.c new file mode 100755 index 0000000000..5f1e77a5e7 --- /dev/null +++ b/components/lwip/core/ipv4/ip4.c @@ -0,0 +1,1085 @@ +/** + * @file + * This is the IPv4 layer implementation for incoming and outgoing IP traffic. + * + * @see ip_frag.c + * + */ + +/* + * Copyright (c) 2001-2004 Swedish Institute of Computer Science. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + * + */ + +#include "lwip/opt.h" + +#if LWIP_IPV4 + +#include "lwip/ip.h" +#include "lwip/def.h" +#include "lwip/mem.h" +#include "lwip/ip_frag.h" +#include "lwip/inet_chksum.h" +#include "lwip/netif.h" +#include "lwip/icmp.h" +#include "lwip/igmp.h" +#include "lwip/raw.h" +#include "lwip/udp.h" +#include "lwip/priv/tcp_priv.h" +#include "lwip/dhcp.h" +#include "lwip/autoip.h" +#include "lwip/stats.h" + +#include + +#ifdef MEMLEAK_DEBUG +static const char mem_debug_file[] ICACHE_RODATA_ATTR STORE_ATTR = __FILE__; +#endif + + +/** Set this to 0 in the rare case of wanting to call an extra function to + * generate the IP checksum (in contrast to calculating it on-the-fly). */ +#ifndef LWIP_INLINE_IP_CHKSUM +#if LWIP_CHECKSUM_CTRL_PER_NETIF +#define LWIP_INLINE_IP_CHKSUM 0 +#else /* LWIP_CHECKSUM_CTRL_PER_NETIF */ +#define LWIP_INLINE_IP_CHKSUM 1 +#endif /* LWIP_CHECKSUM_CTRL_PER_NETIF */ +#endif + +#if LWIP_INLINE_IP_CHKSUM && CHECKSUM_GEN_IP +#define CHECKSUM_GEN_IP_INLINE 1 +#else +#define CHECKSUM_GEN_IP_INLINE 0 +#endif + +#if LWIP_DHCP || defined(LWIP_IP_ACCEPT_UDP_PORT) +#define IP_ACCEPT_LINK_LAYER_ADDRESSING 1 + +/** Some defines for DHCP to let link-layer-addressed packets through while the + * netif is down. + * To use this in your own application/protocol, define LWIP_IP_ACCEPT_UDP_PORT(port) + * to return 1 if the port is accepted and 0 if the port is not accepted. + */ +#if LWIP_DHCP && defined(LWIP_IP_ACCEPT_UDP_PORT) +/* accept DHCP client port and custom port */ +#define IP_ACCEPT_LINK_LAYER_ADDRESSED_PORT(port) (((port) == PP_NTOHS(DHCP_CLIENT_PORT)) \ + || (LWIP_IP_ACCEPT_UDP_PORT(port))) +#elif defined(LWIP_IP_ACCEPT_UDP_PORT) /* LWIP_DHCP && defined(LWIP_IP_ACCEPT_UDP_PORT) */ +/* accept custom port only */ +#define IP_ACCEPT_LINK_LAYER_ADDRESSED_PORT(port) (LWIP_IP_ACCEPT_UDP_PORT(port)) +#else /* LWIP_DHCP && defined(LWIP_IP_ACCEPT_UDP_PORT) */ +/* accept DHCP client port only */ +#define IP_ACCEPT_LINK_LAYER_ADDRESSED_PORT(port) ((port) == PP_NTOHS(DHCP_CLIENT_PORT)) +#endif /* LWIP_DHCP && defined(LWIP_IP_ACCEPT_UDP_PORT) */ + +#else /* LWIP_DHCP */ +#define IP_ACCEPT_LINK_LAYER_ADDRESSING 0 +#endif /* LWIP_DHCP */ + +/** The IP header ID of the next outgoing IP packet */ +static u16_t ip_id; + +#if LWIP_MULTICAST_TX_OPTIONS +/** The default netif used for multicast */ +static struct netif* ip4_default_multicast_netif; + +/** Set a default netif for IPv4 multicast. */ +void +ip4_set_default_multicast_netif(struct netif* default_multicast_netif) +{ + ip4_default_multicast_netif = default_multicast_netif; +} +#endif /* LWIP_MULTICAST_TX_OPTIONS */ + +#ifdef LWIP_HOOK_IP4_ROUTE_SRC +/** + * Source based IPv4 routing must be fully implemented in + * LWIP_HOOK_IP4_ROUTE_SRC(). This function only provides he parameters. + */ +struct netif * +ip4_route_src(const ip4_addr_t *dest, const ip4_addr_t *src) +{ + if (src != NULL) { + /* when src==NULL, the hook is called from ip4_route(dest) */ + struct netif *netif = LWIP_HOOK_IP4_ROUTE_SRC(dest, src); + if (netif != NULL) { + return netif; + } + } + return ip4_route(dest); +} +#endif /* LWIP_HOOK_IP4_ROUTE_SRC */ + +/** + * Finds the appropriate network interface for a given IP address. It + * searches the list of network interfaces linearly. A match is found + * if the masked IP address of the network interface equals the masked + * IP address given to the function. + * + * @param dest the destination IP address for which to find the route + * @return the netif on which to send to reach dest + */ +struct netif * +ip4_route(const ip4_addr_t *dest) +{ +#ifdef LWIP_ESP8266 + struct netif *non_default_netif = NULL; +#endif + struct netif *netif; + +#if LWIP_MULTICAST_TX_OPTIONS + /* Use administratively selected interface for multicast by default */ + if (ip4_addr_ismulticast(dest) && ip4_default_multicast_netif) { + return ip4_default_multicast_netif; + } +#endif /* LWIP_MULTICAST_TX_OPTIONS */ + + /* iterate through netifs */ + for (netif = netif_list; netif != NULL; netif = netif->next) { + /* is the netif up, does it have a link and a valid address? */ + if (netif_is_up(netif) && netif_is_link_up(netif) && !ip4_addr_isany_val(*netif_ip4_addr(netif))) { + /* network mask matches? */ + if (ip4_addr_netcmp(dest, netif_ip4_addr(netif), netif_ip4_netmask(netif))) { + /* return netif on which to forward IP packet */ + return netif; + } + /* gateway matches on a non broadcast interface? (i.e. peer in a point to point interface) */ + if (((netif->flags & NETIF_FLAG_BROADCAST) == 0) && ip4_addr_cmp(dest, netif_ip4_gw(netif))) { + /* return netif on which to forward IP packet */ + return netif; + } + + if (netif != netif_default){ + non_default_netif = netif; + } + } + } + +#ifdef LWIP_ESP8266 + if (non_default_netif && !ip4_addr_isbroadcast(dest, non_default_netif)){ + return non_default_netif; + } +#endif + +#if LWIP_NETIF_LOOPBACK && !LWIP_HAVE_LOOPIF + /* loopif is disabled, looopback traffic is passed through any netif */ + if (ip4_addr_isloopback(dest)) { + /* don't check for link on loopback traffic */ + if (netif_is_up(netif_default)) { + return netif_default; + } + /* default netif is not up, just use any netif for loopback traffic */ + for (netif = netif_list; netif != NULL; netif = netif->next) { + if (netif_is_up(netif)) { + return netif; + } + } + return NULL; + } +#endif /* LWIP_NETIF_LOOPBACK && !LWIP_HAVE_LOOPIF */ + +#ifdef LWIP_HOOK_IP4_ROUTE_SRC + netif = LWIP_HOOK_IP4_ROUTE_SRC(dest, NULL); + if (netif != NULL) { + return netif; + } +#elif defined(LWIP_HOOK_IP4_ROUTE) + netif = LWIP_HOOK_IP4_ROUTE(dest); + if (netif != NULL) { + return netif; + } +#endif + + if ((netif_default == NULL) || !netif_is_up(netif_default) || !netif_is_link_up(netif_default) || + ip4_addr_isany_val(*netif_ip4_addr(netif_default))) { + /* No matching netif found and default netif is not usable. + If this is not good enough for you, use LWIP_HOOK_IP4_ROUTE() */ + LWIP_DEBUGF(IP_DEBUG | LWIP_DBG_LEVEL_SERIOUS, ("ip4_route: No route to %"U16_F".%"U16_F".%"U16_F".%"U16_F"\n", + ip4_addr1_16(dest), ip4_addr2_16(dest), ip4_addr3_16(dest), ip4_addr4_16(dest))); + IP_STATS_INC(ip.rterr); + MIB2_STATS_INC(mib2.ipoutnoroutes); + return NULL; + } + + return netif_default; +} + +#if IP_FORWARD +/** + * Determine whether an IP address is in a reserved set of addresses + * that may not be forwarded, or whether datagrams to that destination + * may be forwarded. + * @param p the packet to forward + * @param dest the destination IP address + * @return 1: can forward 0: discard + */ +static int +ip4_canforward(struct pbuf *p) +{ + u32_t addr = htonl(ip4_addr_get_u32(ip4_current_dest_addr())); + + if (p->flags & PBUF_FLAG_LLBCAST) { + /* don't route link-layer broadcasts */ + return 0; + } + if ((p->flags & PBUF_FLAG_LLMCAST) && !IP_MULTICAST(addr)) { + /* don't route link-layer multicasts unless the destination address is an IP + multicast address */ + return 0; + } + if (IP_EXPERIMENTAL(addr)) { + return 0; + } + if (IP_CLASSA(addr)) { + u32_t net = addr & IP_CLASSA_NET; + if ((net == 0) || (net == ((u32_t)IP_LOOPBACKNET << IP_CLASSA_NSHIFT))) { + /* don't route loopback packets */ + return 0; + } + } + return 1; +} + +/** + * Forwards an IP packet. It finds an appropriate route for the + * packet, decrements the TTL value of the packet, adjusts the + * checksum and outputs the packet on the appropriate interface. + * + * @param p the packet to forward (p->payload points to IP header) + * @param iphdr the IP header of the input packet + * @param inp the netif on which this packet was received + */ +static void +ip4_forward(struct pbuf *p, struct ip_hdr *iphdr, struct netif *inp) +{ + struct netif *netif; + + PERF_START; + + if (!ip4_canforward(p)) { + goto return_noroute; + } + + /* RFC3927 2.7: do not forward link-local addresses */ + if (ip4_addr_islinklocal(ip4_current_dest_addr())) { + LWIP_DEBUGF(IP_DEBUG, ("ip4_forward: not forwarding LLA %"U16_F".%"U16_F".%"U16_F".%"U16_F"\n", + ip4_addr1_16(ip4_current_dest_addr()), ip4_addr2_16(ip4_current_dest_addr()), + ip4_addr3_16(ip4_current_dest_addr()), ip4_addr4_16(ip4_current_dest_addr()))); + goto return_noroute; + } + + /* Find network interface where to forward this IP packet to. */ + netif = ip4_route_src(ip4_current_dest_addr(), ip4_current_src_addr()); + if (netif == NULL) { + LWIP_DEBUGF(IP_DEBUG, ("ip4_forward: no forwarding route for %"U16_F".%"U16_F".%"U16_F".%"U16_F" found\n", + ip4_addr1_16(ip4_current_dest_addr()), ip4_addr2_16(ip4_current_dest_addr()), + ip4_addr3_16(ip4_current_dest_addr()), ip4_addr4_16(ip4_current_dest_addr()))); + /* @todo: send ICMP_DUR_NET? */ + goto return_noroute; + } +#if !IP_FORWARD_ALLOW_TX_ON_RX_NETIF + /* Do not forward packets onto the same network interface on which + * they arrived. */ + if (netif == inp) { + LWIP_DEBUGF(IP_DEBUG, ("ip4_forward: not bouncing packets back on incoming interface.\n")); + goto return_noroute; + } +#endif /* IP_FORWARD_ALLOW_TX_ON_RX_NETIF */ + + /* decrement TTL */ + IPH_TTL_SET(iphdr, IPH_TTL(iphdr) - 1); + /* send ICMP if TTL == 0 */ + if (IPH_TTL(iphdr) == 0) { + MIB2_STATS_INC(mib2.ipinhdrerrors); +#if LWIP_ICMP + /* Don't send ICMP messages in response to ICMP messages */ + if (IPH_PROTO(iphdr) != IP_PROTO_ICMP) { + icmp_time_exceeded(p, ICMP_TE_TTL); + } +#endif /* LWIP_ICMP */ + return; + } + + /* Incrementally update the IP checksum. */ + if (IPH_CHKSUM(iphdr) >= PP_HTONS(0xffffU - 0x100)) { + IPH_CHKSUM_SET(iphdr, IPH_CHKSUM(iphdr) + PP_HTONS(0x100) + 1); + } else { + IPH_CHKSUM_SET(iphdr, IPH_CHKSUM(iphdr) + PP_HTONS(0x100)); + } + + LWIP_DEBUGF(IP_DEBUG, ("ip4_forward: forwarding packet to %"U16_F".%"U16_F".%"U16_F".%"U16_F"\n", + ip4_addr1_16(ip4_current_dest_addr()), ip4_addr2_16(ip4_current_dest_addr()), + ip4_addr3_16(ip4_current_dest_addr()), ip4_addr4_16(ip4_current_dest_addr()))); + + IP_STATS_INC(ip.fw); + MIB2_STATS_INC(mib2.ipforwdatagrams); + IP_STATS_INC(ip.xmit); + + PERF_STOP("ip4_forward"); + /* don't fragment if interface has mtu set to 0 [loopif] */ + if (netif->mtu && (p->tot_len > netif->mtu)) { + if ((IPH_OFFSET(iphdr) & PP_NTOHS(IP_DF)) == 0) { +#if IP_FRAG + ip4_frag(p, netif, ip4_current_dest_addr()); +#else /* IP_FRAG */ + /* @todo: send ICMP Destination Unreachable code 13 "Communication administratively prohibited"? */ +#endif /* IP_FRAG */ + } else { +#if LWIP_ICMP + /* send ICMP Destination Unreachable code 4: "Fragmentation Needed and DF Set" */ + icmp_dest_unreach(p, ICMP_DUR_FRAG); +#endif /* LWIP_ICMP */ + } + return; + } + /* transmit pbuf on chosen interface */ + netif->output(netif, p, ip4_current_dest_addr()); + return; +return_noroute: + MIB2_STATS_INC(mib2.ipoutnoroutes); +} +#endif /* IP_FORWARD */ + +/** + * This function is called by the network interface device driver when + * an IP packet is received. The function does the basic checks of the + * IP header such as packet size being at least larger than the header + * size etc. If the packet was not destined for us, the packet is + * forwarded (using ip_forward). The IP checksum is always checked. + * + * Finally, the packet is sent to the upper layer protocol input function. + * + * @param p the received IP packet (p->payload points to IP header) + * @param inp the netif on which this packet was received + * @return ERR_OK if the packet was processed (could return ERR_* if it wasn't + * processed, but currently always returns ERR_OK) + */ +err_t +ip4_input(struct pbuf *p, struct netif *inp) +{ + struct ip_hdr *iphdr; + struct netif *netif; + u16_t iphdr_hlen; + u16_t iphdr_len; +#if IP_ACCEPT_LINK_LAYER_ADDRESSING || LWIP_IGMP + int check_ip_src = 1; +#endif /* IP_ACCEPT_LINK_LAYER_ADDRESSING || LWIP_IGMP */ + + IP_STATS_INC(ip.recv); + MIB2_STATS_INC(mib2.ipinreceives); + + /* identify the IP header */ + iphdr = (struct ip_hdr *)p->payload; + if (IPH_V(iphdr) != 4) { + LWIP_DEBUGF(IP_DEBUG | LWIP_DBG_LEVEL_WARNING, ("IP packet dropped due to bad version number %"U16_F"\n", IPH_V(iphdr))); + ip4_debug_print(p); + pbuf_free(p); + IP_STATS_INC(ip.err); + IP_STATS_INC(ip.drop); + MIB2_STATS_INC(mib2.ipinhdrerrors); + return ERR_OK; + } + +#ifdef LWIP_HOOK_IP4_INPUT + if (LWIP_HOOK_IP4_INPUT(p, inp)) { + /* the packet has been eaten */ + return ERR_OK; + } +#endif + + /* obtain IP header length in number of 32-bit words */ + iphdr_hlen = IPH_HL(iphdr); + /* calculate IP header length in bytes */ + iphdr_hlen *= 4; + /* obtain ip length in bytes */ + iphdr_len = ntohs(IPH_LEN(iphdr)); + + /* Trim pbuf. This is especially required for packets < 60 bytes. */ + if (iphdr_len < p->tot_len) { + pbuf_realloc(p, iphdr_len); + } + + /* header length exceeds first pbuf length, or ip length exceeds total pbuf length? */ + if ((iphdr_hlen > p->len) || (iphdr_len > p->tot_len)) { + if (iphdr_hlen > p->len) { + LWIP_DEBUGF(IP_DEBUG | LWIP_DBG_LEVEL_SERIOUS, + ("IP header (len %"U16_F") does not fit in first pbuf (len %"U16_F"), IP packet dropped.\n", + iphdr_hlen, p->len)); + } + if (iphdr_len > p->tot_len) { + LWIP_DEBUGF(IP_DEBUG | LWIP_DBG_LEVEL_SERIOUS, + ("IP (len %"U16_F") is longer than pbuf (len %"U16_F"), IP packet dropped.\n", + iphdr_len, p->tot_len)); + } + /* free (drop) packet pbufs */ + pbuf_free(p); + IP_STATS_INC(ip.lenerr); + IP_STATS_INC(ip.drop); + MIB2_STATS_INC(mib2.ipindiscards); + return ERR_OK; + } + + /* verify checksum */ +#if CHECKSUM_CHECK_IP + IF__NETIF_CHECKSUM_ENABLED(inp, NETIF_CHECKSUM_CHECK_IP) { + if (inet_chksum(iphdr, iphdr_hlen) != 0) { + + LWIP_DEBUGF(IP_DEBUG | LWIP_DBG_LEVEL_SERIOUS, + ("Checksum (0x%"X16_F") failed, IP packet dropped.\n", inet_chksum(iphdr, iphdr_hlen))); + ip4_debug_print(p); + pbuf_free(p); + IP_STATS_INC(ip.chkerr); + IP_STATS_INC(ip.drop); + MIB2_STATS_INC(mib2.ipinhdrerrors); + return ERR_OK; + } + } +#endif + + /* copy IP addresses to aligned ip_addr_t */ + ip_addr_copy_from_ip4(ip_data.current_iphdr_dest, iphdr->dest); + ip_addr_copy_from_ip4(ip_data.current_iphdr_src, iphdr->src); + + /* match packet against an interface, i.e. is this packet for us? */ + if (ip4_addr_ismulticast(ip4_current_dest_addr())) { +#if LWIP_IGMP + if ((inp->flags & NETIF_FLAG_IGMP) && (igmp_lookfor_group(inp, ip4_current_dest_addr()))) { + /* IGMP snooping switches need 0.0.0.0 to be allowed as source address (RFC 4541) */ + ip4_addr_t allsystems; + IP4_ADDR(&allsystems, 224, 0, 0, 1); + if (ip4_addr_cmp(ip4_current_dest_addr(), &allsystems) && + ip4_addr_isany(ip4_current_src_addr())) { + check_ip_src = 0; + } + netif = inp; + } else { + netif = NULL; + } +#else /* LWIP_IGMP */ + if ((netif_is_up(inp)) && (!ip4_addr_isany_val(*netif_ip4_addr(inp)))) { + netif = inp; + } else { + netif = NULL; + } +#endif /* LWIP_IGMP */ + } else { + /* start trying with inp. if that's not acceptable, start walking the + list of configured netifs. + 'first' is used as a boolean to mark whether we started walking the list */ + int first = 1; + netif = inp; + do { + LWIP_DEBUGF(IP_DEBUG, ("ip_input: iphdr->dest 0x%"X32_F" netif->ip_addr 0x%"X32_F" (0x%"X32_F", 0x%"X32_F", 0x%"X32_F")\n", + ip4_addr_get_u32(&iphdr->dest), ip4_addr_get_u32(netif_ip4_addr(netif)), + ip4_addr_get_u32(&iphdr->dest) & ip4_addr_get_u32(netif_ip4_netmask(netif)), + ip4_addr_get_u32(netif_ip4_addr(netif)) & ip4_addr_get_u32(netif_ip4_netmask(netif)), + ip4_addr_get_u32(&iphdr->dest) & ~ip4_addr_get_u32(netif_ip4_netmask(netif)))); + + /* interface is up and configured? */ + if ((netif_is_up(netif)) && (!ip4_addr_isany_val(*netif_ip4_addr(netif)))) { + /* unicast to this interface address? */ + if (ip4_addr_cmp(ip4_current_dest_addr(), netif_ip4_addr(netif)) || + /* or broadcast on this interface network address? */ + ip4_addr_isbroadcast(ip4_current_dest_addr(), netif) +#if LWIP_NETIF_LOOPBACK && !LWIP_HAVE_LOOPIF + || (ip4_addr_get_u32(ip4_current_dest_addr()) == PP_HTONL(IPADDR_LOOPBACK)) +#endif /* LWIP_NETIF_LOOPBACK && !LWIP_HAVE_LOOPIF */ + ) { + LWIP_DEBUGF(IP_DEBUG, ("ip4_input: packet accepted on interface %c%c\n", + netif->name[0], netif->name[1])); + /* break out of for loop */ + break; + } +#if LWIP_AUTOIP + /* connections to link-local addresses must persist after changing + the netif's address (RFC3927 ch. 1.9) */ + if ((netif->autoip != NULL) && + ip4_addr_cmp(ip4_current_dest_addr(), &(netif->autoip->llipaddr))) { + LWIP_DEBUGF(IP_DEBUG, ("ip4_input: LLA packet accepted on interface %c%c\n", + netif->name[0], netif->name[1])); + /* break out of for loop */ + break; + } +#endif /* LWIP_AUTOIP */ + } + if (first) { + first = 0; + netif = netif_list; + } else { + netif = netif->next; + } + if (netif == inp) { + netif = netif->next; + } + } while (netif != NULL); + } + +#if IP_ACCEPT_LINK_LAYER_ADDRESSING + /* Pass DHCP messages regardless of destination address. DHCP traffic is addressed + * using link layer addressing (such as Ethernet MAC) so we must not filter on IP. + * According to RFC 1542 section 3.1.1, referred by RFC 2131). + * + * If you want to accept private broadcast communication while a netif is down, + * define LWIP_IP_ACCEPT_UDP_PORT(dst_port), e.g.: + * + * #define LWIP_IP_ACCEPT_UDP_PORT(dst_port) ((dst_port) == PP_NTOHS(12345)) + */ + if (netif == NULL) { + /* remote port is DHCP server? */ + if (IPH_PROTO(iphdr) == IP_PROTO_UDP) { + struct udp_hdr *udphdr = (struct udp_hdr *)((u8_t *)iphdr + iphdr_hlen); + LWIP_DEBUGF(IP_DEBUG | LWIP_DBG_TRACE, ("ip4_input: UDP packet to DHCP client port %"U16_F"\n", + ntohs(udphdr->dest))); + if (IP_ACCEPT_LINK_LAYER_ADDRESSED_PORT(udphdr->dest)) { + LWIP_DEBUGF(IP_DEBUG | LWIP_DBG_TRACE, ("ip4_input: DHCP packet accepted.\n")); + netif = inp; + check_ip_src = 0; + } + } + } +#endif /* IP_ACCEPT_LINK_LAYER_ADDRESSING */ + + /* broadcast or multicast packet source address? Compliant with RFC 1122: 3.2.1.3 */ +#if LWIP_IGMP || IP_ACCEPT_LINK_LAYER_ADDRESSING + if (check_ip_src +#if IP_ACCEPT_LINK_LAYER_ADDRESSING + /* DHCP servers need 0.0.0.0 to be allowed as source address (RFC 1.1.2.2: 3.2.1.3/a) */ + && !ip4_addr_isany_val(*ip4_current_src_addr()) +#endif /* IP_ACCEPT_LINK_LAYER_ADDRESSING */ + ) +#endif /* LWIP_IGMP || IP_ACCEPT_LINK_LAYER_ADDRESSING */ + { + if ((ip4_addr_isbroadcast(ip4_current_src_addr(), inp)) || + (ip4_addr_ismulticast(ip4_current_src_addr()))) { + /* packet source is not valid */ + LWIP_DEBUGF(IP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_WARNING, ("ip4_input: packet source is not valid.\n")); + /* free (drop) packet pbufs */ + pbuf_free(p); + IP_STATS_INC(ip.drop); + MIB2_STATS_INC(mib2.ipinaddrerrors); + MIB2_STATS_INC(mib2.ipindiscards); + return ERR_OK; + } + } + + /* packet not for us? */ + if (netif == NULL) { + /* packet not for us, route or discard */ + LWIP_DEBUGF(IP_DEBUG | LWIP_DBG_TRACE, ("ip4_input: packet not for us.\n")); +#if IP_FORWARD + /* non-broadcast packet? */ + if (!ip4_addr_isbroadcast(ip4_current_dest_addr(), inp)) { + /* try to forward IP packet on (other) interfaces */ + ip4_forward(p, iphdr, inp); + } else +#endif /* IP_FORWARD */ + { + MIB2_STATS_INC(mib2.ipinaddrerrors); + MIB2_STATS_INC(mib2.ipindiscards); + } + pbuf_free(p); + return ERR_OK; + } + /* packet consists of multiple fragments? */ + if ((IPH_OFFSET(iphdr) & PP_HTONS(IP_OFFMASK | IP_MF)) != 0) { +#if IP_REASSEMBLY /* packet fragment reassembly code present? */ + LWIP_DEBUGF(IP_DEBUG, ("IP packet is a fragment (id=0x%04"X16_F" tot_len=%"U16_F" len=%"U16_F" MF=%"U16_F" offset=%"U16_F"), calling ip4_reass()\n", + ntohs(IPH_ID(iphdr)), p->tot_len, ntohs(IPH_LEN(iphdr)), !!(IPH_OFFSET(iphdr) & PP_HTONS(IP_MF)), (ntohs(IPH_OFFSET(iphdr)) & IP_OFFMASK)*8)); + /* reassemble the packet*/ + p = ip4_reass(p); + /* packet not fully reassembled yet? */ + if (p == NULL) { + return ERR_OK; + } + iphdr = (struct ip_hdr *)p->payload; +#else /* IP_REASSEMBLY == 0, no packet fragment reassembly code present */ + pbuf_free(p); + LWIP_DEBUGF(IP_DEBUG | LWIP_DBG_LEVEL_SERIOUS, ("IP packet dropped since it was fragmented (0x%"X16_F") (while IP_REASSEMBLY == 0).\n", + ntohs(IPH_OFFSET(iphdr)))); + IP_STATS_INC(ip.opterr); + IP_STATS_INC(ip.drop); + /* unsupported protocol feature */ + MIB2_STATS_INC(mib2.ipinunknownprotos); + return ERR_OK; +#endif /* IP_REASSEMBLY */ + } + +#if IP_OPTIONS_ALLOWED == 0 /* no support for IP options in the IP header? */ + +#if LWIP_IGMP + /* there is an extra "router alert" option in IGMP messages which we allow for but do not police */ + if ((iphdr_hlen > IP_HLEN) && (IPH_PROTO(iphdr) != IP_PROTO_IGMP)) { +#else + if (iphdr_hlen > IP_HLEN) { +#endif /* LWIP_IGMP */ + LWIP_DEBUGF(IP_DEBUG | LWIP_DBG_LEVEL_SERIOUS, ("IP packet dropped since there were IP options (while IP_OPTIONS_ALLOWED == 0).\n")); + pbuf_free(p); + IP_STATS_INC(ip.opterr); + IP_STATS_INC(ip.drop); + /* unsupported protocol feature */ + MIB2_STATS_INC(mib2.ipinunknownprotos); + return ERR_OK; + } +#endif /* IP_OPTIONS_ALLOWED == 0 */ + + /* send to upper layers */ + LWIP_DEBUGF(IP_DEBUG, ("ip4_input: \n")); + ip4_debug_print(p); + LWIP_DEBUGF(IP_DEBUG, ("ip4_input: p->len %"U16_F" p->tot_len %"U16_F"\n", p->len, p->tot_len)); + + ip_data.current_netif = netif; + ip_data.current_input_netif = inp; + ip_data.current_ip4_header = iphdr; + ip_data.current_ip_header_tot_len = IPH_HL(iphdr) * 4; + +#if LWIP_RAW + /* raw input did not eat the packet? */ + if (raw_input(p, inp) == 0) +#endif /* LWIP_RAW */ + { + pbuf_header(p, -(s16_t)iphdr_hlen); /* Move to payload, no check necessary. */ + + switch (IPH_PROTO(iphdr)) { +#if LWIP_UDP + case IP_PROTO_UDP: +#if LWIP_UDPLITE + case IP_PROTO_UDPLITE: +#endif /* LWIP_UDPLITE */ + MIB2_STATS_INC(mib2.ipindelivers); + udp_input(p, inp); + break; +#endif /* LWIP_UDP */ +#if LWIP_TCP + case IP_PROTO_TCP: + MIB2_STATS_INC(mib2.ipindelivers); + tcp_input(p, inp); + break; +#endif /* LWIP_TCP */ +#if LWIP_ICMP + case IP_PROTO_ICMP: + MIB2_STATS_INC(mib2.ipindelivers); + icmp_input(p, inp); + break; +#endif /* LWIP_ICMP */ +#if LWIP_IGMP + case IP_PROTO_IGMP: + igmp_input(p, inp, ip4_current_dest_addr()); + break; +#endif /* LWIP_IGMP */ + default: +#if LWIP_ICMP + /* send ICMP destination protocol unreachable unless is was a broadcast */ + if (!ip4_addr_isbroadcast(ip4_current_dest_addr(), netif) && + !ip4_addr_ismulticast(ip4_current_dest_addr())) { + pbuf_header_force(p, iphdr_hlen); /* Move to ip header, no check necessary. */ + p->payload = iphdr; + icmp_dest_unreach(p, ICMP_DUR_PROTO); + } +#endif /* LWIP_ICMP */ + pbuf_free(p); + + LWIP_DEBUGF(IP_DEBUG | LWIP_DBG_LEVEL_SERIOUS, ("Unsupported transport protocol %"U16_F"\n", IPH_PROTO(iphdr))); + + IP_STATS_INC(ip.proterr); + IP_STATS_INC(ip.drop); + MIB2_STATS_INC(mib2.ipinunknownprotos); + } + } + + /* @todo: this is not really necessary... */ + ip_data.current_netif = NULL; + ip_data.current_input_netif = NULL; + ip_data.current_ip4_header = NULL; + ip_data.current_ip_header_tot_len = 0; + ip4_addr_set_any(ip4_current_src_addr()); + ip4_addr_set_any(ip4_current_dest_addr()); + + return ERR_OK; +} + +/** + * Sends an IP packet on a network interface. This function constructs + * the IP header and calculates the IP header checksum. If the source + * IP address is NULL, the IP address of the outgoing network + * interface is filled in as source address. + * If the destination IP address is IP_HDRINCL, p is assumed to already + * include an IP header and p->payload points to it instead of the data. + * + * @param p the packet to send (p->payload points to the data, e.g. next + protocol header; if dest == IP_HDRINCL, p already includes an IP + header and p->payload points to that IP header) + * @param src the source IP address to send from (if src == IP_ADDR_ANY, the + * IP address of the netif used to send is used as source address) + * @param dest the destination IP address to send the packet to + * @param ttl the TTL value to be set in the IP header + * @param tos the TOS value to be set in the IP header + * @param proto the PROTOCOL to be set in the IP header + * @param netif the netif on which to send this packet + * @return ERR_OK if the packet was sent OK + * ERR_BUF if p doesn't have enough space for IP/LINK headers + * returns errors returned by netif->output + * + * @note ip_id: RFC791 "some host may be able to simply use + * unique identifiers independent of destination" + */ +err_t +ip4_output_if(struct pbuf *p, const ip4_addr_t *src, const ip4_addr_t *dest, + u8_t ttl, u8_t tos, + u8_t proto, struct netif *netif) +{ +#if IP_OPTIONS_SEND + return ip4_output_if_opt(p, src, dest, ttl, tos, proto, netif, NULL, 0); +} + +/** + * Same as ip_output_if() but with the possibility to include IP options: + * + * @ param ip_options pointer to the IP options, copied into the IP header + * @ param optlen length of ip_options + */ +err_t +ip4_output_if_opt(struct pbuf *p, const ip4_addr_t *src, const ip4_addr_t *dest, + u8_t ttl, u8_t tos, u8_t proto, struct netif *netif, void *ip_options, + u16_t optlen) +{ +#endif /* IP_OPTIONS_SEND */ + const ip4_addr_t *src_used = src; + if (dest != IP_HDRINCL) { + if (ip4_addr_isany(src)) { + src_used = netif_ip4_addr(netif); + } + } + +#if IP_OPTIONS_SEND + return ip4_output_if_opt_src(p, src_used, dest, ttl, tos, proto, netif, + ip_options, optlen); +#else /* IP_OPTIONS_SEND */ + return ip4_output_if_src(p, src_used, dest, ttl, tos, proto, netif); +#endif /* IP_OPTIONS_SEND */ +} + +/** + * Same as ip_output_if() but 'src' address is not replaced by netif address + * when it is 'any'. + */ +err_t +ip4_output_if_src(struct pbuf *p, const ip4_addr_t *src, const ip4_addr_t *dest, + u8_t ttl, u8_t tos, + u8_t proto, struct netif *netif) +{ +#if IP_OPTIONS_SEND + return ip4_output_if_opt_src(p, src, dest, ttl, tos, proto, netif, NULL, 0); +} + +/** + * Same as ip_output_if_opt() but 'src' address is not replaced by netif address + * when it is 'any'. + */ +err_t +ip4_output_if_opt_src(struct pbuf *p, const ip4_addr_t *src, const ip4_addr_t *dest, + u8_t ttl, u8_t tos, u8_t proto, struct netif *netif, void *ip_options, + u16_t optlen) +{ +#endif /* IP_OPTIONS_SEND */ + struct ip_hdr *iphdr; + ip4_addr_t dest_addr; +#if CHECKSUM_GEN_IP_INLINE + u32_t chk_sum = 0; +#endif /* CHECKSUM_GEN_IP_INLINE */ + + LWIP_IP_CHECK_PBUF_REF_COUNT_FOR_TX(p); + + MIB2_STATS_INC(mib2.ipoutrequests); + + /* Should the IP header be generated or is it already included in p? */ + if (dest != IP_HDRINCL) { + u16_t ip_hlen = IP_HLEN; +#if IP_OPTIONS_SEND + u16_t optlen_aligned = 0; + if (optlen != 0) { +#if CHECKSUM_GEN_IP_INLINE + int i; +#endif /* CHECKSUM_GEN_IP_INLINE */ + /* round up to a multiple of 4 */ + optlen_aligned = ((optlen + 3) & ~3); + ip_hlen += optlen_aligned; + /* First write in the IP options */ + if (pbuf_header(p, optlen_aligned)) { + LWIP_DEBUGF(IP_DEBUG | LWIP_DBG_LEVEL_SERIOUS, ("ip4_output_if_opt: not enough room for IP options in pbuf\n")); + IP_STATS_INC(ip.err); + MIB2_STATS_INC(mib2.ipoutdiscards); + return ERR_BUF; + } + MEMCPY(p->payload, ip_options, optlen); + if (optlen < optlen_aligned) { + /* zero the remaining bytes */ + memset(((char*)p->payload) + optlen, 0, optlen_aligned - optlen); + } +#if CHECKSUM_GEN_IP_INLINE + for (i = 0; i < optlen_aligned/2; i++) { + chk_sum += ((u16_t*)p->payload)[i]; + } +#endif /* CHECKSUM_GEN_IP_INLINE */ + } +#endif /* IP_OPTIONS_SEND */ + /* generate IP header */ + if (pbuf_header(p, IP_HLEN)) { + LWIP_DEBUGF(IP_DEBUG | LWIP_DBG_LEVEL_SERIOUS, ("ip4_output: not enough room for IP header in pbuf\n")); + + IP_STATS_INC(ip.err); + MIB2_STATS_INC(mib2.ipoutdiscards); + return ERR_BUF; + } + + iphdr = (struct ip_hdr *)p->payload; + LWIP_ASSERT("check that first pbuf can hold struct ip_hdr", + (p->len >= sizeof(struct ip_hdr))); + + IPH_TTL_SET(iphdr, ttl); + IPH_PROTO_SET(iphdr, proto); +#if CHECKSUM_GEN_IP_INLINE + chk_sum += LWIP_MAKE_U16(proto, ttl); +#endif /* CHECKSUM_GEN_IP_INLINE */ + + /* dest cannot be NULL here */ + ip4_addr_copy(iphdr->dest, *dest); +#if CHECKSUM_GEN_IP_INLINE + chk_sum += ip4_addr_get_u32(&iphdr->dest) & 0xFFFF; + chk_sum += ip4_addr_get_u32(&iphdr->dest) >> 16; +#endif /* CHECKSUM_GEN_IP_INLINE */ + + IPH_VHL_SET(iphdr, 4, ip_hlen / 4); + IPH_TOS_SET(iphdr, tos); +#if CHECKSUM_GEN_IP_INLINE + chk_sum += LWIP_MAKE_U16(tos, iphdr->_v_hl); +#endif /* CHECKSUM_GEN_IP_INLINE */ + IPH_LEN_SET(iphdr, htons(p->tot_len)); +#if CHECKSUM_GEN_IP_INLINE + chk_sum += iphdr->_len; +#endif /* CHECKSUM_GEN_IP_INLINE */ + IPH_OFFSET_SET(iphdr, 0); + IPH_ID_SET(iphdr, htons(ip_id)); +#if CHECKSUM_GEN_IP_INLINE + chk_sum += iphdr->_id; +#endif /* CHECKSUM_GEN_IP_INLINE */ + ++ip_id; + + if (src == NULL) { + ip4_addr_copy(iphdr->src, *IP4_ADDR_ANY); + } else { + /* src cannot be NULL here */ + ip4_addr_copy(iphdr->src, *src); + } + +#if CHECKSUM_GEN_IP_INLINE + chk_sum += ip4_addr_get_u32(&iphdr->src) & 0xFFFF; + chk_sum += ip4_addr_get_u32(&iphdr->src) >> 16; + chk_sum = (chk_sum >> 16) + (chk_sum & 0xFFFF); + chk_sum = (chk_sum >> 16) + chk_sum; + chk_sum = ~chk_sum; + IF__NETIF_CHECKSUM_ENABLED(netif, NETIF_CHECKSUM_GEN_IP) { + iphdr->_chksum = (u16_t)chk_sum; /* network order */ + } +#if LWIP_CHECKSUM_CTRL_PER_NETIF + else { + IPH_CHKSUM_SET(iphdr, 0); + } +#endif /* LWIP_CHECKSUM_CTRL_PER_NETIF*/ +#else /* CHECKSUM_GEN_IP_INLINE */ + IPH_CHKSUM_SET(iphdr, 0); +#if CHECKSUM_GEN_IP + IF__NETIF_CHECKSUM_ENABLED(netif, NETIF_CHECKSUM_GEN_IP) { + IPH_CHKSUM_SET(iphdr, inet_chksum(iphdr, ip_hlen)); + } +#endif /* CHECKSUM_GEN_IP */ +#endif /* CHECKSUM_GEN_IP_INLINE */ + } else { + /* IP header already included in p */ + iphdr = (struct ip_hdr *)p->payload; + ip4_addr_copy(dest_addr, iphdr->dest); + dest = &dest_addr; + } + + IP_STATS_INC(ip.xmit); + + LWIP_DEBUGF(IP_DEBUG, ("ip4_output_if: %c%c%"U16_F"\n", netif->name[0], netif->name[1], netif->num)); + ip4_debug_print(p); + +#if ENABLE_LOOPBACK + if (ip4_addr_cmp(dest, netif_ip4_addr(netif)) +#if !LWIP_HAVE_LOOPIF + || ip4_addr_isloopback(dest) +#endif /* !LWIP_HAVE_LOOPIF */ + ) { + /* Packet to self, enqueue it for loopback */ + LWIP_DEBUGF(IP_DEBUG, ("netif_loop_output()")); + return netif_loop_output(netif, p); + } +#if LWIP_MULTICAST_TX_OPTIONS + if ((p->flags & PBUF_FLAG_MCASTLOOP) != 0) { + netif_loop_output(netif, p); + } +#endif /* LWIP_MULTICAST_TX_OPTIONS */ +#endif /* ENABLE_LOOPBACK */ +#if IP_FRAG + /* don't fragment if interface has mtu set to 0 [loopif] */ + if (netif->mtu && (p->tot_len > netif->mtu)) { + return ip4_frag(p, netif, dest); + } +#endif /* IP_FRAG */ + + LWIP_DEBUGF(IP_DEBUG, ("ip4_output_if: call netif->output()\n")); + return netif->output(netif, p, dest); +} + +/** + * Simple interface to ip_output_if. It finds the outgoing network + * interface and calls upon ip_output_if to do the actual work. + * + * @param p the packet to send (p->payload points to the data, e.g. next + protocol header; if dest == IP_HDRINCL, p already includes an IP + header and p->payload points to that IP header) + * @param src the source IP address to send from (if src == IP_ADDR_ANY, the + * IP address of the netif used to send is used as source address) + * @param dest the destination IP address to send the packet to + * @param ttl the TTL value to be set in the IP header + * @param tos the TOS value to be set in the IP header + * @param proto the PROTOCOL to be set in the IP header + * + * @return ERR_RTE if no route is found + * see ip_output_if() for more return values + */ +err_t +ip4_output(struct pbuf *p, const ip4_addr_t *src, const ip4_addr_t *dest, + u8_t ttl, u8_t tos, u8_t proto) +{ + struct netif *netif; + + LWIP_IP_CHECK_PBUF_REF_COUNT_FOR_TX(p); + + if ((netif = ip4_route_src(dest, src)) == NULL) { + LWIP_DEBUGF(IP_DEBUG, ("ip4_output: No route to %"U16_F".%"U16_F".%"U16_F".%"U16_F"\n", + ip4_addr1_16(dest), ip4_addr2_16(dest), ip4_addr3_16(dest), ip4_addr4_16(dest))); + IP_STATS_INC(ip.rterr); + return ERR_RTE; + } + + return ip4_output_if(p, src, dest, ttl, tos, proto, netif); +} + +#if LWIP_NETIF_HWADDRHINT +/** Like ip_output, but takes and addr_hint pointer that is passed on to netif->addr_hint + * before calling ip_output_if. + * + * @param p the packet to send (p->payload points to the data, e.g. next + protocol header; if dest == IP_HDRINCL, p already includes an IP + header and p->payload points to that IP header) + * @param src the source IP address to send from (if src == IP_ADDR_ANY, the + * IP address of the netif used to send is used as source address) + * @param dest the destination IP address to send the packet to + * @param ttl the TTL value to be set in the IP header + * @param tos the TOS value to be set in the IP header + * @param proto the PROTOCOL to be set in the IP header + * @param addr_hint address hint pointer set to netif->addr_hint before + * calling ip_output_if() + * + * @return ERR_RTE if no route is found + * see ip_output_if() for more return values + */ +err_t +ip4_output_hinted(struct pbuf *p, const ip4_addr_t *src, const ip4_addr_t *dest, + u8_t ttl, u8_t tos, u8_t proto, u8_t *addr_hint) +{ + struct netif *netif; + err_t err; + + LWIP_IP_CHECK_PBUF_REF_COUNT_FOR_TX(p); + + if ((netif = ip4_route_src(dest, src)) == NULL) { + LWIP_DEBUGF(IP_DEBUG, ("ip4_output: No route to %"U16_F".%"U16_F".%"U16_F".%"U16_F"\n", + ip4_addr1_16(dest), ip4_addr2_16(dest), ip4_addr3_16(dest), ip4_addr4_16(dest))); + IP_STATS_INC(ip.rterr); + return ERR_RTE; + } + + NETIF_SET_HWADDRHINT(netif, addr_hint); + err = ip4_output_if(p, src, dest, ttl, tos, proto, netif); + NETIF_SET_HWADDRHINT(netif, NULL); + + return err; +} +#endif /* LWIP_NETIF_HWADDRHINT*/ + +#if IP_DEBUG +/* Print an IP header by using LWIP_DEBUGF + * @param p an IP packet, p->payload pointing to the IP header + */ +void +ip4_debug_print(struct pbuf *p) +{ + struct ip_hdr *iphdr = (struct ip_hdr *)p->payload; + + LWIP_DEBUGF(IP_DEBUG, ("IP header:\n")); + LWIP_DEBUGF(IP_DEBUG, ("+-------------------------------+\n")); + LWIP_DEBUGF(IP_DEBUG, ("|%2"S16_F" |%2"S16_F" | 0x%02"X16_F" | %5"U16_F" | (v, hl, tos, len)\n", + IPH_V(iphdr), + IPH_HL(iphdr), + IPH_TOS(iphdr), + ntohs(IPH_LEN(iphdr)))); + LWIP_DEBUGF(IP_DEBUG, ("+-------------------------------+\n")); + LWIP_DEBUGF(IP_DEBUG, ("| %5"U16_F" |%"U16_F"%"U16_F"%"U16_F"| %4"U16_F" | (id, flags, offset)\n", + ntohs(IPH_ID(iphdr)), + ntohs(IPH_OFFSET(iphdr)) >> 15 & 1, + ntohs(IPH_OFFSET(iphdr)) >> 14 & 1, + ntohs(IPH_OFFSET(iphdr)) >> 13 & 1, + ntohs(IPH_OFFSET(iphdr)) & IP_OFFMASK)); + LWIP_DEBUGF(IP_DEBUG, ("+-------------------------------+\n")); + LWIP_DEBUGF(IP_DEBUG, ("| %3"U16_F" | %3"U16_F" | 0x%04"X16_F" | (ttl, proto, chksum)\n", + IPH_TTL(iphdr), + IPH_PROTO(iphdr), + ntohs(IPH_CHKSUM(iphdr)))); + LWIP_DEBUGF(IP_DEBUG, ("+-------------------------------+\n")); + LWIP_DEBUGF(IP_DEBUG, ("| %3"U16_F" | %3"U16_F" | %3"U16_F" | %3"U16_F" | (src)\n", + ip4_addr1_16(&iphdr->src), + ip4_addr2_16(&iphdr->src), + ip4_addr3_16(&iphdr->src), + ip4_addr4_16(&iphdr->src))); + LWIP_DEBUGF(IP_DEBUG, ("+-------------------------------+\n")); + LWIP_DEBUGF(IP_DEBUG, ("| %3"U16_F" | %3"U16_F" | %3"U16_F" | %3"U16_F" | (dest)\n", + ip4_addr1_16(&iphdr->dest), + ip4_addr2_16(&iphdr->dest), + ip4_addr3_16(&iphdr->dest), + ip4_addr4_16(&iphdr->dest))); + LWIP_DEBUGF(IP_DEBUG, ("+-------------------------------+\n")); +} +#endif /* IP_DEBUG */ + +#endif /* LWIP_IPV4 */ diff --git a/components/lwip/core/ipv4/ip4_addr.c b/components/lwip/core/ipv4/ip4_addr.c new file mode 100755 index 0000000000..3053cf087e --- /dev/null +++ b/components/lwip/core/ipv4/ip4_addr.c @@ -0,0 +1,372 @@ +/** + * @file + * This is the IPv4 address tools implementation. + * + */ + +/* + * Copyright (c) 2001-2004 Swedish Institute of Computer Science. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + * + */ + +#include "lwip/opt.h" + +#if LWIP_IPV4 + +#include "lwip/ip_addr.h" +#include "lwip/netif.h" + +/* used by IP_ADDR_ANY and IP_ADDR_BROADCAST in ip_addr.h */ + +#ifdef LWIP_ESP8266 +//TO_DO +//const ip_addr_t ip_addr_any ICACHE_RODATA_ATTR STORE_ATTR = IPADDR4_INIT(IPADDR_ANY); +//const ip_addr_t ip_addr_broadcast ICACHE_RODATA_ATTR STORE_ATTR = IPADDR4_INIT(IPADDR_BROADCAST); +const ip_addr_t ip_addr_any = IPADDR4_INIT(IPADDR_ANY); +const ip_addr_t ip_addr_broadcast = IPADDR4_INIT(IPADDR_BROADCAST); +#else +const ip_addr_t ip_addr_any = IPADDR4_INIT(IPADDR_ANY); +const ip_addr_t ip_addr_broadcast = IPADDR4_INIT(IPADDR_BROADCAST); +#endif + + +/** + * Determine if an address is a broadcast address on a network interface + * + * @param addr address to be checked + * @param netif the network interface against which the address is checked + * @return returns non-zero if the address is a broadcast address + */ +u8_t +ip4_addr_isbroadcast_u32(u32_t addr, const struct netif *netif) +{ + ip4_addr_t ipaddr; + ip4_addr_set_u32(&ipaddr, addr); + + /* all ones (broadcast) or all zeroes (old skool broadcast) */ + if ((~addr == IPADDR_ANY) || + (addr == IPADDR_ANY)) { + return 1; + /* no broadcast support on this network interface? */ + } else if ((netif->flags & NETIF_FLAG_BROADCAST) == 0) { + /* the given address cannot be a broadcast address + * nor can we check against any broadcast addresses */ + return 0; + /* address matches network interface address exactly? => no broadcast */ + } else if (addr == ip4_addr_get_u32(netif_ip4_addr(netif))) { + return 0; + /* on the same (sub) network... */ + } else if (ip4_addr_netcmp(&ipaddr, netif_ip4_addr(netif), netif_ip4_netmask(netif)) + /* ...and host identifier bits are all ones? =>... */ + && ((addr & ~ip4_addr_get_u32(netif_ip4_netmask(netif))) == + (IPADDR_BROADCAST & ~ip4_addr_get_u32(netif_ip4_netmask(netif))))) { + /* => network broadcast address */ + return 1; + } else { + return 0; + } +} + +/** Checks if a netmask is valid (starting with ones, then only zeros) + * + * @param netmask the IPv4 netmask to check (in network byte order!) + * @return 1 if the netmask is valid, 0 if it is not + */ +u8_t +ip4_addr_netmask_valid(u32_t netmask) +{ + u32_t mask; + u32_t nm_hostorder = lwip_htonl(netmask); + + /* first, check for the first zero */ + for (mask = 1UL << 31 ; mask != 0; mask >>= 1) { + if ((nm_hostorder & mask) == 0) { + break; + } + } + /* then check that there is no one */ + for (; mask != 0; mask >>= 1) { + if ((nm_hostorder & mask) != 0) { + /* there is a one after the first zero -> invalid */ + return 0; + } + } + /* no one after the first zero -> valid */ + return 1; +} + +/* Here for now until needed in other places in lwIP */ +#ifndef isprint +#define in_range(c, lo, up) ((u8_t)c >= lo && (u8_t)c <= up) +#define isprint(c) in_range(c, 0x20, 0x7f) +#define isdigit(c) in_range(c, '0', '9') +#define isxdigit(c) (isdigit(c) || in_range(c, 'a', 'f') || in_range(c, 'A', 'F')) +#define islower(c) in_range(c, 'a', 'z') +#define isspace(c) (c == ' ' || c == '\f' || c == '\n' || c == '\r' || c == '\t' || c == '\v') +#endif + +/** + * Ascii internet address interpretation routine. + * The value returned is in network order. + * + * @param cp IP address in ascii representation (e.g. "127.0.0.1") + * @return ip address in network order + */ +u32_t +ipaddr_addr(const char *cp) +{ + ip4_addr_t val; + + if (ip4addr_aton(cp, &val)) { + return ip4_addr_get_u32(&val); + } + return (IPADDR_NONE); +} + +/** + * Check whether "cp" is a valid ascii representation + * of an Internet address and convert to a binary address. + * Returns 1 if the address is valid, 0 if not. + * This replaces inet_addr, the return value from which + * cannot distinguish between failure and a local broadcast address. + * + * @param cp IP address in ascii representation (e.g. "127.0.0.1") + * @param addr pointer to which to save the ip address in network order + * @return 1 if cp could be converted to addr, 0 on failure + */ +int +ip4addr_aton(const char *cp, ip4_addr_t *addr) +{ + u32_t val; + u8_t base; + char c; + u32_t parts[4]; + u32_t *pp = parts; + +#ifdef LWIP_ESP8266 +//#if 0 + char ch; + unsigned long cutoff; + int cutlim; +#endif + + c = *cp; + for (;;) { + /* + * Collect number up to ``.''. + * Values are specified as for C: + * 0x=hex, 0=octal, 1-9=decimal. + */ + if (!isdigit(c)) { + return 0; + } + val = 0; + base = 10; + if (c == '0') { + c = *++cp; + if (c == 'x' || c == 'X') { + base = 16; + c = *++cp; + } else { + base = 8; + } + } + +#ifdef LWIP_ESP8266 +//#if 0 + cutoff =(unsigned long)0xffffffff / (unsigned long)base; + cutlim =(unsigned long)0xffffffff % (unsigned long)base; + for (;;) { + if (isdigit(c)) { + ch = (int)(c - '0'); + if (val > cutoff || (val == cutoff && ch > cutlim)) + return (0); + val = (val * base) + (int)(c - '0'); + c = *++cp; + } else if (base == 16 && isxdigit(c)) { + ch = (int)(c + 10 - (islower(c) ? 'a' : 'A')); + if (val > cutoff || (val == cutoff && ch > cutlim)) + return (0); + val = (val << 4) | (int)(c + 10 - (islower(c) ? 'a' : 'A')); + c = *++cp; + } else + break; + } +#else + for (;;) { + if (isdigit(c)) { + val = (val * base) + (int)(c - '0'); + c = *++cp; + } else if (base == 16 && isxdigit(c)) { + val = (val << 4) | (int)(c + 10 - (islower(c) ? 'a' : 'A')); + c = *++cp; + } else { + break; + } + } +#endif + + if (c == '.') { + /* + * Internet format: + * a.b.c.d + * a.b.c (with c treated as 16 bits) + * a.b (with b treated as 24 bits) + */ + if (pp >= parts + 3) { + return 0; + } + *pp++ = val; + c = *++cp; + } else { + break; + } + } + /* + * Check for trailing characters. + */ + if (c != '\0' && !isspace(c)) { + return 0; + } + /* + * Concoct the address according to + * the number of parts specified. + */ + switch (pp - parts + 1) { + + case 0: + return 0; /* initial nondigit */ + + case 1: /* a -- 32 bits */ + break; + + case 2: /* a.b -- 8.24 bits */ + if (val > 0xffffffUL) { + return 0; + } + if (parts[0] > 0xff) { + return 0; + } + val |= parts[0] << 24; + break; + + case 3: /* a.b.c -- 8.8.16 bits */ + if (val > 0xffff) { + return 0; + } + if ((parts[0] > 0xff) || (parts[1] > 0xff)) { + return 0; + } + val |= (parts[0] << 24) | (parts[1] << 16); + break; + + case 4: /* a.b.c.d -- 8.8.8.8 bits */ + if (val > 0xff) { + return 0; + } + if ((parts[0] > 0xff) || (parts[1] > 0xff) || (parts[2] > 0xff)) { + return 0; + } + val |= (parts[0] << 24) | (parts[1] << 16) | (parts[2] << 8); + break; + default: + LWIP_ASSERT("unhandled", 0); + break; + } + if (addr) { + ip4_addr_set_u32(addr, htonl(val)); + } + return 1; +} + +/** + * Convert numeric IP address into decimal dotted ASCII representation. + * returns ptr to static buffer; not reentrant! + * + * @param addr ip address in network order to convert + * @return pointer to a global static (!) buffer that holds the ASCII + * representation of addr + */ +char* +ip4addr_ntoa(const ip4_addr_t *addr) +{ + static char str[IP4ADDR_STRLEN_MAX]; + return ip4addr_ntoa_r(addr, str, IP4ADDR_STRLEN_MAX); +} + +/** + * Same as ipaddr_ntoa, but reentrant since a user-supplied buffer is used. + * + * @param addr ip address in network order to convert + * @param buf target buffer where the string is stored + * @param buflen length of buf + * @return either pointer to buf which now holds the ASCII + * representation of addr or NULL if buf was too small + */ +char* +ip4addr_ntoa_r(const ip4_addr_t *addr, char *buf, int buflen) +{ + u32_t s_addr; + char inv[3]; + char *rp; + u8_t *ap; + u8_t rem; + u8_t n; + u8_t i; + int len = 0; + + s_addr = ip4_addr_get_u32(addr); + + rp = buf; + ap = (u8_t *)&s_addr; + for (n = 0; n < 4; n++) { + i = 0; + do { + rem = *ap % (u8_t)10; + *ap /= (u8_t)10; + inv[i++] = '0' + rem; + } while (*ap); + while (i--) { + if (len++ >= buflen) { + return NULL; + } + *rp++ = inv[i]; + } + if (len++ >= buflen) { + return NULL; + } + *rp++ = '.'; + ap++; + } + *--rp = 0; + return buf; +} + +#endif /* LWIP_IPV4 */ diff --git a/components/lwip/core/ipv4/ip_frag.c b/components/lwip/core/ipv4/ip_frag.c new file mode 100755 index 0000000000..1e6b053e6f --- /dev/null +++ b/components/lwip/core/ipv4/ip_frag.c @@ -0,0 +1,902 @@ +/** + * @file + * This is the IPv4 packet segmentation and reassembly implementation. + * + */ + +/* + * Copyright (c) 2001-2004 Swedish Institute of Computer Science. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Jani Monoses + * Simon Goldschmidt + * original reassembly code by Adam Dunkels + * + */ + +#include "lwip/opt.h" + +#if LWIP_IPV4 + +#include "lwip/ip_frag.h" +#include "lwip/def.h" +#include "lwip/inet_chksum.h" +#include "lwip/netif.h" +#include "lwip/stats.h" +#include "lwip/icmp.h" + +#include + +#ifdef MEMLEAK_DEBUG +static const char mem_debug_file[] ICACHE_RODATA_ATTR STORE_ATTR = __FILE__; +#endif + + +#if IP_REASSEMBLY +/** + * The IP reassembly code currently has the following limitations: + * - IP header options are not supported + * - fragments must not overlap (e.g. due to different routes), + * currently, overlapping or duplicate fragments are thrown away + * if IP_REASS_CHECK_OVERLAP=1 (the default)! + * + * @todo: work with IP header options + */ + +/** Setting this to 0, you can turn off checking the fragments for overlapping + * regions. The code gets a little smaller. Only use this if you know that + * overlapping won't occur on your network! */ +#ifndef IP_REASS_CHECK_OVERLAP +#define IP_REASS_CHECK_OVERLAP 1 +#endif /* IP_REASS_CHECK_OVERLAP */ + +/** Set to 0 to prevent freeing the oldest datagram when the reassembly buffer is + * full (IP_REASS_MAX_PBUFS pbufs are enqueued). The code gets a little smaller. + * Datagrams will be freed by timeout only. Especially useful when MEMP_NUM_REASSDATA + * is set to 1, so one datagram can be reassembled at a time, only. */ +#ifndef IP_REASS_FREE_OLDEST +#define IP_REASS_FREE_OLDEST 1 +#endif /* IP_REASS_FREE_OLDEST */ + +#define IP_REASS_FLAG_LASTFRAG 0x01 + +/** This is a helper struct which holds the starting + * offset and the ending offset of this fragment to + * easily chain the fragments. + * It has the same packing requirements as the IP header, since it replaces + * the IP header in memory in incoming fragments (after copying it) to keep + * track of the various fragments. (-> If the IP header doesn't need packing, + * this struct doesn't need packing, too.) + */ +#ifdef PACK_STRUCT_USE_INCLUDES +# include "arch/bpstruct.h" +#endif +PACK_STRUCT_BEGIN +struct ip_reass_helper { + PACK_STRUCT_FIELD(struct pbuf *next_pbuf); + PACK_STRUCT_FIELD(u16_t start); + PACK_STRUCT_FIELD(u16_t end); +} PACK_STRUCT_STRUCT; +PACK_STRUCT_END +#ifdef PACK_STRUCT_USE_INCLUDES +# include "arch/epstruct.h" +#endif + +#define IP_ADDRESSES_AND_ID_MATCH(iphdrA, iphdrB) \ + (ip4_addr_cmp(&(iphdrA)->src, &(iphdrB)->src) && \ + ip4_addr_cmp(&(iphdrA)->dest, &(iphdrB)->dest) && \ + IPH_ID(iphdrA) == IPH_ID(iphdrB)) ? 1 : 0 + +/* global variables */ +static struct ip_reassdata *reassdatagrams; +static u16_t ip_reass_pbufcount; + +/* function prototypes */ +static void ip_reass_dequeue_datagram(struct ip_reassdata *ipr, struct ip_reassdata *prev); +static int ip_reass_free_complete_datagram(struct ip_reassdata *ipr, struct ip_reassdata *prev); + +/** + * Reassembly timer base function + * for both NO_SYS == 0 and 1 (!). + * + * Should be called every 1000 msec (defined by IP_TMR_INTERVAL). + */ +void +ip_reass_tmr(void) +{ + struct ip_reassdata *r, *prev = NULL; + + r = reassdatagrams; + while (r != NULL) { + /* Decrement the timer. Once it reaches 0, + * clean up the incomplete fragment assembly */ + if (r->timer > 0) { + r->timer--; + LWIP_DEBUGF(IP_REASS_DEBUG, ("ip_reass_tmr: timer dec %"U16_F"\n",(u16_t)r->timer)); + prev = r; + r = r->next; + } else { + /* reassembly timed out */ + struct ip_reassdata *tmp; + LWIP_DEBUGF(IP_REASS_DEBUG, ("ip_reass_tmr: timer timed out\n")); + tmp = r; + /* get the next pointer before freeing */ + r = r->next; + /* free the helper struct and all enqueued pbufs */ + ip_reass_free_complete_datagram(tmp, prev); + } + } +} + +/** + * Free a datagram (struct ip_reassdata) and all its pbufs. + * Updates the total count of enqueued pbufs (ip_reass_pbufcount), + * SNMP counters and sends an ICMP time exceeded packet. + * + * @param ipr datagram to free + * @param prev the previous datagram in the linked list + * @return the number of pbufs freed + */ +static int +ip_reass_free_complete_datagram(struct ip_reassdata *ipr, struct ip_reassdata *prev) +{ + u16_t pbufs_freed = 0; + u8_t clen; + struct pbuf *p; + struct ip_reass_helper *iprh; + + LWIP_ASSERT("prev != ipr", prev != ipr); + if (prev != NULL) { + LWIP_ASSERT("prev->next == ipr", prev->next == ipr); + } + + MIB2_STATS_INC(mib2.ipreasmfails); +#if LWIP_ICMP + iprh = (struct ip_reass_helper *)ipr->p->payload; + if (iprh->start == 0) { + /* The first fragment was received, send ICMP time exceeded. */ + /* First, de-queue the first pbuf from r->p. */ + p = ipr->p; + ipr->p = iprh->next_pbuf; + /* Then, copy the original header into it. */ + SMEMCPY(p->payload, &ipr->iphdr, IP_HLEN); + icmp_time_exceeded(p, ICMP_TE_FRAG); + clen = pbuf_clen(p); + LWIP_ASSERT("pbufs_freed + clen <= 0xffff", pbufs_freed + clen <= 0xffff); + pbufs_freed += clen; + pbuf_free(p); + } +#endif /* LWIP_ICMP */ + + /* First, free all received pbufs. The individual pbufs need to be released + separately as they have not yet been chained */ + p = ipr->p; + while (p != NULL) { + struct pbuf *pcur; + iprh = (struct ip_reass_helper *)p->payload; + pcur = p; + /* get the next pointer before freeing */ + p = iprh->next_pbuf; + clen = pbuf_clen(pcur); + LWIP_ASSERT("pbufs_freed + clen <= 0xffff", pbufs_freed + clen <= 0xffff); + pbufs_freed += clen; + pbuf_free(pcur); + } + /* Then, unchain the struct ip_reassdata from the list and free it. */ + ip_reass_dequeue_datagram(ipr, prev); + LWIP_ASSERT("ip_reass_pbufcount >= clen", ip_reass_pbufcount >= pbufs_freed); + ip_reass_pbufcount -= pbufs_freed; + + return pbufs_freed; +} + +#if IP_REASS_FREE_OLDEST +/** + * Free the oldest datagram to make room for enqueueing new fragments. + * The datagram 'fraghdr' belongs to is not freed! + * + * @param fraghdr IP header of the current fragment + * @param pbufs_needed number of pbufs needed to enqueue + * (used for freeing other datagrams if not enough space) + * @return the number of pbufs freed + */ +static int +ip_reass_remove_oldest_datagram(struct ip_hdr *fraghdr, int pbufs_needed) +{ + /* @todo Can't we simply remove the last datagram in the + * linked list behind reassdatagrams? + */ + struct ip_reassdata *r, *oldest, *prev, *oldest_prev; + int pbufs_freed = 0, pbufs_freed_current; + int other_datagrams; + + /* Free datagrams until being allowed to enqueue 'pbufs_needed' pbufs, + * but don't free the datagram that 'fraghdr' belongs to! */ + do { + oldest = NULL; + prev = NULL; + oldest_prev = NULL; + other_datagrams = 0; + r = reassdatagrams; + while (r != NULL) { + if (!IP_ADDRESSES_AND_ID_MATCH(&r->iphdr, fraghdr)) { + /* Not the same datagram as fraghdr */ + other_datagrams++; + if (oldest == NULL) { + oldest = r; + oldest_prev = prev; + } else if (r->timer <= oldest->timer) { + /* older than the previous oldest */ + oldest = r; + oldest_prev = prev; + } + } + if (r->next != NULL) { + prev = r; + } + r = r->next; + } + if (oldest != NULL) { + pbufs_freed_current = ip_reass_free_complete_datagram(oldest, oldest_prev); + pbufs_freed += pbufs_freed_current; + } + } while ((pbufs_freed < pbufs_needed) && (other_datagrams > 1)); + return pbufs_freed; +} +#endif /* IP_REASS_FREE_OLDEST */ + +/** + * Enqueues a new fragment into the fragment queue + * @param fraghdr points to the new fragments IP hdr + * @param clen number of pbufs needed to enqueue (used for freeing other datagrams if not enough space) + * @return A pointer to the queue location into which the fragment was enqueued + */ +static struct ip_reassdata* +ip_reass_enqueue_new_datagram(struct ip_hdr *fraghdr, int clen) +{ + struct ip_reassdata* ipr; +#if ! IP_REASS_FREE_OLDEST + LWIP_UNUSED_ARG(clen); +#endif + + /* No matching previous fragment found, allocate a new reassdata struct */ + ipr = (struct ip_reassdata *)memp_malloc(MEMP_REASSDATA); + if (ipr == NULL) { +#if IP_REASS_FREE_OLDEST + if (ip_reass_remove_oldest_datagram(fraghdr, clen) >= clen) { + ipr = (struct ip_reassdata *)memp_malloc(MEMP_REASSDATA); + } + if (ipr == NULL) +#endif /* IP_REASS_FREE_OLDEST */ + { + IPFRAG_STATS_INC(ip_frag.memerr); + LWIP_DEBUGF(IP_REASS_DEBUG,("Failed to alloc reassdata struct\n")); + return NULL; + } + } + memset(ipr, 0, sizeof(struct ip_reassdata)); + ipr->timer = IP_REASS_MAXAGE; + + /* enqueue the new structure to the front of the list */ + ipr->next = reassdatagrams; + reassdatagrams = ipr; + /* copy the ip header for later tests and input */ + /* @todo: no ip options supported? */ + SMEMCPY(&(ipr->iphdr), fraghdr, IP_HLEN); + return ipr; +} + +/** + * Dequeues a datagram from the datagram queue. Doesn't deallocate the pbufs. + * @param ipr points to the queue entry to dequeue + */ +static void +ip_reass_dequeue_datagram(struct ip_reassdata *ipr, struct ip_reassdata *prev) +{ + /* dequeue the reass struct */ + if (reassdatagrams == ipr) { + /* it was the first in the list */ + reassdatagrams = ipr->next; + } else { + /* it wasn't the first, so it must have a valid 'prev' */ + LWIP_ASSERT("sanity check linked list", prev != NULL); + prev->next = ipr->next; + } + + /* now we can free the ip_reassdata struct */ + memp_free(MEMP_REASSDATA, ipr); +} + +/** + * Chain a new pbuf into the pbuf list that composes the datagram. The pbuf list + * will grow over time as new pbufs are rx. + * Also checks that the datagram passes basic continuity checks (if the last + * fragment was received at least once). + * @param root_p points to the 'root' pbuf for the current datagram being assembled. + * @param new_p points to the pbuf for the current fragment + * @return 0 if invalid, >0 otherwise + */ +static int +ip_reass_chain_frag_into_datagram_and_validate(struct ip_reassdata *ipr, struct pbuf *new_p) +{ + struct ip_reass_helper *iprh, *iprh_tmp, *iprh_prev=NULL; + struct pbuf *q; + u16_t offset,len; + struct ip_hdr *fraghdr; + int valid = 1; + + /* Extract length and fragment offset from current fragment */ + fraghdr = (struct ip_hdr*)new_p->payload; + len = ntohs(IPH_LEN(fraghdr)) - IPH_HL(fraghdr) * 4; + offset = (ntohs(IPH_OFFSET(fraghdr)) & IP_OFFMASK) * 8; + + /* overwrite the fragment's ip header from the pbuf with our helper struct, + * and setup the embedded helper structure. */ + /* make sure the struct ip_reass_helper fits into the IP header */ + LWIP_ASSERT("sizeof(struct ip_reass_helper) <= IP_HLEN", + sizeof(struct ip_reass_helper) <= IP_HLEN); + iprh = (struct ip_reass_helper*)new_p->payload; + iprh->next_pbuf = NULL; + iprh->start = offset; + iprh->end = offset + len; + + /* Iterate through until we either get to the end of the list (append), + * or we find one with a larger offset (insert). */ + for (q = ipr->p; q != NULL;) { + iprh_tmp = (struct ip_reass_helper*)q->payload; + if (iprh->start < iprh_tmp->start) { + /* the new pbuf should be inserted before this */ + iprh->next_pbuf = q; + if (iprh_prev != NULL) { + /* not the fragment with the lowest offset */ +#if IP_REASS_CHECK_OVERLAP + if ((iprh->start < iprh_prev->end) || (iprh->end > iprh_tmp->start)) { + /* fragment overlaps with previous or following, throw away */ + goto freepbuf; + } +#endif /* IP_REASS_CHECK_OVERLAP */ + iprh_prev->next_pbuf = new_p; + } else { + /* fragment with the lowest offset */ + ipr->p = new_p; + } + break; + } else if (iprh->start == iprh_tmp->start) { + /* received the same datagram twice: no need to keep the datagram */ + goto freepbuf; +#if IP_REASS_CHECK_OVERLAP + } else if (iprh->start < iprh_tmp->end) { + /* overlap: no need to keep the new datagram */ + goto freepbuf; +#endif /* IP_REASS_CHECK_OVERLAP */ + } else { + /* Check if the fragments received so far have no holes. */ + if (iprh_prev != NULL) { + if (iprh_prev->end != iprh_tmp->start) { + /* There is a fragment missing between the current + * and the previous fragment */ + valid = 0; + } + } + } + q = iprh_tmp->next_pbuf; + iprh_prev = iprh_tmp; + } + + /* If q is NULL, then we made it to the end of the list. Determine what to do now */ + if (q == NULL) { + if (iprh_prev != NULL) { + /* this is (for now), the fragment with the highest offset: + * chain it to the last fragment */ +#if IP_REASS_CHECK_OVERLAP + LWIP_ASSERT("check fragments don't overlap", iprh_prev->end <= iprh->start); +#endif /* IP_REASS_CHECK_OVERLAP */ + iprh_prev->next_pbuf = new_p; + if (iprh_prev->end != iprh->start) { + valid = 0; + } + } else { +#if IP_REASS_CHECK_OVERLAP + LWIP_ASSERT("no previous fragment, this must be the first fragment!", + ipr->p == NULL); +#endif /* IP_REASS_CHECK_OVERLAP */ + /* this is the first fragment we ever received for this ip datagram */ + ipr->p = new_p; + } + } + + /* At this point, the validation part begins: */ + /* If we already received the last fragment */ + if ((ipr->flags & IP_REASS_FLAG_LASTFRAG) != 0) { + /* and had no holes so far */ + if (valid) { + /* then check if the rest of the fragments is here */ + /* Check if the queue starts with the first datagram */ + if ((ipr->p == NULL) || (((struct ip_reass_helper*)ipr->p->payload)->start != 0)) { + valid = 0; + } else { + /* and check that there are no holes after this datagram */ + iprh_prev = iprh; + q = iprh->next_pbuf; + while (q != NULL) { + iprh = (struct ip_reass_helper*)q->payload; + if (iprh_prev->end != iprh->start) { + valid = 0; + break; + } + iprh_prev = iprh; + q = iprh->next_pbuf; + } + /* if still valid, all fragments are received + * (because to the MF==0 already arrived */ + if (valid) { + LWIP_ASSERT("sanity check", ipr->p != NULL); + LWIP_ASSERT("sanity check", + ((struct ip_reass_helper*)ipr->p->payload) != iprh); + LWIP_ASSERT("validate_datagram:next_pbuf!=NULL", + iprh->next_pbuf == NULL); + LWIP_ASSERT("validate_datagram:datagram end!=datagram len", + iprh->end == ipr->datagram_len); + } + } + } + /* If valid is 0 here, there are some fragments missing in the middle + * (since MF == 0 has already arrived). Such datagrams simply time out if + * no more fragments are received... */ + return valid; + } + /* If we come here, not all fragments were received, yet! */ + return 0; /* not yet valid! */ +#if IP_REASS_CHECK_OVERLAP +freepbuf: + ip_reass_pbufcount -= pbuf_clen(new_p); + pbuf_free(new_p); + return 0; +#endif /* IP_REASS_CHECK_OVERLAP */ +} + +/** + * Reassembles incoming IP fragments into an IP datagram. + * + * @param p points to a pbuf chain of the fragment + * @return NULL if reassembly is incomplete, ? otherwise + */ +struct pbuf * +ip4_reass(struct pbuf *p) +{ + struct pbuf *r; + struct ip_hdr *fraghdr; + struct ip_reassdata *ipr; + struct ip_reass_helper *iprh; + u16_t offset, len; + u8_t clen; + + IPFRAG_STATS_INC(ip_frag.recv); + MIB2_STATS_INC(mib2.ipreasmreqds); + + fraghdr = (struct ip_hdr*)p->payload; + + if ((IPH_HL(fraghdr) * 4) != IP_HLEN) { + LWIP_DEBUGF(IP_REASS_DEBUG,("ip4_reass: IP options currently not supported!\n")); + IPFRAG_STATS_INC(ip_frag.err); + goto nullreturn; + } + + offset = (ntohs(IPH_OFFSET(fraghdr)) & IP_OFFMASK) * 8; + len = ntohs(IPH_LEN(fraghdr)) - IPH_HL(fraghdr) * 4; + + /* Check if we are allowed to enqueue more datagrams. */ + clen = pbuf_clen(p); + if ((ip_reass_pbufcount + clen) > IP_REASS_MAX_PBUFS) { +#if IP_REASS_FREE_OLDEST + if (!ip_reass_remove_oldest_datagram(fraghdr, clen) || + ((ip_reass_pbufcount + clen) > IP_REASS_MAX_PBUFS)) +#endif /* IP_REASS_FREE_OLDEST */ + { + /* No datagram could be freed and still too many pbufs enqueued */ + LWIP_DEBUGF(IP_REASS_DEBUG,("ip4_reass: Overflow condition: pbufct=%d, clen=%d, MAX=%d\n", + ip_reass_pbufcount, clen, IP_REASS_MAX_PBUFS)); + IPFRAG_STATS_INC(ip_frag.memerr); + /* @todo: send ICMP time exceeded here? */ + /* drop this pbuf */ + goto nullreturn; + } + } + + /* Look for the datagram the fragment belongs to in the current datagram queue, + * remembering the previous in the queue for later dequeueing. */ + for (ipr = reassdatagrams; ipr != NULL; ipr = ipr->next) { + /* Check if the incoming fragment matches the one currently present + in the reassembly buffer. If so, we proceed with copying the + fragment into the buffer. */ + if (IP_ADDRESSES_AND_ID_MATCH(&ipr->iphdr, fraghdr)) { + LWIP_DEBUGF(IP_REASS_DEBUG, ("ip4_reass: matching previous fragment ID=%"X16_F"\n", + ntohs(IPH_ID(fraghdr)))); + IPFRAG_STATS_INC(ip_frag.cachehit); + break; + } + } + + if (ipr == NULL) { + /* Enqueue a new datagram into the datagram queue */ + ipr = ip_reass_enqueue_new_datagram(fraghdr, clen); + /* Bail if unable to enqueue */ + if (ipr == NULL) { + goto nullreturn; + } + } else { + if (((ntohs(IPH_OFFSET(fraghdr)) & IP_OFFMASK) == 0) && + ((ntohs(IPH_OFFSET(&ipr->iphdr)) & IP_OFFMASK) != 0)) { + /* ipr->iphdr is not the header from the first fragment, but fraghdr is + * -> copy fraghdr into ipr->iphdr since we want to have the header + * of the first fragment (for ICMP time exceeded and later, for copying + * all options, if supported)*/ + SMEMCPY(&ipr->iphdr, fraghdr, IP_HLEN); + } + } + /* Track the current number of pbufs current 'in-flight', in order to limit + the number of fragments that may be enqueued at any one time */ + ip_reass_pbufcount += clen; + + /* At this point, we have either created a new entry or pointing + * to an existing one */ + + /* check for 'no more fragments', and update queue entry*/ + if ((IPH_OFFSET(fraghdr) & PP_NTOHS(IP_MF)) == 0) { + ipr->flags |= IP_REASS_FLAG_LASTFRAG; + ipr->datagram_len = offset + len; + LWIP_DEBUGF(IP_REASS_DEBUG, + ("ip4_reass: last fragment seen, total len %"S16_F"\n", + ipr->datagram_len)); + } + /* find the right place to insert this pbuf */ + /* @todo: trim pbufs if fragments are overlapping */ + if (ip_reass_chain_frag_into_datagram_and_validate(ipr, p)) { + struct ip_reassdata *ipr_prev; + /* the totally last fragment (flag more fragments = 0) was received at least + * once AND all fragments are received */ + ipr->datagram_len += IP_HLEN; + + /* save the second pbuf before copying the header over the pointer */ + r = ((struct ip_reass_helper*)ipr->p->payload)->next_pbuf; + + /* copy the original ip header back to the first pbuf */ + fraghdr = (struct ip_hdr*)(ipr->p->payload); + SMEMCPY(fraghdr, &ipr->iphdr, IP_HLEN); + IPH_LEN_SET(fraghdr, htons(ipr->datagram_len)); + IPH_OFFSET_SET(fraghdr, 0); + IPH_CHKSUM_SET(fraghdr, 0); + /* @todo: do we need to set/calculate the correct checksum? */ +#if CHECKSUM_GEN_IP + IF__NETIF_CHECKSUM_ENABLED(ip_current_input_netif(), NETIF_CHECKSUM_GEN_IP) { + IPH_CHKSUM_SET(fraghdr, inet_chksum(fraghdr, IP_HLEN)); + } +#endif /* CHECKSUM_GEN_IP */ + + p = ipr->p; + + /* chain together the pbufs contained within the reass_data list. */ + while (r != NULL) { + iprh = (struct ip_reass_helper*)r->payload; + + /* hide the ip header for every succeeding fragment */ + pbuf_header(r, -IP_HLEN); + pbuf_cat(p, r); + r = iprh->next_pbuf; + } + + /* find the previous entry in the linked list */ + if (ipr == reassdatagrams) { + ipr_prev = NULL; + } else { + for (ipr_prev = reassdatagrams; ipr_prev != NULL; ipr_prev = ipr_prev->next) { + if (ipr_prev->next == ipr) { + break; + } + } + } + + /* release the sources allocate for the fragment queue entry */ + ip_reass_dequeue_datagram(ipr, ipr_prev); + + /* and adjust the number of pbufs currently queued for reassembly. */ + ip_reass_pbufcount -= pbuf_clen(p); + + MIB2_STATS_INC(mib2.ipreasmoks); + + /* Return the pbuf chain */ + return p; + } + /* the datagram is not (yet?) reassembled completely */ + LWIP_DEBUGF(IP_REASS_DEBUG,("ip_reass_pbufcount: %d out\n", ip_reass_pbufcount)); + return NULL; + +nullreturn: + LWIP_DEBUGF(IP_REASS_DEBUG,("ip4_reass: nullreturn\n")); + IPFRAG_STATS_INC(ip_frag.drop); + pbuf_free(p); + return NULL; +} +#endif /* IP_REASSEMBLY */ + +#if IP_FRAG +#if IP_FRAG_USES_STATIC_BUF +static u8_t buf[LWIP_MEM_ALIGN_SIZE(IP_FRAG_MAX_MTU + MEM_ALIGNMENT - 1)]; +#else /* IP_FRAG_USES_STATIC_BUF */ + +#if !LWIP_NETIF_TX_SINGLE_PBUF +/** Allocate a new struct pbuf_custom_ref */ +static struct pbuf_custom_ref* +ip_frag_alloc_pbuf_custom_ref(void) +{ + return (struct pbuf_custom_ref*)memp_malloc(MEMP_FRAG_PBUF); +} + +/** Free a struct pbuf_custom_ref */ +static void +ip_frag_free_pbuf_custom_ref(struct pbuf_custom_ref* p) +{ + LWIP_ASSERT("p != NULL", p != NULL); + memp_free(MEMP_FRAG_PBUF, p); +} + +/** Free-callback function to free a 'struct pbuf_custom_ref', called by + * pbuf_free. */ +static void +ipfrag_free_pbuf_custom(struct pbuf *p) +{ + struct pbuf_custom_ref *pcr = (struct pbuf_custom_ref*)p; + LWIP_ASSERT("pcr != NULL", pcr != NULL); + LWIP_ASSERT("pcr == p", (void*)pcr == (void*)p); + if (pcr->original != NULL) { + pbuf_free(pcr->original); + } + ip_frag_free_pbuf_custom_ref(pcr); +} +#endif /* !LWIP_NETIF_TX_SINGLE_PBUF */ +#endif /* IP_FRAG_USES_STATIC_BUF */ + +/** + * Fragment an IP datagram if too large for the netif. + * + * Chop the datagram in MTU sized chunks and send them in order + * by using a fixed size static memory buffer (PBUF_REF) or + * point PBUF_REFs into p (depending on IP_FRAG_USES_STATIC_BUF). + * + * @param p ip packet to send + * @param netif the netif on which to send + * @param dest destination ip address to which to send + * + * @return ERR_OK if sent successfully, err_t otherwise + */ +err_t +ip4_frag(struct pbuf *p, struct netif *netif, const ip4_addr_t *dest) +{ + struct pbuf *rambuf; +#if IP_FRAG_USES_STATIC_BUF + struct pbuf *header; +#else +#if !LWIP_NETIF_TX_SINGLE_PBUF + struct pbuf *newpbuf; +#endif + struct ip_hdr *original_iphdr; +#endif + struct ip_hdr *iphdr; + u16_t nfb; + u16_t left, cop; + u16_t mtu = netif->mtu; + u16_t ofo, omf; + u16_t last; + u16_t poff = IP_HLEN; + u16_t tmp; +#if !IP_FRAG_USES_STATIC_BUF && !LWIP_NETIF_TX_SINGLE_PBUF + u16_t newpbuflen = 0; + u16_t left_to_copy; +#endif + + /* Get a RAM based MTU sized pbuf */ +#if IP_FRAG_USES_STATIC_BUF + /* When using a static buffer, we use a PBUF_REF, which we will + * use to reference the packet (without link header). + * Layer and length is irrelevant. + */ + rambuf = pbuf_alloc(PBUF_LINK, 0, PBUF_REF); + if (rambuf == NULL) { + LWIP_DEBUGF(IP_REASS_DEBUG, ("ip_frag: pbuf_alloc(PBUF_LINK, 0, PBUF_REF) failed\n")); + goto memerr; + } + rambuf->tot_len = rambuf->len = mtu; + rambuf->payload = LWIP_MEM_ALIGN((void *)buf); + + /* Copy the IP header in it */ + iphdr = (struct ip_hdr *)rambuf->payload; + SMEMCPY(iphdr, p->payload, IP_HLEN); +#else /* IP_FRAG_USES_STATIC_BUF */ + original_iphdr = (struct ip_hdr *)p->payload; + iphdr = original_iphdr; +#endif /* IP_FRAG_USES_STATIC_BUF */ + + /* Save original offset */ + tmp = ntohs(IPH_OFFSET(iphdr)); + ofo = tmp & IP_OFFMASK; + omf = tmp & IP_MF; + + left = p->tot_len - IP_HLEN; + + nfb = (mtu - IP_HLEN) / 8; + + while (left) { + last = (left <= mtu - IP_HLEN); + + /* Set new offset and MF flag */ + tmp = omf | (IP_OFFMASK & (ofo)); + if (!last) { + tmp = tmp | IP_MF; + } + + /* Fill this fragment */ + cop = last ? left : nfb * 8; + +#if IP_FRAG_USES_STATIC_BUF + poff += pbuf_copy_partial(p, (u8_t*)iphdr + IP_HLEN, cop, poff); +#else /* IP_FRAG_USES_STATIC_BUF */ +#if LWIP_NETIF_TX_SINGLE_PBUF + rambuf = pbuf_alloc(PBUF_IP, cop, PBUF_RAM); + if (rambuf == NULL) { + goto memerr; + } + LWIP_ASSERT("this needs a pbuf in one piece!", + (rambuf->len == rambuf->tot_len) && (rambuf->next == NULL)); + poff += pbuf_copy_partial(p, rambuf->payload, cop, poff); + /* make room for the IP header */ + if (pbuf_header(rambuf, IP_HLEN)) { + pbuf_free(rambuf); + goto memerr; + } + /* fill in the IP header */ + SMEMCPY(rambuf->payload, original_iphdr, IP_HLEN); + iphdr = (struct ip_hdr*)rambuf->payload; +#else /* LWIP_NETIF_TX_SINGLE_PBUF */ + /* When not using a static buffer, create a chain of pbufs. + * The first will be a PBUF_RAM holding the link and IP header. + * The rest will be PBUF_REFs mirroring the pbuf chain to be fragged, + * but limited to the size of an mtu. + */ + rambuf = pbuf_alloc(PBUF_LINK, IP_HLEN, PBUF_RAM); + if (rambuf == NULL) { + goto memerr; + } + LWIP_ASSERT("this needs a pbuf in one piece!", + (p->len >= (IP_HLEN))); + SMEMCPY(rambuf->payload, original_iphdr, IP_HLEN); + iphdr = (struct ip_hdr *)rambuf->payload; + + /* Can just adjust p directly for needed offset. */ + p->payload = (u8_t *)p->payload + poff; + p->len -= poff; + + left_to_copy = cop; + while (left_to_copy) { + struct pbuf_custom_ref *pcr; + newpbuflen = (left_to_copy < p->len) ? left_to_copy : p->len; + /* Is this pbuf already empty? */ + if (!newpbuflen) { + p = p->next; + continue; + } + pcr = ip_frag_alloc_pbuf_custom_ref(); + if (pcr == NULL) { + pbuf_free(rambuf); + goto memerr; + } + /* Mirror this pbuf, although we might not need all of it. */ + newpbuf = pbuf_alloced_custom(PBUF_RAW, newpbuflen, PBUF_REF, &pcr->pc, p->payload, newpbuflen); + if (newpbuf == NULL) { + ip_frag_free_pbuf_custom_ref(pcr); + pbuf_free(rambuf); + goto memerr; + } + pbuf_ref(p); + pcr->original = p; + pcr->pc.custom_free_function = ipfrag_free_pbuf_custom; + + /* Add it to end of rambuf's chain, but using pbuf_cat, not pbuf_chain + * so that it is removed when pbuf_dechain is later called on rambuf. + */ + pbuf_cat(rambuf, newpbuf); + left_to_copy -= newpbuflen; + if (left_to_copy) { + p = p->next; + } + } + poff = newpbuflen; +#endif /* LWIP_NETIF_TX_SINGLE_PBUF */ +#endif /* IP_FRAG_USES_STATIC_BUF */ + + /* Correct header */ + IPH_OFFSET_SET(iphdr, htons(tmp)); + IPH_LEN_SET(iphdr, htons(cop + IP_HLEN)); + IPH_CHKSUM_SET(iphdr, 0); +#if CHECKSUM_GEN_IP + IF__NETIF_CHECKSUM_ENABLED(netif, NETIF_CHECKSUM_GEN_IP) { + IPH_CHKSUM_SET(iphdr, inet_chksum(iphdr, IP_HLEN)); + } +#endif /* CHECKSUM_GEN_IP */ + +#if IP_FRAG_USES_STATIC_BUF + if (last) { + pbuf_realloc(rambuf, left + IP_HLEN); + } + + /* This part is ugly: we alloc a RAM based pbuf for + * the link level header for each chunk and then + * free it. A PBUF_ROM style pbuf for which pbuf_header + * worked would make things simpler. + */ + header = pbuf_alloc(PBUF_LINK, 0, PBUF_RAM); + if (header != NULL) { + pbuf_chain(header, rambuf); + netif->output(netif, header, dest); + IPFRAG_STATS_INC(ip_frag.xmit); + MIB2_STATS_INC(mib2.ipfragcreates); + pbuf_free(header); + } else { + LWIP_DEBUGF(IP_REASS_DEBUG, ("ip_frag: pbuf_alloc() for header failed\n")); + pbuf_free(rambuf); + goto memerr; + } +#else /* IP_FRAG_USES_STATIC_BUF */ + /* No need for separate header pbuf - we allowed room for it in rambuf + * when allocated. + */ + netif->output(netif, rambuf, dest); + IPFRAG_STATS_INC(ip_frag.xmit); + + /* Unfortunately we can't reuse rambuf - the hardware may still be + * using the buffer. Instead we free it (and the ensuing chain) and + * recreate it next time round the loop. If we're lucky the hardware + * will have already sent the packet, the free will really free, and + * there will be zero memory penalty. + */ + + pbuf_free(rambuf); +#endif /* IP_FRAG_USES_STATIC_BUF */ + left -= cop; + ofo += nfb; + } +#if IP_FRAG_USES_STATIC_BUF + pbuf_free(rambuf); +#endif /* IP_FRAG_USES_STATIC_BUF */ + MIB2_STATS_INC(mib2.ipfragoks); + return ERR_OK; +memerr: + MIB2_STATS_INC(mib2.ipfragfails); + return ERR_MEM; +} +#endif /* IP_FRAG */ + +#endif /* LWIP_IPV4 */ diff --git a/components/lwip/core/ipv6/README b/components/lwip/core/ipv6/README new file mode 100755 index 0000000000..362000486e --- /dev/null +++ b/components/lwip/core/ipv6/README @@ -0,0 +1 @@ +IPv6 support in lwIP is very experimental. diff --git a/components/lwip/core/ipv6/dhcp6.c b/components/lwip/core/ipv6/dhcp6.c new file mode 100755 index 0000000000..f27a725e3a --- /dev/null +++ b/components/lwip/core/ipv6/dhcp6.c @@ -0,0 +1,50 @@ +/** + * @file + * + * DHCPv6. + */ + +/* + * Copyright (c) 2010 Inico Technologies Ltd. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Ivan Delamer + * + * + * Please coordinate changes and requests with Ivan Delamer + * + */ + +#include "lwip/opt.h" + +#if LWIP_IPV6 && LWIP_IPV6_DHCP6 /* don't build if not configured for use in lwipopts.h */ + +#include "lwip/ip6_addr.h" +#include "lwip/def.h" + + +#endif /* LWIP_IPV6 && LWIP_IPV6_DHCP6 */ diff --git a/components/lwip/core/ipv6/ethip6.c b/components/lwip/core/ipv6/ethip6.c new file mode 100755 index 0000000000..36aa9523ec --- /dev/null +++ b/components/lwip/core/ipv6/ethip6.c @@ -0,0 +1,159 @@ +/** + * @file + * + * Ethernet output for IPv6. Uses ND tables for link-layer addressing. + */ + +/* + * Copyright (c) 2010 Inico Technologies Ltd. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Ivan Delamer + * + * + * Please coordinate changes and requests with Ivan Delamer + * + */ + +#include "lwip/opt.h" + +#if LWIP_IPV6 && LWIP_ETHERNET + +#include "lwip/ethip6.h" +#include "lwip/nd6.h" +#include "lwip/pbuf.h" +#include "lwip/ip6.h" +#include "lwip/ip6_addr.h" +#include "lwip/inet_chksum.h" +#include "lwip/netif.h" +#include "lwip/icmp6.h" +#include "netif/ethernet.h" + +#include + +/** + * Send an IPv6 packet on the network using netif->linkoutput + * The ethernet header is filled in before sending. + * + * @params netif the lwIP network interface on which to send the packet + * @params p the packet to send, p->payload pointing to the (uninitialized) ethernet header + * @params src the source MAC address to be copied into the ethernet header + * @params dst the destination MAC address to be copied into the ethernet header + * @return ERR_OK if the packet was sent, any other err_t on failure + */ +static err_t +ethip6_send(struct netif *netif, struct pbuf *p, struct eth_addr *src, struct eth_addr *dst) +{ + struct eth_hdr *ethhdr = (struct eth_hdr *)p->payload; + + LWIP_ASSERT("netif->hwaddr_len must be 6 for ethip6!", + (netif->hwaddr_len == 6)); + SMEMCPY(ðhdr->dest, dst, 6); + SMEMCPY(ðhdr->src, src, 6); + ethhdr->type = PP_HTONS(ETHTYPE_IPV6); + LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("ethip6_send: sending packet %p\n", (void *)p)); + /* send the packet */ + return netif->linkoutput(netif, p); +} + +/** + * Resolve and fill-in Ethernet address header for outgoing IPv6 packet. + * + * For IPv6 multicast, corresponding Ethernet addresses + * are selected and the packet is transmitted on the link. + * + * For unicast addresses, ... + * + * @TODO anycast addresses + * + * @param netif The lwIP network interface which the IP packet will be sent on. + * @param q The pbuf(s) containing the IP packet to be sent. + * @param ip6addr The IP address of the packet destination. + * + * @return + * - ERR_RTE No route to destination (no gateway to external networks), + * or the return type of either etharp_query() or etharp_send_ip(). + */ +err_t +ethip6_output(struct netif *netif, struct pbuf *q, const ip6_addr_t *ip6addr) +{ + struct eth_addr dest; + s8_t i; + + /* make room for Ethernet header - should not fail */ + if (pbuf_header(q, sizeof(struct eth_hdr)) != 0) { + /* bail out */ + LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_SERIOUS, + ("etharp_output: could not allocate room for header.\n")); + return ERR_BUF; + } + + /* multicast destination IP address? */ + if (ip6_addr_ismulticast(ip6addr)) { + /* Hash IP multicast address to MAC address.*/ + dest.addr[0] = 0x33; + dest.addr[1] = 0x33; + dest.addr[2] = ((const u8_t *)(&(ip6addr->addr[3])))[0]; + dest.addr[3] = ((const u8_t *)(&(ip6addr->addr[3])))[1]; + dest.addr[4] = ((const u8_t *)(&(ip6addr->addr[3])))[2]; + dest.addr[5] = ((const u8_t *)(&(ip6addr->addr[3])))[3]; + + /* Send out. */ + return ethip6_send(netif, q, (struct eth_addr*)(netif->hwaddr), &dest); + } + + /* We have a unicast destination IP address */ + /* TODO anycast? */ + /* Get next hop record. */ + i = nd6_get_next_hop_entry(ip6addr, netif); + if (i < 0) { + /* failed to get a next hop neighbor record. */ + return ERR_MEM; + } + + /* Now that we have a destination record, send or queue the packet. */ + if (neighbor_cache[i].state == ND6_STALE) { + /* Switch to delay state. */ + neighbor_cache[i].state = ND6_DELAY; + neighbor_cache[i].counter.delay_time = LWIP_ND6_DELAY_FIRST_PROBE_TIME; + } + /* TODO should we send or queue if PROBE? send for now, to let unicast NS pass. */ + if ((neighbor_cache[i].state == ND6_REACHABLE) || + (neighbor_cache[i].state == ND6_DELAY) || + (neighbor_cache[i].state == ND6_PROBE)) { + + /* Send out. */ + SMEMCPY(dest.addr, neighbor_cache[i].lladdr, 6); + return ethip6_send(netif, q, (struct eth_addr*)(netif->hwaddr), &dest); + } + + /* We should queue packet on this interface. */ + pbuf_header(q, -(s16_t)SIZEOF_ETH_HDR); + return nd6_queue_packet(i, q); +} + +#endif /* LWIP_IPV6 && LWIP_ETHERNET */ diff --git a/components/lwip/core/ipv6/icmp6.c b/components/lwip/core/ipv6/icmp6.c new file mode 100755 index 0000000000..0a17da33e1 --- /dev/null +++ b/components/lwip/core/ipv6/icmp6.c @@ -0,0 +1,353 @@ +/** + * @file + * + * IPv6 version of ICMP, as per RFC 4443. + */ + +/* + * Copyright (c) 2010 Inico Technologies Ltd. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Ivan Delamer + * + * + * Please coordinate changes and requests with Ivan Delamer + * + */ + +#include "lwip/opt.h" + +#if LWIP_ICMP6 && LWIP_IPV6 /* don't build if not configured for use in lwipopts.h */ + +#include "lwip/icmp6.h" +#include "lwip/ip6.h" +#include "lwip/ip6_addr.h" +#include "lwip/inet_chksum.h" +#include "lwip/pbuf.h" +#include "lwip/netif.h" +#include "lwip/nd6.h" +#include "lwip/mld6.h" +#include "lwip/ip.h" +#include "lwip/stats.h" + +#include + +#ifdef MEMLEAK_DEBUG +static const char mem_debug_file[] ICACHE_RODATA_ATTR STORE_ATTR = __FILE__; +#endif + +#ifndef LWIP_ICMP6_DATASIZE +#define LWIP_ICMP6_DATASIZE 8 +#endif +#if LWIP_ICMP6_DATASIZE == 0 +#define LWIP_ICMP6_DATASIZE 8 +#endif + +/* Forward declarations */ +static void icmp6_send_response(struct pbuf *p, u8_t code, u32_t data, u8_t type); + + +/** + * Process an input ICMPv6 message. Called by ip6_input. + * + * Will generate a reply for echo requests. Other messages are forwarded + * to nd6_input, or mld6_input. + * + * @param p the mld packet, p->payload pointing to the icmpv6 header + * @param inp the netif on which this packet was received + */ +void +icmp6_input(struct pbuf *p, struct netif *inp) +{ + struct icmp6_hdr *icmp6hdr; + struct pbuf * r; + const ip6_addr_t * reply_src; + + ICMP6_STATS_INC(icmp6.recv); + + /* Check that ICMPv6 header fits in payload */ + if (p->len < sizeof(struct icmp6_hdr)) { + /* drop short packets */ + pbuf_free(p); + ICMP6_STATS_INC(icmp6.lenerr); + ICMP6_STATS_INC(icmp6.drop); + return; + } + + icmp6hdr = (struct icmp6_hdr *)p->payload; + +#if CHECKSUM_CHECK_ICMP6 + IF__NETIF_CHECKSUM_ENABLED(inp, NETIF_CHECKSUM_CHECK_ICMP6) { + if (ip6_chksum_pseudo(p, IP6_NEXTH_ICMP6, p->tot_len, ip6_current_src_addr(), + ip6_current_dest_addr()) != 0) { + /* Checksum failed */ + pbuf_free(p); + ICMP6_STATS_INC(icmp6.chkerr); + ICMP6_STATS_INC(icmp6.drop); + return; + } + } +#endif /* CHECKSUM_CHECK_ICMP6 */ + + switch (icmp6hdr->type) { + case ICMP6_TYPE_NA: /* Neighbor advertisement */ + case ICMP6_TYPE_NS: /* Neighbor solicitation */ + case ICMP6_TYPE_RA: /* Router advertisement */ + case ICMP6_TYPE_RD: /* Redirect */ + case ICMP6_TYPE_PTB: /* Packet too big */ + nd6_input(p, inp); + return; + break; + case ICMP6_TYPE_RS: +#if LWIP_IPV6_FORWARD + /* TODO implement router functionality */ +#endif + break; +#if LWIP_IPV6_MLD + case ICMP6_TYPE_MLQ: + case ICMP6_TYPE_MLR: + case ICMP6_TYPE_MLD: + mld6_input(p, inp); + return; + break; +#endif + case ICMP6_TYPE_EREQ: +#if !LWIP_MULTICAST_PING + /* multicast destination address? */ + if (ip6_addr_ismulticast(ip6_current_dest_addr())) { + /* drop */ + pbuf_free(p); + ICMP6_STATS_INC(icmp6.drop); + return; + } +#endif /* LWIP_MULTICAST_PING */ + + /* Allocate reply. */ + r = pbuf_alloc(PBUF_IP, p->tot_len, PBUF_RAM); + if (r == NULL) { + /* drop */ + pbuf_free(p); + ICMP6_STATS_INC(icmp6.memerr); + return; + } + + /* Copy echo request. */ + if (pbuf_copy(r, p) != ERR_OK) { + /* drop */ + pbuf_free(p); + pbuf_free(r); + ICMP6_STATS_INC(icmp6.err); + return; + } + + /* Determine reply source IPv6 address. */ +#if LWIP_MULTICAST_PING + if (ip6_addr_ismulticast(ip6_current_dest_addr())) { + reply_src = ip_2_ip6(ip6_select_source_address(inp, ip6_current_src_addr())); + if (reply_src == NULL) { + /* drop */ + pbuf_free(p); + pbuf_free(r); + ICMP6_STATS_INC(icmp6.rterr); + return; + } + } + else +#endif /* LWIP_MULTICAST_PING */ + { + reply_src = ip6_current_dest_addr(); + } + + /* Set fields in reply. */ + ((struct icmp6_echo_hdr *)(r->payload))->type = ICMP6_TYPE_EREP; + ((struct icmp6_echo_hdr *)(r->payload))->chksum = 0; +#if CHECKSUM_GEN_ICMP6 + IF__NETIF_CHECKSUM_ENABLED(inp, NETIF_CHECKSUM_GEN_ICMP6) { + ((struct icmp6_echo_hdr *)(r->payload))->chksum = ip6_chksum_pseudo(r, + IP6_NEXTH_ICMP6, r->tot_len, reply_src, ip6_current_src_addr()); + } +#endif /* CHECKSUM_GEN_ICMP6 */ + + /* Send reply. */ + ICMP6_STATS_INC(icmp6.xmit); + ip6_output_if(r, reply_src, ip6_current_src_addr(), + LWIP_ICMP6_HL, 0, IP6_NEXTH_ICMP6, inp); + pbuf_free(r); + + break; + default: + ICMP6_STATS_INC(icmp6.proterr); + ICMP6_STATS_INC(icmp6.drop); + break; + } + + pbuf_free(p); +} + + +/** + * Send an icmpv6 'destination unreachable' packet. + * + * @param p the input packet for which the 'unreachable' should be sent, + * p->payload pointing to the IPv6 header + * @param c ICMPv6 code for the unreachable type + */ +void +icmp6_dest_unreach(struct pbuf *p, enum icmp6_dur_code c) +{ + icmp6_send_response(p, c, 0, ICMP6_TYPE_DUR); +} + +/** + * Send an icmpv6 'packet too big' packet. + * + * @param p the input packet for which the 'packet too big' should be sent, + * p->payload pointing to the IPv6 header + * @param mtu the maximum mtu that we can accept + */ +void +icmp6_packet_too_big(struct pbuf *p, u32_t mtu) +{ + icmp6_send_response(p, 0, mtu, ICMP6_TYPE_PTB); +} + +/** + * Send an icmpv6 'time exceeded' packet. + * + * @param p the input packet for which the 'unreachable' should be sent, + * p->payload pointing to the IPv6 header + * @param c ICMPv6 code for the time exceeded type + */ +void +icmp6_time_exceeded(struct pbuf *p, enum icmp6_te_code c) +{ + icmp6_send_response(p, c, 0, ICMP6_TYPE_TE); +} + +/** + * Send an icmpv6 'parameter problem' packet. + * + * @param p the input packet for which the 'param problem' should be sent, + * p->payload pointing to the IP header + * @param c ICMPv6 code for the param problem type + * @param pointer the pointer to the byte where the parameter is found + */ +void +icmp6_param_problem(struct pbuf *p, enum icmp6_pp_code c, u32_t pointer) +{ + icmp6_send_response(p, c, pointer, ICMP6_TYPE_PP); +} + +/** + * Send an ICMPv6 packet in response to an incoming packet. + * + * @param p the input packet for which the response should be sent, + * p->payload pointing to the IPv6 header + * @param code Code of the ICMPv6 header + * @param data Additional 32-bit parameter in the ICMPv6 header + * @param type Type of the ICMPv6 header + */ +static void +icmp6_send_response(struct pbuf *p, u8_t code, u32_t data, u8_t type) +{ + struct pbuf *q; + struct icmp6_hdr *icmp6hdr; + const ip6_addr_t *reply_src; + ip6_addr_t *reply_dest; + ip6_addr_t reply_src_local, reply_dest_local; + struct ip6_hdr *ip6hdr; + struct netif *netif; + + /* ICMPv6 header + IPv6 header + data */ + q = pbuf_alloc(PBUF_IP, sizeof(struct icmp6_hdr) + IP6_HLEN + LWIP_ICMP6_DATASIZE, + PBUF_RAM); + if (q == NULL) { + LWIP_DEBUGF(ICMP_DEBUG, ("icmp_time_exceeded: failed to allocate pbuf for ICMPv6 packet.\n")); + ICMP6_STATS_INC(icmp6.memerr); + return; + } + LWIP_ASSERT("check that first pbuf can hold icmp 6message", + (q->len >= (sizeof(struct icmp6_hdr) + IP6_HLEN + LWIP_ICMP6_DATASIZE))); + + icmp6hdr = (struct icmp6_hdr *)q->payload; + icmp6hdr->type = type; + icmp6hdr->code = code; + icmp6hdr->data = data; + + /* copy fields from original packet */ + SMEMCPY((u8_t *)q->payload + sizeof(struct icmp6_hdr), (u8_t *)p->payload, + IP6_HLEN + LWIP_ICMP6_DATASIZE); + + /* Get the destination address and netif for this ICMP message. */ + if ((ip_current_netif() == NULL) || + ((code == ICMP6_TE_FRAG) && (type == ICMP6_TYPE_TE))) { + /* Special case, as ip6_current_xxx is either NULL, or points + * to a different packet than the one that expired. + * We must use the addresses that are stored in the expired packet. */ + ip6hdr = (struct ip6_hdr *)p->payload; + /* copy from packed address to aligned address */ + ip6_addr_copy(reply_dest_local, ip6hdr->src); + ip6_addr_copy(reply_src_local, ip6hdr->dest); + reply_dest = &reply_dest_local; + reply_src = &reply_src_local; + netif = ip6_route(reply_src, reply_dest); + if (netif == NULL) { + /* drop */ + pbuf_free(q); + ICMP6_STATS_INC(icmp6.rterr); + return; + } + } + else { + netif = ip_current_netif(); + reply_dest = ip6_current_src_addr(); + + /* Select an address to use as source. */ + reply_src = ip_2_ip6(ip6_select_source_address(netif, reply_dest)); + if (reply_src == NULL) { + /* drop */ + pbuf_free(q); + ICMP6_STATS_INC(icmp6.rterr); + return; + } + } + + /* calculate checksum */ + icmp6hdr->chksum = 0; +#if CHECKSUM_GEN_ICMP6 + IF__NETIF_CHECKSUM_ENABLED(netif, NETIF_CHECKSUM_GEN_ICMP6) { + icmp6hdr->chksum = ip6_chksum_pseudo(q, IP6_NEXTH_ICMP6, q->tot_len, + reply_src, reply_dest); + } +#endif /* CHECKSUM_GEN_ICMP6 */ + + ICMP6_STATS_INC(icmp6.xmit); + ip6_output_if(q, reply_src, reply_dest, LWIP_ICMP6_HL, 0, IP6_NEXTH_ICMP6, netif); + pbuf_free(q); +} + +#endif /* LWIP_ICMP6 && LWIP_IPV6 */ diff --git a/components/lwip/core/ipv6/inet6.c b/components/lwip/core/ipv6/inet6.c new file mode 100755 index 0000000000..d9a992c22a --- /dev/null +++ b/components/lwip/core/ipv6/inet6.c @@ -0,0 +1,53 @@ +/** + * @file + * + * INET v6 addresses. + */ + +/* + * Copyright (c) 2010 Inico Technologies Ltd. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Ivan Delamer + * + * + * Please coordinate changes and requests with Ivan Delamer + * + */ + +#include "lwip/opt.h" + +#if LWIP_IPV6 && LWIP_SOCKET /* don't build if not configured for use in lwipopts.h */ + +#include "lwip/def.h" +#include "lwip/inet.h" + +/** This variable is initialized by the system to contain the wildcard IPv6 address. + */ +const struct in6_addr in6addr_any = IN6ADDR_ANY_INIT; + +#endif /* LWIP_IPV6 */ diff --git a/components/lwip/core/ipv6/ip6.c b/components/lwip/core/ipv6/ip6.c new file mode 100755 index 0000000000..056d33355f --- /dev/null +++ b/components/lwip/core/ipv6/ip6.c @@ -0,0 +1,1104 @@ +/** + * @file + * + * IPv6 layer. + */ + +/* + * Copyright (c) 2010 Inico Technologies Ltd. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Ivan Delamer + * + * + * Please coordinate changes and requests with Ivan Delamer + * + */ + +#include "lwip/opt.h" + +#if LWIP_IPV6 /* don't build if not configured for use in lwipopts.h */ + +#include "lwip/def.h" +#include "lwip/mem.h" +#include "lwip/netif.h" +#include "lwip/ip6.h" +#include "lwip/ip6_addr.h" +#include "lwip/ip6_frag.h" +#include "lwip/icmp6.h" +#include "lwip/raw.h" +#include "lwip/udp.h" +#include "lwip/priv/tcp_priv.h" +#include "lwip/dhcp6.h" +#include "lwip/nd6.h" +#include "lwip/mld6.h" +#include "lwip/debug.h" +#include "lwip/stats.h" + +#ifdef MEMLEAK_DEBUG +static const char mem_debug_file[] ICACHE_RODATA_ATTR STORE_ATTR = __FILE__; +#endif + +/** + * Finds the appropriate network interface for a given IPv6 address. It tries to select + * a netif following a sequence of heuristics: + * 1) if there is only 1 netif, return it + * 2) if the destination is a link-local address, try to match the src address to a netif. + * this is a tricky case because with multiple netifs, link-local addresses only have + * meaning within a particular subnet/link. + * 3) tries to match the destination subnet to a configured address + * 4) tries to find a router + * 5) tries to match the source address to the netif + * 6) returns the default netif, if configured + * + * @param src the source IPv6 address, if known + * @param dest the destination IPv6 address for which to find the route + * @return the netif on which to send to reach dest + */ +struct netif * +ip6_route(const ip6_addr_t *src, const ip6_addr_t *dest) +{ + struct netif *netif; + s8_t i; + + /* If single netif configuration, fast return. */ + if ((netif_list != NULL) && (netif_list->next == NULL)) { + if (!netif_is_up(netif_list) || !netif_is_link_up(netif_list)) { + return NULL; + } + return netif_list; + } + + /* Special processing for link-local addresses. */ + if (ip6_addr_islinklocal(dest)) { + if (ip6_addr_isany(src)) { + /* Use default netif, if Up. */ + if (!netif_is_up(netif_default) || !netif_is_link_up(netif_default)) { + return NULL; + } + return netif_default; + } + + /* Try to find the netif for the source address, checking that link is up. */ + for (netif = netif_list; netif != NULL; netif = netif->next) { + if (!netif_is_up(netif) || !netif_is_link_up(netif)) { + continue; + } + for (i = 0; i < LWIP_IPV6_NUM_ADDRESSES; i++) { + if (ip6_addr_isvalid(netif_ip6_addr_state(netif, i)) && + ip6_addr_cmp(src, netif_ip6_addr(netif, i))) { + return netif; + } + } + } + + /* netif not found, use default netif, if up */ + if (!netif_is_up(netif_default) || !netif_is_link_up(netif_default)) { + return NULL; + } + return netif_default; + } + + /* we come here for non-link-local addresses */ +#ifdef LWIP_HOOK_IP6_ROUTE + netif = LWIP_HOOK_IP6_ROUTE(src, dest); + if (netif != NULL) { + return netif; + } +#endif + + /* See if the destination subnet matches a configured address. */ + for (netif = netif_list; netif != NULL; netif = netif->next) { + if (!netif_is_up(netif) || !netif_is_link_up(netif)) { + continue; + } + for (i = 0; i < LWIP_IPV6_NUM_ADDRESSES; i++) { + if (ip6_addr_isvalid(netif_ip6_addr_state(netif, i)) && + ip6_addr_netcmp(dest, netif_ip6_addr(netif, i))) { + return netif; + } + } + } + + /* Get the netif for a suitable router. */ + i = nd6_select_router(dest, NULL); + if (i >= 0) { + if (default_router_list[i].neighbor_entry != NULL) { + if (default_router_list[i].neighbor_entry->netif != NULL) { + if (netif_is_up(default_router_list[i].neighbor_entry->netif) && netif_is_link_up(default_router_list[i].neighbor_entry->netif)) { + return default_router_list[i].neighbor_entry->netif; + } + } + } + } + + /* try with the netif that matches the source address. */ + if (!ip6_addr_isany(src)) { + for (netif = netif_list; netif != NULL; netif = netif->next) { + if (!netif_is_up(netif) || !netif_is_link_up(netif)) { + continue; + } + for (i = 0; i < LWIP_IPV6_NUM_ADDRESSES; i++) { + if (ip6_addr_isvalid(netif_ip6_addr_state(netif, i)) && + ip6_addr_cmp(src, netif_ip6_addr(netif, i))) { + return netif; + } + } + } + } + +#if LWIP_NETIF_LOOPBACK && !LWIP_HAVE_LOOPIF + /* loopif is disabled, loopback traffic is passed through any netif */ + if (ip6_addr_isloopback(dest)) { + /* don't check for link on loopback traffic */ + if (netif_is_up(netif_default)) { + return netif_default; + } + /* default netif is not up, just use any netif for loopback traffic */ + for (netif = netif_list; netif != NULL; netif = netif->next) { + if (netif_is_up(netif)) { + return netif; + } + } + return NULL; + } +#endif /* LWIP_NETIF_LOOPBACK && !LWIP_HAVE_LOOPIF */ + + /* no matching netif found, use default netif, if up */ + if ((netif_default == NULL) || !netif_is_up(netif_default) || !netif_is_link_up(netif_default)) { + return NULL; + } + return netif_default; +} + +/** + * Select the best IPv6 source address for a given destination + * IPv6 address. Loosely follows RFC 3484. "Strong host" behavior + * is assumed. + * + * @param netif the netif on which to send a packet + * @param dest the destination we are trying to reach + * @return the most suitable source address to use, or NULL if no suitable + * source address is found + */ +const ip_addr_t * +ip6_select_source_address(struct netif *netif, const ip6_addr_t * dest) +{ + const ip_addr_t *src = NULL; + u8_t i; + + /* If dest is link-local, choose a link-local source. */ + if (ip6_addr_islinklocal(dest) || ip6_addr_ismulticast_linklocal(dest) || ip6_addr_ismulticast_iflocal(dest)) { + for (i = 0; i < LWIP_IPV6_NUM_ADDRESSES; i++) { + if (ip6_addr_isvalid(netif_ip6_addr_state(netif, i)) && + ip6_addr_islinklocal(netif_ip6_addr(netif, i))) { + return netif_ip_addr6(netif, i); + } + } + } + + /* Choose a site-local with matching prefix. */ + if (ip6_addr_issitelocal(dest) || ip6_addr_ismulticast_sitelocal(dest)) { + for (i = 0; i < LWIP_IPV6_NUM_ADDRESSES; i++) { + if (ip6_addr_isvalid(netif_ip6_addr_state(netif, i)) && + ip6_addr_issitelocal(netif_ip6_addr(netif, i)) && + ip6_addr_netcmp(dest, netif_ip6_addr(netif, i))) { + return netif_ip_addr6(netif, i); + } + } + } + + /* Choose a unique-local with matching prefix. */ + if (ip6_addr_isuniquelocal(dest) || ip6_addr_ismulticast_orglocal(dest)) { + for (i = 0; i < LWIP_IPV6_NUM_ADDRESSES; i++) { + if (ip6_addr_isvalid(netif_ip6_addr_state(netif, i)) && + ip6_addr_isuniquelocal(netif_ip6_addr(netif, i)) && + ip6_addr_netcmp(dest, netif_ip6_addr(netif, i))) { + return netif_ip_addr6(netif, i); + } + } + } + + /* Choose a global with best matching prefix. */ + if (ip6_addr_isglobal(dest) || ip6_addr_ismulticast_global(dest)) { + for (i = 0; i < LWIP_IPV6_NUM_ADDRESSES; i++) { + if (ip6_addr_isvalid(netif_ip6_addr_state(netif, i)) && + ip6_addr_isglobal(netif_ip6_addr(netif, i))) { + if (src == NULL) { + src = netif_ip_addr6(netif, i); + } + else { + /* Replace src only if we find a prefix match. */ + /* TODO find longest matching prefix. */ + if ((!(ip6_addr_netcmp(ip_2_ip6(src), dest))) && + ip6_addr_netcmp(netif_ip6_addr(netif, i), dest)) { + src = netif_ip_addr6(netif, i); + } + } + } + } + if (src != NULL) { + return src; + } + } + + /* Last resort: see if arbitrary prefix matches. */ + for (i = 0; i < LWIP_IPV6_NUM_ADDRESSES; i++) { + if (ip6_addr_isvalid(netif_ip6_addr_state(netif, i)) && + ip6_addr_netcmp(dest, netif_ip6_addr(netif, i))) { + return netif_ip_addr6(netif, i); + } + } + + return NULL; +} + +#if LWIP_IPV6_FORWARD +/** + * Forwards an IPv6 packet. It finds an appropriate route for the + * packet, decrements the HL value of the packet, and outputs + * the packet on the appropriate interface. + * + * @param p the packet to forward (p->payload points to IP header) + * @param iphdr the IPv6 header of the input packet + * @param inp the netif on which this packet was received + */ +static void +ip6_forward(struct pbuf *p, struct ip6_hdr *iphdr, struct netif *inp) +{ + struct netif *netif; + + /* do not forward link-local addresses */ + if (ip6_addr_islinklocal(ip6_current_dest_addr())) { + LWIP_DEBUGF(IP6_DEBUG, ("ip6_forward: not forwarding link-local address.\n")); + IP6_STATS_INC(ip6.rterr); + IP6_STATS_INC(ip6.drop); + return; + } + + /* Find network interface where to forward this IP packet to. */ + netif = ip6_route(IP6_ADDR_ANY6, ip6_current_dest_addr()); + if (netif == NULL) { + LWIP_DEBUGF(IP6_DEBUG, ("ip6_forward: no route for %"X16_F":%"X16_F":%"X16_F":%"X16_F":%"X16_F":%"X16_F":%"X16_F":%"X16_F"\n", + IP6_ADDR_BLOCK1(ip6_current_dest_addr()), + IP6_ADDR_BLOCK2(ip6_current_dest_addr()), + IP6_ADDR_BLOCK3(ip6_current_dest_addr()), + IP6_ADDR_BLOCK4(ip6_current_dest_addr()), + IP6_ADDR_BLOCK5(ip6_current_dest_addr()), + IP6_ADDR_BLOCK6(ip6_current_dest_addr()), + IP6_ADDR_BLOCK7(ip6_current_dest_addr()), + IP6_ADDR_BLOCK8(ip6_current_dest_addr()))); +#if LWIP_ICMP6 + /* Don't send ICMP messages in response to ICMP messages */ + if (IP6H_NEXTH(iphdr) != IP6_NEXTH_ICMP6) { + icmp6_dest_unreach(p, ICMP6_DUR_NO_ROUTE); + } +#endif /* LWIP_ICMP6 */ + IP6_STATS_INC(ip6.rterr); + IP6_STATS_INC(ip6.drop); + return; + } + /* Do not forward packets onto the same network interface on which + * they arrived. */ + if (netif == inp) { + LWIP_DEBUGF(IP6_DEBUG, ("ip6_forward: not bouncing packets back on incoming interface.\n")); + IP6_STATS_INC(ip6.rterr); + IP6_STATS_INC(ip6.drop); + return; + } + + /* decrement HL */ + IP6H_HOPLIM_SET(iphdr, IP6H_HOPLIM(iphdr) - 1); + /* send ICMP6 if HL == 0 */ + if (IP6H_HOPLIM(iphdr) == 0) { +#if LWIP_ICMP6 + /* Don't send ICMP messages in response to ICMP messages */ + if (IP6H_NEXTH(iphdr) != IP6_NEXTH_ICMP6) { + icmp6_time_exceeded(p, ICMP6_TE_HL); + } +#endif /* LWIP_ICMP6 */ + IP6_STATS_INC(ip6.drop); + return; + } + + if (netif->mtu && (p->tot_len > netif->mtu)) { +#if LWIP_ICMP6 + /* Don't send ICMP messages in response to ICMP messages */ + if (IP6H_NEXTH(iphdr) != IP6_NEXTH_ICMP6) { + icmp6_packet_too_big(p, netif->mtu); + } +#endif /* LWIP_ICMP6 */ + IP6_STATS_INC(ip6.drop); + return; + } + + LWIP_DEBUGF(IP6_DEBUG, ("ip6_forward: forwarding packet to %"X16_F":%"X16_F":%"X16_F":%"X16_F":%"X16_F":%"X16_F":%"X16_F":%"X16_F"\n", + IP6_ADDR_BLOCK1(ip6_current_dest_addr()), + IP6_ADDR_BLOCK2(ip6_current_dest_addr()), + IP6_ADDR_BLOCK3(ip6_current_dest_addr()), + IP6_ADDR_BLOCK4(ip6_current_dest_addr()), + IP6_ADDR_BLOCK5(ip6_current_dest_addr()), + IP6_ADDR_BLOCK6(ip6_current_dest_addr()), + IP6_ADDR_BLOCK7(ip6_current_dest_addr()), + IP6_ADDR_BLOCK8(ip6_current_dest_addr()))); + + /* transmit pbuf on chosen interface */ + netif->output_ip6(netif, p, ip6_current_dest_addr()); + IP6_STATS_INC(ip6.fw); + IP6_STATS_INC(ip6.xmit); + return; +} +#endif /* LWIP_IPV6_FORWARD */ + +/** + * This function is called by the network interface device driver when + * an IPv6 packet is received. The function does the basic checks of the + * IP header such as packet size being at least larger than the header + * size etc. If the packet was not destined for us, the packet is + * forwarded (using ip6_forward). + * + * Finally, the packet is sent to the upper layer protocol input function. + * + * @param p the received IPv6 packet (p->payload points to IPv6 header) + * @param inp the netif on which this packet was received + * @return ERR_OK if the packet was processed (could return ERR_* if it wasn't + * processed, but currently always returns ERR_OK) + */ +err_t +ip6_input(struct pbuf *p, struct netif *inp) +{ + struct ip6_hdr *ip6hdr; + struct netif *netif; + u8_t nexth; + u16_t hlen; /* the current header length */ + u8_t i; +#if 0 /*IP_ACCEPT_LINK_LAYER_ADDRESSING*/ + @todo + int check_ip_src=1; +#endif /* IP_ACCEPT_LINK_LAYER_ADDRESSING */ + + IP6_STATS_INC(ip6.recv); + + /* identify the IP header */ + ip6hdr = (struct ip6_hdr *)p->payload; + if (IP6H_V(ip6hdr) != 6) { + LWIP_DEBUGF(IP6_DEBUG | LWIP_DBG_LEVEL_WARNING, ("IPv6 packet dropped due to bad version number %"U32_F"\n", + IP6H_V(ip6hdr))); + pbuf_free(p); + IP6_STATS_INC(ip6.err); + IP6_STATS_INC(ip6.drop); + return ERR_OK; + } + +#ifdef LWIP_HOOK_IP6_INPUT + if (LWIP_HOOK_IP6_INPUT(p, inp)) { + /* the packet has been eaten */ + return ERR_OK; + } +#endif + + /* header length exceeds first pbuf length, or ip length exceeds total pbuf length? */ + if ((IP6_HLEN > p->len) || ((IP6H_PLEN(ip6hdr) + IP6_HLEN) > p->tot_len)) { + if (IP6_HLEN > p->len) { + LWIP_DEBUGF(IP6_DEBUG | LWIP_DBG_LEVEL_SERIOUS, + ("IPv6 header (len %"U16_F") does not fit in first pbuf (len %"U16_F"), IP packet dropped.\n", + IP6_HLEN, p->len)); + } + if ((IP6H_PLEN(ip6hdr) + IP6_HLEN) > p->tot_len) { + LWIP_DEBUGF(IP6_DEBUG | LWIP_DBG_LEVEL_SERIOUS, + ("IPv6 (plen %"U16_F") is longer than pbuf (len %"U16_F"), IP packet dropped.\n", + IP6H_PLEN(ip6hdr) + IP6_HLEN, p->tot_len)); + } + /* free (drop) packet pbufs */ + pbuf_free(p); + IP6_STATS_INC(ip6.lenerr); + IP6_STATS_INC(ip6.drop); + return ERR_OK; + } + + /* Trim pbuf. This should have been done at the netif layer, + * but we'll do it anyway just to be sure that its done. */ + pbuf_realloc(p, IP6_HLEN + IP6H_PLEN(ip6hdr)); + + /* copy IP addresses to aligned ip6_addr_t */ + ip_addr_copy_from_ip6(ip_data.current_iphdr_dest, ip6hdr->dest); + ip_addr_copy_from_ip6(ip_data.current_iphdr_src, ip6hdr->src); + + /* current header pointer. */ + ip_data.current_ip6_header = ip6hdr; + + /* In netif, used in case we need to send ICMPv6 packets back. */ + ip_data.current_netif = inp; + ip_data.current_input_netif = inp; + + /* match packet against an interface, i.e. is this packet for us? */ + if (ip6_addr_ismulticast(ip6_current_dest_addr())) { + /* Always joined to multicast if-local and link-local all-nodes group. */ + if (ip6_addr_isallnodes_iflocal(ip6_current_dest_addr()) || + ip6_addr_isallnodes_linklocal(ip6_current_dest_addr())) { + netif = inp; + } +#if LWIP_IPV6_MLD + else if (mld6_lookfor_group(inp, ip6_current_dest_addr())) { + netif = inp; + } +#else /* LWIP_IPV6_MLD */ + else if (ip6_addr_issolicitednode(ip6_current_dest_addr())) { + /* Filter solicited node packets when MLD is not enabled + * (for Neighbor discovery). */ + netif = NULL; + for (i = 0; i < LWIP_IPV6_NUM_ADDRESSES; i++) { + if (ip6_addr_isvalid(netif_ip6_addr_state(inp, i)) && + ip6_addr_cmp_solicitednode(ip6_current_dest_addr(), netif_ip6_addr(inp, i))) { + netif = inp; + LWIP_DEBUGF(IP6_DEBUG, ("ip6_input: solicited node packet accepted on interface %c%c\n", + netif->name[0], netif->name[1])); + break; + } + } + } +#endif /* LWIP_IPV6_MLD */ + else { + netif = NULL; + } + } else { + /* start trying with inp. if that's not acceptable, start walking the + list of configured netifs. + 'first' is used as a boolean to mark whether we started walking the list */ + int first = 1; + netif = inp; + do { + /* interface is up? */ + if (netif_is_up(netif)) { + /* unicast to this interface address? address configured? */ + for (i = 0; i < LWIP_IPV6_NUM_ADDRESSES; i++) { + if (ip6_addr_isvalid(netif_ip6_addr_state(netif, i)) && + ip6_addr_cmp(ip6_current_dest_addr(), netif_ip6_addr(netif, i))) { + /* exit outer loop */ + goto netif_found; + } + } + } + if (ip6_addr_islinklocal(ip6_current_dest_addr())) { + /* Do not match link-local addresses to other netifs. */ + netif = NULL; + break; + } + if (first) { + first = 0; + netif = netif_list; + } else { + netif = netif->next; + } + if (netif == inp) { + netif = netif->next; + } + } while (netif != NULL); +netif_found: + LWIP_DEBUGF(IP6_DEBUG, ("ip6_input: packet accepted on interface %c%c\n", + netif ? netif->name[0] : 'X', netif? netif->name[1] : 'X')); + } + + /* "::" packet source address? (used in duplicate address detection) */ + if (ip6_addr_isany(ip6_current_src_addr()) && + (!ip6_addr_issolicitednode(ip6_current_dest_addr()))) { + /* packet source is not valid */ + /* free (drop) packet pbufs */ + LWIP_DEBUGF(IP6_DEBUG, ("ip6_input: packet with src ANY_ADDRESS dropped\n")); + pbuf_free(p); + IP6_STATS_INC(ip6.drop); + goto ip6_input_cleanup; + } + + /* packet not for us? */ + if (netif == NULL) { + /* packet not for us, route or discard */ + LWIP_DEBUGF(IP6_DEBUG | LWIP_DBG_TRACE, ("ip6_input: packet not for us.\n")); +#if LWIP_IPV6_FORWARD + /* non-multicast packet? */ + if (!ip6_addr_ismulticast(ip6_current_dest_addr())) { + /* try to forward IP packet on (other) interfaces */ + ip6_forward(p, ip6hdr, inp); + } +#endif /* LWIP_IPV6_FORWARD */ + pbuf_free(p); + goto ip6_input_cleanup; + } + + /* current netif pointer. */ + ip_data.current_netif = netif; + + /* Save next header type. */ + nexth = IP6H_NEXTH(ip6hdr); + + /* Init header length. */ + hlen = ip_data.current_ip_header_tot_len = IP6_HLEN; + + /* Move to payload. */ + pbuf_header(p, -IP6_HLEN); + + /* Process known option extension headers, if present. */ + while (nexth != IP6_NEXTH_NONE) + { + switch (nexth) { + case IP6_NEXTH_HOPBYHOP: + LWIP_DEBUGF(IP6_DEBUG, ("ip6_input: packet with Hop-by-Hop options header\n")); + /* Get next header type. */ + nexth = *((u8_t *)p->payload); + + /* Get the header length. */ + hlen = 8 * (1 + *((u8_t *)p->payload + 1)); + ip_data.current_ip_header_tot_len += hlen; + + /* Skip over this header. */ + if (hlen > p->len) { + LWIP_DEBUGF(IP6_DEBUG | LWIP_DBG_LEVEL_SERIOUS, + ("IPv6 options header (hlen %"U16_F") does not fit in first pbuf (len %"U16_F"), IPv6 packet dropped.\n", + hlen, p->len)); + /* free (drop) packet pbufs */ + pbuf_free(p); + IP6_STATS_INC(ip6.lenerr); + IP6_STATS_INC(ip6.drop); + goto ip6_input_cleanup; + } + + pbuf_header(p, -(s16_t)hlen); + break; + case IP6_NEXTH_DESTOPTS: + LWIP_DEBUGF(IP6_DEBUG, ("ip6_input: packet with Destination options header\n")); + /* Get next header type. */ + nexth = *((u8_t *)p->payload); + + /* Get the header length. */ + hlen = 8 * (1 + *((u8_t *)p->payload + 1)); + ip_data.current_ip_header_tot_len += hlen; + + /* Skip over this header. */ + if (hlen > p->len) { + LWIP_DEBUGF(IP6_DEBUG | LWIP_DBG_LEVEL_SERIOUS, + ("IPv6 options header (hlen %"U16_F") does not fit in first pbuf (len %"U16_F"), IPv6 packet dropped.\n", + hlen, p->len)); + /* free (drop) packet pbufs */ + pbuf_free(p); + IP6_STATS_INC(ip6.lenerr); + IP6_STATS_INC(ip6.drop); + goto ip6_input_cleanup; + } + + pbuf_header(p, -(s16_t)hlen); + break; + case IP6_NEXTH_ROUTING: + LWIP_DEBUGF(IP6_DEBUG, ("ip6_input: packet with Routing header\n")); + /* Get next header type. */ + nexth = *((u8_t *)p->payload); + + /* Get the header length. */ + hlen = 8 * (1 + *((u8_t *)p->payload + 1)); + ip_data.current_ip_header_tot_len += hlen; + + /* Skip over this header. */ + if (hlen > p->len) { + LWIP_DEBUGF(IP6_DEBUG | LWIP_DBG_LEVEL_SERIOUS, + ("IPv6 options header (hlen %"U16_F") does not fit in first pbuf (len %"U16_F"), IPv6 packet dropped.\n", + hlen, p->len)); + /* free (drop) packet pbufs */ + pbuf_free(p); + IP6_STATS_INC(ip6.lenerr); + IP6_STATS_INC(ip6.drop); + goto ip6_input_cleanup; + } + + pbuf_header(p, -(s16_t)hlen); + break; + + case IP6_NEXTH_FRAGMENT: + { + struct ip6_frag_hdr * frag_hdr; + LWIP_DEBUGF(IP6_DEBUG, ("ip6_input: packet with Fragment header\n")); + + frag_hdr = (struct ip6_frag_hdr *)p->payload; + + /* Get next header type. */ + nexth = frag_hdr->_nexth; + + /* Fragment Header length. */ + hlen = 8; + ip_data.current_ip_header_tot_len += hlen; + + /* Make sure this header fits in current pbuf. */ + if (hlen > p->len) { + LWIP_DEBUGF(IP6_DEBUG | LWIP_DBG_LEVEL_SERIOUS, + ("IPv6 options header (hlen %"U16_F") does not fit in first pbuf (len %"U16_F"), IPv6 packet dropped.\n", + hlen, p->len)); + /* free (drop) packet pbufs */ + pbuf_free(p); + IP6_FRAG_STATS_INC(ip6_frag.lenerr); + IP6_FRAG_STATS_INC(ip6_frag.drop); + goto ip6_input_cleanup; + } + + /* Offset == 0 and more_fragments == 0? */ + if ((frag_hdr->_fragment_offset & + PP_HTONS(IP6_FRAG_OFFSET_MASK | IP6_FRAG_MORE_FLAG)) == 0) { + /* This is a 1-fragment packet, usually a packet that we have + * already reassembled. Skip this header anc continue. */ + pbuf_header(p, -(s16_t)hlen); + } else { +#if LWIP_IPV6_REASS + + /* reassemble the packet */ + p = ip6_reass(p); + /* packet not fully reassembled yet? */ + if (p == NULL) { + goto ip6_input_cleanup; + } + + /* Returned p point to IPv6 header. + * Update all our variables and pointers and continue. */ + ip6hdr = (struct ip6_hdr *)p->payload; + nexth = IP6H_NEXTH(ip6hdr); + hlen = ip_data.current_ip_header_tot_len = IP6_HLEN; + pbuf_header(p, -IP6_HLEN); + +#else /* LWIP_IPV6_REASS */ + /* free (drop) packet pbufs */ + LWIP_DEBUGF(IP6_DEBUG, ("ip6_input: packet with Fragment header dropped (with LWIP_IPV6_REASS==0)\n")); + pbuf_free(p); + IP6_STATS_INC(ip6.opterr); + IP6_STATS_INC(ip6.drop); + goto ip6_input_cleanup; +#endif /* LWIP_IPV6_REASS */ + } + break; + } + default: + goto options_done; + break; + } + } +options_done: + + /* p points to IPv6 header again. */ + pbuf_header_force(p, ip_data.current_ip_header_tot_len); + + /* send to upper layers */ + LWIP_DEBUGF(IP6_DEBUG, ("ip6_input: \n")); + ip6_debug_print(p); + LWIP_DEBUGF(IP6_DEBUG, ("ip6_input: p->len %"U16_F" p->tot_len %"U16_F"\n", p->len, p->tot_len)); + +#if LWIP_RAW + /* raw input did not eat the packet? */ + if (raw_input(p, inp) == 0) +#endif /* LWIP_RAW */ + { + switch (nexth) { + case IP6_NEXTH_NONE: + pbuf_free(p); + break; +#if LWIP_UDP + case IP6_NEXTH_UDP: +#if LWIP_UDPLITE + case IP6_NEXTH_UDPLITE: +#endif /* LWIP_UDPLITE */ + /* Point to payload. */ + pbuf_header(p, -(s16_t)ip_data.current_ip_header_tot_len); + udp_input(p, inp); + break; +#endif /* LWIP_UDP */ +#if LWIP_TCP + case IP6_NEXTH_TCP: + /* Point to payload. */ + pbuf_header(p, -(s16_t)ip_data.current_ip_header_tot_len); + tcp_input(p, inp); + break; +#endif /* LWIP_TCP */ +#if LWIP_ICMP6 + case IP6_NEXTH_ICMP6: + /* Point to payload. */ + pbuf_header(p, -(s16_t)ip_data.current_ip_header_tot_len); + icmp6_input(p, inp); + break; +#endif /* LWIP_ICMP */ + default: +#if LWIP_ICMP6 + /* send ICMP parameter problem unless it was a multicast or ICMPv6 */ + if ((!ip6_addr_ismulticast(ip6_current_dest_addr())) && + (IP6H_NEXTH(ip6hdr) != IP6_NEXTH_ICMP6)) { + icmp6_param_problem(p, ICMP6_PP_HEADER, ip_data.current_ip_header_tot_len - hlen); + } +#endif /* LWIP_ICMP */ + LWIP_DEBUGF(IP6_DEBUG | LWIP_DBG_LEVEL_SERIOUS, ("ip6_input: Unsupported transport protocol %"U16_F"\n", IP6H_NEXTH(ip6hdr))); + pbuf_free(p); + IP6_STATS_INC(ip6.proterr); + IP6_STATS_INC(ip6.drop); + break; + } + } + +ip6_input_cleanup: + ip_data.current_netif = NULL; + ip_data.current_input_netif = NULL; + ip_data.current_ip6_header = NULL; + ip_data.current_ip_header_tot_len = 0; + ip6_addr_set_zero(ip6_current_src_addr()); + ip6_addr_set_zero(ip6_current_dest_addr()); + + return ERR_OK; +} + + +/** + * Sends an IPv6 packet on a network interface. This function constructs + * the IPv6 header. If the source IPv6 address is NULL, the IPv6 "ANY" address is + * used as source (usually during network startup). If the source IPv6 address it + * IP6_ADDR_ANY, the most appropriate IPv6 address of the outgoing network + * interface is filled in as source address. If the destination IPv6 address is + * IP_HDRINCL, p is assumed to already include an IPv6 header and p->payload points + * to it instead of the data. + * + * @param p the packet to send (p->payload points to the data, e.g. next + protocol header; if dest == IP_HDRINCL, p already includes an + IPv6 header and p->payload points to that IPv6 header) + * @param src the source IPv6 address to send from (if src == IP6_ADDR_ANY, an + * IP address of the netif is selected and used as source address. + * if src == NULL, IP6_ADDR_ANY is used as source) + * @param dest the destination IPv6 address to send the packet to + * @param hl the Hop Limit value to be set in the IPv6 header + * @param tc the Traffic Class value to be set in the IPv6 header + * @param nexth the Next Header to be set in the IPv6 header + * @param netif the netif on which to send this packet + * @return ERR_OK if the packet was sent OK + * ERR_BUF if p doesn't have enough space for IPv6/LINK headers + * returns errors returned by netif->output + */ +err_t +ip6_output_if(struct pbuf *p, const ip6_addr_t *src, const ip6_addr_t *dest, + u8_t hl, u8_t tc, + u8_t nexth, struct netif *netif) +{ + const ip6_addr_t *src_used = src; + if (dest != IP_HDRINCL) { + if (src != NULL && ip6_addr_isany(src)) { + src = ip_2_ip6(ip6_select_source_address(netif, dest)); + if ((src == NULL) || ip6_addr_isany(src)) { + /* No appropriate source address was found for this packet. */ + LWIP_DEBUGF(IP6_DEBUG | LWIP_DBG_LEVEL_SERIOUS, ("ip6_output: No suitable source address for packet.\n")); + IP6_STATS_INC(ip6.rterr); + return ERR_RTE; + } + } + } + return ip6_output_if_src(p, src_used, dest, hl, tc, nexth, netif); +} + +/** + * Same as ip6_output_if() but 'src' address is not replaced by netif address + * when it is 'any'. + */ +err_t +ip6_output_if_src(struct pbuf *p, const ip6_addr_t *src, const ip6_addr_t *dest, + u8_t hl, u8_t tc, + u8_t nexth, struct netif *netif) +{ + struct ip6_hdr *ip6hdr; + ip6_addr_t dest_addr; + + LWIP_IP_CHECK_PBUF_REF_COUNT_FOR_TX(p); + + /* Should the IPv6 header be generated or is it already included in p? */ + if (dest != IP_HDRINCL) { + /* generate IPv6 header */ + if (pbuf_header(p, IP6_HLEN)) { + LWIP_DEBUGF(IP6_DEBUG | LWIP_DBG_LEVEL_SERIOUS, ("ip6_output: not enough room for IPv6 header in pbuf\n")); + IP6_STATS_INC(ip6.err); + return ERR_BUF; + } + + ip6hdr = (struct ip6_hdr *)p->payload; + LWIP_ASSERT("check that first pbuf can hold struct ip6_hdr", + (p->len >= sizeof(struct ip6_hdr))); + + IP6H_HOPLIM_SET(ip6hdr, hl); + IP6H_NEXTH_SET(ip6hdr, nexth); + + /* dest cannot be NULL here */ + ip6_addr_copy(ip6hdr->dest, *dest); + + IP6H_VTCFL_SET(ip6hdr, 6, tc, 0); + IP6H_PLEN_SET(ip6hdr, p->tot_len - IP6_HLEN); + + if (src == NULL) { + src = IP6_ADDR_ANY6; + } + /* src cannot be NULL here */ + ip6_addr_copy(ip6hdr->src, *src); + + } else { + /* IP header already included in p */ + ip6hdr = (struct ip6_hdr *)p->payload; + ip6_addr_copy(dest_addr, ip6hdr->dest); + dest = &dest_addr; + } + + IP6_STATS_INC(ip6.xmit); + + LWIP_DEBUGF(IP6_DEBUG, ("ip6_output_if: %c%c%"U16_F"\n", netif->name[0], netif->name[1], netif->num)); + ip6_debug_print(p); + +#if ENABLE_LOOPBACK + { + int i; +#if !LWIP_HAVE_LOOPIF + if (ip6_addr_isloopback(dest)) { + return netif_loop_output(netif, p); + } +#endif /* !LWIP_HAVE_LOOPIF */ + for (i = 0; i < LWIP_IPV6_NUM_ADDRESSES; i++) { + if (ip6_addr_isvalid(netif_ip6_addr_state(netif, i)) && + ip6_addr_cmp(dest, netif_ip6_addr(netif, i))) { + /* Packet to self, enqueue it for loopback */ + LWIP_DEBUGF(IP6_DEBUG, ("netif_loop_output()\n")); + return netif_loop_output(netif, p); + } + } + } +#endif /* ENABLE_LOOPBACK */ +#if LWIP_IPV6_FRAG + /* don't fragment if interface has mtu set to 0 [loopif] */ + if (netif->mtu && (p->tot_len > nd6_get_destination_mtu(dest, netif))) { + return ip6_frag(p, netif, dest); + } +#endif /* LWIP_IPV6_FRAG */ + + LWIP_DEBUGF(IP6_DEBUG, ("netif->output_ip6()\n")); + return netif->output_ip6(netif, p, dest); +} + +/** + * Simple interface to ip6_output_if. It finds the outgoing network + * interface and calls upon ip6_output_if to do the actual work. + * + * @param p the packet to send (p->payload points to the data, e.g. next + protocol header; if dest == IP_HDRINCL, p already includes an + IPv6 header and p->payload points to that IPv6 header) + * @param src the source IPv6 address to send from (if src == IP6_ADDR_ANY, an + * IP address of the netif is selected and used as source address. + * if src == NULL, IP6_ADDR_ANY is used as source) + * @param dest the destination IPv6 address to send the packet to + * @param hl the Hop Limit value to be set in the IPv6 header + * @param tc the Traffic Class value to be set in the IPv6 header + * @param nexth the Next Header to be set in the IPv6 header + * + * @return ERR_RTE if no route is found + * see ip_output_if() for more return values + */ +err_t +ip6_output(struct pbuf *p, const ip6_addr_t *src, const ip6_addr_t *dest, + u8_t hl, u8_t tc, u8_t nexth) +{ + struct netif *netif; + struct ip6_hdr *ip6hdr; + ip6_addr_t src_addr, dest_addr; + + LWIP_IP_CHECK_PBUF_REF_COUNT_FOR_TX(p); + + if (dest != IP_HDRINCL) { + netif = ip6_route(src, dest); + } else { + /* IP header included in p, read addresses. */ + ip6hdr = (struct ip6_hdr *)p->payload; + ip6_addr_copy(src_addr, ip6hdr->src); + ip6_addr_copy(dest_addr, ip6hdr->dest); + netif = ip6_route(&src_addr, &dest_addr); + } + + if (netif == NULL) { + LWIP_DEBUGF(IP6_DEBUG, ("ip6_output: no route for %"X16_F":%"X16_F":%"X16_F":%"X16_F":%"X16_F":%"X16_F":%"X16_F":%"X16_F"\n", + IP6_ADDR_BLOCK1(dest), + IP6_ADDR_BLOCK2(dest), + IP6_ADDR_BLOCK3(dest), + IP6_ADDR_BLOCK4(dest), + IP6_ADDR_BLOCK5(dest), + IP6_ADDR_BLOCK6(dest), + IP6_ADDR_BLOCK7(dest), + IP6_ADDR_BLOCK8(dest))); + IP6_STATS_INC(ip6.rterr); + return ERR_RTE; + } + + return ip6_output_if(p, src, dest, hl, tc, nexth, netif); +} + + +#if LWIP_NETIF_HWADDRHINT +/** Like ip6_output, but takes and addr_hint pointer that is passed on to netif->addr_hint + * before calling ip6_output_if. + * + * @param p the packet to send (p->payload points to the data, e.g. next + protocol header; if dest == IP_HDRINCL, p already includes an + IPv6 header and p->payload points to that IPv6 header) + * @param src the source IPv6 address to send from (if src == IP6_ADDR_ANY, an + * IP address of the netif is selected and used as source address. + * if src == NULL, IP6_ADDR_ANY is used as source) + * @param dest the destination IPv6 address to send the packet to + * @param hl the Hop Limit value to be set in the IPv6 header + * @param tc the Traffic Class value to be set in the IPv6 header + * @param nexth the Next Header to be set in the IPv6 header + * @param addr_hint address hint pointer set to netif->addr_hint before + * calling ip_output_if() + * + * @return ERR_RTE if no route is found + * see ip_output_if() for more return values + */ +err_t +ip6_output_hinted(struct pbuf *p, const ip6_addr_t *src, const ip6_addr_t *dest, + u8_t hl, u8_t tc, u8_t nexth, u8_t *addr_hint) +{ + struct netif *netif; + struct ip6_hdr *ip6hdr; + ip6_addr_t src_addr, dest_addr; + err_t err; + + LWIP_IP_CHECK_PBUF_REF_COUNT_FOR_TX(p); + + if (dest != IP_HDRINCL) { + netif = ip6_route(src, dest); + } else { + /* IP header included in p, read addresses. */ + ip6hdr = (struct ip6_hdr *)p->payload; + ip6_addr_copy(src_addr, ip6hdr->src); + ip6_addr_copy(dest_addr, ip6hdr->dest); + netif = ip6_route(&src_addr, &dest_addr); + } + + if (netif == NULL) { + LWIP_DEBUGF(IP6_DEBUG, ("ip6_output: no route for %"X16_F":%"X16_F":%"X16_F":%"X16_F":%"X16_F":%"X16_F":%"X16_F":%"X16_F"\n", + IP6_ADDR_BLOCK1(dest), + IP6_ADDR_BLOCK2(dest), + IP6_ADDR_BLOCK3(dest), + IP6_ADDR_BLOCK4(dest), + IP6_ADDR_BLOCK5(dest), + IP6_ADDR_BLOCK6(dest), + IP6_ADDR_BLOCK7(dest), + IP6_ADDR_BLOCK8(dest))); + IP6_STATS_INC(ip6.rterr); + return ERR_RTE; + } + + NETIF_SET_HWADDRHINT(netif, addr_hint); + err = ip6_output_if(p, src, dest, hl, tc, nexth, netif); + NETIF_SET_HWADDRHINT(netif, NULL); + + return err; +} +#endif /* LWIP_NETIF_HWADDRHINT*/ + +#if LWIP_IPV6_MLD +/** + * Add a hop-by-hop options header with a router alert option and padding. + * + * Used by MLD when sending a Multicast listener report/done message. + * + * @param p the packet to which we will prepend the options header + * @param nexth the next header protocol number (e.g. IP6_NEXTH_ICMP6) + * @param value the value of the router alert option data (e.g. IP6_ROUTER_ALERT_VALUE_MLD) + * @return ERR_OK if hop-by-hop header was added, ERR_* otherwise + */ +err_t +ip6_options_add_hbh_ra(struct pbuf * p, u8_t nexth, u8_t value) +{ + struct ip6_hbh_hdr * hbh_hdr; + + /* Move pointer to make room for hop-by-hop options header. */ + if (pbuf_header(p, sizeof(struct ip6_hbh_hdr))) { + LWIP_DEBUGF(IP6_DEBUG, ("ip6_options: no space for options header\n")); + IP6_STATS_INC(ip6.err); + return ERR_BUF; + } + + hbh_hdr = (struct ip6_hbh_hdr *)p->payload; + + /* Set fields. */ + hbh_hdr->_nexth = nexth; + hbh_hdr->_hlen = 0; + hbh_hdr->_ra_opt_type = IP6_ROUTER_ALERT_OPTION; + hbh_hdr->_ra_opt_dlen = 2; + hbh_hdr->_ra_opt_data = value; + hbh_hdr->_padn_opt_type = IP6_PADN_ALERT_OPTION; + hbh_hdr->_padn_opt_dlen = 0; + + return ERR_OK; +} +#endif /* LWIP_IPV6_MLD */ + +#if IP6_DEBUG +/* Print an IPv6 header by using LWIP_DEBUGF + * @param p an IPv6 packet, p->payload pointing to the IPv6 header + */ +void +ip6_debug_print(struct pbuf *p) +{ + struct ip6_hdr *ip6hdr = (struct ip6_hdr *)p->payload; + + LWIP_DEBUGF(IP6_DEBUG, ("IPv6 header:\n")); + LWIP_DEBUGF(IP6_DEBUG, ("+-------------------------------+\n")); + LWIP_DEBUGF(IP6_DEBUG, ("| %2"U16_F" | %3"U16_F" | %7"U32_F" | (ver, class, flow)\n", + IP6H_V(ip6hdr), + IP6H_TC(ip6hdr), + IP6H_FL(ip6hdr))); + LWIP_DEBUGF(IP6_DEBUG, ("+-------------------------------+\n")); + LWIP_DEBUGF(IP6_DEBUG, ("| %5"U16_F" | %3"U16_F" | %3"U16_F" | (plen, nexth, hopl)\n", + IP6H_PLEN(ip6hdr), + IP6H_NEXTH(ip6hdr), + IP6H_HOPLIM(ip6hdr))); + LWIP_DEBUGF(IP6_DEBUG, ("+-------------------------------+\n")); + LWIP_DEBUGF(IP6_DEBUG, ("| %4"X32_F" | %4"X32_F" | %4"X32_F" | %4"X32_F" | (src)\n", + IP6_ADDR_BLOCK1(&(ip6hdr->src)), + IP6_ADDR_BLOCK2(&(ip6hdr->src)), + IP6_ADDR_BLOCK3(&(ip6hdr->src)), + IP6_ADDR_BLOCK4(&(ip6hdr->src)))); + LWIP_DEBUGF(IP6_DEBUG, ("| %4"X32_F" | %4"X32_F" | %4"X32_F" | %4"X32_F" |\n", + IP6_ADDR_BLOCK5(&(ip6hdr->src)), + IP6_ADDR_BLOCK6(&(ip6hdr->src)), + IP6_ADDR_BLOCK7(&(ip6hdr->src)), + IP6_ADDR_BLOCK8(&(ip6hdr->src)))); + LWIP_DEBUGF(IP6_DEBUG, ("+-------------------------------+\n")); + LWIP_DEBUGF(IP6_DEBUG, ("| %4"X32_F" | %4"X32_F" | %4"X32_F" | %4"X32_F" | (dest)\n", + IP6_ADDR_BLOCK1(&(ip6hdr->dest)), + IP6_ADDR_BLOCK2(&(ip6hdr->dest)), + IP6_ADDR_BLOCK3(&(ip6hdr->dest)), + IP6_ADDR_BLOCK4(&(ip6hdr->dest)))); + LWIP_DEBUGF(IP6_DEBUG, ("| %4"X32_F" | %4"X32_F" | %4"X32_F" | %4"X32_F" |\n", + IP6_ADDR_BLOCK5(&(ip6hdr->dest)), + IP6_ADDR_BLOCK6(&(ip6hdr->dest)), + IP6_ADDR_BLOCK7(&(ip6hdr->dest)), + IP6_ADDR_BLOCK8(&(ip6hdr->dest)))); + LWIP_DEBUGF(IP6_DEBUG, ("+-------------------------------+\n")); +} +#endif /* IP6_DEBUG */ + +#endif /* LWIP_IPV6 */ diff --git a/components/lwip/core/ipv6/ip6_addr.c b/components/lwip/core/ipv6/ip6_addr.c new file mode 100755 index 0000000000..44d5760702 --- /dev/null +++ b/components/lwip/core/ipv6/ip6_addr.c @@ -0,0 +1,292 @@ +/** + * @file + * + * IPv6 addresses. + */ + +/* + * Copyright (c) 2010 Inico Technologies Ltd. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Ivan Delamer + * + * Functions for handling IPv6 addresses. + * + * Please coordinate changes and requests with Ivan Delamer + * + */ + +#include "lwip/opt.h" + +#if LWIP_IPV6 /* don't build if not configured for use in lwipopts.h */ + +#include "lwip/ip_addr.h" +#include "lwip/def.h" + +/* used by IP6_ADDR_ANY(6) in ip6_addr.h */ +const ip_addr_t ip6_addr_any = IPADDR6_INIT(0ul, 0ul, 0ul, 0ul); + +#ifndef isprint +#define in_range(c, lo, up) ((u8_t)c >= lo && (u8_t)c <= up) +#define isprint(c) in_range(c, 0x20, 0x7f) +#define isdigit(c) in_range(c, '0', '9') +#define isxdigit(c) (isdigit(c) || in_range(c, 'a', 'f') || in_range(c, 'A', 'F')) +#define islower(c) in_range(c, 'a', 'z') +#define isspace(c) (c == ' ' || c == '\f' || c == '\n' || c == '\r' || c == '\t' || c == '\v') +#define xchar(i) ((i) < 10 ? '0' + (i) : 'A' + (i) - 10) +#endif + +/** + * Check whether "cp" is a valid ascii representation + * of an IPv6 address and convert to a binary address. + * Returns 1 if the address is valid, 0 if not. + * + * @param cp IPv6 address in ascii representation (e.g. "FF01::1") + * @param addr pointer to which to save the ip address in network order + * @return 1 if cp could be converted to addr, 0 on failure + */ +int +ip6addr_aton(const char *cp, ip6_addr_t *addr) +{ + u32_t addr_index, zero_blocks, current_block_index, current_block_value; + const char * s; + + /* Count the number of colons, to count the number of blocks in a "::" sequence + zero_blocks may be 1 even if there are no :: sequences */ + zero_blocks = 8; + for (s = cp; *s != 0; s++) { + if (*s == ':') { + zero_blocks--; + } else if (!isxdigit(*s)) { + break; + } + } + + /* parse each block */ + addr_index = 0; + current_block_index = 0; + current_block_value = 0; + for (s = cp; *s != 0; s++) { + if (*s == ':') { + if (addr) { + if (current_block_index & 0x1) { + addr->addr[addr_index++] |= current_block_value; + } + else { + addr->addr[addr_index] = current_block_value << 16; + } + } + current_block_index++; + current_block_value = 0; + if (current_block_index > 7) { + /* address too long! */ + return 0; + } + if (s[1] == ':') { + if (s[2] == ':') { + /* invalid format: three successive colons */ + return 0; + } + s++; + /* "::" found, set zeros */ + while (zero_blocks > 0) { + zero_blocks--; + if (current_block_index & 0x1) { + addr_index++; + } else { + if (addr) { + addr->addr[addr_index] = 0; + } + } + current_block_index++; + if (current_block_index > 7) { + /* address too long! */ + return 0; + } + } + } + } else if (isxdigit(*s)) { + /* add current digit */ + current_block_value = (current_block_value << 4) + + (isdigit(*s) ? *s - '0' : + 10 + (islower(*s) ? *s - 'a' : *s - 'A')); + } else { + /* unexpected digit, space? CRLF? */ + break; + } + } + + if (addr) { + if (current_block_index & 0x1) { + addr->addr[addr_index++] |= current_block_value; + } + else { + addr->addr[addr_index] = current_block_value << 16; + } + } + + /* convert to network byte order. */ + if (addr) { + for (addr_index = 0; addr_index < 4; addr_index++) { + addr->addr[addr_index] = htonl(addr->addr[addr_index]); + } + } + + if (current_block_index != 7) { + return 0; + } + + return 1; +} + +/** + * Convert numeric IPv6 address into ASCII representation. + * returns ptr to static buffer; not reentrant! + * + * @param addr ip6 address in network order to convert + * @return pointer to a global static (!) buffer that holds the ASCII + * representation of addr + */ +char * +ip6addr_ntoa(const ip6_addr_t *addr) +{ + static char str[40]; + return ip6addr_ntoa_r(addr, str, 40); +} + +/** + * Same as ipaddr_ntoa, but reentrant since a user-supplied buffer is used. + * + * @param addr ip6 address in network order to convert + * @param buf target buffer where the string is stored + * @param buflen length of buf + * @return either pointer to buf which now holds the ASCII + * representation of addr or NULL if buf was too small + */ +char * +ip6addr_ntoa_r(const ip6_addr_t *addr, char *buf, int buflen) +{ + u32_t current_block_index, current_block_value, next_block_value; + s32_t i; + u8_t zero_flag, empty_block_flag; + + i = 0; + empty_block_flag = 0; /* used to indicate a zero chain for "::' */ + + for (current_block_index = 0; current_block_index < 8; current_block_index++) { + /* get the current 16-bit block */ + current_block_value = htonl(addr->addr[current_block_index >> 1]); + if ((current_block_index & 0x1) == 0) { + current_block_value = current_block_value >> 16; + } + current_block_value &= 0xffff; + + /* Check for empty block. */ + if (current_block_value == 0) { + if (current_block_index == 7) { + /* special case, we must render a ':' for the last block. */ + buf[i++] = ':'; + if (i >= buflen) { + return NULL; + } + break; + } + if (empty_block_flag == 0) { + /* generate empty block "::", but only if more than one contiguous zero block, + * according to current formatting suggestions RFC 5952. */ + next_block_value = htonl(addr->addr[(current_block_index + 1) >> 1]); + if ((current_block_index & 0x1) == 0x01) { + next_block_value = next_block_value >> 16; + } + next_block_value &= 0xffff; + if (next_block_value == 0) { + empty_block_flag = 1; + buf[i++] = ':'; + if (i >= buflen) { + return NULL; + } + continue; /* move on to next block. */ + } + } else if (empty_block_flag == 1) { + /* move on to next block. */ + continue; + } + } else if (empty_block_flag == 1) { + /* Set this flag value so we don't produce multiple empty blocks. */ + empty_block_flag = 2; + } + + if (current_block_index > 0) { + buf[i++] = ':'; + if (i >= buflen) { + return NULL; + } + } + + if ((current_block_value & 0xf000) == 0) { + zero_flag = 1; + } else { + buf[i++] = xchar(((current_block_value & 0xf000) >> 12)); + zero_flag = 0; + if (i >= buflen) { + return NULL; + } + } + + if (((current_block_value & 0xf00) == 0) && (zero_flag)) { + /* do nothing */ + } else { + buf[i++] = xchar(((current_block_value & 0xf00) >> 8)); + zero_flag = 0; + if (i >= buflen) { + return NULL; + } + } + + if (((current_block_value & 0xf0) == 0) && (zero_flag)) { + /* do nothing */ + } + else { + buf[i++] = xchar(((current_block_value & 0xf0) >> 4)); + zero_flag = 0; + if (i >= buflen) { + return NULL; + } + } + + buf[i++] = xchar((current_block_value & 0xf)); + if (i >= buflen) { + return NULL; + } + } + + buf[i] = 0; + + return buf; +} + +#endif /* LWIP_IPV6 */ diff --git a/components/lwip/core/ipv6/ip6_frag.c b/components/lwip/core/ipv6/ip6_frag.c new file mode 100755 index 0000000000..0792c2e1be --- /dev/null +++ b/components/lwip/core/ipv6/ip6_frag.c @@ -0,0 +1,778 @@ +/** + * @file + * + * IPv6 fragmentation and reassembly. + */ + +/* + * Copyright (c) 2010 Inico Technologies Ltd. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Ivan Delamer + * + * + * Please coordinate changes and requests with Ivan Delamer + * + */ + +#include "lwip/opt.h" +#include "lwip/ip6_frag.h" +#include "lwip/ip6.h" +#include "lwip/icmp6.h" +#include "lwip/nd6.h" +#include "lwip/ip.h" + +#include "lwip/pbuf.h" +#include "lwip/memp.h" +#include "lwip/stats.h" + +#include + +#ifdef MEMLEAK_DEBUG +static const char mem_debug_file[] ICACHE_RODATA_ATTR STORE_ATTR = __FILE__; +#endif + + +#if LWIP_IPV6 && LWIP_IPV6_REASS /* don't build if not configured for use in lwipopts.h */ + + +/** Setting this to 0, you can turn off checking the fragments for overlapping + * regions. The code gets a little smaller. Only use this if you know that + * overlapping won't occur on your network! */ +#ifndef IP_REASS_CHECK_OVERLAP +#define IP_REASS_CHECK_OVERLAP 1 +#endif /* IP_REASS_CHECK_OVERLAP */ + +/** Set to 0 to prevent freeing the oldest datagram when the reassembly buffer is + * full (IP_REASS_MAX_PBUFS pbufs are enqueued). The code gets a little smaller. + * Datagrams will be freed by timeout only. Especially useful when MEMP_NUM_REASSDATA + * is set to 1, so one datagram can be reassembled at a time, only. */ +#ifndef IP_REASS_FREE_OLDEST +#define IP_REASS_FREE_OLDEST 1 +#endif /* IP_REASS_FREE_OLDEST */ + +#if IPV6_FRAG_COPYHEADER +#define IPV6_FRAG_REQROOM ((s16_t)(sizeof(struct ip6_reass_helper) - IP6_FRAG_HLEN)) +#endif + +#define IP_REASS_FLAG_LASTFRAG 0x01 + +/** This is a helper struct which holds the starting + * offset and the ending offset of this fragment to + * easily chain the fragments. + * It has the same packing requirements as the IPv6 header, since it replaces + * the Fragment Header in memory in incoming fragments to keep + * track of the various fragments. + */ +#ifdef PACK_STRUCT_USE_INCLUDES +# include "arch/bpstruct.h" +#endif +PACK_STRUCT_BEGIN +struct ip6_reass_helper { + PACK_STRUCT_FIELD(struct pbuf *next_pbuf); + PACK_STRUCT_FIELD(u16_t start); + PACK_STRUCT_FIELD(u16_t end); +} PACK_STRUCT_STRUCT; +PACK_STRUCT_END +#ifdef PACK_STRUCT_USE_INCLUDES +# include "arch/epstruct.h" +#endif + +/* static variables */ +static struct ip6_reassdata *reassdatagrams; +static u16_t ip6_reass_pbufcount; + +/* Forward declarations. */ +static void ip6_reass_free_complete_datagram(struct ip6_reassdata *ipr); +#if IP_REASS_FREE_OLDEST +static void ip6_reass_remove_oldest_datagram(struct ip6_reassdata *ipr, int pbufs_needed); +#endif /* IP_REASS_FREE_OLDEST */ + +void +ip6_reass_tmr(void) +{ + struct ip6_reassdata *r, *tmp; + +#if !IPV6_FRAG_COPYHEADER + LWIP_ASSERT("sizeof(struct ip6_reass_helper) <= IP6_FRAG_HLEN, set IPV6_FRAG_COPYHEADER to 1", + sizeof(struct ip6_reass_helper) <= IP6_FRAG_HLEN); +#endif /* !IPV6_FRAG_COPYHEADER */ + + r = reassdatagrams; + while (r != NULL) { + /* Decrement the timer. Once it reaches 0, + * clean up the incomplete fragment assembly */ + if (r->timer > 0) { + r->timer--; + r = r->next; + } else { + /* reassembly timed out */ + tmp = r; + /* get the next pointer before freeing */ + r = r->next; + /* free the helper struct and all enqueued pbufs */ + ip6_reass_free_complete_datagram(tmp); + } + } +} + +/** + * Free a datagram (struct ip6_reassdata) and all its pbufs. + * Updates the total count of enqueued pbufs (ip6_reass_pbufcount), + * sends an ICMP time exceeded packet. + * + * @param ipr datagram to free + */ +static void +ip6_reass_free_complete_datagram(struct ip6_reassdata *ipr) +{ + struct ip6_reassdata *prev; + u16_t pbufs_freed = 0; + u8_t clen; + struct pbuf *p; + struct ip6_reass_helper *iprh; + +#if LWIP_ICMP6 + iprh = (struct ip6_reass_helper *)ipr->p->payload; + if (iprh->start == 0) { + /* The first fragment was received, send ICMP time exceeded. */ + /* First, de-queue the first pbuf from r->p. */ + p = ipr->p; + ipr->p = iprh->next_pbuf; + /* Then, move back to the original ipv6 header (we are now pointing to Fragment header). + This cannot fail since we already checked when receiving this fragment. */ + if (pbuf_header_force(p, (s16_t)((u8_t*)p->payload - (u8_t*)IPV6_FRAG_HDRREF(ipr->iphdr)))) { + LWIP_ASSERT("ip6_reass_free: moving p->payload to ip6 header failed\n", 0); + } + else { + icmp6_time_exceeded(p, ICMP6_TE_FRAG); + } + clen = pbuf_clen(p); + LWIP_ASSERT("pbufs_freed + clen <= 0xffff", pbufs_freed + clen <= 0xffff); + pbufs_freed += clen; + pbuf_free(p); + } +#endif /* LWIP_ICMP6 */ + + /* First, free all received pbufs. The individual pbufs need to be released + separately as they have not yet been chained */ + p = ipr->p; + while (p != NULL) { + struct pbuf *pcur; + iprh = (struct ip6_reass_helper *)p->payload; + pcur = p; + /* get the next pointer before freeing */ + p = iprh->next_pbuf; + clen = pbuf_clen(pcur); + LWIP_ASSERT("pbufs_freed + clen <= 0xffff", pbufs_freed + clen <= 0xffff); + pbufs_freed += clen; + pbuf_free(pcur); + } + + /* Then, unchain the struct ip6_reassdata from the list and free it. */ + if (ipr == reassdatagrams) { + reassdatagrams = ipr->next; + } else { + prev = reassdatagrams; + while (prev != NULL) { + if (prev->next == ipr) { + break; + } + prev = prev->next; + } + if (prev != NULL) { + prev->next = ipr->next; + } + } + memp_free(MEMP_IP6_REASSDATA, ipr); + + /* Finally, update number of pbufs in reassembly queue */ + LWIP_ASSERT("ip_reass_pbufcount >= clen", ip6_reass_pbufcount >= pbufs_freed); + ip6_reass_pbufcount -= pbufs_freed; +} + +#if IP_REASS_FREE_OLDEST +/** + * Free the oldest datagram to make room for enqueueing new fragments. + * The datagram ipr is not freed! + * + * @param ipr ip6_reassdata for the current fragment + * @param pbufs_needed number of pbufs needed to enqueue + * (used for freeing other datagrams if not enough space) + */ +static void +ip6_reass_remove_oldest_datagram(struct ip6_reassdata *ipr, int pbufs_needed) +{ + struct ip6_reassdata *r, *oldest; + + /* Free datagrams until being allowed to enqueue 'pbufs_needed' pbufs, + * but don't free the current datagram! */ + do { + r = oldest = reassdatagrams; + while (r != NULL) { + if (r != ipr) { + if (r->timer <= oldest->timer) { + /* older than the previous oldest */ + oldest = r; + } + } + r = r->next; + } + if (oldest == ipr) { + /* nothing to free, ipr is the only element on the list */ + return; + } + if (oldest != NULL) { + ip6_reass_free_complete_datagram(oldest); + } + } while (((ip6_reass_pbufcount + pbufs_needed) > IP_REASS_MAX_PBUFS) && (reassdatagrams != NULL)); +} +#endif /* IP_REASS_FREE_OLDEST */ + +/** + * Reassembles incoming IPv6 fragments into an IPv6 datagram. + * + * @param p points to the IPv6 Fragment Header + * @param len the length of the payload (after Fragment Header) + * @return NULL if reassembly is incomplete, pbuf pointing to + * IPv6 Header if reassembly is complete + */ +struct pbuf * +ip6_reass(struct pbuf *p) +{ + struct ip6_reassdata *ipr, *ipr_prev; + struct ip6_reass_helper *iprh, *iprh_tmp, *iprh_prev=NULL; + struct ip6_frag_hdr * frag_hdr; + u16_t offset, len; + u8_t clen, valid = 1; + struct pbuf *q; + + IP6_FRAG_STATS_INC(ip6_frag.recv); + + LWIP_ASSERT("ip6_frag_hdr must be in the first pbuf, not chained", + (const void*)ip6_current_header() == ((u8_t*)p->payload) - IP6_HLEN); + + frag_hdr = (struct ip6_frag_hdr *) p->payload; + + clen = pbuf_clen(p); + + offset = ntohs(frag_hdr->_fragment_offset); + + /* Calculate fragment length from IPv6 payload length. + * Adjust for headers before Fragment Header. + * And finally adjust by Fragment Header length. */ + len = ntohs(ip6_current_header()->_plen); + len -= (u16_t)(((u8_t*)p->payload - (const u8_t*)ip6_current_header()) - IP6_HLEN); + len -= IP6_FRAG_HLEN; + + /* Look for the datagram the fragment belongs to in the current datagram queue, + * remembering the previous in the queue for later dequeueing. */ + for (ipr = reassdatagrams, ipr_prev = NULL; ipr != NULL; ipr = ipr->next) { + /* Check if the incoming fragment matches the one currently present + in the reassembly buffer. If so, we proceed with copying the + fragment into the buffer. */ + if ((frag_hdr->_identification == ipr->identification) && + ip6_addr_cmp(ip6_current_src_addr(), &(IPV6_FRAG_HDRREF(ipr->iphdr)->src)) && + ip6_addr_cmp(ip6_current_dest_addr(), &(IPV6_FRAG_HDRREF(ipr->iphdr)->dest))) { + IP6_FRAG_STATS_INC(ip6_frag.cachehit); + break; + } + ipr_prev = ipr; + } + + if (ipr == NULL) { + /* Enqueue a new datagram into the datagram queue */ + ipr = (struct ip6_reassdata *)memp_malloc(MEMP_IP6_REASSDATA); + if (ipr == NULL) { +#if IP_REASS_FREE_OLDEST + /* Make room and try again. */ + ip6_reass_remove_oldest_datagram(ipr, clen); + ipr = (struct ip6_reassdata *)memp_malloc(MEMP_IP6_REASSDATA); + if (ipr != NULL) { + /* re-search ipr_prev since it might have been removed */ + for (ipr_prev = reassdatagrams; ipr_prev != NULL; ipr_prev = ipr_prev->next) { + if (ipr_prev->next == ipr) { + break; + } + } + } else +#endif /* IP_REASS_FREE_OLDEST */ + { + IP6_FRAG_STATS_INC(ip6_frag.memerr); + IP6_FRAG_STATS_INC(ip6_frag.drop); + goto nullreturn; + } + } + + memset(ipr, 0, sizeof(struct ip6_reassdata)); + ipr->timer = IP_REASS_MAXAGE; + + /* enqueue the new structure to the front of the list */ + ipr->next = reassdatagrams; + reassdatagrams = ipr; + + /* Use the current IPv6 header for src/dest address reference. + * Eventually, we will replace it when we get the first fragment + * (it might be this one, in any case, it is done later). */ +#if IPV6_FRAG_COPYHEADER + MEMCPY(&ipr->iphdr, ip6_current_header(), IP6_HLEN); +#else /* IPV6_FRAG_COPYHEADER */ + /* need to use the none-const pointer here: */ + ipr->iphdr = ip_data.current_ip6_header; +#endif /* IPV6_FRAG_COPYHEADER */ + + /* copy the fragmented packet id. */ + ipr->identification = frag_hdr->_identification; + + /* copy the nexth field */ + ipr->nexth = frag_hdr->_nexth; + } + + /* Check if we are allowed to enqueue more datagrams. */ + if ((ip6_reass_pbufcount + clen) > IP_REASS_MAX_PBUFS) { +#if IP_REASS_FREE_OLDEST + ip6_reass_remove_oldest_datagram(ipr, clen); + if ((ip6_reass_pbufcount + clen) <= IP_REASS_MAX_PBUFS) { + /* re-search ipr_prev since it might have been removed */ + for (ipr_prev = reassdatagrams; ipr_prev != NULL; ipr_prev = ipr_prev->next) { + if (ipr_prev->next == ipr) { + break; + } + } + } else +#endif /* IP_REASS_FREE_OLDEST */ + { + /* @todo: send ICMPv6 time exceeded here? */ + /* drop this pbuf */ + IP6_FRAG_STATS_INC(ip6_frag.memerr); + IP6_FRAG_STATS_INC(ip6_frag.drop); + goto nullreturn; + } + } + + /* Overwrite Fragment Header with our own helper struct. */ +#if IPV6_FRAG_COPYHEADER + if (IPV6_FRAG_REQROOM > 0) { + /* Make room for struct ip6_reass_helper (only required if sizeof(void*) > 4). + This cannot fail since we already checked when receiving this fragment. */ + err_t hdrerr = pbuf_header_force(p, IPV6_FRAG_REQROOM); + LWIP_ASSERT("no room for struct ip6_reass_helper", hdrerr == ERR_OK); + } +#else /* IPV6_FRAG_COPYHEADER */ + LWIP_ASSERT("sizeof(struct ip6_reass_helper) <= IP6_FRAG_HLEN, set IPV6_FRAG_COPYHEADER to 1", + sizeof(struct ip6_reass_helper) <= IP6_FRAG_HLEN); +#endif /* IPV6_FRAG_COPYHEADER */ + iprh = (struct ip6_reass_helper *)p->payload; + iprh->next_pbuf = NULL; + iprh->start = (offset & IP6_FRAG_OFFSET_MASK); + iprh->end = (offset & IP6_FRAG_OFFSET_MASK) + len; + + /* find the right place to insert this pbuf */ + /* Iterate through until we either get to the end of the list (append), + * or we find on with a larger offset (insert). */ + for (q = ipr->p; q != NULL;) { + iprh_tmp = (struct ip6_reass_helper*)q->payload; + if (iprh->start < iprh_tmp->start) { +#if IP_REASS_CHECK_OVERLAP + if (iprh->end > iprh_tmp->start) { + /* fragment overlaps with following, throw away */ + IP6_FRAG_STATS_INC(ip6_frag.proterr); + IP6_FRAG_STATS_INC(ip6_frag.drop); + goto nullreturn; + } + if (iprh_prev != NULL) { + if (iprh->start < iprh_prev->end) { + /* fragment overlaps with previous, throw away */ + IP6_FRAG_STATS_INC(ip6_frag.proterr); + IP6_FRAG_STATS_INC(ip6_frag.drop); + goto nullreturn; + } + } +#endif /* IP_REASS_CHECK_OVERLAP */ + /* the new pbuf should be inserted before this */ + iprh->next_pbuf = q; + if (iprh_prev != NULL) { + /* not the fragment with the lowest offset */ + iprh_prev->next_pbuf = p; + } else { + /* fragment with the lowest offset */ + ipr->p = p; + } + break; + } else if (iprh->start == iprh_tmp->start) { + /* received the same datagram twice: no need to keep the datagram */ + IP6_FRAG_STATS_INC(ip6_frag.drop); + goto nullreturn; +#if IP_REASS_CHECK_OVERLAP + } else if (iprh->start < iprh_tmp->end) { + /* overlap: no need to keep the new datagram */ + IP6_FRAG_STATS_INC(ip6_frag.proterr); + IP6_FRAG_STATS_INC(ip6_frag.drop); + goto nullreturn; +#endif /* IP_REASS_CHECK_OVERLAP */ + } else { + /* Check if the fragments received so far have no gaps. */ + if (iprh_prev != NULL) { + if (iprh_prev->end != iprh_tmp->start) { + /* There is a fragment missing between the current + * and the previous fragment */ + valid = 0; + } + } + } + q = iprh_tmp->next_pbuf; + iprh_prev = iprh_tmp; + } + + /* If q is NULL, then we made it to the end of the list. Determine what to do now */ + if (q == NULL) { + if (iprh_prev != NULL) { + /* this is (for now), the fragment with the highest offset: + * chain it to the last fragment */ +#if IP_REASS_CHECK_OVERLAP + LWIP_ASSERT("check fragments don't overlap", iprh_prev->end <= iprh->start); +#endif /* IP_REASS_CHECK_OVERLAP */ + iprh_prev->next_pbuf = p; + if (iprh_prev->end != iprh->start) { + valid = 0; + } + } else { +#if IP_REASS_CHECK_OVERLAP + LWIP_ASSERT("no previous fragment, this must be the first fragment!", + ipr->p == NULL); +#endif /* IP_REASS_CHECK_OVERLAP */ + /* this is the first fragment we ever received for this ip datagram */ + ipr->p = p; + } + } + + /* Track the current number of pbufs current 'in-flight', in order to limit + the number of fragments that may be enqueued at any one time */ + ip6_reass_pbufcount += clen; + + /* Remember IPv6 header if this is the first fragment. */ + if (iprh->start == 0) { +#if IPV6_FRAG_COPYHEADER + if (iprh->next_pbuf != NULL) { + MEMCPY(&ipr->iphdr, ip6_current_header(), IP6_HLEN); + } +#else /* IPV6_FRAG_COPYHEADER */ + /* need to use the none-const pointer here: */ + ipr->iphdr = ip_data.current_ip6_header; +#endif /* IPV6_FRAG_COPYHEADER */ + } + + /* If this is the last fragment, calculate total packet length. */ + if ((offset & IP6_FRAG_MORE_FLAG) == 0) { + ipr->datagram_len = iprh->end; + } + + /* Additional validity tests: we have received first and last fragment. */ + iprh_tmp = (struct ip6_reass_helper*)ipr->p->payload; + if (iprh_tmp->start != 0) { + valid = 0; + } + if (ipr->datagram_len == 0) { + valid = 0; + } + + /* Final validity test: no gaps between current and last fragment. */ + iprh_prev = iprh; + q = iprh->next_pbuf; + while ((q != NULL) && valid) { + iprh = (struct ip6_reass_helper*)q->payload; + if (iprh_prev->end != iprh->start) { + valid = 0; + break; + } + iprh_prev = iprh; + q = iprh->next_pbuf; + } + + if (valid) { + /* All fragments have been received */ + struct ip6_hdr* iphdr_ptr; + + /* chain together the pbufs contained within the ip6_reassdata list. */ + iprh = (struct ip6_reass_helper*) ipr->p->payload; + while (iprh != NULL) { + struct pbuf* next_pbuf = iprh->next_pbuf; + if (next_pbuf != NULL) { + /* Save next helper struct (will be hidden in next step). */ + iprh_tmp = (struct ip6_reass_helper*)next_pbuf->payload; + + /* hide the fragment header for every succeeding fragment */ + pbuf_header(next_pbuf, -IP6_FRAG_HLEN); +#if IPV6_FRAG_COPYHEADER + if (IPV6_FRAG_REQROOM > 0) { + /* hide the extra bytes borrowed from ip6_hdr for struct ip6_reass_helper */ + err_t hdrerr = pbuf_header(next_pbuf, -(s16_t)(IPV6_FRAG_REQROOM)); + LWIP_ASSERT("no room for struct ip6_reass_helper", hdrerr == ERR_OK); + } +#endif + pbuf_cat(ipr->p, next_pbuf); + } + else { + iprh_tmp = NULL; + } + + iprh = iprh_tmp; + } + +#if IPV6_FRAG_COPYHEADER + if (IPV6_FRAG_REQROOM > 0) { + /* get back room for struct ip6_reass_helper (only required if sizeof(void*) > 4) */ + err_t hdrerr = pbuf_header(ipr->p, -(s16_t)(IPV6_FRAG_REQROOM)); + LWIP_ASSERT("no room for struct ip6_reass_helper", hdrerr == ERR_OK); + } + iphdr_ptr = (struct ip6_hdr*)((u8_t*)ipr->p->payload - IP6_HLEN); + MEMCPY(iphdr_ptr, &ipr->iphdr, IP6_HLEN); +#else + iphdr_ptr = ipr->iphdr; +#endif + + /* Adjust datagram length by adding header lengths. */ + ipr->datagram_len += (u16_t)(((u8_t*)ipr->p->payload - (u8_t*)iphdr_ptr) + + IP6_FRAG_HLEN + - IP6_HLEN); + + /* Set payload length in ip header. */ + iphdr_ptr->_plen = htons(ipr->datagram_len); + + /* Get the first pbuf. */ + p = ipr->p; + + /* Restore Fragment Header in first pbuf. Mark as "single fragment" + * packet. Restore nexth. */ + frag_hdr = (struct ip6_frag_hdr *) p->payload; + frag_hdr->_nexth = ipr->nexth; + frag_hdr->reserved = 0; + frag_hdr->_fragment_offset = 0; + frag_hdr->_identification = 0; + + /* release the sources allocate for the fragment queue entry */ + if (reassdatagrams == ipr) { + /* it was the first in the list */ + reassdatagrams = ipr->next; + } else { + /* it wasn't the first, so it must have a valid 'prev' */ + LWIP_ASSERT("sanity check linked list", ipr_prev != NULL); + ipr_prev->next = ipr->next; + } + memp_free(MEMP_IP6_REASSDATA, ipr); + + /* adjust the number of pbufs currently queued for reassembly. */ + ip6_reass_pbufcount -= pbuf_clen(p); + + /* Move pbuf back to IPv6 header. + This cannot fail since we already checked when receiving this fragment. */ + if (pbuf_header_force(p, (s16_t)((u8_t*)p->payload - (u8_t*)iphdr_ptr))) { + LWIP_ASSERT("ip6_reass: moving p->payload to ip6 header failed\n", 0); + pbuf_free(p); + return NULL; + } + + /* Return the pbuf chain */ + return p; + } + /* the datagram is not (yet?) reassembled completely */ + return NULL; + +nullreturn: + pbuf_free(p); + return NULL; +} + +#endif /* LWIP_IPV6 && LWIP_IPV6_REASS */ + +#if LWIP_IPV6 && LWIP_IPV6_FRAG + +/** Allocate a new struct pbuf_custom_ref */ +static struct pbuf_custom_ref* +ip6_frag_alloc_pbuf_custom_ref(void) +{ + return (struct pbuf_custom_ref*)memp_malloc(MEMP_FRAG_PBUF); +} + +/** Free a struct pbuf_custom_ref */ +static void +ip6_frag_free_pbuf_custom_ref(struct pbuf_custom_ref* p) +{ + LWIP_ASSERT("p != NULL", p != NULL); + memp_free(MEMP_FRAG_PBUF, p); +} + +/** Free-callback function to free a 'struct pbuf_custom_ref', called by + * pbuf_free. */ +static void +ip6_frag_free_pbuf_custom(struct pbuf *p) +{ + struct pbuf_custom_ref *pcr = (struct pbuf_custom_ref*)p; + LWIP_ASSERT("pcr != NULL", pcr != NULL); + LWIP_ASSERT("pcr == p", (void*)pcr == (void*)p); + if (pcr->original != NULL) { + pbuf_free(pcr->original); + } + ip6_frag_free_pbuf_custom_ref(pcr); +} + +/** + * Fragment an IPv6 datagram if too large for the netif or path MTU. + * + * Chop the datagram in MTU sized chunks and send them in order + * by pointing PBUF_REFs into p + * + * @param p ipv6 packet to send + * @param netif the netif on which to send + * @param dest destination ipv6 address to which to send + * + * @return ERR_OK if sent successfully, err_t otherwise + */ +err_t +ip6_frag(struct pbuf *p, struct netif *netif, const ip6_addr_t *dest) +{ + struct ip6_hdr *original_ip6hdr; + struct ip6_hdr *ip6hdr; + struct ip6_frag_hdr * frag_hdr; + struct pbuf *rambuf; + struct pbuf *newpbuf; + static u32_t identification; + u16_t nfb; + u16_t left, cop; + u16_t mtu; + u16_t fragment_offset = 0; + u16_t last; + u16_t poff = IP6_HLEN; + u16_t newpbuflen = 0; + u16_t left_to_copy; + + identification++; + + original_ip6hdr = (struct ip6_hdr *)p->payload; + + mtu = nd6_get_destination_mtu(dest, netif); + + /* TODO we assume there are no options in the unfragmentable part (IPv6 header). */ + left = p->tot_len - IP6_HLEN; + + nfb = (mtu - (IP6_HLEN + IP6_FRAG_HLEN)) & IP6_FRAG_OFFSET_MASK; + + while (left) { + last = (left <= nfb); + + /* Fill this fragment */ + cop = last ? left : nfb; + + /* When not using a static buffer, create a chain of pbufs. + * The first will be a PBUF_RAM holding the link, IPv6, and Fragment header. + * The rest will be PBUF_REFs mirroring the pbuf chain to be fragged, + * but limited to the size of an mtu. + */ + rambuf = pbuf_alloc(PBUF_LINK, IP6_HLEN + IP6_FRAG_HLEN, PBUF_RAM); + if (rambuf == NULL) { + IP6_FRAG_STATS_INC(ip6_frag.memerr); + return ERR_MEM; + } + LWIP_ASSERT("this needs a pbuf in one piece!", + (p->len >= (IP6_HLEN + IP6_FRAG_HLEN))); + SMEMCPY(rambuf->payload, original_ip6hdr, IP6_HLEN); + ip6hdr = (struct ip6_hdr *)rambuf->payload; + frag_hdr = (struct ip6_frag_hdr *)((u8_t*)rambuf->payload + IP6_HLEN); + + /* Can just adjust p directly for needed offset. */ + p->payload = (u8_t *)p->payload + poff; + p->len -= poff; + p->tot_len -= poff; + + left_to_copy = cop; + while (left_to_copy) { + struct pbuf_custom_ref *pcr; + newpbuflen = (left_to_copy < p->len) ? left_to_copy : p->len; + /* Is this pbuf already empty? */ + if (!newpbuflen) { + p = p->next; + continue; + } + pcr = ip6_frag_alloc_pbuf_custom_ref(); + if (pcr == NULL) { + pbuf_free(rambuf); + IP6_FRAG_STATS_INC(ip6_frag.memerr); + return ERR_MEM; + } + /* Mirror this pbuf, although we might not need all of it. */ + newpbuf = pbuf_alloced_custom(PBUF_RAW, newpbuflen, PBUF_REF, &pcr->pc, p->payload, newpbuflen); + if (newpbuf == NULL) { + ip6_frag_free_pbuf_custom_ref(pcr); + pbuf_free(rambuf); + IP6_FRAG_STATS_INC(ip6_frag.memerr); + return ERR_MEM; + } + pbuf_ref(p); + pcr->original = p; + pcr->pc.custom_free_function = ip6_frag_free_pbuf_custom; + + /* Add it to end of rambuf's chain, but using pbuf_cat, not pbuf_chain + * so that it is removed when pbuf_dechain is later called on rambuf. + */ + pbuf_cat(rambuf, newpbuf); + left_to_copy -= newpbuflen; + if (left_to_copy) { + p = p->next; + } + } + poff = newpbuflen; + + /* Set headers */ + frag_hdr->_nexth = original_ip6hdr->_nexth; + frag_hdr->reserved = 0; + frag_hdr->_fragment_offset = htons((fragment_offset & IP6_FRAG_OFFSET_MASK) | (last ? 0 : IP6_FRAG_MORE_FLAG)); + frag_hdr->_identification = htonl(identification); + + IP6H_NEXTH_SET(ip6hdr, IP6_NEXTH_FRAGMENT); + IP6H_PLEN_SET(ip6hdr, cop + IP6_FRAG_HLEN); + + /* No need for separate header pbuf - we allowed room for it in rambuf + * when allocated. + */ + IP6_FRAG_STATS_INC(ip6_frag.xmit); + netif->output_ip6(netif, rambuf, dest); + + /* Unfortunately we can't reuse rambuf - the hardware may still be + * using the buffer. Instead we free it (and the ensuing chain) and + * recreate it next time round the loop. If we're lucky the hardware + * will have already sent the packet, the free will really free, and + * there will be zero memory penalty. + */ + + pbuf_free(rambuf); + left -= cop; + fragment_offset += cop; + } + return ERR_OK; +} + +#endif /* LWIP_IPV6 && LWIP_IPV6_FRAG */ diff --git a/components/lwip/core/ipv6/mld6.c b/components/lwip/core/ipv6/mld6.c new file mode 100755 index 0000000000..6a2d55c549 --- /dev/null +++ b/components/lwip/core/ipv6/mld6.c @@ -0,0 +1,593 @@ +/** + * @file + * + * Multicast listener discovery for IPv6. Aims to be compliant with RFC 2710. + * No support for MLDv2. + */ + +/* + * Copyright (c) 2010 Inico Technologies Ltd. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Ivan Delamer + * + * + * Please coordinate changes and requests with Ivan Delamer + * + */ + +/* Based on igmp.c implementation of igmp v2 protocol */ + +#include "lwip/opt.h" + +#if LWIP_IPV6 && LWIP_IPV6_MLD /* don't build if not configured for use in lwipopts.h */ + +#include "lwip/mld6.h" +#include "lwip/icmp6.h" +#include "lwip/ip6.h" +#include "lwip/ip6_addr.h" +#include "lwip/ip.h" +#include "lwip/inet_chksum.h" +#include "lwip/pbuf.h" +#include "lwip/netif.h" +#include "lwip/memp.h" +#include "lwip/stats.h" + +#include + +#ifdef MEMLEAK_DEBUG +static const char mem_debug_file[] ICACHE_RODATA_ATTR STORE_ATTR = __FILE__; +#endif + + +/* + * MLD constants + */ +#define MLD6_HL 1 +#define MLD6_JOIN_DELAYING_MEMBER_TMR_MS (500) + +#define MLD6_GROUP_NON_MEMBER 0 +#define MLD6_GROUP_DELAYING_MEMBER 1 +#define MLD6_GROUP_IDLE_MEMBER 2 + + +/* The list of joined groups. */ +static struct mld_group* mld_group_list; + + +/* Forward declarations. */ +static struct mld_group * mld6_new_group(struct netif *ifp, const ip6_addr_t *addr); +static err_t mld6_free_group(struct mld_group *group); +static void mld6_delayed_report(struct mld_group *group, u16_t maxresp); +static void mld6_send(struct mld_group *group, u8_t type); + + +/** + * Stop MLD processing on interface + * + * @param netif network interface on which stop MLD processing + */ +err_t +mld6_stop(struct netif *netif) +{ + struct mld_group *group = mld_group_list; + struct mld_group *prev = NULL; + struct mld_group *next; + + /* look for groups joined on this interface further down the list */ + while (group != NULL) { + next = group->next; + /* is it a group joined on this interface? */ + if (group->netif == netif) { + /* is it the first group of the list? */ + if (group == mld_group_list) { + mld_group_list = next; + } + /* is there a "previous" group defined? */ + if (prev != NULL) { + prev->next = next; + } + /* disable the group at the MAC level */ + if (netif->mld_mac_filter != NULL) { + netif->mld_mac_filter(netif, &(group->group_address), MLD6_DEL_MAC_FILTER); + } + /* free group */ + memp_free(MEMP_MLD6_GROUP, group); + } else { + /* change the "previous" */ + prev = group; + } + /* move to "next" */ + group = next; + } + return ERR_OK; +} + +/** + * Report MLD memberships for this interface + * + * @param netif network interface on which report MLD memberships + */ +void +mld6_report_groups(struct netif *netif) +{ + struct mld_group *group = mld_group_list; + + while (group != NULL) { + if (group->netif == netif) { + mld6_delayed_report(group, MLD6_JOIN_DELAYING_MEMBER_TMR_MS); + } + group = group->next; + } +} + +/** + * Search for a group that is joined on a netif + * + * @param ifp the network interface for which to look + * @param addr the group ipv6 address to search for + * @return a struct mld_group* if the group has been found, + * NULL if the group wasn't found. + */ +struct mld_group * +mld6_lookfor_group(struct netif *ifp, const ip6_addr_t *addr) +{ + struct mld_group *group = mld_group_list; + + while (group != NULL) { + if ((group->netif == ifp) && (ip6_addr_cmp(&(group->group_address), addr))) { + return group; + } + group = group->next; + } + + return NULL; +} + + +/** + * create a new group + * + * @param ifp the network interface for which to create + * @param addr the new group ipv6 + * @return a struct mld_group*, + * NULL on memory error. + */ +static struct mld_group * +mld6_new_group(struct netif *ifp, const ip6_addr_t *addr) +{ + struct mld_group *group; + + group = (struct mld_group *)memp_malloc(MEMP_MLD6_GROUP); + if (group != NULL) { + group->netif = ifp; + ip6_addr_set(&(group->group_address), addr); + group->timer = 0; /* Not running */ + group->group_state = MLD6_GROUP_IDLE_MEMBER; + group->last_reporter_flag = 0; + group->use = 0; + group->next = mld_group_list; + + mld_group_list = group; + } + + return group; +} + +/** + * Remove a group in the mld_group_list and free + * + * @param group the group to remove + * @return ERR_OK if group was removed from the list, an err_t otherwise + */ +static err_t +mld6_free_group(struct mld_group *group) +{ + err_t err = ERR_OK; + + /* Is it the first group? */ + if (mld_group_list == group) { + mld_group_list = group->next; + } else { + /* look for group further down the list */ + struct mld_group *tmpGroup; + for (tmpGroup = mld_group_list; tmpGroup != NULL; tmpGroup = tmpGroup->next) { + if (tmpGroup->next == group) { + tmpGroup->next = group->next; + break; + } + } + /* Group not find group */ + if (tmpGroup == NULL) { + err = ERR_ARG; + } + } + /* free group */ + memp_free(MEMP_MLD6_GROUP, group); + + return err; +} + + +/** + * Process an input MLD message. Called by icmp6_input. + * + * @param p the mld packet, p->payload pointing to the icmpv6 header + * @param inp the netif on which this packet was received + */ +void +mld6_input(struct pbuf *p, struct netif *inp) +{ + struct mld_header * mld_hdr; + struct mld_group* group; + + MLD6_STATS_INC(mld6.recv); + + /* Check that mld header fits in packet. */ + if (p->len < sizeof(struct mld_header)) { + /* TODO debug message */ + pbuf_free(p); + MLD6_STATS_INC(mld6.lenerr); + MLD6_STATS_INC(mld6.drop); + return; + } + + mld_hdr = (struct mld_header *)p->payload; + + switch (mld_hdr->type) { + case ICMP6_TYPE_MLQ: /* Multicast listener query. */ + /* Is it a general query? */ + if (ip6_addr_isallnodes_linklocal(ip6_current_dest_addr()) && + ip6_addr_isany(&(mld_hdr->multicast_address))) { + MLD6_STATS_INC(mld6.rx_general); + /* Report all groups, except all nodes group, and if-local groups. */ + group = mld_group_list; + while (group != NULL) { + if ((group->netif == inp) && + (!(ip6_addr_ismulticast_iflocal(&(group->group_address)))) && + (!(ip6_addr_isallnodes_linklocal(&(group->group_address))))) { + mld6_delayed_report(group, mld_hdr->max_resp_delay); + } + group = group->next; + } + } else { + /* Have we joined this group? + * We use IP6 destination address to have a memory aligned copy. + * mld_hdr->multicast_address should be the same. */ + MLD6_STATS_INC(mld6.rx_group); + group = mld6_lookfor_group(inp, ip6_current_dest_addr()); + if (group != NULL) { + /* Schedule a report. */ + mld6_delayed_report(group, mld_hdr->max_resp_delay); + } + } + break; /* ICMP6_TYPE_MLQ */ + case ICMP6_TYPE_MLR: /* Multicast listener report. */ + /* Have we joined this group? + * We use IP6 destination address to have a memory aligned copy. + * mld_hdr->multicast_address should be the same. */ + MLD6_STATS_INC(mld6.rx_report); + group = mld6_lookfor_group(inp, ip6_current_dest_addr()); + if (group != NULL) { + /* If we are waiting to report, cancel it. */ + if (group->group_state == MLD6_GROUP_DELAYING_MEMBER) { + group->timer = 0; /* stopped */ + group->group_state = MLD6_GROUP_IDLE_MEMBER; + group->last_reporter_flag = 0; + } + } + break; /* ICMP6_TYPE_MLR */ + case ICMP6_TYPE_MLD: /* Multicast listener done. */ + /* Do nothing, router will query us. */ + break; /* ICMP6_TYPE_MLD */ + default: + MLD6_STATS_INC(mld6.proterr); + MLD6_STATS_INC(mld6.drop); + break; + } + + pbuf_free(p); +} + +/** + * Join a group on a network interface. + * + * @param srcaddr ipv6 address of the network interface which should + * join a new group. If IP6_ADDR_ANY, join on all netifs + * @param groupaddr the ipv6 address of the group to join + * @return ERR_OK if group was joined on the netif(s), an err_t otherwise + */ +err_t +mld6_joingroup(const ip6_addr_t *srcaddr, const ip6_addr_t *groupaddr) +{ + err_t err = ERR_VAL; /* no matching interface */ + struct netif *netif; + + /* loop through netif's */ + netif = netif_list; + while (netif != NULL) { + /* Should we join this interface ? */ + if (ip6_addr_isany(srcaddr) || + netif_get_ip6_addr_match(netif, srcaddr) >= 0) { + err = mld6_joingroup_netif(netif, groupaddr); + if (err != ERR_OK) { + return err; + } + } + + /* proceed to next network interface */ + netif = netif->next; + } + + return err; +} + +/** + * Join a group on a network interface. + * + * @param netif the network interface which should join a new group. + * @param groupaddr the ipv6 address of the group to join + * @return ERR_OK if group was joined on the netif, an err_t otherwise + */ +err_t +mld6_joingroup_netif(struct netif *netif, const ip6_addr_t *groupaddr) +{ + struct mld_group *group; + + /* find group or create a new one if not found */ + group = mld6_lookfor_group(netif, groupaddr); + + if (group == NULL) { + /* Joining a new group. Create a new group entry. */ + group = mld6_new_group(netif, groupaddr); + if (group == NULL) { + return ERR_MEM; + } + + /* Activate this address on the MAC layer. */ + if (netif->mld_mac_filter != NULL) { + netif->mld_mac_filter(netif, groupaddr, MLD6_ADD_MAC_FILTER); + } + + /* Report our membership. */ + MLD6_STATS_INC(mld6.tx_report); + mld6_send(group, ICMP6_TYPE_MLR); + mld6_delayed_report(group, MLD6_JOIN_DELAYING_MEMBER_TMR_MS); + } + + /* Increment group use */ + group->use++; + return ERR_OK; +} + +/** + * Leave a group on a network interface. + * + * @param srcaddr ipv6 address of the network interface which should + * leave the group. If IP6_ISANY, leave on all netifs + * @param groupaddr the ipv6 address of the group to leave + * @return ERR_OK if group was left on the netif(s), an err_t otherwise + */ +err_t +mld6_leavegroup(const ip6_addr_t *srcaddr, const ip6_addr_t *groupaddr) +{ + err_t err = ERR_VAL; /* no matching interface */ + struct netif *netif; + + /* loop through netif's */ + netif = netif_list; + while (netif != NULL) { + /* Should we leave this interface ? */ + if (ip6_addr_isany(srcaddr) || + netif_get_ip6_addr_match(netif, srcaddr) >= 0) { + err_t res = mld6_leavegroup_netif(netif, groupaddr); + if (err != ERR_OK) { + /* Store this result if we have not yet gotten a success */ + err = res; + } + } + /* proceed to next network interface */ + netif = netif->next; + } + + return err; +} + +/** + * Leave a group on a network interface. + * + * @param netif the network interface which should leave the group. + * @param groupaddr the ipv6 address of the group to leave + * @return ERR_OK if group was left on the netif, an err_t otherwise + */ +err_t +mld6_leavegroup_netif(struct netif *netif, const ip6_addr_t *groupaddr) +{ + struct mld_group *group; + + /* find group */ + group = mld6_lookfor_group(netif, groupaddr); + + if (group != NULL) { + /* Leave if there is no other use of the group */ + if (group->use <= 1) { + /* If we are the last reporter for this group */ + if (group->last_reporter_flag) { + MLD6_STATS_INC(mld6.tx_leave); + mld6_send(group, ICMP6_TYPE_MLD); + } + + /* Disable the group at the MAC level */ + if (netif->mld_mac_filter != NULL) { + netif->mld_mac_filter(netif, groupaddr, MLD6_DEL_MAC_FILTER); + } + + /* Free the group */ + mld6_free_group(group); + } else { + /* Decrement group use */ + group->use--; + } + + /* Left group */ + return ERR_OK; + } + + /* Group not found */ + return ERR_VAL; +} + + +/** + * Periodic timer for mld processing. Must be called every + * MLD6_TMR_INTERVAL milliseconds (100). + * + * When a delaying member expires, a membership report is sent. + */ +void +mld6_tmr(void) +{ + struct mld_group *group = mld_group_list; + + while (group != NULL) { + if (group->timer > 0) { + group->timer--; + if (group->timer == 0) { + /* If the state is MLD6_GROUP_DELAYING_MEMBER then we send a report for this group */ + if (group->group_state == MLD6_GROUP_DELAYING_MEMBER) { + MLD6_STATS_INC(mld6.tx_report); + mld6_send(group, ICMP6_TYPE_MLR); + group->group_state = MLD6_GROUP_IDLE_MEMBER; + } + } + } + group = group->next; + } +} + +/** + * Schedule a delayed membership report for a group + * + * @param group the mld_group for which "delaying" membership report + * should be sent + * @param maxresp the max resp delay provided in the query + */ +static void +mld6_delayed_report(struct mld_group *group, u16_t maxresp) +{ + /* Convert maxresp from milliseconds to tmr ticks */ + maxresp = maxresp / MLD6_TMR_INTERVAL; + if (maxresp == 0) { + maxresp = 1; + } + +#ifdef LWIP_RAND + /* Randomize maxresp. (if LWIP_RAND is supported) */ + maxresp = LWIP_RAND() % maxresp; + if (maxresp == 0) { + maxresp = 1; + } +#endif /* LWIP_RAND */ + + /* Apply timer value if no report has been scheduled already. */ + if ((group->group_state == MLD6_GROUP_IDLE_MEMBER) || + ((group->group_state == MLD6_GROUP_DELAYING_MEMBER) && + ((group->timer == 0) || (maxresp < group->timer)))) { + group->timer = maxresp; + group->group_state = MLD6_GROUP_DELAYING_MEMBER; + } +} + +/** + * Send a MLD message (report or done). + * + * An IPv6 hop-by-hop options header with a router alert option + * is prepended. + * + * @param group the group to report or quit + * @param type ICMP6_TYPE_MLR (report) or ICMP6_TYPE_MLD (done) + */ +static void +mld6_send(struct mld_group *group, u8_t type) +{ + struct mld_header * mld_hdr; + struct pbuf * p; + const ip6_addr_t * src_addr; + + /* Allocate a packet. Size is MLD header + IPv6 Hop-by-hop options header. */ + p = pbuf_alloc(PBUF_IP, sizeof(struct mld_header) + sizeof(struct ip6_hbh_hdr), PBUF_RAM); + if (p == NULL) { + MLD6_STATS_INC(mld6.memerr); + return; + } + + /* Move to make room for Hop-by-hop options header. */ + if (pbuf_header(p, -IP6_HBH_HLEN)) { + pbuf_free(p); + MLD6_STATS_INC(mld6.lenerr); + return; + } + + /* Select our source address. */ + if (!ip6_addr_isvalid(netif_ip6_addr_state(group->netif, 0))) { + /* This is a special case, when we are performing duplicate address detection. + * We must join the multicast group, but we don't have a valid address yet. */ + src_addr = IP6_ADDR_ANY6; + } else { + /* Use link-local address as source address. */ + src_addr = netif_ip6_addr(group->netif, 0); + } + + /* MLD message header pointer. */ + mld_hdr = (struct mld_header *)p->payload; + + /* Set fields. */ + mld_hdr->type = type; + mld_hdr->code = 0; + mld_hdr->chksum = 0; + mld_hdr->max_resp_delay = 0; + mld_hdr->reserved = 0; + ip6_addr_set(&(mld_hdr->multicast_address), &(group->group_address)); + +#if CHECKSUM_GEN_ICMP6 + IF__NETIF_CHECKSUM_ENABLED(group->netif, NETIF_CHECKSUM_GEN_ICMP6) { + mld_hdr->chksum = ip6_chksum_pseudo(p, IP6_NEXTH_ICMP6, p->len, + src_addr, &(group->group_address)); + } +#endif /* CHECKSUM_GEN_ICMP6 */ + + /* Add hop-by-hop headers options: router alert with MLD value. */ + ip6_options_add_hbh_ra(p, IP6_NEXTH_ICMP6, IP6_ROUTER_ALERT_VALUE_MLD); + + /* Send the packet out. */ + MLD6_STATS_INC(mld6.xmit); + ip6_output_if(p, (ip6_addr_isany(src_addr)) ? NULL : src_addr, &(group->group_address), + MLD6_HL, 0, IP6_NEXTH_HOPBYHOP, group->netif); + pbuf_free(p); +} + +#endif /* LWIP_IPV6 */ diff --git a/components/lwip/core/ipv6/nd6.c b/components/lwip/core/ipv6/nd6.c new file mode 100755 index 0000000000..39e7bfed03 --- /dev/null +++ b/components/lwip/core/ipv6/nd6.c @@ -0,0 +1,1846 @@ +/** + * @file + * + * Neighbor discovery and stateless address autoconfiguration for IPv6. + * Aims to be compliant with RFC 4861 (Neighbor discovery) and RFC 4862 + * (Address autoconfiguration). + */ + +/* + * Copyright (c) 2010 Inico Technologies Ltd. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Ivan Delamer + * + * + * Please coordinate changes and requests with Ivan Delamer + * + */ + +#include "lwip/opt.h" + +#if LWIP_IPV6 /* don't build if not configured for use in lwipopts.h */ + +#include "lwip/nd6.h" +#include "lwip/pbuf.h" +#include "lwip/mem.h" +#include "lwip/memp.h" +#include "lwip/ip6.h" +#include "lwip/ip6_addr.h" +#include "lwip/inet_chksum.h" +#include "lwip/netif.h" +#include "lwip/icmp6.h" +#include "lwip/mld6.h" +#include "lwip/ip.h" +#include "lwip/stats.h" + +#include + +#ifdef MEMLEAK_DEBUG +static const char mem_debug_file[] ICACHE_RODATA_ATTR STORE_ATTR = __FILE__; +#endif + + +/* Router tables. */ +struct nd6_neighbor_cache_entry neighbor_cache[LWIP_ND6_NUM_NEIGHBORS]; +struct nd6_destination_cache_entry destination_cache[LWIP_ND6_NUM_DESTINATIONS]; +struct nd6_prefix_list_entry prefix_list[LWIP_ND6_NUM_PREFIXES]; +struct nd6_router_list_entry default_router_list[LWIP_ND6_NUM_ROUTERS]; + +/* Default values, can be updated by a RA message. */ +u32_t reachable_time = LWIP_ND6_REACHABLE_TIME; +u32_t retrans_timer = LWIP_ND6_RETRANS_TIMER; /* TODO implement this value in timer */ + +/* Index for cache entries. */ +static u8_t nd6_cached_neighbor_index; +static u8_t nd6_cached_destination_index; + +/* Multicast address holder. */ +static ip6_addr_t multicast_address; + +/* Static buffer to parse RA packet options (size of a prefix option, biggest option) */ +static u8_t nd6_ra_buffer[sizeof(struct prefix_option)]; + +/* Forward declarations. */ +static s8_t nd6_find_neighbor_cache_entry(const ip6_addr_t * ip6addr); +static s8_t nd6_new_neighbor_cache_entry(void); +static void nd6_free_neighbor_cache_entry(s8_t i); +static s8_t nd6_find_destination_cache_entry(const ip6_addr_t * ip6addr); +static s8_t nd6_new_destination_cache_entry(void); +static s8_t nd6_is_prefix_in_netif(const ip6_addr_t * ip6addr, struct netif * netif); +static s8_t nd6_get_router(const ip6_addr_t * router_addr, struct netif * netif); +static s8_t nd6_new_router(const ip6_addr_t * router_addr, struct netif * netif); +static s8_t nd6_get_onlink_prefix(ip6_addr_t * prefix, struct netif * netif); +static s8_t nd6_new_onlink_prefix(ip6_addr_t * prefix, struct netif * netif); + +#define ND6_SEND_FLAG_MULTICAST_DEST 0x01 +#define ND6_SEND_FLAG_ALLNODES_DEST 0x02 +static void nd6_send_ns(struct netif * netif, const ip6_addr_t * target_addr, u8_t flags); +static void nd6_send_na(struct netif * netif, const ip6_addr_t * target_addr, u8_t flags); +#if LWIP_IPV6_SEND_ROUTER_SOLICIT +static err_t nd6_send_rs(struct netif * netif); +#endif /* LWIP_IPV6_SEND_ROUTER_SOLICIT */ + +#if LWIP_ND6_QUEUEING +static void nd6_free_q(struct nd6_q_entry *q); +#else /* LWIP_ND6_QUEUEING */ +#define nd6_free_q(q) pbuf_free(q) +#endif /* LWIP_ND6_QUEUEING */ +static void nd6_send_q(s8_t i); + + +/** + * Process an incoming neighbor discovery message + * + * @param p the nd packet, p->payload pointing to the icmpv6 header + * @param inp the netif on which this packet was received + */ +void +nd6_input(struct pbuf *p, struct netif *inp) +{ + u8_t msg_type; + s8_t i; + + ND6_STATS_INC(nd6.recv); + + msg_type = *((u8_t *)p->payload); + switch (msg_type) { + case ICMP6_TYPE_NA: /* Neighbor Advertisement. */ + { + struct na_header * na_hdr; + struct lladdr_option * lladdr_opt; + + /* Check that na header fits in packet. */ + if (p->len < (sizeof(struct na_header))) { + /* TODO debug message */ + pbuf_free(p); + ND6_STATS_INC(nd6.lenerr); + ND6_STATS_INC(nd6.drop); + return; + } + + na_hdr = (struct na_header *)p->payload; + + /* Unsolicited NA?*/ + if (ip6_addr_ismulticast(ip6_current_dest_addr())) { + /* This is an unsolicited NA. + * link-layer changed? + * part of DAD mechanism? */ + + /* Check that link-layer address option also fits in packet. */ + if (p->len < (sizeof(struct na_header) + 2)) { + /* TODO debug message */ + pbuf_free(p); + ND6_STATS_INC(nd6.lenerr); + ND6_STATS_INC(nd6.drop); + return; + } + + lladdr_opt = (struct lladdr_option *)((u8_t*)p->payload + sizeof(struct na_header)); + + if (p->len < (sizeof(struct na_header) + (lladdr_opt->length << 3))) { + /* TODO debug message */ + pbuf_free(p); + ND6_STATS_INC(nd6.lenerr); + ND6_STATS_INC(nd6.drop); + return; + } + + /* Override ip6_current_dest_addr() so that we have an aligned copy. */ + ip6_addr_set(ip6_current_dest_addr(), &(na_hdr->target_address)); + +#if LWIP_IPV6_DUP_DETECT_ATTEMPTS + /* If the target address matches this netif, it is a DAD response. */ + for (i = 0; i < LWIP_IPV6_NUM_ADDRESSES; i++) { + if (!ip6_addr_isinvalid(netif_ip6_addr_state(inp, i)) && + ip6_addr_cmp(ip6_current_dest_addr(), netif_ip6_addr(inp, i))) { + /* We are using a duplicate address. */ + netif_ip6_addr_set_state(inp, i, IP6_ADDR_INVALID); + +#if LWIP_IPV6_MLD + /* Leave solicited node multicast group. */ + ip6_addr_set_solicitednode(&multicast_address, netif_ip6_addr(inp, i)->addr[3]); + mld6_leavegroup(netif_ip6_addr(inp, i), &multicast_address); +#endif /* LWIP_IPV6_MLD */ + +#if LWIP_IPV6_AUTOCONFIG + /* Check to see if this address was autoconfigured. */ + if (!ip6_addr_islinklocal(ip6_current_dest_addr())) { + i = nd6_get_onlink_prefix(ip6_current_dest_addr(), inp); + if (i >= 0) { + /* Mark this prefix as duplicate, so that we don't use it + * to generate this address again. */ + prefix_list[i].flags |= ND6_PREFIX_AUTOCONFIG_ADDRESS_DUPLICATE; + } + } +#endif /* LWIP_IPV6_AUTOCONFIG */ + + pbuf_free(p); + return; + } + } +#endif /* LWIP_IPV6_DUP_DETECT_ATTEMPTS */ + + /* This is an unsolicited NA, most likely there was a LLADDR change. */ + i = nd6_find_neighbor_cache_entry(ip6_current_dest_addr()); + if (i >= 0) { + if (na_hdr->flags & ND6_FLAG_OVERRIDE) { + MEMCPY(neighbor_cache[i].lladdr, lladdr_opt->addr, inp->hwaddr_len); + } + } + } else { + /* This is a solicited NA. + * neighbor address resolution response? + * neighbor unreachability detection response? */ + + /* Override ip6_current_dest_addr() so that we have an aligned copy. */ + ip6_addr_set(ip6_current_dest_addr(), &(na_hdr->target_address)); + + /* Find the cache entry corresponding to this na. */ + i = nd6_find_neighbor_cache_entry(ip6_current_dest_addr()); + if (i < 0) { + /* We no longer care about this target address. drop it. */ + pbuf_free(p); + return; + } + + /* Update cache entry. */ + neighbor_cache[i].netif = inp; + neighbor_cache[i].counter.reachable_time = reachable_time; + if ((na_hdr->flags & ND6_FLAG_OVERRIDE) || + (neighbor_cache[i].state == ND6_INCOMPLETE)) { + /* Check that link-layer address option also fits in packet. */ + if (p->len < (sizeof(struct na_header) + 2)) { + /* TODO debug message */ + pbuf_free(p); + ND6_STATS_INC(nd6.lenerr); + ND6_STATS_INC(nd6.drop); + return; + } + + lladdr_opt = (struct lladdr_option *)((u8_t*)p->payload + sizeof(struct na_header)); + + if (p->len < (sizeof(struct na_header) + (lladdr_opt->length << 3))) { + /* TODO debug message */ + pbuf_free(p); + ND6_STATS_INC(nd6.lenerr); + ND6_STATS_INC(nd6.drop); + return; + } + + MEMCPY(neighbor_cache[i].lladdr, lladdr_opt->addr, inp->hwaddr_len); + } + neighbor_cache[i].state = ND6_REACHABLE; + + /* Send queued packets, if any. */ + if (neighbor_cache[i].q != NULL) { + nd6_send_q(i); + } + } + + break; /* ICMP6_TYPE_NA */ + } + case ICMP6_TYPE_NS: /* Neighbor solicitation. */ + { + struct ns_header * ns_hdr; + struct lladdr_option * lladdr_opt; + u8_t accepted; + + /* Check that ns header fits in packet. */ + if (p->len < sizeof(struct ns_header)) { + /* TODO debug message */ + pbuf_free(p); + ND6_STATS_INC(nd6.lenerr); + ND6_STATS_INC(nd6.drop); + return; + } + + ns_hdr = (struct ns_header *)p->payload; + + /* Check if there is a link-layer address provided. Only point to it if in this buffer. */ + if (p->len >= (sizeof(struct ns_header) + 2)) { + lladdr_opt = (struct lladdr_option *)((u8_t*)p->payload + sizeof(struct ns_header)); + if (p->len < (sizeof(struct ns_header) + (lladdr_opt->length << 3))) { + lladdr_opt = NULL; + } + } else { + lladdr_opt = NULL; + } + + /* Check if the target address is configured on the receiving netif. */ + accepted = 0; + for (i = 0; i < LWIP_IPV6_NUM_ADDRESSES; ++i) { + if ((ip6_addr_isvalid(netif_ip6_addr_state(inp, i)) || + (ip6_addr_istentative(netif_ip6_addr_state(inp, i)) && + ip6_addr_isany(ip6_current_src_addr()))) && + ip6_addr_cmp(&(ns_hdr->target_address), netif_ip6_addr(inp, i))) { + accepted = 1; + break; + } + } + + /* NS not for us? */ + if (!accepted) { + pbuf_free(p); + return; + } + + /* Check for ANY address in src (DAD algorithm). */ + if (ip6_addr_isany(ip6_current_src_addr())) { + /* Sender is validating this address. */ + for (i = 0; i < LWIP_IPV6_NUM_ADDRESSES; ++i) { + if (!ip6_addr_isinvalid(netif_ip6_addr_state(inp, i)) && + ip6_addr_cmp(&(ns_hdr->target_address), netif_ip6_addr(inp, i))) { + /* Send a NA back so that the sender does not use this address. */ + nd6_send_na(inp, netif_ip6_addr(inp, i), ND6_FLAG_OVERRIDE | ND6_SEND_FLAG_ALLNODES_DEST); + if (ip6_addr_istentative(netif_ip6_addr_state(inp, i))) { + /* We shouldn't use this address either. */ + netif_ip6_addr_set_state(inp, i, IP6_ADDR_INVALID); + } + } + } + } else { + /* Sender is trying to resolve our address. */ + /* Verify that they included their own link-layer address. */ + if (lladdr_opt == NULL) { + /* Not a valid message. */ + pbuf_free(p); + ND6_STATS_INC(nd6.proterr); + ND6_STATS_INC(nd6.drop); + return; + } + + i = nd6_find_neighbor_cache_entry(ip6_current_src_addr()); + if (i>= 0) { + /* We already have a record for the solicitor. */ + if (neighbor_cache[i].state == ND6_INCOMPLETE) { + neighbor_cache[i].netif = inp; + MEMCPY(neighbor_cache[i].lladdr, lladdr_opt->addr, inp->hwaddr_len); + + /* Delay probe in case we get confirmation of reachability from upper layer (TCP). */ + neighbor_cache[i].state = ND6_DELAY; + neighbor_cache[i].counter.delay_time = LWIP_ND6_DELAY_FIRST_PROBE_TIME; + } + } else { + /* Add their IPv6 address and link-layer address to neighbor cache. + * We will need it at least to send a unicast NA message, but most + * likely we will also be communicating with this node soon. */ + i = nd6_new_neighbor_cache_entry(); + if (i < 0) { + /* We couldn't assign a cache entry for this neighbor. + * we won't be able to reply. drop it. */ + pbuf_free(p); + ND6_STATS_INC(nd6.memerr); + return; + } + neighbor_cache[i].netif = inp; + MEMCPY(neighbor_cache[i].lladdr, lladdr_opt->addr, inp->hwaddr_len); + ip6_addr_set(&(neighbor_cache[i].next_hop_address), ip6_current_src_addr()); + + /* Receiving a message does not prove reachability: only in one direction. + * Delay probe in case we get confirmation of reachability from upper layer (TCP). */ + neighbor_cache[i].state = ND6_DELAY; + neighbor_cache[i].counter.delay_time = LWIP_ND6_DELAY_FIRST_PROBE_TIME; + } + + /* Override ip6_current_dest_addr() so that we have an aligned copy. */ + ip6_addr_set(ip6_current_dest_addr(), &(ns_hdr->target_address)); + + /* Send back a NA for us. Allocate the reply pbuf. */ + nd6_send_na(inp, ip6_current_dest_addr(), ND6_FLAG_SOLICITED | ND6_FLAG_OVERRIDE); + } + + break; /* ICMP6_TYPE_NS */ + } + case ICMP6_TYPE_RA: /* Router Advertisement. */ + { + struct ra_header * ra_hdr; + u8_t * buffer; /* Used to copy options. */ + u16_t offset; + + /* Check that RA header fits in packet. */ + if (p->len < sizeof(struct ra_header)) { + /* TODO debug message */ + pbuf_free(p); + ND6_STATS_INC(nd6.lenerr); + ND6_STATS_INC(nd6.drop); + return; + } + + ra_hdr = (struct ra_header *)p->payload; + + /* If we are sending RS messages, stop. */ +#if LWIP_IPV6_SEND_ROUTER_SOLICIT + /* ensure at least one solicitation is sent */ + if ((inp->rs_count < LWIP_ND6_MAX_MULTICAST_SOLICIT) || + (nd6_send_rs(inp) == ERR_OK)) { + inp->rs_count = 0; + } +#endif /* LWIP_IPV6_SEND_ROUTER_SOLICIT */ + + /* Get the matching default router entry. */ + i = nd6_get_router(ip6_current_src_addr(), inp); + if (i < 0) { + /* Create a new router entry. */ + i = nd6_new_router(ip6_current_src_addr(), inp); + } + + if (i < 0) { + /* Could not create a new router entry. */ + pbuf_free(p); + ND6_STATS_INC(nd6.memerr); + return; + } + + /* Re-set invalidation timer. */ + default_router_list[i].invalidation_timer = htons(ra_hdr->router_lifetime); + + /* Re-set default timer values. */ +#if LWIP_ND6_ALLOW_RA_UPDATES + if (ra_hdr->retrans_timer > 0) { + retrans_timer = htonl(ra_hdr->retrans_timer); + } + if (ra_hdr->reachable_time > 0) { + reachable_time = htonl(ra_hdr->reachable_time); + } +#endif /* LWIP_ND6_ALLOW_RA_UPDATES */ + + /* TODO set default hop limit... */ + /* ra_hdr->current_hop_limit;*/ + + /* Update flags in local entry (incl. preference). */ + default_router_list[i].flags = ra_hdr->flags; + + /* Offset to options. */ + offset = sizeof(struct ra_header); + + /* Process each option. */ + while ((p->tot_len - offset) > 0) { + if (p->len == p->tot_len) { + /* no need to copy from contiguous pbuf */ + buffer = &((u8_t*)p->payload)[offset]; + } else { + buffer = nd6_ra_buffer; + pbuf_copy_partial(p, buffer, sizeof(struct prefix_option), offset); + } + switch (buffer[0]) { + case ND6_OPTION_TYPE_SOURCE_LLADDR: + { + struct lladdr_option * lladdr_opt; + lladdr_opt = (struct lladdr_option *)buffer; + if ((default_router_list[i].neighbor_entry != NULL) && + (default_router_list[i].neighbor_entry->state == ND6_INCOMPLETE)) { + SMEMCPY(default_router_list[i].neighbor_entry->lladdr, lladdr_opt->addr, inp->hwaddr_len); + default_router_list[i].neighbor_entry->state = ND6_REACHABLE; + default_router_list[i].neighbor_entry->counter.reachable_time = reachable_time; + } + break; + } + case ND6_OPTION_TYPE_MTU: + { + struct mtu_option * mtu_opt; + mtu_opt = (struct mtu_option *)buffer; + if (htonl(mtu_opt->mtu) >= 1280) { +#if LWIP_ND6_ALLOW_RA_UPDATES + inp->mtu = (u16_t)htonl(mtu_opt->mtu); +#endif /* LWIP_ND6_ALLOW_RA_UPDATES */ + } + break; + } + case ND6_OPTION_TYPE_PREFIX_INFO: + { + struct prefix_option * prefix_opt; + prefix_opt = (struct prefix_option *)buffer; + + if (prefix_opt->flags & ND6_PREFIX_FLAG_ON_LINK) { + /* Add to on-link prefix list. */ + s8_t prefix; + + /* Get a memory-aligned copy of the prefix. */ + ip6_addr_set(ip6_current_dest_addr(), &(prefix_opt->prefix)); + + /* find cache entry for this prefix. */ + prefix = nd6_get_onlink_prefix(ip6_current_dest_addr(), inp); + if (prefix < 0) { + /* Create a new cache entry. */ + prefix = nd6_new_onlink_prefix(ip6_current_dest_addr(), inp); + } + if (prefix >= 0) { + prefix_list[prefix].invalidation_timer = htonl(prefix_opt->valid_lifetime); + +#if LWIP_IPV6_AUTOCONFIG + if (prefix_opt->flags & ND6_PREFIX_FLAG_AUTONOMOUS) { + /* Mark prefix as autonomous, so that address autoconfiguration can take place. + * Only OR flag, so that we don't over-write other flags (such as ADDRESS_DUPLICATE)*/ + prefix_list[prefix].flags |= ND6_PREFIX_AUTOCONFIG_AUTONOMOUS; + } +#endif /* LWIP_IPV6_AUTOCONFIG */ + } + } + + break; + } + case ND6_OPTION_TYPE_ROUTE_INFO: + /* TODO implement preferred routes. + struct route_option * route_opt; + route_opt = (struct route_option *)buffer;*/ + + break; + default: + /* Unrecognized option, abort. */ + ND6_STATS_INC(nd6.proterr); + break; + } + offset += 8 * ((u16_t)buffer[1]); + } + + break; /* ICMP6_TYPE_RA */ + } + case ICMP6_TYPE_RD: /* Redirect */ + { + struct redirect_header * redir_hdr; + struct lladdr_option * lladdr_opt; + + /* Check that Redir header fits in packet. */ + if (p->len < sizeof(struct redirect_header)) { + /* TODO debug message */ + pbuf_free(p); + ND6_STATS_INC(nd6.lenerr); + ND6_STATS_INC(nd6.drop); + return; + } + + redir_hdr = (struct redirect_header *)p->payload; + + if (p->len >= (sizeof(struct redirect_header) + 2)) { + lladdr_opt = (struct lladdr_option *)((u8_t*)p->payload + sizeof(struct redirect_header)); + if (p->len < (sizeof(struct redirect_header) + (lladdr_opt->length << 3))) { + lladdr_opt = NULL; + } + } else { + lladdr_opt = NULL; + } + + /* Copy original destination address to current source address, to have an aligned copy. */ + ip6_addr_set(ip6_current_src_addr(), &(redir_hdr->destination_address)); + + /* Find dest address in cache */ + i = nd6_find_destination_cache_entry(ip6_current_src_addr()); + if (i < 0) { + /* Destination not in cache, drop packet. */ + pbuf_free(p); + return; + } + + /* Set the new target address. */ + ip6_addr_set(&(destination_cache[i].next_hop_addr), &(redir_hdr->target_address)); + + /* If Link-layer address of other router is given, try to add to neighbor cache. */ + if (lladdr_opt != NULL) { + if (lladdr_opt->type == ND6_OPTION_TYPE_TARGET_LLADDR) { + /* Copy target address to current source address, to have an aligned copy. */ + ip6_addr_set(ip6_current_src_addr(), &(redir_hdr->target_address)); + + i = nd6_find_neighbor_cache_entry(ip6_current_src_addr()); + if (i < 0) { + i = nd6_new_neighbor_cache_entry(); + if (i >= 0) { + neighbor_cache[i].netif = inp; + MEMCPY(neighbor_cache[i].lladdr, lladdr_opt->addr, inp->hwaddr_len); + ip6_addr_set(&(neighbor_cache[i].next_hop_address), ip6_current_src_addr()); + + /* Receiving a message does not prove reachability: only in one direction. + * Delay probe in case we get confirmation of reachability from upper layer (TCP). */ + neighbor_cache[i].state = ND6_DELAY; + neighbor_cache[i].counter.delay_time = LWIP_ND6_DELAY_FIRST_PROBE_TIME; + } + } + if (i >= 0) { + if (neighbor_cache[i].state == ND6_INCOMPLETE) { + MEMCPY(neighbor_cache[i].lladdr, lladdr_opt->addr, inp->hwaddr_len); + /* Receiving a message does not prove reachability: only in one direction. + * Delay probe in case we get confirmation of reachability from upper layer (TCP). */ + neighbor_cache[i].state = ND6_DELAY; + neighbor_cache[i].counter.delay_time = LWIP_ND6_DELAY_FIRST_PROBE_TIME; + } + } + } + } + break; /* ICMP6_TYPE_RD */ + } + case ICMP6_TYPE_PTB: /* Packet too big */ + { + struct icmp6_hdr *icmp6hdr; /* Packet too big message */ + struct ip6_hdr * ip6hdr; /* IPv6 header of the packet which caused the error */ + u32_t pmtu; + + /* Check that ICMPv6 header + IPv6 header fit in payload */ + if (p->len < (sizeof(struct icmp6_hdr) + IP6_HLEN)) { + /* drop short packets */ + pbuf_free(p); + ND6_STATS_INC(nd6.lenerr); + ND6_STATS_INC(nd6.drop); + return; + } + + icmp6hdr = (struct icmp6_hdr *)p->payload; + ip6hdr = (struct ip6_hdr *)((u8_t*)p->payload + sizeof(struct icmp6_hdr)); + + /* Copy original destination address to current source address, to have an aligned copy. */ + ip6_addr_set(ip6_current_src_addr(), &(ip6hdr->dest)); + + /* Look for entry in destination cache. */ + i = nd6_find_destination_cache_entry(ip6_current_src_addr()); + if (i < 0) { + /* Destination not in cache, drop packet. */ + pbuf_free(p); + return; + } + + /* Change the Path MTU. */ + pmtu = htonl(icmp6hdr->data); + destination_cache[i].pmtu = (u16_t)LWIP_MIN(pmtu, 0xFFFF); + + break; /* ICMP6_TYPE_PTB */ + } + + default: + ND6_STATS_INC(nd6.proterr); + ND6_STATS_INC(nd6.drop); + break; /* default */ + } + + pbuf_free(p); +} + + +/** + * Periodic timer for Neighbor discovery functions: + * + * - Update neighbor reachability states + * - Update destination cache entries age + * - Update invalidation timers of default routers and on-link prefixes + * - Perform duplicate address detection (DAD) for our addresses + * - Send router solicitations + */ +void +nd6_tmr(void) +{ + s8_t i; + struct netif * netif; + + /* Process neighbor entries. */ + for (i = 0; i < LWIP_ND6_NUM_NEIGHBORS; i++) { + switch (neighbor_cache[i].state) { + case ND6_INCOMPLETE: + if ((neighbor_cache[i].counter.probes_sent >= LWIP_ND6_MAX_MULTICAST_SOLICIT) && + (!neighbor_cache[i].isrouter)) { + /* Retries exceeded. */ + nd6_free_neighbor_cache_entry(i); + } else { + /* Send a NS for this entry. */ + neighbor_cache[i].counter.probes_sent++; + nd6_send_ns(neighbor_cache[i].netif, &(neighbor_cache[i].next_hop_address), ND6_SEND_FLAG_MULTICAST_DEST); + } + break; + case ND6_REACHABLE: + /* Send queued packets, if any are left. Should have been sent already. */ + if (neighbor_cache[i].q != NULL) { + nd6_send_q(i); + } + if (neighbor_cache[i].counter.reachable_time <= ND6_TMR_INTERVAL) { + /* Change to stale state. */ + neighbor_cache[i].state = ND6_STALE; + neighbor_cache[i].counter.stale_time = 0; + } else { + neighbor_cache[i].counter.reachable_time -= ND6_TMR_INTERVAL; + } + break; + case ND6_STALE: + neighbor_cache[i].counter.stale_time += ND6_TMR_INTERVAL; + break; + case ND6_DELAY: + if (neighbor_cache[i].counter.delay_time <= ND6_TMR_INTERVAL) { + /* Change to PROBE state. */ + neighbor_cache[i].state = ND6_PROBE; + neighbor_cache[i].counter.probes_sent = 0; + } else { + neighbor_cache[i].counter.delay_time -= ND6_TMR_INTERVAL; + } + break; + case ND6_PROBE: + if ((neighbor_cache[i].counter.probes_sent >= LWIP_ND6_MAX_MULTICAST_SOLICIT) && + (!neighbor_cache[i].isrouter)) { + /* Retries exceeded. */ + nd6_free_neighbor_cache_entry(i); + } else { + /* Send a NS for this entry. */ + neighbor_cache[i].counter.probes_sent++; + nd6_send_ns(neighbor_cache[i].netif, &(neighbor_cache[i].next_hop_address), 0); + } + break; + case ND6_NO_ENTRY: + default: + /* Do nothing. */ + break; + } + } + + /* Process destination entries. */ + for (i = 0; i < LWIP_ND6_NUM_DESTINATIONS; i++) { + destination_cache[i].age++; + } + + /* Process router entries. */ + for (i = 0; i < LWIP_ND6_NUM_ROUTERS; i++) { + if (default_router_list[i].neighbor_entry != NULL) { + /* Active entry. */ + if (default_router_list[i].invalidation_timer > 0) { + default_router_list[i].invalidation_timer -= ND6_TMR_INTERVAL / 1000; + } + if (default_router_list[i].invalidation_timer < ND6_TMR_INTERVAL / 1000) { + /* Less than 1 second remaining. Clear this entry. */ + default_router_list[i].neighbor_entry->isrouter = 0; + default_router_list[i].neighbor_entry = NULL; + default_router_list[i].invalidation_timer = 0; + default_router_list[i].flags = 0; + } + } + } + + /* Process prefix entries. */ + for (i = 0; i < LWIP_ND6_NUM_PREFIXES; i++) { + if (prefix_list[i].netif != NULL) { + if (prefix_list[i].invalidation_timer < ND6_TMR_INTERVAL / 1000) { + /* Entry timed out, remove it */ + prefix_list[i].invalidation_timer = 0; + +#if LWIP_IPV6_AUTOCONFIG + /* If any addresses were configured with this prefix, remove them */ + if (prefix_list[i].flags & ND6_PREFIX_AUTOCONFIG_ADDRESS_GENERATED) + { + s8_t j; + + for (j = 1; j < LWIP_IPV6_NUM_ADDRESSES; j++) { + if ((netif_ip6_addr_state(prefix_list[i].netif, j) != IP6_ADDR_INVALID) && + ip6_addr_netcmp(&prefix_list[i].prefix, netif_ip6_addr(prefix_list[i].netif, j))) { + netif_ip6_addr_set_state(prefix_list[i].netif, j, IP6_ADDR_INVALID); + prefix_list[i].flags = 0; + + /* Exit loop. */ + break; + } + } + } +#endif /* LWIP_IPV6_AUTOCONFIG */ + + prefix_list[i].netif = NULL; + prefix_list[i].flags = 0; + } else { + prefix_list[i].invalidation_timer -= ND6_TMR_INTERVAL / 1000; + +#if LWIP_IPV6_AUTOCONFIG + /* Initiate address autoconfiguration for this prefix, if conditions are met. */ + if (prefix_list[i].netif->ip6_autoconfig_enabled && + (prefix_list[i].flags & ND6_PREFIX_AUTOCONFIG_AUTONOMOUS) && + !(prefix_list[i].flags & ND6_PREFIX_AUTOCONFIG_ADDRESS_GENERATED)) { + s8_t j; + /* Try to get an address on this netif that is invalid. + * Skip 0 index (link-local address) */ + for (j = 1; j < LWIP_IPV6_NUM_ADDRESSES; j++) { + if (netif_ip6_addr_state(prefix_list[i].netif, j) == IP6_ADDR_INVALID) { + /* Generate an address using this prefix and interface ID from link-local address. */ + IP_ADDR6(&prefix_list[i].netif->ip6_addr[j], + prefix_list[i].prefix.addr[0], prefix_list[i].prefix.addr[1], + netif_ip6_addr(prefix_list[i].netif, 0)->addr[2], netif_ip6_addr(prefix_list[i].netif, 0)->addr[3]); + + /* Mark it as tentative (DAD will be performed if configured). */ + netif_ip6_addr_set_state(prefix_list[i].netif, j, IP6_ADDR_TENTATIVE); + + /* Mark this prefix with ADDRESS_GENERATED, so that we don't try again. */ + prefix_list[i].flags |= ND6_PREFIX_AUTOCONFIG_ADDRESS_GENERATED; + + /* Exit loop. */ + break; + } + } + } +#endif /* LWIP_IPV6_AUTOCONFIG */ + } + } + } + + + /* Process our own addresses, if DAD configured. */ + for (netif = netif_list; netif != NULL; netif = netif->next) { + for (i = 0; i < LWIP_IPV6_NUM_ADDRESSES; ++i) { + if (ip6_addr_istentative(netif->ip6_addr_state[i])) { + if ((netif->ip6_addr_state[i] & 0x07) >= LWIP_IPV6_DUP_DETECT_ATTEMPTS) { + /* No NA received in response. Mark address as valid. */ + netif->ip6_addr_state[i] = IP6_ADDR_PREFERRED; + /* TODO implement preferred and valid lifetimes. */ + } else if (netif->flags & NETIF_FLAG_UP) { +#if LWIP_IPV6_MLD + if ((netif->ip6_addr_state[i] & 0x07) == 0) { + /* Join solicited node multicast group. */ + ip6_addr_set_solicitednode(&multicast_address, netif_ip6_addr(netif, i)->addr[3]); + mld6_joingroup(netif_ip6_addr(netif, i), &multicast_address); + } +#endif /* LWIP_IPV6_MLD */ + /* Send a NS for this address. */ + nd6_send_ns(netif, netif_ip6_addr(netif, i), ND6_SEND_FLAG_MULTICAST_DEST); + (netif->ip6_addr_state[i])++; + /* TODO send max 1 NS per tmr call? enable return*/ + /*return;*/ + } + } + } + } + +#if LWIP_IPV6_SEND_ROUTER_SOLICIT + /* Send router solicitation messages, if necessary. */ + for (netif = netif_list; netif != NULL; netif = netif->next) { + if ((netif->rs_count > 0) && (netif->flags & NETIF_FLAG_UP) && + (!ip6_addr_isinvalid(netif_ip6_addr_state(netif, 0)))) { + if (nd6_send_rs(netif) == ERR_OK) { + netif->rs_count--; + } + } + } +#endif /* LWIP_IPV6_SEND_ROUTER_SOLICIT */ + +} + +/** + * Send a neighbor solicitation message + * + * @param netif the netif on which to send the message + * @param target_addr the IPv6 target address for the ND message + * @param flags one of ND6_SEND_FLAG_* + */ +static void +nd6_send_ns(struct netif * netif, const ip6_addr_t * target_addr, u8_t flags) +{ + struct ns_header * ns_hdr; + struct lladdr_option * lladdr_opt; + struct pbuf * p; + const ip6_addr_t * src_addr; + u16_t lladdr_opt_len; + + if (ip6_addr_isvalid(netif_ip6_addr_state(netif,0))) { + /* Use link-local address as source address. */ + src_addr = netif_ip6_addr(netif, 0); + } else { + src_addr = IP6_ADDR_ANY6; + } + + /* Allocate a packet. */ + lladdr_opt_len = ((netif->hwaddr_len + 2) >> 3) + (((netif->hwaddr_len + 2) & 0x07) ? 1 : 0); + p = pbuf_alloc(PBUF_IP, sizeof(struct ns_header) + (lladdr_opt_len << 3), PBUF_RAM); + if (p == NULL) { + ND6_STATS_INC(nd6.memerr); + return; + } + + /* Set fields. */ + ns_hdr = (struct ns_header *)p->payload; + lladdr_opt = (struct lladdr_option *)((u8_t*)p->payload + sizeof(struct ns_header)); + + ns_hdr->type = ICMP6_TYPE_NS; + ns_hdr->code = 0; + ns_hdr->chksum = 0; + ns_hdr->reserved = 0; + ip6_addr_set(&(ns_hdr->target_address), target_addr); + + lladdr_opt->type = ND6_OPTION_TYPE_SOURCE_LLADDR; + lladdr_opt->length = (u8_t)lladdr_opt_len; + SMEMCPY(lladdr_opt->addr, netif->hwaddr, netif->hwaddr_len); + + /* Generate the solicited node address for the target address. */ + if (flags & ND6_SEND_FLAG_MULTICAST_DEST) { + ip6_addr_set_solicitednode(&multicast_address, target_addr->addr[3]); + target_addr = &multicast_address; + } + +#if CHECKSUM_GEN_ICMP6 + IF__NETIF_CHECKSUM_ENABLED(netif, NETIF_CHECKSUM_GEN_ICMP6) { + ns_hdr->chksum = ip6_chksum_pseudo(p, IP6_NEXTH_ICMP6, p->len, src_addr, + target_addr); + } +#endif /* CHECKSUM_GEN_ICMP6 */ + + /* Send the packet out. */ + ND6_STATS_INC(nd6.xmit); + ip6_output_if(p, (src_addr == IP6_ADDR_ANY6) ? NULL : src_addr, target_addr, + LWIP_ICMP6_HL, 0, IP6_NEXTH_ICMP6, netif); + pbuf_free(p); +} + +/** + * Send a neighbor advertisement message + * + * @param netif the netif on which to send the message + * @param target_addr the IPv6 target address for the ND message + * @param flags one of ND6_SEND_FLAG_* + */ +static void +nd6_send_na(struct netif * netif, const ip6_addr_t * target_addr, u8_t flags) +{ + struct na_header * na_hdr; + struct lladdr_option * lladdr_opt; + struct pbuf * p; + const ip6_addr_t * src_addr; + const ip6_addr_t * dest_addr; + u16_t lladdr_opt_len; + + /* Use link-local address as source address. */ + /* src_addr = &(netif->ip6_addr[0]); */ + /* Use target address as source address. */ + src_addr = target_addr; + + /* Allocate a packet. */ + lladdr_opt_len = ((netif->hwaddr_len + 2) >> 3) + (((netif->hwaddr_len + 2) & 0x07) ? 1 : 0); + p = pbuf_alloc(PBUF_IP, sizeof(struct na_header) + (lladdr_opt_len << 3), PBUF_RAM); + if (p == NULL) { + ND6_STATS_INC(nd6.memerr); + return; + } + + /* Set fields. */ + na_hdr = (struct na_header *)p->payload; + lladdr_opt = (struct lladdr_option *)((u8_t*)p->payload + sizeof(struct na_header)); + + na_hdr->type = ICMP6_TYPE_NA; + na_hdr->code = 0; + na_hdr->chksum = 0; + na_hdr->flags = flags & 0xf0; + na_hdr->reserved[0] = 0; + na_hdr->reserved[1] = 0; + na_hdr->reserved[2] = 0; + ip6_addr_set(&(na_hdr->target_address), target_addr); + + lladdr_opt->type = ND6_OPTION_TYPE_TARGET_LLADDR; + lladdr_opt->length = (u8_t)lladdr_opt_len; + SMEMCPY(lladdr_opt->addr, netif->hwaddr, netif->hwaddr_len); + + /* Generate the solicited node address for the target address. */ + if (flags & ND6_SEND_FLAG_MULTICAST_DEST) { + ip6_addr_set_solicitednode(&multicast_address, target_addr->addr[3]); + dest_addr = &multicast_address; + } else if (flags & ND6_SEND_FLAG_ALLNODES_DEST) { + ip6_addr_set_allnodes_linklocal(&multicast_address); + dest_addr = &multicast_address; + } else { + dest_addr = ip6_current_src_addr(); + } + +#if CHECKSUM_GEN_ICMP6 + IF__NETIF_CHECKSUM_ENABLED(netif, NETIF_CHECKSUM_GEN_ICMP6) { + na_hdr->chksum = ip6_chksum_pseudo(p, IP6_NEXTH_ICMP6, p->len, src_addr, + dest_addr); + } +#endif /* CHECKSUM_GEN_ICMP6 */ + + /* Send the packet out. */ + ND6_STATS_INC(nd6.xmit); + ip6_output_if(p, src_addr, dest_addr, + LWIP_ICMP6_HL, 0, IP6_NEXTH_ICMP6, netif); + pbuf_free(p); +} + +#if LWIP_IPV6_SEND_ROUTER_SOLICIT +/** + * Send a router solicitation message + * + * @param netif the netif on which to send the message + */ +static err_t +nd6_send_rs(struct netif * netif) +{ + struct rs_header * rs_hdr; + struct lladdr_option * lladdr_opt; + struct pbuf * p; + const ip6_addr_t * src_addr; + err_t err; + u16_t lladdr_opt_len = 0; + + /* Link-local source address, or unspecified address? */ + if (ip6_addr_isvalid(netif_ip6_addr_state(netif, 0))) { + src_addr = netif_ip6_addr(netif, 0); + } else { + src_addr = IP6_ADDR_ANY6; + } + + /* Generate the all routers target address. */ + ip6_addr_set_allrouters_linklocal(&multicast_address); + + /* Allocate a packet. */ + if (src_addr != IP6_ADDR_ANY6) { + lladdr_opt_len = ((netif->hwaddr_len + 2) >> 3) + (((netif->hwaddr_len + 2) & 0x07) ? 1 : 0); + } + p = pbuf_alloc(PBUF_IP, sizeof(struct rs_header) + (lladdr_opt_len << 3), PBUF_RAM); + if (p == NULL) { + ND6_STATS_INC(nd6.memerr); + return ERR_BUF; + } + + /* Set fields. */ + rs_hdr = (struct rs_header *)p->payload; + + rs_hdr->type = ICMP6_TYPE_RS; + rs_hdr->code = 0; + rs_hdr->chksum = 0; + rs_hdr->reserved = 0; + + if (src_addr != IP6_ADDR_ANY6) { + /* Include our hw address. */ + lladdr_opt = (struct lladdr_option *)((u8_t*)p->payload + sizeof(struct rs_header)); + lladdr_opt->type = ND6_OPTION_TYPE_SOURCE_LLADDR; + lladdr_opt->length = (u8_t)lladdr_opt_len; + SMEMCPY(lladdr_opt->addr, netif->hwaddr, netif->hwaddr_len); + } + +#if CHECKSUM_GEN_ICMP6 + IF__NETIF_CHECKSUM_ENABLED(netif, NETIF_CHECKSUM_GEN_ICMP6) { + rs_hdr->chksum = ip6_chksum_pseudo(p, IP6_NEXTH_ICMP6, p->len, src_addr, + &multicast_address); + } +#endif /* CHECKSUM_GEN_ICMP6 */ + + /* Send the packet out. */ + ND6_STATS_INC(nd6.xmit); + + err = ip6_output_if(p, (src_addr == IP6_ADDR_ANY6) ? NULL : src_addr, &multicast_address, + LWIP_ICMP6_HL, 0, IP6_NEXTH_ICMP6, netif); + pbuf_free(p); + + return err; +} +#endif /* LWIP_IPV6_SEND_ROUTER_SOLICIT */ + +/** + * Search for a neighbor cache entry + * + * @param ip6addr the IPv6 address of the neighbor + * @return The neighbor cache entry index that matched, -1 if no + * entry is found + */ +static s8_t +nd6_find_neighbor_cache_entry(const ip6_addr_t * ip6addr) +{ + s8_t i; + for (i = 0; i < LWIP_ND6_NUM_NEIGHBORS; i++) { + if (ip6_addr_cmp(ip6addr, &(neighbor_cache[i].next_hop_address))) { + return i; + } + } + return -1; +} + +/** + * Create a new neighbor cache entry. + * + * If no unused entry is found, will try to recycle an old entry + * according to ad-hoc "age" heuristic. + * + * @return The neighbor cache entry index that was created, -1 if no + * entry could be created + */ +static s8_t +nd6_new_neighbor_cache_entry(void) +{ + s8_t i; + s8_t j; + u32_t time; + + + /* First, try to find an empty entry. */ + for (i = 0; i < LWIP_ND6_NUM_NEIGHBORS; i++) { + if (neighbor_cache[i].state == ND6_NO_ENTRY) { + return i; + } + } + + /* We need to recycle an entry. in general, do not recycle if it is a router. */ + + /* Next, try to find a Stale entry. */ + for (i = 0; i < LWIP_ND6_NUM_NEIGHBORS; i++) { + if ((neighbor_cache[i].state == ND6_STALE) && + (!neighbor_cache[i].isrouter)) { + nd6_free_neighbor_cache_entry(i); + return i; + } + } + + /* Next, try to find a Probe entry. */ + for (i = 0; i < LWIP_ND6_NUM_NEIGHBORS; i++) { + if ((neighbor_cache[i].state == ND6_PROBE) && + (!neighbor_cache[i].isrouter)) { + nd6_free_neighbor_cache_entry(i); + return i; + } + } + + /* Next, try to find a Delayed entry. */ + for (i = 0; i < LWIP_ND6_NUM_NEIGHBORS; i++) { + if ((neighbor_cache[i].state == ND6_DELAY) && + (!neighbor_cache[i].isrouter)) { + nd6_free_neighbor_cache_entry(i); + return i; + } + } + + /* Next, try to find the oldest reachable entry. */ + time = 0xfffffffful; + j = -1; + for (i = 0; i < LWIP_ND6_NUM_NEIGHBORS; i++) { + if ((neighbor_cache[i].state == ND6_REACHABLE) && + (!neighbor_cache[i].isrouter)) { + if (neighbor_cache[i].counter.reachable_time < time) { + j = i; + time = neighbor_cache[i].counter.reachable_time; + } + } + } + if (j >= 0) { + nd6_free_neighbor_cache_entry(j); + return j; + } + + /* Next, find oldest incomplete entry without queued packets. */ + time = 0; + j = -1; + for (i = 0; i < LWIP_ND6_NUM_NEIGHBORS; i++) { + if ( + (neighbor_cache[i].q == NULL) && + (neighbor_cache[i].state == ND6_INCOMPLETE) && + (!neighbor_cache[i].isrouter)) { + if (neighbor_cache[i].counter.probes_sent >= time) { + j = i; + time = neighbor_cache[i].counter.probes_sent; + } + } + } + if (j >= 0) { + nd6_free_neighbor_cache_entry(j); + return j; + } + + /* Next, find oldest incomplete entry with queued packets. */ + time = 0; + j = -1; + for (i = 0; i < LWIP_ND6_NUM_NEIGHBORS; i++) { + if ((neighbor_cache[i].state == ND6_INCOMPLETE) && + (!neighbor_cache[i].isrouter)) { + if (neighbor_cache[i].counter.probes_sent >= time) { + j = i; + time = neighbor_cache[i].counter.probes_sent; + } + } + } + if (j >= 0) { + nd6_free_neighbor_cache_entry(j); + return j; + } + + /* No more entries to try. */ + return -1; +} + +/** + * Will free any resources associated with a neighbor cache + * entry, and will mark it as unused. + * + * @param i the neighbor cache entry index to free + */ +static void +nd6_free_neighbor_cache_entry(s8_t i) +{ + if ((i < 0) || (i >= LWIP_ND6_NUM_NEIGHBORS)) { + return; + } + if (neighbor_cache[i].isrouter) { + /* isrouter needs to be cleared before deleting a neighbor cache entry */ + return; + } + + /* Free any queued packets. */ + if (neighbor_cache[i].q != NULL) { + nd6_free_q(neighbor_cache[i].q); + neighbor_cache[i].q = NULL; + } + + neighbor_cache[i].state = ND6_NO_ENTRY; + neighbor_cache[i].isrouter = 0; + neighbor_cache[i].netif = NULL; + neighbor_cache[i].counter.reachable_time = 0; + ip6_addr_set_zero(&(neighbor_cache[i].next_hop_address)); +} + +/** + * Search for a destination cache entry + * + * @param ip6addr the IPv6 address of the destination + * @return The destination cache entry index that matched, -1 if no + * entry is found + */ +static s8_t +nd6_find_destination_cache_entry(const ip6_addr_t * ip6addr) +{ + s8_t i; + for (i = 0; i < LWIP_ND6_NUM_DESTINATIONS; i++) { + if (ip6_addr_cmp(ip6addr, &(destination_cache[i].destination_addr))) { + return i; + } + } + return -1; +} + +/** + * Create a new destination cache entry. If no unused entry is found, + * will recycle oldest entry. + * + * @return The destination cache entry index that was created, -1 if no + * entry was created + */ +static s8_t +nd6_new_destination_cache_entry(void) +{ + s8_t i, j; + u32_t age; + + /* Find an empty entry. */ + for (i = 0; i < LWIP_ND6_NUM_DESTINATIONS; i++) { + if (ip6_addr_isany(&(destination_cache[i].destination_addr))) { + return i; + } + } + + /* Find oldest entry. */ + age = 0; + j = LWIP_ND6_NUM_DESTINATIONS - 1; + for (i = 0; i < LWIP_ND6_NUM_DESTINATIONS; i++) { + if (destination_cache[i].age > age) { + j = i; + } + } + + return j; +} + +/** + * Determine whether an address matches an on-link prefix. + * + * @param ip6addr the IPv6 address to match + * @return 1 if the address is on-link, 0 otherwise + */ +static s8_t +nd6_is_prefix_in_netif(const ip6_addr_t * ip6addr, struct netif * netif) +{ + s8_t i; + for (i = 0; i < LWIP_ND6_NUM_PREFIXES; i++) { + if ((prefix_list[i].netif == netif) && + (prefix_list[i].invalidation_timer > 0) && + ip6_addr_netcmp(ip6addr, &(prefix_list[i].prefix))) { + return 1; + } + } + /* Check to see if address prefix matches a (manually?) configured address. */ + for (i = 0; i < LWIP_IPV6_NUM_ADDRESSES; i++) { + if (ip6_addr_isvalid(netif_ip6_addr_state(netif, i)) && + ip6_addr_netcmp(ip6addr, netif_ip6_addr(netif, i))) { + return 1; + } + } + return 0; +} + +/** + * Select a default router for a destination. + * + * @param ip6addr the destination address + * @param netif the netif for the outgoing packet, if known + * @return the default router entry index, or -1 if no suitable + * router is found + */ +s8_t +nd6_select_router(const ip6_addr_t * ip6addr, struct netif * netif) +{ + s8_t i; + /* last_router is used for round-robin router selection (as recommended + * in RFC). This is more robust in case one router is not reachable, + * we are not stuck trying to resolve it. */ + static s8_t last_router; + (void)ip6addr; /* TODO match preferred routes!! (must implement ND6_OPTION_TYPE_ROUTE_INFO) */ + + /* TODO: implement default router preference */ + + /* Look for reachable routers. */ + for (i = 0; i < LWIP_ND6_NUM_ROUTERS; i++) { + if (++last_router >= LWIP_ND6_NUM_ROUTERS) { + last_router = 0; + } + if ((default_router_list[i].neighbor_entry != NULL) && + (netif != NULL ? netif == default_router_list[i].neighbor_entry->netif : 1) && + (default_router_list[i].invalidation_timer > 0) && + (default_router_list[i].neighbor_entry->state == ND6_REACHABLE)) { + return i; + } + } + + /* Look for router in other reachability states, but still valid according to timer. */ + for (i = 0; i < LWIP_ND6_NUM_ROUTERS; i++) { + if (++last_router >= LWIP_ND6_NUM_ROUTERS) { + last_router = 0; + } + if ((default_router_list[i].neighbor_entry != NULL) && + (netif != NULL ? netif == default_router_list[i].neighbor_entry->netif : 1) && + (default_router_list[i].invalidation_timer > 0)) { + return i; + } + } + + /* Look for any router for which we have any information at all. */ + for (i = 0; i < LWIP_ND6_NUM_ROUTERS; i++) { + if (++last_router >= LWIP_ND6_NUM_ROUTERS) { + last_router = 0; + } + if (default_router_list[i].neighbor_entry != NULL && + (netif != NULL ? netif == default_router_list[i].neighbor_entry->netif : 1)) { + return i; + } + } + + /* no suitable router found. */ + return -1; +} + +/** + * Find an entry for a default router. + * + * @param router_addr the IPv6 address of the router + * @param netif the netif on which the router is found, if known + * @return the index of the router entry, or -1 if not found + */ +static s8_t +nd6_get_router(const ip6_addr_t * router_addr, struct netif * netif) +{ + s8_t i; + + /* Look for router. */ + for (i = 0; i < LWIP_ND6_NUM_ROUTERS; i++) { + if ((default_router_list[i].neighbor_entry != NULL) && + ((netif != NULL) ? netif == default_router_list[i].neighbor_entry->netif : 1) && + ip6_addr_cmp(router_addr, &(default_router_list[i].neighbor_entry->next_hop_address))) { + return i; + } + } + + /* router not found. */ + return -1; +} + +/** + * Create a new entry for a default router. + * + * @param router_addr the IPv6 address of the router + * @param netif the netif on which the router is connected, if known + * @return the index on the router table, or -1 if could not be created + */ +static s8_t +nd6_new_router(const ip6_addr_t * router_addr, struct netif * netif) +{ + s8_t router_index; + s8_t neighbor_index; + + /* Do we have a neighbor entry for this router? */ + neighbor_index = nd6_find_neighbor_cache_entry(router_addr); + if (neighbor_index < 0) { + /* Create a neighbor entry for this router. */ + neighbor_index = nd6_new_neighbor_cache_entry(); + if (neighbor_index < 0) { + /* Could not create neighbor entry for this router. */ + return -1; + } + ip6_addr_set(&(neighbor_cache[neighbor_index].next_hop_address), router_addr); + neighbor_cache[neighbor_index].netif = netif; + neighbor_cache[neighbor_index].q = NULL; + neighbor_cache[neighbor_index].state = ND6_INCOMPLETE; + neighbor_cache[neighbor_index].counter.probes_sent = 0; + } + + /* Mark neighbor as router. */ + neighbor_cache[neighbor_index].isrouter = 1; + + /* Look for empty entry. */ + for (router_index = 0; router_index < LWIP_ND6_NUM_ROUTERS; router_index++) { + if (default_router_list[router_index].neighbor_entry == NULL) { + default_router_list[router_index].neighbor_entry = &(neighbor_cache[neighbor_index]); + return router_index; + } + } + + /* Could not create a router entry. */ + + /* Mark neighbor entry as not-router. Entry might be useful as neighbor still. */ + neighbor_cache[neighbor_index].isrouter = 0; + + /* router not found. */ + return -1; +} + +/** + * Find the cached entry for an on-link prefix. + * + * @param prefix the IPv6 prefix that is on-link + * @param netif the netif on which the prefix is on-link + * @return the index on the prefix table, or -1 if not found + */ +static s8_t +nd6_get_onlink_prefix(ip6_addr_t * prefix, struct netif * netif) +{ + s8_t i; + + /* Look for prefix in list. */ + for (i = 0; i < LWIP_ND6_NUM_PREFIXES; ++i) { + if ((ip6_addr_netcmp(&(prefix_list[i].prefix), prefix)) && + (prefix_list[i].netif == netif)) { + return i; + } + } + + /* Entry not available. */ + return -1; +} + +/** + * Creates a new entry for an on-link prefix. + * + * @param prefix the IPv6 prefix that is on-link + * @param netif the netif on which the prefix is on-link + * @return the index on the prefix table, or -1 if not created + */ +static s8_t +nd6_new_onlink_prefix(ip6_addr_t * prefix, struct netif * netif) +{ + s8_t i; + + /* Create new entry. */ + for (i = 0; i < LWIP_ND6_NUM_PREFIXES; ++i) { + if ((prefix_list[i].netif == NULL) || + (prefix_list[i].invalidation_timer == 0)) { + /* Found empty prefix entry. */ + prefix_list[i].netif = netif; + ip6_addr_set(&(prefix_list[i].prefix), prefix); +#if LWIP_IPV6_AUTOCONFIG + prefix_list[i].flags = 0; +#endif /* LWIP_IPV6_AUTOCONFIG */ + return i; + } + } + + /* Entry not available. */ + return -1; +} + +/** + * Determine the next hop for a destination. Will determine if the + * destination is on-link, else a suitable on-link router is selected. + * + * The last entry index is cached for fast entry search. + * + * @param ip6addr the destination address + * @param netif the netif on which the packet will be sent + * @return the neighbor cache entry for the next hop, ERR_RTE if no + * suitable next hop was found, ERR_MEM if no cache entry + * could be created + */ +s8_t +nd6_get_next_hop_entry(const ip6_addr_t * ip6addr, struct netif * netif) +{ + s8_t i; + +#if LWIP_NETIF_HWADDRHINT + if (netif->addr_hint != NULL) { + /* per-pcb cached entry was given */ + u8_t addr_hint = *(netif->addr_hint); + if (addr_hint < LWIP_ND6_NUM_DESTINATIONS) { + nd6_cached_destination_index = addr_hint; + } + } +#endif /* LWIP_NETIF_HWADDRHINT */ + + /* Look for ip6addr in destination cache. */ + if (ip6_addr_cmp(ip6addr, &(destination_cache[nd6_cached_destination_index].destination_addr))) { + /* the cached entry index is the right one! */ + /* do nothing. */ + ND6_STATS_INC(nd6.cachehit); + } else { + /* Search destination cache. */ + i = nd6_find_destination_cache_entry(ip6addr); + if (i >= 0) { + /* found destination entry. make it our new cached index. */ + nd6_cached_destination_index = i; + } else { + /* Not found. Create a new destination entry. */ + i = nd6_new_destination_cache_entry(); + if (i >= 0) { + /* got new destination entry. make it our new cached index. */ + nd6_cached_destination_index = i; + } else { + /* Could not create a destination cache entry. */ + return ERR_MEM; + } + + /* Copy dest address to destination cache. */ + ip6_addr_set(&(destination_cache[nd6_cached_destination_index].destination_addr), ip6addr); + + /* Now find the next hop. is it a neighbor? */ + if (ip6_addr_islinklocal(ip6addr) || + nd6_is_prefix_in_netif(ip6addr, netif)) { + /* Destination in local link. */ + destination_cache[nd6_cached_destination_index].pmtu = netif->mtu; + ip6_addr_copy(destination_cache[nd6_cached_destination_index].next_hop_addr, destination_cache[nd6_cached_destination_index].destination_addr); + } else { + /* We need to select a router. */ + i = nd6_select_router(ip6addr, netif); + if (i < 0) { + /* No router found. */ + ip6_addr_set_any(&(destination_cache[nd6_cached_destination_index].destination_addr)); + return ERR_RTE; + } + destination_cache[nd6_cached_destination_index].pmtu = netif->mtu; /* Start with netif mtu, correct through ICMPv6 if necessary */ + ip6_addr_copy(destination_cache[nd6_cached_destination_index].next_hop_addr, default_router_list[i].neighbor_entry->next_hop_address); + } + } + } + +#if LWIP_NETIF_HWADDRHINT + if (netif->addr_hint != NULL) { + /* per-pcb cached entry was given */ + *(netif->addr_hint) = nd6_cached_destination_index; + } +#endif /* LWIP_NETIF_HWADDRHINT */ + + /* Look in neighbor cache for the next-hop address. */ + if (ip6_addr_cmp(&(destination_cache[nd6_cached_destination_index].next_hop_addr), + &(neighbor_cache[nd6_cached_neighbor_index].next_hop_address))) { + /* Cache hit. */ + /* Do nothing. */ + ND6_STATS_INC(nd6.cachehit); + } else { + i = nd6_find_neighbor_cache_entry(&(destination_cache[nd6_cached_destination_index].next_hop_addr)); + if (i >= 0) { + /* Found a matching record, make it new cached entry. */ + nd6_cached_neighbor_index = i; + } else { + /* Neighbor not in cache. Make a new entry. */ + i = nd6_new_neighbor_cache_entry(); + if (i >= 0) { + /* got new neighbor entry. make it our new cached index. */ + nd6_cached_neighbor_index = i; + } else { + /* Could not create a neighbor cache entry. */ + return ERR_MEM; + } + + /* Initialize fields. */ + ip6_addr_copy(neighbor_cache[i].next_hop_address, + destination_cache[nd6_cached_destination_index].next_hop_addr); + neighbor_cache[i].isrouter = 0; + neighbor_cache[i].netif = netif; + neighbor_cache[i].state = ND6_INCOMPLETE; + neighbor_cache[i].counter.probes_sent = 0; + } + } + + /* Reset this destination's age. */ + destination_cache[nd6_cached_destination_index].age = 0; + + return nd6_cached_neighbor_index; +} + +/** + * Queue a packet for a neighbor. + * + * @param neighbor_index the index in the neighbor cache table + * @param q packet to be queued + * @return ERR_OK if succeeded, ERR_MEM if out of memory + */ +err_t +nd6_queue_packet(s8_t neighbor_index, struct pbuf * q) +{ + err_t result = ERR_MEM; + struct pbuf *p; + int copy_needed = 0; +#if LWIP_ND6_QUEUEING + struct nd6_q_entry *new_entry, *r; +#endif /* LWIP_ND6_QUEUEING */ + + if ((neighbor_index < 0) || (neighbor_index >= LWIP_ND6_NUM_NEIGHBORS)) { + return ERR_ARG; + } + + /* IF q includes a PBUF_REF, PBUF_POOL or PBUF_RAM, we have no choice but + * to copy the whole queue into a new PBUF_RAM (see bug #11400) + * PBUF_ROMs can be left as they are, since ROM must not get changed. */ + p = q; + while (p) { + if (p->type != PBUF_ROM) { + copy_needed = 1; + break; + } + p = p->next; + } + if (copy_needed) { + /* copy the whole packet into new pbufs */ + p = pbuf_alloc(PBUF_LINK, q->tot_len, PBUF_RAM); + while ((p == NULL) && (neighbor_cache[neighbor_index].q != NULL)) { + /* Free oldest packet (as per RFC recommendation) */ +#if LWIP_ND6_QUEUEING + r = neighbor_cache[neighbor_index].q; + neighbor_cache[neighbor_index].q = r->next; + r->next = NULL; + nd6_free_q(r); +#else /* LWIP_ND6_QUEUEING */ + pbuf_free(neighbor_cache[neighbor_index].q); + neighbor_cache[neighbor_index].q = NULL; +#endif /* LWIP_ND6_QUEUEING */ + p = pbuf_alloc(PBUF_LINK, q->tot_len, PBUF_RAM); + } + if (p != NULL) { + if (pbuf_copy(p, q) != ERR_OK) { + pbuf_free(p); + p = NULL; + } + } + } else { + /* referencing the old pbuf is enough */ + p = q; + pbuf_ref(p); + } + /* packet was copied/ref'd? */ + if (p != NULL) { + /* queue packet ... */ +#if LWIP_ND6_QUEUEING + /* allocate a new nd6 queue entry */ + new_entry = (struct nd6_q_entry *)memp_malloc(MEMP_ND6_QUEUE); + if ((new_entry == NULL) && (neighbor_cache[neighbor_index].q != NULL)) { + /* Free oldest packet (as per RFC recommendation) */ + r = neighbor_cache[neighbor_index].q; + neighbor_cache[neighbor_index].q = r->next; + r->next = NULL; + nd6_free_q(r); + new_entry = (struct nd6_q_entry *)memp_malloc(MEMP_ND6_QUEUE); + } + if (new_entry != NULL) { + new_entry->next = NULL; + new_entry->p = p; + if (neighbor_cache[neighbor_index].q != NULL) { + /* queue was already existent, append the new entry to the end */ + r = neighbor_cache[neighbor_index].q; + while (r->next != NULL) { + r = r->next; + } + r->next = new_entry; + } else { + /* queue did not exist, first item in queue */ + neighbor_cache[neighbor_index].q = new_entry; + } + LWIP_DEBUGF(LWIP_DBG_TRACE, ("ipv6: queued packet %p on neighbor entry %"S16_F"\n", (void *)p, (s16_t)neighbor_index)); + result = ERR_OK; + } else { + /* the pool MEMP_ND6_QUEUE is empty */ + pbuf_free(p); + LWIP_DEBUGF(LWIP_DBG_TRACE, ("ipv6: could not queue a copy of packet %p (out of memory)\n", (void *)p)); + /* { result == ERR_MEM } through initialization */ + } +#else /* LWIP_ND6_QUEUEING */ + /* Queue a single packet. If an older packet is already queued, free it as per RFC. */ + if (neighbor_cache[neighbor_index].q != NULL) { + pbuf_free(neighbor_cache[neighbor_index].q); + } + neighbor_cache[neighbor_index].q = p; + LWIP_DEBUGF(LWIP_DBG_TRACE, ("ipv6: queued packet %p on neighbor entry %"S16_F"\n", (void *)p, (s16_t)neighbor_index)); + result = ERR_OK; +#endif /* LWIP_ND6_QUEUEING */ + } else { + LWIP_DEBUGF(LWIP_DBG_TRACE, ("ipv6: could not queue a copy of packet %p (out of memory)\n", (void *)q)); + /* { result == ERR_MEM } through initialization */ + } + + return result; +} + +#if LWIP_ND6_QUEUEING +/** + * Free a complete queue of nd6 q entries + * + * @param q a queue of nd6_q_entry to free + */ +static void +nd6_free_q(struct nd6_q_entry *q) +{ + struct nd6_q_entry *r; + LWIP_ASSERT("q != NULL", q != NULL); + LWIP_ASSERT("q->p != NULL", q->p != NULL); + while (q) { + r = q; + q = q->next; + LWIP_ASSERT("r->p != NULL", (r->p != NULL)); + pbuf_free(r->p); + memp_free(MEMP_ND6_QUEUE, r); + } +} +#endif /* LWIP_ND6_QUEUEING */ + +/** + * Send queued packets for a neighbor + * + * @param i the neighbor to send packets to + */ +static void +nd6_send_q(s8_t i) +{ + struct ip6_hdr *ip6hdr; +#if LWIP_ND6_QUEUEING + struct nd6_q_entry *q; +#endif /* LWIP_ND6_QUEUEING */ + + if ((i < 0) || (i >= LWIP_ND6_NUM_NEIGHBORS)) { + return; + } + +#if LWIP_ND6_QUEUEING + while (neighbor_cache[i].q != NULL) { + /* remember first in queue */ + q = neighbor_cache[i].q; + /* pop first item off the queue */ + neighbor_cache[i].q = q->next; + /* Get ipv6 header. */ + ip6hdr = (struct ip6_hdr *)(q->p->payload); + /* Override ip6_current_dest_addr() so that we have an aligned copy. */ + ip6_addr_set(ip6_current_dest_addr(), &(ip6hdr->dest)); + /* send the queued IPv6 packet */ + (neighbor_cache[i].netif)->output_ip6(neighbor_cache[i].netif, q->p, ip6_current_dest_addr()); + /* free the queued IP packet */ + pbuf_free(q->p); + /* now queue entry can be freed */ + memp_free(MEMP_ND6_QUEUE, q); + } +#else /* LWIP_ND6_QUEUEING */ + if (neighbor_cache[i].q != NULL) { + /* Get ipv6 header. */ + ip6hdr = (struct ip6_hdr *)(neighbor_cache[i].q->payload); + /* Override ip6_current_dest_addr() so that we have an aligned copy. */ + ip6_addr_set(ip6_current_dest_addr(), &(ip6hdr->dest)); + /* send the queued IPv6 packet */ + (neighbor_cache[i].netif)->output_ip6(neighbor_cache[i].netif, neighbor_cache[i].q, ip6_current_dest_addr()); + /* free the queued IP packet */ + pbuf_free(neighbor_cache[i].q); + neighbor_cache[i].q = NULL; + } +#endif /* LWIP_ND6_QUEUEING */ +} + + +/** + * Get the Path MTU for a destination. + * + * @param ip6addr the destination address + * @param netif the netif on which the packet will be sent + * @return the Path MTU, if known, or the netif default MTU + */ +u16_t +nd6_get_destination_mtu(const ip6_addr_t * ip6addr, struct netif * netif) +{ + s8_t i; + + i = nd6_find_destination_cache_entry(ip6addr); + if (i >= 0) { + if (destination_cache[i].pmtu > 0) { + return destination_cache[i].pmtu; + } + } + + if (netif != NULL) { + return netif->mtu; + } + + return 1280; /* Minimum MTU */ +} + + +#if LWIP_ND6_TCP_REACHABILITY_HINTS +/** + * Provide the Neighbor discovery process with a hint that a + * destination is reachable. Called by tcp_receive when ACKs are + * received or sent (as per RFC). This is useful to avoid sending + * NS messages every 30 seconds. + * + * @param ip6addr the destination address which is know to be reachable + * by an upper layer protocol (TCP) + */ +void +nd6_reachability_hint(const ip6_addr_t * ip6addr) +{ + s8_t i; + + /* Find destination in cache. */ + if (ip6_addr_cmp(ip6addr, &(destination_cache[nd6_cached_destination_index].destination_addr))) { + i = nd6_cached_destination_index; + ND6_STATS_INC(nd6.cachehit); + } else { + i = nd6_find_destination_cache_entry(ip6addr); + } + if (i < 0) { + return; + } + + /* Find next hop neighbor in cache. */ + if (ip6_addr_cmp(&(destination_cache[i].next_hop_addr), &(neighbor_cache[nd6_cached_neighbor_index].next_hop_address))) { + i = nd6_cached_neighbor_index; + ND6_STATS_INC(nd6.cachehit); + } else { + i = nd6_find_neighbor_cache_entry(&(destination_cache[i].next_hop_addr)); + } + if (i < 0) { + return; + } + + /* For safety: don't set as reachable if we don't have a LL address yet. Misuse protection. */ + if (neighbor_cache[i].state == ND6_INCOMPLETE || neighbor_cache[i].state == ND6_NO_ENTRY) { + return; + } + + /* Set reachability state. */ + neighbor_cache[i].state = ND6_REACHABLE; + neighbor_cache[i].counter.reachable_time = reachable_time; +} +#endif /* LWIP_ND6_TCP_REACHABILITY_HINTS */ + +#endif /* LWIP_IPV6 */ diff --git a/components/lwip/core/mem.c b/components/lwip/core/mem.c new file mode 100755 index 0000000000..42df6daeba --- /dev/null +++ b/components/lwip/core/mem.c @@ -0,0 +1,686 @@ +/** + * @file + * Dynamic memory manager + * + * This is a lightweight replacement for the standard C library malloc(). + * + * If you want to use the standard C library malloc() instead, define + * MEM_LIBC_MALLOC to 1 in your lwipopts.h + * + * To let mem_malloc() use pools (prevents fragmentation and is much faster than + * a heap but might waste some memory), define MEM_USE_POOLS to 1, define + * MEM_USE_CUSTOM_POOLS to 1 and create a file "lwippools.h" that includes a list + * of pools like this (more pools can be added between _START and _END): + * + * Define three pools with sizes 256, 512, and 1512 bytes + * LWIP_MALLOC_MEMPOOL_START + * LWIP_MALLOC_MEMPOOL(20, 256) + * LWIP_MALLOC_MEMPOOL(10, 512) + * LWIP_MALLOC_MEMPOOL(5, 1512) + * LWIP_MALLOC_MEMPOOL_END + */ + +/* + * Copyright (c) 2001-2004 Swedish Institute of Computer Science. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + * Simon Goldschmidt + * + */ + +#include "lwip/opt.h" + +#if !MEM_LIBC_MALLOC /* don't build if not configured for use in lwipopts.h */ + +#include "lwip/def.h" +#include "lwip/mem.h" +#include "lwip/sys.h" +#include "lwip/stats.h" +#include "lwip/err.h" + +#include + +#ifdef MEMLEAK_DEBUG +static const char mem_debug_file[] ICACHE_RODATA_ATTR STORE_ATTR = __FILE__; +#endif + +#if MEM_USE_POOLS + +#if MEMP_MEM_MALLOC +#error MEM_USE_POOLS and MEMP_MEM_MALLOC cannot be used together +#endif + +/* lwIP head implemented with different sized pools */ + +/** + * Allocate memory: determine the smallest pool that is big enough + * to contain an element of 'size' and get an element from that pool. + * + * @param size the size in bytes of the memory needed + * @return a pointer to the allocated memory or NULL if the pool is empty + */ +void * +mem_malloc(mem_size_t size) +{ + void *ret; + struct memp_malloc_helper *element; + memp_t poolnr; + mem_size_t required_size = size + LWIP_MEM_ALIGN_SIZE(sizeof(struct memp_malloc_helper)); + + for (poolnr = MEMP_POOL_FIRST; poolnr <= MEMP_POOL_LAST; poolnr = (memp_t)(poolnr + 1)) { +#if MEM_USE_POOLS_TRY_BIGGER_POOL +again: +#endif /* MEM_USE_POOLS_TRY_BIGGER_POOL */ + /* is this pool big enough to hold an element of the required size + plus a struct memp_malloc_helper that saves the pool this element came from? */ + if (required_size <= memp_pools[poolnr]->size) { + break; + } + } + if (poolnr > MEMP_POOL_LAST) { + LWIP_ASSERT("mem_malloc(): no pool is that big!", 0); + return NULL; + } + element = (struct memp_malloc_helper*)memp_malloc(poolnr); + if (element == NULL) { + /* No need to DEBUGF or ASSERT: This error is already + taken care of in memp.c */ +#if MEM_USE_POOLS_TRY_BIGGER_POOL + /** Try a bigger pool if this one is empty! */ + if (poolnr < MEMP_POOL_LAST) { + poolnr++; + goto again; + } +#endif /* MEM_USE_POOLS_TRY_BIGGER_POOL */ + return NULL; + } + + /* save the pool number this element came from */ + element->poolnr = poolnr; + /* and return a pointer to the memory directly after the struct memp_malloc_helper */ + ret = (u8_t*)element + LWIP_MEM_ALIGN_SIZE(sizeof(struct memp_malloc_helper)); + +#if MEMP_OVERFLOW_CHECK + /* initialize unused memory */ + element->size = size; + memset((u8_t*)ret + size, 0xcd, memp_pools[poolnr]->size - size); +#endif /* MEMP_OVERFLOW_CHECK */ + return ret; +} + +/** + * Free memory previously allocated by mem_malloc. Loads the pool number + * and calls memp_free with that pool number to put the element back into + * its pool + * + * @param rmem the memory element to free + */ +void +mem_free(void *rmem) +{ + struct memp_malloc_helper *hmem; + + LWIP_ASSERT("rmem != NULL", (rmem != NULL)); + LWIP_ASSERT("rmem == MEM_ALIGN(rmem)", (rmem == LWIP_MEM_ALIGN(rmem))); + + /* get the original struct memp_malloc_helper */ + hmem = (struct memp_malloc_helper*)(void*)((u8_t*)rmem - LWIP_MEM_ALIGN_SIZE(sizeof(struct memp_malloc_helper))); + + LWIP_ASSERT("hmem != NULL", (hmem != NULL)); + LWIP_ASSERT("hmem == MEM_ALIGN(hmem)", (hmem == LWIP_MEM_ALIGN(hmem))); + LWIP_ASSERT("hmem->poolnr < MEMP_MAX", (hmem->poolnr < MEMP_MAX)); + +#if MEMP_OVERFLOW_CHECK + { + u16_t i; + LWIP_ASSERT("MEM_USE_POOLS: invalid chunk size", + hmem->size <= memp_pools[hmem->poolnr]->size); + /* check that unused memory remained untouched */ + for (i = hmem->size; i < memp_pools[hmem->poolnr]->size; i++) { + u8_t data = *((u8_t*)rmem + i); + LWIP_ASSERT("MEM_USE_POOLS: mem overflow detected", data == 0xcd); + } + } +#endif /* MEMP_OVERFLOW_CHECK */ + + /* and put it in the pool we saved earlier */ + memp_free(hmem->poolnr, hmem); +} + +#else /* MEM_USE_POOLS */ +/* lwIP replacement for your libc malloc() */ + +/** + * The heap is made up as a list of structs of this type. + * This does not have to be aligned since for getting its size, + * we only use the macro SIZEOF_STRUCT_MEM, which automatically aligns. + */ +struct mem { + /** index (-> ram[next]) of the next struct */ + mem_size_t next; + /** index (-> ram[prev]) of the previous struct */ + mem_size_t prev; + /** 1: this area is used; 0: this area is unused */ + u8_t used; +}; + +/** All allocated blocks will be MIN_SIZE bytes big, at least! + * MIN_SIZE can be overridden to suit your needs. Smaller values save space, + * larger values could prevent too small blocks to fragment the RAM too much. */ +#ifndef MIN_SIZE +#define MIN_SIZE 12 +#endif /* MIN_SIZE */ +/* some alignment macros: we define them here for better source code layout */ +#define MIN_SIZE_ALIGNED LWIP_MEM_ALIGN_SIZE(MIN_SIZE) +#define SIZEOF_STRUCT_MEM LWIP_MEM_ALIGN_SIZE(sizeof(struct mem)) +#define MEM_SIZE_ALIGNED LWIP_MEM_ALIGN_SIZE(MEM_SIZE) + +/** If you want to relocate the heap to external memory, simply define + * LWIP_RAM_HEAP_POINTER as a void-pointer to that location. + * If so, make sure the memory at that location is big enough (see below on + * how that space is calculated). */ +#ifndef LWIP_RAM_HEAP_POINTER +/** the heap. we need one struct mem at the end and some room for alignment */ +u8_t ram_heap[MEM_SIZE_ALIGNED + (2U*SIZEOF_STRUCT_MEM) + MEM_ALIGNMENT]; +#define LWIP_RAM_HEAP_POINTER ram_heap +#endif /* LWIP_RAM_HEAP_POINTER */ + +/** pointer to the heap (ram_heap): for alignment, ram is now a pointer instead of an array */ +static u8_t *ram; +/** the last entry, always unused! */ +static struct mem *ram_end; +/** pointer to the lowest free block, this is used for faster search */ +static struct mem *lfree; + +/** concurrent access protection */ +#if !NO_SYS +static sys_mutex_t mem_mutex; +#endif + +#if LWIP_ALLOW_MEM_FREE_FROM_OTHER_CONTEXT + +static volatile u8_t mem_free_count; + +/* Allow mem_free from other (e.g. interrupt) context */ +#define LWIP_MEM_FREE_DECL_PROTECT() SYS_ARCH_DECL_PROTECT(lev_free) +#define LWIP_MEM_FREE_PROTECT() SYS_ARCH_PROTECT(lev_free) +#define LWIP_MEM_FREE_UNPROTECT() SYS_ARCH_UNPROTECT(lev_free) +#define LWIP_MEM_ALLOC_DECL_PROTECT() SYS_ARCH_DECL_PROTECT(lev_alloc) +#define LWIP_MEM_ALLOC_PROTECT() SYS_ARCH_PROTECT(lev_alloc) +#define LWIP_MEM_ALLOC_UNPROTECT() SYS_ARCH_UNPROTECT(lev_alloc) + +#else /* LWIP_ALLOW_MEM_FREE_FROM_OTHER_CONTEXT */ + +/* Protect the heap only by using a semaphore */ +#define LWIP_MEM_FREE_DECL_PROTECT() +#define LWIP_MEM_FREE_PROTECT() sys_mutex_lock(&mem_mutex) +#define LWIP_MEM_FREE_UNPROTECT() sys_mutex_unlock(&mem_mutex) +/* mem_malloc is protected using semaphore AND LWIP_MEM_ALLOC_PROTECT */ +#define LWIP_MEM_ALLOC_DECL_PROTECT() +#define LWIP_MEM_ALLOC_PROTECT() +#define LWIP_MEM_ALLOC_UNPROTECT() + +#endif /* LWIP_ALLOW_MEM_FREE_FROM_OTHER_CONTEXT */ + + +/** + * "Plug holes" by combining adjacent empty struct mems. + * After this function is through, there should not exist + * one empty struct mem pointing to another empty struct mem. + * + * @param mem this points to a struct mem which just has been freed + * @internal this function is only called by mem_free() and mem_trim() + * + * This assumes access to the heap is protected by the calling function + * already. + */ +static void +plug_holes(struct mem *mem) +{ + struct mem *nmem; + struct mem *pmem; + + LWIP_ASSERT("plug_holes: mem >= ram", (u8_t *)mem >= ram); + LWIP_ASSERT("plug_holes: mem < ram_end", (u8_t *)mem < (u8_t *)ram_end); + LWIP_ASSERT("plug_holes: mem->used == 0", mem->used == 0); + + /* plug hole forward */ + LWIP_ASSERT("plug_holes: mem->next <= MEM_SIZE_ALIGNED", mem->next <= MEM_SIZE_ALIGNED); + + nmem = (struct mem *)(void *)&ram[mem->next]; + if (mem != nmem && nmem->used == 0 && (u8_t *)nmem != (u8_t *)ram_end) { + /* if mem->next is unused and not end of ram, combine mem and mem->next */ + if (lfree == nmem) { + lfree = mem; + } + mem->next = nmem->next; + ((struct mem *)(void *)&ram[nmem->next])->prev = (mem_size_t)((u8_t *)mem - ram); + } + + /* plug hole backward */ + pmem = (struct mem *)(void *)&ram[mem->prev]; + if (pmem != mem && pmem->used == 0) { + /* if mem->prev is unused, combine mem and mem->prev */ + if (lfree == mem) { + lfree = pmem; + } + pmem->next = mem->next; + ((struct mem *)(void *)&ram[mem->next])->prev = (mem_size_t)((u8_t *)pmem - ram); + } +} + +/** + * Zero the heap and initialize start, end and lowest-free + */ +void +mem_init(void) +{ + struct mem *mem; + + LWIP_ASSERT("Sanity check alignment", + (SIZEOF_STRUCT_MEM & (MEM_ALIGNMENT-1)) == 0); + + /* align the heap */ + ram = (u8_t *)LWIP_MEM_ALIGN(LWIP_RAM_HEAP_POINTER); + /* initialize the start of the heap */ + mem = (struct mem *)(void *)ram; + mem->next = MEM_SIZE_ALIGNED; + mem->prev = 0; + mem->used = 0; + /* initialize the end of the heap */ + ram_end = (struct mem *)(void *)&ram[MEM_SIZE_ALIGNED]; + ram_end->used = 1; + ram_end->next = MEM_SIZE_ALIGNED; + ram_end->prev = MEM_SIZE_ALIGNED; + + /* initialize the lowest-free pointer to the start of the heap */ + lfree = (struct mem *)(void *)ram; + + MEM_STATS_AVAIL(avail, MEM_SIZE_ALIGNED); + + if (sys_mutex_new(&mem_mutex) != ERR_OK) { + LWIP_ASSERT("failed to create mem_mutex", 0); + } +} + +/** + * Put a struct mem back on the heap + * + * @param rmem is the data portion of a struct mem as returned by a previous + * call to mem_malloc() + */ +void +mem_free(void *rmem) +{ + struct mem *mem; + LWIP_MEM_FREE_DECL_PROTECT(); + + if (rmem == NULL) { + LWIP_DEBUGF(MEM_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_SERIOUS, ("mem_free(p == NULL) was called.\n")); + return; + } + LWIP_ASSERT("mem_free: sanity check alignment", (((mem_ptr_t)rmem) & (MEM_ALIGNMENT-1)) == 0); + + LWIP_ASSERT("mem_free: legal memory", (u8_t *)rmem >= (u8_t *)ram && + (u8_t *)rmem < (u8_t *)ram_end); + + if ((u8_t *)rmem < (u8_t *)ram || (u8_t *)rmem >= (u8_t *)ram_end) { + SYS_ARCH_DECL_PROTECT(lev); + LWIP_DEBUGF(MEM_DEBUG | LWIP_DBG_LEVEL_SEVERE, ("mem_free: illegal memory\n")); + /* protect mem stats from concurrent access */ + SYS_ARCH_PROTECT(lev); + MEM_STATS_INC(illegal); + SYS_ARCH_UNPROTECT(lev); + return; + } + /* protect the heap from concurrent access */ + LWIP_MEM_FREE_PROTECT(); + /* Get the corresponding struct mem ... */ + mem = (struct mem *)(void *)((u8_t *)rmem - SIZEOF_STRUCT_MEM); + /* ... which has to be in a used state ... */ + LWIP_ASSERT("mem_free: mem->used", mem->used); + /* ... and is now unused. */ + mem->used = 0; + + if (mem < lfree) { + /* the newly freed struct is now the lowest */ + lfree = mem; + } + + MEM_STATS_DEC_USED(used, mem->next - (mem_size_t)(((u8_t *)mem - ram))); + + /* finally, see if prev or next are free also */ + plug_holes(mem); +#if LWIP_ALLOW_MEM_FREE_FROM_OTHER_CONTEXT + mem_free_count = 1; +#endif /* LWIP_ALLOW_MEM_FREE_FROM_OTHER_CONTEXT */ + LWIP_MEM_FREE_UNPROTECT(); +} + +/** + * Shrink memory returned by mem_malloc(). + * + * @param rmem pointer to memory allocated by mem_malloc the is to be shrinked + * @param newsize required size after shrinking (needs to be smaller than or + * equal to the previous size) + * @return for compatibility reasons: is always == rmem, at the moment + * or NULL if newsize is > old size, in which case rmem is NOT touched + * or freed! + */ +void * +mem_trim(void *rmem, mem_size_t newsize) +{ + mem_size_t size; + mem_size_t ptr, ptr2; + struct mem *mem, *mem2; + /* use the FREE_PROTECT here: it protects with sem OR SYS_ARCH_PROTECT */ + LWIP_MEM_FREE_DECL_PROTECT(); + + /* Expand the size of the allocated memory region so that we can + adjust for alignment. */ + newsize = LWIP_MEM_ALIGN_SIZE(newsize); + + if (newsize < MIN_SIZE_ALIGNED) { + /* every data block must be at least MIN_SIZE_ALIGNED long */ + newsize = MIN_SIZE_ALIGNED; + } + + if (newsize > MEM_SIZE_ALIGNED) { + return NULL; + } + + LWIP_ASSERT("mem_trim: legal memory", (u8_t *)rmem >= (u8_t *)ram && + (u8_t *)rmem < (u8_t *)ram_end); + + if ((u8_t *)rmem < (u8_t *)ram || (u8_t *)rmem >= (u8_t *)ram_end) { + SYS_ARCH_DECL_PROTECT(lev); + LWIP_DEBUGF(MEM_DEBUG | LWIP_DBG_LEVEL_SEVERE, ("mem_trim: illegal memory\n")); + /* protect mem stats from concurrent access */ + SYS_ARCH_PROTECT(lev); + MEM_STATS_INC(illegal); + SYS_ARCH_UNPROTECT(lev); + return rmem; + } + /* Get the corresponding struct mem ... */ + mem = (struct mem *)(void *)((u8_t *)rmem - SIZEOF_STRUCT_MEM); + /* ... and its offset pointer */ + ptr = (mem_size_t)((u8_t *)mem - ram); + + size = mem->next - ptr - SIZEOF_STRUCT_MEM; + LWIP_ASSERT("mem_trim can only shrink memory", newsize <= size); + if (newsize > size) { + /* not supported */ + return NULL; + } + if (newsize == size) { + /* No change in size, simply return */ + return rmem; + } + + /* protect the heap from concurrent access */ + LWIP_MEM_FREE_PROTECT(); + + mem2 = (struct mem *)(void *)&ram[mem->next]; + if (mem2->used == 0) { + /* The next struct is unused, we can simply move it at little */ + mem_size_t next; + /* remember the old next pointer */ + next = mem2->next; + /* create new struct mem which is moved directly after the shrinked mem */ + ptr2 = ptr + SIZEOF_STRUCT_MEM + newsize; + if (lfree == mem2) { + lfree = (struct mem *)(void *)&ram[ptr2]; + } + mem2 = (struct mem *)(void *)&ram[ptr2]; + mem2->used = 0; + /* restore the next pointer */ + mem2->next = next; + /* link it back to mem */ + mem2->prev = ptr; + /* link mem to it */ + mem->next = ptr2; + /* last thing to restore linked list: as we have moved mem2, + * let 'mem2->next->prev' point to mem2 again. but only if mem2->next is not + * the end of the heap */ + if (mem2->next != MEM_SIZE_ALIGNED) { + ((struct mem *)(void *)&ram[mem2->next])->prev = ptr2; + } + MEM_STATS_DEC_USED(used, (size - newsize)); + /* no need to plug holes, we've already done that */ + } else if (newsize + SIZEOF_STRUCT_MEM + MIN_SIZE_ALIGNED <= size) { + /* Next struct is used but there's room for another struct mem with + * at least MIN_SIZE_ALIGNED of data. + * Old size ('size') must be big enough to contain at least 'newsize' plus a struct mem + * ('SIZEOF_STRUCT_MEM') with some data ('MIN_SIZE_ALIGNED'). + * @todo we could leave out MIN_SIZE_ALIGNED. We would create an empty + * region that couldn't hold data, but when mem->next gets freed, + * the 2 regions would be combined, resulting in more free memory */ + ptr2 = ptr + SIZEOF_STRUCT_MEM + newsize; + mem2 = (struct mem *)(void *)&ram[ptr2]; + if (mem2 < lfree) { + lfree = mem2; + } + mem2->used = 0; + mem2->next = mem->next; + mem2->prev = ptr; + mem->next = ptr2; + if (mem2->next != MEM_SIZE_ALIGNED) { + ((struct mem *)(void *)&ram[mem2->next])->prev = ptr2; + } + MEM_STATS_DEC_USED(used, (size - newsize)); + /* the original mem->next is used, so no need to plug holes! */ + } + /* else { + next struct mem is used but size between mem and mem2 is not big enough + to create another struct mem + -> don't do anyhting. + -> the remaining space stays unused since it is too small + } */ +#if LWIP_ALLOW_MEM_FREE_FROM_OTHER_CONTEXT + mem_free_count = 1; +#endif /* LWIP_ALLOW_MEM_FREE_FROM_OTHER_CONTEXT */ + LWIP_MEM_FREE_UNPROTECT(); + return rmem; +} + +/** + * Adam's mem_malloc() plus solution for bug #17922 + * Allocate a block of memory with a minimum of 'size' bytes. + * + * @param size is the minimum size of the requested block in bytes. + * @return pointer to allocated memory or NULL if no free memory was found. + * + * Note that the returned value will always be aligned (as defined by MEM_ALIGNMENT). + */ +void * +mem_malloc(mem_size_t size) +{ + mem_size_t ptr, ptr2; + struct mem *mem, *mem2; +#if LWIP_ALLOW_MEM_FREE_FROM_OTHER_CONTEXT + u8_t local_mem_free_count = 0; +#endif /* LWIP_ALLOW_MEM_FREE_FROM_OTHER_CONTEXT */ + LWIP_MEM_ALLOC_DECL_PROTECT(); + + if (size == 0) { + return NULL; + } + + /* Expand the size of the allocated memory region so that we can + adjust for alignment. */ + size = LWIP_MEM_ALIGN_SIZE(size); + + if (size < MIN_SIZE_ALIGNED) { + /* every data block must be at least MIN_SIZE_ALIGNED long */ + size = MIN_SIZE_ALIGNED; + } + + if (size > MEM_SIZE_ALIGNED) { + return NULL; + } + + /* protect the heap from concurrent access */ + sys_mutex_lock(&mem_mutex); + LWIP_MEM_ALLOC_PROTECT(); +#if LWIP_ALLOW_MEM_FREE_FROM_OTHER_CONTEXT + /* run as long as a mem_free disturbed mem_malloc or mem_trim */ + do { + local_mem_free_count = 0; +#endif /* LWIP_ALLOW_MEM_FREE_FROM_OTHER_CONTEXT */ + + /* Scan through the heap searching for a free block that is big enough, + * beginning with the lowest free block. + */ + for (ptr = (mem_size_t)((u8_t *)lfree - ram); ptr < MEM_SIZE_ALIGNED - size; + ptr = ((struct mem *)(void *)&ram[ptr])->next) { + mem = (struct mem *)(void *)&ram[ptr]; +#if LWIP_ALLOW_MEM_FREE_FROM_OTHER_CONTEXT + mem_free_count = 0; + LWIP_MEM_ALLOC_UNPROTECT(); + /* allow mem_free or mem_trim to run */ + LWIP_MEM_ALLOC_PROTECT(); + if (mem_free_count != 0) { + /* If mem_free or mem_trim have run, we have to restart since they + could have altered our current struct mem. */ + local_mem_free_count = 1; + break; + } +#endif /* LWIP_ALLOW_MEM_FREE_FROM_OTHER_CONTEXT */ + + if ((!mem->used) && + (mem->next - (ptr + SIZEOF_STRUCT_MEM)) >= size) { + /* mem is not used and at least perfect fit is possible: + * mem->next - (ptr + SIZEOF_STRUCT_MEM) gives us the 'user data size' of mem */ + + if (mem->next - (ptr + SIZEOF_STRUCT_MEM) >= (size + SIZEOF_STRUCT_MEM + MIN_SIZE_ALIGNED)) { + /* (in addition to the above, we test if another struct mem (SIZEOF_STRUCT_MEM) containing + * at least MIN_SIZE_ALIGNED of data also fits in the 'user data space' of 'mem') + * -> split large block, create empty remainder, + * remainder must be large enough to contain MIN_SIZE_ALIGNED data: if + * mem->next - (ptr + (2*SIZEOF_STRUCT_MEM)) == size, + * struct mem would fit in but no data between mem2 and mem2->next + * @todo we could leave out MIN_SIZE_ALIGNED. We would create an empty + * region that couldn't hold data, but when mem->next gets freed, + * the 2 regions would be combined, resulting in more free memory + */ + ptr2 = ptr + SIZEOF_STRUCT_MEM + size; + /* create mem2 struct */ + mem2 = (struct mem *)(void *)&ram[ptr2]; + mem2->used = 0; + mem2->next = mem->next; + mem2->prev = ptr; + /* and insert it between mem and mem->next */ + mem->next = ptr2; + mem->used = 1; + + if (mem2->next != MEM_SIZE_ALIGNED) { + ((struct mem *)(void *)&ram[mem2->next])->prev = ptr2; + } + MEM_STATS_INC_USED(used, (size + SIZEOF_STRUCT_MEM)); + } else { + /* (a mem2 struct does no fit into the user data space of mem and mem->next will always + * be used at this point: if not we have 2 unused structs in a row, plug_holes should have + * take care of this). + * -> near fit or exact fit: do not split, no mem2 creation + * also can't move mem->next directly behind mem, since mem->next + * will always be used at this point! + */ + mem->used = 1; + MEM_STATS_INC_USED(used, mem->next - (mem_size_t)((u8_t *)mem - ram)); + } +#if LWIP_ALLOW_MEM_FREE_FROM_OTHER_CONTEXT +mem_malloc_adjust_lfree: +#endif /* LWIP_ALLOW_MEM_FREE_FROM_OTHER_CONTEXT */ + if (mem == lfree) { + struct mem *cur = lfree; + /* Find next free block after mem and update lowest free pointer */ + while (cur->used && cur != ram_end) { +#if LWIP_ALLOW_MEM_FREE_FROM_OTHER_CONTEXT + mem_free_count = 0; + LWIP_MEM_ALLOC_UNPROTECT(); + /* prevent high interrupt latency... */ + LWIP_MEM_ALLOC_PROTECT(); + if (mem_free_count != 0) { + /* If mem_free or mem_trim have run, we have to restart since they + could have altered our current struct mem or lfree. */ + goto mem_malloc_adjust_lfree; + } +#endif /* LWIP_ALLOW_MEM_FREE_FROM_OTHER_CONTEXT */ + cur = (struct mem *)(void *)&ram[cur->next]; + } + lfree = cur; + LWIP_ASSERT("mem_malloc: !lfree->used", ((lfree == ram_end) || (!lfree->used))); + } + LWIP_MEM_ALLOC_UNPROTECT(); + sys_mutex_unlock(&mem_mutex); + LWIP_ASSERT("mem_malloc: allocated memory not above ram_end.", + (mem_ptr_t)mem + SIZEOF_STRUCT_MEM + size <= (mem_ptr_t)ram_end); + LWIP_ASSERT("mem_malloc: allocated memory properly aligned.", + ((mem_ptr_t)mem + SIZEOF_STRUCT_MEM) % MEM_ALIGNMENT == 0); + LWIP_ASSERT("mem_malloc: sanity check alignment", + (((mem_ptr_t)mem) & (MEM_ALIGNMENT-1)) == 0); + + return (u8_t *)mem + SIZEOF_STRUCT_MEM; + } + } +#if LWIP_ALLOW_MEM_FREE_FROM_OTHER_CONTEXT + /* if we got interrupted by a mem_free, try again */ + } while (local_mem_free_count != 0); +#endif /* LWIP_ALLOW_MEM_FREE_FROM_OTHER_CONTEXT */ + LWIP_DEBUGF(MEM_DEBUG | LWIP_DBG_LEVEL_SERIOUS, ("mem_malloc: could not allocate %"S16_F" bytes\n", (s16_t)size)); + MEM_STATS_INC(err); + LWIP_MEM_ALLOC_UNPROTECT(); + sys_mutex_unlock(&mem_mutex); + return NULL; +} + +#endif /* MEM_USE_POOLS */ +/** + * Contiguously allocates enough space for count objects that are size bytes + * of memory each and returns a pointer to the allocated memory. + * + * The allocated memory is filled with bytes of value zero. + * + * @param count number of objects to allocate + * @param size size of the objects to allocate + * @return pointer to allocated memory / NULL pointer if there is an error + */ +void *mem_calloc(mem_size_t count, mem_size_t size) +{ + void *p; + + /* allocate 'count' objects of size 'size' */ + p = mem_malloc(count * size); + if (p) { + /* zero the memory */ + memset(p, 0, (size_t)count * (size_t)size); + } + return p; +} + +#endif /* !MEM_LIBC_MALLOC */ diff --git a/components/lwip/core/memp.c b/components/lwip/core/memp.c new file mode 100755 index 0000000000..a5169abc81 --- /dev/null +++ b/components/lwip/core/memp.c @@ -0,0 +1,436 @@ +/** + * @file + * Dynamic pool memory manager + * + * lwIP has dedicated pools for many structures (netconn, protocol control blocks, + * packet buffers, ...). All these pools are managed here. + */ + +/* + * Copyright (c) 2001-2004 Swedish Institute of Computer Science. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + * + */ + +#include "lwip/opt.h" + +#include "lwip/memp.h" +#include "lwip/pbuf.h" +#include "lwip/udp.h" +#include "lwip/raw.h" +#include "lwip/igmp.h" +#include "lwip/api.h" +#include "lwip/priv/api_msg.h" +#include "lwip/sockets.h" +#include "lwip/sys.h" +#include "lwip/timers.h" +#include "lwip/stats.h" +#include "netif/etharp.h" +#include "lwip/ip_frag.h" +#include "lwip/dns.h" +#include "lwip/netdb.h" +#include "netif/ppp/ppp.h" +#include "netif/ppp/pppos.h" +#include "netif/ppp/pppoe.h" +#include "netif/ppp/pppol2tp.h" +#include "lwip/nd6.h" +#include "lwip/ip6_frag.h" +#include "lwip/mld6.h" +#include "lwip/tcp.h" +#include "lwip/tcpip.h" +#include "lwip/priv/tcp_priv.h" +#include "lwip/priv/tcpip_priv.h" +#include "lwip/netifapi.h" + +#include + +#ifdef MEMLEAK_DEBUG +static const char mem_debug_file[] ICACHE_RODATA_ATTR STORE_ATTR = __FILE__; +#endif + +#define LWIP_MEMPOOL(name,num,size,desc) LWIP_MEMPOOL_DECLARE(name,num,size,desc) +#include "lwip/priv/memp_std.h" + +const struct memp_desc* const memp_pools[MEMP_MAX] = { +#define LWIP_MEMPOOL(name,num,size,desc) &memp_ ## name, +#include "lwip/priv/memp_std.h" +}; + +#if !MEMP_MEM_MALLOC /* don't build if not configured for use in lwipopts.h */ + +#if MEMP_SANITY_CHECK +/** + * Check that memp-lists don't form a circle, using "Floyd's cycle-finding algorithm". + */ +static int +memp_sanity(const struct memp_desc *desc) +{ + struct memp *t, *h; + + t = *desc->tab; + if (t != NULL) { + for (h = t->next; (t != NULL) && (h != NULL); t = t->next, + h = ((h->next != NULL) ? h->next->next : NULL)) { + if (t == h) { + return 0; + } + } + } + + return 1; +} +#endif /* MEMP_SANITY_CHECK*/ + +#if MEMP_OVERFLOW_CHECK + +/** + * Check if a memp element was victim of an overflow + * (e.g. the restricted area after it has been altered) + * + * @param p the memp element to check + * @param memp_type the pool p comes from + */ +static void +memp_overflow_check_element_overflow(struct memp *p, const struct memp_desc *desc) +{ + u16_t k; + u8_t *m; +#if MEMP_SANITY_REGION_AFTER_ALIGNED > 0 + m = (u8_t*)p + MEMP_SIZE + desc->size; + for (k = 0; k < MEMP_SANITY_REGION_AFTER_ALIGNED; k++) { + if (m[k] != 0xcd) { + char errstr[128] = "detected memp overflow in pool "; + strcat(errstr, desc->desc); + LWIP_ASSERT(errstr, 0); + } + } +#endif +} + +/** + * Check if a memp element was victim of an underflow + * (e.g. the restricted area before it has been altered) + * + * @param p the memp element to check + * @param memp_type the pool p comes from + */ +static void +memp_overflow_check_element_underflow(struct memp *p, const struct memp_desc *desc) +{ + u16_t k; + u8_t *m; +#if MEMP_SANITY_REGION_BEFORE_ALIGNED > 0 + m = (u8_t*)p + MEMP_SIZE - MEMP_SANITY_REGION_BEFORE_ALIGNED; + for (k = 0; k < MEMP_SANITY_REGION_BEFORE_ALIGNED; k++) { + if (m[k] != 0xcd) { + char errstr[128] = "detected memp underflow in pool "; + strcat(errstr, desc->desc); + LWIP_ASSERT(errstr, 0); + } + } +#endif +} + +/** + * Do an overflow check for all elements in every pool. + * + * @see memp_overflow_check_element for a description of the check + */ +static void +memp_overflow_check_all(void) +{ + u16_t i, j; + struct memp *p; + + for (i = 0; i < MEMP_MAX; ++i) { + p = (struct memp *)(size_t)(memp_pools[i]->base); + for (j = 0; j < memp_pools[i]->num; ++j) { + memp_overflow_check_element_overflow(p, memp_pools[i]); + memp_overflow_check_element_underflow(p, memp_pools[i]); + p = (struct memp*)(size_t)((u8_t*)p + MEMP_SIZE + memp_pools[i]->size + MEMP_SANITY_REGION_AFTER_ALIGNED); + } + } +} + +/** + * Initialize the restricted areas of all memp elements in every pool. + */ +static void +memp_overflow_init(const struct memp_desc *desc) +{ + u16_t i; + struct memp *p; + u8_t *m; + + p = (struct memp *)(size_t)(desc->base); + for (i = 0; i < desc->num; ++i) { +#if MEMP_SANITY_REGION_BEFORE_ALIGNED > 0 + m = (u8_t*)p + MEMP_SIZE - MEMP_SANITY_REGION_BEFORE_ALIGNED; + memset(m, 0xcd, MEMP_SANITY_REGION_BEFORE_ALIGNED); +#endif +#if MEMP_SANITY_REGION_AFTER_ALIGNED > 0 + m = (u8_t*)p + MEMP_SIZE + desc->size; + memset(m, 0xcd, MEMP_SANITY_REGION_AFTER_ALIGNED); +#endif + p = (struct memp*)(size_t)((u8_t*)p + MEMP_SIZE + desc->size + MEMP_SANITY_REGION_AFTER_ALIGNED); + } +} +#endif /* MEMP_OVERFLOW_CHECK */ + + +void +memp_init_pool(const struct memp_desc *desc) +{ + int i; + struct memp *memp; + + *desc->tab = NULL; + memp = (struct memp*)LWIP_MEM_ALIGN(desc->base); + /* create a linked list of memp elements */ + for (i = 0; i < desc->num; ++i) { + memp->next = *desc->tab; + *desc->tab = memp; + memp = (struct memp *)(void *)((u8_t *)memp + MEMP_SIZE + desc->size +#if MEMP_OVERFLOW_CHECK + + MEMP_SANITY_REGION_AFTER_ALIGNED +#endif + ); + } + +#if MEMP_OVERFLOW_CHECK + memp_overflow_init(desc); +#endif /* MEMP_OVERFLOW_CHECK */ +} + +/** + * Initialize this module. + * + * Carves out memp_memory into linked lists for each pool-type. + */ +void +memp_init(void) +{ + u16_t i; + + for (i = 0; i < MEMP_MAX; ++i) { + MEMP_STATS_AVAIL(used, i, 0); + MEMP_STATS_AVAIL(max, i, 0); + MEMP_STATS_AVAIL(err, i, 0); + MEMP_STATS_AVAIL(avail, i, memp_pools[i]->num); + } + + /* for every pool: */ + for (i = 0; i < MEMP_MAX; ++i) { + memp_init_pool(memp_pools[i]); + } + +#if MEMP_OVERFLOW_CHECK + /* check everything a first time to see if it worked */ + memp_overflow_check_all(); +#endif /* MEMP_OVERFLOW_CHECK */ +} + +void * +#if !MEMP_OVERFLOW_CHECK +memp_malloc_pool(const struct memp_desc *desc) +#else +memp_malloc_pool_fn(const struct memp_desc *desc, const char* file, const int line) +#endif +{ + struct memp *memp; + SYS_ARCH_DECL_PROTECT(old_level); + + SYS_ARCH_PROTECT(old_level); + + memp = *desc->tab; + +#if MEMP_OVERFLOW_CHECK == 1 + memp_overflow_check_element_overflow(memp, desc); + memp_overflow_check_element_underflow(memp, desc); +#endif /* MEMP_OVERFLOW_CHECK */ + + if (memp != NULL) { + *desc->tab = memp->next; +#if MEMP_OVERFLOW_CHECK + memp->next = NULL; + memp->file = file; + memp->line = line; +#endif /* MEMP_OVERFLOW_CHECK */ + LWIP_ASSERT("memp_malloc: memp properly aligned", + ((mem_ptr_t)memp % MEM_ALIGNMENT) == 0); + memp = (struct memp*)(void *)((u8_t*)memp + MEMP_SIZE); + } + + SYS_ARCH_UNPROTECT(old_level); + + return memp; +} + +/** + * Get an element from a specific pool. + * + * @param type the pool to get an element from + * + * the debug version has two more parameters: + * @param file file name calling this function + * @param line number of line where this function is called + * + * @return a pointer to the allocated memory or a NULL pointer on error + */ +void * +#if !MEMP_OVERFLOW_CHECK +memp_malloc(memp_t type) +#else +memp_malloc_fn(memp_t type, const char* file, const int line) +#endif +{ + void *memp; + SYS_ARCH_DECL_PROTECT(old_level); + + LWIP_ERROR("memp_malloc: type < MEMP_MAX", (type < MEMP_MAX), return NULL;); + + SYS_ARCH_PROTECT(old_level); + +#if MEMP_OVERFLOW_CHECK >= 2 + memp_overflow_check_all(); +#endif /* MEMP_OVERFLOW_CHECK >= 2 */ + +#if !MEMP_OVERFLOW_CHECK + memp = memp_malloc_pool(memp_pools[type]); +#else + memp = memp_malloc_pool_fn(memp_pools[type], file, line); +#endif + + if (memp != NULL) { + MEMP_STATS_INC(used, type); + if(MEMP_STATS_GET(used, type) > MEMP_STATS_GET(max, type)) { + MEMP_STATS_AVAIL(max, type, MEMP_STATS_GET(used, type)); + } + } else { + LWIP_DEBUGF(MEMP_DEBUG | LWIP_DBG_LEVEL_SERIOUS, ("memp_malloc: out of memory in pool %s\n", memp_pools[type]->desc)); + MEMP_STATS_INC(err, type); + } + + SYS_ARCH_UNPROTECT(old_level); + + return memp; +} + +static void +#ifdef LWIP_HOOK_MEMP_AVAILABLE +do_memp_free_pool(const struct memp_desc* desc, void *mem, struct memp **old_first) +#else +do_memp_free_pool(const struct memp_desc* desc, void *mem) +#endif +{ + struct memp *memp; + SYS_ARCH_DECL_PROTECT(old_level); + + LWIP_ASSERT("memp_free: mem properly aligned", + ((mem_ptr_t)mem % MEM_ALIGNMENT) == 0); + + memp = (struct memp *)(void *)((u8_t*)mem - MEMP_SIZE); + + SYS_ARCH_PROTECT(old_level); + +#if MEMP_OVERFLOW_CHECK == 1 + memp_overflow_check_element_overflow(memp, desc); + memp_overflow_check_element_underflow(memp, desc); +#endif /* MEMP_OVERFLOW_CHECK */ + + memp->next = *desc->tab; + +#ifdef LWIP_HOOK_MEMP_AVAILABLE + if (old_first) + *old_first = *desc->tab; +#endif + + *desc->tab = memp; + +#if MEMP_SANITY_CHECK + LWIP_ASSERT("memp sanity", memp_sanity(desc)); +#endif /* MEMP_SANITY_CHECK */ + + SYS_ARCH_UNPROTECT(old_level); +} + +void +memp_free_pool(const struct memp_desc* desc, void *mem) +{ + if ((desc == NULL) || (mem == NULL)) { + return; + } + +#ifdef LWIP_HOOK_MEMP_AVAILABLE + do_memp_free_pool(desc, mem, NULL); +#else + do_memp_free_pool(desc, mem); +#endif +} + +/** + * Put an element back into its pool. + * + * @param type the pool where to put mem + * @param mem the memp element to free + */ +void +memp_free(memp_t type, void *mem) +{ +#ifdef LWIP_HOOK_MEMP_AVAILABLE + struct memp *old_first; +#endif + SYS_ARCH_DECL_PROTECT(old_level); + + LWIP_ERROR("memp_free: type < MEMP_MAX", (type < MEMP_MAX), return;); + + SYS_ARCH_PROTECT(old_level); + +#if MEMP_OVERFLOW_CHECK >= 2 + memp_overflow_check_all(); +#endif /* MEMP_OVERFLOW_CHECK >= 2 */ + + MEMP_STATS_DEC(used, type); + +#ifdef LWIP_HOOK_MEMP_AVAILABLE + do_memp_free_pool(memp_pools[type], mem, &old_first); +#else + do_memp_free_pool(memp_pools[type], mem); +#endif + + SYS_ARCH_UNPROTECT(old_level); + +#ifdef LWIP_HOOK_MEMP_AVAILABLE + if (old_first == NULL) { + LWIP_HOOK_MEMP_AVAILABLE(type); + } +#endif +} + +#endif /* MEMP_MEM_MALLOC */ diff --git a/components/lwip/core/netif.c b/components/lwip/core/netif.c new file mode 100755 index 0000000000..42309f1a31 --- /dev/null +++ b/components/lwip/core/netif.c @@ -0,0 +1,1090 @@ +/** + * @file + * lwIP network interface abstraction + * + */ + +/* + * Copyright (c) 2001-2004 Swedish Institute of Computer Science. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + * + */ + +#include "lwip/opt.h" + +#include "lwip/def.h" +#include "lwip/ip_addr.h" +#include "lwip/ip6_addr.h" +#include "lwip/netif.h" +#include "lwip/priv/tcp_priv.h" +#include "lwip/udp.h" +#include "lwip/snmp.h" +#include "lwip/igmp.h" +#include "netif/etharp.h" +#include "lwip/stats.h" +#include "lwip/sys.h" +#if ENABLE_LOOPBACK +#include "lwip/sys.h" +#if LWIP_NETIF_LOOPBACK_MULTITHREADING +#include "lwip/tcpip.h" +#endif /* LWIP_NETIF_LOOPBACK_MULTITHREADING */ +#endif /* ENABLE_LOOPBACK */ + +#if LWIP_AUTOIP +#include "lwip/autoip.h" +#endif /* LWIP_AUTOIP */ +#if LWIP_DHCP +#include "lwip/dhcp.h" +#endif /* LWIP_DHCP */ +#if LWIP_IPV6_DHCP6 +#include "lwip/dhcp6.h" +#endif /* LWIP_IPV6_DHCP6 */ +#if LWIP_IPV6_MLD +#include "lwip/mld6.h" +#endif /* LWIP_IPV6_MLD */ + +#if LWIP_NETIF_STATUS_CALLBACK +#define NETIF_STATUS_CALLBACK(n) do{ if (n->status_callback) { (n->status_callback)(n); }}while(0) +#else +#define NETIF_STATUS_CALLBACK(n) +#endif /* LWIP_NETIF_STATUS_CALLBACK */ + +#if LWIP_NETIF_LINK_CALLBACK +#define NETIF_LINK_CALLBACK(n) do{ if (n->link_callback) { (n->link_callback)(n); }}while(0) +#else +#define NETIF_LINK_CALLBACK(n) +#endif /* LWIP_NETIF_LINK_CALLBACK */ + +#ifdef MEMLEAK_DEBUG +static const char mem_debug_file[] ICACHE_RODATA_ATTR STORE_ATTR = __FILE__; +#endif + +struct netif *netif_list; +struct netif *netif_default; + +static u8_t netif_num; + +#define NETIF_REPORT_TYPE_IPV4 0x01 +#define NETIF_REPORT_TYPE_IPV6 0x02 +static void netif_issue_reports(struct netif* netif, u8_t report_type); + +#if LWIP_IPV6 +static err_t netif_null_output_ip6(struct netif *netif, struct pbuf *p, const ip6_addr_t *ipaddr); +#endif /* LWIP_IPV6 */ + +#if LWIP_HAVE_LOOPIF +#if LWIP_IPV4 +static err_t netif_loop_output_ipv4(struct netif *netif, struct pbuf *p, const ip4_addr_t* addr); +#endif +#if LWIP_IPV6 +static err_t netif_loop_output_ipv6(struct netif *netif, struct pbuf *p, const ip6_addr_t* addr); +#endif + + +static struct netif loop_netif; + +/** + * Initialize a lwip network interface structure for a loopback interface + * + * @param netif the lwip network interface structure for this loopif + * @return ERR_OK if the loopif is initialized + * ERR_MEM if private data couldn't be allocated + */ +static err_t +netif_loopif_init(struct netif *netif) +{ + /* initialize the snmp variables and counters inside the struct netif + * ifSpeed: no assumption can be made! + */ + MIB2_INIT_NETIF(netif, snmp_ifType_softwareLoopback, 0); + + netif->name[0] = 'l'; + netif->name[1] = 'o'; +#if LWIP_IPV4 + netif->output = netif_loop_output_ipv4; +#endif +#if LWIP_IPV6 + netif->output_ip6 = netif_loop_output_ipv6; +#endif +#if LWIP_LOOPIF_MULTICAST + netif->flags |= NETIF_FLAG_IGMP; +#endif + return ERR_OK; +} +#endif /* LWIP_HAVE_LOOPIF */ + +void +netif_init(void) +{ +#if LWIP_HAVE_LOOPIF +#if LWIP_IPV4 +#define LOOPIF_ADDRINIT &loop_ipaddr, &loop_netmask, &loop_gw, + ip4_addr_t loop_ipaddr, loop_netmask, loop_gw; + IP4_ADDR(&loop_gw, 127,0,0,1); + IP4_ADDR(&loop_ipaddr, 127,0,0,1); + IP4_ADDR(&loop_netmask, 255,0,0,0); +#else /* LWIP_IPV4 */ +#define LOOPIF_ADDRINIT +#endif /* LWIP_IPV4 */ + +#if NO_SYS + netif_add(&loop_netif, LOOPIF_ADDRINIT NULL, netif_loopif_init, ip_input); +#else /* NO_SYS */ + netif_add(&loop_netif, LOOPIF_ADDRINIT NULL, netif_loopif_init, tcpip_input); +#endif /* NO_SYS */ + +#if LWIP_IPV6 + IP_ADDR6(loop_netif.ip6_addr, 0, 0, 0, PP_HTONL(0x00000001UL)); + loop_netif.ip6_addr_state[0] = IP6_ADDR_VALID; +#endif /* LWIP_IPV6 */ + + netif_set_link_up(&loop_netif); + netif_set_up(&loop_netif); + +#endif /* LWIP_HAVE_LOOPIF */ +} + +/** + * Add a network interface to the list of lwIP netifs. + * + * @param netif a pre-allocated netif structure + * @param ipaddr IP address for the new netif + * @param netmask network mask for the new netif + * @param gw default gateway IP address for the new netif + * @param state opaque data passed to the new netif + * @param init callback function that initializes the interface + * @param input callback function that is called to pass + * ingress packets up in the protocol layer stack. + * + * @return netif, or NULL if failed. + */ +struct netif * +netif_add(struct netif *netif, +#if LWIP_IPV4 + const ip4_addr_t *ipaddr, const ip4_addr_t *netmask, const ip4_addr_t *gw, +#endif /* LWIP_IPV4 */ + void *state, netif_init_fn init, netif_input_fn input) +{ +#if LWIP_IPV6 + u32_t i; +#endif + + LWIP_ASSERT("No init function given", init != NULL); + + /* reset new interface configuration state */ +#if LWIP_IPV4 + ip_addr_set_zero_ip4(&netif->ip_addr); + ip_addr_set_zero_ip4(&netif->netmask); + ip_addr_set_zero_ip4(&netif->gw); +#endif /* LWIP_IPV4 */ + +#if LWIP_IPV6 + for (i = 0; i < LWIP_IPV6_NUM_ADDRESSES; i++) { + ip_addr_set_zero_ip6(&netif->ip6_addr[i]); + netif_ip6_addr_set_state(netif, i, IP6_ADDR_INVALID); + } + netif->output_ip6 = netif_null_output_ip6; +#endif /* LWIP_IPV6 */ + + + NETIF_SET_CHECKSUM_CTRL(netif, NETIF_CHECKSUM_ENABLE_ALL); + netif->flags = 0; + +#if LWIP_DHCP + /* netif not under DHCP control by default */ + netif->dhcp = NULL; + +#ifdef LWIP_ESP8266 + netif->dhcps_pcb = NULL; +#endif + +#endif /* LWIP_DHCP */ + + +#if LWIP_AUTOIP + /* netif not under AutoIP control by default */ + netif->autoip = NULL; +#endif /* LWIP_AUTOIP */ +#if LWIP_IPV6_AUTOCONFIG + +#ifdef LWIP_ESP8266 +//#if 0 + netif->ip6_autoconfig_enabled = 1; +#else + /* IPv6 address autoconfiguration not enabled by default */ + netif->ip6_autoconfig_enabled = 0; +#endif + +#endif /* LWIP_IPV6_AUTOCONFIG */ + + +#if LWIP_IPV6_SEND_ROUTER_SOLICIT + netif->rs_count = LWIP_ND6_MAX_MULTICAST_SOLICIT; +#endif /* LWIP_IPV6_SEND_ROUTER_SOLICIT */ +#if LWIP_IPV6_DHCP6 + /* netif not under DHCPv6 control by default */ + netif->dhcp6 = NULL; +#endif /* LWIP_IPV6_DHCP6 */ +#if LWIP_NETIF_STATUS_CALLBACK + netif->status_callback = NULL; +#endif /* LWIP_NETIF_STATUS_CALLBACK */ +#if LWIP_NETIF_LINK_CALLBACK + netif->link_callback = NULL; +#endif /* LWIP_NETIF_LINK_CALLBACK */ +#if LWIP_IGMP + netif->igmp_mac_filter = NULL; +#endif /* LWIP_IGMP */ +#if LWIP_IPV6 && LWIP_IPV6_MLD + netif->mld_mac_filter = NULL; +#endif /* LWIP_IPV6 && LWIP_IPV6_MLD */ +#if ENABLE_LOOPBACK + netif->loop_first = NULL; + netif->loop_last = NULL; +#endif /* ENABLE_LOOPBACK */ + + + /* remember netif specific state information data */ + netif->state = state; + netif->num = netif_num++; + netif->input = input; + NETIF_SET_HWADDRHINT(netif, NULL); +#if ENABLE_LOOPBACK && LWIP_LOOPBACK_MAX_PBUFS + netif->loop_cnt_current = 0; +#endif /* ENABLE_LOOPBACK && LWIP_LOOPBACK_MAX_PBUFS */ + +#if LWIP_IPV4 + netif_set_addr(netif, ipaddr, netmask, gw); +#endif /* LWIP_IPV4 */ + + + /* call user specified initialization function for netif */ + if (init(netif) != ERR_OK) { + return NULL; + } + + /* add this netif to the list */ + netif->next = netif_list; + netif_list = netif; + mib2_netif_added(netif); + +#if LWIP_IGMP + /* start IGMP processing */ + if (netif->flags & NETIF_FLAG_IGMP) { + igmp_start(netif); + } +#endif /* LWIP_IGMP */ + + LWIP_DEBUGF(NETIF_DEBUG, ("netif: added interface %c%c IP", + netif->name[0], netif->name[1])); +#if LWIP_IPV4 + LWIP_DEBUGF(NETIF_DEBUG, (" addr ")); + ip4_addr_debug_print(NETIF_DEBUG, ipaddr); + LWIP_DEBUGF(NETIF_DEBUG, (" netmask ")); + ip4_addr_debug_print(NETIF_DEBUG, netmask); + LWIP_DEBUGF(NETIF_DEBUG, (" gw ")); + ip4_addr_debug_print(NETIF_DEBUG, gw); +#endif /* LWIP_IPV4 */ + LWIP_DEBUGF(NETIF_DEBUG, ("\n")); + + return netif; +} + +typedef int (*netif_addr_change_cb_t)(struct netif *netif); +static netif_addr_change_cb_t g_netif_addr_change_cb = NULL; + +void netif_reg_addr_change_cb(void *cb) +{ + g_netif_addr_change_cb = (netif_addr_change_cb_t)cb; +} + +#if LWIP_IPV4 +/** + * Change IP address configuration for a network interface (including netmask + * and default gateway). + * + * @param netif the network interface to change + * @param ipaddr the new IP address + * @param netmask the new netmask + * @param gw the new default gateway + */ +void +netif_set_addr(struct netif *netif, const ip4_addr_t *ipaddr, const ip4_addr_t *netmask, + const ip4_addr_t *gw) +{ + netif_set_netmask(netif, netmask); + netif_set_gw(netif, gw); + /* set ipaddr last to ensure netmask/gw have been set when status callback is called */ + netif_set_ipaddr(netif, ipaddr); + if (g_netif_addr_change_cb){ + g_netif_addr_change_cb(netif); + } +} + +#endif /* LWIP_IPV4*/ + +/** + * Remove a network interface from the list of lwIP netifs. + * + * @param netif the network interface to remove + */ +void +netif_remove(struct netif *netif) +{ + if (netif == NULL) { + return; + } + +#if LWIP_IPV4 + if (!ip4_addr_isany_val(*netif_ip4_addr(netif))) { +#if LWIP_TCP + tcp_netif_ipv4_addr_changed(netif_ip4_addr(netif), NULL); +#endif /* LWIP_TCP */ + /* cannot do this for UDP, as there is no 'err' callback in udp pcbs */ + } + +#if LWIP_IGMP + /* stop IGMP processing */ + if (netif->flags & NETIF_FLAG_IGMP) { + igmp_stop(netif); + } +#endif /* LWIP_IGMP */ +#endif /* LWIP_IPV4*/ + +#if LWIP_IPV6 && LWIP_IPV6_MLD + /* stop MLD processing */ + mld6_stop(netif); +#endif /* LWIP_IPV6 && LWIP_IPV6_MLD */ + if (netif_is_up(netif)) { + /* set netif down before removing (call callback function) */ + netif_set_down(netif); + } + + mib2_remove_ip4(netif); + + /* this netif is default? */ + if (netif_default == netif) { + /* reset default netif */ + netif_set_default(NULL); + } + /* is it the first netif? */ + if (netif_list == netif) { + netif_list = netif->next; + } else { + /* look for netif further down the list */ + struct netif * tmp_netif; + for (tmp_netif = netif_list; tmp_netif != NULL; tmp_netif = tmp_netif->next) { + if (tmp_netif->next == netif) { + tmp_netif->next = netif->next; + break; + } + } + if (tmp_netif == NULL) { + return; /* netif is not on the list */ + } + } + mib2_netif_removed(netif); +#if LWIP_NETIF_REMOVE_CALLBACK + if (netif->remove_callback) { + netif->remove_callback(netif); + } +#endif /* LWIP_NETIF_REMOVE_CALLBACK */ + LWIP_DEBUGF( NETIF_DEBUG, ("netif_remove: removed netif\n") ); +} + +/** + * Find a network interface by searching for its name + * + * @param name the name of the netif (like netif->name) plus concatenated number + * in ascii representation (e.g. 'en0') + */ +struct netif * +netif_find(const char *name) +{ + struct netif *netif; + u8_t num; + + if (name == NULL) { + return NULL; + } + + num = name[2] - '0'; + + for (netif = netif_list; netif != NULL; netif = netif->next) { + if (num == netif->num && + name[0] == netif->name[0] && + name[1] == netif->name[1]) { + LWIP_DEBUGF(NETIF_DEBUG, ("netif_find: found %c%c\n", name[0], name[1])); + return netif; + } + } + LWIP_DEBUGF(NETIF_DEBUG, ("netif_find: didn't find %c%c\n", name[0], name[1])); + return NULL; +} + +#if LWIP_IPV4 +/** + * Change the IP address of a network interface + * + * @param netif the network interface to change + * @param ipaddr the new IP address + * + * @note call netif_set_addr() if you also want to change netmask and + * default gateway + */ +void +netif_set_ipaddr(struct netif *netif, const ip4_addr_t *ipaddr) +{ + ip4_addr_t new_addr = (ipaddr ? *ipaddr : *IP4_ADDR_ANY); + /* address is actually being changed? */ + if (ip4_addr_cmp(&new_addr, netif_ip4_addr(netif)) == 0) { + LWIP_DEBUGF(NETIF_DEBUG | LWIP_DBG_STATE, ("netif_set_ipaddr: netif address being changed\n")); +#if LWIP_TCP + tcp_netif_ipv4_addr_changed(netif_ip4_addr(netif), ipaddr); +#endif /* LWIP_TCP */ +#if LWIP_UDP + udp_netif_ipv4_addr_changed(netif_ip4_addr(netif), ipaddr); +#endif /* LWIP_UDP */ + + mib2_remove_ip4(netif); + mib2_remove_route_ip4(0, netif); + /* set new IP address to netif */ + ip4_addr_set(ip_2_ip4(&netif->ip_addr), ipaddr); + IP_SET_TYPE_VAL(netif->ip_addr, IPADDR_TYPE_V4); + mib2_add_ip4(netif); + mib2_add_route_ip4(0, netif); + + netif_issue_reports(netif, NETIF_REPORT_TYPE_IPV4); + + NETIF_STATUS_CALLBACK(netif); + } + + LWIP_DEBUGF(NETIF_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("netif: IP address of interface %c%c set to %"U16_F".%"U16_F".%"U16_F".%"U16_F"\n", + netif->name[0], netif->name[1], + ip4_addr1_16(netif_ip4_addr(netif)), + ip4_addr2_16(netif_ip4_addr(netif)), + ip4_addr3_16(netif_ip4_addr(netif)), + ip4_addr4_16(netif_ip4_addr(netif)))); +} + +/** + * Change the default gateway for a network interface + * + * @param netif the network interface to change + * @param gw the new default gateway + * + * @note call netif_set_addr() if you also want to change ip address and netmask + */ +void +netif_set_gw(struct netif *netif, const ip4_addr_t *gw) +{ + ip4_addr_set(ip_2_ip4(&netif->gw), gw); + IP_SET_TYPE_VAL(netif->gw, IPADDR_TYPE_V4); + LWIP_DEBUGF(NETIF_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("netif: GW address of interface %c%c set to %"U16_F".%"U16_F".%"U16_F".%"U16_F"\n", + netif->name[0], netif->name[1], + ip4_addr1_16(netif_ip4_gw(netif)), + ip4_addr2_16(netif_ip4_gw(netif)), + ip4_addr3_16(netif_ip4_gw(netif)), + ip4_addr4_16(netif_ip4_gw(netif)))); +} + +/** + * Change the netmask of a network interface + * + * @param netif the network interface to change + * @param netmask the new netmask + * + * @note call netif_set_addr() if you also want to change ip address and + * default gateway + */ +void +netif_set_netmask(struct netif *netif, const ip4_addr_t *netmask) +{ + mib2_remove_route_ip4(0, netif); + /* set new netmask to netif */ + ip4_addr_set(ip_2_ip4(&netif->netmask), netmask); + IP_SET_TYPE_VAL(netif->netmask, IPADDR_TYPE_V4); + mib2_add_route_ip4(0, netif); + LWIP_DEBUGF(NETIF_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("netif: netmask of interface %c%c set to %"U16_F".%"U16_F".%"U16_F".%"U16_F"\n", + netif->name[0], netif->name[1], + ip4_addr1_16(netif_ip4_netmask(netif)), + ip4_addr2_16(netif_ip4_netmask(netif)), + ip4_addr3_16(netif_ip4_netmask(netif)), + ip4_addr4_16(netif_ip4_netmask(netif)))); +} +#endif /* LWIP_IPV4 */ + +/** + * Set a network interface as the default network interface + * (used to output all packets for which no specific route is found) + * + * @param netif the default network interface + */ +void +netif_set_default(struct netif *netif) +{ + if (netif == NULL) { + /* remove default route */ + mib2_remove_route_ip4(1, netif); + } else { + /* install default route */ + mib2_add_route_ip4(1, netif); + } + netif_default = netif; + LWIP_DEBUGF(NETIF_DEBUG, ("netif: setting default interface %c%c\n", + netif ? netif->name[0] : '\'', netif ? netif->name[1] : '\'')); +} + +/** + * Bring an interface up, available for processing + * traffic. + */ +void +netif_set_up(struct netif *netif) +{ + if (!(netif->flags & NETIF_FLAG_UP)) { + netif->flags |= NETIF_FLAG_UP; + + MIB2_COPY_SYSUPTIME_TO(&netif->ts); + + NETIF_STATUS_CALLBACK(netif); + + if (netif->flags & NETIF_FLAG_LINK_UP) { + netif_issue_reports(netif, NETIF_REPORT_TYPE_IPV4|NETIF_REPORT_TYPE_IPV6); + } + } +} + +/** Send ARP/IGMP/MLD/RS events, e.g. on link-up/netif-up or addr-change + */ +static void +netif_issue_reports(struct netif* netif, u8_t report_type) +{ +#if LWIP_IPV4 + if ((report_type & NETIF_REPORT_TYPE_IPV4) && + !ip4_addr_isany_val(*netif_ip4_addr(netif))) { +#if LWIP_ARP + /* For Ethernet network interfaces, we would like to send a "gratuitous ARP" */ + if (netif->flags & (NETIF_FLAG_ETHARP)) { + etharp_gratuitous(netif); + } +#endif /* LWIP_ARP */ + +#if LWIP_IGMP + /* resend IGMP memberships */ + if (netif->flags & NETIF_FLAG_IGMP) { + igmp_report_groups(netif); + } +#endif /* LWIP_IGMP */ + } +#endif /* LWIP_IPV4 */ + +#if LWIP_IPV6 + if (report_type & NETIF_REPORT_TYPE_IPV6) { +#if LWIP_IPV6_MLD + /* send mld memberships */ + mld6_report_groups(netif); +#endif /* LWIP_IPV6_MLD */ +#if LWIP_IPV6_SEND_ROUTER_SOLICIT + /* Send Router Solicitation messages. */ + netif->rs_count = LWIP_ND6_MAX_MULTICAST_SOLICIT; +#endif /* LWIP_IPV6_SEND_ROUTER_SOLICIT */ + } +#endif /* LWIP_IPV6 */ +} + +/** + * Bring an interface down, disabling any traffic processing. + */ +void +netif_set_down(struct netif *netif) +{ + if (netif->flags & NETIF_FLAG_UP) { + netif->flags &= ~NETIF_FLAG_UP; + MIB2_COPY_SYSUPTIME_TO(&netif->ts); + +#if LWIP_IPV4 && LWIP_ARP + if (netif->flags & NETIF_FLAG_ETHARP) { + etharp_cleanup_netif(netif); + } +#endif /* LWIP_IPV4 && LWIP_ARP */ + NETIF_STATUS_CALLBACK(netif); + } +} + +#if LWIP_NETIF_STATUS_CALLBACK +/** + * Set callback to be called when interface is brought up/down or address is changed while up + */ +void +netif_set_status_callback(struct netif *netif, netif_status_callback_fn status_callback) +{ + if (netif) { + netif->status_callback = status_callback; + } +} +#endif /* LWIP_NETIF_STATUS_CALLBACK */ + +#if LWIP_NETIF_REMOVE_CALLBACK +/** + * Set callback to be called when the interface has been removed + */ +void +netif_set_remove_callback(struct netif *netif, netif_status_callback_fn remove_callback) +{ + if (netif) { + netif->remove_callback = remove_callback; + } +} +#endif /* LWIP_NETIF_REMOVE_CALLBACK */ + +/** + * Called by a driver when its link goes up + */ +void +netif_set_link_up(struct netif *netif) +{ + if (!(netif->flags & NETIF_FLAG_LINK_UP)) { + netif->flags |= NETIF_FLAG_LINK_UP; + +#if LWIP_DHCP + if (netif->dhcp) { + dhcp_network_changed(netif); + } +#endif /* LWIP_DHCP */ + +#if LWIP_AUTOIP + if (netif->autoip) { + autoip_network_changed(netif); + } +#endif /* LWIP_AUTOIP */ + + if (netif->flags & NETIF_FLAG_UP) { + netif_issue_reports(netif, NETIF_REPORT_TYPE_IPV4|NETIF_REPORT_TYPE_IPV6); + } + NETIF_LINK_CALLBACK(netif); + } +} + +/** + * Called by a driver when its link goes down + */ +void +netif_set_link_down(struct netif *netif ) +{ + if (netif->flags & NETIF_FLAG_LINK_UP) { + netif->flags &= ~NETIF_FLAG_LINK_UP; + NETIF_LINK_CALLBACK(netif); + } +} + +#if LWIP_NETIF_LINK_CALLBACK +/** + * Set callback to be called when link is brought up/down + */ +void +netif_set_link_callback(struct netif *netif, netif_status_callback_fn link_callback) +{ + if (netif) { + netif->link_callback = link_callback; + } +} +#endif /* LWIP_NETIF_LINK_CALLBACK */ + +#if ENABLE_LOOPBACK +/** + * Send an IP packet to be received on the same netif (loopif-like). + * The pbuf is simply copied and handed back to netif->input. + * In multithreaded mode, this is done directly since netif->input must put + * the packet on a queue. + * In callback mode, the packet is put on an internal queue and is fed to + * netif->input by netif_poll(). + * + * @param netif the lwip network interface structure + * @param p the (IP) packet to 'send' + * @return ERR_OK if the packet has been sent + * ERR_MEM if the pbuf used to copy the packet couldn't be allocated + */ +err_t +netif_loop_output(struct netif *netif, struct pbuf *p) +{ + struct pbuf *r; + err_t err; + struct pbuf *last; +#if LWIP_LOOPBACK_MAX_PBUFS + u8_t clen = 0; +#endif /* LWIP_LOOPBACK_MAX_PBUFS */ + /* If we have a loopif, SNMP counters are adjusted for it, + * if not they are adjusted for 'netif'. */ +#if MIB2_STATS +#if LWIP_HAVE_LOOPIF + struct netif *stats_if = &loop_netif; +#else /* LWIP_HAVE_LOOPIF */ + struct netif *stats_if = netif; +#endif /* LWIP_HAVE_LOOPIF */ +#endif /* MIB2_STATS */ + SYS_ARCH_DECL_PROTECT(lev); + + /* Allocate a new pbuf */ + r = pbuf_alloc(PBUF_LINK, p->tot_len, PBUF_RAM); + if (r == NULL) { + LINK_STATS_INC(link.memerr); + LINK_STATS_INC(link.drop); + MIB2_STATS_NETIF_INC(stats_if, ifoutdiscards); + return ERR_MEM; + } +#if LWIP_LOOPBACK_MAX_PBUFS + clen = pbuf_clen(r); + /* check for overflow or too many pbuf on queue */ + if (((netif->loop_cnt_current + clen) < netif->loop_cnt_current) || + ((netif->loop_cnt_current + clen) > LWIP_LOOPBACK_MAX_PBUFS)) { + pbuf_free(r); + LINK_STATS_INC(link.memerr); + LINK_STATS_INC(link.drop); + MIB2_STATS_NETIF_INC(stats_if, ifoutdiscards); + return ERR_MEM; + } + netif->loop_cnt_current += clen; +#endif /* LWIP_LOOPBACK_MAX_PBUFS */ + + /* Copy the whole pbuf queue p into the single pbuf r */ + if ((err = pbuf_copy(r, p)) != ERR_OK) { + pbuf_free(r); + LINK_STATS_INC(link.memerr); + LINK_STATS_INC(link.drop); + MIB2_STATS_NETIF_INC(stats_if, ifoutdiscards); + return err; + } + + /* Put the packet on a linked list which gets emptied through calling + netif_poll(). */ + + /* let last point to the last pbuf in chain r */ + for (last = r; last->next != NULL; last = last->next); + + SYS_ARCH_PROTECT(lev); + if (netif->loop_first != NULL) { + LWIP_ASSERT("if first != NULL, last must also be != NULL", netif->loop_last != NULL); + netif->loop_last->next = r; + netif->loop_last = last; + } else { + netif->loop_first = r; + netif->loop_last = last; + } + SYS_ARCH_UNPROTECT(lev); + + LINK_STATS_INC(link.xmit); + MIB2_STATS_NETIF_ADD(stats_if, ifoutoctets, p->tot_len); + MIB2_STATS_NETIF_INC(stats_if, ifoutucastpkts); + +#if LWIP_NETIF_LOOPBACK_MULTITHREADING + /* For multithreading environment, schedule a call to netif_poll */ + tcpip_callback_with_block((tcpip_callback_fn)netif_poll, netif, 0); +#endif /* LWIP_NETIF_LOOPBACK_MULTITHREADING */ + + return ERR_OK; +} + +#if LWIP_HAVE_LOOPIF +#if LWIP_IPV4 +static err_t +netif_loop_output_ipv4(struct netif *netif, struct pbuf *p, const ip4_addr_t* addr) +{ + LWIP_UNUSED_ARG(addr); + return netif_loop_output(netif, p); +} +#endif /* LWIP_IPV4 */ + +#if LWIP_IPV6 +static err_t +netif_loop_output_ipv6(struct netif *netif, struct pbuf *p, const ip6_addr_t* addr) +{ + LWIP_UNUSED_ARG(addr); + return netif_loop_output(netif, p); +} +#endif /* LWIP_IPV6 */ +#endif /* LWIP_HAVE_LOOPIF */ + + +/** + * Call netif_poll() in the main loop of your application. This is to prevent + * reentering non-reentrant functions like tcp_input(). Packets passed to + * netif_loop_output() are put on a list that is passed to netif->input() by + * netif_poll(). + */ +void +netif_poll(struct netif *netif) +{ + struct pbuf *in; + /* If we have a loopif, SNMP counters are adjusted for it, + * if not they are adjusted for 'netif'. */ +#if MIB2_STATS +#if LWIP_HAVE_LOOPIF + struct netif *stats_if = &loop_netif; +#else /* LWIP_HAVE_LOOPIF */ + struct netif *stats_if = netif; +#endif /* LWIP_HAVE_LOOPIF */ +#endif /* MIB2_STATS */ + SYS_ARCH_DECL_PROTECT(lev); + + do { + /* Get a packet from the list. With SYS_LIGHTWEIGHT_PROT=1, this is protected */ + SYS_ARCH_PROTECT(lev); + in = netif->loop_first; + if (in != NULL) { + struct pbuf *in_end = in; +#if LWIP_LOOPBACK_MAX_PBUFS + u8_t clen = 1; +#endif /* LWIP_LOOPBACK_MAX_PBUFS */ + while (in_end->len != in_end->tot_len) { + LWIP_ASSERT("bogus pbuf: len != tot_len but next == NULL!", in_end->next != NULL); + in_end = in_end->next; +#if LWIP_LOOPBACK_MAX_PBUFS + clen++; +#endif /* LWIP_LOOPBACK_MAX_PBUFS */ + } +#if LWIP_LOOPBACK_MAX_PBUFS + /* adjust the number of pbufs on queue */ + LWIP_ASSERT("netif->loop_cnt_current underflow", + ((netif->loop_cnt_current - clen) < netif->loop_cnt_current)); + netif->loop_cnt_current -= clen; +#endif /* LWIP_LOOPBACK_MAX_PBUFS */ + + /* 'in_end' now points to the last pbuf from 'in' */ + if (in_end == netif->loop_last) { + /* this was the last pbuf in the list */ + netif->loop_first = netif->loop_last = NULL; + } else { + /* pop the pbuf off the list */ + netif->loop_first = in_end->next; + LWIP_ASSERT("should not be null since first != last!", netif->loop_first != NULL); + } + /* De-queue the pbuf from its successors on the 'loop_' list. */ + in_end->next = NULL; + } + SYS_ARCH_UNPROTECT(lev); + + if (in != NULL) { + LINK_STATS_INC(link.recv); + MIB2_STATS_NETIF_ADD(stats_if, ifinoctets, in->tot_len); + MIB2_STATS_NETIF_INC(stats_if, ifinucastpkts); + /* loopback packets are always IP packets! */ + if (ip_input(in, netif) != ERR_OK) { + pbuf_free(in); + } + /* Don't reference the packet any more! */ + in = NULL; + } + /* go on while there is a packet on the list */ + } while (netif->loop_first != NULL); +} + +#if !LWIP_NETIF_LOOPBACK_MULTITHREADING +/** + * Calls netif_poll() for every netif on the netif_list. + */ +void +netif_poll_all(void) +{ + struct netif *netif = netif_list; + /* loop through netifs */ + while (netif != NULL) { + netif_poll(netif); + /* proceed to next network interface */ + netif = netif->next; + } +} +#endif /* !LWIP_NETIF_LOOPBACK_MULTITHREADING */ +#endif /* ENABLE_LOOPBACK */ + +#if LWIP_IPV6 +/** Checks if a specific address is assigned to the netif and returns its + * index. + * + * @param netif the netif to check + * @param ip6addr the IPv6 address to find + * @return >= 0: address found, this is its index + * -1: address not found on this netif + */ +s8_t +netif_get_ip6_addr_match(struct netif *netif, const ip6_addr_t *ip6addr) +{ + s8_t i; + for (i = 0; i < LWIP_IPV6_NUM_ADDRESSES; i++) { + if (!ip6_addr_isinvalid(netif_ip6_addr_state(netif, i)) && + ip6_addr_cmp(netif_ip6_addr(netif, i), ip6addr)) { + return i; + } + } + return -1; +} + +/** Create a link-local IPv6 address on a netif (stored in slot 0) + * + * @param netif the netif to create the address on + * @param from_mac_48bit if != 0, assume hwadr is a 48-bit MAC address (std conversion) + * if == 0, use hwaddr directly as interface ID + */ +void +netif_create_ip6_linklocal_address(struct netif *netif, u8_t from_mac_48bit) +{ + u8_t i, addr_index; + + /* Link-local prefix. */ + ip_2_ip6(&netif->ip6_addr[0])->addr[0] = PP_HTONL(0xfe800000ul); + ip_2_ip6(&netif->ip6_addr[0])->addr[1] = 0; + + /* Generate interface ID. */ + if (from_mac_48bit) { + /* Assume hwaddr is a 48-bit IEEE 802 MAC. Convert to EUI-64 address. Complement Group bit. */ + ip_2_ip6(&netif->ip6_addr[0])->addr[2] = htonl((((u32_t)(netif->hwaddr[0] ^ 0x02)) << 24) | + ((u32_t)(netif->hwaddr[1]) << 16) | + ((u32_t)(netif->hwaddr[2]) << 8) | + (0xff)); + ip_2_ip6(&netif->ip6_addr[0])->addr[3] = htonl((0xfeul << 24) | + ((u32_t)(netif->hwaddr[3]) << 16) | + ((u32_t)(netif->hwaddr[4]) << 8) | + (netif->hwaddr[5])); + } else { + /* Use hwaddr directly as interface ID. */ + ip_2_ip6(&netif->ip6_addr[0])->addr[2] = 0; + ip_2_ip6(&netif->ip6_addr[0])->addr[3] = 0; + + addr_index = 3; + for (i = 0; (i < 8) && (i < netif->hwaddr_len); i++) { + if (i == 4) { + addr_index--; + } + ip_2_ip6(&netif->ip6_addr[0])->addr[addr_index] |= ((u32_t)(netif->hwaddr[netif->hwaddr_len - i - 1])) << (8 * (i & 0x03)); + } + } + +#ifdef LWIP_ESP8266 + ip6_addr_set( ip_2_ip6(&netif->link_local_addr), ip_2_ip6(&netif->ip6_addr[0]) ); +#endif + + /* Set address state. */ +#if LWIP_IPV6_DUP_DETECT_ATTEMPTS + /* Will perform duplicate address detection (DAD). */ + netif->ip6_addr_state[0] = IP6_ADDR_TENTATIVE; +#else + /* Consider address valid. */ + netif->ip6_addr_state[0] = IP6_ADDR_PREFERRED; +#endif /* LWIP_IPV6_AUTOCONFIG */ +} + +/** This function allows for the easy addition of a new IPv6 address to an interface. + * It takes care of finding an empty slot and then sets the address tentative + * (to make sure that all the subsequent processing happens). + * + * @param netif netif to add the address on + * @param ip6addr address to add + * @param chosen_idx if != NULL, the chosen IPv6 address index will be stored here + */ +err_t +netif_add_ip6_address(struct netif *netif, const ip6_addr_t *ip6addr, s8_t *chosen_idx) +{ + s8_t i; + + i = netif_get_ip6_addr_match(netif, ip6addr); + if (i >= 0) { + /* Address already added */ + if (chosen_idx != NULL) { + *chosen_idx = i; + } + return ERR_OK; + } + + /* Find a free slot -- musn't be the first one (reserved for link local) */ + for (i = 1; i < LWIP_IPV6_NUM_ADDRESSES; i++) { + if (!ip6_addr_isvalid(netif->ip6_addr_state[i])) { + ip_addr_copy_from_ip6(netif->ip6_addr[i], *ip6addr); + netif_ip6_addr_set_state(netif, i, IP6_ADDR_TENTATIVE); + if (chosen_idx != NULL) { + *chosen_idx = i; + } + return ERR_OK; + } + } + + if (chosen_idx != NULL) { + *chosen_idx = -1; + } + return ERR_VAL; +} + + +#ifdef LWIP_ESP8266 +void +netif_create_ip4_linklocal_address(struct netif * netif) +{ +#if 1 + ip_addr_t linklocal; + ip_addr_t linklocal_mask; + ip4_addr_t addr = {0}; + /* Link-local prefix and mask. */ + IP4_ADDR(ip_2_ip4(&linklocal), 169, 254, 0, 0); + IP4_ADDR(ip_2_ip4(&linklocal_mask), 255, 255, 0, 0); + + if (!ip4_addr_netcmp( ip_2_ip4(&linklocal), ip_2_ip4(&netif->link_local_addr), ip_2_ip4(&linklocal_mask) ) && + !ip4_addr_isany(ip_2_ip4(&netif->ip_addr)) ) { + IP4_ADDR( ip_2_ip4(&netif->link_local_addr), 169, 254, ip4_addr3( ip_2_ip4(&netif->ip_addr) ) + , ip4_addr4( ip_2_ip4(&netif->ip_addr) ) ); + return; + } + + while ( !(addr.addr) || !ip4_addr4(&addr) ) + //os_get_random((unsigned char *)&addr, sizeof(addr)); + addr.addr = LWIP_RAND(); + + + if ( ip_2_ip4(&netif->netmask)->addr > IP_CLASSB_NET && + !ip4_addr_isany( ip_2_ip4(&netif->ip_addr) )) { // random host address + IP4_ADDR( ip_2_ip4(&netif->link_local_addr), 169, 254, ip4_addr3( ip_2_ip4(&netif->ip_addr)) + , ip4_addr4(&addr)); + } else { + IP4_ADDR( ip_2_ip4(&netif->link_local_addr), 169, 254, ip4_addr3(&addr), ip4_addr4(&addr) ); + } +#endif +} + +#endif + + +/** Dummy IPv6 output function for netifs not supporting IPv6 + */ +static err_t +netif_null_output_ip6(struct netif *netif, struct pbuf *p, const ip6_addr_t *ipaddr) +{ + LWIP_UNUSED_ARG(netif); + LWIP_UNUSED_ARG(p); + LWIP_UNUSED_ARG(ipaddr); + + return ERR_IF; +} +#endif /* LWIP_IPV6 */ diff --git a/components/lwip/core/pbuf.c b/components/lwip/core/pbuf.c new file mode 100755 index 0000000000..e35f8a6b7f --- /dev/null +++ b/components/lwip/core/pbuf.c @@ -0,0 +1,1396 @@ +/** + * @file + * Packet buffer management + * + * Packets are built from the pbuf data structure. It supports dynamic + * memory allocation for packet contents or can reference externally + * managed packet contents both in RAM and ROM. Quick allocation for + * incoming packets is provided through pools with fixed sized pbufs. + * + * A packet may span over multiple pbufs, chained as a singly linked + * list. This is called a "pbuf chain". + * + * Multiple packets may be queued, also using this singly linked list. + * This is called a "packet queue". + * + * So, a packet queue consists of one or more pbuf chains, each of + * which consist of one or more pbufs. CURRENTLY, PACKET QUEUES ARE + * NOT SUPPORTED!!! Use helper structs to queue multiple packets. + * + * The differences between a pbuf chain and a packet queue are very + * precise but subtle. + * + * The last pbuf of a packet has a ->tot_len field that equals the + * ->len field. It can be found by traversing the list. If the last + * pbuf of a packet has a ->next field other than NULL, more packets + * are on the queue. + * + * Therefore, looping through a pbuf of a single packet, has an + * loop end condition (tot_len == p->len), NOT (next == NULL). + */ + +/* + * Copyright (c) 2001-2004 Swedish Institute of Computer Science. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + * + */ + +#include "lwip/opt.h" + +#include "lwip/stats.h" +#include "lwip/def.h" +#include "lwip/mem.h" +#include "lwip/memp.h" +#include "lwip/pbuf.h" +#include "lwip/sys.h" +#if LWIP_TCP && TCP_QUEUE_OOSEQ +#include "lwip/priv/tcp_priv.h" +#endif +#if LWIP_CHECKSUM_ON_COPY +#include "lwip/inet_chksum.h" +#endif + +#include + +#ifdef MEMLEAK_DEBUG +static const char mem_debug_file[] ICACHE_RODATA_ATTR STORE_ATTR = __FILE__; +#endif + +#ifdef LWIP_ESP8266 +#define EP_OFFSET 0 +#endif + +#define SIZEOF_STRUCT_PBUF LWIP_MEM_ALIGN_SIZE(sizeof(struct pbuf)) +/* Since the pool is created in memp, PBUF_POOL_BUFSIZE will be automatically + aligned there. Therefore, PBUF_POOL_BUFSIZE_ALIGNED can be used here. */ +#define PBUF_POOL_BUFSIZE_ALIGNED LWIP_MEM_ALIGN_SIZE(PBUF_POOL_BUFSIZE) + +#if !LWIP_TCP || !TCP_QUEUE_OOSEQ || !PBUF_POOL_FREE_OOSEQ +#define PBUF_POOL_IS_EMPTY() +#else /* !LWIP_TCP || !TCP_QUEUE_OOSEQ || !PBUF_POOL_FREE_OOSEQ */ + +#if !NO_SYS +#ifndef PBUF_POOL_FREE_OOSEQ_QUEUE_CALL +#include "lwip/tcpip.h" +#define PBUF_POOL_FREE_OOSEQ_QUEUE_CALL() do { \ + if (tcpip_callback_with_block(pbuf_free_ooseq_callback, NULL, 0) != ERR_OK) { \ + SYS_ARCH_PROTECT(old_level); \ + pbuf_free_ooseq_pending = 0; \ + SYS_ARCH_UNPROTECT(old_level); \ + } } while(0) +#endif /* PBUF_POOL_FREE_OOSEQ_QUEUE_CALL */ +#endif /* !NO_SYS */ + +volatile u8_t pbuf_free_ooseq_pending; +#define PBUF_POOL_IS_EMPTY() pbuf_pool_is_empty() + +/** + * Attempt to reclaim some memory from queued out-of-sequence TCP segments + * if we run out of pool pbufs. It's better to give priority to new packets + * if we're running out. + * + * This must be done in the correct thread context therefore this function + * can only be used with NO_SYS=0 and through tcpip_callback. + */ +#if !NO_SYS +static +#endif /* !NO_SYS */ +void +pbuf_free_ooseq(void) +{ + struct tcp_pcb* pcb; + SYS_ARCH_SET(pbuf_free_ooseq_pending, 0); + + for (pcb = tcp_active_pcbs; NULL != pcb; pcb = pcb->next) { + if (NULL != pcb->ooseq) { + /** Free the ooseq pbufs of one PCB only */ + LWIP_DEBUGF(PBUF_DEBUG | LWIP_DBG_TRACE, ("pbuf_free_ooseq: freeing out-of-sequence pbufs\n")); + tcp_segs_free(pcb->ooseq); + pcb->ooseq = NULL; + return; + } + } +} + +#if !NO_SYS +/** + * Just a callback function for tcpip_callback() that calls pbuf_free_ooseq(). + */ +static void +pbuf_free_ooseq_callback(void *arg) +{ + LWIP_UNUSED_ARG(arg); + pbuf_free_ooseq(); +} +#endif /* !NO_SYS */ + +/** Queue a call to pbuf_free_ooseq if not already queued. */ +static void +pbuf_pool_is_empty(void) +{ +#ifndef PBUF_POOL_FREE_OOSEQ_QUEUE_CALL + SYS_ARCH_SET(pbuf_free_ooseq_pending, 1); +#else /* PBUF_POOL_FREE_OOSEQ_QUEUE_CALL */ + u8_t queued; + SYS_ARCH_DECL_PROTECT(old_level); + SYS_ARCH_PROTECT(old_level); + queued = pbuf_free_ooseq_pending; + pbuf_free_ooseq_pending = 1; + SYS_ARCH_UNPROTECT(old_level); + + if (!queued) { + /* queue a call to pbuf_free_ooseq if not already queued */ + PBUF_POOL_FREE_OOSEQ_QUEUE_CALL(); + } +#endif /* PBUF_POOL_FREE_OOSEQ_QUEUE_CALL */ +} +#endif /* !LWIP_TCP || !TCP_QUEUE_OOSEQ || !PBUF_POOL_FREE_OOSEQ */ + +/** + * Allocates a pbuf of the given type (possibly a chain for PBUF_POOL type). + * + * The actual memory allocated for the pbuf is determined by the + * layer at which the pbuf is allocated and the requested size + * (from the size parameter). + * + * @param layer flag to define header size + * @param length size of the pbuf's payload + * @param type this parameter decides how and where the pbuf + * should be allocated as follows: + * + * - PBUF_RAM: buffer memory for pbuf is allocated as one large + * chunk. This includes protocol headers as well. + * - PBUF_ROM: no buffer memory is allocated for the pbuf, even for + * protocol headers. Additional headers must be prepended + * by allocating another pbuf and chain in to the front of + * the ROM pbuf. It is assumed that the memory used is really + * similar to ROM in that it is immutable and will not be + * changed. Memory which is dynamic should generally not + * be attached to PBUF_ROM pbufs. Use PBUF_REF instead. + * - PBUF_REF: no buffer memory is allocated for the pbuf, even for + * protocol headers. It is assumed that the pbuf is only + * being used in a single thread. If the pbuf gets queued, + * then pbuf_take should be called to copy the buffer. + * - PBUF_POOL: the pbuf is allocated as a pbuf chain, with pbufs from + * the pbuf pool that is allocated during pbuf_init(). + * + * @return the allocated pbuf. If multiple pbufs where allocated, this + * is the first pbuf of a pbuf chain. + */ +struct pbuf * +pbuf_alloc(pbuf_layer layer, u16_t length, pbuf_type type) +{ + struct pbuf *p, *q, *r; + +#ifdef LWIP_ESP8266 + u16_t offset = 0; +#else + u16_t offset; +#endif + + s32_t rem_len; /* remaining length */ + LWIP_DEBUGF(PBUF_DEBUG | LWIP_DBG_TRACE, ("pbuf_alloc(length=%"U16_F")\n", length)); + + /* determine header offset */ + switch (layer) { + case PBUF_TRANSPORT: + /* add room for transport (often TCP) layer header */ + offset = PBUF_LINK_ENCAPSULATION_HLEN + PBUF_LINK_HLEN + PBUF_IP_HLEN + PBUF_TRANSPORT_HLEN; + +#ifdef LWIP_ESP8266 //TO_DO + offset += EP_OFFSET; +#endif + + break; + case PBUF_IP: + /* add room for IP layer header */ + offset = PBUF_LINK_ENCAPSULATION_HLEN + PBUF_LINK_HLEN + PBUF_IP_HLEN; + +#ifdef LWIP_ESP8266 //TO_DO + offset += EP_OFFSET; +#endif + + break; + case PBUF_LINK: + /* add room for link layer header */ + offset = PBUF_LINK_ENCAPSULATION_HLEN + PBUF_LINK_HLEN; + +#ifdef LWIP_ESP8266 //TO_DO + /* + * 1. LINK_HLEN 14Byte will be remove in WLAN layer + * 2. IEEE80211_HDR_MAX_LEN needs 40 bytes. + * 3. encryption needs exra 4 bytes ahead of actual data payload, and require + * DAddr and SAddr to be 4-byte aligned. + * 4. TRANSPORT and IP are all 20, 4 bytes aligned, nice... + * 5. LCC add 6 bytes more, We don't consider WAPI yet... + * 6. define LWIP_MEM_ALIGN to be 4 Byte aligned, pbuf struct is 16B, Only thing may be + * matter is ether_hdr is not 4B aligned. + * + * So, we need extra (40 + 4 - 14) = 30 and it's happen to be 4-Byte aligned + * + * 1. lwip + * | empty 30B | eth_hdr (14B) | payload ...| + * total: 44B ahead payload + * 2. net80211 + * | max 80211 hdr, 32B | ccmp/tkip iv (8B) | sec rsv(4B) | payload ...| + * total: 40B ahead sec_rsv and 44B ahead payload + * + */ + offset += EP_OFFSET; //remove LINK hdr in wlan +#endif + + break; + case PBUF_RAW_TX: + /* add room for encapsulating link layer headers (e.g. 802.11) */ + offset = PBUF_LINK_ENCAPSULATION_HLEN; + break; + case PBUF_RAW: + offset = 0; + +#ifdef LWIP_ESP8266 //TO_DO + offset += EP_OFFSET; +#endif + + break; + default: + LWIP_ASSERT("pbuf_alloc: bad pbuf layer", 0); + return NULL; + } + + switch (type) { + case PBUF_POOL: + /* allocate head of pbuf chain into p */ + p = (struct pbuf *)memp_malloc(MEMP_PBUF_POOL); + LWIP_DEBUGF(PBUF_DEBUG | LWIP_DBG_TRACE, ("pbuf_alloc: allocated pbuf %p\n", (void *)p)); + if (p == NULL) { + PBUF_POOL_IS_EMPTY(); + return NULL; + } + p->type = type; + p->next = NULL; + + /* make the payload pointer point 'offset' bytes into pbuf data memory */ + p->payload = LWIP_MEM_ALIGN((void *)((u8_t *)p + (SIZEOF_STRUCT_PBUF + offset))); + LWIP_ASSERT("pbuf_alloc: pbuf p->payload properly aligned", + ((mem_ptr_t)p->payload % MEM_ALIGNMENT) == 0); + /* the total length of the pbuf chain is the requested size */ + p->tot_len = length; + /* set the length of the first pbuf in the chain */ + p->len = LWIP_MIN(length, PBUF_POOL_BUFSIZE_ALIGNED - LWIP_MEM_ALIGN_SIZE(offset)); + LWIP_ASSERT("check p->payload + p->len does not overflow pbuf", + ((u8_t*)p->payload + p->len <= + (u8_t*)p + SIZEOF_STRUCT_PBUF + PBUF_POOL_BUFSIZE_ALIGNED)); + LWIP_ASSERT("PBUF_POOL_BUFSIZE must be bigger than MEM_ALIGNMENT", + (PBUF_POOL_BUFSIZE_ALIGNED - LWIP_MEM_ALIGN_SIZE(offset)) > 0 ); + /* set reference count (needed here in case we fail) */ + p->ref = 1; + + /* now allocate the tail of the pbuf chain */ + + /* remember first pbuf for linkage in next iteration */ + r = p; + /* remaining length to be allocated */ + rem_len = length - p->len; + /* any remaining pbufs to be allocated? */ + while (rem_len > 0) { + q = (struct pbuf *)memp_malloc(MEMP_PBUF_POOL); + if (q == NULL) { + PBUF_POOL_IS_EMPTY(); + /* free chain so far allocated */ + pbuf_free(p); + /* bail out unsuccessfully */ + return NULL; + } + q->type = type; + q->flags = 0; + q->next = NULL; + /* make previous pbuf point to this pbuf */ + r->next = q; + /* set total length of this pbuf and next in chain */ + LWIP_ASSERT("rem_len < max_u16_t", rem_len < 0xffff); + q->tot_len = (u16_t)rem_len; + /* this pbuf length is pool size, unless smaller sized tail */ + q->len = LWIP_MIN((u16_t)rem_len, PBUF_POOL_BUFSIZE_ALIGNED); + q->payload = (void *)((u8_t *)q + SIZEOF_STRUCT_PBUF); + LWIP_ASSERT("pbuf_alloc: pbuf q->payload properly aligned", + ((mem_ptr_t)q->payload % MEM_ALIGNMENT) == 0); + LWIP_ASSERT("check p->payload + p->len does not overflow pbuf", + ((u8_t*)p->payload + p->len <= + (u8_t*)p + SIZEOF_STRUCT_PBUF + PBUF_POOL_BUFSIZE_ALIGNED)); + q->ref = 1; + /* calculate remaining length to be allocated */ + rem_len -= q->len; + /* remember this pbuf for linkage in next iteration */ + r = q; + } + /* end of chain */ + /*r->next = NULL;*/ + + break; + case PBUF_RAM: + /* If pbuf is to be allocated in RAM, allocate memory for it. */ + p = (struct pbuf*)mem_malloc(LWIP_MEM_ALIGN_SIZE(SIZEOF_STRUCT_PBUF + offset) + LWIP_MEM_ALIGN_SIZE(length)); + if (p == NULL) { + return NULL; + } + /* Set up internal structure of the pbuf. */ + p->payload = LWIP_MEM_ALIGN((void *)((u8_t *)p + SIZEOF_STRUCT_PBUF + offset)); + p->len = p->tot_len = length; + p->next = NULL; + p->type = type; + + LWIP_ASSERT("pbuf_alloc: pbuf->payload properly aligned", + ((mem_ptr_t)p->payload % MEM_ALIGNMENT) == 0); + break; + /* pbuf references existing (non-volatile static constant) ROM payload? */ + case PBUF_ROM: + /* pbuf references existing (externally allocated) RAM payload? */ + case PBUF_REF: + /* only allocate memory for the pbuf structure */ + p = (struct pbuf *)memp_malloc(MEMP_PBUF); + if (p == NULL) { + LWIP_DEBUGF(PBUF_DEBUG | LWIP_DBG_LEVEL_SERIOUS, + ("pbuf_alloc: Could not allocate MEMP_PBUF for PBUF_%s.\n", + (type == PBUF_ROM) ? "ROM" : "REF")); + return NULL; + } + /* caller must set this field properly, afterwards */ + p->payload = NULL; + p->len = p->tot_len = length; + p->next = NULL; + p->type = type; + break; + default: + LWIP_ASSERT("pbuf_alloc: erroneous type", 0); + return NULL; + } + /* set reference count */ + p->ref = 1; + /* set flags */ + p->flags = 0; + +#ifdef LWIP_ESP8266 + p->eb = NULL; +#endif + LWIP_DEBUGF(PBUF_DEBUG | LWIP_DBG_TRACE, ("pbuf_alloc(length=%"U16_F") == %p\n", length, (void *)p)); + return p; +} + +#if LWIP_SUPPORT_CUSTOM_PBUF +/** Initialize a custom pbuf (already allocated). + * + * @param layer flag to define header size + * @param length size of the pbuf's payload + * @param type type of the pbuf (only used to treat the pbuf accordingly, as + * this function allocates no memory) + * @param p pointer to the custom pbuf to initialize (already allocated) + * @param payload_mem pointer to the buffer that is used for payload and headers, + * must be at least big enough to hold 'length' plus the header size, + * may be NULL if set later. + * ATTENTION: The caller is responsible for correct alignment of this buffer!! + * @param payload_mem_len the size of the 'payload_mem' buffer, must be at least + * big enough to hold 'length' plus the header size + */ +struct pbuf* +pbuf_alloced_custom(pbuf_layer l, u16_t length, pbuf_type type, struct pbuf_custom *p, + void *payload_mem, u16_t payload_mem_len) +{ + u16_t offset; + LWIP_DEBUGF(PBUF_DEBUG | LWIP_DBG_TRACE, ("pbuf_alloced_custom(length=%"U16_F")\n", length)); + + /* determine header offset */ + switch (l) { + case PBUF_TRANSPORT: + /* add room for transport (often TCP) layer header */ + offset = PBUF_LINK_ENCAPSULATION_HLEN + PBUF_LINK_HLEN + PBUF_IP_HLEN + PBUF_TRANSPORT_HLEN; + break; + case PBUF_IP: + /* add room for IP layer header */ + offset = PBUF_LINK_ENCAPSULATION_HLEN + PBUF_LINK_HLEN + PBUF_IP_HLEN; + break; + case PBUF_LINK: + /* add room for link layer header */ + offset = PBUF_LINK_ENCAPSULATION_HLEN + PBUF_LINK_HLEN; + break; + case PBUF_RAW_TX: + /* add room for encapsulating link layer headers (e.g. 802.11) */ + offset = PBUF_LINK_ENCAPSULATION_HLEN; + break; + case PBUF_RAW: + offset = 0; + break; + default: + LWIP_ASSERT("pbuf_alloced_custom: bad pbuf layer", 0); + return NULL; + } + + if (LWIP_MEM_ALIGN_SIZE(offset) + length > payload_mem_len) { + LWIP_DEBUGF(PBUF_DEBUG | LWIP_DBG_LEVEL_WARNING, ("pbuf_alloced_custom(length=%"U16_F") buffer too short\n", length)); + return NULL; + } + + p->pbuf.next = NULL; + if (payload_mem != NULL) { + p->pbuf.payload = (u8_t *)payload_mem + LWIP_MEM_ALIGN_SIZE(offset); + } else { + p->pbuf.payload = NULL; + } + p->pbuf.flags = PBUF_FLAG_IS_CUSTOM; + p->pbuf.len = p->pbuf.tot_len = length; + p->pbuf.type = type; + p->pbuf.ref = 1; + return &p->pbuf; +} +#endif /* LWIP_SUPPORT_CUSTOM_PBUF */ + +/** + * Shrink a pbuf chain to a desired length. + * + * @param p pbuf to shrink. + * @param new_len desired new length of pbuf chain + * + * Depending on the desired length, the first few pbufs in a chain might + * be skipped and left unchanged. The new last pbuf in the chain will be + * resized, and any remaining pbufs will be freed. + * + * @note If the pbuf is ROM/REF, only the ->tot_len and ->len fields are adjusted. + * @note May not be called on a packet queue. + * + * @note Despite its name, pbuf_realloc cannot grow the size of a pbuf (chain). + */ +void +pbuf_realloc(struct pbuf *p, u16_t new_len) +{ + struct pbuf *q; + u16_t rem_len; /* remaining length */ + s32_t grow; + + LWIP_ASSERT("pbuf_realloc: p != NULL", p != NULL); + LWIP_ASSERT("pbuf_realloc: sane p->type", p->type == PBUF_POOL || + p->type == PBUF_ROM || + p->type == PBUF_RAM || + p->type == PBUF_REF); + + /* desired length larger than current length? */ + if (new_len >= p->tot_len) { + /* enlarging not yet supported */ + return; + } + + /* the pbuf chain grows by (new_len - p->tot_len) bytes + * (which may be negative in case of shrinking) */ + grow = new_len - p->tot_len; + + /* first, step over any pbufs that should remain in the chain */ + rem_len = new_len; + q = p; + /* should this pbuf be kept? */ + while (rem_len > q->len) { + /* decrease remaining length by pbuf length */ + rem_len -= q->len; + /* decrease total length indicator */ + LWIP_ASSERT("grow < max_u16_t", grow < 0xffff); + q->tot_len += (u16_t)grow; + /* proceed to next pbuf in chain */ + q = q->next; + LWIP_ASSERT("pbuf_realloc: q != NULL", q != NULL); + } + /* we have now reached the new last pbuf (in q) */ + /* rem_len == desired length for pbuf q */ + + /* shrink allocated memory for PBUF_RAM */ + /* (other types merely adjust their length fields */ + if ((q->type == PBUF_RAM) && (rem_len != q->len) +#if LWIP_SUPPORT_CUSTOM_PBUF + && ((q->flags & PBUF_FLAG_IS_CUSTOM) == 0) +#endif /* LWIP_SUPPORT_CUSTOM_PBUF */ + ) { + /* reallocate and adjust the length of the pbuf that will be split */ + q = (struct pbuf *)mem_trim(q, (u16_t)((u8_t *)q->payload - (u8_t *)q) + rem_len); + LWIP_ASSERT("mem_trim returned q == NULL", q != NULL); + } + /* adjust length fields for new last pbuf */ + q->len = rem_len; + q->tot_len = q->len; + + /* any remaining pbufs in chain? */ + if (q->next != NULL) { + /* free remaining pbufs in chain */ + pbuf_free(q->next); + } + /* q is last packet in chain */ + q->next = NULL; + +} + +/** + * Adjusts the payload pointer to hide or reveal headers in the payload. + * @see pbuf_header. + * + * @param p pbuf to change the header size. + * @param header_size_increment Number of bytes to increment header size. + * @param force Allow 'header_size_increment > 0' for PBUF_REF/PBUF_ROM types + * + * @return non-zero on failure, zero on success. + * + */ +static u8_t +pbuf_header_impl(struct pbuf *p, s16_t header_size_increment, u8_t force) +{ + u16_t type; + void *payload; + u16_t increment_magnitude; + + LWIP_ASSERT("p != NULL", p != NULL); + if ((header_size_increment == 0) || (p == NULL)) { + return 0; + } + + if (header_size_increment < 0) { + increment_magnitude = -header_size_increment; + /* Check that we aren't going to move off the end of the pbuf */ + LWIP_ERROR("increment_magnitude <= p->len", (increment_magnitude <= p->len), return 1;); + } else { + increment_magnitude = header_size_increment; +#if 0 + /* Can't assert these as some callers speculatively call + pbuf_header() to see if it's OK. Will return 1 below instead. */ + /* Check that we've got the correct type of pbuf to work with */ + LWIP_ASSERT("p->type == PBUF_RAM || p->type == PBUF_POOL", + p->type == PBUF_RAM || p->type == PBUF_POOL); + /* Check that we aren't going to move off the beginning of the pbuf */ + LWIP_ASSERT("p->payload - increment_magnitude >= p + SIZEOF_STRUCT_PBUF", + (u8_t *)p->payload - increment_magnitude >= (u8_t *)p + SIZEOF_STRUCT_PBUF); +#endif + } + + type = p->type; + /* remember current payload pointer */ + payload = p->payload; + + /* pbuf types containing payloads? */ + if (type == PBUF_RAM || type == PBUF_POOL) { + /* set new payload pointer */ + p->payload = (u8_t *)p->payload - header_size_increment; + /* boundary check fails? */ + if ((u8_t *)p->payload < (u8_t *)p + SIZEOF_STRUCT_PBUF) { + LWIP_DEBUGF( PBUF_DEBUG | LWIP_DBG_LEVEL_SERIOUS, + ("pbuf_header: failed as %p < %p (not enough space for new header size)\n", + (void *)p->payload, (void *)(p + 1))); + /* restore old payload pointer */ + p->payload = payload; + /* bail out unsuccessfully */ + return 1; + } + /* pbuf types referring to external payloads? */ + } else if (type == PBUF_REF || type == PBUF_ROM) { + /* hide a header in the payload? */ + if ((header_size_increment < 0) && (increment_magnitude <= p->len)) { + /* increase payload pointer */ + p->payload = (u8_t *)p->payload - header_size_increment; + } else if ((header_size_increment > 0) && force) { + p->payload = (u8_t *)p->payload - header_size_increment; + } else { + /* cannot expand payload to front (yet!) + * bail out unsuccessfully */ + return 1; + } + } else { + /* Unknown type */ + LWIP_ASSERT("bad pbuf type", 0); + return 1; + } + /* modify pbuf length fields */ + p->len += header_size_increment; + p->tot_len += header_size_increment; + + LWIP_DEBUGF(PBUF_DEBUG | LWIP_DBG_TRACE, ("pbuf_header: old %p new %p (%"S16_F")\n", + (void *)payload, (void *)p->payload, header_size_increment)); + + return 0; +} + +/** + * Adjusts the payload pointer to hide or reveal headers in the payload. + * + * Adjusts the ->payload pointer so that space for a header + * (dis)appears in the pbuf payload. + * + * The ->payload, ->tot_len and ->len fields are adjusted. + * + * @param p pbuf to change the header size. + * @param header_size_increment Number of bytes to increment header size which + * increases the size of the pbuf. New space is on the front. + * (Using a negative value decreases the header size.) + * If hdr_size_inc is 0, this function does nothing and returns successful. + * + * PBUF_ROM and PBUF_REF type buffers cannot have their sizes increased, so + * the call will fail. A check is made that the increase in header size does + * not move the payload pointer in front of the start of the buffer. + * @return non-zero on failure, zero on success. + * + */ +u8_t +pbuf_header(struct pbuf *p, s16_t header_size_increment) +{ + return pbuf_header_impl(p, header_size_increment, 0); +} + +/** + * Same as pbuf_header but does not check if 'header_size > 0' is allowed. + * This is used internally only, to allow PBUF_REF for RX. + */ +u8_t +pbuf_header_force(struct pbuf *p, s16_t header_size_increment) +{ + return pbuf_header_impl(p, header_size_increment, 1); +} + +/** + * Dereference a pbuf chain or queue and deallocate any no-longer-used + * pbufs at the head of this chain or queue. + * + * Decrements the pbuf reference count. If it reaches zero, the pbuf is + * deallocated. + * + * For a pbuf chain, this is repeated for each pbuf in the chain, + * up to the first pbuf which has a non-zero reference count after + * decrementing. So, when all reference counts are one, the whole + * chain is free'd. + * + * @param p The pbuf (chain) to be dereferenced. + * + * @return the number of pbufs that were de-allocated + * from the head of the chain. + * + * @note MUST NOT be called on a packet queue (Not verified to work yet). + * @note the reference counter of a pbuf equals the number of pointers + * that refer to the pbuf (or into the pbuf). + * + * @internal examples: + * + * Assuming existing chains a->b->c with the following reference + * counts, calling pbuf_free(a) results in: + * + * 1->2->3 becomes ...1->3 + * 3->3->3 becomes 2->3->3 + * 1->1->2 becomes ......1 + * 2->1->1 becomes 1->1->1 + * 1->1->1 becomes ....... + * + */ +u8_t +pbuf_free(struct pbuf *p) +{ + u16_t type; + struct pbuf *q; + u8_t count; + + if (p == NULL) { + LWIP_ASSERT("p != NULL", p != NULL); + /* if assertions are disabled, proceed with debug output */ + LWIP_DEBUGF(PBUF_DEBUG | LWIP_DBG_LEVEL_SERIOUS, + ("pbuf_free(p == NULL) was called.\n")); + return 0; + } + LWIP_DEBUGF(PBUF_DEBUG | LWIP_DBG_TRACE, ("pbuf_free(%p)\n", (void *)p)); + + PERF_START; + + LWIP_ASSERT("pbuf_free: sane type", + p->type == PBUF_RAM || p->type == PBUF_ROM || + p->type == PBUF_REF || p->type == PBUF_POOL); + + count = 0; + /* de-allocate all consecutive pbufs from the head of the chain that + * obtain a zero reference count after decrementing*/ + while (p != NULL) { + u16_t ref; + SYS_ARCH_DECL_PROTECT(old_level); + /* Since decrementing ref cannot be guaranteed to be a single machine operation + * we must protect it. We put the new ref into a local variable to prevent + * further protection. */ + SYS_ARCH_PROTECT(old_level); + /* all pbufs in a chain are referenced at least once */ + LWIP_ASSERT("pbuf_free: p->ref > 0", p->ref > 0); + /* decrease reference count (number of pointers to pbuf) */ + ref = --(p->ref); + SYS_ARCH_UNPROTECT(old_level); + /* this pbuf is no longer referenced to? */ + if (ref == 0) { + /* remember next pbuf in chain for next iteration */ + q = p->next; + LWIP_DEBUGF( PBUF_DEBUG | LWIP_DBG_TRACE, ("pbuf_free: deallocating %p\n", (void *)p)); + type = p->type; +#if LWIP_SUPPORT_CUSTOM_PBUF + /* is this a custom pbuf? */ + if ((p->flags & PBUF_FLAG_IS_CUSTOM) != 0) { + struct pbuf_custom *pc = (struct pbuf_custom*)p; + LWIP_ASSERT("pc->custom_free_function != NULL", pc->custom_free_function != NULL); + pc->custom_free_function(p); + } else +#endif /* LWIP_SUPPORT_CUSTOM_PBUF */ + { + /* is this a pbuf from the pool? */ + if (type == PBUF_POOL) { + memp_free(MEMP_PBUF_POOL, p); + /* is this a ROM or RAM referencing pbuf? */ + } else if (type == PBUF_ROM || type == PBUF_REF) { + +#ifdef LWIP_ESP8266 + extern void system_pp_recycle_rx_pkt(void*); + if (type == PBUF_REF && p->eb != NULL ) system_pp_recycle_rx_pkt(p->eb); +#endif + + memp_free(MEMP_PBUF, p); + /* type == PBUF_RAM */ + } else { + mem_free(p); + } + } + count++; + /* proceed to next pbuf */ + p = q; + /* p->ref > 0, this pbuf is still referenced to */ + /* (and so the remaining pbufs in chain as well) */ + } else { + LWIP_DEBUGF( PBUF_DEBUG | LWIP_DBG_TRACE, ("pbuf_free: %p has ref %"U16_F", ending here.\n", (void *)p, ref)); + /* stop walking through the chain */ + p = NULL; + } + } + PERF_STOP("pbuf_free"); + /* return number of de-allocated pbufs */ + return count; +} + +/** + * Count number of pbufs in a chain + * + * @param p first pbuf of chain + * @return the number of pbufs in a chain + */ + +u8_t +pbuf_clen(struct pbuf *p) +{ + u8_t len; + + len = 0; + while (p != NULL) { + ++len; + p = p->next; + } + return len; +} + +/** + * Increment the reference count of the pbuf. + * + * @param p pbuf to increase reference counter of + * + */ +void +pbuf_ref(struct pbuf *p) +{ + SYS_ARCH_DECL_PROTECT(old_level); + /* pbuf given? */ + if (p != NULL) { + SYS_ARCH_PROTECT(old_level); + ++(p->ref); + SYS_ARCH_UNPROTECT(old_level); + } +} + +/** + * Concatenate two pbufs (each may be a pbuf chain) and take over + * the caller's reference of the tail pbuf. + * + * @note The caller MAY NOT reference the tail pbuf afterwards. + * Use pbuf_chain() for that purpose. + * + * @see pbuf_chain() + */ + +void +pbuf_cat(struct pbuf *h, struct pbuf *t) +{ + struct pbuf *p; + + LWIP_ERROR("(h != NULL) && (t != NULL) (programmer violates API)", + ((h != NULL) && (t != NULL)), return;); + + /* proceed to last pbuf of chain */ + for (p = h; p->next != NULL; p = p->next) { + /* add total length of second chain to all totals of first chain */ + p->tot_len += t->tot_len; + } + /* { p is last pbuf of first h chain, p->next == NULL } */ + LWIP_ASSERT("p->tot_len == p->len (of last pbuf in chain)", p->tot_len == p->len); + LWIP_ASSERT("p->next == NULL", p->next == NULL); + /* add total length of second chain to last pbuf total of first chain */ + p->tot_len += t->tot_len; + /* chain last pbuf of head (p) with first of tail (t) */ + p->next = t; + /* p->next now references t, but the caller will drop its reference to t, + * so netto there is no change to the reference count of t. + */ +} + +/** + * Chain two pbufs (or pbuf chains) together. + * + * The caller MUST call pbuf_free(t) once it has stopped + * using it. Use pbuf_cat() instead if you no longer use t. + * + * @param h head pbuf (chain) + * @param t tail pbuf (chain) + * @note The pbufs MUST belong to the same packet. + * @note MAY NOT be called on a packet queue. + * + * The ->tot_len fields of all pbufs of the head chain are adjusted. + * The ->next field of the last pbuf of the head chain is adjusted. + * The ->ref field of the first pbuf of the tail chain is adjusted. + * + */ +void +pbuf_chain(struct pbuf *h, struct pbuf *t) +{ + pbuf_cat(h, t); + /* t is now referenced by h */ + pbuf_ref(t); + LWIP_DEBUGF(PBUF_DEBUG | LWIP_DBG_TRACE, ("pbuf_chain: %p references %p\n", (void *)h, (void *)t)); +} + +/** + * Dechains the first pbuf from its succeeding pbufs in the chain. + * + * Makes p->tot_len field equal to p->len. + * @param p pbuf to dechain + * @return remainder of the pbuf chain, or NULL if it was de-allocated. + * @note May not be called on a packet queue. + */ +struct pbuf * +pbuf_dechain(struct pbuf *p) +{ + struct pbuf *q; + u8_t tail_gone = 1; + /* tail */ + q = p->next; + /* pbuf has successor in chain? */ + if (q != NULL) { + /* assert tot_len invariant: (p->tot_len == p->len + (p->next? p->next->tot_len: 0) */ + LWIP_ASSERT("p->tot_len == p->len + q->tot_len", q->tot_len == p->tot_len - p->len); + /* enforce invariant if assertion is disabled */ + q->tot_len = p->tot_len - p->len; + /* decouple pbuf from remainder */ + p->next = NULL; + /* total length of pbuf p is its own length only */ + p->tot_len = p->len; + /* q is no longer referenced by p, free it */ + LWIP_DEBUGF(PBUF_DEBUG | LWIP_DBG_TRACE, ("pbuf_dechain: unreferencing %p\n", (void *)q)); + tail_gone = pbuf_free(q); + if (tail_gone > 0) { + LWIP_DEBUGF(PBUF_DEBUG | LWIP_DBG_TRACE, + ("pbuf_dechain: deallocated %p (as it is no longer referenced)\n", (void *)q)); + } + /* return remaining tail or NULL if deallocated */ + } + /* assert tot_len invariant: (p->tot_len == p->len + (p->next? p->next->tot_len: 0) */ + LWIP_ASSERT("p->tot_len == p->len", p->tot_len == p->len); + return ((tail_gone > 0) ? NULL : q); +} + +/** + * + * Create PBUF_RAM copies of pbufs. + * + * Used to queue packets on behalf of the lwIP stack, such as + * ARP based queueing. + * + * @note You MUST explicitly use p = pbuf_take(p); + * + * @note Only one packet is copied, no packet queue! + * + * @param p_to pbuf destination of the copy + * @param p_from pbuf source of the copy + * + * @return ERR_OK if pbuf was copied + * ERR_ARG if one of the pbufs is NULL or p_to is not big + * enough to hold p_from + */ +err_t +pbuf_copy(struct pbuf *p_to, struct pbuf *p_from) +{ + u16_t offset_to=0, offset_from=0, len; + + LWIP_DEBUGF(PBUF_DEBUG | LWIP_DBG_TRACE, ("pbuf_copy(%p, %p)\n", + (void*)p_to, (void*)p_from)); + + /* is the target big enough to hold the source? */ + LWIP_ERROR("pbuf_copy: target not big enough to hold source", ((p_to != NULL) && + (p_from != NULL) && (p_to->tot_len >= p_from->tot_len)), return ERR_ARG;); + + /* iterate through pbuf chain */ + do + { + /* copy one part of the original chain */ + if ((p_to->len - offset_to) >= (p_from->len - offset_from)) { + /* complete current p_from fits into current p_to */ + len = p_from->len - offset_from; + } else { + /* current p_from does not fit into current p_to */ + len = p_to->len - offset_to; + } + MEMCPY((u8_t*)p_to->payload + offset_to, (u8_t*)p_from->payload + offset_from, len); + offset_to += len; + offset_from += len; + LWIP_ASSERT("offset_to <= p_to->len", offset_to <= p_to->len); + LWIP_ASSERT("offset_from <= p_from->len", offset_from <= p_from->len); + if (offset_from >= p_from->len) { + /* on to next p_from (if any) */ + offset_from = 0; + p_from = p_from->next; + } + if (offset_to == p_to->len) { + /* on to next p_to (if any) */ + offset_to = 0; + p_to = p_to->next; + LWIP_ERROR("p_to != NULL", (p_to != NULL) || (p_from == NULL) , return ERR_ARG;); + } + + if ((p_from != NULL) && (p_from->len == p_from->tot_len)) { + /* don't copy more than one packet! */ + LWIP_ERROR("pbuf_copy() does not allow packet queues!", + (p_from->next == NULL), return ERR_VAL;); + } + if ((p_to != NULL) && (p_to->len == p_to->tot_len)) { + /* don't copy more than one packet! */ + LWIP_ERROR("pbuf_copy() does not allow packet queues!", + (p_to->next == NULL), return ERR_VAL;); + } + } while (p_from); + LWIP_DEBUGF(PBUF_DEBUG | LWIP_DBG_TRACE, ("pbuf_copy: end of chain reached.\n")); + return ERR_OK; +} + +/** + * Copy (part of) the contents of a packet buffer + * to an application supplied buffer. + * + * @param buf the pbuf from which to copy data + * @param dataptr the application supplied buffer + * @param len length of data to copy (dataptr must be big enough). No more + * than buf->tot_len will be copied, irrespective of len + * @param offset offset into the packet buffer from where to begin copying len bytes + * @return the number of bytes copied, or 0 on failure + */ +u16_t +pbuf_copy_partial(struct pbuf *buf, void *dataptr, u16_t len, u16_t offset) +{ + struct pbuf *p; + u16_t left; + u16_t buf_copy_len; + u16_t copied_total = 0; + + LWIP_ERROR("pbuf_copy_partial: invalid buf", (buf != NULL), return 0;); + LWIP_ERROR("pbuf_copy_partial: invalid dataptr", (dataptr != NULL), return 0;); + + left = 0; + + if ((buf == NULL) || (dataptr == NULL)) { + return 0; + } + + /* Note some systems use byte copy if dataptr or one of the pbuf payload pointers are unaligned. */ + for (p = buf; len != 0 && p != NULL; p = p->next) { + if ((offset != 0) && (offset >= p->len)) { + /* don't copy from this buffer -> on to the next */ + offset -= p->len; + } else { + /* copy from this buffer. maybe only partially. */ + buf_copy_len = p->len - offset; + if (buf_copy_len > len) + buf_copy_len = len; + /* copy the necessary parts of the buffer */ + MEMCPY(&((char*)dataptr)[left], &((char*)p->payload)[offset], buf_copy_len); + copied_total += buf_copy_len; + left += buf_copy_len; + len -= buf_copy_len; + offset = 0; + } + } + return copied_total; +} + +#if LWIP_TCP && TCP_QUEUE_OOSEQ && LWIP_WND_SCALE +/** + * This method modifies a 'pbuf chain', so that its total length is + * smaller than 64K. The remainder of the original pbuf chain is stored + * in *rest. + * This function never creates new pbufs, but splits an existing chain + * in two parts. The tot_len of the modified packet queue will likely be + * smaller than 64K. + * 'packet queues' are not supported by this function. + * + * @param p the pbuf queue to be split + * @param rest pointer to store the remainder (after the first 64K) + */ +void pbuf_split_64k(struct pbuf *p, struct pbuf **rest) +{ + *rest = NULL; + if ((p != NULL) && (p->next != NULL)) { + u16_t tot_len_front = p->len; + struct pbuf *i = p; + struct pbuf *r = p->next; + + /* continue until the total length (summed up as u16_t) overflows */ + while ((r != NULL) && ((u16_t)(tot_len_front + r->len) > tot_len_front)) { + tot_len_front += r->len; + i = r; + r = r->next; + } + /* i now points to last packet of the first segment. Set next + pointer to NULL */ + i->next = NULL; + + if (r != NULL) { + /* Update the tot_len field in the first part */ + for (i = p; i != NULL; i = i->next) { + i->tot_len -= r->tot_len; + LWIP_ASSERT("tot_len/len mismatch in last pbuf", + (i->next != NULL) || (i->tot_len == i->len)); + } + if (p->flags & PBUF_FLAG_TCP_FIN) { + r->flags |= PBUF_FLAG_TCP_FIN; + } + + /* tot_len field in rest does not need modifications */ + /* reference counters do not need modifications */ + *rest = r; + } + } +} +#endif /* LWIP_TCP && TCP_QUEUE_OOSEQ && LWIP_WND_SCALE */ + +/** + * Skip a number of bytes at the start of a pbuf + * + * @param in input pbuf + * @param in_offset offset to skip + * @param out_offset resulting offset in the returned pbuf + * @return the pbuf in the queue where the offset is + */ +struct pbuf* +pbuf_skip(struct pbuf* in, u16_t in_offset, u16_t* out_offset) +{ + u16_t offset_left = in_offset; + struct pbuf* q = in; + + /* get the correct pbuf */ + while ((q != NULL) && (q->len <= offset_left)) { + offset_left -= q->len; + q = q->next; + } + if (out_offset != NULL) { + *out_offset = offset_left; + } + return q; +} + +/** + * Copy application supplied data into a pbuf. + * This function can only be used to copy the equivalent of buf->tot_len data. + * + * @param buf pbuf to fill with data + * @param dataptr application supplied data buffer + * @param len length of the application supplied data buffer + * + * @return ERR_OK if successful, ERR_MEM if the pbuf is not big enough + */ +err_t +pbuf_take(struct pbuf *buf, const void *dataptr, u16_t len) +{ + struct pbuf *p; + u16_t buf_copy_len; + u16_t total_copy_len = len; + u16_t copied_total = 0; + + LWIP_ERROR("pbuf_take: invalid buf", (buf != NULL), return ERR_ARG;); + LWIP_ERROR("pbuf_take: invalid dataptr", (dataptr != NULL), return ERR_ARG;); + LWIP_ERROR("pbuf_take: buf not large enough", (buf->tot_len >= len), return ERR_MEM;); + + if ((buf == NULL) || (dataptr == NULL) || (buf->tot_len < len)) { + return ERR_ARG; + } + + /* Note some systems use byte copy if dataptr or one of the pbuf payload pointers are unaligned. */ + for (p = buf; total_copy_len != 0; p = p->next) { + LWIP_ASSERT("pbuf_take: invalid pbuf", p != NULL); + buf_copy_len = total_copy_len; + if (buf_copy_len > p->len) { + /* this pbuf cannot hold all remaining data */ + buf_copy_len = p->len; + } + /* copy the necessary parts of the buffer */ + MEMCPY(p->payload, &((const char*)dataptr)[copied_total], buf_copy_len); + total_copy_len -= buf_copy_len; + copied_total += buf_copy_len; + } + LWIP_ASSERT("did not copy all data", total_copy_len == 0 && copied_total == len); + return ERR_OK; +} + +/** + * Same as pbuf_take() but puts data at an offset + * + * @param buf pbuf to fill with data + * @param dataptr application supplied data buffer + * @param len length of the application supplied data buffer + * + * @return ERR_OK if successful, ERR_MEM if the pbuf is not big enough + */ +err_t +pbuf_take_at(struct pbuf *buf, const void *dataptr, u16_t len, u16_t offset) +{ + u16_t target_offset; + struct pbuf* q = pbuf_skip(buf, offset, &target_offset); + + /* return requested data if pbuf is OK */ + if ((q != NULL) && (q->tot_len >= target_offset + len)) { + u16_t remaining_len = len; + const u8_t* src_ptr = (const u8_t*)dataptr; + /* copy the part that goes into the first pbuf */ + u16_t first_copy_len = LWIP_MIN(q->len - target_offset, len); + MEMCPY(((u8_t*)q->payload) + target_offset, dataptr, first_copy_len); + remaining_len -= first_copy_len; + src_ptr += first_copy_len; + if (remaining_len > 0) { + return pbuf_take(q->next, src_ptr, remaining_len); + } + return ERR_OK; + } + return ERR_MEM; +} + +/** + * Creates a single pbuf out of a queue of pbufs. + * + * @remark: Either the source pbuf 'p' is freed by this function or the original + * pbuf 'p' is returned, therefore the caller has to check the result! + * + * @param p the source pbuf + * @param layer pbuf_layer of the new pbuf + * + * @return a new, single pbuf (p->next is NULL) + * or the old pbuf if allocation fails + */ +struct pbuf* +pbuf_coalesce(struct pbuf *p, pbuf_layer layer) +{ + struct pbuf *q; + err_t err; + if (p->next == NULL) { + return p; + } + q = pbuf_alloc(layer, p->tot_len, PBUF_RAM); + if (q == NULL) { + /* @todo: what do we do now? */ + return p; + } + err = pbuf_copy(q, p); + LWIP_ASSERT("pbuf_copy failed", err == ERR_OK); + pbuf_free(p); + return q; +} + +#if LWIP_CHECKSUM_ON_COPY +/** + * Copies data into a single pbuf (*not* into a pbuf queue!) and updates + * the checksum while copying + * + * @param p the pbuf to copy data into + * @param start_offset offset of p->payload where to copy the data to + * @param dataptr data to copy into the pbuf + * @param len length of data to copy into the pbuf + * @param chksum pointer to the checksum which is updated + * @return ERR_OK if successful, another error if the data does not fit + * within the (first) pbuf (no pbuf queues!) + */ +err_t +pbuf_fill_chksum(struct pbuf *p, u16_t start_offset, const void *dataptr, + u16_t len, u16_t *chksum) +{ + u32_t acc; + u16_t copy_chksum; + char *dst_ptr; + LWIP_ASSERT("p != NULL", p != NULL); + LWIP_ASSERT("dataptr != NULL", dataptr != NULL); + LWIP_ASSERT("chksum != NULL", chksum != NULL); + LWIP_ASSERT("len != 0", len != 0); + + if ((start_offset >= p->len) || (start_offset + len > p->len)) { + return ERR_ARG; + } + + dst_ptr = ((char*)p->payload) + start_offset; + copy_chksum = LWIP_CHKSUM_COPY(dst_ptr, dataptr, len); + if ((start_offset & 1) != 0) { + copy_chksum = SWAP_BYTES_IN_WORD(copy_chksum); + } + acc = *chksum; + acc += copy_chksum; + *chksum = FOLD_U32T(acc); + return ERR_OK; +} +#endif /* LWIP_CHECKSUM_ON_COPY */ + + /** Get one byte from the specified position in a pbuf + * WARNING: returns zero for offset >= p->tot_len + * + * @param p pbuf to parse + * @param offset offset into p of the byte to return + * @return byte at an offset into p OR ZERO IF 'offset' >= p->tot_len + */ +u8_t +pbuf_get_at(struct pbuf* p, u16_t offset) +{ + u16_t q_idx; + struct pbuf* q = pbuf_skip(p, offset, &q_idx); + + /* return requested data if pbuf is OK */ + if ((q != NULL) && (q->len > q_idx)) { + return ((u8_t*)q->payload)[q_idx]; + } + return 0; +} + + /** Put one byte to the specified position in a pbuf + * WARNING: silently ignores offset >= p->tot_len + * + * @param p pbuf to fill + * @param offset offset into p of the byte to write + * @param data byte to write at an offset into p + */ +void +pbuf_put_at(struct pbuf* p, u16_t offset, u8_t data) +{ + u16_t q_idx; + struct pbuf* q = pbuf_skip(p, offset, &q_idx); + + /* write requested data if pbuf is OK */ + if ((q != NULL) && (q->len > q_idx)) { + ((u8_t*)q->payload)[q_idx] = data; + } +} + +/** Compare pbuf contents at specified offset with memory s2, both of length n + * + * @param p pbuf to compare + * @param offset offset into p at which to start comparing + * @param s2 buffer to compare + * @param n length of buffer to compare + * @return zero if equal, nonzero otherwise + * (0xffff if p is too short, diffoffset+1 otherwise) + */ +u16_t +pbuf_memcmp(struct pbuf* p, u16_t offset, const void* s2, u16_t n) +{ + u16_t start = offset; + struct pbuf* q = p; + + /* get the correct pbuf */ + while ((q != NULL) && (q->len <= start)) { + start -= q->len; + q = q->next; + } + /* return requested data if pbuf is OK */ + if ((q != NULL) && (q->len > start)) { + u16_t i; + for (i = 0; i < n; i++) { + u8_t a = pbuf_get_at(q, start + i); + u8_t b = ((const u8_t*)s2)[i]; + if (a != b) { + return i+1; + } + } + return 0; + } + return 0xffff; +} + +/** Find occurrence of mem (with length mem_len) in pbuf p, starting at offset + * start_offset. + * + * @param p pbuf to search, maximum length is 0xFFFE since 0xFFFF is used as + * return value 'not found' + * @param mem search for the contents of this buffer + * @param mem_len length of 'mem' + * @param start_offset offset into p at which to start searching + * @return 0xFFFF if substr was not found in p or the index where it was found + */ +u16_t +pbuf_memfind(struct pbuf* p, const void* mem, u16_t mem_len, u16_t start_offset) +{ + u16_t i; + u16_t max = p->tot_len - mem_len; + if (p->tot_len >= mem_len + start_offset) { + for (i = start_offset; i <= max; i++) { + u16_t plus = pbuf_memcmp(p, i, mem, mem_len); + if (plus == 0) { + return i; + } + } + } + return 0xFFFF; +} + +/** Find occurrence of substr with length substr_len in pbuf p, start at offset + * start_offset + * WARNING: in contrast to strstr(), this one does not stop at the first \0 in + * the pbuf/source string! + * + * @param p pbuf to search, maximum length is 0xFFFE since 0xFFFF is used as + * return value 'not found' + * @param substr string to search for in p, maximum length is 0xFFFE + * @return 0xFFFF if substr was not found in p or the index where it was found + */ +u16_t +pbuf_strstr(struct pbuf* p, const char* substr) +{ + size_t substr_len; + if ((substr == NULL) || (substr[0] == 0) || (p->tot_len == 0xFFFF)) { + return 0xFFFF; + } + substr_len = strlen(substr); + if (substr_len >= 0xFFFF) { + return 0xFFFF; + } + return pbuf_memfind(p, substr, (u16_t)substr_len, 0); +} diff --git a/components/lwip/core/raw.c b/components/lwip/core/raw.c new file mode 100755 index 0000000000..72a58d381d --- /dev/null +++ b/components/lwip/core/raw.c @@ -0,0 +1,483 @@ +/** + * @file + * Implementation of raw protocol PCBs for low-level handling of + * different types of protocols besides (or overriding) those + * already available in lwIP. + * + */ + +/* + * Copyright (c) 2001-2004 Swedish Institute of Computer Science. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + * + */ + +#include "lwip/opt.h" + +#if LWIP_RAW /* don't build if not configured for use in lwipopts.h */ + +#include "lwip/def.h" +#include "lwip/memp.h" +#include "lwip/ip_addr.h" +#include "lwip/netif.h" +#include "lwip/raw.h" +#include "lwip/stats.h" +#include "lwip/ip6.h" +#include "lwip/ip6_addr.h" +#include "lwip/inet_chksum.h" + +#include + +#ifdef MEMLEAK_DEBUG +static const char mem_debug_file[] ICACHE_RODATA_ATTR STORE_ATTR = __FILE__; +#endif + +/** The list of RAW PCBs */ +static struct raw_pcb *raw_pcbs; + +static u8_t +raw_input_match(struct raw_pcb *pcb, u8_t broadcast) +{ + LWIP_UNUSED_ARG(broadcast); /* in IPv6 only case */ + + /* Dual-stack: PCBs listening to any IP type also listen to any IP address */ + if(IP_IS_ANY_TYPE_VAL(pcb->local_ip)) { +#if LWIP_IPV4 && IP_SOF_BROADCAST_RECV + if((broadcast != 0) && !ip_get_option(pcb, SOF_BROADCAST)) { + return 0; + } +#endif /* LWIP_IPV4 && IP_SOF_BROADCAST_RECV */ + return 1; + } + + /* Only need to check PCB if incoming IP version matches PCB IP version */ + if(IP_ADDR_PCB_VERSION_MATCH_EXACT(pcb, ip_current_dest_addr())) { +#if LWIP_IPV4 + /* Special case: IPv4 broadcast: receive all broadcasts + * Note: broadcast variable can only be 1 if it is an IPv4 broadcast */ + if(broadcast != 0) { +#if IP_SOF_BROADCAST_RECV + if(ip_get_option(pcb, SOF_BROADCAST)) +#endif /* IP_SOF_BROADCAST_RECV */ + { + if(ip4_addr_isany(ip_2_ip4(&pcb->local_ip))) { + return 1; + } + } + } else +#endif /* LWIP_IPV4 */ + /* Handle IPv4 and IPv6: catch all or exact match */ + if(ip_addr_isany(&pcb->local_ip) || + ip_addr_cmp(&pcb->local_ip, ip_current_dest_addr())) { + return 1; + } + } + + return 0; +} + +/** + * Determine if in incoming IP packet is covered by a RAW PCB + * and if so, pass it to a user-provided receive callback function. + * + * Given an incoming IP datagram (as a chain of pbufs) this function + * finds a corresponding RAW PCB and calls the corresponding receive + * callback function. + * + * @param p pbuf to be demultiplexed to a RAW PCB. + * @param inp network interface on which the datagram was received. + * @return - 1 if the packet has been eaten by a RAW PCB receive + * callback function. The caller MAY NOT not reference the + * packet any longer, and MAY NOT call pbuf_free(). + * @return - 0 if packet is not eaten (pbuf is still referenced by the + * caller). + * + */ +u8_t +raw_input(struct pbuf *p, struct netif *inp) +{ + struct raw_pcb *pcb, *prev; + s16_t proto; + u8_t eaten = 0; + u8_t broadcast = ip_addr_isbroadcast(ip_current_dest_addr(), ip_current_netif()); + + LWIP_UNUSED_ARG(inp); + +#if LWIP_IPV6 +#if LWIP_IPV4 + if (IP_HDR_GET_VERSION(p->payload) == 6) +#endif /* LWIP_IPV4 */ + { + struct ip6_hdr *ip6hdr = (struct ip6_hdr *)p->payload; + proto = IP6H_NEXTH(ip6hdr); + } +#if LWIP_IPV4 + else +#endif /* LWIP_IPV4 */ +#endif /* LWIP_IPV6 */ +#if LWIP_IPV4 + { + proto = IPH_PROTO((struct ip_hdr *)p->payload); + } +#endif /* LWIP_IPV4 */ + + prev = NULL; + pcb = raw_pcbs; + /* loop through all raw pcbs until the packet is eaten by one */ + /* this allows multiple pcbs to match against the packet by design */ + while ((eaten == 0) && (pcb != NULL)) { + if ((pcb->protocol == proto) && raw_input_match(pcb, broadcast)) { + /* receive callback function available? */ + if (pcb->recv != NULL) { +#ifndef LWIP_NOASSERT + void* old_payload = p->payload; +#endif + /* the receive callback function did not eat the packet? */ + eaten = pcb->recv(pcb->recv_arg, pcb, p, ip_current_src_addr()); + if (eaten != 0) { + /* receive function ate the packet */ + p = NULL; + eaten = 1; + if (prev != NULL) { + /* move the pcb to the front of raw_pcbs so that is + found faster next time */ + prev->next = pcb->next; + pcb->next = raw_pcbs; + raw_pcbs = pcb; + } + } else { + /* sanity-check that the receive callback did not alter the pbuf */ + LWIP_ASSERT("raw pcb recv callback altered pbuf payload pointer without eating packet", + p->payload == old_payload); + } + } + /* no receive callback function was set for this raw PCB */ + } + /* drop the packet */ + prev = pcb; + pcb = pcb->next; + } + return eaten; +} + +/** + * Bind a RAW PCB. + * + * @param pcb RAW PCB to be bound with a local address ipaddr. + * @param ipaddr local IP address to bind with. Use IP_ADDR_ANY to + * bind to all local interfaces. + * + * @return lwIP error code. + * - ERR_OK. Successful. No error occurred. + * - ERR_USE. The specified IP address is already bound to by + * another RAW PCB. + * + * @see raw_disconnect() + */ +err_t +raw_bind(struct raw_pcb *pcb, const ip_addr_t *ipaddr) +{ + if ((pcb == NULL) || (ipaddr == NULL) || !IP_ADDR_PCB_VERSION_MATCH_EXACT(pcb, ipaddr)) { + return ERR_VAL; + } + ip_addr_set_ipaddr(&pcb->local_ip, ipaddr); + return ERR_OK; +} + +/** + * Connect an RAW PCB. This function is required by upper layers + * of lwip. Using the raw api you could use raw_sendto() instead + * + * This will associate the RAW PCB with the remote address. + * + * @param pcb RAW PCB to be connected with remote address ipaddr and port. + * @param ipaddr remote IP address to connect with. + * + * @return lwIP error code + * + * @see raw_disconnect() and raw_sendto() + */ +err_t +raw_connect(struct raw_pcb *pcb, const ip_addr_t *ipaddr) +{ + if ((pcb == NULL) || (ipaddr == NULL) || !IP_ADDR_PCB_VERSION_MATCH_EXACT(pcb, ipaddr)) { + return ERR_VAL; + } + ip_addr_set_ipaddr(&pcb->remote_ip, ipaddr); + return ERR_OK; +} + +/** + * Set the callback function for received packets that match the + * raw PCB's protocol and binding. + * + * The callback function MUST either + * - eat the packet by calling pbuf_free() and returning non-zero. The + * packet will not be passed to other raw PCBs or other protocol layers. + * - not free the packet, and return zero. The packet will be matched + * against further PCBs and/or forwarded to another protocol layers. + * + * @return non-zero if the packet was free()d, zero if the packet remains + * available for others. + */ +void +raw_recv(struct raw_pcb *pcb, raw_recv_fn recv, void *recv_arg) +{ + /* remember recv() callback and user data */ + pcb->recv = recv; + pcb->recv_arg = recv_arg; +} + +/** + * Send the raw IP packet to the given address. Note that actually you cannot + * modify the IP headers (this is inconsistent with the receive callback where + * you actually get the IP headers), you can only specify the IP payload here. + * It requires some more changes in lwIP. (there will be a raw_send() function + * then.) + * + * @param pcb the raw pcb which to send + * @param p the IP payload to send + * @param ipaddr the destination address of the IP packet + * + */ +err_t +raw_sendto(struct raw_pcb *pcb, struct pbuf *p, const ip_addr_t *ipaddr) +{ + err_t err; + struct netif *netif; + const ip_addr_t *src_ip; + struct pbuf *q; /* q will be sent down the stack */ + s16_t header_size; + const ip_addr_t *dst_ip = ipaddr; + + if ((pcb == NULL) || (ipaddr == NULL) || !IP_ADDR_PCB_VERSION_MATCH(pcb, ipaddr)) { + return ERR_VAL; + } + + LWIP_DEBUGF(RAW_DEBUG | LWIP_DBG_TRACE, ("raw_sendto\n")); + + header_size = ( +#if LWIP_IPV4 && LWIP_IPV6 + IP_IS_V6(ipaddr) ? IP6_HLEN : IP_HLEN); +#elif LWIP_IPV4 + IP_HLEN); +#else + IP6_HLEN); +#endif + + /* not enough space to add an IP header to first pbuf in given p chain? */ + if (pbuf_header(p, header_size)) { + /* allocate header in new pbuf */ + q = pbuf_alloc(PBUF_IP, 0, PBUF_RAM); + /* new header pbuf could not be allocated? */ + if (q == NULL) { + LWIP_DEBUGF(RAW_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_SERIOUS, ("raw_sendto: could not allocate header\n")); + return ERR_MEM; + } + if (p->tot_len != 0) { + /* chain header q in front of given pbuf p */ + pbuf_chain(q, p); + } + /* { first pbuf q points to header pbuf } */ + LWIP_DEBUGF(RAW_DEBUG, ("raw_sendto: added header pbuf %p before given pbuf %p\n", (void *)q, (void *)p)); + } else { + /* first pbuf q equals given pbuf */ + q = p; + if (pbuf_header(q, -header_size)) { + LWIP_ASSERT("Can't restore header we just removed!", 0); + return ERR_MEM; + } + } + + netif = ip_route(&pcb->local_ip, dst_ip); + if (netif == NULL) { + LWIP_DEBUGF(RAW_DEBUG | LWIP_DBG_LEVEL_WARNING, ("raw_sendto: No route to ")); + ip_addr_debug_print(RAW_DEBUG | LWIP_DBG_LEVEL_WARNING, dst_ip); + /* free any temporary header pbuf allocated by pbuf_header() */ + if (q != p) { + pbuf_free(q); + } + return ERR_RTE; + } + +#if IP_SOF_BROADCAST + if (!IP_IS_V6(ipaddr)) + { + /* broadcast filter? */ + if (!ip_get_option(pcb, SOF_BROADCAST) && ip_addr_isbroadcast(ipaddr, netif)) { + LWIP_DEBUGF(RAW_DEBUG | LWIP_DBG_LEVEL_WARNING, ("raw_sendto: SOF_BROADCAST not enabled on pcb %p\n", (void *)pcb)); + /* free any temporary header pbuf allocated by pbuf_header() */ + if (q != p) { + pbuf_free(q); + } + return ERR_VAL; + } + } +#endif /* IP_SOF_BROADCAST */ + + if (ip_addr_isany(&pcb->local_ip)) { + /* use outgoing network interface IP address as source address */ + src_ip = ip_netif_get_local_ip(netif, dst_ip); +#if LWIP_IPV6 + if (src_ip == NULL) { + if (q != p) { + pbuf_free(q); + } + return ERR_RTE; + } +#endif /* LWIP_IPV6 */ + } else { + /* use RAW PCB local IP address as source address */ + src_ip = &pcb->local_ip; + } + +#if LWIP_IPV6 + /* If requested, based on the IPV6_CHECKSUM socket option per RFC3542, + compute the checksum and update the checksum in the payload. */ + if (IP_IS_V6(dst_ip) && pcb->chksum_reqd) { + u16_t chksum = ip6_chksum_pseudo(p, pcb->protocol, p->tot_len, ip_2_ip6(src_ip), ip_2_ip6(dst_ip)); + LWIP_ASSERT("Checksum must fit into first pbuf", p->len >= (pcb->chksum_offset + 2)); + SMEMCPY(((u8_t *)p->payload) + pcb->chksum_offset, &chksum, sizeof(u16_t)); + } +#endif + + NETIF_SET_HWADDRHINT(netif, &pcb->addr_hint); + err = ip_output_if(q, src_ip, dst_ip, pcb->ttl, pcb->tos, pcb->protocol, netif); + NETIF_SET_HWADDRHINT(netif, NULL); + + /* did we chain a header earlier? */ + if (q != p) { + /* free the header */ + pbuf_free(q); + } + return err; +} + +/** + * Send the raw IP packet to the address given by raw_connect() + * + * @param pcb the raw pcb which to send + * @param p the IP payload to send + * + */ +err_t +raw_send(struct raw_pcb *pcb, struct pbuf *p) +{ + return raw_sendto(pcb, p, &pcb->remote_ip); +} + +/** + * Remove an RAW PCB. + * + * @param pcb RAW PCB to be removed. The PCB is removed from the list of + * RAW PCB's and the data structure is freed from memory. + * + * @see raw_new() + */ +void +raw_remove(struct raw_pcb *pcb) +{ + struct raw_pcb *pcb2; + /* pcb to be removed is first in list? */ + if (raw_pcbs == pcb) { + /* make list start at 2nd pcb */ + raw_pcbs = raw_pcbs->next; + /* pcb not 1st in list */ + } else { + for (pcb2 = raw_pcbs; pcb2 != NULL; pcb2 = pcb2->next) { + /* find pcb in raw_pcbs list */ + if (pcb2->next != NULL && pcb2->next == pcb) { + /* remove pcb from list */ + pcb2->next = pcb->next; + break; + } + } + } + memp_free(MEMP_RAW_PCB, pcb); +} + +/** + * Create a RAW PCB. + * + * @return The RAW PCB which was created. NULL if the PCB data structure + * could not be allocated. + * + * @param proto the protocol number of the IPs payload (e.g. IP_PROTO_ICMP) + * + * @see raw_remove() + */ +struct raw_pcb * +raw_new(u8_t proto) +{ + struct raw_pcb *pcb; + + LWIP_DEBUGF(RAW_DEBUG | LWIP_DBG_TRACE, ("raw_new\n")); + + pcb = (struct raw_pcb *)memp_malloc(MEMP_RAW_PCB); + /* could allocate RAW PCB? */ + if (pcb != NULL) { + /* initialize PCB to all zeroes */ + memset(pcb, 0, sizeof(struct raw_pcb)); + pcb->protocol = proto; + pcb->ttl = RAW_TTL; + pcb->next = raw_pcbs; + raw_pcbs = pcb; + } + return pcb; +} + +/** + * Create a RAW PCB for IPv6. + * + * @return The RAW PCB which was created. NULL if the PCB data structure + * could not be allocated. + * + * @param type IP address type, see IPADDR_TYPE_XX definitions. + * @param proto the protocol number (next header) of the IPv6 packet payload + * (e.g. IP6_NEXTH_ICMP6) + * + * @see raw_remove() + */ +struct raw_pcb * +raw_new_ip_type(u8_t type, u8_t proto) +{ + struct raw_pcb *pcb; + pcb = raw_new(proto); +#if LWIP_IPV4 && LWIP_IPV6 + if(pcb != NULL) { + IP_SET_TYPE_VAL(pcb->local_ip, type); + IP_SET_TYPE_VAL(pcb->remote_ip, type); + } +#else /* LWIP_IPV4 && LWIP_IPV6 */ + LWIP_UNUSED_ARG(type); +#endif /* LWIP_IPV4 && LWIP_IPV6 */ + return pcb; +} + +#endif /* LWIP_RAW */ diff --git a/components/lwip/core/stats.c b/components/lwip/core/stats.c new file mode 100755 index 0000000000..77ac3c675e --- /dev/null +++ b/components/lwip/core/stats.c @@ -0,0 +1,188 @@ +/** + * @file + * Statistics module + * + */ + +/* + * Copyright (c) 2001-2004 Swedish Institute of Computer Science. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + * + */ + +#include "lwip/opt.h" + +#if LWIP_STATS /* don't build if not configured for use in lwipopts.h */ + +#include "lwip/def.h" +#include "lwip/stats.h" +#include "lwip/mem.h" +#include "lwip/debug.h" + +#include + +#ifdef MEMLEAK_DEBUG +static const char mem_debug_file[] ICACHE_RODATA_ATTR STORE_ATTR = __FILE__; +#endif + +struct stats_ lwip_stats; + +#if defined(LWIP_DEBUG) || LWIP_STATS_DISPLAY +#if MEMP_STATS +static const char * memp_names[] = { +#define LWIP_MEMPOOL(name,num,size,desc) desc, +#include "lwip/priv/memp_std.h" +}; +#endif /* MEMP_STATS */ +#endif /* LWIP_DEBUG || LWIP_STATS_DISPLAY */ + +void +stats_init(void) +{ +#ifdef LWIP_DEBUG +#if MEMP_STATS + int i; + for (i = 0; i < MEMP_MAX; i++) { + lwip_stats.memp[i].name = memp_names[i]; + } +#endif /* MEMP_STATS */ +#if MEM_STATS + lwip_stats.mem.name = "MEM"; +#endif /* MEM_STATS */ +#endif /* LWIP_DEBUG */ +} + +#if LWIP_STATS_DISPLAY +void +stats_display_proto(struct stats_proto *proto, const char *name) +{ + LWIP_PLATFORM_DIAG(("\n%s\n\t", name)); + LWIP_PLATFORM_DIAG(("xmit: %"STAT_COUNTER_F"\n\t", proto->xmit)); + LWIP_PLATFORM_DIAG(("recv: %"STAT_COUNTER_F"\n\t", proto->recv)); + LWIP_PLATFORM_DIAG(("fw: %"STAT_COUNTER_F"\n\t", proto->fw)); + LWIP_PLATFORM_DIAG(("drop: %"STAT_COUNTER_F"\n\t", proto->drop)); + LWIP_PLATFORM_DIAG(("chkerr: %"STAT_COUNTER_F"\n\t", proto->chkerr)); + LWIP_PLATFORM_DIAG(("lenerr: %"STAT_COUNTER_F"\n\t", proto->lenerr)); + LWIP_PLATFORM_DIAG(("memerr: %"STAT_COUNTER_F"\n\t", proto->memerr)); + LWIP_PLATFORM_DIAG(("rterr: %"STAT_COUNTER_F"\n\t", proto->rterr)); + LWIP_PLATFORM_DIAG(("proterr: %"STAT_COUNTER_F"\n\t", proto->proterr)); + LWIP_PLATFORM_DIAG(("opterr: %"STAT_COUNTER_F"\n\t", proto->opterr)); + LWIP_PLATFORM_DIAG(("err: %"STAT_COUNTER_F"\n\t", proto->err)); + LWIP_PLATFORM_DIAG(("cachehit: %"STAT_COUNTER_F"\n", proto->cachehit)); +} + +#if IGMP_STATS || MLD6_STATS +void +stats_display_igmp(struct stats_igmp *igmp, const char *name) +{ + LWIP_PLATFORM_DIAG(("\n%s\n\t", name)); + LWIP_PLATFORM_DIAG(("xmit: %"STAT_COUNTER_F"\n\t", igmp->xmit)); + LWIP_PLATFORM_DIAG(("recv: %"STAT_COUNTER_F"\n\t", igmp->recv)); + LWIP_PLATFORM_DIAG(("drop: %"STAT_COUNTER_F"\n\t", igmp->drop)); + LWIP_PLATFORM_DIAG(("chkerr: %"STAT_COUNTER_F"\n\t", igmp->chkerr)); + LWIP_PLATFORM_DIAG(("lenerr: %"STAT_COUNTER_F"\n\t", igmp->lenerr)); + LWIP_PLATFORM_DIAG(("memerr: %"STAT_COUNTER_F"\n\t", igmp->memerr)); + LWIP_PLATFORM_DIAG(("proterr: %"STAT_COUNTER_F"\n\t", igmp->proterr)); + LWIP_PLATFORM_DIAG(("rx_v1: %"STAT_COUNTER_F"\n\t", igmp->rx_v1)); + LWIP_PLATFORM_DIAG(("rx_group: %"STAT_COUNTER_F"\n\t", igmp->rx_group)); + LWIP_PLATFORM_DIAG(("rx_general: %"STAT_COUNTER_F"\n\t", igmp->rx_general)); + LWIP_PLATFORM_DIAG(("rx_report: %"STAT_COUNTER_F"\n\t", igmp->rx_report)); + LWIP_PLATFORM_DIAG(("tx_join: %"STAT_COUNTER_F"\n\t", igmp->tx_join)); + LWIP_PLATFORM_DIAG(("tx_leave: %"STAT_COUNTER_F"\n\t", igmp->tx_leave)); + LWIP_PLATFORM_DIAG(("tx_report: %"STAT_COUNTER_F"\n\t", igmp->tx_report)); +} +#endif /* IGMP_STATS || MLD6_STATS */ + +#if MEM_STATS || MEMP_STATS +void +stats_display_mem(struct stats_mem *mem, const char *name) +{ + LWIP_PLATFORM_DIAG(("\nMEM %s\n\t", name)); + LWIP_PLATFORM_DIAG(("avail: %"U32_F"\n\t", (u32_t)mem->avail)); + LWIP_PLATFORM_DIAG(("used: %"U32_F"\n\t", (u32_t)mem->used)); + LWIP_PLATFORM_DIAG(("max: %"U32_F"\n\t", (u32_t)mem->max)); + LWIP_PLATFORM_DIAG(("err: %"U32_F"\n", (u32_t)mem->err)); +} + +#if MEMP_STATS +void +stats_display_memp(struct stats_mem *mem, int index) +{ + if (index < MEMP_MAX) { + stats_display_mem(mem, memp_names[index]); + } +} +#endif /* MEMP_STATS */ +#endif /* MEM_STATS || MEMP_STATS */ + +#if SYS_STATS +void +stats_display_sys(struct stats_sys *sys) +{ + LWIP_PLATFORM_DIAG(("\nSYS\n\t")); + LWIP_PLATFORM_DIAG(("sem.used: %"U32_F"\n\t", (u32_t)sys->sem.used)); + LWIP_PLATFORM_DIAG(("sem.max: %"U32_F"\n\t", (u32_t)sys->sem.max)); + LWIP_PLATFORM_DIAG(("sem.err: %"U32_F"\n\t", (u32_t)sys->sem.err)); + LWIP_PLATFORM_DIAG(("mutex.used: %"U32_F"\n\t", (u32_t)sys->mutex.used)); + LWIP_PLATFORM_DIAG(("mutex.max: %"U32_F"\n\t", (u32_t)sys->mutex.max)); + LWIP_PLATFORM_DIAG(("mutex.err: %"U32_F"\n\t", (u32_t)sys->mutex.err)); + LWIP_PLATFORM_DIAG(("mbox.used: %"U32_F"\n\t", (u32_t)sys->mbox.used)); + LWIP_PLATFORM_DIAG(("mbox.max: %"U32_F"\n\t", (u32_t)sys->mbox.max)); + LWIP_PLATFORM_DIAG(("mbox.err: %"U32_F"\n\t", (u32_t)sys->mbox.err)); +} +#endif /* SYS_STATS */ + +void +stats_display(void) +{ + s16_t i; + + LINK_STATS_DISPLAY(); + ETHARP_STATS_DISPLAY(); + IPFRAG_STATS_DISPLAY(); + IP6_FRAG_STATS_DISPLAY(); + IP_STATS_DISPLAY(); + ND6_STATS_DISPLAY(); + IP6_STATS_DISPLAY(); + IGMP_STATS_DISPLAY(); + MLD6_STATS_DISPLAY(); + ICMP_STATS_DISPLAY(); + ICMP6_STATS_DISPLAY(); + UDP_STATS_DISPLAY(); + TCP_STATS_DISPLAY(); + MEM_STATS_DISPLAY(); + for (i = 0; i < MEMP_MAX; i++) { + MEMP_STATS_DISPLAY(i); + } + SYS_STATS_DISPLAY(); +} +#endif /* LWIP_STATS_DISPLAY */ + +#endif /* LWIP_STATS */ + diff --git a/components/lwip/core/sys.c b/components/lwip/core/sys.c new file mode 100755 index 0000000000..f177737262 --- /dev/null +++ b/components/lwip/core/sys.c @@ -0,0 +1,68 @@ +/** + * @file + * lwIP Operating System abstraction + * + */ + +/* + * Copyright (c) 2001-2004 Swedish Institute of Computer Science. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + * + */ + +#include "lwip/opt.h" + +#include "lwip/sys.h" + +/* Most of the functions defined in sys.h must be implemented in the + * architecture-dependent file sys_arch.c */ + +#if !NO_SYS + +#ifndef sys_msleep +/** + * Sleep for some ms. Timeouts are NOT processed while sleeping. + * + * @param ms number of milliseconds to sleep + */ +void +sys_msleep(u32_t ms) +{ + if (ms > 0) { + sys_sem_t delaysem; + err_t err = sys_sem_new(&delaysem, 0); + if (err == ERR_OK) { + sys_arch_sem_wait(&delaysem, ms); + sys_sem_free(&delaysem); + } + } +} +#endif /* sys_msleep */ + +#endif /* !NO_SYS */ diff --git a/components/lwip/core/tcp.c b/components/lwip/core/tcp.c new file mode 100755 index 0000000000..e8fda52c8d --- /dev/null +++ b/components/lwip/core/tcp.c @@ -0,0 +1,2155 @@ +/** + * @file + * Transmission Control Protocol for IP + * + * This file contains common functions for the TCP implementation, such as functinos + * for manipulating the data structures and the TCP timer functions. TCP functions + * related to input and output is found in tcp_in.c and tcp_out.c respectively. + * + */ + +/* + * Copyright (c) 2001-2004 Swedish Institute of Computer Science. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + * + */ + +#include "lwip/opt.h" + +#if LWIP_TCP /* don't build if not configured for use in lwipopts.h */ + +#include "lwip/def.h" +#include "lwip/mem.h" +#include "lwip/memp.h" +#include "lwip/tcp.h" +#include "lwip/priv/tcp_priv.h" +#include "lwip/debug.h" +#include "lwip/stats.h" +#include "lwip/ip6.h" +#include "lwip/ip6_addr.h" +#include "lwip/nd6.h" + +#include + +#ifdef MEMLEAK_DEBUG +static const char mem_debug_file[] ICACHE_RODATA_ATTR STORE_ATTR = __FILE__; +#endif + +#ifndef TCP_LOCAL_PORT_RANGE_START +/* From http://www.iana.org/assignments/port-numbers: + "The Dynamic and/or Private Ports are those from 49152 through 65535" */ +#define TCP_LOCAL_PORT_RANGE_START 0xc000 +#define TCP_LOCAL_PORT_RANGE_END 0xffff +#define TCP_ENSURE_LOCAL_PORT_RANGE(port) ((u16_t)(((port) & ~TCP_LOCAL_PORT_RANGE_START) + TCP_LOCAL_PORT_RANGE_START)) +#endif + +#if LWIP_TCP_KEEPALIVE +#define TCP_KEEP_DUR(pcb) ((pcb)->keep_cnt * (pcb)->keep_intvl) +#define TCP_KEEP_INTVL(pcb) ((pcb)->keep_intvl) +#else /* LWIP_TCP_KEEPALIVE */ +#define TCP_KEEP_DUR(pcb) TCP_MAXIDLE +#define TCP_KEEP_INTVL(pcb) TCP_KEEPINTVL_DEFAULT +#endif /* LWIP_TCP_KEEPALIVE */ + +#ifdef LWIP_ESP8266 +//TO_DO +//char tcp_state_str[12]; +//const char tcp_state_str_rodata[][12] ICACHE_RODATA_ATTR STORE_ATTR = { +const char * const tcp_state_str[] = { +#else +const char * const tcp_state_str[] = { +#endif + "CLOSED", + "LISTEN", + "SYN_SENT", + "SYN_RCVD", + "ESTABLISHED", + "FIN_WAIT_1", + "FIN_WAIT_2", + "CLOSE_WAIT", + "CLOSING", + "LAST_ACK", + "TIME_WAIT" +}; + + +/* last local TCP port */ +#ifdef LWIP_ESP8266 +static s16_t tcp_port = TCP_LOCAL_PORT_RANGE_START; +#else +static u16_t tcp_port = TCP_LOCAL_PORT_RANGE_START; +#endif + +/* Incremented every coarse grained timer shot (typically every 500 ms). */ +u32_t tcp_ticks; + +#ifdef LWIP_ESP8266 +//TO_DO +//const u8_t tcp_backoff[13] ICACHE_RODATA_ATTR STORE_ATTR ={ 1, 2, 3, 4, 5, 6, 7, 7, 7, 7, 7, 7, 7}; +//const u8_t tcp_persist_backoff[7] ICACHE_RODATA_ATTR STORE_ATTR = { 3, 6, 12, 24, 48, 96, 120 }; + +const u8_t tcp_backoff[13] = { 1, 2, 3, 4, 5, 6, 7, 7, 7, 7, 7, 7, 7}; +const u8_t tcp_persist_backoff[7] = { 3, 6, 12, 24, 48, 96, 120 }; +#else +const u8_t tcp_backoff[13] = { 1, 2, 3, 4, 5, 6, 7, 7, 7, 7, 7, 7, 7}; + /* Times per slowtmr hits */ +const u8_t tcp_persist_backoff[7] = { 3, 6, 12, 24, 48, 96, 120 }; +#endif + + +/* The TCP PCB lists. */ + +/** List of all TCP PCBs bound but not yet (connected || listening) */ +struct tcp_pcb *tcp_bound_pcbs; +/** List of all TCP PCBs in LISTEN state */ +union tcp_listen_pcbs_t tcp_listen_pcbs; +/** List of all TCP PCBs that are in a state in which + * they accept or send data. */ +struct tcp_pcb *tcp_active_pcbs; +/** List of all TCP PCBs in TIME-WAIT state */ +struct tcp_pcb *tcp_tw_pcbs; + +/** An array with all (non-temporary) PCB lists, mainly used for smaller code size */ +#ifdef LWIP_ESP8266 +//TO_DO +//struct tcp_pcb ** const tcp_pcb_lists[] ICACHE_RODATA_ATTR STORE_ATTR = {&tcp_listen_pcbs.pcbs, &tcp_bound_pcbs, + // &tcp_active_pcbs, &tcp_tw_pcbs}; +struct tcp_pcb ** const tcp_pcb_lists[] = {&tcp_listen_pcbs.pcbs, &tcp_bound_pcbs, + &tcp_active_pcbs, &tcp_tw_pcbs}; + +#else +struct tcp_pcb ** const tcp_pcb_lists[] = {&tcp_listen_pcbs.pcbs, &tcp_bound_pcbs, + &tcp_active_pcbs, &tcp_tw_pcbs}; +#endif + + +u8_t tcp_active_pcbs_changed; + +/** Timer counter to handle calling slow-timer from tcp_tmr() */ +static u8_t tcp_timer; +static u8_t tcp_timer_ctr; +static u16_t tcp_new_port(void); + +/** + * Initialize this module. + */ +void +tcp_init(void) +{ +#if LWIP_RANDOMIZE_INITIAL_LOCAL_PORTS && defined(LWIP_RAND) + tcp_port = TCP_ENSURE_LOCAL_PORT_RANGE(LWIP_RAND()); +#endif /* LWIP_RANDOMIZE_INITIAL_LOCAL_PORTS && defined(LWIP_RAND) */ +} + +/** + * Called periodically to dispatch TCP timers. + */ +void +tcp_tmr(void) +{ + /* Call tcp_fasttmr() every 250 ms */ + tcp_fasttmr(); + + if (++tcp_timer & 1) { + /* Call tcp_slowtmr() every 500 ms, i.e., every other timer + tcp_tmr() is called. */ + tcp_slowtmr(); + } +} + +/** + * Closes the TX side of a connection held by the PCB. + * For tcp_close(), a RST is sent if the application didn't receive all data + * (tcp_recved() not called for all data passed to recv callback). + * + * Listening pcbs are freed and may not be referenced any more. + * Connection pcbs are freed if not yet connected and may not be referenced + * any more. If a connection is established (at least SYN received or in + * a closing state), the connection is closed, and put in a closing state. + * The pcb is then automatically freed in tcp_slowtmr(). It is therefore + * unsafe to reference it. + * + * @param pcb the tcp_pcb to close + * @return ERR_OK if connection has been closed + * another err_t if closing failed and pcb is not freed + */ +static err_t +tcp_close_shutdown(struct tcp_pcb *pcb, u8_t rst_on_unacked_data) +{ + err_t err; + + if (rst_on_unacked_data && ((pcb->state == ESTABLISHED) || (pcb->state == CLOSE_WAIT))) { + if ((pcb->refused_data != NULL) || (pcb->rcv_wnd != TCP_WND_MAX(pcb))) { + /* Not all data received by application, send RST to tell the remote + side about this. */ + LWIP_ASSERT("pcb->flags & TF_RXCLOSED", pcb->flags & TF_RXCLOSED); + + /* don't call tcp_abort here: we must not deallocate the pcb since + that might not be expected when calling tcp_close */ + tcp_rst(pcb->snd_nxt, pcb->rcv_nxt, &pcb->local_ip, &pcb->remote_ip, + pcb->local_port, pcb->remote_port); + + tcp_pcb_purge(pcb); + TCP_RMV_ACTIVE(pcb); + if (pcb->state == ESTABLISHED) { + /* move to TIME_WAIT since we close actively */ + pcb->state = TIME_WAIT; + TCP_REG(&tcp_tw_pcbs, pcb); + } else { + /* CLOSE_WAIT: deallocate the pcb since we already sent a RST for it */ + if (tcp_input_pcb == pcb) { + /* prevent using a deallocated pcb: free it from tcp_input later */ + tcp_trigger_input_pcb_close(); + } else { + memp_free(MEMP_TCP_PCB, pcb); + } + } + return ERR_OK; + } + } + + switch (pcb->state) { + case CLOSED: + /* Closing a pcb in the CLOSED state might seem erroneous, + * however, it is in this state once allocated and as yet unused + * and the user needs some way to free it should the need arise. + * Calling tcp_close() with a pcb that has already been closed, (i.e. twice) + * or for a pcb that has been used and then entered the CLOSED state + * is erroneous, but this should never happen as the pcb has in those cases + * been freed, and so any remaining handles are bogus. */ + err = ERR_OK; + if (pcb->local_port != 0) { + TCP_RMV(&tcp_bound_pcbs, pcb); + } + memp_free(MEMP_TCP_PCB, pcb); + pcb = NULL; + break; + case LISTEN: + err = ERR_OK; + tcp_pcb_remove(&tcp_listen_pcbs.pcbs, pcb); + memp_free(MEMP_TCP_PCB_LISTEN, pcb); + pcb = NULL; + break; + case SYN_SENT: + err = ERR_OK; + TCP_PCB_REMOVE_ACTIVE(pcb); + memp_free(MEMP_TCP_PCB, pcb); + pcb = NULL; + MIB2_STATS_INC(mib2.tcpattemptfails); + break; + case SYN_RCVD: + err = tcp_send_fin(pcb); + if (err == ERR_OK) { + MIB2_STATS_INC(mib2.tcpattemptfails); + pcb->state = FIN_WAIT_1; + } + break; + case ESTABLISHED: + err = tcp_send_fin(pcb); + if (err == ERR_OK) { + MIB2_STATS_INC(mib2.tcpestabresets); + pcb->state = FIN_WAIT_1; + } + break; + case CLOSE_WAIT: + err = tcp_send_fin(pcb); + if (err == ERR_OK) { + MIB2_STATS_INC(mib2.tcpestabresets); + pcb->state = LAST_ACK; + } + break; + default: + /* Has already been closed, do nothing. */ + err = ERR_OK; + pcb = NULL; + break; + } + + if (pcb != NULL && err == ERR_OK) { + /* To ensure all data has been sent when tcp_close returns, we have + to make sure tcp_output doesn't fail. + Since we don't really have to ensure all data has been sent when tcp_close + returns (unsent data is sent from tcp timer functions, also), we don't care + for the return value of tcp_output for now. */ + tcp_output(pcb); + } + return err; +} + +/** + * Closes the connection held by the PCB. + * + * Listening pcbs are freed and may not be referenced any more. + * Connection pcbs are freed if not yet connected and may not be referenced + * any more. If a connection is established (at least SYN received or in + * a closing state), the connection is closed, and put in a closing state. + * The pcb is then automatically freed in tcp_slowtmr(). It is therefore + * unsafe to reference it (unless an error is returned). + * + * @param pcb the tcp_pcb to close + * @return ERR_OK if connection has been closed + * another err_t if closing failed and pcb is not freed + */ +err_t +tcp_close(struct tcp_pcb *pcb) +{ + LWIP_DEBUGF(TCP_DEBUG, ("tcp_close: closing in ")); + tcp_debug_print_state(pcb->state); + + if (pcb->state != LISTEN) { + /* Set a flag not to receive any more data... */ + pcb->flags |= TF_RXCLOSED; + } + /* ... and close */ + return tcp_close_shutdown(pcb, 1); +} + +/** + * Causes all or part of a full-duplex connection of this PCB to be shut down. + * This doesn't deallocate the PCB unless shutting down both sides! + * Shutting down both sides is the same as calling tcp_close, so if it succeds, + * the PCB should not be referenced any more. + * + * @param pcb PCB to shutdown + * @param shut_rx shut down receive side if this is != 0 + * @param shut_tx shut down send side if this is != 0 + * @return ERR_OK if shutdown succeeded (or the PCB has already been shut down) + * another err_t on error. + */ +err_t +tcp_shutdown(struct tcp_pcb *pcb, int shut_rx, int shut_tx) +{ + if (pcb->state == LISTEN) { + return ERR_CONN; + } + if (shut_rx) { + /* shut down the receive side: set a flag not to receive any more data... */ + pcb->flags |= TF_RXCLOSED; + if (shut_tx) { + /* shutting down the tx AND rx side is the same as closing for the raw API */ + return tcp_close_shutdown(pcb, 1); + } + /* ... and free buffered data */ + if (pcb->refused_data != NULL) { + pbuf_free(pcb->refused_data); + pcb->refused_data = NULL; + } + } + if (shut_tx) { + /* This can't happen twice since if it succeeds, the pcb's state is changed. + Only close in these states as the others directly deallocate the PCB */ + switch (pcb->state) { + case SYN_RCVD: + case ESTABLISHED: + case CLOSE_WAIT: + return tcp_close_shutdown(pcb, (u8_t)shut_rx); + default: + /* Not (yet?) connected, cannot shutdown the TX side as that would bring us + into CLOSED state, where the PCB is deallocated. */ + return ERR_CONN; + } + } + return ERR_OK; +} + +/** + * Abandons a connection and optionally sends a RST to the remote + * host. Deletes the local protocol control block. This is done when + * a connection is killed because of shortage of memory. + * + * @param pcb the tcp_pcb to abort + * @param reset boolean to indicate whether a reset should be sent + */ +void +tcp_abandon(struct tcp_pcb *pcb, int reset) +{ + u32_t seqno, ackno; +#if LWIP_CALLBACK_API + tcp_err_fn errf; +#endif /* LWIP_CALLBACK_API */ + void *errf_arg; + + /* pcb->state LISTEN not allowed here */ + LWIP_ASSERT("don't call tcp_abort/tcp_abandon for listen-pcbs", + pcb->state != LISTEN); + /* Figure out on which TCP PCB list we are, and remove us. If we + are in an active state, call the receive function associated with + the PCB with a NULL argument, and send an RST to the remote end. */ + if (pcb->state == TIME_WAIT) { + tcp_pcb_remove(&tcp_tw_pcbs, pcb); + memp_free(MEMP_TCP_PCB, pcb); + } else { + int send_rst = 0; + u16_t local_port = 0; + seqno = pcb->snd_nxt; + ackno = pcb->rcv_nxt; +#if LWIP_CALLBACK_API + errf = pcb->errf; +#endif /* LWIP_CALLBACK_API */ + errf_arg = pcb->callback_arg; + if ((pcb->state == CLOSED) && (pcb->local_port != 0)) { + /* bound, not yet opened */ + TCP_RMV(&tcp_bound_pcbs, pcb); + } else { + send_rst = reset; + local_port = pcb->local_port; + TCP_PCB_REMOVE_ACTIVE(pcb); + } + if (pcb->unacked != NULL) { + tcp_segs_free(pcb->unacked); + } + if (pcb->unsent != NULL) { + tcp_segs_free(pcb->unsent); + } +#if TCP_QUEUE_OOSEQ + if (pcb->ooseq != NULL) { + tcp_segs_free(pcb->ooseq); + } +#endif /* TCP_QUEUE_OOSEQ */ + if (send_rst) { + LWIP_DEBUGF(TCP_RST_DEBUG, ("tcp_abandon: sending RST\n")); + tcp_rst(seqno, ackno, &pcb->local_ip, &pcb->remote_ip, local_port, pcb->remote_port); + } + memp_free(MEMP_TCP_PCB, pcb); + TCP_EVENT_ERR(errf, errf_arg, ERR_ABRT); + } +} + +/** + * Aborts the connection by sending a RST (reset) segment to the remote + * host. The pcb is deallocated. This function never fails. + * + * ATTENTION: When calling this from one of the TCP callbacks, make + * sure you always return ERR_ABRT (and never return ERR_ABRT otherwise + * or you will risk accessing deallocated memory or memory leaks! + * + * @param pcb the tcp pcb to abort + */ +void +tcp_abort(struct tcp_pcb *pcb) +{ + tcp_abandon(pcb, 1); +} + +/** + * Binds the connection to a local port number and IP address. If the + * IP address is not given (i.e., ipaddr == NULL), the IP address of + * the outgoing network interface is used instead. + * + * @param pcb the tcp_pcb to bind (no check is done whether this pcb is + * already bound!) + * @param ipaddr the local ip address to bind to (use IP_ADDR_ANY to bind + * to any local address + * @param port the local port to bind to + * @return ERR_USE if the port is already in use + * ERR_VAL if bind failed because the PCB is not in a valid state + * ERR_OK if bound + */ +err_t +tcp_bind(struct tcp_pcb *pcb, const ip_addr_t *ipaddr, u16_t port) +{ + int i; + int max_pcb_list = NUM_TCP_PCB_LISTS; + struct tcp_pcb *cpcb; + +#if LWIP_IPV4 + /* Don't propagate NULL pointer (IPv4 ANY) to subsequent functions */ + if (ipaddr == NULL) { + ipaddr = IP_ADDR_ANY; + } +#endif /* LWIP_IPV4 */ + + /* still need to check for ipaddr == NULL in IPv6 only case */ + if ((pcb == NULL) || (ipaddr == NULL) || !IP_ADDR_PCB_VERSION_MATCH_EXACT(pcb, ipaddr)) { + return ERR_VAL; + } + + LWIP_ERROR("tcp_bind: can only bind in state CLOSED", pcb->state == CLOSED, return ERR_VAL); + +#if SO_REUSE + /* Unless the REUSEADDR flag is set, + we have to check the pcbs in TIME-WAIT state, also. + We do not dump TIME_WAIT pcb's; they can still be matched by incoming + packets using both local and remote IP addresses and ports to distinguish. + */ + if (ip_get_option(pcb, SOF_REUSEADDR)) { + max_pcb_list = NUM_TCP_PCB_LISTS_NO_TIME_WAIT; + } +#endif /* SO_REUSE */ + + if (port == 0) { + port = tcp_new_port(); + if (port == 0) { + return ERR_BUF; + } + } else { + /* Check if the address already is in use (on all lists) */ + for (i = 0; i < max_pcb_list; i++) { + for (cpcb = *tcp_pcb_lists[i]; cpcb != NULL; cpcb = cpcb->next) { + if (cpcb->local_port == port) { +#if SO_REUSE + /* Omit checking for the same port if both pcbs have REUSEADDR set. + For SO_REUSEADDR, the duplicate-check for a 5-tuple is done in + tcp_connect. */ + if (!ip_get_option(pcb, SOF_REUSEADDR) || + !ip_get_option(cpcb, SOF_REUSEADDR)) +#endif /* SO_REUSE */ + { + /* @todo: check accept_any_ip_version */ + if ((IP_IS_V6(ipaddr) == IP_IS_V6_VAL(cpcb->local_ip)) && + (ip_addr_isany(&cpcb->local_ip) || + ip_addr_isany(ipaddr) || + ip_addr_cmp(&cpcb->local_ip, ipaddr))) { + return ERR_USE; + } + } + } + } + } + } + + if (!ip_addr_isany(ipaddr)) { + ip_addr_set(&pcb->local_ip, ipaddr); + } + pcb->local_port = port; + TCP_REG(&tcp_bound_pcbs, pcb); + LWIP_DEBUGF(TCP_DEBUG, ("tcp_bind: bind to port %"U16_F"\n", port)); + return ERR_OK; +} +#if LWIP_CALLBACK_API +/** + * Default accept callback if no accept callback is specified by the user. + */ +static err_t +tcp_accept_null(void *arg, struct tcp_pcb *pcb, err_t err) +{ + LWIP_UNUSED_ARG(arg); + LWIP_UNUSED_ARG(err); + + tcp_abort(pcb); + + return ERR_ABRT; +} +#endif /* LWIP_CALLBACK_API */ + +/** + * Set the state of the connection to be LISTEN, which means that it + * is able to accept incoming connections. The protocol control block + * is reallocated in order to consume less memory. Setting the + * connection to LISTEN is an irreversible process. + * + * @param pcb the original tcp_pcb + * @param backlog the incoming connections queue limit + * @return tcp_pcb used for listening, consumes less memory. + * + * @note The original tcp_pcb is freed. This function therefore has to be + * called like this: + * tpcb = tcp_listen(tpcb); + */ +struct tcp_pcb * +tcp_listen_with_backlog(struct tcp_pcb *pcb, u8_t backlog) +{ + struct tcp_pcb_listen *lpcb; + + LWIP_UNUSED_ARG(backlog); + LWIP_ERROR("tcp_listen: pcb already connected", pcb->state == CLOSED, return NULL); + + /* already listening? */ + if (pcb->state == LISTEN) { + return pcb; + } +#if SO_REUSE + if (ip_get_option(pcb, SOF_REUSEADDR)) { + /* Since SOF_REUSEADDR allows reusing a local address before the pcb's usage + is declared (listen-/connection-pcb), we have to make sure now that + this port is only used once for every local IP. */ + for (lpcb = tcp_listen_pcbs.listen_pcbs; lpcb != NULL; lpcb = lpcb->next) { + if ((lpcb->local_port == pcb->local_port) && + ip_addr_cmp(&lpcb->local_ip, &pcb->local_ip)) { + /* this address/port is already used */ + return NULL; + } + } + } +#endif /* SO_REUSE */ + lpcb = (struct tcp_pcb_listen *)memp_malloc(MEMP_TCP_PCB_LISTEN); + if (lpcb == NULL) { + return NULL; + } + lpcb->callback_arg = pcb->callback_arg; + lpcb->local_port = pcb->local_port; + lpcb->state = LISTEN; + lpcb->prio = pcb->prio; + lpcb->so_options = pcb->so_options; + lpcb->ttl = pcb->ttl; + lpcb->tos = pcb->tos; +#if LWIP_IPV4 && LWIP_IPV6 + IP_SET_TYPE_VAL(lpcb->remote_ip, pcb->local_ip.type); +#endif /* LWIP_IPV4 && LWIP_IPV6 */ + ip_addr_copy(lpcb->local_ip, pcb->local_ip); + if (pcb->local_port != 0) { + TCP_RMV(&tcp_bound_pcbs, pcb); + } + memp_free(MEMP_TCP_PCB, pcb); +#if LWIP_CALLBACK_API + lpcb->accept = tcp_accept_null; +#endif /* LWIP_CALLBACK_API */ +#if TCP_LISTEN_BACKLOG + lpcb->accepts_pending = 0; + tcp_backlog_set(lpcb, backlog); +#endif /* TCP_LISTEN_BACKLOG */ + TCP_REG(&tcp_listen_pcbs.pcbs, (struct tcp_pcb *)lpcb); + return (struct tcp_pcb *)lpcb; +} + +/** + * Update the state that tracks the available window space to advertise. + * + * Returns how much extra window would be advertised if we sent an + * update now. + */ +u32_t tcp_update_rcv_ann_wnd(struct tcp_pcb *pcb) +{ + u32_t new_right_edge = pcb->rcv_nxt + pcb->rcv_wnd; + + if (TCP_SEQ_GEQ(new_right_edge, pcb->rcv_ann_right_edge + LWIP_MIN((TCP_WND / 2), pcb->mss))) { + /* we can advertise more window */ + pcb->rcv_ann_wnd = pcb->rcv_wnd; + return new_right_edge - pcb->rcv_ann_right_edge; + } else { + if (TCP_SEQ_GT(pcb->rcv_nxt, pcb->rcv_ann_right_edge)) { + /* Can happen due to other end sending out of advertised window, + * but within actual available (but not yet advertised) window */ + pcb->rcv_ann_wnd = 0; + } else { + /* keep the right edge of window constant */ + u32_t new_rcv_ann_wnd = pcb->rcv_ann_right_edge - pcb->rcv_nxt; +#if !LWIP_WND_SCALE + LWIP_ASSERT("new_rcv_ann_wnd <= 0xffff", new_rcv_ann_wnd <= 0xffff); +#endif + pcb->rcv_ann_wnd = (tcpwnd_size_t)new_rcv_ann_wnd; + } + return 0; + } +} + +/** + * This function should be called by the application when it has + * processed the data. The purpose is to advertise a larger window + * when the data has been processed. + * + * @param pcb the tcp_pcb for which data is read + * @param len the amount of bytes that have been read by the application + */ +void +tcp_recved(struct tcp_pcb *pcb, u16_t len) +{ + int wnd_inflation; + + /* pcb->state LISTEN not allowed here */ + LWIP_ASSERT("don't call tcp_recved for listen-pcbs", + pcb->state != LISTEN); + + pcb->rcv_wnd += len; + if (pcb->rcv_wnd > TCP_WND_MAX(pcb)) { + pcb->rcv_wnd = TCP_WND_MAX(pcb); + } else if (pcb->rcv_wnd == 0) { + /* rcv_wnd overflowed */ + if ((pcb->state == CLOSE_WAIT) || (pcb->state == LAST_ACK)) { + /* In passive close, we allow this, since the FIN bit is added to rcv_wnd + by the stack itself, since it is not mandatory for an application + to call tcp_recved() for the FIN bit, but e.g. the netconn API does so. */ + pcb->rcv_wnd = TCP_WND_MAX(pcb); + } else { + LWIP_ASSERT("tcp_recved: len wrapped rcv_wnd\n", 0); + } + } + + wnd_inflation = tcp_update_rcv_ann_wnd(pcb); + + /* If the change in the right edge of window is significant (default + * watermark is TCP_WND/4), then send an explicit update now. + * Otherwise wait for a packet to be sent in the normal course of + * events (or more window to be available later) */ + if (wnd_inflation >= TCP_WND_UPDATE_THRESHOLD) { + tcp_ack_now(pcb); + tcp_output(pcb); + } + + LWIP_DEBUGF(TCP_DEBUG, ("tcp_recved: received %"U16_F" bytes, wnd %"TCPWNDSIZE_F" (%"TCPWNDSIZE_F").\n", + len, pcb->rcv_wnd, TCP_WND_MAX(pcb) - pcb->rcv_wnd)); +} + +/** + * Allocate a new local TCP port. + * + * @return a new (free) local TCP port number + */ +static u16_t +tcp_new_port(void) +{ + u8_t i; + u16_t n = 0; + struct tcp_pcb *pcb; + +again: + +#ifdef LWIP_ESP8266 + tcp_port = system_get_time(); + if (tcp_port < 0) + tcp_port = LWIP_RAND() - tcp_port; + tcp_port %= TCP_LOCAL_PORT_RANGE_START; +#else + if (tcp_port++ == TCP_LOCAL_PORT_RANGE_END) { + tcp_port = TCP_LOCAL_PORT_RANGE_START; + } +#endif + + /* Check all PCB lists. */ + for (i = 0; i < NUM_TCP_PCB_LISTS; i++) { + for (pcb = *tcp_pcb_lists[i]; pcb != NULL; pcb = pcb->next) { + if (pcb->local_port == tcp_port) { + if (++n > (TCP_LOCAL_PORT_RANGE_END - TCP_LOCAL_PORT_RANGE_START)) { + return 0; + } + goto again; + } + } + } + return tcp_port; +} + +/** + * Connects to another host. The function given as the "connected" + * argument will be called when the connection has been established. + * + * @param pcb the tcp_pcb used to establish the connection + * @param ipaddr the remote ip address to connect to + * @param port the remote tcp port to connect to + * @param connected callback function to call when connected (on error, + the err calback will be called) + * @return ERR_VAL if invalid arguments are given + * ERR_OK if connect request has been sent + * other err_t values if connect request couldn't be sent + */ +err_t +tcp_connect(struct tcp_pcb *pcb, const ip_addr_t *ipaddr, u16_t port, + tcp_connected_fn connected) +{ + err_t ret; + u32_t iss; + u16_t old_local_port; + + if ((pcb == NULL) || (ipaddr == NULL) || !IP_ADDR_PCB_VERSION_MATCH_EXACT(pcb, ipaddr)) { + return ERR_VAL; + } + + LWIP_ERROR("tcp_connect: can only connect from state CLOSED", pcb->state == CLOSED, return ERR_ISCONN); + + LWIP_DEBUGF(TCP_DEBUG, ("tcp_connect to port %"U16_F"\n", port)); + ip_addr_set(&pcb->remote_ip, ipaddr); + pcb->remote_port = port; + + /* check if we have a route to the remote host */ + if (ip_addr_isany(&pcb->local_ip)) { + /* no local IP address set, yet. */ + struct netif *netif; + const ip_addr_t *local_ip; + ip_route_get_local_ip(&pcb->local_ip, &pcb->remote_ip, netif, local_ip); + if ((netif == NULL) || (local_ip == NULL)) { + /* Don't even try to send a SYN packet if we have no route + since that will fail. */ + return ERR_RTE; + } + /* Use the address as local address of the pcb. */ + ip_addr_copy(pcb->local_ip, *local_ip); + } + + old_local_port = pcb->local_port; + if (pcb->local_port == 0) { + pcb->local_port = tcp_new_port(); + if (pcb->local_port == 0) { + return ERR_BUF; + } + } else { +#if SO_REUSE + if (ip_get_option(pcb, SOF_REUSEADDR)) { + /* Since SOF_REUSEADDR allows reusing a local address, we have to make sure + now that the 5-tuple is unique. */ + struct tcp_pcb *cpcb; + int i; + /* Don't check listen- and bound-PCBs, check active- and TIME-WAIT PCBs. */ + for (i = 2; i < NUM_TCP_PCB_LISTS; i++) { + for (cpcb = *tcp_pcb_lists[i]; cpcb != NULL; cpcb = cpcb->next) { + if ((cpcb->local_port == pcb->local_port) && + (cpcb->remote_port == port) && + ip_addr_cmp(&cpcb->local_ip, &pcb->local_ip) && + ip_addr_cmp(&cpcb->remote_ip, ipaddr)) { + /* linux returns EISCONN here, but ERR_USE should be OK for us */ + return ERR_USE; + } + } + } + } +#endif /* SO_REUSE */ + } + + iss = tcp_next_iss(); + pcb->rcv_nxt = 0; + pcb->snd_nxt = iss; + pcb->lastack = iss - 1; + pcb->snd_lbb = iss - 1; + /* Start with a window that does not need scaling. When window scaling is + enabled and used, the window is enlarged when both sides agree on scaling. */ + pcb->rcv_wnd = pcb->rcv_ann_wnd = TCPWND_MIN16(TCP_WND); + pcb->rcv_ann_right_edge = pcb->rcv_nxt; + pcb->snd_wnd = TCP_WND; + /* As initial send MSS, we use TCP_MSS but limit it to 536. + The send MSS is updated when an MSS option is received. */ + pcb->mss = (TCP_MSS > 536) ? 536 : TCP_MSS; +#if TCP_CALCULATE_EFF_SEND_MSS + pcb->mss = tcp_eff_send_mss(pcb->mss, &pcb->local_ip, &pcb->remote_ip); +#endif /* TCP_CALCULATE_EFF_SEND_MSS */ + pcb->cwnd = 1; + pcb->ssthresh = TCP_WND; +#if LWIP_CALLBACK_API + pcb->connected = connected; +#else /* LWIP_CALLBACK_API */ + LWIP_UNUSED_ARG(connected); +#endif /* LWIP_CALLBACK_API */ + + /* Send a SYN together with the MSS option. */ + ret = tcp_enqueue_flags(pcb, TCP_SYN); + if (ret == ERR_OK) { + /* SYN segment was enqueued, changed the pcbs state now */ + pcb->state = SYN_SENT; + if (old_local_port != 0) { + TCP_RMV(&tcp_bound_pcbs, pcb); + } + TCP_REG_ACTIVE(pcb); + MIB2_STATS_INC(mib2.tcpactiveopens); + + tcp_output(pcb); + } + return ret; +} + +/** + * Called every 500 ms and implements the retransmission timer and the timer that + * removes PCBs that have been in TIME-WAIT for enough time. It also increments + * various timers such as the inactivity timer in each PCB. + * + * Automatically called from tcp_tmr(). + */ +void +tcp_slowtmr(void) +{ + struct tcp_pcb *pcb, *prev; + tcpwnd_size_t eff_wnd; + u8_t pcb_remove; /* flag if a PCB should be removed */ + u8_t pcb_reset; /* flag if a RST should be sent when removing */ + err_t err; + + err = ERR_OK; + + ++tcp_ticks; + ++tcp_timer_ctr; + +tcp_slowtmr_start: + /* Steps through all of the active PCBs. */ + prev = NULL; + pcb = tcp_active_pcbs; + if (pcb == NULL) { + LWIP_DEBUGF(TCP_DEBUG, ("tcp_slowtmr: no active pcbs\n")); + } + while (pcb != NULL) { + LWIP_DEBUGF(TCP_DEBUG, ("tcp_slowtmr: processing active pcb\n")); + LWIP_ASSERT("tcp_slowtmr: active pcb->state != CLOSED\n", pcb->state != CLOSED); + LWIP_ASSERT("tcp_slowtmr: active pcb->state != LISTEN\n", pcb->state != LISTEN); + LWIP_ASSERT("tcp_slowtmr: active pcb->state != TIME-WAIT\n", pcb->state != TIME_WAIT); + if (pcb->last_timer == tcp_timer_ctr) { + /* skip this pcb, we have already processed it */ + pcb = pcb->next; + continue; + } + pcb->last_timer = tcp_timer_ctr; + + pcb_remove = 0; + pcb_reset = 0; + + if (pcb->state == SYN_SENT && pcb->nrtx == TCP_SYNMAXRTX) { + ++pcb_remove; + LWIP_DEBUGF(TCP_DEBUG, ("tcp_slowtmr: max SYN retries reached\n")); + } + else if (pcb->nrtx == TCP_MAXRTX) { + ++pcb_remove; + LWIP_DEBUGF(TCP_DEBUG, ("tcp_slowtmr: max DATA retries reached\n")); + } else { + if (pcb->persist_backoff > 0) { + + /* If snd_wnd is zero, use persist timer to send 1 byte probes + * instead of using the standard retransmission mechanism. */ +#ifdef LWIP_ESP8266 +//NEED TO DO + //u8_t backoff_cnt = system_get_data_of_array_8(tcp_persist_backoff, pcb->persist_backoff-1); + u8_t backoff_cnt = tcp_persist_backoff[pcb->persist_backoff-1]; +#else + u8_t backoff_cnt = tcp_persist_backoff[pcb->persist_backoff-1]; +#endif + + if (pcb->persist_cnt < backoff_cnt) { + pcb->persist_cnt++; + } + if (pcb->persist_cnt >= backoff_cnt) { + if (tcp_zero_window_probe(pcb) == ERR_OK) { + pcb->persist_cnt = 0; + if (pcb->persist_backoff < sizeof(tcp_persist_backoff)) { + pcb->persist_backoff++; + } + } + } + } else { + /* Increase the retransmission timer if it is running */ + if (pcb->rtime >= 0) { + ++pcb->rtime; + } + + if (pcb->unacked != NULL && pcb->rtime >= pcb->rto) { + /* Time for a retransmission. */ + LWIP_DEBUGF(TCP_RTO_DEBUG, ("tcp_slowtmr: rtime %"S16_F + " pcb->rto %"S16_F"\n", + pcb->rtime, pcb->rto)); + + /* Double retransmission time-out unless we are trying to + * connect to somebody (i.e., we are in SYN_SENT). */ + if (pcb->state != SYN_SENT) { + +#ifdef LWIP_ESP8266 +//TO_DO +// pcb->rto = ((pcb->sa >> 3) + pcb->sv) << system_get_data_of_array_8(tcp_backoff, pcb->nrtx); + pcb->rto = ((pcb->sa >> 3) + pcb->sv) << tcp_backoff[pcb->nrtx]; +#else + pcb->rto = ((pcb->sa >> 3) + pcb->sv) << tcp_backoff[pcb->nrtx]; +#endif + + } + + /* Reset the retransmission timer. */ + pcb->rtime = 0; + + /* Reduce congestion window and ssthresh. */ + eff_wnd = LWIP_MIN(pcb->cwnd, pcb->snd_wnd); + pcb->ssthresh = eff_wnd >> 1; + if (pcb->ssthresh < (tcpwnd_size_t)(pcb->mss << 1)) { + pcb->ssthresh = (pcb->mss << 1); + } + pcb->cwnd = pcb->mss; + LWIP_DEBUGF(TCP_CWND_DEBUG, ("tcp_slowtmr: cwnd %"TCPWNDSIZE_F + " ssthresh %"TCPWNDSIZE_F"\n", + pcb->cwnd, pcb->ssthresh)); + + /* The following needs to be called AFTER cwnd is set to one + mss - STJ */ + tcp_rexmit_rto(pcb); + } + } + } + /* Check if this PCB has stayed too long in FIN-WAIT-2 */ + if (pcb->state == FIN_WAIT_2) { + /* If this PCB is in FIN_WAIT_2 because of SHUT_WR don't let it time out. */ + if (pcb->flags & TF_RXCLOSED) { + /* PCB was fully closed (either through close() or SHUT_RDWR): + normal FIN-WAIT timeout handling. */ + if ((u32_t)(tcp_ticks - pcb->tmr) > + TCP_FIN_WAIT_TIMEOUT / TCP_SLOW_INTERVAL) { + ++pcb_remove; + LWIP_DEBUGF(TCP_DEBUG, ("tcp_slowtmr: removing pcb stuck in FIN-WAIT-2\n")); + } + } + } + + /* Check if KEEPALIVE should be sent */ + if (ip_get_option(pcb, SOF_KEEPALIVE) && + ((pcb->state == ESTABLISHED) || + (pcb->state == CLOSE_WAIT))) { + if ((u32_t)(tcp_ticks - pcb->tmr) > + (pcb->keep_idle + TCP_KEEP_DUR(pcb)) / TCP_SLOW_INTERVAL) + { + LWIP_DEBUGF(TCP_DEBUG, ("tcp_slowtmr: KEEPALIVE timeout. Aborting connection to ")); + ip_addr_debug_print(TCP_DEBUG, &pcb->remote_ip); + LWIP_DEBUGF(TCP_DEBUG, ("\n")); + + ++pcb_remove; + ++pcb_reset; + } else if ((u32_t)(tcp_ticks - pcb->tmr) > + (pcb->keep_idle + pcb->keep_cnt_sent * TCP_KEEP_INTVL(pcb)) + / TCP_SLOW_INTERVAL) + { + err = tcp_keepalive(pcb); + if (err == ERR_OK) { + pcb->keep_cnt_sent++; + } + } + } + + /* If this PCB has queued out of sequence data, but has been + inactive for too long, will drop the data (it will eventually + be retransmitted). */ +#if TCP_QUEUE_OOSEQ + if (pcb->ooseq != NULL && + (u32_t)tcp_ticks - pcb->tmr >= pcb->rto * TCP_OOSEQ_TIMEOUT) { + tcp_segs_free(pcb->ooseq); + pcb->ooseq = NULL; + LWIP_DEBUGF(TCP_CWND_DEBUG, ("tcp_slowtmr: dropping OOSEQ queued data\n")); + } +#endif /* TCP_QUEUE_OOSEQ */ + + /* Check if this PCB has stayed too long in SYN-RCVD */ + if (pcb->state == SYN_RCVD) { + if ((u32_t)(tcp_ticks - pcb->tmr) > + TCP_SYN_RCVD_TIMEOUT / TCP_SLOW_INTERVAL) { + ++pcb_remove; + LWIP_DEBUGF(TCP_DEBUG, ("tcp_slowtmr: removing pcb stuck in SYN-RCVD\n")); + } + } + + /* Check if this PCB has stayed too long in LAST-ACK */ + if (pcb->state == LAST_ACK) { + if ((u32_t)(tcp_ticks - pcb->tmr) > 2 * TCP_MSL / TCP_SLOW_INTERVAL) { + ++pcb_remove; + LWIP_DEBUGF(TCP_DEBUG, ("tcp_slowtmr: removing pcb stuck in LAST-ACK\n")); + } + } + + /* If the PCB should be removed, do it. */ + if (pcb_remove) { + struct tcp_pcb *pcb2; + tcp_err_fn err_fn; + void *err_arg; + tcp_pcb_purge(pcb); + /* Remove PCB from tcp_active_pcbs list. */ + if (prev != NULL) { + LWIP_ASSERT("tcp_slowtmr: middle tcp != tcp_active_pcbs", pcb != tcp_active_pcbs); + prev->next = pcb->next; + } else { + /* This PCB was the first. */ + LWIP_ASSERT("tcp_slowtmr: first pcb == tcp_active_pcbs", tcp_active_pcbs == pcb); + tcp_active_pcbs = pcb->next; + } + + if (pcb_reset) { + tcp_rst(pcb->snd_nxt, pcb->rcv_nxt, &pcb->local_ip, &pcb->remote_ip, + pcb->local_port, pcb->remote_port); + } + + err_fn = pcb->errf; + err_arg = pcb->callback_arg; + pcb2 = pcb; + pcb = pcb->next; + memp_free(MEMP_TCP_PCB, pcb2); + + tcp_active_pcbs_changed = 0; + TCP_EVENT_ERR(err_fn, err_arg, ERR_ABRT); + if (tcp_active_pcbs_changed) { + goto tcp_slowtmr_start; + } + } else { + /* get the 'next' element now and work with 'prev' below (in case of abort) */ + prev = pcb; + pcb = pcb->next; + + /* We check if we should poll the connection. */ + ++prev->polltmr; + if (prev->polltmr >= prev->pollinterval) { + prev->polltmr = 0; + LWIP_DEBUGF(TCP_DEBUG, ("tcp_slowtmr: polling application\n")); + tcp_active_pcbs_changed = 0; + TCP_EVENT_POLL(prev, err); + if (tcp_active_pcbs_changed) { + goto tcp_slowtmr_start; + } + /* if err == ERR_ABRT, 'prev' is already deallocated */ + if (err == ERR_OK) { + tcp_output(prev); + } + } + } + } + + + /* Steps through all of the TIME-WAIT PCBs. */ + prev = NULL; + pcb = tcp_tw_pcbs; + while (pcb != NULL) { + LWIP_ASSERT("tcp_slowtmr: TIME-WAIT pcb->state == TIME-WAIT", pcb->state == TIME_WAIT); + pcb_remove = 0; + + /* Check if this PCB has stayed long enough in TIME-WAIT */ + if ((u32_t)(tcp_ticks - pcb->tmr) > 2 * TCP_MSL / TCP_SLOW_INTERVAL) { + ++pcb_remove; + } + + /* If the PCB should be removed, do it. */ + if (pcb_remove) { + struct tcp_pcb *pcb2; + tcp_pcb_purge(pcb); + /* Remove PCB from tcp_tw_pcbs list. */ + if (prev != NULL) { + LWIP_ASSERT("tcp_slowtmr: middle tcp != tcp_tw_pcbs", pcb != tcp_tw_pcbs); + prev->next = pcb->next; + } else { + /* This PCB was the first. */ + LWIP_ASSERT("tcp_slowtmr: first pcb == tcp_tw_pcbs", tcp_tw_pcbs == pcb); + tcp_tw_pcbs = pcb->next; + } + pcb2 = pcb; + pcb = pcb->next; + memp_free(MEMP_TCP_PCB, pcb2); + } else { + prev = pcb; + pcb = pcb->next; + } + } +} + +/** + * Is called every TCP_FAST_INTERVAL (250 ms) and process data previously + * "refused" by upper layer (application) and sends delayed ACKs. + * + * Automatically called from tcp_tmr(). + */ +void +tcp_fasttmr(void) +{ + struct tcp_pcb *pcb; + + ++tcp_timer_ctr; + +tcp_fasttmr_start: + pcb = tcp_active_pcbs; + + while (pcb != NULL) { + if (pcb->last_timer != tcp_timer_ctr) { + struct tcp_pcb *next; + pcb->last_timer = tcp_timer_ctr; + /* send delayed ACKs */ + if (pcb->flags & TF_ACK_DELAY) { + LWIP_DEBUGF(TCP_DEBUG, ("tcp_fasttmr: delayed ACK\n")); + tcp_ack_now(pcb); + tcp_output(pcb); + pcb->flags &= ~(TF_ACK_DELAY | TF_ACK_NOW); + } + + next = pcb->next; + + /* If there is data which was previously "refused" by upper layer */ + if (pcb->refused_data != NULL) { + tcp_active_pcbs_changed = 0; + tcp_process_refused_data(pcb); + if (tcp_active_pcbs_changed) { + /* application callback has changed the pcb list: restart the loop */ + goto tcp_fasttmr_start; + } + } + pcb = next; + } else { + pcb = pcb->next; + } + } +} + +/** Call tcp_output for all active pcbs that have TF_NAGLEMEMERR set */ +void +tcp_txnow(void) +{ + struct tcp_pcb *pcb; + + for (pcb = tcp_active_pcbs; pcb != NULL; pcb = pcb->next) { + if (pcb->flags & TF_NAGLEMEMERR) { + tcp_output(pcb); + } + } +} + +/** Pass pcb->refused_data to the recv callback */ +err_t +tcp_process_refused_data(struct tcp_pcb *pcb) +{ +#if TCP_QUEUE_OOSEQ && LWIP_WND_SCALE + struct pbuf *rest; + while (pcb->refused_data != NULL) +#endif /* TCP_QUEUE_OOSEQ && LWIP_WND_SCALE */ + { + err_t err; + u8_t refused_flags = pcb->refused_data->flags; + /* set pcb->refused_data to NULL in case the callback frees it and then + closes the pcb */ + struct pbuf *refused_data = pcb->refused_data; +#if TCP_QUEUE_OOSEQ && LWIP_WND_SCALE + pbuf_split_64k(refused_data, &rest); + pcb->refused_data = rest; +#else /* TCP_QUEUE_OOSEQ && LWIP_WND_SCALE */ + pcb->refused_data = NULL; +#endif /* TCP_QUEUE_OOSEQ && LWIP_WND_SCALE */ + /* Notify again application with data previously received. */ + LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_input: notify kept packet\n")); + TCP_EVENT_RECV(pcb, refused_data, ERR_OK, err); + if (err == ERR_OK) { + /* did refused_data include a FIN? */ + if (refused_flags & PBUF_FLAG_TCP_FIN +#if TCP_QUEUE_OOSEQ && LWIP_WND_SCALE + && (rest == NULL) +#endif /* TCP_QUEUE_OOSEQ && LWIP_WND_SCALE */ + ) { + /* correct rcv_wnd as the application won't call tcp_recved() + for the FIN's seqno */ + if (pcb->rcv_wnd != TCP_WND_MAX(pcb)) { + pcb->rcv_wnd++; + } + TCP_EVENT_CLOSED(pcb, err); + if (err == ERR_ABRT) { + return ERR_ABRT; + } + } + } else if (err == ERR_ABRT) { + /* if err == ERR_ABRT, 'pcb' is already deallocated */ + /* Drop incoming packets because pcb is "full" (only if the incoming + segment contains data). */ + LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_input: drop incoming packets, because pcb is \"full\"\n")); + return ERR_ABRT; + } else { + /* data is still refused, pbuf is still valid (go on for ACK-only packets) */ +#if TCP_QUEUE_OOSEQ && LWIP_WND_SCALE + if (rest != NULL) { + pbuf_cat(refused_data, rest); + } +#endif /* TCP_QUEUE_OOSEQ && LWIP_WND_SCALE */ + pcb->refused_data = refused_data; + return ERR_INPROGRESS; + } + } + return ERR_OK; +} + +/** + * Deallocates a list of TCP segments (tcp_seg structures). + * + * @param seg tcp_seg list of TCP segments to free + */ +void +tcp_segs_free(struct tcp_seg *seg) +{ + while (seg != NULL) { + struct tcp_seg *next = seg->next; + tcp_seg_free(seg); + seg = next; + } +} + +/** + * Frees a TCP segment (tcp_seg structure). + * + * @param seg single tcp_seg to free + */ +void +tcp_seg_free(struct tcp_seg *seg) +{ + if (seg != NULL) { + if (seg->p != NULL) { + pbuf_free(seg->p); +#if TCP_DEBUG + seg->p = NULL; +#endif /* TCP_DEBUG */ + } + memp_free(MEMP_TCP_SEG, seg); + } +} + +/** + * Sets the priority of a connection. + * + * @param pcb the tcp_pcb to manipulate + * @param prio new priority + */ +void +tcp_setprio(struct tcp_pcb *pcb, u8_t prio) +{ + pcb->prio = prio; +} + +#if TCP_QUEUE_OOSEQ +/** + * Returns a copy of the given TCP segment. + * The pbuf and data are not copied, only the pointers + * + * @param seg the old tcp_seg + * @return a copy of seg + */ +struct tcp_seg * +tcp_seg_copy(struct tcp_seg *seg) +{ + struct tcp_seg *cseg; + + cseg = (struct tcp_seg *)memp_malloc(MEMP_TCP_SEG); + if (cseg == NULL) { + return NULL; + } + SMEMCPY((u8_t *)cseg, (const u8_t *)seg, sizeof(struct tcp_seg)); + pbuf_ref(cseg->p); + return cseg; +} +#endif /* TCP_QUEUE_OOSEQ */ + +#if LWIP_CALLBACK_API +/** + * Default receive callback that is called if the user didn't register + * a recv callback for the pcb. + */ +err_t +tcp_recv_null(void *arg, struct tcp_pcb *pcb, struct pbuf *p, err_t err) +{ + LWIP_UNUSED_ARG(arg); + if (p != NULL) { + tcp_recved(pcb, p->tot_len); + pbuf_free(p); + } else if (err == ERR_OK) { + return tcp_close(pcb); + } + return ERR_OK; +} +#endif /* LWIP_CALLBACK_API */ + +/** + * Kills the oldest active connection that has the same or lower priority than + * 'prio'. + * + * @param prio minimum priority + */ +static void +tcp_kill_prio(u8_t prio) +{ + struct tcp_pcb *pcb, *inactive; + u32_t inactivity; + u8_t mprio; + + mprio = LWIP_MIN(TCP_PRIO_MAX, prio); + + /* We kill the oldest active connection that has lower priority than prio. */ + inactivity = 0; + inactive = NULL; + for (pcb = tcp_active_pcbs; pcb != NULL; pcb = pcb->next) { + if (pcb->prio <= mprio && + (u32_t)(tcp_ticks - pcb->tmr) >= inactivity) { + inactivity = tcp_ticks - pcb->tmr; + inactive = pcb; + mprio = pcb->prio; + } + } + if (inactive != NULL) { + LWIP_DEBUGF(TCP_DEBUG, ("tcp_kill_prio: killing oldest PCB %p (%"S32_F")\n", + (void *)inactive, inactivity)); + tcp_abort(inactive); + } +} + +/** + * Kills the oldest connection that is in specific state. + * Called from tcp_alloc() for LAST_ACK and CLOSING if no more connections are available. + */ +static void +tcp_kill_state(enum tcp_state state) +{ + struct tcp_pcb *pcb, *inactive; + u32_t inactivity; + + LWIP_ASSERT("invalid state", (state == CLOSING) || (state == LAST_ACK)); + + inactivity = 0; + inactive = NULL; + /* Go through the list of active pcbs and get the oldest pcb that is in state + CLOSING/LAST_ACK. */ + for (pcb = tcp_active_pcbs; pcb != NULL; pcb = pcb->next) { + if (pcb->state == state) { + if ((u32_t)(tcp_ticks - pcb->tmr) >= inactivity) { + inactivity = tcp_ticks - pcb->tmr; + inactive = pcb; + } + } + } + if (inactive != NULL) { + LWIP_DEBUGF(TCP_DEBUG, ("tcp_kill_closing: killing oldest %s PCB %p (%"S32_F")\n", + tcp_state_str[state], (void *)inactive, inactivity)); + /* Don't send a RST, since no data is lost. */ + tcp_abandon(inactive, 0); + } +} + +/** + * Kills the oldest connection that is in TIME_WAIT state. + * Called from tcp_alloc() if no more connections are available. + */ +static void +tcp_kill_timewait(void) +{ + struct tcp_pcb *pcb, *inactive; + u32_t inactivity; + + inactivity = 0; + inactive = NULL; + /* Go through the list of TIME_WAIT pcbs and get the oldest pcb. */ + for (pcb = tcp_tw_pcbs; pcb != NULL; pcb = pcb->next) { + if ((u32_t)(tcp_ticks - pcb->tmr) >= inactivity) { + inactivity = tcp_ticks - pcb->tmr; + inactive = pcb; + } + } + if (inactive != NULL) { + LWIP_DEBUGF(TCP_DEBUG, ("tcp_kill_timewait: killing oldest TIME-WAIT PCB %p (%"S32_F")\n", + (void *)inactive, inactivity)); + tcp_abort(inactive); + } +} + +#ifdef LWIP_ESP8266 +/** + * Kills the oldest connection that is in FIN_WAIT_2 state. + * Called from tcp_alloc() if no more connections are available. + */ +static void tcp_kill_finwait2(void) +{ + struct tcp_pcb *pcb, *inactive; + u32_t inactivity; + /* Go through the list of FIN_WAIT_2 pcbs and get the oldest pcb. */ + inactivity = 0; + inactive = NULL; + for (pcb = tcp_active_pcbs; pcb != NULL; pcb = pcb->next) { + if (pcb->state == FIN_WAIT_2) { + if ((u32_t) (tcp_ticks - pcb->tmr) >= inactivity) { + inactivity = tcp_ticks - pcb->tmr; + inactive = pcb; + } + } + } + if (inactive != NULL) { + tcp_pcb_remove(&tcp_active_pcbs, inactive); + memp_free(MEMP_TCP_PCB, inactive); + } +} + +/** + * Kills the oldest connection that is in LAST_ACK state. + * Called from tcp_alloc() if no more connections are available. + */ +static void tcp_kill_lastack(void) +{ + struct tcp_pcb *pcb, *inactive; + u32_t inactivity; + /* Go through the list of LAST_ACK pcbs and get the oldest pcb. */ + inactivity = 0; + inactive = NULL; + for (pcb = tcp_active_pcbs; pcb != NULL; pcb = pcb->next) { + if (pcb->state == LAST_ACK) { + if ((u32_t) (tcp_ticks - pcb->tmr) >= inactivity) { + inactivity = tcp_ticks - pcb->tmr; + inactive = pcb; + } + } + } + if (inactive != NULL) { + tcp_pcb_remove(&tcp_active_pcbs, inactive); + memp_free(MEMP_TCP_PCB, inactive); + } +} +#endif + + + +/** + * Allocate a new tcp_pcb structure. + * + * @param prio priority for the new pcb + * @return a new tcp_pcb that initially is in state CLOSED + */ +struct tcp_pcb * +tcp_alloc(u8_t prio) +{ + struct tcp_pcb *pcb; + u32_t iss; + +#ifdef LWIP_ESP8266 + /*Kills the oldest connection that is in TIME_WAIT state.*/ + u8_t time_wait_num = 0; + for(pcb = tcp_tw_pcbs; pcb != NULL; pcb = pcb->next) { + time_wait_num ++; + } + + if (time_wait_num >= MEMP_NUM_TCP_PCB) + tcp_kill_timewait(); + + /*Kills the oldest connection that is in FIN_WAIT_2 state.*/ + time_wait_num = 0; + for (pcb = tcp_active_pcbs; pcb != NULL; pcb = pcb->next){ + if (pcb->state == FIN_WAIT_2) + time_wait_num ++; + } + + if (time_wait_num >= MEMP_NUM_TCP_PCB) + tcp_kill_finwait2(); + + /*Kills the oldest connection that is in LAST_ACK state.*/ + time_wait_num = 0; + for (pcb = tcp_active_pcbs; pcb != NULL; pcb = pcb->next){ + if (pcb->state == LAST_ACK) + time_wait_num ++; + } + + if (time_wait_num >= MEMP_NUM_TCP_PCB) + tcp_kill_lastack(); +#endif + + pcb = (struct tcp_pcb *)memp_malloc(MEMP_TCP_PCB); + if (pcb == NULL) { + /* Try killing oldest connection in TIME-WAIT. */ + LWIP_DEBUGF(TCP_DEBUG, ("tcp_alloc: killing off oldest TIME-WAIT connection\n")); + tcp_kill_timewait(); + /* Try to allocate a tcp_pcb again. */ + pcb = (struct tcp_pcb *)memp_malloc(MEMP_TCP_PCB); + if (pcb == NULL) { + /* Try killing oldest connection in LAST-ACK (these wouldn't go to TIME-WAIT). */ + LWIP_DEBUGF(TCP_DEBUG, ("tcp_alloc: killing off oldest LAST-ACK connection\n")); + tcp_kill_state(LAST_ACK); + /* Try to allocate a tcp_pcb again. */ + pcb = (struct tcp_pcb *)memp_malloc(MEMP_TCP_PCB); + if (pcb == NULL) { + /* Try killing oldest connection in CLOSING. */ + LWIP_DEBUGF(TCP_DEBUG, ("tcp_alloc: killing off oldest CLOSING connection\n")); + tcp_kill_state(CLOSING); + /* Try to allocate a tcp_pcb again. */ + pcb = (struct tcp_pcb *)memp_malloc(MEMP_TCP_PCB); + if (pcb == NULL) { + /* Try killing active connections with lower priority than the new one. */ + LWIP_DEBUGF(TCP_DEBUG, ("tcp_alloc: killing connection with prio lower than %d\n", prio)); + tcp_kill_prio(prio); + /* Try to allocate a tcp_pcb again. */ + pcb = (struct tcp_pcb *)memp_malloc(MEMP_TCP_PCB); + if (pcb != NULL) { + /* adjust err stats: memp_malloc failed multiple times before */ + MEMP_STATS_DEC(err, MEMP_TCP_PCB); + } + } + if (pcb != NULL) { + /* adjust err stats: memp_malloc failed multiple times before */ + MEMP_STATS_DEC(err, MEMP_TCP_PCB); + } + } + if (pcb != NULL) { + /* adjust err stats: memp_malloc failed multiple times before */ + MEMP_STATS_DEC(err, MEMP_TCP_PCB); + } + } + if (pcb != NULL) { + /* adjust err stats: memp_malloc failed above */ + MEMP_STATS_DEC(err, MEMP_TCP_PCB); + } + } + if (pcb != NULL) { + memset(pcb, 0, sizeof(struct tcp_pcb)); + pcb->prio = prio; + pcb->snd_buf = TCP_SND_BUF; + pcb->snd_queuelen = 0; + /* Start with a window that does not need scaling. When window scaling is + enabled and used, the window is enlarged when both sides agree on scaling. */ + pcb->rcv_wnd = pcb->rcv_ann_wnd = TCPWND_MIN16(TCP_WND); +#if LWIP_WND_SCALE + /* snd_scale and rcv_scale are zero unless both sides agree to use scaling */ + pcb->snd_scale = 0; + pcb->rcv_scale = 0; +#endif + pcb->tos = 0; + pcb->ttl = TCP_TTL; + /* As initial send MSS, we use TCP_MSS but limit it to 536. + The send MSS is updated when an MSS option is received. */ + pcb->mss = (TCP_MSS > 536) ? 536 : TCP_MSS; + pcb->rto = 3000 / TCP_SLOW_INTERVAL; + pcb->sa = 0; + pcb->sv = 3000 / TCP_SLOW_INTERVAL; + pcb->rtime = -1; + pcb->cwnd = 1; + iss = tcp_next_iss(); + pcb->snd_wl2 = iss; + pcb->snd_nxt = iss; + pcb->lastack = iss; + pcb->snd_lbb = iss; + pcb->tmr = tcp_ticks; + pcb->last_timer = tcp_timer_ctr; + + pcb->polltmr = 0; + +#if LWIP_CALLBACK_API + pcb->recv = tcp_recv_null; +#endif /* LWIP_CALLBACK_API */ + + /* Init KEEPALIVE timer */ + pcb->keep_idle = TCP_KEEPIDLE_DEFAULT; + +#if LWIP_TCP_KEEPALIVE + pcb->keep_intvl = TCP_KEEPINTVL_DEFAULT; + pcb->keep_cnt = TCP_KEEPCNT_DEFAULT; +#endif /* LWIP_TCP_KEEPALIVE */ + + pcb->keep_cnt_sent = 0; + } + return pcb; +} + +/** + * Creates a new TCP protocol control block but doesn't place it on + * any of the TCP PCB lists. + * The pcb is not put on any list until binding using tcp_bind(). + * + * @internal: Maybe there should be a idle TCP PCB list where these + * PCBs are put on. Port reservation using tcp_bind() is implemented but + * allocated pcbs that are not bound can't be killed automatically if wanting + * to allocate a pcb with higher prio (@see tcp_kill_prio()) + * + * @return a new tcp_pcb that initially is in state CLOSED + */ +struct tcp_pcb * +tcp_new(void) +{ + return tcp_alloc(TCP_PRIO_NORMAL); +} + +/** + * Creates a new TCP protocol control block but doesn't + * place it on any of the TCP PCB lists. + * The pcb is not put on any list until binding using tcp_bind(). + * + * @param type IP address type, see IPADDR_TYPE_XX definitions. + * @return a new tcp_pcb that initially is in state CLOSED + */ +struct tcp_pcb * +tcp_new_ip_type(u8_t type) +{ + struct tcp_pcb * pcb; + pcb = tcp_alloc(TCP_PRIO_NORMAL); +#if LWIP_IPV4 && LWIP_IPV6 + if(pcb != NULL) { + IP_SET_TYPE_VAL(pcb->local_ip, type); + IP_SET_TYPE_VAL(pcb->remote_ip, type); + } +#else + LWIP_UNUSED_ARG(type); +#endif /* LWIP_IPV4 && LWIP_IPV6 */ + return pcb; +} + +/** + * Used to specify the argument that should be passed callback + * functions. + * + * @param pcb tcp_pcb to set the callback argument + * @param arg void pointer argument to pass to callback functions + */ +void +tcp_arg(struct tcp_pcb *pcb, void *arg) +{ + /* This function is allowed to be called for both listen pcbs and + connection pcbs. */ + pcb->callback_arg = arg; +} +#if LWIP_CALLBACK_API + +/** + * Used to specify the function that should be called when a TCP + * connection receives data. + * + * @param pcb tcp_pcb to set the recv callback + * @param recv callback function to call for this pcb when data is received + */ +void +tcp_recv(struct tcp_pcb *pcb, tcp_recv_fn recv) +{ + LWIP_ASSERT("invalid socket state for recv callback", pcb->state != LISTEN); + pcb->recv = recv; +} + +/** + * Used to specify the function that should be called when TCP data + * has been successfully delivered to the remote host. + * + * @param pcb tcp_pcb to set the sent callback + * @param sent callback function to call for this pcb when data is successfully sent + */ +void +tcp_sent(struct tcp_pcb *pcb, tcp_sent_fn sent) +{ + LWIP_ASSERT("invalid socket state for sent callback", pcb->state != LISTEN); + pcb->sent = sent; +} + +/** + * Used to specify the function that should be called when a fatal error + * has occurred on the connection. + * + * @param pcb tcp_pcb to set the err callback + * @param err callback function to call for this pcb when a fatal error + * has occurred on the connection + */ +void +tcp_err(struct tcp_pcb *pcb, tcp_err_fn err) +{ + LWIP_ASSERT("invalid socket state for err callback", pcb->state != LISTEN); + pcb->errf = err; +} + +/** + * Used for specifying the function that should be called when a + * LISTENing connection has been connected to another host. + * + * @param pcb tcp_pcb to set the accept callback + * @param accept callback function to call for this pcb when LISTENing + * connection has been connected to another host + */ +void +tcp_accept(struct tcp_pcb *pcb, tcp_accept_fn accept) +{ + /* This function is allowed to be called for both listen pcbs and + connection pcbs. */ + pcb->accept = accept; +} +#endif /* LWIP_CALLBACK_API */ + + +/** + * Used to specify the function that should be called periodically + * from TCP. The interval is specified in terms of the TCP coarse + * timer interval, which is called twice a second. + * + */ +void +tcp_poll(struct tcp_pcb *pcb, tcp_poll_fn poll, u8_t interval) +{ + LWIP_ASSERT("invalid socket state for poll", pcb->state != LISTEN); +#if LWIP_CALLBACK_API + pcb->poll = poll; +#else /* LWIP_CALLBACK_API */ + LWIP_UNUSED_ARG(poll); +#endif /* LWIP_CALLBACK_API */ + pcb->pollinterval = interval; +} + +/** + * Purges a TCP PCB. Removes any buffered data and frees the buffer memory + * (pcb->ooseq, pcb->unsent and pcb->unacked are freed). + * + * @param pcb tcp_pcb to purge. The pcb itself is not deallocated! + */ +void +tcp_pcb_purge(struct tcp_pcb *pcb) +{ + if (pcb->state != CLOSED && + pcb->state != TIME_WAIT && + pcb->state != LISTEN) { + + LWIP_DEBUGF(TCP_DEBUG, ("tcp_pcb_purge\n")); + +#if TCP_LISTEN_BACKLOG + if (pcb->state == SYN_RCVD) { + /* Need to find the corresponding listen_pcb and decrease its accepts_pending */ + struct tcp_pcb_listen *lpcb; + LWIP_ASSERT("tcp_pcb_purge: pcb->state == SYN_RCVD but tcp_listen_pcbs is NULL", + tcp_listen_pcbs.listen_pcbs != NULL); + for (lpcb = tcp_listen_pcbs.listen_pcbs; lpcb != NULL; lpcb = lpcb->next) { + if ((lpcb->local_port == pcb->local_port) && + (IP_IS_V6_VAL(pcb->local_ip) == IP_IS_V6_VAL(lpcb->local_ip)) && + (ip_addr_isany(&lpcb->local_ip) || + ip_addr_cmp(&pcb->local_ip, &lpcb->local_ip))) { + /* port and address of the listen pcb match the timed-out pcb */ + LWIP_ASSERT("tcp_pcb_purge: listen pcb does not have accepts pending", + lpcb->accepts_pending > 0); + lpcb->accepts_pending--; + break; + } + } + } +#endif /* TCP_LISTEN_BACKLOG */ + + + if (pcb->refused_data != NULL) { + LWIP_DEBUGF(TCP_DEBUG, ("tcp_pcb_purge: data left on ->refused_data\n")); + pbuf_free(pcb->refused_data); + pcb->refused_data = NULL; + } + if (pcb->unsent != NULL) { + LWIP_DEBUGF(TCP_DEBUG, ("tcp_pcb_purge: not all data sent\n")); + } + if (pcb->unacked != NULL) { + LWIP_DEBUGF(TCP_DEBUG, ("tcp_pcb_purge: data left on ->unacked\n")); + } +#if TCP_QUEUE_OOSEQ + if (pcb->ooseq != NULL) { + LWIP_DEBUGF(TCP_DEBUG, ("tcp_pcb_purge: data left on ->ooseq\n")); + } + tcp_segs_free(pcb->ooseq); + pcb->ooseq = NULL; +#endif /* TCP_QUEUE_OOSEQ */ + + /* Stop the retransmission timer as it will expect data on unacked + queue if it fires */ + pcb->rtime = -1; + + tcp_segs_free(pcb->unsent); + tcp_segs_free(pcb->unacked); + pcb->unacked = pcb->unsent = NULL; +#if TCP_OVERSIZE + pcb->unsent_oversize = 0; +#endif /* TCP_OVERSIZE */ + } +} + +/** + * Purges the PCB and removes it from a PCB list. Any delayed ACKs are sent first. + * + * @param pcblist PCB list to purge. + * @param pcb tcp_pcb to purge. The pcb itself is NOT deallocated! + */ +void +tcp_pcb_remove(struct tcp_pcb **pcblist, struct tcp_pcb *pcb) +{ + TCP_RMV(pcblist, pcb); + + tcp_pcb_purge(pcb); + + /* if there is an outstanding delayed ACKs, send it */ + if (pcb->state != TIME_WAIT && + pcb->state != LISTEN && + pcb->flags & TF_ACK_DELAY) { + pcb->flags |= TF_ACK_NOW; + tcp_output(pcb); + } + + if (pcb->state != LISTEN) { + LWIP_ASSERT("unsent segments leaking", pcb->unsent == NULL); + LWIP_ASSERT("unacked segments leaking", pcb->unacked == NULL); +#if TCP_QUEUE_OOSEQ + LWIP_ASSERT("ooseq segments leaking", pcb->ooseq == NULL); +#endif /* TCP_QUEUE_OOSEQ */ + } + + pcb->state = CLOSED; + /* reset the local port to prevent the pcb from being 'bound' */ + pcb->local_port = 0; + + LWIP_ASSERT("tcp_pcb_remove: tcp_pcbs_sane()", tcp_pcbs_sane()); +} + +/** + * Calculates a new initial sequence number for new connections. + * + * @return u32_t pseudo random sequence number + */ +u32_t +tcp_next_iss(void) +{ + static u32_t iss = 6510; + + iss += tcp_ticks; /* XXX */ + return iss; +} + +#if TCP_CALCULATE_EFF_SEND_MSS +/** + * Calculates the effective send mss that can be used for a specific IP address + * by using ip_route to determine the netif used to send to the address and + * calculating the minimum of TCP_MSS and that netif's mtu (if set). + */ +u16_t +tcp_eff_send_mss_impl(u16_t sendmss, const ip_addr_t *dest +#if LWIP_IPV6 || LWIP_IPV4_SRC_ROUTING + , const ip_addr_t *src +#endif /* LWIP_IPV6 || LWIP_IPV4_SRC_ROUTING */ + ) +{ + u16_t mss_s; + struct netif *outif; + s16_t mtu; + + outif = ip_route(src, dest); +#if LWIP_IPV6 +#if LWIP_IPV4 + if (IP_IS_V6(dest)) +#endif /* LWIP_IPV4 */ + { + /* First look in destination cache, to see if there is a Path MTU. */ + mtu = nd6_get_destination_mtu(ip_2_ip6(dest), outif); + } +#if LWIP_IPV4 + else +#endif /* LWIP_IPV4 */ +#endif /* LWIP_IPV6 */ +#if LWIP_IPV4 + { + if (outif == NULL) { + return sendmss; + } + mtu = outif->mtu; + } +#endif /* LWIP_IPV4 */ + + if (mtu != 0) { +#if LWIP_IPV6 +#if LWIP_IPV4 + if (IP_IS_V6(dest)) +#endif /* LWIP_IPV4 */ + { + mss_s = mtu - IP6_HLEN - TCP_HLEN; + } +#if LWIP_IPV4 + else +#endif /* LWIP_IPV4 */ +#endif /* LWIP_IPV6 */ +#if LWIP_IPV4 + { + mss_s = mtu - IP_HLEN - TCP_HLEN; + } +#endif /* LWIP_IPV4 */ + /* RFC 1122, chap 4.2.2.6: + * Eff.snd.MSS = min(SendMSS+20, MMS_S) - TCPhdrsize - IPoptionsize + * We correct for TCP options in tcp_write(), and don't support IP options. + */ + sendmss = LWIP_MIN(sendmss, mss_s); + } + return sendmss; +} +#endif /* TCP_CALCULATE_EFF_SEND_MSS */ + +#if LWIP_IPV4 +/** Helper function for tcp_netif_ipv4_addr_changed() that iterates a pcb list */ +static void +tcp_netif_ipv4_addr_changed_pcblist(const ip4_addr_t* old_addr, struct tcp_pcb* pcb_list) +{ + struct tcp_pcb *pcb; + pcb = pcb_list; + while (pcb != NULL) { + /* PCB bound to current local interface address? */ + if (!IP_IS_V6_VAL(pcb->local_ip) && ip4_addr_cmp(ip_2_ip4(&pcb->local_ip), old_addr) +#if LWIP_AUTOIP + /* connections to link-local addresses must persist (RFC3927 ch. 1.9) */ + && !ip4_addr_islinklocal(ip_2_ip4(&pcb->local_ip)) +#endif /* LWIP_AUTOIP */ + ) { + /* this connection must be aborted */ + struct tcp_pcb *next = pcb->next; + LWIP_DEBUGF(NETIF_DEBUG | LWIP_DBG_STATE, ("netif_set_ipaddr: aborting TCP pcb %p\n", (void *)pcb)); + tcp_abort(pcb); + pcb = next; + } else { + pcb = pcb->next; + } + } +} + +/** This function is called from netif.c when address is changed or netif is removed + * + * @param old_addr IPv4 address of the netif before change + * @param new_addr IPv4 address of the netif after change or NULL if netif has been removed + */ +void tcp_netif_ipv4_addr_changed(const ip4_addr_t* old_addr, const ip4_addr_t* new_addr) +{ + struct tcp_pcb_listen *lpcb, *next; + + tcp_netif_ipv4_addr_changed_pcblist(old_addr, tcp_active_pcbs); + tcp_netif_ipv4_addr_changed_pcblist(old_addr, tcp_bound_pcbs); + + if (!ip4_addr_isany(new_addr)) { + /* PCB bound to current local interface address? */ + for (lpcb = tcp_listen_pcbs.listen_pcbs; lpcb != NULL; lpcb = next) { + next = lpcb->next; + /* Is this an IPv4 pcb? */ + if (!IP_IS_V6_VAL(lpcb->local_ip)) { + /* PCB bound to current local interface address? */ + if ((!(ip4_addr_isany(ip_2_ip4(&lpcb->local_ip)))) && + (ip4_addr_cmp(ip_2_ip4(&lpcb->local_ip), old_addr))) { + /* The PCB is listening to the old ipaddr and + * is set to listen to the new one instead */ + ip_addr_copy_from_ip4(lpcb->local_ip, *new_addr); + } + } + } + } +} +#endif /* LWIP_IPV4 */ + +const char* +tcp_debug_state_str(enum tcp_state s) +{ +#ifdef LWIP_ESP8266 +//TO_DO + //system_get_string_from_flash(tcp_state_str_rodata[s], tcp_state_str, 12); + //return tcp_state_str; + return tcp_state_str[s]; +#else + return tcp_state_str[s]; +#endif +} + +#if TCP_DEBUG || TCP_INPUT_DEBUG || TCP_OUTPUT_DEBUG +/** + * Print a tcp header for debugging purposes. + * + * @param tcphdr pointer to a struct tcp_hdr + */ +void +tcp_debug_print(struct tcp_hdr *tcphdr) +{ + LWIP_DEBUGF(TCP_DEBUG, ("TCP header:\n")); + LWIP_DEBUGF(TCP_DEBUG, ("+-------------------------------+\n")); + LWIP_DEBUGF(TCP_DEBUG, ("| %5"U16_F" | %5"U16_F" | (src port, dest port)\n", + ntohs(tcphdr->src), ntohs(tcphdr->dest))); + LWIP_DEBUGF(TCP_DEBUG, ("+-------------------------------+\n")); + LWIP_DEBUGF(TCP_DEBUG, ("| %010"U32_F" | (seq no)\n", + ntohl(tcphdr->seqno))); + LWIP_DEBUGF(TCP_DEBUG, ("+-------------------------------+\n")); + LWIP_DEBUGF(TCP_DEBUG, ("| %010"U32_F" | (ack no)\n", + ntohl(tcphdr->ackno))); + LWIP_DEBUGF(TCP_DEBUG, ("+-------------------------------+\n")); + LWIP_DEBUGF(TCP_DEBUG, ("| %2"U16_F" | |%"U16_F"%"U16_F"%"U16_F"%"U16_F"%"U16_F"%"U16_F"| %5"U16_F" | (hdrlen, flags (", + TCPH_HDRLEN(tcphdr), + TCPH_FLAGS(tcphdr) >> 5 & 1, + TCPH_FLAGS(tcphdr) >> 4 & 1, + TCPH_FLAGS(tcphdr) >> 3 & 1, + TCPH_FLAGS(tcphdr) >> 2 & 1, + TCPH_FLAGS(tcphdr) >> 1 & 1, + TCPH_FLAGS(tcphdr) & 1, + ntohs(tcphdr->wnd))); + tcp_debug_print_flags(TCPH_FLAGS(tcphdr)); + LWIP_DEBUGF(TCP_DEBUG, ("), win)\n")); + LWIP_DEBUGF(TCP_DEBUG, ("+-------------------------------+\n")); + LWIP_DEBUGF(TCP_DEBUG, ("| 0x%04"X16_F" | %5"U16_F" | (chksum, urgp)\n", + ntohs(tcphdr->chksum), ntohs(tcphdr->urgp))); + LWIP_DEBUGF(TCP_DEBUG, ("+-------------------------------+\n")); +} + +/** + * Print a tcp state for debugging purposes. + * + * @param s enum tcp_state to print + */ +void +tcp_debug_print_state(enum tcp_state s) +{ + LWIP_DEBUGF(TCP_DEBUG, ("State: %s\n", tcp_state_str[s])); +} + +/** + * Print tcp flags for debugging purposes. + * + * @param flags tcp flags, all active flags are printed + */ +void +tcp_debug_print_flags(u8_t flags) +{ + if (flags & TCP_FIN) { + LWIP_DEBUGF(TCP_DEBUG, ("FIN ")); + } + if (flags & TCP_SYN) { + LWIP_DEBUGF(TCP_DEBUG, ("SYN ")); + } + if (flags & TCP_RST) { + LWIP_DEBUGF(TCP_DEBUG, ("RST ")); + } + if (flags & TCP_PSH) { + LWIP_DEBUGF(TCP_DEBUG, ("PSH ")); + } + if (flags & TCP_ACK) { + LWIP_DEBUGF(TCP_DEBUG, ("ACK ")); + } + if (flags & TCP_URG) { + LWIP_DEBUGF(TCP_DEBUG, ("URG ")); + } + if (flags & TCP_ECE) { + LWIP_DEBUGF(TCP_DEBUG, ("ECE ")); + } + if (flags & TCP_CWR) { + LWIP_DEBUGF(TCP_DEBUG, ("CWR ")); + } + LWIP_DEBUGF(TCP_DEBUG, ("\n")); +} + +/** + * Print all tcp_pcbs in every list for debugging purposes. + */ +void +tcp_debug_print_pcbs(void) +{ + struct tcp_pcb *pcb; + LWIP_DEBUGF(TCP_DEBUG, ("Active PCB states:\n")); + for (pcb = tcp_active_pcbs; pcb != NULL; pcb = pcb->next) { + LWIP_DEBUGF(TCP_DEBUG, ("Local port %"U16_F", foreign port %"U16_F" snd_nxt %"U32_F" rcv_nxt %"U32_F" ", + pcb->local_port, pcb->remote_port, + pcb->snd_nxt, pcb->rcv_nxt)); + tcp_debug_print_state(pcb->state); + } + LWIP_DEBUGF(TCP_DEBUG, ("Listen PCB states:\n")); + for (pcb = (struct tcp_pcb *)tcp_listen_pcbs.pcbs; pcb != NULL; pcb = pcb->next) { + LWIP_DEBUGF(TCP_DEBUG, ("Local port %"U16_F", foreign port %"U16_F" snd_nxt %"U32_F" rcv_nxt %"U32_F" ", + pcb->local_port, pcb->remote_port, + pcb->snd_nxt, pcb->rcv_nxt)); + tcp_debug_print_state(pcb->state); + } + LWIP_DEBUGF(TCP_DEBUG, ("TIME-WAIT PCB states:\n")); + for (pcb = tcp_tw_pcbs; pcb != NULL; pcb = pcb->next) { + LWIP_DEBUGF(TCP_DEBUG, ("Local port %"U16_F", foreign port %"U16_F" snd_nxt %"U32_F" rcv_nxt %"U32_F" ", + pcb->local_port, pcb->remote_port, + pcb->snd_nxt, pcb->rcv_nxt)); + tcp_debug_print_state(pcb->state); + } +} + +/** + * Check state consistency of the tcp_pcb lists. + */ +s16_t +tcp_pcbs_sane(void) +{ + struct tcp_pcb *pcb; + for (pcb = tcp_active_pcbs; pcb != NULL; pcb = pcb->next) { + LWIP_ASSERT("tcp_pcbs_sane: active pcb->state != CLOSED", pcb->state != CLOSED); + LWIP_ASSERT("tcp_pcbs_sane: active pcb->state != LISTEN", pcb->state != LISTEN); + LWIP_ASSERT("tcp_pcbs_sane: active pcb->state != TIME-WAIT", pcb->state != TIME_WAIT); + } + for (pcb = tcp_tw_pcbs; pcb != NULL; pcb = pcb->next) { + LWIP_ASSERT("tcp_pcbs_sane: tw pcb->state == TIME-WAIT", pcb->state == TIME_WAIT); + } + return 1; +} +#endif /* TCP_DEBUG */ + +#endif /* LWIP_TCP */ diff --git a/components/lwip/core/tcp_in.c b/components/lwip/core/tcp_in.c new file mode 100755 index 0000000000..25d7403851 --- /dev/null +++ b/components/lwip/core/tcp_in.c @@ -0,0 +1,1802 @@ +/** + * @file + * Transmission Control Protocol, incoming traffic + * + * The input processing functions of the TCP layer. + * + * These functions are generally called in the order (ip_input() ->) + * tcp_input() -> * tcp_process() -> tcp_receive() (-> application). + * + */ + +/* + * Copyright (c) 2001-2004 Swedish Institute of Computer Science. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + * + */ + +#include "lwip/opt.h" + +#if LWIP_TCP /* don't build if not configured for use in lwipopts.h */ + +#include "lwip/priv/tcp_priv.h" +#include "lwip/def.h" +#include "lwip/ip_addr.h" +#include "lwip/netif.h" +#include "lwip/mem.h" +#include "lwip/memp.h" +#include "lwip/inet_chksum.h" +#include "lwip/stats.h" +#include "lwip/ip6.h" +#include "lwip/ip6_addr.h" +#include "lwip/inet_chksum.h" +#if LWIP_ND6_TCP_REACHABILITY_HINTS +#include "lwip/nd6.h" +#endif /* LWIP_ND6_TCP_REACHABILITY_HINTS */ + +#ifdef MEMLEAK_DEBUG +static const char mem_debug_file[] ICACHE_RODATA_ATTR STORE_ATTR = __FILE__; +#endif + + +/** Initial CWND calculation as defined RFC 2581 */ +#define LWIP_TCP_CALC_INITIAL_CWND(mss) LWIP_MIN((4U * (mss)), LWIP_MAX((2U * (mss)), 4380U)); +/** Initial slow start threshold value: we use the full window */ +#define LWIP_TCP_INITIAL_SSTHRESH(pcb) ((pcb)->snd_wnd) + +/* These variables are global to all functions involved in the input + processing of TCP segments. They are set by the tcp_input() + function. */ +static struct tcp_seg inseg; +static struct tcp_hdr *tcphdr; +static u16_t tcphdr_optlen; +static u16_t tcphdr_opt1len; +static u8_t* tcphdr_opt2; +static u16_t tcp_optidx; +static u32_t seqno, ackno; +static u8_t flags; +static u16_t tcplen; + +static u8_t recv_flags; +static struct pbuf *recv_data; + +struct tcp_pcb *tcp_input_pcb; + +/* Forward declarations. */ +static err_t tcp_process(struct tcp_pcb *pcb); +static void tcp_receive(struct tcp_pcb *pcb); +static void tcp_parseopt(struct tcp_pcb *pcb); + +static err_t tcp_listen_input(struct tcp_pcb_listen *pcb); +static err_t tcp_timewait_input(struct tcp_pcb *pcb); + +/** + * The initial input processing of TCP. It verifies the TCP header, demultiplexes + * the segment between the PCBs and passes it on to tcp_process(), which implements + * the TCP finite state machine. This function is called by the IP layer (in + * ip_input()). + * + * @param p received TCP segment to process (p->payload pointing to the TCP header) + * @param inp network interface on which this segment was received + */ +void +tcp_input(struct pbuf *p, struct netif *inp) +{ + struct tcp_pcb *pcb, *prev; + struct tcp_pcb_listen *lpcb; +#if SO_REUSE + struct tcp_pcb *lpcb_prev = NULL; + struct tcp_pcb_listen *lpcb_any = NULL; +#endif /* SO_REUSE */ + u8_t hdrlen; + err_t err; + + LWIP_UNUSED_ARG(inp); + + PERF_START; + + TCP_STATS_INC(tcp.recv); + MIB2_STATS_INC(mib2.tcpinsegs); + + tcphdr = (struct tcp_hdr *)p->payload; + +#if TCP_INPUT_DEBUG + tcp_debug_print(tcphdr); +#endif + + /* Check that TCP header fits in payload */ + if (p->len < sizeof(struct tcp_hdr)) { + /* drop short packets */ + LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_input: short packet (%"U16_F" bytes) discarded\n", p->tot_len)); + TCP_STATS_INC(tcp.lenerr); + goto dropped; + } + + /* Don't even process incoming broadcasts/multicasts. */ + if (ip_addr_isbroadcast(ip_current_dest_addr(), ip_current_netif()) || + ip_addr_ismulticast(ip_current_dest_addr())) { + TCP_STATS_INC(tcp.proterr); + goto dropped; + } + +#if CHECKSUM_CHECK_TCP + IF__NETIF_CHECKSUM_ENABLED(inp, NETIF_CHECKSUM_CHECK_TCP) { + /* Verify TCP checksum. */ + u16_t chksum = ip_chksum_pseudo(p, IP_PROTO_TCP, p->tot_len, + ip_current_src_addr(), ip_current_dest_addr()); + if (chksum != 0) { + LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_input: packet discarded due to failing checksum 0x%04"X16_F"\n", + chksum)); + tcp_debug_print(tcphdr); + TCP_STATS_INC(tcp.chkerr); + goto dropped; + } + } +#endif /* CHECKSUM_CHECK_TCP */ + + /* Move the payload pointer in the pbuf so that it points to the + TCP data instead of the TCP header. */ + hdrlen = TCPH_HDRLEN(tcphdr); + tcphdr_optlen = tcphdr_opt1len = (hdrlen * 4) - TCP_HLEN; + tcphdr_opt2 = NULL; + if (p->len < hdrlen * 4) { + if (p->len >= TCP_HLEN) { + /* TCP header fits into first pbuf, options don't - data is in the next pbuf */ + u16_t optlen = tcphdr_opt1len; + pbuf_header(p, -TCP_HLEN); /* cannot fail */ + LWIP_ASSERT("tcphdr_opt1len >= p->len", tcphdr_opt1len >= p->len); + LWIP_ASSERT("p->next != NULL", p->next != NULL); + tcphdr_opt1len = p->len; + if (optlen > tcphdr_opt1len) { + s16_t opt2len; + /* options continue in the next pbuf: set p to zero length and hide the + options in the next pbuf (adjusting p->tot_len) */ + u8_t phret = pbuf_header(p, -(s16_t)tcphdr_opt1len); + LWIP_ASSERT("phret == 0", phret == 0); + if(tcphdr_optlen - tcphdr_opt1len > p->tot_len) { + /* drop short packets */ + LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_input: short packet (%"U16_F" bytes) discarded\n", p->tot_len)); + TCP_STATS_INC(tcp.lenerr); + goto dropped; + } + tcphdr_opt2 = (u8_t*)p->next->payload; + opt2len = optlen - tcphdr_opt1len; + phret = pbuf_header(p->next, -opt2len); + LWIP_ASSERT("phret == 0", phret == 0); + /* p->next->payload now points to the TCP data */ + /* manually adjust p->tot_len to changed p->next->tot_len change */ + p->tot_len -= opt2len; + } + LWIP_ASSERT("p->len == 0", p->len == 0); + } else { + /* drop short packets */ + LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_input: short packet\n")); + TCP_STATS_INC(tcp.lenerr); + goto dropped; + } + } else { + pbuf_header(p, -(hdrlen * 4)); /* cannot fail */ + } + + /* Convert fields in TCP header to host byte order. */ + tcphdr->src = ntohs(tcphdr->src); + tcphdr->dest = ntohs(tcphdr->dest); + seqno = tcphdr->seqno = ntohl(tcphdr->seqno); + ackno = tcphdr->ackno = ntohl(tcphdr->ackno); + tcphdr->wnd = ntohs(tcphdr->wnd); + + flags = TCPH_FLAGS(tcphdr); + tcplen = p->tot_len + ((flags & (TCP_FIN | TCP_SYN)) ? 1 : 0); + + /* Demultiplex an incoming segment. First, we check if it is destined + for an active connection. */ + prev = NULL; + + for (pcb = tcp_active_pcbs; pcb != NULL; pcb = pcb->next) { + LWIP_ASSERT("tcp_input: active pcb->state != CLOSED", pcb->state != CLOSED); + LWIP_ASSERT("tcp_input: active pcb->state != TIME-WAIT", pcb->state != TIME_WAIT); + LWIP_ASSERT("tcp_input: active pcb->state != LISTEN", pcb->state != LISTEN); + if (pcb->remote_port == tcphdr->src && + pcb->local_port == tcphdr->dest && + ip_addr_cmp(&pcb->remote_ip, ip_current_src_addr()) && + ip_addr_cmp(&pcb->local_ip, ip_current_dest_addr())) { + /* Move this PCB to the front of the list so that subsequent + lookups will be faster (we exploit locality in TCP segment + arrivals). */ + LWIP_ASSERT("tcp_input: pcb->next != pcb (before cache)", pcb->next != pcb); + if (prev != NULL) { + prev->next = pcb->next; + pcb->next = tcp_active_pcbs; + tcp_active_pcbs = pcb; + } else { + TCP_STATS_INC(tcp.cachehit); + } + LWIP_ASSERT("tcp_input: pcb->next != pcb (after cache)", pcb->next != pcb); + break; + } + prev = pcb; + } + + if (pcb == NULL) { + /* If it did not go to an active connection, we check the connections + in the TIME-WAIT state. */ + for (pcb = tcp_tw_pcbs; pcb != NULL; pcb = pcb->next) { + LWIP_ASSERT("tcp_input: TIME-WAIT pcb->state == TIME-WAIT", pcb->state == TIME_WAIT); + if (pcb->remote_port == tcphdr->src && + pcb->local_port == tcphdr->dest && + ip_addr_cmp(&pcb->remote_ip, ip_current_src_addr()) && + ip_addr_cmp(&pcb->local_ip, ip_current_dest_addr())) { + /* We don't really care enough to move this PCB to the front + of the list since we are not very likely to receive that + many segments for connections in TIME-WAIT. */ + LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_input: packed for TIME_WAITing connection.\n")); + tcp_timewait_input(pcb); + pbuf_free(p); + return; + } + } + + /* Finally, if we still did not get a match, we check all PCBs that + are LISTENing for incoming connections. */ + prev = NULL; + for (lpcb = tcp_listen_pcbs.listen_pcbs; lpcb != NULL; lpcb = lpcb->next) { + if (lpcb->local_port == tcphdr->dest) { + if (IP_IS_ANY_TYPE_VAL(lpcb->local_ip)) { + /* found an ANY TYPE (IPv4/IPv6) match */ +#if SO_REUSE + lpcb_any = lpcb; + lpcb_prev = prev; +#else /* SO_REUSE */ + break; +#endif /* SO_REUSE */ + } else if (IP_ADDR_PCB_VERSION_MATCH_EXACT(lpcb, ip_current_dest_addr())) { + if (ip_addr_cmp(&lpcb->local_ip, ip_current_dest_addr())) { + /* found an exact match */ + break; + } else if (ip_addr_isany(&lpcb->local_ip)) { + /* found an ANY-match */ +#if SO_REUSE + lpcb_any = lpcb; + lpcb_prev = prev; +#else /* SO_REUSE */ + break; + #endif /* SO_REUSE */ + } + } + } + prev = (struct tcp_pcb *)lpcb; + } +#if SO_REUSE + /* first try specific local IP */ + if (lpcb == NULL) { + /* only pass to ANY if no specific local IP has been found */ + lpcb = lpcb_any; + prev = lpcb_prev; + } +#endif /* SO_REUSE */ + if (lpcb != NULL) { + /* Move this PCB to the front of the list so that subsequent + lookups will be faster (we exploit locality in TCP segment + arrivals). */ + if (prev != NULL) { + ((struct tcp_pcb_listen *)prev)->next = lpcb->next; + /* our successor is the remainder of the listening list */ + lpcb->next = tcp_listen_pcbs.listen_pcbs; + /* put this listening pcb at the head of the listening list */ + tcp_listen_pcbs.listen_pcbs = lpcb; + } else { + TCP_STATS_INC(tcp.cachehit); + } + + LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_input: packed for LISTENing connection.\n")); + tcp_listen_input(lpcb); + pbuf_free(p); + return; + } + } + +#if TCP_INPUT_DEBUG + LWIP_DEBUGF(TCP_INPUT_DEBUG, ("+-+-+-+-+-+-+-+-+-+-+-+-+-+- tcp_input: flags ")); + tcp_debug_print_flags(TCPH_FLAGS(tcphdr)); + LWIP_DEBUGF(TCP_INPUT_DEBUG, ("-+-+-+-+-+-+-+-+-+-+-+-+-+-+\n")); +#endif /* TCP_INPUT_DEBUG */ + + + if (pcb != NULL) { + +#ifdef LWIP_ESP8266 +//No Need Any more +/* + extern char RxNodeNum(void); + if(RxNodeNum() <= 2) + { +extern void pbuf_free_ooseq(void); + pbuf_free_ooseq(); + } +*/ +#endif + + + /* The incoming segment belongs to a connection. */ +#if TCP_INPUT_DEBUG + tcp_debug_print_state(pcb->state); +#endif /* TCP_INPUT_DEBUG */ + + /* Set up a tcp_seg structure. */ + inseg.next = NULL; + inseg.len = p->tot_len; + inseg.p = p; + inseg.tcphdr = tcphdr; + + recv_data = NULL; + recv_flags = 0; + + if (flags & TCP_PSH) { + p->flags |= PBUF_FLAG_PUSH; + } + + /* If there is data which was previously "refused" by upper layer */ + if (pcb->refused_data != NULL) { + if ((tcp_process_refused_data(pcb) == ERR_ABRT) || + ((pcb->refused_data != NULL) && (tcplen > 0))) { + /* pcb has been aborted or refused data is still refused and the new + segment contains data */ + TCP_STATS_INC(tcp.drop); + MIB2_STATS_INC(mib2.tcpinerrs); + goto aborted; + } + } + tcp_input_pcb = pcb; + err = tcp_process(pcb); + /* A return value of ERR_ABRT means that tcp_abort() was called + and that the pcb has been freed. If so, we don't do anything. */ + if (err != ERR_ABRT) { + if (recv_flags & TF_RESET) { + /* TF_RESET means that the connection was reset by the other + end. We then call the error callback to inform the + application that the connection is dead before we + deallocate the PCB. */ + TCP_EVENT_ERR(pcb->errf, pcb->callback_arg, ERR_RST); + tcp_pcb_remove(&tcp_active_pcbs, pcb); + memp_free(MEMP_TCP_PCB, pcb); + } else { + err = ERR_OK; + /* If the application has registered a "sent" function to be + called when new send buffer space is available, we call it + now. */ + if (pcb->acked > 0) { + u16_t acked; +#if LWIP_WND_SCALE + /* pcb->acked is u32_t but the sent callback only takes a u16_t, + so we might have to call it multiple times. */ + u32_t pcb_acked = pcb->acked; + while (pcb_acked > 0) { + acked = (u16_t)LWIP_MIN(pcb_acked, 0xffffu); + pcb_acked -= acked; +#else + { + acked = pcb->acked; +#endif + TCP_EVENT_SENT(pcb, (u16_t)acked, err); + if (err == ERR_ABRT) { + goto aborted; + } + } + } + if (recv_flags & TF_CLOSED) { + /* The connection has been closed and we will deallocate the + PCB. */ + if (!(pcb->flags & TF_RXCLOSED)) { + /* Connection closed although the application has only shut down the + tx side: call the PCB's err callback and indicate the closure to + ensure the application doesn't continue using the PCB. */ + TCP_EVENT_ERR(pcb->errf, pcb->callback_arg, ERR_CLSD); + } + tcp_pcb_remove(&tcp_active_pcbs, pcb); + memp_free(MEMP_TCP_PCB, pcb); + goto aborted; + } +#if TCP_QUEUE_OOSEQ && LWIP_WND_SCALE + while (recv_data != NULL) { + struct pbuf *rest = NULL; + pbuf_split_64k(recv_data, &rest); +#else /* TCP_QUEUE_OOSEQ && LWIP_WND_SCALE */ + if (recv_data != NULL) { +#endif /* TCP_QUEUE_OOSEQ && LWIP_WND_SCALE */ + + LWIP_ASSERT("pcb->refused_data == NULL", pcb->refused_data == NULL); + if (pcb->flags & TF_RXCLOSED) { + /* received data although already closed -> abort (send RST) to + notify the remote host that not all data has been processed */ + pbuf_free(recv_data); +#if TCP_QUEUE_OOSEQ && LWIP_WND_SCALE + if (rest != NULL) { + pbuf_free(rest); + } +#endif /* TCP_QUEUE_OOSEQ && LWIP_WND_SCALE */ + tcp_abort(pcb); + goto aborted; + } + + /* Notify application that data has been received. */ + TCP_EVENT_RECV(pcb, recv_data, ERR_OK, err); + if (err == ERR_ABRT) { +#if TCP_QUEUE_OOSEQ && LWIP_WND_SCALE + if (rest != NULL) { + pbuf_free(rest); + } +#endif /* TCP_QUEUE_OOSEQ && LWIP_WND_SCALE */ + goto aborted; + } + + /* If the upper layer can't receive this data, store it */ + if (err != ERR_OK) { +#if TCP_QUEUE_OOSEQ && LWIP_WND_SCALE + if (rest != NULL) { + pbuf_cat(recv_data, rest); + } +#endif /* TCP_QUEUE_OOSEQ && LWIP_WND_SCALE */ + pcb->refused_data = recv_data; + LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_input: keep incoming packet, because pcb is \"full\"\n")); +#if TCP_QUEUE_OOSEQ && LWIP_WND_SCALE + break; + } else { + /* Upper layer received the data, go on with the rest if > 64K */ + recv_data = rest; +#endif /* TCP_QUEUE_OOSEQ && LWIP_WND_SCALE */ + } + } + + /* If a FIN segment was received, we call the callback + function with a NULL buffer to indicate EOF. */ + if (recv_flags & TF_GOT_FIN) { + if (pcb->refused_data != NULL) { + /* Delay this if we have refused data. */ + pcb->refused_data->flags |= PBUF_FLAG_TCP_FIN; + } else { + /* correct rcv_wnd as the application won't call tcp_recved() + for the FIN's seqno */ + if (pcb->rcv_wnd != TCP_WND_MAX(pcb)) { + pcb->rcv_wnd++; + } + TCP_EVENT_CLOSED(pcb, err); + if (err == ERR_ABRT) { + goto aborted; + } + } + } + + tcp_input_pcb = NULL; + /* Try to send something out. */ + tcp_output(pcb); +#if TCP_INPUT_DEBUG +#if TCP_DEBUG + tcp_debug_print_state(pcb->state); +#endif /* TCP_DEBUG */ +#endif /* TCP_INPUT_DEBUG */ + } + } + /* Jump target if pcb has been aborted in a callback (by calling tcp_abort()). + Below this line, 'pcb' may not be dereferenced! */ +aborted: + tcp_input_pcb = NULL; + recv_data = NULL; + + /* give up our reference to inseg.p */ + if (inseg.p != NULL) + { + pbuf_free(inseg.p); + inseg.p = NULL; + } + } else { + + /* If no matching PCB was found, send a TCP RST (reset) to the + sender. */ + LWIP_DEBUGF(TCP_RST_DEBUG, ("tcp_input: no PCB match found, resetting.\n")); + if (!(TCPH_FLAGS(tcphdr) & TCP_RST)) { + TCP_STATS_INC(tcp.proterr); + TCP_STATS_INC(tcp.drop); + tcp_rst(ackno, seqno + tcplen, ip_current_dest_addr(), + ip_current_src_addr(), tcphdr->dest, tcphdr->src); + } + pbuf_free(p); + } + + LWIP_ASSERT("tcp_input: tcp_pcbs_sane()", tcp_pcbs_sane()); + PERF_STOP("tcp_input"); + return; +dropped: + TCP_STATS_INC(tcp.drop); + MIB2_STATS_INC(mib2.tcpinerrs); + pbuf_free(p); +} + +/** + * Called by tcp_input() when a segment arrives for a listening + * connection (from tcp_input()). + * + * @param pcb the tcp_pcb_listen for which a segment arrived + * @return ERR_OK if the segment was processed + * another err_t on error + * + * @note the return value is not (yet?) used in tcp_input() + * @note the segment which arrived is saved in global variables, therefore only the pcb + * involved is passed as a parameter to this function + */ +static err_t +tcp_listen_input(struct tcp_pcb_listen *pcb) +{ + struct tcp_pcb *npcb; + err_t rc; + + if (flags & TCP_RST) { + /* An incoming RST should be ignored. Return. */ + return ERR_OK; + } + + /* In the LISTEN state, we check for incoming SYN segments, + creates a new PCB, and responds with a SYN|ACK. */ + if (flags & TCP_ACK) { + /* For incoming segments with the ACK flag set, respond with a + RST. */ + LWIP_DEBUGF(TCP_RST_DEBUG, ("tcp_listen_input: ACK in LISTEN, sending reset\n")); + tcp_rst(ackno, seqno + tcplen, ip_current_dest_addr(), + ip_current_src_addr(), tcphdr->dest, tcphdr->src); + } else if (flags & TCP_SYN) { + LWIP_DEBUGF(TCP_DEBUG, ("TCP connection request %"U16_F" -> %"U16_F".\n", tcphdr->src, tcphdr->dest)); +#if TCP_LISTEN_BACKLOG + if (pcb->accepts_pending >= pcb->backlog) { + LWIP_DEBUGF(TCP_DEBUG, ("tcp_listen_input: listen backlog exceeded for port %"U16_F"\n", tcphdr->dest)); + return ERR_ABRT; + } +#endif /* TCP_LISTEN_BACKLOG */ + npcb = tcp_alloc(pcb->prio); + /* If a new PCB could not be created (probably due to lack of memory), + we don't do anything, but rely on the sender will retransmit the + SYN at a time when we have more memory available. */ + if (npcb == NULL) { + LWIP_DEBUGF(TCP_DEBUG, ("tcp_listen_input: could not allocate PCB\n")); + TCP_STATS_INC(tcp.memerr); + return ERR_MEM; + } +#if TCP_LISTEN_BACKLOG + pcb->accepts_pending++; +#endif /* TCP_LISTEN_BACKLOG */ + /* Set up the new PCB. */ + ip_addr_copy(npcb->local_ip, *ip_current_dest_addr()); + ip_addr_copy(npcb->remote_ip, *ip_current_src_addr()); + npcb->local_port = pcb->local_port; + npcb->remote_port = tcphdr->src; + npcb->state = SYN_RCVD; + npcb->rcv_nxt = seqno + 1; + npcb->rcv_ann_right_edge = npcb->rcv_nxt; + npcb->snd_wl1 = seqno - 1;/* initialise to seqno-1 to force window update */ + npcb->callback_arg = pcb->callback_arg; +#if LWIP_CALLBACK_API + npcb->accept = pcb->accept; +#endif /* LWIP_CALLBACK_API */ + /* inherit socket options */ + npcb->so_options = pcb->so_options & SOF_INHERITED; + /* Register the new PCB so that we can begin receiving segments + for it. */ + TCP_REG_ACTIVE(npcb); + + /* Parse any options in the SYN. */ + tcp_parseopt(npcb); + npcb->snd_wnd = SND_WND_SCALE(npcb, tcphdr->wnd); + npcb->snd_wnd_max = npcb->snd_wnd; + npcb->ssthresh = LWIP_TCP_INITIAL_SSTHRESH(npcb); + +#if TCP_CALCULATE_EFF_SEND_MSS + npcb->mss = tcp_eff_send_mss(npcb->mss, &npcb->local_ip, &npcb->remote_ip); +#endif /* TCP_CALCULATE_EFF_SEND_MSS */ + + MIB2_STATS_INC(mib2.tcppassiveopens); + + /* Send a SYN|ACK together with the MSS option. */ + rc = tcp_enqueue_flags(npcb, TCP_SYN | TCP_ACK); + if (rc != ERR_OK) { + tcp_abandon(npcb, 0); + return rc; + } + return tcp_output(npcb); + } + return ERR_OK; +} + +/** + * Called by tcp_input() when a segment arrives for a connection in + * TIME_WAIT. + * + * @param pcb the tcp_pcb for which a segment arrived + * + * @note the segment which arrived is saved in global variables, therefore only the pcb + * involved is passed as a parameter to this function + */ +static err_t +tcp_timewait_input(struct tcp_pcb *pcb) +{ + /* RFC 1337: in TIME_WAIT, ignore RST and ACK FINs + any 'acceptable' segments */ + /* RFC 793 3.9 Event Processing - Segment Arrives: + * - first check sequence number - we skip that one in TIME_WAIT (always + * acceptable since we only send ACKs) + * - second check the RST bit (... return) */ + if (flags & TCP_RST) { + return ERR_OK; + } + /* - fourth, check the SYN bit, */ + if (flags & TCP_SYN) { + /* If an incoming segment is not acceptable, an acknowledgment + should be sent in reply */ + if (TCP_SEQ_BETWEEN(seqno, pcb->rcv_nxt, pcb->rcv_nxt + pcb->rcv_wnd)) { + /* If the SYN is in the window it is an error, send a reset */ + tcp_rst(ackno, seqno + tcplen, ip_current_dest_addr(), + ip_current_src_addr(), tcphdr->dest, tcphdr->src); + return ERR_OK; + } + } else if (flags & TCP_FIN) { + /* - eighth, check the FIN bit: Remain in the TIME-WAIT state. + Restart the 2 MSL time-wait timeout.*/ + pcb->tmr = tcp_ticks; + } + + if ((tcplen > 0)) { + /* Acknowledge data, FIN or out-of-window SYN */ + pcb->flags |= TF_ACK_NOW; + return tcp_output(pcb); + } + return ERR_OK; +} + +/** + * Implements the TCP state machine. Called by tcp_input. In some + * states tcp_receive() is called to receive data. The tcp_seg + * argument will be freed by the caller (tcp_input()) unless the + * recv_data pointer in the pcb is set. + * + * @param pcb the tcp_pcb for which a segment arrived + * + * @note the segment which arrived is saved in global variables, therefore only the pcb + * involved is passed as a parameter to this function + */ +static err_t +tcp_process(struct tcp_pcb *pcb) +{ + struct tcp_seg *rseg; + u8_t acceptable = 0; + err_t err; + + err = ERR_OK; + + /* Process incoming RST segments. */ + if (flags & TCP_RST) { + /* First, determine if the reset is acceptable. */ + if (pcb->state == SYN_SENT) { + if (ackno == pcb->snd_nxt) { + acceptable = 1; + } + } else { + if (TCP_SEQ_BETWEEN(seqno, pcb->rcv_nxt, + pcb->rcv_nxt + pcb->rcv_wnd)) { + acceptable = 1; + } + } + + if (acceptable) { + LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_process: Connection RESET\n")); + LWIP_ASSERT("tcp_input: pcb->state != CLOSED", pcb->state != CLOSED); + recv_flags |= TF_RESET; + pcb->flags &= ~TF_ACK_DELAY; + return ERR_RST; + } else { + LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_process: unacceptable reset seqno %"U32_F" rcv_nxt %"U32_F"\n", + seqno, pcb->rcv_nxt)); + LWIP_DEBUGF(TCP_DEBUG, ("tcp_process: unacceptable reset seqno %"U32_F" rcv_nxt %"U32_F"\n", + seqno, pcb->rcv_nxt)); + return ERR_OK; + } + } + + if ((flags & TCP_SYN) && (pcb->state != SYN_SENT && pcb->state != SYN_RCVD)) { + /* Cope with new connection attempt after remote end crashed */ + tcp_ack_now(pcb); + return ERR_OK; + } + + if ((pcb->flags & TF_RXCLOSED) == 0) { + /* Update the PCB (in)activity timer unless rx is closed (see tcp_shutdown) */ + pcb->tmr = tcp_ticks; + } + pcb->keep_cnt_sent = 0; + + tcp_parseopt(pcb); + + /* Do different things depending on the TCP state. */ + switch (pcb->state) { + case SYN_SENT: + LWIP_DEBUGF(TCP_INPUT_DEBUG, ("SYN-SENT: ackno %"U32_F" pcb->snd_nxt %"U32_F" unacked %"U32_F"\n", ackno, + pcb->snd_nxt, ntohl(pcb->unacked->tcphdr->seqno))); + /* received SYN ACK with expected sequence number? */ + if ((flags & TCP_ACK) && (flags & TCP_SYN) + && ackno == ntohl(pcb->unacked->tcphdr->seqno) + 1) { + pcb->snd_buf++; + pcb->rcv_nxt = seqno + 1; + pcb->rcv_ann_right_edge = pcb->rcv_nxt; + pcb->lastack = ackno; + pcb->snd_wnd = SND_WND_SCALE(pcb, tcphdr->wnd); + pcb->snd_wnd_max = pcb->snd_wnd; + pcb->snd_wl1 = seqno - 1; /* initialise to seqno - 1 to force window update */ + pcb->state = ESTABLISHED; + +#if TCP_CALCULATE_EFF_SEND_MSS + pcb->mss = tcp_eff_send_mss(pcb->mss, &pcb->local_ip, &pcb->remote_ip); +#endif /* TCP_CALCULATE_EFF_SEND_MSS */ + + /* Set ssthresh again after changing 'mss' and 'snd_wnd' */ + pcb->ssthresh = LWIP_TCP_INITIAL_SSTHRESH(pcb); + + pcb->cwnd = LWIP_TCP_CALC_INITIAL_CWND(pcb->mss); + LWIP_DEBUGF(TCP_CWND_DEBUG, ("tcp_process (SENT): cwnd %"TCPWNDSIZE_F + " ssthresh %"TCPWNDSIZE_F"\n", + pcb->cwnd, pcb->ssthresh)); + LWIP_ASSERT("pcb->snd_queuelen > 0", (pcb->snd_queuelen > 0)); + --pcb->snd_queuelen; + LWIP_DEBUGF(TCP_QLEN_DEBUG, ("tcp_process: SYN-SENT --queuelen %"TCPWNDSIZE_F"\n", (tcpwnd_size_t)pcb->snd_queuelen)); + rseg = pcb->unacked; + pcb->unacked = rseg->next; + tcp_seg_free(rseg); + + /* If there's nothing left to acknowledge, stop the retransmit + timer, otherwise reset it to start again */ + if (pcb->unacked == NULL) { + pcb->rtime = -1; + } else { + pcb->rtime = 0; + pcb->nrtx = 0; + } + + /* Call the user specified function to call when successfully + * connected. */ + TCP_EVENT_CONNECTED(pcb, ERR_OK, err); + if (err == ERR_ABRT) { + return ERR_ABRT; + } + tcp_ack_now(pcb); + } + /* received ACK? possibly a half-open connection */ + else if (flags & TCP_ACK) { + /* send a RST to bring the other side in a non-synchronized state. */ + tcp_rst(ackno, seqno + tcplen, ip_current_dest_addr(), + ip_current_src_addr(), tcphdr->dest, tcphdr->src); + } + break; + case SYN_RCVD: + if (flags & TCP_ACK) { + /* expected ACK number? */ + if (TCP_SEQ_BETWEEN(ackno, pcb->lastack+1, pcb->snd_nxt)) { + pcb->state = ESTABLISHED; + LWIP_DEBUGF(TCP_DEBUG, ("TCP connection established %"U16_F" -> %"U16_F".\n", inseg.tcphdr->src, inseg.tcphdr->dest)); +#if LWIP_CALLBACK_API + LWIP_ASSERT("pcb->accept != NULL", pcb->accept != NULL); +#endif + /* Call the accept function. */ + TCP_EVENT_ACCEPT(pcb, ERR_OK, err); + if (err != ERR_OK) { + /* If the accept function returns with an error, we abort + * the connection. */ + /* Already aborted? */ + if (err != ERR_ABRT) { + tcp_abort(pcb); + } + return ERR_ABRT; + } + /* If there was any data contained within this ACK, + * we'd better pass it on to the application as well. */ + tcp_receive(pcb); + + /* passive open: update initial ssthresh now that the correct window is + known: if the remote side supports window scaling, the window sent + with the initial SYN can be smaller than the one used later */ + pcb->ssthresh = LWIP_TCP_INITIAL_SSTHRESH(pcb); + + /* Prevent ACK for SYN to generate a sent event */ + if (pcb->acked != 0) { + pcb->acked--; + } + + pcb->cwnd = LWIP_TCP_CALC_INITIAL_CWND(pcb->mss); + LWIP_DEBUGF(TCP_CWND_DEBUG, ("tcp_process (SYN_RCVD): cwnd %"TCPWNDSIZE_F + " ssthresh %"TCPWNDSIZE_F"\n", + pcb->cwnd, pcb->ssthresh)); + + if (recv_flags & TF_GOT_FIN) { + tcp_ack_now(pcb); + pcb->state = CLOSE_WAIT; + } + } else { + /* incorrect ACK number, send RST */ + tcp_rst(ackno, seqno + tcplen, ip_current_dest_addr(), + ip_current_src_addr(), tcphdr->dest, tcphdr->src); + } + } else if ((flags & TCP_SYN) && (seqno == pcb->rcv_nxt - 1)) { + /* Looks like another copy of the SYN - retransmit our SYN-ACK */ + tcp_rexmit(pcb); + } + break; + case CLOSE_WAIT: + /* FALLTHROUGH */ + case ESTABLISHED: + tcp_receive(pcb); + if (recv_flags & TF_GOT_FIN) { /* passive close */ + tcp_ack_now(pcb); + pcb->state = CLOSE_WAIT; + } + break; + case FIN_WAIT_1: + tcp_receive(pcb); + if (recv_flags & TF_GOT_FIN) { + if ((flags & TCP_ACK) && (ackno == pcb->snd_nxt)) { + LWIP_DEBUGF(TCP_DEBUG, + ("TCP connection closed: FIN_WAIT_1 %"U16_F" -> %"U16_F".\n", inseg.tcphdr->src, inseg.tcphdr->dest)); + tcp_ack_now(pcb); + tcp_pcb_purge(pcb); + TCP_RMV_ACTIVE(pcb); + pcb->state = TIME_WAIT; + TCP_REG(&tcp_tw_pcbs, pcb); + } else { + tcp_ack_now(pcb); + pcb->state = CLOSING; + } + } else if ((flags & TCP_ACK) && (ackno == pcb->snd_nxt)) { + pcb->state = FIN_WAIT_2; + } + break; + case FIN_WAIT_2: + tcp_receive(pcb); + if (recv_flags & TF_GOT_FIN) { + LWIP_DEBUGF(TCP_DEBUG, ("TCP connection closed: FIN_WAIT_2 %"U16_F" -> %"U16_F".\n", inseg.tcphdr->src, inseg.tcphdr->dest)); + tcp_ack_now(pcb); + tcp_pcb_purge(pcb); + TCP_RMV_ACTIVE(pcb); + pcb->state = TIME_WAIT; + TCP_REG(&tcp_tw_pcbs, pcb); + } + break; + case CLOSING: + tcp_receive(pcb); + if (flags & TCP_ACK && ackno == pcb->snd_nxt) { + LWIP_DEBUGF(TCP_DEBUG, ("TCP connection closed: CLOSING %"U16_F" -> %"U16_F".\n", inseg.tcphdr->src, inseg.tcphdr->dest)); + tcp_pcb_purge(pcb); + TCP_RMV_ACTIVE(pcb); + pcb->state = TIME_WAIT; + TCP_REG(&tcp_tw_pcbs, pcb); + } + break; + case LAST_ACK: + tcp_receive(pcb); + if (flags & TCP_ACK && ackno == pcb->snd_nxt) { + LWIP_DEBUGF(TCP_DEBUG, ("TCP connection closed: LAST_ACK %"U16_F" -> %"U16_F".\n", inseg.tcphdr->src, inseg.tcphdr->dest)); + /* bugfix #21699: don't set pcb->state to CLOSED here or we risk leaking segments */ + recv_flags |= TF_CLOSED; + } + break; + default: + break; + } + return ERR_OK; +} + +#if TCP_QUEUE_OOSEQ +/** + * Insert segment into the list (segments covered with new one will be deleted) + * + * Called from tcp_receive() + */ +static void +tcp_oos_insert_segment(struct tcp_seg *cseg, struct tcp_seg *next) +{ + struct tcp_seg *old_seg; + + if (TCPH_FLAGS(cseg->tcphdr) & TCP_FIN) { + /* received segment overlaps all following segments */ + tcp_segs_free(next); + next = NULL; + } else { + /* delete some following segments + oos queue may have segments with FIN flag */ + while (next && + TCP_SEQ_GEQ((seqno + cseg->len), + (next->tcphdr->seqno + next->len))) { + /* cseg with FIN already processed */ + if (TCPH_FLAGS(next->tcphdr) & TCP_FIN) { + TCPH_SET_FLAG(cseg->tcphdr, TCP_FIN); + } + old_seg = next; + next = next->next; + tcp_seg_free(old_seg); + } + if (next && + TCP_SEQ_GT(seqno + cseg->len, next->tcphdr->seqno)) { + /* We need to trim the incoming segment. */ + cseg->len = (u16_t)(next->tcphdr->seqno - seqno); + pbuf_realloc(cseg->p, cseg->len); + } + } + cseg->next = next; +} +#endif /* TCP_QUEUE_OOSEQ */ + +/** + * Called by tcp_process. Checks if the given segment is an ACK for outstanding + * data, and if so frees the memory of the buffered data. Next, it places the + * segment on any of the receive queues (pcb->recved or pcb->ooseq). If the segment + * is buffered, the pbuf is referenced by pbuf_ref so that it will not be freed until + * it has been removed from the buffer. + * + * If the incoming segment constitutes an ACK for a segment that was used for RTT + * estimation, the RTT is estimated here as well. + * + * Called from tcp_process(). + */ +static void +tcp_receive(struct tcp_pcb *pcb) +{ + struct tcp_seg *next; +#if TCP_QUEUE_OOSEQ + struct tcp_seg *prev, *cseg; +#endif /* TCP_QUEUE_OOSEQ */ + struct pbuf *p; + s32_t off; + s16_t m; + u32_t right_wnd_edge; + u16_t new_tot_len; + int found_dupack = 0; +#if TCP_OOSEQ_MAX_BYTES || TCP_OOSEQ_MAX_PBUFS + u32_t ooseq_blen; + u16_t ooseq_qlen; +#endif /* TCP_OOSEQ_MAX_BYTES || TCP_OOSEQ_MAX_PBUFS */ + + LWIP_ASSERT("tcp_receive: wrong state", pcb->state >= ESTABLISHED); + + if (flags & TCP_ACK) { + right_wnd_edge = pcb->snd_wnd + pcb->snd_wl2; + + /* Update window. */ + if (TCP_SEQ_LT(pcb->snd_wl1, seqno) || + (pcb->snd_wl1 == seqno && TCP_SEQ_LT(pcb->snd_wl2, ackno)) || + (pcb->snd_wl2 == ackno && (u32_t)SND_WND_SCALE(pcb, tcphdr->wnd) > pcb->snd_wnd)) { + pcb->snd_wnd = SND_WND_SCALE(pcb, tcphdr->wnd); + /* keep track of the biggest window announced by the remote host to calculate + the maximum segment size */ + if (pcb->snd_wnd_max < pcb->snd_wnd) { + pcb->snd_wnd_max = pcb->snd_wnd; + } + pcb->snd_wl1 = seqno; + pcb->snd_wl2 = ackno; + if (pcb->snd_wnd == 0) { + if (pcb->persist_backoff == 0) { + /* start persist timer */ + pcb->persist_cnt = 0; + pcb->persist_backoff = 1; + } + } else if (pcb->persist_backoff > 0) { + /* stop persist timer */ + pcb->persist_backoff = 0; + } + LWIP_DEBUGF(TCP_WND_DEBUG, ("tcp_receive: window update %"TCPWNDSIZE_F"\n", pcb->snd_wnd)); +#if TCP_WND_DEBUG + } else { + if (pcb->snd_wnd != (tcpwnd_size_t)SND_WND_SCALE(pcb, tcphdr->wnd)) { + LWIP_DEBUGF(TCP_WND_DEBUG, + ("tcp_receive: no window update lastack %"U32_F" ackno %" + U32_F" wl1 %"U32_F" seqno %"U32_F" wl2 %"U32_F"\n", + pcb->lastack, ackno, pcb->snd_wl1, seqno, pcb->snd_wl2)); + } +#endif /* TCP_WND_DEBUG */ + } + + /* (From Stevens TCP/IP Illustrated Vol II, p970.) Its only a + * duplicate ack if: + * 1) It doesn't ACK new data + * 2) length of received packet is zero (i.e. no payload) + * 3) the advertised window hasn't changed + * 4) There is outstanding unacknowledged data (retransmission timer running) + * 5) The ACK is == biggest ACK sequence number so far seen (snd_una) + * + * If it passes all five, should process as a dupack: + * a) dupacks < 3: do nothing + * b) dupacks == 3: fast retransmit + * c) dupacks > 3: increase cwnd + * + * If it only passes 1-3, should reset dupack counter (and add to + * stats, which we don't do in lwIP) + * + * If it only passes 1, should reset dupack counter + * + */ + + /* Clause 1 */ + if (TCP_SEQ_LEQ(ackno, pcb->lastack)) { + pcb->acked = 0; + /* Clause 2 */ + if (tcplen == 0) { + /* Clause 3 */ + if (pcb->snd_wl2 + pcb->snd_wnd == right_wnd_edge) { + /* Clause 4 */ + if (pcb->rtime >= 0) { + /* Clause 5 */ + if (pcb->lastack == ackno) { + found_dupack = 1; + if ((u8_t)(pcb->dupacks + 1) > pcb->dupacks) { + ++pcb->dupacks; + } + if (pcb->dupacks > 3) { + /* Inflate the congestion window, but not if it means that + the value overflows. */ + if ((tcpwnd_size_t)(pcb->cwnd + pcb->mss) > pcb->cwnd) { + pcb->cwnd += pcb->mss; + } + } else if (pcb->dupacks == 3) { + /* Do fast retransmit */ + tcp_rexmit_fast(pcb); + } + } + } + } + } + /* If Clause (1) or more is true, but not a duplicate ack, reset + * count of consecutive duplicate acks */ + if (!found_dupack) { + pcb->dupacks = 0; + } + } else if (TCP_SEQ_BETWEEN(ackno, pcb->lastack+1, pcb->snd_nxt)) { + /* We come here when the ACK acknowledges new data. */ + + /* Reset the "IN Fast Retransmit" flag, since we are no longer + in fast retransmit. Also reset the congestion window to the + slow start threshold. */ + if (pcb->flags & TF_INFR) { + pcb->flags &= ~TF_INFR; + pcb->cwnd = pcb->ssthresh; + } + + /* Reset the number of retransmissions. */ + pcb->nrtx = 0; + + /* Reset the retransmission time-out. */ + pcb->rto = (pcb->sa >> 3) + pcb->sv; + + /* Update the send buffer space. Diff between the two can never exceed 64K + unless window scaling is used. */ + pcb->acked = (tcpwnd_size_t)(ackno - pcb->lastack); + + pcb->snd_buf += pcb->acked; + + /* Reset the fast retransmit variables. */ + pcb->dupacks = 0; + pcb->lastack = ackno; + + /* Update the congestion control variables (cwnd and + ssthresh). */ + if (pcb->state >= ESTABLISHED) { + if (pcb->cwnd < pcb->ssthresh) { + if ((tcpwnd_size_t)(pcb->cwnd + pcb->mss) > pcb->cwnd) { + pcb->cwnd += pcb->mss; + } + LWIP_DEBUGF(TCP_CWND_DEBUG, ("tcp_receive: slow start cwnd %"TCPWNDSIZE_F"\n", pcb->cwnd)); + } else { + tcpwnd_size_t new_cwnd = (pcb->cwnd + pcb->mss * pcb->mss / pcb->cwnd); + if (new_cwnd > pcb->cwnd) { + pcb->cwnd = new_cwnd; + } + LWIP_DEBUGF(TCP_CWND_DEBUG, ("tcp_receive: congestion avoidance cwnd %"TCPWNDSIZE_F"\n", pcb->cwnd)); + } + } + LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_receive: ACK for %"U32_F", unacked->seqno %"U32_F":%"U32_F"\n", + ackno, + pcb->unacked != NULL? + ntohl(pcb->unacked->tcphdr->seqno): 0, + pcb->unacked != NULL? + ntohl(pcb->unacked->tcphdr->seqno) + TCP_TCPLEN(pcb->unacked): 0)); + + /* Remove segment from the unacknowledged list if the incoming + ACK acknowledges them. */ + while (pcb->unacked != NULL && + TCP_SEQ_LEQ(ntohl(pcb->unacked->tcphdr->seqno) + + TCP_TCPLEN(pcb->unacked), ackno)) { + LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_receive: removing %"U32_F":%"U32_F" from pcb->unacked\n", + ntohl(pcb->unacked->tcphdr->seqno), + ntohl(pcb->unacked->tcphdr->seqno) + + TCP_TCPLEN(pcb->unacked))); + + next = pcb->unacked; + pcb->unacked = pcb->unacked->next; + + LWIP_DEBUGF(TCP_QLEN_DEBUG, ("tcp_receive: queuelen %"TCPWNDSIZE_F" ... ", (tcpwnd_size_t)pcb->snd_queuelen)); + LWIP_ASSERT("pcb->snd_queuelen >= pbuf_clen(next->p)", (pcb->snd_queuelen >= pbuf_clen(next->p))); + /* Prevent ACK for FIN to generate a sent event */ + if ((pcb->acked != 0) && ((TCPH_FLAGS(next->tcphdr) & TCP_FIN) != 0)) { + pcb->acked--; + } + + pcb->snd_queuelen -= pbuf_clen(next->p); + tcp_seg_free(next); + + LWIP_DEBUGF(TCP_QLEN_DEBUG, ("%"TCPWNDSIZE_F" (after freeing unacked)\n", (tcpwnd_size_t)pcb->snd_queuelen)); + if (pcb->snd_queuelen != 0) { + LWIP_ASSERT("tcp_receive: valid queue length", pcb->unacked != NULL || + pcb->unsent != NULL); + } + } + + /* If there's nothing left to acknowledge, stop the retransmit + timer, otherwise reset it to start again */ + if (pcb->unacked == NULL) { + pcb->rtime = -1; + } else { + pcb->rtime = 0; + } + + pcb->polltmr = 0; + +#if LWIP_IPV6 && LWIP_ND6_TCP_REACHABILITY_HINTS + if (ip_current_is_v6()) { + /* Inform neighbor reachability of forward progress. */ + nd6_reachability_hint(ip6_current_src_addr()); + } +#endif /* LWIP_IPV6 && LWIP_ND6_TCP_REACHABILITY_HINTS*/ + } else { + /* Out of sequence ACK, didn't really ack anything */ + pcb->acked = 0; + tcp_send_empty_ack(pcb); + } + + /* We go through the ->unsent list to see if any of the segments + on the list are acknowledged by the ACK. This may seem + strange since an "unsent" segment shouldn't be acked. The + rationale is that lwIP puts all outstanding segments on the + ->unsent list after a retransmission, so these segments may + in fact have been sent once. */ + while (pcb->unsent != NULL && + TCP_SEQ_BETWEEN(ackno, ntohl(pcb->unsent->tcphdr->seqno) + + TCP_TCPLEN(pcb->unsent), pcb->snd_nxt)) { + LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_receive: removing %"U32_F":%"U32_F" from pcb->unsent\n", + ntohl(pcb->unsent->tcphdr->seqno), ntohl(pcb->unsent->tcphdr->seqno) + + TCP_TCPLEN(pcb->unsent))); + + next = pcb->unsent; + pcb->unsent = pcb->unsent->next; +#if TCP_OVERSIZE + if (pcb->unsent == NULL) { + pcb->unsent_oversize = 0; + } +#endif /* TCP_OVERSIZE */ + LWIP_DEBUGF(TCP_QLEN_DEBUG, ("tcp_receive: queuelen %"TCPWNDSIZE_F" ... ", (tcpwnd_size_t)pcb->snd_queuelen)); + LWIP_ASSERT("pcb->snd_queuelen >= pbuf_clen(next->p)", (pcb->snd_queuelen >= pbuf_clen(next->p))); + /* Prevent ACK for FIN to generate a sent event */ + if ((pcb->acked != 0) && ((TCPH_FLAGS(next->tcphdr) & TCP_FIN) != 0)) { + pcb->acked--; + } + pcb->snd_queuelen -= pbuf_clen(next->p); + tcp_seg_free(next); + LWIP_DEBUGF(TCP_QLEN_DEBUG, ("%"TCPWNDSIZE_F" (after freeing unsent)\n", (tcpwnd_size_t)pcb->snd_queuelen)); + if (pcb->snd_queuelen != 0) { + LWIP_ASSERT("tcp_receive: valid queue length", + pcb->unacked != NULL || pcb->unsent != NULL); + } + } + /* End of ACK for new data processing. */ + + LWIP_DEBUGF(TCP_RTO_DEBUG, ("tcp_receive: pcb->rttest %"U32_F" rtseq %"U32_F" ackno %"U32_F"\n", + pcb->rttest, pcb->rtseq, ackno)); + + /* RTT estimation calculations. This is done by checking if the + incoming segment acknowledges the segment we use to take a + round-trip time measurement. */ + if (pcb->rttest && TCP_SEQ_LT(pcb->rtseq, ackno)) { + /* diff between this shouldn't exceed 32K since this are tcp timer ticks + and a round-trip shouldn't be that long... */ + m = (s16_t)(tcp_ticks - pcb->rttest); + + LWIP_DEBUGF(TCP_RTO_DEBUG, ("tcp_receive: experienced rtt %"U16_F" ticks (%"U16_F" msec).\n", + m, m * TCP_SLOW_INTERVAL)); + + /* This is taken directly from VJs original code in his paper */ + m = m - (pcb->sa >> 3); + pcb->sa += m; + if (m < 0) { + m = -m; + } + m = m - (pcb->sv >> 2); + pcb->sv += m; + pcb->rto = (pcb->sa >> 3) + pcb->sv; + + LWIP_DEBUGF(TCP_RTO_DEBUG, ("tcp_receive: RTO %"U16_F" (%"U16_F" milliseconds)\n", + pcb->rto, pcb->rto * TCP_SLOW_INTERVAL)); + + pcb->rttest = 0; + } + } + + /* If the incoming segment contains data, we must process it + further unless the pcb already received a FIN. + (RFC 793, chapter 3.9, "SEGMENT ARRIVES" in states CLOSE-WAIT, CLOSING, + LAST-ACK and TIME-WAIT: "Ignore the segment text.") */ + if ((tcplen > 0) && (pcb->state < CLOSE_WAIT)) { + /* This code basically does three things: + + +) If the incoming segment contains data that is the next + in-sequence data, this data is passed to the application. This + might involve trimming the first edge of the data. The rcv_nxt + variable and the advertised window are adjusted. + + +) If the incoming segment has data that is above the next + sequence number expected (->rcv_nxt), the segment is placed on + the ->ooseq queue. This is done by finding the appropriate + place in the ->ooseq queue (which is ordered by sequence + number) and trim the segment in both ends if needed. An + immediate ACK is sent to indicate that we received an + out-of-sequence segment. + + +) Finally, we check if the first segment on the ->ooseq queue + now is in sequence (i.e., if rcv_nxt >= ooseq->seqno). If + rcv_nxt > ooseq->seqno, we must trim the first edge of the + segment on ->ooseq before we adjust rcv_nxt. The data in the + segments that are now on sequence are chained onto the + incoming segment so that we only need to call the application + once. + */ + + /* First, we check if we must trim the first edge. We have to do + this if the sequence number of the incoming segment is less + than rcv_nxt, and the sequence number plus the length of the + segment is larger than rcv_nxt. */ + /* if (TCP_SEQ_LT(seqno, pcb->rcv_nxt)) { + if (TCP_SEQ_LT(pcb->rcv_nxt, seqno + tcplen)) {*/ + if (TCP_SEQ_BETWEEN(pcb->rcv_nxt, seqno + 1, seqno + tcplen - 1)) { + /* Trimming the first edge is done by pushing the payload + pointer in the pbuf downwards. This is somewhat tricky since + we do not want to discard the full contents of the pbuf up to + the new starting point of the data since we have to keep the + TCP header which is present in the first pbuf in the chain. + + What is done is really quite a nasty hack: the first pbuf in + the pbuf chain is pointed to by inseg.p. Since we need to be + able to deallocate the whole pbuf, we cannot change this + inseg.p pointer to point to any of the later pbufs in the + chain. Instead, we point the ->payload pointer in the first + pbuf to data in one of the later pbufs. We also set the + inseg.data pointer to point to the right place. This way, the + ->p pointer will still point to the first pbuf, but the + ->p->payload pointer will point to data in another pbuf. + + After we are done with adjusting the pbuf pointers we must + adjust the ->data pointer in the seg and the segment + length.*/ + + off = pcb->rcv_nxt - seqno; + p = inseg.p; + LWIP_ASSERT("inseg.p != NULL", inseg.p); + LWIP_ASSERT("insane offset!", (off < 0x7fff)); + if (inseg.p->len < off) { + LWIP_ASSERT("pbuf too short!", (((s32_t)inseg.p->tot_len) >= off)); + new_tot_len = (u16_t)(inseg.p->tot_len - off); + while (p->len < off) { + off -= p->len; + /* KJM following line changed (with addition of new_tot_len var) + to fix bug #9076 + inseg.p->tot_len -= p->len; */ + p->tot_len = new_tot_len; + p->len = 0; + p = p->next; + } + if (pbuf_header(p, (s16_t)-off)) { + /* Do we need to cope with this failing? Assert for now */ + LWIP_ASSERT("pbuf_header failed", 0); + } + } else { + if (pbuf_header(inseg.p, (s16_t)-off)) { + /* Do we need to cope with this failing? Assert for now */ + LWIP_ASSERT("pbuf_header failed", 0); + } + } + inseg.len -= (u16_t)(pcb->rcv_nxt - seqno); + inseg.tcphdr->seqno = seqno = pcb->rcv_nxt; + } + else { + if (TCP_SEQ_LT(seqno, pcb->rcv_nxt)) { + /* the whole segment is < rcv_nxt */ + /* must be a duplicate of a packet that has already been correctly handled */ + + LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_receive: duplicate seqno %"U32_F"\n", seqno)); + tcp_ack_now(pcb); + } + } + + /* The sequence number must be within the window (above rcv_nxt + and below rcv_nxt + rcv_wnd) in order to be further + processed. */ + if (TCP_SEQ_BETWEEN(seqno, pcb->rcv_nxt, + pcb->rcv_nxt + pcb->rcv_wnd - 1)) { + if (pcb->rcv_nxt == seqno) { + /* The incoming segment is the next in sequence. We check if + we have to trim the end of the segment and update rcv_nxt + and pass the data to the application. */ + tcplen = TCP_TCPLEN(&inseg); + + if (tcplen > pcb->rcv_wnd) { + LWIP_DEBUGF(TCP_INPUT_DEBUG, + ("tcp_receive: other end overran receive window" + "seqno %"U32_F" len %"U16_F" right edge %"U32_F"\n", + seqno, tcplen, pcb->rcv_nxt + pcb->rcv_wnd)); + if (TCPH_FLAGS(inseg.tcphdr) & TCP_FIN) { + /* Must remove the FIN from the header as we're trimming + * that byte of sequence-space from the packet */ + TCPH_FLAGS_SET(inseg.tcphdr, TCPH_FLAGS(inseg.tcphdr) & ~(unsigned int)TCP_FIN); + } + /* Adjust length of segment to fit in the window. */ + TCPWND_CHECK16(pcb->rcv_wnd); + inseg.len = (u16_t)pcb->rcv_wnd; + if (TCPH_FLAGS(inseg.tcphdr) & TCP_SYN) { + inseg.len -= 1; + } + pbuf_realloc(inseg.p, inseg.len); + tcplen = TCP_TCPLEN(&inseg); + LWIP_ASSERT("tcp_receive: segment not trimmed correctly to rcv_wnd\n", + (seqno + tcplen) == (pcb->rcv_nxt + pcb->rcv_wnd)); + } +#if TCP_QUEUE_OOSEQ + /* Received in-sequence data, adjust ooseq data if: + - FIN has been received or + - inseq overlaps with ooseq */ + if (pcb->ooseq != NULL) { + if (TCPH_FLAGS(inseg.tcphdr) & TCP_FIN) { + LWIP_DEBUGF(TCP_INPUT_DEBUG, + ("tcp_receive: received in-order FIN, binning ooseq queue\n")); + /* Received in-order FIN means anything that was received + * out of order must now have been received in-order, so + * bin the ooseq queue */ + while (pcb->ooseq != NULL) { + struct tcp_seg *old_ooseq = pcb->ooseq; + pcb->ooseq = pcb->ooseq->next; + tcp_seg_free(old_ooseq); + } + } else { + next = pcb->ooseq; + /* Remove all segments on ooseq that are covered by inseg already. + * FIN is copied from ooseq to inseg if present. */ + while (next && + TCP_SEQ_GEQ(seqno + tcplen, + next->tcphdr->seqno + next->len)) { + /* inseg cannot have FIN here (already processed above) */ + if (TCPH_FLAGS(next->tcphdr) & TCP_FIN && + (TCPH_FLAGS(inseg.tcphdr) & TCP_SYN) == 0) { + TCPH_SET_FLAG(inseg.tcphdr, TCP_FIN); + tcplen = TCP_TCPLEN(&inseg); + } + prev = next; + next = next->next; + tcp_seg_free(prev); + } + /* Now trim right side of inseg if it overlaps with the first + * segment on ooseq */ + if (next && + TCP_SEQ_GT(seqno + tcplen, + next->tcphdr->seqno)) { + /* inseg cannot have FIN here (already processed above) */ + inseg.len = (u16_t)(next->tcphdr->seqno - seqno); + if (TCPH_FLAGS(inseg.tcphdr) & TCP_SYN) { + inseg.len -= 1; + } + pbuf_realloc(inseg.p, inseg.len); + tcplen = TCP_TCPLEN(&inseg); + LWIP_ASSERT("tcp_receive: segment not trimmed correctly to ooseq queue\n", + (seqno + tcplen) == next->tcphdr->seqno); + } + pcb->ooseq = next; + } + } +#endif /* TCP_QUEUE_OOSEQ */ + + pcb->rcv_nxt = seqno + tcplen; + + /* Update the receiver's (our) window. */ + LWIP_ASSERT("tcp_receive: tcplen > rcv_wnd\n", pcb->rcv_wnd >= tcplen); + pcb->rcv_wnd -= tcplen; + + tcp_update_rcv_ann_wnd(pcb); + + /* If there is data in the segment, we make preparations to + pass this up to the application. The ->recv_data variable + is used for holding the pbuf that goes to the + application. The code for reassembling out-of-sequence data + chains its data on this pbuf as well. + + If the segment was a FIN, we set the TF_GOT_FIN flag that will + be used to indicate to the application that the remote side has + closed its end of the connection. */ + if (inseg.p->tot_len > 0) { + recv_data = inseg.p; + /* Since this pbuf now is the responsibility of the + application, we delete our reference to it so that we won't + (mistakingly) deallocate it. */ + inseg.p = NULL; + } + if (TCPH_FLAGS(inseg.tcphdr) & TCP_FIN) { + LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_receive: received FIN.\n")); + recv_flags |= TF_GOT_FIN; + } + +#if TCP_QUEUE_OOSEQ + /* We now check if we have segments on the ->ooseq queue that + are now in sequence. */ + while (pcb->ooseq != NULL && + pcb->ooseq->tcphdr->seqno == pcb->rcv_nxt) { + + cseg = pcb->ooseq; + seqno = pcb->ooseq->tcphdr->seqno; + + pcb->rcv_nxt += TCP_TCPLEN(cseg); + LWIP_ASSERT("tcp_receive: ooseq tcplen > rcv_wnd\n", + pcb->rcv_wnd >= TCP_TCPLEN(cseg)); + pcb->rcv_wnd -= TCP_TCPLEN(cseg); + + tcp_update_rcv_ann_wnd(pcb); + + if (cseg->p->tot_len > 0) { + /* Chain this pbuf onto the pbuf that we will pass to + the application. */ + /* With window scaling, this can overflow recv_data->tot_len, but + that's not a problem since we explicitly fix that before passing + recv_data to the application. */ + if (recv_data) { + pbuf_cat(recv_data, cseg->p); + } else { + recv_data = cseg->p; + } + cseg->p = NULL; + } + if (TCPH_FLAGS(cseg->tcphdr) & TCP_FIN) { + LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_receive: dequeued FIN.\n")); + recv_flags |= TF_GOT_FIN; + if (pcb->state == ESTABLISHED) { /* force passive close or we can move to active close */ + pcb->state = CLOSE_WAIT; + } + } + + pcb->ooseq = cseg->next; + tcp_seg_free(cseg); + } +#endif /* TCP_QUEUE_OOSEQ */ + + + /* Acknowledge the segment(s). */ + tcp_ack(pcb); + +#if LWIP_IPV6 && LWIP_ND6_TCP_REACHABILITY_HINTS + if (ip_current_is_v6()) { + /* Inform neighbor reachability of forward progress. */ + nd6_reachability_hint(ip6_current_src_addr()); + } +#endif /* LWIP_IPV6 && LWIP_ND6_TCP_REACHABILITY_HINTS*/ + + } else { + /* We get here if the incoming segment is out-of-sequence. */ + tcp_send_empty_ack(pcb); +#if TCP_QUEUE_OOSEQ + /* We queue the segment on the ->ooseq queue. */ + if (pcb->ooseq == NULL) { + pcb->ooseq = tcp_seg_copy(&inseg); + } else { + /* If the queue is not empty, we walk through the queue and + try to find a place where the sequence number of the + incoming segment is between the sequence numbers of the + previous and the next segment on the ->ooseq queue. That is + the place where we put the incoming segment. If needed, we + trim the second edges of the previous and the incoming + segment so that it will fit into the sequence. + + If the incoming segment has the same sequence number as a + segment on the ->ooseq queue, we discard the segment that + contains less data. */ + + prev = NULL; + for (next = pcb->ooseq; next != NULL; next = next->next) { + if (seqno == next->tcphdr->seqno) { + /* The sequence number of the incoming segment is the + same as the sequence number of the segment on + ->ooseq. We check the lengths to see which one to + discard. */ + if (inseg.len > next->len) { + /* The incoming segment is larger than the old + segment. We replace some segments with the new + one. */ + cseg = tcp_seg_copy(&inseg); + if (cseg != NULL) { + if (prev != NULL) { + prev->next = cseg; + } else { + pcb->ooseq = cseg; + } + tcp_oos_insert_segment(cseg, next); + } + break; + } else { + /* Either the lengths are the same or the incoming + segment was smaller than the old one; in either + case, we ditch the incoming segment. */ + break; + } + } else { + if (prev == NULL) { + if (TCP_SEQ_LT(seqno, next->tcphdr->seqno)) { + /* The sequence number of the incoming segment is lower + than the sequence number of the first segment on the + queue. We put the incoming segment first on the + queue. */ + cseg = tcp_seg_copy(&inseg); + if (cseg != NULL) { + pcb->ooseq = cseg; + tcp_oos_insert_segment(cseg, next); + } + break; + } + } else { + /*if (TCP_SEQ_LT(prev->tcphdr->seqno, seqno) && + TCP_SEQ_LT(seqno, next->tcphdr->seqno)) {*/ + if (TCP_SEQ_BETWEEN(seqno, prev->tcphdr->seqno+1, next->tcphdr->seqno-1)) { + /* The sequence number of the incoming segment is in + between the sequence numbers of the previous and + the next segment on ->ooseq. We trim trim the previous + segment, delete next segments that included in received segment + and trim received, if needed. */ + cseg = tcp_seg_copy(&inseg); + if (cseg != NULL) { + if (TCP_SEQ_GT(prev->tcphdr->seqno + prev->len, seqno)) { + /* We need to trim the prev segment. */ + prev->len = (u16_t)(seqno - prev->tcphdr->seqno); + pbuf_realloc(prev->p, prev->len); + } + prev->next = cseg; + tcp_oos_insert_segment(cseg, next); + } + break; + } + } + /* If the "next" segment is the last segment on the + ooseq queue, we add the incoming segment to the end + of the list. */ + if (next->next == NULL && + TCP_SEQ_GT(seqno, next->tcphdr->seqno)) { + if (TCPH_FLAGS(next->tcphdr) & TCP_FIN) { + /* segment "next" already contains all data */ + break; + } + next->next = tcp_seg_copy(&inseg); + if (next->next != NULL) { + if (TCP_SEQ_GT(next->tcphdr->seqno + next->len, seqno)) { + /* We need to trim the last segment. */ + next->len = (u16_t)(seqno - next->tcphdr->seqno); + pbuf_realloc(next->p, next->len); + } + /* check if the remote side overruns our receive window */ + if (TCP_SEQ_GT((u32_t)tcplen + seqno, pcb->rcv_nxt + (u32_t)pcb->rcv_wnd)) { + LWIP_DEBUGF(TCP_INPUT_DEBUG, + ("tcp_receive: other end overran receive window" + "seqno %"U32_F" len %"U16_F" right edge %"U32_F"\n", + seqno, tcplen, pcb->rcv_nxt + pcb->rcv_wnd)); + if (TCPH_FLAGS(next->next->tcphdr) & TCP_FIN) { + /* Must remove the FIN from the header as we're trimming + * that byte of sequence-space from the packet */ + TCPH_FLAGS_SET(next->next->tcphdr, TCPH_FLAGS(next->next->tcphdr) & ~TCP_FIN); + } + /* Adjust length of segment to fit in the window. */ + next->next->len = (u16_t)(pcb->rcv_nxt + pcb->rcv_wnd - seqno); + pbuf_realloc(next->next->p, next->next->len); + tcplen = TCP_TCPLEN(next->next); + LWIP_ASSERT("tcp_receive: segment not trimmed correctly to rcv_wnd\n", + (seqno + tcplen) == (pcb->rcv_nxt + pcb->rcv_wnd)); + } + } + break; + } + } + prev = next; + } + } +#if TCP_OOSEQ_MAX_BYTES || TCP_OOSEQ_MAX_PBUFS + /* Check that the data on ooseq doesn't exceed one of the limits + and throw away everything above that limit. */ + ooseq_blen = 0; + ooseq_qlen = 0; + prev = NULL; + for (next = pcb->ooseq; next != NULL; prev = next, next = next->next) { + struct pbuf *p = next->p; + ooseq_blen += p->tot_len; + ooseq_qlen += pbuf_clen(p); + if ((ooseq_blen > TCP_OOSEQ_MAX_BYTES) || + (ooseq_qlen > TCP_OOSEQ_MAX_PBUFS)) { + /* too much ooseq data, dump this and everything after it */ + tcp_segs_free(next); + if (prev == NULL) { + /* first ooseq segment is too much, dump the whole queue */ + pcb->ooseq = NULL; + } else { + /* just dump 'next' and everything after it */ + prev->next = NULL; + } + break; + } + } +#endif /* TCP_OOSEQ_MAX_BYTES || TCP_OOSEQ_MAX_PBUFS */ +#endif /* TCP_QUEUE_OOSEQ */ + } + } else { + /* The incoming segment is not within the window. */ + tcp_send_empty_ack(pcb); + } + } else { + /* Segments with length 0 is taken care of here. Segments that + fall out of the window are ACKed. */ + if (!TCP_SEQ_BETWEEN(seqno, pcb->rcv_nxt, pcb->rcv_nxt + pcb->rcv_wnd - 1)) { + tcp_ack_now(pcb); + } + } +} + +static u8_t +tcp_getoptbyte(void) +{ + if ((tcphdr_opt2 == NULL) || (tcp_optidx < tcphdr_opt1len)) { + u8_t* opts = (u8_t *)tcphdr + TCP_HLEN; + return opts[tcp_optidx++]; + } else { + u8_t idx = (u8_t)(tcp_optidx++ - tcphdr_opt1len); + return tcphdr_opt2[idx]; + } +} + +/** + * Parses the options contained in the incoming segment. + * + * Called from tcp_listen_input() and tcp_process(). + * Currently, only the MSS option is supported! + * + * @param pcb the tcp_pcb for which a segment arrived + */ +static void +tcp_parseopt(struct tcp_pcb *pcb) +{ + u8_t data; + u16_t mss; +#if LWIP_TCP_TIMESTAMPS + u32_t tsval; +#endif + + /* Parse the TCP MSS option, if present. */ + if (tcphdr_optlen != 0) { + for (tcp_optidx = 0; tcp_optidx < tcphdr_optlen; ) { + u8_t opt = tcp_getoptbyte(); + switch (opt) { + case LWIP_TCP_OPT_EOL: + /* End of options. */ + LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_parseopt: EOL\n")); + return; + case LWIP_TCP_OPT_NOP: + /* NOP option. */ + LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_parseopt: NOP\n")); + break; + case LWIP_TCP_OPT_MSS: + LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_parseopt: MSS\n")); + if (tcp_getoptbyte() != LWIP_TCP_OPT_LEN_MSS || (tcp_optidx - 2 + LWIP_TCP_OPT_LEN_MSS) > tcphdr_optlen) { + /* Bad length */ + LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_parseopt: bad length\n")); + return; + } + /* An MSS option with the right option length. */ + mss = (tcp_getoptbyte() << 8); + mss |= tcp_getoptbyte(); + /* Limit the mss to the configured TCP_MSS and prevent division by zero */ + pcb->mss = ((mss > TCP_MSS) || (mss == 0)) ? TCP_MSS : mss; + break; +#if LWIP_WND_SCALE + case LWIP_TCP_OPT_WS: + LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_parseopt: WND_SCALE\n")); + if (tcp_getoptbyte() != LWIP_TCP_OPT_LEN_WS || (tcp_optidx - 2 + LWIP_TCP_OPT_LEN_WS) > tcphdr_optlen) { + /* Bad length */ + LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_parseopt: bad length\n")); + return; + } + /* If syn was received with wnd scale option, + activate wnd scale opt, but only if this is not a retransmission */ + if ((flags & TCP_SYN) && !(pcb->flags & TF_WND_SCALE)) { + /* An WND_SCALE option with the right option length. */ + data = tcp_getoptbyte(); + pcb->snd_scale = data; + if (pcb->snd_scale > 14U) { + pcb->snd_scale = 14U; + } + pcb->rcv_scale = TCP_RCV_SCALE; + pcb->flags |= TF_WND_SCALE; + /* window scaling is enabled, we can use the full receive window */ + LWIP_ASSERT("window not at default value", pcb->rcv_wnd == TCPWND_MIN16(TCP_WND)); + LWIP_ASSERT("window not at default value", pcb->rcv_ann_wnd == TCPWND_MIN16(TCP_WND)); + pcb->rcv_wnd = pcb->rcv_ann_wnd = TCP_WND; + } + break; +#endif +#if LWIP_TCP_TIMESTAMPS + case LWIP_TCP_OPT_TS: + LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_parseopt: TS\n")); + if (tcp_getoptbyte() != LWIP_TCP_OPT_LEN_TS || (tcp_optidx - 2 + LWIP_TCP_OPT_LEN_TS) > tcphdr_optlen) { + /* Bad length */ + LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_parseopt: bad length\n")); + return; + } + /* TCP timestamp option with valid length */ + tsval = tcp_getoptbyte(); + tsval |= (tcp_getoptbyte() << 8); + tsval |= (tcp_getoptbyte() << 16); + tsval |= (tcp_getoptbyte() << 24); + if (flags & TCP_SYN) { + pcb->ts_recent = ntohl(tsval); + /* Enable sending timestamps in every segment now that we know + the remote host supports it. */ + pcb->flags |= TF_TIMESTAMP; + } else if (TCP_SEQ_BETWEEN(pcb->ts_lastacksent, seqno, seqno+tcplen)) { + pcb->ts_recent = ntohl(tsval); + } + /* Advance to next option (6 bytes already read) */ + tcp_optidx += LWIP_TCP_OPT_LEN_TS - 6; + break; +#endif + default: + LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_parseopt: other\n")); + data = tcp_getoptbyte(); + if (data < 2) { + LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_parseopt: bad length\n")); + /* If the length field is zero, the options are malformed + and we don't process them further. */ + return; + } + /* All other options have a length field, so that we easily + can skip past them. */ + tcp_optidx += data - 2; + } + } + } +} + +void +tcp_trigger_input_pcb_close(void) +{ + recv_flags |= TF_CLOSED; +} + +#endif /* LWIP_TCP */ diff --git a/components/lwip/core/tcp_out.c b/components/lwip/core/tcp_out.c new file mode 100755 index 0000000000..aac02e4ebe --- /dev/null +++ b/components/lwip/core/tcp_out.c @@ -0,0 +1,1614 @@ +/** + * @file + * Transmission Control Protocol, outgoing traffic + * + * The output functions of TCP. + * + */ + +/* + * Copyright (c) 2001-2004 Swedish Institute of Computer Science. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + * + */ + +#include "lwip/opt.h" + +#if LWIP_TCP /* don't build if not configured for use in lwipopts.h */ + +#include "lwip/priv/tcp_priv.h" +#include "lwip/def.h" +#include "lwip/mem.h" +#include "lwip/memp.h" +#include "lwip/ip_addr.h" +#include "lwip/netif.h" +#include "lwip/inet_chksum.h" +#include "lwip/stats.h" +#include "lwip/ip6.h" +#include "lwip/ip6_addr.h" +#include "lwip/inet_chksum.h" +#if LWIP_TCP_TIMESTAMPS +#include "lwip/sys.h" +#endif + +#include + +#ifdef MEMLEAK_DEBUG +static const char mem_debug_file[] ICACHE_RODATA_ATTR STORE_ATTR = __FILE__; +#endif + +/* Define some copy-macros for checksum-on-copy so that the code looks + nicer by preventing too many ifdef's. */ +#if TCP_CHECKSUM_ON_COPY +#define TCP_DATA_COPY(dst, src, len, seg) do { \ + tcp_seg_add_chksum(LWIP_CHKSUM_COPY(dst, src, len), \ + len, &seg->chksum, &seg->chksum_swapped); \ + seg->flags |= TF_SEG_DATA_CHECKSUMMED; } while(0) +#define TCP_DATA_COPY2(dst, src, len, chksum, chksum_swapped) \ + tcp_seg_add_chksum(LWIP_CHKSUM_COPY(dst, src, len), len, chksum, chksum_swapped); +#else /* TCP_CHECKSUM_ON_COPY*/ +#define TCP_DATA_COPY(dst, src, len, seg) MEMCPY(dst, src, len) +#define TCP_DATA_COPY2(dst, src, len, chksum, chksum_swapped) MEMCPY(dst, src, len) +#endif /* TCP_CHECKSUM_ON_COPY*/ + +/** Define this to 1 for an extra check that the output checksum is valid + * (usefule when the checksum is generated by the application, not the stack) */ +#ifndef TCP_CHECKSUM_ON_COPY_SANITY_CHECK +#define TCP_CHECKSUM_ON_COPY_SANITY_CHECK 0 +#endif +/* Allow to override the failure of sanity check from warning to e.g. hard failure */ +#if TCP_CHECKSUM_ON_COPY_SANITY_CHECK +#ifndef TCP_CHECKSUM_ON_COPY_SANITY_CHECK_FAIL +#define TCP_CHECKSUM_ON_COPY_SANITY_CHECK_FAIL(msg) LWIP_DEBUGF(TCP_DEBUG | LWIP_DBG_LEVEL_WARNING, msg) +#endif +#endif + +#if TCP_OVERSIZE +/** The size of segment pbufs created when TCP_OVERSIZE is enabled */ +#ifndef TCP_OVERSIZE_CALC_LENGTH +#define TCP_OVERSIZE_CALC_LENGTH(length) ((length) + TCP_OVERSIZE) +#endif +#endif + +/* Forward declarations.*/ +static err_t tcp_output_segment(struct tcp_seg *seg, struct tcp_pcb *pcb); + +/** Allocate a pbuf and create a tcphdr at p->payload, used for output + * functions other than the default tcp_output -> tcp_output_segment + * (e.g. tcp_send_empty_ack, etc.) + * + * @param pcb tcp pcb for which to send a packet (used to initialize tcp_hdr) + * @param optlen length of header-options + * @param datalen length of tcp data to reserve in pbuf + * @param seqno_be seqno in network byte order (big-endian) + * @return pbuf with p->payload being the tcp_hdr + */ +static struct pbuf * +tcp_output_alloc_header(struct tcp_pcb *pcb, u16_t optlen, u16_t datalen, + u32_t seqno_be /* already in network byte order */) +{ + struct tcp_hdr *tcphdr; + struct pbuf *p = pbuf_alloc(PBUF_IP, TCP_HLEN + optlen + datalen, PBUF_RAM); + if (p != NULL) { + LWIP_ASSERT("check that first pbuf can hold struct tcp_hdr", + (p->len >= TCP_HLEN + optlen)); + tcphdr = (struct tcp_hdr *)p->payload; + tcphdr->src = htons(pcb->local_port); + tcphdr->dest = htons(pcb->remote_port); + tcphdr->seqno = seqno_be; + tcphdr->ackno = htonl(pcb->rcv_nxt); + TCPH_HDRLEN_FLAGS_SET(tcphdr, (5 + optlen / 4), TCP_ACK); + tcphdr->wnd = htons(TCPWND_MIN16(RCV_WND_SCALE(pcb, pcb->rcv_ann_wnd))); + tcphdr->chksum = 0; + tcphdr->urgp = 0; + + /* If we're sending a packet, update the announced right window edge */ + pcb->rcv_ann_right_edge = pcb->rcv_nxt + pcb->rcv_ann_wnd; + } + return p; +} + +/** + * Called by tcp_close() to send a segment including FIN flag but not data. + * + * @param pcb the tcp_pcb over which to send a segment + * @return ERR_OK if sent, another err_t otherwise + */ +err_t +tcp_send_fin(struct tcp_pcb *pcb) +{ + /* first, try to add the fin to the last unsent segment */ + if (pcb->unsent != NULL) { + struct tcp_seg *last_unsent; + for (last_unsent = pcb->unsent; last_unsent->next != NULL; + last_unsent = last_unsent->next); + + if ((TCPH_FLAGS(last_unsent->tcphdr) & (TCP_SYN | TCP_FIN | TCP_RST)) == 0) { + /* no SYN/FIN/RST flag in the header, we can add the FIN flag */ + TCPH_SET_FLAG(last_unsent->tcphdr, TCP_FIN); + pcb->flags |= TF_FIN; + return ERR_OK; + } + } + /* no data, no length, flags, copy=1, no optdata */ + return tcp_enqueue_flags(pcb, TCP_FIN); +} + +/** + * Create a TCP segment with prefilled header. + * + * Called by tcp_write and tcp_enqueue_flags. + * + * @param pcb Protocol control block for the TCP connection. + * @param p pbuf that is used to hold the TCP header. + * @param flags TCP flags for header. + * @param seqno TCP sequence number of this packet + * @param optflags options to include in TCP header + * @return a new tcp_seg pointing to p, or NULL. + * The TCP header is filled in except ackno and wnd. + * p is freed on failure. + */ +static struct tcp_seg * +tcp_create_segment(struct tcp_pcb *pcb, struct pbuf *p, u8_t flags, u32_t seqno, u8_t optflags) +{ + struct tcp_seg *seg; + u8_t optlen = LWIP_TCP_OPT_LENGTH(optflags); + + if ((seg = (struct tcp_seg *)memp_malloc(MEMP_TCP_SEG)) == NULL) { + LWIP_DEBUGF(TCP_OUTPUT_DEBUG | LWIP_DBG_LEVEL_SERIOUS, ("tcp_create_segment: no memory.\n")); + pbuf_free(p); + return NULL; + } + seg->flags = optflags; + seg->next = NULL; + seg->p = p; + LWIP_ASSERT("p->tot_len >= optlen", p->tot_len >= optlen); + seg->len = p->tot_len - optlen; +#if TCP_OVERSIZE_DBGCHECK + seg->oversize_left = 0; +#endif /* TCP_OVERSIZE_DBGCHECK */ +#if TCP_CHECKSUM_ON_COPY + seg->chksum = 0; + seg->chksum_swapped = 0; + /* check optflags */ + LWIP_ASSERT("invalid optflags passed: TF_SEG_DATA_CHECKSUMMED", + (optflags & TF_SEG_DATA_CHECKSUMMED) == 0); +#endif /* TCP_CHECKSUM_ON_COPY */ + + /* build TCP header */ + if (pbuf_header(p, TCP_HLEN)) { + LWIP_DEBUGF(TCP_OUTPUT_DEBUG | LWIP_DBG_LEVEL_SERIOUS, ("tcp_create_segment: no room for TCP header in pbuf.\n")); + TCP_STATS_INC(tcp.err); + tcp_seg_free(seg); + return NULL; + } + seg->tcphdr = (struct tcp_hdr *)seg->p->payload; + seg->tcphdr->src = htons(pcb->local_port); + seg->tcphdr->dest = htons(pcb->remote_port); + seg->tcphdr->seqno = htonl(seqno); + /* ackno is set in tcp_output */ + TCPH_HDRLEN_FLAGS_SET(seg->tcphdr, (5 + optlen / 4), flags); + /* wnd and chksum are set in tcp_output */ + seg->tcphdr->urgp = 0; + return seg; +} + +/** + * Allocate a PBUF_RAM pbuf, perhaps with extra space at the end. + * + * This function is like pbuf_alloc(layer, length, PBUF_RAM) except + * there may be extra bytes available at the end. + * + * @param layer flag to define header size. + * @param length size of the pbuf's payload. + * @param max_length maximum usable size of payload+oversize. + * @param oversize pointer to a u16_t that will receive the number of usable tail bytes. + * @param pcb The TCP connection that willo enqueue the pbuf. + * @param apiflags API flags given to tcp_write. + * @param first_seg true when this pbuf will be used in the first enqueued segment. + */ +#if TCP_OVERSIZE +static struct pbuf * +tcp_pbuf_prealloc(pbuf_layer layer, u16_t length, u16_t max_length, + u16_t *oversize, struct tcp_pcb *pcb, u8_t apiflags, + u8_t first_seg) +{ + struct pbuf *p; + u16_t alloc = length; + +#if LWIP_NETIF_TX_SINGLE_PBUF + LWIP_UNUSED_ARG(max_length); + LWIP_UNUSED_ARG(pcb); + LWIP_UNUSED_ARG(apiflags); + LWIP_UNUSED_ARG(first_seg); + /* always create MSS-sized pbufs */ + alloc = max_length; +#else /* LWIP_NETIF_TX_SINGLE_PBUF */ + if (length < max_length) { + /* Should we allocate an oversized pbuf, or just the minimum + * length required? If tcp_write is going to be called again + * before this segment is transmitted, we want the oversized + * buffer. If the segment will be transmitted immediately, we can + * save memory by allocating only length. We use a simple + * heuristic based on the following information: + * + * Did the user set TCP_WRITE_FLAG_MORE? + * + * Will the Nagle algorithm defer transmission of this segment? + */ + if ((apiflags & TCP_WRITE_FLAG_MORE) || + (!(pcb->flags & TF_NODELAY) && + (!first_seg || + pcb->unsent != NULL || + pcb->unacked != NULL))) { + alloc = LWIP_MIN(max_length, LWIP_MEM_ALIGN_SIZE(TCP_OVERSIZE_CALC_LENGTH(length))); + } + } +#endif /* LWIP_NETIF_TX_SINGLE_PBUF */ + p = pbuf_alloc(layer, alloc, PBUF_RAM); + if (p == NULL) { + return NULL; + } + LWIP_ASSERT("need unchained pbuf", p->next == NULL); + *oversize = p->len - length; + /* trim p->len to the currently used size */ + p->len = p->tot_len = length; + return p; +} +#else /* TCP_OVERSIZE */ +#define tcp_pbuf_prealloc(layer, length, mx, os, pcb, api, fst) pbuf_alloc((layer), (length), PBUF_RAM) +#endif /* TCP_OVERSIZE */ + +#if TCP_CHECKSUM_ON_COPY +/** Add a checksum of newly added data to the segment */ +static void +tcp_seg_add_chksum(u16_t chksum, u16_t len, u16_t *seg_chksum, + u8_t *seg_chksum_swapped) +{ + u32_t helper; + /* add chksum to old chksum and fold to u16_t */ + helper = chksum + *seg_chksum; + chksum = FOLD_U32T(helper); + if ((len & 1) != 0) { + *seg_chksum_swapped = 1 - *seg_chksum_swapped; + chksum = SWAP_BYTES_IN_WORD(chksum); + } + *seg_chksum = chksum; +} +#endif /* TCP_CHECKSUM_ON_COPY */ + +/** Checks if tcp_write is allowed or not (checks state, snd_buf and snd_queuelen). + * + * @param pcb the tcp pcb to check for + * @param len length of data to send (checked agains snd_buf) + * @return ERR_OK if tcp_write is allowed to proceed, another err_t otherwise + */ +static err_t +tcp_write_checks(struct tcp_pcb *pcb, u16_t len) +{ + /* connection is in invalid state for data transmission? */ + if ((pcb->state != ESTABLISHED) && + (pcb->state != CLOSE_WAIT) && + (pcb->state != SYN_SENT) && + (pcb->state != SYN_RCVD)) { + LWIP_DEBUGF(TCP_OUTPUT_DEBUG | LWIP_DBG_STATE | LWIP_DBG_LEVEL_SEVERE, ("tcp_write() called in invalid state\n")); + return ERR_CONN; + } else if (len == 0) { + return ERR_OK; + } + + /* fail on too much data */ + if (len > pcb->snd_buf) { + LWIP_DEBUGF(TCP_OUTPUT_DEBUG | LWIP_DBG_LEVEL_SEVERE, ("tcp_write: too much data (len=%"U16_F" > snd_buf=%"TCPWNDSIZE_F")\n", + len, pcb->snd_buf)); + pcb->flags |= TF_NAGLEMEMERR; + return ERR_MEM; + } + + LWIP_DEBUGF(TCP_QLEN_DEBUG, ("tcp_write: queuelen: %"TCPWNDSIZE_F"\n", (tcpwnd_size_t)pcb->snd_queuelen)); + + /* If total number of pbufs on the unsent/unacked queues exceeds the + * configured maximum, return an error */ + /* check for configured max queuelen and possible overflow */ + if ((pcb->snd_queuelen >= TCP_SND_QUEUELEN) || (pcb->snd_queuelen > TCP_SNDQUEUELEN_OVERFLOW)) { + LWIP_DEBUGF(TCP_OUTPUT_DEBUG | LWIP_DBG_LEVEL_SEVERE, ("tcp_write: too long queue %"U16_F" (max %"U16_F")\n", + pcb->snd_queuelen, TCP_SND_QUEUELEN)); + TCP_STATS_INC(tcp.memerr); + pcb->flags |= TF_NAGLEMEMERR; + return ERR_MEM; + } + if (pcb->snd_queuelen != 0) { + LWIP_ASSERT("tcp_write: pbufs on queue => at least one queue non-empty", + pcb->unacked != NULL || pcb->unsent != NULL); + } else { + LWIP_ASSERT("tcp_write: no pbufs on queue => both queues empty", + pcb->unacked == NULL && pcb->unsent == NULL); + } + return ERR_OK; +} + +/** + * Write data for sending (but does not send it immediately). + * + * It waits in the expectation of more data being sent soon (as + * it can send them more efficiently by combining them together). + * To prompt the system to send data now, call tcp_output() after + * calling tcp_write(). + * + * @param pcb Protocol control block for the TCP connection to enqueue data for. + * @param arg Pointer to the data to be enqueued for sending. + * @param len Data length in bytes + * @param apiflags combination of following flags : + * - TCP_WRITE_FLAG_COPY (0x01) data will be copied into memory belonging to the stack + * - TCP_WRITE_FLAG_MORE (0x02) for TCP connection, PSH flag will not be set on last segment sent, + * @return ERR_OK if enqueued, another err_t on error + */ +err_t +tcp_write(struct tcp_pcb *pcb, const void *arg, u16_t len, u8_t apiflags) +{ + struct pbuf *concat_p = NULL; + struct tcp_seg *last_unsent = NULL, *seg = NULL, *prev_seg = NULL, *queue = NULL; + u16_t pos = 0; /* position in 'arg' data */ + u16_t queuelen; + u8_t optlen = 0; + u8_t optflags = 0; +#if TCP_OVERSIZE + u16_t oversize = 0; + u16_t oversize_used = 0; +#endif /* TCP_OVERSIZE */ +#if TCP_CHECKSUM_ON_COPY + u16_t concat_chksum = 0; + u8_t concat_chksum_swapped = 0; + u16_t concat_chksummed = 0; +#endif /* TCP_CHECKSUM_ON_COPY */ + err_t err; + /* don't allocate segments bigger than half the maximum window we ever received */ + u16_t mss_local = LWIP_MIN(pcb->mss, TCPWND_MIN16(pcb->snd_wnd_max/2)); + mss_local = mss_local ? mss_local : pcb->mss; + +#if LWIP_NETIF_TX_SINGLE_PBUF + /* Always copy to try to create single pbufs for TX */ + apiflags |= TCP_WRITE_FLAG_COPY; +#endif /* LWIP_NETIF_TX_SINGLE_PBUF */ + + LWIP_DEBUGF(TCP_OUTPUT_DEBUG, ("tcp_write(pcb=%p, data=%p, len=%"U16_F", apiflags=%"U16_F")\n", + (void *)pcb, arg, len, (u16_t)apiflags)); + LWIP_ERROR("tcp_write: arg == NULL (programmer violates API)", + arg != NULL, return ERR_ARG;); + + err = tcp_write_checks(pcb, len); + if (err != ERR_OK) { + return err; + } + queuelen = pcb->snd_queuelen; + +#if LWIP_TCP_TIMESTAMPS + if ((pcb->flags & TF_TIMESTAMP)) { + /* Make sure the timestamp option is only included in data segments if we + agreed about it with the remote host. */ + optflags = TF_SEG_OPTS_TS; + optlen = LWIP_TCP_OPT_LENGTH(TF_SEG_OPTS_TS); + /* ensure that segments can hold at least one data byte... */ + mss_local = LWIP_MAX(mss_local, LWIP_TCP_OPT_LEN_TS + 1); + } +#endif /* LWIP_TCP_TIMESTAMPS */ + + + /* + * TCP segmentation is done in three phases with increasing complexity: + * + * 1. Copy data directly into an oversized pbuf. + * 2. Chain a new pbuf to the end of pcb->unsent. + * 3. Create new segments. + * + * We may run out of memory at any point. In that case we must + * return ERR_MEM and not change anything in pcb. Therefore, all + * changes are recorded in local variables and committed at the end + * of the function. Some pcb fields are maintained in local copies: + * + * queuelen = pcb->snd_queuelen + * oversize = pcb->unsent_oversize + * + * These variables are set consistently by the phases: + * + * seg points to the last segment tampered with. + * + * pos records progress as data is segmented. + */ + + /* Find the tail of the unsent queue. */ + if (pcb->unsent != NULL) { + u16_t space; + u16_t unsent_optlen; + + /* @todo: this could be sped up by keeping last_unsent in the pcb */ + for (last_unsent = pcb->unsent; last_unsent->next != NULL; + last_unsent = last_unsent->next); + + /* Usable space at the end of the last unsent segment */ + unsent_optlen = LWIP_TCP_OPT_LENGTH(last_unsent->flags); + LWIP_ASSERT("mss_local is too small", mss_local >= last_unsent->len + unsent_optlen); + space = mss_local - (last_unsent->len + unsent_optlen); + + /* + * Phase 1: Copy data directly into an oversized pbuf. + * + * The number of bytes copied is recorded in the oversize_used + * variable. The actual copying is done at the bottom of the + * function. + */ +#if TCP_OVERSIZE +#if TCP_OVERSIZE_DBGCHECK + /* check that pcb->unsent_oversize matches last_unsent->unsent_oversize */ + LWIP_ASSERT("unsent_oversize mismatch (pcb vs. last_unsent)", + pcb->unsent_oversize == last_unsent->oversize_left); +#endif /* TCP_OVERSIZE_DBGCHECK */ + oversize = pcb->unsent_oversize; + if (oversize > 0) { + LWIP_ASSERT("inconsistent oversize vs. space", oversize_used <= space); + seg = last_unsent; + oversize_used = oversize < len ? oversize : len; + pos += oversize_used; + oversize -= oversize_used; + space -= oversize_used; + } + /* now we are either finished or oversize is zero */ + LWIP_ASSERT("inconsistend oversize vs. len", (oversize == 0) || (pos == len)); +#endif /* TCP_OVERSIZE */ + + /* + * Phase 2: Chain a new pbuf to the end of pcb->unsent. + * + * We don't extend segments containing SYN/FIN flags or options + * (len==0). The new pbuf is kept in concat_p and pbuf_cat'ed at + * the end. + */ + if ((pos < len) && (space > 0) && (last_unsent->len > 0)) { + u16_t seglen = space < len - pos ? space : len - pos; + seg = last_unsent; + + /* Create a pbuf with a copy or reference to seglen bytes. We + * can use PBUF_RAW here since the data appears in the middle of + * a segment. A header will never be prepended. */ + if (apiflags & TCP_WRITE_FLAG_COPY) { + /* Data is copied */ + if ((concat_p = tcp_pbuf_prealloc(PBUF_RAW, seglen, space, &oversize, pcb, apiflags, 1)) == NULL) { + LWIP_DEBUGF(TCP_OUTPUT_DEBUG | LWIP_DBG_LEVEL_SERIOUS, + ("tcp_write : could not allocate memory for pbuf copy size %"U16_F"\n", + seglen)); + goto memerr; + } +#if TCP_OVERSIZE_DBGCHECK + last_unsent->oversize_left += oversize; +#endif /* TCP_OVERSIZE_DBGCHECK */ + TCP_DATA_COPY2(concat_p->payload, (const u8_t*)arg + pos, seglen, &concat_chksum, &concat_chksum_swapped); +#if TCP_CHECKSUM_ON_COPY + concat_chksummed += seglen; +#endif /* TCP_CHECKSUM_ON_COPY */ + } else { + /* Data is not copied */ + if ((concat_p = pbuf_alloc(PBUF_RAW, seglen, PBUF_ROM)) == NULL) { + LWIP_DEBUGF(TCP_OUTPUT_DEBUG | LWIP_DBG_LEVEL_SERIOUS, + ("tcp_write: could not allocate memory for zero-copy pbuf\n")); + goto memerr; + } +#if TCP_CHECKSUM_ON_COPY + /* calculate the checksum of nocopy-data */ + tcp_seg_add_chksum(~inet_chksum((const u8_t*)arg + pos, seglen), seglen, + &concat_chksum, &concat_chksum_swapped); + concat_chksummed += seglen; +#endif /* TCP_CHECKSUM_ON_COPY */ + /* reference the non-volatile payload data */ + ((struct pbuf_rom*)concat_p)->payload = (const u8_t*)arg + pos; + } + + pos += seglen; + queuelen += pbuf_clen(concat_p); + } + } else { +#if TCP_OVERSIZE + LWIP_ASSERT("unsent_oversize mismatch (pcb->unsent is NULL)", + pcb->unsent_oversize == 0); +#endif /* TCP_OVERSIZE */ + } + + /* + * Phase 3: Create new segments. + * + * The new segments are chained together in the local 'queue' + * variable, ready to be appended to pcb->unsent. + */ + while (pos < len) { + struct pbuf *p; + u16_t left = len - pos; + u16_t max_len = mss_local - optlen; + u16_t seglen = left > max_len ? max_len : left; +#if TCP_CHECKSUM_ON_COPY + u16_t chksum = 0; + u8_t chksum_swapped = 0; +#endif /* TCP_CHECKSUM_ON_COPY */ + + if (apiflags & TCP_WRITE_FLAG_COPY) { + /* If copy is set, memory should be allocated and data copied + * into pbuf */ + if ((p = tcp_pbuf_prealloc(PBUF_TRANSPORT, seglen + optlen, mss_local, &oversize, pcb, apiflags, queue == NULL)) == NULL) { + LWIP_DEBUGF(TCP_OUTPUT_DEBUG | LWIP_DBG_LEVEL_SERIOUS, ("tcp_write : could not allocate memory for pbuf copy size %"U16_F"\n", seglen)); + goto memerr; + } + LWIP_ASSERT("tcp_write: check that first pbuf can hold the complete seglen", + (p->len >= seglen)); + TCP_DATA_COPY2((char *)p->payload + optlen, (const u8_t*)arg + pos, seglen, &chksum, &chksum_swapped); + } else { + /* Copy is not set: First allocate a pbuf for holding the data. + * Since the referenced data is available at least until it is + * sent out on the link (as it has to be ACKed by the remote + * party) we can safely use PBUF_ROM instead of PBUF_REF here. + */ + struct pbuf *p2; +#if TCP_OVERSIZE + LWIP_ASSERT("oversize == 0", oversize == 0); +#endif /* TCP_OVERSIZE */ + if ((p2 = pbuf_alloc(PBUF_TRANSPORT, seglen, PBUF_ROM)) == NULL) { + LWIP_DEBUGF(TCP_OUTPUT_DEBUG | LWIP_DBG_LEVEL_SERIOUS, ("tcp_write: could not allocate memory for zero-copy pbuf\n")); + goto memerr; + } +#if TCP_CHECKSUM_ON_COPY + /* calculate the checksum of nocopy-data */ + chksum = ~inet_chksum((const u8_t*)arg + pos, seglen); + if (seglen & 1) { + chksum_swapped = 1; + chksum = SWAP_BYTES_IN_WORD(chksum); + } +#endif /* TCP_CHECKSUM_ON_COPY */ + /* reference the non-volatile payload data */ + ((struct pbuf_rom*)p2)->payload = (const u8_t*)arg + pos; + + /* Second, allocate a pbuf for the headers. */ + if ((p = pbuf_alloc(PBUF_TRANSPORT, optlen, PBUF_RAM)) == NULL) { + /* If allocation fails, we have to deallocate the data pbuf as + * well. */ + pbuf_free(p2); + LWIP_DEBUGF(TCP_OUTPUT_DEBUG | LWIP_DBG_LEVEL_SERIOUS, ("tcp_write: could not allocate memory for header pbuf\n")); + goto memerr; + } + /* Concatenate the headers and data pbufs together. */ + pbuf_cat(p/*header*/, p2/*data*/); + } + + queuelen += pbuf_clen(p); + + /* Now that there are more segments queued, we check again if the + * length of the queue exceeds the configured maximum or + * overflows. */ + if ((queuelen > TCP_SND_QUEUELEN) || (queuelen > TCP_SNDQUEUELEN_OVERFLOW)) { + LWIP_DEBUGF(TCP_OUTPUT_DEBUG | LWIP_DBG_LEVEL_SERIOUS, ("tcp_write: queue too long %"U16_F" (%d)\n", + queuelen, (int)TCP_SND_QUEUELEN)); + pbuf_free(p); + goto memerr; + } + + if ((seg = tcp_create_segment(pcb, p, 0, pcb->snd_lbb + pos, optflags)) == NULL) { + goto memerr; + } +#if TCP_OVERSIZE_DBGCHECK + seg->oversize_left = oversize; +#endif /* TCP_OVERSIZE_DBGCHECK */ +#if TCP_CHECKSUM_ON_COPY + seg->chksum = chksum; + seg->chksum_swapped = chksum_swapped; + seg->flags |= TF_SEG_DATA_CHECKSUMMED; +#endif /* TCP_CHECKSUM_ON_COPY */ + + /* first segment of to-be-queued data? */ + if (queue == NULL) { + queue = seg; + } else { + /* Attach the segment to the end of the queued segments */ + LWIP_ASSERT("prev_seg != NULL", prev_seg != NULL); + prev_seg->next = seg; + } + /* remember last segment of to-be-queued data for next iteration */ + prev_seg = seg; + + LWIP_DEBUGF(TCP_OUTPUT_DEBUG | LWIP_DBG_TRACE, ("tcp_write: queueing %"U32_F":%"U32_F"\n", + ntohl(seg->tcphdr->seqno), + ntohl(seg->tcphdr->seqno) + TCP_TCPLEN(seg))); + + pos += seglen; + } + + /* + * All three segmentation phases were successful. We can commit the + * transaction. + */ + + /* + * Phase 1: If data has been added to the preallocated tail of + * last_unsent, we update the length fields of the pbuf chain. + */ +#if TCP_OVERSIZE + if (oversize_used > 0) { + struct pbuf *p; + /* Bump tot_len of whole chain, len of tail */ + for (p = last_unsent->p; p; p = p->next) { + p->tot_len += oversize_used; + if (p->next == NULL) { + TCP_DATA_COPY((char *)p->payload + p->len, arg, oversize_used, last_unsent); + p->len += oversize_used; + } + } + last_unsent->len += oversize_used; +#if TCP_OVERSIZE_DBGCHECK + LWIP_ASSERT("last_unsent->oversize_left >= oversize_used", + last_unsent->oversize_left >= oversize_used); + last_unsent->oversize_left -= oversize_used; +#endif /* TCP_OVERSIZE_DBGCHECK */ + } + pcb->unsent_oversize = oversize; +#endif /* TCP_OVERSIZE */ + + /* + * Phase 2: concat_p can be concatenated onto last_unsent->p + */ + if (concat_p != NULL) { + LWIP_ASSERT("tcp_write: cannot concatenate when pcb->unsent is empty", + (last_unsent != NULL)); + pbuf_cat(last_unsent->p, concat_p); + last_unsent->len += concat_p->tot_len; +#if TCP_CHECKSUM_ON_COPY + if (concat_chksummed) { + /*if concat checksumm swapped - swap it back */ + if (concat_chksum_swapped) { + concat_chksum = SWAP_BYTES_IN_WORD(concat_chksum); + } + tcp_seg_add_chksum(concat_chksum, concat_chksummed, &last_unsent->chksum, + &last_unsent->chksum_swapped); + last_unsent->flags |= TF_SEG_DATA_CHECKSUMMED; + } +#endif /* TCP_CHECKSUM_ON_COPY */ + } + + /* + * Phase 3: Append queue to pcb->unsent. Queue may be NULL, but that + * is harmless + */ + if (last_unsent == NULL) { + pcb->unsent = queue; + } else { + last_unsent->next = queue; + } + + /* + * Finally update the pcb state. + */ + pcb->snd_lbb += len; + pcb->snd_buf -= len; + pcb->snd_queuelen = queuelen; + + LWIP_DEBUGF(TCP_QLEN_DEBUG, ("tcp_write: %"S16_F" (after enqueued)\n", + pcb->snd_queuelen)); + if (pcb->snd_queuelen != 0) { + LWIP_ASSERT("tcp_write: valid queue length", + pcb->unacked != NULL || pcb->unsent != NULL); + } + + /* Set the PSH flag in the last segment that we enqueued. */ + if (seg != NULL && seg->tcphdr != NULL && ((apiflags & TCP_WRITE_FLAG_MORE)==0)) { + TCPH_SET_FLAG(seg->tcphdr, TCP_PSH); + } + + return ERR_OK; +memerr: + pcb->flags |= TF_NAGLEMEMERR; + TCP_STATS_INC(tcp.memerr); + + if (concat_p != NULL) { + pbuf_free(concat_p); + } + if (queue != NULL) { + tcp_segs_free(queue); + } + if (pcb->snd_queuelen != 0) { + LWIP_ASSERT("tcp_write: valid queue length", pcb->unacked != NULL || + pcb->unsent != NULL); + } + LWIP_DEBUGF(TCP_QLEN_DEBUG | LWIP_DBG_STATE, ("tcp_write: %"S16_F" (with mem err)\n", pcb->snd_queuelen)); + return ERR_MEM; +} + +/** + * Enqueue TCP options for transmission. + * + * Called by tcp_connect(), tcp_listen_input(), and tcp_send_ctrl(). + * + * @param pcb Protocol control block for the TCP connection. + * @param flags TCP header flags to set in the outgoing segment. + * @param optdata pointer to TCP options, or NULL. + * @param optlen length of TCP options in bytes. + */ +err_t +tcp_enqueue_flags(struct tcp_pcb *pcb, u8_t flags) +{ + struct pbuf *p; + struct tcp_seg *seg; + u8_t optflags = 0; + u8_t optlen = 0; + + LWIP_DEBUGF(TCP_QLEN_DEBUG, ("tcp_enqueue_flags: queuelen: %"U16_F"\n", (u16_t)pcb->snd_queuelen)); + + LWIP_ASSERT("tcp_enqueue_flags: need either TCP_SYN or TCP_FIN in flags (programmer violates API)", + (flags & (TCP_SYN | TCP_FIN)) != 0); + + /* check for configured max queuelen and possible overflow (FIN flag should always come through!) */ + if (((pcb->snd_queuelen >= TCP_SND_QUEUELEN) || (pcb->snd_queuelen > TCP_SNDQUEUELEN_OVERFLOW)) && + ((flags & TCP_FIN) == 0)) { + LWIP_DEBUGF(TCP_OUTPUT_DEBUG | LWIP_DBG_LEVEL_SEVERE, ("tcp_enqueue_flags: too long queue %"U16_F" (max %"U16_F")\n", + pcb->snd_queuelen, TCP_SND_QUEUELEN)); + TCP_STATS_INC(tcp.memerr); + pcb->flags |= TF_NAGLEMEMERR; + return ERR_MEM; + } + + if (flags & TCP_SYN) { + optflags = TF_SEG_OPTS_MSS; +#if LWIP_WND_SCALE + if ((pcb->state != SYN_RCVD) || (pcb->flags & TF_WND_SCALE)) { + /* In a (sent in state SYN_RCVD), the window scale option may only + be sent if we received a window scale option from the remote host. */ + optflags |= TF_SEG_OPTS_WND_SCALE; + } +#endif /* LWIP_WND_SCALE */ + } +#if LWIP_TCP_TIMESTAMPS + if ((pcb->flags & TF_TIMESTAMP)) { + /* Make sure the timestamp option is only included in data segments if we + agreed about it with the remote host. */ + optflags |= TF_SEG_OPTS_TS; + } +#endif /* LWIP_TCP_TIMESTAMPS */ + optlen = LWIP_TCP_OPT_LENGTH(optflags); + + /* tcp_enqueue_flags is always called with either SYN or FIN in flags. + * We need one available snd_buf byte to do that. + * This means we can't send FIN while snd_buf==0. A better fix would be to + * not include SYN and FIN sequence numbers in the snd_buf count. */ + if (pcb->snd_buf == 0) { + LWIP_DEBUGF(TCP_OUTPUT_DEBUG | LWIP_DBG_LEVEL_SEVERE, ("tcp_enqueue_flags: no send buffer available\n")); + TCP_STATS_INC(tcp.memerr); + return ERR_MEM; + } + + /* Allocate pbuf with room for TCP header + options */ + if ((p = pbuf_alloc(PBUF_TRANSPORT, optlen, PBUF_RAM)) == NULL) { + pcb->flags |= TF_NAGLEMEMERR; + TCP_STATS_INC(tcp.memerr); + return ERR_MEM; + } + LWIP_ASSERT("tcp_enqueue_flags: check that first pbuf can hold optlen", + (p->len >= optlen)); + + /* Allocate memory for tcp_seg, and fill in fields. */ + if ((seg = tcp_create_segment(pcb, p, flags, pcb->snd_lbb, optflags)) == NULL) { + pcb->flags |= TF_NAGLEMEMERR; + TCP_STATS_INC(tcp.memerr); + return ERR_MEM; + } + LWIP_ASSERT("seg->tcphdr not aligned", ((mem_ptr_t)seg->tcphdr % LWIP_MIN(MEM_ALIGNMENT, 4)) == 0); + LWIP_ASSERT("tcp_enqueue_flags: invalid segment length", seg->len == 0); + + LWIP_DEBUGF(TCP_OUTPUT_DEBUG | LWIP_DBG_TRACE, + ("tcp_enqueue_flags: queueing %"U32_F":%"U32_F" (0x%"X16_F")\n", + ntohl(seg->tcphdr->seqno), + ntohl(seg->tcphdr->seqno) + TCP_TCPLEN(seg), + (u16_t)flags)); + + /* Now append seg to pcb->unsent queue */ + if (pcb->unsent == NULL) { + pcb->unsent = seg; + } else { + struct tcp_seg *useg; + for (useg = pcb->unsent; useg->next != NULL; useg = useg->next); + useg->next = seg; + } +#if TCP_OVERSIZE + /* The new unsent tail has no space */ + pcb->unsent_oversize = 0; +#endif /* TCP_OVERSIZE */ + + /* SYN and FIN bump the sequence number */ + if ((flags & TCP_SYN) || (flags & TCP_FIN)) { + pcb->snd_lbb++; + /* optlen does not influence snd_buf */ + pcb->snd_buf--; + } + if (flags & TCP_FIN) { + pcb->flags |= TF_FIN; + } + + /* update number of segments on the queues */ + pcb->snd_queuelen += pbuf_clen(seg->p); + LWIP_DEBUGF(TCP_QLEN_DEBUG, ("tcp_enqueue_flags: %"S16_F" (after enqueued)\n", pcb->snd_queuelen)); + if (pcb->snd_queuelen != 0) { + LWIP_ASSERT("tcp_enqueue_flags: invalid queue length", + pcb->unacked != NULL || pcb->unsent != NULL); + } + + return ERR_OK; +} + +#if LWIP_TCP_TIMESTAMPS +/* Build a timestamp option (12 bytes long) at the specified options pointer) + * + * @param pcb tcp_pcb + * @param opts option pointer where to store the timestamp option + */ +static void +tcp_build_timestamp_option(struct tcp_pcb *pcb, u32_t *opts) +{ + /* Pad with two NOP options to make everything nicely aligned */ + opts[0] = PP_HTONL(0x0101080A); + opts[1] = htonl(sys_now()); + opts[2] = htonl(pcb->ts_recent); +} +#endif + +#if LWIP_WND_SCALE +/** Build a window scale option (3 bytes long) at the specified options pointer) + * + * @param opts option pointer where to store the window scale option + */ +static void +tcp_build_wnd_scale_option(u32_t *opts) +{ + /* Pad with one NOP option to make everything nicely aligned */ + opts[0] = PP_HTONL(0x01030300 | TCP_RCV_SCALE); +} +#endif + +/** Send an ACK without data. + * + * @param pcb Protocol control block for the TCP connection to send the ACK + */ +err_t +tcp_send_empty_ack(struct tcp_pcb *pcb) +{ + err_t err; + struct pbuf *p; + u8_t optlen = 0; + struct netif *netif; +#if LWIP_TCP_TIMESTAMPS || CHECKSUM_GEN_TCP + struct tcp_hdr *tcphdr; +#endif /* LWIP_TCP_TIMESTAMPS || CHECKSUM_GEN_TCP */ + +#if LWIP_TCP_TIMESTAMPS + if (pcb->flags & TF_TIMESTAMP) { + optlen = LWIP_TCP_OPT_LENGTH(TF_SEG_OPTS_TS); + } +#endif + + p = tcp_output_alloc_header(pcb, optlen, 0, htonl(pcb->snd_nxt)); + if (p == NULL) { + /* let tcp_fasttmr retry sending this ACK */ + pcb->flags |= (TF_ACK_DELAY | TF_ACK_NOW); + LWIP_DEBUGF(TCP_OUTPUT_DEBUG, ("tcp_output: (ACK) could not allocate pbuf\n")); + return ERR_BUF; + } +#if LWIP_TCP_TIMESTAMPS || CHECKSUM_GEN_TCP + tcphdr = (struct tcp_hdr *)p->payload; +#endif /* LWIP_TCP_TIMESTAMPS || CHECKSUM_GEN_TCP */ + LWIP_DEBUGF(TCP_OUTPUT_DEBUG, + ("tcp_output: sending ACK for %"U32_F"\n", pcb->rcv_nxt)); + + /* NB. MSS and window scale options are only sent on SYNs, so ignore them here */ +#if LWIP_TCP_TIMESTAMPS + pcb->ts_lastacksent = pcb->rcv_nxt; + + if (pcb->flags & TF_TIMESTAMP) { + tcp_build_timestamp_option(pcb, (u32_t *)(tcphdr + 1)); + } +#endif + + netif = ip_route(&pcb->local_ip, &pcb->remote_ip); + if (netif == NULL) { + err = ERR_RTE; + } else { +#if CHECKSUM_GEN_TCP + IF__NETIF_CHECKSUM_ENABLED(netif, NETIF_CHECKSUM_GEN_TCP) { + tcphdr->chksum = ip_chksum_pseudo(p, IP_PROTO_TCP, p->tot_len, + &pcb->local_ip, &pcb->remote_ip); + } +#endif + NETIF_SET_HWADDRHINT(netif, &(pcb->addr_hint)); + err = ip_output_if(p, &pcb->local_ip, &pcb->remote_ip, + pcb->ttl, pcb->tos, IP_PROTO_TCP, netif); + NETIF_SET_HWADDRHINT(netif, NULL); + } + pbuf_free(p); + + if (err != ERR_OK) { + /* let tcp_fasttmr retry sending this ACK */ + pcb->flags |= (TF_ACK_DELAY | TF_ACK_NOW); + } else { + /* remove ACK flags from the PCB, as we sent an empty ACK now */ + pcb->flags &= ~(TF_ACK_DELAY | TF_ACK_NOW); + } + + return err; +} + +/** + * Find out what we can send and send it + * + * @param pcb Protocol control block for the TCP connection to send data + * @return ERR_OK if data has been sent or nothing to send + * another err_t on error + */ +err_t +tcp_output(struct tcp_pcb *pcb) +{ + struct tcp_seg *seg, *useg; + u32_t wnd, snd_nxt; + err_t err; +#if TCP_CWND_DEBUG + s16_t i = 0; +#endif /* TCP_CWND_DEBUG */ + + + /* pcb->state LISTEN not allowed here */ + LWIP_ASSERT("don't call tcp_output for listen-pcbs", + pcb->state != LISTEN); + + /* First, check if we are invoked by the TCP input processing + code. If so, we do not output anything. Instead, we rely on the + input processing code to call us when input processing is done + with. */ + if (tcp_input_pcb == pcb) { + + return ERR_OK; + } + + wnd = LWIP_MIN(pcb->snd_wnd, pcb->cwnd); + + seg = pcb->unsent; + + /* If the TF_ACK_NOW flag is set and no data will be sent (either + * because the ->unsent queue is empty or because the window does + * not allow it), construct an empty ACK segment and send it. + * + * If data is to be sent, we will just piggyback the ACK (see below). + */ + if (pcb->flags & TF_ACK_NOW && + (seg == NULL || + ntohl(seg->tcphdr->seqno) - pcb->lastack + seg->len > wnd)) { + return tcp_send_empty_ack(pcb); + } + + /* useg should point to last segment on unacked queue */ + useg = pcb->unacked; + if (useg != NULL) { + for (; useg->next != NULL; useg = useg->next); + } + +#if TCP_OUTPUT_DEBUG + if (seg == NULL) { + LWIP_DEBUGF(TCP_OUTPUT_DEBUG, ("tcp_output: nothing to send (%p)\n", + (void*)pcb->unsent)); + } +#endif /* TCP_OUTPUT_DEBUG */ +#if TCP_CWND_DEBUG + if (seg == NULL) { + LWIP_DEBUGF(TCP_CWND_DEBUG, ("tcp_output: snd_wnd %"TCPWNDSIZE_F + ", cwnd %"TCPWNDSIZE_F", wnd %"U32_F + ", seg == NULL, ack %"U32_F"\n", + pcb->snd_wnd, pcb->cwnd, wnd, pcb->lastack)); + } else { + LWIP_DEBUGF(TCP_CWND_DEBUG, + ("tcp_output: snd_wnd %"TCPWNDSIZE_F", cwnd %"TCPWNDSIZE_F", wnd %"U32_F + ", effwnd %"U32_F", seq %"U32_F", ack %"U32_F"\n", + pcb->snd_wnd, pcb->cwnd, wnd, + ntohl(seg->tcphdr->seqno) - pcb->lastack + seg->len, + ntohl(seg->tcphdr->seqno), pcb->lastack)); + } +#endif /* TCP_CWND_DEBUG */ + /* data available and window allows it to be sent? */ + while (seg != NULL && + ntohl(seg->tcphdr->seqno) - pcb->lastack + seg->len <= wnd) { + LWIP_ASSERT("RST not expected here!", + (TCPH_FLAGS(seg->tcphdr) & TCP_RST) == 0); + /* Stop sending if the nagle algorithm would prevent it + * Don't stop: + * - if tcp_write had a memory error before (prevent delayed ACK timeout) or + * - if FIN was already enqueued for this PCB (SYN is always alone in a segment - + * either seg->next != NULL or pcb->unacked == NULL; + * RST is no sent using tcp_write/tcp_output. + */ + if((tcp_do_output_nagle(pcb) == 0) && + ((pcb->flags & (TF_NAGLEMEMERR | TF_FIN)) == 0)) { + break; + } +#if TCP_CWND_DEBUG + LWIP_DEBUGF(TCP_CWND_DEBUG, ("tcp_output: snd_wnd %"TCPWNDSIZE_F", cwnd %"TCPWNDSIZE_F", wnd %"U32_F", effwnd %"U32_F", seq %"U32_F", ack %"U32_F", i %"S16_F"\n", + pcb->snd_wnd, pcb->cwnd, wnd, + ntohl(seg->tcphdr->seqno) + seg->len - + pcb->lastack, + ntohl(seg->tcphdr->seqno), pcb->lastack, i)); + ++i; +#endif /* TCP_CWND_DEBUG */ + + if (pcb->state != SYN_SENT) { + TCPH_SET_FLAG(seg->tcphdr, TCP_ACK); + } + +#if TCP_OVERSIZE_DBGCHECK + seg->oversize_left = 0; +#endif /* TCP_OVERSIZE_DBGCHECK */ + err = tcp_output_segment(seg, pcb); + if (err != ERR_OK) { + /* segment could not be sent, for whatever reason */ + pcb->flags |= TF_NAGLEMEMERR; + return err; + } + pcb->unsent = seg->next; + if (pcb->state != SYN_SENT) { + pcb->flags &= ~(TF_ACK_DELAY | TF_ACK_NOW); + } + snd_nxt = ntohl(seg->tcphdr->seqno) + TCP_TCPLEN(seg); + if (TCP_SEQ_LT(pcb->snd_nxt, snd_nxt)) { + pcb->snd_nxt = snd_nxt; + } + /* put segment on unacknowledged list if length > 0 */ + if (TCP_TCPLEN(seg) > 0) { + seg->next = NULL; + /* unacked list is empty? */ + if (pcb->unacked == NULL) { + pcb->unacked = seg; + useg = seg; + /* unacked list is not empty? */ + } else { + /* In the case of fast retransmit, the packet should not go to the tail + * of the unacked queue, but rather somewhere before it. We need to check for + * this case. -STJ Jul 27, 2004 */ + if (TCP_SEQ_LT(ntohl(seg->tcphdr->seqno), ntohl(useg->tcphdr->seqno))) { + /* add segment to before tail of unacked list, keeping the list sorted */ + struct tcp_seg **cur_seg = &(pcb->unacked); + while (*cur_seg && + TCP_SEQ_LT(ntohl((*cur_seg)->tcphdr->seqno), ntohl(seg->tcphdr->seqno))) { + cur_seg = &((*cur_seg)->next ); + } + seg->next = (*cur_seg); + (*cur_seg) = seg; + } else { + /* add segment to tail of unacked list */ + useg->next = seg; + useg = useg->next; + } + } + /* do not queue empty segments on the unacked list */ + } else { + tcp_seg_free(seg); + } + seg = pcb->unsent; + } +#if TCP_OVERSIZE + if (pcb->unsent == NULL) { + /* last unsent has been removed, reset unsent_oversize */ + pcb->unsent_oversize = 0; + } +#endif /* TCP_OVERSIZE */ + + pcb->flags &= ~TF_NAGLEMEMERR; + return ERR_OK; +} + +/** + * Called by tcp_output() to actually send a TCP segment over IP. + * + * @param seg the tcp_seg to send + * @param pcb the tcp_pcb for the TCP connection used to send the segment + */ +static err_t +tcp_output_segment(struct tcp_seg *seg, struct tcp_pcb *pcb) +{ + err_t err; + u16_t len; + u32_t *opts; + struct netif *netif; + + /** @bug Exclude retransmitted segments from this count. */ + MIB2_STATS_INC(mib2.tcpoutsegs); + + /* The TCP header has already been constructed, but the ackno and + wnd fields remain. */ + seg->tcphdr->ackno = htonl(pcb->rcv_nxt); + + /* advertise our receive window size in this TCP segment */ +#if LWIP_WND_SCALE + if (seg->flags & TF_SEG_OPTS_WND_SCALE) { + /* The Window field in a SYN segment itself (the only type where we send + the window scale option) is never scaled. */ + seg->tcphdr->wnd = htons(TCPWND_MIN16(pcb->rcv_ann_wnd)); + } else +#endif /* LWIP_WND_SCALE */ + { + seg->tcphdr->wnd = htons(TCPWND_MIN16(RCV_WND_SCALE(pcb, pcb->rcv_ann_wnd))); + } + + pcb->rcv_ann_right_edge = pcb->rcv_nxt + pcb->rcv_ann_wnd; + + /* Add any requested options. NB MSS option is only set on SYN + packets, so ignore it here */ + opts = (u32_t *)(void *)(seg->tcphdr + 1); + if (seg->flags & TF_SEG_OPTS_MSS) { + u16_t mss; +#if TCP_CALCULATE_EFF_SEND_MSS + mss = tcp_eff_send_mss(TCP_MSS, &pcb->local_ip, &pcb->remote_ip); +#else /* TCP_CALCULATE_EFF_SEND_MSS */ + mss = TCP_MSS; +#endif /* TCP_CALCULATE_EFF_SEND_MSS */ + *opts = TCP_BUILD_MSS_OPTION(mss); + opts += 1; + } +#if LWIP_TCP_TIMESTAMPS + pcb->ts_lastacksent = pcb->rcv_nxt; + + if (seg->flags & TF_SEG_OPTS_TS) { + tcp_build_timestamp_option(pcb, opts); + opts += 3; + } +#endif +#if LWIP_WND_SCALE + if (seg->flags & TF_SEG_OPTS_WND_SCALE) { + tcp_build_wnd_scale_option(opts); + opts += 1; + } +#endif + + /* Set retransmission timer running if it is not currently enabled + This must be set before checking the route. */ + if (pcb->rtime == -1) { + pcb->rtime = 0; + } + + netif = ip_route(&pcb->local_ip, &pcb->remote_ip); + if (netif == NULL) { + return ERR_RTE; + } + + /* If we don't have a local IP address, we get one from netif */ + if (ip_addr_isany(&pcb->local_ip)) { + const ip_addr_t *local_ip = ip_netif_get_local_ip(netif, &pcb->remote_ip); + if (local_ip == NULL) { + return ERR_RTE; + } + ip_addr_copy(pcb->local_ip, *local_ip); + } + + if (pcb->rttest == 0) { + pcb->rttest = tcp_ticks; + pcb->rtseq = ntohl(seg->tcphdr->seqno); + + LWIP_DEBUGF(TCP_RTO_DEBUG, ("tcp_output_segment: rtseq %"U32_F"\n", pcb->rtseq)); + } + LWIP_DEBUGF(TCP_OUTPUT_DEBUG, ("tcp_output_segment: %"U32_F":%"U32_F"\n", + htonl(seg->tcphdr->seqno), htonl(seg->tcphdr->seqno) + + seg->len)); + + len = (u16_t)((u8_t *)seg->tcphdr - (u8_t *)seg->p->payload); + + seg->p->len -= len; + seg->p->tot_len -= len; + + seg->p->payload = seg->tcphdr; + + seg->tcphdr->chksum = 0; +#if CHECKSUM_GEN_TCP + IF__NETIF_CHECKSUM_ENABLED(netif, NETIF_CHECKSUM_GEN_TCP) { +#if TCP_CHECKSUM_ON_COPY + u32_t acc; +#if TCP_CHECKSUM_ON_COPY_SANITY_CHECK + u16_t chksum_slow = ip_chksum_pseudo(seg->p, IP_PROTO_TCP, + seg->p->tot_len, &pcb->local_ip, &pcb->remote_ip); +#endif /* TCP_CHECKSUM_ON_COPY_SANITY_CHECK */ + if ((seg->flags & TF_SEG_DATA_CHECKSUMMED) == 0) { + LWIP_ASSERT("data included but not checksummed", + seg->p->tot_len == (TCPH_HDRLEN(seg->tcphdr) * 4)); + } + + /* rebuild TCP header checksum (TCP header changes for retransmissions!) */ + acc = ip_chksum_pseudo_partial(seg->p, IP_PROTO_TCP, + seg->p->tot_len, TCPH_HDRLEN(seg->tcphdr) * 4, &pcb->local_ip, &pcb->remote_ip); + /* add payload checksum */ + if (seg->chksum_swapped) { + seg->chksum = SWAP_BYTES_IN_WORD(seg->chksum); + seg->chksum_swapped = 0; + } + acc += (u16_t)~(seg->chksum); + seg->tcphdr->chksum = FOLD_U32T(acc); +#if TCP_CHECKSUM_ON_COPY_SANITY_CHECK + if (chksum_slow != seg->tcphdr->chksum) { + TCP_CHECKSUM_ON_COPY_SANITY_CHECK_FAIL( + ("tcp_output_segment: calculated checksum is %"X16_F" instead of %"X16_F"\n", + seg->tcphdr->chksum, chksum_slow)); + seg->tcphdr->chksum = chksum_slow; + } +#endif /* TCP_CHECKSUM_ON_COPY_SANITY_CHECK */ +#else /* TCP_CHECKSUM_ON_COPY */ + seg->tcphdr->chksum = ip_chksum_pseudo(seg->p, IP_PROTO_TCP, + seg->p->tot_len, &pcb->local_ip, &pcb->remote_ip); +#endif /* TCP_CHECKSUM_ON_COPY */ + } +#endif /* CHECKSUM_GEN_TCP */ + TCP_STATS_INC(tcp.xmit); + + NETIF_SET_HWADDRHINT(netif, &(pcb->addr_hint)); + err = ip_output_if(seg->p, &pcb->local_ip, &pcb->remote_ip, pcb->ttl, + pcb->tos, IP_PROTO_TCP, netif); + NETIF_SET_HWADDRHINT(netif, NULL); + return err; +} + +/** + * Send a TCP RESET packet (empty segment with RST flag set) either to + * abort a connection or to show that there is no matching local connection + * for a received segment. + * + * Called by tcp_abort() (to abort a local connection), tcp_input() (if no + * matching local pcb was found), tcp_listen_input() (if incoming segment + * has ACK flag set) and tcp_process() (received segment in the wrong state) + * + * Since a RST segment is in most cases not sent for an active connection, + * tcp_rst() has a number of arguments that are taken from a tcp_pcb for + * most other segment output functions. + * + * @param seqno the sequence number to use for the outgoing segment + * @param ackno the acknowledge number to use for the outgoing segment + * @param local_ip the local IP address to send the segment from + * @param remote_ip the remote IP address to send the segment to + * @param local_port the local TCP port to send the segment from + * @param remote_port the remote TCP port to send the segment to + */ +void +tcp_rst(u32_t seqno, u32_t ackno, + const ip_addr_t *local_ip, const ip_addr_t *remote_ip, + u16_t local_port, u16_t remote_port) +{ + struct pbuf *p; + struct tcp_hdr *tcphdr; + struct netif *netif; + p = pbuf_alloc(PBUF_IP, TCP_HLEN, PBUF_RAM); + if (p == NULL) { + LWIP_DEBUGF(TCP_DEBUG, ("tcp_rst: could not allocate memory for pbuf\n")); + return; + } + LWIP_ASSERT("check that first pbuf can hold struct tcp_hdr", + (p->len >= sizeof(struct tcp_hdr))); + + tcphdr = (struct tcp_hdr *)p->payload; + tcphdr->src = htons(local_port); + tcphdr->dest = htons(remote_port); + tcphdr->seqno = htonl(seqno); + tcphdr->ackno = htonl(ackno); + TCPH_HDRLEN_FLAGS_SET(tcphdr, TCP_HLEN/4, TCP_RST | TCP_ACK); +#if LWIP_WND_SCALE + tcphdr->wnd = PP_HTONS(((TCP_WND >> TCP_RCV_SCALE) & 0xFFFF)); +#else + tcphdr->wnd = PP_HTONS(TCP_WND); +#endif + tcphdr->chksum = 0; + tcphdr->urgp = 0; + + TCP_STATS_INC(tcp.xmit); + MIB2_STATS_INC(mib2.tcpoutrsts); + + netif = ip_route(local_ip, remote_ip); + if (netif != NULL) { +#if CHECKSUM_GEN_TCP + IF__NETIF_CHECKSUM_ENABLED(netif, NETIF_CHECKSUM_GEN_TCP) { + tcphdr->chksum = ip_chksum_pseudo(p, IP_PROTO_TCP, p->tot_len, + local_ip, remote_ip); + } +#endif + /* Send output with hardcoded TTL/HL since we have no access to the pcb */ + ip_output_if(p, local_ip, remote_ip, TCP_TTL, 0, IP_PROTO_TCP, netif); + } + pbuf_free(p); + LWIP_DEBUGF(TCP_RST_DEBUG, ("tcp_rst: seqno %"U32_F" ackno %"U32_F".\n", seqno, ackno)); +} + +/** + * Requeue all unacked segments for retransmission + * + * Called by tcp_slowtmr() for slow retransmission. + * + * @param pcb the tcp_pcb for which to re-enqueue all unacked segments + */ +void +tcp_rexmit_rto(struct tcp_pcb *pcb) +{ + struct tcp_seg *seg; + + if (pcb->unacked == NULL) { + return; + } + + /* Move all unacked segments to the head of the unsent queue */ + for (seg = pcb->unacked; seg->next != NULL; seg = seg->next); + /* concatenate unsent queue after unacked queue */ + seg->next = pcb->unsent; +#if TCP_OVERSIZE_DBGCHECK + /* if last unsent changed, we need to update unsent_oversize */ + if (pcb->unsent == NULL) { + pcb->unsent_oversize = seg->oversize_left; + } +#endif /* TCP_OVERSIZE_DBGCHECK */ + /* unsent queue is the concatenated queue (of unacked, unsent) */ + pcb->unsent = pcb->unacked; + /* unacked queue is now empty */ + pcb->unacked = NULL; + + /* increment number of retransmissions */ + ++pcb->nrtx; + + /* Don't take any RTT measurements after retransmitting. */ + pcb->rttest = 0; + + /* Do the actual retransmission */ + tcp_output(pcb); +} + +/** + * Requeue the first unacked segment for retransmission + * + * Called by tcp_receive() for fast retramsmit. + * + * @param pcb the tcp_pcb for which to retransmit the first unacked segment + */ +void +tcp_rexmit(struct tcp_pcb *pcb) +{ + struct tcp_seg *seg; + struct tcp_seg **cur_seg; + + if (pcb->unacked == NULL) { + return; + } + + /* Move the first unacked segment to the unsent queue */ + /* Keep the unsent queue sorted. */ + seg = pcb->unacked; + pcb->unacked = seg->next; + + cur_seg = &(pcb->unsent); + while (*cur_seg && + TCP_SEQ_LT(ntohl((*cur_seg)->tcphdr->seqno), ntohl(seg->tcphdr->seqno))) { + cur_seg = &((*cur_seg)->next ); + } + seg->next = *cur_seg; + *cur_seg = seg; +#if TCP_OVERSIZE + if (seg->next == NULL) { + /* the retransmitted segment is last in unsent, so reset unsent_oversize */ + pcb->unsent_oversize = 0; + } +#endif /* TCP_OVERSIZE */ + + ++pcb->nrtx; + + /* Don't take any rtt measurements after retransmitting. */ + pcb->rttest = 0; + + /* Do the actual retransmission. */ + MIB2_STATS_INC(mib2.tcpretranssegs); + /* No need to call tcp_output: we are always called from tcp_input() + and thus tcp_output directly returns. */ +} + + +/** + * Handle retransmission after three dupacks received + * + * @param pcb the tcp_pcb for which to retransmit the first unacked segment + */ +void +tcp_rexmit_fast(struct tcp_pcb *pcb) +{ + if (pcb->unacked != NULL && !(pcb->flags & TF_INFR)) { + /* This is fast retransmit. Retransmit the first unacked segment. */ + LWIP_DEBUGF(TCP_FR_DEBUG, + ("tcp_receive: dupacks %"U16_F" (%"U32_F + "), fast retransmit %"U32_F"\n", + (u16_t)pcb->dupacks, pcb->lastack, + ntohl(pcb->unacked->tcphdr->seqno))); + tcp_rexmit(pcb); + + /* Set ssthresh to half of the minimum of the current + * cwnd and the advertised window */ + if (pcb->cwnd > pcb->snd_wnd) { + pcb->ssthresh = pcb->snd_wnd / 2; + } else { + pcb->ssthresh = pcb->cwnd / 2; + } + + /* The minimum value for ssthresh should be 2 MSS */ + if (pcb->ssthresh < (2U * pcb->mss)) { + LWIP_DEBUGF(TCP_FR_DEBUG, + ("tcp_receive: The minimum value for ssthresh %"TCPWNDSIZE_F + " should be min 2 mss %"U16_F"...\n", + pcb->ssthresh, 2*pcb->mss)); + pcb->ssthresh = 2*pcb->mss; + } + + pcb->cwnd = pcb->ssthresh + 3 * pcb->mss; + pcb->flags |= TF_INFR; + } +} + + +/** + * Send keepalive packets to keep a connection active although + * no data is sent over it. + * + * Called by tcp_slowtmr() + * + * @param pcb the tcp_pcb for which to send a keepalive packet + */ +err_t +tcp_keepalive(struct tcp_pcb *pcb) +{ + err_t err; + struct pbuf *p; + struct netif *netif; + + LWIP_DEBUGF(TCP_DEBUG, ("tcp_keepalive: sending KEEPALIVE probe to ")); + ip_addr_debug_print(TCP_DEBUG, &pcb->remote_ip); + LWIP_DEBUGF(TCP_DEBUG, ("\n")); + + LWIP_DEBUGF(TCP_DEBUG, ("tcp_keepalive: tcp_ticks %"U32_F" pcb->tmr %"U32_F" pcb->keep_cnt_sent %"U16_F"\n", + tcp_ticks, pcb->tmr, pcb->keep_cnt_sent)); + + p = tcp_output_alloc_header(pcb, 0, 0, htonl(pcb->snd_nxt - 1)); + if (p == NULL) { + LWIP_DEBUGF(TCP_DEBUG, + ("tcp_keepalive: could not allocate memory for pbuf\n")); + return ERR_MEM; + } + netif = ip_route(&pcb->local_ip, &pcb->remote_ip); + if (netif == NULL) { + err = ERR_RTE; + } else { +#if CHECKSUM_GEN_TCP + IF__NETIF_CHECKSUM_ENABLED(netif, NETIF_CHECKSUM_GEN_TCP) { + struct tcp_hdr *tcphdr = (struct tcp_hdr *)p->payload; + tcphdr->chksum = ip_chksum_pseudo(p, IP_PROTO_TCP, p->tot_len, + &pcb->local_ip, &pcb->remote_ip); + } +#endif /* CHECKSUM_GEN_TCP */ + TCP_STATS_INC(tcp.xmit); + + /* Send output to IP */ + NETIF_SET_HWADDRHINT(netif, &(pcb->addr_hint)); + err = ip_output_if(p, &pcb->local_ip, &pcb->remote_ip, pcb->ttl, 0, IP_PROTO_TCP, netif); + NETIF_SET_HWADDRHINT(netif, NULL); + } + pbuf_free(p); + + LWIP_DEBUGF(TCP_DEBUG, ("tcp_keepalive: seqno %"U32_F" ackno %"U32_F" err %d.\n", + pcb->snd_nxt - 1, pcb->rcv_nxt, (int)err)); + return err; +} + + +/** + * Send persist timer zero-window probes to keep a connection active + * when a window update is lost. + * + * Called by tcp_slowtmr() + * + * @param pcb the tcp_pcb for which to send a zero-window probe packet + */ +err_t +tcp_zero_window_probe(struct tcp_pcb *pcb) +{ + err_t err; + struct pbuf *p; + struct tcp_hdr *tcphdr; + struct tcp_seg *seg; + u16_t len; + u8_t is_fin; + struct netif *netif; + + LWIP_DEBUGF(TCP_DEBUG, ("tcp_zero_window_probe: sending ZERO WINDOW probe to ")); + ip_addr_debug_print(TCP_DEBUG, &pcb->remote_ip); + LWIP_DEBUGF(TCP_DEBUG, ("\n")); + + LWIP_DEBUGF(TCP_DEBUG, + ("tcp_zero_window_probe: tcp_ticks %"U32_F + " pcb->tmr %"U32_F" pcb->keep_cnt_sent %"U16_F"\n", + tcp_ticks, pcb->tmr, pcb->keep_cnt_sent)); + + seg = pcb->unacked; + + if (seg == NULL) { + seg = pcb->unsent; + } + if (seg == NULL) { + /* nothing to send, zero window probe not needed */ + return ERR_OK; + } + + is_fin = ((TCPH_FLAGS(seg->tcphdr) & TCP_FIN) != 0) && (seg->len == 0); + /* we want to send one seqno: either FIN or data (no options) */ + len = is_fin ? 0 : 1; + + p = tcp_output_alloc_header(pcb, 0, len, seg->tcphdr->seqno); + if (p == NULL) { + LWIP_DEBUGF(TCP_DEBUG, ("tcp_zero_window_probe: no memory for pbuf\n")); + return ERR_MEM; + } + tcphdr = (struct tcp_hdr *)p->payload; + + if (is_fin) { + /* FIN segment, no data */ + TCPH_FLAGS_SET(tcphdr, TCP_ACK | TCP_FIN); + } else { + /* Data segment, copy in one byte from the head of the unacked queue */ + char *d = ((char *)p->payload + TCP_HLEN); + /* Depending on whether the segment has already been sent (unacked) or not + (unsent), seg->p->payload points to the IP header or TCP header. + Ensure we copy the first TCP data byte: */ + pbuf_copy_partial(seg->p, d, 1, seg->p->tot_len - seg->len); + } + + netif = ip_route(&pcb->local_ip, &pcb->remote_ip); + if (netif == NULL) { + err = ERR_RTE; + } else { +#if CHECKSUM_GEN_TCP + IF__NETIF_CHECKSUM_ENABLED(netif, NETIF_CHECKSUM_GEN_TCP) { + tcphdr->chksum = ip_chksum_pseudo(p, IP_PROTO_TCP, p->tot_len, + &pcb->local_ip, &pcb->remote_ip); + } +#endif + TCP_STATS_INC(tcp.xmit); + + /* Send output to IP */ + NETIF_SET_HWADDRHINT(netif, &(pcb->addr_hint)); + err = ip_output_if(p, &pcb->local_ip, &pcb->remote_ip, pcb->ttl, + 0, IP_PROTO_TCP, netif); + NETIF_SET_HWADDRHINT(netif, NULL); + } + + pbuf_free(p); + + LWIP_DEBUGF(TCP_DEBUG, ("tcp_zero_window_probe: seqno %"U32_F + " ackno %"U32_F" err %d.\n", + pcb->snd_nxt - 1, pcb->rcv_nxt, (int)err)); + return err; +} +#endif /* LWIP_TCP */ diff --git a/components/lwip/core/timers.c b/components/lwip/core/timers.c new file mode 100755 index 0000000000..0a361474eb --- /dev/null +++ b/components/lwip/core/timers.c @@ -0,0 +1,614 @@ +/** + * @file + * Stack-internal timers implementation. + * This file includes timer callbacks for stack-internal timers as well as + * functions to set up or stop timers and check for expired timers. + * + */ + +/* + * Copyright (c) 2001-2004 Swedish Institute of Computer Science. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + * Simon Goldschmidt + * + */ + +#include "lwip/opt.h" + +#include "lwip/timers.h" +#include "lwip/priv/tcp_priv.h" + +#if LWIP_TIMERS + +#include "lwip/def.h" +#include "lwip/memp.h" +#include "lwip/priv/tcpip_priv.h" + +#include "lwip/ip_frag.h" +#include "netif/etharp.h" +#include "lwip/dhcp.h" +#include "lwip/autoip.h" +#include "lwip/igmp.h" +#include "lwip/dns.h" +#include "lwip/nd6.h" +#include "lwip/ip6_frag.h" +#include "lwip/mld6.h" +#include "lwip/sys.h" +#include "lwip/pbuf.h" + +#ifdef MEMLEAK_DEBUG +static const char mem_debug_file[] ICACHE_RODATA_ATTR STORE_ATTR = __FILE__; +#endif + + +/** The one and only timeout list */ +static struct sys_timeo *next_timeout; +#if NO_SYS +static u32_t timeouts_last_time; +#endif /* NO_SYS */ + +#if LWIP_TCP +/** global variable that shows if the tcp timer is currently scheduled or not */ +static int tcpip_tcp_timer_active; + +/** + * Timer callback function that calls tcp_tmr() and reschedules itself. + * + * @param arg unused argument + */ +static void +tcpip_tcp_timer(void *arg) +{ + LWIP_UNUSED_ARG(arg); + + /* call TCP timer handler */ + tcp_tmr(); + /* timer still needed? */ + if (tcp_active_pcbs || tcp_tw_pcbs) { + /* restart timer */ + sys_timeout(TCP_TMR_INTERVAL, tcpip_tcp_timer, NULL); + } else { + /* disable timer */ + tcpip_tcp_timer_active = 0; + } +} + +/** + * Called from TCP_REG when registering a new PCB: + * the reason is to have the TCP timer only running when + * there are active (or time-wait) PCBs. + */ +void +tcp_timer_needed(void) +{ + /* timer is off but needed again? */ + if (!tcpip_tcp_timer_active && (tcp_active_pcbs || tcp_tw_pcbs)) { + /* enable and start timer */ + tcpip_tcp_timer_active = 1; + sys_timeout(TCP_TMR_INTERVAL, tcpip_tcp_timer, NULL); + } +} +#endif /* LWIP_TCP */ + +#if LWIP_IPV4 +#if IP_REASSEMBLY +/** + * Timer callback function that calls ip_reass_tmr() and reschedules itself. + * + * @param arg unused argument + */ +static void +ip_reass_timer(void *arg) +{ + LWIP_UNUSED_ARG(arg); + LWIP_DEBUGF(TIMERS_DEBUG, ("tcpip: ip_reass_tmr()\n")); + ip_reass_tmr(); + sys_timeout(IP_TMR_INTERVAL, ip_reass_timer, NULL); +} +#endif /* IP_REASSEMBLY */ + +#if LWIP_ARP +/** + * Timer callback function that calls etharp_tmr() and reschedules itself. + * + * @param arg unused argument + */ +static void +arp_timer(void *arg) +{ + LWIP_UNUSED_ARG(arg); + LWIP_DEBUGF(TIMERS_DEBUG, ("tcpip: etharp_tmr()\n")); + etharp_tmr(); + sys_timeout(ARP_TMR_INTERVAL, arp_timer, NULL); +} +#endif /* LWIP_ARP */ + +#if LWIP_DHCP +/** + * Timer callback function that calls dhcp_coarse_tmr() and reschedules itself. + * + * @param arg unused argument + */ +static void +dhcp_timer_coarse(void *arg) +{ + LWIP_UNUSED_ARG(arg); + LWIP_DEBUGF(TIMERS_DEBUG, ("tcpip: dhcp_coarse_tmr()\n")); + dhcp_coarse_tmr(); + +#ifdef LWIP_ESP8266 + extern void dhcps_coarse_tmr(void); + dhcps_coarse_tmr(); +#endif + + sys_timeout(DHCP_COARSE_TIMER_MSECS, dhcp_timer_coarse, NULL); +} + +/** + * Timer callback function that calls dhcp_fine_tmr() and reschedules itself. + * + * @param arg unused argument + */ +static void +dhcp_timer_fine(void *arg) +{ + LWIP_UNUSED_ARG(arg); + LWIP_DEBUGF(TIMERS_DEBUG, ("tcpip: dhcp_fine_tmr()\n")); + dhcp_fine_tmr(); + sys_timeout(DHCP_FINE_TIMER_MSECS, dhcp_timer_fine, NULL); +} +#endif /* LWIP_DHCP */ + +#if LWIP_AUTOIP +/** + * Timer callback function that calls autoip_tmr() and reschedules itself. + * + * @param arg unused argument + */ +static void +autoip_timer(void *arg) +{ + LWIP_UNUSED_ARG(arg); + LWIP_DEBUGF(TIMERS_DEBUG, ("tcpip: autoip_tmr()\n")); + autoip_tmr(); + sys_timeout(AUTOIP_TMR_INTERVAL, autoip_timer, NULL); +} +#endif /* LWIP_AUTOIP */ + +#if LWIP_IGMP +/** + * Timer callback function that calls igmp_tmr() and reschedules itself. + * + * @param arg unused argument + */ +static void +igmp_timer(void *arg) +{ + LWIP_UNUSED_ARG(arg); + LWIP_DEBUGF(TIMERS_DEBUG, ("tcpip: igmp_tmr()\n")); + igmp_tmr(); + sys_timeout(IGMP_TMR_INTERVAL, igmp_timer, NULL); +} +#endif /* LWIP_IGMP */ +#endif /* LWIP_IPV4 */ + +#if LWIP_DNS +/** + * Timer callback function that calls dns_tmr() and reschedules itself. + * + * @param arg unused argument + */ +static void +dns_timer(void *arg) +{ + LWIP_UNUSED_ARG(arg); + LWIP_DEBUGF(TIMERS_DEBUG, ("tcpip: dns_tmr()\n")); + dns_tmr(); + sys_timeout(DNS_TMR_INTERVAL, dns_timer, NULL); +} +#endif /* LWIP_DNS */ + +#if LWIP_IPV6 +/** + * Timer callback function that calls nd6_tmr() and reschedules itself. + * + * @param arg unused argument + */ +static void +nd6_timer(void *arg) +{ + LWIP_UNUSED_ARG(arg); + LWIP_DEBUGF(TIMERS_DEBUG, ("tcpip: nd6_tmr()\n")); + nd6_tmr(); + sys_timeout(ND6_TMR_INTERVAL, nd6_timer, NULL); +} + +#if LWIP_IPV6_REASS +/** + * Timer callback function that calls ip6_reass_tmr() and reschedules itself. + * + * @param arg unused argument + */ +static void +ip6_reass_timer(void *arg) +{ + LWIP_UNUSED_ARG(arg); + LWIP_DEBUGF(TIMERS_DEBUG, ("tcpip: ip6_reass_tmr()\n")); + ip6_reass_tmr(); + sys_timeout(IP6_REASS_TMR_INTERVAL, ip6_reass_timer, NULL); +} +#endif /* LWIP_IPV6_REASS */ + +#if LWIP_IPV6_MLD +/** + * Timer callback function that calls mld6_tmr() and reschedules itself. + * + * @param arg unused argument + */ +static void +mld6_timer(void *arg) +{ + LWIP_UNUSED_ARG(arg); + LWIP_DEBUGF(TIMERS_DEBUG, ("tcpip: mld6_tmr()\n")); + mld6_tmr(); + sys_timeout(MLD6_TMR_INTERVAL, mld6_timer, NULL); +} +#endif /* LWIP_IPV6_MLD */ +#endif /* LWIP_IPV6 */ + +/** Initialize this module */ +void sys_timeouts_init(void) +{ +#if LWIP_IPV4 +#if IP_REASSEMBLY + sys_timeout(IP_TMR_INTERVAL, ip_reass_timer, NULL); +#endif /* IP_REASSEMBLY */ +#if LWIP_ARP + sys_timeout(ARP_TMR_INTERVAL, arp_timer, NULL); +#endif /* LWIP_ARP */ +#if LWIP_DHCP + +#ifdef LWIP_ESP8266 + // DHCP_MAXRTX = 0; +#endif + + + + sys_timeout(DHCP_COARSE_TIMER_MSECS, dhcp_timer_coarse, NULL); + sys_timeout(DHCP_FINE_TIMER_MSECS, dhcp_timer_fine, NULL); +#endif /* LWIP_DHCP */ +#if LWIP_AUTOIP + sys_timeout(AUTOIP_TMR_INTERVAL, autoip_timer, NULL); +#endif /* LWIP_AUTOIP */ +#if LWIP_IGMP + sys_timeout(IGMP_TMR_INTERVAL, igmp_timer, NULL); +#endif /* LWIP_IGMP */ +#endif /* LWIP_IPV4 */ + +#if LWIP_DNS + sys_timeout(DNS_TMR_INTERVAL, dns_timer, NULL); +#endif /* LWIP_DNS */ + +#if LWIP_IPV6 + sys_timeout(ND6_TMR_INTERVAL, nd6_timer, NULL); +#if LWIP_IPV6_REASS + sys_timeout(IP6_REASS_TMR_INTERVAL, ip6_reass_timer, NULL); +#endif /* LWIP_IPV6_REASS */ +#if LWIP_IPV6_MLD + sys_timeout(MLD6_TMR_INTERVAL, mld6_timer, NULL); +#endif /* LWIP_IPV6_MLD */ +#endif /* LWIP_IPV6 */ + +#if NO_SYS + /* Initialise timestamp for sys_check_timeouts */ + timeouts_last_time = sys_now(); +#endif +} + +/** + * Create a one-shot timer (aka timeout). Timeouts are processed in the + * following cases: + * - while waiting for a message using sys_timeouts_mbox_fetch() + * - by calling sys_check_timeouts() (NO_SYS==1 only) + * + * @param msecs time in milliseconds after that the timer should expire + * @param handler callback function to call when msecs have elapsed + * @param arg argument to pass to the callback function + */ +#if LWIP_DEBUG_TIMERNAMES +void +sys_timeout_debug(u32_t msecs, sys_timeout_handler handler, void *arg, const char* handler_name) +#else /* LWIP_DEBUG_TIMERNAMES */ + +#ifdef LWIP_ESP8266 + u32_t LwipTimOutLim = 0; // For light sleep. time out. limit is 3000ms +#endif + +void +sys_timeout(u32_t msecs, sys_timeout_handler handler, void *arg) +#endif /* LWIP_DEBUG_TIMERNAMES */ +{ + struct sys_timeo *timeout, *t; +#if NO_SYS + u32_t now, diff; +#endif + + timeout = (struct sys_timeo *)memp_malloc(MEMP_SYS_TIMEOUT); + if (timeout == NULL) { + LWIP_ASSERT("sys_timeout: timeout != NULL, pool MEMP_SYS_TIMEOUT is empty", timeout != NULL); + return; + } + +#if NO_SYS + now = sys_now(); + if (next_timeout == NULL) { + diff = 0; + timeouts_last_time = now; + } else { + diff = now - timeouts_last_time; + } +#endif + + timeout->next = NULL; + timeout->h = handler; + timeout->arg = arg; + +#ifdef LWIP_ESP8266 + if(msecs < LwipTimOutLim) + msecs = LwipTimOutLim; +#endif + +#if NO_SYS + timeout->time = msecs + diff; +#else + timeout->time = msecs; +#endif +#if LWIP_DEBUG_TIMERNAMES + timeout->handler_name = handler_name; + LWIP_DEBUGF(TIMERS_DEBUG, ("sys_timeout: %p msecs=%"U32_F" handler=%s arg=%p\n", + (void *)timeout, msecs, handler_name, (void *)arg)); +#endif /* LWIP_DEBUG_TIMERNAMES */ + + if (next_timeout == NULL) { + next_timeout = timeout; + return; + } + + if (next_timeout->time > msecs) { + next_timeout->time -= msecs; + timeout->next = next_timeout; + next_timeout = timeout; + } else { + for (t = next_timeout; t != NULL; t = t->next) { + timeout->time -= t->time; + if (t->next == NULL || t->next->time > timeout->time) { + if (t->next != NULL) { + t->next->time -= timeout->time; + } + timeout->next = t->next; + t->next = timeout; + break; + } + } + } +} + +/** + * Go through timeout list (for this task only) and remove the first matching + * entry (subsequent entries remain untouched), even though the timeout has not + * triggered yet. + * + * @param handler callback function that would be called by the timeout + * @param arg callback argument that would be passed to handler +*/ +void +sys_untimeout(sys_timeout_handler handler, void *arg) +{ + struct sys_timeo *prev_t, *t; + + if (next_timeout == NULL) { + return; + } + + for (t = next_timeout, prev_t = NULL; t != NULL; prev_t = t, t = t->next) { + if ((t->h == handler) && (t->arg == arg)) { + /* We have a match */ + /* Unlink from previous in list */ + if (prev_t == NULL) { + next_timeout = t->next; + } else { + prev_t->next = t->next; + } + /* If not the last one, add time of this one back to next */ + if (t->next != NULL) { + t->next->time += t->time; + } + memp_free(MEMP_SYS_TIMEOUT, t); + return; + } + } + return; +} + +#if NO_SYS + +/** Handle timeouts for NO_SYS==1 (i.e. without using + * tcpip_thread/sys_timeouts_mbox_fetch(). Uses sys_now() to call timeout + * handler functions when timeouts expire. + * + * Must be called periodically from your main loop. + */ +void +sys_check_timeouts(void) +{ + if (next_timeout) { + struct sys_timeo *tmptimeout; + u32_t diff; + sys_timeout_handler handler; + void *arg; + u8_t had_one; + u32_t now; + + now = sys_now(); + /* this cares for wraparounds */ + diff = now - timeouts_last_time; + do { +#if PBUF_POOL_FREE_OOSEQ + PBUF_CHECK_FREE_OOSEQ(); +#endif /* PBUF_POOL_FREE_OOSEQ */ + had_one = 0; + tmptimeout = next_timeout; + if (tmptimeout && (tmptimeout->time <= diff)) { + /* timeout has expired */ + had_one = 1; + timeouts_last_time += tmptimeout->time; + diff -= tmptimeout->time; + next_timeout = tmptimeout->next; + handler = tmptimeout->h; + arg = tmptimeout->arg; +#if LWIP_DEBUG_TIMERNAMES + if (handler != NULL) { + LWIP_DEBUGF(TIMERS_DEBUG, ("sct calling h=%s arg=%p\n", + tmptimeout->handler_name, arg)); + } +#endif /* LWIP_DEBUG_TIMERNAMES */ + memp_free(MEMP_SYS_TIMEOUT, tmptimeout); + if (handler != NULL) { + handler(arg); + } + } + /* repeat until all expired timers have been called */ + } while (had_one); + } +} + +/** Set back the timestamp of the last call to sys_check_timeouts() + * This is necessary if sys_check_timeouts() hasn't been called for a long + * time (e.g. while saving energy) to prevent all timer functions of that + * period being called. + */ +void +sys_restart_timeouts(void) +{ + timeouts_last_time = sys_now(); +} + +/** Return the time left before the next timeout is due. If no timeouts are + * enqueued, returns 0xffffffff + */ +u32_t +sys_timeouts_sleeptime(void) +{ + u32_t diff; + if (next_timeout == NULL) { + return 0xffffffff; + } + diff = sys_now() - timeouts_last_time; + if (diff > next_timeout->time) { + return 0; + } else { + return next_timeout->time - diff; + } +} + +#else /* NO_SYS */ + +/** + * Wait (forever) for a message to arrive in an mbox. + * While waiting, timeouts are processed. + * + * @param mbox the mbox to fetch the message from + * @param msg the place to store the message + */ +void +sys_timeouts_mbox_fetch(sys_mbox_t *mbox, void **msg) +{ + u32_t time_needed; + struct sys_timeo *tmptimeout; + sys_timeout_handler handler; + void *arg; + + again: + if (!next_timeout) { + time_needed = sys_arch_mbox_fetch(mbox, msg, 0); + } else { + if (next_timeout->time > 0) { + time_needed = sys_arch_mbox_fetch(mbox, msg, next_timeout->time); + } else { + time_needed = SYS_ARCH_TIMEOUT; + } + + if (time_needed == SYS_ARCH_TIMEOUT) { + /* If time == SYS_ARCH_TIMEOUT, a timeout occurred before a message + could be fetched. We should now call the timeout handler and + deallocate the memory allocated for the timeout. */ + tmptimeout = next_timeout; + next_timeout = tmptimeout->next; + handler = tmptimeout->h; + arg = tmptimeout->arg; +#if LWIP_DEBUG_TIMERNAMES + if (handler != NULL) { + LWIP_DEBUGF(TIMERS_DEBUG, ("stmf calling h=%s arg=%p\n", + tmptimeout->handler_name, arg)); + } +#endif /* LWIP_DEBUG_TIMERNAMES */ + memp_free(MEMP_SYS_TIMEOUT, tmptimeout); + if (handler != NULL) { + /* For LWIP_TCPIP_CORE_LOCKING, lock the core before calling the + timeout handler function. */ + LOCK_TCPIP_CORE(); + handler(arg); + UNLOCK_TCPIP_CORE(); + } + LWIP_TCPIP_THREAD_ALIVE(); + + /* We try again to fetch a message from the mbox. */ + goto again; + } else { + /* If time != SYS_ARCH_TIMEOUT, a message was received before the timeout + occured. The time variable is set to the number of + milliseconds we waited for the message. */ + if (time_needed < next_timeout->time) { + next_timeout->time -= time_needed; + } else { + next_timeout->time = 0; + } + } + } +} + +#endif /* NO_SYS */ + +#else /* LWIP_TIMERS */ +/* Satisfy the TCP code which calls this function */ +void +tcp_timer_needed(void) +{ +} +#endif /* LWIP_TIMERS */ diff --git a/components/lwip/core/udp.c b/components/lwip/core/udp.c new file mode 100755 index 0000000000..e44ab7e73d --- /dev/null +++ b/components/lwip/core/udp.c @@ -0,0 +1,1198 @@ +/** + * @file + * User Datagram Protocol module + * + */ + +/* + * Copyright (c) 2001-2004 Swedish Institute of Computer Science. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + * + */ + + +/* udp.c + * + * The code for the User Datagram Protocol UDP & UDPLite (RFC 3828). + * + */ + +/* @todo Check the use of '(struct udp_pcb).chksum_len_rx'! + */ + +#include "lwip/opt.h" + +#if LWIP_UDP /* don't build if not configured for use in lwipopts.h */ + +#include "lwip/udp.h" +#include "lwip/def.h" +#include "lwip/memp.h" +#include "lwip/inet_chksum.h" +#include "lwip/ip_addr.h" +#include "lwip/ip6.h" +#include "lwip/ip6_addr.h" +#include "lwip/inet_chksum.h" +#include "lwip/netif.h" +#include "lwip/icmp.h" +#include "lwip/icmp6.h" +#include "lwip/stats.h" +#include "lwip/snmp.h" +#include "lwip/dhcp.h" + +#include + +#ifdef MEMLEAK_DEBUG +static const char mem_debug_file[] ICACHE_RODATA_ATTR STORE_ATTR = __FILE__; +#endif + + +#ifndef UDP_LOCAL_PORT_RANGE_START +/* From http://www.iana.org/assignments/port-numbers: + "The Dynamic and/or Private Ports are those from 49152 through 65535" */ +#define UDP_LOCAL_PORT_RANGE_START 0xc000 +#define UDP_LOCAL_PORT_RANGE_END 0xffff +#define UDP_ENSURE_LOCAL_PORT_RANGE(port) ((u16_t)(((port) & ~UDP_LOCAL_PORT_RANGE_START) + UDP_LOCAL_PORT_RANGE_START)) +#endif + +/* last local UDP port */ +static u16_t udp_port = UDP_LOCAL_PORT_RANGE_START; + +/* The list of UDP PCBs */ +/* exported in udp.h (was static) */ +struct udp_pcb *udp_pcbs; + +/** + * Initialize this module. + */ +void +udp_init(void) +{ +#if LWIP_RANDOMIZE_INITIAL_LOCAL_PORTS && defined(LWIP_RAND) + udp_port = UDP_ENSURE_LOCAL_PORT_RANGE(LWIP_RAND()); +#endif /* LWIP_RANDOMIZE_INITIAL_LOCAL_PORTS && defined(LWIP_RAND) */ +} + +/** + * Allocate a new local UDP port. + * + * @return a new (free) local UDP port number + */ +static u16_t +udp_new_port(void) +{ + u16_t n = 0; + struct udp_pcb *pcb; + +again: + if (udp_port++ == UDP_LOCAL_PORT_RANGE_END) { + udp_port = UDP_LOCAL_PORT_RANGE_START; + } + /* Check all PCBs. */ + for (pcb = udp_pcbs; pcb != NULL; pcb = pcb->next) { + if (pcb->local_port == udp_port) { + if (++n > (UDP_LOCAL_PORT_RANGE_END - UDP_LOCAL_PORT_RANGE_START)) { + return 0; + } + goto again; + } + } + return udp_port; +#if 0 + struct udp_pcb *ipcb = udp_pcbs; + while ((ipcb != NULL) && (udp_port != UDP_LOCAL_PORT_RANGE_END)) { + if (ipcb->local_port == udp_port) { + /* port is already used by another udp_pcb */ + udp_port++; + /* restart scanning all udp pcbs */ + ipcb = udp_pcbs; + } else { + /* go on with next udp pcb */ + ipcb = ipcb->next; + } + } + if (ipcb != NULL) { + return 0; + } + return udp_port; +#endif +} + +/** Common code to see if the current input packet matches the pcb + * (current input packet is accessed via ip(4/6)_current_* macros) + * + * @param pcb pcb to check + * @param inp network interface on which the datagram was received (only used for IPv4) + * @param broadcast 1 if his is an IPv4 broadcast (global or subnet-only), 0 otherwise (only used for IPv4) + * @return 1 on match, 0 otherwise + */ +static u8_t +udp_input_local_match(struct udp_pcb *pcb, struct netif *inp, u8_t broadcast) +{ + LWIP_UNUSED_ARG(inp); /* in IPv6 only case */ + LWIP_UNUSED_ARG(broadcast); /* in IPv6 only case */ + + /* Dual-stack: PCBs listening to any IP type also listen to any IP address */ + if(IP_IS_ANY_TYPE_VAL(pcb->local_ip)) { +#if LWIP_IPV4 && IP_SOF_BROADCAST_RECV + if((broadcast != 0) && !ip_get_option(pcb, SOF_BROADCAST)) { + return 0; + } +#endif /* LWIP_IPV4 && IP_SOF_BROADCAST_RECV */ + return 1; + } + + /* Only need to check PCB if incoming IP version matches PCB IP version */ + if(IP_ADDR_PCB_VERSION_MATCH_EXACT(pcb, ip_current_dest_addr())) { + LWIP_ASSERT("UDP PCB: inconsistent local/remote IP versions", IP_IS_V6_VAL(pcb->local_ip) == IP_IS_V6_VAL(pcb->remote_ip)); + +#if LWIP_IPV4 + /* Special case: IPv4 broadcast: all or broadcasts in my subnet + * Note: broadcast variable can only be 1 if it is an IPv4 broadcast */ + if(broadcast != 0) { +#if IP_SOF_BROADCAST_RECV + if(ip_get_option(pcb, SOF_BROADCAST)) +#endif /* IP_SOF_BROADCAST_RECV */ + { + if(ip4_addr_isany(ip_2_ip4(&pcb->local_ip)) || + ((ip4_current_dest_addr()->addr == IPADDR_BROADCAST)) || + ip4_addr_netcmp(ip_2_ip4(&pcb->local_ip), ip4_current_dest_addr(), netif_ip4_netmask(inp))) { + return 1; + } + } + } else +#endif /* LWIP_IPV4 */ + /* Handle IPv4 and IPv6: all, multicast or exact match */ + if(ip_addr_isany(&pcb->local_ip) || +#if LWIP_IPV6_MLD + (ip_current_is_v6() && ip6_addr_ismulticast(ip6_current_dest_addr())) || +#endif /* LWIP_IPV6_MLD */ +#if LWIP_IGMP + (!ip_current_is_v6() && ip4_addr_ismulticast(ip4_current_dest_addr())) || +#endif /* LWIP_IGMP */ + ip_addr_cmp(&pcb->local_ip, ip_current_dest_addr())) { + return 1; + } + } + + return 0; +} + +/** + * Process an incoming UDP datagram. + * + * Given an incoming UDP datagram (as a chain of pbufs) this function + * finds a corresponding UDP PCB and hands over the pbuf to the pcbs + * recv function. If no pcb is found or the datagram is incorrect, the + * pbuf is freed. + * + * @param p pbuf to be demultiplexed to a UDP PCB (p->payload pointing to the UDP header) + * @param inp network interface on which the datagram was received. + * + */ +void +udp_input(struct pbuf *p, struct netif *inp) +{ + struct udp_hdr *udphdr; + struct udp_pcb *pcb, *prev; + struct udp_pcb *uncon_pcb; + u16_t src, dest; + u8_t broadcast; + u8_t for_us = 0; + + LWIP_UNUSED_ARG(inp); + + PERF_START; + + UDP_STATS_INC(udp.recv); + + /* Check minimum length (UDP header) */ + if (p->len < UDP_HLEN) { + /* drop short packets */ + LWIP_DEBUGF(UDP_DEBUG, + ("udp_input: short UDP datagram (%"U16_F" bytes) discarded\n", p->tot_len)); + UDP_STATS_INC(udp.lenerr); + UDP_STATS_INC(udp.drop); + MIB2_STATS_INC(mib2.udpinerrors); + pbuf_free(p); + goto end; + } + + udphdr = (struct udp_hdr *)p->payload; + + /* is broadcast packet ? */ + broadcast = ip_addr_isbroadcast(ip_current_dest_addr(), ip_current_netif()); + + LWIP_DEBUGF(UDP_DEBUG, ("udp_input: received datagram of length %"U16_F"\n", p->tot_len)); + + /* convert src and dest ports to host byte order */ + src = ntohs(udphdr->src); + dest = ntohs(udphdr->dest); + + udp_debug_print(udphdr); + + /* print the UDP source and destination */ + LWIP_DEBUGF(UDP_DEBUG, ("udp (")); + ip_addr_debug_print(UDP_DEBUG, ip_current_dest_addr()); + LWIP_DEBUGF(UDP_DEBUG, (", %"U16_F") <-- (", ntohs(udphdr->dest))); + ip_addr_debug_print(UDP_DEBUG, ip_current_src_addr()); + LWIP_DEBUGF(UDP_DEBUG, (", %"U16_F")\n", ntohs(udphdr->src))); + + pcb = NULL; + prev = NULL; + uncon_pcb = NULL; + /* Iterate through the UDP pcb list for a matching pcb. + * 'Perfect match' pcbs (connected to the remote port & ip address) are + * preferred. If no perfect match is found, the first unconnected pcb that + * matches the local port and ip address gets the datagram. */ + for (pcb = udp_pcbs; pcb != NULL; pcb = pcb->next) { + /* print the PCB local and remote address */ + LWIP_DEBUGF(UDP_DEBUG, ("pcb (")); + ip_addr_debug_print(UDP_DEBUG, &pcb->local_ip); + LWIP_DEBUGF(UDP_DEBUG, (", %"U16_F") <-- (", pcb->local_port)); + ip_addr_debug_print(UDP_DEBUG, &pcb->remote_ip); + LWIP_DEBUGF(UDP_DEBUG, (", %"U16_F")\n", pcb->remote_port)); + + /* compare PCB local addr+port to UDP destination addr+port */ + if ((pcb->local_port == dest) && + (udp_input_local_match(pcb, inp, broadcast) != 0)) { + if ((uncon_pcb == NULL) && + ((pcb->flags & UDP_FLAGS_CONNECTED) == 0)) { + /* the first unconnected matching PCB */ + uncon_pcb = pcb; + } + + /* compare PCB remote addr+port to UDP source addr+port */ + if ((pcb->remote_port == src) && + (ip_addr_isany_val(pcb->remote_ip) || + ip_addr_cmp(&pcb->remote_ip, ip_current_src_addr()))) { + /* the first fully matching PCB */ + if (prev != NULL) { + /* move the pcb to the front of udp_pcbs so that is + found faster next time */ + prev->next = pcb->next; + pcb->next = udp_pcbs; + udp_pcbs = pcb; + } else { + UDP_STATS_INC(udp.cachehit); + } + break; + } + } + + prev = pcb; + } + /* no fully matching pcb found? then look for an unconnected pcb */ + if (pcb == NULL) { + pcb = uncon_pcb; + } + + /* Check checksum if this is a match or if it was directed at us. */ + if (pcb != NULL) { + for_us = 1; + } else { +#if LWIP_IPV6 + if (ip_current_is_v6()) { + for_us = netif_get_ip6_addr_match(inp, ip6_current_dest_addr()) >= 0; + } +#endif /* LWIP_IPV6 */ +#if LWIP_IPV4 + if (!ip_current_is_v6()) { + for_us = ip4_addr_cmp(netif_ip4_addr(inp), ip4_current_dest_addr()); + } +#endif /* LWIP_IPV4 */ + } + + if (for_us) { + LWIP_DEBUGF(UDP_DEBUG | LWIP_DBG_TRACE, ("udp_input: calculating checksum\n")); +#if CHECKSUM_CHECK_UDP + IF__NETIF_CHECKSUM_ENABLED(inp, CHECKSUM_CHECK_UDP) { +#if LWIP_UDPLITE + if (ip_current_header_proto() == IP_PROTO_UDPLITE) { + /* Do the UDP Lite checksum */ + u16_t chklen = ntohs(udphdr->len); + if (chklen < sizeof(struct udp_hdr)) { + if (chklen == 0) { + /* For UDP-Lite, checksum length of 0 means checksum + over the complete packet (See RFC 3828 chap. 3.1) */ + chklen = p->tot_len; + } else { + /* At least the UDP-Lite header must be covered by the + checksum! (Again, see RFC 3828 chap. 3.1) */ + goto chkerr; + } + } + if (ip_chksum_pseudo_partial(p, IP_PROTO_UDPLITE, + p->tot_len, chklen, + ip_current_src_addr(), ip_current_dest_addr()) != 0) { + goto chkerr; + } + } else +#endif /* LWIP_UDPLITE */ + { + if (udphdr->chksum != 0) { + if (ip_chksum_pseudo(p, IP_PROTO_UDP, p->tot_len, + ip_current_src_addr(), + ip_current_dest_addr()) != 0) { + goto chkerr; + } + } + } + } +#endif /* CHECKSUM_CHECK_UDP */ + if (pbuf_header(p, -UDP_HLEN)) { + /* Can we cope with this failing? Just assert for now */ + LWIP_ASSERT("pbuf_header failed\n", 0); + UDP_STATS_INC(udp.drop); + MIB2_STATS_INC(mib2.udpinerrors); + pbuf_free(p); + goto end; + } + + if (pcb != NULL) { + MIB2_STATS_INC(mib2.udpindatagrams); +#if SO_REUSE && SO_REUSE_RXTOALL + if (ip_get_option(pcb, SOF_REUSEADDR) && + (broadcast || ip_addr_ismulticast(ip_current_dest_addr()))) { + /* pass broadcast- or multicast packets to all multicast pcbs + if SOF_REUSEADDR is set on the first match */ + struct udp_pcb *mpcb; + u8_t p_header_changed = 0; + s16_t hdrs_len = (s16_t)(ip_current_header_tot_len() + UDP_HLEN); + for (mpcb = udp_pcbs; mpcb != NULL; mpcb = mpcb->next) { + if (mpcb != pcb) { + /* compare PCB local addr+port to UDP destination addr+port */ + if ((mpcb->local_port == dest) && + (udp_input_local_match(mpcb, inp, broadcast) != 0)) { + /* pass a copy of the packet to all local matches */ + if (mpcb->recv != NULL) { + struct pbuf *q; + /* for that, move payload to IP header again */ + if (p_header_changed == 0) { + pbuf_header_force(p, hdrs_len); + p_header_changed = 1; + } + q = pbuf_alloc(PBUF_RAW, p->tot_len, PBUF_RAM); + if (q != NULL) { + err_t err = pbuf_copy(q, p); + if (err == ERR_OK) { + /* move payload to UDP data */ + pbuf_header(q, -hdrs_len); + mpcb->recv(mpcb->recv_arg, mpcb, q, ip_current_src_addr(), src); + } + } + } + } + } + } + if (p_header_changed) { + /* and move payload to UDP data again */ + pbuf_header(p, -hdrs_len); + } + } +#endif /* SO_REUSE && SO_REUSE_RXTOALL */ + /* callback */ + if (pcb->recv != NULL) { + /* now the recv function is responsible for freeing p */ + pcb->recv(pcb->recv_arg, pcb, p, ip_current_src_addr(), src); + } else { + /* no recv function registered? then we have to free the pbuf! */ + pbuf_free(p); + goto end; + } + } else { + LWIP_DEBUGF(UDP_DEBUG | LWIP_DBG_TRACE, ("udp_input: not for us.\n")); + +#if LWIP_ICMP || LWIP_ICMP6 + /* No match was found, send ICMP destination port unreachable unless + destination address was broadcast/multicast. */ + if (!broadcast && !ip_addr_ismulticast(ip_current_dest_addr())) { + /* move payload pointer back to ip header */ + pbuf_header_force(p, ip_current_header_tot_len() + UDP_HLEN); + icmp_port_unreach(ip_current_is_v6(), p); + } +#endif /* LWIP_ICMP || LWIP_ICMP6 */ + UDP_STATS_INC(udp.proterr); + UDP_STATS_INC(udp.drop); + MIB2_STATS_INC(mib2.udpnoports); + pbuf_free(p); + } + } else { + pbuf_free(p); + } +end: + PERF_STOP("udp_input"); + return; +#if CHECKSUM_CHECK_UDP +chkerr: + LWIP_DEBUGF(UDP_DEBUG | LWIP_DBG_LEVEL_SERIOUS, + ("udp_input: UDP (or UDP Lite) datagram discarded due to failing checksum\n")); + UDP_STATS_INC(udp.chkerr); + UDP_STATS_INC(udp.drop); + MIB2_STATS_INC(mib2.udpinerrors); + pbuf_free(p); + PERF_STOP("udp_input"); +#endif /* CHECKSUM_CHECK_UDP */ +} + +/** + * Send data using UDP. + * + * @param pcb UDP PCB used to send the data. + * @param p chain of pbuf's to be sent. + * + * The datagram will be sent to the current remote_ip & remote_port + * stored in pcb. If the pcb is not bound to a port, it will + * automatically be bound to a random port. + * + * @return lwIP error code. + * - ERR_OK. Successful. No error occurred. + * - ERR_MEM. Out of memory. + * - ERR_RTE. Could not find route to destination address. + * - ERR_VAL. No PCB or PCB is dual-stack + * - More errors could be returned by lower protocol layers. + * + * @see udp_disconnect() udp_sendto() + */ +err_t +udp_send(struct udp_pcb *pcb, struct pbuf *p) +{ + if ((pcb == NULL) || IP_IS_ANY_TYPE_VAL(pcb->remote_ip)) { + return ERR_VAL; + } + + /* send to the packet using remote ip and port stored in the pcb */ + return udp_sendto(pcb, p, &pcb->remote_ip, pcb->remote_port); +} + +#if LWIP_CHECKSUM_ON_COPY && CHECKSUM_GEN_UDP +/** Same as udp_send() but with checksum + */ +err_t +udp_send_chksum(struct udp_pcb *pcb, struct pbuf *p, + u8_t have_chksum, u16_t chksum) +{ + if ((pcb == NULL) || IP_IS_ANY_TYPE_VAL(pcb->remote_ip)) { + return ERR_VAL; + } + + /* send to the packet using remote ip and port stored in the pcb */ + return udp_sendto_chksum(pcb, p, &pcb->remote_ip, pcb->remote_port, + have_chksum, chksum); +} +#endif /* LWIP_CHECKSUM_ON_COPY && CHECKSUM_GEN_UDP */ + +/** + * Send data to a specified address using UDP. + * + * @param pcb UDP PCB used to send the data. + * @param p chain of pbuf's to be sent. + * @param dst_ip Destination IP address. + * @param dst_port Destination UDP port. + * + * dst_ip & dst_port are expected to be in the same byte order as in the pcb. + * + * If the PCB already has a remote address association, it will + * be restored after the data is sent. + * + * @return lwIP error code (@see udp_send for possible error codes) + * + * @see udp_disconnect() udp_send() + */ +err_t +udp_sendto(struct udp_pcb *pcb, struct pbuf *p, + const ip_addr_t *dst_ip, u16_t dst_port) +{ +#if LWIP_CHECKSUM_ON_COPY && CHECKSUM_GEN_UDP + return udp_sendto_chksum(pcb, p, dst_ip, dst_port, 0, 0); +} + +/** Same as udp_sendto(), but with checksum */ +err_t +udp_sendto_chksum(struct udp_pcb *pcb, struct pbuf *p, const ip_addr_t *dst_ip, + u16_t dst_port, u8_t have_chksum, u16_t chksum) +{ +#endif /* LWIP_CHECKSUM_ON_COPY && CHECKSUM_GEN_UDP */ + struct netif *netif; + const ip_addr_t *dst_ip_route = dst_ip; + + if ((pcb == NULL) || (dst_ip == NULL) || !IP_ADDR_PCB_VERSION_MATCH(pcb, dst_ip)) { + return ERR_VAL; + } + + LWIP_DEBUGF(UDP_DEBUG | LWIP_DBG_TRACE, ("udp_send\n")); + +#if LWIP_IPV6 || (LWIP_IPV4 && LWIP_MULTICAST_TX_OPTIONS) + if (ip_addr_ismulticast(dst_ip_route)) { +#if LWIP_IPV6 + if (IP_IS_V6(dst_ip)) { + /* For multicast, find a netif based on source address. */ + dst_ip_route = &pcb->local_ip; + } else +#endif /* LWIP_IPV6 */ + { +#if LWIP_IPV4 && LWIP_MULTICAST_TX_OPTIONS + /* IPv4 does not use source-based routing by default, so we use an + administratively selected interface for multicast by default. + However, this can be overridden by setting an interface address + in pcb->multicast_ip that is used for routing. */ + if (!ip_addr_isany_val(pcb->multicast_ip) && + !ip4_addr_cmp(ip_2_ip4(&pcb->multicast_ip), IP4_ADDR_BROADCAST)) { + dst_ip_route = &pcb->multicast_ip; + } +#endif /* LWIP_IPV4 && LWIP_MULTICAST_TX_OPTIONS */ + } + } +#endif /* LWIP_IPV6 || (LWIP_IPV4 && LWIP_MULTICAST_TX_OPTIONS) */ + + /* find the outgoing network interface for this packet */ + netif = ip_route(&pcb->local_ip, dst_ip_route); + + /* no outgoing network interface could be found? */ + if (netif == NULL) { + LWIP_DEBUGF(UDP_DEBUG | LWIP_DBG_LEVEL_SERIOUS, ("udp_send: No route to ")); + ip_addr_debug_print(UDP_DEBUG | LWIP_DBG_LEVEL_SERIOUS, dst_ip); + LWIP_DEBUGF(UDP_DEBUG, ("\n")); + UDP_STATS_INC(udp.rterr); + return ERR_RTE; + } +#if LWIP_CHECKSUM_ON_COPY && CHECKSUM_GEN_UDP + return udp_sendto_if_chksum(pcb, p, dst_ip, dst_port, netif, have_chksum, chksum); +#else /* LWIP_CHECKSUM_ON_COPY && CHECKSUM_GEN_UDP */ + return udp_sendto_if(pcb, p, dst_ip, dst_port, netif); +#endif /* LWIP_CHECKSUM_ON_COPY && CHECKSUM_GEN_UDP */ +} + +/** + * Send data to a specified address using UDP. + * The netif used for sending can be specified. + * + * This function exists mainly for DHCP, to be able to send UDP packets + * on a netif that is still down. + * + * @param pcb UDP PCB used to send the data. + * @param p chain of pbuf's to be sent. + * @param dst_ip Destination IP address. + * @param dst_port Destination UDP port. + * @param netif the netif used for sending. + * + * dst_ip & dst_port are expected to be in the same byte order as in the pcb. + * + * @return lwIP error code (@see udp_send for possible error codes) + * + * @see udp_disconnect() udp_send() + */ +err_t +udp_sendto_if(struct udp_pcb *pcb, struct pbuf *p, + const ip_addr_t *dst_ip, u16_t dst_port, struct netif *netif) +{ +#if LWIP_CHECKSUM_ON_COPY && CHECKSUM_GEN_UDP + return udp_sendto_if_chksum(pcb, p, dst_ip, dst_port, netif, 0, 0); +} + +/** Same as udp_sendto_if(), but with checksum */ +err_t +udp_sendto_if_chksum(struct udp_pcb *pcb, struct pbuf *p, const ip_addr_t *dst_ip, + u16_t dst_port, struct netif *netif, u8_t have_chksum, + u16_t chksum) +{ +#endif /* LWIP_CHECKSUM_ON_COPY && CHECKSUM_GEN_UDP */ + const ip_addr_t *src_ip; + + if ((pcb == NULL) || (dst_ip == NULL) || !IP_ADDR_PCB_VERSION_MATCH(pcb, dst_ip)) { + return ERR_VAL; + } + + /* PCB local address is IP_ANY_ADDR? */ +#if LWIP_IPV6 + if (IP_IS_V6(dst_ip)) { + if (ip6_addr_isany(ip_2_ip6(&pcb->local_ip))) { + src_ip = ip6_select_source_address(netif, ip_2_ip6(dst_ip)); + if (src_ip == NULL) { + /* No suitable source address was found. */ + return ERR_RTE; + } + } else { + /* use UDP PCB local IPv6 address as source address, if still valid. */ + if (netif_get_ip6_addr_match(netif, ip_2_ip6(&pcb->local_ip)) < 0) { + /* Address isn't valid anymore. */ + return ERR_RTE; + } + src_ip = &pcb->local_ip; + } + } +#endif /* LWIP_IPV6 */ +#if LWIP_IPV4 && LWIP_IPV6 + else +#endif /* LWIP_IPV4 && LWIP_IPV6 */ +#if LWIP_IPV4 + if (ip4_addr_isany(ip_2_ip4(&pcb->local_ip))) { + /* use outgoing network interface IP address as source address */ + src_ip = netif_ip_addr4(netif); + } else { + /* check if UDP PCB local IP address is correct + * this could be an old address if netif->ip_addr has changed */ + if (!ip4_addr_cmp(ip_2_ip4(&(pcb->local_ip)), netif_ip4_addr(netif))) { + /* local_ip doesn't match, drop the packet */ + return ERR_VAL; + } + /* use UDP PCB local IP address as source address */ + src_ip = &pcb->local_ip; + } +#endif /* LWIP_IPV4 */ +#if LWIP_CHECKSUM_ON_COPY && CHECKSUM_GEN_UDP + return udp_sendto_if_src_chksum(pcb, p, dst_ip, dst_port, netif, have_chksum, chksum, src_ip); +#else /* LWIP_CHECKSUM_ON_COPY && CHECKSUM_GEN_UDP */ + return udp_sendto_if_src(pcb, p, dst_ip, dst_port, netif, src_ip); +#endif /* LWIP_CHECKSUM_ON_COPY && CHECKSUM_GEN_UDP */ +} + +/** Same as udp_sendto_if(), but with source address */ +err_t +udp_sendto_if_src(struct udp_pcb *pcb, struct pbuf *p, + const ip_addr_t *dst_ip, u16_t dst_port, struct netif *netif, const ip_addr_t *src_ip) +{ +#if LWIP_CHECKSUM_ON_COPY && CHECKSUM_GEN_UDP + return udp_sendto_if_src_chksum(pcb, p, dst_ip, dst_port, netif, 0, 0, src_ip); +} + +/** Same as udp_sendto_if_src(), but with checksum */ +err_t +udp_sendto_if_src_chksum(struct udp_pcb *pcb, struct pbuf *p, const ip_addr_t *dst_ip, + u16_t dst_port, struct netif *netif, u8_t have_chksum, + u16_t chksum, const ip_addr_t *src_ip) +{ +#endif /* LWIP_CHECKSUM_ON_COPY && CHECKSUM_GEN_UDP */ + struct udp_hdr *udphdr; + err_t err; + struct pbuf *q; /* q will be sent down the stack */ + u8_t ip_proto; + u8_t ttl; + + if ((pcb == NULL) || (dst_ip == NULL) || !IP_ADDR_PCB_VERSION_MATCH(pcb, src_ip) || + !IP_ADDR_PCB_VERSION_MATCH(pcb, dst_ip)) { + return ERR_VAL; + } + +#if LWIP_IPV4 && IP_SOF_BROADCAST + /* broadcast filter? */ + if (!ip_get_option(pcb, SOF_BROADCAST) && +#if LWIP_IPV6 + !IP_IS_V6(dst_ip) && +#endif /* LWIP_IPV6 */ + ip_addr_isbroadcast(dst_ip, netif)) { + LWIP_DEBUGF(UDP_DEBUG | LWIP_DBG_LEVEL_SERIOUS, + ("udp_sendto_if: SOF_BROADCAST not enabled on pcb %p\n", (void *)pcb)); + return ERR_VAL; + } +#endif /* LWIP_IPV4 && IP_SOF_BROADCAST */ + + /* if the PCB is not yet bound to a port, bind it here */ + if (pcb->local_port == 0) { + LWIP_DEBUGF(UDP_DEBUG | LWIP_DBG_TRACE, ("udp_send: not yet bound to a port, binding now\n")); + err = udp_bind(pcb, &pcb->local_ip, pcb->local_port); + if (err != ERR_OK) { + LWIP_DEBUGF(UDP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_SERIOUS, ("udp_send: forced port bind failed\n")); + return err; + } + } + + /* not enough space to add an UDP header to first pbuf in given p chain? */ + if (pbuf_header(p, UDP_HLEN)) { + /* allocate header in a separate new pbuf */ + q = pbuf_alloc(PBUF_IP, UDP_HLEN, PBUF_RAM); + /* new header pbuf could not be allocated? */ + if (q == NULL) { + LWIP_DEBUGF(UDP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_SERIOUS, ("udp_send: could not allocate header\n")); + return ERR_MEM; + } + if (p->tot_len != 0) { + /* chain header q in front of given pbuf p (only if p contains data) */ + pbuf_chain(q, p); + } + /* first pbuf q points to header pbuf */ + LWIP_DEBUGF(UDP_DEBUG, + ("udp_send: added header pbuf %p before given pbuf %p\n", (void *)q, (void *)p)); + } else { + /* adding space for header within p succeeded */ + /* first pbuf q equals given pbuf */ + q = p; + LWIP_DEBUGF(UDP_DEBUG, ("udp_send: added header in given pbuf %p\n", (void *)p)); + } + LWIP_ASSERT("check that first pbuf can hold struct udp_hdr", + (q->len >= sizeof(struct udp_hdr))); + /* q now represents the packet to be sent */ + udphdr = (struct udp_hdr *)q->payload; + udphdr->src = htons(pcb->local_port); + udphdr->dest = htons(dst_port); + /* in UDP, 0 checksum means 'no checksum' */ + udphdr->chksum = 0x0000; + + /* Multicast Loop? */ +#if (LWIP_IPV4 && LWIP_MULTICAST_TX_OPTIONS) || (LWIP_IPV6 && LWIP_IPV6_MLD) + if (((pcb->flags & UDP_FLAGS_MULTICAST_LOOP) != 0) && ip_addr_ismulticast(dst_ip)) { + q->flags |= PBUF_FLAG_MCASTLOOP; + } +#endif /* (LWIP_IPV4 && LWIP_MULTICAST_TX_OPTIONS) || (LWIP_IPV6 && LWIP_IPV6_MLD) */ + + LWIP_DEBUGF(UDP_DEBUG, ("udp_send: sending datagram of length %"U16_F"\n", q->tot_len)); + +#if LWIP_UDPLITE + /* UDP Lite protocol? */ + if (pcb->flags & UDP_FLAGS_UDPLITE) { + u16_t chklen, chklen_hdr; + LWIP_DEBUGF(UDP_DEBUG, ("udp_send: UDP LITE packet length %"U16_F"\n", q->tot_len)); + /* set UDP message length in UDP header */ + chklen_hdr = chklen = pcb->chksum_len_tx; + if ((chklen < sizeof(struct udp_hdr)) || (chklen > q->tot_len)) { + if (chklen != 0) { + LWIP_DEBUGF(UDP_DEBUG, ("udp_send: UDP LITE pcb->chksum_len is illegal: %"U16_F"\n", chklen)); + } + /* For UDP-Lite, checksum length of 0 means checksum + over the complete packet. (See RFC 3828 chap. 3.1) + At least the UDP-Lite header must be covered by the + checksum, therefore, if chksum_len has an illegal + value, we generate the checksum over the complete + packet to be safe. */ + chklen_hdr = 0; + chklen = q->tot_len; + } + udphdr->len = htons(chklen_hdr); + /* calculate checksum */ +#if CHECKSUM_GEN_UDP + IF__NETIF_CHECKSUM_ENABLED(netif, NETIF_CHECKSUM_GEN_UDP) { +#if LWIP_CHECKSUM_ON_COPY + if (have_chksum) { + chklen = UDP_HLEN; + } +#endif /* LWIP_CHECKSUM_ON_COPY */ + udphdr->chksum = ip_chksum_pseudo_partial(q, IP_PROTO_UDPLITE, + q->tot_len, chklen, src_ip, dst_ip); +#if LWIP_CHECKSUM_ON_COPY + if (have_chksum) { + u32_t acc; + acc = udphdr->chksum + (u16_t)~(chksum); + udphdr->chksum = FOLD_U32T(acc); + } +#endif /* LWIP_CHECKSUM_ON_COPY */ + + /* chksum zero must become 0xffff, as zero means 'no checksum' */ + if (udphdr->chksum == 0x0000) { + udphdr->chksum = 0xffff; + } + } +#endif /* CHECKSUM_GEN_UDP */ + + ip_proto = IP_PROTO_UDPLITE; + } else +#endif /* LWIP_UDPLITE */ + { /* UDP */ + LWIP_DEBUGF(UDP_DEBUG, ("udp_send: UDP packet length %"U16_F"\n", q->tot_len)); + udphdr->len = htons(q->tot_len); + /* calculate checksum */ +#if CHECKSUM_GEN_UDP + IF__NETIF_CHECKSUM_ENABLED(netif, NETIF_CHECKSUM_GEN_UDP) { + /* Checksum is mandatory over IPv6. */ + if (IP_IS_V6(dst_ip) || (pcb->flags & UDP_FLAGS_NOCHKSUM) == 0) { + u16_t udpchksum; +#if LWIP_CHECKSUM_ON_COPY + if (have_chksum) { + u32_t acc; + udpchksum = ip_chksum_pseudo_partial(q, IP_PROTO_UDP, + q->tot_len, UDP_HLEN, src_ip, dst_ip); + acc = udpchksum + (u16_t)~(chksum); + udpchksum = FOLD_U32T(acc); + } else +#endif /* LWIP_CHECKSUM_ON_COPY */ + { + udpchksum = ip_chksum_pseudo(q, IP_PROTO_UDP, q->tot_len, + src_ip, dst_ip); + } + + /* chksum zero must become 0xffff, as zero means 'no checksum' */ + if (udpchksum == 0x0000) { + udpchksum = 0xffff; + } + udphdr->chksum = udpchksum; + } + } +#endif /* CHECKSUM_GEN_UDP */ + ip_proto = IP_PROTO_UDP; + } + + /* Determine TTL to use */ +#if LWIP_MULTICAST_TX_OPTIONS + ttl = (ip_addr_ismulticast(dst_ip) ? pcb->mcast_ttl : pcb->ttl); +#else /* LWIP_MULTICAST_TX_OPTIONS */ + ttl = pcb->ttl; +#endif /* LWIP_MULTICAST_TX_OPTIONS */ + + LWIP_DEBUGF(UDP_DEBUG, ("udp_send: UDP checksum 0x%04"X16_F"\n", udphdr->chksum)); + LWIP_DEBUGF(UDP_DEBUG, ("udp_send: ip_output_if (,,,,0x%02"X16_F",)\n", (u16_t)ip_proto)); + /* output to IP */ + NETIF_SET_HWADDRHINT(netif, &(pcb->addr_hint)); + err = ip_output_if_src(q, src_ip, dst_ip, ttl, pcb->tos, ip_proto, netif); + NETIF_SET_HWADDRHINT(netif, NULL); + + /* TODO: must this be increased even if error occurred? */ + MIB2_STATS_INC(mib2.udpoutdatagrams); + + /* did we chain a separate header pbuf earlier? */ + if (q != p) { + /* free the header pbuf */ + pbuf_free(q); + q = NULL; + /* p is still referenced by the caller, and will live on */ + } + + UDP_STATS_INC(udp.xmit); + return err; +} + +/** + * Bind an UDP PCB. + * + * @param pcb UDP PCB to be bound with a local address ipaddr and port. + * @param ipaddr local IP address to bind with. Use IP_ADDR_ANY to + * bind to all local interfaces. + * @param port local UDP port to bind with. Use 0 to automatically bind + * to a random port between UDP_LOCAL_PORT_RANGE_START and + * UDP_LOCAL_PORT_RANGE_END. + * + * ipaddr & port are expected to be in the same byte order as in the pcb. + * + * @return lwIP error code. + * - ERR_OK. Successful. No error occurred. + * - ERR_USE. The specified ipaddr and port are already bound to by + * another UDP PCB. + * + * @see udp_disconnect() + */ +err_t +udp_bind(struct udp_pcb *pcb, const ip_addr_t *ipaddr, u16_t port) +{ + struct udp_pcb *ipcb; + u8_t rebind; + +#if LWIP_IPV4 + /* Don't propagate NULL pointer (IPv4 ANY) to subsequent functions */ + if (ipaddr == NULL) { + ipaddr = IP_ADDR_ANY; + } +#endif /* LWIP_IPV4 */ + + /* still need to check for ipaddr == NULL in IPv6 only case */ + if ((pcb == NULL) || (ipaddr == NULL) || !IP_ADDR_PCB_VERSION_MATCH_EXACT(pcb, ipaddr)) { + return ERR_VAL; + } + + LWIP_DEBUGF(UDP_DEBUG | LWIP_DBG_TRACE, ("udp_bind(ipaddr = ")); + ip_addr_debug_print(UDP_DEBUG | LWIP_DBG_TRACE, ipaddr); + LWIP_DEBUGF(UDP_DEBUG | LWIP_DBG_TRACE, (", port = %"U16_F")\n", port)); + + rebind = 0; + /* Check for double bind and rebind of the same pcb */ + for (ipcb = udp_pcbs; ipcb != NULL; ipcb = ipcb->next) { + /* is this UDP PCB already on active list? */ + if (pcb == ipcb) { + rebind = 1; + break; + } + } + + /* no port specified? */ + if (port == 0) { + port = udp_new_port(); + if (port == 0) { + /* no more ports available in local range */ + LWIP_DEBUGF(UDP_DEBUG, ("udp_bind: out of free UDP ports\n")); + return ERR_USE; + } + } else { + for (ipcb = udp_pcbs; ipcb != NULL; ipcb = ipcb->next) { + if (pcb != ipcb) { + /* By default, we don't allow to bind to a port that any other udp + PCB is already bound to, unless *all* PCBs with that port have tha + REUSEADDR flag set. */ +#if SO_REUSE + if (!ip_get_option(pcb, SOF_REUSEADDR) || + !ip_get_option(ipcb, SOF_REUSEADDR)) +#endif /* SO_REUSE */ + { + /* port matches that of PCB in list and REUSEADDR not set -> reject */ + if ((ipcb->local_port == port) && (IP_IS_V6(ipaddr) == IP_IS_V6_VAL(ipcb->local_ip)) && + /* IP address matches, or one is IP_ADDR_ANY? */ + (ip_addr_isany(&ipcb->local_ip) || + ip_addr_isany(ipaddr) || + ip_addr_cmp(&ipcb->local_ip, ipaddr))) { + /* other PCB already binds to this local IP and port */ + LWIP_DEBUGF(UDP_DEBUG, + ("udp_bind: local port %"U16_F" already bound by another pcb\n", port)); + return ERR_USE; + } + } + } + } + } + + ip_addr_set_ipaddr(&pcb->local_ip, ipaddr); + + pcb->local_port = port; + mib2_udp_bind(pcb); + /* pcb not active yet? */ + if (rebind == 0) { + /* place the PCB on the active list if not already there */ + pcb->next = udp_pcbs; + udp_pcbs = pcb; + } + LWIP_DEBUGF(UDP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("udp_bind: bound to ")); + ip_addr_debug_print(UDP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, &pcb->local_ip); + LWIP_DEBUGF(UDP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, (", port %"U16_F")\n", pcb->local_port)); + return ERR_OK; +} + +/** + * Connect an UDP PCB. + * + * This will associate the UDP PCB with the remote address. + * + * @param pcb UDP PCB to be connected with remote address ipaddr and port. + * @param ipaddr remote IP address to connect with. + * @param port remote UDP port to connect with. + * + * @return lwIP error code + * + * ipaddr & port are expected to be in the same byte order as in the pcb. + * + * The udp pcb is bound to a random local port if not already bound. + * + * @see udp_disconnect() + */ +err_t +udp_connect(struct udp_pcb *pcb, const ip_addr_t *ipaddr, u16_t port) +{ + struct udp_pcb *ipcb; + + if ((pcb == NULL) || (ipaddr == NULL) || !IP_ADDR_PCB_VERSION_MATCH_EXACT(pcb, ipaddr)) { + return ERR_VAL; + } + + if (pcb->local_port == 0) { + err_t err = udp_bind(pcb, &pcb->local_ip, pcb->local_port); + if (err != ERR_OK) { + return err; + } + } + + ip_addr_set_ipaddr(&pcb->remote_ip, ipaddr); + pcb->remote_port = port; + pcb->flags |= UDP_FLAGS_CONNECTED; + + LWIP_DEBUGF(UDP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("udp_connect: connected to ")); + ip_addr_debug_print(UDP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, + &pcb->remote_ip); + LWIP_DEBUGF(UDP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, (", port %"U16_F")\n", pcb->remote_port)); + + /* Insert UDP PCB into the list of active UDP PCBs. */ + for (ipcb = udp_pcbs; ipcb != NULL; ipcb = ipcb->next) { + if (pcb == ipcb) { + /* already on the list, just return */ + return ERR_OK; + } + } + /* PCB not yet on the list, add PCB now */ + pcb->next = udp_pcbs; + udp_pcbs = pcb; + return ERR_OK; +} + +/** + * Disconnect a UDP PCB + * + * @param pcb the udp pcb to disconnect. + */ +void +udp_disconnect(struct udp_pcb *pcb) +{ + /* reset remote address association */ + ip_addr_set_any(IP_IS_V6_VAL(pcb->remote_ip), &pcb->remote_ip); + pcb->remote_port = 0; + /* mark PCB as unconnected */ + pcb->flags &= ~UDP_FLAGS_CONNECTED; +} + +/** + * Set a receive callback for a UDP PCB + * + * This callback will be called when receiving a datagram for the pcb. + * + * @param pcb the pcb for which to set the recv callback + * @param recv function pointer of the callback function + * @param recv_arg additional argument to pass to the callback function + */ +void +udp_recv(struct udp_pcb *pcb, udp_recv_fn recv, void *recv_arg) +{ + /* remember recv() callback and user data */ + pcb->recv = recv; + pcb->recv_arg = recv_arg; +} + +/** + * Remove an UDP PCB. + * + * @param pcb UDP PCB to be removed. The PCB is removed from the list of + * UDP PCB's and the data structure is freed from memory. + * + * @see udp_new() + */ +void +udp_remove(struct udp_pcb *pcb) +{ + struct udp_pcb *pcb2; + + mib2_udp_unbind(pcb); + /* pcb to be removed is first in list? */ + if (udp_pcbs == pcb) { + /* make list start at 2nd pcb */ + udp_pcbs = udp_pcbs->next; + /* pcb not 1st in list */ + } else { + for (pcb2 = udp_pcbs; pcb2 != NULL; pcb2 = pcb2->next) { + /* find pcb in udp_pcbs list */ + if (pcb2->next != NULL && pcb2->next == pcb) { + /* remove pcb from list */ + pcb2->next = pcb->next; + break; + } + } + } + memp_free(MEMP_UDP_PCB, pcb); +} + +/** + * Create a UDP PCB. + * + * @return The UDP PCB which was created. NULL if the PCB data structure + * could not be allocated. + * + * @see udp_remove() + */ +struct udp_pcb * +udp_new(void) +{ + struct udp_pcb *pcb; + pcb = (struct udp_pcb *)memp_malloc(MEMP_UDP_PCB); + /* could allocate UDP PCB? */ + if (pcb != NULL) { + /* UDP Lite: by initializing to all zeroes, chksum_len is set to 0 + * which means checksum is generated over the whole datagram per default + * (recommended as default by RFC 3828). */ + /* initialize PCB to all zeroes */ + memset(pcb, 0, sizeof(struct udp_pcb)); + pcb->ttl = UDP_TTL; +#if LWIP_MULTICAST_TX_OPTIONS + pcb->mcast_ttl = UDP_TTL; +#endif /* LWIP_MULTICAST_TX_OPTIONS */ + } + return pcb; +} + +/** + * Create a UDP PCB for specific IP type. + * + * @param type IP address type, see IPADDR_TYPE_XX definitions. + * @return The UDP PCB which was created. NULL if the PCB data structure + * could not be allocated. + * + * @see udp_remove() + */ +struct udp_pcb * +udp_new_ip_type(u8_t type) +{ + struct udp_pcb *pcb; + pcb = udp_new(); +#if LWIP_IPV4 && LWIP_IPV6 + if(pcb != NULL) { + IP_SET_TYPE_VAL(pcb->local_ip, type); + IP_SET_TYPE_VAL(pcb->remote_ip, type); + } +#else + LWIP_UNUSED_ARG(type); +#endif /* LWIP_IPV4 && LWIP_IPV6 */ + return pcb; +} + +#if LWIP_IPV4 +/** This function is called from netif.c when address is changed + * + * @param old_addr IPv4 address of the netif before change + * @param new_addr IPv4 address of the netif after change + */ +void udp_netif_ipv4_addr_changed(const ip4_addr_t* old_addr, const ip4_addr_t* new_addr) +{ + struct udp_pcb* upcb; + + if (!ip4_addr_isany(new_addr)) { + for (upcb = udp_pcbs; upcb != NULL; upcb = upcb->next) { + /* Is this an IPv4 pcb? */ + if (!IP_IS_V6_VAL(upcb->local_ip)) { + /* PCB bound to current local interface address? */ + if (!ip4_addr_isany(ip_2_ip4(&upcb->local_ip)) && + ip4_addr_cmp(ip_2_ip4(&upcb->local_ip), old_addr)) { + /* The PCB is bound to the old ipaddr and + * is set to bound to the new one instead */ + ip_addr_copy_from_ip4(upcb->local_ip, *new_addr); + } + } + } + } +} +#endif /* LWIP_IPV4 */ + +#if UDP_DEBUG +/** + * Print UDP header information for debug purposes. + * + * @param udphdr pointer to the udp header in memory. + */ +void +udp_debug_print(struct udp_hdr *udphdr) +{ + LWIP_DEBUGF(UDP_DEBUG, ("UDP header:\n")); + LWIP_DEBUGF(UDP_DEBUG, ("+-------------------------------+\n")); + LWIP_DEBUGF(UDP_DEBUG, ("| %5"U16_F" | %5"U16_F" | (src port, dest port)\n", + ntohs(udphdr->src), ntohs(udphdr->dest))); + LWIP_DEBUGF(UDP_DEBUG, ("+-------------------------------+\n")); + LWIP_DEBUGF(UDP_DEBUG, ("| %5"U16_F" | 0x%04"X16_F" | (len, chksum)\n", + ntohs(udphdr->len), ntohs(udphdr->chksum))); + LWIP_DEBUGF(UDP_DEBUG, ("+-------------------------------+\n")); +} +#endif /* UDP_DEBUG */ + +#endif /* LWIP_UDP */ diff --git a/components/lwip/include/lwip/apps/dhcpserver.h b/components/lwip/include/lwip/apps/dhcpserver.h new file mode 100644 index 0000000000..a0099e32d8 --- /dev/null +++ b/components/lwip/include/lwip/apps/dhcpserver.h @@ -0,0 +1,494 @@ +// Copyright 2015-2016 Espressif Systems (Shanghai) PTE LTD +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at + +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +#ifndef __DHCPS_H__ +#define __DHCPS_H__ + +#include "lwip/ip_addr.h" +//#include "esp_common.h" +#define USE_DNS +/* Here for now until needed in other places in lwIP */ +#ifndef isprint +#define in_range(c, lo, up) ((u8_t)c >= lo && (u8_t)c <= up) +#define isprint(c) in_range(c, 0x20, 0x7f) +#define isdigit(c) in_range(c, '0', '9') +#define isxdigit(c) (isdigit(c) || in_range(c, 'a', 'f') || in_range(c, 'A', 'F')) +#define islower(c) in_range(c, 'a', 'z') +#define isspace(c) (c == ' ' || c == '\f' || c == '\n' || c == '\r' || c == '\t' || c == '\v') +#endif + +#ifdef LWIP_ESP8266 + +typedef struct dhcps_state{ + s16_t state; +} dhcps_state; + +typedef struct dhcps_msg { + u8_t op, htype, hlen, hops; + u8_t xid[4]; + u16_t secs, flags; + u8_t ciaddr[4]; + u8_t yiaddr[4]; + u8_t siaddr[4]; + u8_t giaddr[4]; + u8_t chaddr[16]; + u8_t sname[64]; + u8_t file[128]; + u8_t options[312]; +}dhcps_msg; + +struct dhcps_lease { + bool enable; + ip4_addr_t start_ip; + ip4_addr_t end_ip; +}; + +enum dhcps_offer_option{ + OFFER_START = 0x00, + OFFER_ROUTER = 0x01, + OFFER_END +}; + +struct dhcps_pool{ + ip4_addr_t ip; + u8_t mac[6]; + u32_t lease_timer; +}; + +typedef struct _list_node{ + void *pnode; + struct _list_node *pnext; +}list_node; + +extern u32_t dhcps_lease_time; +#define DHCPS_LEASE_TIMER dhcps_lease_time //0x05A0 + +#define dhcps_router_enabled(offer) ((offer & OFFER_ROUTER) != 0) +void dhcps_start(struct netif *netif); +void dhcps_stop(struct netif *netif); + +#else +#include "lwip/opt.h" + +#include "lwip/netif.h" +#include "lwip/udp.h" + +/** DHCP DEBUG INFO **/ +#define DHCPS_DEBUG 1 +#if DHCPS_DEBUG +#define log_info(message, ...) do { \ + os_printf((message), ##__VA_ARGS__); \ + os_printf("\n"); \ + } while(0); + +#else +#define log_info(message, ...) +#endif + +#if (!defined(unlikely)) +#define unlikely(Expression) !!(Expression) +#endif + +#define REQUIRE_ASSERT(Expression) do{if (!(Expression)) log_info("%d\n", __LINE__);}while(0) + +#define REQUIRE_ACTION(Expression,Label,Action) \ + do{\ + if (unlikely(!(Expression))) \ + {\ + log_info("%d\n", __LINE__);\ + {Action;}\ + goto Label;\ + }\ + }while(0) + +#define REQUIRE_NOERROR(Expression,Label) \ + do{\ + int LocalError;\ + LocalError = (int)Expression;\ + if (unlikely(LocalError != 0)) \ + {\ + log_info("%d 0x%x\n", __LINE__, LocalError);\ + goto Label;\ + }\ + }while(0) + +#define REQUIRE_NOERROR_ACTION(Expression,Label,Action) \ + do{\ + int LocalError;\ + LocalError = (int)Expression;\ + if (unlikely(LocalError != 0)) \ + {\ + log_info("%d\n", __LINE__);\ + {Action;}\ + goto Label;\ + }\ + }while(0) + +#define DHCP_OK 0 +#define DHCP_FAIL -1 +#define DHCP_SERVER_OPENDNS 0xd043dede /* OpenDNS DNS server 208.67.222.222 */ + +/* DHCP message */ +/* + * Code ID of DHCP and BOOTP options + * as defined in RFC 2132 + */ +typedef enum +{ + DHCP_NONE = 0, + DHCPS_DISCOVER = 1, + DHCPS_OFFER = 2, + DHCPS_REQUEST = 3, + DHCPS_DECLINE = 4, + DHCPS_ACK = 5, + DHCPS_NAK = 6, + DHCPS_RELEASE = 7, + DHCPS_INFORM = 8, + DHCP_FORCE_RENEW = 9, + DHCP_LEASE_QUERY = 10, + DHCP_LEASE_UNASSIGNED = 11, + DHCP_LEASE_UNKNOWN = 12, + DHCP_LEASE_ACTIVE = 13, +} dhcp_msg_type; + +typedef enum +{ + BOOTPS = 67, + BOOTPC = 68 +} ports; + +typedef enum +{ + BOOTREQUEST = 1, + BOOTREPLY = 2, +} op_types; + +typedef enum +{ + ETHERNET = 0x01, + ETHERNET_LAN = 0x06, + ETHEFDDI = 0x08, + ETHEIEEE1394 = 0x18 +} hardware_types; + +typedef enum +{ + DHCPS_CHADDR_LEN = 16U, + DHCPS_SNAME_LEN = 64U, + DHCPS_FILE_LEN = 128U, + DHCP_HEADER_SIZE = 236U // without size of options +} head_size; + +typedef struct dhcps +{ + /** transaction identifier of last sent request */ + u32_t xid; + /** incoming msg */ + struct dhcps_msg *msg_in; + /** track PCB allocation state */ + u8_t pcb_allocated; + /** current DHCP state machine state */ + u8_t state; + /** retries of current request */ + u8_t tries; +#if LWIP_DHCP_AUTOIP_COOP + u8_t autoip_coop_state; +#endif + u8_t subnet_mask_given; + + struct pbuf *p_out; /* pbuf of outcoming msg */ + struct dhcp_msg *msg_out; /* outgoing msg */ + u16_t options_out_len; /* outgoing msg options length */ + u16_t request_timeout; /* #ticks with period DHCP_FINE_TIMER_SECS for request timeout */ + u16_t t1_timeout; /* #ticks with period DHCP_COARSE_TIMER_SECS for renewal time */ + u16_t t2_timeout; /* #ticks with period DHCP_COARSE_TIMER_SECS for rebind time */ + u16_t t1_renew_time; /* #ticks with period DHCP_COARSE_TIMER_SECS until next renew try */ + u16_t t2_rebind_time; /* #ticks with period DHCP_COARSE_TIMER_SECS until next rebind try */ + u16_t lease_used; /* #ticks with period DHCP_COARSE_TIMER_SECS since last received DHCP ack */ + u16_t t0_timeout; /* #ticks with period DHCP_COARSE_TIMER_SECS for lease time */ + ip_addr_t server_ip_addr; /* dhcp server address that offered this lease (ip_addr_t because passed to UDP) */ + ip4_addr_t offered_ip_addr; + ip4_addr_t offered_sn_mask; + ip4_addr_t offered_gw_addr; + + u32_t offered_t0_lease; /* lease period (in seconds) */ + u32_t offered_t1_renew; /* recommended renew time (usually 50% of lease period) */ + u32_t offered_t2_rebind; /* recommended rebind time (usually 87.5 of lease period) */ +#if LWIP_DHCP_BOOTP_FILE + ip_addr_t offered_si_addr; + char boot_file_name[DHCP_FILE_LEN]; +#endif /* LWIP_DHCP_BOOTPFILE */ + +} dhcps; + +typedef struct dhcp_message +{ + PACK_STRUCT_FLD_8(u8_t op); + PACK_STRUCT_FLD_8(u8_t htype); + PACK_STRUCT_FLD_8(u8_t hlen); + PACK_STRUCT_FLD_8(u8_t hops); + PACK_STRUCT_FIELD(u32_t xid); + PACK_STRUCT_FIELD(u16_t secs); + PACK_STRUCT_FIELD(u16_t flags); + PACK_STRUCT_FLD_S(ip4_addr_p_t ciaddr); + PACK_STRUCT_FLD_S(ip4_addr_p_t yiaddr); + PACK_STRUCT_FLD_S(ip4_addr_p_t siaddr); + PACK_STRUCT_FLD_S(ip4_addr_p_t giaddr); + PACK_STRUCT_FLD_8(u8_t chaddr[DHCPS_CHADDR_LEN]); + PACK_STRUCT_FLD_8(u8_t sname[DHCPS_SNAME_LEN]); + PACK_STRUCT_FLD_8(u8_t file[DHCPS_FILE_LEN]); +// PACK_STRUCT_FIELD(u32_t cookie); +#define DHCPS_MIN_OPTIONS_LEN 312U + /** make sure user does not configure this too small */ +#if ((defined(DHCPS_OPTIONS_LEN)) && (DHCPS_OPTIONS_LEN < DHCPS_MIN_OPTIONS_LEN)) +#undef DHCPS_OPTIONS_LEN +#endif + /** allow this to be configured in lwipopts.h, but not too small */ +#if (!defined(DHCPS_OPTIONS_LEN)) + /** set this to be sufficient for your options in outgoing DHCP msgs */ +#define DHCPS_OPTIONS_LEN DHCPS_MIN_OPTIONS_LEN +#endif + PACK_STRUCT_FLD_8(u8_t options[DHCPS_OPTIONS_LEN]); +} dhcp_message; + +/** DHCP OPTIONS CODE **/ +typedef enum +{ + /* RFC 1497 Vendor Extensions */ + + PAD = 0, + END = 255, + + SUBNET_MASK = 1, + TIME_OFFSET = 2, + ROUTER = 3, + TIME_SERVER = 4, + NAME_SERVER = 5, + DOMAIN_NAME_SERVER = 6, + LOG_SERVER = 7, + COOKIE_SERVER = 8, + LPR_SERVER = 9, + IMPRESS_SERVER = 10, + RESOURCE_LOCATION_SERVER = 11, + HOST_NAME = 12, + BOOT_FILE_SIZE = 13, + MERIT_DUMP_FILE = 14, + DOMAIN_NAME = 15, + SWAP_SERVER = 16, + ROOT_PATH = 17, + EXTENSIONS_PATH = 18, + + /* IP Layer Parameters per Host */ + + IP_FORWARDING = 19, + NON_LOCAL_SOURCE_ROUTING = 20, + POLICY_FILTER = 21, + MAXIMUM_DATAGRAM_REASSEMBLY_SIZE = 22, + DEFAULT_IP_TIME_TO_LIVE = 23, + PATH_MTU_AGING_TIMEOUT = 24, + PATH_MTU_PLATEAU_TABLE = 25, + + /* IP Layer Parameters per Interface */ + + INTERFACE_MTU = 26, + ALL_SUBNETS_ARE_LOCAL = 27, + BROADCAST_ADDRESS = 28, + PERFORM_MASK_DISCOVERY = 29, + MASK_SUPPLIER = 30, + PERFORM_ROUTER_DISCOVERY = 31, + ROUTER_SOLICITATION_ADDRESS = 32, + STATIC_ROUTE = 33, + + /* Link Layer Parameters per Interface */ + + TRAILER_ENCAPSULATION = 34, + ARP_CACHE_TIMEOUT = 35, + ETHERNET_ENCAPSULATION = 36, + + /* TCP Parameters */ + + TCP_DEFAULT_TTL = 37, + TCP_KEEPALIVE_INTERVAL = 38, + TCP_KEEPALIVE_GARBAGE = 39, + + /* Application and Service Parameters */ + + NETWORK_INFORMATION_SERVICE_DOMAIN = 40, + NETWORK_INFORMATION_SERVERS = 41, + NETWORK_TIME_PROTOCOL_SERVERS = 42, + VENDOR_SPECIFIC_INFORMATION = 43, + NETBIOS_OVER_TCP_IP_NAME_SERVER = 44, + NETBIOS_OVER_TCP_IP_DATAGRAM_DISTRIBUTION_SERVER = 45, + NETBIOS_OVER_TCP_IP_NODE_TYPE = 46, + NETBIOS_OVER_TCP_IP_SCOPE = 47, + X_WINDOW_SYSTEM_FONT_SERVER = 48, + X_WINDOW_SYSTEM_DISPLAY_MANAGER = 49, + NETWORK_INFORMATION_SERVICE_PLUS_DOMAIN = 64, + NETWORK_INFORMATION_SERVICE_PLUS_SERVERS = 65, + MOBILE_IP_HOME_AGENT = 68, + SMTP_SERVER = 69, + POP3_SERVER = 70, + NNTP_SERVER = 71, + DEFAULT_WWW_SERVER = 72, + DEFAULT_FINGER_SERVER = 73, + DEFAULT_IRC_SERVER = 74, + STREETTALK_SERVER = 75, + STREETTALK_DIRECTORY_ASSISTANCE_SERVER = 76, + + /* DHCP Extensions */ + + REQUESTED_IP_ADDRESS = 50, + IP_ADDRESS_LEASE_TIME = 51, + OPTION_OVERLOAD = 52, + TFTP_SERVER_NAME = 66, + BOOTFILE_NAME = 67, + DHCP_MESSAGE_TYPE = 53, + SERVER_IDENTIFIER = 54, + PARAMETER_REQUEST_LIST = 55, + MESSAGE = 56, + MAXIMUM_DHCP_MESSAGE_SIZE = 57, + RENEWAL_T1_TIME_VALUE = 58, + REBINDING_T2_TIME_VALUE = 59, + VENDOR_CLASS_IDENTIFIER = 60, + CLIENT_IDENTIFIER = 61, + + USER_CLASS = 77, + FQDN = 81, + DHCP_AGENT_OPTIONS = 82, + NDS_SERVERS = 85, + NDS_TREE_NAME = 86, + NDS_CONTEXT = 87, + CLIENT_LAST_TRANSACTION_TIME = 91, + ASSOCIATED_IP = 92, + USER_AUTHENTICATION_PROTOCOL = 98, + AUTO_CONFIGURE = 116, + NAME_SERVICE_SEARCH = 117, + SUBNET_SELECTION = 118, + DOMAIN_SEARCH = 119, + CLASSLESS_ROUTE = 121, +} dhcp_msg_option; + +typedef struct dhcp_option +{ + uint8_t id; // option id + uint8_t len; // option length + uint8_t data[256]; // option data + + STAILQ_ENTRY(dhcp_option) pointers; // pointers, see queue(3) +} dhcp_option; + +typedef STAILQ_HEAD(dhcp_option_list_, dhcp_option) DHCP_OPTION_LIST; +typedef struct dhcp_option_list_ dhcp_option_list; + +/* + * Header to manage the database of address bindings. + */ + +// static association or dynamic +enum +{ + DYNAMIC = 0, + STATIC = 1, + STATIC_OR_DYNAMIC = 2 +}; + +// binding status +enum +{ + EMPTY = 0, + ASSOCIATED, + PENDINGD, + EXPIRED, + RELEASED +}; + +/* + * IP address used to delimitate an address pool. + */ +typedef struct pool_indexes +{ + uint32_t first; // first address of the pool + uint32_t last; // last address of the pool + uint32_t current; // current available address +}pool_indexes; + +/* + * The bindings are organized as a double linked list + * using the standard queue(3) library + */ +typedef struct address_binding +{ + uint32_t address; // address + uint8_t cident_len; // client identifier len + uint8_t cident[256]; // client identifier + + time_t binding_time; // time of binding + time_t lease_time; // duration of lease + + int status; // binding status + int is_static; // check if it is a static binding + + STAILQ_ENTRY(address_binding) pointers; // list pointers, see queue(3) +}address_binding; + +typedef STAILQ_HEAD(binding_list_, address_binding) BINDING_LIST_HEAD; +typedef struct binding_list_ binding_list; + +/* + * Global association pool. + * + * The (static or dynamic) associations tables of the DHCP server, + * are maintained in this global structure. + * + * Note: all the IP addresses are in host order, + * to allow an easy manipulation. + */ + +typedef struct address_pool +{ + uint32_t server_id; // this server id (IP address) + uint32_t netmask; // network mask + uint32_t gateway; // network gateway + + char device[16]; // network device to use + + pool_indexes indexes; // used to delimitate a pool of available addresses + + time_t lease_time; // default lease time + time_t pending_time; // duration of a binding in the pending state + struct udp_pcb *socket; // + bool flags; + + dhcp_option_list options; // options for this pool, see queue + + binding_list bindings; // associated addresses, see queue(3) +}address_pool; + +/* + * Internal representation of a DHCP message, + * with options parsed into a list... + */ +typedef struct dhcps_msg +{ + dhcp_message hdr; + dhcp_option_list opts; +} dhcps_msg; + +bool dhcps_option_set(u8_t opt_id, void* optarg); +void dhcps_start(struct netif *netif, struct dhcps_lease *lease_pool); +void dhcps_stop(struct netif *netif); +bool dhcps_lease_set(struct dhcps_lease *please); +bool dhcps_lease_get(struct dhcps_lease *please); + +#endif +#endif diff --git a/components/lwip/include/lwip/lwip/api.h b/components/lwip/include/lwip/lwip/api.h new file mode 100755 index 0000000000..985eb76d4a --- /dev/null +++ b/components/lwip/include/lwip/lwip/api.h @@ -0,0 +1,368 @@ +/* + * Copyright (c) 2001-2004 Swedish Institute of Computer Science. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + * + */ +#ifndef LWIP_HDR_API_H +#define LWIP_HDR_API_H + +#include "lwip/opt.h" + +#if LWIP_NETCONN || LWIP_SOCKET /* don't build if not configured for use in lwipopts.h */ +/* Note: Netconn API is always available when sockets are enabled - + * sockets are implemented on top of them */ + +#include /* for size_t */ + +#include "lwip/netbuf.h" +#include "lwip/sys.h" +#include "lwip/ip_addr.h" +#include "lwip/err.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/* Throughout this file, IP addresses and port numbers are expected to be in + * the same byte order as in the corresponding pcb. + */ + +/* Flags for netconn_write (u8_t) */ +#define NETCONN_NOFLAG 0x00 +#define NETCONN_NOCOPY 0x00 /* Only for source code compatibility */ +#define NETCONN_COPY 0x01 +#define NETCONN_MORE 0x02 +#define NETCONN_DONTBLOCK 0x04 + +/* Flags for struct netconn.flags (u8_t) */ +/** Should this netconn avoid blocking? */ +#define NETCONN_FLAG_NON_BLOCKING 0x02 +/** Was the last connect action a non-blocking one? */ +#define NETCONN_FLAG_IN_NONBLOCKING_CONNECT 0x04 +/** If this is set, a TCP netconn must call netconn_recved() to update + the TCP receive window (done automatically if not set). */ +#define NETCONN_FLAG_NO_AUTO_RECVED 0x08 +/** If a nonblocking write has been rejected before, poll_tcp needs to + check if the netconn is writable again */ +#define NETCONN_FLAG_CHECK_WRITESPACE 0x10 +#if LWIP_IPV6 +/** If this flag is set then only IPv6 communication is allowed on the + netconn. As per RFC#3493 this features defaults to OFF allowing + dual-stack usage by default. */ +#define NETCONN_FLAG_IPV6_V6ONLY 0x20 +#endif /* LWIP_IPV6 */ + + + /* Helpers to process several netconn_types by the same code */ +#define NETCONNTYPE_GROUP(t) ((t)&0xF0) +#define NETCONNTYPE_DATAGRAM(t) ((t)&0xE0) +#if LWIP_IPV6 +#define NETCONN_TYPE_IPV6 0x08 +#define NETCONNTYPE_ISIPV6(t) (((t)&NETCONN_TYPE_IPV6) != 0) +#define NETCONNTYPE_ISUDPLITE(t) (((t)&0xF3) == NETCONN_UDPLITE) +#define NETCONNTYPE_ISUDPNOCHKSUM(t) (((t)&0xF3) == NETCONN_UDPNOCHKSUM) +#else /* LWIP_IPV6 */ +#define NETCONNTYPE_ISUDPLITE(t) ((t) == NETCONN_UDPLITE) +#define NETCONNTYPE_ISUDPNOCHKSUM(t) ((t) == NETCONN_UDPNOCHKSUM) +#endif /* LWIP_IPV6 */ + +/** Protocol family and type of the netconn */ +enum netconn_type { + NETCONN_INVALID = 0, + /* NETCONN_TCP Group */ + NETCONN_TCP = 0x10, +#if LWIP_IPV6 + NETCONN_TCP_IPV6 = NETCONN_TCP | NETCONN_TYPE_IPV6 /* 0x18 */, +#endif /* LWIP_IPV6 */ + /* NETCONN_UDP Group */ + NETCONN_UDP = 0x20, + NETCONN_UDPLITE = 0x21, + NETCONN_UDPNOCHKSUM = 0x22, + +#if LWIP_IPV6 + NETCONN_UDP_IPV6 = NETCONN_UDP | NETCONN_TYPE_IPV6 /* 0x28 */, + NETCONN_UDPLITE_IPV6 = NETCONN_UDPLITE | NETCONN_TYPE_IPV6 /* 0x29 */, + NETCONN_UDPNOCHKSUM_IPV6 = NETCONN_UDPNOCHKSUM | NETCONN_TYPE_IPV6 /* 0x2a */, +#endif /* LWIP_IPV6 */ + + /* NETCONN_RAW Group */ + NETCONN_RAW = 0x40 +#if LWIP_IPV6 + , NETCONN_RAW_IPV6 = NETCONN_RAW | NETCONN_TYPE_IPV6 /* 0x48 */ +#endif /* LWIP_IPV6 */ +}; + +/** Current state of the netconn. Non-TCP netconns are always + * in state NETCONN_NONE! */ +enum netconn_state { + NETCONN_NONE, + NETCONN_WRITE, + NETCONN_LISTEN, + NETCONN_CONNECT, + NETCONN_CLOSE +}; + +/** Use to inform the callback function about changes */ +enum netconn_evt { + NETCONN_EVT_RCVPLUS, + NETCONN_EVT_RCVMINUS, + NETCONN_EVT_SENDPLUS, + NETCONN_EVT_SENDMINUS, + NETCONN_EVT_ERROR +}; + +#if LWIP_IGMP || (LWIP_IPV6 && LWIP_IPV6_MLD) +/** Used for netconn_join_leave_group() */ +enum netconn_igmp { + NETCONN_JOIN, + NETCONN_LEAVE +}; +#endif /* LWIP_IGMP || (LWIP_IPV6 && LWIP_IPV6_MLD) */ + +#if LWIP_DNS +/* Used for netconn_gethostbyname_addrtype(), these should match the DNS_ADDRTYPE defines in dns.h */ +#define NETCONN_DNS_DEFAULT NETCONN_DNS_IPV4_IPV6 +#define NETCONN_DNS_IPV4 0 +#define NETCONN_DNS_IPV6 1 +#define NETCONN_DNS_IPV4_IPV6 2 /* try to resolve IPv4 first, try IPv6 if IPv4 fails only */ +#define NETCONN_DNS_IPV6_IPV4 3 /* try to resolve IPv6 first, try IPv4 if IPv6 fails only */ +#endif /* LWIP_DNS */ + +/* forward-declare some structs to avoid to include their headers */ +struct ip_pcb; +struct tcp_pcb; +struct udp_pcb; +struct raw_pcb; +struct netconn; +struct api_msg_msg; + +/** A callback prototype to inform about events for a netconn */ +typedef void (* netconn_callback)(struct netconn *, enum netconn_evt, u16_t len); + +/** A netconn descriptor */ +struct netconn { + /** type of the netconn (TCP, UDP or RAW) */ + enum netconn_type type; + /** current state of the netconn */ + enum netconn_state state; + /** the lwIP internal protocol control block */ + union { + struct ip_pcb *ip; + struct tcp_pcb *tcp; + struct udp_pcb *udp; + struct raw_pcb *raw; + } pcb; + /** the last error this netconn had */ + err_t last_err; + +#if !LWIP_NETCONN_SEM_PER_THREAD + /** sem that is used to synchronously execute functions in the core context */ + sys_sem_t op_completed; + +#ifdef LWIP_ESP8266 + sys_sem_t snd_op_completed; //only for snd semphore +#endif + +#endif + + /** mbox where received packets are stored until they are fetched + by the netconn application thread (can grow quite big) */ + sys_mbox_t recvmbox; +#if LWIP_TCP + /** mbox where new connections are stored until processed + by the application thread */ + sys_mbox_t acceptmbox; +#endif /* LWIP_TCP */ + /** only used for socket layer */ +#if LWIP_SOCKET + int socket; +#endif /* LWIP_SOCKET */ +#if LWIP_SO_SNDTIMEO + /** timeout to wait for sending data (which means enqueueing data for sending + in internal buffers) in milliseconds */ + s32_t send_timeout; +#endif /* LWIP_SO_RCVTIMEO */ +#if LWIP_SO_RCVTIMEO + /** timeout in milliseconds to wait for new data to be received + (or connections to arrive for listening netconns) */ + int recv_timeout; +#endif /* LWIP_SO_RCVTIMEO */ +#if LWIP_SO_RCVBUF + /** maximum amount of bytes queued in recvmbox + not used for TCP: adjust TCP_WND instead! */ + int recv_bufsize; + /** number of bytes currently in recvmbox to be received, + tested against recv_bufsize to limit bytes on recvmbox + for UDP and RAW, used for FIONREAD */ + int recv_avail; +#endif /* LWIP_SO_RCVBUF */ +#if LWIP_SO_LINGER + /** values <0 mean linger is disabled, values > 0 are seconds to linger */ + s16_t linger; +#endif /* LWIP_SO_LINGER */ + /** flags holding more netconn-internal state, see NETCONN_FLAG_* defines */ + u8_t flags; +#if LWIP_TCP + /** TCP: when data passed to netconn_write doesn't fit into the send buffer, + this temporarily stores how much is already sent. */ + size_t write_offset; + /** TCP: when data passed to netconn_write doesn't fit into the send buffer, + this temporarily stores the message. + Also used during connect and close. */ + struct api_msg_msg *current_msg; +#endif /* LWIP_TCP */ + /** A callback function that is informed about events for this netconn */ + netconn_callback callback; +}; + +/** Register an Network connection event */ +#define API_EVENT(c,e,l) if (c->callback) { \ + (*c->callback)(c, e, l); \ + } + +/** Set conn->last_err to err but don't overwrite fatal errors */ +#define NETCONN_SET_SAFE_ERR(conn, err) do { if ((conn) != NULL) { \ + SYS_ARCH_DECL_PROTECT(netconn_set_safe_err_lev); \ + SYS_ARCH_PROTECT(netconn_set_safe_err_lev); \ + if (!ERR_IS_FATAL((conn)->last_err)) { \ + (conn)->last_err = err; \ + } \ + SYS_ARCH_UNPROTECT(netconn_set_safe_err_lev); \ +}} while(0); + +/* Network connection functions: */ +#define netconn_new(t) netconn_new_with_proto_and_callback(t, 0, NULL) +#define netconn_new_with_callback(t, c) netconn_new_with_proto_and_callback(t, 0, c) +struct netconn *netconn_new_with_proto_and_callback(enum netconn_type t, u8_t proto, + netconn_callback callback); +err_t netconn_delete(struct netconn *conn); +/** Get the type of a netconn (as enum netconn_type). */ +#define netconn_type(conn) (conn->type) + +err_t netconn_getaddr(struct netconn *conn, ip_addr_t *addr, + u16_t *port, u8_t local); +#define netconn_peer(c,i,p) netconn_getaddr(c,i,p,0) +#define netconn_addr(c,i,p) netconn_getaddr(c,i,p,1) + +err_t netconn_bind(struct netconn *conn, const ip_addr_t *addr, u16_t port); +err_t netconn_connect(struct netconn *conn, const ip_addr_t *addr, u16_t port); +err_t netconn_disconnect (struct netconn *conn); +err_t netconn_listen_with_backlog(struct netconn *conn, u8_t backlog); +#define netconn_listen(conn) netconn_listen_with_backlog(conn, TCP_DEFAULT_LISTEN_BACKLOG) +err_t netconn_accept(struct netconn *conn, struct netconn **new_conn); +err_t netconn_recv(struct netconn *conn, struct netbuf **new_buf); +err_t netconn_recv_tcp_pbuf(struct netconn *conn, struct pbuf **new_buf); +void netconn_recved(struct netconn *conn, u32_t length); +err_t netconn_sendto(struct netconn *conn, struct netbuf *buf, + const ip_addr_t *addr, u16_t port); +err_t netconn_send(struct netconn *conn, struct netbuf *buf); +err_t netconn_write_partly(struct netconn *conn, const void *dataptr, size_t size, + u8_t apiflags, size_t *bytes_written); +#define netconn_write(conn, dataptr, size, apiflags) \ + netconn_write_partly(conn, dataptr, size, apiflags, NULL) +err_t netconn_close(struct netconn *conn); +err_t netconn_shutdown(struct netconn *conn, u8_t shut_rx, u8_t shut_tx); + +#if LWIP_IGMP || (LWIP_IPV6 && LWIP_IPV6_MLD) +err_t netconn_join_leave_group(struct netconn *conn, const ip_addr_t *multiaddr, + const ip_addr_t *netif_addr, enum netconn_igmp join_or_leave); +#endif /* LWIP_IGMP || (LWIP_IPV6 && LWIP_IPV6_MLD) */ +#if LWIP_DNS +#if LWIP_IPV4 && LWIP_IPV6 +err_t netconn_gethostbyname_addrtype(const char *name, ip_addr_t *addr, u8_t dns_addrtype); +#define netconn_gethostbyname(name, addr) netconn_gethostbyname_addrtype(name, addr, NETCONN_DNS_DEFAULT) +#else /* LWIP_IPV4 && LWIP_IPV6 */ +err_t netconn_gethostbyname(const char *name, ip_addr_t *addr); +#define netconn_gethostbyname_addrtype(name, addr, dns_addrtype) netconn_gethostbyname(name, addr) +#endif /* LWIP_IPV4 && LWIP_IPV6 */ +#endif /* LWIP_DNS */ + +#define netconn_err(conn) ((conn)->last_err) +#define netconn_recv_bufsize(conn) ((conn)->recv_bufsize) + +/** Set the blocking status of netconn calls (@todo: write/send is missing) */ +#define netconn_set_nonblocking(conn, val) do { if(val) { \ + (conn)->flags |= NETCONN_FLAG_NON_BLOCKING; \ +} else { \ + (conn)->flags &= ~ NETCONN_FLAG_NON_BLOCKING; }} while(0) +/** Get the blocking status of netconn calls (@todo: write/send is missing) */ +#define netconn_is_nonblocking(conn) (((conn)->flags & NETCONN_FLAG_NON_BLOCKING) != 0) + +/** TCP: Set the no-auto-recved status of netconn calls (see NETCONN_FLAG_NO_AUTO_RECVED) */ +#define netconn_set_noautorecved(conn, val) do { if(val) { \ + (conn)->flags |= NETCONN_FLAG_NO_AUTO_RECVED; \ +} else { \ + (conn)->flags &= ~ NETCONN_FLAG_NO_AUTO_RECVED; }} while(0) +/** TCP: Get the no-auto-recved status of netconn calls (see NETCONN_FLAG_NO_AUTO_RECVED) */ +#define netconn_get_noautorecved(conn) (((conn)->flags & NETCONN_FLAG_NO_AUTO_RECVED) != 0) + +#if LWIP_IPV6 +/** TCP: Set the IPv6 ONLY status of netconn calls (see NETCONN_FLAG_IPV6_V6ONLY) */ +#define netconn_set_ipv6only(conn, val) do { if(val) { \ + (conn)->flags |= NETCONN_FLAG_IPV6_V6ONLY; \ +} else { \ + (conn)->flags &= ~ NETCONN_FLAG_IPV6_V6ONLY; }} while(0) +/** TCP: Get the IPv6 ONLY status of netconn calls (see NETCONN_FLAG_IPV6_V6ONLY) */ +#define netconn_get_ipv6only(conn) (((conn)->flags & NETCONN_FLAG_IPV6_V6ONLY) != 0) +#endif /* LWIP_IPV6 */ + +#if LWIP_SO_SNDTIMEO +/** Set the send timeout in milliseconds */ +#define netconn_set_sendtimeout(conn, timeout) ((conn)->send_timeout = (timeout)) +/** Get the send timeout in milliseconds */ +#define netconn_get_sendtimeout(conn) ((conn)->send_timeout) +#endif /* LWIP_SO_SNDTIMEO */ +#if LWIP_SO_RCVTIMEO +/** Set the receive timeout in milliseconds */ +#define netconn_set_recvtimeout(conn, timeout) ((conn)->recv_timeout = (timeout)) +/** Get the receive timeout in milliseconds */ +#define netconn_get_recvtimeout(conn) ((conn)->recv_timeout) +#endif /* LWIP_SO_RCVTIMEO */ +#if LWIP_SO_RCVBUF +/** Set the receive buffer in bytes */ +#define netconn_set_recvbufsize(conn, recvbufsize) ((conn)->recv_bufsize = (recvbufsize)) +/** Get the receive buffer in bytes */ +#define netconn_get_recvbufsize(conn) ((conn)->recv_bufsize) +#endif /* LWIP_SO_RCVBUF*/ + +#if LWIP_NETCONN_SEM_PER_THREAD +void netconn_thread_init(void); +void netconn_thread_cleanup(void); +#else /* LWIP_NETCONN_SEM_PER_THREAD */ +#define netconn_thread_init() +#define netconn_thread_cleanup() +#endif /* LWIP_NETCONN_SEM_PER_THREAD */ + +#ifdef __cplusplus +} +#endif + +#endif /* LWIP_NETCONN || LWIP_SOCKET */ + +#endif /* LWIP_HDR_API_H */ diff --git a/components/lwip/include/lwip/lwip/arch.h b/components/lwip/include/lwip/lwip/arch.h new file mode 100755 index 0000000000..7b99c2606b --- /dev/null +++ b/components/lwip/include/lwip/lwip/arch.h @@ -0,0 +1,233 @@ +/* + * Copyright (c) 2001-2004 Swedish Institute of Computer Science. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + * + */ +#ifndef LWIP_HDR_ARCH_H +#define LWIP_HDR_ARCH_H + +#ifndef LITTLE_ENDIAN +#define LITTLE_ENDIAN 1234 +#endif + +#ifndef BIG_ENDIAN +#define BIG_ENDIAN 4321 +#endif + +#include "arch/cc.h" + +/** Temporary: define format string for size_t if not defined in cc.h */ +#ifndef SZT_F +#define SZT_F U32_F +#endif /* SZT_F */ +/** Temporary upgrade helper: define format string for u8_t as hex if not + defined in cc.h */ +#ifndef X8_F +#define X8_F "02x" +#endif /* X8_F */ + +#ifdef __cplusplus +extern "C" { +#endif + +#ifndef PACK_STRUCT_BEGIN +#define PACK_STRUCT_BEGIN +#endif /* PACK_STRUCT_BEGIN */ + +#ifndef PACK_STRUCT_END +#define PACK_STRUCT_END +#endif /* PACK_STRUCT_END */ + +#ifndef PACK_STRUCT_STRUCT +#define PACK_STRUCT_STRUCT +#endif /* PACK_STRUCT_STRUCT */ + +#ifndef PACK_STRUCT_FIELD +#define PACK_STRUCT_FIELD(x) x +#endif /* PACK_STRUCT_FIELD */ + +/* Used for struct fields of u8_t, + * where some compilers warn that packing is not necessary */ +#ifndef PACK_STRUCT_FLD_8 +#define PACK_STRUCT_FLD_8(x) PACK_STRUCT_FIELD(x) +#endif /* PACK_STRUCT_FLD_8 */ + +/* Used for struct fields of that are packed structs themself, + * where some compilers warn that packing is not necessary */ +#ifndef PACK_STRUCT_FLD_S +#define PACK_STRUCT_FLD_S(x) PACK_STRUCT_FIELD(x) +#endif /* PACK_STRUCT_FLD_S */ + + +#ifndef LWIP_UNUSED_ARG +#define LWIP_UNUSED_ARG(x) (void)x +#endif /* LWIP_UNUSED_ARG */ + + +#ifdef LWIP_PROVIDE_ERRNO + +#define EPERM 1 /* Operation not permitted */ +#define ENOENT 2 /* No such file or directory */ +#define ESRCH 3 /* No such process */ +#define EINTR 4 /* Interrupted system call */ +#define EIO 5 /* I/O error */ +#define ENXIO 6 /* No such device or address */ +#define E2BIG 7 /* Arg list too long */ +#define ENOEXEC 8 /* Exec format error */ +#define EBADF 9 /* Bad file number */ +#define ECHILD 10 /* No child processes */ +#define EAGAIN 11 /* Try again */ +#define ENOMEM 12 /* Out of memory */ +#define EACCES 13 /* Permission denied */ +#define EFAULT 14 /* Bad address */ +#define ENOTBLK 15 /* Block device required */ +#define EBUSY 16 /* Device or resource busy */ +#define EEXIST 17 /* File exists */ +#define EXDEV 18 /* Cross-device link */ +#define ENODEV 19 /* No such device */ +#define ENOTDIR 20 /* Not a directory */ +#define EISDIR 21 /* Is a directory */ +#define EINVAL 22 /* Invalid argument */ +#define ENFILE 23 /* File table overflow */ +#define EMFILE 24 /* Too many open files */ +#define ENOTTY 25 /* Not a typewriter */ +#define ETXTBSY 26 /* Text file busy */ +#define EFBIG 27 /* File too large */ +#define ENOSPC 28 /* No space left on device */ +#define ESPIPE 29 /* Illegal seek */ +#define EROFS 30 /* Read-only file system */ +#define EMLINK 31 /* Too many links */ +#define EPIPE 32 /* Broken pipe */ +#define EDOM 33 /* Math argument out of domain of func */ +#define ERANGE 34 /* Math result not representable */ +#define EDEADLK 35 /* Resource deadlock would occur */ +#define ENAMETOOLONG 36 /* File name too long */ +#define ENOLCK 37 /* No record locks available */ +#define ENOSYS 38 /* Function not implemented */ +#define ENOTEMPTY 39 /* Directory not empty */ +#define ELOOP 40 /* Too many symbolic links encountered */ +#define EWOULDBLOCK EAGAIN /* Operation would block */ +#define ENOMSG 42 /* No message of desired type */ +#define EIDRM 43 /* Identifier removed */ +#define ECHRNG 44 /* Channel number out of range */ +#define EL2NSYNC 45 /* Level 2 not synchronized */ +#define EL3HLT 46 /* Level 3 halted */ +#define EL3RST 47 /* Level 3 reset */ +#define ELNRNG 48 /* Link number out of range */ +#define EUNATCH 49 /* Protocol driver not attached */ +#define ENOCSI 50 /* No CSI structure available */ +#define EL2HLT 51 /* Level 2 halted */ +#define EBADE 52 /* Invalid exchange */ +#define EBADR 53 /* Invalid request descriptor */ +#define EXFULL 54 /* Exchange full */ +#define ENOANO 55 /* No anode */ +#define EBADRQC 56 /* Invalid request code */ +#define EBADSLT 57 /* Invalid slot */ + +#define EDEADLOCK EDEADLK + +#define EBFONT 59 /* Bad font file format */ +#define ENOSTR 60 /* Device not a stream */ +#define ENODATA 61 /* No data available */ +#define ETIME 62 /* Timer expired */ +#define ENOSR 63 /* Out of streams resources */ +#define ENONET 64 /* Machine is not on the network */ +#define ENOPKG 65 /* Package not installed */ +#define EREMOTE 66 /* Object is remote */ +#define ENOLINK 67 /* Link has been severed */ +#define EADV 68 /* Advertise error */ +#define ESRMNT 69 /* Srmount error */ +#define ECOMM 70 /* Communication error on send */ +#define EPROTO 71 /* Protocol error */ +#define EMULTIHOP 72 /* Multihop attempted */ +#define EDOTDOT 73 /* RFS specific error */ +#define EBADMSG 74 /* Not a data message */ +#define EOVERFLOW 75 /* Value too large for defined data type */ +#define ENOTUNIQ 76 /* Name not unique on network */ +#define EBADFD 77 /* File descriptor in bad state */ +#define EREMCHG 78 /* Remote address changed */ +#define ELIBACC 79 /* Can not access a needed shared library */ +#define ELIBBAD 80 /* Accessing a corrupted shared library */ +#define ELIBSCN 81 /* .lib section in a.out corrupted */ +#define ELIBMAX 82 /* Attempting to link in too many shared libraries */ +#define ELIBEXEC 83 /* Cannot exec a shared library directly */ +#define EILSEQ 84 /* Illegal byte sequence */ +#define ERESTART 85 /* Interrupted system call should be restarted */ +#define ESTRPIPE 86 /* Streams pipe error */ +#define EUSERS 87 /* Too many users */ +#define ENOTSOCK 88 /* Socket operation on non-socket */ +#define EDESTADDRREQ 89 /* Destination address required */ +#define EMSGSIZE 90 /* Message too long */ +#define EPROTOTYPE 91 /* Protocol wrong type for socket */ +#define ENOPROTOOPT 92 /* Protocol not available */ +#define EPROTONOSUPPORT 93 /* Protocol not supported */ +#define ESOCKTNOSUPPORT 94 /* Socket type not supported */ +#define EOPNOTSUPP 95 /* Operation not supported on transport endpoint */ +#define EPFNOSUPPORT 96 /* Protocol family not supported */ +#define EAFNOSUPPORT 97 /* Address family not supported by protocol */ +#define EADDRINUSE 98 /* Address already in use */ +#define EADDRNOTAVAIL 99 /* Cannot assign requested address */ +#define ENETDOWN 100 /* Network is down */ +#define ENETUNREACH 101 /* Network is unreachable */ +#define ENETRESET 102 /* Network dropped connection because of reset */ +#define ECONNABORTED 103 /* Software caused connection abort */ +#define ECONNRESET 104 /* Connection reset by peer */ +#define ENOBUFS 105 /* No buffer space available */ +#define EISCONN 106 /* Transport endpoint is already connected */ +#define ENOTCONN 107 /* Transport endpoint is not connected */ +#define ESHUTDOWN 108 /* Cannot send after transport endpoint shutdown */ +#define ETOOMANYREFS 109 /* Too many references: cannot splice */ +#define ETIMEDOUT 110 /* Connection timed out */ +#define ECONNREFUSED 111 /* Connection refused */ +#define EHOSTDOWN 112 /* Host is down */ +#define EHOSTUNREACH 113 /* No route to host */ +#define EALREADY 114 /* Operation already in progress */ +#define EINPROGRESS 115 /* Operation now in progress */ +#define ESTALE 116 /* Stale NFS file handle */ +#define EUCLEAN 117 /* Structure needs cleaning */ +#define ENOTNAM 118 /* Not a XENIX named type file */ +#define ENAVAIL 119 /* No XENIX semaphores available */ +#define EISNAM 120 /* Is a named type file */ +#define EREMOTEIO 121 /* Remote I/O error */ +#define EDQUOT 122 /* Quota exceeded */ + +#define ENOMEDIUM 123 /* No medium found */ +#define EMEDIUMTYPE 124 /* Wrong medium type */ + +#ifndef errno +extern int errno; +#endif + +#endif /* LWIP_PROVIDE_ERRNO */ + +#ifdef __cplusplus +} +#endif + +#endif /* LWIP_HDR_ARCH_H */ diff --git a/components/lwip/include/lwip/lwip/autoip.h b/components/lwip/include/lwip/lwip/autoip.h new file mode 100755 index 0000000000..c89fe3ff12 --- /dev/null +++ b/components/lwip/include/lwip/lwip/autoip.h @@ -0,0 +1,124 @@ +/** + * @file + * + * AutoIP Automatic LinkLocal IP Configuration + */ + +/* + * + * Copyright (c) 2007 Dominik Spies + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * Author: Dominik Spies + * + * This is a AutoIP implementation for the lwIP TCP/IP stack. It aims to conform + * with RFC 3927. + * + * + * Please coordinate changes and requests with Dominik Spies + * + */ + +#ifndef LWIP_HDR_AUTOIP_H +#define LWIP_HDR_AUTOIP_H + +#include "lwip/opt.h" + +#if LWIP_IPV4 && LWIP_AUTOIP /* don't build if not configured for use in lwipopts.h */ + +#include "lwip/netif.h" +/* #include "lwip/udp.h" */ +#include "netif/etharp.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/* AutoIP Timing */ +#define AUTOIP_TMR_INTERVAL 100 +#define AUTOIP_TICKS_PER_SECOND (1000 / AUTOIP_TMR_INTERVAL) + +/* RFC 3927 Constants */ +#define PROBE_WAIT 1 /* second (initial random delay) */ +#define PROBE_MIN 1 /* second (minimum delay till repeated probe) */ +#define PROBE_MAX 2 /* seconds (maximum delay till repeated probe) */ +#define PROBE_NUM 3 /* (number of probe packets) */ +#define ANNOUNCE_NUM 2 /* (number of announcement packets) */ +#define ANNOUNCE_INTERVAL 2 /* seconds (time between announcement packets) */ +#define ANNOUNCE_WAIT 2 /* seconds (delay before announcing) */ +#define MAX_CONFLICTS 10 /* (max conflicts before rate limiting) */ +#define RATE_LIMIT_INTERVAL 60 /* seconds (delay between successive attempts) */ +#define DEFEND_INTERVAL 10 /* seconds (min. wait between defensive ARPs) */ + +/* AutoIP client states */ +#define AUTOIP_STATE_OFF 0 +#define AUTOIP_STATE_PROBING 1 +#define AUTOIP_STATE_ANNOUNCING 2 +#define AUTOIP_STATE_BOUND 3 + +struct autoip +{ + ip4_addr_t llipaddr; /* the currently selected, probed, announced or used LL IP-Address */ + u8_t state; /* current AutoIP state machine state */ + u8_t sent_num; /* sent number of probes or announces, dependent on state */ + u16_t ttw; /* ticks to wait, tick is AUTOIP_TMR_INTERVAL long */ + u8_t lastconflict; /* ticks until a conflict can be solved by defending */ + u8_t tried_llipaddr; /* total number of probed/used Link Local IP-Addresses */ +}; + + +#define autoip_init() /* Compatibility define, no init needed. */ + +/** Set a struct autoip allocated by the application to work with */ +void autoip_set_struct(struct netif *netif, struct autoip *autoip); + +/** Remove a struct autoip previously set to the netif using autoip_set_struct() */ +#define autoip_remove_struct(netif) do { (netif)->autoip = NULL; } while (0) + +/** Start AutoIP client */ +err_t autoip_start(struct netif *netif); + +/** Stop AutoIP client */ +err_t autoip_stop(struct netif *netif); + +/** Handles every incoming ARP Packet, called by etharp_arp_input */ +void autoip_arp_reply(struct netif *netif, struct etharp_hdr *hdr); + +/** Has to be called in loop every AUTOIP_TMR_INTERVAL milliseconds */ +void autoip_tmr(void); + +/** Handle a possible change in the network configuration */ +void autoip_network_changed(struct netif *netif); + +/** check if AutoIP supplied netif->ip_addr */ +u8_t autoip_supplied_address(struct netif *netif); + +#ifdef __cplusplus +} +#endif + +#endif /* LWIP_IPV4 && LWIP_AUTOIP */ + +#endif /* LWIP_HDR_AUTOIP_H */ diff --git a/components/lwip/include/lwip/lwip/debug.h b/components/lwip/include/lwip/lwip/debug.h new file mode 100755 index 0000000000..973a633d9d --- /dev/null +++ b/components/lwip/include/lwip/lwip/debug.h @@ -0,0 +1,117 @@ +/* + * Copyright (c) 2001-2004 Swedish Institute of Computer Science. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + * + */ +#ifndef LWIP_HDR_DEBUG_H +#define LWIP_HDR_DEBUG_H + +#include "lwip/arch.h" +#include "lwip/opt.h" + +/** lower two bits indicate debug level + * - 0 all + * - 1 warning + * - 2 serious + * - 3 severe + */ +#define LWIP_DBG_LEVEL_ALL 0x00 +#define LWIP_DBG_LEVEL_OFF LWIP_DBG_LEVEL_ALL /* compatibility define only */ +#define LWIP_DBG_LEVEL_WARNING 0x01 /* bad checksums, dropped packets, ... */ +#define LWIP_DBG_LEVEL_SERIOUS 0x02 /* memory allocation failures, ... */ +#define LWIP_DBG_LEVEL_SEVERE 0x03 +#define LWIP_DBG_MASK_LEVEL 0x03 + +/** flag for LWIP_DEBUGF to enable that debug message */ +#define LWIP_DBG_ON 0x80U +/** flag for LWIP_DEBUGF to disable that debug message */ +#define LWIP_DBG_OFF 0x00U + +/** flag for LWIP_DEBUGF indicating a tracing message (to follow program flow) */ +#define LWIP_DBG_TRACE 0x40U +/** flag for LWIP_DEBUGF indicating a state debug message (to follow module states) */ +#define LWIP_DBG_STATE 0x20U +/** flag for LWIP_DEBUGF indicating newly added code, not thoroughly tested yet */ +#define LWIP_DBG_FRESH 0x10U +/** flag for LWIP_DEBUGF to halt after printing this debug message */ +#define LWIP_DBG_HALT 0x08U + +/** + * LWIP_NOASSERT: Disable LWIP_ASSERT checks. + * -- To disable assertions define LWIP_NOASSERT in arch/cc.h. + */ +#ifndef LWIP_NOASSERT +#define LWIP_ASSERT(message, assertion) do { if(!(assertion)) \ + LWIP_PLATFORM_ASSERT(message); } while(0) +#ifndef LWIP_PLATFORM_ASSERT +#error "If you want to use LWIP_ASSERT, LWIP_PLATFORM_ASSERT(message) needs to be defined in your arch/cc.h" +#endif +#else /* LWIP_NOASSERT */ +#define LWIP_ASSERT(message, assertion) +#endif /* LWIP_NOASSERT */ + +/** if "expression" isn't true, then print "message" and execute "handler" expression */ +#ifndef LWIP_ERROR +#ifndef LWIP_NOASSERT +#define LWIP_PLATFORM_ERROR(message) LWIP_PLATFORM_ASSERT(message) +#elif defined LWIP_DEBUG +#define LWIP_PLATFORM_ERROR(message) LWIP_PLATFORM_DIAG((message)) +#else +#define LWIP_PLATFORM_ERROR(message) +#endif + +#define LWIP_ERROR(message, expression, handler) do { if (!(expression)) { \ + LWIP_PLATFORM_ERROR(message); handler;}} while(0) +#endif /* LWIP_ERROR */ + +#ifdef LWIP_DEBUG +#ifndef LWIP_PLATFORM_DIAG +#error "If you want to use LWIP_DEBUG, LWIP_PLATFORM_DIAG(message) needs to be defined in your arch/cc.h" +#endif +/** print debug message only if debug message type is enabled... + * AND is of correct type AND is at least LWIP_DBG_LEVEL + */ +#define LWIP_DEBUGF(debug, message) do { \ + if ( \ + ((debug) & LWIP_DBG_ON) && \ + ((debug) & LWIP_DBG_TYPES_ON) && \ + ((s16_t)((debug) & LWIP_DBG_MASK_LEVEL) >= LWIP_DBG_MIN_LEVEL)) { \ + LWIP_PLATFORM_DIAG(message); \ + if ((debug) & LWIP_DBG_HALT) { \ + while(1); \ + } \ + } \ + } while(0) + +#else /* LWIP_DEBUG */ +#define LWIP_DEBUGF(debug, message) +#endif /* LWIP_DEBUG */ + +#endif /* LWIP_HDR_DEBUG_H */ + diff --git a/components/lwip/include/lwip/lwip/def.h b/components/lwip/include/lwip/lwip/def.h new file mode 100755 index 0000000000..49571363cd --- /dev/null +++ b/components/lwip/include/lwip/lwip/def.h @@ -0,0 +1,132 @@ +/* + * Copyright (c) 2001-2004 Swedish Institute of Computer Science. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + * + */ +#ifndef LWIP_HDR_DEF_H +#define LWIP_HDR_DEF_H + +/* arch.h might define NULL already */ +#include "lwip/arch.h" +#include "lwip/opt.h" +#if LWIP_PERF +#include "arch/perf.h" +#else /* LWIP_PERF */ +#define PERF_START /* null definition */ +#define PERF_STOP(x) /* null definition */ +#endif /* LWIP_PERF */ + +#ifdef __cplusplus +extern "C" { +#endif + +#define LWIP_MAX(x , y) (((x) > (y)) ? (x) : (y)) +#define LWIP_MIN(x , y) (((x) < (y)) ? (x) : (y)) + +/* Get the number of entries in an array ('x' must NOT be a pointer!) */ +#define LWIP_ARRAYSIZE(x) (sizeof(x)/sizeof((x)[0])) + +#ifndef NULL +#define NULL ((void *)0) +#endif + +/* Endianess-optimized shifting of two u8_t to create one u16_t */ +#if BYTE_ORDER == LITTLE_ENDIAN +#define LWIP_MAKE_U16(a, b) ((a << 8) | b) +#else +#define LWIP_MAKE_U16(a, b) ((b << 8) | a) +#endif + +#ifndef LWIP_PLATFORM_BYTESWAP +#define LWIP_PLATFORM_BYTESWAP 0 +#endif + +#ifndef LWIP_PREFIX_BYTEORDER_FUNCS +/* workaround for naming collisions on some platforms */ + +#ifdef htons +#undef htons +#endif /* htons */ +#ifdef htonl +#undef htonl +#endif /* htonl */ +#ifdef ntohs +#undef ntohs +#endif /* ntohs */ +#ifdef ntohl +#undef ntohl +#endif /* ntohl */ + +#define htons(x) lwip_htons(x) +#define ntohs(x) lwip_ntohs(x) +#define htonl(x) lwip_htonl(x) +#define ntohl(x) lwip_ntohl(x) +#endif /* LWIP_PREFIX_BYTEORDER_FUNCS */ + +#if BYTE_ORDER == BIG_ENDIAN +#define lwip_htons(x) (x) +#define lwip_ntohs(x) (x) +#define lwip_htonl(x) (x) +#define lwip_ntohl(x) (x) +#define PP_HTONS(x) (x) +#define PP_NTOHS(x) (x) +#define PP_HTONL(x) (x) +#define PP_NTOHL(x) (x) +#else /* BYTE_ORDER != BIG_ENDIAN */ +#if LWIP_PLATFORM_BYTESWAP +#define lwip_htons(x) LWIP_PLATFORM_HTONS(x) +#define lwip_ntohs(x) LWIP_PLATFORM_HTONS(x) +#define lwip_htonl(x) LWIP_PLATFORM_HTONL(x) +#define lwip_ntohl(x) LWIP_PLATFORM_HTONL(x) +#else /* LWIP_PLATFORM_BYTESWAP */ +u16_t lwip_htons(u16_t x); +u16_t lwip_ntohs(u16_t x); +u32_t lwip_htonl(u32_t x); +u32_t lwip_ntohl(u32_t x); +#endif /* LWIP_PLATFORM_BYTESWAP */ + +/* These macros should be calculated by the preprocessor and are used + with compile-time constants only (so that there is no little-endian + overhead at runtime). */ +#define PP_HTONS(x) ((((x) & 0xff) << 8) | (((x) & 0xff00) >> 8)) +#define PP_NTOHS(x) PP_HTONS(x) +#define PP_HTONL(x) ((((x) & 0xff) << 24) | \ + (((x) & 0xff00) << 8) | \ + (((x) & 0xff0000UL) >> 8) | \ + (((x) & 0xff000000UL) >> 24)) +#define PP_NTOHL(x) PP_HTONL(x) + +#endif /* BYTE_ORDER == BIG_ENDIAN */ + +#ifdef __cplusplus +} +#endif + +#endif /* LWIP_HDR_DEF_H */ + diff --git a/components/lwip/include/lwip/lwip/dhcp.h b/components/lwip/include/lwip/lwip/dhcp.h new file mode 100755 index 0000000000..57b6359573 --- /dev/null +++ b/components/lwip/include/lwip/lwip/dhcp.h @@ -0,0 +1,298 @@ +/* + * Copyright (c) 2001-2004 Leon Woestenberg + * Copyright (c) 2001-2004 Axon Digital Design B.V., The Netherlands. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Leon Woestenberg + * + */ +#ifndef LWIP_HDR_DHCP_H +#define LWIP_HDR_DHCP_H + +#include "lwip/opt.h" + +#if LWIP_DHCP /* don't build if not configured for use in lwipopts.h */ + +#include "lwip/netif.h" +#include "lwip/udp.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** period (in seconds) of the application calling dhcp_coarse_tmr() */ +#define DHCP_COARSE_TIMER_SECS 60 +/** period (in milliseconds) of the application calling dhcp_coarse_tmr() */ +#define DHCP_COARSE_TIMER_MSECS (DHCP_COARSE_TIMER_SECS * 1000UL) +/** period (in milliseconds) of the application calling dhcp_fine_tmr() */ +#define DHCP_FINE_TIMER_MSECS 500 + +#define DHCP_CHADDR_LEN 16U +#define DHCP_SNAME_LEN 64U +#define DHCP_FILE_LEN 128U + +struct dhcp +{ + /** transaction identifier of last sent request */ + u32_t xid; + /** incoming msg */ + struct dhcp_msg *msg_in; + /** track PCB allocation state */ + u8_t pcb_allocated; + /** current DHCP state machine state */ + u8_t state; + /** retries of current request */ + u8_t tries; +#if LWIP_DHCP_AUTOIP_COOP + u8_t autoip_coop_state; +#endif + u8_t subnet_mask_given; + + struct pbuf *p_out; /* pbuf of outcoming msg */ + struct dhcp_msg *msg_out; /* outgoing msg */ + u16_t options_out_len; /* outgoing msg options length */ + u16_t request_timeout; /* #ticks with period DHCP_FINE_TIMER_SECS for request timeout */ + u16_t t1_timeout; /* #ticks with period DHCP_COARSE_TIMER_SECS for renewal time */ + u16_t t2_timeout; /* #ticks with period DHCP_COARSE_TIMER_SECS for rebind time */ + u16_t t1_renew_time; /* #ticks with period DHCP_COARSE_TIMER_SECS until next renew try */ + u16_t t2_rebind_time; /* #ticks with period DHCP_COARSE_TIMER_SECS until next rebind try */ + u16_t lease_used; /* #ticks with period DHCP_COARSE_TIMER_SECS since last received DHCP ack */ + u16_t t0_timeout; /* #ticks with period DHCP_COARSE_TIMER_SECS for lease time */ + ip_addr_t server_ip_addr; /* dhcp server address that offered this lease (ip_addr_t because passed to UDP) */ + ip4_addr_t offered_ip_addr; + ip4_addr_t offered_sn_mask; + ip4_addr_t offered_gw_addr; + + u32_t offered_t0_lease; /* lease period (in seconds) */ + u32_t offered_t1_renew; /* recommended renew time (usually 50% of lease period) */ + u32_t offered_t2_rebind; /* recommended rebind time (usually 87.5 of lease period) */ +#if LWIP_DHCP_BOOTP_FILE + ip_addr_t offered_si_addr; + char boot_file_name[DHCP_FILE_LEN]; +#endif /* LWIP_DHCP_BOOTPFILE */ +}; + +/* MUST be compiled with "pack structs" or equivalent! */ +#ifdef PACK_STRUCT_USE_INCLUDES +# include "arch/bpstruct.h" +#endif +PACK_STRUCT_BEGIN +/** minimum set of fields of any DHCP message */ +struct dhcp_msg +{ + PACK_STRUCT_FLD_8(u8_t op); + PACK_STRUCT_FLD_8(u8_t htype); + PACK_STRUCT_FLD_8(u8_t hlen); + PACK_STRUCT_FLD_8(u8_t hops); + PACK_STRUCT_FIELD(u32_t xid); + PACK_STRUCT_FIELD(u16_t secs); + PACK_STRUCT_FIELD(u16_t flags); + PACK_STRUCT_FLD_S(ip4_addr_p_t ciaddr); + PACK_STRUCT_FLD_S(ip4_addr_p_t yiaddr); + PACK_STRUCT_FLD_S(ip4_addr_p_t siaddr); + PACK_STRUCT_FLD_S(ip4_addr_p_t giaddr); + PACK_STRUCT_FLD_8(u8_t chaddr[DHCP_CHADDR_LEN]); + PACK_STRUCT_FLD_8(u8_t sname[DHCP_SNAME_LEN]); + PACK_STRUCT_FLD_8(u8_t file[DHCP_FILE_LEN]); + PACK_STRUCT_FIELD(u32_t cookie); +#define DHCP_MIN_OPTIONS_LEN 68U +/** make sure user does not configure this too small */ +#if ((defined(DHCP_OPTIONS_LEN)) && (DHCP_OPTIONS_LEN < DHCP_MIN_OPTIONS_LEN)) +# undef DHCP_OPTIONS_LEN +#endif +/** allow this to be configured in lwipopts.h, but not too small */ +#if (!defined(DHCP_OPTIONS_LEN)) +/** set this to be sufficient for your options in outgoing DHCP msgs */ +# define DHCP_OPTIONS_LEN DHCP_MIN_OPTIONS_LEN +#endif + PACK_STRUCT_FLD_8(u8_t options[DHCP_OPTIONS_LEN]); +} PACK_STRUCT_STRUCT; +PACK_STRUCT_END +#ifdef PACK_STRUCT_USE_INCLUDES +# include "arch/epstruct.h" +#endif + +void dhcp_set_struct(struct netif *netif, struct dhcp *dhcp); +/** Remove a struct dhcp previously set to the netif using dhcp_set_struct() */ +#define dhcp_remove_struct(netif) do { (netif)->dhcp = NULL; } while(0) +void dhcp_cleanup(struct netif *netif); +/** start DHCP configuration */ +err_t dhcp_start(struct netif *netif); +/** enforce early lease renewal (not needed normally)*/ +err_t dhcp_renew(struct netif *netif); +/** release the DHCP lease, usually called before dhcp_stop()*/ +err_t dhcp_release(struct netif *netif); +/** stop DHCP configuration */ +void dhcp_stop(struct netif *netif); +/** inform server of our manual IP address */ +void dhcp_inform(struct netif *netif); +/** Handle a possible change in the network configuration */ +void dhcp_network_changed(struct netif *netif); + +/** if enabled, check whether the offered IP address is not in use, using ARP */ +#if DHCP_DOES_ARP_CHECK +void dhcp_arp_reply(struct netif *netif, const ip4_addr_t *addr); +#endif + +/** check if DHCP supplied netif->ip_addr */ +u8_t dhcp_supplied_address(struct netif *netif); + +/** to be called every minute */ +void dhcp_coarse_tmr(void); +/** to be called every half second */ +void dhcp_fine_tmr(void); + +/** DHCP message item offsets and length */ +#define DHCP_OP_OFS 0 +#define DHCP_HTYPE_OFS 1 +#define DHCP_HLEN_OFS 2 +#define DHCP_HOPS_OFS 3 +#define DHCP_XID_OFS 4 +#define DHCP_SECS_OFS 8 +#define DHCP_FLAGS_OFS 10 +#define DHCP_CIADDR_OFS 12 +#define DHCP_YIADDR_OFS 16 +#define DHCP_SIADDR_OFS 20 +#define DHCP_GIADDR_OFS 24 +#define DHCP_CHADDR_OFS 28 +#define DHCP_SNAME_OFS 44 +#define DHCP_FILE_OFS 108 +#define DHCP_MSG_LEN 236 + +#define DHCP_COOKIE_OFS DHCP_MSG_LEN +#define DHCP_OPTIONS_OFS (DHCP_MSG_LEN + 4) + +#define DHCP_CLIENT_PORT 68 +#define DHCP_SERVER_PORT 67 + +/** DHCP client states */ +#define DHCP_STATE_OFF 0 +#define DHCP_STATE_REQUESTING 1 +#define DHCP_STATE_INIT 2 +#define DHCP_STATE_REBOOTING 3 +#define DHCP_STATE_REBINDING 4 +#define DHCP_STATE_RENEWING 5 +#define DHCP_STATE_SELECTING 6 +#define DHCP_STATE_INFORMING 7 +#define DHCP_STATE_CHECKING 8 +/** not yet implemented #define DHCP_STATE_PERMANENT 9 */ +#define DHCP_STATE_BOUND 10 +/** not yet implemented #define DHCP_STATE_RELEASING 11 */ +#define DHCP_STATE_BACKING_OFF 12 + +/** AUTOIP cooperation flags */ +#define DHCP_AUTOIP_COOP_STATE_OFF 0 +#define DHCP_AUTOIP_COOP_STATE_ON 1 + +#define DHCP_BOOTREQUEST 1 +#define DHCP_BOOTREPLY 2 + +/** DHCP message types */ +#define DHCP_DISCOVER 1 +#define DHCP_OFFER 2 +#define DHCP_REQUEST 3 +#define DHCP_DECLINE 4 +#define DHCP_ACK 5 +#define DHCP_NAK 6 +#define DHCP_RELEASE 7 +#define DHCP_INFORM 8 + +/** DHCP hardware type, currently only ethernet is supported */ +#define DHCP_HTYPE_ETH 1 + +#define DHCP_MAGIC_COOKIE 0x63825363UL + +/* This is a list of options for BOOTP and DHCP, see RFC 2132 for descriptions */ + +/** BootP options */ +#define DHCP_OPTION_PAD 0 +#define DHCP_OPTION_SUBNET_MASK 1 /* RFC 2132 3.3 */ +#define DHCP_OPTION_ROUTER 3 +#define DHCP_OPTION_DNS_SERVER 6 +#define DHCP_OPTION_HOSTNAME 12 +#define DHCP_OPTION_IP_TTL 23 +#define DHCP_OPTION_MTU 26 +#define DHCP_OPTION_BROADCAST 28 +#define DHCP_OPTION_TCP_TTL 37 +#define DHCP_OPTION_NTP 42 +#define DHCP_OPTION_END 255 + +#ifdef LWIP_ESP8266 +/**add options for support more router by liuHan**/ +#define DHCP_OPTION_DOMAIN_NAME 15 +#define DHCP_OPTION_PRD 31 +#define DHCP_OPTION_STATIC_ROUTER 33 +#define DHCP_OPTION_VSN 43 +#define DHCP_OPTION_NB_TINS 44 +#define DHCP_OPTION_NB_TINT 46 +#define DHCP_OPTION_NB_TIS 47 +#define DHCP_OPTION_CLASSLESS_STATIC_ROUTER 121 +#endif + + + +/** DHCP options */ +#define DHCP_OPTION_REQUESTED_IP 50 /* RFC 2132 9.1, requested IP address */ +#define DHCP_OPTION_LEASE_TIME 51 /* RFC 2132 9.2, time in seconds, in 4 bytes */ +#define DHCP_OPTION_OVERLOAD 52 /* RFC2132 9.3, use file and/or sname field for options */ + +#define DHCP_OPTION_MESSAGE_TYPE 53 /* RFC 2132 9.6, important for DHCP */ +#define DHCP_OPTION_MESSAGE_TYPE_LEN 1 + +#define DHCP_OPTION_SERVER_ID 54 /* RFC 2132 9.7, server IP address */ +#define DHCP_OPTION_PARAMETER_REQUEST_LIST 55 /* RFC 2132 9.8, requested option types */ + +#define DHCP_OPTION_MAX_MSG_SIZE 57 /* RFC 2132 9.10, message size accepted >= 576 */ +#define DHCP_OPTION_MAX_MSG_SIZE_LEN 2 + +#define DHCP_OPTION_T1 58 /* T1 renewal time */ +#define DHCP_OPTION_T2 59 /* T2 rebinding time */ +#define DHCP_OPTION_US 60 +#define DHCP_OPTION_CLIENT_ID 61 +#define DHCP_OPTION_TFTP_SERVERNAME 66 +#define DHCP_OPTION_BOOTFILE 67 + +/** possible combinations of overloading the file and sname fields with options */ +#define DHCP_OVERLOAD_NONE 0 +#define DHCP_OVERLOAD_FILE 1 +#define DHCP_OVERLOAD_SNAME 2 +#define DHCP_OVERLOAD_SNAME_FILE 3 + +#if LWIP_DHCP_GET_NTP_SRV +/** This function must exist, in other to add offered NTP servers to + * the NTP (or SNTP) engine. + * See LWIP_DHCP_MAX_NTP_SERVERS */ +extern void dhcp_set_ntp_servers(u8_t num_ntp_servers, const ip4_addr_t* ntp_server_addrs); +#endif /* LWIP_DHCP_GET_NTP_SRV */ + +#ifdef __cplusplus +} +#endif + +#endif /* LWIP_DHCP */ + +#endif /*LWIP_HDR_DHCP_H*/ diff --git a/components/lwip/include/lwip/lwip/dhcp6.h b/components/lwip/include/lwip/lwip/dhcp6.h new file mode 100755 index 0000000000..345bcf00ec --- /dev/null +++ b/components/lwip/include/lwip/lwip/dhcp6.h @@ -0,0 +1,58 @@ +/** + * @file + * + * IPv6 address autoconfiguration as per RFC 4862. + */ + +/* + * Copyright (c) 2010 Inico Technologies Ltd. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Ivan Delamer + * + * IPv6 address autoconfiguration as per RFC 4862. + * + * Please coordinate changes and requests with Ivan Delamer + * + */ + +#ifndef LWIP_HDR_IP6_DHCP6_H +#define LWIP_HDR_IP6_DHCP6_H + +#include "lwip/opt.h" + +#if LWIP_IPV6_DHCP6 /* don't build if not configured for use in lwipopts.h */ + + +struct dhcp6 +{ + /*TODO: implement DHCP6*/ +}; + +#endif /* LWIP_IPV6_DHCP6 */ + +#endif /* LWIP_HDR_IP6_DHCP6_H */ diff --git a/components/lwip/include/lwip/lwip/dns.h b/components/lwip/include/lwip/lwip/dns.h new file mode 100755 index 0000000000..1ceed0d883 --- /dev/null +++ b/components/lwip/include/lwip/lwip/dns.h @@ -0,0 +1,118 @@ +/** + * lwip DNS resolver header file. + + * Author: Jim Pettinato + * April 2007 + + * ported from uIP resolv.c Copyright (c) 2002-2003, Adam Dunkels. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote + * products derived from this software without specific prior + * written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef LWIP_HDR_DNS_H +#define LWIP_HDR_DNS_H + +#include "lwip/opt.h" + +#ifdef LWIP_ESP8266 +#include "lwip/err.h" +#endif + + +#if LWIP_DNS + +#include "lwip/ip_addr.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** DNS timer period */ +#define DNS_TMR_INTERVAL 1000 + +/* DNS resolve types: */ +#define LWIP_DNS_ADDRTYPE_IPV4 0 +#define LWIP_DNS_ADDRTYPE_IPV6 1 +#define LWIP_DNS_ADDRTYPE_IPV4_IPV6 2 /* try to resolve IPv4 first, try IPv6 if IPv4 fails only */ +#define LWIP_DNS_ADDRTYPE_IPV6_IPV4 3 /* try to resolve IPv6 first, try IPv4 if IPv6 fails only */ +#if LWIP_IPV4 && LWIP_IPV6 +#ifndef LWIP_DNS_ADDRTYPE_DEFAULT +#define LWIP_DNS_ADDRTYPE_DEFAULT LWIP_DNS_ADDRTYPE_IPV4_IPV6 +#endif +#elif defined(LWIP_IPV4) +#define LWIP_DNS_ADDRTYPE_DEFAULT LWIP_DNS_ADDRTYPE_IPV4 +#else +#define LWIP_DNS_ADDRTYPE_DEFAULT LWIP_DNS_ADDRTYPE_IPV6 +#endif + +#if DNS_LOCAL_HOSTLIST +/** struct used for local host-list */ +struct local_hostlist_entry { + /** static hostname */ + const char *name; + /** static host address in network byteorder */ + ip_addr_t addr; + struct local_hostlist_entry *next; +}; +#if DNS_LOCAL_HOSTLIST_IS_DYNAMIC +#ifndef DNS_LOCAL_HOSTLIST_MAX_NAMELEN +#define DNS_LOCAL_HOSTLIST_MAX_NAMELEN DNS_MAX_NAME_LENGTH +#endif +#define LOCALHOSTLIST_ELEM_SIZE ((sizeof(struct local_hostlist_entry) + DNS_LOCAL_HOSTLIST_MAX_NAMELEN + 1)) +#endif /* DNS_LOCAL_HOSTLIST_IS_DYNAMIC */ +#endif /* DNS_LOCAL_HOSTLIST */ + +/** Callback which is invoked when a hostname is found. + * A function of this type must be implemented by the application using the DNS resolver. + * @param name pointer to the name that was looked up. + * @param ipaddr pointer to an ip_addr_t containing the IP address of the hostname, + * or NULL if the name could not be found (or on any other error). + * @param callback_arg a user-specified callback argument passed to dns_gethostbyname +*/ +typedef void (*dns_found_callback)(const char *name, const ip_addr_t *ipaddr, void *callback_arg); + +void dns_init(void); +void dns_tmr(void); +void dns_setserver(u8_t numdns, const ip_addr_t *dnsserver); +ip_addr_t dns_getserver(u8_t numdns); +err_t dns_gethostbyname(const char *hostname, ip_addr_t *addr, + dns_found_callback found, void *callback_arg); +err_t dns_gethostbyname_addrtype(const char *hostname, ip_addr_t *addr, + dns_found_callback found, void *callback_arg, + u8_t dns_addrtype); + + +#if DNS_LOCAL_HOSTLIST && DNS_LOCAL_HOSTLIST_IS_DYNAMIC +int dns_local_removehost(const char *hostname, const ip_addr_t *addr); +err_t dns_local_addhost(const char *hostname, const ip_addr_t *addr); +#endif /* DNS_LOCAL_HOSTLIST && DNS_LOCAL_HOSTLIST_IS_DYNAMIC */ + +#ifdef __cplusplus +} +#endif + +#endif /* LWIP_DNS */ + +#endif /* LWIP_HDR_DNS_H */ diff --git a/components/lwip/include/lwip/lwip/err.h b/components/lwip/include/lwip/lwip/err.h new file mode 100755 index 0000000000..26fb91db9b --- /dev/null +++ b/components/lwip/include/lwip/lwip/err.h @@ -0,0 +1,95 @@ +/* + * Copyright (c) 2001-2004 Swedish Institute of Computer Science. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + * + */ +#ifndef LWIP_HDR_ERR_H +#define LWIP_HDR_ERR_H + +#include "lwip/opt.h" +#include "lwip/arch.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** Define LWIP_ERR_T in cc.h if you want to use + * a different type for your platform (must be signed). */ +#ifdef LWIP_ERR_T +typedef LWIP_ERR_T err_t; +#else /* LWIP_ERR_T */ +typedef s8_t err_t; +#endif /* LWIP_ERR_T*/ + +/* Definitions for error constants. */ + +#define ERR_OK 0 /* No error, everything OK. */ +#define ERR_MEM -1 /* Out of memory error. */ +#define ERR_BUF -2 /* Buffer error. */ +#define ERR_TIMEOUT -3 /* Timeout. */ +#define ERR_RTE -4 /* Routing problem. */ +#define ERR_INPROGRESS -5 /* Operation in progress */ +#define ERR_VAL -6 /* Illegal value. */ +#define ERR_WOULDBLOCK -7 /* Operation would block. */ +#define ERR_USE -8 /* Address in use. */ + + +#ifdef LWIP_ESP8266 +#define ERR_ALREADY -9 /* Already connected. */ +#define ERR_ISCONN -10 /* Conn already established.*/ +#define ERR_IS_FATAL(e) ((e) < ERR_ISCONN) +#define ERR_ABRT -11 /* Connection aborted. */ +#define ERR_RST -12 /* Connection reset. */ +#define ERR_CLSD -13 /* Connection closed. */ +#define ERR_CONN -14 /* Not connected. */ +#define ERR_ARG -15 /* Illegal argument. */ +#define ERR_IF -16 /* Low-level netif error */ +#else +#define ERR_ALREADY -9 /* Already connecting. */ +#define ERR_ISCONN -10 /* Conn already established.*/ +#define ERR_CONN -11 /* Not connected. */ +#define ERR_IF -12 /* Low-level netif error */ +#define ERR_IS_FATAL(e) ((e) <= ERR_ABRT) +#define ERR_ABRT -13 /* Connection aborted. */ +#define ERR_RST -14 /* Connection reset. */ +#define ERR_CLSD -15 /* Connection closed. */ +#define ERR_ARG -16 /* Illegal argument. */ +#endif + +#ifdef LWIP_DEBUG +extern const char *lwip_strerr(err_t err); +#else +#define lwip_strerr(x) "" +#endif /* LWIP_DEBUG */ + +#ifdef __cplusplus +} +#endif + +#endif /* LWIP_HDR_ERR_H */ diff --git a/components/lwip/include/lwip/lwip/ethip6.h b/components/lwip/include/lwip/lwip/ethip6.h new file mode 100755 index 0000000000..5e88dffd05 --- /dev/null +++ b/components/lwip/include/lwip/lwip/ethip6.h @@ -0,0 +1,68 @@ +/** + * @file + * + * Ethernet output for IPv6. Uses ND tables for link-layer addressing. + */ + +/* + * Copyright (c) 2010 Inico Technologies Ltd. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Ivan Delamer + * + * + * Please coordinate changes and requests with Ivan Delamer + * + */ + +#ifndef LWIP_HDR_ETHIP6_H +#define LWIP_HDR_ETHIP6_H + +#include "lwip/opt.h" + +#if LWIP_IPV6 && LWIP_ETHERNET /* don't build if not configured for use in lwipopts.h */ + +#include "lwip/pbuf.h" +#include "lwip/ip6.h" +#include "lwip/ip6_addr.h" +#include "lwip/netif.h" + + +#ifdef __cplusplus +extern "C" { +#endif + + +err_t ethip6_output(struct netif *netif, struct pbuf *q, const ip6_addr_t *ip6addr); + +#ifdef __cplusplus +} +#endif + +#endif /* LWIP_IPV6 && LWIP_ETHERNET */ + +#endif /* LWIP_HDR_ETHIP6_H */ diff --git a/components/lwip/include/lwip/lwip/icmp.h b/components/lwip/include/lwip/lwip/icmp.h new file mode 100755 index 0000000000..af3a455083 --- /dev/null +++ b/components/lwip/include/lwip/lwip/icmp.h @@ -0,0 +1,137 @@ +/* + * Copyright (c) 2001-2004 Swedish Institute of Computer Science. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + * + */ +#ifndef LWIP_HDR_ICMP_H +#define LWIP_HDR_ICMP_H + +#include "lwip/opt.h" +#include "lwip/pbuf.h" +#include "lwip/ip_addr.h" +#include "lwip/netif.h" + +#if LWIP_IPV6 && LWIP_ICMP6 +#include "lwip/icmp6.h" +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +#define ICMP_ER 0 /* echo reply */ +#define ICMP_DUR 3 /* destination unreachable */ +#define ICMP_SQ 4 /* source quench */ +#define ICMP_RD 5 /* redirect */ +#define ICMP_ECHO 8 /* echo */ +#define ICMP_TE 11 /* time exceeded */ +#define ICMP_PP 12 /* parameter problem */ +#define ICMP_TS 13 /* timestamp */ +#define ICMP_TSR 14 /* timestamp reply */ +#define ICMP_IRQ 15 /* information request */ +#define ICMP_IR 16 /* information reply */ +#define ICMP_AM 17 /* address mask request */ +#define ICMP_AMR 18 /* address mask reply */ + +enum icmp_dur_type { + ICMP_DUR_NET = 0, /* net unreachable */ + ICMP_DUR_HOST = 1, /* host unreachable */ + ICMP_DUR_PROTO = 2, /* protocol unreachable */ + ICMP_DUR_PORT = 3, /* port unreachable */ + ICMP_DUR_FRAG = 4, /* fragmentation needed and DF set */ + ICMP_DUR_SR = 5 /* source route failed */ +}; + +enum icmp_te_type { + ICMP_TE_TTL = 0, /* time to live exceeded in transit */ + ICMP_TE_FRAG = 1 /* fragment reassembly time exceeded */ +}; + +#ifdef PACK_STRUCT_USE_INCLUDES +# include "arch/bpstruct.h" +#endif +/** This is the standard ICMP header only that the u32_t data + * is split to two u16_t like ICMP echo needs it. + * This header is also used for other ICMP types that do not + * use the data part. + */ +PACK_STRUCT_BEGIN +struct icmp_echo_hdr { + PACK_STRUCT_FLD_8(u8_t type); + PACK_STRUCT_FLD_8(u8_t code); + PACK_STRUCT_FIELD(u16_t chksum); + PACK_STRUCT_FIELD(u16_t id); + PACK_STRUCT_FIELD(u16_t seqno); +} PACK_STRUCT_STRUCT; +PACK_STRUCT_END +#ifdef PACK_STRUCT_USE_INCLUDES +# include "arch/epstruct.h" +#endif + +#define ICMPH_TYPE(hdr) ((hdr)->type) +#define ICMPH_CODE(hdr) ((hdr)->code) + +/** Combines type and code to an u16_t */ +#define ICMPH_TYPE_SET(hdr, t) ((hdr)->type = (t)) +#define ICMPH_CODE_SET(hdr, c) ((hdr)->code = (c)) + + +#if LWIP_IPV4 && LWIP_ICMP /* don't build if not configured for use in lwipopts.h */ + +void icmp_input(struct pbuf *p, struct netif *inp); +void icmp_dest_unreach(struct pbuf *p, enum icmp_dur_type t); +void icmp_time_exceeded(struct pbuf *p, enum icmp_te_type t); + +#endif /* LWIP_IPV4 && LWIP_ICMP */ + +#if LWIP_IPV4 && LWIP_IPV6 +#if LWIP_ICMP && LWIP_ICMP6 +#define icmp_port_unreach(isipv6, pbuf) ((isipv6) ? \ + icmp6_dest_unreach(pbuf, ICMP6_DUR_PORT) : \ + icmp_dest_unreach(pbuf, ICMP_DUR_PORT)) +#elif LWIP_ICMP +#define icmp_port_unreach(isipv6, pbuf) do{ if(!(isipv6)) { icmp_dest_unreach(pbuf, ICMP_DUR_PORT);}}while(0) +#elif LWIP_ICMP6 +#define icmp_port_unreach(isipv6, pbuf) do{ if(isipv6) { icmp6_dest_unreach(pbuf, ICMP6_DUR_PORT);}}while(0) +#else +#define icmp_port_unreach(isipv6, pbuf) +#endif +#elif LWIP_IPV6 && LWIP_ICMP6 +#define icmp_port_unreach(isipv6, pbuf) icmp6_dest_unreach(pbuf, ICMP6_DUR_PORT) +#elif LWIP_IPV4 && LWIP_ICMP +#define icmp_port_unreach(isipv6, pbuf) icmp_dest_unreach(pbuf, ICMP_DUR_PORT) +#else /* (LWIP_IPV6 && LWIP_ICMP6) || (LWIP_IPV4 && LWIP_ICMP) */ +#define icmp_port_unreach(isipv6, pbuf) +#endif /* (LWIP_IPV6 && LWIP_ICMP6) || (LWIP_IPV4 && LWIP_ICMP) LWIP_IPV4*/ + +#ifdef __cplusplus +} +#endif + +#endif /* LWIP_HDR_ICMP_H */ diff --git a/components/lwip/include/lwip/lwip/icmp6.h b/components/lwip/include/lwip/lwip/icmp6.h new file mode 100755 index 0000000000..9d57103fc1 --- /dev/null +++ b/components/lwip/include/lwip/lwip/icmp6.h @@ -0,0 +1,152 @@ +/** + * @file + * + * IPv6 version of ICMP, as per RFC 4443. + */ + +/* + * Copyright (c) 2010 Inico Technologies Ltd. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Ivan Delamer + * + * + * Please coordinate changes and requests with Ivan Delamer + * + */ +#ifndef LWIP_HDR_ICMP6_H +#define LWIP_HDR_ICMP6_H + +#include "lwip/opt.h" +#include "lwip/pbuf.h" +#include "lwip/ip6_addr.h" +#include "lwip/netif.h" + + +#ifdef __cplusplus +extern "C" { +#endif + +enum icmp6_type { + ICMP6_TYPE_DUR = 1, /* Destination unreachable */ + ICMP6_TYPE_PTB = 2, /* Packet too big */ + ICMP6_TYPE_TE = 3, /* Time exceeded */ + ICMP6_TYPE_PP = 4, /* Parameter problem */ + ICMP6_TYPE_PE1 = 100, /* Private experimentation */ + ICMP6_TYPE_PE2 = 101, /* Private experimentation */ + ICMP6_TYPE_RSV_ERR = 127, /* Reserved for expansion of error messages */ + + ICMP6_TYPE_EREQ = 128, /* Echo request */ + ICMP6_TYPE_EREP = 129, /* Echo reply */ + ICMP6_TYPE_MLQ = 130, /* Multicast listener query */ + ICMP6_TYPE_MLR = 131, /* Multicast listener report */ + ICMP6_TYPE_MLD = 132, /* Multicast listener done */ + ICMP6_TYPE_RS = 133, /* Router solicitation */ + ICMP6_TYPE_RA = 134, /* Router advertisement */ + ICMP6_TYPE_NS = 135, /* Neighbor solicitation */ + ICMP6_TYPE_NA = 136, /* Neighbor advertisement */ + ICMP6_TYPE_RD = 137, /* Redirect */ + ICMP6_TYPE_MRA = 151, /* Multicast router advertisement */ + ICMP6_TYPE_MRS = 152, /* Multicast router solicitation */ + ICMP6_TYPE_MRT = 153, /* Multicast router termination */ + ICMP6_TYPE_PE3 = 200, /* Private experimentation */ + ICMP6_TYPE_PE4 = 201, /* Private experimentation */ + ICMP6_TYPE_RSV_INF = 255 /* Reserved for expansion of informational messages */ +}; + +enum icmp6_dur_code { + ICMP6_DUR_NO_ROUTE = 0, /* No route to destination */ + ICMP6_DUR_PROHIBITED = 1, /* Communication with destination administratively prohibited */ + ICMP6_DUR_SCOPE = 2, /* Beyond scope of source address */ + ICMP6_DUR_ADDRESS = 3, /* Address unreachable */ + ICMP6_DUR_PORT = 4, /* Port unreachable */ + ICMP6_DUR_POLICY = 5, /* Source address failed ingress/egress policy */ + ICMP6_DUR_REJECT_ROUTE = 6 /* Reject route to destination */ +}; + +enum icmp6_te_code { + ICMP6_TE_HL = 0, /* Hop limit exceeded in transit */ + ICMP6_TE_FRAG = 1 /* Fragment reassembly time exceeded */ +}; + +enum icmp6_pp_code { + ICMP6_PP_FIELD = 0, /* Erroneous header field encountered */ + ICMP6_PP_HEADER = 1, /* Unrecognized next header type encountered */ + ICMP6_PP_OPTION = 2 /* Unrecognized IPv6 option encountered */ +}; + +/** This is the standard ICMP6 header. */ +#ifdef PACK_STRUCT_USE_INCLUDES +# include "arch/bpstruct.h" +#endif +PACK_STRUCT_BEGIN +struct icmp6_hdr { + PACK_STRUCT_FLD_8(u8_t type); + PACK_STRUCT_FLD_8(u8_t code); + PACK_STRUCT_FIELD(u16_t chksum); + PACK_STRUCT_FIELD(u32_t data); +} PACK_STRUCT_STRUCT; +PACK_STRUCT_END +#ifdef PACK_STRUCT_USE_INCLUDES +# include "arch/epstruct.h" +#endif + +/** This is the ICMP6 header adapted for echo req/resp. */ +#ifdef PACK_STRUCT_USE_INCLUDES +# include "arch/bpstruct.h" +#endif +PACK_STRUCT_BEGIN +struct icmp6_echo_hdr { + PACK_STRUCT_FLD_8(u8_t type); + PACK_STRUCT_FLD_8(u8_t code); + PACK_STRUCT_FIELD(u16_t chksum); + PACK_STRUCT_FIELD(u16_t id); + PACK_STRUCT_FIELD(u16_t seqno); +} PACK_STRUCT_STRUCT; +PACK_STRUCT_END +#ifdef PACK_STRUCT_USE_INCLUDES +# include "arch/epstruct.h" +#endif + + +#if LWIP_ICMP6 && LWIP_IPV6 /* don't build if not configured for use in lwipopts.h */ + +void icmp6_input(struct pbuf *p, struct netif *inp); +void icmp6_dest_unreach(struct pbuf *p, enum icmp6_dur_code c); +void icmp6_packet_too_big(struct pbuf *p, u32_t mtu); +void icmp6_time_exceeded(struct pbuf *p, enum icmp6_te_code c); +void icmp6_param_problem(struct pbuf *p, enum icmp6_pp_code c, u32_t pointer); + +#endif /* LWIP_ICMP6 && LWIP_IPV6 */ + + +#ifdef __cplusplus +} +#endif + + +#endif /* LWIP_HDR_ICMP6_H */ diff --git a/components/lwip/include/lwip/lwip/igmp.h b/components/lwip/include/lwip/lwip/igmp.h new file mode 100755 index 0000000000..bff1a61350 --- /dev/null +++ b/components/lwip/include/lwip/lwip/igmp.h @@ -0,0 +1,108 @@ +/* + * Copyright (c) 2002 CITEL Technologies Ltd. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of CITEL Technologies Ltd nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY CITEL TECHNOLOGIES AND CONTRIBUTORS ``AS IS'' + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL CITEL TECHNOLOGIES OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * This file is a contribution to the lwIP TCP/IP stack. + * The Swedish Institute of Computer Science and Adam Dunkels + * are specifically granted permission to redistribute this + * source code. +*/ + +#ifndef LWIP_HDR_IGMP_H +#define LWIP_HDR_IGMP_H + +#include "lwip/opt.h" +#include "lwip/ip_addr.h" +#include "lwip/netif.h" +#include "lwip/pbuf.h" + +#if LWIP_IPV4 && LWIP_IGMP /* don't build if not configured for use in lwipopts.h */ + +#ifdef __cplusplus +extern "C" { +#endif + + +/* IGMP timer */ +#define IGMP_TMR_INTERVAL 100 /* Milliseconds */ +#define IGMP_V1_DELAYING_MEMBER_TMR (1000/IGMP_TMR_INTERVAL) +#define IGMP_JOIN_DELAYING_MEMBER_TMR (500 /IGMP_TMR_INTERVAL) + +/* MAC Filter Actions, these are passed to a netif's + * igmp_mac_filter callback function. */ +#define IGMP_DEL_MAC_FILTER 0 +#define IGMP_ADD_MAC_FILTER 1 + + +/** + * igmp group structure - there is + * a list of groups for each interface + * these should really be linked from the interface, but + * if we keep them separate we will not affect the lwip original code + * too much + * + * There will be a group for the all systems group address but this + * will not run the state machine as it is used to kick off reports + * from all the other groups + */ +struct igmp_group { + /** next link */ + struct igmp_group *next; + /** interface on which the group is active */ + struct netif *netif; + /** multicast address */ + ip4_addr_t group_address; + /** signifies we were the last person to report */ + u8_t last_reporter_flag; + /** current state of the group */ + u8_t group_state; + /** timer for reporting, negative is OFF */ + u16_t timer; + /** counter of simultaneous uses */ + u8_t use; +}; + +/* Prototypes */ +void igmp_init(void); +err_t igmp_start(struct netif *netif); +err_t igmp_stop(struct netif *netif); +void igmp_report_groups(struct netif *netif); +struct igmp_group *igmp_lookfor_group(struct netif *ifp, const ip4_addr_t *addr); +void igmp_input(struct pbuf *p, struct netif *inp, const ip4_addr_t *dest); +err_t igmp_joingroup(const ip4_addr_t *ifaddr, const ip4_addr_t *groupaddr); +err_t igmp_joingroup_netif(struct netif *netif, const ip4_addr_t *groupaddr); +err_t igmp_leavegroup(const ip4_addr_t *ifaddr, const ip4_addr_t *groupaddr); +err_t igmp_leavegroup_netif(struct netif *netif, const ip4_addr_t *groupaddr); +void igmp_tmr(void); + +#ifdef __cplusplus +} +#endif + +#endif /* LWIP_IPV4 && LWIP_IGMP */ + +#endif /* LWIP_HDR_IGMP_H */ diff --git a/components/lwip/include/lwip/lwip/inet.h b/components/lwip/include/lwip/lwip/inet.h new file mode 100755 index 0000000000..036cd988d2 --- /dev/null +++ b/components/lwip/include/lwip/lwip/inet.h @@ -0,0 +1,172 @@ +/** + * @file + * This file (together with sockets.h) aims to provide structs and functions from + * - arpa/inet.h + * - netinet/in.h + * + */ + +/* + * Copyright (c) 2001-2004 Swedish Institute of Computer Science. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + * + */ +#ifndef LWIP_HDR_INET_H +#define LWIP_HDR_INET_H + +#include "lwip/opt.h" +#include "lwip/def.h" +#include "lwip/ip_addr.h" +#include "lwip/ip6_addr.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/* If your port already typedef's in_addr_t, define IN_ADDR_T_DEFINED + to prevent this code from redefining it. */ +#if !defined(in_addr_t) && !defined(IN_ADDR_T_DEFINED) +typedef u32_t in_addr_t; +#endif + +struct in_addr { + in_addr_t s_addr; +}; + +struct in6_addr { + union { + u32_t u32_addr[4]; + u8_t u8_addr[16]; + } un; +#define s6_addr un.u8_addr +}; + +/** 255.255.255.255 */ +#define INADDR_NONE IPADDR_NONE +/** 127.0.0.1 */ +#define INADDR_LOOPBACK IPADDR_LOOPBACK +/** 0.0.0.0 */ +#define INADDR_ANY IPADDR_ANY +/** 255.255.255.255 */ +#define INADDR_BROADCAST IPADDR_BROADCAST + +/** This macro can be used to initialize a variable of type struct in6_addr + to the IPv6 wildcard address. */ +#define IN6ADDR_ANY_INIT {{{0,0,0,0}}} +/** This macro can be used to initialize a variable of type struct in6_addr + to the IPv6 loopback address. */ +#define IN6ADDR_LOOPBACK_INIT {{{0,0,0,PP_HTONL(1)}}} +/** This variable is initialized by the system to contain the wildcard IPv6 address. */ +extern const struct in6_addr in6addr_any; + +/* Definitions of the bits in an (IPv4) Internet address integer. + + On subnets, host and network parts are found according to + the subnet mask, not these masks. */ +#define IN_CLASSA(a) IP_CLASSA(a) +#define IN_CLASSA_NET IP_CLASSA_NET +#define IN_CLASSA_NSHIFT IP_CLASSA_NSHIFT +#define IN_CLASSA_HOST IP_CLASSA_HOST +#define IN_CLASSA_MAX IP_CLASSA_MAX + +#define IN_CLASSB(b) IP_CLASSB(b) +#define IN_CLASSB_NET IP_CLASSB_NET +#define IN_CLASSB_NSHIFT IP_CLASSB_NSHIFT +#define IN_CLASSB_HOST IP_CLASSB_HOST +#define IN_CLASSB_MAX IP_CLASSB_MAX + +#define IN_CLASSC(c) IP_CLASSC(c) +#define IN_CLASSC_NET IP_CLASSC_NET +#define IN_CLASSC_NSHIFT IP_CLASSC_NSHIFT +#define IN_CLASSC_HOST IP_CLASSC_HOST +#define IN_CLASSC_MAX IP_CLASSC_MAX + +#define IN_CLASSD(d) IP_CLASSD(d) +#define IN_CLASSD_NET IP_CLASSD_NET /* These ones aren't really */ +#define IN_CLASSD_NSHIFT IP_CLASSD_NSHIFT /* net and host fields, but */ +#define IN_CLASSD_HOST IP_CLASSD_HOST /* routing needn't know. */ +#define IN_CLASSD_MAX IP_CLASSD_MAX + +#define IN_MULTICAST(a) IP_MULTICAST(a) + +#define IN_EXPERIMENTAL(a) IP_EXPERIMENTAL(a) +#define IN_BADCLASS(a) IP_BADCLASS(a) + +#define IN_LOOPBACKNET IP_LOOPBACKNET + + +#ifndef INET_ADDRSTRLEN +#define INET_ADDRSTRLEN IP4ADDR_STRLEN_MAX +#endif +#if LWIP_IPV6 +#ifndef INET6_ADDRSTRLEN +#define INET6_ADDRSTRLEN IP6ADDR_STRLEN_MAX +#endif +#endif + +#if LWIP_IPV4 + +#define inet_addr_from_ipaddr(target_inaddr, source_ipaddr) ((target_inaddr)->s_addr = ip4_addr_get_u32(source_ipaddr)) +#define inet_addr_to_ipaddr(target_ipaddr, source_inaddr) (ip4_addr_set_u32(target_ipaddr, (source_inaddr)->s_addr)) +/* ATTENTION: the next define only works because both s_addr and ip_addr_t are an u32_t effectively! */ +#define inet_addr_to_ipaddr_p(target_ipaddr_p, source_inaddr) ((target_ipaddr_p) = (ip_addr_t*)&((source_inaddr)->s_addr)) + +/* directly map this to the lwip internal functions */ +#define inet_addr(cp) ipaddr_addr(cp) +#define inet_aton(cp, addr) ip4addr_aton(cp, (ip4_addr_t*)addr) +#define inet_ntoa(addr) ip4addr_ntoa((const ip4_addr_t*)&(addr)) +#define inet_ntoa_r(addr, buf, buflen) ip4addr_ntoa_r((const ip4_addr_t*)&(addr), buf, buflen) + +#endif /* LWIP_IPV4 */ + +#if LWIP_IPV6 +#define inet6_addr_from_ip6addr(target_in6addr, source_ip6addr) {(target_in6addr)->un.u32_addr[0] = (source_ip6addr)->addr[0]; \ + (target_in6addr)->un.u32_addr[1] = (source_ip6addr)->addr[1]; \ + (target_in6addr)->un.u32_addr[2] = (source_ip6addr)->addr[2]; \ + (target_in6addr)->un.u32_addr[3] = (source_ip6addr)->addr[3];} +#define inet6_addr_to_ip6addr(target_ip6addr, source_in6addr) {(target_ip6addr)->addr[0] = (source_in6addr)->un.u32_addr[0]; \ + (target_ip6addr)->addr[1] = (source_in6addr)->un.u32_addr[1]; \ + (target_ip6addr)->addr[2] = (source_in6addr)->un.u32_addr[2]; \ + (target_ip6addr)->addr[3] = (source_in6addr)->un.u32_addr[3];} +/* ATTENTION: the next define only works because both in6_addr and ip6_addr_t are an u32_t[4] effectively! */ +#define inet6_addr_to_ip6addr_p(target_ip6addr_p, source_in6addr) ((target_ip6addr_p) = (ip6_addr_t*)(source_in6addr)) + +/* directly map this to the lwip internal functions */ +#define inet6_aton(cp, addr) ip6addr_aton(cp, (ip6_addr_t*)addr) +#define inet6_ntoa(addr) ip6addr_ntoa((const ip6_addr_t*)&(addr)) +#define inet6_ntoa_r(addr, buf, buflen) ip6addr_ntoa_r((const ip6_addr_t*)&(addr), buf, buflen) + +#endif /* LWIP_IPV6 */ + + +#ifdef __cplusplus +} +#endif + +#endif /* LWIP_HDR_INET_H */ diff --git a/components/lwip/include/lwip/lwip/inet_chksum.h b/components/lwip/include/lwip/lwip/inet_chksum.h new file mode 100755 index 0000000000..1766f4b5d8 --- /dev/null +++ b/components/lwip/include/lwip/lwip/inet_chksum.h @@ -0,0 +1,106 @@ +/* + * Copyright (c) 2001-2004 Swedish Institute of Computer Science. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + * + */ +#ifndef LWIP_HDR_INET_CHKSUM_H +#define LWIP_HDR_INET_CHKSUM_H + +#include "lwip/opt.h" + +#include "lwip/pbuf.h" +#include "lwip/ip_addr.h" + +/** Swap the bytes in an u16_t: much like htons() for little-endian */ +#ifndef SWAP_BYTES_IN_WORD +#if LWIP_PLATFORM_BYTESWAP && (BYTE_ORDER == LITTLE_ENDIAN) +/* little endian and PLATFORM_BYTESWAP defined */ +#define SWAP_BYTES_IN_WORD(w) LWIP_PLATFORM_HTONS(w) +#else /* LWIP_PLATFORM_BYTESWAP && (BYTE_ORDER == LITTLE_ENDIAN) */ +/* can't use htons on big endian (or PLATFORM_BYTESWAP not defined)... */ +#define SWAP_BYTES_IN_WORD(w) (((w) & 0xff) << 8) | (((w) & 0xff00) >> 8) +#endif /* LWIP_PLATFORM_BYTESWAP && (BYTE_ORDER == LITTLE_ENDIAN)*/ +#endif /* SWAP_BYTES_IN_WORD */ + +/** Split an u32_t in two u16_ts and add them up */ +#ifndef FOLD_U32T +#define FOLD_U32T(u) (((u) >> 16) + ((u) & 0x0000ffffUL)) +#endif + +#if LWIP_CHECKSUM_ON_COPY +/** Function-like macro: same as MEMCPY but returns the checksum of copied data + as u16_t */ +# ifndef LWIP_CHKSUM_COPY +# define LWIP_CHKSUM_COPY(dst, src, len) lwip_chksum_copy(dst, src, len) +# ifndef LWIP_CHKSUM_COPY_ALGORITHM +# define LWIP_CHKSUM_COPY_ALGORITHM 1 +# endif /* LWIP_CHKSUM_COPY_ALGORITHM */ +# else /* LWIP_CHKSUM_COPY */ +# define LWIP_CHKSUM_COPY_ALGORITHM 0 +# endif /* LWIP_CHKSUM_COPY */ +#else /* LWIP_CHECKSUM_ON_COPY */ +# define LWIP_CHKSUM_COPY_ALGORITHM 0 +#endif /* LWIP_CHECKSUM_ON_COPY */ + +#ifdef __cplusplus +extern "C" { +#endif + +u16_t inet_chksum(const void *dataptr, u16_t len); +u16_t inet_chksum_pbuf(struct pbuf *p); +#if LWIP_CHKSUM_COPY_ALGORITHM +u16_t lwip_chksum_copy(void *dst, const void *src, u16_t len); +#endif /* LWIP_CHKSUM_COPY_ALGORITHM */ + +#if LWIP_IPV4 +u16_t inet_chksum_pseudo(struct pbuf *p, u8_t proto, u16_t proto_len, + const ip4_addr_t *src, const ip4_addr_t *dest); +u16_t inet_chksum_pseudo_partial(struct pbuf *p, u8_t proto, + u16_t proto_len, u16_t chksum_len, const ip4_addr_t *src, const ip4_addr_t *dest); +#endif /* LWIP_IPV4 */ + +#if LWIP_IPV6 +u16_t ip6_chksum_pseudo(struct pbuf *p, u8_t proto, u16_t proto_len, + const ip6_addr_t *src, const ip6_addr_t *dest); +u16_t ip6_chksum_pseudo_partial(struct pbuf *p, u8_t proto, u16_t proto_len, + u16_t chksum_len, const ip6_addr_t *src, const ip6_addr_t *dest); +#endif /* LWIP_IPV6 */ + + +u16_t ip_chksum_pseudo(struct pbuf *p, u8_t proto, u16_t proto_len, + const ip_addr_t *src, const ip_addr_t *dest); +u16_t ip_chksum_pseudo_partial(struct pbuf *p, u8_t proto, u16_t proto_len, + u16_t chksum_len, const ip_addr_t *src, const ip_addr_t *dest); + +#ifdef __cplusplus +} +#endif + +#endif /* LWIP_HDR_INET_H */ + diff --git a/components/lwip/include/lwip/lwip/init.h b/components/lwip/include/lwip/lwip/init.h new file mode 100755 index 0000000000..70351b86fc --- /dev/null +++ b/components/lwip/include/lwip/lwip/init.h @@ -0,0 +1,72 @@ +/* + * Copyright (c) 2001-2004 Swedish Institute of Computer Science. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + * + */ +#ifndef LWIP_HDR_INIT_H +#define LWIP_HDR_INIT_H + +#include "lwip/opt.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** X.x.x: Major version of the stack */ +#define LWIP_VERSION_MAJOR 1U +/** x.X.x: Minor version of the stack */ +#define LWIP_VERSION_MINOR 5U +/** x.x.X: Revision of the stack */ +#define LWIP_VERSION_REVISION 0U +/** For release candidates, this is set to 1..254 + * For official releases, this is set to 255 (LWIP_RC_RELEASE) + * For development versions (Git), this is set to 0 (LWIP_RC_DEVELOPMENT) */ +#define LWIP_VERSION_RC 0U + +/** LWIP_VERSION_RC is set to LWIP_RC_RELEASE for official releases */ +#define LWIP_RC_RELEASE 255U +/** LWIP_VERSION_RC is set to LWIP_RC_DEVELOPMENT for Git versions */ +#define LWIP_RC_DEVELOPMENT 0U + +#define LWIP_VERSION_IS_RELEASE (LWIP_VERSION_RC == LWIP_RC_RELEASE) +#define LWIP_VERSION_IS_DEVELOPMENT (LWIP_VERSION_RC == LWIP_RC_DEVELOPMENT) +#define LWIP_VERSION_IS_RC ((LWIP_VERSION_RC != LWIP_RC_RELEASE) && (LWIP_VERSION_RC != LWIP_RC_DEVELOPMENT)) + +/** Provides the version of the stack */ +#define LWIP_VERSION (LWIP_VERSION_MAJOR << 24 | LWIP_VERSION_MINOR << 16 | \ + LWIP_VERSION_REVISION << 8 | LWIP_VERSION_RC) + +/* Modules initialization */ +void lwip_init(void); + +#ifdef __cplusplus +} +#endif + +#endif /* LWIP_HDR_INIT_H */ diff --git a/components/lwip/include/lwip/lwip/ip.h b/components/lwip/include/lwip/lwip/ip.h new file mode 100755 index 0000000000..d42fe68110 --- /dev/null +++ b/components/lwip/include/lwip/lwip/ip.h @@ -0,0 +1,304 @@ +/* + * Copyright (c) 2001-2004 Swedish Institute of Computer Science. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + * + */ +#ifndef LWIP_HDR_IP_H__ +#define LWIP_HDR_IP_H__ + +#include "lwip/opt.h" + +#include "lwip/def.h" +#include "lwip/pbuf.h" +#include "lwip/ip_addr.h" +#include "lwip/err.h" +#include "lwip/netif.h" +#include "lwip/ip4.h" +#include "lwip/ip6.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#define IP_PROTO_ICMP 1 +#define IP_PROTO_IGMP 2 +#define IP_PROTO_UDP 17 +#define IP_PROTO_UDPLITE 136 +#define IP_PROTO_TCP 6 + +/** This operates on a void* by loading the first byte */ +#define IP_HDR_GET_VERSION(ptr) ((*(u8_t*)(ptr)) >> 4) + +/* This is passed as the destination address to ip_output_if (not + to ip_output), meaning that an IP header already is constructed + in the pbuf. This is used when TCP retransmits. */ +#ifdef IP_HDRINCL +#undef IP_HDRINCL +#endif /* IP_HDRINCL */ +#define IP_HDRINCL NULL + +/** pbufs passed to IP must have a ref-count of 1 as their payload pointer + gets altered as the packet is passed down the stack */ +#ifndef LWIP_IP_CHECK_PBUF_REF_COUNT_FOR_TX +#define LWIP_IP_CHECK_PBUF_REF_COUNT_FOR_TX(p) LWIP_ASSERT("p->ref == 1", (p)->ref == 1) +#endif + +#if LWIP_NETIF_HWADDRHINT +#define IP_PCB_ADDRHINT ;u8_t addr_hint +#else +#define IP_PCB_ADDRHINT +#endif /* LWIP_NETIF_HWADDRHINT */ + +/* This is the common part of all PCB types. It needs to be at the + beginning of a PCB type definition. It is located here so that + changes to this common part are made in one location instead of + having to change all PCB structs. */ +#define IP_PCB \ + /* ip addresses in network byte order */ \ + ip_addr_t local_ip; \ + ip_addr_t remote_ip; \ + /* Socket options */ \ + u8_t so_options; \ + /* Type Of Service */ \ + u8_t tos; \ + /* Time To Live */ \ + u8_t ttl \ + /* link layer address resolution hint */ \ + IP_PCB_ADDRHINT + +struct ip_pcb { +/* Common members of all PCB types */ + IP_PCB; +}; + +/* + * Option flags per-socket. These are the same like SO_XXX in sockets.h + */ +#define SOF_REUSEADDR 0x04U /* allow local address reuse */ +#define SOF_KEEPALIVE 0x08U /* keep connections alive */ +#define SOF_BROADCAST 0x20U /* permit to send and to receive broadcast messages (see IP_SOF_BROADCAST option) */ + +/* These flags are inherited (e.g. from a listen-pcb to a connection-pcb): */ +#define SOF_INHERITED (SOF_REUSEADDR|SOF_KEEPALIVE) + +/* Global variables of this module, kept in a struct for efficient access using base+index. */ +struct ip_globals +{ + /** The interface that accepted the packet for the current callback invocation. */ + struct netif *current_netif; + /** The interface that received the packet for the current callback invocation. */ + struct netif *current_input_netif; +#if LWIP_IPV4 + /** Header of the input packet currently being processed. */ + struct ip_hdr *current_ip4_header; +#endif /* LWIP_IPV4 */ +#if LWIP_IPV6 + /** Header of the input IPv6 packet currently being processed. */ + struct ip6_hdr *current_ip6_header; +#endif /* LWIP_IPV6 */ + /** Total header length of current_ip4/6_header (i.e. after this, the UDP/TCP header starts) */ + u16_t current_ip_header_tot_len; + /** Source IP address of current_header */ + ip_addr_t current_iphdr_src; + /** Destination IP address of current_header */ + ip_addr_t current_iphdr_dest; +}; +extern struct ip_globals ip_data; + + +/** Get the interface that accepted the current packet. + * This may or may not be the receiving netif, depending on your netif/network setup. + * This function must only be called from a receive callback (udp_recv, + * raw_recv, tcp_accept). It will return NULL otherwise. */ +#define ip_current_netif() (ip_data.current_netif) +/** Get the interface that received the current packet. + * This function must only be called from a receive callback (udp_recv, + * raw_recv, tcp_accept). It will return NULL otherwise. */ +#define ip_current_input_netif() (ip_data.current_input_netif) +/** Total header length of ip(6)_current_header() (i.e. after this, the UDP/TCP header starts) */ +#define ip_current_header_tot_len() (ip_data.current_ip_header_tot_len) +/** Source IP address of current_header */ +#define ip_current_src_addr() (&ip_data.current_iphdr_src) +/** Destination IP address of current_header */ +#define ip_current_dest_addr() (&ip_data.current_iphdr_dest) + +#if LWIP_IPV4 && LWIP_IPV6 +/** Get the IPv4 header of the current packet. + * This function must only be called from a receive callback (udp_recv, + * raw_recv, tcp_accept). It will return NULL otherwise. */ +#define ip4_current_header() ((const struct ip_hdr*)(ip_data.current_ip4_header)) +/** Get the IPv6 header of the current packet. + * This function must only be called from a receive callback (udp_recv, + * raw_recv, tcp_accept). It will return NULL otherwise. */ +#define ip6_current_header() ((const struct ip6_hdr*)(ip_data.current_ip6_header)) +/** Returns TRUE if the current IP input packet is IPv6, FALSE if it is IPv4 */ +#define ip_current_is_v6() (ip6_current_header() != NULL) +/** Source IPv6 address of current_header */ +#define ip6_current_src_addr() (ip_2_ip6(&ip_data.current_iphdr_src)) +/** Destination IPv6 address of current_header */ +#define ip6_current_dest_addr() (ip_2_ip6(&ip_data.current_iphdr_dest)) +/** Get the transport layer protocol */ +#define ip_current_header_proto() (ip_current_is_v6() ? \ + IP6H_NEXTH(ip6_current_header()) :\ + IPH_PROTO(ip4_current_header())) +/** Get the transport layer header */ +#define ip_next_header_ptr() ((const void*)((ip_current_is_v6() ? \ + (const u8_t*)ip6_current_header() : (const u8_t*)ip4_current_header()) + ip_current_header_tot_len())) + +/** Source IP4 address of current_header */ +#define ip4_current_src_addr() (ip_2_ip4(&ip_data.current_iphdr_src)) +/** Destination IP4 address of current_header */ +#define ip4_current_dest_addr() (ip_2_ip4(&ip_data.current_iphdr_dest)) + +#elif LWIP_IPV4 /* LWIP_IPV4 && LWIP_IPV6 */ + +/** Get the IPv4 header of the current packet. + * This function must only be called from a receive callback (udp_recv, + * raw_recv, tcp_accept). It will return NULL otherwise. */ +#define ip4_current_header() ((const struct ip_hdr*)(ip_data.current_ip4_header)) +/** Always returns FALSE when only supporting IPv4 only */ +#define ip_current_is_v6() 0 +/** Get the transport layer protocol */ +#define ip_current_header_proto() IPH_PROTO(ip4_current_header()) +/** Get the transport layer header */ +#define ip_next_header_ptr() ((const void*)((const u8_t*)ip4_current_header() + ip_current_header_tot_len())) +/** Source IP4 address of current_header */ +#define ip4_current_src_addr() (&ip_data.current_iphdr_src) +/** Destination IP4 address of current_header */ +#define ip4_current_dest_addr() (&ip_data.current_iphdr_dest) + +#elif LWIP_IPV6 /* LWIP_IPV4 && LWIP_IPV6 */ + +/** Get the IPv6 header of the current packet. + * This function must only be called from a receive callback (udp_recv, + * raw_recv, tcp_accept). It will return NULL otherwise. */ +#define ip6_current_header() ((const struct ip6_hdr*)(ip_data.current_ip6_header)) +/** Always returns TRUE when only supporting IPv6 only */ +#define ip_current_is_v6() 1 +/** Get the transport layer protocol */ +#define ip_current_header_proto() IP6H_NEXTH(ip6_current_header()) +/** Get the transport layer header */ +#define ip_next_header_ptr() ((const void*)((const u8_t*)ip6_current_header())) +/** Source IP6 address of current_header */ +#define ip6_current_src_addr() (&ip_data.current_iphdr_src) +/** Destination IP6 address of current_header */ +#define ip6_current_dest_addr() (&ip_data.current_iphdr_dest) + +#endif /* LWIP_IPV6 */ + +/** Union source address of current_header */ +#define ip_current_src_addr() (&ip_data.current_iphdr_src) +/** Union destination address of current_header */ +#define ip_current_dest_addr() (&ip_data.current_iphdr_dest) + +/** Gets an IP pcb option (SOF_* flags) */ +#define ip_get_option(pcb, opt) ((pcb)->so_options & (opt)) +/** Sets an IP pcb option (SOF_* flags) */ +#define ip_set_option(pcb, opt) ((pcb)->so_options |= (opt)) +/** Resets an IP pcb option (SOF_* flags) */ +#define ip_reset_option(pcb, opt) ((pcb)->so_options &= ~(opt)) + +#if LWIP_IPV4 && LWIP_IPV6 +#define ip_output(p, src, dest, ttl, tos, proto) \ + (IP_IS_V6(dest) ? \ + ip6_output(p, ip_2_ip6(src), ip_2_ip6(dest), ttl, tos, proto) : \ + ip4_output(p, ip_2_ip4(src), ip_2_ip4(dest), ttl, tos, proto)) +#define ip_output_if(p, src, dest, ttl, tos, proto, netif) \ + (IP_IS_V6(dest) ? \ + ip6_output_if(p, ip_2_ip6(src), ip_2_ip6(dest), ttl, tos, proto, netif) : \ + ip4_output_if(p, ip_2_ip4(src), ip_2_ip4(dest), ttl, tos, proto, netif)) +#define ip_output_if_src(p, src, dest, ttl, tos, proto, netif) \ + (IP_IS_V6(dest) ? \ + ip6_output_if_src(p, ip_2_ip6(src), ip_2_ip6(dest), ttl, tos, proto, netif) : \ + ip4_output_if_src(p, ip_2_ip4(src), ip_2_ip4(dest), ttl, tos, proto, netif)) +#define ip_output_hinted(p, src, dest, ttl, tos, proto, addr_hint) \ + (IP_IS_V6(dest) ? \ + ip6_output_hinted(p, ip_2_ip6(src), ip_2_ip6(dest), ttl, tos, proto, addr_hint) : \ + ip4_output_hinted(p, ip_2_ip4(src), ip_2_ip4(dest), ttl, tos, proto, addr_hint)) +#define ip_route(src, dest) \ + (IP_IS_V6(dest) ? \ + ip6_route(ip_2_ip6(src), ip_2_ip6(dest)) : \ + ip4_route_src(ip_2_ip4(dest), ip_2_ip4(src))) +#define ip_netif_get_local_ip(netif, dest) (IP_IS_V6(dest) ? \ + ip6_netif_get_local_ip(netif, ip_2_ip6(dest)) : \ + ip4_netif_get_local_ip(netif)) +#define ip_debug_print(is_ipv6, p) ((is_ipv6) ? ip6_debug_print(p) : ip4_debug_print(p)) + +err_t ip_input(struct pbuf *p, struct netif *inp); + +#elif LWIP_IPV4 /* LWIP_IPV4 && LWIP_IPV6 */ + +#define ip_output(p, src, dest, ttl, tos, proto) \ + ip4_output(p, src, dest, ttl, tos, proto) +#define ip_output_if(p, src, dest, ttl, tos, proto, netif) \ + ip4_output_if(p, src, dest, ttl, tos, proto, netif) +#define ip_output_if_src(p, src, dest, ttl, tos, proto, netif) \ + ip4_output_if_src(p, src, dest, ttl, tos, proto, netif) +#define ip_output_hinted(p, src, dest, ttl, tos, proto, addr_hint) \ + ip4_output_hinted(p, src, dest, ttl, tos, proto, addr_hint) +#define ip_route(src, dest) \ + ip4_route_src(dest, src) +#define ip_netif_get_local_ip(netif, dest) \ + ip4_netif_get_local_ip(netif) +#define ip_debug_print(is_ipv6, p) ip4_debug_print(p) + +#define ip_input ip4_input + +#elif LWIP_IPV6 /* LWIP_IPV4 && LWIP_IPV6 */ + +#define ip_output(p, src, dest, ttl, tos, proto) \ + ip6_output(p, src, dest, ttl, tos, proto) +#define ip_output_if(p, src, dest, ttl, tos, proto, netif) \ + ip6_output_if(p, src, dest, ttl, tos, proto, netif) +#define ip_output_if_src(p, src, dest, ttl, tos, proto, netif) \ + ip6_output_if_src(p, src, dest, ttl, tos, proto, netif) +#define ip_output_hinted(p, src, dest, ttl, tos, proto, addr_hint) \ + ip6_output_hinted(p, src, dest, ttl, tos, proto, addr_hint) +#define ip_route(src, dest) \ + ip6_route(src, dest) +#define ip_netif_get_local_ip(netif, dest) \ + ip6_netif_get_local_ip(netif, dest) +#define ip_debug_print(is_ipv6, p) ip6_debug_print(p) + +#define ip_input ip6_input + +#endif /* LWIP_IPV6 */ + +#define ip_route_get_local_ip(src, dest, netif, ipaddr) do { \ + (netif) = ip_route(src, dest); \ + (ipaddr) = ip_netif_get_local_ip(netif, dest); \ +}while(0) + +#ifdef __cplusplus +} +#endif + +#endif /* LWIP_HDR_IP_H__ */ + + diff --git a/components/lwip/include/lwip/lwip/ip4.h b/components/lwip/include/lwip/lwip/ip4.h new file mode 100755 index 0000000000..e69e55c754 --- /dev/null +++ b/components/lwip/include/lwip/lwip/ip4.h @@ -0,0 +1,161 @@ +/* + * Copyright (c) 2001-2004 Swedish Institute of Computer Science. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + * + */ +#ifndef LWIP_HDR_IP4_H +#define LWIP_HDR_IP4_H + +#include "lwip/opt.h" + +#if LWIP_IPV4 + +#include "lwip/def.h" +#include "lwip/pbuf.h" +#include "lwip/ip4_addr.h" +#include "lwip/err.h" +#include "lwip/netif.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#ifdef LWIP_HOOK_IP4_ROUTE_SRC +#define LWIP_IPV4_SRC_ROUTING 1 +#else +#define LWIP_IPV4_SRC_ROUTING 0 +#endif + +/** Currently, the function ip_output_if_opt() is only used with IGMP */ +#define IP_OPTIONS_SEND (LWIP_IPV4 && LWIP_IGMP) + +#define IP_HLEN 20 + + +#ifdef PACK_STRUCT_USE_INCLUDES +# include "arch/bpstruct.h" +#endif +PACK_STRUCT_BEGIN +struct ip_hdr { + /* version / header length */ + PACK_STRUCT_FLD_8(u8_t _v_hl); + /* type of service */ + PACK_STRUCT_FLD_8(u8_t _tos); + /* total length */ + PACK_STRUCT_FIELD(u16_t _len); + /* identification */ + PACK_STRUCT_FIELD(u16_t _id); + /* fragment offset field */ + PACK_STRUCT_FIELD(u16_t _offset); +#define IP_RF 0x8000U /* reserved fragment flag */ +#define IP_DF 0x4000U /* don't fragment flag */ +#define IP_MF 0x2000U /* more fragments flag */ +#define IP_OFFMASK 0x1fffU /* mask for fragmenting bits */ + /* time to live */ + PACK_STRUCT_FLD_8(u8_t _ttl); + /* protocol*/ + PACK_STRUCT_FLD_8(u8_t _proto); + /* checksum */ + PACK_STRUCT_FIELD(u16_t _chksum); + /* source and destination IP addresses */ + PACK_STRUCT_FLD_S(ip4_addr_p_t src); + PACK_STRUCT_FLD_S(ip4_addr_p_t dest); +} PACK_STRUCT_STRUCT; +PACK_STRUCT_END +#ifdef PACK_STRUCT_USE_INCLUDES +# include "arch/epstruct.h" +#endif + +#define IPH_V(hdr) ((hdr)->_v_hl >> 4) +#define IPH_HL(hdr) ((hdr)->_v_hl & 0x0f) +#define IPH_TOS(hdr) ((hdr)->_tos) +#define IPH_LEN(hdr) ((hdr)->_len) +#define IPH_ID(hdr) ((hdr)->_id) +#define IPH_OFFSET(hdr) ((hdr)->_offset) +#define IPH_TTL(hdr) ((hdr)->_ttl) +#define IPH_PROTO(hdr) ((hdr)->_proto) +#define IPH_CHKSUM(hdr) ((hdr)->_chksum) + +#define IPH_VHL_SET(hdr, v, hl) (hdr)->_v_hl = (u8_t)((((v) << 4) | (hl))) +#define IPH_TOS_SET(hdr, tos) (hdr)->_tos = (tos) +#define IPH_LEN_SET(hdr, len) (hdr)->_len = (len) +#define IPH_ID_SET(hdr, id) (hdr)->_id = (id) +#define IPH_OFFSET_SET(hdr, off) (hdr)->_offset = (off) +#define IPH_TTL_SET(hdr, ttl) (hdr)->_ttl = (u8_t)(ttl) +#define IPH_PROTO_SET(hdr, proto) (hdr)->_proto = (u8_t)(proto) +#define IPH_CHKSUM_SET(hdr, chksum) (hdr)->_chksum = (chksum) + +#define ip_init() /* Compatibility define, no init needed. */ +struct netif *ip4_route(const ip4_addr_t *dest); +#if LWIP_IPV4_SRC_ROUTING +struct netif *ip4_route_src(const ip4_addr_t *dest, const ip4_addr_t *src); +#else /* LWIP_IPV4_SRC_ROUTING */ +#define ip4_route_src(dest, src) ip4_route(dest) +#endif /* LWIP_IPV4_SRC_ROUTING */ +err_t ip4_input(struct pbuf *p, struct netif *inp); +err_t ip4_output(struct pbuf *p, const ip4_addr_t *src, const ip4_addr_t *dest, + u8_t ttl, u8_t tos, u8_t proto); +err_t ip4_output_if(struct pbuf *p, const ip4_addr_t *src, const ip4_addr_t *dest, + u8_t ttl, u8_t tos, u8_t proto, struct netif *netif); +err_t ip4_output_if_src(struct pbuf *p, const ip4_addr_t *src, const ip4_addr_t *dest, + u8_t ttl, u8_t tos, u8_t proto, struct netif *netif); +#if LWIP_NETIF_HWADDRHINT +err_t ip4_output_hinted(struct pbuf *p, const ip4_addr_t *src, const ip4_addr_t *dest, + u8_t ttl, u8_t tos, u8_t proto, u8_t *addr_hint); +#endif /* LWIP_NETIF_HWADDRHINT */ +#if IP_OPTIONS_SEND +err_t ip4_output_if_opt(struct pbuf *p, const ip4_addr_t *src, const ip4_addr_t *dest, + u8_t ttl, u8_t tos, u8_t proto, struct netif *netif, void *ip_options, + u16_t optlen); +err_t ip4_output_if_opt_src(struct pbuf *p, const ip4_addr_t *src, const ip4_addr_t *dest, + u8_t ttl, u8_t tos, u8_t proto, struct netif *netif, void *ip_options, + u16_t optlen); +#endif /* IP_OPTIONS_SEND */ + +#if LWIP_MULTICAST_TX_OPTIONS +void ip4_set_default_multicast_netif(struct netif* default_multicast_netif); +#endif /* LWIP_MULTICAST_TX_OPTIONS */ + +#define ip4_netif_get_local_ip(netif) (((netif) != NULL) ? netif_ip_addr4(netif) : NULL) + +#if IP_DEBUG +void ip4_debug_print(struct pbuf *p); +#else +#define ip4_debug_print(p) +#endif /* IP_DEBUG */ + +#ifdef __cplusplus +} +#endif + +#endif /* LWIP_IPV4 */ + +#endif /* LWIP_HDR_IP_H */ + + diff --git a/components/lwip/include/lwip/lwip/ip4_addr.h b/components/lwip/include/lwip/lwip/ip4_addr.h new file mode 100755 index 0000000000..9483a2f7b9 --- /dev/null +++ b/components/lwip/include/lwip/lwip/ip4_addr.h @@ -0,0 +1,253 @@ +/* + * Copyright (c) 2001-2004 Swedish Institute of Computer Science. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + * + */ +#ifndef LWIP_HDR_IP4_ADDR_H +#define LWIP_HDR_IP4_ADDR_H + +#include "lwip/opt.h" +#include "lwip/def.h" + +#if LWIP_IPV4 + +#ifdef __cplusplus +extern "C" { +#endif + +/* This is the aligned version of ip4_addr_t, + used as local variable, on the stack, etc. */ +struct ip4_addr { + u32_t addr; +}; + +/* This is the packed version of ip4_addr_t, + used in network headers that are itself packed */ +#ifdef PACK_STRUCT_USE_INCLUDES +# include "arch/bpstruct.h" +#endif +PACK_STRUCT_BEGIN +struct ip4_addr_packed { + PACK_STRUCT_FIELD(u32_t addr); +} PACK_STRUCT_STRUCT; +PACK_STRUCT_END +#ifdef PACK_STRUCT_USE_INCLUDES +# include "arch/epstruct.h" +#endif + +/** ip4_addr_t uses a struct for convenience only, so that the same defines can + * operate both on ip4_addr_t as well as on ip4_addr_p_t. */ +typedef struct ip4_addr ip4_addr_t; +typedef struct ip4_addr_packed ip4_addr_p_t; + +/* + * struct ipaddr2 is used in the definition of the ARP packet format in + * order to support compilers that don't have structure packing. + */ +#ifdef PACK_STRUCT_USE_INCLUDES +# include "arch/bpstruct.h" +#endif +PACK_STRUCT_BEGIN +struct ip4_addr2 { + PACK_STRUCT_FIELD(u16_t addrw[2]); +} PACK_STRUCT_STRUCT; +PACK_STRUCT_END +#ifdef PACK_STRUCT_USE_INCLUDES +# include "arch/epstruct.h" +#endif + +/* Forward declaration to not include netif.h */ +struct netif; + +/** 255.255.255.255 */ +#define IPADDR_NONE ((u32_t)0xffffffffUL) +/** 127.0.0.1 */ +#define IPADDR_LOOPBACK ((u32_t)0x7f000001UL) +/** 0.0.0.0 */ +#define IPADDR_ANY ((u32_t)0x00000000UL) +/** 255.255.255.255 */ +#define IPADDR_BROADCAST ((u32_t)0xffffffffUL) + +/* Definitions of the bits in an Internet address integer. + + On subnets, host and network parts are found according to + the subnet mask, not these masks. */ +#define IP_CLASSA(a) ((((u32_t)(a)) & 0x80000000UL) == 0) +#define IP_CLASSA_NET 0xff000000 +#define IP_CLASSA_NSHIFT 24 +#define IP_CLASSA_HOST (0xffffffff & ~IP_CLASSA_NET) +#define IP_CLASSA_MAX 128 + +#define IP_CLASSB(a) ((((u32_t)(a)) & 0xc0000000UL) == 0x80000000UL) +#define IP_CLASSB_NET 0xffff0000 +#define IP_CLASSB_NSHIFT 16 +#define IP_CLASSB_HOST (0xffffffff & ~IP_CLASSB_NET) +#define IP_CLASSB_MAX 65536 + +#define IP_CLASSC(a) ((((u32_t)(a)) & 0xe0000000UL) == 0xc0000000UL) +#define IP_CLASSC_NET 0xffffff00 +#define IP_CLASSC_NSHIFT 8 +#define IP_CLASSC_HOST (0xffffffff & ~IP_CLASSC_NET) + +#define IP_CLASSD(a) (((u32_t)(a) & 0xf0000000UL) == 0xe0000000UL) +#define IP_CLASSD_NET 0xf0000000 /* These ones aren't really */ +#define IP_CLASSD_NSHIFT 28 /* net and host fields, but */ +#define IP_CLASSD_HOST 0x0fffffff /* routing needn't know. */ +#define IP_MULTICAST(a) IP_CLASSD(a) + +#define IP_EXPERIMENTAL(a) (((u32_t)(a) & 0xf0000000UL) == 0xf0000000UL) +#define IP_BADCLASS(a) (((u32_t)(a) & 0xf0000000UL) == 0xf0000000UL) + +#define IP_LOOPBACKNET 127 /* official! */ + + +#if BYTE_ORDER == BIG_ENDIAN +/** Set an IP address given by the four byte-parts */ +#define IP4_ADDR(ipaddr, a,b,c,d) \ + (ipaddr)->addr = ((u32_t)((a) & 0xff) << 24) | \ + ((u32_t)((b) & 0xff) << 16) | \ + ((u32_t)((c) & 0xff) << 8) | \ + (u32_t)((d) & 0xff) +#else +/** Set an IP address given by the four byte-parts. + Little-endian version that prevents the use of htonl. */ +#define IP4_ADDR(ipaddr, a,b,c,d) \ + (ipaddr)->addr = ((u32_t)((d) & 0xff) << 24) | \ + ((u32_t)((c) & 0xff) << 16) | \ + ((u32_t)((b) & 0xff) << 8) | \ + (u32_t)((a) & 0xff) +#endif + +/** MEMCPY-like copying of IP addresses where addresses are known to be + * 16-bit-aligned if the port is correctly configured (so a port could define + * this to copying 2 u16_t's) - no NULL-pointer-checking needed. */ +#ifndef IPADDR2_COPY +#define IPADDR2_COPY(dest, src) SMEMCPY(dest, src, sizeof(ip4_addr_t)) +#endif + +/** Copy IP address - faster than ip4_addr_set: no NULL check */ +#define ip4_addr_copy(dest, src) ((dest).addr = (src).addr) +/** Safely copy one IP address to another (src may be NULL) */ +#define ip4_addr_set(dest, src) ((dest)->addr = \ + ((src) == NULL ? 0 : \ + (src)->addr)) +/** Set complete address to zero */ +#define ip4_addr_set_zero(ipaddr) ((ipaddr)->addr = 0) +/** Set address to IPADDR_ANY (no need for htonl()) */ +#define ip4_addr_set_any(ipaddr) ((ipaddr)->addr = IPADDR_ANY) +/** Set address to loopback address */ +#define ip4_addr_set_loopback(ipaddr) ((ipaddr)->addr = PP_HTONL(IPADDR_LOOPBACK)) +/** Check if an address is in the loopback region */ +#define ip4_addr_isloopback(ipaddr) (((ipaddr)->addr & PP_HTONL(IP_CLASSA_NET)) == PP_HTONL(((u32_t)IP_LOOPBACKNET) << 24)) +/** Safely copy one IP address to another and change byte order + * from host- to network-order. */ +#define ip4_addr_set_hton(dest, src) ((dest)->addr = \ + ((src) == NULL ? 0:\ + htonl((src)->addr))) +/** IPv4 only: set the IP address given as an u32_t */ +#define ip4_addr_set_u32(dest_ipaddr, src_u32) ((dest_ipaddr)->addr = (src_u32)) +/** IPv4 only: get the IP address as an u32_t */ +#define ip4_addr_get_u32(src_ipaddr) ((src_ipaddr)->addr) + +/** Get the network address by combining host address with netmask */ +#define ip4_addr_get_network(target, host, netmask) do { ((target)->addr = ((host)->addr) & ((netmask)->addr)); } while(0) + +/** + * Determine if two address are on the same network. + * + * @arg addr1 IP address 1 + * @arg addr2 IP address 2 + * @arg mask network identifier mask + * @return !0 if the network identifiers of both address match + */ +#define ip4_addr_netcmp(addr1, addr2, mask) (((addr1)->addr & \ + (mask)->addr) == \ + ((addr2)->addr & \ + (mask)->addr)) +#define ip4_addr_cmp(addr1, addr2) ((addr1)->addr == (addr2)->addr) + +#define ip4_addr_isany_val(addr1) ((addr1).addr == IPADDR_ANY) +#define ip4_addr_isany(addr1) ((addr1) == NULL || ip4_addr_isany_val(*(addr1))) + +#define ip4_addr_isbroadcast(addr1, netif) ip4_addr_isbroadcast_u32((addr1)->addr, netif) +u8_t ip4_addr_isbroadcast_u32(u32_t addr, const struct netif *netif); + +#define ip_addr_netmask_valid(netmask) ip4_addr_netmask_valid((netmask)->addr) +u8_t ip4_addr_netmask_valid(u32_t netmask); + +#define ip4_addr_ismulticast(addr1) (((addr1)->addr & PP_HTONL(0xf0000000UL)) == PP_HTONL(0xe0000000UL)) + +#define ip4_addr_islinklocal(addr1) (((addr1)->addr & PP_HTONL(0xffff0000UL)) == PP_HTONL(0xa9fe0000UL)) + +#define ip4_addr_debug_print_parts(debug, a, b, c, d) \ + LWIP_DEBUGF(debug, ("%" U16_F ".%" U16_F ".%" U16_F ".%" U16_F, a, b, c, d)) +#define ip4_addr_debug_print(debug, ipaddr) \ + ip4_addr_debug_print_parts(debug, \ + (ipaddr) != NULL ? ip4_addr1_16(ipaddr) : 0, \ + (ipaddr) != NULL ? ip4_addr2_16(ipaddr) : 0, \ + (ipaddr) != NULL ? ip4_addr3_16(ipaddr) : 0, \ + (ipaddr) != NULL ? ip4_addr4_16(ipaddr) : 0) +#define ip4_addr_debug_print_val(debug, ipaddr) \ + ip4_addr_debug_print_parts(debug, \ + ip4_addr1_16(&(ipaddr)), \ + ip4_addr2_16(&(ipaddr)), \ + ip4_addr3_16(&(ipaddr)), \ + ip4_addr4_16(&(ipaddr))) + +/* Get one byte from the 4-byte address */ +#define ip4_addr1(ipaddr) (((const u8_t*)(&(ipaddr)->addr))[0]) +#define ip4_addr2(ipaddr) (((const u8_t*)(&(ipaddr)->addr))[1]) +#define ip4_addr3(ipaddr) (((const u8_t*)(&(ipaddr)->addr))[2]) +#define ip4_addr4(ipaddr) (((const u8_t*)(&(ipaddr)->addr))[3]) +/* These are cast to u16_t, with the intent that they are often arguments + * to printf using the U16_F format from cc.h. */ +#define ip4_addr1_16(ipaddr) ((u16_t)ip4_addr1(ipaddr)) +#define ip4_addr2_16(ipaddr) ((u16_t)ip4_addr2(ipaddr)) +#define ip4_addr3_16(ipaddr) ((u16_t)ip4_addr3(ipaddr)) +#define ip4_addr4_16(ipaddr) ((u16_t)ip4_addr4(ipaddr)) + +#define IP4ADDR_STRLEN_MAX 16 +#define IPADDR_STRLEN_MAX IP4ADDR_STRLEN_MAX + +/** For backwards compatibility */ +#define ip_ntoa(ipaddr) ipaddr_ntoa(ipaddr) + +u32_t ipaddr_addr(const char *cp); +int ip4addr_aton(const char *cp, ip4_addr_t *addr); +/** returns ptr to static buffer; not reentrant! */ +char *ip4addr_ntoa(const ip4_addr_t *addr); +char *ip4addr_ntoa_r(const ip4_addr_t *addr, char *buf, int buflen); + +#ifdef __cplusplus +} +#endif + +#endif /* LWIP_IPV4 */ + +#endif /* LWIP_HDR_IP_ADDR_H */ diff --git a/components/lwip/include/lwip/lwip/ip6.h b/components/lwip/include/lwip/lwip/ip6.h new file mode 100755 index 0000000000..f1ffb6b733 --- /dev/null +++ b/components/lwip/include/lwip/lwip/ip6.h @@ -0,0 +1,197 @@ +/** + * @file + * + * IPv6 layer. + */ + +/* + * Copyright (c) 2010 Inico Technologies Ltd. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Ivan Delamer + * + * + * Please coordinate changes and requests with Ivan Delamer + * + */ +#ifndef LWIP_HDR_IP6_H +#define LWIP_HDR_IP6_H + +#include "lwip/opt.h" + +#if LWIP_IPV6 /* don't build if not configured for use in lwipopts.h */ + +#include "lwip/ip6_addr.h" +#include "lwip/def.h" +#include "lwip/pbuf.h" +#include "lwip/netif.h" + +#include "lwip/err.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#define IP6_HLEN 40 + +#define IP6_NEXTH_HOPBYHOP 0 +#define IP6_NEXTH_TCP 6 +#define IP6_NEXTH_UDP 17 +#define IP6_NEXTH_ENCAPS 41 +#define IP6_NEXTH_ROUTING 43 +#define IP6_NEXTH_FRAGMENT 44 +#define IP6_NEXTH_ICMP6 58 +#define IP6_NEXTH_NONE 59 +#define IP6_NEXTH_DESTOPTS 60 +#define IP6_NEXTH_UDPLITE 136 + + +/* The IPv6 header. */ +#ifdef PACK_STRUCT_USE_INCLUDES +# include "arch/bpstruct.h" +#endif +PACK_STRUCT_BEGIN +struct ip6_hdr { + /* version / traffic class / flow label */ + PACK_STRUCT_FIELD(u32_t _v_tc_fl); + /* payload length */ + PACK_STRUCT_FIELD(u16_t _plen); + /* next header */ + PACK_STRUCT_FLD_8(u8_t _nexth); + /* hop limit */ + PACK_STRUCT_FLD_8(u8_t _hoplim); + /* source and destination IP addresses */ + PACK_STRUCT_FLD_S(ip6_addr_p_t src); + PACK_STRUCT_FLD_S(ip6_addr_p_t dest); +} PACK_STRUCT_STRUCT; +PACK_STRUCT_END +#ifdef PACK_STRUCT_USE_INCLUDES +# include "arch/epstruct.h" +#endif + +/* Hop-by-hop router alert option. */ +#define IP6_HBH_HLEN 8 +#define IP6_PAD1_OPTION 0 +#define IP6_PADN_ALERT_OPTION 1 +#define IP6_ROUTER_ALERT_OPTION 5 +#define IP6_ROUTER_ALERT_VALUE_MLD 0 +#ifdef PACK_STRUCT_USE_INCLUDES +# include "arch/bpstruct.h" +#endif +PACK_STRUCT_BEGIN +struct ip6_hbh_hdr { + /* next header */ + PACK_STRUCT_FLD_8(u8_t _nexth); + /* header length */ + PACK_STRUCT_FLD_8(u8_t _hlen); + /* router alert option type */ + PACK_STRUCT_FLD_8(u8_t _ra_opt_type); + /* router alert option data len */ + PACK_STRUCT_FLD_8(u8_t _ra_opt_dlen); + /* router alert option data */ + PACK_STRUCT_FIELD(u16_t _ra_opt_data); + /* PadN option type */ + PACK_STRUCT_FLD_8(u8_t _padn_opt_type); + /* PadN option data len */ + PACK_STRUCT_FLD_8(u8_t _padn_opt_dlen); +} PACK_STRUCT_STRUCT; +PACK_STRUCT_END +#ifdef PACK_STRUCT_USE_INCLUDES +# include "arch/epstruct.h" +#endif + +/* Fragment header. */ +#define IP6_FRAG_HLEN 8 +#define IP6_FRAG_OFFSET_MASK 0xfff8 +#define IP6_FRAG_MORE_FLAG 0x0001 +#ifdef PACK_STRUCT_USE_INCLUDES +# include "arch/bpstruct.h" +#endif +PACK_STRUCT_BEGIN +struct ip6_frag_hdr { + /* next header */ + PACK_STRUCT_FLD_8(u8_t _nexth); + /* reserved */ + PACK_STRUCT_FLD_8(u8_t reserved); + /* fragment offset */ + PACK_STRUCT_FIELD(u16_t _fragment_offset); + /* fragmented packet identification */ + PACK_STRUCT_FIELD(u32_t _identification); +} PACK_STRUCT_STRUCT; +PACK_STRUCT_END +#ifdef PACK_STRUCT_USE_INCLUDES +# include "arch/epstruct.h" +#endif + +#define IP6H_V(hdr) ((ntohl((hdr)->_v_tc_fl) >> 28) & 0x0f) +#define IP6H_TC(hdr) ((ntohl((hdr)->_v_tc_fl) >> 20) & 0xff) +#define IP6H_FL(hdr) (ntohl((hdr)->_v_tc_fl) & 0x000fffff) +#define IP6H_PLEN(hdr) (ntohs((hdr)->_plen)) +#define IP6H_NEXTH(hdr) ((hdr)->_nexth) +#define IP6H_NEXTH_P(hdr) ((u8_t *)(hdr) + 6) +#define IP6H_HOPLIM(hdr) ((hdr)->_hoplim) + +#define IP6H_VTCFL_SET(hdr, v, tc, fl) (hdr)->_v_tc_fl = (htonl((((u32_t)(v)) << 28) | (((u32_t)(tc)) << 20) | (fl))) +#define IP6H_PLEN_SET(hdr, plen) (hdr)->_plen = htons(plen) +#define IP6H_NEXTH_SET(hdr, nexth) (hdr)->_nexth = (nexth) +#define IP6H_HOPLIM_SET(hdr, hl) (hdr)->_hoplim = (u8_t)(hl) + + +struct netif *ip6_route(const ip6_addr_t *src, const ip6_addr_t *dest); +const ip_addr_t *ip6_select_source_address(struct netif *netif, const ip6_addr_t * dest); +err_t ip6_input(struct pbuf *p, struct netif *inp); +err_t ip6_output(struct pbuf *p, const ip6_addr_t *src, const ip6_addr_t *dest, + u8_t hl, u8_t tc, u8_t nexth); +err_t ip6_output_if(struct pbuf *p, const ip6_addr_t *src, const ip6_addr_t *dest, + u8_t hl, u8_t tc, u8_t nexth, struct netif *netif); +err_t ip6_output_if_src(struct pbuf *p, const ip6_addr_t *src, const ip6_addr_t *dest, + u8_t hl, u8_t tc, u8_t nexth, struct netif *netif); +#if LWIP_NETIF_HWADDRHINT +err_t ip6_output_hinted(struct pbuf *p, const ip6_addr_t *src, const ip6_addr_t *dest, + u8_t hl, u8_t tc, u8_t nexth, u8_t *addr_hint); +#endif /* LWIP_NETIF_HWADDRHINT */ +#if LWIP_IPV6_MLD +err_t ip6_options_add_hbh_ra(struct pbuf * p, u8_t nexth, u8_t value); +#endif /* LWIP_IPV6_MLD */ + +#define ip6_netif_get_local_ip(netif, dest) (((netif) != NULL) ? \ + ip6_select_source_address(netif, dest) : NULL) + +#if IP6_DEBUG +void ip6_debug_print(struct pbuf *p); +#else +#define ip6_debug_print(p) +#endif /* IP6_DEBUG */ + + +#ifdef __cplusplus +} +#endif + +#endif /* LWIP_IPV6 */ + +#endif /* LWIP_HDR_IP6_H */ diff --git a/components/lwip/include/lwip/lwip/ip6_addr.h b/components/lwip/include/lwip/lwip/ip6_addr.h new file mode 100755 index 0000000000..a75d894851 --- /dev/null +++ b/components/lwip/include/lwip/lwip/ip6_addr.h @@ -0,0 +1,301 @@ +/** + * @file + * + * IPv6 addresses. + */ + +/* + * Copyright (c) 2010 Inico Technologies Ltd. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Ivan Delamer + * + * Structs and macros for handling IPv6 addresses. + * + * Please coordinate changes and requests with Ivan Delamer + * + */ +#ifndef LWIP_HDR_IP6_ADDR_H +#define LWIP_HDR_IP6_ADDR_H + +#include "lwip/opt.h" + +#if LWIP_IPV6 /* don't build if not configured for use in lwipopts.h */ + + +#ifdef __cplusplus +extern "C" { +#endif + + +/* This is the aligned version of ip6_addr_t, + used as local variable, on the stack, etc. */ +struct ip6_addr { + u32_t addr[4]; +}; + +/* This is the packed version of ip6_addr_t, + used in network headers that are itself packed */ +#ifdef PACK_STRUCT_USE_INCLUDES +# include "arch/bpstruct.h" +#endif +PACK_STRUCT_BEGIN +struct ip6_addr_packed { + PACK_STRUCT_FIELD(u32_t addr[4]); +} PACK_STRUCT_STRUCT; +PACK_STRUCT_END +#ifdef PACK_STRUCT_USE_INCLUDES +# include "arch/epstruct.h" +#endif + +typedef struct ip6_addr ip6_addr_t; +typedef struct ip6_addr_packed ip6_addr_p_t; + + +#if BYTE_ORDER == BIG_ENDIAN +/** Set an IPv6 partial address given by byte-parts. */ +#define IP6_ADDR_PART(ip6addr, index, a,b,c,d) \ + (ip6addr)->addr[index] = ((u32_t)((a) & 0xff) << 24) | \ + ((u32_t)((b) & 0xff) << 16) | \ + ((u32_t)((c) & 0xff) << 8) | \ + (u32_t)((d) & 0xff) +#else +/** Set an IPv6 partial address given by byte-parts. +Little-endian version, stored in network order (no htonl). */ +#define IP6_ADDR_PART(ip6addr, index, a,b,c,d) \ + (ip6addr)->addr[index] = ((u32_t)((d) & 0xff) << 24) | \ + ((u32_t)((c) & 0xff) << 16) | \ + ((u32_t)((b) & 0xff) << 8) | \ + (u32_t)((a) & 0xff) +#endif + +/** Set a full IPv6 address by passing the 4 u32_t indices in network byte order + (use PP_HTONL() for constants) */ +#define IP6_ADDR(ip6addr, idx0, idx1, idx2, idx3) do { \ + (ip6addr)->addr[0] = idx0; \ + (ip6addr)->addr[1] = idx1; \ + (ip6addr)->addr[2] = idx2; \ + (ip6addr)->addr[3] = idx3; } while(0) + +/** Access address in 16-bit block */ +#define IP6_ADDR_BLOCK1(ip6addr) ((u16_t)(htonl((ip6addr)->addr[0]) >> 16) & 0xffff) +#define IP6_ADDR_BLOCK2(ip6addr) ((u16_t)(htonl((ip6addr)->addr[0])) & 0xffff) +#define IP6_ADDR_BLOCK3(ip6addr) ((u16_t)(htonl((ip6addr)->addr[1]) >> 16) & 0xffff) +#define IP6_ADDR_BLOCK4(ip6addr) ((u16_t)(htonl((ip6addr)->addr[1])) & 0xffff) +#define IP6_ADDR_BLOCK5(ip6addr) ((u16_t)(htonl((ip6addr)->addr[2]) >> 16) & 0xffff) +#define IP6_ADDR_BLOCK6(ip6addr) ((u16_t)(htonl((ip6addr)->addr[2])) & 0xffff) +#define IP6_ADDR_BLOCK7(ip6addr) ((u16_t)(htonl((ip6addr)->addr[3]) >> 16) & 0xffff) +#define IP6_ADDR_BLOCK8(ip6addr) ((u16_t)(htonl((ip6addr)->addr[3])) & 0xffff) + +/** Copy IPv6 address - faster than ip6_addr_set: no NULL check */ +#define ip6_addr_copy(dest, src) do{(dest).addr[0] = (src).addr[0]; \ + (dest).addr[1] = (src).addr[1]; \ + (dest).addr[2] = (src).addr[2]; \ + (dest).addr[3] = (src).addr[3];}while(0) +/** Safely copy one IPv6 address to another (src may be NULL) */ +#define ip6_addr_set(dest, src) do{(dest)->addr[0] = (src) == NULL ? 0 : (src)->addr[0]; \ + (dest)->addr[1] = (src) == NULL ? 0 : (src)->addr[1]; \ + (dest)->addr[2] = (src) == NULL ? 0 : (src)->addr[2]; \ + (dest)->addr[3] = (src) == NULL ? 0 : (src)->addr[3];}while(0) + +/** Set complete address to zero */ +#define ip6_addr_set_zero(ip6addr) do{(ip6addr)->addr[0] = 0; \ + (ip6addr)->addr[1] = 0; \ + (ip6addr)->addr[2] = 0; \ + (ip6addr)->addr[3] = 0;}while(0) + +/** Set address to ipv6 'any' (no need for htonl()) */ +#define ip6_addr_set_any(ip6addr) ip6_addr_set_zero(ip6addr) +/** Set address to ipv6 loopback address */ +#define ip6_addr_set_loopback(ip6addr) do{(ip6addr)->addr[0] = 0; \ + (ip6addr)->addr[1] = 0; \ + (ip6addr)->addr[2] = 0; \ + (ip6addr)->addr[3] = PP_HTONL(0x00000001UL);}while(0) +/** Safely copy one IPv6 address to another and change byte order + * from host- to network-order. */ +#define ip6_addr_set_hton(dest, src) do{(dest)->addr[0] = (src) == NULL ? 0 : htonl((src)->addr[0]); \ + (dest)->addr[1] = (src) == NULL ? 0 : htonl((src)->addr[1]); \ + (dest)->addr[2] = (src) == NULL ? 0 : htonl((src)->addr[2]); \ + (dest)->addr[3] = (src) == NULL ? 0 : htonl((src)->addr[3]);}while(0) + + +/** + * Determine if two IPv6 address are on the same network. + * + * @arg addr1 IPv6 address 1 + * @arg addr2 IPv6 address 2 + * @return !0 if the network identifiers of both address match + */ +#define ip6_addr_netcmp(addr1, addr2) (((addr1)->addr[0] == (addr2)->addr[0]) && \ + ((addr1)->addr[1] == (addr2)->addr[1])) + +#define ip6_addr_cmp(addr1, addr2) (((addr1)->addr[0] == (addr2)->addr[0]) && \ + ((addr1)->addr[1] == (addr2)->addr[1]) && \ + ((addr1)->addr[2] == (addr2)->addr[2]) && \ + ((addr1)->addr[3] == (addr2)->addr[3])) + +#define ip6_get_subnet_id(ip6addr) (htonl((ip6addr)->addr[2]) & 0x0000ffffUL) + +#define ip6_addr_isany_val(ip6addr) (((ip6addr).addr[0] == 0) && \ + ((ip6addr).addr[1] == 0) && \ + ((ip6addr).addr[2] == 0) && \ + ((ip6addr).addr[3] == 0)) +#define ip6_addr_isany(ip6addr) (((ip6addr) == NULL) || ip6_addr_isany_val(*(ip6addr))) + +#define ip6_addr_isloopback(ip6addr) (((ip6addr)->addr[0] == 0UL) && \ + ((ip6addr)->addr[1] == 0UL) && \ + ((ip6addr)->addr[2] == 0UL) && \ + ((ip6addr)->addr[3] == PP_HTONL(0x00000001UL))) + +#define ip6_addr_isglobal(ip6addr) (((ip6addr)->addr[0] & PP_HTONL(0xe0000000UL)) == PP_HTONL(0x20000000UL)) + +#define ip6_addr_islinklocal(ip6addr) (((ip6addr)->addr[0] & PP_HTONL(0xffc00000UL)) == PP_HTONL(0xfe800000UL)) + +#define ip6_addr_issitelocal(ip6addr) (((ip6addr)->addr[0] & PP_HTONL(0xffc00000UL)) == PP_HTONL(0xfec00000UL)) + +#define ip6_addr_isuniquelocal(ip6addr) (((ip6addr)->addr[0] & PP_HTONL(0xfe000000UL)) == PP_HTONL(0xfc000000UL)) + +#define ip6_addr_ismulticast(ip6addr) (((ip6addr)->addr[0] & PP_HTONL(0xff000000UL)) == PP_HTONL(0xff000000UL)) +#define ip6_addr_multicast_transient_flag(ip6addr) ((ip6addr)->addr[0] & PP_HTONL(0x00100000UL)) +#define ip6_addr_multicast_prefix_flag(ip6addr) ((ip6addr)->addr[0] & PP_HTONL(0x00200000UL)) +#define ip6_addr_multicast_rendezvous_flag(ip6addr) ((ip6addr)->addr[0] & PP_HTONL(0x00400000UL)) +#define ip6_addr_multicast_scope(ip6addr) ((htonl((ip6addr)->addr[0]) >> 16) & 0xf) +#define IP6_MULTICAST_SCOPE_RESERVED 0x0 +#define IP6_MULTICAST_SCOPE_RESERVED0 0x0 +#define IP6_MULTICAST_SCOPE_INTERFACE_LOCAL 0x1 +#define IP6_MULTICAST_SCOPE_LINK_LOCAL 0x2 +#define IP6_MULTICAST_SCOPE_RESERVED3 0x3 +#define IP6_MULTICAST_SCOPE_ADMIN_LOCAL 0x4 +#define IP6_MULTICAST_SCOPE_SITE_LOCAL 0x5 +#define IP6_MULTICAST_SCOPE_ORGANIZATION_LOCAL 0x8 +#define IP6_MULTICAST_SCOPE_GLOBAL 0xe +#define IP6_MULTICAST_SCOPE_RESERVEDF 0xf +#define ip6_addr_ismulticast_iflocal(ip6addr) (((ip6addr)->addr[0] & PP_HTONL(0xff8f0000UL)) == PP_HTONL(0xff010000UL)) +#define ip6_addr_ismulticast_linklocal(ip6addr) (((ip6addr)->addr[0] & PP_HTONL(0xff8f0000UL)) == PP_HTONL(0xff020000UL)) +#define ip6_addr_ismulticast_adminlocal(ip6addr) (((ip6addr)->addr[0] & PP_HTONL(0xff8f0000UL)) == PP_HTONL(0xff040000UL)) +#define ip6_addr_ismulticast_sitelocal(ip6addr) (((ip6addr)->addr[0] & PP_HTONL(0xff8f0000UL)) == PP_HTONL(0xff050000UL)) +#define ip6_addr_ismulticast_orglocal(ip6addr) (((ip6addr)->addr[0] & PP_HTONL(0xff8f0000UL)) == PP_HTONL(0xff080000UL)) +#define ip6_addr_ismulticast_global(ip6addr) (((ip6addr)->addr[0] & PP_HTONL(0xff8f0000UL)) == PP_HTONL(0xff0e0000UL)) + +/* TODO define get/set for well-know multicast addresses, e.g. ff02::1 */ +#define ip6_addr_isallnodes_iflocal(ip6addr) (((ip6addr)->addr[0] == PP_HTONL(0xff010000UL)) && \ + ((ip6addr)->addr[1] == 0UL) && \ + ((ip6addr)->addr[2] == 0UL) && \ + ((ip6addr)->addr[3] == PP_HTONL(0x00000001UL))) + +#define ip6_addr_isallnodes_linklocal(ip6addr) (((ip6addr)->addr[0] == PP_HTONL(0xff020000UL)) && \ + ((ip6addr)->addr[1] == 0UL) && \ + ((ip6addr)->addr[2] == 0UL) && \ + ((ip6addr)->addr[3] == PP_HTONL(0x00000001UL))) +#define ip6_addr_set_allnodes_linklocal(ip6addr) do{(ip6addr)->addr[0] = PP_HTONL(0xff020000UL); \ + (ip6addr)->addr[1] = 0; \ + (ip6addr)->addr[2] = 0; \ + (ip6addr)->addr[3] = PP_HTONL(0x00000001UL);}while(0) + +#define ip6_addr_isallrouters_linklocal(ip6addr) (((ip6addr)->addr[0] == PP_HTONL(0xff020000UL)) && \ + ((ip6addr)->addr[1] == 0UL) && \ + ((ip6addr)->addr[2] == 0UL) && \ + ((ip6addr)->addr[3] == PP_HTONL(0x00000002UL))) +#define ip6_addr_set_allrouters_linklocal(ip6addr) do{(ip6addr)->addr[0] = PP_HTONL(0xff020000UL); \ + (ip6addr)->addr[1] = 0; \ + (ip6addr)->addr[2] = 0; \ + (ip6addr)->addr[3] = PP_HTONL(0x00000002UL);}while(0) + +#define ip6_addr_issolicitednode(ip6addr) ( ((ip6addr)->addr[0] == PP_HTONL(0xff020000UL)) && \ + ((ip6addr)->addr[2] == PP_HTONL(0x00000001UL)) && \ + (((ip6addr)->addr[3] & PP_HTONL(0xff000000UL)) == PP_HTONL(0xff000000UL)) ) + +#define ip6_addr_set_solicitednode(ip6addr, if_id) do{(ip6addr)->addr[0] = PP_HTONL(0xff020000UL); \ + (ip6addr)->addr[1] = 0; \ + (ip6addr)->addr[2] = PP_HTONL(0x00000001UL); \ + (ip6addr)->addr[3] = (PP_HTONL(0xff000000UL) | (if_id));}while(0) + +#define ip6_addr_cmp_solicitednode(ip6addr, sn_addr) (((ip6addr)->addr[0] == PP_HTONL(0xff020000UL)) && \ + ((ip6addr)->addr[1] == 0) && \ + ((ip6addr)->addr[2] == PP_HTONL(0x00000001UL)) && \ + ((ip6addr)->addr[3] == (PP_HTONL(0xff000000UL) | (sn_addr)->addr[3]))) + +/* IPv6 address states. */ +#define IP6_ADDR_INVALID 0x00 +#define IP6_ADDR_TENTATIVE 0x08 +#define IP6_ADDR_TENTATIVE_1 0x09 /* 1 probe sent */ +#define IP6_ADDR_TENTATIVE_2 0x0a /* 2 probes sent */ +#define IP6_ADDR_TENTATIVE_3 0x0b /* 3 probes sent */ +#define IP6_ADDR_TENTATIVE_4 0x0c /* 4 probes sent */ +#define IP6_ADDR_TENTATIVE_5 0x0d /* 5 probes sent */ +#define IP6_ADDR_TENTATIVE_6 0x0e /* 6 probes sent */ +#define IP6_ADDR_TENTATIVE_7 0x0f /* 7 probes sent */ +#define IP6_ADDR_VALID 0x10 +#define IP6_ADDR_PREFERRED 0x30 +#define IP6_ADDR_DEPRECATED 0x50 + +#define ip6_addr_isinvalid(addr_state) (addr_state == IP6_ADDR_INVALID) +#define ip6_addr_istentative(addr_state) (addr_state & IP6_ADDR_TENTATIVE) +#define ip6_addr_isvalid(addr_state) (addr_state & IP6_ADDR_VALID) /* Include valid, preferred, and deprecated. */ +#define ip6_addr_ispreferred(addr_state) (addr_state == IP6_ADDR_PREFERRED) +#define ip6_addr_isdeprecated(addr_state) (addr_state == IP6_ADDR_DEPRECATED) + +#define ip6_addr_debug_print_parts(debug, a, b, c, d, e, f, g, h) \ + LWIP_DEBUGF(debug, ("%" X16_F ":%" X16_F ":%" X16_F ":%" X16_F ":%" X16_F ":%" X16_F ":%" X16_F ":%" X16_F, \ + a, b, c, d, e, f, g, h)) +#define ip6_addr_debug_print(debug, ipaddr) \ + ip6_addr_debug_print_parts(debug, \ + (ipaddr) != NULL ? IP6_ADDR_BLOCK1(ipaddr) : 0, \ + (ipaddr) != NULL ? IP6_ADDR_BLOCK2(ipaddr) : 0, \ + (ipaddr) != NULL ? IP6_ADDR_BLOCK3(ipaddr) : 0, \ + (ipaddr) != NULL ? IP6_ADDR_BLOCK4(ipaddr) : 0, \ + (ipaddr) != NULL ? IP6_ADDR_BLOCK5(ipaddr) : 0, \ + (ipaddr) != NULL ? IP6_ADDR_BLOCK6(ipaddr) : 0, \ + (ipaddr) != NULL ? IP6_ADDR_BLOCK7(ipaddr) : 0, \ + (ipaddr) != NULL ? IP6_ADDR_BLOCK8(ipaddr) : 0) +#define ip6_addr_debug_print_val(debug, ipaddr) \ + ip6_addr_debug_print_parts(debug, \ + IP6_ADDR_BLOCK1(&(ipaddr)), \ + IP6_ADDR_BLOCK2(&(ipaddr)), \ + IP6_ADDR_BLOCK3(&(ipaddr)), \ + IP6_ADDR_BLOCK4(&(ipaddr)), \ + IP6_ADDR_BLOCK5(&(ipaddr)), \ + IP6_ADDR_BLOCK6(&(ipaddr)), \ + IP6_ADDR_BLOCK7(&(ipaddr)), \ + IP6_ADDR_BLOCK8(&(ipaddr))) + +#define IP6ADDR_STRLEN_MAX 46 + +int ip6addr_aton(const char *cp, ip6_addr_t *addr); +/** returns ptr to static buffer; not reentrant! */ +char *ip6addr_ntoa(const ip6_addr_t *addr); +char *ip6addr_ntoa_r(const ip6_addr_t *addr, char *buf, int buflen); + + + +#ifdef __cplusplus +} +#endif + +#endif /* LWIP_IPV6 */ + +#endif /* LWIP_HDR_IP6_ADDR_H */ diff --git a/components/lwip/include/lwip/lwip/ip6_frag.h b/components/lwip/include/lwip/lwip/ip6_frag.h new file mode 100755 index 0000000000..16336e5872 --- /dev/null +++ b/components/lwip/include/lwip/lwip/ip6_frag.h @@ -0,0 +1,120 @@ +/** + * @file + * + * IPv6 fragmentation and reassembly. + */ + +/* + * Copyright (c) 2010 Inico Technologies Ltd. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Ivan Delamer + * + * + * Please coordinate changes and requests with Ivan Delamer + * + */ +#ifndef LWIP_HDR_IP6_FRAG_H +#define LWIP_HDR_IP6_FRAG_H + +#include "lwip/opt.h" +#include "lwip/pbuf.h" +#include "lwip/ip6_addr.h" +#include "lwip/ip6.h" +#include "lwip/netif.h" + +#ifdef __cplusplus +extern "C" { +#endif + + +#if LWIP_IPV6 && LWIP_IPV6_REASS /* don't build if not configured for use in lwipopts.h */ + +/** IP6_FRAG_COPYHEADER==1: for platforms where sizeof(void*) > 4, this needs to + * be enabled (to not overwrite part of the data). When enabled, the IPv6 header + * is copied instead of referencing it, which gives more room for struct ip6_reass_helper */ +#ifndef IPV6_FRAG_COPYHEADER +#define IPV6_FRAG_COPYHEADER 0 +#endif + +/* The IPv6 reassembly timer interval in milliseconds. */ +#define IP6_REASS_TMR_INTERVAL 1000 + +/* Copy the complete header of the first fragment to struct ip6_reassdata + or just point to its original location in the first pbuf? */ +#if IPV6_FRAG_COPYHEADER +#define IPV6_FRAG_HDRPTR +#define IPV6_FRAG_HDRREF(hdr) (&(hdr)) +#else /* IPV6_FRAG_COPYHEADER */ +#define IPV6_FRAG_HDRPTR * +#define IPV6_FRAG_HDRREF(hdr) (hdr) +#endif /* IPV6_FRAG_COPYHEADER */ + +/* IPv6 reassembly helper struct. + * This is exported because memp needs to know the size. + */ +struct ip6_reassdata { + struct ip6_reassdata *next; + struct pbuf *p; + struct ip6_hdr IPV6_FRAG_HDRPTR iphdr; + u32_t identification; + u16_t datagram_len; + u8_t nexth; + u8_t timer; +}; + +#define ip6_reass_init() /* Compatibility define */ +void ip6_reass_tmr(void); +struct pbuf * ip6_reass(struct pbuf *p); + +#endif /* LWIP_IPV6 && LWIP_IPV6_REASS */ + +#if LWIP_IPV6 && LWIP_IPV6_FRAG /* don't build if not configured for use in lwipopts.h */ + +/** A custom pbuf that holds a reference to another pbuf, which is freed + * when this custom pbuf is freed. This is used to create a custom PBUF_REF + * that points into the original pbuf. */ +#ifndef LWIP_PBUF_CUSTOM_REF_DEFINED +#define LWIP_PBUF_CUSTOM_REF_DEFINED +struct pbuf_custom_ref { + /** 'base class' */ + struct pbuf_custom pc; + /** pointer to the original pbuf that is referenced */ + struct pbuf *original; +}; +#endif /* LWIP_PBUF_CUSTOM_REF_DEFINED */ + +err_t ip6_frag(struct pbuf *p, struct netif *netif, const ip6_addr_t *dest); + +#endif /* LWIP_IPV6 && LWIP_IPV6_FRAG */ + + +#ifdef __cplusplus +} +#endif + +#endif /* LWIP_HDR_IP6_FRAG_H */ diff --git a/components/lwip/include/lwip/lwip/ip_addr.h b/components/lwip/include/lwip/lwip/ip_addr.h new file mode 100755 index 0000000000..1e1ffb3f1e --- /dev/null +++ b/components/lwip/include/lwip/lwip/ip_addr.h @@ -0,0 +1,291 @@ +/* + * Copyright (c) 2001-2004 Swedish Institute of Computer Science. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + * + */ +#ifndef LWIP_HDR_IP_ADDR_H__ +#define LWIP_HDR_IP_ADDR_H__ + +#include "lwip/opt.h" +#include "lwip/def.h" + +#include "lwip/ip4_addr.h" +#include "lwip/ip6_addr.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** These are the values for ip_addr_t.type */ +#define IPADDR_TYPE_V4 0U +#define IPADDR_TYPE_V6 6U +#define IPADDR_TYPE_ANY 46U + +#if LWIP_IPV4 && LWIP_IPV6 +/** A union struct for both IP version's addresses. + * ATTENTION: watch out for its size when adding IPv6 address scope! + */ +typedef struct _ip_addr { + union { + ip6_addr_t ip6; + ip4_addr_t ip4; + } u_addr; + u8_t type; +} ip_addr_t; + +extern const ip_addr_t ip_addr_any_type; + +#define IPADDR4_INIT(u32val) { { { { u32val, 0ul, 0ul, 0ul } } }, IPADDR_TYPE_V4 } +#define IPADDR6_INIT(a, b, c, d) { { { { a, b, c, d } } }, IPADDR_TYPE_V6 } + +#define IP_IS_ANY_TYPE_VAL(ipaddr) (IP_GET_TYPE(&ipaddr) == IPADDR_TYPE_ANY) +#define IPADDR_ANY_TYPE_INIT { { { { 0ul, 0ul, 0ul, 0ul } } }, IPADDR_TYPE_ANY } + +#define IP_IS_V6_VAL(ipaddr) (IP_GET_TYPE(&ipaddr) == IPADDR_TYPE_V6) +#define IP_IS_V6(ipaddr) (((ipaddr) != NULL) && IP_IS_V6_VAL(*(ipaddr))) +#define IP_SET_TYPE_VAL(ipaddr, iptype) do { (ipaddr).type = (iptype); }while(0) +#define IP_SET_TYPE(ipaddr, iptype) do { if((ipaddr) != NULL) { IP_SET_TYPE_VAL(*(ipaddr), iptype); }}while(0) +#define IP_GET_TYPE(ipaddr) ((ipaddr)->type) + +#define IP_ADDR_PCB_VERSION_MATCH_EXACT(pcb, ipaddr) (IP_GET_TYPE(&pcb->local_ip) == IP_GET_TYPE(ipaddr)) +#define IP_ADDR_PCB_VERSION_MATCH(pcb, ipaddr) (IP_IS_ANY_TYPE_VAL(pcb->local_ip) || IP_ADDR_PCB_VERSION_MATCH_EXACT(pcb, ipaddr)) + +/* Convert generic ip address to specific protocol version */ +#define ip_2_ip6(ipaddr) (&((ipaddr)->u_addr.ip6)) +#define ip_2_ip4(ipaddr) (&((ipaddr)->u_addr.ip4)) + +#define IP_ADDR4(ipaddr,a,b,c,d) do { IP4_ADDR(ip_2_ip4(ipaddr),a,b,c,d); \ + IP_SET_TYPE_VAL(*(ipaddr), IPADDR_TYPE_V4); } while(0) +#define IP_ADDR6(ipaddr,i0,i1,i2,i3) do { IP6_ADDR(ip_2_ip6(ipaddr),i0,i1,i2,i3); \ + IP_SET_TYPE_VAL(*(ipaddr), IPADDR_TYPE_V6); } while(0) + +#define ip_addr_copy(dest, src) do{ IP_SET_TYPE_VAL(dest, IP_GET_TYPE(&src)); if(IP_IS_V6_VAL(src)){ \ + ip6_addr_copy(*ip_2_ip6(&(dest)), *ip_2_ip6(&(src))); }else{ \ + ip4_addr_copy(*ip_2_ip4(&(dest)), *ip_2_ip4(&(src))); }}while(0) +#define ip_addr_copy_from_ip6(dest, src) do{ \ + ip6_addr_copy(*ip_2_ip6(&(dest)), src); IP_SET_TYPE_VAL(dest, IPADDR_TYPE_V6); }while(0) +#define ip_addr_copy_from_ip4(dest, src) do{ \ + ip4_addr_copy(*ip_2_ip4(&(dest)), src); IP_SET_TYPE_VAL(dest, IPADDR_TYPE_V4); }while(0) +#define ip_addr_set_ip4_u32(ipaddr, val) do{if(ipaddr){ip4_addr_set_u32(ip_2_ip4(ipaddr), val); \ + IP_SET_TYPE(ipaddr, IPADDR_TYPE_V4); }}while(0) +#define ip_addr_get_ip4_u32(ipaddr) (((ipaddr) && !IP_IS_V6(ipaddr)) ? \ + ip4_addr_get_u32(ip_2_ip4(ipaddr)) : 0) + +#define ip_addr_set(dest, src) do{ IP_SET_TYPE(dest, IP_GET_TYPE(src)); if(IP_IS_V6(src)){ \ + ip6_addr_set(ip_2_ip6(dest), ip_2_ip6(src)); }else{ \ + ip4_addr_set(ip_2_ip4(dest), ip_2_ip4(src)); }}while(0) + +#define ip_addr_set_ipaddr(dest, src) ip_addr_set(dest, src) +#define ip_addr_set_zero(ipaddr) do{ \ + ip6_addr_set_zero(ip_2_ip6(ipaddr)); IP_SET_TYPE(ipaddr, 0); }while(0) +#define ip_addr_set_zero_ip4(ipaddr) do{ \ + ip6_addr_set_zero(ip_2_ip6(ipaddr)); IP_SET_TYPE(ipaddr, IPADDR_TYPE_V4); }while(0) +#define ip_addr_set_zero_ip6(ipaddr) do{ \ + ip6_addr_set_zero(ip_2_ip6(ipaddr)); IP_SET_TYPE(ipaddr, IPADDR_TYPE_V6); }while(0) +#define ip_addr_set_any(is_ipv6, ipaddr) do{if(is_ipv6){ \ + ip6_addr_set_any(ip_2_ip6(ipaddr)); IP_SET_TYPE(ipaddr, IPADDR_TYPE_V6); }else{ \ + ip4_addr_set_any(ip_2_ip4(ipaddr)); IP_SET_TYPE(ipaddr, IPADDR_TYPE_V4); }}while(0) +#define ip_addr_set_loopback(is_ipv6, ipaddr) do{if(is_ipv6){ \ + ip6_addr_set_loopback(ip_2_ip6(ipaddr)); IP_SET_TYPE(ipaddr, IPADDR_TYPE_V6); }else{ \ + ip4_addr_set_loopback(ip_2_ip4(ipaddr)); IP_SET_TYPE(ipaddr, IPADDR_TYPE_V4); }}while(0) +#define ip_addr_set_hton(dest, src) do{if(IP_IS_V6(src)){ \ + ip6_addr_set_hton(ip_2_ip6(ipaddr), (src)); IP_SET_TYPE(dest, IPADDR_TYPE_V6); }else{ \ + ip4_addr_set_hton(ip_2_ip4(ipaddr), (src)); IP_SET_TYPE(dest, IPADDR_TYPE_V4); }}while(0) +#define ip_addr_get_network(target, host, netmask) do{if(IP_IS_V6(host)){ \ + ip4_addr_set_zero(ip_2_ip4(target)); IP_SET_TYPE(target, IPADDR_TYPE_V6); } else { \ + ip4_addr_get_network(ip_2_ip4(target), ip_2_ip4(host), ip_2_ip4(netmask)); IP_SET_TYPE(target, IPADDR_TYPE_V4); }}while(0) +#define ip_addr_netcmp(addr1, addr2, mask) ((IP_IS_V6(addr1) && IP_IS_V6(addr2)) ? \ + 0 : \ + ip4_addr_netcmp(ip_2_ip4(addr1), ip_2_ip4(addr2), mask)) +#define ip_addr_cmp(addr1, addr2) ((IP_GET_TYPE(addr1) != IP_GET_TYPE(addr2)) ? 0 : (IP_IS_V6_VAL(*(addr1)) ? \ + ip6_addr_cmp(ip_2_ip6(addr1), ip_2_ip6(addr2)) : \ + ip4_addr_cmp(ip_2_ip4(addr1), ip_2_ip4(addr2)))) +#define ip_addr_isany(ipaddr) ((IP_IS_V6(ipaddr)) ? \ + ip6_addr_isany(ip_2_ip6(ipaddr)) : \ + ip4_addr_isany(ip_2_ip4(ipaddr))) +#define ip_addr_isany_val(ipaddr) ((IP_IS_V6_VAL(ipaddr)) ? \ + ip6_addr_isany_val(*ip_2_ip6(&(ipaddr))) : \ + ip4_addr_isany_val(*ip_2_ip4(&(ipaddr)))) +#define ip_addr_isbroadcast(ipaddr, netif) ((IP_IS_V6(ipaddr)) ? \ + 0 : \ + ip4_addr_isbroadcast(ip_2_ip4(ipaddr), netif)) +#define ip_addr_ismulticast(ipaddr) ((IP_IS_V6(ipaddr)) ? \ + ip6_addr_ismulticast(ip_2_ip6(ipaddr)) : \ + ip4_addr_ismulticast(ip_2_ip4(ipaddr))) +#define ip_addr_isloopback(ipaddr) ((IP_IS_V6(ipaddr)) ? \ + ip6_addr_isloopback(ip_2_ip6(ipaddr)) : \ + ip4_addr_isloopback(ip_2_ip4(ipaddr))) +#define ip_addr_islinklocal(ipaddr) ((IP_IS_V6(ipaddr)) ? \ + ip6_addr_islinklocal(ip_2_ip6(ipaddr)) : \ + ip4_addr_islinklocal(ip_2_ip4(ipaddr))) +#define ip_addr_debug_print(debug, ipaddr) do { if(IP_IS_V6(ipaddr)) { \ + ip6_addr_debug_print(debug, ip_2_ip6(ipaddr)); } else { \ + ip4_addr_debug_print(debug, ip_2_ip4(ipaddr)); }}while(0) +#define ip_addr_debug_print_val(debug, ipaddr) do { if(IP_IS_V6_VAL(ipaddr)) { \ + ip6_addr_debug_print_val(debug, *ip_2_ip6(&(ipaddr))); } else { \ + ip4_addr_debug_print_val(debug, *ip_2_ip4(&(ipaddr))); }}while(0) +#define ipaddr_ntoa(addr) (((addr) == NULL) ? "NULL" : \ + ((IP_IS_V6(addr)) ? ip6addr_ntoa(ip_2_ip6(addr)) : ip4addr_ntoa(ip_2_ip4(addr)))) +#define ipaddr_ntoa_r(addr, buf, buflen) (((addr) == NULL) ? "NULL" : \ + ((IP_IS_V6(addr)) ? ip6addr_ntoa_r(ip_2_ip6(addr), buf, buflen) : ip4addr_ntoa_r(ip_2_ip4(addr), buf, buflen))) +int ipaddr_aton(const char *cp, ip_addr_t *addr); + +#else /* LWIP_IPV4 && LWIP_IPV6 */ + +#define IP_ADDR_PCB_VERSION_MATCH(addr, pcb) 1 +#define IP_ADDR_PCB_VERSION_MATCH_EXACT(pcb, ipaddr) 1 + +#if LWIP_IPV4 + +typedef ip4_addr_t ip_addr_t; +#define IPADDR4_INIT(u32val) { u32val } +#define IP_IS_V6_VAL(ipaddr) 0 +#define IP_IS_V6(ipaddr) 0 +#define IP_IS_ANY_TYPE_VAL(ipaddr) 0 +#define IP_SET_TYPE_VAL(ipaddr, iptype) +#define IP_SET_TYPE(ipaddr, iptype) +#define IP_GET_TYPE(ipaddr) IPADDR_TYPE_V4 +#define ip_2_ip4(ipaddr) (ipaddr) +#define IP_ADDR4(ipaddr,a,b,c,d) IP4_ADDR(ipaddr,a,b,c,d) + +#define ip_addr_copy(dest, src) ip4_addr_copy(dest, src) +#define ip_addr_copy_from_ip4(dest, src) ip4_addr_copy(dest, src) +#define ip_addr_set_ip4_u32(ipaddr, val) ip4_addr_set_u32(ip_2_ip4(ipaddr), val) +#define ip_addr_get_ip4_u32(ipaddr) ip4_addr_get_u32(ip_2_ip4(ipaddr)) +#define ip_addr_set(dest, src) ip4_addr_set(dest, src) +#define ip_addr_set_ipaddr(dest, src) ip4_addr_set(dest, src) +#define ip_addr_set_zero(ipaddr) ip4_addr_set_zero(ipaddr) +#define ip_addr_set_zero_ip4(ipaddr) ip4_addr_set_zero(ipaddr) +#define ip_addr_set_any(is_ipv6, ipaddr) ip4_addr_set_any(ipaddr) +#define ip_addr_set_loopback(is_ipv6, ipaddr) ip4_addr_set_loopback(ipaddr) +#define ip_addr_set_hton(dest, src) ip4_addr_set_hton(dest, src) +#define ip_addr_get_network(target, host, mask) ip4_addr_get_network(target, host, mask) +#define ip_addr_netcmp(addr1, addr2, mask) ip4_addr_netcmp(addr1, addr2, mask) +#define ip_addr_cmp(addr1, addr2) ip4_addr_cmp(addr1, addr2) +#define ip_addr_isany(ipaddr) ip4_addr_isany(ipaddr) +#define ip_addr_isany_val(ipaddr) ip4_addr_isany_val(ipaddr) +#define ip_addr_isloopback(ipaddr) ip4_addr_isloopback(ipaddr) +#define ip_addr_islinklocal(ipaddr) ip4_addr_islinklocal(ipaddr) +#define ip_addr_isbroadcast(addr, netif) ip4_addr_isbroadcast(addr, netif) +#define ip_addr_ismulticast(ipaddr) ip4_addr_ismulticast(ipaddr) +#define ip_addr_debug_print(debug, ipaddr) ip4_addr_debug_print(debug, ipaddr) +#define ip_addr_debug_print_val(debug, ipaddr) ip4_addr_debug_print_val(debug, ipaddr) +#define ipaddr_ntoa(ipaddr) ip4addr_ntoa(ipaddr) +#define ipaddr_ntoa_r(ipaddr, buf, buflen) ip4addr_ntoa_r(ipaddr, buf, buflen) +#define ipaddr_aton(cp, addr) ip4addr_aton(cp, addr) + +#else /* LWIP_IPV4 */ + +typedef ip6_addr_t ip_addr_t; +#define IPADDR6_INIT(a, b, c, d) { { a, b, c, d } } +#define IP_IS_V6_VAL(ipaddr) 1 +#define IP_IS_V6(ipaddr) 1 +#define IP_IS_ANY_TYPE_VAL(ipaddr) 0 +#define IP_SET_TYPE_VAL(ipaddr, iptype) +#define IP_SET_TYPE(ipaddr, iptype) +#define IP_GET_TYPE(ipaddr) IPADDR_TYPE_V6 +#define ip_2_ip6(ipaddr) (ipaddr) +#define IP_ADDR6(ipaddr,i0,i1,i2,i3) IP6_ADDR(ipaddr,i0,i1,i2,i3) + +#define ip_addr_copy(dest, src) ip6_addr_copy(dest, src) +#define ip_addr_copy_from_ip6(dest, src) ip6_addr_copy(dest, src) +#define ip_addr_set(dest, src) ip6_addr_set(dest, src) +#define ip_addr_set_ipaddr(dest, src) ip6_addr_set(dest, src) +#define ip_addr_set_zero(ipaddr) ip6_addr_set_zero(ipaddr) +#define ip_addr_set_zero_ip6(ipaddr) ip6_addr_set_zero(ipaddr) +#define ip_addr_set_any(is_ipv6, ipaddr) ip6_addr_set_any(ipaddr) +#define ip_addr_set_loopback(is_ipv6, ipaddr) ip6_addr_set_loopback(ipaddr) +#define ip_addr_set_hton(dest, src) ip6_addr_set_hton(dest, src) +#define ip_addr_get_network(target, host, mask) ip6_addr_set_zero(target) +#define ip_addr_netcmp(addr1, addr2, mask) 0 +#define ip_addr_cmp(addr1, addr2) ip6_addr_cmp(addr1, addr2) +#define ip_addr_isany(ipaddr) ip6_addr_isany(ipaddr) +#define ip_addr_isany_val(ipaddr) ip6_addr_isany_val(ipaddr) +#define ip_addr_isloopback(ipaddr) ip6_addr_isloopback(ipaddr) +#define ip_addr_islinklocal(ipaddr) ip6_addr_islinklocal(ipaddr) +#define ip_addr_isbroadcast(addr, netif) 0 +#define ip_addr_ismulticast(ipaddr) ip6_addr_ismulticast(ipaddr) +#define ip_addr_debug_print(debug, ipaddr) ip6_addr_debug_print(debug, ipaddr) +#define ip_addr_debug_print_val(debug, ipaddr) ip6_addr_debug_print_val(debug, ipaddr) +#define ipaddr_ntoa(ipaddr) ip6addr_ntoa(ipaddr) +#define ipaddr_ntoa_r(ipaddr, buf, buflen) ip6addr_ntoa_r(ipaddr, buf, buflen) +#define ipaddr_aton(cp, addr) ip6addr_aton(cp, addr) + +#endif /* LWIP_IPV4 */ +#endif /* LWIP_IPV4 && LWIP_IPV6 */ + +#if LWIP_IPV4 + +extern const ip_addr_t ip_addr_any; +extern const ip_addr_t ip_addr_broadcast; + +/** IP_ADDR_ can be used as a fixed/const ip_addr_t + * for the IPv4 wildcard and the broadcast address + */ +#define IP_ADDR_ANY (&ip_addr_any) +#define IP_ADDR_BROADCAST (&ip_addr_broadcast) +/** IP4_ADDR_ can be used as a fixed/const ip4_addr_t + * for the wildcard and the broadcast address + */ +#define IP4_ADDR_ANY (ip_2_ip4(&ip_addr_any)) +#define IP4_ADDR_BROADCAST (ip_2_ip4(&ip_addr_broadcast)) + +#endif /* LWIP_IPV4*/ + +#if LWIP_IPV6 + +extern const ip_addr_t ip6_addr_any; + +/** IP6_ADDR_ANY can be used as a fixed ip_addr_t + * for the IPv6 wildcard address + */ +#define IP6_ADDR_ANY (&ip6_addr_any) +/** IP6_ADDR_ANY6 can be used as a fixed ip6_addr_t + * for the IPv6 wildcard address + */ +#define IP6_ADDR_ANY6 (ip_2_ip6(&ip6_addr_any)) + +#if !LWIP_IPV4 +/** Just a little upgrade-helper for IPv6-only configurations: */ +#define IP_ADDR_ANY IP6_ADDR_ANY +#endif /* !LWIP_IPV4 */ + +#endif + +#if LWIP_IPV4 && LWIP_IPV6 +#define IP_ANY_TYPE (&ip_addr_any_type) +#else +#define IP_ANY_TYPE IP_ADDR_ANY +#endif + +#ifdef __cplusplus +} +#endif + +#endif /* LWIP_HDR_IP_ADDR_H__ */ diff --git a/components/lwip/include/lwip/lwip/ip_frag.h b/components/lwip/include/lwip/lwip/ip_frag.h new file mode 100755 index 0000000000..deeb2f4efc --- /dev/null +++ b/components/lwip/include/lwip/lwip/ip_frag.h @@ -0,0 +1,95 @@ +/* + * Copyright (c) 2001-2004 Swedish Institute of Computer Science. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Jani Monoses + * + */ + +#ifndef LWIP_HDR_IP_FRAG_H +#define LWIP_HDR_IP_FRAG_H + +#include "lwip/opt.h" +#include "lwip/err.h" +#include "lwip/pbuf.h" +#include "lwip/netif.h" +#include "lwip/ip_addr.h" +#include "lwip/ip.h" + +#if LWIP_IPV4 + +#ifdef __cplusplus +extern "C" { +#endif + +#if IP_REASSEMBLY +/* The IP reassembly timer interval in milliseconds. */ +#define IP_TMR_INTERVAL 1000 + +/* IP reassembly helper struct. + * This is exported because memp needs to know the size. + */ +struct ip_reassdata { + struct ip_reassdata *next; + struct pbuf *p; + struct ip_hdr iphdr; + u16_t datagram_len; + u8_t flags; + u8_t timer; +}; + +void ip_reass_init(void); +void ip_reass_tmr(void); +struct pbuf * ip4_reass(struct pbuf *p); +#endif /* IP_REASSEMBLY */ + +#if IP_FRAG +#if !IP_FRAG_USES_STATIC_BUF && !LWIP_NETIF_TX_SINGLE_PBUF +/** A custom pbuf that holds a reference to another pbuf, which is freed + * when this custom pbuf is freed. This is used to create a custom PBUF_REF + * that points into the original pbuf. */ +#ifndef LWIP_PBUF_CUSTOM_REF_DEFINED +#define LWIP_PBUF_CUSTOM_REF_DEFINED +struct pbuf_custom_ref { + /** 'base class' */ + struct pbuf_custom pc; + /** pointer to the original pbuf that is referenced */ + struct pbuf *original; +}; +#endif /* LWIP_PBUF_CUSTOM_REF_DEFINED */ +#endif /* !IP_FRAG_USES_STATIC_BUF && !LWIP_NETIF_TX_SINGLE_PBUF */ + +err_t ip4_frag(struct pbuf *p, struct netif *netif, const ip4_addr_t *dest); +#endif /* IP_FRAG */ + +#ifdef __cplusplus +} +#endif + +#endif /* LWIP_IPV4 */ + +#endif /* LWIP_HDR_IP_FRAG_H */ diff --git a/components/lwip/include/lwip/lwip/mem.h b/components/lwip/include/lwip/lwip/mem.h new file mode 100755 index 0000000000..ca76f66322 --- /dev/null +++ b/components/lwip/include/lwip/lwip/mem.h @@ -0,0 +1,162 @@ +/* + * Copyright (c) 2001-2004 Swedish Institute of Computer Science. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + * + */ +#ifndef LWIP_HDR_MEM_H +#define LWIP_HDR_MEM_H + +#include "lwip/opt.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#if MEM_LIBC_MALLOC + +#include /* for size_t */ + +typedef size_t mem_size_t; +#define MEM_SIZE_F SZT_F + +/* aliases for C library malloc() */ +#define mem_init() +/* in case C library malloc() needs extra protection, + * allow these defines to be overridden. + */ + +#ifndef MEMLEAK_DEBUG + +#ifndef mem_free +#define mem_free free +#endif +#ifndef mem_malloc +#define mem_malloc malloc +#endif +#ifndef mem_calloc +#define mem_calloc calloc +#endif + +/* DYC_NEED_TO_DO_LATER +#ifndef mem_realloc +#define mem_realloc +#endif +#ifndef mem_zalloc +#define mem_zalloc +#endif +*/ + +#else +/* +#ifndef mem_free +#define mem_free(s) \ + do{\ + const char *file = mem_debug_file;\ + vPortFree(s, file, __LINE__);\ + }while(0) +#endif +#ifndef mem_malloc +#define mem_malloc(s) ({const char *file = mem_debug_file; pvPortMalloc(s, file, __LINE__);}) +#endif +#ifndef mem_calloc +#define mem_calloc(s) ({const char *file = mem_debug_file; pvPortCalloc(s, file, __LINE__);}) +#endif +#ifndef mem_realloc +#define mem_realloc(p, s) ({const char *file = mem_debug_file; pvPortRealloc(p, s, file, __LINE__);}) +#endif +#ifndef mem_zalloc +#define mem_zalloc(s) ({const char *file = mem_debug_file; pvPortZalloc(s, file, __LINE__);}) +#endif +*/ +#endif + + + +/* Since there is no C library allocation function to shrink memory without + moving it, define this to nothing. */ +#ifndef mem_trim +#define mem_trim(mem, size) (mem) +#endif +#else /* MEM_LIBC_MALLOC */ + +/* MEM_SIZE would have to be aligned, but using 64000 here instead of + * 65535 leaves some room for alignment... + */ +#if MEM_SIZE > 64000L +typedef u32_t mem_size_t; +#define MEM_SIZE_F U32_F +#else +typedef u16_t mem_size_t; +#define MEM_SIZE_F U16_F +#endif /* MEM_SIZE > 64000 */ + +#if MEM_USE_POOLS +/** mem_init is not used when using pools instead of a heap */ +#define mem_init() +/** mem_trim is not used when using pools instead of a heap: + we can't free part of a pool element and don't want to copy the rest */ +#define mem_trim(mem, size) (mem) +#else /* MEM_USE_POOLS */ +/* lwIP alternative malloc */ +void mem_init(void); +void *mem_trim(void *mem, mem_size_t size); +#endif /* MEM_USE_POOLS */ +void *mem_malloc(mem_size_t size); +void *mem_calloc(mem_size_t count, mem_size_t size); +void mem_free(void *mem); +#endif /* MEM_LIBC_MALLOC */ + +/** Calculate memory size for an aligned buffer - returns the next highest + * multiple of MEM_ALIGNMENT (e.g. LWIP_MEM_ALIGN_SIZE(3) and + * LWIP_MEM_ALIGN_SIZE(4) will both yield 4 for MEM_ALIGNMENT == 4). + */ +#ifndef LWIP_MEM_ALIGN_SIZE +#define LWIP_MEM_ALIGN_SIZE(size) (((size) + MEM_ALIGNMENT - 1U) & ~(MEM_ALIGNMENT-1U)) +#endif + +/** Calculate safe memory size for an aligned buffer when using an unaligned + * type as storage. This includes a safety-margin on (MEM_ALIGNMENT - 1) at the + * start (e.g. if buffer is u8_t[] and actual data will be u32_t*) + */ +#ifndef LWIP_MEM_ALIGN_BUFFER +#define LWIP_MEM_ALIGN_BUFFER(size) (((size) + MEM_ALIGNMENT - 1U)) +#endif + +/** Align a memory pointer to the alignment defined by MEM_ALIGNMENT + * so that ADDR % MEM_ALIGNMENT == 0 + */ +#ifndef LWIP_MEM_ALIGN +#define LWIP_MEM_ALIGN(addr) ((void *)(((mem_ptr_t)(addr) + MEM_ALIGNMENT - 1) & ~(mem_ptr_t)(MEM_ALIGNMENT-1))) +#endif + +#ifdef __cplusplus +} +#endif + +#endif /* LWIP_HDR_MEM_H */ diff --git a/components/lwip/include/lwip/lwip/memp.h b/components/lwip/include/lwip/lwip/memp.h new file mode 100755 index 0000000000..d7463f2b33 --- /dev/null +++ b/components/lwip/include/lwip/lwip/memp.h @@ -0,0 +1,133 @@ +/* + * Copyright (c) 2001-2004 Swedish Institute of Computer Science. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + * + */ + +#ifndef LWIP_HDR_MEMP_H +#define LWIP_HDR_MEMP_H + +#ifdef __cplusplus +extern "C" { +#endif + +/* run once with empty definition to handle all custom includes in lwippools.h */ +#define LWIP_MEMPOOL(name,num,size,desc) +#include "lwip/priv/memp_std.h" + +/* Create the list of all memory pools managed by memp. MEMP_MAX represents a NULL pool at the end */ +typedef enum { +#define LWIP_MEMPOOL(name,num,size,desc) MEMP_##name, +#include "lwip/priv/memp_std.h" + MEMP_MAX +} memp_t; + +#include "lwip/priv/memp_priv.h" + +/* Private mempools example: + * .h: only when pool is used in multiple .c files: LWIP_MEMPOOL_PROTOTYPE(my_private_pool); + * .c: + * - in global variables section: LWIP_MEMPOOL_DECLARE(my_private_pool, 10, sizeof(foo), "Some description") + * - call ONCE before using pool (e.g. in some init() function): LWIP_MEMPOOL_INIT(my_private_pool); + * - allocate: void* my_new_mem = LWIP_MEMPOOL_ALLOC(my_private_pool); + * - free: LWIP_MEMPOOL_FREE(my_private_pool, my_new_mem); + * + * To relocate a pool, declare it as extern in cc.h. Example for GCC: + * extern u8_t __attribute__((section(".onchip_mem"))) memp_memory_my_private_pool[]; + */ + +extern const struct memp_desc* const memp_pools[MEMP_MAX]; + +#define LWIP_MEMPOOL_PROTOTYPE(name) extern const struct memp_desc memp_ ## name + +#if MEMP_MEM_MALLOC + +#include "lwip/mem.h" + +#define memp_init() +#define memp_malloc(type) mem_malloc(memp_pools[type]->size) +#define memp_free(type, mem) mem_free(mem) + +#define LWIP_MEMPOOL_DECLARE(name,num,size,desc) \ + const struct memp_desc memp_ ## name = { \ + LWIP_MEM_ALIGN_SIZE(size) \ + }; + +#define LWIP_MEMPOOL_INIT(name) +#define LWIP_MEMPOOL_ALLOC(name) mem_malloc(memp_ ## name.size) +#define LWIP_MEMPOOL_FREE(name, x) mem_free(x) + +#else /* MEMP_MEM_MALLOC */ + +#define LWIP_MEMPOOL_DECLARE(name,num,size,desc) u8_t memp_memory_ ## name ## _base \ + [((num) * (MEMP_SIZE + MEMP_ALIGN_SIZE(size)))]; \ + \ + static struct memp *memp_tab_ ## name; \ + \ + const struct memp_desc memp_ ## name = { \ + LWIP_MEM_ALIGN_SIZE(size), \ + (num), \ + DECLARE_LWIP_MEMPOOL_DESC(desc) \ + memp_memory_ ## name ## _base, \ + &memp_tab_ ## name \ + }; + +#define LWIP_MEMPOOL_INIT(name) memp_init_pool(&memp_ ## name) +#define LWIP_MEMPOOL_ALLOC(name) memp_malloc_pool(&memp_ ## name) +#define LWIP_MEMPOOL_FREE(name, x) memp_free_pool(&memp_ ## name, (x)) + +#if MEM_USE_POOLS +/** This structure is used to save the pool one element came from. */ +struct memp_malloc_helper +{ + memp_t poolnr; +#if MEMP_OVERFLOW_CHECK + u16_t size; +#endif /* MEMP_OVERFLOW_CHECK */ +}; + +#endif /* MEM_USE_POOLS */ + +void memp_init(void); + +#if MEMP_OVERFLOW_CHECK +void *memp_malloc_fn(memp_t type, const char* file, const int line); +#define memp_malloc(t) memp_malloc_fn((t), __FILE__, __LINE__) +#else +void *memp_malloc(memp_t type); +#endif +void memp_free(memp_t type, void *mem); + +#endif /* MEMP_MEM_MALLOC */ + +#ifdef __cplusplus +} +#endif + +#endif /* LWIP_HDR_MEMP_H */ diff --git a/components/lwip/include/lwip/lwip/mld6.h b/components/lwip/include/lwip/lwip/mld6.h new file mode 100755 index 0000000000..a54dd49e91 --- /dev/null +++ b/components/lwip/include/lwip/lwip/mld6.h @@ -0,0 +1,119 @@ +/** + * @file + * + * Multicast listener discovery for IPv6. Aims to be compliant with RFC 2710. + * No support for MLDv2. + */ + +/* + * Copyright (c) 2010 Inico Technologies Ltd. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Ivan Delamer + * + * + * Please coordinate changes and requests with Ivan Delamer + * + */ + +#ifndef LWIP_HDR_MLD6_H +#define LWIP_HDR_MLD6_H + +#include "lwip/opt.h" + +#if LWIP_IPV6_MLD && LWIP_IPV6 /* don't build if not configured for use in lwipopts.h */ + +#include "lwip/pbuf.h" +#include "lwip/netif.h" + + +#ifdef __cplusplus +extern "C" { +#endif + +struct mld_group { + /** next link */ + struct mld_group *next; + /** interface on which the group is active */ + struct netif *netif; + /** multicast address */ + ip6_addr_t group_address; + /** signifies we were the last person to report */ + u8_t last_reporter_flag; + /** current state of the group */ + u8_t group_state; + /** timer for reporting */ + u16_t timer; + /** counter of simultaneous uses */ + u8_t use; +}; + +/** Multicast listener report/query/done message header. */ +#ifdef PACK_STRUCT_USE_INCLUDES +# include "arch/bpstruct.h" +#endif +PACK_STRUCT_BEGIN +struct mld_header { + PACK_STRUCT_FLD_8(u8_t type); + PACK_STRUCT_FLD_8(u8_t code); + PACK_STRUCT_FIELD(u16_t chksum); + PACK_STRUCT_FIELD(u16_t max_resp_delay); + PACK_STRUCT_FIELD(u16_t reserved); + PACK_STRUCT_FLD_S(ip6_addr_p_t multicast_address); + /* Options follow. */ +} PACK_STRUCT_STRUCT; +PACK_STRUCT_END +#ifdef PACK_STRUCT_USE_INCLUDES +# include "arch/epstruct.h" +#endif + +#define MLD6_TMR_INTERVAL 100 /* Milliseconds */ + +/* MAC Filter Actions, these are passed to a netif's + * mld_mac_filter callback function. */ +#define MLD6_DEL_MAC_FILTER 0 +#define MLD6_ADD_MAC_FILTER 1 + + +err_t mld6_stop(struct netif *netif); +void mld6_report_groups(struct netif *netif); +void mld6_tmr(void); +struct mld_group *mld6_lookfor_group(struct netif *ifp, const ip6_addr_t *addr); +void mld6_input(struct pbuf *p, struct netif *inp); +err_t mld6_joingroup(const ip6_addr_t *srcaddr, const ip6_addr_t *groupaddr); +err_t mld6_joingroup_netif(struct netif *netif, const ip6_addr_t *groupaddr); +err_t mld6_leavegroup(const ip6_addr_t *srcaddr, const ip6_addr_t *groupaddr); +err_t mld6_leavegroup_netif(struct netif *netif, const ip6_addr_t *groupaddr); + + +#ifdef __cplusplus +} +#endif + +#endif /* LWIP_IPV6_MLD && LWIP_IPV6 */ + +#endif /* LWIP_HDR_MLD6_H */ diff --git a/components/lwip/include/lwip/lwip/nd6.h b/components/lwip/include/lwip/lwip/nd6.h new file mode 100755 index 0000000000..d0646f1b4e --- /dev/null +++ b/components/lwip/include/lwip/lwip/nd6.h @@ -0,0 +1,361 @@ +/** + * @file + * + * Neighbor discovery and stateless address autoconfiguration for IPv6. + * Aims to be compliant with RFC 4861 (Neighbor discovery) and RFC 4862 + * (Address autoconfiguration). + */ + +/* + * Copyright (c) 2010 Inico Technologies Ltd. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Ivan Delamer + * + * + * Please coordinate changes and requests with Ivan Delamer + * + */ + +#ifndef LWIP_HDR_ND6_H +#define LWIP_HDR_ND6_H + +#include "lwip/opt.h" + +#if LWIP_IPV6 /* don't build if not configured for use in lwipopts.h */ + +#include "lwip/pbuf.h" +#include "lwip/ip6.h" +#include "lwip/ip6_addr.h" +#include "lwip/netif.h" + + +#ifdef __cplusplus +extern "C" { +#endif + +/* Struct for tables. */ +struct nd6_neighbor_cache_entry { + ip6_addr_t next_hop_address; + struct netif * netif; + u8_t lladdr[NETIF_MAX_HWADDR_LEN]; + /*u32_t pmtu;*/ +#if LWIP_ND6_QUEUEING + /** Pointer to queue of pending outgoing packets on this entry. */ + struct nd6_q_entry *q; +#else /* LWIP_ND6_QUEUEING */ + /** Pointer to a single pending outgoing packet on this entry. */ + struct pbuf *q; +#endif /* LWIP_ND6_QUEUEING */ + u8_t state; + u8_t isrouter; + union { + u32_t reachable_time; + u32_t delay_time; + u32_t probes_sent; + u32_t stale_time; + } counter; +}; + +struct nd6_destination_cache_entry { + ip6_addr_t destination_addr; + ip6_addr_t next_hop_addr; + u16_t pmtu; + u32_t age; +}; + +struct nd6_prefix_list_entry { + ip6_addr_t prefix; + struct netif * netif; + u32_t invalidation_timer; +#if LWIP_IPV6_AUTOCONFIG + u8_t flags; +#define ND6_PREFIX_AUTOCONFIG_AUTONOMOUS 0x01 +#define ND6_PREFIX_AUTOCONFIG_ADDRESS_GENERATED 0x02 +#define ND6_PREFIX_AUTOCONFIG_ADDRESS_DUPLICATE 0x04 +#endif /* LWIP_IPV6_AUTOCONFIG */ +}; + +struct nd6_router_list_entry { + struct nd6_neighbor_cache_entry * neighbor_entry; + u32_t invalidation_timer; + u8_t flags; +}; + + +enum nd6_neighbor_cache_entry_state { + ND6_NO_ENTRY = 0, + ND6_INCOMPLETE, + ND6_REACHABLE, + ND6_STALE, + ND6_DELAY, + ND6_PROBE +}; + +#if LWIP_ND6_QUEUEING +/** struct for queueing outgoing packets for unknown address + * defined here to be accessed by memp.h + */ +struct nd6_q_entry { + struct nd6_q_entry *next; + struct pbuf *p; +}; +#endif /* LWIP_ND6_QUEUEING */ + +/** Neighbor solicitation message header. */ +#ifdef PACK_STRUCT_USE_INCLUDES +# include "arch/bpstruct.h" +#endif +PACK_STRUCT_BEGIN +struct ns_header { + PACK_STRUCT_FLD_8(u8_t type); + PACK_STRUCT_FLD_8(u8_t code); + PACK_STRUCT_FIELD(u16_t chksum); + PACK_STRUCT_FIELD(u32_t reserved); + PACK_STRUCT_FLD_S(ip6_addr_p_t target_address); + /* Options follow. */ +} PACK_STRUCT_STRUCT; +PACK_STRUCT_END +#ifdef PACK_STRUCT_USE_INCLUDES +# include "arch/epstruct.h" +#endif + +/** Neighbor advertisement message header. */ +#ifdef PACK_STRUCT_USE_INCLUDES +# include "arch/bpstruct.h" +#endif +PACK_STRUCT_BEGIN +struct na_header { + PACK_STRUCT_FLD_8(u8_t type); + PACK_STRUCT_FLD_8(u8_t code); + PACK_STRUCT_FIELD(u16_t chksum); + PACK_STRUCT_FLD_8(u8_t flags); + PACK_STRUCT_FLD_8(u8_t reserved[3]); + PACK_STRUCT_FLD_S(ip6_addr_p_t target_address); + /* Options follow. */ +} PACK_STRUCT_STRUCT; +PACK_STRUCT_END +#ifdef PACK_STRUCT_USE_INCLUDES +# include "arch/epstruct.h" +#endif +#define ND6_FLAG_ROUTER (0x80) +#define ND6_FLAG_SOLICITED (0x40) +#define ND6_FLAG_OVERRIDE (0x20) + +/** Router solicitation message header. */ +#ifdef PACK_STRUCT_USE_INCLUDES +# include "arch/bpstruct.h" +#endif +PACK_STRUCT_BEGIN +struct rs_header { + PACK_STRUCT_FLD_8(u8_t type); + PACK_STRUCT_FLD_8(u8_t code); + PACK_STRUCT_FIELD(u16_t chksum); + PACK_STRUCT_FIELD(u32_t reserved); + /* Options follow. */ +} PACK_STRUCT_STRUCT; +PACK_STRUCT_END +#ifdef PACK_STRUCT_USE_INCLUDES +# include "arch/epstruct.h" +#endif + +/** Router advertisement message header. */ +#define ND6_RA_FLAG_MANAGED_ADDR_CONFIG (0x80) +#define ND6_RA_FLAG_OTHER_CONFIG (0x40) +#define ND6_RA_FLAG_HOME_AGENT (0x20) +#define ND6_RA_PREFERENCE_MASK (0x18) +#define ND6_RA_PREFERENCE_HIGH (0x08) +#define ND6_RA_PREFERENCE_MEDIUM (0x00) +#define ND6_RA_PREFERENCE_LOW (0x18) +#define ND6_RA_PREFERENCE_DISABLED (0x10) +#ifdef PACK_STRUCT_USE_INCLUDES +# include "arch/bpstruct.h" +#endif +PACK_STRUCT_BEGIN +struct ra_header { + PACK_STRUCT_FLD_8(u8_t type); + PACK_STRUCT_FLD_8(u8_t code); + PACK_STRUCT_FIELD(u16_t chksum); + PACK_STRUCT_FLD_8(u8_t current_hop_limit); + PACK_STRUCT_FLD_8(u8_t flags); + PACK_STRUCT_FIELD(u16_t router_lifetime); + PACK_STRUCT_FIELD(u32_t reachable_time); + PACK_STRUCT_FIELD(u32_t retrans_timer); + /* Options follow. */ +} PACK_STRUCT_STRUCT; +PACK_STRUCT_END +#ifdef PACK_STRUCT_USE_INCLUDES +# include "arch/epstruct.h" +#endif + +/** Redirect message header. */ +#ifdef PACK_STRUCT_USE_INCLUDES +# include "arch/bpstruct.h" +#endif +PACK_STRUCT_BEGIN +struct redirect_header { + PACK_STRUCT_FLD_8(u8_t type); + PACK_STRUCT_FLD_8(u8_t code); + PACK_STRUCT_FIELD(u16_t chksum); + PACK_STRUCT_FIELD(u32_t reserved); + PACK_STRUCT_FLD_S(ip6_addr_p_t target_address); + PACK_STRUCT_FLD_S(ip6_addr_p_t destination_address); + /* Options follow. */ +} PACK_STRUCT_STRUCT; +PACK_STRUCT_END +#ifdef PACK_STRUCT_USE_INCLUDES +# include "arch/epstruct.h" +#endif + +/** Link-layer address option. */ +#define ND6_OPTION_TYPE_SOURCE_LLADDR (0x01) +#define ND6_OPTION_TYPE_TARGET_LLADDR (0x02) +#ifdef PACK_STRUCT_USE_INCLUDES +# include "arch/bpstruct.h" +#endif +PACK_STRUCT_BEGIN +struct lladdr_option { + PACK_STRUCT_FLD_8(u8_t type); + PACK_STRUCT_FLD_8(u8_t length); + PACK_STRUCT_FLD_8(u8_t addr[NETIF_MAX_HWADDR_LEN]); +} PACK_STRUCT_STRUCT; +PACK_STRUCT_END +#ifdef PACK_STRUCT_USE_INCLUDES +# include "arch/epstruct.h" +#endif + +/** Prefix information option. */ +#define ND6_OPTION_TYPE_PREFIX_INFO (0x03) +#define ND6_PREFIX_FLAG_ON_LINK (0x80) +#define ND6_PREFIX_FLAG_AUTONOMOUS (0x40) +#define ND6_PREFIX_FLAG_ROUTER_ADDRESS (0x20) +#define ND6_PREFIX_FLAG_SITE_PREFIX (0x10) +#ifdef PACK_STRUCT_USE_INCLUDES +# include "arch/bpstruct.h" +#endif +PACK_STRUCT_BEGIN +struct prefix_option { + PACK_STRUCT_FLD_8(u8_t type); + PACK_STRUCT_FLD_8(u8_t length); + PACK_STRUCT_FLD_8(u8_t prefix_length); + PACK_STRUCT_FLD_8(u8_t flags); + PACK_STRUCT_FIELD(u32_t valid_lifetime); + PACK_STRUCT_FIELD(u32_t preferred_lifetime); + PACK_STRUCT_FLD_8(u8_t reserved2[3]); + PACK_STRUCT_FLD_8(u8_t site_prefix_length); + PACK_STRUCT_FLD_S(ip6_addr_p_t prefix); +} PACK_STRUCT_STRUCT; +PACK_STRUCT_END +#ifdef PACK_STRUCT_USE_INCLUDES +# include "arch/epstruct.h" +#endif + +/** Redirected header option. */ +#define ND6_OPTION_TYPE_REDIR_HDR (0x04) +#ifdef PACK_STRUCT_USE_INCLUDES +# include "arch/bpstruct.h" +#endif +PACK_STRUCT_BEGIN +struct redirected_header_option { + PACK_STRUCT_FLD_8(u8_t type); + PACK_STRUCT_FLD_8(u8_t length); + PACK_STRUCT_FLD_8(u8_t reserved[6]); + /* Portion of redirected packet follows. */ + /* PACK_STRUCT_FLD_8(u8_t redirected[8]); */ +} PACK_STRUCT_STRUCT; +PACK_STRUCT_END +#ifdef PACK_STRUCT_USE_INCLUDES +# include "arch/epstruct.h" +#endif + +/** MTU option. */ +#define ND6_OPTION_TYPE_MTU (0x05) +#ifdef PACK_STRUCT_USE_INCLUDES +# include "arch/bpstruct.h" +#endif +PACK_STRUCT_BEGIN +struct mtu_option { + PACK_STRUCT_FLD_8(u8_t type); + PACK_STRUCT_FLD_8(u8_t length); + PACK_STRUCT_FIELD(u16_t reserved); + PACK_STRUCT_FIELD(u32_t mtu); +} PACK_STRUCT_STRUCT; +PACK_STRUCT_END +#ifdef PACK_STRUCT_USE_INCLUDES +# include "arch/epstruct.h" +#endif + +/** Route information option. */ +#define ND6_OPTION_TYPE_ROUTE_INFO (24) +#ifdef PACK_STRUCT_USE_INCLUDES +# include "arch/bpstruct.h" +#endif +PACK_STRUCT_BEGIN +struct route_option { + PACK_STRUCT_FLD_8(u8_t type); + PACK_STRUCT_FLD_8(u8_t length); + PACK_STRUCT_FLD_8(u8_t prefix_length); + PACK_STRUCT_FLD_8(u8_t preference); + PACK_STRUCT_FIELD(u32_t route_lifetime); + PACK_STRUCT_FLD_S(ip6_addr_p_t prefix); +} PACK_STRUCT_STRUCT; +PACK_STRUCT_END +#ifdef PACK_STRUCT_USE_INCLUDES +# include "arch/epstruct.h" +#endif + +/** 1 second period */ +#define ND6_TMR_INTERVAL 1000 + +/* Router tables. */ +/* TODO make these static? and entries accessible through API? */ +extern struct nd6_neighbor_cache_entry neighbor_cache[]; +extern struct nd6_destination_cache_entry destination_cache[]; +extern struct nd6_prefix_list_entry prefix_list[]; +extern struct nd6_router_list_entry default_router_list[]; + +/* Default values, can be updated by a RA message. */ +extern u32_t reachable_time; +extern u32_t retrans_timer; + +void nd6_tmr(void); +void nd6_input(struct pbuf *p, struct netif *inp); +s8_t nd6_get_next_hop_entry(const ip6_addr_t * ip6addr, struct netif * netif); +s8_t nd6_select_router(const ip6_addr_t * ip6addr, struct netif * netif); +u16_t nd6_get_destination_mtu(const ip6_addr_t * ip6addr, struct netif * netif); +err_t nd6_queue_packet(s8_t neighbor_index, struct pbuf * p); +#if LWIP_ND6_TCP_REACHABILITY_HINTS +void nd6_reachability_hint(const ip6_addr_t * ip6addr); +#endif /* LWIP_ND6_TCP_REACHABILITY_HINTS */ + +#ifdef __cplusplus +} +#endif + +#endif /* LWIP_IPV6 */ + +#endif /* LWIP_HDR_ND6_H */ diff --git a/components/lwip/include/lwip/lwip/netbuf.h b/components/lwip/include/lwip/lwip/netbuf.h new file mode 100755 index 0000000000..8875e12d8e --- /dev/null +++ b/components/lwip/include/lwip/lwip/netbuf.h @@ -0,0 +1,112 @@ +/* + * Copyright (c) 2001-2004 Swedish Institute of Computer Science. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + * + */ +#ifndef LWIP_HDR_NETBUF_H +#define LWIP_HDR_NETBUF_H + +#include "lwip/opt.h" + +#if LWIP_NETCONN || LWIP_SOCKET /* don't build if not configured for use in lwipopts.h */ +/* Note: Netconn API is always available when sockets are enabled - + * sockets are implemented on top of them */ + +#include "lwip/pbuf.h" +#include "lwip/ip_addr.h" +#include "lwip/ip6_addr.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** This netbuf has dest-addr/port set */ +#define NETBUF_FLAG_DESTADDR 0x01 +/** This netbuf includes a checksum */ +#define NETBUF_FLAG_CHKSUM 0x02 + +struct netbuf { + struct pbuf *p, *ptr; + ip_addr_t addr; + u16_t port; +#if LWIP_NETBUF_RECVINFO || LWIP_CHECKSUM_ON_COPY +#if LWIP_CHECKSUM_ON_COPY + u8_t flags; +#endif /* LWIP_CHECKSUM_ON_COPY */ + u16_t toport_chksum; +#if LWIP_NETBUF_RECVINFO + ip_addr_t toaddr; +#endif /* LWIP_NETBUF_RECVINFO */ +#endif /* LWIP_NETBUF_RECVINFO || LWIP_CHECKSUM_ON_COPY */ +}; + +/* Network buffer functions: */ +struct netbuf * netbuf_new (void); +void netbuf_delete (struct netbuf *buf); +void * netbuf_alloc (struct netbuf *buf, u16_t size); +void netbuf_free (struct netbuf *buf); +err_t netbuf_ref (struct netbuf *buf, + const void *dataptr, u16_t size); +void netbuf_chain (struct netbuf *head, struct netbuf *tail); + +err_t netbuf_data (struct netbuf *buf, + void **dataptr, u16_t *len); +s8_t netbuf_next (struct netbuf *buf); +void netbuf_first (struct netbuf *buf); + + +#define netbuf_copy_partial(buf, dataptr, len, offset) \ + pbuf_copy_partial((buf)->p, (dataptr), (len), (offset)) +#define netbuf_copy(buf,dataptr,len) netbuf_copy_partial(buf, dataptr, len, 0) +#define netbuf_take(buf, dataptr, len) pbuf_take((buf)->p, dataptr, len) +#define netbuf_len(buf) ((buf)->p->tot_len) +#define netbuf_fromaddr(buf) (&((buf)->addr)) +#define netbuf_set_fromaddr(buf, fromaddr) ip_addr_set(&((buf)->addr), fromaddr) +#define netbuf_fromport(buf) ((buf)->port) +#if LWIP_NETBUF_RECVINFO +#define netbuf_destaddr(buf) (&((buf)->toaddr)) +#define netbuf_set_destaddr(buf, destaddr) ip_addr_set(&((buf)->toaddr), destaddr) +#if LWIP_CHECKSUM_ON_COPY +#define netbuf_destport(buf) (((buf)->flags & NETBUF_FLAG_DESTADDR) ? (buf)->toport_chksum : 0) +#else /* LWIP_CHECKSUM_ON_COPY */ +#define netbuf_destport(buf) ((buf)->toport_chksum) +#endif /* LWIP_CHECKSUM_ON_COPY */ +#endif /* LWIP_NETBUF_RECVINFO */ +#if LWIP_CHECKSUM_ON_COPY +#define netbuf_set_chksum(buf, chksum) do { (buf)->flags = NETBUF_FLAG_CHKSUM; \ + (buf)->toport_chksum = chksum; } while(0) +#endif /* LWIP_CHECKSUM_ON_COPY */ + +#ifdef __cplusplus +} +#endif + +#endif /* LWIP_NETCONN || LWIP_SOCKET */ + +#endif /* LWIP_HDR_NETBUF_H */ diff --git a/components/lwip/include/lwip/lwip/netdb.h b/components/lwip/include/lwip/lwip/netdb.h new file mode 100755 index 0000000000..144a6e0bd4 --- /dev/null +++ b/components/lwip/include/lwip/lwip/netdb.h @@ -0,0 +1,142 @@ +/* + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Simon Goldschmidt + * + */ +#ifndef LWIP_HDR_NETDB_H +#define LWIP_HDR_NETDB_H + +#include "lwip/opt.h" + +#if LWIP_DNS && LWIP_SOCKET + +#include /* for size_t */ + +#include "lwip/inet.h" +#include "lwip/sockets.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/* some rarely used options */ +#ifndef LWIP_DNS_API_DECLARE_H_ERRNO +#define LWIP_DNS_API_DECLARE_H_ERRNO 1 +#endif + +#ifndef LWIP_DNS_API_DEFINE_ERRORS +#define LWIP_DNS_API_DEFINE_ERRORS 1 +#endif + +#ifndef LWIP_DNS_API_DEFINE_FLAGS +#define LWIP_DNS_API_DEFINE_FLAGS 1 +#endif + +#ifndef LWIP_DNS_API_DECLARE_STRUCTS +#define LWIP_DNS_API_DECLARE_STRUCTS 1 +#endif + +#if LWIP_DNS_API_DEFINE_ERRORS +/** Errors used by the DNS API functions, h_errno can be one of them */ +#define EAI_NONAME 200 +#define EAI_SERVICE 201 +#define EAI_FAIL 202 +#define EAI_MEMORY 203 +#define EAI_FAMILY 204 + +#define HOST_NOT_FOUND 210 +#define NO_DATA 211 +#define NO_RECOVERY 212 +#define TRY_AGAIN 213 +#endif /* LWIP_DNS_API_DEFINE_ERRORS */ + +#if LWIP_DNS_API_DEFINE_FLAGS +/* input flags for struct addrinfo */ +#define AI_PASSIVE 0x01 +#define AI_CANONNAME 0x02 +#define AI_NUMERICHOST 0x04 +#define AI_NUMERICSERV 0x08 +#define AI_V4MAPPED 0x10 +#define AI_ALL 0x20 +#define AI_ADDRCONFIG 0x40 +#endif /* LWIP_DNS_API_DEFINE_FLAGS */ + +#if LWIP_DNS_API_DECLARE_STRUCTS +struct hostent { + char *h_name; /* Official name of the host. */ + char **h_aliases; /* A pointer to an array of pointers to alternative host names, + terminated by a null pointer. */ + int h_addrtype; /* Address type. */ + int h_length; /* The length, in bytes, of the address. */ + char **h_addr_list; /* A pointer to an array of pointers to network addresses (in + network byte order) for the host, terminated by a null pointer. */ +#define h_addr h_addr_list[0] /* for backward compatibility */ +}; + +struct addrinfo { + int ai_flags; /* Input flags. */ + int ai_family; /* Address family of socket. */ + int ai_socktype; /* Socket type. */ + int ai_protocol; /* Protocol of socket. */ + socklen_t ai_addrlen; /* Length of socket address. */ + struct sockaddr *ai_addr; /* Socket address of socket. */ + char *ai_canonname; /* Canonical name of service location. */ + struct addrinfo *ai_next; /* Pointer to next in list. */ +}; +#endif /* LWIP_DNS_API_DECLARE_STRUCTS */ + +#define NETDB_ELEM_SIZE (sizeof(struct addrinfo) + sizeof(struct sockaddr_storage) + DNS_MAX_NAME_LENGTH + 1) + +#if LWIP_DNS_API_DECLARE_H_ERRNO +/* application accessible error code set by the DNS API functions */ +extern int h_errno; +#endif /* LWIP_DNS_API_DECLARE_H_ERRNO*/ + +struct hostent *lwip_gethostbyname(const char *name); +int lwip_gethostbyname_r(const char *name, struct hostent *ret, char *buf, + size_t buflen, struct hostent **result, int *h_errnop); +void lwip_freeaddrinfo(struct addrinfo *ai); +int lwip_getaddrinfo(const char *nodename, + const char *servname, + const struct addrinfo *hints, + struct addrinfo **res); + +#if LWIP_COMPAT_SOCKETS +#define gethostbyname(name) lwip_gethostbyname(name) +#define gethostbyname_r(name, ret, buf, buflen, result, h_errnop) \ + lwip_gethostbyname_r(name, ret, buf, buflen, result, h_errnop) +#define freeaddrinfo(addrinfo) lwip_freeaddrinfo(addrinfo) +#define getaddrinfo(nodname, servname, hints, res) \ + lwip_getaddrinfo(nodname, servname, hints, res) +#endif /* LWIP_COMPAT_SOCKETS */ + +#ifdef __cplusplus +} +#endif + +#endif /* LWIP_DNS && LWIP_SOCKET */ + +#endif /* LWIP_HDR_NETDB_H */ diff --git a/components/lwip/include/lwip/lwip/netif.h b/components/lwip/include/lwip/lwip/netif.h new file mode 100755 index 0000000000..99066a5a1f --- /dev/null +++ b/components/lwip/include/lwip/lwip/netif.h @@ -0,0 +1,447 @@ +/* + * Copyright (c) 2001-2004 Swedish Institute of Computer Science. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + * + */ +#ifndef LWIP_HDR_NETIF_H +#define LWIP_HDR_NETIF_H + +#include "lwip/opt.h" + +#define ENABLE_LOOPBACK (LWIP_NETIF_LOOPBACK || LWIP_HAVE_LOOPIF) + +#include "lwip/err.h" + +#include "lwip/ip_addr.h" + +#include "lwip/def.h" +#include "lwip/pbuf.h" +#include "lwip/stats.h" + +#if LWIP_DHCP +struct dhcp; +#endif +#if LWIP_AUTOIP +struct autoip; +#endif +#if LWIP_IPV6_DHCP6 +struct dhcp6; +#endif /* LWIP_IPV6_DHCP6 */ + +#ifdef __cplusplus +extern "C" { +#endif + +/* Throughout this file, IP addresses are expected to be in + * the same byte order as in IP_PCB. */ + +/** Must be the maximum of all used hardware address lengths + across all types of interfaces in use. + This does not have to be changed, normally. */ +#ifndef NETIF_MAX_HWADDR_LEN +#define NETIF_MAX_HWADDR_LEN 6U +#endif + +/** Whether the network interface is 'up'. This is + * a software flag used to control whether this network + * interface is enabled and processes traffic. + * It must be set by the startup code before this netif can be used + * (also for dhcp/autoip). + */ +#define NETIF_FLAG_UP 0x01U +/** If set, the netif has broadcast capability. + * Set by the netif driver in its init function. */ +#define NETIF_FLAG_BROADCAST 0x02U +/** If set, the interface has an active link + * (set by the network interface driver). + * Either set by the netif driver in its init function (if the link + * is up at that time) or at a later point once the link comes up + * (if link detection is supported by the hardware). */ +#define NETIF_FLAG_LINK_UP 0x04U +/** If set, the netif is an ethernet device using ARP. + * Set by the netif driver in its init function. + * Used to check input packet types and use of DHCP. */ +#define NETIF_FLAG_ETHARP 0x08U +/** If set, the netif is an ethernet device. It might not use + * ARP or TCP/IP if it is used for PPPoE only. + */ +#define NETIF_FLAG_ETHERNET 0x10U +/** If set, the netif has IGMP capability. + * Set by the netif driver in its init function. */ +#define NETIF_FLAG_IGMP 0x20U +/** If set, the netif has MLD6 capability. + * Set by the netif driver in its init function. */ +#define NETIF_FLAG_MLD6 0x40U + +#if LWIP_CHECKSUM_CTRL_PER_NETIF +#define NETIF_CHECKSUM_GEN_IP 0x0001 +#define NETIF_CHECKSUM_GEN_UDP 0x0002 +#define NETIF_CHECKSUM_GEN_TCP 0x0004 +#define NETIF_CHECKSUM_GEN_ICMP 0x0008 +#define NETIF_CHECKSUM_GEN_ICMP6 0x0010 +#define NETIF_CHECKSUM_CHECK_IP 0x0100 +#define NETIF_CHECKSUM_CHECK_UDP 0x0200 +#define NETIF_CHECKSUM_CHECK_TCP 0x0400 +#define NETIF_CHECKSUM_CHECK_ICMP 0x0800 +#define NETIF_CHECKSUM_CHECK_ICMP6 0x1000 +#define NETIF_CHECKSUM_ENABLE_ALL 0xFFFF +#define NETIF_CHECKSUM_DISABLE_ALL 0x0000 +#endif /* LWIP_CHECKSUM_CTRL_PER_NETIF */ + +struct netif; + +/** Function prototype for netif init functions. Set up flags and output/linkoutput + * callback functions in this function. + * + * @param netif The netif to initialize + */ +typedef err_t (*netif_init_fn)(struct netif *netif); +/** Function prototype for netif->input functions. This function is saved as 'input' + * callback function in the netif struct. Call it when a packet has been received. + * + * @param p The received packet, copied into a pbuf + * @param inp The netif which received the packet + */ +typedef err_t (*netif_input_fn)(struct pbuf *p, struct netif *inp); + +#if LWIP_IPV4 +/** Function prototype for netif->output functions. Called by lwIP when a packet + * shall be sent. For ethernet netif, set this to 'etharp_output' and set + * 'linkoutput'. + * + * @param netif The netif which shall send a packet + * @param p The packet to send (p->payload points to IP header) + * @param ipaddr The IP address to which the packet shall be sent + */ +typedef err_t (*netif_output_fn)(struct netif *netif, struct pbuf *p, + const ip4_addr_t *ipaddr); +#endif /* LWIP_IPV4*/ + +#if LWIP_IPV6 +/** Function prototype for netif->output_ip6 functions. Called by lwIP when a packet + * shall be sent. For ethernet netif, set this to 'ethip6_output' and set + * 'linkoutput'. + * + * @param netif The netif which shall send a packet + * @param p The packet to send (p->payload points to IP header) + * @param ipaddr The IPv6 address to which the packet shall be sent + */ +typedef err_t (*netif_output_ip6_fn)(struct netif *netif, struct pbuf *p, + const ip6_addr_t *ipaddr); +#endif /* LWIP_IPV6 */ + +/** Function prototype for netif->linkoutput functions. Only used for ethernet + * netifs. This function is called by ARP when a packet shall be sent. + * + * @param netif The netif which shall send a packet + * @param p The packet to send (raw ethernet packet) + */ +typedef err_t (*netif_linkoutput_fn)(struct netif *netif, struct pbuf *p); +/** Function prototype for netif status- or link-callback functions. */ +typedef void (*netif_status_callback_fn)(struct netif *netif); +#if LWIP_IPV4 && LWIP_IGMP +/** Function prototype for netif igmp_mac_filter functions */ +typedef err_t (*netif_igmp_mac_filter_fn)(struct netif *netif, + const ip4_addr_t *group, u8_t action); +#endif /* LWIP_IPV4 && LWIP_IGMP */ +#if LWIP_IPV6 && LWIP_IPV6_MLD +/** Function prototype for netif mld_mac_filter functions */ +typedef err_t (*netif_mld_mac_filter_fn)(struct netif *netif, + const ip6_addr_t *group, u8_t action); +#endif /* LWIP_IPV6 && LWIP_IPV6_MLD */ + + +#ifdef LWIP_ESP8266 +/*add DHCP event processing by LiuHan*/ +typedef void (*dhcp_event_fn)(void); +#endif + + +/** Generic data structure used for all lwIP network interfaces. + * The following fields should be filled in by the initialization + * function for the device driver: hwaddr_len, hwaddr[], mtu, flags */ +struct netif { + /** pointer to next in linked list */ + struct netif *next; + +#ifdef LWIP_ESP8266 +//ip_addr_t is changed by marco IPV4, IPV6 + ip_addr_t link_local_addr; +#endif + +#if LWIP_IPV4 + /** IP address configuration in network byte order */ + ip_addr_t ip_addr; + ip_addr_t netmask; + ip_addr_t gw; +#endif /* LWIP_IPV4 */ +#if LWIP_IPV6 + /** Array of IPv6 addresses for this netif. */ + ip_addr_t ip6_addr[LWIP_IPV6_NUM_ADDRESSES]; + /** The state of each IPv6 address (Tentative, Preferred, etc). + * @see ip6_addr.h */ + u8_t ip6_addr_state[LWIP_IPV6_NUM_ADDRESSES]; +#endif /* LWIP_IPV6 */ + /** This function is called by the network device driver + * to pass a packet up the TCP/IP stack. */ + netif_input_fn input; +#if LWIP_IPV4 + /** This function is called by the IP module when it wants + * to send a packet on the interface. This function typically + * first resolves the hardware address, then sends the packet. */ + netif_output_fn output; +#endif /* LWIP_IPV4 */ + /** This function is called by the ARP module when it wants + * to send a packet on the interface. This function outputs + * the pbuf as-is on the link medium. */ + netif_linkoutput_fn linkoutput; +#if LWIP_IPV6 + /** This function is called by the IPv6 module when it wants + * to send a packet on the interface. This function typically + * first resolves the hardware address, then sends the packet. */ + netif_output_ip6_fn output_ip6; +#endif /* LWIP_IPV6 */ +#if LWIP_NETIF_STATUS_CALLBACK + /** This function is called when the netif state is set to up or down + */ + netif_status_callback_fn status_callback; +#endif /* LWIP_NETIF_STATUS_CALLBACK */ +#if LWIP_NETIF_LINK_CALLBACK + /** This function is called when the netif link is set to up or down + */ + netif_status_callback_fn link_callback; +#endif /* LWIP_NETIF_LINK_CALLBACK */ +#if LWIP_NETIF_REMOVE_CALLBACK + /** This function is called when the netif has been removed */ + netif_status_callback_fn remove_callback; +#endif /* LWIP_NETIF_REMOVE_CALLBACK */ + /** This field can be set by the device driver and could point + * to state information for the device. */ + void *state; +#if LWIP_DHCP + /** the DHCP client state information for this netif */ + struct dhcp *dhcp; + +#ifdef LWIP_ESP8266 + struct udp_pcb *dhcps_pcb; + dhcp_event_fn dhcp_event; +#endif + +#endif /* LWIP_DHCP */ + +#if LWIP_AUTOIP + /** the AutoIP client state information for this netif */ + struct autoip *autoip; +#endif + +#if LWIP_IPV6_AUTOCONFIG + /** is this netif enabled for IPv6 autoconfiguration */ + u8_t ip6_autoconfig_enabled; +#endif /* LWIP_IPV6_AUTOCONFIG */ + +#if LWIP_IPV6_SEND_ROUTER_SOLICIT + /** Number of Router Solicitation messages that remain to be sent. */ + u8_t rs_count; +#endif /* LWIP_IPV6_SEND_ROUTER_SOLICIT */ + +#if LWIP_IPV6_DHCP6 + /** the DHCPv6 client state information for this netif */ + struct dhcp6 *dhcp6; +#endif /* LWIP_IPV6_DHCP6 */ + +#if LWIP_NETIF_HOSTNAME + /* the hostname for this netif, NULL is a valid value */ + const char* hostname; +#endif /* LWIP_NETIF_HOSTNAME */ + +#if LWIP_CHECKSUM_CTRL_PER_NETIF + u16_t chksum_flags; +#endif /* LWIP_CHECKSUM_CTRL_PER_NETIF*/ + + /** maximum transfer unit (in bytes) */ + u16_t mtu; + /** number of bytes used in hwaddr */ + u8_t hwaddr_len; + /** link level hardware address of this interface */ + u8_t hwaddr[NETIF_MAX_HWADDR_LEN]; + /** flags (see NETIF_FLAG_ above) */ + u8_t flags; + /** descriptive abbreviation */ + char name[2]; + /** number of this interface */ + u8_t num; + +#if MIB2_STATS + /** link type (from "snmp_ifType" enum from snmp_mib2.h) */ + u8_t link_type; + /** (estimate) link speed */ + u32_t link_speed; + /** timestamp at last change made (up/down) */ + u32_t ts; + /** counters */ + struct stats_mib2_netif_ctrs mib2_counters; +#endif /* MIB2_STATS */ + +#if LWIP_IPV4 && LWIP_IGMP + /** This function could be called to add or delete an entry in the multicast + filter table of the ethernet MAC.*/ + netif_igmp_mac_filter_fn igmp_mac_filter; +#endif /* LWIP_IPV4 && LWIP_IGMP */ + +#if LWIP_IPV6 && LWIP_IPV6_MLD + /** This function could be called to add or delete an entry in the IPv6 multicast + filter table of the ethernet MAC. */ + netif_mld_mac_filter_fn mld_mac_filter; +#endif /* LWIP_IPV6 && LWIP_IPV6_MLD */ + +#if LWIP_NETIF_HWADDRHINT + u8_t *addr_hint; +#endif /* LWIP_NETIF_HWADDRHINT */ +#if ENABLE_LOOPBACK + /* List of packets to be queued for ourselves. */ + struct pbuf *loop_first; + struct pbuf *loop_last; +#if LWIP_LOOPBACK_MAX_PBUFS + u16_t loop_cnt_current; +#endif /* LWIP_LOOPBACK_MAX_PBUFS */ +#endif /* ENABLE_LOOPBACK */ +}; + +#if LWIP_CHECKSUM_CTRL_PER_NETIF +#define NETIF_SET_CHECKSUM_CTRL(netif, chksumflags) do { \ + (netif)->chksum_flags = chksumflags; } while(0) +#define IF__NETIF_CHECKSUM_ENABLED(netif, chksumflag) if (((netif) == NULL) || (((netif)->chksum_flags & (chksumflag)) != 0)) +#else /* LWIP_CHECKSUM_CTRL_PER_NETIF */ +#define NETIF_SET_CHECKSUM_CTRL(netif, chksumflags) +#define IF__NETIF_CHECKSUM_ENABLED(netif, chksumflag) +#endif /* LWIP_CHECKSUM_CTRL_PER_NETIF */ + +/** The list of network interfaces. */ +extern struct netif *netif_list; +/** The default network interface. */ +extern struct netif *netif_default; + +void netif_init(void); + +struct netif *netif_add(struct netif *netif, +#if LWIP_IPV4 + const ip4_addr_t *ipaddr, const ip4_addr_t *netmask, const ip4_addr_t *gw, +#endif /* LWIP_IPV4 */ + void *state, netif_init_fn init, netif_input_fn input); +#if LWIP_IPV4 +void netif_set_addr(struct netif *netif, const ip4_addr_t *ipaddr, const ip4_addr_t *netmask, + const ip4_addr_t *gw); +#endif /* LWIP_IPV4 */ +void netif_remove(struct netif * netif); + +/* Returns a network interface given its name. The name is of the form + "et0", where the first two letters are the "name" field in the + netif structure, and the digit is in the num field in the same + structure. */ +struct netif *netif_find(const char *name); + +void netif_set_default(struct netif *netif); + +#if LWIP_IPV4 +void netif_set_ipaddr(struct netif *netif, const ip4_addr_t *ipaddr); +void netif_set_netmask(struct netif *netif, const ip4_addr_t *netmask); +void netif_set_gw(struct netif *netif, const ip4_addr_t *gw); +#define netif_ip4_addr(netif) ((const ip4_addr_t*)ip_2_ip4(&((netif)->ip_addr))) +#define netif_ip4_netmask(netif) ((const ip4_addr_t*)ip_2_ip4(&((netif)->netmask))) +#define netif_ip4_gw(netif) ((const ip4_addr_t*)ip_2_ip4(&((netif)->gw))) +#define netif_ip_addr4(netif) ((const ip_addr_t*)&((netif)->ip_addr)) +#define netif_ip_gw4(netif) ((const ip_addr_t*)&((netif)->gw)) +#endif /* LWIP_IPV4 */ + +void netif_set_up(struct netif *netif); +void netif_set_down(struct netif *netif); +/** Ask if an interface is up */ +#define netif_is_up(netif) (((netif)->flags & NETIF_FLAG_UP) ? (u8_t)1 : (u8_t)0) + +#if LWIP_NETIF_STATUS_CALLBACK +void netif_set_status_callback(struct netif *netif, netif_status_callback_fn status_callback); +#endif /* LWIP_NETIF_STATUS_CALLBACK */ +#if LWIP_NETIF_REMOVE_CALLBACK +void netif_set_remove_callback(struct netif *netif, netif_status_callback_fn remove_callback); +#endif /* LWIP_NETIF_REMOVE_CALLBACK */ + +void netif_set_link_up(struct netif *netif); +void netif_set_link_down(struct netif *netif); +/** Ask if a link is up */ +#define netif_is_link_up(netif) (((netif)->flags & NETIF_FLAG_LINK_UP) ? (u8_t)1 : (u8_t)0) + +#if LWIP_NETIF_LINK_CALLBACK +void netif_set_link_callback(struct netif *netif, netif_status_callback_fn link_callback); +#endif /* LWIP_NETIF_LINK_CALLBACK */ + +#if LWIP_NETIF_HOSTNAME +#define netif_set_hostname(netif, name) do { if((netif) != NULL) { (netif)->hostname = name; }}while(0) +#define netif_get_hostname(netif) (((netif) != NULL) ? ((netif)->hostname) : NULL) +#endif /* LWIP_NETIF_HOSTNAME */ + +#if LWIP_IGMP +#define netif_set_igmp_mac_filter(netif, function) do { if((netif) != NULL) { (netif)->igmp_mac_filter = function; }}while(0) +#define netif_get_igmp_mac_filter(netif) (((netif) != NULL) ? ((netif)->igmp_mac_filter) : NULL) +#endif /* LWIP_IGMP */ + +#if LWIP_IPV6 && LWIP_IPV6_MLD +#define netif_set_mld_mac_filter(netif, function) do { if((netif) != NULL) { (netif)->mld_mac_filter = function; }}while(0) +#define netif_get_mld_mac_filter(netif) (((netif) != NULL) ? ((netif)->mld_mac_filter) : NULL) +#endif /* LWIP_IPV6 && LWIP_IPV6_MLD */ + +#if ENABLE_LOOPBACK +err_t netif_loop_output(struct netif *netif, struct pbuf *p); +void netif_poll(struct netif *netif); +#if !LWIP_NETIF_LOOPBACK_MULTITHREADING +void netif_poll_all(void); +#endif /* !LWIP_NETIF_LOOPBACK_MULTITHREADING */ +#endif /* ENABLE_LOOPBACK */ + +#if LWIP_IPV6 +#define netif_ip_addr6(netif, i) ((const ip_addr_t*)(&((netif)->ip6_addr[i]))) +#define netif_ip6_addr(netif, i) ((const ip6_addr_t*)ip_2_ip6(&((netif)->ip6_addr[i]))) +#define netif_ip6_addr_set(netif, i, addr6) do { ip6_addr_set(ip_2_ip6(&((netif)->ip6_addr[i])), addr6); IP_SET_TYPE_VAL((netif)->ip6_addr[i], IPADDR_TYPE_V6); } while(0) +#define netif_ip6_addr_state(netif, i) ((netif)->ip6_addr_state[i]) +#define netif_ip6_addr_set_state(netif, i, state) ((netif)->ip6_addr_state[i] = (state)) +s8_t netif_get_ip6_addr_match(struct netif *netif, const ip6_addr_t *ip6addr); +void netif_create_ip6_linklocal_address(struct netif *netif, u8_t from_mac_48bit); +err_t netif_add_ip6_address(struct netif *netif, const ip6_addr_t *ip6addr, s8_t *chosen_idx); +#endif /* LWIP_IPV6 */ + +#if LWIP_NETIF_HWADDRHINT +#define NETIF_SET_HWADDRHINT(netif, hint) ((netif)->addr_hint = (hint)) +#else /* LWIP_NETIF_HWADDRHINT */ +#define NETIF_SET_HWADDRHINT(netif, hint) +#endif /* LWIP_NETIF_HWADDRHINT */ + +#ifdef __cplusplus +} +#endif + +#endif /* LWIP_HDR_NETIF_H */ diff --git a/components/lwip/include/lwip/lwip/netifapi.h b/components/lwip/include/lwip/lwip/netifapi.h new file mode 100755 index 0000000000..b09316be66 --- /dev/null +++ b/components/lwip/include/lwip/lwip/netifapi.h @@ -0,0 +1,108 @@ +/* + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + */ +#ifndef LWIP_HDR_NETIFAPI_H +#define LWIP_HDR_NETIFAPI_H + +#include "lwip/opt.h" + +#if LWIP_NETIF_API /* don't build if not configured for use in lwipopts.h */ + +#include "lwip/sys.h" +#include "lwip/netif.h" +#include "lwip/dhcp.h" +#include "lwip/autoip.h" +#include "lwip/priv/tcpip_priv.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#if LWIP_MPU_COMPATIBLE +#define NETIFAPI_IPADDR_DEF(type, m) type m +#else /* LWIP_MPU_COMPATIBLE */ +#define NETIFAPI_IPADDR_DEF(type, m) const type * m +#endif /* LWIP_MPU_COMPATIBLE */ + +typedef void (*netifapi_void_fn)(struct netif *netif); +typedef err_t (*netifapi_errt_fn)(struct netif *netif); + +struct netifapi_msg { + struct tcpip_api_call call; + struct netif *netif; + union { + struct { +#if LWIP_IPV4 + NETIFAPI_IPADDR_DEF(ip4_addr_t, ipaddr); + NETIFAPI_IPADDR_DEF(ip4_addr_t, netmask); + NETIFAPI_IPADDR_DEF(ip4_addr_t, gw); +#endif /* LWIP_IPV4 */ + void *state; + netif_init_fn init; + netif_input_fn input; + } add; + struct { + netifapi_void_fn voidfunc; + netifapi_errt_fn errtfunc; + } common; + } msg; +}; + + +/* API for application */ +err_t netifapi_netif_add(struct netif *netif, +#if LWIP_IPV4 + const ip4_addr_t *ipaddr, const ip4_addr_t *netmask, const ip4_addr_t *gw, +#endif /* LWIP_IPV4 */ + void *state, netif_init_fn init, netif_input_fn input); + +#if LWIP_IPV4 +err_t netifapi_netif_set_addr(struct netif *netif, const ip4_addr_t *ipaddr, + const ip4_addr_t *netmask, const ip4_addr_t *gw); +#endif /* LWIP_IPV4*/ + +err_t netifapi_netif_common(struct netif *netif, netifapi_void_fn voidfunc, + netifapi_errt_fn errtfunc); + +#define netifapi_netif_remove(n) netifapi_netif_common(n, netif_remove, NULL) +#define netifapi_netif_set_up(n) netifapi_netif_common(n, netif_set_up, NULL) +#define netifapi_netif_set_down(n) netifapi_netif_common(n, netif_set_down, NULL) +#define netifapi_netif_set_default(n) netifapi_netif_common(n, netif_set_default, NULL) +#define netifapi_dhcp_start(n) netifapi_netif_common(n, NULL, dhcp_start) +#define netifapi_dhcp_stop(n) netifapi_netif_common(n, dhcp_stop, NULL) +#define netifapi_dhcp_inform(n) netifapi_netif_common(n, dhcp_inform, NULL) +#define netifapi_dhcp_renew(n) netifapi_netif_common(n, NULL, dhcp_renew) +#define netifapi_dhcp_release(n) netifapi_netif_common(n, NULL, dhcp_release) +#define netifapi_autoip_start(n) netifapi_netif_common(n, NULL, autoip_start) +#define netifapi_autoip_stop(n) netifapi_netif_common(n, NULL, autoip_stop) + +#ifdef __cplusplus +} +#endif + +#endif /* LWIP_NETIF_API */ + +#endif /* LWIP_HDR_NETIFAPI_H */ diff --git a/components/lwip/include/lwip/lwip/opt.h b/components/lwip/include/lwip/lwip/opt.h new file mode 100755 index 0000000000..76fff88052 --- /dev/null +++ b/components/lwip/include/lwip/lwip/opt.h @@ -0,0 +1,3015 @@ +/** + * @file + * + * lwIP Options Configuration + */ + +/* + * Copyright (c) 2001-2004 Swedish Institute of Computer Science. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + * + */ +#ifndef LWIP_HDR_OPT_H +#define LWIP_HDR_OPT_H + +/* + * Include user defined options first. Anything not defined in these files + * will be set to standard values. Override anything you don't like! + */ +#include "lwipopts.h" +#include "lwip/debug.h" + +/* + ----------------------------------------------- + ---------- Platform specific locking ---------- + ----------------------------------------------- +*/ + +/** + * SYS_LIGHTWEIGHT_PROT==1: if you want inter-task protection for certain + * critical regions during buffer allocation, deallocation and memory + * allocation and deallocation. + */ +#ifndef SYS_LIGHTWEIGHT_PROT +#define SYS_LIGHTWEIGHT_PROT 0 +#endif + +/** + * NO_SYS==1: Provides VERY minimal functionality. Otherwise, + * use lwIP facilities. + */ +#ifndef NO_SYS +#define NO_SYS 0 +#endif + +/** + * NO_SYS_NO_TIMERS==1: Drop support for sys_timeout when NO_SYS==1 + * Mainly for compatibility to old versions. + */ +#ifndef NO_SYS_NO_TIMERS +#define NO_SYS_NO_TIMERS 0 +#endif + +/** + * MEMCPY: override this if you have a faster implementation at hand than the + * one included in your C library + */ +#ifndef MEMCPY +#define MEMCPY(dst,src,len) memcpy(dst,src,len) +#endif + +/** + * SMEMCPY: override this with care! Some compilers (e.g. gcc) can inline a + * call to memcpy() if the length is known at compile time and is small. + */ +#ifndef SMEMCPY +#define SMEMCPY(dst,src,len) memcpy(dst,src,len) +#endif + +/** + * LWIP_MPU_COMPATIBLE: enables special memory management mechanism + * which makes lwip able to work on MPU (Memory Protection Unit) system + * by not passing stack-pointers to other threads + * (this decreases performance) + */ +#ifndef LWIP_MPU_COMPATIBLE +#define LWIP_MPU_COMPATIBLE 0 +#endif + +/* + ------------------------------------ + ---------- Memory options ---------- + ------------------------------------ +*/ +/** + * MEM_LIBC_MALLOC==1: Use malloc/free/realloc provided by your C-library + * instead of the lwip internal allocator. Can save code size if you + * already use it. + */ +#ifndef MEM_LIBC_MALLOC +#define MEM_LIBC_MALLOC 0 +#endif + +/** +* MEMP_MEM_MALLOC==1: Use mem_malloc/mem_free instead of the lwip pool allocator. +* Especially useful with MEM_LIBC_MALLOC but handle with care regarding execution +* speed and usage from interrupts! +*/ +#ifndef MEMP_MEM_MALLOC +#define MEMP_MEM_MALLOC 0 +#endif + +/** + * MEM_ALIGNMENT: should be set to the alignment of the CPU + * 4 byte alignment -> #define MEM_ALIGNMENT 4 + * 2 byte alignment -> #define MEM_ALIGNMENT 2 + */ +#ifndef MEM_ALIGNMENT +#define MEM_ALIGNMENT 1 +#endif + +/** + * MEM_SIZE: the size of the heap memory. If the application will send + * a lot of data that needs to be copied, this should be set high. + */ +#ifndef MEM_SIZE +#define MEM_SIZE 1600 +#endif + +/** + * MEMP_OVERFLOW_CHECK: memp overflow protection reserves a configurable + * amount of bytes before and after each memp element in every pool and fills + * it with a prominent default value. + * MEMP_OVERFLOW_CHECK == 0 no checking + * MEMP_OVERFLOW_CHECK == 1 checks each element when it is freed + * MEMP_OVERFLOW_CHECK >= 2 checks each element in every pool every time + * memp_malloc() or memp_free() is called (useful but slow!) + */ +#ifndef MEMP_OVERFLOW_CHECK +#define MEMP_OVERFLOW_CHECK 0 +#endif + +/** + * MEMP_SANITY_CHECK==1: run a sanity check after each memp_free() to make + * sure that there are no cycles in the linked lists. + */ +#ifndef MEMP_SANITY_CHECK +#define MEMP_SANITY_CHECK 0 +#endif + +/** + * MEM_USE_POOLS==1: Use an alternative to malloc() by allocating from a set + * of memory pools of various sizes. When mem_malloc is called, an element of + * the smallest pool that can provide the length needed is returned. + * To use this, MEMP_USE_CUSTOM_POOLS also has to be enabled. + */ +#ifndef MEM_USE_POOLS +#define MEM_USE_POOLS 0 +#endif + +/** + * MEM_USE_POOLS_TRY_BIGGER_POOL==1: if one malloc-pool is empty, try the next + * bigger pool - WARNING: THIS MIGHT WASTE MEMORY but it can make a system more + * reliable. */ +#ifndef MEM_USE_POOLS_TRY_BIGGER_POOL +#define MEM_USE_POOLS_TRY_BIGGER_POOL 0 +#endif + +/** + * MEMP_USE_CUSTOM_POOLS==1: whether to include a user file lwippools.h + * that defines additional pools beyond the "standard" ones required + * by lwIP. If you set this to 1, you must have lwippools.h in your + * include path somewhere. + */ +#ifndef MEMP_USE_CUSTOM_POOLS +#define MEMP_USE_CUSTOM_POOLS 0 +#endif + +/** + * Set this to 1 if you want to free PBUF_RAM pbufs (or call mem_free()) from + * interrupt context (or another context that doesn't allow waiting for a + * semaphore). + * If set to 1, mem_malloc will be protected by a semaphore and SYS_ARCH_PROTECT, + * while mem_free will only use SYS_ARCH_PROTECT. mem_malloc SYS_ARCH_UNPROTECTs + * with each loop so that mem_free can run. + * + * ATTENTION: As you can see from the above description, this leads to dis-/ + * enabling interrupts often, which can be slow! Also, on low memory, mem_malloc + * can need longer. + * + * If you don't want that, at least for NO_SYS=0, you can still use the following + * functions to enqueue a deallocation call which then runs in the tcpip_thread + * context: + * - pbuf_free_callback(p); + * - mem_free_callback(m); + */ +#ifndef LWIP_ALLOW_MEM_FREE_FROM_OTHER_CONTEXT +#define LWIP_ALLOW_MEM_FREE_FROM_OTHER_CONTEXT 0 +#endif + +/* + ------------------------------------------------ + ---------- Internal Memory Pool Sizes ---------- + ------------------------------------------------ +*/ +/** + * MEMP_NUM_PBUF: the number of memp struct pbufs (used for PBUF_ROM and PBUF_REF). + * If the application sends a lot of data out of ROM (or other static memory), + * this should be set high. + */ +#ifndef MEMP_NUM_PBUF +#define MEMP_NUM_PBUF 16 +#endif + +/** + * MEMP_NUM_RAW_PCB: Number of raw connection PCBs + * (requires the LWIP_RAW option) + */ +#ifndef MEMP_NUM_RAW_PCB +#define MEMP_NUM_RAW_PCB 4 +#endif + +/** + * MEMP_NUM_UDP_PCB: the number of UDP protocol control blocks. One + * per active UDP "connection". + * (requires the LWIP_UDP option) + */ +#ifndef MEMP_NUM_UDP_PCB +#define MEMP_NUM_UDP_PCB 4 +#endif + +/** + * MEMP_NUM_TCP_PCB: the number of simultaneously active TCP connections. + * (requires the LWIP_TCP option) + */ +#ifndef MEMP_NUM_TCP_PCB +#define MEMP_NUM_TCP_PCB 5 +#endif + +/** + * MEMP_NUM_TCP_PCB_LISTEN: the number of listening TCP connections. + * (requires the LWIP_TCP option) + */ +#ifndef MEMP_NUM_TCP_PCB_LISTEN +#define MEMP_NUM_TCP_PCB_LISTEN 8 +#endif + +/** + * MEMP_NUM_TCP_SEG: the number of simultaneously queued TCP segments. + * (requires the LWIP_TCP option) + */ +#ifndef MEMP_NUM_TCP_SEG +#define MEMP_NUM_TCP_SEG 16 +#endif + +/** + * MEMP_NUM_REASSDATA: the number of IP packets simultaneously queued for + * reassembly (whole packets, not fragments!) + */ +#ifndef MEMP_NUM_REASSDATA +#define MEMP_NUM_REASSDATA 5 +#endif + +/** + * MEMP_NUM_FRAG_PBUF: the number of IP fragments simultaneously sent + * (fragments, not whole packets!). + * This is only used with IP_FRAG_USES_STATIC_BUF==0 and + * LWIP_NETIF_TX_SINGLE_PBUF==0 and only has to be > 1 with DMA-enabled MACs + * where the packet is not yet sent when netif->output returns. + */ +#ifndef MEMP_NUM_FRAG_PBUF +#define MEMP_NUM_FRAG_PBUF 15 +#endif + +/** + * MEMP_NUM_ARP_QUEUE: the number of simultaneously queued outgoing + * packets (pbufs) that are waiting for an ARP request (to resolve + * their destination address) to finish. + * (requires the ARP_QUEUEING option) + */ +#ifndef MEMP_NUM_ARP_QUEUE +#define MEMP_NUM_ARP_QUEUE 30 +#endif + +/** + * MEMP_NUM_IGMP_GROUP: The number of multicast groups whose network interfaces + * can be members at the same time (one per netif - allsystems group -, plus one + * per netif membership). + * (requires the LWIP_IGMP option) + */ +#ifndef MEMP_NUM_IGMP_GROUP +#define MEMP_NUM_IGMP_GROUP 8 +#endif + +/** + * MEMP_NUM_SYS_TIMEOUT: the number of simultaneously active timeouts. + * The default number of timeouts is calculated here for all enabled modules. + * The formula expects settings to be either '0' or '1'. + */ +#ifndef MEMP_NUM_SYS_TIMEOUT +#define MEMP_NUM_SYS_TIMEOUT (LWIP_TCP + IP_REASSEMBLY + LWIP_ARP + (2*LWIP_DHCP) + LWIP_AUTOIP + LWIP_IGMP + LWIP_DNS + (PPP_SUPPORT*6*MEMP_NUM_PPP_PCB) + (LWIP_IPV6 ? (1 + LWIP_IPV6_REASS + LWIP_IPV6_MLD) : 0)) +#endif + +/** + * MEMP_NUM_NETBUF: the number of struct netbufs. + * (only needed if you use the sequential API, like api_lib.c) + */ +#ifndef MEMP_NUM_NETBUF +#define MEMP_NUM_NETBUF 2 +#endif + +/** + * MEMP_NUM_NETCONN: the number of struct netconns. + * (only needed if you use the sequential API, like api_lib.c) + */ +#ifndef MEMP_NUM_NETCONN +#define MEMP_NUM_NETCONN 4 +#endif + +/** + * MEMP_NUM_TCPIP_MSG_API: the number of struct tcpip_msg, which are used + * for callback/timeout API communication. + * (only needed if you use tcpip.c) + */ +#ifndef MEMP_NUM_TCPIP_MSG_API +#define MEMP_NUM_TCPIP_MSG_API 8 +#endif + +/** + * MEMP_NUM_TCPIP_MSG_INPKT: the number of struct tcpip_msg, which are used + * for incoming packets. + * (only needed if you use tcpip.c) + */ +#ifndef MEMP_NUM_TCPIP_MSG_INPKT +#define MEMP_NUM_TCPIP_MSG_INPKT 8 +#endif + +/** + * MEMP_NUM_NETDB: the number of concurrently running lwip_addrinfo() calls + * (before freeing the corresponding memory using lwip_freeaddrinfo()). + */ +#ifndef MEMP_NUM_NETDB +#define MEMP_NUM_NETDB 1 +#endif + +/** + * MEMP_NUM_LOCALHOSTLIST: the number of host entries in the local host list + * if DNS_LOCAL_HOSTLIST_IS_DYNAMIC==1. + */ +#ifndef MEMP_NUM_LOCALHOSTLIST +#define MEMP_NUM_LOCALHOSTLIST 1 +#endif + +/** + * MEMP_NUM_PPP_PCB: the number of simultaneously active PPP + * connections (requires the PPP_SUPPORT option) + */ +#ifndef MEMP_NUM_PPP_PCB +#define MEMP_NUM_PPP_PCB 1 +#endif + +/** + * MEMP_NUM_PPPOS_INTERFACES: the number of concurrently active PPPoS + * interfaces (only used with PPPOS_SUPPORT==1) + */ +#ifndef MEMP_NUM_PPPOS_INTERFACES +#define MEMP_NUM_PPPOS_INTERFACES MEMP_NUM_PPP_PCB +#endif + +/** + * MEMP_NUM_PPPOE_INTERFACES: the number of concurrently active PPPoE + * interfaces (only used with PPPOE_SUPPORT==1) + */ +#ifndef MEMP_NUM_PPPOE_INTERFACES +#define MEMP_NUM_PPPOE_INTERFACES 1 +#endif + +/** + * MEMP_NUM_PPPOL2TP_INTERFACES: the number of concurrently active PPPoL2TP + * interfaces (only used with PPPOL2TP_SUPPORT==1) + */ +#ifndef MEMP_NUM_PPPOL2TP_INTERFACES +#define MEMP_NUM_PPPOL2TP_INTERFACES 1 +#endif + +/** + * PBUF_POOL_SIZE: the number of buffers in the pbuf pool. + */ +#ifndef PBUF_POOL_SIZE +#define PBUF_POOL_SIZE 16 +#endif + +/** MEMP_NUM_API_MSG: the number of concurrently active calls to various + * socket, netconn, and tcpip functions + */ +#ifndef MEMP_NUM_API_MSG +#define MEMP_NUM_API_MSG MEMP_NUM_TCPIP_MSG_API +#endif + +/** MEMP_NUM_DNS_API_MSG: the number of concurrently active calls to netconn_gethostbyname + */ +#ifndef MEMP_NUM_DNS_API_MSG +#define MEMP_NUM_DNS_API_MSG MEMP_NUM_TCPIP_MSG_API +#endif + +/** MEMP_NUM_SOCKET_SETGETSOCKOPT_DATA: the number of concurrently active calls + * to getsockopt/setsockopt + */ +#ifndef MEMP_NUM_SOCKET_SETGETSOCKOPT_DATA +#define MEMP_NUM_SOCKET_SETGETSOCKOPT_DATA MEMP_NUM_TCPIP_MSG_API +#endif + +/** MEMP_NUM_NETIFAPI_MSG: the number of concurrently active calls to the + * netifapi functions + */ +#ifndef MEMP_NUM_NETIFAPI_MSG +#define MEMP_NUM_NETIFAPI_MSG MEMP_NUM_TCPIP_MSG_API +#endif + +/* + --------------------------------- + ---------- ARP options ---------- + --------------------------------- +*/ +/** + * LWIP_ARP==1: Enable ARP functionality. + */ +#ifndef LWIP_ARP +#define LWIP_ARP 1 +#endif + +/** + * ARP_TABLE_SIZE: Number of active MAC-IP address pairs cached. + */ +#ifndef ARP_TABLE_SIZE +#define ARP_TABLE_SIZE 10 +#endif + +/** the time an ARP entry stays valid after its last update, + * for ARP_TMR_INTERVAL = 1000, this is + * (60 * 5) seconds = 5 minutes. + */ +#ifndef ARP_MAXAGE +#define ARP_MAXAGE 300 +#endif + +/** + * ARP_QUEUEING==1: Multiple outgoing packets are queued during hardware address + * resolution. By default, only the most recent packet is queued per IP address. + * This is sufficient for most protocols and mainly reduces TCP connection + * startup time. Set this to 1 if you know your application sends more than one + * packet in a row to an IP address that is not in the ARP cache. + */ +#ifndef ARP_QUEUEING +#define ARP_QUEUEING 0 +#endif + +/** The maximum number of packets which may be queued for each + * unresolved address by other network layers. Defaults to 3, 0 means disabled. + * Old packets are dropped, new packets are queued. + */ +#ifndef ARP_QUEUE_LEN +#define ARP_QUEUE_LEN 3 +#endif + +/** + * ETHARP_TRUST_IP_MAC==1: Incoming IP packets cause the ARP table to be + * updated with the source MAC and IP addresses supplied in the packet. + * You may want to disable this if you do not trust LAN peers to have the + * correct addresses, or as a limited approach to attempt to handle + * spoofing. If disabled, lwIP will need to make a new ARP request if + * the peer is not already in the ARP table, adding a little latency. + * The peer *is* in the ARP table if it requested our address before. + * Also notice that this slows down input processing of every IP packet! + */ +#ifndef ETHARP_TRUST_IP_MAC +#define ETHARP_TRUST_IP_MAC 0 +#endif + +/** + * ETHARP_SUPPORT_VLAN==1: support receiving and sending ethernet packets with + * VLAN header. See the description of LWIP_HOOK_VLAN_CHECK and + * LWIP_HOOK_VLAN_SET hooks to check/set VLAN headers. + * Additionally, you can define ETHARP_VLAN_CHECK to an u16_t VLAN ID to check. + * If ETHARP_VLAN_CHECK is defined, only VLAN-traffic for this VLAN is accepted. + * If ETHARP_VLAN_CHECK is not defined, all traffic is accepted. + * Alternatively, define a function/define ETHARP_VLAN_CHECK_FN(eth_hdr, vlan) + * that returns 1 to accept a packet or 0 to drop a packet. + */ +#ifndef ETHARP_SUPPORT_VLAN +#define ETHARP_SUPPORT_VLAN 0 +#endif + +/** LWIP_ETHERNET==1: enable ethernet support for PPPoE even though ARP + * might be disabled + */ +#ifndef LWIP_ETHERNET +#define LWIP_ETHERNET (LWIP_ARP || PPPOE_SUPPORT) +#endif + +/** ETH_PAD_SIZE: number of bytes added before the ethernet header to ensure + * alignment of payload after that header. Since the header is 14 bytes long, + * without this padding e.g. addresses in the IP header will not be aligned + * on a 32-bit boundary, so setting this to 2 can speed up 32-bit-platforms. + */ +#ifndef ETH_PAD_SIZE +#define ETH_PAD_SIZE 0 +#endif + +/** ETHARP_SUPPORT_STATIC_ENTRIES==1: enable code to support static ARP table + * entries (using etharp_add_static_entry/etharp_remove_static_entry). + */ +#ifndef ETHARP_SUPPORT_STATIC_ENTRIES +#define ETHARP_SUPPORT_STATIC_ENTRIES 0 +#endif + +/** ETHARP_TABLE_MATCH_NETIF==1: Match netif for ARP table entries. + * If disabled, duplicate IP address on multiple netifs are not supported + * (but this should only occur for AutoIP). + */ +#ifndef ETHARP_TABLE_MATCH_NETIF +#define ETHARP_TABLE_MATCH_NETIF 0 +#endif + +/* + -------------------------------- + ---------- IP options ---------- + -------------------------------- +*/ +/** + * LWIP_IPV4==1: Enable IPv4 + */ +#ifndef LWIP_IPV4 +#define LWIP_IPV4 1 +#endif + +/** + * IP_FORWARD==1: Enables the ability to forward IP packets across network + * interfaces. If you are going to run lwIP on a device with only one network + * interface, define this to 0. + */ +#ifndef IP_FORWARD +#define IP_FORWARD 0 +#endif + +/** + * IP_REASSEMBLY==1: Reassemble incoming fragmented IP packets. Note that + * this option does not affect outgoing packet sizes, which can be controlled + * via IP_FRAG. + */ +#ifndef IP_REASSEMBLY +#define IP_REASSEMBLY 1 +#endif + +/** + * IP_FRAG==1: Fragment outgoing IP packets if their size exceeds MTU. Note + * that this option does not affect incoming packet sizes, which can be + * controlled via IP_REASSEMBLY. + */ +#ifndef IP_FRAG +#define IP_FRAG 1 +#endif + +#if !LWIP_IPV4 +/* disable IPv4 extensions when IPv4 is disabled */ +#undef IP_FORWARD +#define IP_FORWARD 0 +#undef IP_REASSEMBLY +#define IP_REASSEMBLY 0 +#undef IP_FRAG +#define IP_FRAG 0 +#endif /* !LWIP_IPV4 */ + +/** + * IP_OPTIONS_ALLOWED: Defines the behavior for IP options. + * IP_OPTIONS_ALLOWED==0: All packets with IP options are dropped. + * IP_OPTIONS_ALLOWED==1: IP options are allowed (but not parsed). + */ +#ifndef IP_OPTIONS_ALLOWED +#define IP_OPTIONS_ALLOWED 1 +#endif + +/** + * IP_REASS_MAXAGE: Maximum time (in multiples of IP_TMR_INTERVAL - so seconds, normally) + * a fragmented IP packet waits for all fragments to arrive. If not all fragments arrived + * in this time, the whole packet is discarded. + */ +#ifndef IP_REASS_MAXAGE +#define IP_REASS_MAXAGE 3 +#endif + +/** + * IP_REASS_MAX_PBUFS: Total maximum amount of pbufs waiting to be reassembled. + * Since the received pbufs are enqueued, be sure to configure + * PBUF_POOL_SIZE > IP_REASS_MAX_PBUFS so that the stack is still able to receive + * packets even if the maximum amount of fragments is enqueued for reassembly! + */ +#ifndef IP_REASS_MAX_PBUFS +#define IP_REASS_MAX_PBUFS 10 +#endif + +/** + * IP_FRAG_USES_STATIC_BUF==1: Use a static MTU-sized buffer for IP + * fragmentation. Otherwise pbufs are allocated and reference the original + * packet data to be fragmented (or with LWIP_NETIF_TX_SINGLE_PBUF==1, + * new PBUF_RAM pbufs are used for fragments). + * ATTENTION: IP_FRAG_USES_STATIC_BUF==1 may not be used for DMA-enabled MACs! + */ +#ifndef IP_FRAG_USES_STATIC_BUF +#define IP_FRAG_USES_STATIC_BUF 0 +#endif + +/** + * IP_FRAG_MAX_MTU: Assumed max MTU on any interface for IP frag buffer + * (requires IP_FRAG_USES_STATIC_BUF==1) + */ +#if IP_FRAG_USES_STATIC_BUF && !defined(IP_FRAG_MAX_MTU) +#define IP_FRAG_MAX_MTU 1500 +#endif + +/** + * IP_DEFAULT_TTL: Default value for Time-To-Live used by transport layers. + */ +#ifndef IP_DEFAULT_TTL +#define IP_DEFAULT_TTL 255 +#endif + +/** + * IP_SOF_BROADCAST=1: Use the SOF_BROADCAST field to enable broadcast + * filter per pcb on udp and raw send operations. To enable broadcast filter + * on recv operations, you also have to set IP_SOF_BROADCAST_RECV=1. + */ +#ifndef IP_SOF_BROADCAST +#define IP_SOF_BROADCAST 0 +#endif + +/** + * IP_SOF_BROADCAST_RECV (requires IP_SOF_BROADCAST=1) enable the broadcast + * filter on recv operations. + */ +#ifndef IP_SOF_BROADCAST_RECV +#define IP_SOF_BROADCAST_RECV 0 +#endif + +/** + * IP_FORWARD_ALLOW_TX_ON_RX_NETIF==1: allow ip_forward() to send packets back + * out on the netif where it was received. This should only be used for + * wireless networks. + * ATTENTION: When this is 1, make sure your netif driver correctly marks incoming + * link-layer-broadcast/multicast packets as such using the corresponding pbuf flags! + */ +#ifndef IP_FORWARD_ALLOW_TX_ON_RX_NETIF +#define IP_FORWARD_ALLOW_TX_ON_RX_NETIF 0 +#endif + +/** + * LWIP_RANDOMIZE_INITIAL_LOCAL_PORTS==1: randomize the local port for the first + * local TCP/UDP pcb (default==0). This can prevent creating predictable port + * numbers after booting a device. + */ +#ifndef LWIP_RANDOMIZE_INITIAL_LOCAL_PORTS +#define LWIP_RANDOMIZE_INITIAL_LOCAL_PORTS 0 +#endif + +/* + ---------------------------------- + ---------- ICMP options ---------- + ---------------------------------- +*/ +/** + * LWIP_ICMP==1: Enable ICMP module inside the IP stack. + * Be careful, disable that make your product non-compliant to RFC1122 + */ +#ifndef LWIP_ICMP +#define LWIP_ICMP 1 +#endif + +/** + * ICMP_TTL: Default value for Time-To-Live used by ICMP packets. + */ +#ifndef ICMP_TTL +#define ICMP_TTL (IP_DEFAULT_TTL) +#endif + +/** + * LWIP_BROADCAST_PING==1: respond to broadcast pings (default is unicast only) + */ +#ifndef LWIP_BROADCAST_PING +#define LWIP_BROADCAST_PING 0 +#endif + +/** + * LWIP_MULTICAST_PING==1: respond to multicast pings (default is unicast only) + */ +#ifndef LWIP_MULTICAST_PING +#define LWIP_MULTICAST_PING 0 +#endif + +/* + --------------------------------- + ---------- RAW options ---------- + --------------------------------- +*/ +/** + * LWIP_RAW==1: Enable application layer to hook into the IP layer itself. + */ +#ifndef LWIP_RAW +#define LWIP_RAW 0 +#endif + +/** + * LWIP_RAW==1: Enable application layer to hook into the IP layer itself. + */ +#ifndef RAW_TTL +#define RAW_TTL (IP_DEFAULT_TTL) +#endif + +/* + ---------------------------------- + ---------- DHCP options ---------- + ---------------------------------- +*/ +/** + * LWIP_DHCP==1: Enable DHCP module. + */ +#ifndef LWIP_DHCP +#define LWIP_DHCP 0 +#endif +#if !LWIP_IPV4 +/* disable DHCP when IPv4 is disabled */ +#undef LWIP_DHCP +#define LWIP_DHCP 0 +#endif /* !LWIP_IPV4 */ + +/** + * DHCP_DOES_ARP_CHECK==1: Do an ARP check on the offered address. + */ +#ifndef DHCP_DOES_ARP_CHECK +#define DHCP_DOES_ARP_CHECK ((LWIP_DHCP) && (LWIP_ARP)) +#endif + +/** + * LWIP_DHCP_CHECK_LINK_UP==1: dhcp_start() only really starts if the netif has + * NETIF_FLAG_LINK_UP set in its flags. As this is only an optimization and + * netif drivers might not set this flag, the default is off. If enabled, + * netif_set_link_up() must be called to continue dhcp starting. + */ +#ifndef LWIP_DHCP_CHECK_LINK_UP +#define LWIP_DHCP_CHECK_LINK_UP 0 +#endif + +/** + * LWIP_DHCP_BOOTP_FILE==1: Store offered_si_addr and boot_file_name. + */ +#ifndef LWIP_DHCP_BOOTP_FILE +#define LWIP_DHCP_BOOTP_FILE 0 +#endif + +/** + * LWIP_DHCP_GETS_NTP==1: Request NTP servers with discover/select. For each + * response packet, an callback is called, which has to be provided by the port: + * void dhcp_set_ntp_servers(u8_t num_ntp_servers, ip_addr_t* ntp_server_addrs); +*/ +#ifndef LWIP_DHCP_GET_NTP_SRV +#define LWIP_DHCP_GET_NTP_SRV 0 +#endif + +/** + * The maximum of NTP servers requested + */ +#ifndef LWIP_DHCP_MAX_NTP_SERVERS +#define LWIP_DHCP_MAX_NTP_SERVERS 1 +#endif + +/* + ------------------------------------ + ---------- AUTOIP options ---------- + ------------------------------------ +*/ +/** + * LWIP_AUTOIP==1: Enable AUTOIP module. + */ +#ifndef LWIP_AUTOIP +#define LWIP_AUTOIP 0 +#endif +#if !LWIP_IPV4 +/* disable AUTOIP when IPv4 is disabled */ +#undef LWIP_AUTOIP +#define LWIP_AUTOIP 0 +#endif /* !LWIP_IPV4 */ + +/** + * LWIP_DHCP_AUTOIP_COOP==1: Allow DHCP and AUTOIP to be both enabled on + * the same interface at the same time. + */ +#ifndef LWIP_DHCP_AUTOIP_COOP +#define LWIP_DHCP_AUTOIP_COOP 0 +#endif + +/** + * LWIP_DHCP_AUTOIP_COOP_TRIES: Set to the number of DHCP DISCOVER probes + * that should be sent before falling back on AUTOIP. This can be set + * as low as 1 to get an AutoIP address very quickly, but you should + * be prepared to handle a changing IP address when DHCP overrides + * AutoIP. + */ +#ifndef LWIP_DHCP_AUTOIP_COOP_TRIES +#define LWIP_DHCP_AUTOIP_COOP_TRIES 9 +#endif + +/* + ---------------------------------- + ----- SNMP MIB2 support ----- + ---------------------------------- +*/ +/** + * LWIP_MIB2_CALLBACKS==1: Turn on SNMP MIB2 callbacks. + * Turn this on to get callbacks needed to implement MIB2. + * Usually MIB2_STATS should be enabled, too. + */ +#ifndef LWIP_MIB2_CALLBACKS +#define LWIP_MIB2_CALLBACKS 0 +#endif + +/* + ---------------------------------- + ----- Multicast/IGMP options ----- + ---------------------------------- +*/ +/** + * LWIP_IGMP==1: Turn on IGMP module. + */ +#ifndef LWIP_IGMP +#define LWIP_IGMP 1 +#endif +#if !LWIP_IPV4 +#undef LWIP_IGMP +#define LWIP_IGMP 0 +#endif + +/** + * LWIP_MULTICAST_TX_OPTIONS==1: Enable multicast TX support like the socket options + * IP_MULTICAST_TTL/IP_MULTICAST_IF/IP_MULTICAST_LOOP + */ +#ifndef LWIP_MULTICAST_TX_OPTIONS +#define LWIP_MULTICAST_TX_OPTIONS LWIP_IGMP +#endif + +/* + ---------------------------------- + ---------- DNS options ----------- + ---------------------------------- +*/ +/** + * LWIP_DNS==1: Turn on DNS module. UDP must be available for DNS + * transport. + */ +#ifndef LWIP_DNS +#define LWIP_DNS 0 +#endif + +/** DNS maximum number of entries to maintain locally. */ +#ifndef DNS_TABLE_SIZE +#define DNS_TABLE_SIZE 4 +#endif + +/** DNS maximum host name length supported in the name table. */ +#ifndef DNS_MAX_NAME_LENGTH +#define DNS_MAX_NAME_LENGTH 256 +#endif + +/** The maximum of DNS servers + * The first server can be initialized automatically by defining + * DNS_SERVER_ADDRESS(ipaddr), where 'ipaddr' is an 'ip_addr_t*' + */ +#ifndef DNS_MAX_SERVERS +#define DNS_MAX_SERVERS 2 +#endif + +/** DNS do a name checking between the query and the response. */ +#ifndef DNS_DOES_NAME_CHECK +#define DNS_DOES_NAME_CHECK 1 +#endif + +/** LWIP_DNS_SECURE: controls the security level of the DNS implementation + * Use all DNS security features by default. + * This is overridable but should only be needed by very small targets + * or when using against non standard DNS servers. */ +#ifndef LWIP_DNS_SECURE +#define LWIP_DNS_SECURE (LWIP_DNS_SECURE_RAND_XID | LWIP_DNS_SECURE_NO_MULTIPLE_OUTSTANDING | LWIP_DNS_SECURE_RAND_SRC_PORT) +#endif +/* A list of DNS security features follows */ +#define LWIP_DNS_SECURE_RAND_XID 1 +#define LWIP_DNS_SECURE_NO_MULTIPLE_OUTSTANDING 2 +#define LWIP_DNS_SECURE_RAND_SRC_PORT 4 + +/** DNS_LOCAL_HOSTLIST: Implements a local host-to-address list. If enabled, + * you have to define + * #define DNS_LOCAL_HOSTLIST_INIT {{"host1", 0x123}, {"host2", 0x234}} + * (an array of structs name/address, where address is an u32_t in network + * byte order). + * + * Instead, you can also use an external function: + * #define DNS_LOOKUP_LOCAL_EXTERN(x) extern u32_t my_lookup_function(const char *name) + * that returns the IP address or INADDR_NONE if not found. + */ +#ifndef DNS_LOCAL_HOSTLIST +#define DNS_LOCAL_HOSTLIST 0 +#endif /* DNS_LOCAL_HOSTLIST */ + +/** If this is turned on, the local host-list can be dynamically changed + * at runtime. */ +#ifndef DNS_LOCAL_HOSTLIST_IS_DYNAMIC +#define DNS_LOCAL_HOSTLIST_IS_DYNAMIC 0 +#endif /* DNS_LOCAL_HOSTLIST_IS_DYNAMIC */ + +/* + --------------------------------- + ---------- UDP options ---------- + --------------------------------- +*/ +/** + * LWIP_UDP==1: Turn on UDP. + */ +#ifndef LWIP_UDP +#define LWIP_UDP 1 +#endif + +/** + * LWIP_UDPLITE==1: Turn on UDP-Lite. (Requires LWIP_UDP) + */ +#ifndef LWIP_UDPLITE +#define LWIP_UDPLITE 0 +#endif + +/** + * UDP_TTL: Default Time-To-Live value. + */ +#ifndef UDP_TTL +#define UDP_TTL (IP_DEFAULT_TTL) +#endif + +/** + * LWIP_NETBUF_RECVINFO==1: append destination addr and port to every netbuf. + */ +#ifndef LWIP_NETBUF_RECVINFO +#define LWIP_NETBUF_RECVINFO 0 +#endif + +/* + --------------------------------- + ---------- TCP options ---------- + --------------------------------- +*/ +/** + * LWIP_TCP==1: Turn on TCP. + */ +#ifndef LWIP_TCP +#define LWIP_TCP 1 +#endif + +/** + * TCP_TTL: Default Time-To-Live value. + */ +#ifndef TCP_TTL +#define TCP_TTL (IP_DEFAULT_TTL) +#endif + +/** + * TCP_WND: The size of a TCP window. This must be at least + * (2 * TCP_MSS) for things to work well + */ +#ifndef TCP_WND +#define TCP_WND (4 * TCP_MSS) +#endif + +/** + * TCP_MAXRTX: Maximum number of retransmissions of data segments. + */ +#ifndef TCP_MAXRTX +#define TCP_MAXRTX 12 +#endif + +/** + * TCP_SYNMAXRTX: Maximum number of retransmissions of SYN segments. + */ +#ifndef TCP_SYNMAXRTX +#define TCP_SYNMAXRTX 6 +#endif + +/** + * TCP_QUEUE_OOSEQ==1: TCP will queue segments that arrive out of order. + * Define to 0 if your device is low on memory. + */ +#ifndef TCP_QUEUE_OOSEQ +#define TCP_QUEUE_OOSEQ (LWIP_TCP) +#endif + +/** + * TCP_MSS: TCP Maximum segment size. (default is 536, a conservative default, + * you might want to increase this.) + * For the receive side, this MSS is advertised to the remote side + * when opening a connection. For the transmit size, this MSS sets + * an upper limit on the MSS advertised by the remote host. + */ +#ifndef TCP_MSS +#define TCP_MSS 536 +#endif + +/** + * TCP_CALCULATE_EFF_SEND_MSS: "The maximum size of a segment that TCP really + * sends, the 'effective send MSS,' MUST be the smaller of the send MSS (which + * reflects the available reassembly buffer size at the remote host) and the + * largest size permitted by the IP layer" (RFC 1122) + * Setting this to 1 enables code that checks TCP_MSS against the MTU of the + * netif used for a connection and limits the MSS if it would be too big otherwise. + */ +#ifndef TCP_CALCULATE_EFF_SEND_MSS +#define TCP_CALCULATE_EFF_SEND_MSS 1 +#endif + + +/** + * TCP_SND_BUF: TCP sender buffer space (bytes). + * To achieve good performance, this should be at least 2 * TCP_MSS. + */ +#ifndef TCP_SND_BUF +#define TCP_SND_BUF (2 * TCP_MSS) +#endif + +/** + * TCP_SND_QUEUELEN: TCP sender buffer space (pbufs). This must be at least + * as much as (2 * TCP_SND_BUF/TCP_MSS) for things to work. + */ +#ifndef TCP_SND_QUEUELEN +#define TCP_SND_QUEUELEN ((4 * (TCP_SND_BUF) + (TCP_MSS - 1))/(TCP_MSS)) +#endif + +/** + * TCP_SNDLOWAT: TCP writable space (bytes). This must be less than + * TCP_SND_BUF. It is the amount of space which must be available in the + * TCP snd_buf for select to return writable (combined with TCP_SNDQUEUELOWAT). + */ +#ifndef TCP_SNDLOWAT +#define TCP_SNDLOWAT LWIP_MIN(LWIP_MAX(((TCP_SND_BUF)/2), (2 * TCP_MSS) + 1), (TCP_SND_BUF) - 1) +#endif + +/** + * TCP_SNDQUEUELOWAT: TCP writable bufs (pbuf count). This must be less + * than TCP_SND_QUEUELEN. If the number of pbufs queued on a pcb drops below + * this number, select returns writable (combined with TCP_SNDLOWAT). + */ +#ifndef TCP_SNDQUEUELOWAT +#define TCP_SNDQUEUELOWAT LWIP_MAX(((TCP_SND_QUEUELEN)/2), 5) +#endif + +/** + * TCP_OOSEQ_MAX_BYTES: The maximum number of bytes queued on ooseq per pcb. + * Default is 0 (no limit). Only valid for TCP_QUEUE_OOSEQ==0. + */ +#ifndef TCP_OOSEQ_MAX_BYTES +#define TCP_OOSEQ_MAX_BYTES 0 +#endif + +/** + * TCP_OOSEQ_MAX_PBUFS: The maximum number of pbufs queued on ooseq per pcb. + * Default is 0 (no limit). Only valid for TCP_QUEUE_OOSEQ==0. + */ +#ifndef TCP_OOSEQ_MAX_PBUFS +#define TCP_OOSEQ_MAX_PBUFS 0 +#endif + +/** + * TCP_LISTEN_BACKLOG: Enable the backlog option for tcp listen pcb. + */ +#ifndef TCP_LISTEN_BACKLOG +#define TCP_LISTEN_BACKLOG 0 +#endif + +/** + * The maximum allowed backlog for TCP listen netconns. + * This backlog is used unless another is explicitly specified. + * 0xff is the maximum (u8_t). + */ +#ifndef TCP_DEFAULT_LISTEN_BACKLOG +#define TCP_DEFAULT_LISTEN_BACKLOG 0xff +#endif + +/** + * TCP_OVERSIZE: The maximum number of bytes that tcp_write may + * allocate ahead of time in an attempt to create shorter pbuf chains + * for transmission. The meaningful range is 0 to TCP_MSS. Some + * suggested values are: + * + * 0: Disable oversized allocation. Each tcp_write() allocates a new + pbuf (old behaviour). + * 1: Allocate size-aligned pbufs with minimal excess. Use this if your + * scatter-gather DMA requires aligned fragments. + * 128: Limit the pbuf/memory overhead to 20%. + * TCP_MSS: Try to create unfragmented TCP packets. + * TCP_MSS/4: Try to create 4 fragments or less per TCP packet. + */ +#ifndef TCP_OVERSIZE +#define TCP_OVERSIZE TCP_MSS +#endif + +/** + * LWIP_TCP_TIMESTAMPS==1: support the TCP timestamp option. + * The timestamp option is currently only used to help remote hosts, it is not + * really used locally. Therefore, it is only enabled when a TS option is + * received in the initial SYN packet from a remote host. + */ +#ifndef LWIP_TCP_TIMESTAMPS +#define LWIP_TCP_TIMESTAMPS 0 +#endif + +/** + * TCP_WND_UPDATE_THRESHOLD: difference in window to trigger an + * explicit window update + */ +#ifndef TCP_WND_UPDATE_THRESHOLD +#define TCP_WND_UPDATE_THRESHOLD LWIP_MIN((TCP_WND / 4), (TCP_MSS * 4)) +#endif + +/** + * LWIP_EVENT_API and LWIP_CALLBACK_API: Only one of these should be set to 1. + * LWIP_EVENT_API==1: The user defines lwip_tcp_event() to receive all + * events (accept, sent, etc) that happen in the system. + * LWIP_CALLBACK_API==1: The PCB callback function is called directly + * for the event. This is the default. + */ +#if !defined(LWIP_EVENT_API) && !defined(LWIP_CALLBACK_API) +#define LWIP_EVENT_API 0 +#define LWIP_CALLBACK_API 1 +#endif + +/** + * LWIP_WND_SCALE and TCP_RCV_SCALE: + * Set LWIP_WND_SCALE to 1 to enable window scaling. + * Set TCP_RCV_SCALE to the desired scaling factor (shift count in the + * range of [0..14]). + * When LWIP_WND_SCALE is enabled but TCP_RCV_SCALE is 0, we can use a large + * send window while having a small receive window only. + */ +#ifndef LWIP_WND_SCALE +#define LWIP_WND_SCALE 0 +#define TCP_RCV_SCALE 0 +#endif + + +/* + ---------------------------------- + ---------- Pbuf options ---------- + ---------------------------------- +*/ +/** + * PBUF_LINK_HLEN: the number of bytes that should be allocated for a + * link level header. The default is 14, the standard value for + * Ethernet. + */ +#ifndef PBUF_LINK_HLEN +#ifdef LWIP_HOOK_VLAN_SET +#define PBUF_LINK_HLEN (18 + ETH_PAD_SIZE) +#else /* LWIP_HOOK_VLAN_SET */ +#define PBUF_LINK_HLEN (14 + ETH_PAD_SIZE) +#endif /* LWIP_HOOK_VLAN_SET */ +#endif + +/** + * PBUF_LINK_ENCAPSULATION_HLEN: the number of bytes that should be allocated + * for an additional encapsulation header before ethernet headers (e.g. 802.11) + */ +#ifndef PBUF_LINK_ENCAPSULATION_HLEN +#define PBUF_LINK_ENCAPSULATION_HLEN 0 +#endif + +/** + * PBUF_POOL_BUFSIZE: the size of each pbuf in the pbuf pool. The default is + * designed to accommodate single full size TCP frame in one pbuf, including + * TCP_MSS, IP header, and link header. + */ +#ifndef PBUF_POOL_BUFSIZE +#define PBUF_POOL_BUFSIZE LWIP_MEM_ALIGN_SIZE(TCP_MSS+40+PBUF_LINK_ENCAPSULATION_HLEN+PBUF_LINK_HLEN) +#endif + +/* + ------------------------------------------------ + ---------- Network Interfaces options ---------- + ------------------------------------------------ +*/ +/** + * LWIP_NETIF_HOSTNAME==1: use DHCP_OPTION_HOSTNAME with netif's hostname + * field. + */ +#ifndef LWIP_NETIF_HOSTNAME +#define LWIP_NETIF_HOSTNAME 0 +#endif + +/** + * LWIP_NETIF_API==1: Support netif api (in netifapi.c) + */ +#ifndef LWIP_NETIF_API +#define LWIP_NETIF_API 0 +#endif + +/** + * LWIP_NETIF_STATUS_CALLBACK==1: Support a callback function whenever an interface + * changes its up/down status (i.e., due to DHCP IP acquisition) + */ +#ifndef LWIP_NETIF_STATUS_CALLBACK +#define LWIP_NETIF_STATUS_CALLBACK 0 +#endif + +/** + * LWIP_NETIF_LINK_CALLBACK==1: Support a callback function from an interface + * whenever the link changes (i.e., link down) + */ +#ifndef LWIP_NETIF_LINK_CALLBACK +#define LWIP_NETIF_LINK_CALLBACK 0 +#endif + +/** + * LWIP_NETIF_REMOVE_CALLBACK==1: Support a callback function that is called + * when a netif has been removed + */ +#ifndef LWIP_NETIF_REMOVE_CALLBACK +#define LWIP_NETIF_REMOVE_CALLBACK 0 +#endif + +/** + * LWIP_NETIF_HWADDRHINT==1: Cache link-layer-address hints (e.g. table + * indices) in struct netif. TCP and UDP can make use of this to prevent + * scanning the ARP table for every sent packet. While this is faster for big + * ARP tables or many concurrent connections, it might be counterproductive + * if you have a tiny ARP table or if there never are concurrent connections. + */ +#ifndef LWIP_NETIF_HWADDRHINT +#define LWIP_NETIF_HWADDRHINT 0 +#endif + +/** + * LWIP_NETIF_LOOPBACK==1: Support sending packets with a destination IP + * address equal to the netif IP address, looping them back up the stack. + */ +#ifndef LWIP_NETIF_LOOPBACK +#define LWIP_NETIF_LOOPBACK 0 +#endif + +/** + * LWIP_LOOPBACK_MAX_PBUFS: Maximum number of pbufs on queue for loopback + * sending for each netif (0 = disabled) + */ +#ifndef LWIP_LOOPBACK_MAX_PBUFS +#define LWIP_LOOPBACK_MAX_PBUFS 0 +#endif + +/** + * LWIP_NETIF_LOOPBACK_MULTITHREADING: Indicates whether threading is enabled in + * the system, as netifs must change how they behave depending on this setting + * for the LWIP_NETIF_LOOPBACK option to work. + * Setting this is needed to avoid reentering non-reentrant functions like + * tcp_input(). + * LWIP_NETIF_LOOPBACK_MULTITHREADING==1: Indicates that the user is using a + * multithreaded environment like tcpip.c. In this case, netif->input() + * is called directly. + * LWIP_NETIF_LOOPBACK_MULTITHREADING==0: Indicates a polling (or NO_SYS) setup. + * The packets are put on a list and netif_poll() must be called in + * the main application loop. + */ +#ifndef LWIP_NETIF_LOOPBACK_MULTITHREADING +#define LWIP_NETIF_LOOPBACK_MULTITHREADING (!NO_SYS) +#endif + +/** + * LWIP_NETIF_TX_SINGLE_PBUF: if this is set to 1, lwIP tries to put all data + * to be sent into one single pbuf. This is for compatibility with DMA-enabled + * MACs that do not support scatter-gather. + * Beware that this might involve CPU-memcpy before transmitting that would not + * be needed without this flag! Use this only if you need to! + * + * @todo: TCP and IP-frag do not work with this, yet: + */ +#ifndef LWIP_NETIF_TX_SINGLE_PBUF +#define LWIP_NETIF_TX_SINGLE_PBUF 0 +#endif /* LWIP_NETIF_TX_SINGLE_PBUF */ + +/* + ------------------------------------ + ---------- LOOPIF options ---------- + ------------------------------------ +*/ +/** + * LWIP_HAVE_LOOPIF==1: Support loop interface (127.0.0.1). + * This is only needed when no real netifs are available. If at least one other + * netif is available, loopback traffic uses this netif. + */ +#ifndef LWIP_HAVE_LOOPIF +#define LWIP_HAVE_LOOPIF LWIP_NETIF_LOOPBACK +#endif + +/** + * LWIP_LOOPIF_MULTICAST==1: Support multicast/IGMP on loop interface (127.0.0.1). + */ +#ifndef LWIP_LOOPIF_MULTICAST +#define LWIP_LOOPIF_MULTICAST 0 +#endif + +/* + ------------------------------------ + ---------- SLIPIF options ---------- + ------------------------------------ +*/ +/** + * LWIP_HAVE_SLIPIF==1: Support slip interface and slipif.c + */ +#ifndef LWIP_HAVE_SLIPIF +#define LWIP_HAVE_SLIPIF 0 +#endif + +/* + ------------------------------------ + ---------- Thread options ---------- + ------------------------------------ +*/ +/** + * TCPIP_THREAD_NAME: The name assigned to the main tcpip thread. + */ +#ifndef TCPIP_THREAD_NAME +#define TCPIP_THREAD_NAME "tcpip_thread" +#endif + +/** + * TCPIP_THREAD_STACKSIZE: The stack size used by the main tcpip thread. + * The stack size value itself is platform-dependent, but is passed to + * sys_thread_new() when the thread is created. + */ +#ifndef TCPIP_THREAD_STACKSIZE +#define TCPIP_THREAD_STACKSIZE 0 +#endif + +/** + * TCPIP_THREAD_PRIO: The priority assigned to the main tcpip thread. + * The priority value itself is platform-dependent, but is passed to + * sys_thread_new() when the thread is created. + */ +#ifndef TCPIP_THREAD_PRIO +#define TCPIP_THREAD_PRIO 1 +#endif + +/** + * TCPIP_MBOX_SIZE: The mailbox size for the tcpip thread messages + * The queue size value itself is platform-dependent, but is passed to + * sys_mbox_new() when tcpip_init is called. + */ +#ifndef TCPIP_MBOX_SIZE +#define TCPIP_MBOX_SIZE 0 +#endif + +/** + * SLIPIF_THREAD_NAME: The name assigned to the slipif_loop thread. + */ +#ifndef SLIPIF_THREAD_NAME +#define SLIPIF_THREAD_NAME "slipif_loop" +#endif + +/** + * SLIP_THREAD_STACKSIZE: The stack size used by the slipif_loop thread. + * The stack size value itself is platform-dependent, but is passed to + * sys_thread_new() when the thread is created. + */ +#ifndef SLIPIF_THREAD_STACKSIZE +#define SLIPIF_THREAD_STACKSIZE 0 +#endif + +/** + * SLIPIF_THREAD_PRIO: The priority assigned to the slipif_loop thread. + * The priority value itself is platform-dependent, but is passed to + * sys_thread_new() when the thread is created. + */ +#ifndef SLIPIF_THREAD_PRIO +#define SLIPIF_THREAD_PRIO 1 +#endif + +/** + * DEFAULT_THREAD_NAME: The name assigned to any other lwIP thread. + */ +#ifndef DEFAULT_THREAD_NAME +#define DEFAULT_THREAD_NAME "lwIP" +#endif + +/** + * DEFAULT_THREAD_STACKSIZE: The stack size used by any other lwIP thread. + * The stack size value itself is platform-dependent, but is passed to + * sys_thread_new() when the thread is created. + */ +#ifndef DEFAULT_THREAD_STACKSIZE +#define DEFAULT_THREAD_STACKSIZE 0 +#endif + +/** + * DEFAULT_THREAD_PRIO: The priority assigned to any other lwIP thread. + * The priority value itself is platform-dependent, but is passed to + * sys_thread_new() when the thread is created. + */ +#ifndef DEFAULT_THREAD_PRIO +#define DEFAULT_THREAD_PRIO 1 +#endif + +/** + * DEFAULT_RAW_RECVMBOX_SIZE: The mailbox size for the incoming packets on a + * NETCONN_RAW. The queue size value itself is platform-dependent, but is passed + * to sys_mbox_new() when the recvmbox is created. + */ +#ifndef DEFAULT_RAW_RECVMBOX_SIZE +#define DEFAULT_RAW_RECVMBOX_SIZE 0 +#endif + +/** + * DEFAULT_UDP_RECVMBOX_SIZE: The mailbox size for the incoming packets on a + * NETCONN_UDP. The queue size value itself is platform-dependent, but is passed + * to sys_mbox_new() when the recvmbox is created. + */ +#ifndef DEFAULT_UDP_RECVMBOX_SIZE +#define DEFAULT_UDP_RECVMBOX_SIZE 0 +#endif + +/** + * DEFAULT_TCP_RECVMBOX_SIZE: The mailbox size for the incoming packets on a + * NETCONN_TCP. The queue size value itself is platform-dependent, but is passed + * to sys_mbox_new() when the recvmbox is created. + */ +#ifndef DEFAULT_TCP_RECVMBOX_SIZE +#define DEFAULT_TCP_RECVMBOX_SIZE 0 +#endif + +/** + * DEFAULT_ACCEPTMBOX_SIZE: The mailbox size for the incoming connections. + * The queue size value itself is platform-dependent, but is passed to + * sys_mbox_new() when the acceptmbox is created. + */ +#ifndef DEFAULT_ACCEPTMBOX_SIZE +#define DEFAULT_ACCEPTMBOX_SIZE 0 +#endif + +/* + ---------------------------------------------- + ---------- Sequential layer options ---------- + ---------------------------------------------- +*/ +/** + * LWIP_TCPIP_CORE_LOCKING: (EXPERIMENTAL!) + * Don't use it if you're not an active lwIP project member + */ +#ifndef LWIP_TCPIP_CORE_LOCKING +#define LWIP_TCPIP_CORE_LOCKING 0 +#endif + +/** + * LWIP_TCPIP_CORE_LOCKING_INPUT: (EXPERIMENTAL!) + * Don't use it if you're not an active lwIP project member + */ +#ifndef LWIP_TCPIP_CORE_LOCKING_INPUT +#define LWIP_TCPIP_CORE_LOCKING_INPUT 0 +#endif + +/** + * LWIP_NETCONN==1: Enable Netconn API (require to use api_lib.c) + */ +#ifndef LWIP_NETCONN +#define LWIP_NETCONN 1 +#endif + +/** LWIP_TCPIP_TIMEOUT==1: Enable tcpip_timeout/tcpip_untimeout to create + * timers running in tcpip_thread from another thread. + */ +#ifndef LWIP_TCPIP_TIMEOUT +#define LWIP_TCPIP_TIMEOUT 0 +#endif + +/** LWIP_NETCONN_SEM_PER_THREAD==1: Use one (thread-local) semaphore per + * thread calling socket/netconn functions instead of allocating one + * semaphore per netconn (and per select etc.) + * ATTENTION: a thread-local semaphore for API calls is needed: + * - LWIP_NETCONN_THREAD_SEM_GET() returning a sys_sem_t* + * - LWIP_NETCONN_THREAD_SEM_ALLOC() creating the semaphore + * - LWIP_NETCONN_THREAD_SEM_FREE() freeing the semaphore + * The latter 2 can be invoked up by calling netconn_thread_init()/netconn_thread_cleanup(). + * Ports may call these for threads created with sys_thread_new(). + */ +#ifndef LWIP_NETCONN_SEM_PER_THREAD +#define LWIP_NETCONN_SEM_PER_THREAD 0 +#endif + +/** LWIP_NETCONN_FULLDUPLEX==1: Enable code that allows reading from one thread, + * writing from a 2nd thread and closing from a 3rd thread at the same time. + * ATTENTION: This is currently really alpha! Some requirements: + * - LWIP_NETCONN_SEM_PER_THREAD==1 is required to use one socket/netconn from + * multiple threads at once + * - sys_mbox_free() has to unblock receive tasks waiting on recvmbox/acceptmbox + * and prevent a task pending on this during/after deletion + */ +#ifndef LWIP_NETCONN_FULLDUPLEX +#define LWIP_NETCONN_FULLDUPLEX 0 +#endif + +/* + ------------------------------------ + ---------- Socket options ---------- + ------------------------------------ +*/ +/** + * LWIP_SOCKET==1: Enable Socket API (require to use sockets.c) + */ +#ifndef LWIP_SOCKET +#define LWIP_SOCKET 1 +#endif + +/* LWIP_SOCKET_SET_ERRNO==1: Set errno when socket functions cannot complete + * successfully, as required by POSIX. Default is POSIX-compliant. + */ +#ifndef LWIP_SOCKET_SET_ERRNO +#define LWIP_SOCKET_SET_ERRNO 1 +#endif + +/** + * LWIP_COMPAT_SOCKETS==1: Enable BSD-style sockets functions names through defines. + * LWIP_COMPAT_SOCKETS==2: Same as ==1 but correctly named functions are created. + * While this helps code completion, it might conflict with existing libraries. + * (only used if you use sockets.c) + */ +#ifndef LWIP_COMPAT_SOCKETS +#define LWIP_COMPAT_SOCKETS 1 +#endif + +/** + * LWIP_POSIX_SOCKETS_IO_NAMES==1: Enable POSIX-style sockets functions names. + * Disable this option if you use a POSIX operating system that uses the same + * names (read, write & close). (only used if you use sockets.c) + */ +#ifndef LWIP_POSIX_SOCKETS_IO_NAMES +#define LWIP_POSIX_SOCKETS_IO_NAMES 1 +#endif + +/** + * LWIP_SOCKET_OFFSET==n: Increases the file descriptor number created by LwIP with n. + * This can be useful when there are multiple APIs which create file descriptors. + * When they all start with a different offset and you won't make them overlap you can + * re implement read/write/close/ioctl/fnctl to send the requested action to the right + * library (sharing select will need more work though). + */ +#ifndef LWIP_SOCKET_OFFSET +#define LWIP_SOCKET_OFFSET 0 +#endif + +/** + * LWIP_TCP_KEEPALIVE==1: Enable TCP_KEEPIDLE, TCP_KEEPINTVL and TCP_KEEPCNT + * options processing. Note that TCP_KEEPIDLE and TCP_KEEPINTVL have to be set + * in seconds. (does not require sockets.c, and will affect tcp.c) + */ +#ifndef LWIP_TCP_KEEPALIVE +#define LWIP_TCP_KEEPALIVE 0 +#endif + +/** + * LWIP_SO_SNDTIMEO==1: Enable send timeout for sockets/netconns and + * SO_SNDTIMEO processing. + */ +#ifndef LWIP_SO_SNDTIMEO +#define LWIP_SO_SNDTIMEO 0 +#endif + +/** + * LWIP_SO_RCVTIMEO==1: Enable receive timeout for sockets/netconns and + * SO_RCVTIMEO processing. + */ +#ifndef LWIP_SO_RCVTIMEO +#define LWIP_SO_RCVTIMEO 0 +#endif + +/** + * LWIP_SO_SNDRCVTIMEO_NONSTANDARD==1: SO_RCVTIMEO/SO_SNDTIMEO take an int + * (milliseconds, much like winsock does) instead of a struct timeval (default). + */ +#ifndef LWIP_SO_SNDRCVTIMEO_NONSTANDARD +#define LWIP_SO_SNDRCVTIMEO_NONSTANDARD 0 +#endif + +/** + * LWIP_SO_RCVBUF==1: Enable SO_RCVBUF processing. + */ +#ifndef LWIP_SO_RCVBUF +#define LWIP_SO_RCVBUF 0 +#endif + +/** + * LWIP_SO_LINGER==1: Enable SO_LINGER processing. + */ +#ifndef LWIP_SO_LINGER +#define LWIP_SO_LINGER 0 +#endif + +/** + * If LWIP_SO_RCVBUF is used, this is the default value for recv_bufsize. + */ +#ifndef RECV_BUFSIZE_DEFAULT +#define RECV_BUFSIZE_DEFAULT INT_MAX +#endif + +/** + * By default, TCP socket/netconn close waits 20 seconds max to send the FIN + */ +#ifndef LWIP_TCP_CLOSE_TIMEOUT_MS_DEFAULT +#define LWIP_TCP_CLOSE_TIMEOUT_MS_DEFAULT 20000 +#endif + +/** + * SO_REUSE==1: Enable SO_REUSEADDR option. + */ +#ifndef SO_REUSE +#define SO_REUSE 0 +#endif + +/** + * SO_REUSE_RXTOALL==1: Pass a copy of incoming broadcast/multicast packets + * to all local matches if SO_REUSEADDR is turned on. + * WARNING: Adds a memcpy for every packet if passing to more than one pcb! + */ +#ifndef SO_REUSE_RXTOALL +#define SO_REUSE_RXTOALL 0 +#endif + +/** + * LWIP_FIONREAD_LINUXMODE==0 (default): ioctl/FIONREAD returns the amount of + * pending data in the network buffer. This is the way windows does it. It's + * the default for lwIP since it is smaller. + * LWIP_FIONREAD_LINUXMODE==1: ioctl/FIONREAD returns the size of the next + * pending datagram in bytes. This is the way linux does it. This code is only + * here for compatibility. + */ +#ifndef LWIP_FIONREAD_LINUXMODE +#define LWIP_FIONREAD_LINUXMODE 0 +#endif + +/* + ---------------------------------------- + ---------- Statistics options ---------- + ---------------------------------------- +*/ +/** + * LWIP_STATS==1: Enable statistics collection in lwip_stats. + */ +#ifndef LWIP_STATS +#define LWIP_STATS 1 +#endif + +#if LWIP_STATS + +/** + * LWIP_STATS_DISPLAY==1: Compile in the statistics output functions. + */ +#ifndef LWIP_STATS_DISPLAY +#define LWIP_STATS_DISPLAY 0 +#endif + +/** + * LINK_STATS==1: Enable link stats. + */ +#ifndef LINK_STATS +#define LINK_STATS 1 +#endif + +/** + * ETHARP_STATS==1: Enable etharp stats. + */ +#ifndef ETHARP_STATS +#define ETHARP_STATS (LWIP_ARP) +#endif + +/** + * IP_STATS==1: Enable IP stats. + */ +#ifndef IP_STATS +#define IP_STATS 1 +#endif + +/** + * IPFRAG_STATS==1: Enable IP fragmentation stats. Default is + * on if using either frag or reass. + */ +#ifndef IPFRAG_STATS +#define IPFRAG_STATS (IP_REASSEMBLY || IP_FRAG) +#endif + +/** + * ICMP_STATS==1: Enable ICMP stats. + */ +#ifndef ICMP_STATS +#define ICMP_STATS 1 +#endif + +/** + * IGMP_STATS==1: Enable IGMP stats. + */ +#ifndef IGMP_STATS +#define IGMP_STATS (LWIP_IGMP) +#endif + +/** + * UDP_STATS==1: Enable UDP stats. Default is on if + * UDP enabled, otherwise off. + */ +#ifndef UDP_STATS +#define UDP_STATS (LWIP_UDP) +#endif + +/** + * TCP_STATS==1: Enable TCP stats. Default is on if TCP + * enabled, otherwise off. + */ +#ifndef TCP_STATS +#define TCP_STATS (LWIP_TCP) +#endif + +/** + * MEM_STATS==1: Enable mem.c stats. + */ +#ifndef MEM_STATS +#define MEM_STATS ((MEM_LIBC_MALLOC == 0) && (MEM_USE_POOLS == 0)) +#endif + +/** + * MEMP_STATS==1: Enable memp.c pool stats. + */ +#ifndef MEMP_STATS +#define MEMP_STATS (MEMP_MEM_MALLOC == 0) +#endif + +/** + * SYS_STATS==1: Enable system stats (sem and mbox counts, etc). + */ +#ifndef SYS_STATS +#define SYS_STATS (NO_SYS == 0) +#endif + +/** + * IP6_STATS==1: Enable IPv6 stats. + */ +#ifndef IP6_STATS +#define IP6_STATS (LWIP_IPV6) +#endif + +/** + * ICMP6_STATS==1: Enable ICMP for IPv6 stats. + */ +#ifndef ICMP6_STATS +#define ICMP6_STATS (LWIP_IPV6 && LWIP_ICMP6) +#endif + +/** + * IP6_FRAG_STATS==1: Enable IPv6 fragmentation stats. + */ +#ifndef IP6_FRAG_STATS +#define IP6_FRAG_STATS (LWIP_IPV6 && (LWIP_IPV6_FRAG || LWIP_IPV6_REASS)) +#endif + +/** + * MLD6_STATS==1: Enable MLD for IPv6 stats. + */ +#ifndef MLD6_STATS +#define MLD6_STATS (LWIP_IPV6 && LWIP_IPV6_MLD) +#endif + +/** + * ND6_STATS==1: Enable Neighbor discovery for IPv6 stats. + */ +#ifndef ND6_STATS +#define ND6_STATS (LWIP_IPV6) +#endif + +/** + * MIB2_STATS==1: Stats for SNMP MIB2. + */ +#ifndef MIB2_STATS +#define MIB2_STATS 0 +#endif + +#else + +#define LINK_STATS 0 +#define ETHARP_STATS 0 +#define IP_STATS 0 +#define IPFRAG_STATS 0 +#define ICMP_STATS 0 +#define IGMP_STATS 0 +#define UDP_STATS 0 +#define TCP_STATS 0 +#define MEM_STATS 0 +#define MEMP_STATS 0 +#define SYS_STATS 0 +#define LWIP_STATS_DISPLAY 0 +#define IP6_STATS 0 +#define ICMP6_STATS 0 +#define IP6_FRAG_STATS 0 +#define MLD6_STATS 0 +#define ND6_STATS 0 +#define MIB2_STATS 0 + +#endif /* LWIP_STATS */ + +/* + --------------------------------- + ---------- PPP options ---------- + --------------------------------- +*/ + +/** + * PPP_SUPPORT==1: Enable PPP. + */ +#ifndef PPP_SUPPORT +#define PPP_SUPPORT 0 +#endif + +/** + * PPPOE_SUPPORT==1: Enable PPP Over Ethernet + */ +#ifndef PPPOE_SUPPORT +#define PPPOE_SUPPORT 0 +#endif + +/** + * PPPOL2TP_SUPPORT==1: Enable PPP Over L2TP + */ +#ifndef PPPOL2TP_SUPPORT +#define PPPOL2TP_SUPPORT 0 +#endif + +/** + * PPPOL2TP_AUTH_SUPPORT==1: Enable PPP Over L2TP Auth (enable MD5 support) + */ +#ifndef PPPOL2TP_AUTH_SUPPORT +#define PPPOL2TP_AUTH_SUPPORT PPPOL2TP_SUPPORT +#endif + +/** + * PPPOS_SUPPORT==1: Enable PPP Over Serial + */ +#ifndef PPPOS_SUPPORT +#define PPPOS_SUPPORT PPP_SUPPORT +#endif + +/** + * LWIP_PPP_API==1: Enable PPP API (in pppapi.c) + */ +#ifndef LWIP_PPP_API +#define LWIP_PPP_API (PPP_SUPPORT && (NO_SYS == 0)) +#endif + +#if PPP_SUPPORT + +/** + * PPP_INPROC_IRQ_SAFE==1 call pppos_input() using tcpip_callback(). + * + * Please read the "PPPoS input path" chapter in the PPP documentation about this option. + */ +#ifndef PPP_INPROC_IRQ_SAFE +#define PPP_INPROC_IRQ_SAFE 0 +#endif + +/** + * PRINTPKT_SUPPORT==1: Enable PPP print packet support + * + * Mandatory for debugging, it displays exchanged packet content in debug trace. + */ +#ifndef PRINTPKT_SUPPORT +#define PRINTPKT_SUPPORT 0 +#endif + +/** + * PPP_IPV4_SUPPORT==1: Enable PPP IPv4 support + */ +#ifndef PPP_IPV4_SUPPORT +#define PPP_IPV4_SUPPORT (LWIP_IPV4) +#endif + +/** + * PPP_IPV6_SUPPORT==1: Enable PPP IPv6 support + */ +#ifndef PPP_IPV6_SUPPORT +#define PPP_IPV6_SUPPORT (LWIP_IPV6) +#endif + +/** + * PPP_NOTIFY_PHASE==1: Support PPP notify phase support + * + * PPP notify phase support allows you to set a callback which is + * called on change of the internal PPP state machine. + * + * This can be used for example to set a LED pattern depending on the + * current phase of the PPP session. + */ +#ifndef PPP_NOTIFY_PHASE +#define PPP_NOTIFY_PHASE 0 +#endif + +/** + * pbuf_type PPP is using for LCP, PAP, CHAP, EAP, CCP, IPCP and IP6CP packets. + * + * Memory allocated must be single buffered for PPP to works, it requires pbuf + * that are not going to be chained when allocated. This requires setting + * PBUF_POOL_BUFSIZE to at least 512 bytes, which is quite huge for small systems. + * + * Setting PPP_USE_PBUF_RAM to 1 makes PPP use memory from heap where continuous + * buffers are required, allowing you to use a smaller PBUF_POOL_BUFSIZE. + */ +#ifndef PPP_USE_PBUF_RAM +#define PPP_USE_PBUF_RAM 0 +#endif + +/** + * PPP_FCS_TABLE: Keep a 256*2 byte table to speed up FCS calculation for PPPoS + */ +#ifndef PPP_FCS_TABLE +#define PPP_FCS_TABLE 1 +#endif + +/** + * PAP_SUPPORT==1: Support PAP. + */ +#ifndef PAP_SUPPORT +#define PAP_SUPPORT 0 +#endif + +/** + * CHAP_SUPPORT==1: Support CHAP. + */ +#ifndef CHAP_SUPPORT +#define CHAP_SUPPORT 0 +#endif + +/** + * MSCHAP_SUPPORT==1: Support MSCHAP. + */ +#ifndef MSCHAP_SUPPORT +#define MSCHAP_SUPPORT 0 +#endif +#if MSCHAP_SUPPORT +/* MSCHAP requires CHAP support */ +#undef CHAP_SUPPORT +#define CHAP_SUPPORT 1 +#endif /* MSCHAP_SUPPORT */ + +/** + * EAP_SUPPORT==1: Support EAP. + */ +#ifndef EAP_SUPPORT +#define EAP_SUPPORT 0 +#endif + +/** + * CCP_SUPPORT==1: Support CCP. + */ +#ifndef CCP_SUPPORT +#define CCP_SUPPORT 0 +#endif + +/** + * MPPE_SUPPORT==1: Support MPPE. + */ +#ifndef MPPE_SUPPORT +#define MPPE_SUPPORT 0 +#endif +#if MPPE_SUPPORT +/* MPPE requires CCP support */ +#undef CCP_SUPPORT +#define CCP_SUPPORT 1 +/* MPPE requires MSCHAP support */ +#undef MSCHAP_SUPPORT +#define MSCHAP_SUPPORT 1 +/* MSCHAP requires CHAP support */ +#undef CHAP_SUPPORT +#define CHAP_SUPPORT 1 +#endif /* MPPE_SUPPORT */ + +/** + * CBCP_SUPPORT==1: Support CBCP. CURRENTLY NOT SUPPORTED! DO NOT SET! + */ +#ifndef CBCP_SUPPORT +#define CBCP_SUPPORT 0 +#endif + +/** + * ECP_SUPPORT==1: Support ECP. CURRENTLY NOT SUPPORTED! DO NOT SET! + */ +#ifndef ECP_SUPPORT +#define ECP_SUPPORT 0 +#endif + +/** + * DEMAND_SUPPORT==1: Support dial on demand. CURRENTLY NOT SUPPORTED! DO NOT SET! + */ +#ifndef DEMAND_SUPPORT +#define DEMAND_SUPPORT 0 +#endif + +/** + * LQR_SUPPORT==1: Support Link Quality Report. Do nothing except exchanging some LCP packets. + */ +#ifndef LQR_SUPPORT +#define LQR_SUPPORT 0 +#endif + +/** + * PPP_SERVER==1: Enable PPP server support (waiting for incoming PPP session). + * + * Currently only supported for PPPoS. + */ +#ifndef PPP_SERVER +#define PPP_SERVER 0 +#endif + +#if PPP_SERVER +/* + * PPP_OUR_NAME: Our name for authentication purposes + */ +#ifndef PPP_OUR_NAME +#define PPP_OUR_NAME "lwIP" +#endif +#endif /* PPP_SERVER */ + +/** + * VJ_SUPPORT==1: Support VJ header compression. + */ +#ifndef VJ_SUPPORT +#define VJ_SUPPORT 1 +#endif +/* VJ compression is only supported for IPv4 over PPPoS. */ +#if !PPPOS_SUPPORT || !PPP_IPV4_SUPPORT +#undef VJ_SUPPORT +#define VJ_SUPPORT 0 +#endif /* !PPPOS_SUPPORT */ + +/** + * PPP_MD5_RANDM==1: Use MD5 for better randomness. + * Enabled by default if CHAP, EAP, or L2TP AUTH support is enabled. + */ +#ifndef PPP_MD5_RANDM +#define PPP_MD5_RANDM (CHAP_SUPPORT || EAP_SUPPORT || PPPOL2TP_AUTH_SUPPORT) +#endif + +/** + * PolarSSL library, used if necessary and not previously disabled + * + * + * lwIP contains some files fetched from the latest BSD release of + * the PolarSSL project for ciphers and encryption methods we need for lwIP + * PPP support. + * + * The PolarSSL files were cleaned to contain only the necessary struct + * fields and functions needed for lwIP. + * + * The PolarSSL API was not changed at all, so if you are already using + * PolarSSL you can choose to skip the compilation of the included PolarSSL + * library into lwIP: + * + * The following defines are available for flexibility: + * + * LWIP_INCLUDED_POLARSSL_MD4 ; Use lwIP internal PolarSSL for MD4 + * LWIP_INCLUDED_POLARSSL_MD5 ; Use lwIP internal PolarSSL for MD5 + * LWIP_INCLUDED_POLARSSL_SHA1 ; Use lwIP internal PolarSSL for SHA1 + * LWIP_INCLUDED_POLARSSL_DES ; Use lwIP internal PolarSSL for DES + * + * If set (=1), the default if required by another enabled PPP feature unless + * explicitly set to 0, using included lwIP PolarSSL. + * + * If clear (=0), not needed or using external PolarSSL. + * + * Beware of the stack requirements which can be a lot larger if you are not + * using our cleaned PolarSSL library. + */ + +/* CHAP, EAP, L2TP AUTH and MD5 Random require MD5 support */ +#if CHAP_SUPPORT || EAP_SUPPORT || PPPOL2TP_AUTH_SUPPORT || PPP_MD5_RANDM +#ifndef LWIP_INCLUDED_POLARSSL_MD5 +#define LWIP_INCLUDED_POLARSSL_MD5 1 +#endif /* LWIP_INCLUDED_POLARSSL_MD5 */ +#endif /* CHAP_SUPPORT || EAP_SUPPORT || PPPOL2TP_AUTH_SUPPORT || PPP_MD5_RANDM */ + +#if MSCHAP_SUPPORT +/* MSCHAP require MD4 support */ +#ifndef LWIP_INCLUDED_POLARSSL_MD4 +#define LWIP_INCLUDED_POLARSSL_MD4 1 +#endif /* LWIP_INCLUDED_POLARSSL_MD4 */ +/* MSCHAP require SHA1 support */ +#ifndef LWIP_INCLUDED_POLARSSL_SHA1 +#define LWIP_INCLUDED_POLARSSL_SHA1 1 +#endif /* LWIP_INCLUDED_POLARSSL_SHA1 */ +/* MSCHAP require DES support */ +#ifndef LWIP_INCLUDED_POLARSSL_DES +#define LWIP_INCLUDED_POLARSSL_DES 1 +#endif /* LWIP_INCLUDED_POLARSSL_DES */ +/* MS-CHAP support is required for MPPE */ +#if MPPE_SUPPORT +/* MPPE require ARC4 support */ +#ifndef LWIP_INCLUDED_POLARSSL_ARC4 +#define LWIP_INCLUDED_POLARSSL_ARC4 1 +#endif /* LWIP_INCLUDED_POLARSSL_ARC4*/ +#endif /* MPPE_SUPPORT */ +#endif /* MSCHAP_SUPPORT */ + +/* Default value if unset */ +#ifndef LWIP_INCLUDED_POLARSSL_MD4 +#define LWIP_INCLUDED_POLARSSL_MD4 0 +#endif /* LWIP_INCLUDED_POLARSSL_MD4 */ +#ifndef LWIP_INCLUDED_POLARSSL_MD5 +#define LWIP_INCLUDED_POLARSSL_MD5 0 +#endif /* LWIP_INCLUDED_POLARSSL_MD5 */ +#ifndef LWIP_INCLUDED_POLARSSL_SHA1 +#define LWIP_INCLUDED_POLARSSL_SHA1 0 +#endif /* LWIP_INCLUDED_POLARSSL_SHA1 */ +#ifndef LWIP_INCLUDED_POLARSSL_DES +#define LWIP_INCLUDED_POLARSSL_DES 0 +#endif /* LWIP_INCLUDED_POLARSSL_DES */ +#ifndef LWIP_INCLUDED_POLARSSL_ARC4 +#define LWIP_INCLUDED_POLARSSL_ARC4 0 +#endif /* LWIP_INCLUDED_POLARSSL_ARC4 */ + +/* + * PPP Timeouts + */ + +/** + * FSM_DEFTIMEOUT: Timeout time in seconds + */ +#ifndef FSM_DEFTIMEOUT +#define FSM_DEFTIMEOUT 6 +#endif + +/** + * FSM_DEFMAXTERMREQS: Maximum Terminate-Request transmissions + */ +#ifndef FSM_DEFMAXTERMREQS +#define FSM_DEFMAXTERMREQS 2 +#endif + +/** + * FSM_DEFMAXCONFREQS: Maximum Configure-Request transmissions + */ +#ifndef FSM_DEFMAXCONFREQS +#define FSM_DEFMAXCONFREQS 10 +#endif + +/** + * FSM_DEFMAXNAKLOOPS: Maximum number of nak loops + */ +#ifndef FSM_DEFMAXNAKLOOPS +#define FSM_DEFMAXNAKLOOPS 5 +#endif + +/** + * UPAP_DEFTIMEOUT: Timeout (seconds) for retransmitting req + */ +#ifndef UPAP_DEFTIMEOUT +#define UPAP_DEFTIMEOUT 6 +#endif + +/** + * UPAP_DEFTRANSMITS: Maximum number of auth-reqs to send + */ +#ifndef UPAP_DEFTRANSMITS +#define UPAP_DEFTRANSMITS 10 +#endif + +#if PPP_SERVER +/** + * UPAP_DEFREQTIME: Time to wait for auth-req from peer + */ +#ifndef UPAP_DEFREQTIME +#define UPAP_DEFREQTIME 30 +#endif +#endif /* PPP_SERVER */ + +/** + * CHAP_DEFTIMEOUT: Timeout (seconds) for retransmitting req + */ +#ifndef CHAP_DEFTIMEOUT +#define CHAP_DEFTIMEOUT 6 +#endif + +/** + * CHAP_DEFTRANSMITS: max # times to send challenge + */ +#ifndef CHAP_DEFTRANSMITS +#define CHAP_DEFTRANSMITS 10 +#endif + +#if PPP_SERVER +/** + * CHAP_DEFRECHALLENGETIME: If this option is > 0, rechallenge the peer every n seconds + */ +#ifndef CHAP_DEFRECHALLENGETIME +#define CHAP_DEFRECHALLENGETIME 0 +#endif +#endif /* PPP_SERVER */ + +/** + * EAP_DEFREQTIME: Time to wait for peer request + */ +#ifndef EAP_DEFREQTIME +#define EAP_DEFREQTIME 6 +#endif + +/** + * EAP_DEFALLOWREQ: max # times to accept requests + */ +#ifndef EAP_DEFALLOWREQ +#define EAP_DEFALLOWREQ 10 +#endif + +#if PPP_SERVER +/** + * EAP_DEFTIMEOUT: Timeout (seconds) for rexmit + */ +#ifndef EAP_DEFTIMEOUT +#define EAP_DEFTIMEOUT 6 +#endif + +/** + * EAP_DEFTRANSMITS: max # times to transmit + */ +#ifndef EAP_DEFTRANSMITS +#define EAP_DEFTRANSMITS 10 +#endif +#endif /* PPP_SERVER */ + +/** + * LCP_DEFLOOPBACKFAIL: Default number of times we receive our magic number from the peer + * before deciding the link is looped-back. + */ +#ifndef LCP_DEFLOOPBACKFAIL +#define LCP_DEFLOOPBACKFAIL 10 +#endif + +/** + * LCP_ECHOINTERVAL: Interval in seconds between keepalive echo requests, 0 to disable. + */ +#ifndef LCP_ECHOINTERVAL +#define LCP_ECHOINTERVAL 0 +#endif + +/** + * LCP_MAXECHOFAILS: Number of unanswered echo requests before failure. + */ +#ifndef LCP_MAXECHOFAILS +#define LCP_MAXECHOFAILS 3 +#endif + +/** + * PPP_MAXIDLEFLAG: Max Xmit idle time (in ms) before resend flag char. + */ +#ifndef PPP_MAXIDLEFLAG +#define PPP_MAXIDLEFLAG 100 +#endif + +/** + * PPP Packet sizes + */ + +/** + * PPP_MRU: Default MRU + */ +#ifndef PPP_MRU +#define PPP_MRU 1500 +#endif + +/** + * PPP_DEFMRU: Default MRU to try + */ +#ifndef PPP_DEFMRU +#define PPP_DEFMRU 1500 +#endif + +/** + * PPP_MAXMRU: Normally limit MRU to this (pppd default = 16384) + */ +#ifndef PPP_MAXMRU +#define PPP_MAXMRU 1500 +#endif + +/** + * PPP_MINMRU: No MRUs below this + */ +#ifndef PPP_MINMRU +#define PPP_MINMRU 128 +#endif + +/** + * PPPOL2TP_DEFMRU: Default MTU and MRU for L2TP + * Default = 1500 - PPPoE(6) - PPP Protocol(2) - IPv4 header(20) - UDP Header(8) + * - L2TP Header(6) - HDLC Header(2) - PPP Protocol(2) - MPPE Header(2) - PPP Protocol(2) + */ +#if PPPOL2TP_SUPPORT +#ifndef PPPOL2TP_DEFMRU +#define PPPOL2TP_DEFMRU 1450 +#endif +#endif /* PPPOL2TP_SUPPORT */ + +/** + * MAXNAMELEN: max length of hostname or name for auth + */ +#ifndef MAXNAMELEN +#define MAXNAMELEN 256 +#endif + +/** + * MAXSECRETLEN: max length of password or secret + */ +#ifndef MAXSECRETLEN +#define MAXSECRETLEN 256 +#endif + +#endif /* PPP_SUPPORT */ + +/* + -------------------------------------- + ---------- Checksum options ---------- + -------------------------------------- +*/ + +/** + * LWIP_CHECKSUM_CTRL_PER_NETIF==1: Checksum generation/check can be enabled/disabled + * per netif. + * ATTENTION: if enabled, the CHECKSUM_GEN_* and CHECKSUM_CHECK_* defines must be enabled! + */ +#ifndef LWIP_CHECKSUM_CTRL_PER_NETIF +#define LWIP_CHECKSUM_CTRL_PER_NETIF 0 +#endif + +/** + * CHECKSUM_GEN_IP==1: Generate checksums in software for outgoing IP packets. + */ +#ifndef CHECKSUM_GEN_IP +#define CHECKSUM_GEN_IP 1 +#endif + +/** + * CHECKSUM_GEN_UDP==1: Generate checksums in software for outgoing UDP packets. + */ +#ifndef CHECKSUM_GEN_UDP +#define CHECKSUM_GEN_UDP 1 +#endif + +/** + * CHECKSUM_GEN_TCP==1: Generate checksums in software for outgoing TCP packets. + */ +#ifndef CHECKSUM_GEN_TCP +#define CHECKSUM_GEN_TCP 1 +#endif + +/** + * CHECKSUM_GEN_ICMP==1: Generate checksums in software for outgoing ICMP packets. + */ +#ifndef CHECKSUM_GEN_ICMP +#define CHECKSUM_GEN_ICMP 1 +#endif + +/** + * CHECKSUM_GEN_ICMP6==1: Generate checksums in software for outgoing ICMP6 packets. + */ +#ifndef CHECKSUM_GEN_ICMP6 +#define CHECKSUM_GEN_ICMP6 1 +#endif + +/** + * CHECKSUM_CHECK_IP==1: Check checksums in software for incoming IP packets. + */ +#ifndef CHECKSUM_CHECK_IP +#define CHECKSUM_CHECK_IP 1 +#endif + +/** + * CHECKSUM_CHECK_UDP==1: Check checksums in software for incoming UDP packets. + */ +#ifndef CHECKSUM_CHECK_UDP +#define CHECKSUM_CHECK_UDP 1 +#endif + +/** + * CHECKSUM_CHECK_TCP==1: Check checksums in software for incoming TCP packets. + */ +#ifndef CHECKSUM_CHECK_TCP +#define CHECKSUM_CHECK_TCP 1 +#endif + +/** + * CHECKSUM_CHECK_ICMP==1: Check checksums in software for incoming ICMP packets. + */ +#ifndef CHECKSUM_CHECK_ICMP +#define CHECKSUM_CHECK_ICMP 1 +#endif + +/** + * CHECKSUM_CHECK_ICMP6==1: Check checksums in software for incoming ICMPv6 packets + */ +#ifndef CHECKSUM_CHECK_ICMP6 +#define CHECKSUM_CHECK_ICMP6 1 +#endif + +/** + * LWIP_CHECKSUM_ON_COPY==1: Calculate checksum when copying data from + * application buffers to pbufs. + */ +#ifndef LWIP_CHECKSUM_ON_COPY +#define LWIP_CHECKSUM_ON_COPY 0 +#endif + +/* + --------------------------------------- + ---------- IPv6 options --------------- + --------------------------------------- +*/ +/** + * LWIP_IPV6==1: Enable IPv6 + */ +#ifndef LWIP_IPV6 +#define LWIP_IPV6 0 +#endif + +/** + * LWIP_IPV6_NUM_ADDRESSES: Number of IPv6 addresses per netif. + */ +#ifndef LWIP_IPV6_NUM_ADDRESSES +#define LWIP_IPV6_NUM_ADDRESSES 3 +#endif + +/** + * LWIP_IPV6_FORWARD==1: Forward IPv6 packets across netifs + */ +#ifndef LWIP_IPV6_FORWARD +#define LWIP_IPV6_FORWARD 0 +#endif + +/** + * LWIP_ICMP6==1: Enable ICMPv6 (mandatory per RFC) + */ +#ifndef LWIP_ICMP6 +#define LWIP_ICMP6 (LWIP_IPV6) +#endif + +/** + * LWIP_ICMP6_DATASIZE: bytes from original packet to send back in + * ICMPv6 error messages. + */ +#ifndef LWIP_ICMP6_DATASIZE +#define LWIP_ICMP6_DATASIZE 8 +#endif + +/** + * LWIP_ICMP6_HL: default hop limit for ICMPv6 messages + */ +#ifndef LWIP_ICMP6_HL +#define LWIP_ICMP6_HL 255 +#endif + +/** + * LWIP_IPV6_MLD==1: Enable multicast listener discovery protocol. + */ +#ifndef LWIP_IPV6_MLD +#define LWIP_IPV6_MLD (LWIP_IPV6) +#endif + +/** + * MEMP_NUM_MLD6_GROUP: Max number of IPv6 multicast that can be joined. + */ +#ifndef MEMP_NUM_MLD6_GROUP +#define MEMP_NUM_MLD6_GROUP 4 +#endif + +/** + * LWIP_IPV6_FRAG==1: Fragment outgoing IPv6 packets that are too big. + */ +#ifndef LWIP_IPV6_FRAG +#define LWIP_IPV6_FRAG 0 +#endif + +/** + * LWIP_IPV6_REASS==1: reassemble incoming IPv6 packets that fragmented + */ +#ifndef LWIP_IPV6_REASS +#define LWIP_IPV6_REASS (LWIP_IPV6) +#endif + +/** + * LWIP_ND6_QUEUEING==1: queue outgoing IPv6 packets while MAC address + * is being resolved. + */ +#ifndef LWIP_ND6_QUEUEING +#define LWIP_ND6_QUEUEING (LWIP_IPV6) +#endif + +/** + * MEMP_NUM_ND6_QUEUE: Max number of IPv6 packets to queue during MAC resolution. + */ +#ifndef MEMP_NUM_ND6_QUEUE +#define MEMP_NUM_ND6_QUEUE 20 +#endif + +/** + * LWIP_ND6_NUM_NEIGHBORS: Number of entries in IPv6 neighbor cache + */ +#ifndef LWIP_ND6_NUM_NEIGHBORS +#define LWIP_ND6_NUM_NEIGHBORS 10 +#endif + +/** + * LWIP_ND6_NUM_DESTINATIONS: number of entries in IPv6 destination cache + */ +#ifndef LWIP_ND6_NUM_DESTINATIONS +#define LWIP_ND6_NUM_DESTINATIONS 10 +#endif + +/** + * LWIP_ND6_NUM_PREFIXES: number of entries in IPv6 on-link prefixes cache + */ +#ifndef LWIP_ND6_NUM_PREFIXES +#define LWIP_ND6_NUM_PREFIXES 5 +#endif + +/** + * LWIP_ND6_NUM_ROUTERS: number of entries in IPv6 default router cache + */ +#ifndef LWIP_ND6_NUM_ROUTERS +#define LWIP_ND6_NUM_ROUTERS 3 +#endif + +/** + * LWIP_ND6_MAX_MULTICAST_SOLICIT: max number of multicast solicit messages to send + * (neighbor solicit and router solicit) + */ +#ifndef LWIP_ND6_MAX_MULTICAST_SOLICIT +#define LWIP_ND6_MAX_MULTICAST_SOLICIT 3 +#endif + +/** + * LWIP_ND6_MAX_UNICAST_SOLICIT: max number of unicast neighbor solicitation messages + * to send during neighbor reachability detection. + */ +#ifndef LWIP_ND6_MAX_UNICAST_SOLICIT +#define LWIP_ND6_MAX_UNICAST_SOLICIT 3 +#endif + +/** + * Unused: See ND RFC (time in milliseconds). + */ +#ifndef LWIP_ND6_MAX_ANYCAST_DELAY_TIME +#define LWIP_ND6_MAX_ANYCAST_DELAY_TIME 1000 +#endif + +/** + * Unused: See ND RFC + */ +#ifndef LWIP_ND6_MAX_NEIGHBOR_ADVERTISEMENT +#define LWIP_ND6_MAX_NEIGHBOR_ADVERTISEMENT 3 +#endif + +/** + * LWIP_ND6_REACHABLE_TIME: default neighbor reachable time (in milliseconds). + * May be updated by router advertisement messages. + */ +#ifndef LWIP_ND6_REACHABLE_TIME +#define LWIP_ND6_REACHABLE_TIME 30000 +#endif + +/** + * LWIP_ND6_RETRANS_TIMER: default retransmission timer for solicitation messages + */ +#ifndef LWIP_ND6_RETRANS_TIMER +#define LWIP_ND6_RETRANS_TIMER 1000 +#endif + +/** + * LWIP_ND6_DELAY_FIRST_PROBE_TIME: Delay before first unicast neighbor solicitation + * message is sent, during neighbor reachability detection. + */ +#ifndef LWIP_ND6_DELAY_FIRST_PROBE_TIME +#define LWIP_ND6_DELAY_FIRST_PROBE_TIME 5000 +#endif + +/** + * LWIP_ND6_ALLOW_RA_UPDATES==1: Allow Router Advertisement messages to update + * Reachable time and retransmission timers, and netif MTU. + */ +#ifndef LWIP_ND6_ALLOW_RA_UPDATES +#define LWIP_ND6_ALLOW_RA_UPDATES 1 +#endif + +/** + * LWIP_IPV6_SEND_ROUTER_SOLICIT==1: Send router solicitation messages during + * network startup. + */ +#ifndef LWIP_IPV6_SEND_ROUTER_SOLICIT +#define LWIP_IPV6_SEND_ROUTER_SOLICIT 1 +#endif + +/** + * LWIP_ND6_TCP_REACHABILITY_HINTS==1: Allow TCP to provide Neighbor Discovery + * with reachability hints for connected destinations. This helps avoid sending + * unicast neighbor solicitation messages. + */ +#ifndef LWIP_ND6_TCP_REACHABILITY_HINTS +#define LWIP_ND6_TCP_REACHABILITY_HINTS 1 +#endif + +/** + * LWIP_IPV6_AUTOCONFIG==1: Enable stateless address autoconfiguration as per RFC 4862. + */ +#ifndef LWIP_IPV6_AUTOCONFIG +#define LWIP_IPV6_AUTOCONFIG (LWIP_IPV6) +#endif + +/** + * LWIP_IPV6_DUP_DETECT_ATTEMPTS: Number of duplicate address detection attempts. + */ +#ifndef LWIP_IPV6_DUP_DETECT_ATTEMPTS +#define LWIP_IPV6_DUP_DETECT_ATTEMPTS 1 +#endif + +/** + * LWIP_IPV6_DHCP6==1: enable DHCPv6 stateful address autoconfiguration. + */ +#ifndef LWIP_IPV6_DHCP6 +#define LWIP_IPV6_DHCP6 0 +#endif + +/* + --------------------------------------- + ---------- Hook options --------------- + --------------------------------------- +*/ + +/* Hooks are undefined by default, define them to a function if you need them. */ + +/** + * LWIP_HOOK_IP4_INPUT(pbuf, input_netif): + * - called from ip_input() (IPv4) + * - pbuf: received struct pbuf passed to ip_input() + * - input_netif: struct netif on which the packet has been received + * Return values: + * - 0: Hook has not consumed the packet, packet is processed as normal + * - != 0: Hook has consumed the packet. + * If the hook consumed the packet, 'pbuf' is in the responsibility of the hook + * (i.e. free it when done). + */ + +/** + * LWIP_HOOK_IP4_ROUTE(dest): + * - called from ip_route() (IPv4) + * - dest: destination IPv4 address + * Returns the destination netif or NULL if no destination netif is found. In + * that case, ip_route() continues as normal. + */ + +/** + * LWIP_HOOK_IP4_ROUTE_SRC(dest, src): + * - source-based routing for IPv4 (see LWIP_HOOK_IP4_ROUTE(), src may be NULL) + */ + +/** + * LWIP_HOOK_ETHARP_GET_GW(netif, dest): + * - called from etharp_output() (IPv4) + * - netif: the netif used for sending + * - dest: the destination IPv4 address + * Returns the IPv4 address of the gateway to handle the specified destination + * IPv4 address. If NULL is returned, the netif's default gateway is used. + * The returned address MUST be reachable on the specified netif! + * This function is meant to implement advanced IPv4 routing together with + * LWIP_HOOK_IP4_ROUTE(). The actual routing/gateway table implementation is + * not part of lwIP but can e.g. be hidden in the netif's state argument. +*/ + +/** + * LWIP_HOOK_IP6_INPUT(pbuf, input_netif): + * - called from ip6_input() (IPv6) + * - pbuf: received struct pbuf passed to ip6_input() + * - input_netif: struct netif on which the packet has been received + * Return values: + * - 0: Hook has not consumed the packet, packet is processed as normal + * - != 0: Hook has consumed the packet. + * If the hook consumed the packet, 'pbuf' is in the responsibility of the hook + * (i.e. free it when done). + */ + +/** + * LWIP_HOOK_IP6_ROUTE(src, dest): + * - called from ip6_route() (IPv6) + * - src: sourc IPv6 address + * - dest: destination IPv6 address + * Returns the destination netif or NULL if no destination netif is found. In + * that case, ip6_route() continues as normal. + */ + +/** + * LWIP_HOOK_VLAN_CHECK(netif, eth_hdr, vlan_hdr): + * - called from ethernet_input() if VLAN support is enabled + * - netif: struct netif on which the packet has been received + * - eth_hdr: struct eth_hdr of the packet + * - vlan_hdr: struct eth_vlan_hdr of the packet + * Return values: + * - 0: Packet must be dropped. + * - != 0: Packet must be accepted. + */ + +/** + * LWIP_HOOK_VLAN_SET(netif, eth_hdr, vlan_hdr): + * - called from etharp_raw() and etharp_send_ip() if VLAN support is enabled + * - netif: struct netif that the packet will be sent through + * - eth_hdr: struct eth_hdr of the packet + * - vlan_hdr: struct eth_vlan_hdr of the packet + * Return values: + * - 0: Packet shall not contain VLAN header. + * - != 0: Packet shall contain VLAN header. + * Hook can be used to set prio_vid field of vlan_hdr. + */ + +/** + * LWIP_HOOK_MEMP_AVAILABLE(memp_t_type): + * - called from memp_free() when a memp pool was empty and an item is now available + */ + +/* + --------------------------------------- + ---------- Debugging options ---------- + --------------------------------------- +*/ +/** + * LWIP_DBG_MIN_LEVEL: After masking, the value of the debug is + * compared against this value. If it is smaller, then debugging + * messages are written. + */ +#ifndef LWIP_DBG_MIN_LEVEL +#define LWIP_DBG_MIN_LEVEL LWIP_DBG_LEVEL_ALL +#endif + +/** + * LWIP_DBG_TYPES_ON: A mask that can be used to globally enable/disable + * debug messages of certain types. + */ +#ifndef LWIP_DBG_TYPES_ON +#define LWIP_DBG_TYPES_ON LWIP_DBG_ON +#endif + +/** + * ETHARP_DEBUG: Enable debugging in etharp.c. + */ +#ifndef ETHARP_DEBUG +#define ETHARP_DEBUG LWIP_DBG_OFF +#endif + +/** + * NETIF_DEBUG: Enable debugging in netif.c. + */ +#ifndef NETIF_DEBUG +#define NETIF_DEBUG LWIP_DBG_OFF +#endif + +/** + * PBUF_DEBUG: Enable debugging in pbuf.c. + */ +#ifndef PBUF_DEBUG +#define PBUF_DEBUG LWIP_DBG_OFF +#endif + +/** + * API_LIB_DEBUG: Enable debugging in api_lib.c. + */ +#ifndef API_LIB_DEBUG +#define API_LIB_DEBUG LWIP_DBG_OFF +#endif + +/** + * API_MSG_DEBUG: Enable debugging in api_msg.c. + */ +#ifndef API_MSG_DEBUG +#define API_MSG_DEBUG LWIP_DBG_OFF +#endif + +/** + * SOCKETS_DEBUG: Enable debugging in sockets.c. + */ +#ifndef SOCKETS_DEBUG +#define SOCKETS_DEBUG LWIP_DBG_OFF +#endif + +/** + * ICMP_DEBUG: Enable debugging in icmp.c. + */ +#ifndef ICMP_DEBUG +#define ICMP_DEBUG LWIP_DBG_OFF +#endif + +/** + * IGMP_DEBUG: Enable debugging in igmp.c. + */ +#ifndef IGMP_DEBUG +#define IGMP_DEBUG LWIP_DBG_OFF +#endif + +/** + * INET_DEBUG: Enable debugging in inet.c. + */ +#ifndef INET_DEBUG +#define INET_DEBUG LWIP_DBG_OFF +#endif + +/** + * IP_DEBUG: Enable debugging for IP. + */ +#ifndef IP_DEBUG +#define IP_DEBUG LWIP_DBG_OFF +#endif + +/** + * IP_REASS_DEBUG: Enable debugging in ip_frag.c for both frag & reass. + */ +#ifndef IP_REASS_DEBUG +#define IP_REASS_DEBUG LWIP_DBG_OFF +#endif + +/** + * RAW_DEBUG: Enable debugging in raw.c. + */ +#ifndef RAW_DEBUG +#define RAW_DEBUG LWIP_DBG_OFF +#endif + +/** + * MEM_DEBUG: Enable debugging in mem.c. + */ +#ifndef MEM_DEBUG +#define MEM_DEBUG LWIP_DBG_OFF +#endif + +/** + * MEMP_DEBUG: Enable debugging in memp.c. + */ +#ifndef MEMP_DEBUG +#define MEMP_DEBUG LWIP_DBG_OFF +#endif + +/** + * SYS_DEBUG: Enable debugging in sys.c. + */ +#ifndef SYS_DEBUG +#define SYS_DEBUG LWIP_DBG_OFF +#endif + +/** + * TIMERS_DEBUG: Enable debugging in timers.c. + */ +#ifndef TIMERS_DEBUG +#define TIMERS_DEBUG LWIP_DBG_OFF +#endif + +/** + * TCP_DEBUG: Enable debugging for TCP. + */ +#ifndef TCP_DEBUG +#define TCP_DEBUG LWIP_DBG_OFF +#endif + +/** + * TCP_INPUT_DEBUG: Enable debugging in tcp_in.c for incoming debug. + */ +#ifndef TCP_INPUT_DEBUG +#define TCP_INPUT_DEBUG LWIP_DBG_OFF +#endif + +/** + * TCP_FR_DEBUG: Enable debugging in tcp_in.c for fast retransmit. + */ +#ifndef TCP_FR_DEBUG +#define TCP_FR_DEBUG LWIP_DBG_OFF +#endif + +/** + * TCP_RTO_DEBUG: Enable debugging in TCP for retransmit + * timeout. + */ +#ifndef TCP_RTO_DEBUG +#define TCP_RTO_DEBUG LWIP_DBG_OFF +#endif + +/** + * TCP_CWND_DEBUG: Enable debugging for TCP congestion window. + */ +#ifndef TCP_CWND_DEBUG +#define TCP_CWND_DEBUG LWIP_DBG_OFF +#endif + +/** + * TCP_WND_DEBUG: Enable debugging in tcp_in.c for window updating. + */ +#ifndef TCP_WND_DEBUG +#define TCP_WND_DEBUG LWIP_DBG_OFF +#endif + +/** + * TCP_OUTPUT_DEBUG: Enable debugging in tcp_out.c output functions. + */ +#ifndef TCP_OUTPUT_DEBUG +#define TCP_OUTPUT_DEBUG LWIP_DBG_OFF +#endif + +/** + * TCP_RST_DEBUG: Enable debugging for TCP with the RST message. + */ +#ifndef TCP_RST_DEBUG +#define TCP_RST_DEBUG LWIP_DBG_OFF +#endif + +/** + * TCP_QLEN_DEBUG: Enable debugging for TCP queue lengths. + */ +#ifndef TCP_QLEN_DEBUG +#define TCP_QLEN_DEBUG LWIP_DBG_OFF +#endif + +/** + * UDP_DEBUG: Enable debugging in UDP. + */ +#ifndef UDP_DEBUG +#define UDP_DEBUG LWIP_DBG_OFF +#endif + +/** + * TCPIP_DEBUG: Enable debugging in tcpip.c. + */ +#ifndef TCPIP_DEBUG +#define TCPIP_DEBUG LWIP_DBG_OFF +#endif + +/** + * PPP_DEBUG: Enable debugging for PPP. + */ +#ifndef PPP_DEBUG +#define PPP_DEBUG LWIP_DBG_OFF +#endif + +/** + * SLIP_DEBUG: Enable debugging in slipif.c. + */ +#ifndef SLIP_DEBUG +#define SLIP_DEBUG LWIP_DBG_OFF +#endif + +/** + * DHCP_DEBUG: Enable debugging in dhcp.c. + */ +#ifndef DHCP_DEBUG +#define DHCP_DEBUG LWIP_DBG_OFF +#endif + +/** + * AUTOIP_DEBUG: Enable debugging in autoip.c. + */ +#ifndef AUTOIP_DEBUG +#define AUTOIP_DEBUG LWIP_DBG_OFF +#endif + +/** + * DNS_DEBUG: Enable debugging for DNS. + */ +#ifndef DNS_DEBUG +#define DNS_DEBUG LWIP_DBG_OFF +#endif + +/** + * IP6_DEBUG: Enable debugging for IPv6. + */ +#ifndef IP6_DEBUG +#define IP6_DEBUG LWIP_DBG_OFF +#endif + +/* + -------------------------------------------------- + ---------- Performance tracking options ---------- + -------------------------------------------------- +*/ +/** + * LWIP_PERF: Enable performance testing for lwIP + * (if enabled, arch/perf.h is included) + */ +#ifndef LWIP_PERF +#define LWIP_PERF 0 +#endif + +#ifndef THREAD_SAFE_DEBUG +#define THREAD_SAFE_DEBUG 0 +#endif + +#endif /* LWIP_HDR_OPT_H */ diff --git a/components/lwip/include/lwip/lwip/pbuf.h b/components/lwip/include/lwip/lwip/pbuf.h new file mode 100755 index 0000000000..aaf5e294af --- /dev/null +++ b/components/lwip/include/lwip/lwip/pbuf.h @@ -0,0 +1,231 @@ +/* + * Copyright (c) 2001-2004 Swedish Institute of Computer Science. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + * + */ + +#ifndef LWIP_HDR_PBUF_H +#define LWIP_HDR_PBUF_H + +#include "lwip/opt.h" +#include "lwip/err.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** LWIP_SUPPORT_CUSTOM_PBUF==1: Custom pbufs behave much like their pbuf type + * but they are allocated by external code (initialised by calling + * pbuf_alloced_custom()) and when pbuf_free gives up their last reference, they + * are freed by calling pbuf_custom->custom_free_function(). + * Currently, the pbuf_custom code is only needed for one specific configuration + * of IP_FRAG, unless required by external driver/application code. */ +#ifndef LWIP_SUPPORT_CUSTOM_PBUF +#define LWIP_SUPPORT_CUSTOM_PBUF ((IP_FRAG && !IP_FRAG_USES_STATIC_BUF && !LWIP_NETIF_TX_SINGLE_PBUF) || (LWIP_IPV6 && LWIP_IPV6_FRAG)) +#endif + +/* @todo: We need a mechanism to prevent wasting memory in every pbuf + (TCP vs. UDP, IPv4 vs. IPv6: UDP/IPv4 packets may waste up to 28 bytes) */ + +#define PBUF_TRANSPORT_HLEN 20 +#if LWIP_IPV6 +#define PBUF_IP_HLEN 40 +#else +#define PBUF_IP_HLEN 20 +#endif + +typedef enum { + PBUF_TRANSPORT, + PBUF_IP, + PBUF_LINK, + PBUF_RAW_TX, + PBUF_RAW +} pbuf_layer; + +typedef enum { + /** pbuf data is stored in RAM, used for TX mostly, struct pbuf and its payload + are allocated in one piece of contiguous memory (so the first payload byte + can be calculated from struct pbuf) + pbuf_alloc() allocates PBUF_RAM pbufs as unchained pbufs (although that might + change in future versions) */ + PBUF_RAM, + /** pbuf data is stored in ROM, i.e. struct pbuf and its payload are located in + totally different memory areas. Since it points to ROM, payload does not + have to be copied when queued for transmission. */ + PBUF_ROM, + /** pbuf comes from the pbuf pool. Much like PBUF_ROM but payload might change + so it has to be duplicated when queued before transmitting, depending on + who has a 'ref' to it. */ + PBUF_REF, + /** pbuf payload refers to RAM. This one comes from a pool and should be used + for RX. Payload can be chained (scatter-gather RX) but like PBUF_RAM, struct + pbuf and its payload are allocated in one piece of contiguous memory (so + the first payload byte can be calculated from struct pbuf) */ + PBUF_POOL +} pbuf_type; + + +/** indicates this packet's data should be immediately passed to the application */ +#define PBUF_FLAG_PUSH 0x01U +/** indicates this is a custom pbuf: pbuf_free calls pbuf_custom->custom_free_function() + when the last reference is released (plus custom PBUF_RAM cannot be trimmed) */ +#define PBUF_FLAG_IS_CUSTOM 0x02U +/** indicates this pbuf is UDP multicast to be looped back */ +#define PBUF_FLAG_MCASTLOOP 0x04U +/** indicates this pbuf was received as link-level broadcast */ +#define PBUF_FLAG_LLBCAST 0x08U +/** indicates this pbuf was received as link-level multicast */ +#define PBUF_FLAG_LLMCAST 0x10U +/** indicates this pbuf includes a TCP FIN flag */ +#define PBUF_FLAG_TCP_FIN 0x20U + +struct pbuf { + /** next pbuf in singly linked pbuf chain */ + struct pbuf *next; + + /** pointer to the actual data in the buffer */ + void *payload; + + /** + * total length of this buffer and all next buffers in chain + * belonging to the same packet. + * + * For non-queue packet chains this is the invariant: + * p->tot_len == p->len + (p->next? p->next->tot_len: 0) + */ + u16_t tot_len; + + /** length of this buffer */ + u16_t len; + + /** pbuf_type as u8_t instead of enum to save space */ + u8_t /*pbuf_type*/ type; + + /** misc flags */ + u8_t flags; + + /** + * the reference count always equals the number of pointers + * that refer to this pbuf. This can be pointers from an application, + * the stack itself, or pbuf->next pointers from a chain. + */ + u16_t ref; + +#ifdef LWIP_ESP8266 + void *eb; +#endif +}; + + +/** Helper struct for const-correctness only. + * The only meaning of this one is to provide a const payload pointer + * for PBUF_ROM type. + */ +struct pbuf_rom { + /** next pbuf in singly linked pbuf chain */ + struct pbuf *next; + + /** pointer to the actual data in the buffer */ + const void *payload; +}; + +#if LWIP_SUPPORT_CUSTOM_PBUF +/** Prototype for a function to free a custom pbuf */ +typedef void (*pbuf_free_custom_fn)(struct pbuf *p); + +/** A custom pbuf: like a pbuf, but following a function pointer to free it. */ +struct pbuf_custom { + /** The actual pbuf */ + struct pbuf pbuf; + /** This function is called when pbuf_free deallocates this pbuf(_custom) */ + pbuf_free_custom_fn custom_free_function; +}; +#endif /* LWIP_SUPPORT_CUSTOM_PBUF */ + +#if LWIP_TCP && TCP_QUEUE_OOSEQ +/** Define this to 0 to prevent freeing ooseq pbufs when the PBUF_POOL is empty */ +#ifndef PBUF_POOL_FREE_OOSEQ +#define PBUF_POOL_FREE_OOSEQ 1 +#endif /* PBUF_POOL_FREE_OOSEQ */ +#if NO_SYS && PBUF_POOL_FREE_OOSEQ +extern volatile u8_t pbuf_free_ooseq_pending; +void pbuf_free_ooseq(void); +/** When not using sys_check_timeouts(), call PBUF_CHECK_FREE_OOSEQ() + at regular intervals from main level to check if ooseq pbufs need to be + freed! */ +#define PBUF_CHECK_FREE_OOSEQ() do { if(pbuf_free_ooseq_pending) { \ + /* pbuf_alloc() reported PBUF_POOL to be empty -> try to free some \ + ooseq queued pbufs now */ \ + pbuf_free_ooseq(); }}while(0) +#endif /* NO_SYS && PBUF_POOL_FREE_OOSEQ*/ +#endif /* LWIP_TCP && TCP_QUEUE_OOSEQ */ + +/* Initializes the pbuf module. This call is empty for now, but may not be in future. */ +#define pbuf_init() + +struct pbuf *pbuf_alloc(pbuf_layer l, u16_t length, pbuf_type type); +#if LWIP_SUPPORT_CUSTOM_PBUF +struct pbuf *pbuf_alloced_custom(pbuf_layer l, u16_t length, pbuf_type type, + struct pbuf_custom *p, void *payload_mem, + u16_t payload_mem_len); +#endif /* LWIP_SUPPORT_CUSTOM_PBUF */ +void pbuf_realloc(struct pbuf *p, u16_t size); +u8_t pbuf_header(struct pbuf *p, s16_t header_size); +u8_t pbuf_header_force(struct pbuf *p, s16_t header_size); +void pbuf_ref(struct pbuf *p); +u8_t pbuf_free(struct pbuf *p); +u8_t pbuf_clen(struct pbuf *p); +void pbuf_cat(struct pbuf *head, struct pbuf *tail); +void pbuf_chain(struct pbuf *head, struct pbuf *tail); +struct pbuf *pbuf_dechain(struct pbuf *p); +err_t pbuf_copy(struct pbuf *p_to, struct pbuf *p_from); +u16_t pbuf_copy_partial(struct pbuf *p, void *dataptr, u16_t len, u16_t offset); +err_t pbuf_take(struct pbuf *buf, const void *dataptr, u16_t len); +err_t pbuf_take_at(struct pbuf *buf, const void *dataptr, u16_t len, u16_t offset); +struct pbuf *pbuf_skip(struct pbuf* in, u16_t in_offset, u16_t* out_offset); +struct pbuf *pbuf_coalesce(struct pbuf *p, pbuf_layer layer); +#if LWIP_CHECKSUM_ON_COPY +err_t pbuf_fill_chksum(struct pbuf *p, u16_t start_offset, const void *dataptr, + u16_t len, u16_t *chksum); +#endif /* LWIP_CHECKSUM_ON_COPY */ +#if LWIP_TCP && TCP_QUEUE_OOSEQ && LWIP_WND_SCALE +void pbuf_split_64k(struct pbuf *p, struct pbuf **rest); +#endif /* LWIP_TCP && TCP_QUEUE_OOSEQ && LWIP_WND_SCALE */ + +u8_t pbuf_get_at(struct pbuf* p, u16_t offset); +void pbuf_put_at(struct pbuf* p, u16_t offset, u8_t data); +u16_t pbuf_memcmp(struct pbuf* p, u16_t offset, const void* s2, u16_t n); +u16_t pbuf_memfind(struct pbuf* p, const void* mem, u16_t mem_len, u16_t start_offset); +u16_t pbuf_strstr(struct pbuf* p, const char* substr); + +#ifdef __cplusplus +} +#endif + +#endif /* LWIP_HDR_PBUF_H */ diff --git a/components/lwip/include/lwip/lwip/pppapi.h b/components/lwip/include/lwip/lwip/pppapi.h new file mode 100755 index 0000000000..3ddf3daf9a --- /dev/null +++ b/components/lwip/include/lwip/lwip/pppapi.h @@ -0,0 +1,148 @@ +/* + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + */ + +#ifndef __LWIP_PPPAPI_H__ +#define __LWIP_PPPAPI_H__ + +#include "lwip/opt.h" + +#if LWIP_PPP_API /* don't build if not configured for use in lwipopts.h */ + +#include "lwip/sys.h" +#include "lwip/netif.h" +#include "lwip/priv/tcpip_priv.h" +#include "netif/ppp/ppp.h" +#if PPPOS_SUPPORT +#include "netif/ppp/pppos.h" +#endif /* PPPOS_SUPPORT */ + +#ifdef __cplusplus +extern "C" { +#endif + +struct pppapi_msg_msg { + ppp_pcb *ppp; + union { + struct { + u8_t authtype; + const char *user; + const char *passwd; + } setauth; +#if PPP_NOTIFY_PHASE + struct { + ppp_notify_phase_cb_fn notify_phase_cb; + } setnotifyphasecb; +#endif /* PPP_NOTIFY_PHASE */ +#if PPPOS_SUPPORT + struct { + struct netif *pppif; + pppos_output_cb_fn output_cb; + ppp_link_status_cb_fn link_status_cb; + void *ctx_cb; + } serialcreate; +#endif /* PPPOS_SUPPORT */ +#if PPPOE_SUPPORT + struct { + struct netif *pppif; + struct netif *ethif; + const char *service_name; + const char *concentrator_name; + ppp_link_status_cb_fn link_status_cb; + void *ctx_cb; + } ethernetcreate; +#endif /* PPPOE_SUPPORT */ +#if PPPOL2TP_SUPPORT + struct { + struct netif *pppif; + struct netif *netif; + ip_addr_t *ipaddr; + u16_t port; +#if PPPOL2TP_AUTH_SUPPORT + const u8_t *secret; + u8_t secret_len; +#endif /* PPPOL2TP_AUTH_SUPPORT */ + ppp_link_status_cb_fn link_status_cb; + void *ctx_cb; + } l2tpcreate; +#endif /* PPPOL2TP_SUPPORT */ + struct { + u16_t holdoff; + } connect; +#if PPP_SERVER + struct { + struct ppp_addrs *addrs; + } listen; +#endif /* PPP_SERVER */ + struct { + u8_t nocarrier; + } close; + struct { + u8_t cmd; + void *arg; + } ioctl; + } msg; +}; + +struct pppapi_msg { + struct tcpip_api_call call; + struct pppapi_msg_msg msg; +}; + +/* API for application */ +void pppapi_set_default(ppp_pcb *pcb); +void pppapi_set_auth(ppp_pcb *pcb, u8_t authtype, const char *user, const char *passwd); +#if PPP_NOTIFY_PHASE +void pppapi_set_notify_phase_callback(ppp_pcb *pcb, ppp_notify_phase_cb_fn notify_phase_cb); +#endif /* PPP_NOTIFY_PHASE */ +#if PPPOS_SUPPORT +ppp_pcb *pppapi_pppos_create(struct netif *pppif, pppos_output_cb_fn output_cb, ppp_link_status_cb_fn link_status_cb, void *ctx_cb); +#endif /* PPPOS_SUPPORT */ +#if PPPOE_SUPPORT +ppp_pcb *pppapi_pppoe_create(struct netif *pppif, struct netif *ethif, const char *service_name, + const char *concentrator_name, ppp_link_status_cb_fn link_status_cb, + void *ctx_cb); +#endif /* PPPOE_SUPPORT */ +#if PPPOL2TP_SUPPORT +ppp_pcb *pppapi_pppol2tp_create(struct netif *pppif, struct netif *netif, ip_addr_t *ipaddr, u16_t port, + const u8_t *secret, u8_t secret_len, + ppp_link_status_cb_fn link_status_cb, void *ctx_cb); +#endif /* PPPOL2TP_SUPPORT */ +err_t pppapi_connect(ppp_pcb *pcb, u16_t holdoff); +#if PPP_SERVER +err_t pppapi_listen(ppp_pcb *pcb, struct ppp_addrs *addrs); +#endif /* PPP_SERVER */ +err_t pppapi_close(ppp_pcb *pcb, u8_t nocarrier); +err_t pppapi_free(ppp_pcb *pcb); +err_t pppapi_ioctl(ppp_pcb *pcb, u8_t cmd, void *arg); + +#ifdef __cplusplus +} +#endif + +#endif /* LWIP_PPP_API */ + +#endif /* __LWIP_PPPAPI_H__ */ diff --git a/components/lwip/include/lwip/lwip/priv/api_msg.h b/components/lwip/include/lwip/lwip/priv/api_msg.h new file mode 100755 index 0000000000..dceff82d64 --- /dev/null +++ b/components/lwip/include/lwip/lwip/priv/api_msg.h @@ -0,0 +1,260 @@ +/* + * Copyright (c) 2001-2004 Swedish Institute of Computer Science. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + * + */ +#ifndef LWIP_HDR_API_MSG_H +#define LWIP_HDR_API_MSG_H + +#include "lwip/opt.h" + +#if LWIP_NETCONN || LWIP_SOCKET /* don't build if not configured for use in lwipopts.h */ +/* Note: Netconn API is always available when sockets are enabled - + * sockets are implemented on top of them */ + +#include /* for size_t */ + +#include "lwip/ip_addr.h" +#include "lwip/err.h" +#include "lwip/sys.h" +#include "lwip/igmp.h" +#include "lwip/api.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#if LWIP_MPU_COMPATIBLE +#define API_MSG_M_DEF(m) m +#define API_MSG_M_DEF_C(t, m) t m +#if LWIP_NETCONN_SEM_PER_THREAD +#define API_MSG_M_DEF_SEM(m) *m +#else +#define API_MSG_M_DEF_SEM(m) API_MSG_M_DEF(m) +#endif +#else /* LWIP_MPU_COMPATIBLE */ +#define API_MSG_M_DEF(m) *m +#define API_MSG_M_DEF_C(t, m) const t * m +#define API_MSG_M_DEF_SEM(m) API_MSG_M_DEF(m) +#endif /* LWIP_MPU_COMPATIBLE */ + +/* For the netconn API, these values are use as a bitmask! */ +#define NETCONN_SHUT_RD 1 +#define NETCONN_SHUT_WR 2 +#define NETCONN_SHUT_RDWR (NETCONN_SHUT_RD | NETCONN_SHUT_WR) + +/* IP addresses and port numbers are expected to be in + * the same byte order as in the corresponding pcb. + */ +/** This struct includes everything that is necessary to execute a function + for a netconn in another thread context (mainly used to process netconns + in the tcpip_thread context to be thread safe). */ +struct api_msg_msg { + /** The netconn which to process - always needed: it includes the semaphore + which is used to block the application thread until the function finished. */ + struct netconn *conn; + /** The return value of the function executed in tcpip_thread. */ + err_t err; + /** Depending on the executed function, one of these union members is used */ + union { + /** used for lwip_netconn_do_send */ + struct netbuf *b; + /** used for lwip_netconn_do_newconn */ + struct { + u8_t proto; + } n; + /** used for lwip_netconn_do_bind and lwip_netconn_do_connect */ + struct { + API_MSG_M_DEF_C(ip_addr_t, ipaddr); + u16_t port; + } bc; + /** used for lwip_netconn_do_getaddr */ + struct { + ip_addr_t API_MSG_M_DEF(ipaddr); + u16_t API_MSG_M_DEF(port); + u8_t local; + } ad; + /** used for lwip_netconn_do_write */ + struct { + const void *dataptr; + size_t len; + u8_t apiflags; +#if LWIP_SO_SNDTIMEO + u32_t time_started; +#endif /* LWIP_SO_SNDTIMEO */ + } w; + /** used for lwip_netconn_do_recv */ + struct { + u32_t len; + } r; +#if LWIP_TCP + /** used for lwip_netconn_do_close (/shutdown) */ + struct { + u8_t shut; +#if LWIP_SO_SNDTIMEO || LWIP_SO_LINGER + u32_t time_started; +#else /* LWIP_SO_SNDTIMEO || LWIP_SO_LINGER */ + u8_t polls_left; +#endif /* LWIP_SO_SNDTIMEO || LWIP_SO_LINGER */ + } sd; +#endif /* LWIP_TCP */ +#if LWIP_IGMP || (LWIP_IPV6 && LWIP_IPV6_MLD) + /** used for lwip_netconn_do_join_leave_group */ + struct { + API_MSG_M_DEF_C(ip_addr_t, multiaddr); + API_MSG_M_DEF_C(ip_addr_t, netif_addr); + enum netconn_igmp join_or_leave; + } jl; +#endif /* LWIP_IGMP || (LWIP_IPV6 && LWIP_IPV6_MLD) */ +#if TCP_LISTEN_BACKLOG + struct { + u8_t backlog; + } lb; +#endif /* TCP_LISTEN_BACKLOG */ + } msg; +#if LWIP_NETCONN_SEM_PER_THREAD + sys_sem_t* op_completed_sem; +#endif /* LWIP_NETCONN_SEM_PER_THREAD */ +}; + +#if LWIP_NETCONN_SEM_PER_THREAD +#define LWIP_API_MSG_SEM(msg) ((msg)->op_completed_sem) +#else /* LWIP_NETCONN_SEM_PER_THREAD */ +#define LWIP_API_MSG_SEM(msg) (&(msg)->conn->op_completed) +#endif /* LWIP_NETCONN_SEM_PER_THREAD */ + + +/** This struct contains a function to execute in another thread context and + a struct api_msg_msg that serves as an argument for this function. + This is passed to tcpip_apimsg to execute functions in tcpip_thread context. */ +struct api_msg { + /** function to execute in tcpip_thread context */ + void (* function)(void *msg); + /** arguments for this function */ + struct api_msg_msg msg; +}; + +#if LWIP_DNS +/** As lwip_netconn_do_gethostbyname requires more arguments but doesn't require a netconn, + it has its own struct (to avoid struct api_msg getting bigger than necessary). + lwip_netconn_do_gethostbyname must be called using tcpip_callback instead of tcpip_apimsg + (see netconn_gethostbyname). */ +struct dns_api_msg { + /** Hostname to query or dotted IP address string */ +#if LWIP_MPU_COMPATIBLE + char name[DNS_MAX_NAME_LENGTH]; +#else /* LWIP_MPU_COMPATIBLE */ + const char *name; +#endif /* LWIP_MPU_COMPATIBLE */ + /** The resolved address is stored here */ + ip_addr_t API_MSG_M_DEF(addr); +#if LWIP_IPV4 && LWIP_IPV6 + /** Type of resolve call */ + u8_t dns_addrtype; +#endif /* LWIP_IPV4 && LWIP_IPV6 */ + /** This semaphore is posted when the name is resolved, the application thread + should wait on it. */ + sys_sem_t API_MSG_M_DEF_SEM(sem); + /** Errors are given back here */ + err_t API_MSG_M_DEF(err); +}; +#endif /* LWIP_DNS */ + +#if LWIP_NETCONN_SEM_PER_THREAD +#ifdef LWIP_ESP8266 +#define LWIP_NETCONN_THREAD_SEM_GET() sys_thread_sem() +#define LWIP_NETCONN_THREAD_SEM_ALLOC() +#define LWIP_NETCONN_THREAD_SEM_FREE() +#endif +#endif + +#if LWIP_TCPIP_CORE_LOCKING +#ifdef LWIP_DEBUG +#define TCIP_APIMSG_SET_ERR(m, e) (m)->msg.err = e /* catch functions that don't set err */ +#else +#define TCIP_APIMSG_SET_ERR(m, e) +#endif +#if LWIP_NETCONN_SEM_PER_THREAD +#define TCPIP_APIMSG_SET_SEM(m) ((m)->msg.op_completed_sem = LWIP_NETCONN_THREAD_SEM_GET()) +#else +#define TCPIP_APIMSG_SET_SEM(m) +#endif +#define TCPIP_APIMSG_NOERR(m,f) do { \ + TCIP_APIMSG_SET_ERR(m, ERR_VAL); \ + TCPIP_APIMSG_SET_SEM(m); \ + LOCK_TCPIP_CORE(); \ + f(&((m)->msg)); \ + UNLOCK_TCPIP_CORE(); \ +} while(0) +#define TCPIP_APIMSG(m,f,e) do { \ + TCPIP_APIMSG_NOERR(m,f); \ + (e) = (m)->msg.err; \ +} while(0) +#define TCPIP_APIMSG_ACK(m) NETCONN_SET_SAFE_ERR((m)->conn, (m)->err) +#else /* LWIP_TCPIP_CORE_LOCKING */ +#define TCPIP_APIMSG_NOERR(m,f) do { (m)->function = f; tcpip_apimsg(m); } while(0) +#define TCPIP_APIMSG(m,f,e) do { (m)->function = f; (e) = tcpip_apimsg(m); } while(0) +#define TCPIP_APIMSG_ACK(m) do { NETCONN_SET_SAFE_ERR((m)->conn, (m)->err); sys_sem_signal(LWIP_API_MSG_SEM(m)); } while(0) + +#ifdef LWIP_ESP8266 +#define TCPIP_APIMSG_ACK_SND(m) do { NETCONN_SET_SAFE_ERR((m)->conn, (m)->err); sys_sem_signal(LWIP_API_MSG_SND_SEM(m)); } while(0) +#endif + +#endif /* LWIP_TCPIP_CORE_LOCKING */ + +void lwip_netconn_do_newconn (void *m); +void lwip_netconn_do_delconn (void *m); +void lwip_netconn_do_bind (void *m); +void lwip_netconn_do_connect (void *m); +void lwip_netconn_do_disconnect (void *m); +void lwip_netconn_do_listen (void *m); +void lwip_netconn_do_send (void *m); +void lwip_netconn_do_recv (void *m); +void lwip_netconn_do_write (void *m); +void lwip_netconn_do_getaddr (void *m); +void lwip_netconn_do_close (void *m); +void lwip_netconn_do_shutdown (void *m); +#if LWIP_IGMP || (LWIP_IPV6 && LWIP_IPV6_MLD) +void lwip_netconn_do_join_leave_group(void *m); +#endif /* LWIP_IGMP || (LWIP_IPV6 && LWIP_IPV6_MLD) */ + +#if LWIP_DNS +void lwip_netconn_do_gethostbyname(void *arg); +#endif /* LWIP_DNS */ + +struct netconn* netconn_alloc(enum netconn_type t, netconn_callback callback); +void netconn_free(struct netconn *conn); + +#ifdef __cplusplus +} +#endif + +#endif /* LWIP_NETCONN || LWIP_SOCKET */ + +#endif /* LWIP_HDR_API_MSG_H */ diff --git a/components/lwip/include/lwip/lwip/priv/memp_priv.h b/components/lwip/include/lwip/lwip/priv/memp_priv.h new file mode 100755 index 0000000000..34edb9d971 --- /dev/null +++ b/components/lwip/include/lwip/lwip/priv/memp_priv.h @@ -0,0 +1,163 @@ +/* + * Copyright (c) 2001-2004 Swedish Institute of Computer Science. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + * + */ + +#ifndef LWIP_HDR_MEMP_PRIV_H +#define LWIP_HDR_MEMP_PRIV_H + +#include "lwip/opt.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#include "lwip/mem.h" + +#if MEMP_OVERFLOW_CHECK +/* if MEMP_OVERFLOW_CHECK is turned on, we reserve some bytes at the beginning + * and at the end of each element, initialize them as 0xcd and check + * them later. */ +/* If MEMP_OVERFLOW_CHECK is >= 2, on every call to memp_malloc or memp_free, + * every single element in each pool is checked! + * This is VERY SLOW but also very helpful. */ +/* MEMP_SANITY_REGION_BEFORE and MEMP_SANITY_REGION_AFTER can be overridden in + * lwipopts.h to change the amount reserved for checking. */ +#ifndef MEMP_SANITY_REGION_BEFORE +#define MEMP_SANITY_REGION_BEFORE 16 +#endif /* MEMP_SANITY_REGION_BEFORE*/ +#if MEMP_SANITY_REGION_BEFORE > 0 +#define MEMP_SANITY_REGION_BEFORE_ALIGNED LWIP_MEM_ALIGN_SIZE(MEMP_SANITY_REGION_BEFORE) +#else +#define MEMP_SANITY_REGION_BEFORE_ALIGNED 0 +#endif /* MEMP_SANITY_REGION_BEFORE*/ +#ifndef MEMP_SANITY_REGION_AFTER +#define MEMP_SANITY_REGION_AFTER 16 +#endif /* MEMP_SANITY_REGION_AFTER*/ +#if MEMP_SANITY_REGION_AFTER > 0 +#define MEMP_SANITY_REGION_AFTER_ALIGNED LWIP_MEM_ALIGN_SIZE(MEMP_SANITY_REGION_AFTER) +#else +#define MEMP_SANITY_REGION_AFTER_ALIGNED 0 +#endif /* MEMP_SANITY_REGION_AFTER*/ + +/* MEMP_SIZE: save space for struct memp and for sanity check */ +#define MEMP_SIZE (LWIP_MEM_ALIGN_SIZE(sizeof(struct memp)) + MEMP_SANITY_REGION_BEFORE_ALIGNED) +#define MEMP_ALIGN_SIZE(x) (LWIP_MEM_ALIGN_SIZE(x) + MEMP_SANITY_REGION_AFTER_ALIGNED) + +#else /* MEMP_OVERFLOW_CHECK */ + +/* No sanity checks + * We don't need to preserve the struct memp while not allocated, so we + * can save a little space and set MEMP_SIZE to 0. + */ +#define MEMP_SIZE 0 +#define MEMP_ALIGN_SIZE(x) (LWIP_MEM_ALIGN_SIZE(x)) + +#endif /* MEMP_OVERFLOW_CHECK */ + +struct memp { + struct memp *next; +#if MEMP_OVERFLOW_CHECK + const char *file; + int line; +#endif /* MEMP_OVERFLOW_CHECK */ +}; + +#if MEM_USE_POOLS +/* Use a helper type to get the start and end of the user "memory pools" for mem_malloc */ +typedef enum { + /* Get the first (via: + MEMP_POOL_HELPER_START = ((u8_t) 1*MEMP_POOL_A + 0*MEMP_POOL_B + 0*MEMP_POOL_C + 0)*/ + MEMP_POOL_HELPER_FIRST = ((u8_t) +#define LWIP_MEMPOOL(name,num,size,desc) +#define LWIP_MALLOC_MEMPOOL_START 1 +#define LWIP_MALLOC_MEMPOOL(num, size) * MEMP_POOL_##size + 0 +#define LWIP_MALLOC_MEMPOOL_END +#include "lwip/priv/memp_std.h" + ) , + /* Get the last (via: + MEMP_POOL_HELPER_END = ((u8_t) 0 + MEMP_POOL_A*0 + MEMP_POOL_B*0 + MEMP_POOL_C*1) */ + MEMP_POOL_HELPER_LAST = ((u8_t) +#define LWIP_MEMPOOL(name,num,size,desc) +#define LWIP_MALLOC_MEMPOOL_START +#define LWIP_MALLOC_MEMPOOL(num, size) 0 + MEMP_POOL_##size * +#define LWIP_MALLOC_MEMPOOL_END 1 +#include "lwip/priv/memp_std.h" + ) +} memp_pool_helper_t; + +/* The actual start and stop values are here (cast them over) + We use this helper type and these defines so we can avoid using const memp_t values */ +#define MEMP_POOL_FIRST ((memp_t) MEMP_POOL_HELPER_FIRST) +#define MEMP_POOL_LAST ((memp_t) MEMP_POOL_HELPER_LAST) +#endif /* MEM_USE_POOLS */ + +struct memp_desc { + /** Element size */ + u16_t size; + +#if !MEMP_MEM_MALLOC + /** Number of elements */ + u16_t num; + +#if defined(LWIP_DEBUG) || MEMP_OVERFLOW_CHECK + /** Textual description */ + const char *desc; +#endif /* LWIP_DEBUG || MEMP_OVERFLOW_CHECK */ + + /** Base */ + u8_t *base; + + /** First free element of each pool. Elements form a linked list. */ + struct memp **tab; +#endif /* MEMP_MEM_MALLOC */ +}; + +#ifdef LWIP_DEBUG +#define DECLARE_LWIP_MEMPOOL_DESC(desc) (desc), +#else +#define DECLARE_LWIP_MEMPOOL_DESC(desc) +#endif + +void memp_init_pool(const struct memp_desc *desc); + +#if MEMP_OVERFLOW_CHECK +void *memp_malloc_pool_fn(const struct memp_desc* desc, const char* file, const int line); +#define memp_malloc_pool(d) memp_malloc_pool_fn((d), __FILE__, __LINE__) +#else +void *memp_malloc_pool(const struct memp_desc *desc); +#endif +void memp_free_pool(const struct memp_desc* desc, void *mem); + +#ifdef __cplusplus +} +#endif + +#endif /* LWIP_HDR_MEMP_PRIV_H */ diff --git a/components/lwip/include/lwip/lwip/priv/memp_std.h b/components/lwip/include/lwip/lwip/priv/memp_std.h new file mode 100755 index 0000000000..4def116d82 --- /dev/null +++ b/components/lwip/include/lwip/lwip/priv/memp_std.h @@ -0,0 +1,151 @@ +/* + * SETUP: Make sure we define everything we will need. + * + * We have create three types of pools: + * 1) MEMPOOL - standard pools + * 2) MALLOC_MEMPOOL - to be used by mem_malloc in mem.c + * 3) PBUF_MEMPOOL - a mempool of pbuf's, so include space for the pbuf struct + * + * If the include'r doesn't require any special treatment of each of the types + * above, then will declare #2 & #3 to be just standard mempools. + */ +#ifndef LWIP_MALLOC_MEMPOOL +/* This treats "malloc pools" just like any other pool. + The pools are a little bigger to provide 'size' as the amount of user data. */ +#define LWIP_MALLOC_MEMPOOL(num, size) LWIP_MEMPOOL(POOL_##size, num, (size + LWIP_MEM_ALIGN_SIZE(sizeof(struct memp_malloc_helper))), "MALLOC_"#size) +#define LWIP_MALLOC_MEMPOOL_START +#define LWIP_MALLOC_MEMPOOL_END +#endif /* LWIP_MALLOC_MEMPOOL */ + +#ifndef LWIP_PBUF_MEMPOOL +/* This treats "pbuf pools" just like any other pool. + * Allocates buffers for a pbuf struct AND a payload size */ +#define LWIP_PBUF_MEMPOOL(name, num, payload, desc) LWIP_MEMPOOL(name, num, (MEMP_ALIGN_SIZE(sizeof(struct pbuf)) + MEMP_ALIGN_SIZE(payload)), desc) +#endif /* LWIP_PBUF_MEMPOOL */ + + +/* + * A list of internal pools used by LWIP. + * + * LWIP_MEMPOOL(pool_name, number_elements, element_size, pool_description) + * creates a pool name MEMP_pool_name. description is used in stats.c + */ +#if LWIP_RAW +LWIP_MEMPOOL(RAW_PCB, MEMP_NUM_RAW_PCB, sizeof(struct raw_pcb), "RAW_PCB") +#endif /* LWIP_RAW */ + +#if LWIP_UDP +LWIP_MEMPOOL(UDP_PCB, MEMP_NUM_UDP_PCB, sizeof(struct udp_pcb), "UDP_PCB") +#endif /* LWIP_UDP */ + +#if LWIP_TCP +LWIP_MEMPOOL(TCP_PCB, MEMP_NUM_TCP_PCB, sizeof(struct tcp_pcb), "TCP_PCB") +LWIP_MEMPOOL(TCP_PCB_LISTEN, MEMP_NUM_TCP_PCB_LISTEN, sizeof(struct tcp_pcb_listen), "TCP_PCB_LISTEN") +LWIP_MEMPOOL(TCP_SEG, MEMP_NUM_TCP_SEG, sizeof(struct tcp_seg), "TCP_SEG") +#endif /* LWIP_TCP */ + +#if LWIP_IPV4 && IP_REASSEMBLY +LWIP_MEMPOOL(REASSDATA, MEMP_NUM_REASSDATA, sizeof(struct ip_reassdata), "REASSDATA") +#endif /* LWIP_IPV4 && IP_REASSEMBLY */ +#if (IP_FRAG && !IP_FRAG_USES_STATIC_BUF && !LWIP_NETIF_TX_SINGLE_PBUF) || (LWIP_IPV6 && LWIP_IPV6_FRAG) +LWIP_MEMPOOL(FRAG_PBUF, MEMP_NUM_FRAG_PBUF, sizeof(struct pbuf_custom_ref),"FRAG_PBUF") +#endif /* IP_FRAG && !IP_FRAG_USES_STATIC_BUF && !LWIP_NETIF_TX_SINGLE_PBUF */ + +#if LWIP_NETCONN || LWIP_SOCKET +LWIP_MEMPOOL(NETBUF, MEMP_NUM_NETBUF, sizeof(struct netbuf), "NETBUF") +LWIP_MEMPOOL(NETCONN, MEMP_NUM_NETCONN, sizeof(struct netconn), "NETCONN") +#endif /* LWIP_NETCONN || LWIP_SOCKET */ + +#if NO_SYS==0 +LWIP_MEMPOOL(TCPIP_MSG_API, MEMP_NUM_TCPIP_MSG_API, sizeof(struct tcpip_msg), "TCPIP_MSG_API") +#if LWIP_MPU_COMPATIBLE +LWIP_MEMPOOL(API_MSG, MEMP_NUM_API_MSG, sizeof(struct api_msg), "API_MSG") +#if LWIP_DNS +LWIP_MEMPOOL(DNS_API_MSG, MEMP_NUM_DNS_API_MSG, sizeof(struct dns_api_msg), "DNS_API_MSG") +#endif +#if LWIP_SOCKET && !LWIP_TCPIP_CORE_LOCKING +LWIP_MEMPOOL(SOCKET_SETGETSOCKOPT_DATA, MEMP_NUM_SOCKET_SETGETSOCKOPT_DATA, sizeof(struct lwip_setgetsockopt_data), "SOCKET_SETGETSOCKOPT_DATA") +#endif +#if LWIP_NETIF_API +LWIP_MEMPOOL(NETIFAPI_MSG, MEMP_NUM_NETIFAPI_MSG, sizeof(struct netifapi_msg), "NETIFAPI_MSG") +#endif +#endif /* LWIP_MPU_COMPATIBLE */ +#if !LWIP_TCPIP_CORE_LOCKING_INPUT +LWIP_MEMPOOL(TCPIP_MSG_INPKT,MEMP_NUM_TCPIP_MSG_INPKT, sizeof(struct tcpip_msg), "TCPIP_MSG_INPKT") +#endif /* !LWIP_TCPIP_CORE_LOCKING_INPUT */ +#endif /* NO_SYS==0 */ + +#if LWIP_IPV4 && LWIP_ARP && ARP_QUEUEING +LWIP_MEMPOOL(ARP_QUEUE, MEMP_NUM_ARP_QUEUE, sizeof(struct etharp_q_entry), "ARP_QUEUE") +#endif /* LWIP_IPV4 && LWIP_ARP && ARP_QUEUEING */ + +#if LWIP_IGMP +LWIP_MEMPOOL(IGMP_GROUP, MEMP_NUM_IGMP_GROUP, sizeof(struct igmp_group), "IGMP_GROUP") +#endif /* LWIP_IGMP */ + +#if (!NO_SYS || (NO_SYS && !NO_SYS_NO_TIMERS)) /* LWIP_TIMERS */ +LWIP_MEMPOOL(SYS_TIMEOUT, MEMP_NUM_SYS_TIMEOUT, sizeof(struct sys_timeo), "SYS_TIMEOUT") +#endif /* LWIP_TIMERS */ + +#if LWIP_DNS && LWIP_SOCKET +LWIP_MEMPOOL(NETDB, MEMP_NUM_NETDB, NETDB_ELEM_SIZE, "NETDB") +#endif /* LWIP_DNS && LWIP_SOCKET */ +#if LWIP_DNS && DNS_LOCAL_HOSTLIST && DNS_LOCAL_HOSTLIST_IS_DYNAMIC +LWIP_MEMPOOL(LOCALHOSTLIST, MEMP_NUM_LOCALHOSTLIST, LOCALHOSTLIST_ELEM_SIZE, "LOCALHOSTLIST") +#endif /* LWIP_DNS && DNS_LOCAL_HOSTLIST && DNS_LOCAL_HOSTLIST_IS_DYNAMIC */ + +#if PPP_SUPPORT +LWIP_MEMPOOL(PPP_PCB, MEMP_NUM_PPP_PCB, sizeof(ppp_pcb), "PPP_PCB") +#if PPPOS_SUPPORT +LWIP_MEMPOOL(PPPOS_PCB, MEMP_NUM_PPPOS_INTERFACES, sizeof(pppos_pcb), "PPPOS_PCB") +#endif /* PPPOS_SUPPORT */ +#if PPPOE_SUPPORT +LWIP_MEMPOOL(PPPOE_IF, MEMP_NUM_PPPOE_INTERFACES, sizeof(struct pppoe_softc), "PPPOE_IF") +#endif /* PPPOE_SUPPORT */ +#if PPPOL2TP_SUPPORT +LWIP_MEMPOOL(PPPOL2TP_PCB, MEMP_NUM_PPPOL2TP_INTERFACES, sizeof(pppol2tp_pcb), "PPPOL2TP_PCB") +#endif /* PPPOL2TP_SUPPORT */ +#endif /* PPP_SUPPORT */ + +#if LWIP_IPV6 && LWIP_ND6_QUEUEING +LWIP_MEMPOOL(ND6_QUEUE, MEMP_NUM_ND6_QUEUE, sizeof(struct nd6_q_entry), "ND6_QUEUE") +#endif /* LWIP_IPV6 && LWIP_ND6_QUEUEING */ + +#if LWIP_IPV6 && LWIP_IPV6_REASS +LWIP_MEMPOOL(IP6_REASSDATA, MEMP_NUM_REASSDATA, sizeof(struct ip6_reassdata), "IP6_REASSDATA") +#endif /* LWIP_IPV6 && LWIP_IPV6_REASS */ + +#if LWIP_IPV6 && LWIP_IPV6_MLD +LWIP_MEMPOOL(MLD6_GROUP, MEMP_NUM_MLD6_GROUP, sizeof(struct mld_group), "MLD6_GROUP") +#endif /* LWIP_IPV6 && LWIP_IPV6_MLD */ + + +/* + * A list of pools of pbuf's used by LWIP. + * + * LWIP_PBUF_MEMPOOL(pool_name, number_elements, pbuf_payload_size, pool_description) + * creates a pool name MEMP_pool_name. description is used in stats.c + * This allocates enough space for the pbuf struct and a payload. + * (Example: pbuf_payload_size=0 allocates only size for the struct) + */ +LWIP_PBUF_MEMPOOL(PBUF, MEMP_NUM_PBUF, 0, "PBUF_REF/ROM") +LWIP_PBUF_MEMPOOL(PBUF_POOL, PBUF_POOL_SIZE, PBUF_POOL_BUFSIZE, "PBUF_POOL") + + +/* + * Allow for user-defined pools; this must be explicitly set in lwipopts.h + * since the default is to NOT look for lwippools.h + */ +#if MEMP_USE_CUSTOM_POOLS +#include "lwippools.h" +#endif /* MEMP_USE_CUSTOM_POOLS */ + +/* + * REQUIRED CLEANUP: Clear up so we don't get "multiply defined" error later + * (#undef is ignored for something that is not defined) + */ +#undef LWIP_MEMPOOL +#undef LWIP_MALLOC_MEMPOOL +#undef LWIP_MALLOC_MEMPOOL_START +#undef LWIP_MALLOC_MEMPOOL_END +#undef LWIP_PBUF_MEMPOOL diff --git a/components/lwip/include/lwip/lwip/priv/tcp_priv.h b/components/lwip/include/lwip/lwip/priv/tcp_priv.h new file mode 100755 index 0000000000..b5261b445c --- /dev/null +++ b/components/lwip/include/lwip/lwip/priv/tcp_priv.h @@ -0,0 +1,545 @@ +/* + * Copyright (c) 2001-2004 Swedish Institute of Computer Science. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + * + */ +#ifndef LWIP_HDR_TCP_IMPL_H +#define LWIP_HDR_TCP_IMPL_H + +#include "lwip/opt.h" + +#if LWIP_TCP /* don't build if not configured for use in lwipopts.h */ + +#include "lwip/tcp.h" +#include "lwip/mem.h" +#include "lwip/pbuf.h" +#include "lwip/ip.h" +#include "lwip/icmp.h" +#include "lwip/err.h" +#include "lwip/ip6.h" +#include "lwip/ip6_addr.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/* Functions for interfacing with TCP: */ + +/* Lower layer interface to TCP: */ +void tcp_init (void); /* Initialize this module. */ +void tcp_tmr (void); /* Must be called every + TCP_TMR_INTERVAL + ms. (Typically 250 ms). */ +/* It is also possible to call these two functions at the right + intervals (instead of calling tcp_tmr()). */ +void tcp_slowtmr (void); +void tcp_fasttmr (void); + +/* Call this from a netif driver (watch out for threading issues!) that has + returned a memory error on transmit and now has free buffers to send more. + This iterates all active pcbs that had an error and tries to call + tcp_output, so use this with care as it might slow down the system. */ +void tcp_txnow (void); + +/* Only used by IP to pass a TCP segment to TCP: */ +void tcp_input (struct pbuf *p, struct netif *inp); +/* Used within the TCP code only: */ +struct tcp_pcb * tcp_alloc (u8_t prio); +void tcp_abandon (struct tcp_pcb *pcb, int reset); +err_t tcp_send_empty_ack(struct tcp_pcb *pcb); +void tcp_rexmit (struct tcp_pcb *pcb); +void tcp_rexmit_rto (struct tcp_pcb *pcb); +void tcp_rexmit_fast (struct tcp_pcb *pcb); +u32_t tcp_update_rcv_ann_wnd(struct tcp_pcb *pcb); +err_t tcp_process_refused_data(struct tcp_pcb *pcb); + +/** + * This is the Nagle algorithm: try to combine user data to send as few TCP + * segments as possible. Only send if + * - no previously transmitted data on the connection remains unacknowledged or + * - the TF_NODELAY flag is set (nagle algorithm turned off for this pcb) or + * - the only unsent segment is at least pcb->mss bytes long (or there is more + * than one unsent segment - with lwIP, this can happen although unsent->len < mss) + * - or if we are in fast-retransmit (TF_INFR) + */ +#define tcp_do_output_nagle(tpcb) ((((tpcb)->unacked == NULL) || \ + ((tpcb)->flags & (TF_NODELAY | TF_INFR)) || \ + (((tpcb)->unsent != NULL) && (((tpcb)->unsent->next != NULL) || \ + ((tpcb)->unsent->len >= (tpcb)->mss))) || \ + ((tcp_sndbuf(tpcb) == 0) || (tcp_sndqueuelen(tpcb) >= TCP_SND_QUEUELEN)) \ + ) ? 1 : 0) +#define tcp_output_nagle(tpcb) (tcp_do_output_nagle(tpcb) ? tcp_output(tpcb) : ERR_OK) + + +#define TCP_SEQ_LT(a,b) ((s32_t)((u32_t)(a) - (u32_t)(b)) < 0) +#define TCP_SEQ_LEQ(a,b) ((s32_t)((u32_t)(a) - (u32_t)(b)) <= 0) +#define TCP_SEQ_GT(a,b) ((s32_t)((u32_t)(a) - (u32_t)(b)) > 0) +#define TCP_SEQ_GEQ(a,b) ((s32_t)((u32_t)(a) - (u32_t)(b)) >= 0) +/* is b<=a<=c? */ +#if 0 /* see bug #10548 */ +#define TCP_SEQ_BETWEEN(a,b,c) ((c)-(b) >= (a)-(b)) +#endif +#define TCP_SEQ_BETWEEN(a,b,c) (TCP_SEQ_GEQ(a,b) && TCP_SEQ_LEQ(a,c)) +#define TCP_FIN 0x01U +#define TCP_SYN 0x02U +#define TCP_RST 0x04U +#define TCP_PSH 0x08U +#define TCP_ACK 0x10U +#define TCP_URG 0x20U +#define TCP_ECE 0x40U +#define TCP_CWR 0x80U + +#define TCP_FLAGS 0x3fU + +/* Length of the TCP header, excluding options. */ +#define TCP_HLEN 20 + +#ifndef TCP_TMR_INTERVAL +#define TCP_TMR_INTERVAL 250 /* The TCP timer interval in milliseconds. */ +#endif /* TCP_TMR_INTERVAL */ + +#ifndef TCP_FAST_INTERVAL +#define TCP_FAST_INTERVAL TCP_TMR_INTERVAL /* the fine grained timeout in milliseconds */ +#endif /* TCP_FAST_INTERVAL */ + +#ifndef TCP_SLOW_INTERVAL +#define TCP_SLOW_INTERVAL (2*TCP_TMR_INTERVAL) /* the coarse grained timeout in milliseconds */ +#endif /* TCP_SLOW_INTERVAL */ + +#define TCP_FIN_WAIT_TIMEOUT 20000 /* milliseconds */ +#define TCP_SYN_RCVD_TIMEOUT 20000 /* milliseconds */ + +#define TCP_OOSEQ_TIMEOUT 6U /* x RTO */ + +#ifndef TCP_MSL +#define TCP_MSL 60000UL /* The maximum segment lifetime in milliseconds */ +#endif + +/* Keepalive values, compliant with RFC 1122. Don't change this unless you know what you're doing */ +#ifndef TCP_KEEPIDLE_DEFAULT +#define TCP_KEEPIDLE_DEFAULT 7200000UL /* Default KEEPALIVE timer in milliseconds */ +#endif + +#ifndef TCP_KEEPINTVL_DEFAULT +#define TCP_KEEPINTVL_DEFAULT 75000UL /* Default Time between KEEPALIVE probes in milliseconds */ +#endif + +#ifndef TCP_KEEPCNT_DEFAULT +#define TCP_KEEPCNT_DEFAULT 9U /* Default Counter for KEEPALIVE probes */ +#endif + +#define TCP_MAXIDLE TCP_KEEPCNT_DEFAULT * TCP_KEEPINTVL_DEFAULT /* Maximum KEEPALIVE probe time */ + +/* Fields are (of course) in network byte order. + * Some fields are converted to host byte order in tcp_input(). + */ +#ifdef PACK_STRUCT_USE_INCLUDES +# include "arch/bpstruct.h" +#endif +PACK_STRUCT_BEGIN +struct tcp_hdr { + PACK_STRUCT_FIELD(u16_t src); + PACK_STRUCT_FIELD(u16_t dest); + PACK_STRUCT_FIELD(u32_t seqno); + PACK_STRUCT_FIELD(u32_t ackno); + PACK_STRUCT_FIELD(u16_t _hdrlen_rsvd_flags); + PACK_STRUCT_FIELD(u16_t wnd); + PACK_STRUCT_FIELD(u16_t chksum); + PACK_STRUCT_FIELD(u16_t urgp); +} PACK_STRUCT_STRUCT; +PACK_STRUCT_END +#ifdef PACK_STRUCT_USE_INCLUDES +# include "arch/epstruct.h" +#endif + +#define TCPH_HDRLEN(phdr) (ntohs((phdr)->_hdrlen_rsvd_flags) >> 12) +#define TCPH_FLAGS(phdr) (ntohs((phdr)->_hdrlen_rsvd_flags) & TCP_FLAGS) + +#define TCPH_HDRLEN_SET(phdr, len) (phdr)->_hdrlen_rsvd_flags = htons(((len) << 12) | TCPH_FLAGS(phdr)) +#define TCPH_FLAGS_SET(phdr, flags) (phdr)->_hdrlen_rsvd_flags = (((phdr)->_hdrlen_rsvd_flags & PP_HTONS(~TCP_FLAGS)) | htons(flags)) +#define TCPH_HDRLEN_FLAGS_SET(phdr, len, flags) (phdr)->_hdrlen_rsvd_flags = htons(((len) << 12) | (flags)) + +#define TCPH_SET_FLAG(phdr, flags ) (phdr)->_hdrlen_rsvd_flags = ((phdr)->_hdrlen_rsvd_flags | htons(flags)) +#define TCPH_UNSET_FLAG(phdr, flags) (phdr)->_hdrlen_rsvd_flags = ((phdr)->_hdrlen_rsvd_flags & ~htons(flags)) + +#define TCP_TCPLEN(seg) ((seg)->len + (((TCPH_FLAGS((seg)->tcphdr) & (TCP_FIN | TCP_SYN)) != 0) ? 1U : 0U)) + +/** Flags used on input processing, not on pcb->flags +*/ +#define TF_RESET (u8_t)0x08U /* Connection was reset. */ +#define TF_CLOSED (u8_t)0x10U /* Connection was successfully closed. */ +#define TF_GOT_FIN (u8_t)0x20U /* Connection was closed by the remote end. */ + + +#if LWIP_EVENT_API + +#define TCP_EVENT_ACCEPT(pcb,err,ret) ret = lwip_tcp_event((pcb)->callback_arg, (pcb),\ + LWIP_EVENT_ACCEPT, NULL, 0, err) +#define TCP_EVENT_SENT(pcb,space,ret) ret = lwip_tcp_event((pcb)->callback_arg, (pcb),\ + LWIP_EVENT_SENT, NULL, space, ERR_OK) +#define TCP_EVENT_RECV(pcb,p,err,ret) ret = lwip_tcp_event((pcb)->callback_arg, (pcb),\ + LWIP_EVENT_RECV, (p), 0, (err)) +#define TCP_EVENT_CLOSED(pcb,ret) ret = lwip_tcp_event((pcb)->callback_arg, (pcb),\ + LWIP_EVENT_RECV, NULL, 0, ERR_OK) +#define TCP_EVENT_CONNECTED(pcb,err,ret) ret = lwip_tcp_event((pcb)->callback_arg, (pcb),\ + LWIP_EVENT_CONNECTED, NULL, 0, (err)) +#define TCP_EVENT_POLL(pcb,ret) ret = lwip_tcp_event((pcb)->callback_arg, (pcb),\ + LWIP_EVENT_POLL, NULL, 0, ERR_OK) +#define TCP_EVENT_ERR(errf,arg,err) lwip_tcp_event((arg), NULL, \ + LWIP_EVENT_ERR, NULL, 0, (err)) + +#else /* LWIP_EVENT_API */ + +#define TCP_EVENT_ACCEPT(pcb,err,ret) \ + do { \ + if((pcb)->accept != NULL) \ + (ret) = (pcb)->accept((pcb)->callback_arg,(pcb),(err)); \ + else (ret) = ERR_ARG; \ + } while (0) + +#define TCP_EVENT_SENT(pcb,space,ret) \ + do { \ + if((pcb)->sent != NULL) \ + (ret) = (pcb)->sent((pcb)->callback_arg,(pcb),(space)); \ + else (ret) = ERR_OK; \ + } while (0) + +#define TCP_EVENT_RECV(pcb,p,err,ret) \ + do { \ + if((pcb)->recv != NULL) { \ + (ret) = (pcb)->recv((pcb)->callback_arg,(pcb),(p),(err));\ + } else { \ + (ret) = tcp_recv_null(NULL, (pcb), (p), (err)); \ + } \ + } while (0) + +#define TCP_EVENT_CLOSED(pcb,ret) \ + do { \ + if(((pcb)->recv != NULL)) { \ + (ret) = (pcb)->recv((pcb)->callback_arg,(pcb),NULL,ERR_OK);\ + } else { \ + (ret) = ERR_OK; \ + } \ + } while (0) + +#define TCP_EVENT_CONNECTED(pcb,err,ret) \ + do { \ + if((pcb)->connected != NULL) \ + (ret) = (pcb)->connected((pcb)->callback_arg,(pcb),(err)); \ + else (ret) = ERR_OK; \ + } while (0) + +#define TCP_EVENT_POLL(pcb,ret) \ + do { \ + if((pcb)->poll != NULL) \ + (ret) = (pcb)->poll((pcb)->callback_arg,(pcb)); \ + else (ret) = ERR_OK; \ + } while (0) + +#define TCP_EVENT_ERR(errf,arg,err) \ + do { \ + if((errf) != NULL) \ + (errf)((arg),(err)); \ + } while (0) + +#endif /* LWIP_EVENT_API */ + +/** Enabled extra-check for TCP_OVERSIZE if LWIP_DEBUG is enabled */ +#if TCP_OVERSIZE && defined(LWIP_DEBUG) +#define TCP_OVERSIZE_DBGCHECK 1 +#else +#define TCP_OVERSIZE_DBGCHECK 0 +#endif + +/** Don't generate checksum on copy if CHECKSUM_GEN_TCP is disabled */ +#define TCP_CHECKSUM_ON_COPY (LWIP_CHECKSUM_ON_COPY && CHECKSUM_GEN_TCP) + +/* This structure represents a TCP segment on the unsent, unacked and ooseq queues */ +struct tcp_seg { + struct tcp_seg *next; /* used when putting segments on a queue */ + struct pbuf *p; /* buffer containing data + TCP header */ + u16_t len; /* the TCP length of this segment */ +#if TCP_OVERSIZE_DBGCHECK + u16_t oversize_left; /* Extra bytes available at the end of the last + pbuf in unsent (used for asserting vs. + tcp_pcb.unsent_oversized only) */ +#endif /* TCP_OVERSIZE_DBGCHECK */ +#if TCP_CHECKSUM_ON_COPY + u16_t chksum; + u8_t chksum_swapped; +#endif /* TCP_CHECKSUM_ON_COPY */ + u8_t flags; +#define TF_SEG_OPTS_MSS (u8_t)0x01U /* Include MSS option. */ +#define TF_SEG_OPTS_TS (u8_t)0x02U /* Include timestamp option. */ +#define TF_SEG_DATA_CHECKSUMMED (u8_t)0x04U /* ALL data (not the header) is + checksummed into 'chksum' */ +#define TF_SEG_OPTS_WND_SCALE (u8_t)0x08U /* Include WND SCALE option */ + struct tcp_hdr *tcphdr; /* the TCP header */ +}; + +#define LWIP_TCP_OPT_EOL 0 +#define LWIP_TCP_OPT_NOP 1 +#define LWIP_TCP_OPT_MSS 2 +#define LWIP_TCP_OPT_WS 3 +#define LWIP_TCP_OPT_TS 8 + +#define LWIP_TCP_OPT_LEN_MSS 4 +#if LWIP_TCP_TIMESTAMPS +#define LWIP_TCP_OPT_LEN_TS 10 +#define LWIP_TCP_OPT_LEN_TS_OUT 12 /* aligned for output (includes NOP padding) */ +#else +#define LWIP_TCP_OPT_LEN_TS_OUT 0 +#endif +#if LWIP_WND_SCALE +#define LWIP_TCP_OPT_LEN_WS 3 +#define LWIP_TCP_OPT_LEN_WS_OUT 4 /* aligned for output (includes NOP padding) */ +#else +#define LWIP_TCP_OPT_LEN_WS_OUT 0 +#endif + +#define LWIP_TCP_OPT_LENGTH(flags) \ + (flags & TF_SEG_OPTS_MSS ? LWIP_TCP_OPT_LEN_MSS : 0) + \ + (flags & TF_SEG_OPTS_TS ? LWIP_TCP_OPT_LEN_TS_OUT : 0) + \ + (flags & TF_SEG_OPTS_WND_SCALE ? LWIP_TCP_OPT_LEN_WS_OUT : 0) + +/** This returns a TCP header option for MSS in an u32_t */ +#define TCP_BUILD_MSS_OPTION(mss) htonl(0x02040000 | ((mss) & 0xFFFF)) + +#if LWIP_WND_SCALE +#define TCPWNDSIZE_F U32_F +#define TCPWND_MAX 0xFFFFFFFFU +#define TCPWND_CHECK16(x) LWIP_ASSERT("window size > 0xFFFF", (x) <= 0xFFFF) +#define TCPWND_MIN16(x) ((u16_t)LWIP_MIN((x), 0xFFFF)) +#else /* LWIP_WND_SCALE */ +#define TCPWNDSIZE_F U16_F +#define TCPWND_MAX 0xFFFFU +#define TCPWND_CHECK16(x) +#define TCPWND_MIN16(x) x +#endif /* LWIP_WND_SCALE */ + +/* Global variables: */ +extern struct tcp_pcb *tcp_input_pcb; +extern u32_t tcp_ticks; +extern u8_t tcp_active_pcbs_changed; + +/* The TCP PCB lists. */ +union tcp_listen_pcbs_t { /* List of all TCP PCBs in LISTEN state. */ + struct tcp_pcb_listen *listen_pcbs; + struct tcp_pcb *pcbs; +}; +extern struct tcp_pcb *tcp_bound_pcbs; +extern union tcp_listen_pcbs_t tcp_listen_pcbs; +extern struct tcp_pcb *tcp_active_pcbs; /* List of all TCP PCBs that are in a + state in which they accept or send + data. */ +extern struct tcp_pcb *tcp_tw_pcbs; /* List of all TCP PCBs in TIME-WAIT. */ + +#define NUM_TCP_PCB_LISTS_NO_TIME_WAIT 3 +#define NUM_TCP_PCB_LISTS 4 +extern struct tcp_pcb ** const tcp_pcb_lists[NUM_TCP_PCB_LISTS]; + +/* Axioms about the above lists: + 1) Every TCP PCB that is not CLOSED is in one of the lists. + 2) A PCB is only in one of the lists. + 3) All PCBs in the tcp_listen_pcbs list is in LISTEN state. + 4) All PCBs in the tcp_tw_pcbs list is in TIME-WAIT state. +*/ +/* Define two macros, TCP_REG and TCP_RMV that registers a TCP PCB + with a PCB list or removes a PCB from a list, respectively. */ +#ifndef TCP_DEBUG_PCB_LISTS +#define TCP_DEBUG_PCB_LISTS 0 +#endif +#if TCP_DEBUG_PCB_LISTS +#define TCP_REG(pcbs, npcb) do {\ + struct tcp_pcb *tcp_tmp_pcb; \ + LWIP_DEBUGF(TCP_DEBUG, ("TCP_REG %p local port %d\n", (npcb), (npcb)->local_port)); \ + for (tcp_tmp_pcb = *(pcbs); \ + tcp_tmp_pcb != NULL; \ + tcp_tmp_pcb = tcp_tmp_pcb->next) { \ + LWIP_ASSERT("TCP_REG: already registered\n", tcp_tmp_pcb != (npcb)); \ + } \ + LWIP_ASSERT("TCP_REG: pcb->state != CLOSED", ((pcbs) == &tcp_bound_pcbs) || ((npcb)->state != CLOSED)); \ + (npcb)->next = *(pcbs); \ + LWIP_ASSERT("TCP_REG: npcb->next != npcb", (npcb)->next != (npcb)); \ + *(pcbs) = (npcb); \ + LWIP_ASSERT("TCP_RMV: tcp_pcbs sane", tcp_pcbs_sane()); \ + tcp_timer_needed(); \ + } while(0) +#define TCP_RMV(pcbs, npcb) do { \ + struct tcp_pcb *tcp_tmp_pcb; \ + LWIP_ASSERT("TCP_RMV: pcbs != NULL", *(pcbs) != NULL); \ + LWIP_DEBUGF(TCP_DEBUG, ("TCP_RMV: removing %p from %p\n", (npcb), *(pcbs))); \ + if(*(pcbs) == (npcb)) { \ + *(pcbs) = (*pcbs)->next; \ + } else for (tcp_tmp_pcb = *(pcbs); tcp_tmp_pcb != NULL; tcp_tmp_pcb = tcp_tmp_pcb->next) { \ + if(tcp_tmp_pcb->next == (npcb)) { \ + tcp_tmp_pcb->next = (npcb)->next; \ + break; \ + } \ + } \ + (npcb)->next = NULL; \ + LWIP_ASSERT("TCP_RMV: tcp_pcbs sane", tcp_pcbs_sane()); \ + LWIP_DEBUGF(TCP_DEBUG, ("TCP_RMV: removed %p from %p\n", (npcb), *(pcbs))); \ + } while(0) + +#else /* LWIP_DEBUG */ + +#define TCP_REG(pcbs, npcb) \ + do { \ + (npcb)->next = *pcbs; \ + *(pcbs) = (npcb); \ + tcp_timer_needed(); \ + } while (0) + +#define TCP_RMV(pcbs, npcb) \ + do { \ + if(*(pcbs) == (npcb)) { \ + (*(pcbs)) = (*pcbs)->next; \ + } \ + else { \ + struct tcp_pcb *tcp_tmp_pcb; \ + for (tcp_tmp_pcb = *pcbs; \ + tcp_tmp_pcb != NULL; \ + tcp_tmp_pcb = tcp_tmp_pcb->next) { \ + if(tcp_tmp_pcb->next == (npcb)) { \ + tcp_tmp_pcb->next = (npcb)->next; \ + break; \ + } \ + } \ + } \ + (npcb)->next = NULL; \ + } while(0) + +#endif /* LWIP_DEBUG */ + +#define TCP_REG_ACTIVE(npcb) \ + do { \ + TCP_REG(&tcp_active_pcbs, npcb); \ + tcp_active_pcbs_changed = 1; \ + } while (0) + +#define TCP_RMV_ACTIVE(npcb) \ + do { \ + TCP_RMV(&tcp_active_pcbs, npcb); \ + tcp_active_pcbs_changed = 1; \ + } while (0) + +#define TCP_PCB_REMOVE_ACTIVE(pcb) \ + do { \ + tcp_pcb_remove(&tcp_active_pcbs, pcb); \ + tcp_active_pcbs_changed = 1; \ + } while (0) + + +/* Internal functions: */ +struct tcp_pcb *tcp_pcb_copy(struct tcp_pcb *pcb); +void tcp_pcb_purge(struct tcp_pcb *pcb); +void tcp_pcb_remove(struct tcp_pcb **pcblist, struct tcp_pcb *pcb); + +void tcp_segs_free(struct tcp_seg *seg); +void tcp_seg_free(struct tcp_seg *seg); +struct tcp_seg *tcp_seg_copy(struct tcp_seg *seg); + +#define tcp_ack(pcb) \ + do { \ + if((pcb)->flags & TF_ACK_DELAY) { \ + (pcb)->flags &= ~TF_ACK_DELAY; \ + (pcb)->flags |= TF_ACK_NOW; \ + } \ + else { \ + (pcb)->flags |= TF_ACK_DELAY; \ + } \ + } while (0) + +#define tcp_ack_now(pcb) \ + do { \ + (pcb)->flags |= TF_ACK_NOW; \ + } while (0) + +err_t tcp_send_fin(struct tcp_pcb *pcb); +err_t tcp_enqueue_flags(struct tcp_pcb *pcb, u8_t flags); + +void tcp_rexmit_seg(struct tcp_pcb *pcb, struct tcp_seg *seg); + +void tcp_rst(u32_t seqno, u32_t ackno, + const ip_addr_t *local_ip, const ip_addr_t *remote_ip, + u16_t local_port, u16_t remote_port); + +u32_t tcp_next_iss(void); + +err_t tcp_keepalive(struct tcp_pcb *pcb); +err_t tcp_zero_window_probe(struct tcp_pcb *pcb); +void tcp_trigger_input_pcb_close(void); + +#if TCP_CALCULATE_EFF_SEND_MSS +u16_t tcp_eff_send_mss_impl(u16_t sendmss, const ip_addr_t *dest +#if LWIP_IPV6 || LWIP_IPV4_SRC_ROUTING + , const ip_addr_t *src +#endif /* LWIP_IPV6 || LWIP_IPV4_SRC_ROUTING */ + ); +#if LWIP_IPV6 || LWIP_IPV4_SRC_ROUTING +#define tcp_eff_send_mss(sendmss, src, dest) tcp_eff_send_mss_impl(sendmss, dest, src) +#else /* LWIP_IPV6 || LWIP_IPV4_SRC_ROUTING */ +#define tcp_eff_send_mss(sendmss, src, dest) tcp_eff_send_mss_impl(sendmss, dest) +#endif /* LWIP_IPV6 || LWIP_IPV4_SRC_ROUTING */ +#endif /* TCP_CALCULATE_EFF_SEND_MSS */ + +#if LWIP_CALLBACK_API +err_t tcp_recv_null(void *arg, struct tcp_pcb *pcb, struct pbuf *p, err_t err); +#endif /* LWIP_CALLBACK_API */ + +#if TCP_DEBUG || TCP_INPUT_DEBUG || TCP_OUTPUT_DEBUG +void tcp_debug_print(struct tcp_hdr *tcphdr); +void tcp_debug_print_flags(u8_t flags); +void tcp_debug_print_state(enum tcp_state s); +void tcp_debug_print_pcbs(void); +s16_t tcp_pcbs_sane(void); +#else +# define tcp_debug_print(tcphdr) +# define tcp_debug_print_flags(flags) +# define tcp_debug_print_state(s) +# define tcp_debug_print_pcbs() +# define tcp_pcbs_sane() 1 +#endif /* TCP_DEBUG */ + +/** External function (implemented in timers.c), called when TCP detects + * that a timer is needed (i.e. active- or time-wait-pcb found). */ +void tcp_timer_needed(void); + +#if LWIP_IPV4 +void tcp_netif_ipv4_addr_changed(const ip4_addr_t* old_addr, const ip4_addr_t* new_addr); +#endif /* LWIP_IPV4 */ + +#ifdef __cplusplus +} +#endif + +#endif /* LWIP_TCP */ + +#endif /* LWIP_HDR_TCP_H */ diff --git a/components/lwip/include/lwip/lwip/priv/tcpip_priv.h b/components/lwip/include/lwip/lwip/priv/tcpip_priv.h new file mode 100755 index 0000000000..cc1c54ebb5 --- /dev/null +++ b/components/lwip/include/lwip/lwip/priv/tcpip_priv.h @@ -0,0 +1,163 @@ +/* + * Copyright (c) 2001-2004 Swedish Institute of Computer Science. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + * + */ +#ifndef LWIP_HDR_TCPIP_PRIV_H +#define LWIP_HDR_TCPIP_PRIV_H + +#include "lwip/opt.h" + +#if !NO_SYS /* don't build if not configured for use in lwipopts.h */ + +#include "lwip/tcpip.h" +#include "lwip/sys.h" +#include "lwip/timers.h" + +#ifdef __cplusplus +extern "C" { +#endif + +struct pbuf; +struct netif; + +/** Define this to something that triggers a watchdog. This is called from + * tcpip_thread after processing a message. */ +#ifndef LWIP_TCPIP_THREAD_ALIVE +#define LWIP_TCPIP_THREAD_ALIVE() +#endif + +#if LWIP_TCPIP_CORE_LOCKING +/** The global semaphore to lock the stack. */ +extern sys_mutex_t lock_tcpip_core; +#define LOCK_TCPIP_CORE() sys_mutex_lock(&lock_tcpip_core) +#define UNLOCK_TCPIP_CORE() sys_mutex_unlock(&lock_tcpip_core) +#else /* LWIP_TCPIP_CORE_LOCKING */ +#define LOCK_TCPIP_CORE() +#define UNLOCK_TCPIP_CORE() +#endif /* LWIP_TCPIP_CORE_LOCKING */ + +#if LWIP_MPU_COMPATIBLE +#define API_VAR_REF(name) (*(name)) +#define API_VAR_DECLARE(type, name) type * name +#define API_VAR_ALLOC(type, pool, name) do { \ + name = (type *)memp_malloc(pool); \ + if (name == NULL) { \ + return ERR_MEM; \ + } \ + } while(0) +#define API_VAR_ALLOC_DONTFAIL(type, pool, name) do { \ + name = (type *)memp_malloc(pool); \ + LWIP_ASSERT("pool empty", name != NULL); \ + } while(0) +#define API_VAR_FREE(pool, name) memp_free(pool, name) +#define API_EXPR_REF(expr) &(expr) +#if LWIP_NETCONN_SEM_PER_THREAD +#define API_EXPR_REF_SEM(expr) (expr) +#else +#define API_EXPR_REF_SEM(expr) API_EXPR_REF(expr) +#endif +#define API_EXPR_DEREF(expr) expr +#else /* LWIP_MPU_COMPATIBLE */ +#define API_VAR_REF(name) name +#define API_VAR_DECLARE(type, name) type name +#define API_VAR_ALLOC(type, pool, name) +#define API_VAR_ALLOC_DONTFAIL(type, pool, name) +#define API_VAR_FREE(pool, name) +#define API_EXPR_REF(expr) expr +#define API_EXPR_REF_SEM(expr) API_EXPR_REF(expr) +#define API_EXPR_DEREF(expr) *(expr) +#endif /* LWIP_MPU_COMPATIBLE */ + +#if !LWIP_TCPIP_CORE_LOCKING +err_t tcpip_send_api_msg(tcpip_callback_fn fn, void *apimsg, sys_sem_t* sem); +#endif /* !LWIP_TCPIP_CORE_LOCKING */ + +struct tcpip_api_call; +typedef err_t (*tcpip_api_call_fn)(struct tcpip_api_call* call); +struct tcpip_api_call +{ + tcpip_api_call_fn function; +#if !LWIP_TCPIP_CORE_LOCKING +#if LWIP_NETCONN_SEM_PER_THREAD + sys_sem_t *sem; +#else /* LWIP_NETCONN_SEM_PER_THREAD */ + sys_sem_t sem; +#endif /* LWIP_NETCONN_SEM_PER_THREAD */ + err_t err; +#endif /* !LWIP_TCPIP_CORE_LOCKING */ +}; +err_t tcpip_api_call(tcpip_api_call_fn fn, struct tcpip_api_call *call); + +enum tcpip_msg_type { + TCPIP_MSG_API, + TCPIP_MSG_API_CALL, + TCPIP_MSG_INPKT, +#if LWIP_TCPIP_TIMEOUT + TCPIP_MSG_TIMEOUT, + TCPIP_MSG_UNTIMEOUT, +#endif /* LWIP_TCPIP_TIMEOUT */ + TCPIP_MSG_CALLBACK, + TCPIP_MSG_CALLBACK_STATIC +}; + +struct tcpip_msg { + enum tcpip_msg_type type; + union { + struct { + tcpip_callback_fn function; + void* msg; + } api; + struct tcpip_api_call *api_call; + struct { + struct pbuf *p; + struct netif *netif; + netif_input_fn input_fn; + } inp; + struct { + tcpip_callback_fn function; + void *ctx; + } cb; +#if LWIP_TCPIP_TIMEOUT + struct { + u32_t msecs; + sys_timeout_handler h; + void *arg; + } tmo; +#endif /* LWIP_TCPIP_TIMEOUT */ + } msg; +}; + +#ifdef __cplusplus +} +#endif + +#endif /* !NO_SYS */ + +#endif /* LWIP_HDR_TCPIP_PRIV_H */ diff --git a/components/lwip/include/lwip/lwip/raw.h b/components/lwip/include/lwip/lwip/raw.h new file mode 100755 index 0000000000..474fdc1546 --- /dev/null +++ b/components/lwip/include/lwip/lwip/raw.h @@ -0,0 +1,109 @@ +/* + * Copyright (c) 2001-2004 Swedish Institute of Computer Science. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + * + */ +#ifndef LWIP_HDR_RAW_H +#define LWIP_HDR_RAW_H + +#include "lwip/opt.h" + +#if LWIP_RAW /* don't build if not configured for use in lwipopts.h */ + +#include "lwip/pbuf.h" +#include "lwip/def.h" +#include "lwip/ip.h" +#include "lwip/ip_addr.h" +#include "lwip/ip6_addr.h" + +#ifdef __cplusplus +extern "C" { +#endif + +struct raw_pcb; + +/** Function prototype for raw pcb receive callback functions. + * @param arg user supplied argument (raw_pcb.recv_arg) + * @param pcb the raw_pcb which received data + * @param p the packet buffer that was received + * @param addr the remote IP address from which the packet was received + * @return 1 if the packet was 'eaten' (aka. deleted), + * 0 if the packet lives on + * If returning 1, the callback is responsible for freeing the pbuf + * if it's not used any more. + */ +typedef u8_t (*raw_recv_fn)(void *arg, struct raw_pcb *pcb, struct pbuf *p, + const ip_addr_t *addr); + +struct raw_pcb { + /* Common members of all PCB types */ + IP_PCB; + + struct raw_pcb *next; + + u8_t protocol; + + /** receive callback function */ + raw_recv_fn recv; + /* user-supplied argument for the recv callback */ + void *recv_arg; +#if LWIP_IPV6 + /* fields for handling checksum computations as per RFC3542. */ + u16_t chksum_offset; + u8_t chksum_reqd; +#endif +}; + +/* The following functions is the application layer interface to the + RAW code. */ +struct raw_pcb * raw_new (u8_t proto); +struct raw_pcb * raw_new_ip_type(u8_t type, u8_t proto); +void raw_remove (struct raw_pcb *pcb); +err_t raw_bind (struct raw_pcb *pcb, const ip_addr_t *ipaddr); +err_t raw_connect (struct raw_pcb *pcb, const ip_addr_t *ipaddr); + +err_t raw_sendto (struct raw_pcb *pcb, struct pbuf *p, const ip_addr_t *ipaddr); +err_t raw_send (struct raw_pcb *pcb, struct pbuf *p); + +void raw_recv (struct raw_pcb *pcb, raw_recv_fn recv, void *recv_arg); + +/* The following functions are the lower layer interface to RAW. */ +u8_t raw_input (struct pbuf *p, struct netif *inp); +#define raw_init() /* Compatibility define, no init needed. */ + +/* for compatibility with older implementation */ +#define raw_new_ip6(proto) raw_new_ip_type(IPADDR_TYPE_V6, proto) + +#ifdef __cplusplus +} +#endif + +#endif /* LWIP_RAW */ + +#endif /* LWIP_HDR_RAW_H */ diff --git a/components/lwip/include/lwip/lwip/sio.h b/components/lwip/include/lwip/lwip/sio.h new file mode 100755 index 0000000000..09cf799abc --- /dev/null +++ b/components/lwip/include/lwip/lwip/sio.h @@ -0,0 +1,141 @@ +/* + * Copyright (c) 2001-2004 Swedish Institute of Computer Science. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + */ + +/* + * This is the interface to the platform specific serial IO module + * It needs to be implemented by those platforms which need SLIP or PPP + */ + +#ifndef SIO_H +#define SIO_H + +#include "lwip/arch.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/* If you want to define sio_fd_t elsewhere or differently, + define this in your cc.h file. */ +#ifndef __sio_fd_t_defined +typedef void * sio_fd_t; +#endif + +/* The following functions can be defined to something else in your cc.h file + or be implemented in your custom sio.c file. */ + +#ifndef sio_open +/** + * Opens a serial device for communication. + * + * @param devnum device number + * @return handle to serial device if successful, NULL otherwise + */ +sio_fd_t sio_open(u8_t devnum); +#endif + +#ifndef sio_send +/** + * Sends a single character to the serial device. + * + * @param c character to send + * @param fd serial device handle + * + * @note This function will block until the character can be sent. + */ +void sio_send(u8_t c, sio_fd_t fd); +#endif + +#ifndef sio_recv +/** + * Receives a single character from the serial device. + * + * @param fd serial device handle + * + * @note This function will block until a character is received. + */ +u8_t sio_recv(sio_fd_t fd); +#endif + +#ifndef sio_read +/** + * Reads from the serial device. + * + * @param fd serial device handle + * @param data pointer to data buffer for receiving + * @param len maximum length (in bytes) of data to receive + * @return number of bytes actually received - may be 0 if aborted by sio_read_abort + * + * @note This function will block until data can be received. The blocking + * can be cancelled by calling sio_read_abort(). + */ +u32_t sio_read(sio_fd_t fd, u8_t *data, u32_t len); +#endif + +#ifndef sio_tryread +/** + * Tries to read from the serial device. Same as sio_read but returns + * immediately if no data is available and never blocks. + * + * @param fd serial device handle + * @param data pointer to data buffer for receiving + * @param len maximum length (in bytes) of data to receive + * @return number of bytes actually received + */ +u32_t sio_tryread(sio_fd_t fd, u8_t *data, u32_t len); +#endif + +#ifndef sio_write +/** + * Writes to the serial device. + * + * @param fd serial device handle + * @param data pointer to data to send + * @param len length (in bytes) of data to send + * @return number of bytes actually sent + * + * @note This function will block until all data can be sent. + */ +u32_t sio_write(sio_fd_t fd, u8_t *data, u32_t len); +#endif + +#ifndef sio_read_abort +/** + * Aborts a blocking sio_read() call. + * + * @param fd serial device handle + */ +void sio_read_abort(sio_fd_t fd); +#endif + +#ifdef __cplusplus +} +#endif + +#endif /* SIO_H */ diff --git a/components/lwip/include/lwip/lwip/snmp.h b/components/lwip/include/lwip/lwip/snmp.h new file mode 100755 index 0000000000..07368cc68a --- /dev/null +++ b/components/lwip/include/lwip/lwip/snmp.h @@ -0,0 +1,195 @@ +/** + * @file + * MIB2 callback functions called from throughout the stack to integrate a MIB2 + * into lwIP (together with MIB2_STATS). + */ + +/* + * Copyright (c) 2001-2004 Swedish Institute of Computer Science. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Dirk Ziegelmeier + * + */ +#ifndef LWIP_HDR_SNMP_H +#define LWIP_HDR_SNMP_H + +#include "lwip/opt.h" +#include "lwip/ip_addr.h" + +#ifdef __cplusplus +extern "C" { +#endif + +struct udp_pcb; +struct netif; + +/* MIB2 statistics functions */ +#if MIB2_STATS /* don't build if not configured for use in lwipopts.h */ +/** + * @see RFC1213, "MIB-II, 6. Definitions" + */ +enum snmp_ifType { + snmp_ifType_other=1, /* none of the following */ + snmp_ifType_regular1822, + snmp_ifType_hdh1822, + snmp_ifType_ddn_x25, + snmp_ifType_rfc877_x25, + snmp_ifType_ethernet_csmacd, + snmp_ifType_iso88023_csmacd, + snmp_ifType_iso88024_tokenBus, + snmp_ifType_iso88025_tokenRing, + snmp_ifType_iso88026_man, + snmp_ifType_starLan, + snmp_ifType_proteon_10Mbit, + snmp_ifType_proteon_80Mbit, + snmp_ifType_hyperchannel, + snmp_ifType_fddi, + snmp_ifType_lapb, + snmp_ifType_sdlc, + snmp_ifType_ds1, /* T-1 */ + snmp_ifType_e1, /* european equiv. of T-1 */ + snmp_ifType_basicISDN, + snmp_ifType_primaryISDN, /* proprietary serial */ + snmp_ifType_propPointToPointSerial, + snmp_ifType_ppp, + snmp_ifType_softwareLoopback, + snmp_ifType_eon, /* CLNP over IP [11] */ + snmp_ifType_ethernet_3Mbit, + snmp_ifType_nsip, /* XNS over IP */ + snmp_ifType_slip, /* generic SLIP */ + snmp_ifType_ultra, /* ULTRA technologies */ + snmp_ifType_ds3, /* T-3 */ + snmp_ifType_sip, /* SMDS */ + snmp_ifType_frame_relay +}; + +/* This macro has a precision of ~49 days because sys_now returns u32_t. #define your own if you want ~490 days. */ +#ifndef MIB2_COPY_SYSUPTIME_TO +#define MIB2_COPY_SYSUPTIME_TO(ptrToVal) (*(ptrToVal) = (sys_now() / 10)) +#endif + +#define MIB2_STATS_NETIF_INC(n, x) do { ++(n)->mib2_counters.x; } while(0) +#define MIB2_STATS_NETIF_ADD(n, x, val) do { (n)->mib2_counters.x += (val); } while(0) + +#define MIB2_INIT_NETIF(netif, type, speed) do { \ + /* use "snmp_ifType" enum from snmp_mib2.h for "type", snmp_ifType_ethernet_csmacd by example */ \ + (netif)->link_type = (type); \ + /* your link speed here (units: bits per second) */ \ + (netif)->link_speed = (speed);\ + (netif)->ts = 0; \ + (netif)->mib2_counters.ifinoctets = 0; \ + (netif)->mib2_counters.ifinucastpkts = 0; \ + (netif)->mib2_counters.ifinnucastpkts = 0; \ + (netif)->mib2_counters.ifindiscards = 0; \ + (netif)->mib2_counters.ifinerrors = 0; \ + (netif)->mib2_counters.ifinunknownprotos = 0; \ + (netif)->mib2_counters.ifoutoctets = 0; \ + (netif)->mib2_counters.ifoutucastpkts = 0; \ + (netif)->mib2_counters.ifoutnucastpkts = 0; \ + (netif)->mib2_counters.ifoutdiscards = 0; \ + (netif)->mib2_counters.ifouterrors = 0; } while(0) +#else /* MIB2_STATS */ +#ifndef MIB2_COPY_SYSUPTIME_TO +#define MIB2_COPY_SYSUPTIME_TO(ptrToVal) +#endif +#define MIB2_INIT_NETIF(netif, type, speed) +#define MIB2_STATS_NETIF_INC(n, x) +#define MIB2_STATS_NETIF_ADD(n, x, val) +#endif /* MIB2_STATS */ + +/* LWIP MIB2 callbacks */ +#if LWIP_MIB2_CALLBACKS /* don't build if not configured for use in lwipopts.h */ +/* network interface */ +void mib2_netif_added(struct netif *ni); +void mib2_netif_removed(struct netif *ni); + +#if LWIP_IPV4 && LWIP_ARP +/* ARP (for atTable and ipNetToMediaTable) */ +void mib2_add_arp_entry(struct netif *ni, ip4_addr_t *ip); +void mib2_remove_arp_entry(struct netif *ni, ip4_addr_t *ip); +#else /* LWIP_IPV4 && LWIP_ARP */ +#define mib2_add_arp_entry(ni,ip) +#define mib2_remove_arp_entry(ni,ip) +#endif /* LWIP_IPV4 && LWIP_ARP */ + +/* IP */ +#if LWIP_IPV4 +void mib2_add_ip4(struct netif *ni); +void mib2_remove_ip4(struct netif *ni); +void mib2_add_route_ip4(u8_t dflt, struct netif *ni); +void mib2_remove_route_ip4(u8_t dflt, struct netif *ni); +#endif /* LWIP_IPV4 */ + +/* UDP */ +#if LWIP_UDP +void mib2_udp_bind(struct udp_pcb *pcb); +void mib2_udp_unbind(struct udp_pcb *pcb); +#endif /* LWIP_UDP */ + +#else /* LWIP_MIB2_CALLBACKS */ +/* LWIP_MIB2_CALLBACKS support not available */ +/* define everything to be empty */ + +/* network interface */ +#define mib2_netif_added(ni) +#define mib2_netif_removed(ni) + +/* ARP */ +#define mib2_add_arp_entry(ni,ip) +#define mib2_remove_arp_entry(ni,ip) + +/* IP */ +#define mib2_add_ip4(ni) +#define mib2_remove_ip4(ni) +#define mib2_add_route_ip4(dflt, ni) +#define mib2_remove_route_ip4(dflt, ni) + +/* UDP */ +#define mib2_udp_bind(pcb) +#define mib2_udp_unbind(pcb) +#endif /* LWIP_MIB2_CALLBACKS */ + +/* for source-code compatibility reasons only, can be removed (not used internally) */ +#define NETIF_INIT_SNMP MIB2_INIT_NETIF +#define snmp_add_ifinoctets(ni,value) MIB2_STATS_NETIF_ADD(ni, ifinoctets, value) +#define snmp_inc_ifinucastpkts(ni) MIB2_STATS_NETIF_INC(ni, ifinucastpkts) +#define snmp_inc_ifinnucastpkts(ni) MIB2_STATS_NETIF_INC(ni, ifinnucastpkts) +#define snmp_inc_ifindiscards(ni) MIB2_STATS_NETIF_INC(ni, ifindiscards) +#define snmp_inc_ifinerrors(ni) MIB2_STATS_NETIF_INC(ni, ifinerrors) +#define snmp_inc_ifinunknownprotos(ni) MIB2_STATS_NETIF_INC(ni, ifinunknownprotos) +#define snmp_add_ifoutoctets(ni,value) MIB2_STATS_NETIF_ADD(ni, ifoutoctets, value) +#define snmp_inc_ifoutucastpkts(ni) MIB2_STATS_NETIF_INC(ni, ifoutucastpkts) +#define snmp_inc_ifoutnucastpkts(ni) MIB2_STATS_NETIF_INC(ni, ifoutnucastpkts) +#define snmp_inc_ifoutdiscards(ni) MIB2_STATS_NETIF_INC(ni, ifoutdiscards) +#define snmp_inc_ifouterrors(ni) MIB2_STATS_NETIF_INC(ni, ifouterrors) + +#ifdef __cplusplus +} +#endif + +#endif /* LWIP_HDR_SNMP_H */ diff --git a/components/lwip/include/lwip/lwip/sockets.h b/components/lwip/include/lwip/lwip/sockets.h new file mode 100755 index 0000000000..b79e3b7f5b --- /dev/null +++ b/components/lwip/include/lwip/lwip/sockets.h @@ -0,0 +1,624 @@ +/* + * Copyright (c) 2001-2004 Swedish Institute of Computer Science. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + * + */ + + +#ifndef LWIP_HDR_SOCKETS_H +#define LWIP_HDR_SOCKETS_H + +#include "lwip/opt.h" + +#if LWIP_SOCKET /* don't build if not configured for use in lwipopts.h */ + +#include /* for size_t */ + +#include "lwip/ip_addr.h" +#include "lwip/err.h" +#include "lwip/inet.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/* If your port already typedef's sa_family_t, define SA_FAMILY_T_DEFINED + to prevent this code from redefining it. */ +#if !defined(sa_family_t) && !defined(SA_FAMILY_T_DEFINED) +typedef u8_t sa_family_t; +#endif +/* If your port already typedef's in_port_t, define IN_PORT_T_DEFINED + to prevent this code from redefining it. */ +#if !defined(in_port_t) && !defined(IN_PORT_T_DEFINED) +typedef u16_t in_port_t; +#endif + +#if LWIP_IPV4 +/* members are in network byte order */ +struct sockaddr_in { + u8_t sin_len; + sa_family_t sin_family; + in_port_t sin_port; + struct in_addr sin_addr; +#define SIN_ZERO_LEN 8 + char sin_zero[SIN_ZERO_LEN]; +}; +#endif /* LWIP_IPV4 */ + +#if LWIP_IPV6 +struct sockaddr_in6 { + u8_t sin6_len; /* length of this structure */ + sa_family_t sin6_family; /* AF_INET6 */ + in_port_t sin6_port; /* Transport layer port # */ + u32_t sin6_flowinfo; /* IPv6 flow information */ + struct in6_addr sin6_addr; /* IPv6 address */ + u32_t sin6_scope_id; /* Set of interfaces for scope */ +}; +#endif /* LWIP_IPV6 */ + +struct sockaddr { + u8_t sa_len; + sa_family_t sa_family; + char sa_data[14]; +}; + +struct sockaddr_storage { + u8_t s2_len; + sa_family_t ss_family; + char s2_data1[2]; + u32_t s2_data2[3]; +#if LWIP_IPV6 + u32_t s2_data3[3]; +#endif /* LWIP_IPV6 */ +}; + +/* If your port already typedef's socklen_t, define SOCKLEN_T_DEFINED + to prevent this code from redefining it. */ +#if !defined(socklen_t) && !defined(SOCKLEN_T_DEFINED) +typedef u32_t socklen_t; +#endif + +struct lwip_sock; + +#if !LWIP_TCPIP_CORE_LOCKING +/** Maximum optlen used by setsockopt/getsockopt */ +#define LWIP_SETGETSOCKOPT_MAXOPTLEN 16 + +/** This struct is used to pass data to the set/getsockopt_internal + * functions running in tcpip_thread context (only a void* is allowed) */ +struct lwip_setgetsockopt_data { + /** socket index for which to change options */ + int s; + /** level of the option to process */ + int level; + /** name of the option to process */ + int optname; + /** set: value to set the option to + * get: value of the option is stored here */ +#if LWIP_MPU_COMPATIBLE + u8_t optval[LWIP_SETGETSOCKOPT_MAXOPTLEN]; +#else + union { + void *p; + const void *pc; + } optval; +#endif + /** size of *optval */ + socklen_t optlen; + /** if an error occurs, it is temporarily stored here */ + err_t err; + /** semaphore to wake up the calling task */ + void* completed_sem; +}; +#endif /* !LWIP_TCPIP_CORE_LOCKING */ + +#if !defined(iovec) +struct iovec { + void *iov_base; + size_t iov_len; +}; +#endif + +struct msghdr { + void *msg_name; + socklen_t msg_namelen; + struct iovec *msg_iov; + int msg_iovlen; + void *msg_control; + socklen_t msg_controllen; + int msg_flags; +}; + +/* Socket protocol types (TCP/UDP/RAW) */ +#define SOCK_STREAM 1 +#define SOCK_DGRAM 2 +#define SOCK_RAW 3 + +/* + * Option flags per-socket. These must match the SOF_ flags in ip.h (checked in init.c) + */ +#define SO_REUSEADDR 0x0004 /* Allow local address reuse */ +#define SO_KEEPALIVE 0x0008 /* keep connections alive */ +#define SO_BROADCAST 0x0020 /* permit to send and to receive broadcast messages (see IP_SOF_BROADCAST option) */ + + +/* + * Additional options, not kept in so_options. + */ +#define SO_DEBUG 0x0001 /* Unimplemented: turn on debugging info recording */ +#define SO_ACCEPTCONN 0x0002 /* socket has had listen() */ +#define SO_DONTROUTE 0x0010 /* Unimplemented: just use interface addresses */ +#define SO_USELOOPBACK 0x0040 /* Unimplemented: bypass hardware when possible */ +#define SO_LINGER 0x0080 /* linger on close if data present */ +#define SO_DONTLINGER ((int)(~SO_LINGER)) +#define SO_OOBINLINE 0x0100 /* Unimplemented: leave received OOB data in line */ +#define SO_REUSEPORT 0x0200 /* Unimplemented: allow local address & port reuse */ +#define SO_SNDBUF 0x1001 /* Unimplemented: send buffer size */ +#define SO_RCVBUF 0x1002 /* receive buffer size */ +#define SO_SNDLOWAT 0x1003 /* Unimplemented: send low-water mark */ +#define SO_RCVLOWAT 0x1004 /* Unimplemented: receive low-water mark */ +#define SO_SNDTIMEO 0x1005 /* send timeout */ +#define SO_RCVTIMEO 0x1006 /* receive timeout */ +#define SO_ERROR 0x1007 /* get error status and clear */ +#define SO_TYPE 0x1008 /* get socket type */ +#define SO_CONTIMEO 0x1009 /* Unimplemented: connect timeout */ +#define SO_NO_CHECK 0x100a /* don't create UDP checksum */ + + +/* + * Structure used for manipulating linger option. + */ +struct linger { + int l_onoff; /* option on/off */ + int l_linger; /* linger time in seconds */ +}; + +/* + * Level number for (get/set)sockopt() to apply to socket itself. + */ +#define SOL_SOCKET 0xfff /* options for socket level */ + + +#define AF_UNSPEC 0 +#define AF_INET 2 +#if LWIP_IPV6 +#define AF_INET6 10 +#else /* LWIP_IPV6 */ +#define AF_INET6 AF_UNSPEC +#endif /* LWIP_IPV6 */ +#define PF_INET AF_INET +#define PF_INET6 AF_INET6 +#define PF_UNSPEC AF_UNSPEC + +#define IPPROTO_IP 0 +#define IPPROTO_ICMP 1 +#define IPPROTO_TCP 6 +#define IPPROTO_UDP 17 +#if LWIP_IPV6 +#define IPPROTO_IPV6 41 +#define IPPROTO_ICMPV6 58 +#endif /* LWIP_IPV6 */ +#define IPPROTO_UDPLITE 136 +#define IPPROTO_RAW 255 + +/* Flags we can use with send and recv. */ +#define MSG_PEEK 0x01 /* Peeks at an incoming message */ +#define MSG_WAITALL 0x02 /* Unimplemented: Requests that the function block until the full amount of data requested can be returned */ +#define MSG_OOB 0x04 /* Unimplemented: Requests out-of-band data. The significance and semantics of out-of-band data are protocol-specific */ +#define MSG_DONTWAIT 0x08 /* Nonblocking i/o for this operation only */ +#define MSG_MORE 0x10 /* Sender will send more */ + + +/* + * Options for level IPPROTO_IP + */ +#define IP_TOS 1 +#define IP_TTL 2 + +#if LWIP_TCP +/* + * Options for level IPPROTO_TCP + */ +#define TCP_NODELAY 0x01 /* don't delay send to coalesce packets */ +#define TCP_KEEPALIVE 0x02 /* send KEEPALIVE probes when idle for pcb->keep_idle milliseconds */ +#define TCP_KEEPIDLE 0x03 /* set pcb->keep_idle - Same as TCP_KEEPALIVE, but use seconds for get/setsockopt */ +#define TCP_KEEPINTVL 0x04 /* set pcb->keep_intvl - Use seconds for get/setsockopt */ +#define TCP_KEEPCNT 0x05 /* set pcb->keep_cnt - Use number of probes sent for get/setsockopt */ +#endif /* LWIP_TCP */ + +#if LWIP_IPV6 +/* + * Options for level IPPROTO_IPV6 + */ +#define IPV6_CHECKSUM 7 /* RFC3542: calculate and insert the ICMPv6 checksum for raw sockets. */ +#define IPV6_V6ONLY 27 /* RFC3493: boolean control to restrict AF_INET6 sockets to IPv6 communications only. */ +#endif /* LWIP_IPV6 */ + +#if LWIP_UDP && LWIP_UDPLITE +/* + * Options for level IPPROTO_UDPLITE + */ +#define UDPLITE_SEND_CSCOV 0x01 /* sender checksum coverage */ +#define UDPLITE_RECV_CSCOV 0x02 /* minimal receiver checksum coverage */ +#endif /* LWIP_UDP && LWIP_UDPLITE*/ + + +#if LWIP_MULTICAST_TX_OPTIONS +/* + * Options and types for UDP multicast traffic handling + */ +#define IP_MULTICAST_TTL 5 +#define IP_MULTICAST_IF 6 +#define IP_MULTICAST_LOOP 7 +#endif /* LWIP_MULTICAST_TX_OPTIONS */ + +#if LWIP_IGMP +/* + * Options and types related to multicast membership + */ +#define IP_ADD_MEMBERSHIP 3 +#define IP_DROP_MEMBERSHIP 4 + +typedef struct ip_mreq { + struct in_addr imr_multiaddr; /* IP multicast address of group */ + struct in_addr imr_interface; /* local IP address of interface */ +} ip_mreq; +#endif /* LWIP_IGMP */ + +/* + * The Type of Service provides an indication of the abstract + * parameters of the quality of service desired. These parameters are + * to be used to guide the selection of the actual service parameters + * when transmitting a datagram through a particular network. Several + * networks offer service precedence, which somehow treats high + * precedence traffic as more important than other traffic (generally + * by accepting only traffic above a certain precedence at time of high + * load). The major choice is a three way tradeoff between low-delay, + * high-reliability, and high-throughput. + * The use of the Delay, Throughput, and Reliability indications may + * increase the cost (in some sense) of the service. In many networks + * better performance for one of these parameters is coupled with worse + * performance on another. Except for very unusual cases at most two + * of these three indications should be set. + */ +#define IPTOS_TOS_MASK 0x1E +#define IPTOS_TOS(tos) ((tos) & IPTOS_TOS_MASK) +#define IPTOS_LOWDELAY 0x10 +#define IPTOS_THROUGHPUT 0x08 +#define IPTOS_RELIABILITY 0x04 +#define IPTOS_LOWCOST 0x02 +#define IPTOS_MINCOST IPTOS_LOWCOST + +/* + * The Network Control precedence designation is intended to be used + * within a network only. The actual use and control of that + * designation is up to each network. The Internetwork Control + * designation is intended for use by gateway control originators only. + * If the actual use of these precedence designations is of concern to + * a particular network, it is the responsibility of that network to + * control the access to, and use of, those precedence designations. + */ +#define IPTOS_PREC_MASK 0xe0 +#define IPTOS_PREC(tos) ((tos) & IPTOS_PREC_MASK) +#define IPTOS_PREC_NETCONTROL 0xe0 +#define IPTOS_PREC_INTERNETCONTROL 0xc0 +#define IPTOS_PREC_CRITIC_ECP 0xa0 +#define IPTOS_PREC_FLASHOVERRIDE 0x80 +#define IPTOS_PREC_FLASH 0x60 +#define IPTOS_PREC_IMMEDIATE 0x40 +#define IPTOS_PREC_PRIORITY 0x20 +#define IPTOS_PREC_ROUTINE 0x00 + + +/* + * Commands for ioctlsocket(), taken from the BSD file fcntl.h. + * lwip_ioctl only supports FIONREAD and FIONBIO, for now + * + * Ioctl's have the command encoded in the lower word, + * and the size of any in or out parameters in the upper + * word. The high 2 bits of the upper word are used + * to encode the in/out status of the parameter; for now + * we restrict parameters to at most 128 bytes. + */ +#if !defined(FIONREAD) || !defined(FIONBIO) +#define IOCPARM_MASK 0x7fU /* parameters must be < 128 bytes */ +#define IOC_VOID 0x20000000UL /* no parameters */ +#define IOC_OUT 0x40000000UL /* copy out parameters */ +#define IOC_IN 0x80000000UL /* copy in parameters */ +#define IOC_INOUT (IOC_IN|IOC_OUT) + /* 0x20000000 distinguishes new & + old ioctl's */ +#define _IO(x,y) (IOC_VOID|((x)<<8)|(y)) + +#define _IOR(x,y,t) (IOC_OUT|(((long)sizeof(t)&IOCPARM_MASK)<<16)|((x)<<8)|(y)) + +#define _IOW(x,y,t) (IOC_IN|(((long)sizeof(t)&IOCPARM_MASK)<<16)|((x)<<8)|(y)) +#endif /* !defined(FIONREAD) || !defined(FIONBIO) */ + +#ifndef FIONREAD +#define FIONREAD _IOR('f', 127, unsigned long) /* get # bytes to read */ +#endif +#ifndef FIONBIO +#define FIONBIO _IOW('f', 126, unsigned long) /* set/clear non-blocking i/o */ +#endif + +/* Socket I/O Controls: unimplemented */ +#ifndef SIOCSHIWAT +#define SIOCSHIWAT _IOW('s', 0, unsigned long) /* set high watermark */ +#define SIOCGHIWAT _IOR('s', 1, unsigned long) /* get high watermark */ +#define SIOCSLOWAT _IOW('s', 2, unsigned long) /* set low watermark */ +#define SIOCGLOWAT _IOR('s', 3, unsigned long) /* get low watermark */ +#define SIOCATMARK _IOR('s', 7, unsigned long) /* at oob mark? */ +#endif + +/* commands for fnctl */ +#ifndef F_GETFL +#define F_GETFL 3 +#endif +#ifndef F_SETFL +#define F_SETFL 4 +#endif + +/* File status flags and file access modes for fnctl, + these are bits in an int. */ +#ifndef O_NONBLOCK +#define O_NONBLOCK 1 /* nonblocking I/O */ +#endif +#ifndef O_NDELAY +#define O_NDELAY 1 /* same as O_NONBLOCK, for compatibility */ +#endif + +#ifndef SHUT_RD + #define SHUT_RD 0 + #define SHUT_WR 1 + #define SHUT_RDWR 2 +#endif + +/* FD_SET used for lwip_select */ +#ifndef FD_SET +#undef FD_SETSIZE +/* Make FD_SETSIZE match NUM_SOCKETS in socket.c */ +#define FD_SETSIZE MEMP_NUM_NETCONN +#define FDSETSAFESET(n, code) do { \ + if (((n) - LWIP_SOCKET_OFFSET < MEMP_NUM_NETCONN) && (((int)(n) - LWIP_SOCKET_OFFSET) >= 0)) { \ + code; }} while(0) +#define FDSETSAFEGET(n, code) (((n) - LWIP_SOCKET_OFFSET < MEMP_NUM_NETCONN) && (((int)(n) - LWIP_SOCKET_OFFSET) >= 0) ?\ + (code) : 0) +#define FD_SET(n, p) FDSETSAFESET(n, (p)->fd_bits[((n)-LWIP_SOCKET_OFFSET)/8] |= (1 << (((n)-LWIP_SOCKET_OFFSET) & 7))) +#define FD_CLR(n, p) FDSETSAFESET(n, (p)->fd_bits[((n)-LWIP_SOCKET_OFFSET)/8] &= ~(1 << (((n)-LWIP_SOCKET_OFFSET) & 7))) +#define FD_ISSET(n,p) FDSETSAFEGET(n, (p)->fd_bits[((n)-LWIP_SOCKET_OFFSET)/8] & (1 << (((n)-LWIP_SOCKET_OFFSET) & 7))) +#define FD_ZERO(p) memset((void*)(p), 0, sizeof(*(p))) + +typedef struct fd_set +{ + unsigned char fd_bits [(FD_SETSIZE+7)/8]; +} fd_set; + +#elif LWIP_SOCKET_OFFSET +#error LWIP_SOCKET_OFFSET does not work with external FD_SET! +#endif /* FD_SET */ + +/** LWIP_TIMEVAL_PRIVATE: if you want to use the struct timeval provided + * by your system, set this to 0 and include in cc.h */ +#ifndef LWIP_TIMEVAL_PRIVATE +#define LWIP_TIMEVAL_PRIVATE 1 +#endif + +#if LWIP_TIMEVAL_PRIVATE +struct timeval { + long tv_sec; /* seconds */ + long tv_usec; /* and microseconds */ +}; +#endif /* LWIP_TIMEVAL_PRIVATE */ + +#define lwip_socket_init() /* Compatibility define, no init needed. */ +void lwip_socket_thread_init(void); /* LWIP_NETCONN_SEM_PER_THREAD==1: initialize thread-local semaphore */ +void lwip_socket_thread_cleanup(void); /* LWIP_NETCONN_SEM_PER_THREAD==1: destroy thread-local semaphore */ + +#if LWIP_COMPAT_SOCKETS == 2 + + +/* This helps code parsers/code completion by not having the COMPAT functions as defines */ +#define lwip_accept accept +#define lwip_bind bind +#define lwip_shutdown shutdown +#define lwip_getpeername getpeername +#define lwip_getsockname getsockname +#define lwip_setsockopt setsockopt +#define lwip_getsockopt getsockopt +#define lwip_close closesocket +#define lwip_connect connect +#define lwip_listen listen +#define lwip_recv recv +#define lwip_recvfrom recvfrom +#define lwip_send send +#define lwip_sendmsg sendmsg +#define lwip_sendto sendto +#define lwip_socket socket +#define lwip_select select +#define lwip_ioctlsocket ioctl + +#if LWIP_POSIX_SOCKETS_IO_NAMES +#define lwip_read read +#define lwip_write write +#define lwip_writev writev +#undef lwip_close +#define lwip_close close +#define closesocket(s) close(s) +#define lwip_fcntl fcntl +#define lwip_ioctl ioctl +#endif /* LWIP_POSIX_SOCKETS_IO_NAMES */ +#endif /* LWIP_COMPAT_SOCKETS == 2 */ + +int lwip_accept(int s, struct sockaddr *addr, socklen_t *addrlen); +int lwip_bind(int s, const struct sockaddr *name, socklen_t namelen); +int lwip_shutdown(int s, int how); +int lwip_getpeername (int s, struct sockaddr *name, socklen_t *namelen); +int lwip_getsockname (int s, struct sockaddr *name, socklen_t *namelen); +int lwip_getsockopt (int s, int level, int optname, void *optval, socklen_t *optlen); +int lwip_setsockopt (int s, int level, int optname, const void *optval, socklen_t optlen); +int lwip_close(int s); +int lwip_connect(int s, const struct sockaddr *name, socklen_t namelen); +int lwip_listen(int s, int backlog); +int lwip_recv(int s, void *mem, size_t len, int flags); +int lwip_read(int s, void *mem, size_t len); +int lwip_recvfrom(int s, void *mem, size_t len, int flags, + struct sockaddr *from, socklen_t *fromlen); +int lwip_send(int s, const void *dataptr, size_t size, int flags); +int lwip_sendmsg(int s, const struct msghdr *message, int flags); +int lwip_sendto(int s, const void *dataptr, size_t size, int flags, + const struct sockaddr *to, socklen_t tolen); +int lwip_socket(int domain, int type, int protocol); +int lwip_write(int s, const void *dataptr, size_t size); +int lwip_writev(int s, const struct iovec *iov, int iovcnt); +int lwip_select(int maxfdp1, fd_set *readset, fd_set *writeset, fd_set *exceptset, + struct timeval *timeout); +int lwip_ioctl(int s, long cmd, void *argp); +int lwip_fcntl(int s, int cmd, int val); + +#if LWIP_COMPAT_SOCKETS +#if LWIP_COMPAT_SOCKETS != 2 + +#ifdef LWIP_THREAD_SAFE + +int lwip_accept_r(int s, struct sockaddr *addr, socklen_t *addrlen); +int lwip_bind_r(int s, const struct sockaddr *name, socklen_t namelen); +int lwip_shutdown_r(int s, int how); +int lwip_getpeername_r (int s, struct sockaddr *name, socklen_t *namelen); +int lwip_getsockname_r (int s, struct sockaddr *name, socklen_t *namelen); +int lwip_getsockopt_r (int s, int level, int optname, void *optval, socklen_t *optlen); +int lwip_setsockopt_r (int s, int level, int optname, const void *optval, socklen_t optlen); +int lwip_close_r(int s); +int lwip_connect_r(int s, const struct sockaddr *name, socklen_t namelen); +int lwip_listen_r(int s, int backlog); +int lwip_recv_r(int s, void *mem, size_t len, int flags); +int lwip_read_r(int s, void *mem, size_t len); +int lwip_recvfrom_r(int s, void *mem, size_t len, int flags, + struct sockaddr *from, socklen_t *fromlen); +int lwip_send_r(int s, const void *dataptr, size_t size, int flags); +int lwip_sendmsg_r(int s, const struct msghdr *message, int flags); +int lwip_sendto_r(int s, const void *dataptr, size_t size, int flags, + const struct sockaddr *to, socklen_t tolen); +int lwip_socket(int domain, int type, int protocol); +int lwip_write_r(int s, const void *dataptr, size_t size); +int lwip_writev_r(int s, const struct iovec *iov, int iovcnt); +int lwip_select(int maxfdp1, fd_set *readset, fd_set *writeset, fd_set *exceptset, + struct timeval *timeout); +int lwip_ioctl_r(int s, long cmd, void *argp); +int lwip_fcntl_r(int s, int cmd, int val); + +#define accept(s,addr,addrlen) lwip_accept_r(s,addr,addrlen) +#define bind(s,name,namelen) lwip_bind_r(s,name,namelen) +#define shutdown(s,how) lwip_shutdown_r(s,how) +#define getpeername(s,name,namelen) lwip_getpeername_r(s,name,namelen) +#define getsockname(s,name,namelen) lwip_getsockname_r(s,name,namelen) +#define setsockopt(s,level,optname,opval,optlen) lwip_setsockopt_r(s,level,optname,opval,optlen) +#define getsockopt(s,level,optname,opval,optlen) lwip_getsockopt_r(s,level,optname,opval,optlen) +#define closesocket(s) lwip_close_r(s) +#define connect(s,name,namelen) lwip_connect_r(s,name,namelen) +#define listen(s,backlog) lwip_listen_r(s,backlog) +#define recv(s,mem,len,flags) lwip_recv_r(s,mem,len,flags) +#define recvfrom(s,mem,len,flags,from,fromlen) lwip_recvfrom_r(s,mem,len,flags,from,fromlen) +#define send(s,dataptr,size,flags) lwip_send_r(s,dataptr,size,flags) +#define sendmsg(s,message,flags) lwip_sendmsg_r(s,message,flags) +#define sendto(s,dataptr,size,flags,to,tolen) lwip_sendto_r(s,dataptr,size,flags,to,tolen) +#define socket(domain,type,protocol) lwip_socket(domain,type,protocol) +#define select(maxfdp1,readset,writeset,exceptset,timeout) lwip_select(maxfdp1,readset,writeset,exceptset,timeout) +#define ioctlsocket(s,cmd,argp) lwip_ioctl_r(s,cmd,argp) + +#if LWIP_POSIX_SOCKETS_IO_NAMES +#define read(s,mem,len) lwip_read_r(s,mem,len) +#define write(s,dataptr,len) lwip_write_r(s,dataptr,len) +#define writev(s,iov,iovcnt) lwip_writev_r(s,iov,iovcnt) +#define close(s) lwip_close_r(s) +#define fcntl(s,cmd,val) lwip_fcntl_r(s,cmd,val) +#define ioctl(s,cmd,argp) lwip_ioctl_r(s,cmd,argp) +#endif /* LWIP_POSIX_SOCKETS_IO_NAMES */ + +#else + +#define accept(s,addr,addrlen) lwip_accept(s,addr,addrlen) +#define bind(s,name,namelen) lwip_bind(s,name,namelen) +#define shutdown(s,how) lwip_shutdown(s,how) +#define getpeername(s,name,namelen) lwip_getpeername(s,name,namelen) +#define getsockname(s,name,namelen) lwip_getsockname(s,name,namelen) +#define setsockopt(s,level,optname,opval,optlen) lwip_setsockopt(s,level,optname,opval,optlen) +#define getsockopt(s,level,optname,opval,optlen) lwip_getsockopt(s,level,optname,opval,optlen) +#define closesocket(s) lwip_close(s) +#define connect(s,name,namelen) lwip_connect(s,name,namelen) +#define listen(s,backlog) lwip_listen(s,backlog) +#define recv(s,mem,len,flags) lwip_recv(s,mem,len,flags) +#define recvfrom(s,mem,len,flags,from,fromlen) lwip_recvfrom(s,mem,len,flags,from,fromlen) +#define send(s,dataptr,size,flags) lwip_send(s,dataptr,size,flags) +#define sendmsg(s,message,flags) lwip_sendmsg(s,message,flags) +#define sendto(s,dataptr,size,flags,to,tolen) lwip_sendto(s,dataptr,size,flags,to,tolen) +#define socket(domain,type,protocol) lwip_socket(domain,type,protocol) +#define select(maxfdp1,readset,writeset,exceptset,timeout) lwip_select(maxfdp1,readset,writeset,exceptset,timeout) +#define ioctlsocket(s,cmd,argp) lwip_ioctl(s,cmd,argp) + +#if LWIP_POSIX_SOCKETS_IO_NAMES +#define read(s,mem,len) lwip_read(s,mem,len) +#define write(s,dataptr,len) lwip_write(s,dataptr,len) +#define writev(s,iov,iovcnt) lwip_writev(s,iov,iovcnt) +#define close(s) lwip_close(s) +#define fcntl(s,cmd,val) lwip_fcntl(s,cmd,val) +#define ioctl(s,cmd,argp) lwip_ioctl(s,cmd,argp) +#endif /* LWIP_POSIX_SOCKETS_IO_NAMES */ +#endif /* LWIP_THREAD_SAFE */ + +#endif /* LWIP_COMPAT_SOCKETS != 2 */ + +#if LWIP_IPV4 && LWIP_IPV6 +#define inet_ntop(af,src,dst,size) \ + (((af) == AF_INET6) ? ip6addr_ntoa_r((const ip6_addr_t*)(src),(dst),(size)) \ + : (((af) == AF_INET) ? ip4addr_ntoa_r((const ip4_addr_t*)(src),(dst),(size)) : NULL)) +#define inet_pton(af,src,dst) \ + (((af) == AF_INET6) ? ip6addr_aton((src),(ip6_addr_t*)(dst)) \ + : (((af) == AF_INET) ? ip4addr_aton((src),(ip4_addr_t*)(dst)) : 0)) +#elif LWIP_IPV4 /* LWIP_IPV4 && LWIP_IPV6 */ +#define inet_ntop(af,src,dst,size) \ + (((af) == AF_INET) ? ip4addr_ntoa_r((const ip4_addr_t*)(src),(dst),(size)) : NULL) +#define inet_pton(af,src,dst) \ + (((af) == AF_INET) ? ip4addr_aton((src),(ip4_addr_t*)(dst)) : 0) +#else /* LWIP_IPV4 && LWIP_IPV6 */ +#define inet_ntop(af,src,dst,size) \ + (((af) == AF_INET6) ? ip6addr_ntoa_r((const ip6_addr_t*)(src),(dst),(size)) : NULL) +#define inet_pton(af,src,dst) \ + (((af) == AF_INET6) ? ip6addr_aton((src),(ip6_addr_t*)(dst)) : 0) +#endif /* LWIP_IPV4 && LWIP_IPV6 */ + +#endif /* LWIP_COMPAT_SOCKETS */ + +#ifdef __cplusplus +} +#endif + +#endif /* LWIP_SOCKET */ + +#endif /* LWIP_HDR_SOCKETS_H */ diff --git a/components/lwip/include/lwip/lwip/stats.h b/components/lwip/include/lwip/lwip/stats.h new file mode 100755 index 0000000000..176723d27f --- /dev/null +++ b/components/lwip/include/lwip/lwip/stats.h @@ -0,0 +1,462 @@ +/* + * Copyright (c) 2001-2004 Swedish Institute of Computer Science. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + * + */ +#ifndef LWIP_HDR_STATS_H +#define LWIP_HDR_STATS_H + +#include "lwip/opt.h" + +#include "lwip/mem.h" +#include "lwip/memp.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#if LWIP_STATS + +#ifndef LWIP_STATS_LARGE +#define LWIP_STATS_LARGE 0 +#endif + +#if LWIP_STATS_LARGE +#define STAT_COUNTER u32_t +#define STAT_COUNTER_F U32_F +#else +#define STAT_COUNTER u16_t +#define STAT_COUNTER_F U16_F +#endif + +struct stats_proto { + STAT_COUNTER xmit; /* Transmitted packets. */ + STAT_COUNTER recv; /* Received packets. */ + STAT_COUNTER fw; /* Forwarded packets. */ + STAT_COUNTER drop; /* Dropped packets. */ + STAT_COUNTER chkerr; /* Checksum error. */ + STAT_COUNTER lenerr; /* Invalid length error. */ + STAT_COUNTER memerr; /* Out of memory error. */ + STAT_COUNTER rterr; /* Routing error. */ + STAT_COUNTER proterr; /* Protocol error. */ + STAT_COUNTER opterr; /* Error in options. */ + STAT_COUNTER err; /* Misc error. */ + STAT_COUNTER cachehit; +}; + +struct stats_igmp { + STAT_COUNTER xmit; /* Transmitted packets. */ + STAT_COUNTER recv; /* Received packets. */ + STAT_COUNTER drop; /* Dropped packets. */ + STAT_COUNTER chkerr; /* Checksum error. */ + STAT_COUNTER lenerr; /* Invalid length error. */ + STAT_COUNTER memerr; /* Out of memory error. */ + STAT_COUNTER proterr; /* Protocol error. */ + STAT_COUNTER rx_v1; /* Received v1 frames. */ + STAT_COUNTER rx_group; /* Received group-specific queries. */ + STAT_COUNTER rx_general; /* Received general queries. */ + STAT_COUNTER rx_report; /* Received reports. */ + STAT_COUNTER tx_join; /* Sent joins. */ + STAT_COUNTER tx_leave; /* Sent leaves. */ + STAT_COUNTER tx_report; /* Sent reports. */ +}; + +struct stats_mem { +#ifdef LWIP_DEBUG + const char *name; +#endif /* LWIP_DEBUG */ + STAT_COUNTER err; + mem_size_t avail; + mem_size_t used; + mem_size_t max; + STAT_COUNTER illegal; +}; + +struct stats_syselem { + STAT_COUNTER used; + STAT_COUNTER max; + STAT_COUNTER err; +}; + +struct stats_sys { + struct stats_syselem sem; + struct stats_syselem mutex; + struct stats_syselem mbox; +}; + +struct stats_mib2 { + /* IP */ + u32_t ipinhdrerrors; + u32_t ipinaddrerrors; + u32_t ipinunknownprotos; + u32_t ipindiscards; + u32_t ipindelivers; + u32_t ipoutrequests; + u32_t ipoutdiscards; + u32_t ipoutnoroutes; + u32_t ipreasmoks; + u32_t ipreasmfails; + u32_t ipfragoks; + u32_t ipfragfails; + u32_t ipfragcreates; + u32_t ipreasmreqds; + u32_t ipforwdatagrams; + u32_t ipinreceives; + + /* TCP */ + u32_t tcpactiveopens; + u32_t tcppassiveopens; + u32_t tcpattemptfails; + u32_t tcpestabresets; + u32_t tcpoutsegs; + u32_t tcpretranssegs; + u32_t tcpinsegs; + u32_t tcpinerrs; + u32_t tcpoutrsts; + + /* UDP */ + u32_t udpindatagrams; + u32_t udpnoports; + u32_t udpinerrors; + u32_t udpoutdatagrams; + + /* ICMP */ + u32_t icmpinmsgs; + u32_t icmpinerrors; + u32_t icmpindestunreachs; + u32_t icmpintimeexcds; + u32_t icmpinparmprobs; + u32_t icmpinsrcquenchs; + u32_t icmpinredirects; + u32_t icmpinechos; + u32_t icmpinechoreps; + u32_t icmpintimestamps; + u32_t icmpintimestampreps; + u32_t icmpinaddrmasks; + u32_t icmpinaddrmaskreps; + u32_t icmpoutmsgs; + u32_t icmpouterrors; + u32_t icmpoutdestunreachs; + u32_t icmpouttimeexcds; + u32_t icmpoutechos; /* can be incremented by user application ('ping') */ + u32_t icmpoutechoreps; +}; + +struct stats_mib2_netif_ctrs { + /* The total number of octets received on the interface, including framing characters */ + u32_t ifinoctets; + /* The number of packets, delivered by this sub-layer to a higher (sub-)layer, which were + * not addressed to a multicast or broadcast address at this sub-layer */ + u32_t ifinucastpkts; + /* The number of packets, delivered by this sub-layer to a higher (sub-)layer, which were + * addressed to a multicast or broadcast address at this sub-layer */ + u32_t ifinnucastpkts; + /* The number of inbound packets which were chosen to be discarded even though no errors had + * been detected to prevent their being deliverable to a higher-layer protocol. One possible + * reason for discarding such a packet could be to free up buffer space */ + u32_t ifindiscards; + /* For packet-oriented interfaces, the number of inbound packets that contained errors + * preventing them from being deliverable to a higher-layer protocol. For character- + * oriented or fixed-length interfaces, the number of inbound transmission units that + * contained errors preventing them from being deliverable to a higher-layer protocol. */ + u32_t ifinerrors; + /* For packet-oriented interfaces, the number of packets received via the interface which + * were discarded because of an unknown or unsupported protocol. For character-oriented + * or fixed-length interfaces that support protocol multiplexing the number of transmission + * units received via the interface which were discarded because of an unknown or unsupported + * protocol. For any interface that does not support protocol multiplexing, this counter will + * always be 0 */ + u32_t ifinunknownprotos; + /* The total number of octets transmitted out of the interface, including framing characters. */ + u32_t ifoutoctets; + /* The total number of packets that higher-level protocols requested be transmitted, and + * which were not addressed to a multicast or broadcast address at this sub-layer, including + * those that were discarded or not sent. */ + u32_t ifoutucastpkts; + /* The total number of packets that higher-level protocols requested be transmitted, and which + * were addressed to a multicast or broadcast address at this sub-layer, including + * those that were discarded or not sent. */ + u32_t ifoutnucastpkts; + /* The number of outbound packets which were chosen to be discarded even though no errors had + * been detected to prevent their being transmitted. One possible reason for discarding + * such a packet could be to free up buffer space. */ + u32_t ifoutdiscards; + /* For packet-oriented interfaces, the number of outbound packets that could not be transmitted + * because of errors. For character-oriented or fixed-length interfaces, the number of outbound + * transmission units that could not be transmitted because of errors. */ + u32_t ifouterrors; +}; + +struct stats_ { +#if LINK_STATS + struct stats_proto link; +#endif +#if ETHARP_STATS + struct stats_proto etharp; +#endif +#if IPFRAG_STATS + struct stats_proto ip_frag; +#endif +#if IP_STATS + struct stats_proto ip; +#endif +#if ICMP_STATS + struct stats_proto icmp; +#endif +#if IGMP_STATS + struct stats_igmp igmp; +#endif +#if UDP_STATS + struct stats_proto udp; +#endif +#if TCP_STATS + struct stats_proto tcp; +#endif +#if MEM_STATS + struct stats_mem mem; +#endif +#if MEMP_STATS + struct stats_mem memp[MEMP_MAX]; +#endif +#if SYS_STATS + struct stats_sys sys; +#endif +#if IP6_STATS + struct stats_proto ip6; +#endif +#if ICMP6_STATS + struct stats_proto icmp6; +#endif +#if IP6_FRAG_STATS + struct stats_proto ip6_frag; +#endif +#if MLD6_STATS + struct stats_igmp mld6; +#endif +#if ND6_STATS + struct stats_proto nd6; +#endif +#if MIB2_STATS + struct stats_mib2 mib2; +#endif +}; + +extern struct stats_ lwip_stats; + +void stats_init(void); + +#define STATS_INC(x) ++lwip_stats.x +#define STATS_DEC(x) --lwip_stats.x +#define STATS_INC_USED(x, y) do { lwip_stats.x.used += y; \ + if (lwip_stats.x.max < lwip_stats.x.used) { \ + lwip_stats.x.max = lwip_stats.x.used; \ + } \ + } while(0) +#define STATS_GET(x) lwip_stats.x +#else /* LWIP_STATS */ +#define stats_init() +#define STATS_INC(x) +#define STATS_DEC(x) +#define STATS_INC_USED(x) +#endif /* LWIP_STATS */ + +#if TCP_STATS +#define TCP_STATS_INC(x) STATS_INC(x) +#define TCP_STATS_DISPLAY() stats_display_proto(&lwip_stats.tcp, "TCP") +#else +#define TCP_STATS_INC(x) +#define TCP_STATS_DISPLAY() +#endif + +#if UDP_STATS +#define UDP_STATS_INC(x) STATS_INC(x) +#define UDP_STATS_DISPLAY() stats_display_proto(&lwip_stats.udp, "UDP") +#else +#define UDP_STATS_INC(x) +#define UDP_STATS_DISPLAY() +#endif + +#if ICMP_STATS +#define ICMP_STATS_INC(x) STATS_INC(x) +#define ICMP_STATS_DISPLAY() stats_display_proto(&lwip_stats.icmp, "ICMP") +#else +#define ICMP_STATS_INC(x) +#define ICMP_STATS_DISPLAY() +#endif + +#if IGMP_STATS +#define IGMP_STATS_INC(x) STATS_INC(x) +#define IGMP_STATS_DISPLAY() stats_display_igmp(&lwip_stats.igmp, "IGMP") +#else +#define IGMP_STATS_INC(x) +#define IGMP_STATS_DISPLAY() +#endif + +#if IP_STATS +#define IP_STATS_INC(x) STATS_INC(x) +#define IP_STATS_DISPLAY() stats_display_proto(&lwip_stats.ip, "IP") +#else +#define IP_STATS_INC(x) +#define IP_STATS_DISPLAY() +#endif + +#if IPFRAG_STATS +#define IPFRAG_STATS_INC(x) STATS_INC(x) +#define IPFRAG_STATS_DISPLAY() stats_display_proto(&lwip_stats.ip_frag, "IP_FRAG") +#else +#define IPFRAG_STATS_INC(x) +#define IPFRAG_STATS_DISPLAY() +#endif + +#if ETHARP_STATS +#define ETHARP_STATS_INC(x) STATS_INC(x) +#define ETHARP_STATS_DISPLAY() stats_display_proto(&lwip_stats.etharp, "ETHARP") +#else +#define ETHARP_STATS_INC(x) +#define ETHARP_STATS_DISPLAY() +#endif + +#if LINK_STATS +#define LINK_STATS_INC(x) STATS_INC(x) +#define LINK_STATS_DISPLAY() stats_display_proto(&lwip_stats.link, "LINK") +#else +#define LINK_STATS_INC(x) +#define LINK_STATS_DISPLAY() +#endif + +#if MEM_STATS +#define MEM_STATS_AVAIL(x, y) lwip_stats.mem.x = y +#define MEM_STATS_INC(x) STATS_INC(mem.x) +#define MEM_STATS_INC_USED(x, y) STATS_INC_USED(mem, y) +#define MEM_STATS_DEC_USED(x, y) lwip_stats.mem.x -= y +#define MEM_STATS_DISPLAY() stats_display_mem(&lwip_stats.mem, "HEAP") +#else +#define MEM_STATS_AVAIL(x, y) +#define MEM_STATS_INC(x) +#define MEM_STATS_INC_USED(x, y) +#define MEM_STATS_DEC_USED(x, y) +#define MEM_STATS_DISPLAY() +#endif + +#if MEMP_STATS +#define MEMP_STATS_AVAIL(x, i, y) lwip_stats.memp[i].x = y +#define MEMP_STATS_INC(x, i) STATS_INC(memp[i].x) +#define MEMP_STATS_DEC(x, i) STATS_DEC(memp[i].x) +#define MEMP_STATS_INC_USED(x, i) STATS_INC_USED(memp[i], 1) +#define MEMP_STATS_DISPLAY(i) stats_display_memp(&lwip_stats.memp[i], i) +#define MEMP_STATS_GET(x, i) STATS_GET(memp[i].x) +#else +#define MEMP_STATS_AVAIL(x, i, y) +#define MEMP_STATS_INC(x, i) +#define MEMP_STATS_DEC(x, i) +#define MEMP_STATS_INC_USED(x, i) +#define MEMP_STATS_DISPLAY(i) +#define MEMP_STATS_GET(x, i) 0 +#endif + +#if SYS_STATS +#define SYS_STATS_INC(x) STATS_INC(sys.x) +#define SYS_STATS_DEC(x) STATS_DEC(sys.x) +#define SYS_STATS_INC_USED(x) STATS_INC_USED(sys.x, 1) +#define SYS_STATS_DISPLAY() stats_display_sys(&lwip_stats.sys) +#else +#define SYS_STATS_INC(x) +#define SYS_STATS_DEC(x) +#define SYS_STATS_INC_USED(x) +#define SYS_STATS_DISPLAY() +#endif + +#if IP6_STATS +#define IP6_STATS_INC(x) STATS_INC(x) +#define IP6_STATS_DISPLAY() stats_display_proto(&lwip_stats.ip6, "IPv6") +#else +#define IP6_STATS_INC(x) +#define IP6_STATS_DISPLAY() +#endif + +#if ICMP6_STATS +#define ICMP6_STATS_INC(x) STATS_INC(x) +#define ICMP6_STATS_DISPLAY() stats_display_proto(&lwip_stats.icmp6, "ICMPv6") +#else +#define ICMP6_STATS_INC(x) +#define ICMP6_STATS_DISPLAY() +#endif + +#if IP6_FRAG_STATS +#define IP6_FRAG_STATS_INC(x) STATS_INC(x) +#define IP6_FRAG_STATS_DISPLAY() stats_display_proto(&lwip_stats.ip6_frag, "IPv6 FRAG") +#else +#define IP6_FRAG_STATS_INC(x) +#define IP6_FRAG_STATS_DISPLAY() +#endif + +#if MLD6_STATS +#define MLD6_STATS_INC(x) STATS_INC(x) +#define MLD6_STATS_DISPLAY() stats_display_igmp(&lwip_stats.mld6, "MLDv1") +#else +#define MLD6_STATS_INC(x) +#define MLD6_STATS_DISPLAY() +#endif + +#if ND6_STATS +#define ND6_STATS_INC(x) STATS_INC(x) +#define ND6_STATS_DISPLAY() stats_display_proto(&lwip_stats.nd6, "ND") +#else +#define ND6_STATS_INC(x) +#define ND6_STATS_DISPLAY() +#endif + +#if MIB2_STATS +#define MIB2_STATS_INC(x) STATS_INC(x) +#else +#define MIB2_STATS_INC(x) +#endif + +/* Display of statistics */ +#if LWIP_STATS_DISPLAY +void stats_display(void); +void stats_display_proto(struct stats_proto *proto, const char *name); +void stats_display_igmp(struct stats_igmp *igmp, const char *name); +void stats_display_mem(struct stats_mem *mem, const char *name); +void stats_display_memp(struct stats_mem *mem, int index); +void stats_display_sys(struct stats_sys *sys); +#else /* LWIP_STATS_DISPLAY */ +#define stats_display() +#define stats_display_proto(proto, name) +#define stats_display_igmp(igmp, name) +#define stats_display_mem(mem, name) +#define stats_display_memp(mem, index) +#define stats_display_sys(sys) +#endif /* LWIP_STATS_DISPLAY */ + +#ifdef __cplusplus +} +#endif + +#endif /* LWIP_HDR_STATS_H */ diff --git a/components/lwip/include/lwip/lwip/sys.h b/components/lwip/include/lwip/lwip/sys.h new file mode 100755 index 0000000000..86d0f3b336 --- /dev/null +++ b/components/lwip/include/lwip/lwip/sys.h @@ -0,0 +1,362 @@ +/* + * Copyright (c) 2001-2004 Swedish Institute of Computer Science. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + * + */ +#ifndef LWIP_HDR_SYS_H +#define LWIP_HDR_SYS_H + +#include "lwip/opt.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#if NO_SYS + +/* For a totally minimal and standalone system, we provide null + definitions of the sys_ functions. */ +typedef u8_t sys_sem_t; +typedef u8_t sys_mutex_t; +typedef u8_t sys_mbox_t; + +#define sys_sem_new(s, c) ERR_OK +#define sys_sem_signal(s) +#define sys_sem_wait(s) +#define sys_arch_sem_wait(s,t) +#define sys_sem_free(s) +#define sys_sem_valid(s) 0 +#define sys_sem_valid_val(s) 0 +#define sys_sem_set_invalid(s) +#define sys_sem_set_invalid_val(s) +#define sys_mutex_new(mu) ERR_OK +#define sys_mutex_lock(mu) +#define sys_mutex_unlock(mu) +#define sys_mutex_free(mu) +#define sys_mutex_valid(mu) 0 +#define sys_mutex_set_invalid(mu) +#define sys_mbox_new(m, s) ERR_OK +#define sys_mbox_fetch(m,d) +#define sys_mbox_tryfetch(m,d) +#define sys_mbox_post(m,d) +#define sys_mbox_trypost(m,d) +#define sys_mbox_free(m) +#define sys_mbox_valid(m) +#define sys_mbox_valid_val(m) +#define sys_mbox_set_invalid(m) +#define sys_mbox_set_invalid_val(m) + +#define sys_thread_new(n,t,a,s,p) + +#define sys_msleep(t) + +#else /* NO_SYS */ + +/** Return code for timeouts from sys_arch_mbox_fetch and sys_arch_sem_wait */ +#define SYS_ARCH_TIMEOUT 0xffffffffUL + +/** sys_mbox_tryfetch() returns SYS_MBOX_EMPTY if appropriate. + * For now we use the same magic value, but we allow this to change in future. + */ +#define SYS_MBOX_EMPTY SYS_ARCH_TIMEOUT + +#include "lwip/err.h" +#include "arch/sys_arch.h" + +/** Function prototype for thread functions */ +typedef void (*lwip_thread_fn)(void *arg); + +/* Function prototypes for functions to be implemented by platform ports + (in sys_arch.c) */ + +/* Mutex functions: */ + +/** Define LWIP_COMPAT_MUTEX if the port has no mutexes and binary semaphores + should be used instead */ +#ifndef LWIP_COMPAT_MUTEX +#define LWIP_COMPAT_MUTEX 0 +#endif + +#if LWIP_COMPAT_MUTEX +/* for old ports that don't have mutexes: define them to binary semaphores */ +#define sys_mutex_t sys_sem_t +#define sys_mutex_new(mutex) sys_sem_new(mutex, 1) +#define sys_mutex_lock(mutex) sys_sem_wait(mutex) +#define sys_mutex_unlock(mutex) sys_sem_signal(mutex) +#define sys_mutex_free(mutex) sys_sem_free(mutex) +#define sys_mutex_valid(mutex) sys_sem_valid(mutex) +#define sys_mutex_set_invalid(mutex) sys_sem_set_invalid(mutex) + +#else /* LWIP_COMPAT_MUTEX */ + +/** Create a new mutex + * @param mutex pointer to the mutex to create + * @return a new mutex */ +err_t sys_mutex_new(sys_mutex_t *mutex); +/** Lock a mutex + * @param mutex the mutex to lock */ +void sys_mutex_lock(sys_mutex_t *mutex); +/** Unlock a mutex + * @param mutex the mutex to unlock */ +void sys_mutex_unlock(sys_mutex_t *mutex); +/** Delete a semaphore + * @param mutex the mutex to delete */ +void sys_mutex_free(sys_mutex_t *mutex); +#ifndef sys_mutex_valid +/** Check if a mutex is valid/allocated: return 1 for valid, 0 for invalid */ +int sys_mutex_valid(sys_mutex_t *mutex); +#endif +#ifndef sys_mutex_set_invalid +/** Set a mutex invalid so that sys_mutex_valid returns 0 */ +void sys_mutex_set_invalid(sys_mutex_t *mutex); +#endif +#endif /* LWIP_COMPAT_MUTEX */ + +/* Semaphore functions: */ + +/** Create a new semaphore + * @param sem pointer to the semaphore to create + * @param count initial count of the semaphore + * @return ERR_OK if successful, another err_t otherwise */ +err_t sys_sem_new(sys_sem_t *sem, u8_t count); +/** Signals a semaphore + * @param sem the semaphore to signal */ +void sys_sem_signal(sys_sem_t *sem); +/** Wait for a semaphore for the specified timeout + * @param sem the semaphore to wait for + * @param timeout timeout in milliseconds to wait (0 = wait forever) + * @return time (in milliseconds) waited for the semaphore + * or SYS_ARCH_TIMEOUT on timeout */ +u32_t sys_arch_sem_wait(sys_sem_t *sem, u32_t timeout); +/** Delete a semaphore + * @param sem semaphore to delete */ +void sys_sem_free(sys_sem_t *sem); +/** Wait for a semaphore - forever/no timeout */ +#define sys_sem_wait(sem) sys_arch_sem_wait(sem, 0) +#ifndef sys_sem_valid +/** Check if a semaphore is valid/allocated: return 1 for valid, 0 for invalid */ +int sys_sem_valid(sys_sem_t *sem); +#endif +#ifndef sys_sem_set_invalid +/** Set a semaphore invalid so that sys_sem_valid returns 0 */ +void sys_sem_set_invalid(sys_sem_t *sem); +#endif +#ifndef sys_sem_valid_val +/** Same as sys_sem_valid() but taking a value, not a pointer */ +#define sys_sem_valid_val(sem) sys_sem_valid(&(sem)) +#endif +#ifndef sys_sem_set_invalid_val +/** Same as sys_sem_set_invalid() but taking a value, not a pointer */ +#define sys_sem_set_invalid_val(sem) sys_sem_set_invalid(&(sem)) +#endif + +/* Time functions. */ +#ifndef sys_msleep +void sys_msleep(u32_t ms); /* only has a (close to) 1 ms resolution. */ +#endif + +/* Mailbox functions. */ + +/** Create a new mbox of specified size + * @param mbox pointer to the mbox to create + * @param size (minimum) number of messages in this mbox + * @return ERR_OK if successful, another err_t otherwise */ +err_t sys_mbox_new(sys_mbox_t *mbox, int size); +/** Post a message to an mbox - may not fail + * -> blocks if full, only used from tasks not from ISR + * @param mbox mbox to posts the message + * @param msg message to post (ATTENTION: can be NULL) */ +void sys_mbox_post(sys_mbox_t *mbox, void *msg); +/** Try to post a message to an mbox - may fail if full or ISR + * @param mbox mbox to posts the message + * @param msg message to post (ATTENTION: can be NULL) */ +err_t sys_mbox_trypost(sys_mbox_t *mbox, void *msg); +/** Wait for a new message to arrive in the mbox + * @param mbox mbox to get a message from + * @param msg pointer where the message is stored + * @param timeout maximum time (in milliseconds) to wait for a message (0 = wait forever) + * @return time (in milliseconds) waited for a message, may be 0 if not waited + or SYS_ARCH_TIMEOUT on timeout + * The returned time has to be accurate to prevent timer jitter! */ +u32_t sys_arch_mbox_fetch(sys_mbox_t *mbox, void **msg, u32_t timeout); +/* Allow port to override with a macro, e.g. special timeout for sys_arch_mbox_fetch() */ +#ifndef sys_arch_mbox_tryfetch +/** Wait for a new message to arrive in the mbox + * @param mbox mbox to get a message from + * @param msg pointer where the message is stored + * @return 0 (milliseconds) if a message has been received + * or SYS_MBOX_EMPTY if the mailbox is empty */ +u32_t sys_arch_mbox_tryfetch(sys_mbox_t *mbox, void **msg); +#endif +/** For now, we map straight to sys_arch implementation. */ +#define sys_mbox_tryfetch(mbox, msg) sys_arch_mbox_tryfetch(mbox, msg) +/** Delete an mbox + * @param mbox mbox to delete */ +void sys_mbox_free(sys_mbox_t *mbox); +#define sys_mbox_fetch(mbox, msg) sys_arch_mbox_fetch(mbox, msg, 0) +#ifndef sys_mbox_valid +/** Check if an mbox is valid/allocated: return 1 for valid, 0 for invalid */ +int sys_mbox_valid(sys_mbox_t *mbox); +#endif +#ifndef sys_mbox_set_invalid +/** Set an mbox invalid so that sys_mbox_valid returns 0 */ +void sys_mbox_set_invalid(sys_mbox_t *mbox); +#endif +#ifndef sys_mbox_valid_val +/** Same as sys_mbox_valid() but taking a value, not a pointer */ +#define sys_mbox_valid_val(mbox) sys_mbox_valid(&(mbox)) +#endif +#ifndef sys_mbox_set_invalid_val +/** Same as sys_mbox_set_invalid() but taking a value, not a pointer */ +#define sys_mbox_set_invalid_val(mbox) sys_mbox_set_invalid(&(mbox)) +#endif + + +/** The only thread function: + * Creates a new thread + * ATTENTION: although this function returns a value, it MUST NOT FAIL (ports have to assert this!) + * @param name human-readable name for the thread (used for debugging purposes) + * @param thread thread-function + * @param arg parameter passed to 'thread' + * @param stacksize stack size in bytes for the new thread (may be ignored by ports) + * @param prio priority of the new thread (may be ignored by ports) */ +sys_thread_t sys_thread_new(const char *name, lwip_thread_fn thread, void *arg, int stacksize, int prio); + +#endif /* NO_SYS */ + +/* sys_init() must be called before anything else. */ +void sys_init(void); + +#ifndef sys_jiffies +/** Ticks/jiffies since power up. */ +u32_t sys_jiffies(void); +#endif + +/** Returns the current time in milliseconds, + * may be the same as sys_jiffies or at least based on it. */ +u32_t sys_now(void); + +/* Critical Region Protection */ +/* These functions must be implemented in the sys_arch.c file. + In some implementations they can provide a more light-weight protection + mechanism than using semaphores. Otherwise semaphores can be used for + implementation */ +#ifndef SYS_ARCH_PROTECT +/** SYS_LIGHTWEIGHT_PROT + * define SYS_LIGHTWEIGHT_PROT in lwipopts.h if you want inter-task protection + * for certain critical regions during buffer allocation, deallocation and memory + * allocation and deallocation. + */ +#if SYS_LIGHTWEIGHT_PROT + +/** SYS_ARCH_DECL_PROTECT + * declare a protection variable. This macro will default to defining a variable of + * type sys_prot_t. If a particular port needs a different implementation, then + * this macro may be defined in sys_arch.h. + */ +#define SYS_ARCH_DECL_PROTECT(lev) sys_prot_t lev +/** SYS_ARCH_PROTECT + * Perform a "fast" protect. This could be implemented by + * disabling interrupts for an embedded system or by using a semaphore or + * mutex. The implementation should allow calling SYS_ARCH_PROTECT when + * already protected. The old protection level is returned in the variable + * "lev". This macro will default to calling the sys_arch_protect() function + * which should be implemented in sys_arch.c. If a particular port needs a + * different implementation, then this macro may be defined in sys_arch.h + */ +#define SYS_ARCH_PROTECT(lev) lev = sys_arch_protect() +/** SYS_ARCH_UNPROTECT + * Perform a "fast" set of the protection level to "lev". This could be + * implemented by setting the interrupt level to "lev" within the MACRO or by + * using a semaphore or mutex. This macro will default to calling the + * sys_arch_unprotect() function which should be implemented in + * sys_arch.c. If a particular port needs a different implementation, then + * this macro may be defined in sys_arch.h + */ +#define SYS_ARCH_UNPROTECT(lev) sys_arch_unprotect(lev) +sys_prot_t sys_arch_protect(void); +void sys_arch_unprotect(sys_prot_t pval); + +#else + +#define SYS_ARCH_DECL_PROTECT(lev) +#define SYS_ARCH_PROTECT(lev) +#define SYS_ARCH_UNPROTECT(lev) + +#endif /* SYS_LIGHTWEIGHT_PROT */ + +#endif /* SYS_ARCH_PROTECT */ + +/* + * Macros to set/get and increase/decrease variables in a thread-safe way. + * Use these for accessing variable that are used from more than one thread. + */ + +#ifndef SYS_ARCH_INC +#define SYS_ARCH_INC(var, val) do { \ + SYS_ARCH_DECL_PROTECT(old_level); \ + SYS_ARCH_PROTECT(old_level); \ + var += val; \ + SYS_ARCH_UNPROTECT(old_level); \ + } while(0) +#endif /* SYS_ARCH_INC */ + +#ifndef SYS_ARCH_DEC +#define SYS_ARCH_DEC(var, val) do { \ + SYS_ARCH_DECL_PROTECT(old_level); \ + SYS_ARCH_PROTECT(old_level); \ + var -= val; \ + SYS_ARCH_UNPROTECT(old_level); \ + } while(0) +#endif /* SYS_ARCH_DEC */ + +#ifndef SYS_ARCH_GET +#define SYS_ARCH_GET(var, ret) do { \ + SYS_ARCH_DECL_PROTECT(old_level); \ + SYS_ARCH_PROTECT(old_level); \ + ret = var; \ + SYS_ARCH_UNPROTECT(old_level); \ + } while(0) +#endif /* SYS_ARCH_GET */ + +#ifndef SYS_ARCH_SET +#define SYS_ARCH_SET(var, val) do { \ + SYS_ARCH_DECL_PROTECT(old_level); \ + SYS_ARCH_PROTECT(old_level); \ + var = val; \ + SYS_ARCH_UNPROTECT(old_level); \ + } while(0) +#endif /* SYS_ARCH_SET */ + + +#ifdef __cplusplus +} +#endif + +#endif /* LWIP_HDR_SYS_H */ diff --git a/components/lwip/include/lwip/lwip/tcp.h b/components/lwip/include/lwip/lwip/tcp.h new file mode 100755 index 0000000000..d52040f99c --- /dev/null +++ b/components/lwip/include/lwip/lwip/tcp.h @@ -0,0 +1,411 @@ +/* + * Copyright (c) 2001-2004 Swedish Institute of Computer Science. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + * + */ +#ifndef LWIP_HDR_TCP_H +#define LWIP_HDR_TCP_H + +#include "lwip/opt.h" + +#if LWIP_TCP /* don't build if not configured for use in lwipopts.h */ + +#include "lwip/mem.h" +#include "lwip/pbuf.h" +#include "lwip/ip.h" +#include "lwip/icmp.h" +#include "lwip/err.h" +#include "lwip/ip6.h" +#include "lwip/ip6_addr.h" + +#ifdef __cplusplus +extern "C" { +#endif + +struct tcp_pcb; + +/** Function prototype for tcp accept callback functions. Called when a new + * connection can be accepted on a listening pcb. + * + * @param arg Additional argument to pass to the callback function (@see tcp_arg()) + * @param newpcb The new connection pcb + * @param err An error code if there has been an error accepting. + * Only return ERR_ABRT if you have called tcp_abort from within the + * callback function! + */ +typedef err_t (*tcp_accept_fn)(void *arg, struct tcp_pcb *newpcb, err_t err); + +/** Function prototype for tcp receive callback functions. Called when data has + * been received. + * + * @param arg Additional argument to pass to the callback function (@see tcp_arg()) + * @param tpcb The connection pcb which received data + * @param p The received data (or NULL when the connection has been closed!) + * @param err An error code if there has been an error receiving + * Only return ERR_ABRT if you have called tcp_abort from within the + * callback function! + */ +typedef err_t (*tcp_recv_fn)(void *arg, struct tcp_pcb *tpcb, + struct pbuf *p, err_t err); + +/** Function prototype for tcp sent callback functions. Called when sent data has + * been acknowledged by the remote side. Use it to free corresponding resources. + * This also means that the pcb has now space available to send new data. + * + * @param arg Additional argument to pass to the callback function (@see tcp_arg()) + * @param tpcb The connection pcb for which data has been acknowledged + * @param len The amount of bytes acknowledged + * @return ERR_OK: try to send some data by calling tcp_output + * Only return ERR_ABRT if you have called tcp_abort from within the + * callback function! + */ +typedef err_t (*tcp_sent_fn)(void *arg, struct tcp_pcb *tpcb, + u16_t len); + +/** Function prototype for tcp poll callback functions. Called periodically as + * specified by @see tcp_poll. + * + * @param arg Additional argument to pass to the callback function (@see tcp_arg()) + * @param tpcb tcp pcb + * @return ERR_OK: try to send some data by calling tcp_output + * Only return ERR_ABRT if you have called tcp_abort from within the + * callback function! + */ +typedef err_t (*tcp_poll_fn)(void *arg, struct tcp_pcb *tpcb); + +/** Function prototype for tcp error callback functions. Called when the pcb + * receives a RST or is unexpectedly closed for any other reason. + * + * @note The corresponding pcb is already freed when this callback is called! + * + * @param arg Additional argument to pass to the callback function (@see tcp_arg()) + * @param err Error code to indicate why the pcb has been closed + * ERR_ABRT: aborted through tcp_abort or by a TCP timer + * ERR_RST: the connection was reset by the remote host + */ +typedef void (*tcp_err_fn)(void *arg, err_t err); + +/** Function prototype for tcp connected callback functions. Called when a pcb + * is connected to the remote side after initiating a connection attempt by + * calling tcp_connect(). + * + * @param arg Additional argument to pass to the callback function (@see tcp_arg()) + * @param tpcb The connection pcb which is connected + * @param err An unused error code, always ERR_OK currently ;-) TODO! + * Only return ERR_ABRT if you have called tcp_abort from within the + * callback function! + * + * @note When a connection attempt fails, the error callback is currently called! + */ +typedef err_t (*tcp_connected_fn)(void *arg, struct tcp_pcb *tpcb, err_t err); + +#if LWIP_WND_SCALE +#define RCV_WND_SCALE(pcb, wnd) (((wnd) >> (pcb)->rcv_scale)) +#define SND_WND_SCALE(pcb, wnd) (((wnd) << (pcb)->snd_scale)) +#define TCPWND16(x) ((u16_t)LWIP_MIN((x), 0xFFFF)) +#define TCP_WND_MAX(pcb) ((tcpwnd_size_t)(((pcb)->flags & TF_WND_SCALE) ? TCP_WND : TCPWND16(TCP_WND))) +typedef u32_t tcpwnd_size_t; +typedef u16_t tcpflags_t; +#else +#define RCV_WND_SCALE(pcb, wnd) (wnd) +#define SND_WND_SCALE(pcb, wnd) (wnd) +#define TCPWND16(x) (x) +#define TCP_WND_MAX(pcb) TCP_WND +typedef u16_t tcpwnd_size_t; +typedef u8_t tcpflags_t; +#endif + +enum tcp_state { + CLOSED = 0, + LISTEN = 1, + SYN_SENT = 2, + SYN_RCVD = 3, + ESTABLISHED = 4, + FIN_WAIT_1 = 5, + FIN_WAIT_2 = 6, + CLOSE_WAIT = 7, + CLOSING = 8, + LAST_ACK = 9, + TIME_WAIT = 10 +}; + +#if LWIP_CALLBACK_API + /* Function to call when a listener has been connected. + * @param arg user-supplied argument (tcp_pcb.callback_arg) + * @param pcb a new tcp_pcb that now is connected + * @param err an error argument (TODO: that is current always ERR_OK?) + * @return ERR_OK: accept the new connection, + * any other err_t aborts the new connection + */ +#define DEF_ACCEPT_CALLBACK tcp_accept_fn accept; +#else /* LWIP_CALLBACK_API */ +#define DEF_ACCEPT_CALLBACK +#endif /* LWIP_CALLBACK_API */ + +/** + * members common to struct tcp_pcb and struct tcp_listen_pcb + */ +#define TCP_PCB_COMMON(type) \ + type *next; /* for the linked list */ \ + void *callback_arg; \ + /* the accept callback for listen- and normal pcbs, if LWIP_CALLBACK_API */ \ + DEF_ACCEPT_CALLBACK \ + enum tcp_state state; /* TCP state */ \ + u8_t prio; \ + /* ports are in host byte order */ \ + u16_t local_port + + +/* the TCP protocol control block */ +struct tcp_pcb { +/** common PCB members */ + IP_PCB; +/** protocol specific PCB members */ + TCP_PCB_COMMON(struct tcp_pcb); + + /* ports are in host byte order */ + u16_t remote_port; + + tcpflags_t flags; +#define TF_ACK_DELAY 0x01U /* Delayed ACK. */ +#define TF_ACK_NOW 0x02U /* Immediate ACK. */ +#define TF_INFR 0x04U /* In fast recovery. */ +#define TF_TIMESTAMP 0x08U /* Timestamp option enabled */ +#define TF_RXCLOSED 0x10U /* rx closed by tcp_shutdown */ +#define TF_FIN 0x20U /* Connection was closed locally (FIN segment enqueued). */ +#define TF_NODELAY 0x40U /* Disable Nagle algorithm */ +#define TF_NAGLEMEMERR 0x80U /* nagle enabled, memerr, try to output to prevent delayed ACK to happen */ +#if LWIP_WND_SCALE +#define TF_WND_SCALE 0x0100U /* Window Scale option enabled */ +#endif + + /* the rest of the fields are in host byte order + as we have to do some math with them */ + + /* Timers */ + u8_t polltmr, pollinterval; + u8_t last_timer; + u32_t tmr; + + /* receiver variables */ + u32_t rcv_nxt; /* next seqno expected */ + tcpwnd_size_t rcv_wnd; /* receiver window available */ + tcpwnd_size_t rcv_ann_wnd; /* receiver window to announce */ + u32_t rcv_ann_right_edge; /* announced right edge of window */ + + /* Retransmission timer. */ + s16_t rtime; + + u16_t mss; /* maximum segment size */ + + /* RTT (round trip time) estimation variables */ + u32_t rttest; /* RTT estimate in 500ms ticks */ + u32_t rtseq; /* sequence number being timed */ + s16_t sa, sv; /* @todo document this */ + + s16_t rto; /* retransmission time-out */ + u8_t nrtx; /* number of retransmissions */ + + /* fast retransmit/recovery */ + u8_t dupacks; + u32_t lastack; /* Highest acknowledged seqno. */ + + /* congestion avoidance/control variables */ + tcpwnd_size_t cwnd; + tcpwnd_size_t ssthresh; + + /* sender variables */ + u32_t snd_nxt; /* next new seqno to be sent */ + u32_t snd_wl1, snd_wl2; /* Sequence and acknowledgement numbers of last + window update. */ + u32_t snd_lbb; /* Sequence number of next byte to be buffered. */ + tcpwnd_size_t snd_wnd; /* sender window */ + tcpwnd_size_t snd_wnd_max; /* the maximum sender window announced by the remote host */ + + tcpwnd_size_t acked; + + tcpwnd_size_t snd_buf; /* Available buffer space for sending (in bytes). */ +#define TCP_SNDQUEUELEN_OVERFLOW (0xffffU-3) + u16_t snd_queuelen; /* Number of pbufs currently in the send buffer. */ + +#if TCP_OVERSIZE + /* Extra bytes available at the end of the last pbuf in unsent. */ + u16_t unsent_oversize; +#endif /* TCP_OVERSIZE */ + + /* These are ordered by sequence number: */ + struct tcp_seg *unsent; /* Unsent (queued) segments. */ + struct tcp_seg *unacked; /* Sent but unacknowledged segments. */ +#if TCP_QUEUE_OOSEQ + struct tcp_seg *ooseq; /* Received out of sequence segments. */ +#endif /* TCP_QUEUE_OOSEQ */ + + struct pbuf *refused_data; /* Data previously received but not yet taken by upper layer */ + +#if LWIP_CALLBACK_API + /* Function to be called when more send buffer space is available. */ + tcp_sent_fn sent; + /* Function to be called when (in-sequence) data has arrived. */ + tcp_recv_fn recv; + /* Function to be called when a connection has been set up. */ + tcp_connected_fn connected; + /* Function which is called periodically. */ + tcp_poll_fn poll; + /* Function to be called whenever a fatal error occurs. */ + tcp_err_fn errf; +#endif /* LWIP_CALLBACK_API */ + +#if LWIP_TCP_TIMESTAMPS + u32_t ts_lastacksent; + u32_t ts_recent; +#endif /* LWIP_TCP_TIMESTAMPS */ + + /* idle time before KEEPALIVE is sent */ + u32_t keep_idle; +#if LWIP_TCP_KEEPALIVE + u32_t keep_intvl; + u32_t keep_cnt; +#endif /* LWIP_TCP_KEEPALIVE */ + + /* Persist timer counter */ + u8_t persist_cnt; + /* Persist timer back-off */ + u8_t persist_backoff; + + /* KEEPALIVE counter */ + u8_t keep_cnt_sent; + +#if LWIP_WND_SCALE + u8_t snd_scale; + u8_t rcv_scale; +#endif +}; + +struct tcp_pcb_listen { +/* Common members of all PCB types */ + IP_PCB; +/* Protocol specific PCB members */ + TCP_PCB_COMMON(struct tcp_pcb_listen); + +#if TCP_LISTEN_BACKLOG + u8_t backlog; + u8_t accepts_pending; +#endif /* TCP_LISTEN_BACKLOG */ +}; + +#if LWIP_EVENT_API + +enum lwip_event { + LWIP_EVENT_ACCEPT, + LWIP_EVENT_SENT, + LWIP_EVENT_RECV, + LWIP_EVENT_CONNECTED, + LWIP_EVENT_POLL, + LWIP_EVENT_ERR +}; + +err_t lwip_tcp_event(void *arg, struct tcp_pcb *pcb, + enum lwip_event, + struct pbuf *p, + u16_t size, + err_t err); + +#endif /* LWIP_EVENT_API */ + +/* Application program's interface: */ +struct tcp_pcb * tcp_new (void); +struct tcp_pcb * tcp_new_ip_type (u8_t type); + +void tcp_arg (struct tcp_pcb *pcb, void *arg); +void tcp_accept (struct tcp_pcb *pcb, tcp_accept_fn accept); +void tcp_recv (struct tcp_pcb *pcb, tcp_recv_fn recv); +void tcp_sent (struct tcp_pcb *pcb, tcp_sent_fn sent); +void tcp_poll (struct tcp_pcb *pcb, tcp_poll_fn poll, u8_t interval); +void tcp_err (struct tcp_pcb *pcb, tcp_err_fn err); + +#define tcp_mss(pcb) (((pcb)->flags & TF_TIMESTAMP) ? ((pcb)->mss - 12) : (pcb)->mss) +#define tcp_sndbuf(pcb) (TCPWND16((pcb)->snd_buf)) +#define tcp_sndqueuelen(pcb) ((pcb)->snd_queuelen) +#define tcp_nagle_disable(pcb) ((pcb)->flags |= TF_NODELAY) +#define tcp_nagle_enable(pcb) ((pcb)->flags = (tcpflags_t)((pcb)->flags & ~TF_NODELAY)) +#define tcp_nagle_disabled(pcb) (((pcb)->flags & TF_NODELAY) != 0) + +#if TCP_LISTEN_BACKLOG +#define tcp_accepted(pcb) do { \ + LWIP_ASSERT("pcb->state == LISTEN (called for wrong pcb?)", pcb->state == LISTEN); \ + (((struct tcp_pcb_listen *)(pcb))->accepts_pending--); } while(0) +#define tcp_backlog_set(pcb, new_backlog) do { \ + LWIP_ASSERT("pcb->state == LISTEN (called for wrong pcb?)", (pcb)->state == LISTEN); \ + ((struct tcp_pcb_listen *)(pcb))->backlog = ((new_backlog) ? (new_backlog) : 1); } while(0) +#else /* TCP_LISTEN_BACKLOG */ +#define tcp_accepted(pcb) LWIP_ASSERT("pcb->state == LISTEN (called for wrong pcb?)", \ + (pcb)->state == LISTEN) +#endif /* TCP_LISTEN_BACKLOG */ + +void tcp_recved (struct tcp_pcb *pcb, u16_t len); +err_t tcp_bind (struct tcp_pcb *pcb, const ip_addr_t *ipaddr, + u16_t port); +err_t tcp_connect (struct tcp_pcb *pcb, const ip_addr_t *ipaddr, + u16_t port, tcp_connected_fn connected); + +struct tcp_pcb * tcp_listen_with_backlog(struct tcp_pcb *pcb, u8_t backlog); +#define tcp_listen(pcb) tcp_listen_with_backlog(pcb, TCP_DEFAULT_LISTEN_BACKLOG) + +void tcp_abort (struct tcp_pcb *pcb); +err_t tcp_close (struct tcp_pcb *pcb); +err_t tcp_shutdown(struct tcp_pcb *pcb, int shut_rx, int shut_tx); + +/* Flags for "apiflags" parameter in tcp_write */ +#define TCP_WRITE_FLAG_COPY 0x01 +#define TCP_WRITE_FLAG_MORE 0x02 + +err_t tcp_write (struct tcp_pcb *pcb, const void *dataptr, u16_t len, + u8_t apiflags); + +void tcp_setprio (struct tcp_pcb *pcb, u8_t prio); + +#define TCP_PRIO_MIN 1 +#define TCP_PRIO_NORMAL 64 +#define TCP_PRIO_MAX 127 + +err_t tcp_output (struct tcp_pcb *pcb); + + +const char* tcp_debug_state_str(enum tcp_state s); + +/* for compatibility with older implementation */ +#define tcp_new_ip6() tcp_new_ip_type(IPADDR_TYPE_V6) + +#ifdef __cplusplus +} +#endif + +#endif /* LWIP_TCP */ + +#endif /* LWIP_HDR_TCP_H */ diff --git a/components/lwip/include/lwip/lwip/tcpip.h b/components/lwip/include/lwip/lwip/tcpip.h new file mode 100755 index 0000000000..c1235865ae --- /dev/null +++ b/components/lwip/include/lwip/lwip/tcpip.h @@ -0,0 +1,85 @@ +/* + * Copyright (c) 2001-2004 Swedish Institute of Computer Science. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + * + */ +#ifndef LWIP_HDR_TCPIP_H +#define LWIP_HDR_TCPIP_H + +#include "lwip/opt.h" + +#if !NO_SYS /* don't build if not configured for use in lwipopts.h */ + +#include "lwip/err.h" +#include "lwip/timers.h" +#include "lwip/netif.h" + +#ifdef __cplusplus +extern "C" { +#endif + +struct pbuf; +struct netif; + +/** Function prototype for the init_done function passed to tcpip_init */ +typedef void (*tcpip_init_done_fn)(void *arg); +/** Function prototype for functions passed to tcpip_callback() */ +typedef void (*tcpip_callback_fn)(void *ctx); + +/* Forward declarations */ +struct tcpip_callback_msg; + +void tcpip_init(tcpip_init_done_fn tcpip_init_done, void *arg); + +err_t tcpip_inpkt(struct pbuf *p, struct netif *inp, netif_input_fn input_fn); +err_t tcpip_input(struct pbuf *p, struct netif *inp); + +err_t tcpip_callback_with_block(tcpip_callback_fn function, void *ctx, u8_t block); +#define tcpip_callback(f, ctx) tcpip_callback_with_block(f, ctx, 1) + +struct tcpip_callback_msg* tcpip_callbackmsg_new(tcpip_callback_fn function, void *ctx); +void tcpip_callbackmsg_delete(struct tcpip_callback_msg* msg); +err_t tcpip_trycallback(struct tcpip_callback_msg* msg); + +/* free pbufs or heap memory from another context without blocking */ +err_t pbuf_free_callback(struct pbuf *p); +err_t mem_free_callback(void *m); + +#if LWIP_TCPIP_TIMEOUT +err_t tcpip_timeout(u32_t msecs, sys_timeout_handler h, void *arg); +err_t tcpip_untimeout(sys_timeout_handler h, void *arg); +#endif /* LWIP_TCPIP_TIMEOUT */ + +#ifdef __cplusplus +} +#endif + +#endif /* !NO_SYS */ + +#endif /* LWIP_HDR_TCPIP_H */ diff --git a/components/lwip/include/lwip/lwip/timers.h b/components/lwip/include/lwip/lwip/timers.h new file mode 100755 index 0000000000..d735392dde --- /dev/null +++ b/components/lwip/include/lwip/lwip/timers.h @@ -0,0 +1,101 @@ +/* + * Copyright (c) 2001-2004 Swedish Institute of Computer Science. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + * Simon Goldschmidt + * + */ +#ifndef LWIP_HDR_TIMERS_H +#define LWIP_HDR_TIMERS_H + +#include "lwip/opt.h" + +/* Timers are not supported when NO_SYS==1 and NO_SYS_NO_TIMERS==1 */ +#define LWIP_TIMERS (!NO_SYS || (NO_SYS && !NO_SYS_NO_TIMERS)) + +#if LWIP_TIMERS + +#include "lwip/err.h" +#if !NO_SYS +#include "lwip/sys.h" +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +#ifndef LWIP_DEBUG_TIMERNAMES +#ifdef LWIP_DEBUG +#define LWIP_DEBUG_TIMERNAMES SYS_DEBUG +#else /* LWIP_DEBUG */ +#define LWIP_DEBUG_TIMERNAMES 0 +#endif /* LWIP_DEBUG*/ +#endif + +/** Function prototype for a timeout callback function. Register such a function + * using sys_timeout(). + * + * @param arg Additional argument to pass to the function - set up by sys_timeout() + */ +typedef void (* sys_timeout_handler)(void *arg); + +struct sys_timeo { + struct sys_timeo *next; + u32_t time; + sys_timeout_handler h; + void *arg; +#if LWIP_DEBUG_TIMERNAMES + const char* handler_name; +#endif /* LWIP_DEBUG_TIMERNAMES */ +}; + +void sys_timeouts_init(void); + +#if LWIP_DEBUG_TIMERNAMES +void sys_timeout_debug(u32_t msecs, sys_timeout_handler handler, void *arg, const char* handler_name); +#define sys_timeout(msecs, handler, arg) sys_timeout_debug(msecs, handler, arg, #handler) +#else /* LWIP_DEBUG_TIMERNAMES */ +void sys_timeout(u32_t msecs, sys_timeout_handler handler, void *arg); +#endif /* LWIP_DEBUG_TIMERNAMES */ + +void sys_untimeout(sys_timeout_handler handler, void *arg); +#if NO_SYS +void sys_check_timeouts(void); +void sys_restart_timeouts(void); +u32_t sys_timeouts_sleeptime(void); +#else /* NO_SYS */ +void sys_timeouts_mbox_fetch(sys_mbox_t *mbox, void **msg); +#endif /* NO_SYS */ + + +#ifdef __cplusplus +} +#endif + +#endif /* LWIP_TIMERS */ +#endif /* LWIP_HDR_TIMERS_H */ diff --git a/components/lwip/include/lwip/lwip/udp.h b/components/lwip/include/lwip/lwip/udp.h new file mode 100755 index 0000000000..a370d3f9b9 --- /dev/null +++ b/components/lwip/include/lwip/lwip/udp.h @@ -0,0 +1,194 @@ +/* + * Copyright (c) 2001-2004 Swedish Institute of Computer Science. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + * + */ +#ifndef LWIP_HDR_UDP_H +#define LWIP_HDR_UDP_H + +#include "lwip/opt.h" + +#if LWIP_UDP /* don't build if not configured for use in lwipopts.h */ + +#include "lwip/pbuf.h" +#include "lwip/netif.h" +#include "lwip/ip_addr.h" +#include "lwip/ip.h" +#include "lwip/ip6_addr.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#define UDP_HLEN 8 + +/* Fields are (of course) in network byte order. */ +#ifdef PACK_STRUCT_USE_INCLUDES +# include "arch/bpstruct.h" +#endif +PACK_STRUCT_BEGIN +struct udp_hdr { + PACK_STRUCT_FIELD(u16_t src); + PACK_STRUCT_FIELD(u16_t dest); /* src/dest UDP ports */ + PACK_STRUCT_FIELD(u16_t len); + PACK_STRUCT_FIELD(u16_t chksum); +} PACK_STRUCT_STRUCT; +PACK_STRUCT_END +#ifdef PACK_STRUCT_USE_INCLUDES +# include "arch/epstruct.h" +#endif + +#define UDP_FLAGS_NOCHKSUM 0x01U +#define UDP_FLAGS_UDPLITE 0x02U +#define UDP_FLAGS_CONNECTED 0x04U +#define UDP_FLAGS_MULTICAST_LOOP 0x08U + +struct udp_pcb; + +/** Function prototype for udp pcb receive callback functions + * addr and port are in same byte order as in the pcb + * The callback is responsible for freeing the pbuf + * if it's not used any more. + * + * ATTENTION: Be aware that 'addr' might point into the pbuf 'p' so freeing this pbuf + * can make 'addr' invalid, too. + * + * @param arg user supplied argument (udp_pcb.recv_arg) + * @param pcb the udp_pcb which received data + * @param p the packet buffer that was received + * @param addr the remote IP address from which the packet was received + * @param port the remote port from which the packet was received + */ +typedef void (*udp_recv_fn)(void *arg, struct udp_pcb *pcb, struct pbuf *p, + const ip_addr_t *addr, u16_t port); + +struct udp_pcb { +/* Common members of all PCB types */ + IP_PCB; + +/* Protocol specific PCB members */ + + struct udp_pcb *next; + + u8_t flags; + /** ports are in host byte order */ + u16_t local_port, remote_port; + +#if LWIP_MULTICAST_TX_OPTIONS + /** outgoing network interface for multicast packets */ + ip_addr_t multicast_ip; + /** TTL for outgoing multicast packets */ + u8_t mcast_ttl; +#endif /* LWIP_MULTICAST_TX_OPTIONS */ + +#if LWIP_UDPLITE + /** used for UDP_LITE only */ + u16_t chksum_len_rx, chksum_len_tx; +#endif /* LWIP_UDPLITE */ + + /** receive callback function */ + udp_recv_fn recv; + /** user-supplied argument for the recv callback */ + void *recv_arg; +}; +/* udp_pcbs export for external reference (e.g. SNMP agent) */ +extern struct udp_pcb *udp_pcbs; + +/* The following functions is the application layer interface to the + UDP code. */ +struct udp_pcb * udp_new (void); +struct udp_pcb * udp_new_ip_type(u8_t type); +void udp_remove (struct udp_pcb *pcb); +err_t udp_bind (struct udp_pcb *pcb, const ip_addr_t *ipaddr, + u16_t port); +err_t udp_connect (struct udp_pcb *pcb, const ip_addr_t *ipaddr, + u16_t port); +void udp_disconnect (struct udp_pcb *pcb); +void udp_recv (struct udp_pcb *pcb, udp_recv_fn recv, + void *recv_arg); +err_t udp_sendto_if (struct udp_pcb *pcb, struct pbuf *p, + const ip_addr_t *dst_ip, u16_t dst_port, + struct netif *netif); +err_t udp_sendto_if_src(struct udp_pcb *pcb, struct pbuf *p, + const ip_addr_t *dst_ip, u16_t dst_port, + struct netif *netif, const ip_addr_t *src_ip); +err_t udp_sendto (struct udp_pcb *pcb, struct pbuf *p, + const ip_addr_t *dst_ip, u16_t dst_port); +err_t udp_send (struct udp_pcb *pcb, struct pbuf *p); + +#if LWIP_CHECKSUM_ON_COPY && CHECKSUM_GEN_UDP +err_t udp_sendto_if_chksum(struct udp_pcb *pcb, struct pbuf *p, + const ip_addr_t *dst_ip, u16_t dst_port, + struct netif *netif, u8_t have_chksum, + u16_t chksum); +err_t udp_sendto_chksum(struct udp_pcb *pcb, struct pbuf *p, + const ip_addr_t *dst_ip, u16_t dst_port, + u8_t have_chksum, u16_t chksum); +err_t udp_send_chksum(struct udp_pcb *pcb, struct pbuf *p, + u8_t have_chksum, u16_t chksum); +err_t udp_sendto_if_src_chksum(struct udp_pcb *pcb, struct pbuf *p, + const ip_addr_t *dst_ip, u16_t dst_port, struct netif *netif, + u8_t have_chksum, u16_t chksum, const ip_addr_t *src_ip); +#endif /* LWIP_CHECKSUM_ON_COPY && CHECKSUM_GEN_UDP */ + +#define udp_flags(pcb) ((pcb)->flags) +#define udp_setflags(pcb, f) ((pcb)->flags = (f)) + +/* The following functions are the lower layer interface to UDP. */ +void udp_input (struct pbuf *p, struct netif *inp); + +void udp_init (void); + +/* for compatibility with older implementation */ +#define udp_new_ip6() udp_new_ip_type(IPADDR_TYPE_V6) + +#if LWIP_MULTICAST_TX_OPTIONS +#define udp_set_multicast_netif_addr(pcb, ip4addr) ip_addr_copy_from_ip4((pcb)->multicast_ip, *(ip4addr)) +#define udp_get_multicast_netif_addr(pcb) ip_2_ip4(&(pcb)->multicast_ip) +#define udp_set_multicast_ttl(pcb, value) do { (pcb)->mcast_ttl = value; } while(0) +#define udp_get_multicast_ttl(pcb) ((pcb)->mcast_ttl) +#endif /* LWIP_MULTICAST_TX_OPTIONS */ + +#if UDP_DEBUG +void udp_debug_print(struct udp_hdr *udphdr); +#else +#define udp_debug_print(udphdr) +#endif + +#if LWIP_IPV4 +void udp_netif_ipv4_addr_changed(const ip4_addr_t* old_addr, const ip4_addr_t* new_addr); +#endif /* LWIP_IPV4 */ + +#ifdef __cplusplus +} +#endif + +#endif /* LWIP_UDP */ + +#endif /* LWIP_HDR_UDP_H */ diff --git a/components/lwip/include/lwip/netif/etharp.h b/components/lwip/include/lwip/netif/etharp.h new file mode 100755 index 0000000000..e745dcc3ee --- /dev/null +++ b/components/lwip/include/lwip/netif/etharp.h @@ -0,0 +1,143 @@ +/* + * Copyright (c) 2001-2003 Swedish Institute of Computer Science. + * Copyright (c) 2003-2004 Leon Woestenberg + * Copyright (c) 2003-2004 Axon Digital Design B.V., The Netherlands. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + * + */ + +#ifndef LWIP_HDR_NETIF_ETHARP_H +#define LWIP_HDR_NETIF_ETHARP_H + +#include "lwip/opt.h" + +#if LWIP_ARP || LWIP_ETHERNET /* don't build if not configured for use in lwipopts.h */ + +#include "lwip/pbuf.h" +#include "lwip/ip4_addr.h" +#include "lwip/netif.h" +#include "lwip/ip4.h" +#include "netif/ethernet.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#if LWIP_IPV4 && LWIP_ARP /* don't build if not configured for use in lwipopts.h */ + +#ifndef ETHARP_HWADDR_LEN +#define ETHARP_HWADDR_LEN ETH_HWADDR_LEN +#endif + +#ifdef PACK_STRUCT_USE_INCLUDES +# include "arch/bpstruct.h" +#endif +PACK_STRUCT_BEGIN +/** the ARP message, see RFC 826 ("Packet format") */ +struct etharp_hdr { + PACK_STRUCT_FIELD(u16_t hwtype); + PACK_STRUCT_FIELD(u16_t proto); + PACK_STRUCT_FLD_8(u8_t hwlen); + PACK_STRUCT_FLD_8(u8_t protolen); + PACK_STRUCT_FIELD(u16_t opcode); + PACK_STRUCT_FLD_S(struct eth_addr shwaddr); + PACK_STRUCT_FLD_S(struct ip4_addr2 sipaddr); + PACK_STRUCT_FLD_S(struct eth_addr dhwaddr); + PACK_STRUCT_FLD_S(struct ip4_addr2 dipaddr); +} PACK_STRUCT_STRUCT; +PACK_STRUCT_END +#ifdef PACK_STRUCT_USE_INCLUDES +# include "arch/epstruct.h" +#endif + +#define SIZEOF_ETHARP_HDR 28 + +#define SIZEOF_ETHARP_PACKET (SIZEOF_ETH_HDR + SIZEOF_ETHARP_HDR) +#if ETHARP_SUPPORT_VLAN && defined(LWIP_HOOK_VLAN_SET) +#define SIZEOF_ETHARP_PACKET_TX (SIZEOF_ETHARP_PACKET + SIZEOF_VLAN_HDR) +#else /* ETHARP_SUPPORT_VLAN && defined(LWIP_HOOK_VLAN_SET) */ +#define SIZEOF_ETHARP_PACKET_TX SIZEOF_ETHARP_PACKET +#endif /* ETHARP_SUPPORT_VLAN && defined(LWIP_HOOK_VLAN_SET) */ + +/** 1 seconds period */ +#define ARP_TMR_INTERVAL 1000 + +/** ARP message types (opcodes) */ +#define ARP_REQUEST 1 +#define ARP_REPLY 2 + +#if ARP_QUEUEING +/** struct for queueing outgoing packets for unknown address + * defined here to be accessed by memp.h + */ +struct etharp_q_entry { + struct etharp_q_entry *next; + struct pbuf *p; +}; +#endif /* ARP_QUEUEING */ + +#define etharp_init() /* Compatibility define, no init needed. */ +void etharp_tmr(void); +s8_t etharp_find_addr(struct netif *netif, const ip4_addr_t *ipaddr, + struct eth_addr **eth_ret, const ip4_addr_t **ip_ret); +u8_t etharp_get_entry(u8_t i, ip4_addr_t **ipaddr, struct netif **netif, struct eth_addr **eth_ret); +err_t etharp_output(struct netif *netif, struct pbuf *q, const ip4_addr_t *ipaddr); +err_t etharp_query(struct netif *netif, const ip4_addr_t *ipaddr, struct pbuf *q); +err_t etharp_request(struct netif *netif, const ip4_addr_t *ipaddr); +/** For Ethernet network interfaces, we might want to send "gratuitous ARP"; + * this is an ARP packet sent by a node in order to spontaneously cause other + * nodes to update an entry in their ARP cache. + * From RFC 3220 "IP Mobility Support for IPv4" section 4.6. */ +#define etharp_gratuitous(netif) etharp_request((netif), netif_ip4_addr(netif)) +void etharp_cleanup_netif(struct netif *netif); + +#if ETHARP_SUPPORT_STATIC_ENTRIES +err_t etharp_add_static_entry(const ip4_addr_t *ipaddr, struct eth_addr *ethaddr); +err_t etharp_remove_static_entry(const ip4_addr_t *ipaddr); +#endif /* ETHARP_SUPPORT_STATIC_ENTRIES */ + +#if LWIP_AUTOIP +err_t etharp_raw(struct netif *netif, const struct eth_addr *ethsrc_addr, + const struct eth_addr *ethdst_addr, + const struct eth_addr *hwsrc_addr, const ip4_addr_t *ipsrc_addr, + const struct eth_addr *hwdst_addr, const ip4_addr_t *ipdst_addr, + const u16_t opcode); +#endif /* LWIP_AUTOIP */ + +#endif /* LWIP_IPV4 && LWIP_ARP */ + +void etharp_arp_input(struct netif *netif, struct eth_addr *ethaddr, struct pbuf *p); + +#ifdef __cplusplus +} +#endif + +#endif /* LWIP_ARP || LWIP_ETHERNET */ + +#endif /* LWIP_HDR_NETIF_ETHARP_H */ diff --git a/components/lwip/include/lwip/netif/ethernet.h b/components/lwip/include/lwip/netif/ethernet.h new file mode 100755 index 0000000000..17623e4ad1 --- /dev/null +++ b/components/lwip/include/lwip/netif/ethernet.h @@ -0,0 +1,171 @@ +/* + * Copyright (c) 2001-2003 Swedish Institute of Computer Science. + * Copyright (c) 2003-2004 Leon Woestenberg + * Copyright (c) 2003-2004 Axon Digital Design B.V., The Netherlands. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + * + */ + +#ifndef LWIP_HDR_NETIF_ETHERNET_H +#define LWIP_HDR_NETIF_ETHERNET_H + +#include "lwip/opt.h" + +#include "lwip/pbuf.h" +#include "lwip/netif.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#ifndef ETH_HWADDR_LEN +#ifdef ETHARP_HWADDR_LEN +#define ETH_HWADDR_LEN ETHARP_HWADDR_LEN /* compatibility mode */ +#else +#define ETH_HWADDR_LEN 6 +#endif +#endif + +#ifdef PACK_STRUCT_USE_INCLUDES +# include "arch/bpstruct.h" +#endif +PACK_STRUCT_BEGIN +struct eth_addr { + PACK_STRUCT_FLD_8(u8_t addr[ETH_HWADDR_LEN]); +} PACK_STRUCT_STRUCT; +PACK_STRUCT_END +#ifdef PACK_STRUCT_USE_INCLUDES +# include "arch/epstruct.h" +#endif + +#ifdef PACK_STRUCT_USE_INCLUDES +# include "arch/bpstruct.h" +#endif +PACK_STRUCT_BEGIN +/** Ethernet header */ +struct eth_hdr { +#if ETH_PAD_SIZE + PACK_STRUCT_FLD_8(u8_t padding[ETH_PAD_SIZE]); +#endif + PACK_STRUCT_FLD_S(struct eth_addr dest); + PACK_STRUCT_FLD_S(struct eth_addr src); + PACK_STRUCT_FIELD(u16_t type); +} PACK_STRUCT_STRUCT; +PACK_STRUCT_END +#ifdef PACK_STRUCT_USE_INCLUDES +# include "arch/epstruct.h" +#endif + +#define SIZEOF_ETH_HDR (14 + ETH_PAD_SIZE) + +#if ETHARP_SUPPORT_VLAN + +#ifdef PACK_STRUCT_USE_INCLUDES +# include "arch/bpstruct.h" +#endif +PACK_STRUCT_BEGIN +/** VLAN header inserted between ethernet header and payload + * if 'type' in ethernet header is ETHTYPE_VLAN. + * See IEEE802.Q */ +struct eth_vlan_hdr { + PACK_STRUCT_FIELD(u16_t prio_vid); + PACK_STRUCT_FIELD(u16_t tpid); +} PACK_STRUCT_STRUCT; +PACK_STRUCT_END +#ifdef PACK_STRUCT_USE_INCLUDES +# include "arch/epstruct.h" +#endif + +#define SIZEOF_VLAN_HDR 4 +#define VLAN_ID(vlan_hdr) (htons((vlan_hdr)->prio_vid) & 0xFFF) + +#endif /* ETHARP_SUPPORT_VLAN */ + +/* A list of often ethtypes (although lwIP does not use all of them): */ +#define ETHTYPE_IP 0x0800U /* Internet protocol v4 */ +#define ETHTYPE_ARP 0x0806U /* Address resolution protocol */ +#define ETHTYPE_WOL 0x0842U /* Wake on lan */ +#define ETHTYPE_VLAN 0x8100U /* Virtual local area network */ +#define ETHTYPE_IPV6 0x86DDU /* Internet protocol v6 */ +#define ETHTYPE_PPPOEDISC 0x8863U /* PPP Over Ethernet Discovery Stage */ +#define ETHTYPE_PPPOE 0x8864U /* PPP Over Ethernet Session Stage */ +#define ETHTYPE_JUMBO 0x8870U /* Jumbo Frames */ +#define ETHTYPE_PROFINET 0x8892U /* Process field network */ +#define ETHTYPE_ETHERCAT 0x88A4U /* Ethernet for control automation technology */ +#define ETHTYPE_LLDP 0x88CCU /* Link layer discovery protocol */ +#define ETHTYPE_SERCOS 0x88CDU /* Serial real-time communication system */ +#define ETHTYPE_PTP 0x88F7U /* Precision time protocol */ +#define ETHTYPE_QINQ 0x9100U /* Q-in-Q, 802.1ad */ + +/** The 24-bit IANA IPv4-multicast OUI is 01-00-5e: */ +#define LL_IP4_MULTICAST_ADDR_0 0x01 +#define LL_IP4_MULTICAST_ADDR_1 0x00 +#define LL_IP4_MULTICAST_ADDR_2 0x5e + +/** IPv6 multicast uses this prefix */ +#define LL_IP6_MULTICAST_ADDR_0 0x33 +#define LL_IP6_MULTICAST_ADDR_1 0x33 + +/** MEMCPY-like macro to copy to/from struct eth_addr's that are local variables + * or known to be 32-bit aligned within the protocol header. */ +#ifndef ETHADDR32_COPY +#define ETHADDR32_COPY(dst, src) SMEMCPY(dst, src, ETH_HWADDR_LEN) +#endif + +/** MEMCPY-like macro to copy to/from struct eth_addr's that are no local + * variables and known to be 16-bit aligned within the protocol header. */ +#ifndef ETHADDR16_COPY +#define ETHADDR16_COPY(dst, src) SMEMCPY(dst, src, ETH_HWADDR_LEN) +#endif + +#if LWIP_ARP || LWIP_ETHERNET + +/** Define this to 1 and define LWIP_ARP_FILTER_NETIF_FN(pbuf, netif, type) + * to a filter function that returns the correct netif when using multiple + * netifs on one hardware interface where the netif's low-level receive + * routine cannot decide for the correct netif (e.g. when mapping multiple + * IP addresses to one hardware interface). + */ +#ifndef LWIP_ARP_FILTER_NETIF +#define LWIP_ARP_FILTER_NETIF 0 +#endif + +err_t ethernet_input(struct pbuf *p, struct netif *netif); + +#define eth_addr_cmp(addr1, addr2) (memcmp((addr1)->addr, (addr2)->addr, ETH_HWADDR_LEN) == 0) + +extern const struct eth_addr ethbroadcast, ethzero; + +#endif /* LWIP_ARP || LWIP_ETHERNET */ + +#ifdef __cplusplus +} +#endif + +#endif /* LWIP_HDR_NETIF_ETHERNET_H */ diff --git a/components/lwip/include/lwip/netif/lowpan6.h b/components/lwip/include/lwip/netif/lowpan6.h new file mode 100755 index 0000000000..2155293899 --- /dev/null +++ b/components/lwip/include/lwip/netif/lowpan6.h @@ -0,0 +1,84 @@ +/** + * @file + * + * 6LowPAN output for IPv6. Uses ND tables for link-layer addressing. Fragments packets to 6LowPAN units. + */ + +/* + * Copyright (c) 2015 Inico Technologies Ltd. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Ivan Delamer + * + * + * Please coordinate changes and requests with Ivan Delamer + * + */ + +#ifndef LWIP_HDR_LOWPAN6_H +#define LWIP_HDR_LOWPAN6_H + +#include "netif/lowpan6_opts.h" + +#if LWIP_IPV6 && LWIP_6LOWPAN /* don't build if not configured for use in lwipopts.h */ + +#include "lwip/pbuf.h" +#include "lwip/ip.h" +#include "lwip/ip_addr.h" +#include "lwip/netif.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** 1 second period */ +#define LOWPAN6_TMR_INTERVAL 1000 + +void lowpan6_tmr(void); + +err_t lowpan6_set_context(u8_t index, const ip6_addr_t * context); +err_t lowpan6_set_short_addr(u8_t addr_high, u8_t addr_low); + +#if LWIP_IPV4 +err_t lowpan4_output(struct netif *netif, struct pbuf *q, const ip4_addr_t *ipaddr); +#endif /* LWIP_IPV4 */ +err_t lowpan6_output(struct netif *netif, struct pbuf *q, const ip6_addr_t *ip6addr); +err_t lowpan6_input(struct pbuf * p, struct netif *netif); +err_t lowpan6_if_init(struct netif *netif); + +/* pan_id in network byte order. */ +err_t lowpan6_set_pan_id(u16_t pan_id); + +err_t tcpip_6lowpan_input(struct pbuf *p, struct netif *inp); + +#ifdef __cplusplus +} +#endif + +#endif /* LWIP_IPV6 && LWIP_6LOWPAN */ + +#endif /* LWIP_HDR_LOWPAN6_H */ diff --git a/components/lwip/include/lwip/netif/lowpan6_opts.h b/components/lwip/include/lwip/netif/lowpan6_opts.h new file mode 100755 index 0000000000..6a76957593 --- /dev/null +++ b/components/lwip/include/lwip/netif/lowpan6_opts.h @@ -0,0 +1,65 @@ +/* + * Copyright (c) 2015 Inico Technologies Ltd. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Ivan Delamer + * + * + * Please coordinate changes and requests with Ivan Delamer + * + */ + +#ifndef LWIP_HDR_LOWPAN6_OPTS_H +#define LWIP_HDR_LOWPAN6_OPTS_H + +#include "lwip/opt.h" + +#ifndef LWIP_6LOWPAN +#define LWIP_6LOWPAN 0 +#endif + +#ifndef LWIP_6LOWPAN_NUM_CONTEXTS +#define LWIP_6LOWPAN_NUM_CONTEXTS 10 +#endif + +#ifndef LWIP_6LOWPAN_INFER_SHORT_ADDRESS +#define LWIP_6LOWPAN_INFER_SHORT_ADDRESS 1 +#endif + +#ifndef LWIP_6LOWPAN_IPHC +#define LWIP_6LOWPAN_IPHC 1 +#endif + +#ifndef LWIP_6LOWPAN_HW_CRC +#define LWIP_6LOWPAN_HW_CRC 1 +#endif + +#ifndef LOWPAN6_DEBUG +#define LOWPAN6_DEBUG LWIP_DBG_OFF +#endif + +#endif /* LWIP_HDR_LOWPAN6_OPTS_H */ diff --git a/components/lwip/include/lwip/netif/ppp/ccp.h b/components/lwip/include/lwip/netif/ppp/ccp.h new file mode 100755 index 0000000000..a8eab9c0af --- /dev/null +++ b/components/lwip/include/lwip/netif/ppp/ccp.h @@ -0,0 +1,156 @@ +/* + * ccp.h - Definitions for PPP Compression Control Protocol. + * + * Copyright (c) 1994-2002 Paul Mackerras. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. The name(s) of the authors of this software must not be used to + * endorse or promote products derived from this software without + * prior written permission. + * + * 3. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by Paul Mackerras + * ". + * + * THE AUTHORS OF THIS SOFTWARE DISCLAIM ALL WARRANTIES WITH REGARD TO + * THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS, IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY + * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN + * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING + * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * $Id: ccp.h,v 1.12 2004/11/04 10:02:26 paulus Exp $ + */ + +#include "lwip/opt.h" +#if PPP_SUPPORT && CCP_SUPPORT /* don't build if not configured for use in lwipopts.h */ + +#ifndef CCP_H +#define CCP_H + +/* + * CCP codes. + */ + +#define CCP_CONFREQ 1 +#define CCP_CONFACK 2 +#define CCP_TERMREQ 5 +#define CCP_TERMACK 6 +#define CCP_RESETREQ 14 +#define CCP_RESETACK 15 + +/* + * Max # bytes for a CCP option + */ + +#define CCP_MAX_OPTION_LENGTH 32 + +/* + * Parts of a CCP packet. + */ + +#define CCP_CODE(dp) ((dp)[0]) +#define CCP_ID(dp) ((dp)[1]) +#define CCP_LENGTH(dp) (((dp)[2] << 8) + (dp)[3]) +#define CCP_HDRLEN 4 + +#define CCP_OPT_CODE(dp) ((dp)[0]) +#define CCP_OPT_LENGTH(dp) ((dp)[1]) +#define CCP_OPT_MINLEN 2 + +#if BSDCOMPRESS_SUPPORT +/* + * Definitions for BSD-Compress. + */ + +#define CI_BSD_COMPRESS 21 /* config. option for BSD-Compress */ +#define CILEN_BSD_COMPRESS 3 /* length of config. option */ + +/* Macros for handling the 3rd byte of the BSD-Compress config option. */ +#define BSD_NBITS(x) ((x) & 0x1F) /* number of bits requested */ +#define BSD_VERSION(x) ((x) >> 5) /* version of option format */ +#define BSD_CURRENT_VERSION 1 /* current version number */ +#define BSD_MAKE_OPT(v, n) (((v) << 5) | (n)) + +#define BSD_MIN_BITS 9 /* smallest code size supported */ +#define BSD_MAX_BITS 15 /* largest code size supported */ +#endif /* BSDCOMPRESS_SUPPORT */ + +#if DEFLATE_SUPPORT +/* + * Definitions for Deflate. + */ + +#define CI_DEFLATE 26 /* config option for Deflate */ +#define CI_DEFLATE_DRAFT 24 /* value used in original draft RFC */ +#define CILEN_DEFLATE 4 /* length of its config option */ + +#define DEFLATE_MIN_SIZE 9 +#define DEFLATE_MAX_SIZE 15 +#define DEFLATE_METHOD_VAL 8 +#define DEFLATE_SIZE(x) (((x) >> 4) + 8) +#define DEFLATE_METHOD(x) ((x) & 0x0F) +#define DEFLATE_MAKE_OPT(w) ((((w) - 8) << 4) + DEFLATE_METHOD_VAL) +#define DEFLATE_CHK_SEQUENCE 0 +#endif /* DEFLATE_SUPPORT */ + +#if MPPE_SUPPORT +/* + * Definitions for MPPE. + */ + +#define CI_MPPE 18 /* config option for MPPE */ +#define CILEN_MPPE 6 /* length of config option */ +#endif /* MPPE_SUPPORT */ + +#if PREDICTOR_SUPPORT +/* + * Definitions for other, as yet unsupported, compression methods. + */ + +#define CI_PREDICTOR_1 1 /* config option for Predictor-1 */ +#define CILEN_PREDICTOR_1 2 /* length of its config option */ +#define CI_PREDICTOR_2 2 /* config option for Predictor-2 */ +#define CILEN_PREDICTOR_2 2 /* length of its config option */ +#endif /* PREDICTOR_SUPPORT */ + +typedef struct ccp_options { +#if DEFLATE_SUPPORT + unsigned int deflate :1; /* do Deflate? */ + unsigned int deflate_correct :1; /* use correct code for deflate? */ + unsigned int deflate_draft :1; /* use draft RFC code for deflate? */ +#endif /* DEFLATE_SUPPORT */ +#if BSDCOMPRESS_SUPPORT + unsigned int bsd_compress :1; /* do BSD Compress? */ +#endif /* BSDCOMPRESS_SUPPORT */ +#if PREDICTOR_SUPPORT + unsigned int predictor_1 :1; /* do Predictor-1? */ + unsigned int predictor_2 :1; /* do Predictor-2? */ +#endif /* PREDICTOR_SUPPORT */ + +#if MPPE_SUPPORT + u8_t mppe; /* MPPE bitfield */ +#endif /* MPPE_SUPPORT */ +#if BSDCOMPRESS_SUPPORT + u_short bsd_bits; /* # bits/code for BSD Compress */ +#endif /* BSDCOMPRESS_SUPPORT */ +#if DEFLATE_SUPPORT + u_short deflate_size; /* lg(window size) for Deflate */ +#endif /* DEFLATE_SUPPORT */ + u8_t method; /* code for chosen compression method */ +} ccp_options; + +extern const struct protent ccp_protent; + +void ccp_resetrequest(ppp_pcb *pcb); /* Issue a reset-request. */ + +#endif /* CCP_H */ +#endif /* PPP_SUPPORT && CCP_SUPPORT */ diff --git a/components/lwip/include/lwip/netif/ppp/chap-md5.h b/components/lwip/include/lwip/netif/ppp/chap-md5.h new file mode 100755 index 0000000000..a05a157d06 --- /dev/null +++ b/components/lwip/include/lwip/netif/ppp/chap-md5.h @@ -0,0 +1,36 @@ +/* + * chap-md5.h - New CHAP/MD5 implementation. + * + * Copyright (c) 2003 Paul Mackerras. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. The name(s) of the authors of this software must not be used to + * endorse or promote products derived from this software without + * prior written permission. + * + * 3. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by Paul Mackerras + * ". + * + * THE AUTHORS OF THIS SOFTWARE DISCLAIM ALL WARRANTIES WITH REGARD TO + * THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS, IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY + * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN + * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING + * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include "lwip/opt.h" +#if PPP_SUPPORT && CHAP_SUPPORT /* don't build if not configured for use in lwipopts.h */ + +extern const struct chap_digest_type md5_digest; + +#endif /* PPP_SUPPORT && CHAP_SUPPORT */ diff --git a/components/lwip/include/lwip/netif/ppp/chap-new.h b/components/lwip/include/lwip/netif/ppp/chap-new.h new file mode 100755 index 0000000000..9b7c048757 --- /dev/null +++ b/components/lwip/include/lwip/netif/ppp/chap-new.h @@ -0,0 +1,192 @@ +/* + * chap-new.c - New CHAP implementation. + * + * Copyright (c) 2003 Paul Mackerras. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. The name(s) of the authors of this software must not be used to + * endorse or promote products derived from this software without + * prior written permission. + * + * 3. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by Paul Mackerras + * ". + * + * THE AUTHORS OF THIS SOFTWARE DISCLAIM ALL WARRANTIES WITH REGARD TO + * THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS, IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY + * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN + * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING + * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include "lwip/opt.h" +#if PPP_SUPPORT && CHAP_SUPPORT /* don't build if not configured for use in lwipopts.h */ + +#ifndef CHAP_H +#define CHAP_H + +#include "ppp.h" + +/* + * CHAP packets begin with a standard header with code, id, len (2 bytes). + */ +#define CHAP_HDRLEN 4 + +/* + * Values for the code field. + */ +#define CHAP_CHALLENGE 1 +#define CHAP_RESPONSE 2 +#define CHAP_SUCCESS 3 +#define CHAP_FAILURE 4 + +/* + * CHAP digest codes. + */ +#define CHAP_MD5 5 +#if MSCHAP_SUPPORT +#define CHAP_MICROSOFT 0x80 +#define CHAP_MICROSOFT_V2 0x81 +#endif /* MSCHAP_SUPPORT */ + +/* + * Semi-arbitrary limits on challenge and response fields. + */ +#define MAX_CHALLENGE_LEN 64 +#define MAX_RESPONSE_LEN 64 + +/* + * These limits apply to challenge and response packets we send. + * The +4 is the +1 that we actually need rounded up. + */ +#define CHAL_MAX_PKTLEN (PPP_HDRLEN + CHAP_HDRLEN + 4 + MAX_CHALLENGE_LEN + MAXNAMELEN) +#define RESP_MAX_PKTLEN (PPP_HDRLEN + CHAP_HDRLEN + 4 + MAX_RESPONSE_LEN + MAXNAMELEN) + +/* bitmask of supported algorithms */ +#if MSCHAP_SUPPORT +#define MDTYPE_MICROSOFT_V2 0x1 +#define MDTYPE_MICROSOFT 0x2 +#endif /* MSCHAP_SUPPORT */ +#define MDTYPE_MD5 0x4 +#define MDTYPE_NONE 0 + +#if MSCHAP_SUPPORT +/* Return the digest alg. ID for the most preferred digest type. */ +#define CHAP_DIGEST(mdtype) \ + ((mdtype) & MDTYPE_MD5)? CHAP_MD5: \ + ((mdtype) & MDTYPE_MICROSOFT_V2)? CHAP_MICROSOFT_V2: \ + ((mdtype) & MDTYPE_MICROSOFT)? CHAP_MICROSOFT: \ + 0 +#else /* !MSCHAP_SUPPORT */ +#define CHAP_DIGEST(mdtype) \ + ((mdtype) & MDTYPE_MD5)? CHAP_MD5: \ + 0 +#endif /* MSCHAP_SUPPORT */ + +/* Return the bit flag (lsb set) for our most preferred digest type. */ +#define CHAP_MDTYPE(mdtype) ((mdtype) ^ ((mdtype) - 1)) & (mdtype) + +/* Return the bit flag for a given digest algorithm ID. */ +#if MSCHAP_SUPPORT +#define CHAP_MDTYPE_D(digest) \ + ((digest) == CHAP_MICROSOFT_V2)? MDTYPE_MICROSOFT_V2: \ + ((digest) == CHAP_MICROSOFT)? MDTYPE_MICROSOFT: \ + ((digest) == CHAP_MD5)? MDTYPE_MD5: \ + 0 +#else /* !MSCHAP_SUPPORT */ +#define CHAP_MDTYPE_D(digest) \ + ((digest) == CHAP_MD5)? MDTYPE_MD5: \ + 0 +#endif /* MSCHAP_SUPPORT */ + +/* Can we do the requested digest? */ +#if MSCHAP_SUPPORT +#define CHAP_CANDIGEST(mdtype, digest) \ + ((digest) == CHAP_MICROSOFT_V2)? (mdtype) & MDTYPE_MICROSOFT_V2: \ + ((digest) == CHAP_MICROSOFT)? (mdtype) & MDTYPE_MICROSOFT: \ + ((digest) == CHAP_MD5)? (mdtype) & MDTYPE_MD5: \ + 0 +#else /* !MSCHAP_SUPPORT */ +#define CHAP_CANDIGEST(mdtype, digest) \ + ((digest) == CHAP_MD5)? (mdtype) & MDTYPE_MD5: \ + 0 +#endif /* MSCHAP_SUPPORT */ + +/* + * The code for each digest type has to supply one of these. + */ +struct chap_digest_type { + int code; + +#if PPP_SERVER + /* + * Note: challenge and response arguments below are formatted as + * a length byte followed by the actual challenge/response data. + */ + void (*generate_challenge)(ppp_pcb *pcb, unsigned char *challenge); + int (*verify_response)(ppp_pcb *pcb, int id, const char *name, + const unsigned char *secret, int secret_len, + const unsigned char *challenge, const unsigned char *response, + char *message, int message_space); +#endif /* PPP_SERVER */ + void (*make_response)(ppp_pcb *pcb, unsigned char *response, int id, const char *our_name, + const unsigned char *challenge, const char *secret, int secret_len, + unsigned char *priv); + int (*check_success)(ppp_pcb *pcb, unsigned char *pkt, int len, unsigned char *priv); + void (*handle_failure)(ppp_pcb *pcb, unsigned char *pkt, int len); +}; + +/* + * Each interface is described by chap structure. + */ +#if CHAP_SUPPORT +typedef struct chap_client_state { + u8_t flags; + const char *name; + const struct chap_digest_type *digest; + unsigned char priv[64]; /* private area for digest's use */ +} chap_client_state; + +#if PPP_SERVER +typedef struct chap_server_state { + u8_t flags; + u8_t id; + const char *name; + const struct chap_digest_type *digest; + int challenge_xmits; + int challenge_pktlen; + unsigned char challenge[CHAL_MAX_PKTLEN]; +} chap_server_state; +#endif /* PPP_SERVER */ +#endif /* CHAP_SUPPORT */ + +#if 0 /* UNUSED */ +/* Hook for a plugin to validate CHAP challenge */ +extern int (*chap_verify_hook)(char *name, char *ourname, int id, + const struct chap_digest_type *digest, + unsigned char *challenge, unsigned char *response, + char *message, int message_space); +#endif /* UNUSED */ + +#if PPP_SERVER +/* Called by authentication code to start authenticating the peer. */ +extern void chap_auth_peer(ppp_pcb *pcb, const char *our_name, int digest_code); +#endif /* PPP_SERVER */ + +/* Called by auth. code to start authenticating us to the peer. */ +extern void chap_auth_with_peer(ppp_pcb *pcb, const char *our_name, int digest_code); + +/* Represents the CHAP protocol to the main pppd code */ +extern const struct protent chap_protent; + +#endif /* CHAP_H */ +#endif /* PPP_SUPPORT && CHAP_SUPPORT */ diff --git a/components/lwip/include/lwip/netif/ppp/chap_ms.h b/components/lwip/include/lwip/netif/ppp/chap_ms.h new file mode 100755 index 0000000000..709bb89915 --- /dev/null +++ b/components/lwip/include/lwip/netif/ppp/chap_ms.h @@ -0,0 +1,44 @@ +/* + * chap_ms.h - Challenge Handshake Authentication Protocol definitions. + * + * Copyright (c) 1995 Eric Rosenquist. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. The name(s) of the authors of this software must not be used to + * endorse or promote products derived from this software without + * prior written permission. + * + * THE AUTHORS OF THIS SOFTWARE DISCLAIM ALL WARRANTIES WITH REGARD TO + * THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS, IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY + * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN + * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING + * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * $Id: chap_ms.h,v 1.13 2004/11/15 22:13:26 paulus Exp $ + */ + +#include "lwip/opt.h" +#if PPP_SUPPORT && MSCHAP_SUPPORT /* don't build if not configured for use in lwipopts.h */ + +#ifndef __CHAPMS_INCLUDE__ + +extern const struct chap_digest_type chapms_digest; +extern const struct chap_digest_type chapms2_digest; + +#define __CHAPMS_INCLUDE__ +#endif /* __CHAPMS_INCLUDE__ */ + +#endif /* PPP_SUPPORT && MSCHAP_SUPPORT */ diff --git a/components/lwip/include/lwip/netif/ppp/eap.h b/components/lwip/include/lwip/netif/ppp/eap.h new file mode 100755 index 0000000000..7dfd67636a --- /dev/null +++ b/components/lwip/include/lwip/netif/ppp/eap.h @@ -0,0 +1,169 @@ +/* + * eap.h - Extensible Authentication Protocol for PPP (RFC 2284) + * + * Copyright (c) 2001 by Sun Microsystems, Inc. + * All rights reserved. + * + * Non-exclusive rights to redistribute, modify, translate, and use + * this software in source and binary forms, in whole or in part, is + * hereby granted, provided that the above copyright notice is + * duplicated in any source form, and that neither the name of the + * copyright holder nor the author is used to endorse or promote + * products derived from this software. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED + * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. + * + * Original version by James Carlson + * + * $Id: eap.h,v 1.2 2003/06/11 23:56:26 paulus Exp $ + */ + +#include "lwip/opt.h" +#if PPP_SUPPORT && EAP_SUPPORT /* don't build if not configured for use in lwipopts.h */ + +#ifndef PPP_EAP_H +#define PPP_EAP_H + +#include "ppp.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/* + * Packet header = Code, id, length. + */ +#define EAP_HEADERLEN 4 + + +/* EAP message codes. */ +#define EAP_REQUEST 1 +#define EAP_RESPONSE 2 +#define EAP_SUCCESS 3 +#define EAP_FAILURE 4 + +/* EAP types */ +#define EAPT_IDENTITY 1 +#define EAPT_NOTIFICATION 2 +#define EAPT_NAK 3 /* (response only) */ +#define EAPT_MD5CHAP 4 +#define EAPT_OTP 5 /* One-Time Password; RFC 1938 */ +#define EAPT_TOKEN 6 /* Generic Token Card */ +/* 7 and 8 are unassigned. */ +#define EAPT_RSA 9 /* RSA Public Key Authentication */ +#define EAPT_DSS 10 /* DSS Unilateral */ +#define EAPT_KEA 11 /* KEA */ +#define EAPT_KEA_VALIDATE 12 /* KEA-VALIDATE */ +#define EAPT_TLS 13 /* EAP-TLS */ +#define EAPT_DEFENDER 14 /* Defender Token (AXENT) */ +#define EAPT_W2K 15 /* Windows 2000 EAP */ +#define EAPT_ARCOT 16 /* Arcot Systems */ +#define EAPT_CISCOWIRELESS 17 /* Cisco Wireless */ +#define EAPT_NOKIACARD 18 /* Nokia IP smart card */ +#define EAPT_SRP 19 /* Secure Remote Password */ +/* 20 is deprecated */ + +/* EAP SRP-SHA1 Subtypes */ +#define EAPSRP_CHALLENGE 1 /* Request 1 - Challenge */ +#define EAPSRP_CKEY 1 /* Response 1 - Client Key */ +#define EAPSRP_SKEY 2 /* Request 2 - Server Key */ +#define EAPSRP_CVALIDATOR 2 /* Response 2 - Client Validator */ +#define EAPSRP_SVALIDATOR 3 /* Request 3 - Server Validator */ +#define EAPSRP_ACK 3 /* Response 3 - final ack */ +#define EAPSRP_LWRECHALLENGE 4 /* Req/resp 4 - Lightweight rechal */ + +#define SRPVAL_EBIT 0x00000001 /* Use shared key for ECP */ + +#define SRP_PSEUDO_ID "pseudo_" +#define SRP_PSEUDO_LEN 7 + +#define MD5_SIGNATURE_SIZE 16 +#define EAP_MIN_CHALLENGE_LENGTH 17 +#define EAP_MAX_CHALLENGE_LENGTH 24 +#define EAP_MIN_MAX_POWER_OF_TWO_CHALLENGE_LENGTH 3 /* 2^3-1 = 7, 17+7 = 24 */ + +#define EAP_STATES \ + "Initial", "Pending", "Closed", "Listen", "Identify", \ + "SRP1", "SRP2", "SRP3", "MD5Chall", "Open", "SRP4", "BadAuth" + +#define eap_client_active(pcb) ((pcb)->eap.es_client.ea_state == eapListen) +#if PPP_SERVER +#define eap_server_active(pcb) \ + ((pcb)->eap.es_server.ea_state >= eapIdentify && \ + (pcb)->eap.es_server.ea_state <= eapMD5Chall) +#endif /* PPP_SERVER */ + +/* + * Complete EAP state for one PPP session. + */ +enum eap_state_code { + eapInitial = 0, /* No EAP authentication yet requested */ + eapPending, /* Waiting for LCP (no timer) */ + eapClosed, /* Authentication not in use */ + eapListen, /* Client ready (and timer running) */ + eapIdentify, /* EAP Identify sent */ + eapSRP1, /* Sent EAP SRP-SHA1 Subtype 1 */ + eapSRP2, /* Sent EAP SRP-SHA1 Subtype 2 */ + eapSRP3, /* Sent EAP SRP-SHA1 Subtype 3 */ + eapMD5Chall, /* Sent MD5-Challenge */ + eapOpen, /* Completed authentication */ + eapSRP4, /* Sent EAP SRP-SHA1 Subtype 4 */ + eapBadAuth /* Failed authentication */ +}; + +struct eap_auth { + const char *ea_name; /* Our name */ + char ea_peer[MAXNAMELEN +1]; /* Peer's name */ + void *ea_session; /* Authentication library linkage */ + u_char *ea_skey; /* Shared encryption key */ + u_short ea_namelen; /* Length of our name */ + u_short ea_peerlen; /* Length of peer's name */ + enum eap_state_code ea_state; + u_char ea_id; /* Current id */ + u_char ea_requests; /* Number of Requests sent/received */ + u_char ea_responses; /* Number of Responses */ + u_char ea_type; /* One of EAPT_* */ + u32_t ea_keyflags; /* SRP shared key usage flags */ +}; + +#ifndef EAP_MAX_CHALLENGE_LENGTH +#define EAP_MAX_CHALLENGE_LENGTH 24 +#endif +typedef struct eap_state { + struct eap_auth es_client; /* Client (authenticatee) data */ +#if PPP_SERVER + struct eap_auth es_server; /* Server (authenticator) data */ +#endif /* PPP_SERVER */ + int es_savedtime; /* Saved timeout */ + int es_rechallenge; /* EAP rechallenge interval */ + int es_lwrechallenge; /* SRP lightweight rechallenge inter */ + u8_t es_usepseudo; /* Use SRP Pseudonym if offered one */ + int es_usedpseudo; /* Set if we already sent PN */ + int es_challen; /* Length of challenge string */ + u_char es_challenge[EAP_MAX_CHALLENGE_LENGTH]; +} eap_state; + +/* + * Timeouts. + */ +#if 0 /* moved to opt.h */ +#define EAP_DEFTIMEOUT 3 /* Timeout (seconds) for rexmit */ +#define EAP_DEFTRANSMITS 10 /* max # times to transmit */ +#define EAP_DEFREQTIME 20 /* Time to wait for peer request */ +#define EAP_DEFALLOWREQ 20 /* max # times to accept requests */ +#endif /* moved to opt.h */ + +void eap_authwithpeer(ppp_pcb *pcb, const char *localname); +void eap_authpeer(ppp_pcb *pcb, const char *localname); + +extern const struct protent eap_protent; + +#ifdef __cplusplus +} +#endif + +#endif /* PPP_EAP_H */ + +#endif /* PPP_SUPPORT && EAP_SUPPORT */ diff --git a/components/lwip/include/lwip/netif/ppp/ecp.h b/components/lwip/include/lwip/netif/ppp/ecp.h new file mode 100755 index 0000000000..cba6678ed0 --- /dev/null +++ b/components/lwip/include/lwip/netif/ppp/ecp.h @@ -0,0 +1,50 @@ +/* + * ecp.h - Definitions for PPP Encryption Control Protocol. + * + * Copyright (c) 2002 Google, Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. The name(s) of the authors of this software must not be used to + * endorse or promote products derived from this software without + * prior written permission. + * + * THE AUTHORS OF THIS SOFTWARE DISCLAIM ALL WARRANTIES WITH REGARD TO + * THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS, IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY + * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN + * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING + * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * $Id: ecp.h,v 1.2 2003/01/10 07:12:36 fcusack Exp $ + */ + +#include "lwip/opt.h" +#if PPP_SUPPORT && ECP_SUPPORT /* don't build if not configured for use in lwipopts.h */ + +typedef struct ecp_options { + bool required; /* Is ECP required? */ + unsigned enctype; /* Encryption type */ +} ecp_options; + +extern fsm ecp_fsm[]; +extern ecp_options ecp_wantoptions[]; +extern ecp_options ecp_gotoptions[]; +extern ecp_options ecp_allowoptions[]; +extern ecp_options ecp_hisoptions[]; + +extern const struct protent ecp_protent; + +#endif /* PPP_SUPPORT && ECP_SUPPORT */ diff --git a/components/lwip/include/lwip/netif/ppp/eui64.h b/components/lwip/include/lwip/netif/ppp/eui64.h new file mode 100755 index 0000000000..dffb5e4150 --- /dev/null +++ b/components/lwip/include/lwip/netif/ppp/eui64.h @@ -0,0 +1,94 @@ +/* + * eui64.h - EUI64 routines for IPv6CP. + * + * Copyright (c) 1999 Tommi Komulainen. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. The name(s) of the authors of this software must not be used to + * endorse or promote products derived from this software without + * prior written permission. + * + * 4. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by Tommi Komulainen + * ". + * + * THE AUTHORS OF THIS SOFTWARE DISCLAIM ALL WARRANTIES WITH REGARD TO + * THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS, IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY + * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN + * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING + * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * $Id: eui64.h,v 1.6 2002/12/04 23:03:32 paulus Exp $ +*/ + +#include "lwip/opt.h" +#if PPP_SUPPORT && PPP_IPV6_SUPPORT /* don't build if not configured for use in lwipopts.h */ + +#ifndef __EUI64_H__ +#define __EUI64_H__ + +/* + * TODO: + * + * Maybe this should be done by processing struct in6_addr directly... + */ +typedef union +{ + u8_t e8[8]; + u16_t e16[4]; + u32_t e32[2]; +} eui64_t; + +#define eui64_iszero(e) (((e).e32[0] | (e).e32[1]) == 0) +#define eui64_equals(e, o) (((e).e32[0] == (o).e32[0]) && \ + ((e).e32[1] == (o).e32[1])) +#define eui64_zero(e) (e).e32[0] = (e).e32[1] = 0; + +#define eui64_copy(s, d) memcpy(&(d), &(s), sizeof(eui64_t)) + +#define eui64_magic(e) do { \ + (e).e32[0] = magic(); \ + (e).e32[1] = magic(); \ + (e).e8[0] &= ~2; \ + } while (0) +#define eui64_magic_nz(x) do { \ + eui64_magic(x); \ + } while (eui64_iszero(x)) +#define eui64_magic_ne(x, y) do { \ + eui64_magic(x); \ + } while (eui64_equals(x, y)) + +#define eui64_get(ll, cp) do { \ + eui64_copy((*cp), (ll)); \ + (cp) += sizeof(eui64_t); \ + } while (0) + +#define eui64_put(ll, cp) do { \ + eui64_copy((ll), (*cp)); \ + (cp) += sizeof(eui64_t); \ + } while (0) + +#define eui64_set32(e, l) do { \ + (e).e32[0] = 0; \ + (e).e32[1] = htonl(l); \ + } while (0) +#define eui64_setlo32(e, l) eui64_set32(e, l) + +char *eui64_ntoa(eui64_t); /* Returns ascii representation of id */ + +#endif /* __EUI64_H__ */ +#endif /* PPP_SUPPORT && PPP_IPV6_SUPPORT */ diff --git a/components/lwip/include/lwip/netif/ppp/fsm.h b/components/lwip/include/lwip/netif/ppp/fsm.h new file mode 100755 index 0000000000..fc0a4b1060 --- /dev/null +++ b/components/lwip/include/lwip/netif/ppp/fsm.h @@ -0,0 +1,175 @@ +/* + * fsm.h - {Link, IP} Control Protocol Finite State Machine definitions. + * + * Copyright (c) 1984-2000 Carnegie Mellon University. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. The name "Carnegie Mellon University" must not be used to + * endorse or promote products derived from this software without + * prior written permission. For permission or any legal + * details, please contact + * Office of Technology Transfer + * Carnegie Mellon University + * 5000 Forbes Avenue + * Pittsburgh, PA 15213-3890 + * (412) 268-4387, fax: (412) 268-7395 + * tech-transfer@andrew.cmu.edu + * + * 4. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by Computing Services + * at Carnegie Mellon University (http://www.cmu.edu/computing/)." + * + * CARNEGIE MELLON UNIVERSITY DISCLAIMS ALL WARRANTIES WITH REGARD TO + * THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS, IN NO EVENT SHALL CARNEGIE MELLON UNIVERSITY BE LIABLE + * FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN + * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING + * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * $Id: fsm.h,v 1.10 2004/11/13 02:28:15 paulus Exp $ + */ + +#include "lwip/opt.h" +#if PPP_SUPPORT /* don't build if not configured for use in lwipopts.h */ + +#ifndef FSM_H +#define FSM_H + +#include "ppp.h" + +/* + * Packet header = Code, id, length. + */ +#define HEADERLEN 4 + + +/* + * CP (LCP, IPCP, etc.) codes. + */ +#define CONFREQ 1 /* Configuration Request */ +#define CONFACK 2 /* Configuration Ack */ +#define CONFNAK 3 /* Configuration Nak */ +#define CONFREJ 4 /* Configuration Reject */ +#define TERMREQ 5 /* Termination Request */ +#define TERMACK 6 /* Termination Ack */ +#define CODEREJ 7 /* Code Reject */ + + +/* + * Each FSM is described by an fsm structure and fsm callbacks. + */ +typedef struct fsm { + ppp_pcb *pcb; /* PPP Interface */ + const struct fsm_callbacks *callbacks; /* Callback routines */ + const char *term_reason; /* Reason for closing protocol */ + u8_t seen_ack; /* Have received valid Ack/Nak/Rej to Req */ + /* -- This is our only flag, we might use u_int :1 if we have more flags */ + u16_t protocol; /* Data Link Layer Protocol field value */ + u8_t state; /* State */ + u8_t flags; /* Contains option bits */ + u8_t id; /* Current id */ + u8_t reqid; /* Current request id */ + u8_t retransmits; /* Number of retransmissions left */ + u8_t nakloops; /* Number of nak loops since last ack */ + u8_t rnakloops; /* Number of naks received */ + u8_t maxnakloops; /* Maximum number of nak loops tolerated + (necessary because IPCP require a custom large max nak loops value) */ + u8_t term_reason_len; /* Length of term_reason */ +} fsm; + + +typedef struct fsm_callbacks { + void (*resetci) /* Reset our Configuration Information */ + (fsm *); + int (*cilen) /* Length of our Configuration Information */ + (fsm *); + void (*addci) /* Add our Configuration Information */ + (fsm *, u_char *, int *); + int (*ackci) /* ACK our Configuration Information */ + (fsm *, u_char *, int); + int (*nakci) /* NAK our Configuration Information */ + (fsm *, u_char *, int, int); + int (*rejci) /* Reject our Configuration Information */ + (fsm *, u_char *, int); + int (*reqci) /* Request peer's Configuration Information */ + (fsm *, u_char *, int *, int); + void (*up) /* Called when fsm reaches PPP_FSM_OPENED state */ + (fsm *); + void (*down) /* Called when fsm leaves PPP_FSM_OPENED state */ + (fsm *); + void (*starting) /* Called when we want the lower layer */ + (fsm *); + void (*finished) /* Called when we don't want the lower layer */ + (fsm *); + void (*protreject) /* Called when Protocol-Reject received */ + (int); + void (*retransmit) /* Retransmission is necessary */ + (fsm *); + int (*extcode) /* Called when unknown code received */ + (fsm *, int, int, u_char *, int); + const char *proto_name; /* String name for protocol (for messages) */ +} fsm_callbacks; + + +/* + * Link states. + */ +#define PPP_FSM_INITIAL 0 /* Down, hasn't been opened */ +#define PPP_FSM_STARTING 1 /* Down, been opened */ +#define PPP_FSM_CLOSED 2 /* Up, hasn't been opened */ +#define PPP_FSM_STOPPED 3 /* Open, waiting for down event */ +#define PPP_FSM_CLOSING 4 /* Terminating the connection, not open */ +#define PPP_FSM_STOPPING 5 /* Terminating, but open */ +#define PPP_FSM_REQSENT 6 /* We've sent a Config Request */ +#define PPP_FSM_ACKRCVD 7 /* We've received a Config Ack */ +#define PPP_FSM_ACKSENT 8 /* We've sent a Config Ack */ +#define PPP_FSM_OPENED 9 /* Connection available */ + + +/* + * Flags - indicate options controlling FSM operation + */ +#define OPT_PASSIVE 1 /* Don't die if we don't get a response */ +#define OPT_RESTART 2 /* Treat 2nd OPEN as DOWN, UP */ +#define OPT_SILENT 4 /* Wait for peer to speak first */ + + +/* + * Timeouts. + */ +#if 0 /* moved to opt.h */ +#define DEFTIMEOUT 3 /* Timeout time in seconds */ +#define DEFMAXTERMREQS 2 /* Maximum Terminate-Request transmissions */ +#define DEFMAXCONFREQS 10 /* Maximum Configure-Request transmissions */ +#define DEFMAXNAKLOOPS 5 /* Maximum number of nak loops */ +#endif /* moved to opt.h */ + + +/* + * Prototypes + */ +void fsm_init(fsm *f); +void fsm_lowerup(fsm *f); +void fsm_lowerdown(fsm *f); +void fsm_open(fsm *f); +void fsm_close(fsm *f, const char *reason); +void fsm_input(fsm *f, u_char *inpacket, int l); +void fsm_protreject(fsm *f); +void fsm_sdata(fsm *f, u_char code, u_char id, const u_char *data, int datalen); + + +#endif /* FSM_H */ +#endif /* PPP_SUPPORT */ diff --git a/components/lwip/include/lwip/netif/ppp/ipcp.h b/components/lwip/include/lwip/netif/ppp/ipcp.h new file mode 100755 index 0000000000..298f8dc66c --- /dev/null +++ b/components/lwip/include/lwip/netif/ppp/ipcp.h @@ -0,0 +1,126 @@ +/* + * ipcp.h - IP Control Protocol definitions. + * + * Copyright (c) 1984-2000 Carnegie Mellon University. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. The name "Carnegie Mellon University" must not be used to + * endorse or promote products derived from this software without + * prior written permission. For permission or any legal + * details, please contact + * Office of Technology Transfer + * Carnegie Mellon University + * 5000 Forbes Avenue + * Pittsburgh, PA 15213-3890 + * (412) 268-4387, fax: (412) 268-7395 + * tech-transfer@andrew.cmu.edu + * + * 4. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by Computing Services + * at Carnegie Mellon University (http://www.cmu.edu/computing/)." + * + * CARNEGIE MELLON UNIVERSITY DISCLAIMS ALL WARRANTIES WITH REGARD TO + * THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS, IN NO EVENT SHALL CARNEGIE MELLON UNIVERSITY BE LIABLE + * FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN + * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING + * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * $Id: ipcp.h,v 1.14 2002/12/04 23:03:32 paulus Exp $ + */ + +#include "lwip/opt.h" +#if PPP_SUPPORT && PPP_IPV4_SUPPORT /* don't build if not configured for use in lwipopts.h */ + +#ifndef IPCP_H +#define IPCP_H + +/* + * Options. + */ +#define CI_ADDRS 1 /* IP Addresses */ +#if VJ_SUPPORT +#define CI_COMPRESSTYPE 2 /* Compression Type */ +#endif /* VJ_SUPPORT */ +#define CI_ADDR 3 + +#if LWIP_DNS +#define CI_MS_DNS1 129 /* Primary DNS value */ +#define CI_MS_DNS2 131 /* Secondary DNS value */ +#endif /* LWIP_DNS */ +#if 0 /* UNUSED - WINS */ +#define CI_MS_WINS1 130 /* Primary WINS value */ +#define CI_MS_WINS2 132 /* Secondary WINS value */ +#endif /* UNUSED - WINS */ + +#if VJ_SUPPORT +#define MAX_STATES 16 /* from slcompress.h */ + +#define IPCP_VJMODE_OLD 1 /* "old" mode (option # = 0x0037) */ +#define IPCP_VJMODE_RFC1172 2 /* "old-rfc"mode (option # = 0x002d) */ +#define IPCP_VJMODE_RFC1332 3 /* "new-rfc"mode (option # = 0x002d, */ + /* maxslot and slot number compression) */ + +#define IPCP_VJ_COMP 0x002d /* current value for VJ compression option*/ +#define IPCP_VJ_COMP_OLD 0x0037 /* "old" (i.e, broken) value for VJ */ + /* compression option*/ +#endif /* VJ_SUPPORT */ + +typedef struct ipcp_options { + unsigned int neg_addr :1; /* Negotiate IP Address? */ + unsigned int old_addrs :1; /* Use old (IP-Addresses) option? */ + unsigned int req_addr :1; /* Ask peer to send IP address? */ +#if 0 /* UNUSED */ + unsigned int default_route :1; /* Assign default route through interface? */ + unsigned int replace_default_route :1; /* Replace default route through interface? */ +#endif /* UNUSED */ +#if 0 /* UNUSED - PROXY ARP */ + unsigned int proxy_arp :1; /* Make proxy ARP entry for peer? */ +#endif /* UNUSED - PROXY ARP */ +#if VJ_SUPPORT + unsigned int neg_vj :1; /* Van Jacobson Compression? */ + unsigned int old_vj :1; /* use old (short) form of VJ option? */ + unsigned int cflag :1; +#endif /* VJ_SUPPORT */ + unsigned int accept_local :1; /* accept peer's value for ouraddr */ + unsigned int accept_remote :1; /* accept peer's value for hisaddr */ +#if LWIP_DNS + unsigned int req_dns1 :1; /* Ask peer to send primary DNS address? */ + unsigned int req_dns2 :1; /* Ask peer to send secondary DNS address? */ +#endif /* LWIP_DNS */ + + u32_t ouraddr, hisaddr; /* Addresses in NETWORK BYTE ORDER */ +#if LWIP_DNS + u32_t dnsaddr[2]; /* Primary and secondary MS DNS entries */ +#endif /* LWIP_DNS */ +#if 0 /* UNUSED - WINS */ + u32_t winsaddr[2]; /* Primary and secondary MS WINS entries */ +#endif /* UNUSED - WINS */ + +#if VJ_SUPPORT + u16_t vj_protocol; /* protocol value to use in VJ option */ + u8_t maxslotindex; /* values for RFC1332 VJ compression neg. */ +#endif /* VJ_SUPPORT */ +} ipcp_options; + +#if 0 /* UNUSED, already defined by lwIP */ +char *ip_ntoa (u32_t); +#endif /* UNUSED, already defined by lwIP */ + +extern const struct protent ipcp_protent; + +#endif /* IPCP_H */ +#endif /* PPP_SUPPORT && PPP_IPV4_SUPPORT */ diff --git a/components/lwip/include/lwip/netif/ppp/ipv6cp.h b/components/lwip/include/lwip/netif/ppp/ipv6cp.h new file mode 100755 index 0000000000..540a7d180a --- /dev/null +++ b/components/lwip/include/lwip/netif/ppp/ipv6cp.h @@ -0,0 +1,183 @@ +/* + * ipv6cp.h - PPP IPV6 Control Protocol. + * + * Copyright (c) 1999 Tommi Komulainen. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. The name(s) of the authors of this software must not be used to + * endorse or promote products derived from this software without + * prior written permission. + * + * 4. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by Tommi Komulainen + * ". + * + * THE AUTHORS OF THIS SOFTWARE DISCLAIM ALL WARRANTIES WITH REGARD TO + * THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS, IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY + * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN + * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING + * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + */ + +/* Original version, based on RFC2023 : + + Copyright (c) 1995, 1996, 1997 Francis.Dupont@inria.fr, INRIA Rocquencourt, + Alain.Durand@imag.fr, IMAG, + Jean-Luc.Richier@imag.fr, IMAG-LSR. + + Copyright (c) 1998, 1999 Francis.Dupont@inria.fr, GIE DYADE, + Alain.Durand@imag.fr, IMAG, + Jean-Luc.Richier@imag.fr, IMAG-LSR. + + Ce travail a été fait au sein du GIE DYADE (Groupement d'Intérêt + Économique ayant pour membres BULL S.A. et l'INRIA). + + Ce logiciel informatique est disponible aux conditions + usuelles dans la recherche, c'est-à-dire qu'il peut + être utilisé, copié, modifié, distribué à l'unique + condition que ce texte soit conservé afin que + l'origine de ce logiciel soit reconnue. + + Le nom de l'Institut National de Recherche en Informatique + et en Automatique (INRIA), de l'IMAG, ou d'une personne morale + ou physique ayant participé à l'élaboration de ce logiciel ne peut + être utilisé sans son accord préalable explicite. + + Ce logiciel est fourni tel quel sans aucune garantie, + support ou responsabilité d'aucune sorte. + Ce logiciel est dérivé de sources d'origine + "University of California at Berkeley" et + "Digital Equipment Corporation" couvertes par des copyrights. + + L'Institut d'Informatique et de Mathématiques Appliquées de Grenoble (IMAG) + est une fédération d'unités mixtes de recherche du CNRS, de l'Institut National + Polytechnique de Grenoble et de l'Université Joseph Fourier regroupant + sept laboratoires dont le laboratoire Logiciels, Systèmes, Réseaux (LSR). + + This work has been done in the context of GIE DYADE (joint R & D venture + between BULL S.A. and INRIA). + + This software is available with usual "research" terms + with the aim of retain credits of the software. + Permission to use, copy, modify and distribute this software for any + purpose and without fee is hereby granted, provided that the above + copyright notice and this permission notice appear in all copies, + and the name of INRIA, IMAG, or any contributor not be used in advertising + or publicity pertaining to this material without the prior explicit + permission. The software is provided "as is" without any + warranties, support or liabilities of any kind. + This software is derived from source code from + "University of California at Berkeley" and + "Digital Equipment Corporation" protected by copyrights. + + Grenoble's Institute of Computer Science and Applied Mathematics (IMAG) + is a federation of seven research units funded by the CNRS, National + Polytechnic Institute of Grenoble and University Joseph Fourier. + The research unit in Software, Systems, Networks (LSR) is member of IMAG. +*/ + +/* + * Derived from : + * + * + * ipcp.h - IP Control Protocol definitions. + * + * Copyright (c) 1984-2000 Carnegie Mellon University. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. The name "Carnegie Mellon University" must not be used to + * endorse or promote products derived from this software without + * prior written permission. For permission or any legal + * details, please contact + * Office of Technology Transfer + * Carnegie Mellon University + * 5000 Forbes Avenue + * Pittsburgh, PA 15213-3890 + * (412) 268-4387, fax: (412) 268-7395 + * tech-transfer@andrew.cmu.edu + * + * 4. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by Computing Services + * at Carnegie Mellon University (http://www.cmu.edu/computing/)." + * + * CARNEGIE MELLON UNIVERSITY DISCLAIMS ALL WARRANTIES WITH REGARD TO + * THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS, IN NO EVENT SHALL CARNEGIE MELLON UNIVERSITY BE LIABLE + * FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN + * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING + * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * $Id: ipv6cp.h,v 1.7 2002/12/04 23:03:32 paulus Exp $ + */ + +#include "lwip/opt.h" +#if PPP_SUPPORT && PPP_IPV6_SUPPORT /* don't build if not configured for use in lwipopts.h */ + +#ifndef IPV6CP_H +#define IPV6CP_H + +#include "eui64.h" + +/* + * Options. + */ +#define CI_IFACEID 1 /* Interface Identifier */ +#ifdef IPV6CP_COMP +#define CI_COMPRESSTYPE 2 /* Compression Type */ +#endif /* IPV6CP_COMP */ + +/* No compression types yet defined. + *#define IPV6CP_COMP 0x004f + */ +typedef struct ipv6cp_options { + unsigned int neg_ifaceid :1; /* Negotiate interface identifier? */ + unsigned int req_ifaceid :1; /* Ask peer to send interface identifier? */ + unsigned int accept_local :1; /* accept peer's value for iface id? */ + unsigned int opt_local :1; /* ourtoken set by option */ + unsigned int opt_remote :1; /* histoken set by option */ + unsigned int use_ip :1; /* use IP as interface identifier */ +#if 0 + unsigned int use_persistent :1; /* use uniquely persistent value for address */ +#endif +#ifdef IPV6CP_COMP + unsigned int neg_vj :1; /* Van Jacobson Compression? */ +#endif /* IPV6CP_COMP */ + +#ifdef IPV6CP_COMP + u_short vj_protocol; /* protocol value to use in VJ option */ +#endif /* IPV6CP_COMP */ + eui64_t ourid, hisid; /* Interface identifiers */ +} ipv6cp_options; + +extern const struct protent ipv6cp_protent; + +#endif /* IPV6CP_H */ +#endif /* PPP_SUPPORT && PPP_IPV6_SUPPORT */ diff --git a/components/lwip/include/lwip/netif/ppp/lcp.h b/components/lwip/include/lwip/netif/ppp/lcp.h new file mode 100755 index 0000000000..04970699ac --- /dev/null +++ b/components/lwip/include/lwip/netif/ppp/lcp.h @@ -0,0 +1,169 @@ +/* + * lcp.h - Link Control Protocol definitions. + * + * Copyright (c) 1984-2000 Carnegie Mellon University. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. The name "Carnegie Mellon University" must not be used to + * endorse or promote products derived from this software without + * prior written permission. For permission or any legal + * details, please contact + * Office of Technology Transfer + * Carnegie Mellon University + * 5000 Forbes Avenue + * Pittsburgh, PA 15213-3890 + * (412) 268-4387, fax: (412) 268-7395 + * tech-transfer@andrew.cmu.edu + * + * 4. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by Computing Services + * at Carnegie Mellon University (http://www.cmu.edu/computing/)." + * + * CARNEGIE MELLON UNIVERSITY DISCLAIMS ALL WARRANTIES WITH REGARD TO + * THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS, IN NO EVENT SHALL CARNEGIE MELLON UNIVERSITY BE LIABLE + * FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN + * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING + * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * $Id: lcp.h,v 1.20 2004/11/14 22:53:42 carlsonj Exp $ + */ + +#include "lwip/opt.h" +#if PPP_SUPPORT /* don't build if not configured for use in lwipopts.h */ + +#ifndef LCP_H +#define LCP_H + +#include "ppp.h" + +/* + * Options. + */ +#define CI_VENDOR 0 /* Vendor Specific */ +#define CI_MRU 1 /* Maximum Receive Unit */ +#define CI_ASYNCMAP 2 /* Async Control Character Map */ +#define CI_AUTHTYPE 3 /* Authentication Type */ +#define CI_QUALITY 4 /* Quality Protocol */ +#define CI_MAGICNUMBER 5 /* Magic Number */ +#define CI_PCOMPRESSION 7 /* Protocol Field Compression */ +#define CI_ACCOMPRESSION 8 /* Address/Control Field Compression */ +#define CI_FCSALTERN 9 /* FCS-Alternatives */ +#define CI_SDP 10 /* Self-Describing-Pad */ +#define CI_NUMBERED 11 /* Numbered-Mode */ +#define CI_CALLBACK 13 /* callback */ +#define CI_MRRU 17 /* max reconstructed receive unit; multilink */ +#define CI_SSNHF 18 /* short sequence numbers for multilink */ +#define CI_EPDISC 19 /* endpoint discriminator */ +#define CI_MPPLUS 22 /* Multi-Link-Plus-Procedure */ +#define CI_LDISC 23 /* Link-Discriminator */ +#define CI_LCPAUTH 24 /* LCP Authentication */ +#define CI_COBS 25 /* Consistent Overhead Byte Stuffing */ +#define CI_PREFELIS 26 /* Prefix Elision */ +#define CI_MPHDRFMT 27 /* MP Header Format */ +#define CI_I18N 28 /* Internationalization */ +#define CI_SDL 29 /* Simple Data Link */ + +/* + * LCP-specific packet types (code numbers). + */ +#define PROTREJ 8 /* Protocol Reject */ +#define ECHOREQ 9 /* Echo Request */ +#define ECHOREP 10 /* Echo Reply */ +#define DISCREQ 11 /* Discard Request */ +#define IDENTIF 12 /* Identification */ +#define TIMEREM 13 /* Time Remaining */ + +/* Value used as data for CI_CALLBACK option */ +#define CBCP_OPT 6 /* Use callback control protocol */ + +#if 0 /* moved to opt.h */ +#define DEFMRU 1500 /* Try for this */ +#define MINMRU 128 /* No MRUs below this */ +#define MAXMRU 16384 /* Normally limit MRU to this */ +#endif /* moved to opt.h */ + +/* An endpoint discriminator, used with multilink. */ +#define MAX_ENDP_LEN 20 /* maximum length of discriminator value */ +struct epdisc { + unsigned char class_; /* -- The word "class" is reserved in C++. */ + unsigned char length; + unsigned char value[MAX_ENDP_LEN]; +}; + +/* + * The state of options is described by an lcp_options structure. + */ +typedef struct lcp_options { + unsigned int passive :1; /* Don't die if we don't get a response */ + unsigned int silent :1; /* Wait for the other end to start first */ + unsigned int restart :1; /* Restart vs. exit after close */ + unsigned int neg_mru :1; /* Negotiate the MRU? */ + unsigned int neg_asyncmap :1; /* Negotiate the async map? */ +#if PAP_SUPPORT + unsigned int neg_upap :1; /* Ask for UPAP authentication? */ +#endif /* PAP_SUPPORT */ +#if CHAP_SUPPORT + unsigned int neg_chap :1; /* Ask for CHAP authentication? */ +#endif /* CHAP_SUPPORT */ +#if EAP_SUPPORT + unsigned int neg_eap :1; /* Ask for EAP authentication? */ +#endif /* EAP_SUPPORT */ + unsigned int neg_magicnumber :1; /* Ask for magic number? */ + unsigned int neg_pcompression :1; /* HDLC Protocol Field Compression? */ + unsigned int neg_accompression :1; /* HDLC Address/Control Field Compression? */ +#if LQR_SUPPORT + unsigned int neg_lqr :1; /* Negotiate use of Link Quality Reports */ +#endif /* LQR_SUPPORT */ + unsigned int neg_cbcp :1; /* Negotiate use of CBCP */ +#ifdef HAVE_MULTILINK + unsigned int neg_mrru :1; /* negotiate multilink MRRU */ +#endif /* HAVE_MULTILINK */ + unsigned int neg_ssnhf :1; /* negotiate short sequence numbers */ + unsigned int neg_endpoint :1; /* negotiate endpoint discriminator */ + + u16_t mru; /* Value of MRU */ +#ifdef HAVE_MULTILINK + u16_t mrru; /* Value of MRRU, and multilink enable */ +#endif /* MULTILINK */ +#if CHAP_SUPPORT + u8_t chap_mdtype; /* which MD types (hashing algorithm) */ +#endif /* CHAP_SUPPORT */ + u32_t asyncmap; /* Value of async map */ + u32_t magicnumber; + u8_t numloops; /* Number of loops during magic number neg. */ +#if LQR_SUPPORT + u32_t lqr_period; /* Reporting period for LQR 1/100ths second */ +#endif /* LQR_SUPPORT */ + struct epdisc endpoint; /* endpoint discriminator */ +} lcp_options; + +void lcp_open(ppp_pcb *pcb); +void lcp_close(ppp_pcb *pcb, const char *reason); +void lcp_lowerup(ppp_pcb *pcb); +void lcp_lowerdown(ppp_pcb *pcb); +void lcp_sprotrej(ppp_pcb *pcb, u_char *p, int len); /* send protocol reject */ + +extern const struct protent lcp_protent; + +#if 0 /* moved to opt.h */ +/* Default number of times we receive our magic number from the peer + before deciding the link is looped-back. */ +#define DEFLOOPBACKFAIL 10 +#endif /* moved to opt.h */ + +#endif /* LCP_H */ +#endif /* PPP_SUPPORT */ diff --git a/components/lwip/include/lwip/netif/ppp/magic.h b/components/lwip/include/lwip/netif/ppp/magic.h new file mode 100755 index 0000000000..678ff724d5 --- /dev/null +++ b/components/lwip/include/lwip/netif/ppp/magic.h @@ -0,0 +1,122 @@ +/* + * magic.h - PPP Magic Number definitions. + * + * Copyright (c) 1984-2000 Carnegie Mellon University. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. The name "Carnegie Mellon University" must not be used to + * endorse or promote products derived from this software without + * prior written permission. For permission or any legal + * details, please contact + * Office of Technology Transfer + * Carnegie Mellon University + * 5000 Forbes Avenue + * Pittsburgh, PA 15213-3890 + * (412) 268-4387, fax: (412) 268-7395 + * tech-transfer@andrew.cmu.edu + * + * 4. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by Computing Services + * at Carnegie Mellon University (http://www.cmu.edu/computing/)." + * + * CARNEGIE MELLON UNIVERSITY DISCLAIMS ALL WARRANTIES WITH REGARD TO + * THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS, IN NO EVENT SHALL CARNEGIE MELLON UNIVERSITY BE LIABLE + * FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN + * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING + * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * $Id: magic.h,v 1.5 2003/06/11 23:56:26 paulus Exp $ + */ +/***************************************************************************** +* randm.h - Random number generator header file. +* +* Copyright (c) 2003 by Marc Boucher, Services Informatiques (MBSI) inc. +* Copyright (c) 1998 Global Election Systems Inc. +* +* The authors hereby grant permission to use, copy, modify, distribute, +* and license this software and its documentation for any purpose, provided +* that existing copyright notices are retained in all copies and that this +* notice and the following disclaimer are included verbatim in any +* distributions. No written agreement, license, or royalty fee is required +* for any of the authorized uses. +* +* THIS SOFTWARE IS PROVIDED BY THE CONTRIBUTORS *AS IS* AND ANY EXPRESS OR +* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES +* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +* IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF +* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +* +****************************************************************************** +* REVISION HISTORY +* +* 03-01-01 Marc Boucher +* Ported to lwIP. +* 98-05-29 Guy Lancaster , Global Election Systems Inc. +* Extracted from avos. +*****************************************************************************/ + +#include "lwip/opt.h" +#if PPP_SUPPORT /* don't build if not configured for use in lwipopts.h */ + +#ifndef MAGIC_H +#define MAGIC_H + +/*********************** +*** PUBLIC FUNCTIONS *** +***********************/ + +/* + * Initialize the random number generator. + */ +void magic_init(void); + +/* + * Randomize our random seed value. To be called for truely random events + * such as user operations and network traffic. + */ +void magic_randomize(void); + +/* + * Return a new random number. + */ +u32_t magic(void); /* Returns the next magic number */ + +/* + * Fill buffer with random bytes + * + * Use the random pool to generate random data. This degrades to pseudo + * random when used faster than randomness is supplied using magic_churnrand(). + * Thus it's important to make sure that the results of this are not + * published directly because one could predict the next result to at + * least some degree. Also, it's important to get a good seed before + * the first use. + */ +void magic_random_bytes(unsigned char *buf, u32_t buf_len); + +/* + * Return a new random number between 0 and (2^pow)-1 included. + */ +u32_t magic_pow(u8_t pow); + +#endif /* MAGIC_H */ + +#endif /* PPP_SUPPORT */ diff --git a/components/lwip/include/lwip/netif/ppp/mppe.h b/components/lwip/include/lwip/netif/ppp/mppe.h new file mode 100755 index 0000000000..93086955c4 --- /dev/null +++ b/components/lwip/include/lwip/netif/ppp/mppe.h @@ -0,0 +1,177 @@ +/* + * mppe.h - Definitions for MPPE + * + * Copyright (c) 2008 Paul Mackerras. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. The name(s) of the authors of this software must not be used to + * endorse or promote products derived from this software without + * prior written permission. + * + * 4. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by Paul Mackerras + * ". + * + * THE AUTHORS OF THIS SOFTWARE DISCLAIM ALL WARRANTIES WITH REGARD TO + * THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS, IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY + * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN + * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING + * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include "lwip/opt.h" +#if PPP_SUPPORT && MPPE_SUPPORT /* don't build if not configured for use in lwipopts.h */ + +#ifndef MPPE_H +#define MPPE_H + +#if LWIP_INCLUDED_POLARSSL_ARC4 +#include "netif/ppp/polarssl/arc4.h" +#else +#include "polarssl/arc4.h" +#endif + +#define MPPE_PAD 4 /* MPPE growth per frame */ +#define MPPE_MAX_KEY_LEN 16 /* largest key length (128-bit) */ + +/* option bits for ccp_options.mppe */ +#define MPPE_OPT_40 0x01 /* 40 bit */ +#define MPPE_OPT_128 0x02 /* 128 bit */ +#define MPPE_OPT_STATEFUL 0x04 /* stateful mode */ +/* unsupported opts */ +#define MPPE_OPT_56 0x08 /* 56 bit */ +#define MPPE_OPT_MPPC 0x10 /* MPPC compression */ +#define MPPE_OPT_D 0x20 /* Unknown */ +#define MPPE_OPT_UNSUPPORTED (MPPE_OPT_56|MPPE_OPT_MPPC|MPPE_OPT_D) +#define MPPE_OPT_UNKNOWN 0x40 /* Bits !defined in RFC 3078 were set */ + +/* + * This is not nice ... the alternative is a bitfield struct though. + * And unfortunately, we cannot share the same bits for the option + * names above since C and H are the same bit. We could do a u_int32 + * but then we have to do a htonl() all the time and/or we still need + * to know which octet is which. + */ +#define MPPE_C_BIT 0x01 /* MPPC */ +#define MPPE_D_BIT 0x10 /* Obsolete, usage unknown */ +#define MPPE_L_BIT 0x20 /* 40-bit */ +#define MPPE_S_BIT 0x40 /* 128-bit */ +#define MPPE_M_BIT 0x80 /* 56-bit, not supported */ +#define MPPE_H_BIT 0x01 /* Stateless (in a different byte) */ + +/* Does not include H bit; used for least significant octet only. */ +#define MPPE_ALL_BITS (MPPE_D_BIT|MPPE_L_BIT|MPPE_S_BIT|MPPE_M_BIT|MPPE_H_BIT) + +/* Build a CI from mppe opts (see RFC 3078) */ +#define MPPE_OPTS_TO_CI(opts, ci) \ + do { \ + u_char *ptr = ci; /* u_char[4] */ \ + \ + /* H bit */ \ + if (opts & MPPE_OPT_STATEFUL) \ + *ptr++ = 0x0; \ + else \ + *ptr++ = MPPE_H_BIT; \ + *ptr++ = 0; \ + *ptr++ = 0; \ + \ + /* S,L bits */ \ + *ptr = 0; \ + if (opts & MPPE_OPT_128) \ + *ptr |= MPPE_S_BIT; \ + if (opts & MPPE_OPT_40) \ + *ptr |= MPPE_L_BIT; \ + /* M,D,C bits not supported */ \ + } while (/* CONSTCOND */ 0) + +/* The reverse of the above */ +#define MPPE_CI_TO_OPTS(ci, opts) \ + do { \ + const u_char *ptr = ci; /* u_char[4] */ \ + \ + opts = 0; \ + \ + /* H bit */ \ + if (!(ptr[0] & MPPE_H_BIT)) \ + opts |= MPPE_OPT_STATEFUL; \ + \ + /* S,L bits */ \ + if (ptr[3] & MPPE_S_BIT) \ + opts |= MPPE_OPT_128; \ + if (ptr[3] & MPPE_L_BIT) \ + opts |= MPPE_OPT_40; \ + \ + /* M,D,C bits */ \ + if (ptr[3] & MPPE_M_BIT) \ + opts |= MPPE_OPT_56; \ + if (ptr[3] & MPPE_D_BIT) \ + opts |= MPPE_OPT_D; \ + if (ptr[3] & MPPE_C_BIT) \ + opts |= MPPE_OPT_MPPC; \ + \ + /* Other bits */ \ + if (ptr[0] & ~MPPE_H_BIT) \ + opts |= MPPE_OPT_UNKNOWN; \ + if (ptr[1] || ptr[2]) \ + opts |= MPPE_OPT_UNKNOWN; \ + if (ptr[3] & ~MPPE_ALL_BITS) \ + opts |= MPPE_OPT_UNKNOWN; \ + } while (/* CONSTCOND */ 0) + +/* Shared MPPE padding between MSCHAP and MPPE */ +#define SHA1_PAD_SIZE 40 + +static const u8_t mppe_sha1_pad1[SHA1_PAD_SIZE] = { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 +}; +static const u8_t mppe_sha1_pad2[SHA1_PAD_SIZE] = { + 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, + 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, + 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, + 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2 +}; + +/* + * State for an MPPE (de)compressor. + */ +typedef struct ppp_mppe_state { + arc4_context arc4; + u8_t master_key[MPPE_MAX_KEY_LEN]; + u8_t session_key[MPPE_MAX_KEY_LEN]; + u8_t keylen; /* key length in bytes */ + /* NB: 128-bit == 16, 40-bit == 8! + * If we want to support 56-bit, the unit has to change to bits + */ + u8_t bits; /* MPPE control bits */ + u16_t ccount; /* 12-bit coherency count (seqno) */ + u16_t sanity_errors; /* take down LCP if too many */ + unsigned int stateful :1; /* stateful mode flag */ + unsigned int discard :1; /* stateful mode packet loss flag */ +} ppp_mppe_state; + +void mppe_set_key(ppp_pcb *pcb, ppp_mppe_state *state, u8_t *key); +void mppe_init(ppp_pcb *pcb, ppp_mppe_state *state, u8_t options); +void mppe_comp_reset(ppp_pcb *pcb, ppp_mppe_state *state); +err_t mppe_compress(ppp_pcb *pcb, ppp_mppe_state *state, struct pbuf **pb, u16_t protocol); +void mppe_decomp_reset(ppp_pcb *pcb, ppp_mppe_state *state); +err_t mppe_decompress(ppp_pcb *pcb, ppp_mppe_state *state, struct pbuf **pb); + +#endif /* MPPE_H */ +#endif /* PPP_SUPPORT && MPPE_SUPPORT */ diff --git a/components/lwip/include/lwip/netif/ppp/polarssl/arc4.h b/components/lwip/include/lwip/netif/ppp/polarssl/arc4.h new file mode 100755 index 0000000000..95d9b34a93 --- /dev/null +++ b/components/lwip/include/lwip/netif/ppp/polarssl/arc4.h @@ -0,0 +1,81 @@ +/** + * \file arc4.h + * + * Based on XySSL: Copyright (C) 2006-2008 Christophe Devine + * + * Copyright (C) 2009 Paul Bakker + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the names of PolarSSL or XySSL nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED + * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "lwip/opt.h" +#if LWIP_INCLUDED_POLARSSL_ARC4 + +#ifndef LWIP_INCLUDED_POLARSSL_ARC4_H +#define LWIP_INCLUDED_POLARSSL_ARC4_H + +/** + * \brief ARC4 context structure + */ +typedef struct +{ + int x; /*!< permutation index */ + int y; /*!< permutation index */ + unsigned char m[256]; /*!< permutation table */ +} +arc4_context; + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \brief ARC4 key schedule + * + * \param ctx ARC4 context to be initialized + * \param key the secret key + * \param keylen length of the key + */ +void arc4_setup( arc4_context *ctx, unsigned char *key, int keylen ); + +/** + * \brief ARC4 cipher function + * + * \param ctx ARC4 context + * \param buf buffer to be processed + * \param buflen amount of data in buf + */ +void arc4_crypt( arc4_context *ctx, unsigned char *buf, int buflen ); + +#ifdef __cplusplus +} +#endif + +#endif /* LWIP_INCLUDED_POLARSSL_ARC4_H */ + +#endif /* LWIP_INCLUDED_POLARSSL_ARC4 */ diff --git a/components/lwip/include/lwip/netif/ppp/polarssl/des.h b/components/lwip/include/lwip/netif/ppp/polarssl/des.h new file mode 100755 index 0000000000..d0858bd823 --- /dev/null +++ b/components/lwip/include/lwip/netif/ppp/polarssl/des.h @@ -0,0 +1,92 @@ +/** + * \file des.h + * + * Based on XySSL: Copyright (C) 2006-2008 Christophe Devine + * + * Copyright (C) 2009 Paul Bakker + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the names of PolarSSL or XySSL nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED + * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "lwip/opt.h" +#if LWIP_INCLUDED_POLARSSL_DES + +#ifndef LWIP_INCLUDED_POLARSSL_DES_H +#define LWIP_INCLUDED_POLARSSL_DES_H + +#define DES_ENCRYPT 1 +#define DES_DECRYPT 0 + +/** + * \brief DES context structure + */ +typedef struct +{ + int mode; /*!< encrypt/decrypt */ + unsigned long sk[32]; /*!< DES subkeys */ +} +des_context; + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \brief DES key schedule (56-bit, encryption) + * + * \param ctx DES context to be initialized + * \param key 8-byte secret key + */ +void des_setkey_enc( des_context *ctx, unsigned char key[8] ); + +/** + * \brief DES key schedule (56-bit, decryption) + * + * \param ctx DES context to be initialized + * \param key 8-byte secret key + */ +void des_setkey_dec( des_context *ctx, unsigned char key[8] ); + +/** + * \brief DES-ECB block encryption/decryption + * + * \param ctx DES context + * \param input 64-bit input block + * \param output 64-bit output block + */ +void des_crypt_ecb( des_context *ctx, + const unsigned char input[8], + unsigned char output[8] ); + +#ifdef __cplusplus +} +#endif + +#endif /* LWIP_INCLUDED_POLARSSL_DES_H */ + +#endif /* LWIP_INCLUDED_POLARSSL_DES */ diff --git a/components/lwip/include/lwip/netif/ppp/polarssl/md4.h b/components/lwip/include/lwip/netif/ppp/polarssl/md4.h new file mode 100755 index 0000000000..a382f85a85 --- /dev/null +++ b/components/lwip/include/lwip/netif/ppp/polarssl/md4.h @@ -0,0 +1,97 @@ +/** + * \file md4.h + * + * Based on XySSL: Copyright (C) 2006-2008 Christophe Devine + * + * Copyright (C) 2009 Paul Bakker + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the names of PolarSSL or XySSL nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED + * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "lwip/opt.h" +#if LWIP_INCLUDED_POLARSSL_MD4 + +#ifndef LWIP_INCLUDED_POLARSSL_MD4_H +#define LWIP_INCLUDED_POLARSSL_MD4_H + +/** + * \brief MD4 context structure + */ +typedef struct +{ + unsigned long total[2]; /*!< number of bytes processed */ + unsigned long state[4]; /*!< intermediate digest state */ + unsigned char buffer[64]; /*!< data block being processed */ +} +md4_context; + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \brief MD4 context setup + * + * \param ctx context to be initialized + */ +void md4_starts( md4_context *ctx ); + +/** + * \brief MD4 process buffer + * + * \param ctx MD4 context + * \param input buffer holding the data + * \param ilen length of the input data + */ +void md4_update( md4_context *ctx, const unsigned char *input, int ilen ); + +/** + * \brief MD4 final digest + * + * \param ctx MD4 context + * \param output MD4 checksum result + */ +void md4_finish( md4_context *ctx, unsigned char output[16] ); + +/** + * \brief Output = MD4( input buffer ) + * + * \param input buffer holding the data + * \param ilen length of the input data + * \param output MD4 checksum result + */ +void md4( unsigned char *input, int ilen, unsigned char output[16] ); + + +#ifdef __cplusplus +} +#endif + +#endif /* LWIP_INCLUDED_POLARSSL_MD4_H */ + +#endif /* LWIP_INCLUDED_POLARSSL_MD4 */ diff --git a/components/lwip/include/lwip/netif/ppp/polarssl/md5.h b/components/lwip/include/lwip/netif/ppp/polarssl/md5.h new file mode 100755 index 0000000000..a299d98cb5 --- /dev/null +++ b/components/lwip/include/lwip/netif/ppp/polarssl/md5.h @@ -0,0 +1,96 @@ +/** + * \file md5.h + * + * Based on XySSL: Copyright (C) 2006-2008 Christophe Devine + * + * Copyright (C) 2009 Paul Bakker + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the names of PolarSSL or XySSL nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED + * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "lwip/opt.h" +#if LWIP_INCLUDED_POLARSSL_MD5 + +#ifndef LWIP_INCLUDED_POLARSSL_MD5_H +#define LWIP_INCLUDED_POLARSSL_MD5_H + +/** + * \brief MD5 context structure + */ +typedef struct +{ + unsigned long total[2]; /*!< number of bytes processed */ + unsigned long state[4]; /*!< intermediate digest state */ + unsigned char buffer[64]; /*!< data block being processed */ +} +md5_context; + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \brief MD5 context setup + * + * \param ctx context to be initialized + */ +void md5_starts( md5_context *ctx ); + +/** + * \brief MD5 process buffer + * + * \param ctx MD5 context + * \param input buffer holding the data + * \param ilen length of the input data + */ +void md5_update( md5_context *ctx, const unsigned char *input, int ilen ); + +/** + * \brief MD5 final digest + * + * \param ctx MD5 context + * \param output MD5 checksum result + */ +void md5_finish( md5_context *ctx, unsigned char output[16] ); + +/** + * \brief Output = MD5( input buffer ) + * + * \param input buffer holding the data + * \param ilen length of the input data + * \param output MD5 checksum result + */ +void md5( unsigned char *input, int ilen, unsigned char output[16] ); + +#ifdef __cplusplus +} +#endif + +#endif /* LWIP_INCLUDED_POLARSSL_MD5_H */ + +#endif /* LWIP_INCLUDED_POLARSSL_MD5 */ diff --git a/components/lwip/include/lwip/netif/ppp/polarssl/sha1.h b/components/lwip/include/lwip/netif/ppp/polarssl/sha1.h new file mode 100755 index 0000000000..56d947c264 --- /dev/null +++ b/components/lwip/include/lwip/netif/ppp/polarssl/sha1.h @@ -0,0 +1,96 @@ +/** + * \file sha1.h + * + * Based on XySSL: Copyright (C) 2006-2008 Christophe Devine + * + * Copyright (C) 2009 Paul Bakker + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the names of PolarSSL or XySSL nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED + * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "lwip/opt.h" +#if LWIP_INCLUDED_POLARSSL_SHA1 + +#ifndef LWIP_INCLUDED_POLARSSL_SHA1_H +#define LWIP_INCLUDED_POLARSSL_SHA1_H + +/** + * \brief SHA-1 context structure + */ +typedef struct +{ + unsigned long total[2]; /*!< number of bytes processed */ + unsigned long state[5]; /*!< intermediate digest state */ + unsigned char buffer[64]; /*!< data block being processed */ +} +sha1_context; + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \brief SHA-1 context setup + * + * \param ctx context to be initialized + */ +void sha1_starts( sha1_context *ctx ); + +/** + * \brief SHA-1 process buffer + * + * \param ctx SHA-1 context + * \param input buffer holding the data + * \param ilen length of the input data + */ +void sha1_update( sha1_context *ctx, const unsigned char *input, int ilen ); + +/** + * \brief SHA-1 final digest + * + * \param ctx SHA-1 context + * \param output SHA-1 checksum result + */ +void sha1_finish( sha1_context *ctx, unsigned char output[20] ); + +/** + * \brief Output = SHA-1( input buffer ) + * + * \param input buffer holding the data + * \param ilen length of the input data + * \param output SHA-1 checksum result + */ +void sha1( unsigned char *input, int ilen, unsigned char output[20] ); + +#ifdef __cplusplus +} +#endif + +#endif /* LWIP_INCLUDED_POLARSSL_SHA1_H */ + +#endif /* LWIP_INCLUDED_POLARSSL_SHA1 */ diff --git a/components/lwip/include/lwip/netif/ppp/ppp.h b/components/lwip/include/lwip/netif/ppp/ppp.h new file mode 100755 index 0000000000..4a50205476 --- /dev/null +++ b/components/lwip/include/lwip/netif/ppp/ppp.h @@ -0,0 +1,573 @@ +/***************************************************************************** +* ppp.h - Network Point to Point Protocol header file. +* +* Copyright (c) 2003 by Marc Boucher, Services Informatiques (MBSI) inc. +* portions Copyright (c) 1997 Global Election Systems Inc. +* +* The authors hereby grant permission to use, copy, modify, distribute, +* and license this software and its documentation for any purpose, provided +* that existing copyright notices are retained in all copies and that this +* notice and the following disclaimer are included verbatim in any +* distributions. No written agreement, license, or royalty fee is required +* for any of the authorized uses. +* +* THIS SOFTWARE IS PROVIDED BY THE CONTRIBUTORS *AS IS* AND ANY EXPRESS OR +* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES +* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +* IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF +* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +* +****************************************************************************** +* REVISION HISTORY +* +* 03-01-01 Marc Boucher +* Ported to lwIP. +* 97-11-05 Guy Lancaster , Global Election Systems Inc. +* Original derived from BSD codes. +*****************************************************************************/ + +#include "lwip/opt.h" +#if PPP_SUPPORT /* don't build if not configured for use in lwipopts.h */ + +#ifndef PPP_H +#define PPP_H + +#include "lwip/def.h" +#include "lwip/stats.h" +#include "lwip/mem.h" +#include "lwip/netif.h" +#include "lwip/sys.h" +#include "lwip/sio.h" +#include "lwip/timers.h" +#if PPP_IPV6_SUPPORT +#include "lwip/ip6_addr.h" +#endif /* PPP_IPV6_SUPPORT */ + +/* Disable non-working or rarely used PPP feature, so rarely that we don't want to bloat opt.h with them */ +#ifndef PPP_OPTIONS +#define PPP_OPTIONS 0 +#endif + +#ifndef PPP_NOTIFY +#define PPP_NOTIFY 0 +#endif + +#ifndef PPP_REMOTENAME +#define PPP_REMOTENAME 0 +#endif + +#ifndef PPP_IDLETIMELIMIT +#define PPP_IDLETIMELIMIT 0 +#endif + +#ifndef PPP_LCP_ADAPTIVE +#define PPP_LCP_ADAPTIVE 0 +#endif + +#ifndef PPP_MAXCONNECT +#define PPP_MAXCONNECT 0 +#endif + +#ifndef PPP_ALLOWED_ADDRS +#define PPP_ALLOWED_ADDRS 0 +#endif + +#ifndef PPP_PROTOCOLNAME +#define PPP_PROTOCOLNAME 0 +#endif + +#ifndef PPP_STATS_SUPPORT +#define PPP_STATS_SUPPORT 0 +#endif + +#ifndef DEFLATE_SUPPORT +#define DEFLATE_SUPPORT 0 +#endif + +#ifndef BSDCOMPRESS_SUPPORT +#define BSDCOMPRESS_SUPPORT 0 +#endif + +#ifndef PREDICTOR_SUPPORT +#define PREDICTOR_SUPPORT 0 +#endif + +/************************* +*** PUBLIC DEFINITIONS *** +*************************/ + +/* + * The basic PPP frame. + */ +#define PPP_HDRLEN 4 /* octets for standard ppp header */ +#define PPP_FCSLEN 2 /* octets for FCS */ + +/* + * Values for phase. + */ +#define PPP_PHASE_DEAD 0 +#define PPP_PHASE_INITIALIZE 1 +#define PPP_PHASE_SERIALCONN 2 +#define PPP_PHASE_DORMANT 3 +#define PPP_PHASE_ESTABLISH 4 +#define PPP_PHASE_AUTHENTICATE 5 +#define PPP_PHASE_CALLBACK 6 +#define PPP_PHASE_NETWORK 7 +#define PPP_PHASE_RUNNING 8 +#define PPP_PHASE_TERMINATE 9 +#define PPP_PHASE_DISCONNECT 10 +#define PPP_PHASE_HOLDOFF 11 +#define PPP_PHASE_MASTER 12 + +/* Error codes. */ +#define PPPERR_NONE 0 /* No error. */ +#define PPPERR_PARAM 1 /* Invalid parameter. */ +#define PPPERR_OPEN 2 /* Unable to open PPP session. */ +#define PPPERR_DEVICE 3 /* Invalid I/O device for PPP. */ +#define PPPERR_ALLOC 4 /* Unable to allocate resources. */ +#define PPPERR_USER 5 /* User interrupt. */ +#define PPPERR_CONNECT 6 /* Connection lost. */ +#define PPPERR_AUTHFAIL 7 /* Failed authentication challenge. */ +#define PPPERR_PROTOCOL 8 /* Failed to meet protocol. */ +#define PPPERR_PEERDEAD 9 /* Connection timeout */ +#define PPPERR_IDLETIMEOUT 10 /* Idle Timeout */ +#define PPPERR_CONNECTTIME 11 /* Max connect time reached */ +#define PPPERR_LOOPBACK 12 /* Loopback detected */ + +/* Whether auth support is enabled at all */ +#define PPP_AUTH_SUPPORT (PAP_SUPPORT || CHAP_SUPPORT || EAP_SUPPORT) + +/************************ +*** PUBLIC DATA TYPES *** +************************/ + +/* + * Other headers require ppp_pcb definition for prototypes, but ppp_pcb + * require some structure definition from other headers as well, we are + * fixing the dependency loop here by declaring the ppp_pcb type then + * by including headers containing necessary struct definition for ppp_pcb + */ +typedef struct ppp_pcb_s ppp_pcb; + +/* Type definitions for BSD code. */ +#ifndef __u_char_defined +typedef unsigned long u_long; +typedef unsigned int u_int; +typedef unsigned short u_short; +typedef unsigned char u_char; +#endif + +#include "fsm.h" +#include "lcp.h" +#if CCP_SUPPORT +#include "ccp.h" +#endif /* CCP_SUPPORT */ +#if MPPE_SUPPORT +#include "mppe.h" +#endif /* MPPE_SUPPORT */ +#if PPP_IPV4_SUPPORT +#include "ipcp.h" +#endif /* PPP_IPV4_SUPPORT */ +#if PPP_IPV6_SUPPORT +#include "ipv6cp.h" +#endif /* PPP_IPV6_SUPPORT */ +#if PAP_SUPPORT +#include "upap.h" +#endif /* PAP_SUPPORT */ +#if CHAP_SUPPORT +#include "chap-new.h" +#endif /* CHAP_SUPPORT */ +#if EAP_SUPPORT +#include "eap.h" +#endif /* EAP_SUPPORT */ +#if VJ_SUPPORT +#include "vj.h" +#endif /* VJ_SUPPORT */ + +/* Link status callback function prototype */ +typedef void (*ppp_link_status_cb_fn)(ppp_pcb *pcb, int err_code, void *ctx); + +/* + * PPP configuration. + */ +typedef struct ppp_settings_s { + +#if PPP_SERVER && PPP_AUTH_SUPPORT + unsigned int auth_required :1; /* Peer is required to authenticate */ + unsigned int null_login :1; /* Username of "" and a password of "" are acceptable */ +#endif /* PPP_SERVER && PPP_AUTH_SUPPORT */ +#if PPP_REMOTENAME + unsigned int explicit_remote :1; /* remote_name specified with remotename opt */ +#endif /* PPP_REMOTENAME */ +#if PAP_SUPPORT + unsigned int refuse_pap :1; /* Don't proceed auth. with PAP */ +#endif /* PAP_SUPPORT */ +#if CHAP_SUPPORT + unsigned int refuse_chap :1; /* Don't proceed auth. with CHAP */ +#endif /* CHAP_SUPPORT */ +#if MSCHAP_SUPPORT + unsigned int refuse_mschap :1; /* Don't proceed auth. with MS-CHAP */ + unsigned int refuse_mschap_v2 :1; /* Don't proceed auth. with MS-CHAPv2 */ +#endif /* MSCHAP_SUPPORT */ +#if EAP_SUPPORT + unsigned int refuse_eap :1; /* Don't proceed auth. with EAP */ +#endif /* EAP_SUPPORT */ +#if LWIP_DNS + unsigned int usepeerdns :1; /* Ask peer for DNS adds */ +#endif /* LWIP_DNS */ + unsigned int persist :1; /* Persist mode, always try to open the connection */ +#if PRINTPKT_SUPPORT + unsigned int hide_password :1; /* Hide password in dumped packets */ +#endif /* PRINTPKT_SUPPORT */ + unsigned int noremoteip :1; /* Let him have no IP address */ + unsigned int lax_recv :1; /* accept control chars in asyncmap */ + unsigned int noendpoint :1; /* don't send/accept endpoint discriminator */ +#if PPP_LCP_ADAPTIVE + unsigned int lcp_echo_adaptive :1; /* request echo only if the link was idle */ +#endif /* PPP_LCP_ADAPTIVE */ +#if MPPE_SUPPORT + unsigned int require_mppe :1; /* Require MPPE (Microsoft Point to Point Encryption) */ + unsigned int refuse_mppe_40 :1; /* Allow MPPE 40-bit mode? */ + unsigned int refuse_mppe_128 :1; /* Allow MPPE 128-bit mode? */ + unsigned int refuse_mppe_stateful :1; /* Allow MPPE stateful mode? */ +#endif /* MPPE_SUPPORT */ + + u16_t listen_time; /* time to listen first (ms), waiting for peer to send LCP packet */ + +#if PPP_IDLETIMELIMIT + u16_t idle_time_limit; /* Disconnect if idle for this many seconds */ +#endif /* PPP_IDLETIMELIMIT */ +#if PPP_MAXCONNECT + u32_t maxconnect; /* Maximum connect time (seconds) */ +#endif /* PPP_MAXCONNECT */ + +#if PPP_AUTH_SUPPORT + /* auth data */ + const char *user; /* Username for PAP */ + const char *passwd; /* Password for PAP, secret for CHAP */ +#if PPP_REMOTENAME + char remote_name[MAXNAMELEN + 1]; /* Peer's name for authentication */ +#endif /* PPP_REMOTENAME */ + +#if PAP_SUPPORT + u8_t pap_timeout_time; /* Timeout (seconds) for auth-req retrans. */ + u8_t pap_max_transmits; /* Number of auth-reqs sent */ +#if PPP_SERVER + u8_t pap_req_timeout; /* Time to wait for auth-req from peer */ +#endif /* PPP_SERVER */ +#endif /* PAP_SUPPPORT */ + +#if CHAP_SUPPORT + u8_t chap_timeout_time; /* Timeout (seconds) for retransmitting req */ + u8_t chap_max_transmits; /* max # times to send challenge */ +#if PPP_SERVER + u8_t chap_rechallenge_time; /* Time to wait for auth-req from peer */ +#endif /* PPP_SERVER */ +#endif /* CHAP_SUPPPORT */ + +#if EAP_SUPPORT + u8_t eap_req_time; /* Time to wait (for retransmit/fail) */ + u8_t eap_allow_req; /* Max Requests allowed */ +#if PPP_SERVER + u8_t eap_timeout_time; /* Time to wait (for retransmit/fail) */ + u8_t eap_max_transmits; /* Max Requests allowed */ +#endif /* PPP_SERVER */ +#endif /* EAP_SUPPORT */ + +#endif /* PPP_AUTH_SUPPORT */ + + u8_t fsm_timeout_time; /* Timeout time in seconds */ + u8_t fsm_max_conf_req_transmits; /* Maximum Configure-Request transmissions */ + u8_t fsm_max_term_transmits; /* Maximum Terminate-Request transmissions */ + u8_t fsm_max_nak_loops; /* Maximum number of nak loops tolerated */ + + u8_t lcp_loopbackfail; /* Number of times we receive our magic number from the peer + before deciding the link is looped-back. */ + u8_t lcp_echo_interval; /* Interval between LCP echo-requests */ + u8_t lcp_echo_fails; /* Tolerance to unanswered echo-requests */ + +} ppp_settings; + +#if PPP_SERVER +struct ppp_addrs { +#if PPP_IPV4_SUPPORT + ip4_addr_t our_ipaddr, his_ipaddr, netmask; +#if LWIP_DNS + ip4_addr_t dns1, dns2; +#endif /* LWIP_DNS */ +#endif /* PPP_IPV4_SUPPORT */ +#if PPP_IPV6_SUPPORT + ip6_addr_t our6_ipaddr, his6_ipaddr; +#endif /* PPP_IPV6_SUPPORT */ +}; +#endif /* PPP_SERVER */ + +/* + * PPP interface control block. + */ +struct ppp_pcb_s { + /* -- below are data that will NOT be cleared between two sessions */ + ppp_settings settings; + const struct link_callbacks *link_cb; + void *link_ctx_cb; + void (*link_status_cb)(ppp_pcb *pcb, int err_code, void *ctx); /* Status change callback */ +#if PPP_NOTIFY_PHASE + void (*notify_phase_cb)(ppp_pcb *pcb, u8_t phase, void *ctx); /* Notify phase callback */ +#endif /* PPP_NOTIFY_PHASE */ + void *ctx_cb; /* Callbacks optional pointer */ + struct netif *netif; /* PPP interface */ + + /* -- below are data that will be cleared between two sessions */ + + /* + * phase must be the first member of cleared members, because it is used to know + * which part must not be cleared. + */ + u8_t phase; /* where the link is at */ + u8_t err_code; /* Code indicating why interface is down. */ + + /* flags */ +#if PPP_IPV4_SUPPORT + unsigned int ipcp_is_open :1; /* haven't called np_finished() */ + unsigned int ipcp_is_up :1; /* have called ipcp_up() */ + unsigned int if4_up :1; /* True when the IPv4 interface is up. */ +#if 0 /* UNUSED - PROXY ARP */ + unsigned int proxy_arp_set :1; /* Have created proxy arp entry */ +#endif /* UNUSED - PROXY ARP */ +#endif /* PPP_IPV4_SUPPORT */ +#if PPP_IPV6_SUPPORT + unsigned int ipv6cp_is_up :1; /* have called ip6cp_up() */ + unsigned int if6_up :1; /* True when the IPv6 interface is up. */ +#endif /* PPP_IPV6_SUPPORT */ + unsigned int lcp_echo_timer_running :1; /* set if a timer is running */ +#if VJ_SUPPORT + unsigned int vj_enabled :1; /* Flag indicating VJ compression enabled. */ +#endif /* VJ_SUPPORT */ +#if CCP_SUPPORT + unsigned int ccp_all_rejected :1; /* we rejected all peer's options */ +#endif /* CCP_SUPPORT */ +#if MPPE_SUPPORT + unsigned int mppe_keys_set :1; /* Have the MPPE keys been set? */ +#endif /* MPPE_SUPPORT */ + +#if PPP_AUTH_SUPPORT + /* auth data */ +#if PPP_SERVER && defined(HAVE_MULTILINK) + char peer_authname[MAXNAMELEN + 1]; /* The name by which the peer authenticated itself to us. */ +#endif /* PPP_SERVER && defined(HAVE_MULTILINK) */ + u16_t auth_pending; /* Records which authentication operations haven't completed yet. */ + u16_t auth_done; /* Records which authentication operations have been completed. */ + +#if PAP_SUPPORT + upap_state upap; /* PAP data */ +#endif /* PAP_SUPPORT */ + +#if CHAP_SUPPORT + chap_client_state chap_client; /* CHAP client data */ +#if PPP_SERVER + chap_server_state chap_server; /* CHAP server data */ +#endif /* PPP_SERVER */ +#endif /* CHAP_SUPPORT */ + +#if EAP_SUPPORT + eap_state eap; /* EAP data */ +#endif /* EAP_SUPPORT */ +#endif /* PPP_AUTH_SUPPORT */ + + fsm lcp_fsm; /* LCP fsm structure */ + lcp_options lcp_wantoptions; /* Options that we want to request */ + lcp_options lcp_gotoptions; /* Options that peer ack'd */ + lcp_options lcp_allowoptions; /* Options we allow peer to request */ + lcp_options lcp_hisoptions; /* Options that we ack'd */ + u16_t peer_mru; /* currently negotiated peer MRU */ + u8_t lcp_echos_pending; /* Number of outstanding echo msgs */ + u8_t lcp_echo_number; /* ID number of next echo frame */ + + u8_t num_np_open; /* Number of network protocols which we have opened. */ + u8_t num_np_up; /* Number of network protocols which have come up. */ + +#if VJ_SUPPORT + struct vjcompress vj_comp; /* Van Jacobson compression header. */ +#endif /* VJ_SUPPORT */ + +#if CCP_SUPPORT + fsm ccp_fsm; /* CCP fsm structure */ + ccp_options ccp_wantoptions; /* what to request the peer to use */ + ccp_options ccp_gotoptions; /* what the peer agreed to do */ + ccp_options ccp_allowoptions; /* what we'll agree to do */ + ccp_options ccp_hisoptions; /* what we agreed to do */ + u8_t ccp_localstate; /* Local state (mainly for handling reset-reqs and reset-acks). */ + u8_t ccp_receive_method; /* Method chosen on receive path */ + u8_t ccp_transmit_method; /* Method chosen on transmit path */ +#if MPPE_SUPPORT + ppp_mppe_state mppe_comp; /* MPPE "compressor" structure */ + ppp_mppe_state mppe_decomp; /* MPPE "decompressor" structure */ +#endif /* MPPE_SUPPORT */ +#endif /* CCP_SUPPORT */ + +#if PPP_IPV4_SUPPORT + fsm ipcp_fsm; /* IPCP fsm structure */ + ipcp_options ipcp_wantoptions; /* Options that we want to request */ + ipcp_options ipcp_gotoptions; /* Options that peer ack'd */ + ipcp_options ipcp_allowoptions; /* Options we allow peer to request */ + ipcp_options ipcp_hisoptions; /* Options that we ack'd */ +#endif /* PPP_IPV4_SUPPORT */ + +#if PPP_IPV6_SUPPORT + fsm ipv6cp_fsm; /* IPV6CP fsm structure */ + ipv6cp_options ipv6cp_wantoptions; /* Options that we want to request */ + ipv6cp_options ipv6cp_gotoptions; /* Options that peer ack'd */ + ipv6cp_options ipv6cp_allowoptions; /* Options we allow peer to request */ + ipv6cp_options ipv6cp_hisoptions; /* Options that we ack'd */ +#endif /* PPP_IPV6_SUPPORT */ +}; + +/************************ + *** PUBLIC FUNCTIONS *** + ************************/ + +/* + * Set auth helper, optional, you can either fill ppp_pcb->settings. + * + * Warning: Using PPPAUTHTYPE_ANY might have security consequences. + * RFC 1994 says: + * + * In practice, within or associated with each PPP server, there is a + * database which associates "user" names with authentication + * information ("secrets"). It is not anticipated that a particular + * named user would be authenticated by multiple methods. This would + * make the user vulnerable to attacks which negotiate the least secure + * method from among a set (such as PAP rather than CHAP). If the same + * secret was used, PAP would reveal the secret to be used later with + * CHAP. + * + * Instead, for each user name there should be an indication of exactly + * one method used to authenticate that user name. If a user needs to + * make use of different authentication methods under different + * circumstances, then distinct user names SHOULD be employed, each of + * which identifies exactly one authentication method. + * + */ +#define PPPAUTHTYPE_NONE 0x00 +#define PPPAUTHTYPE_PAP 0x01 +#define PPPAUTHTYPE_CHAP 0x02 +#define PPPAUTHTYPE_MSCHAP 0x04 +#define PPPAUTHTYPE_MSCHAP_V2 0x08 +#define PPPAUTHTYPE_EAP 0x10 +#define PPPAUTHTYPE_ANY 0xff +void ppp_set_auth(ppp_pcb *pcb, u8_t authtype, const char *user, const char *passwd); + +/* + * Set a PPP interface as the default network interface + * (used to output all packets for which no specific route is found). + */ +#define ppp_set_default(ppp) netif_set_default(ppp->netif) + +#if PPP_NOTIFY_PHASE +/* + * Set a PPP notify phase callback. + * + * This can be used for example to set a LED pattern depending on the + * current phase of the PPP session. + */ +typedef void (*ppp_notify_phase_cb_fn)(ppp_pcb *pcb, u8_t phase, void *ctx); +void ppp_set_notify_phase_callback(ppp_pcb *pcb, ppp_notify_phase_cb_fn notify_phase_cb); +#endif /* PPP_NOTIFY_PHASE */ + +/* + * Initiate a PPP connection. + * + * This can only be called if PPP is in the dead phase. + * + * Holdoff is the time to wait (in seconds) before initiating + * the connection. + * + * If this port connects to a modem, the modem connection must be + * established before calling this. + */ +err_t ppp_connect(ppp_pcb *pcb, u16_t holdoff); + +#if PPP_SERVER +/* + * Listen for an incoming PPP connection. + * + * This can only be called if PPP is in the dead phase. + * + * Local and remote interface IP addresses, as well as DNS are + * provided through a previously filled struct ppp_addrs. + * + * If this port connects to a modem, the modem connection must be + * established before calling this. + */ +err_t ppp_listen(ppp_pcb *pcb, struct ppp_addrs *addrs); +#endif /* PPP_SERVER */ + +/* + * Initiate the end of a PPP connection. + * Any outstanding packets in the queues are dropped. + * + * Setting nocarrier to 1 close the PPP connection without initiating the + * shutdown procedure. Always using nocarrier = 0 is still recommended, + * this is going to take a little longer time if your link is down, but + * is a safer choice for the PPP state machine. + * + * Return 0 on success, an error code on failure. + */ +err_t ppp_close(ppp_pcb *pcb, u8_t nocarrier); + +/* + * Release the control block. + * + * This can only be called if PPP is in the dead phase. + * + * You must use ppp_close() before if you wish to terminate + * an established PPP session. + * + * Return 0 on success, an error code on failure. + */ +err_t ppp_free(ppp_pcb *pcb); + +/* + * PPP IOCTL commands. + * + * Get the up status - 0 for down, non-zero for up. The argument must + * point to an int. + */ +#define PPPCTLG_UPSTATUS 0 + +/* + * Get the PPP error code. The argument must point to an int. + * Returns a PPPERR_* value. + */ +#define PPPCTLG_ERRCODE 1 + +/* + * Get the fd associated with a PPP over serial + */ +#define PPPCTLG_FD 2 + +/* + * Get and set parameters for the given connection. + * Return 0 on success, an error code on failure. + */ +err_t ppp_ioctl(ppp_pcb *pcb, u8_t cmd, void *arg); + +/* Get the PPP netif interface */ +#define ppp_netif(ppp) (ppp->netif) + +/* Set an lwIP-style status-callback for the selected PPP device */ +#define ppp_set_netif_statuscallback(ppp, status_cb) \ + netif_set_status_callback(ppp->netif, status_cb); + +/* Set an lwIP-style link-callback for the selected PPP device */ +#define ppp_set_netif_linkcallback(ppp, link_cb) \ + netif_set_link_callback(ppp->netif, link_cb); + +#endif /* PPP_H */ + +#endif /* PPP_SUPPORT */ diff --git a/components/lwip/include/lwip/netif/ppp/ppp_impl.h b/components/lwip/include/lwip/netif/ppp/ppp_impl.h new file mode 100755 index 0000000000..324f4b058d --- /dev/null +++ b/components/lwip/include/lwip/netif/ppp/ppp_impl.h @@ -0,0 +1,632 @@ +/***************************************************************************** +* ppp.h - Network Point to Point Protocol header file. +* +* Copyright (c) 2003 by Marc Boucher, Services Informatiques (MBSI) inc. +* portions Copyright (c) 1997 Global Election Systems Inc. +* +* The authors hereby grant permission to use, copy, modify, distribute, +* and license this software and its documentation for any purpose, provided +* that existing copyright notices are retained in all copies and that this +* notice and the following disclaimer are included verbatim in any +* distributions. No written agreement, license, or royalty fee is required +* for any of the authorized uses. +* +* THIS SOFTWARE IS PROVIDED BY THE CONTRIBUTORS *AS IS* AND ANY EXPRESS OR +* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES +* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +* IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF +* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +* +****************************************************************************** +* REVISION HISTORY +* +* 03-01-01 Marc Boucher +* Ported to lwIP. +* 97-11-05 Guy Lancaster , Global Election Systems Inc. +* Original derived from BSD codes. +*****************************************************************************/ +#ifndef LWIP_HDR_PPP_IMPL_H +#define LWIP_HDR_PPP_IMPL_H + +#include "lwip/opt.h" + +#if PPP_SUPPORT /* don't build if not configured for use in lwipopts.h */ + +#ifdef PPP_INCLUDE_SETTINGS_HEADER +#include "ppp_settings.h" +#endif + +#include /* formats */ +#include +#include +#include /* strtol() */ + +#include "lwip/netif.h" +#include "lwip/def.h" +#include "lwip/timers.h" + +#include "ppp.h" +#include "pppdebug.h" + +/* + * Memory used for control packets. + * + * PPP_CTRL_PBUF_MAX_SIZE is the amount of memory we allocate when we + * cannot figure out how much we are going to use before filling the buffer. + */ +#if PPP_USE_PBUF_RAM +#define PPP_CTRL_PBUF_TYPE PBUF_RAM +#define PPP_CTRL_PBUF_MAX_SIZE 512 +#else /* PPP_USE_PBUF_RAM */ +#define PPP_CTRL_PBUF_TYPE PBUF_POOL +#define PPP_CTRL_PBUF_MAX_SIZE PBUF_POOL_BUFSIZE +#endif /* PPP_USE_PBUF_RAM */ + +/* + * The basic PPP frame. + */ +#define PPP_ADDRESS(p) (((u_char *)(p))[0]) +#define PPP_CONTROL(p) (((u_char *)(p))[1]) +#define PPP_PROTOCOL(p) ((((u_char *)(p))[2] << 8) + ((u_char *)(p))[3]) + +/* + * Significant octet values. + */ +#define PPP_ALLSTATIONS 0xff /* All-Stations broadcast address */ +#define PPP_UI 0x03 /* Unnumbered Information */ +#define PPP_FLAG 0x7e /* Flag Sequence */ +#define PPP_ESCAPE 0x7d /* Asynchronous Control Escape */ +#define PPP_TRANS 0x20 /* Asynchronous transparency modifier */ + +/* + * Protocol field values. + */ +#define PPP_IP 0x21 /* Internet Protocol */ +#if 0 /* UNUSED */ +#define PPP_AT 0x29 /* AppleTalk Protocol */ +#define PPP_IPX 0x2b /* IPX protocol */ +#endif /* UNUSED */ +#if VJ_SUPPORT +#define PPP_VJC_COMP 0x2d /* VJ compressed TCP */ +#define PPP_VJC_UNCOMP 0x2f /* VJ uncompressed TCP */ +#endif /* VJ_SUPPORT */ +#if PPP_IPV6_SUPPORT +#define PPP_IPV6 0x57 /* Internet Protocol Version 6 */ +#endif /* PPP_IPV6_SUPPORT */ +#if CCP_SUPPORT +#define PPP_COMP 0xfd /* compressed packet */ +#endif /* CCP_SUPPORT */ +#define PPP_IPCP 0x8021 /* IP Control Protocol */ +#if 0 /* UNUSED */ +#define PPP_ATCP 0x8029 /* AppleTalk Control Protocol */ +#define PPP_IPXCP 0x802b /* IPX Control Protocol */ +#endif /* UNUSED */ +#if PPP_IPV6_SUPPORT +#define PPP_IPV6CP 0x8057 /* IPv6 Control Protocol */ +#endif /* PPP_IPV6_SUPPORT */ +#if CCP_SUPPORT +#define PPP_CCP 0x80fd /* Compression Control Protocol */ +#endif /* CCP_SUPPORT */ +#if ECP_SUPPORT +#define PPP_ECP 0x8053 /* Encryption Control Protocol */ +#endif /* ECP_SUPPORT */ +#define PPP_LCP 0xc021 /* Link Control Protocol */ +#if PAP_SUPPORT +#define PPP_PAP 0xc023 /* Password Authentication Protocol */ +#endif /* PAP_SUPPORT */ +#if LQR_SUPPORT +#define PPP_LQR 0xc025 /* Link Quality Report protocol */ +#endif /* LQR_SUPPORT */ +#if CHAP_SUPPORT +#define PPP_CHAP 0xc223 /* Cryptographic Handshake Auth. Protocol */ +#endif /* CHAP_SUPPORT */ +#if CBCP_SUPPORT +#define PPP_CBCP 0xc029 /* Callback Control Protocol */ +#endif /* CBCP_SUPPORT */ +#if EAP_SUPPORT +#define PPP_EAP 0xc227 /* Extensible Authentication Protocol */ +#endif /* EAP_SUPPORT */ + +/* + * The following struct gives the addresses of procedures to call + * for a particular lower link level protocol. + */ +struct link_callbacks { + /* Start a connection (e.g. Initiate discovery phase) */ + err_t (*connect) (ppp_pcb *pcb, void *ctx); +#if PPP_SERVER + /* Listen for an incoming connection (Passive mode) */ + err_t (*listen) (ppp_pcb *pcb, void *ctx, struct ppp_addrs *addrs); +#endif /* PPP_SERVER */ + /* End a connection (i.e. initiate disconnect phase) */ + void (*disconnect) (ppp_pcb *pcb, void *ctx); + /* Free lower protocol control block */ + err_t (*free) (ppp_pcb *pcb, void *ctx); + /* Write a pbuf to a ppp link, only used from PPP functions to send PPP packets. */ + err_t (*write)(ppp_pcb *pcb, void *ctx, struct pbuf *p); + /* Send a packet from lwIP core (IPv4 or IPv6) */ + err_t (*netif_output)(ppp_pcb *pcb, void *ctx, struct pbuf *p, u_short protocol); + /* configure the transmit-side characteristics of the PPP interface */ + void (*send_config)(ppp_pcb *pcb, void *ctx, u32_t accm, int pcomp, int accomp); + /* confire the receive-side characteristics of the PPP interface */ + void (*recv_config)(ppp_pcb *pcb, void *ctx, u32_t accm, int pcomp, int accomp); +}; + +/* + * What to do with network protocol (NP) packets. + */ +enum NPmode { + NPMODE_PASS, /* pass the packet through */ + NPMODE_DROP, /* silently drop the packet */ + NPMODE_ERROR, /* return an error */ + NPMODE_QUEUE /* save it up for later. */ +}; + +/* + * Statistics. + */ +#if PPP_STATS_SUPPORT +struct pppstat { + unsigned int ppp_ibytes; /* bytes received */ + unsigned int ppp_ipackets; /* packets received */ + unsigned int ppp_ierrors; /* receive errors */ + unsigned int ppp_obytes; /* bytes sent */ + unsigned int ppp_opackets; /* packets sent */ + unsigned int ppp_oerrors; /* transmit errors */ +}; + +#if VJ_SUPPORT +struct vjstat { + unsigned int vjs_packets; /* outbound packets */ + unsigned int vjs_compressed; /* outbound compressed packets */ + unsigned int vjs_searches; /* searches for connection state */ + unsigned int vjs_misses; /* times couldn't find conn. state */ + unsigned int vjs_uncompressedin; /* inbound uncompressed packets */ + unsigned int vjs_compressedin; /* inbound compressed packets */ + unsigned int vjs_errorin; /* inbound unknown type packets */ + unsigned int vjs_tossed; /* inbound packets tossed because of error */ +}; +#endif /* VJ_SUPPORT */ + +struct ppp_stats { + struct pppstat p; /* basic PPP statistics */ +#if VJ_SUPPORT + struct vjstat vj; /* VJ header compression statistics */ +#endif /* VJ_SUPPORT */ +}; + +#if CCP_SUPPORT +struct compstat { + unsigned int unc_bytes; /* total uncompressed bytes */ + unsigned int unc_packets; /* total uncompressed packets */ + unsigned int comp_bytes; /* compressed bytes */ + unsigned int comp_packets; /* compressed packets */ + unsigned int inc_bytes; /* incompressible bytes */ + unsigned int inc_packets; /* incompressible packets */ + unsigned int ratio; /* recent compression ratio << 8 */ +}; + +struct ppp_comp_stats { + struct compstat c; /* packet compression statistics */ + struct compstat d; /* packet decompression statistics */ +}; +#endif /* CCP_SUPPORT */ + +#endif /* PPP_STATS_SUPPORT */ + +#if PPP_IDLETIMELIMIT +/* + * The following structure records the time in seconds since + * the last NP packet was sent or received. + */ +struct ppp_idle { + time_t xmit_idle; /* time since last NP packet sent */ + time_t recv_idle; /* time since last NP packet received */ +}; +#endif /* PPP_IDLETIMELIMIT */ + +/* values for epdisc.class */ +#define EPD_NULL 0 /* null discriminator, no data */ +#define EPD_LOCAL 1 +#define EPD_IP 2 +#define EPD_MAC 3 +#define EPD_MAGIC 4 +#define EPD_PHONENUM 5 + +/* + * Global variables. + */ +#ifdef HAVE_MULTILINK +extern u8_t multilink; /* enable multilink operation */ +extern u8_t doing_multilink; +extern u8_t multilink_master; +extern u8_t bundle_eof; +extern u8_t bundle_terminating; +#endif + +#ifdef MAXOCTETS +extern unsigned int maxoctets; /* Maximum octetes per session (in bytes) */ +extern int maxoctets_dir; /* Direction : + 0 - in+out (default) + 1 - in + 2 - out + 3 - max(in,out) */ +extern int maxoctets_timeout; /* Timeout for check of octets limit */ +#define PPP_OCTETS_DIRECTION_SUM 0 +#define PPP_OCTETS_DIRECTION_IN 1 +#define PPP_OCTETS_DIRECTION_OUT 2 +#define PPP_OCTETS_DIRECTION_MAXOVERAL 3 +/* same as previos, but little different on RADIUS side */ +#define PPP_OCTETS_DIRECTION_MAXSESSION 4 +#endif + +/* Data input may be used by CCP and ECP, remove this entry + * from struct protent to save some flash + */ +#define PPP_DATAINPUT 0 + +/* + * The following struct gives the addresses of procedures to call + * for a particular protocol. + */ +struct protent { + u_short protocol; /* PPP protocol number */ + /* Initialization procedure */ + void (*init) (ppp_pcb *pcb); + /* Process a received packet */ + void (*input) (ppp_pcb *pcb, u_char *pkt, int len); + /* Process a received protocol-reject */ + void (*protrej) (ppp_pcb *pcb); + /* Lower layer has come up */ + void (*lowerup) (ppp_pcb *pcb); + /* Lower layer has gone down */ + void (*lowerdown) (ppp_pcb *pcb); + /* Open the protocol */ + void (*open) (ppp_pcb *pcb); + /* Close the protocol */ + void (*close) (ppp_pcb *pcb, const char *reason); +#if PRINTPKT_SUPPORT + /* Print a packet in readable form */ + int (*printpkt) (const u_char *pkt, int len, + void (*printer) (void *, const char *, ...), + void *arg); +#endif /* PRINTPKT_SUPPORT */ +#if PPP_DATAINPUT + /* Process a received data packet */ + void (*datainput) (ppp_pcb *pcb, u_char *pkt, int len); +#endif /* PPP_DATAINPUT */ +#if PRINTPKT_SUPPORT + const char *name; /* Text name of protocol */ + const char *data_name; /* Text name of corresponding data protocol */ +#endif /* PRINTPKT_SUPPORT */ +#if PPP_OPTIONS + option_t *options; /* List of command-line options */ + /* Check requested options, assign defaults */ + void (*check_options) (void); +#endif /* PPP_OPTIONS */ +#if DEMAND_SUPPORT + /* Configure interface for demand-dial */ + int (*demand_conf) (int unit); + /* Say whether to bring up link for this pkt */ + int (*active_pkt) (u_char *pkt, int len); +#endif /* DEMAND_SUPPORT */ +}; + +/* Table of pointers to supported protocols */ +extern const struct protent* const protocols[]; + + +/* Values for auth_pending, auth_done */ +#if PAP_SUPPORT +#define PAP_WITHPEER 0x1 +#define PAP_PEER 0x2 +#endif /* PAP_SUPPORT */ +#if CHAP_SUPPORT +#define CHAP_WITHPEER 0x4 +#define CHAP_PEER 0x8 +#endif /* CHAP_SUPPORT */ +#if EAP_SUPPORT +#define EAP_WITHPEER 0x10 +#define EAP_PEER 0x20 +#endif /* EAP_SUPPORT */ + +/* Values for auth_done only */ +#if CHAP_SUPPORT +#define CHAP_MD5_WITHPEER 0x40 +#define CHAP_MD5_PEER 0x80 +#if MSCHAP_SUPPORT +#define CHAP_MS_SHIFT 8 /* LSB position for MS auths */ +#define CHAP_MS_WITHPEER 0x100 +#define CHAP_MS_PEER 0x200 +#define CHAP_MS2_WITHPEER 0x400 +#define CHAP_MS2_PEER 0x800 +#endif /* MSCHAP_SUPPORT */ +#endif /* CHAP_SUPPORT */ + +/* Supported CHAP protocols */ +#if CHAP_SUPPORT + +#if MSCHAP_SUPPORT +#define CHAP_MDTYPE_SUPPORTED (MDTYPE_MICROSOFT_V2 | MDTYPE_MICROSOFT | MDTYPE_MD5) +#else /* MSCHAP_SUPPORT */ +#define CHAP_MDTYPE_SUPPORTED (MDTYPE_MD5) +#endif /* MSCHAP_SUPPORT */ + +#else /* CHAP_SUPPORT */ +#define CHAP_MDTYPE_SUPPORTED (MDTYPE_NONE) +#endif /* CHAP_SUPPORT */ + +#if PPP_STATS_SUPPORT +/* + * PPP statistics structure + */ +struct pppd_stats { + unsigned int bytes_in; + unsigned int bytes_out; + unsigned int pkts_in; + unsigned int pkts_out; +}; +#endif /* PPP_STATS_SUPPORT */ + + +/* + * PPP private functions + */ + +/* + * Functions called from lwIP core. + */ + +/* initialize the PPP subsystem */ +int ppp_init(void); + + +/* + * Functions called from PPP link protocols. + */ + +/* Create a new PPP control block */ +ppp_pcb *ppp_new(struct netif *pppif, const struct link_callbacks *callbacks, void *link_ctx_cb, + ppp_link_status_cb_fn link_status_cb, void *ctx_cb); + +/* Set a PPP PCB to its initial state */ +void ppp_clear(ppp_pcb *pcb); + +/* Initiate LCP open request */ +void ppp_start(ppp_pcb *pcb); + +/* Called when link failed to setup */ +void ppp_link_failed(ppp_pcb *pcb); + +/* Called when link is normally down (i.e. it was asked to end) */ +void ppp_link_end(ppp_pcb *pcb); + +/* function called to process input packet */ +void ppp_input(ppp_pcb *pcb, struct pbuf *pb); + +/* helper function, merge a pbuf chain into one pbuf */ +struct pbuf *ppp_singlebuf(struct pbuf *p); + + +/* + * Functions called by PPP protocols. + */ + +/* function called by all PPP subsystems to send packets */ +err_t ppp_write(ppp_pcb *pcb, struct pbuf *p); + +/* functions called by auth.c link_terminated() */ +void ppp_link_terminated(ppp_pcb *pcb); + +void new_phase(ppp_pcb *pcb, int p); + +int ppp_send_config(ppp_pcb *pcb, int mtu, u32_t accm, int pcomp, int accomp); +int ppp_recv_config(ppp_pcb *pcb, int mru, u32_t accm, int pcomp, int accomp); + +#if PPP_IPV4_SUPPORT +int sifaddr(ppp_pcb *pcb, u32_t our_adr, u32_t his_adr, u32_t netmask); +int cifaddr(ppp_pcb *pcb, u32_t our_adr, u32_t his_adr); +#if 0 /* UNUSED - PROXY ARP */ +int sifproxyarp(ppp_pcb *pcb, u32_t his_adr); +int cifproxyarp(ppp_pcb *pcb, u32_t his_adr); +#endif /* UNUSED - PROXY ARP */ +#if LWIP_DNS +int sdns(ppp_pcb *pcb, u32_t ns1, u32_t ns2); +int cdns(ppp_pcb *pcb, u32_t ns1, u32_t ns2); +#endif /* LWIP_DNS */ +#if VJ_SUPPORT +int sifvjcomp(ppp_pcb *pcb, int vjcomp, int cidcomp, int maxcid); +#endif /* VJ_SUPPORT */ +int sifup(ppp_pcb *pcb); +int sifdown (ppp_pcb *pcb); +u32_t get_mask(u32_t addr); +#endif /* PPP_IPV4_SUPPORT */ + +#if PPP_IPV6_SUPPORT +int sif6addr(ppp_pcb *pcb, eui64_t our_eui64, eui64_t his_eui64); +int cif6addr(ppp_pcb *pcb, eui64_t our_eui64, eui64_t his_eui64); +int sif6up(ppp_pcb *pcb); +int sif6down (ppp_pcb *pcb); +#endif /* PPP_IPV6_SUPPORT */ + +#if DEMAND_SUPPORT +int sifnpmode(ppp_pcb *pcb, int proto, enum NPmode mode); +#endif /* DEMAND_SUPPORt */ + +void netif_set_mtu(ppp_pcb *pcb, int mtu); +int netif_get_mtu(ppp_pcb *pcb); + +#if CCP_SUPPORT +#if 0 /* unused */ +int ccp_test(ppp_pcb *pcb, u_char *opt_ptr, int opt_len, int for_transmit); +#endif /* unused */ +void ccp_set(ppp_pcb *pcb, u8_t isopen, u8_t isup, u8_t receive_method, u8_t transmit_method); +void ccp_reset_comp(ppp_pcb *pcb); +void ccp_reset_decomp(ppp_pcb *pcb); +#if 0 /* unused */ +int ccp_fatal_error(ppp_pcb *pcb); +#endif /* unused */ +#endif /* CCP_SUPPORT */ + +#if PPP_IDLETIMELIMIT +int get_idle_time(ppp_pcb *pcb, struct ppp_idle *ip); +#endif /* PPP_IDLETIMELIMIT */ + +#if DEMAND_SUPPORT +int get_loop_output(void); +#endif /* DEMAND_SUPPORT */ + +/* Optional protocol names list, to make our messages a little more informative. */ +#if PPP_PROTOCOLNAME +const char * protocol_name(int proto); +#endif /* PPP_PROTOCOLNAME */ + +/* Optional stats support, to get some statistics on the PPP interface */ +#if PPP_STATS_SUPPORT +void print_link_stats(void); /* Print stats, if available */ +void reset_link_stats(int u); /* Reset (init) stats when link goes up */ +void update_link_stats(int u); /* Get stats at link termination */ +#endif /* PPP_STATS_SUPPORT */ + + + +/* + * Inline versions of get/put char/short/long. + * Pointer is advanced; we assume that both arguments + * are lvalues and will already be in registers. + * cp MUST be u_char *. + */ +#define GETCHAR(c, cp) { \ + (c) = *(cp)++; \ +} +#define PUTCHAR(c, cp) { \ + *(cp)++ = (u_char) (c); \ +} +#define GETSHORT(s, cp) { \ + (s) = *(cp)++ << 8; \ + (s) |= *(cp)++; \ +} +#define PUTSHORT(s, cp) { \ + *(cp)++ = (u_char) ((s) >> 8); \ + *(cp)++ = (u_char) (s); \ +} +#define GETLONG(l, cp) { \ + (l) = *(cp)++ << 8; \ + (l) |= *(cp)++; (l) <<= 8; \ + (l) |= *(cp)++; (l) <<= 8; \ + (l) |= *(cp)++; \ +} +#define PUTLONG(l, cp) { \ + *(cp)++ = (u_char) ((l) >> 24); \ + *(cp)++ = (u_char) ((l) >> 16); \ + *(cp)++ = (u_char) ((l) >> 8); \ + *(cp)++ = (u_char) (l); \ +} + +#define INCPTR(n, cp) ((cp) += (n)) +#define DECPTR(n, cp) ((cp) -= (n)) + +/* + * System dependent definitions for user-level 4.3BSD UNIX implementation. + */ +#define TIMEOUT(f, a, t) do { sys_untimeout((f), (a)); sys_timeout((t)*1000, (f), (a)); } while(0) +#define TIMEOUTMS(f, a, t) do { sys_untimeout((f), (a)); sys_timeout((t), (f), (a)); } while(0) +#define UNTIMEOUT(f, a) sys_untimeout((f), (a)) + +#define BZERO(s, n) memset(s, 0, n) +#define BCMP(s1, s2, l) memcmp(s1, s2, l) + +#define PRINTMSG(m, l) { ppp_info("Remote message: %0.*v", l, m); } + +/* + * MAKEHEADER - Add Header fields to a packet. + */ +#define MAKEHEADER(p, t) { \ + PUTCHAR(PPP_ALLSTATIONS, p); \ + PUTCHAR(PPP_UI, p); \ + PUTSHORT(t, p); } + +/* Procedures exported from auth.c */ +void link_required(ppp_pcb *pcb); /* we are starting to use the link */ +void link_terminated(ppp_pcb *pcb); /* we are finished with the link */ +void link_down(ppp_pcb *pcb); /* the LCP layer has left the Opened state */ +void upper_layers_down(ppp_pcb *pcb); /* take all NCPs down */ +void link_established(ppp_pcb *pcb); /* the link is up; authenticate now */ +void start_networks(ppp_pcb *pcb); /* start all the network control protos */ +void continue_networks(ppp_pcb *pcb); /* start network [ip, etc] control protos */ +#if PPP_AUTH_SUPPORT +#if PPP_SERVER +int auth_check_passwd(ppp_pcb *pcb, char *auser, int userlen, char *apasswd, int passwdlen, const char **msg, int *msglen); + /* check the user name and passwd against configuration */ +void auth_peer_fail(ppp_pcb *pcb, int protocol); + /* peer failed to authenticate itself */ +void auth_peer_success(ppp_pcb *pcb, int protocol, int prot_flavor, const char *name, int namelen); + /* peer successfully authenticated itself */ +#endif /* PPP_SERVER */ +void auth_withpeer_fail(ppp_pcb *pcb, int protocol); + /* we failed to authenticate ourselves */ +void auth_withpeer_success(ppp_pcb *pcb, int protocol, int prot_flavor); + /* we successfully authenticated ourselves */ +#endif /* PPP_AUTH_SUPPORT */ +void np_up(ppp_pcb *pcb, int proto); /* a network protocol has come up */ +void np_down(ppp_pcb *pcb, int proto); /* a network protocol has gone down */ +void np_finished(ppp_pcb *pcb, int proto); /* a network protocol no longer needs link */ +#if PPP_AUTH_SUPPORT +int get_secret(ppp_pcb *pcb, const char *client, const char *server, char *secret, int *secret_len, int am_server); + /* get "secret" for chap */ +#endif /* PPP_AUTH_SUPPORT */ + +/* Procedures exported from ipcp.c */ +/* int parse_dotted_ip (char *, u32_t *); */ + +/* Procedures exported from demand.c */ +#if DEMAND_SUPPORT +void demand_conf (void); /* config interface(s) for demand-dial */ +void demand_block (void); /* set all NPs to queue up packets */ +void demand_unblock (void); /* set all NPs to pass packets */ +void demand_discard (void); /* set all NPs to discard packets */ +void demand_rexmit (int, u32_t); /* retransmit saved frames for an NP*/ +int loop_chars (unsigned char *, int); /* process chars from loopback */ +int loop_frame (unsigned char *, int); /* should we bring link up? */ +#endif /* DEMAND_SUPPORT */ + +/* Procedures exported from multilink.c */ +#ifdef HAVE_MULTILINK +void mp_check_options (void); /* Check multilink-related options */ +int mp_join_bundle (void); /* join our link to an appropriate bundle */ +void mp_exit_bundle (void); /* have disconnected our link from bundle */ +void mp_bundle_terminated (void); +char *epdisc_to_str (struct epdisc *); /* string from endpoint discrim. */ +int str_to_epdisc (struct epdisc *, char *); /* endpt disc. from str */ +#else +#define mp_bundle_terminated() /* nothing */ +#define mp_exit_bundle() /* nothing */ +#define doing_multilink 0 +#define multilink_master 0 +#endif + +/* Procedures exported from utils.c. */ +void ppp_print_string(const u_char *p, int len, void (*printer) (void *, const char *, ...), void *arg); /* Format a string for output */ +int ppp_slprintf(char *buf, int buflen, const char *fmt, ...); /* sprintf++ */ +int ppp_vslprintf(char *buf, int buflen, const char *fmt, va_list args); /* vsprintf++ */ +size_t ppp_strlcpy(char *dest, const char *src, size_t len); /* safe strcpy */ +size_t ppp_strlcat(char *dest, const char *src, size_t len); /* safe strncpy */ +void ppp_dbglog(const char *fmt, ...); /* log a debug message */ +void ppp_info(const char *fmt, ...); /* log an informational message */ +void ppp_notice(const char *fmt, ...); /* log a notice-level message */ +void ppp_warn(const char *fmt, ...); /* log a warning message */ +void ppp_error(const char *fmt, ...); /* log an error message */ +void ppp_fatal(const char *fmt, ...); /* log an error message and die(1) */ +#if PRINTPKT_SUPPORT +void ppp_dump_packet(const char *tag, unsigned char *p, int len); + /* dump packet to debug log if interesting */ +#endif /* PRINTPKT_SUPPORT */ + + +#endif /* PPP_SUPPORT */ +#endif /* LWIP_HDR_PPP_IMPL_H */ diff --git a/components/lwip/include/lwip/netif/ppp/pppcrypt.h b/components/lwip/include/lwip/netif/ppp/pppcrypt.h new file mode 100755 index 0000000000..ef2e87de11 --- /dev/null +++ b/components/lwip/include/lwip/netif/ppp/pppcrypt.h @@ -0,0 +1,43 @@ +/* + * pppcrypt.c - PPP/DES linkage for MS-CHAP and EAP SRP-SHA1 + * + * Extracted from chap_ms.c by James Carlson. + * + * Copyright (c) 1995 Eric Rosenquist. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. The name(s) of the authors of this software must not be used to + * endorse or promote products derived from this software without + * prior written permission. + * + * THE AUTHORS OF THIS SOFTWARE DISCLAIM ALL WARRANTIES WITH REGARD TO + * THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS, IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY + * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN + * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING + * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include "lwip/opt.h" +#if PPP_SUPPORT && MSCHAP_SUPPORT /* don't build if not configured for use in lwipopts.h */ + +#ifndef PPPCRYPT_H +#define PPPCRYPT_H + +void pppcrypt_56_to_64_bit_key(u_char *key, u_char *des_key); + +#endif /* PPPCRYPT_H */ + +#endif /* PPP_SUPPORT && MSCHAP_SUPPORT */ diff --git a/components/lwip/include/lwip/netif/ppp/pppdebug.h b/components/lwip/include/lwip/netif/ppp/pppdebug.h new file mode 100755 index 0000000000..e35c8e090d --- /dev/null +++ b/components/lwip/include/lwip/netif/ppp/pppdebug.h @@ -0,0 +1,80 @@ +/***************************************************************************** +* pppdebug.h - System debugging utilities. +* +* Copyright (c) 2003 by Marc Boucher, Services Informatiques (MBSI) inc. +* portions Copyright (c) 1998 Global Election Systems Inc. +* portions Copyright (c) 2001 by Cognizant Pty Ltd. +* +* The authors hereby grant permission to use, copy, modify, distribute, +* and license this software and its documentation for any purpose, provided +* that existing copyright notices are retained in all copies and that this +* notice and the following disclaimer are included verbatim in any +* distributions. No written agreement, license, or royalty fee is required +* for any of the authorized uses. +* +* THIS SOFTWARE IS PROVIDED BY THE CONTRIBUTORS *AS IS* AND ANY EXPRESS OR +* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES +* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +* IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF +* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +* +****************************************************************************** +* REVISION HISTORY (please don't use tabs!) +* +* 03-01-01 Marc Boucher +* Ported to lwIP. +* 98-07-29 Guy Lancaster , Global Election Systems Inc. +* Original. +* +***************************************************************************** +*/ + +#include "lwip/opt.h" +#if PPP_SUPPORT /* don't build if not configured for use in lwipopts.h */ + +#ifndef PPPDEBUG_H +#define PPPDEBUG_H + +/* Trace levels. */ +#define LOG_CRITICAL (PPP_DEBUG | LWIP_DBG_LEVEL_SEVERE) +#define LOG_ERR (PPP_DEBUG | LWIP_DBG_LEVEL_SEVERE) +#define LOG_NOTICE (PPP_DEBUG | LWIP_DBG_LEVEL_WARNING) +#define LOG_WARNING (PPP_DEBUG | LWIP_DBG_LEVEL_WARNING) +#define LOG_INFO (PPP_DEBUG) +#define LOG_DETAIL (PPP_DEBUG) +#define LOG_DEBUG (PPP_DEBUG) + +#if PPP_DEBUG + +#define MAINDEBUG(a) LWIP_DEBUGF(LWIP_DBG_LEVEL_WARNING, a) +#define SYSDEBUG(a) LWIP_DEBUGF(LWIP_DBG_LEVEL_WARNING, a) +#define FSMDEBUG(a) LWIP_DEBUGF(LWIP_DBG_LEVEL_WARNING, a) +#define LCPDEBUG(a) LWIP_DEBUGF(LWIP_DBG_LEVEL_WARNING, a) +#define IPCPDEBUG(a) LWIP_DEBUGF(LWIP_DBG_LEVEL_WARNING, a) +#define IPV6CPDEBUG(a) LWIP_DEBUGF(LWIP_DBG_LEVEL_WARNING, a) +#define UPAPDEBUG(a) LWIP_DEBUGF(LWIP_DBG_LEVEL_WARNING, a) +#define CHAPDEBUG(a) LWIP_DEBUGF(LWIP_DBG_LEVEL_WARNING, a) +#define PPPDEBUG(a, b) LWIP_DEBUGF(a, b) + +#else /* PPP_DEBUG */ + +#define MAINDEBUG(a) +#define SYSDEBUG(a) +#define FSMDEBUG(a) +#define LCPDEBUG(a) +#define IPCPDEBUG(a) +#define IPV6CPDEBUG(a) +#define UPAPDEBUG(a) +#define CHAPDEBUG(a) +#define PPPDEBUG(a, b) + +#endif /* PPP_DEBUG */ + +#endif /* PPPDEBUG_H */ + +#endif /* PPP_SUPPORT */ diff --git a/components/lwip/include/lwip/netif/ppp/pppoe.h b/components/lwip/include/lwip/netif/ppp/pppoe.h new file mode 100755 index 0000000000..b1dd2fd9c5 --- /dev/null +++ b/components/lwip/include/lwip/netif/ppp/pppoe.h @@ -0,0 +1,179 @@ +/***************************************************************************** +* pppoe.h - PPP Over Ethernet implementation for lwIP. +* +* Copyright (c) 2006 by Marc Boucher, Services Informatiques (MBSI) inc. +* +* The authors hereby grant permission to use, copy, modify, distribute, +* and license this software and its documentation for any purpose, provided +* that existing copyright notices are retained in all copies and that this +* notice and the following disclaimer are included verbatim in any +* distributions. No written agreement, license, or royalty fee is required +* for any of the authorized uses. +* +* THIS SOFTWARE IS PROVIDED BY THE CONTRIBUTORS *AS IS* AND ANY EXPRESS OR +* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES +* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +* IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF +* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +* +****************************************************************************** +* REVISION HISTORY +* +* 06-01-01 Marc Boucher +* Ported to lwIP. +*****************************************************************************/ + + + +/* based on NetBSD: if_pppoe.c,v 1.64 2006/01/31 23:50:15 martin Exp */ + +/*- + * Copyright (c) 2002 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by Martin Husemann . + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the NetBSD + * Foundation, Inc. and its contributors. + * 4. Neither the name of The NetBSD Foundation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ +#include "lwip/opt.h" +#if PPP_SUPPORT && PPPOE_SUPPORT /* don't build if not configured for use in lwipopts.h */ + +#ifndef PPP_OE_H +#define PPP_OE_H + +#include "ppp.h" +#include "netif/etharp.h" + +#ifdef PACK_STRUCT_USE_INCLUDES +# include "arch/bpstruct.h" +#endif +PACK_STRUCT_BEGIN +struct pppoehdr { + PACK_STRUCT_FLD_8(u8_t vertype); + PACK_STRUCT_FLD_8(u8_t code); + PACK_STRUCT_FIELD(u16_t session); + PACK_STRUCT_FIELD(u16_t plen); +} PACK_STRUCT_STRUCT; +PACK_STRUCT_END +#ifdef PACK_STRUCT_USE_INCLUDES +# include "arch/epstruct.h" +#endif + +#ifdef PACK_STRUCT_USE_INCLUDES +# include "arch/bpstruct.h" +#endif +PACK_STRUCT_BEGIN +struct pppoetag { + PACK_STRUCT_FIELD(u16_t tag); + PACK_STRUCT_FIELD(u16_t len); +} PACK_STRUCT_STRUCT; +PACK_STRUCT_END +#ifdef PACK_STRUCT_USE_INCLUDES +# include "arch/epstruct.h" +#endif + + +#define PPPOE_STATE_INITIAL 0 +#define PPPOE_STATE_PADI_SENT 1 +#define PPPOE_STATE_PADR_SENT 2 +#define PPPOE_STATE_SESSION 3 +/* passive */ +#define PPPOE_STATE_PADO_SENT 1 + +#define PPPOE_HEADERLEN sizeof(struct pppoehdr) +#define PPPOE_VERTYPE 0x11 /* VER=1, TYPE = 1 */ + +#define PPPOE_TAG_EOL 0x0000 /* end of list */ +#define PPPOE_TAG_SNAME 0x0101 /* service name */ +#define PPPOE_TAG_ACNAME 0x0102 /* access concentrator name */ +#define PPPOE_TAG_HUNIQUE 0x0103 /* host unique */ +#define PPPOE_TAG_ACCOOKIE 0x0104 /* AC cookie */ +#define PPPOE_TAG_VENDOR 0x0105 /* vendor specific */ +#define PPPOE_TAG_RELAYSID 0x0110 /* relay session id */ +#define PPPOE_TAG_SNAME_ERR 0x0201 /* service name error */ +#define PPPOE_TAG_ACSYS_ERR 0x0202 /* AC system error */ +#define PPPOE_TAG_GENERIC_ERR 0x0203 /* gerneric error */ + +#define PPPOE_CODE_PADI 0x09 /* Active Discovery Initiation */ +#define PPPOE_CODE_PADO 0x07 /* Active Discovery Offer */ +#define PPPOE_CODE_PADR 0x19 /* Active Discovery Request */ +#define PPPOE_CODE_PADS 0x65 /* Active Discovery Session confirmation */ +#define PPPOE_CODE_PADT 0xA7 /* Active Discovery Terminate */ + +#ifndef PPPOE_MAX_AC_COOKIE_LEN +#define PPPOE_MAX_AC_COOKIE_LEN 64 +#endif + +struct pppoe_softc { + struct pppoe_softc *next; + struct netif *sc_ethif; /* ethernet interface we are using */ + ppp_pcb *pcb; /* PPP PCB */ + + struct eth_addr sc_dest; /* hardware address of concentrator */ + u16_t sc_session; /* PPPoE session id */ + u8_t sc_state; /* discovery phase or session connected */ + +#ifdef PPPOE_TODO + u8_t *sc_service_name; /* if != NULL: requested name of service */ + u8_t *sc_concentrator_name; /* if != NULL: requested concentrator id */ +#endif /* PPPOE_TODO */ + u8_t sc_ac_cookie[PPPOE_MAX_AC_COOKIE_LEN]; /* content of AC cookie we must echo back */ + u8_t sc_ac_cookie_len; /* length of cookie data */ +#ifdef PPPOE_SERVER + u8_t *sc_hunique; /* content of host unique we must echo back */ + u8_t sc_hunique_len; /* length of host unique */ +#endif + u8_t sc_padi_retried; /* number of PADI retries already done */ + u8_t sc_padr_retried; /* number of PADR retries already done */ +}; + + +#define pppoe_init() /* compatibility define, no initialization needed */ + +ppp_pcb *pppoe_create(struct netif *pppif, + struct netif *ethif, + const char *service_name, const char *concentrator_name, + ppp_link_status_cb_fn link_status_cb, void *ctx_cb); + +/* + * Functions called from lwIP + * DO NOT CALL FROM lwIP USER APPLICATION. + */ +void pppoe_disc_input(struct netif *netif, struct pbuf *p); +void pppoe_data_input(struct netif *netif, struct pbuf *p); + +#endif /* PPP_OE_H */ + +#endif /* PPP_SUPPORT && PPPOE_SUPPORT */ diff --git a/components/lwip/include/lwip/netif/ppp/pppol2tp.h b/components/lwip/include/lwip/netif/ppp/pppol2tp.h new file mode 100755 index 0000000000..097b4d1891 --- /dev/null +++ b/components/lwip/include/lwip/netif/ppp/pppol2tp.h @@ -0,0 +1,201 @@ +/** + * @file + * Network Point to Point Protocol over Layer 2 Tunneling Protocol header file. + * + */ + +/* + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + */ + +#include "lwip/opt.h" +#if PPP_SUPPORT && PPPOL2TP_SUPPORT /* don't build if not configured for use in lwipopts.h */ + +#ifndef PPPOL2TP_H_ +#define PPPOL2TP_H_ + +#include "ppp.h" + +/* Timeout */ +#define PPPOL2TP_CONTROL_TIMEOUT (5*1000) /* base for quick timeout calculation */ +#define PPPOL2TP_SLOW_RETRY (60*1000) /* persistent retry interval */ + +#define PPPOL2TP_MAXSCCRQ 4 /* retry SCCRQ four times (quickly) */ +#define PPPOL2TP_MAXICRQ 4 /* retry IRCQ four times */ +#define PPPOL2TP_MAXICCN 4 /* retry ICCN four times */ + +/* L2TP header flags */ +#define PPPOL2TP_HEADERFLAG_CONTROL 0x8000 +#define PPPOL2TP_HEADERFLAG_LENGTH 0x4000 +#define PPPOL2TP_HEADERFLAG_SEQUENCE 0x0800 +#define PPPOL2TP_HEADERFLAG_OFFSET 0x0200 +#define PPPOL2TP_HEADERFLAG_PRIORITY 0x0100 +#define PPPOL2TP_HEADERFLAG_VERSION 0x0002 + +/* Mandatory bits for control: Control, Length, Sequence, Version 2 */ +#define PPPOL2TP_HEADERFLAG_CONTROL_MANDATORY (PPPOL2TP_HEADERFLAG_CONTROL|PPPOL2TP_HEADERFLAG_LENGTH|PPPOL2TP_HEADERFLAG_SEQUENCE|PPPOL2TP_HEADERFLAG_VERSION) +/* Forbidden bits for control: Offset, Priority */ +#define PPPOL2TP_HEADERFLAG_CONTROL_FORBIDDEN (PPPOL2TP_HEADERFLAG_OFFSET|PPPOL2TP_HEADERFLAG_PRIORITY) + +/* Mandatory bits for data: Version 2 */ +#define PPPOL2TP_HEADERFLAG_DATA_MANDATORY (PPPOL2TP_HEADERFLAG_VERSION) + +/* AVP (Attribute Value Pair) header */ +#define PPPOL2TP_AVPHEADERFLAG_MANDATORY 0x8000 +#define PPPOL2TP_AVPHEADERFLAG_HIDDEN 0x4000 +#define PPPOL2TP_AVPHEADERFLAG_LENGTHMASK 0x03ff + +/* -- AVP - Message type */ +#define PPPOL2TP_AVPTYPE_MESSAGE 0 /* Message type */ + +/* Control Connection Management */ +#define PPPOL2TP_MESSAGETYPE_SCCRQ 1 /* Start Control Connection Request */ +#define PPPOL2TP_MESSAGETYPE_SCCRP 2 /* Start Control Connection Reply */ +#define PPPOL2TP_MESSAGETYPE_SCCCN 3 /* Start Control Connection Connected */ +#define PPPOL2TP_MESSAGETYPE_STOPCCN 4 /* Stop Control Connection Notification */ +#define PPPOL2TP_MESSAGETYPE_HELLO 6 /* Hello */ +/* Call Management */ +#define PPPOL2TP_MESSAGETYPE_OCRQ 7 /* Outgoing Call Request */ +#define PPPOL2TP_MESSAGETYPE_OCRP 8 /* Outgoing Call Reply */ +#define PPPOL2TP_MESSAGETYPE_OCCN 9 /* Outgoing Call Connected */ +#define PPPOL2TP_MESSAGETYPE_ICRQ 10 /* Incoming Call Request */ +#define PPPOL2TP_MESSAGETYPE_ICRP 11 /* Incoming Call Reply */ +#define PPPOL2TP_MESSAGETYPE_ICCN 12 /* Incoming Call Connected */ +#define PPPOL2TP_MESSAGETYPE_CDN 14 /* Call Disconnect Notify */ +/* Error reporting */ +#define PPPOL2TP_MESSAGETYPE_WEN 15 /* WAN Error Notify */ +/* PPP Session Control */ +#define PPPOL2TP_MESSAGETYPE_SLI 16 /* Set Link Info */ + +/* -- AVP - Result code */ +#define PPPOL2TP_AVPTYPE_RESULTCODE 1 /* Result code */ +#define PPPOL2TP_RESULTCODE 1 /* General request to clear control connection */ + +/* -- AVP - Protocol version (!= L2TP Header version) */ +#define PPPOL2TP_AVPTYPE_VERSION 2 +#define PPPOL2TP_VERSION 0x0100 /* L2TP Protocol version 1, revision 0 */ + +/* -- AVP - Framing capabilities */ +#define PPPOL2TP_AVPTYPE_FRAMINGCAPABILITIES 3 /* Bearer capabilities */ +#define PPPOL2TP_FRAMINGCAPABILITIES 0x00000003 /* Async + Sync framing */ + +/* -- AVP - Bearer capabilities */ +#define PPPOL2TP_AVPTYPE_BEARERCAPABILITIES 4 /* Bearer capabilities */ +#define PPPOL2TP_BEARERCAPABILITIES 0x00000003 /* Analog + Digital Access */ + +/* -- AVP - Tie breaker */ +#define PPPOL2TP_AVPTYPE_TIEBREAKER 5 + +/* -- AVP - Host name */ +#define PPPOL2TP_AVPTYPE_HOSTNAME 7 /* Host name */ +#define PPPOL2TP_HOSTNAME "lwIP" /* FIXME: make it configurable */ + +/* -- AVP - Vendor name */ +#define PPPOL2TP_AVPTYPE_VENDORNAME 8 /* Vendor name */ +#define PPPOL2TP_VENDORNAME "lwIP" /* FIXME: make it configurable */ + +/* -- AVP - Assign tunnel ID */ +#define PPPOL2TP_AVPTYPE_TUNNELID 9 /* Assign Tunnel ID */ + +/* -- AVP - Receive window size */ +#define PPPOL2TP_AVPTYPE_RECEIVEWINDOWSIZE 10 /* Receive window size */ +#define PPPOL2TP_RECEIVEWINDOWSIZE 8 /* FIXME: make it configurable */ + +/* -- AVP - Challenge */ +#define PPPOL2TP_AVPTYPE_CHALLENGE 11 /* Challenge */ + +/* -- AVP - Cause code */ +#define PPPOL2TP_AVPTYPE_CAUSECODE 12 /* Cause code*/ + +/* -- AVP - Challenge response */ +#define PPPOL2TP_AVPTYPE_CHALLENGERESPONSE 13 /* Challenge response */ +#define PPPOL2TP_AVPTYPE_CHALLENGERESPONSE_SIZE 16 + +/* -- AVP - Assign session ID */ +#define PPPOL2TP_AVPTYPE_SESSIONID 14 /* Assign Session ID */ + +/* -- AVP - Call serial number */ +#define PPPOL2TP_AVPTYPE_CALLSERIALNUMBER 15 /* Call Serial Number */ + +/* -- AVP - Framing type */ +#define PPPOL2TP_AVPTYPE_FRAMINGTYPE 19 /* Framing Type */ +#define PPPOL2TP_FRAMINGTYPE 0x00000001 /* Sync framing */ + +/* -- AVP - TX Connect Speed */ +#define PPPOL2TP_AVPTYPE_TXCONNECTSPEED 24 /* TX Connect Speed */ +#define PPPOL2TP_TXCONNECTSPEED 100000000 /* Connect speed: 100 Mbits/s */ + +/* L2TP Session state */ +#define PPPOL2TP_STATE_INITIAL 0 +#define PPPOL2TP_STATE_SCCRQ_SENT 1 +#define PPPOL2TP_STATE_ICRQ_SENT 2 +#define PPPOL2TP_STATE_ICCN_SENT 3 +#define PPPOL2TP_STATE_DATA 4 + +#define PPPOL2TP_OUTPUT_DATA_HEADER_LEN 6 /* Our data header len */ + +/* + * PPPoL2TP interface control block. + */ +typedef struct pppol2tp_pcb_s pppol2tp_pcb; +struct pppol2tp_pcb_s { + ppp_pcb *ppp; /* PPP PCB */ + u8_t phase; /* L2TP phase */ + struct udp_pcb *udp; /* UDP L2TP Socket */ + struct netif *netif; /* Output interface, used as a default route */ + ip_addr_t remote_ip; /* LNS IP Address */ + u16_t remote_port; /* LNS port */ +#if PPPOL2TP_AUTH_SUPPORT + const u8_t *secret; /* Secret string */ + u8_t secret_len; /* Secret string length */ + u8_t secret_rv[16]; /* Random vector */ + u8_t challenge_hash[16]; /* Challenge response */ + u8_t send_challenge; /* Boolean whether the next sent packet should contains a challenge response */ +#endif /* PPPOL2TP_AUTH_SUPPORT */ + + u16_t tunnel_port; /* Tunnel port */ + u16_t our_ns; /* NS to peer */ + u16_t peer_nr; /* NR from peer */ + u16_t peer_ns; /* NS from peer */ + u16_t source_tunnel_id; /* Tunnel ID assigned by peer */ + u16_t remote_tunnel_id; /* Tunnel ID assigned to peer */ + u16_t source_session_id; /* Session ID assigned by peer */ + u16_t remote_session_id; /* Session ID assigned to peer */ + + u8_t sccrq_retried; /* number of SCCRQ retries already done */ + u8_t icrq_retried; /* number of ICRQ retries already done */ + u8_t iccn_retried; /* number of ICCN retries already done */ +}; + + +/* Create a new L2TP session. */ +ppp_pcb *pppol2tp_create(struct netif *pppif, + struct netif *netif, ip_addr_t *ipaddr, u16_t port, + const u8_t *secret, u8_t secret_len, + ppp_link_status_cb_fn link_status_cb, void *ctx_cb); + +#endif /* PPPOL2TP_H_ */ +#endif /* PPP_SUPPORT && PPPOL2TP_SUPPORT */ diff --git a/components/lwip/include/lwip/netif/ppp/pppos.h b/components/lwip/include/lwip/netif/ppp/pppos.h new file mode 100755 index 0000000000..39b2b7d0c3 --- /dev/null +++ b/components/lwip/include/lwip/netif/ppp/pppos.h @@ -0,0 +1,119 @@ +/** + * @file + * Network Point to Point Protocol over Serial header file. + * + */ + +/* + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + */ + +#include "lwip/opt.h" +#if PPP_SUPPORT && PPPOS_SUPPORT /* don't build if not configured for use in lwipopts.h */ + +#ifndef PPPOS_H +#define PPPOS_H + +#include "lwip/sys.h" +#include "lwip/sio.h" + +#include "ppp.h" +#include "vj.h" + +/* PPP packet parser states. Current state indicates operation yet to be + * completed. */ +enum { + PDIDLE = 0, /* Idle state - waiting. */ + PDSTART, /* Process start flag. */ + PDADDRESS, /* Process address field. */ + PDCONTROL, /* Process control field. */ + PDPROTOCOL1, /* Process protocol field 1. */ + PDPROTOCOL2, /* Process protocol field 2. */ + PDDATA /* Process data byte. */ +}; + +/* PPPoS serial output callback function prototype */ +typedef u32_t (*pppos_output_cb_fn)(ppp_pcb *pcb, u8_t *data, u32_t len, void *ctx); + +/* + * Extended asyncmap - allows any character to be escaped. + */ +typedef u8_t ext_accm[32]; + +/* + * PPPoS interface control block. + */ +typedef struct pppos_pcb_s pppos_pcb; +struct pppos_pcb_s { + /* -- below are data that will NOT be cleared between two sessions */ + ppp_pcb *ppp; /* PPP PCB */ + pppos_output_cb_fn output_cb; /* PPP serial output callback */ + + /* -- below are data that will be cleared between two sessions + * + * last_xmit must be the first member of cleared members, because it is + * used to know which part must not be cleared. + */ + u32_t last_xmit; /* Time of last transmission. */ + ext_accm out_accm; /* Async-Ctl-Char-Map for output. */ + + /* flags */ + unsigned int open :1; /* Set if PPPoS is open */ + unsigned int pcomp :1; /* Does peer accept protocol compression? */ + unsigned int accomp :1; /* Does peer accept addr/ctl compression? */ + + /* PPPoS rx */ + ext_accm in_accm; /* Async-Ctl-Char-Map for input. */ + struct pbuf *in_head, *in_tail; /* The input packet. */ + u16_t in_protocol; /* The input protocol code. */ + u16_t in_fcs; /* Input Frame Check Sequence value. */ + u8_t in_state; /* The input process state. */ + u8_t in_escaped; /* Escape next character. */ +}; + +/* Create a new PPPoS session. */ +ppp_pcb *pppos_create(struct netif *pppif, pppos_output_cb_fn output_cb, + ppp_link_status_cb_fn link_status_cb, void *ctx_cb); + +#if !NO_SYS && !PPP_INPROC_IRQ_SAFE +/* Pass received raw characters to PPPoS to be decoded through lwIP TCPIP thread. */ +err_t pppos_input_tcpip(ppp_pcb *ppp, u8_t *s, int l); +#endif /* !NO_SYS && !PPP_INPROC_IRQ_SAFE */ + +/* PPP over Serial: this is the input function to be called for received data. */ +void pppos_input(ppp_pcb *ppp, u8_t* data, int len); + + +/* + * Functions called from lwIP + * DO NOT CALL FROM lwIP USER APPLICATION. + */ +#if !NO_SYS && !PPP_INPROC_IRQ_SAFE +err_t pppos_input_sys(struct pbuf *p, struct netif *inp); +#endif /* !NO_SYS && !PPP_INPROC_IRQ_SAFE */ + +#endif /* PPPOS_H */ +#endif /* PPP_SUPPORT && PPPOL2TP_SUPPORT */ diff --git a/components/lwip/include/lwip/netif/ppp/upap.h b/components/lwip/include/lwip/netif/ppp/upap.h new file mode 100755 index 0000000000..bb9309bdb2 --- /dev/null +++ b/components/lwip/include/lwip/netif/ppp/upap.h @@ -0,0 +1,123 @@ +/* + * upap.h - User/Password Authentication Protocol definitions. + * + * Copyright (c) 1984-2000 Carnegie Mellon University. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. The name "Carnegie Mellon University" must not be used to + * endorse or promote products derived from this software without + * prior written permission. For permission or any legal + * details, please contact + * Office of Technology Transfer + * Carnegie Mellon University + * 5000 Forbes Avenue + * Pittsburgh, PA 15213-3890 + * (412) 268-4387, fax: (412) 268-7395 + * tech-transfer@andrew.cmu.edu + * + * 4. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by Computing Services + * at Carnegie Mellon University (http://www.cmu.edu/computing/)." + * + * CARNEGIE MELLON UNIVERSITY DISCLAIMS ALL WARRANTIES WITH REGARD TO + * THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS, IN NO EVENT SHALL CARNEGIE MELLON UNIVERSITY BE LIABLE + * FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN + * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING + * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * $Id: upap.h,v 1.8 2002/12/04 23:03:33 paulus Exp $ + */ + +#include "lwip/opt.h" +#if PPP_SUPPORT && PAP_SUPPORT /* don't build if not configured for use in lwipopts.h */ + +#ifndef UPAP_H +#define UPAP_H + +#include "ppp.h" + +/* + * Packet header = Code, id, length. + */ +#define UPAP_HEADERLEN 4 + + +/* + * UPAP codes. + */ +#define UPAP_AUTHREQ 1 /* Authenticate-Request */ +#define UPAP_AUTHACK 2 /* Authenticate-Ack */ +#define UPAP_AUTHNAK 3 /* Authenticate-Nak */ + + +/* + * Client states. + */ +#define UPAPCS_INITIAL 0 /* Connection down */ +#define UPAPCS_CLOSED 1 /* Connection up, haven't requested auth */ +#define UPAPCS_PENDING 2 /* Connection down, have requested auth */ +#define UPAPCS_AUTHREQ 3 /* We've sent an Authenticate-Request */ +#define UPAPCS_OPEN 4 /* We've received an Ack */ +#define UPAPCS_BADAUTH 5 /* We've received a Nak */ + +/* + * Server states. + */ +#define UPAPSS_INITIAL 0 /* Connection down */ +#define UPAPSS_CLOSED 1 /* Connection up, haven't requested auth */ +#define UPAPSS_PENDING 2 /* Connection down, have requested auth */ +#define UPAPSS_LISTEN 3 /* Listening for an Authenticate */ +#define UPAPSS_OPEN 4 /* We've sent an Ack */ +#define UPAPSS_BADAUTH 5 /* We've sent a Nak */ + + +/* + * Timeouts. + */ +#if 0 /* moved to opt.h */ +#define UPAP_DEFTIMEOUT 3 /* Timeout (seconds) for retransmitting req */ +#define UPAP_DEFREQTIME 30 /* Time to wait for auth-req from peer */ +#endif /* moved to opt.h */ + +/* + * Each interface is described by upap structure. + */ +#if PAP_SUPPORT +typedef struct upap_state { + const char *us_user; /* User */ + u8_t us_userlen; /* User length */ + const char *us_passwd; /* Password */ + u8_t us_passwdlen; /* Password length */ + u8_t us_clientstate; /* Client state */ +#if PPP_SERVER + u8_t us_serverstate; /* Server state */ +#endif /* PPP_SERVER */ + u8_t us_id; /* Current id */ + u8_t us_transmits; /* Number of auth-reqs sent */ +} upap_state; +#endif /* PAP_SUPPORT */ + + +void upap_authwithpeer(ppp_pcb *pcb, const char *user, const char *password); +#if PPP_SERVER +void upap_authpeer(ppp_pcb *pcb); +#endif /* PPP_SERVER */ + +extern const struct protent pap_protent; + +#endif /* UPAP_H */ +#endif /* PPP_SUPPORT && PAP_SUPPORT */ diff --git a/components/lwip/include/lwip/netif/ppp/vj.h b/components/lwip/include/lwip/netif/ppp/vj.h new file mode 100755 index 0000000000..f2e1f8b4bf --- /dev/null +++ b/components/lwip/include/lwip/netif/ppp/vj.h @@ -0,0 +1,161 @@ +/* + * Definitions for tcp compression routines. + * + * $Id: vj.h,v 1.7 2010/02/22 17:52:09 goldsimon Exp $ + * + * Copyright (c) 1989 Regents of the University of California. + * All rights reserved. + * + * Redistribution and use in source and binary forms are permitted + * provided that the above copyright notice and this paragraph are + * duplicated in all such forms and that any documentation, + * advertising materials, and other materials related to such + * distribution and use acknowledge that the software was developed + * by the University of California, Berkeley. The name of the + * University may not be used to endorse or promote products derived + * from this software without specific prior written permission. + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED + * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. + * + * Van Jacobson (van@helios.ee.lbl.gov), Dec 31, 1989: + * - Initial distribution. + */ + +#include "lwip/opt.h" +#if PPP_SUPPORT && VJ_SUPPORT /* don't build if not configured for use in lwipopts.h */ + +#ifndef VJ_H +#define VJ_H + +#include "lwip/ip.h" +#include "lwip/priv/tcp_priv.h" + +#define MAX_SLOTS 16 /* must be > 2 and < 256 */ +#define MAX_HDR 128 + +/* + * Compressed packet format: + * + * The first octet contains the packet type (top 3 bits), TCP + * 'push' bit, and flags that indicate which of the 4 TCP sequence + * numbers have changed (bottom 5 bits). The next octet is a + * conversation number that associates a saved IP/TCP header with + * the compressed packet. The next two octets are the TCP checksum + * from the original datagram. The next 0 to 15 octets are + * sequence number changes, one change per bit set in the header + * (there may be no changes and there are two special cases where + * the receiver implicitly knows what changed -- see below). + * + * There are 5 numbers which can change (they are always inserted + * in the following order): TCP urgent pointer, window, + * acknowlegement, sequence number and IP ID. (The urgent pointer + * is different from the others in that its value is sent, not the + * change in value.) Since typical use of SLIP links is biased + * toward small packets (see comments on MTU/MSS below), changes + * use a variable length coding with one octet for numbers in the + * range 1 - 255 and 3 octets (0, MSB, LSB) for numbers in the + * range 256 - 65535 or 0. (If the change in sequence number or + * ack is more than 65535, an uncompressed packet is sent.) + */ + +/* + * Packet types (must not conflict with IP protocol version) + * + * The top nibble of the first octet is the packet type. There are + * three possible types: IP (not proto TCP or tcp with one of the + * control flags set); uncompressed TCP (a normal IP/TCP packet but + * with the 8-bit protocol field replaced by an 8-bit connection id -- + * this type of packet syncs the sender & receiver); and compressed + * TCP (described above). + * + * LSB of 4-bit field is TCP "PUSH" bit (a worthless anachronism) and + * is logically part of the 4-bit "changes" field that follows. Top + * three bits are actual packet type. For backward compatibility + * and in the interest of conserving bits, numbers are chosen so the + * IP protocol version number (4) which normally appears in this nibble + * means "IP packet". + */ + +/* packet types */ +#define TYPE_IP 0x40 +#define TYPE_UNCOMPRESSED_TCP 0x70 +#define TYPE_COMPRESSED_TCP 0x80 +#define TYPE_ERROR 0x00 + +/* Bits in first octet of compressed packet */ +#define NEW_C 0x40 /* flag bits for what changed in a packet */ +#define NEW_I 0x20 +#define NEW_S 0x08 +#define NEW_A 0x04 +#define NEW_W 0x02 +#define NEW_U 0x01 + +/* reserved, special-case values of above */ +#define SPECIAL_I (NEW_S|NEW_W|NEW_U) /* echoed interactive traffic */ +#define SPECIAL_D (NEW_S|NEW_A|NEW_W|NEW_U) /* unidirectional data */ +#define SPECIALS_MASK (NEW_S|NEW_A|NEW_W|NEW_U) + +#define TCP_PUSH_BIT 0x10 + + +/* + * "state" data for each active tcp conversation on the wire. This is + * basically a copy of the entire IP/TCP header from the last packet + * we saw from the conversation together with a small identifier + * the transmit & receive ends of the line use to locate saved header. + */ +struct cstate { + struct cstate *cs_next; /* next most recently used state (xmit only) */ + u16_t cs_hlen; /* size of hdr (receive only) */ + u8_t cs_id; /* connection # associated with this state */ + u8_t cs_filler; + union { + char csu_hdr[MAX_HDR]; + struct ip_hdr csu_ip; /* ip/tcp hdr from most recent packet */ + } vjcs_u; +}; +#define cs_ip vjcs_u.csu_ip +#define cs_hdr vjcs_u.csu_hdr + + +struct vjstat { + u32_t vjs_packets; /* outbound packets */ + u32_t vjs_compressed; /* outbound compressed packets */ + u32_t vjs_searches; /* searches for connection state */ + u32_t vjs_misses; /* times couldn't find conn. state */ + u32_t vjs_uncompressedin; /* inbound uncompressed packets */ + u32_t vjs_compressedin; /* inbound compressed packets */ + u32_t vjs_errorin; /* inbound unknown type packets */ + u32_t vjs_tossed; /* inbound packets tossed because of error */ +}; + +/* + * all the state data for one serial line (we need one of these per line). + */ +struct vjcompress { + struct cstate *last_cs; /* most recently used tstate */ + u8_t last_recv; /* last rcvd conn. id */ + u8_t last_xmit; /* last sent conn. id */ + u16_t flags; + u8_t maxSlotIndex; + u8_t compressSlot; /* Flag indicating OK to compress slot ID. */ +#if LINK_STATS + struct vjstat stats; +#endif + struct cstate tstate[MAX_SLOTS]; /* xmit connection states */ + struct cstate rstate[MAX_SLOTS]; /* receive connection states */ +}; + +/* flag values */ +#define VJF_TOSS 1U /* tossing rcvd frames because of input err */ + +extern void vj_compress_init (struct vjcompress *comp); +extern u8_t vj_compress_tcp (struct vjcompress *comp, struct pbuf **pb); +extern void vj_uncompress_err (struct vjcompress *comp); +extern int vj_uncompress_uncomp(struct pbuf *nb, struct vjcompress *comp); +extern int vj_uncompress_tcp (struct pbuf **nb, struct vjcompress *comp); + +#endif /* VJ_H */ + +#endif /* PPP_SUPPORT && VJ_SUPPORT */ diff --git a/components/lwip/include/lwip/netif/slipif.h b/components/lwip/include/lwip/netif/slipif.h new file mode 100755 index 0000000000..d164d44860 --- /dev/null +++ b/components/lwip/include/lwip/netif/slipif.h @@ -0,0 +1,81 @@ +/* + * Copyright (c) 2001, Swedish Institute of Computer Science. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + * + */ +#ifndef LWIP_HDR_NETIF_SLIPIF_H +#define LWIP_HDR_NETIF_SLIPIF_H + +#include "lwip/opt.h" +#include "lwip/netif.h" + +/** Set this to 1 to start a thread that blocks reading on the serial line + * (using sio_read()). + */ +#ifndef SLIP_USE_RX_THREAD +#define SLIP_USE_RX_THREAD !NO_SYS +#endif + +/** Set this to 1 to enable functions to pass in RX bytes from ISR context. + * If enabled, slipif_received_byte[s]() process incoming bytes and put assembled + * packets on a queue, which is fed into lwIP from slipif_poll(). + * If disabled, slipif_poll() polls the serial line (using sio_tryread()). + */ +#ifndef SLIP_RX_FROM_ISR +#define SLIP_RX_FROM_ISR 0 +#endif + +/** Set this to 1 (default for SLIP_RX_FROM_ISR) to queue incoming packets + * received by slipif_received_byte[s]() as long as PBUF_POOL pbufs are available. + * If disabled, packets will be dropped if more than one packet is received. + */ +#ifndef SLIP_RX_QUEUE +#define SLIP_RX_QUEUE SLIP_RX_FROM_ISR +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +err_t slipif_init(struct netif * netif); +void slipif_poll(struct netif *netif); +#if SLIP_RX_FROM_ISR +void slipif_process_rxqueue(struct netif *netif); +void slipif_received_byte(struct netif *netif, u8_t data); +void slipif_received_bytes(struct netif *netif, u8_t *data, u8_t len); +#endif /* SLIP_RX_FROM_ISR */ + +#ifdef __cplusplus +} +#endif + +#endif /* LWIP_HDR_NETIF_SLIPIF_H */ + diff --git a/components/lwip/include/lwip/port/arch/cc.h b/components/lwip/include/lwip/port/arch/cc.h new file mode 100644 index 0000000000..8e98502ccf --- /dev/null +++ b/components/lwip/include/lwip/port/arch/cc.h @@ -0,0 +1,77 @@ +/* + * Copyright (c) 2001, Swedish Institute of Computer Science. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + * + */ +#ifndef __ARCH_CC_H__ +#define __ARCH_CC_H__ + +#include + +#include "arch/sys_arch.h" + +#define BYTE_ORDER LITTLE_ENDIAN + +typedef uint8_t u8_t; +typedef int8_t s8_t; +typedef uint16_t u16_t; +typedef int16_t s16_t; +typedef uint32_t u32_t; +typedef int32_t s32_t; + +typedef unsigned long mem_ptr_t; +typedef int sys_prot_t; + +#define S16_F "d" +#define U16_F "d" +#define X16_F "x" + +#define S32_F "d" +#define U32_F "d" +#define X32_F "x" + +#define PACK_STRUCT_FIELD(x) x +#define PACK_STRUCT_STRUCT __attribute__((packed)) +#define PACK_STRUCT_BEGIN +#define PACK_STRUCT_END + +#include + +#define LWIP_PLATFORM_DIAG(x) do {printf x;} while(0) +#define LWIP_PLATFORM_ASSERT(x) do {printf(x); sys_arch_assert(__FILE__, __LINE__);} while(0) + +//#define LWIP_DEBUG +#define LWIP_NOASSERT +//#define LWIP_ERROR + +#define LWIP_PROVIDE_ERRNO + +#endif /* __ARCH_CC_H__ */ diff --git a/components/lwip/include/lwip/port/arch/perf.h b/components/lwip/include/lwip/port/arch/perf.h new file mode 100644 index 0000000000..089facac1d --- /dev/null +++ b/components/lwip/include/lwip/port/arch/perf.h @@ -0,0 +1,40 @@ +/* + * Copyright (c) 2001, Swedish Institute of Computer Science. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + * + */ +#ifndef __PERF_H__ +#define __PERF_H__ + +#define PERF_START /* null definition */ +#define PERF_STOP(x) /* null definition */ + +#endif /* __PERF_H__ */ diff --git a/components/lwip/include/lwip/port/arch/sys_arch.h b/components/lwip/include/lwip/port/arch/sys_arch.h new file mode 100644 index 0000000000..a78dd5a3fb --- /dev/null +++ b/components/lwip/include/lwip/port/arch/sys_arch.h @@ -0,0 +1,73 @@ +/* + * Copyright (c) 2001-2003 Swedish Institute of Computer Science. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + * + */ + +#ifndef __SYS_ARCH_H__ +#define __SYS_ARCH_H__ + +#include "freertos/FreeRTOS.h" +#include "freertos/task.h" +#include "freertos/queue.h" +#include "freertos/semphr.h" + +typedef xSemaphoreHandle sys_sem_t; +typedef xSemaphoreHandle sys_mutex_t; +typedef xTaskHandle sys_thread_t; + +typedef struct sys_mbox_s { + xQueueHandle os_mbox; + sys_mutex_t lock; + uint8_t alive; +}* sys_mbox_t; + + +#define LWIP_COMPAT_MUTEX 0 + +#if !LWIP_COMPAT_MUTEX +#define sys_mutex_valid( x ) ( ( ( *x ) == NULL) ? pdFALSE : pdTRUE ) +#define sys_mutex_set_invalid( x ) ( ( *x ) = NULL ) +#endif + +#define sys_mbox_valid( x ) ( ( ( *x ) == NULL) ? pdFALSE : pdTRUE ) +#define sys_mbox_set_invalid( x ) ( ( *x ) = NULL ) + +#define sys_sem_valid( x ) ( ( ( *x ) == NULL) ? pdFALSE : pdTRUE ) +#define sys_sem_set_invalid( x ) ( ( *x ) = NULL ) + +void sys_arch_assert(const char *file, int line); +uint32_t system_get_time(void); +sys_sem_t* sys_thread_sem(void); +void sys_delay_ms(uint32_t ms); + + + +#endif /* __SYS_ARCH_H__ */ + diff --git a/components/lwip/include/lwip/port/lwipopts.h b/components/lwip/include/lwip/port/lwipopts.h new file mode 100755 index 0000000000..4958034d78 --- /dev/null +++ b/components/lwip/include/lwip/port/lwipopts.h @@ -0,0 +1,526 @@ +/* + * Copyright (c) 2001-2003 Swedish Institute of Computer Science. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Simon Goldschmidt + * + */ +#ifndef __LWIPOPTS_H__ +#define __LWIPOPTS_H__ + +#include + + +/* + ----------------------------------------------- + ---------- Platform specific locking ---------- + ----------------------------------------------- +*/ +/** + * SYS_LIGHTWEIGHT_PROT==1: if you want inter-task protection for certain + * critical regions during buffer allocation, deallocation and memory + * allocation and deallocation. + */ +#define SYS_LIGHTWEIGHT_PROT 1 + +/** + * MEMCPY: override this if you have a faster implementation at hand than the + * one included in your C library + */ +#define MEMCPY(dst,src,len) memcpy(dst,src,len) + +/** + * SMEMCPY: override this with care! Some compilers (e.g. gcc) can inline a + * call to memcpy() if the length is known at compile time and is small. + */ +#define SMEMCPY(dst,src,len) memcpy(dst,src,len) + +extern unsigned long os_random(void); +#define LWIP_RAND rand +/* + ------------------------------------ + ---------- Memory options ---------- + ------------------------------------ +*/ +/** + * MEM_LIBC_MALLOC==1: Use malloc/free/realloc provided by your C-library + * instead of the lwip internal allocator. Can save code size if you + * already use it. + */ +#define MEM_LIBC_MALLOC 1 + +/** +* MEMP_MEM_MALLOC==1: Use mem_malloc/mem_free instead of the lwip pool allocator. +* Especially useful with MEM_LIBC_MALLOC but handle with care regarding execution +* speed and usage from interrupts! +*/ +#define MEMP_MEM_MALLOC 1 + +/** + * MEM_ALIGNMENT: should be set to the alignment of the CPU + * 4 byte alignment -> #define MEM_ALIGNMENT 4 + * 2 byte alignment -> #define MEM_ALIGNMENT 2 + */ +#define MEM_ALIGNMENT 4 + +/* + ------------------------------------------------ + ---------- Internal Memory Pool Sizes ---------- + ------------------------------------------------ +*/ +/** + * MEMP_NUM_TCP_PCB: the number of simulatenously active TCP connections. + * (requires the LWIP_TCP option) + */ +#define MEMP_NUM_TCP_PCB 5 + +/** + * MEMP_NUM_NETCONN: the number of struct netconns. + * (only needed if you use the sequential API, like api_lib.c) + */ +#define MEMP_NUM_NETCONN 10 + +/* + -------------------------------- + ---------- ARP options ------- + -------------------------------- +*/ +/** + * ARP_QUEUEING==1: Multiple outgoing packets are queued during hardware address + * resolution. By default, only the most recent packet is queued per IP address. + * This is sufficient for most protocols and mainly reduces TCP connection + * startup time. Set this to 1 if you know your application sends more than one + * packet in a row to an IP address that is not in the ARP cache. + */ +#define ARP_QUEUEING 1 + +/* + -------------------------------- + ---------- IP options ---------- + -------------------------------- +*/ +/** + * IP_REASSEMBLY==1: Reassemble incoming fragmented IP packets. Note that + * this option does not affect outgoing packet sizes, which can be controlled + * via IP_FRAG. + */ +#define IP_REASSEMBLY 0 + +/** + * IP_FRAG==1: Fragment outgoing IP packets if their size exceeds MTU. Note + * that this option does not affect incoming packet sizes, which can be + * controlled via IP_REASSEMBLY. + */ +#define IP_FRAG 0 + +/** + * IP_REASS_MAXAGE: Maximum time (in multiples of IP_TMR_INTERVAL - so seconds, normally) + * a fragmented IP packet waits for all fragments to arrive. If not all fragments arrived + * in this time, the whole packet is discarded. + */ +#define IP_REASS_MAXAGE 3 + +/** + * IP_REASS_MAX_PBUFS: Total maximum amount of pbufs waiting to be reassembled. + * Since the received pbufs are enqueued, be sure to configure + * PBUF_POOL_SIZE > IP_REASS_MAX_PBUFS so that the stack is still able to receive + * packets even if the maximum amount of fragments is enqueued for reassembly! + */ +#define IP_REASS_MAX_PBUFS 10 + +/* + ---------------------------------- + ---------- ICMP options ---------- + ---------------------------------- +*/ + +/* + --------------------------------- + ---------- RAW options ---------- + --------------------------------- +*/ + +/* + ---------------------------------- + ---------- DHCP options ---------- + ---------------------------------- +*/ +/** + * LWIP_DHCP==1: Enable DHCP module. + */ +#define LWIP_DHCP 1 + + +#define DHCP_MAXRTX 0 //(*(volatile uint32*)0x600011E0) +/* + ------------------------------------ + ---------- AUTOIP options ---------- + ------------------------------------ +*/ +/* + ---------------------------------- + ---------- SNMP options ---------- + ---------------------------------- +*/ +/* + ---------------------------------- + ---------- IGMP options ---------- + ---------------------------------- +*/ +/** + * LWIP_IGMP==1: Turn on IGMP module. + */ +#define LWIP_IGMP 1 + +/* + ---------------------------------- + ---------- DNS options ----------- + ---------------------------------- +*/ +/** + * LWIP_DNS==1: Turn on DNS module. UDP must be available for DNS + * transport. + */ +#define LWIP_DNS 1 + +/* + --------------------------------- + ---------- UDP options ---------- + --------------------------------- +*/ +/* + --------------------------------- + ---------- TCP options ---------- + --------------------------------- +*/ +/** + * TCP_WND: The size of a TCP window. This must be at least + * (2 * TCP_MSS) for things to work well + */ +#ifdef PERF + +extern unsigned char misc_prof_get_tcpw(void); +extern unsigned char misc_prof_get_tcp_snd_buf(void); +#define TCP_WND (misc_prof_get_tcpw()*TCP_MSS) +#define TCP_SND_BUF (misc_prof_get_tcp_snd_buf()*TCP_MSS) + +#else + +#define TCP_WND (4 * TCP_MSS) +#define TCP_SND_BUF (2 * TCP_MSS) + +#endif + + +/** + * TCP_QUEUE_OOSEQ==1: TCP will queue segments that arrive out of order. + * Define to 0 if your device is low on memory. + */ +#define TCP_QUEUE_OOSEQ 1 + +/* + * LWIP_EVENT_API==1: The user defines lwip_tcp_event() to receive all + * events (accept, sent, etc) that happen in the system. + * LWIP_CALLBACK_API==1: The PCB callback function is called directly + * for the event. This is the default. +*/ +#define TCP_MSS 1460 + +/** + * TCP_MAXRTX: Maximum number of retransmissions of data segments. + */ +#define TCP_MAXRTX 12 //(*(volatile uint32*)0x600011E8) + +/** + * TCP_SYNMAXRTX: Maximum number of retransmissions of SYN segments. + */ +#define TCP_SYNMAXRTX 6 //(*(volatile uint32*)0x600011E4) + +/** + * TCP_LISTEN_BACKLOG: Enable the backlog option for tcp listen pcb. + */ +#define TCP_LISTEN_BACKLOG 1 + +/* + ---------------------------------- + ---------- Pbuf options ---------- + ---------------------------------- +*/ + +/* + ------------------------------------------------ + ---------- Network Interfaces options ---------- + ------------------------------------------------ +*/ + +/** + * LWIP_NETIF_HOSTNAME==1: use DHCP_OPTION_HOSTNAME with netif's hostname + * field. + */ +#define LWIP_NETIF_HOSTNAME 1 + +/** + * LWIP_NETIF_TX_SINGLE_PBUF: if this is set to 1, lwIP tries to put all data + * to be sent into one single pbuf. This is for compatibility with DMA-enabled + * MACs that do not support scatter-gather. + * Beware that this might involve CPU-memcpy before transmitting that would not + * be needed without this flag! Use this only if you need to! + * + * @todo: TCP and IP-frag do not work with this, yet: + */ +#define LWIP_NETIF_TX_SINGLE_PBUF 1 + +/* + ------------------------------------ + ---------- LOOPIF options ---------- + ------------------------------------ +*/ + +/* + ------------------------------------ + ---------- SLIPIF options ---------- + ------------------------------------ +*/ + +/* + ------------------------------------ + ---------- Thread options ---------- + ------------------------------------ +*/ +/** + * TCPIP_THREAD_NAME: The name assigned to the main tcpip thread. + */ +#define TCPIP_THREAD_NAME "tiT" + +/** + * TCPIP_THREAD_STACKSIZE: The stack size used by the main tcpip thread. + * The stack size value itself is platform-dependent, but is passed to + * sys_thread_new() when the thread is created. + */ +#define TCPIP_THREAD_STACKSIZE 2048 //not ok:384 + +/** + * TCPIP_THREAD_PRIO: The priority assigned to the main tcpip thread. + * The priority value itself is platform-dependent, but is passed to + * sys_thread_new() when the thread is created. + */ +#define TCPIP_THREAD_PRIO (configMAX_PRIORITIES-5) + +/** + * TCPIP_MBOX_SIZE: The mailbox size for the tcpip thread messages + * The queue size value itself is platform-dependent, but is passed to + * sys_mbox_new() when tcpip_init is called. + */ +#define TCPIP_MBOX_SIZE 16 + +/** + * DEFAULT_UDP_RECVMBOX_SIZE: The mailbox size for the incoming packets on a + * NETCONN_UDP. The queue size value itself is platform-dependent, but is passed + * to sys_mbox_new() when the recvmbox is created. + */ +#define DEFAULT_UDP_RECVMBOX_SIZE 16 + +/** + * DEFAULT_TCP_RECVMBOX_SIZE: The mailbox size for the incoming packets on a + * NETCONN_TCP. The queue size value itself is platform-dependent, but is passed + * to sys_mbox_new() when the recvmbox is created. + */ +#define DEFAULT_TCP_RECVMBOX_SIZE 16 +//#define DEFAULT_TCP_RECVMBOX_SIZE 6 + +/** + * DEFAULT_ACCEPTMBOX_SIZE: The mailbox size for the incoming connections. + * The queue size value itself is platform-dependent, but is passed to + * sys_mbox_new() when the acceptmbox is created. + */ +#define DEFAULT_ACCEPTMBOX_SIZE 6 + +/* + ---------------------------------------------- + ---------- Sequential layer options ---------- + ---------------------------------------------- +*/ +/** + * LWIP_TCPIP_CORE_LOCKING: (EXPERIMENTAL!) + * Don't use it if you're not an active lwIP project member + */ +#define LWIP_TCPIP_CORE_LOCKING 0 + +/* + ------------------------------------ + ---------- Socket options ---------- + ------------------------------------ +*/ +/** + * LWIP_SO_SNDTIMEO==1: Enable send timeout for sockets/netconns and + * SO_SNDTIMEO processing. + */ +#define LWIP_SO_SNDTIMEO 1 + +/** + * LWIP_SO_RCVTIMEO==1: Enable receive timeout for sockets/netconns and + * SO_RCVTIMEO processing. + */ +#define LWIP_SO_RCVTIMEO 1 + +/** + * LWIP_TCP_KEEPALIVE==1: Enable TCP_KEEPIDLE, TCP_KEEPINTVL and TCP_KEEPCNT + * options processing. Note that TCP_KEEPIDLE and TCP_KEEPINTVL have to be set + * in seconds. (does not require sockets.c, and will affect tcp.c) + */ +#define LWIP_TCP_KEEPALIVE 1 + +/** + * LWIP_SO_RCVBUF==1: Enable SO_RCVBUF processing. + */ +#define LWIP_SO_RCVBUF 0 + +/** + * SO_REUSE==1: Enable SO_REUSEADDR option. + */ +#define SO_REUSE 0 + +/* + ---------------------------------------- + ---------- Statistics options ---------- + ---------------------------------------- +*/ +/** + * LWIP_STATS==1: Enable statistics collection in lwip_stats. + */ +#define LWIP_STATS 0 + +/* + --------------------------------- + ---------- PPP options ---------- + --------------------------------- +*/ + +/* + -------------------------------------- + ---------- Checksum options ---------- + -------------------------------------- +*/ + +/* + --------------------------------------- + ---------- IPv6 options --------------- + --------------------------------------- +*/ +/** + * LWIP_IPV6==1: Enable IPv6 + */ +#define LWIP_IPV6 1 + +/* + --------------------------------------- + ---------- Hook options --------------- + --------------------------------------- +*/ + +/* + --------------------------------------- + ---------- Debugging options ---------- + --------------------------------------- +*/ +/** + * ETHARP_DEBUG: Enable debugging in etharp.c. + */ +#define ETHARP_DEBUG LWIP_DBG_OFF + +/** + * NETIF_DEBUG: Enable debugging in netif.c. + */ +#define NETIF_DEBUG LWIP_DBG_OFF + +/** + * PBUF_DEBUG: Enable debugging in pbuf.c. + */ +#define PBUF_DEBUG LWIP_DBG_OFF + +/** + * API_LIB_DEBUG: Enable debugging in api_lib.c. + */ +#define API_LIB_DEBUG LWIP_DBG_OFF + +/** + * SOCKETS_DEBUG: Enable debugging in sockets.c. + */ +#define SOCKETS_DEBUG LWIP_DBG_OFF + +/** + * ICMP_DEBUG: Enable debugging in icmp.c. + */ +#define ICMP_DEBUG LWIP_DBG_OFF + +/** + * IP_DEBUG: Enable debugging for IP. + */ +#define IP_DEBUG LWIP_DBG_OFF + +/** + * MEMP_DEBUG: Enable debugging in memp.c. + */ +#define MEMP_DEBUG LWIP_DBG_OFF + +/** + * TCP_INPUT_DEBUG: Enable debugging in tcp_in.c for incoming debug. + */ +#define TCP_INPUT_DEBUG LWIP_DBG_OFF + +/** + * TCP_OUTPUT_DEBUG: Enable debugging in tcp_out.c output functions. + */ +#define TCP_OUTPUT_DEBUG LWIP_DBG_OFF + +/** + * TCPIP_DEBUG: Enable debugging in tcpip.c. + */ +#define TCPIP_DEBUG LWIP_DBG_OFF + +/** + * DHCP_DEBUG: Enable debugging in dhcp.c. + */ +#define DHCP_DEBUG LWIP_DBG_OFF +//#define LWIP_DEBUG 1 +//#define TCP_DEBUG LWIP_DBG_ON +#define THREAD_SAFE_DEBUG LWIP_DBG_OFF +#define LWIP_THREAD_SAFE 1 + +#define CHECKSUM_CHECK_UDP 0 +#define CHECKSUM_CHECK_IP 0 + +#define HEAP_HIGHWAT 6*1024 + +#define LWIP_NETCONN_FULLDUPLEX 1 +#define LWIP_NETCONN_SEM_PER_THREAD 1 + + + +#define SOC_SEND_LOG //printf + +#endif /* __LWIPOPTS_H__ */ diff --git a/components/lwip/include/lwip/port/netif/wlanif.h b/components/lwip/include/lwip/port/netif/wlanif.h new file mode 100755 index 0000000000..f9e322ebda --- /dev/null +++ b/components/lwip/include/lwip/port/netif/wlanif.h @@ -0,0 +1,23 @@ +/* + * Copyright (c) 2010-2011 Espressif System + * +*/ + +#ifndef _WLAN_LWIP_IF_H_ +#define _WLAN_LWIP_IF_H_ + +#include "esp_wifi.h" + +#include "lwip/err.h" + +err_t wlanif_init(struct netif *netif); + +void wlanif_input(struct netif *netif, void *buffer, u16_t len, void* eb); + +bool ieee80211_output(wifi_interface_t wifi_if, void *buffer, u16_t len); + +wifi_interface_t wifi_get_interface(void *dev); + +void netif_reg_addr_change_cb(void* cb); + +#endif /* _WLAN_LWIP_IF_H_ */ diff --git a/components/lwip/include/lwip/posix/netdb.h b/components/lwip/include/lwip/posix/netdb.h new file mode 100755 index 0000000000..12d4c7f566 --- /dev/null +++ b/components/lwip/include/lwip/posix/netdb.h @@ -0,0 +1,33 @@ +/** + * @file + * This file is a posix wrapper for lwip/netdb.h. + */ + +/* + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + */ + +#include "lwip/netdb.h" diff --git a/components/lwip/include/lwip/posix/sys/socket.h b/components/lwip/include/lwip/posix/sys/socket.h new file mode 100755 index 0000000000..0ed9baf3d9 --- /dev/null +++ b/components/lwip/include/lwip/posix/sys/socket.h @@ -0,0 +1,33 @@ +/** + * @file + * This file is a posix wrapper for lwip/sockets.h. + */ + +/* + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + */ + +#include "lwip/sockets.h" diff --git a/components/lwip/netif/FILES b/components/lwip/netif/FILES new file mode 100755 index 0000000000..501edac3f0 --- /dev/null +++ b/components/lwip/netif/FILES @@ -0,0 +1,31 @@ +This directory contains generic network interface device drivers that +do not contain any hardware or architecture specific code. The files +are: + +etharp.c + Implements the ARP (Address Resolution Protocol) over + Ethernet. The code in this file should be used together with + Ethernet device drivers. Note that this module has been + largely made Ethernet independent so you should be able to + adapt this for other link layers (such as Firewire). + +ethernetif.c + An example of how an Ethernet device driver could look. This + file can be used as a "skeleton" for developing new Ethernet + network device drivers. It uses the etharp.c ARP code. + +loopif.c + A "loopback" network interface driver. It requires configuration + through the define LWIP_LOOPIF_MULTITHREADING (see opt.h). + +slipif.c + A generic implementation of the SLIP (Serial Line IP) + protocol. It requires a sio (serial I/O) module to work. + +lowpan6.c + 6LoWPAN implementation + +ppp/ Point-to-Point Protocol stack + The lwIP PPP support is based from pppd (http://ppp.samba.org) with + huge changes to match code size and memory requirements for embedded + devices. Please read ppp/PPPD_FOLLOWUP for a detailed explanation. diff --git a/components/lwip/netif/etharp.c b/components/lwip/netif/etharp.c new file mode 100755 index 0000000000..5891c5cfd6 --- /dev/null +++ b/components/lwip/netif/etharp.c @@ -0,0 +1,1385 @@ +/** + * @file + * Address Resolution Protocol module for IP over Ethernet + * + * Functionally, ARP is divided into two parts. The first maps an IP address + * to a physical address when sending a packet, and the second part answers + * requests from other machines for our physical address. + * + * This implementation complies with RFC 826 (Ethernet ARP). It supports + * Gratuitious ARP from RFC3220 (IP Mobility Support for IPv4) section 4.6 + * if an interface calls etharp_gratuitous(our_netif) upon address change. + */ + +/* + * Copyright (c) 2001-2003 Swedish Institute of Computer Science. + * Copyright (c) 2003-2004 Leon Woestenberg + * Copyright (c) 2003-2004 Axon Digital Design B.V., The Netherlands. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + */ + +#include "lwip/opt.h" + +#if LWIP_ARP || LWIP_ETHERNET + +#include "netif/etharp.h" +#include "lwip/stats.h" +#include "lwip/snmp.h" +#include "lwip/dhcp.h" +#include "lwip/autoip.h" + +#include + +#ifdef MEMLEAK_DEBUG +static const char mem_debug_file[] ICACHE_RODATA_ATTR STORE_ATTR = __FILE__; +#endif + +#if LWIP_IPV4 && LWIP_ARP /* don't build if not configured for use in lwipopts.h */ + +/** Re-request a used ARP entry 1 minute before it would expire to prevent + * breaking a steadily used connection because the ARP entry timed out. */ +#define ARP_AGE_REREQUEST_USED_UNICAST (ARP_MAXAGE - 30) +#define ARP_AGE_REREQUEST_USED_BROADCAST (ARP_MAXAGE - 15) + +/** the time an ARP entry stays pending after first request, + * for ARP_TMR_INTERVAL = 1000, this is + * 10 seconds. + * + * @internal Keep this number at least 2, otherwise it might + * run out instantly if the timeout occurs directly after a request. + */ +#define ARP_MAXPENDING 5 + +#define HWTYPE_ETHERNET 1 + +enum etharp_state { + ETHARP_STATE_EMPTY = 0, + ETHARP_STATE_PENDING, + ETHARP_STATE_STABLE, + ETHARP_STATE_STABLE_REREQUESTING_1, + ETHARP_STATE_STABLE_REREQUESTING_2 +#if ETHARP_SUPPORT_STATIC_ENTRIES + ,ETHARP_STATE_STATIC +#endif /* ETHARP_SUPPORT_STATIC_ENTRIES */ +}; + +struct etharp_entry { +#if ARP_QUEUEING + /** Pointer to queue of pending outgoing packets on this ARP entry. */ + struct etharp_q_entry *q; +#else /* ARP_QUEUEING */ + /** Pointer to a single pending outgoing packet on this ARP entry. */ + struct pbuf *q; +#endif /* ARP_QUEUEING */ + ip4_addr_t ipaddr; + struct netif *netif; + struct eth_addr ethaddr; + u16_t ctime; + u8_t state; +}; + +static struct etharp_entry arp_table[ARP_TABLE_SIZE]; + +#if !LWIP_NETIF_HWADDRHINT +static u8_t etharp_cached_entry; +#endif /* !LWIP_NETIF_HWADDRHINT */ + +/** Try hard to create a new entry - we want the IP address to appear in + the cache (even if this means removing an active entry or so). */ +#define ETHARP_FLAG_TRY_HARD 1 +#define ETHARP_FLAG_FIND_ONLY 2 +#if ETHARP_SUPPORT_STATIC_ENTRIES +#define ETHARP_FLAG_STATIC_ENTRY 4 +#endif /* ETHARP_SUPPORT_STATIC_ENTRIES */ + +#if LWIP_NETIF_HWADDRHINT +#define ETHARP_SET_HINT(netif, hint) if (((netif) != NULL) && ((netif)->addr_hint != NULL)) \ + *((netif)->addr_hint) = (hint); +#else /* LWIP_NETIF_HWADDRHINT */ +#define ETHARP_SET_HINT(netif, hint) (etharp_cached_entry = (hint)) +#endif /* LWIP_NETIF_HWADDRHINT */ + + +/* Some checks, instead of etharp_init(): */ +#if (LWIP_ARP && (ARP_TABLE_SIZE > 0x7f)) + #error "ARP_TABLE_SIZE must fit in an s8_t, you have to reduce it in your lwipopts.h" +#endif + + +static err_t etharp_request_dst(struct netif *netif, const ip4_addr_t *ipaddr, const struct eth_addr* hw_dst_addr); + + +#if ARP_QUEUEING +/** + * Free a complete queue of etharp entries + * + * @param q a qeueue of etharp_q_entry's to free + */ +static void +free_etharp_q(struct etharp_q_entry *q) +{ + struct etharp_q_entry *r; + LWIP_ASSERT("q != NULL", q != NULL); + LWIP_ASSERT("q->p != NULL", q->p != NULL); + while (q) { + r = q; + q = q->next; + LWIP_ASSERT("r->p != NULL", (r->p != NULL)); + pbuf_free(r->p); + memp_free(MEMP_ARP_QUEUE, r); + } +} +#else /* ARP_QUEUEING */ + +/** Compatibility define: free the queued pbuf */ +#define free_etharp_q(q) pbuf_free(q) + +#endif /* ARP_QUEUEING */ + +/** Clean up ARP table entries */ +static void +etharp_free_entry(int i) +{ + /* remove from SNMP ARP index tree */ + mib2_remove_arp_entry(arp_table[i].netif, &arp_table[i].ipaddr); + /* and empty packet queue */ + if (arp_table[i].q != NULL) { + /* remove all queued packets */ + LWIP_DEBUGF(ETHARP_DEBUG, ("etharp_free_entry: freeing entry %"U16_F", packet queue %p.\n", (u16_t)i, (void *)(arp_table[i].q))); + free_etharp_q(arp_table[i].q); + arp_table[i].q = NULL; + } + /* recycle entry for re-use */ + arp_table[i].state = ETHARP_STATE_EMPTY; +#ifdef LWIP_DEBUG + /* for debugging, clean out the complete entry */ + arp_table[i].ctime = 0; + arp_table[i].netif = NULL; + ip4_addr_set_zero(&arp_table[i].ipaddr); + arp_table[i].ethaddr = ethzero; +#endif /* LWIP_DEBUG */ +} + +/** + * Clears expired entries in the ARP table. + * + * This function should be called every ARP_TMR_INTERVAL milliseconds (1 second), + * in order to expire entries in the ARP table. + */ +void +etharp_tmr(void) +{ + u8_t i; + + LWIP_DEBUGF(ETHARP_DEBUG, ("etharp_timer\n")); + /* remove expired entries from the ARP table */ + for (i = 0; i < ARP_TABLE_SIZE; ++i) { + u8_t state = arp_table[i].state; + if (state != ETHARP_STATE_EMPTY +#if ETHARP_SUPPORT_STATIC_ENTRIES + && (state != ETHARP_STATE_STATIC) +#endif /* ETHARP_SUPPORT_STATIC_ENTRIES */ + ) { + arp_table[i].ctime++; + if ((arp_table[i].ctime >= ARP_MAXAGE) || + ((arp_table[i].state == ETHARP_STATE_PENDING) && + (arp_table[i].ctime >= ARP_MAXPENDING))) { + /* pending or stable entry has become old! */ + LWIP_DEBUGF(ETHARP_DEBUG, ("etharp_timer: expired %s entry %"U16_F".\n", + arp_table[i].state >= ETHARP_STATE_STABLE ? "stable" : "pending", (u16_t)i)); + /* clean up entries that have just been expired */ + etharp_free_entry(i); + } else if (arp_table[i].state == ETHARP_STATE_STABLE_REREQUESTING_1) { + /* Don't send more than one request every 2 seconds. */ + arp_table[i].state = ETHARP_STATE_STABLE_REREQUESTING_2; + } else if (arp_table[i].state == ETHARP_STATE_STABLE_REREQUESTING_2) { + /* Reset state to stable, so that the next transmitted packet will + re-send an ARP request. */ + arp_table[i].state = ETHARP_STATE_STABLE; + } else if (arp_table[i].state == ETHARP_STATE_PENDING) { + /* still pending, resend an ARP query */ + etharp_request(arp_table[i].netif, &arp_table[i].ipaddr); + } + } + } +} + +/** + * Search the ARP table for a matching or new entry. + * + * If an IP address is given, return a pending or stable ARP entry that matches + * the address. If no match is found, create a new entry with this address set, + * but in state ETHARP_EMPTY. The caller must check and possibly change the + * state of the returned entry. + * + * If ipaddr is NULL, return a initialized new entry in state ETHARP_EMPTY. + * + * In all cases, attempt to create new entries from an empty entry. If no + * empty entries are available and ETHARP_FLAG_TRY_HARD flag is set, recycle + * old entries. Heuristic choose the least important entry for recycling. + * + * @param ipaddr IP address to find in ARP cache, or to add if not found. + * @param flags @see definition of ETHARP_FLAG_* + * @param netif netif related to this address (used for NETIF_HWADDRHINT) + * + * @return The ARP entry index that matched or is created, ERR_MEM if no + * entry is found or could be recycled. + */ +static s8_t +etharp_find_entry(const ip4_addr_t *ipaddr, u8_t flags, struct netif* netif) +{ + s8_t old_pending = ARP_TABLE_SIZE, old_stable = ARP_TABLE_SIZE; + s8_t empty = ARP_TABLE_SIZE; + u8_t i = 0; + /* oldest entry with packets on queue */ + s8_t old_queue = ARP_TABLE_SIZE; + /* its age */ + u16_t age_queue = 0, age_pending = 0, age_stable = 0; + + LWIP_UNUSED_ARG(netif); + + /** + * a) do a search through the cache, remember candidates + * b) select candidate entry + * c) create new entry + */ + + /* a) in a single search sweep, do all of this + * 1) remember the first empty entry (if any) + * 2) remember the oldest stable entry (if any) + * 3) remember the oldest pending entry without queued packets (if any) + * 4) remember the oldest pending entry with queued packets (if any) + * 5) search for a matching IP entry, either pending or stable + * until 5 matches, or all entries are searched for. + */ + + for (i = 0; i < ARP_TABLE_SIZE; ++i) { + u8_t state = arp_table[i].state; + /* no empty entry found yet and now we do find one? */ + if ((empty == ARP_TABLE_SIZE) && (state == ETHARP_STATE_EMPTY)) { + LWIP_DEBUGF(ETHARP_DEBUG, ("etharp_find_entry: found empty entry %"U16_F"\n", (u16_t)i)); + /* remember first empty entry */ + empty = i; + } else if (state != ETHARP_STATE_EMPTY) { + LWIP_ASSERT("state == ETHARP_STATE_PENDING || state >= ETHARP_STATE_STABLE", + state == ETHARP_STATE_PENDING || state >= ETHARP_STATE_STABLE); + /* if given, does IP address match IP address in ARP entry? */ + if (ipaddr && ip4_addr_cmp(ipaddr, &arp_table[i].ipaddr) +#if ETHARP_TABLE_MATCH_NETIF + && ((netif == NULL) || (netif == arp_table[i].netif)) +#endif /* ETHARP_TABLE_MATCH_NETIF */ + ) { + LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("etharp_find_entry: found matching entry %"U16_F"\n", (u16_t)i)); + /* found exact IP address match, simply bail out */ + return i; + } + /* pending entry? */ + if (state == ETHARP_STATE_PENDING) { + /* pending with queued packets? */ + if (arp_table[i].q != NULL) { + if (arp_table[i].ctime >= age_queue) { + old_queue = i; + age_queue = arp_table[i].ctime; + } + } else + /* pending without queued packets? */ + { + if (arp_table[i].ctime >= age_pending) { + old_pending = i; + age_pending = arp_table[i].ctime; + } + } + /* stable entry? */ + } else if (state >= ETHARP_STATE_STABLE) { +#if ETHARP_SUPPORT_STATIC_ENTRIES + /* don't record old_stable for static entries since they never expire */ + if (state < ETHARP_STATE_STATIC) +#endif /* ETHARP_SUPPORT_STATIC_ENTRIES */ + { + /* remember entry with oldest stable entry in oldest, its age in maxtime */ + if (arp_table[i].ctime >= age_stable) { + old_stable = i; + age_stable = arp_table[i].ctime; + } + } + } + } + } + /* { we have no match } => try to create a new entry */ + + /* don't create new entry, only search? */ + if (((flags & ETHARP_FLAG_FIND_ONLY) != 0) || + /* or no empty entry found and not allowed to recycle? */ + ((empty == ARP_TABLE_SIZE) && ((flags & ETHARP_FLAG_TRY_HARD) == 0))) { + LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("etharp_find_entry: no empty entry found and not allowed to recycle\n")); + return (s8_t)ERR_MEM; + } + + /* b) choose the least destructive entry to recycle: + * 1) empty entry + * 2) oldest stable entry + * 3) oldest pending entry without queued packets + * 4) oldest pending entry with queued packets + * + * { ETHARP_FLAG_TRY_HARD is set at this point } + */ + + /* 1) empty entry available? */ + if (empty < ARP_TABLE_SIZE) { + i = empty; + LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("etharp_find_entry: selecting empty entry %"U16_F"\n", (u16_t)i)); + } else { + /* 2) found recyclable stable entry? */ + if (old_stable < ARP_TABLE_SIZE) { + /* recycle oldest stable*/ + i = old_stable; + LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("etharp_find_entry: selecting oldest stable entry %"U16_F"\n", (u16_t)i)); + /* no queued packets should exist on stable entries */ + LWIP_ASSERT("arp_table[i].q == NULL", arp_table[i].q == NULL); + /* 3) found recyclable pending entry without queued packets? */ + } else if (old_pending < ARP_TABLE_SIZE) { + /* recycle oldest pending */ + i = old_pending; + LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("etharp_find_entry: selecting oldest pending entry %"U16_F" (without queue)\n", (u16_t)i)); + /* 4) found recyclable pending entry with queued packets? */ + } else if (old_queue < ARP_TABLE_SIZE) { + /* recycle oldest pending (queued packets are free in etharp_free_entry) */ + i = old_queue; + LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("etharp_find_entry: selecting oldest pending entry %"U16_F", freeing packet queue %p\n", (u16_t)i, (void *)(arp_table[i].q))); + /* no empty or recyclable entries found */ + } else { + LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("etharp_find_entry: no empty or recyclable entries found\n")); + return (s8_t)ERR_MEM; + } + + /* { empty or recyclable entry found } */ + LWIP_ASSERT("i < ARP_TABLE_SIZE", i < ARP_TABLE_SIZE); + etharp_free_entry(i); + } + + LWIP_ASSERT("i < ARP_TABLE_SIZE", i < ARP_TABLE_SIZE); + LWIP_ASSERT("arp_table[i].state == ETHARP_STATE_EMPTY", + arp_table[i].state == ETHARP_STATE_EMPTY); + + /* IP address given? */ + if (ipaddr != NULL) { + /* set IP address */ + ip4_addr_copy(arp_table[i].ipaddr, *ipaddr); + } + arp_table[i].ctime = 0; +#if ETHARP_TABLE_MATCH_NETIF + arp_table[i].netif = netif; +#endif /* ETHARP_TABLE_MATCH_NETIF*/ + return (err_t)i; +} + +/** + * Send an IP packet on the network using netif->linkoutput + * The ethernet header is filled in before sending. + * + * @params netif the lwIP network interface on which to send the packet + * @params p the packet to send, p->payload pointing to the (uninitialized) ethernet header + * @params src the source MAC address to be copied into the ethernet header + * @params dst the destination MAC address to be copied into the ethernet header + * @return ERR_OK if the packet was sent, any other err_t on failure + */ +static err_t +etharp_send_ip(struct netif *netif, struct pbuf *p, struct eth_addr *src, const struct eth_addr *dst) +{ + struct eth_hdr *ethhdr = (struct eth_hdr *)p->payload; +#if ETHARP_SUPPORT_VLAN && defined(LWIP_HOOK_VLAN_SET) + struct eth_vlan_hdr *vlanhdr; +#endif /* ETHARP_SUPPORT_VLAN && defined(LWIP_HOOK_VLAN_SET) */ + + LWIP_ASSERT("netif->hwaddr_len must be the same as ETH_HWADDR_LEN for etharp!", + (netif->hwaddr_len == ETH_HWADDR_LEN)); +#if ETHARP_SUPPORT_VLAN && defined(LWIP_HOOK_VLAN_SET) + ethhdr->type = PP_HTONS(ETHTYPE_VLAN); + vlanhdr = (struct eth_vlan_hdr*)(((u8_t*)ethhdr) + SIZEOF_ETH_HDR); + vlanhdr->prio_vid = 0; + vlanhdr->tpid = PP_HTONS(ETHTYPE_IP); + if (!LWIP_HOOK_VLAN_SET(netif, ethhdr, vlanhdr)) { + /* packet shall not contain VLAN header, so hide it and set correct ethertype */ + pbuf_header(p, -SIZEOF_VLAN_HDR); + ethhdr = (struct eth_hdr *)p->payload; +#endif /* ETHARP_SUPPORT_VLAN && defined(LWIP_HOOK_VLAN_SET) */ + ethhdr->type = PP_HTONS(ETHTYPE_IP); +#if ETHARP_SUPPORT_VLAN && defined(LWIP_HOOK_VLAN_SET) + } +#endif /* ETHARP_SUPPORT_VLAN && defined(LWIP_HOOK_VLAN_SET) */ + ETHADDR32_COPY(ðhdr->dest, dst); + ETHADDR16_COPY(ðhdr->src, src); + LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("etharp_send_ip: sending packet %p\n", (void *)p)); + /* send the packet */ + return netif->linkoutput(netif, p); +} + +/** + * Update (or insert) a IP/MAC address pair in the ARP cache. + * + * If a pending entry is resolved, any queued packets will be sent + * at this point. + * + * @param netif netif related to this entry (used for NETIF_ADDRHINT) + * @param ipaddr IP address of the inserted ARP entry. + * @param ethaddr Ethernet address of the inserted ARP entry. + * @param flags @see definition of ETHARP_FLAG_* + * + * @return + * - ERR_OK Successfully updated ARP cache. + * - ERR_MEM If we could not add a new ARP entry when ETHARP_FLAG_TRY_HARD was set. + * - ERR_ARG Non-unicast address given, those will not appear in ARP cache. + * + * @see pbuf_free() + */ +static err_t +etharp_update_arp_entry(struct netif *netif, const ip4_addr_t *ipaddr, struct eth_addr *ethaddr, u8_t flags) +{ + s8_t i; + LWIP_ASSERT("netif->hwaddr_len == ETH_HWADDR_LEN", netif->hwaddr_len == ETH_HWADDR_LEN); + LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("etharp_update_arp_entry: %"U16_F".%"U16_F".%"U16_F".%"U16_F" - %02"X16_F":%02"X16_F":%02"X16_F":%02"X16_F":%02"X16_F":%02"X16_F"\n", + ip4_addr1_16(ipaddr), ip4_addr2_16(ipaddr), ip4_addr3_16(ipaddr), ip4_addr4_16(ipaddr), + ethaddr->addr[0], ethaddr->addr[1], ethaddr->addr[2], + ethaddr->addr[3], ethaddr->addr[4], ethaddr->addr[5])); + /* non-unicast address? */ + if (ip4_addr_isany(ipaddr) || + ip4_addr_isbroadcast(ipaddr, netif) || + ip4_addr_ismulticast(ipaddr)) { + LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("etharp_update_arp_entry: will not add non-unicast IP address to ARP cache\n")); + return ERR_ARG; + } + /* find or create ARP entry */ + i = etharp_find_entry(ipaddr, flags, netif); + /* bail out if no entry could be found */ + if (i < 0) { + return (err_t)i; + } + +#if ETHARP_SUPPORT_STATIC_ENTRIES + if (flags & ETHARP_FLAG_STATIC_ENTRY) { + /* record static type */ + arp_table[i].state = ETHARP_STATE_STATIC; + } else +#endif /* ETHARP_SUPPORT_STATIC_ENTRIES */ + { + /* mark it stable */ + arp_table[i].state = ETHARP_STATE_STABLE; + } + + /* record network interface */ + arp_table[i].netif = netif; + /* insert in SNMP ARP index tree */ + mib2_add_arp_entry(netif, &arp_table[i].ipaddr); + + LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("etharp_update_arp_entry: updating stable entry %"S16_F"\n", (s16_t)i)); + /* update address */ + ETHADDR32_COPY(&arp_table[i].ethaddr, ethaddr); + /* reset time stamp */ + arp_table[i].ctime = 0; + /* this is where we will send out queued packets! */ +#if ARP_QUEUEING + while (arp_table[i].q != NULL) { + struct pbuf *p; + /* remember remainder of queue */ + struct etharp_q_entry *q = arp_table[i].q; + /* pop first item off the queue */ + arp_table[i].q = q->next; + /* get the packet pointer */ + p = q->p; + /* now queue entry can be freed */ + memp_free(MEMP_ARP_QUEUE, q); +#else /* ARP_QUEUEING */ + if (arp_table[i].q != NULL) { + struct pbuf *p = arp_table[i].q; + arp_table[i].q = NULL; +#endif /* ARP_QUEUEING */ + /* send the queued IP packet */ + etharp_send_ip(netif, p, (struct eth_addr*)(netif->hwaddr), ethaddr); + /* free the queued IP packet */ + pbuf_free(p); + } + return ERR_OK; +} + +#if ETHARP_SUPPORT_STATIC_ENTRIES +/** Add a new static entry to the ARP table. If an entry exists for the + * specified IP address, this entry is overwritten. + * If packets are queued for the specified IP address, they are sent out. + * + * @param ipaddr IP address for the new static entry + * @param ethaddr ethernet address for the new static entry + * @return @see return values of etharp_add_static_entry + */ +err_t +etharp_add_static_entry(const ip4_addr_t *ipaddr, struct eth_addr *ethaddr) +{ + struct netif *netif; + LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("etharp_add_static_entry: %"U16_F".%"U16_F".%"U16_F".%"U16_F" - %02"X16_F":%02"X16_F":%02"X16_F":%02"X16_F":%02"X16_F":%02"X16_F"\n", + ip4_addr1_16(ipaddr), ip4_addr2_16(ipaddr), ip4_addr3_16(ipaddr), ip4_addr4_16(ipaddr), + ethaddr->addr[0], ethaddr->addr[1], ethaddr->addr[2], + ethaddr->addr[3], ethaddr->addr[4], ethaddr->addr[5])); + + netif = ip4_route(ipaddr); + if (netif == NULL) { + return ERR_RTE; + } + + return etharp_update_arp_entry(netif, ipaddr, ethaddr, ETHARP_FLAG_TRY_HARD | ETHARP_FLAG_STATIC_ENTRY); +} + +/** Remove a static entry from the ARP table previously added with a call to + * etharp_add_static_entry. + * + * @param ipaddr IP address of the static entry to remove + * @return ERR_OK: entry removed + * ERR_MEM: entry wasn't found + * ERR_ARG: entry wasn't a static entry but a dynamic one + */ +err_t +etharp_remove_static_entry(const ip4_addr_t *ipaddr) +{ + s8_t i; + LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("etharp_remove_static_entry: %"U16_F".%"U16_F".%"U16_F".%"U16_F"\n", + ip4_addr1_16(ipaddr), ip4_addr2_16(ipaddr), ip4_addr3_16(ipaddr), ip4_addr4_16(ipaddr))); + + /* find or create ARP entry */ + i = etharp_find_entry(ipaddr, ETHARP_FLAG_FIND_ONLY, NULL); + /* bail out if no entry could be found */ + if (i < 0) { + return (err_t)i; + } + + if (arp_table[i].state != ETHARP_STATE_STATIC) { + /* entry wasn't a static entry, cannot remove it */ + return ERR_ARG; + } + /* entry found, free it */ + etharp_free_entry(i); + return ERR_OK; +} +#endif /* ETHARP_SUPPORT_STATIC_ENTRIES */ + +/** + * Remove all ARP table entries of the specified netif. + * + * @param netif points to a network interface + */ +void etharp_cleanup_netif(struct netif *netif) +{ + u8_t i; + + for (i = 0; i < ARP_TABLE_SIZE; ++i) { + u8_t state = arp_table[i].state; + if ((state != ETHARP_STATE_EMPTY) && (arp_table[i].netif == netif)) { + etharp_free_entry(i); + } + } +} + +/** + * Finds (stable) ethernet/IP address pair from ARP table + * using interface and IP address index. + * @note the addresses in the ARP table are in network order! + * + * @param netif points to interface index + * @param ipaddr points to the (network order) IP address index + * @param eth_ret points to return pointer + * @param ip_ret points to return pointer + * @return table index if found, -1 otherwise + */ +s8_t +etharp_find_addr(struct netif *netif, const ip4_addr_t *ipaddr, + struct eth_addr **eth_ret, const ip4_addr_t **ip_ret) +{ + s8_t i; + + LWIP_ASSERT("eth_ret != NULL && ip_ret != NULL", + eth_ret != NULL && ip_ret != NULL); + + LWIP_UNUSED_ARG(netif); + + i = etharp_find_entry(ipaddr, ETHARP_FLAG_FIND_ONLY, netif); + if ((i >= 0) && (arp_table[i].state >= ETHARP_STATE_STABLE)) { + *eth_ret = &arp_table[i].ethaddr; + *ip_ret = &arp_table[i].ipaddr; + return i; + } + return -1; +} + +/** + * Possibility to iterate over stable ARP table entries + * + * @param i entry number, 0 to ARP_TABLE_SIZE + * @param ipaddr return value: IP address + * @param netif return value: points to interface + * @param eth_ret return value: ETH address + * @return 1 on valid index, 0 otherwise + */ +u8_t +etharp_get_entry(u8_t i, ip4_addr_t **ipaddr, struct netif **netif, struct eth_addr **eth_ret) +{ + LWIP_ASSERT("ipaddr != NULL", ipaddr != NULL); + LWIP_ASSERT("netif != NULL", netif != NULL); + LWIP_ASSERT("eth_ret != NULL", eth_ret != NULL); + + if((i < ARP_TABLE_SIZE) && (arp_table[i].state >= ETHARP_STATE_STABLE)) { + *ipaddr = &arp_table[i].ipaddr; + *netif = arp_table[i].netif; + *eth_ret = &arp_table[i].ethaddr; + return 1; + } else { + return 0; + } +} + +#if ETHARP_TRUST_IP_MAC +/** + * Updates the ARP table using the given IP packet. + * + * Uses the incoming IP packet's source address to update the + * ARP cache for the local network. The function does not alter + * or free the packet. This function must be called before the + * packet p is passed to the IP layer. + * + * @param netif The lwIP network interface on which the IP packet pbuf arrived. + * @param p The IP packet that arrived on netif. + * + * @return NULL + * + * @see pbuf_free() + */ +static void +etharp_ip_input(struct netif *netif, struct pbuf *p) +{ + struct eth_hdr *ethhdr; + struct ip_hdr *iphdr; + ip4_addr_t iphdr_src; + LWIP_ERROR("netif != NULL", (netif != NULL), return;); + + /* Only insert an entry if the source IP address of the + incoming IP packet comes from a host on the local network. */ + ethhdr = (struct eth_hdr *)p->payload; + iphdr = (struct ip_hdr *)((u8_t*)ethhdr + SIZEOF_ETH_HDR); +#if ETHARP_SUPPORT_VLAN + if (ethhdr->type == PP_HTONS(ETHTYPE_VLAN)) { + iphdr = (struct ip_hdr *)((u8_t*)ethhdr + SIZEOF_ETH_HDR + SIZEOF_VLAN_HDR); + } +#endif /* ETHARP_SUPPORT_VLAN */ + + ip4_addr_copy(iphdr_src, iphdr->src); + + /* source is not on the local network? */ + if (!ip4_addr_netcmp(&iphdr_src, netif_ip4_addr(netif), netif_ip4_netmask(netif))) { + /* do nothing */ + return; + } + + LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("etharp_ip_input: updating ETHARP table.\n")); + /* update the source IP address in the cache, if present */ + /* @todo We could use ETHARP_FLAG_TRY_HARD if we think we are going to talk + * back soon (for example, if the destination IP address is ours. */ + etharp_update_arp_entry(netif, &iphdr_src, &(ethhdr->src), ETHARP_FLAG_FIND_ONLY); +} +#endif /* ETHARP_TRUST_IP_MAC */ + +/** + * Responds to ARP requests to us. Upon ARP replies to us, add entry to cache + * send out queued IP packets. Updates cache with snooped address pairs. + * + * Should be called for incoming ARP packets. The pbuf in the argument + * is freed by this function. + * + * @param netif The lwIP network interface on which the ARP packet pbuf arrived. + * @param ethaddr Ethernet address of netif. + * @param p The ARP packet that arrived on netif. Is freed by this function. + * + * @return NULL + * + * @see pbuf_free() + */ +void +etharp_arp_input(struct netif *netif, struct eth_addr *ethaddr, struct pbuf *p) +{ + struct etharp_hdr *hdr; + struct eth_hdr *ethhdr; + /* these are aligned properly, whereas the ARP header fields might not be */ + ip4_addr_t sipaddr, dipaddr; + u8_t for_us; +#if LWIP_AUTOIP + const u8_t * ethdst_hwaddr; +#endif /* LWIP_AUTOIP */ + + LWIP_ERROR("netif != NULL", (netif != NULL), return;); + + /* drop short ARP packets: we have to check for p->len instead of p->tot_len here + since a struct etharp_hdr is pointed to p->payload, so it musn't be chained! */ + if (p->len < SIZEOF_ETHARP_PACKET) { + LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_WARNING, + ("etharp_arp_input: packet dropped, too short (%"S16_F"/%"S16_F")\n", p->tot_len, + (s16_t)SIZEOF_ETHARP_PACKET)); + ETHARP_STATS_INC(etharp.lenerr); + ETHARP_STATS_INC(etharp.drop); + pbuf_free(p); + return; + } + + ethhdr = (struct eth_hdr *)p->payload; + hdr = (struct etharp_hdr *)((u8_t*)ethhdr + SIZEOF_ETH_HDR); +#if ETHARP_SUPPORT_VLAN + if (ethhdr->type == PP_HTONS(ETHTYPE_VLAN)) { + hdr = (struct etharp_hdr *)(((u8_t*)ethhdr) + SIZEOF_ETH_HDR + SIZEOF_VLAN_HDR); + } +#endif /* ETHARP_SUPPORT_VLAN */ + + /* RFC 826 "Packet Reception": */ + if ((hdr->hwtype != PP_HTONS(HWTYPE_ETHERNET)) || + (hdr->hwlen != ETH_HWADDR_LEN) || + (hdr->protolen != sizeof(ip4_addr_t)) || + (hdr->proto != PP_HTONS(ETHTYPE_IP))) { + LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_WARNING, + ("etharp_arp_input: packet dropped, wrong hw type, hwlen, proto, protolen or ethernet type (%"U16_F"/%"U16_F"/%"U16_F"/%"U16_F")\n", + hdr->hwtype, hdr->hwlen, hdr->proto, hdr->protolen)); + ETHARP_STATS_INC(etharp.proterr); + ETHARP_STATS_INC(etharp.drop); + pbuf_free(p); + return; + } + ETHARP_STATS_INC(etharp.recv); + +#if LWIP_AUTOIP + /* We have to check if a host already has configured our random + * created link local address and continuously check if there is + * a host with this IP-address so we can detect collisions */ + autoip_arp_reply(netif, hdr); +#endif /* LWIP_AUTOIP */ + + /* Copy struct ip4_addr2 to aligned ip4_addr, to support compilers without + * structure packing (not using structure copy which breaks strict-aliasing rules). */ + IPADDR2_COPY(&sipaddr, &hdr->sipaddr); + IPADDR2_COPY(&dipaddr, &hdr->dipaddr); + + /* this interface is not configured? */ + if (ip4_addr_isany_val(*netif_ip4_addr(netif))) { + for_us = 0; + } else { + /* ARP packet directed to us? */ + for_us = (u8_t)ip4_addr_cmp(&dipaddr, netif_ip4_addr(netif)); + } + + /* ARP message directed to us? + -> add IP address in ARP cache; assume requester wants to talk to us, + can result in directly sending the queued packets for this host. + ARP message not directed to us? + -> update the source IP address in the cache, if present */ + etharp_update_arp_entry(netif, &sipaddr, &(hdr->shwaddr), + for_us ? ETHARP_FLAG_TRY_HARD : ETHARP_FLAG_FIND_ONLY); + + /* now act on the message itself */ + switch (hdr->opcode) { + /* ARP request? */ + case PP_HTONS(ARP_REQUEST): + /* ARP request. If it asked for our address, we send out a + * reply. In any case, we time-stamp any existing ARP entry, + * and possibly send out an IP packet that was queued on it. */ + + LWIP_DEBUGF (ETHARP_DEBUG | LWIP_DBG_TRACE, ("etharp_arp_input: incoming ARP request\n")); + /* ARP request for our address? */ + if (for_us) { + + LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("etharp_arp_input: replying to ARP request for our IP address\n")); + /* Re-use pbuf to send ARP reply. + Since we are re-using an existing pbuf, we can't call etharp_raw since + that would allocate a new pbuf. */ + hdr->opcode = htons(ARP_REPLY); + + IPADDR2_COPY(&hdr->dipaddr, &hdr->sipaddr); + IPADDR2_COPY(&hdr->sipaddr, netif_ip4_addr(netif)); + + LWIP_ASSERT("netif->hwaddr_len must be the same as ETH_HWADDR_LEN for etharp!", + (netif->hwaddr_len == ETH_HWADDR_LEN)); +#if LWIP_AUTOIP + /* If we are using Link-Local, all ARP packets that contain a Link-Local + * 'sender IP address' MUST be sent using link-layer broadcast instead of + * link-layer unicast. (See RFC3927 Section 2.5, last paragraph) */ + ethdst_hwaddr = ip4_addr_islinklocal(netif_ip4_addr(netif)) ? (const u8_t*)(ethbroadcast.addr) : hdr->shwaddr.addr; +#endif /* LWIP_AUTOIP */ + + ETHADDR16_COPY(&hdr->dhwaddr, &hdr->shwaddr); +#if LWIP_AUTOIP + ETHADDR16_COPY(ðhdr->dest, ethdst_hwaddr); +#else /* LWIP_AUTOIP */ + ETHADDR16_COPY(ðhdr->dest, &hdr->shwaddr); +#endif /* LWIP_AUTOIP */ + ETHADDR16_COPY(&hdr->shwaddr, ethaddr); + ETHADDR16_COPY(ðhdr->src, ethaddr); + + /* hwtype, hwaddr_len, proto, protolen and the type in the ethernet header + are already correct, we tested that before */ + + /* return ARP reply */ + netif->linkoutput(netif, p); + /* we are not configured? */ + } else if (ip4_addr_isany_val(*netif_ip4_addr(netif))) { + /* { for_us == 0 and netif->ip_addr.addr == 0 } */ + LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("etharp_arp_input: we are unconfigured, ARP request ignored.\n")); + /* request was not directed to us */ + } else { + /* { for_us == 0 and netif->ip_addr.addr != 0 } */ + LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("etharp_arp_input: ARP request was not for us.\n")); + } + break; + case PP_HTONS(ARP_REPLY): + /* ARP reply. We already updated the ARP cache earlier. */ + LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("etharp_arp_input: incoming ARP reply\n")); +#if (LWIP_DHCP && DHCP_DOES_ARP_CHECK) + /* DHCP wants to know about ARP replies from any host with an + * IP address also offered to us by the DHCP server. We do not + * want to take a duplicate IP address on a single network. + * @todo How should we handle redundant (fail-over) interfaces? */ + dhcp_arp_reply(netif, &sipaddr); +#endif /* (LWIP_DHCP && DHCP_DOES_ARP_CHECK) */ + break; + default: + LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("etharp_arp_input: ARP unknown opcode type %"S16_F"\n", htons(hdr->opcode))); + ETHARP_STATS_INC(etharp.err); + break; + } + /* free ARP packet */ + pbuf_free(p); +} + +/** Just a small helper function that sends a pbuf to an ethernet address + * in the arp_table specified by the index 'arp_idx'. + */ +static err_t +etharp_output_to_arp_index(struct netif *netif, struct pbuf *q, u8_t arp_idx) +{ + LWIP_ASSERT("arp_table[arp_idx].state >= ETHARP_STATE_STABLE", + arp_table[arp_idx].state >= ETHARP_STATE_STABLE); + /* if arp table entry is about to expire: re-request it, + but only if its state is ETHARP_STATE_STABLE to prevent flooding the + network with ARP requests if this address is used frequently. */ + if (arp_table[arp_idx].state == ETHARP_STATE_STABLE) { + if (arp_table[arp_idx].ctime >= ARP_AGE_REREQUEST_USED_BROADCAST) { + /* issue a standard request using broadcast */ + if (etharp_request(netif, &arp_table[arp_idx].ipaddr) == ERR_OK) { + arp_table[arp_idx].state = ETHARP_STATE_STABLE_REREQUESTING_1; + } + } else if (arp_table[arp_idx].ctime >= ARP_AGE_REREQUEST_USED_UNICAST) { + /* issue a unicast request (for 15 seconds) to prevent unnecessary broadcast */ + if (etharp_request_dst(netif, &arp_table[arp_idx].ipaddr, &arp_table[arp_idx].ethaddr) == ERR_OK) { + arp_table[arp_idx].state = ETHARP_STATE_STABLE_REREQUESTING_1; + } + } + } + + return etharp_send_ip(netif, q, (struct eth_addr*)(netif->hwaddr), + &arp_table[arp_idx].ethaddr); +} + +/** + * Resolve and fill-in Ethernet address header for outgoing IP packet. + * + * For IP multicast and broadcast, corresponding Ethernet addresses + * are selected and the packet is transmitted on the link. + * + * For unicast addresses, the packet is submitted to etharp_query(). In + * case the IP address is outside the local network, the IP address of + * the gateway is used. + * + * @param netif The lwIP network interface which the IP packet will be sent on. + * @param q The pbuf(s) containing the IP packet to be sent. + * @param ipaddr The IP address of the packet destination. + * + * @return + * - ERR_RTE No route to destination (no gateway to external networks), + * or the return type of either etharp_query() or etharp_send_ip(). + */ +err_t +etharp_output(struct netif *netif, struct pbuf *q, const ip4_addr_t *ipaddr) +{ + const struct eth_addr *dest; + struct eth_addr mcastaddr; + const ip4_addr_t *dst_addr = ipaddr; + + LWIP_ASSERT("netif != NULL", netif != NULL); + LWIP_ASSERT("q != NULL", q != NULL); + LWIP_ASSERT("ipaddr != NULL", ipaddr != NULL); + + /* make room for Ethernet header - should not fail */ +#if ETHARP_SUPPORT_VLAN && defined(LWIP_HOOK_VLAN_SET) + if (pbuf_header(q, sizeof(struct eth_hdr) + SIZEOF_VLAN_HDR) != 0) { +#else /* ETHARP_SUPPORT_VLAN && defined(LWIP_HOOK_VLAN_SET) */ + if (pbuf_header(q, sizeof(struct eth_hdr)) != 0) { +#endif /* ETHARP_SUPPORT_VLAN && defined(LWIP_HOOK_VLAN_SET) */ + /* bail out */ + LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_SERIOUS, + ("etharp_output: could not allocate room for header.\n")); + LINK_STATS_INC(link.lenerr); + return ERR_BUF; + } + + /* Determine on destination hardware address. Broadcasts and multicasts + * are special, other IP addresses are looked up in the ARP table. */ + + /* broadcast destination IP address? */ + if (ip4_addr_isbroadcast(ipaddr, netif)) { + /* broadcast on Ethernet also */ + dest = (const struct eth_addr *)ðbroadcast; + /* multicast destination IP address? */ + } else if (ip4_addr_ismulticast(ipaddr)) { + /* Hash IP multicast address to MAC address.*/ + mcastaddr.addr[0] = LL_IP4_MULTICAST_ADDR_0; + mcastaddr.addr[1] = LL_IP4_MULTICAST_ADDR_1; + mcastaddr.addr[2] = LL_IP4_MULTICAST_ADDR_2; + mcastaddr.addr[3] = ip4_addr2(ipaddr) & 0x7f; + mcastaddr.addr[4] = ip4_addr3(ipaddr); + mcastaddr.addr[5] = ip4_addr4(ipaddr); + /* destination Ethernet address is multicast */ + dest = &mcastaddr; + /* unicast destination IP address? */ + } else { + s8_t i; + /* outside local network? if so, this can neither be a global broadcast nor + a subnet broadcast. */ + if (!ip4_addr_netcmp(ipaddr, netif_ip4_addr(netif), netif_ip4_netmask(netif)) && + !ip4_addr_islinklocal(ipaddr)) { +#if LWIP_AUTOIP + struct ip_hdr *iphdr = (struct ip_hdr*)((u8_t*)q->payload + +#if ETHARP_SUPPORT_VLAN && defined(LWIP_HOOK_VLAN_SET) + SIZEOF_VLAN_HDR + +#endif /* ETHARP_SUPPORT_VLAN && defined(LWIP_HOOK_VLAN_SET) */ + sizeof(struct eth_hdr)); + /* According to RFC 3297, chapter 2.6.2 (Forwarding Rules), a packet with + a link-local source address must always be "directly to its destination + on the same physical link. The host MUST NOT send the packet to any + router for forwarding". */ + if (!ip4_addr_islinklocal(&iphdr->src)) +#endif /* LWIP_AUTOIP */ + { +#ifdef LWIP_HOOK_ETHARP_GET_GW + /* For advanced routing, a single default gateway might not be enough, so get + the IP address of the gateway to handle the current destination address. */ + dst_addr = LWIP_HOOK_ETHARP_GET_GW(netif, ipaddr); + if (dst_addr == NULL) +#endif /* LWIP_HOOK_ETHARP_GET_GW */ + { + /* interface has default gateway? */ + if (!ip4_addr_isany_val(*netif_ip4_gw(netif))) { + /* send to hardware address of default gateway IP address */ + dst_addr = netif_ip4_gw(netif); + /* no default gateway available */ + } else { + /* no route to destination error (default gateway missing) */ + return ERR_RTE; + } + } + } + } +#if LWIP_NETIF_HWADDRHINT + if (netif->addr_hint != NULL) { + /* per-pcb cached entry was given */ + u8_t etharp_cached_entry = *(netif->addr_hint); + if (etharp_cached_entry < ARP_TABLE_SIZE) { +#endif /* LWIP_NETIF_HWADDRHINT */ + if ((arp_table[etharp_cached_entry].state >= ETHARP_STATE_STABLE) && + (ip4_addr_cmp(dst_addr, &arp_table[etharp_cached_entry].ipaddr))) { + /* the per-pcb-cached entry is stable and the right one! */ + ETHARP_STATS_INC(etharp.cachehit); + return etharp_output_to_arp_index(netif, q, etharp_cached_entry); + } +#if LWIP_NETIF_HWADDRHINT + } + } +#endif /* LWIP_NETIF_HWADDRHINT */ + + /* find stable entry: do this here since this is a critical path for + throughput and etharp_find_entry() is kind of slow */ + for (i = 0; i < ARP_TABLE_SIZE; i++) { + if ((arp_table[i].state >= ETHARP_STATE_STABLE) && + (ip4_addr_cmp(dst_addr, &arp_table[i].ipaddr))) { + /* found an existing, stable entry */ + ETHARP_SET_HINT(netif, i); + return etharp_output_to_arp_index(netif, q, i); + } + } + /* no stable entry found, use the (slower) query function: + queue on destination Ethernet address belonging to ipaddr */ + return etharp_query(netif, dst_addr, q); + } + + /* continuation for multicast/broadcast destinations */ + /* obtain source Ethernet address of the given interface */ + /* send packet directly on the link */ + return etharp_send_ip(netif, q, (struct eth_addr*)(netif->hwaddr), dest); +} + +/** + * Send an ARP request for the given IP address and/or queue a packet. + * + * If the IP address was not yet in the cache, a pending ARP cache entry + * is added and an ARP request is sent for the given address. The packet + * is queued on this entry. + * + * If the IP address was already pending in the cache, a new ARP request + * is sent for the given address. The packet is queued on this entry. + * + * If the IP address was already stable in the cache, and a packet is + * given, it is directly sent and no ARP request is sent out. + * + * If the IP address was already stable in the cache, and no packet is + * given, an ARP request is sent out. + * + * @param netif The lwIP network interface on which ipaddr + * must be queried for. + * @param ipaddr The IP address to be resolved. + * @param q If non-NULL, a pbuf that must be delivered to the IP address. + * q is not freed by this function. + * + * @note q must only be ONE packet, not a packet queue! + * + * @return + * - ERR_BUF Could not make room for Ethernet header. + * - ERR_MEM Hardware address unknown, and no more ARP entries available + * to query for address or queue the packet. + * - ERR_MEM Could not queue packet due to memory shortage. + * - ERR_RTE No route to destination (no gateway to external networks). + * - ERR_ARG Non-unicast address given, those will not appear in ARP cache. + * + */ +err_t +etharp_query(struct netif *netif, const ip4_addr_t *ipaddr, struct pbuf *q) +{ + struct eth_addr * srcaddr = (struct eth_addr *)netif->hwaddr; + err_t result = ERR_MEM; + int is_new_entry = 0; + s8_t i; /* ARP entry index */ + + /* non-unicast address? */ + if (ip4_addr_isbroadcast(ipaddr, netif) || + ip4_addr_ismulticast(ipaddr) || + ip4_addr_isany(ipaddr)) { + LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("etharp_query: will not add non-unicast IP address to ARP cache\n")); + return ERR_ARG; + } + + /* find entry in ARP cache, ask to create entry if queueing packet */ + i = etharp_find_entry(ipaddr, ETHARP_FLAG_TRY_HARD, netif); + + /* could not find or create entry? */ + if (i < 0) { + LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("etharp_query: could not create ARP entry\n")); + if (q) { + LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("etharp_query: packet dropped\n")); + ETHARP_STATS_INC(etharp.memerr); + } + return (err_t)i; + } + + /* mark a fresh entry as pending (we just sent a request) */ + if (arp_table[i].state == ETHARP_STATE_EMPTY) { + is_new_entry = 1; + arp_table[i].state = ETHARP_STATE_PENDING; + /* record network interface for re-sending arp request in etharp_tmr */ + arp_table[i].netif = netif; + } + + /* { i is either a STABLE or (new or existing) PENDING entry } */ + LWIP_ASSERT("arp_table[i].state == PENDING or STABLE", + ((arp_table[i].state == ETHARP_STATE_PENDING) || + (arp_table[i].state >= ETHARP_STATE_STABLE))); + + /* do we have a new entry? or an implicit query request? */ + if (is_new_entry || (q == NULL)) { + /* try to resolve it; send out ARP request */ + result = etharp_request(netif, ipaddr); + if (result != ERR_OK) { + /* ARP request couldn't be sent */ + /* We don't re-send arp request in etharp_tmr, but we still queue packets, + since this failure could be temporary, and the next packet calling + etharp_query again could lead to sending the queued packets. */ + } + if (q == NULL) { + return result; + } + } + + /* packet given? */ + LWIP_ASSERT("q != NULL", q != NULL); + /* stable entry? */ + if (arp_table[i].state >= ETHARP_STATE_STABLE) { + /* we have a valid IP->Ethernet address mapping */ + ETHARP_SET_HINT(netif, i); + /* send the packet */ + result = etharp_send_ip(netif, q, srcaddr, &(arp_table[i].ethaddr)); + /* pending entry? (either just created or already pending */ + } else if (arp_table[i].state == ETHARP_STATE_PENDING) { + /* entry is still pending, queue the given packet 'q' */ + struct pbuf *p; + int copy_needed = 0; + /* IF q includes a PBUF_REF, PBUF_POOL or PBUF_RAM, we have no choice but + * to copy the whole queue into a new PBUF_RAM (see bug #11400) + * PBUF_ROMs can be left as they are, since ROM must not get changed. */ + p = q; + while (p) { + LWIP_ASSERT("no packet queues allowed!", (p->len != p->tot_len) || (p->next == 0)); + if (p->type != PBUF_ROM) { + copy_needed = 1; + break; + } + p = p->next; + } + if (copy_needed) { + /* copy the whole packet into new pbufs */ + p = pbuf_alloc(PBUF_RAW_TX, p->tot_len, PBUF_RAM); + if (p != NULL) { + if (pbuf_copy(p, q) != ERR_OK) { + pbuf_free(p); + p = NULL; + } + } + } else { + /* referencing the old pbuf is enough */ + p = q; + pbuf_ref(p); + } + /* packet could be taken over? */ + if (p != NULL) { + /* queue packet ... */ +#if ARP_QUEUEING + struct etharp_q_entry *new_entry; + /* allocate a new arp queue entry */ + new_entry = (struct etharp_q_entry *)memp_malloc(MEMP_ARP_QUEUE); + if (new_entry != NULL) { + unsigned int qlen = 0; + new_entry->next = 0; + new_entry->p = p; + if (arp_table[i].q != NULL) { + /* queue was already existent, append the new entry to the end */ + struct etharp_q_entry *r; + r = arp_table[i].q; + qlen++; + while (r->next != NULL) { + r = r->next; + qlen++; + } + r->next = new_entry; + } else { + /* queue did not exist, first item in queue */ + arp_table[i].q = new_entry; + } +#if ARP_QUEUE_LEN + if (qlen >= ARP_QUEUE_LEN) { + struct etharp_q_entry *old; + old = arp_table[i].q; + arp_table[i].q = arp_table[i].q->next; + pbuf_free(old->p); + memp_free(MEMP_ARP_QUEUE, old); + } +#endif + LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("etharp_query: queued packet %p on ARP entry %"S16_F"\n", (void *)q, (s16_t)i)); + result = ERR_OK; + } else { + /* the pool MEMP_ARP_QUEUE is empty */ + pbuf_free(p); + LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("etharp_query: could not queue a copy of PBUF_REF packet %p (out of memory)\n", (void *)q)); + result = ERR_MEM; + } +#else /* ARP_QUEUEING */ + /* always queue one packet per ARP request only, freeing a previously queued packet */ + if (arp_table[i].q != NULL) { + LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("etharp_query: dropped previously queued packet %p for ARP entry %"S16_F"\n", (void *)q, (s16_t)i)); + pbuf_free(arp_table[i].q); + } + arp_table[i].q = p; + result = ERR_OK; + LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("etharp_query: queued packet %p on ARP entry %"S16_F"\n", (void *)q, (s16_t)i)); +#endif /* ARP_QUEUEING */ + } else { + ETHARP_STATS_INC(etharp.memerr); + LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("etharp_query: could not queue a copy of PBUF_REF packet %p (out of memory)\n", (void *)q)); + result = ERR_MEM; + } + } + return result; +} + +/** + * Send a raw ARP packet (opcode and all addresses can be modified) + * + * @param netif the lwip network interface on which to send the ARP packet + * @param ethsrc_addr the source MAC address for the ethernet header + * @param ethdst_addr the destination MAC address for the ethernet header + * @param hwsrc_addr the source MAC address for the ARP protocol header + * @param ipsrc_addr the source IP address for the ARP protocol header + * @param hwdst_addr the destination MAC address for the ARP protocol header + * @param ipdst_addr the destination IP address for the ARP protocol header + * @param opcode the type of the ARP packet + * @return ERR_OK if the ARP packet has been sent + * ERR_MEM if the ARP packet couldn't be allocated + * any other err_t on failure + */ +#if !LWIP_AUTOIP +static +#endif /* LWIP_AUTOIP */ +err_t +etharp_raw(struct netif *netif, const struct eth_addr *ethsrc_addr, + const struct eth_addr *ethdst_addr, + const struct eth_addr *hwsrc_addr, const ip4_addr_t *ipsrc_addr, + const struct eth_addr *hwdst_addr, const ip4_addr_t *ipdst_addr, + const u16_t opcode) +{ + struct pbuf *p; + err_t result = ERR_OK; + struct eth_hdr *ethhdr; +#if ETHARP_SUPPORT_VLAN && defined(LWIP_HOOK_VLAN_SET) + struct eth_vlan_hdr *vlanhdr; +#endif /* ETHARP_SUPPORT_VLAN && defined(LWIP_HOOK_VLAN_SET) */ + struct etharp_hdr *hdr; +#if LWIP_AUTOIP + const u8_t * ethdst_hwaddr; +#endif /* LWIP_AUTOIP */ + + LWIP_ASSERT("netif != NULL", netif != NULL); + + /* allocate a pbuf for the outgoing ARP request packet */ + p = pbuf_alloc(PBUF_RAW_TX, SIZEOF_ETHARP_PACKET_TX, PBUF_RAM); + /* could allocate a pbuf for an ARP request? */ + if (p == NULL) { + LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_SERIOUS, + ("etharp_raw: could not allocate pbuf for ARP request.\n")); + ETHARP_STATS_INC(etharp.memerr); + return ERR_MEM; + } + LWIP_ASSERT("check that first pbuf can hold struct etharp_hdr", + (p->len >= SIZEOF_ETHARP_PACKET_TX)); + + ethhdr = (struct eth_hdr *)p->payload; +#if ETHARP_SUPPORT_VLAN && defined(LWIP_HOOK_VLAN_SET) + vlanhdr = (struct eth_vlan_hdr*)(((u8_t*)ethhdr) + SIZEOF_ETH_HDR); + hdr = (struct etharp_hdr *)((u8_t*)ethhdr + SIZEOF_ETH_HDR + SIZEOF_VLAN_HDR); +#else /* ETHARP_SUPPORT_VLAN && defined(LWIP_HOOK_VLAN_SET) */ + hdr = (struct etharp_hdr *)((u8_t*)ethhdr + SIZEOF_ETH_HDR); +#endif /* ETHARP_SUPPORT_VLAN && defined(LWIP_HOOK_VLAN_SET) */ + LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("etharp_raw: sending raw ARP packet.\n")); + hdr->opcode = htons(opcode); + + LWIP_ASSERT("netif->hwaddr_len must be the same as ETH_HWADDR_LEN for etharp!", + (netif->hwaddr_len == ETH_HWADDR_LEN)); +#if LWIP_AUTOIP + /* If we are using Link-Local, all ARP packets that contain a Link-Local + * 'sender IP address' MUST be sent using link-layer broadcast instead of + * link-layer unicast. (See RFC3927 Section 2.5, last paragraph) */ + ethdst_hwaddr = ip4_addr_islinklocal(ipsrc_addr) ? (const u8_t*)(ethbroadcast.addr) : ethdst_addr->addr; +#endif /* LWIP_AUTOIP */ + /* Write the ARP MAC-Addresses */ + ETHADDR16_COPY(&hdr->shwaddr, hwsrc_addr); + ETHADDR16_COPY(&hdr->dhwaddr, hwdst_addr); + /* Copy struct ip4_addr2 to aligned ip4_addr, to support compilers without + * structure packing. */ + IPADDR2_COPY(&hdr->sipaddr, ipsrc_addr); + IPADDR2_COPY(&hdr->dipaddr, ipdst_addr); + + hdr->hwtype = PP_HTONS(HWTYPE_ETHERNET); + hdr->proto = PP_HTONS(ETHTYPE_IP); + /* set hwlen and protolen */ + hdr->hwlen = ETH_HWADDR_LEN; + hdr->protolen = sizeof(ip4_addr_t); + +#if ETHARP_SUPPORT_VLAN && defined(LWIP_HOOK_VLAN_SET) + ethhdr->type = PP_HTONS(ETHTYPE_VLAN); + vlanhdr->tpid = PP_HTONS(ETHTYPE_ARP); + vlanhdr->prio_vid = 0; + if (!LWIP_HOOK_VLAN_SET(netif, ethhdr, vlanhdr)) { + /* packet shall not contain VLAN header, so hide it and set correct ethertype */ + pbuf_header(p, -SIZEOF_VLAN_HDR); + ethhdr = (struct eth_hdr *)p->payload; +#endif /* ETHARP_SUPPORT_VLAN && defined(LWIP_HOOK_VLAN_SET) */ + ethhdr->type = PP_HTONS(ETHTYPE_ARP); +#if ETHARP_SUPPORT_VLAN && defined(LWIP_HOOK_VLAN_SET) + } +#endif /* ETHARP_SUPPORT_VLAN && defined(LWIP_HOOK_VLAN_SET) */ + + /* Write the Ethernet MAC-Addresses */ +#if LWIP_AUTOIP + ETHADDR16_COPY(ðhdr->dest, ethdst_hwaddr); +#else /* LWIP_AUTOIP */ + ETHADDR16_COPY(ðhdr->dest, ethdst_addr); +#endif /* LWIP_AUTOIP */ + ETHADDR16_COPY(ðhdr->src, ethsrc_addr); + + /* send ARP query */ + result = netif->linkoutput(netif, p); + ETHARP_STATS_INC(etharp.xmit); + /* free ARP query packet */ + pbuf_free(p); + p = NULL; + /* could not allocate pbuf for ARP request */ + + return result; +} + +/** + * Send an ARP request packet asking for ipaddr to a specific eth address. + * Used to send unicast request to refresh the ARP table just before an entry + * times out + * + * @param netif the lwip network interface on which to send the request + * @param ipaddr the IP address for which to ask + * @param hw_dst_addr the ethernet address to send this packet to + * @return ERR_OK if the request has been sent + * ERR_MEM if the ARP packet couldn't be allocated + * any other err_t on failure + */ +static err_t +etharp_request_dst(struct netif *netif, const ip4_addr_t *ipaddr, const struct eth_addr* hw_dst_addr) +{ + return etharp_raw(netif, (struct eth_addr *)netif->hwaddr, hw_dst_addr, + (struct eth_addr *)netif->hwaddr, netif_ip4_addr(netif), ðzero, + ipaddr, ARP_REQUEST); +} + +/** + * Send an ARP request packet asking for ipaddr. + * + * @param netif the lwip network interface on which to send the request + * @param ipaddr the IP address for which to ask + * @return ERR_OK if the request has been sent + * ERR_MEM if the ARP packet couldn't be allocated + * any other err_t on failure + */ +err_t +etharp_request(struct netif *netif, const ip4_addr_t *ipaddr) +{ + LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("etharp_request: sending ARP request.\n")); + return etharp_request_dst(netif, ipaddr, ðbroadcast); +} +#endif /* LWIP_IPV4 && LWIP_ARP */ + +#endif /* LWIP_ARP || LWIP_ETHERNET */ diff --git a/components/lwip/netif/ethernet.c b/components/lwip/netif/ethernet.c new file mode 100755 index 0000000000..6d843913da --- /dev/null +++ b/components/lwip/netif/ethernet.c @@ -0,0 +1,222 @@ +/** + * @file + * Ethernet common functions + */ + +/* + * Copyright (c) 2001-2003 Swedish Institute of Computer Science. + * Copyright (c) 2003-2004 Leon Woestenberg + * Copyright (c) 2003-2004 Axon Digital Design B.V., The Netherlands. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + */ + +#include "lwip/opt.h" + +#if LWIP_ARP || LWIP_ETHERNET + +#include "netif/ethernet.h" +#include "lwip/def.h" +#include "lwip/stats.h" +#include "netif/etharp.h" +#include "lwip/ip.h" +#include "lwip/snmp.h" + +#include + +#if PPPOE_SUPPORT +#include "netif/ppp/pppoe.h" +#endif /* PPPOE_SUPPORT */ + +const struct eth_addr ethbroadcast = {{0xff,0xff,0xff,0xff,0xff,0xff}}; +const struct eth_addr ethzero = {{0,0,0,0,0,0}}; + +/** + * Process received ethernet frames. Using this function instead of directly + * calling ip_input and passing ARP frames through etharp in ethernetif_input, + * the ARP cache is protected from concurrent access. + * + * @param p the received packet, p->payload pointing to the ethernet header + * @param netif the network interface on which the packet was received + */ +err_t +ethernet_input(struct pbuf *p, struct netif *netif) +{ + struct eth_hdr* ethhdr; + u16_t type; +#if LWIP_ARP || ETHARP_SUPPORT_VLAN || LWIP_IPV6 + s16_t ip_hdr_offset = SIZEOF_ETH_HDR; +#endif /* LWIP_ARP || ETHARP_SUPPORT_VLAN */ + + if (p->len <= SIZEOF_ETH_HDR) { + /* a packet with only an ethernet header (or less) is not valid for us */ + ETHARP_STATS_INC(etharp.proterr); + ETHARP_STATS_INC(etharp.drop); + MIB2_STATS_NETIF_INC(netif, ifinerrors); + goto free_and_return; + } + + /* points to packet payload, which starts with an Ethernet header */ + ethhdr = (struct eth_hdr *)p->payload; + LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, + ("ethernet_input: dest:%"X8_F":%"X8_F":%"X8_F":%"X8_F":%"X8_F":%"X8_F", src:%"X8_F":%"X8_F":%"X8_F":%"X8_F":%"X8_F":%"X8_F", type:%"X16_F"\n", + (unsigned)ethhdr->dest.addr[0], (unsigned)ethhdr->dest.addr[1], (unsigned)ethhdr->dest.addr[2], + (unsigned)ethhdr->dest.addr[3], (unsigned)ethhdr->dest.addr[4], (unsigned)ethhdr->dest.addr[5], + (unsigned)ethhdr->src.addr[0], (unsigned)ethhdr->src.addr[1], (unsigned)ethhdr->src.addr[2], + (unsigned)ethhdr->src.addr[3], (unsigned)ethhdr->src.addr[4], (unsigned)ethhdr->src.addr[5], + (unsigned)htons(ethhdr->type))); + + type = ethhdr->type; +#if ETHARP_SUPPORT_VLAN + if (type == PP_HTONS(ETHTYPE_VLAN)) { + struct eth_vlan_hdr *vlan = (struct eth_vlan_hdr*)(((char*)ethhdr) + SIZEOF_ETH_HDR); + if (p->len <= SIZEOF_ETH_HDR + SIZEOF_VLAN_HDR) { + /* a packet with only an ethernet/vlan header (or less) is not valid for us */ + ETHARP_STATS_INC(etharp.proterr); + ETHARP_STATS_INC(etharp.drop); + MIB2_STATS_NETIF_INC(netif, ifinerrors); + goto free_and_return; + } +#if defined(LWIP_HOOK_VLAN_CHECK) || defined(ETHARP_VLAN_CHECK) || defined(ETHARP_VLAN_CHECK_FN) /* if not, allow all VLANs */ +#ifdef LWIP_HOOK_VLAN_CHECK + if (!LWIP_HOOK_VLAN_CHECK(netif, ethhdr, vlan)) { +#elif defined(ETHARP_VLAN_CHECK_FN) + if (!ETHARP_VLAN_CHECK_FN(ethhdr, vlan)) { +#elif defined(ETHARP_VLAN_CHECK) + if (VLAN_ID(vlan) != ETHARP_VLAN_CHECK) { +#endif + /* silently ignore this packet: not for our VLAN */ + pbuf_free(p); + return ERR_OK; + } +#endif /* defined(LWIP_HOOK_VLAN_CHECK) || defined(ETHARP_VLAN_CHECK) || defined(ETHARP_VLAN_CHECK_FN) */ + type = vlan->tpid; + ip_hdr_offset = SIZEOF_ETH_HDR + SIZEOF_VLAN_HDR; + } +#endif /* ETHARP_SUPPORT_VLAN */ + +#if LWIP_ARP_FILTER_NETIF + netif = LWIP_ARP_FILTER_NETIF_FN(p, netif, htons(type)); +#endif /* LWIP_ARP_FILTER_NETIF*/ + + if (ethhdr->dest.addr[0] & 1) { + /* this might be a multicast or broadcast packet */ + if (ethhdr->dest.addr[0] == LL_IP4_MULTICAST_ADDR_0) { +#if LWIP_IPV4 + if ((ethhdr->dest.addr[1] == LL_IP4_MULTICAST_ADDR_1) && + (ethhdr->dest.addr[2] == LL_IP4_MULTICAST_ADDR_2)) { + /* mark the pbuf as link-layer multicast */ + p->flags |= PBUF_FLAG_LLMCAST; + } +#endif /* LWIP_IPV4 */ + } +#if LWIP_IPV6 + else if ((ethhdr->dest.addr[0] == LL_IP6_MULTICAST_ADDR_0) && + (ethhdr->dest.addr[1] == LL_IP6_MULTICAST_ADDR_1)) { + /* mark the pbuf as link-layer multicast */ + p->flags |= PBUF_FLAG_LLMCAST; + } +#endif /* LWIP_IPV6 */ + else if (eth_addr_cmp(ðhdr->dest, ðbroadcast)) { + /* mark the pbuf as link-layer broadcast */ + p->flags |= PBUF_FLAG_LLBCAST; + } + } + + switch (type) { +#if LWIP_IPV4 && LWIP_ARP + /* IP packet? */ + case PP_HTONS(ETHTYPE_IP): + if (!(netif->flags & NETIF_FLAG_ETHARP)) { + goto free_and_return; + } +#if ETHARP_TRUST_IP_MAC + /* update ARP table */ + etharp_ip_input(netif, p); +#endif /* ETHARP_TRUST_IP_MAC */ + /* skip Ethernet header */ + if ((p->len < ip_hdr_offset) || pbuf_header(p, (s16_t)-ip_hdr_offset)) { + LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_WARNING, + ("ethernet_input: IPv4 packet dropped, too short (%"S16_F"/%"S16_F")\n", + p->tot_len, ip_hdr_offset)); + LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("Can't move over header in packet")); + goto free_and_return; + } else { + /* pass to IP layer */ + ip4_input(p, netif); + } + break; + + case PP_HTONS(ETHTYPE_ARP): + if (!(netif->flags & NETIF_FLAG_ETHARP)) { + goto free_and_return; + } + /* pass p to ARP module */ + etharp_arp_input(netif, (struct eth_addr*)(netif->hwaddr), p); + break; +#endif /* LWIP_IPV4 && LWIP_ARP */ +#if PPPOE_SUPPORT + case PP_HTONS(ETHTYPE_PPPOEDISC): /* PPP Over Ethernet Discovery Stage */ + pppoe_disc_input(netif, p); + break; + + case PP_HTONS(ETHTYPE_PPPOE): /* PPP Over Ethernet Session Stage */ + pppoe_data_input(netif, p); + break; +#endif /* PPPOE_SUPPORT */ + +#if LWIP_IPV6 + case PP_HTONS(ETHTYPE_IPV6): /* IPv6 */ + /* skip Ethernet header */ + if ((p->len < ip_hdr_offset) || pbuf_header(p, (s16_t)-ip_hdr_offset)) { + LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_WARNING, + ("ethernet_input: IPv6 packet dropped, too short (%"S16_F"/%"S16_F")\n", + p->tot_len, ip_hdr_offset)); + goto free_and_return; + } else { + /* pass to IPv6 layer */ + ip6_input(p, netif); + } + break; +#endif /* LWIP_IPV6 */ + + default: + ETHARP_STATS_INC(etharp.proterr); + ETHARP_STATS_INC(etharp.drop); + MIB2_STATS_NETIF_INC(netif, ifinunknownprotos); + goto free_and_return; + } + + /* This means the pbuf is freed or consumed, + so the caller doesn't have to free it again */ + return ERR_OK; + +free_and_return: + pbuf_free(p); + return ERR_OK; +} +#endif /* LWIP_ARP || LWIP_ETHERNET */ diff --git a/components/lwip/netif/ethernetif.c b/components/lwip/netif/ethernetif.c new file mode 100755 index 0000000000..b42483878e --- /dev/null +++ b/components/lwip/netif/ethernetif.c @@ -0,0 +1,339 @@ +/** + * @file + * Ethernet Interface Skeleton + * + */ + +/* + * Copyright (c) 2001-2004 Swedish Institute of Computer Science. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + * + */ + +/* + * This file is a skeleton for developing Ethernet network interface + * drivers for lwIP. Add code to the low_level functions and do a + * search-and-replace for the word "ethernetif" to replace it with + * something that better describes your network interface. + */ + +#include "lwip/opt.h" + +#if 0 /* don't build, this is only a skeleton, see previous comment */ + +#include "lwip/def.h" +#include "lwip/mem.h" +#include "lwip/pbuf.h" +#include "lwip/stats.h" +#include "lwip/snmp.h" +#include "lwip/ethip6.h" +#include "netif/etharp.h" +#include "netif/ppp/pppoe.h" + +/* Define those to better describe your network interface. */ +#define IFNAME0 'e' +#define IFNAME1 'n' + +/** + * Helper struct to hold private data used to operate your ethernet interface. + * Keeping the ethernet address of the MAC in this struct is not necessary + * as it is already kept in the struct netif. + * But this is only an example, anyway... + */ +struct ethernetif { + struct eth_addr *ethaddr; + /* Add whatever per-interface state that is needed here. */ +}; + +/* Forward declarations. */ +static void ethernetif_input(struct netif *netif); + +/** + * In this function, the hardware should be initialized. + * Called from ethernetif_init(). + * + * @param netif the already initialized lwip network interface structure + * for this ethernetif + */ +static void +low_level_init(struct netif *netif) +{ + struct ethernetif *ethernetif = netif->state; + + /* set MAC hardware address length */ + netif->hwaddr_len = ETHARP_HWADDR_LEN; + + /* set MAC hardware address */ + netif->hwaddr[0] = ; + ... + netif->hwaddr[5] = ; + + /* maximum transfer unit */ + netif->mtu = 1500; + + /* device capabilities */ + /* don't set NETIF_FLAG_ETHARP if this device is not an ethernet one */ + netif->flags = NETIF_FLAG_BROADCAST | NETIF_FLAG_ETHARP | NETIF_FLAG_LINK_UP; + +#if LWIP_IGMP + netif->flags |= NETIF_FLAG_IGMP; +#endif + +#if LWIP_IPV6 && LWIP_IPV6_MLD + /* + * For hardware/netifs that implement MAC filtering. + * All-nodes link-local is handled by default, so we must let the hardware know + * to allow multicast packets in. + * Should set mld_mac_filter previously. */ + if (netif->mld_mac_filter != NULL) { + ip6_addr_t ip6_allnodes_ll; + ip6_addr_set_allnodes_linklocal(&ip6_allnodes_ll); + netif->mld_mac_filter(netif, &ip6_allnodes_ll, MLD6_ADD_MAC_FILTER); + } +#endif /* LWIP_IPV6 && LWIP_IPV6_MLD */ + + /* Do whatever else is needed to initialize interface. */ +} + +/** + * This function should do the actual transmission of the packet. The packet is + * contained in the pbuf that is passed to the function. This pbuf + * might be chained. + * + * @param netif the lwip network interface structure for this ethernetif + * @param p the MAC packet to send (e.g. IP packet including MAC addresses and type) + * @return ERR_OK if the packet could be sent + * an err_t value if the packet couldn't be sent + * + * @note Returning ERR_MEM here if a DMA queue of your MAC is full can lead to + * strange results. You might consider waiting for space in the DMA queue + * to become available since the stack doesn't retry to send a packet + * dropped because of memory failure (except for the TCP timers). + */ + +static err_t +low_level_output(struct netif *netif, struct pbuf *p) +{ + struct ethernetif *ethernetif = netif->state; + struct pbuf *q; + + initiate transfer(); + +#if ETH_PAD_SIZE + pbuf_header(p, -ETH_PAD_SIZE); /* drop the padding word */ +#endif + + for (q = p; q != NULL; q = q->next) { + /* Send the data from the pbuf to the interface, one pbuf at a + time. The size of the data in each pbuf is kept in the ->len + variable. */ + send data from(q->payload, q->len); + } + + signal that packet should be sent(); + +#if ETH_PAD_SIZE + pbuf_header(p, ETH_PAD_SIZE); /* reclaim the padding word */ +#endif + + LINK_STATS_INC(link.xmit); + + return ERR_OK; +} + +/** + * Should allocate a pbuf and transfer the bytes of the incoming + * packet from the interface into the pbuf. + * + * @param netif the lwip network interface structure for this ethernetif + * @return a pbuf filled with the received packet (including MAC header) + * NULL on memory error + */ +static struct pbuf * +low_level_input(struct netif *netif) +{ + struct ethernetif *ethernetif = netif->state; + struct pbuf *p, *q; + u16_t len; + + /* Obtain the size of the packet and put it into the "len" + variable. */ + len = ; + +#if ETH_PAD_SIZE + len += ETH_PAD_SIZE; /* allow room for Ethernet padding */ +#endif + + /* We allocate a pbuf chain of pbufs from the pool. */ + p = pbuf_alloc(PBUF_RAW, len, PBUF_POOL); + + if (p != NULL) { + +#if ETH_PAD_SIZE + pbuf_header(p, -ETH_PAD_SIZE); /* drop the padding word */ +#endif + + /* We iterate over the pbuf chain until we have read the entire + * packet into the pbuf. */ + for (q = p; q != NULL; q = q->next) { + /* Read enough bytes to fill this pbuf in the chain. The + * available data in the pbuf is given by the q->len + * variable. + * This does not necessarily have to be a memcpy, you can also preallocate + * pbufs for a DMA-enabled MAC and after receiving truncate it to the + * actually received size. In this case, ensure the tot_len member of the + * pbuf is the sum of the chained pbuf len members. + */ + read data into(q->payload, q->len); + } + acknowledge that packet has been read(); + +#if ETH_PAD_SIZE + pbuf_header(p, ETH_PAD_SIZE); /* reclaim the padding word */ +#endif + + LINK_STATS_INC(link.recv); + } else { + drop packet(); + LINK_STATS_INC(link.memerr); + LINK_STATS_INC(link.drop); + } + + return p; +} + +/** + * This function should be called when a packet is ready to be read + * from the interface. It uses the function low_level_input() that + * should handle the actual reception of bytes from the network + * interface. Then the type of the received packet is determined and + * the appropriate input function is called. + * + * @param netif the lwip network interface structure for this ethernetif + */ +static void +ethernetif_input(struct netif *netif) +{ + struct ethernetif *ethernetif; + struct eth_hdr *ethhdr; + struct pbuf *p; + + ethernetif = netif->state; + + /* move received packet into a new pbuf */ + p = low_level_input(netif); + /* no packet could be read, silently ignore this */ + if (p == NULL) return; + /* points to packet payload, which starts with an Ethernet header */ + ethhdr = p->payload; + + switch (htons(ethhdr->type)) { + /* IP or ARP packet? */ + case ETHTYPE_IP: + case ETHTYPE_IPV6: + case ETHTYPE_ARP: +#if PPPOE_SUPPORT + /* PPPoE packet? */ + case ETHTYPE_PPPOEDISC: + case ETHTYPE_PPPOE: +#endif /* PPPOE_SUPPORT */ + /* full packet send to tcpip_thread to process */ + if (netif->input(p, netif)!=ERR_OK) + { LWIP_DEBUGF(NETIF_DEBUG, ("ethernetif_input: IP input error\n")); + pbuf_free(p); + p = NULL; + } + break; + + default: + pbuf_free(p); + p = NULL; + break; + } +} + +/** + * Should be called at the beginning of the program to set up the + * network interface. It calls the function low_level_init() to do the + * actual setup of the hardware. + * + * This function should be passed as a parameter to netif_add(). + * + * @param netif the lwip network interface structure for this ethernetif + * @return ERR_OK if the loopif is initialized + * ERR_MEM if private data couldn't be allocated + * any other err_t on error + */ +err_t +ethernetif_init(struct netif *netif) +{ + struct ethernetif *ethernetif; + + LWIP_ASSERT("netif != NULL", (netif != NULL)); + + ethernetif = mem_malloc(sizeof(struct ethernetif)); + if (ethernetif == NULL) { + LWIP_DEBUGF(NETIF_DEBUG, ("ethernetif_init: out of memory\n")); + return ERR_MEM; + } + +#if LWIP_NETIF_HOSTNAME + /* Initialize interface hostname */ + netif->hostname = "lwip"; +#endif /* LWIP_NETIF_HOSTNAME */ + + /* + * Initialize the snmp variables and counters inside the struct netif. + * The last argument should be replaced with your link speed, in units + * of bits per second. + */ + MIB2_INIT_NETIF(netif, snmp_ifType_ethernet_csmacd, LINK_SPEED_OF_YOUR_NETIF_IN_BPS); + + netif->state = ethernetif; + netif->name[0] = IFNAME0; + netif->name[1] = IFNAME1; + /* We directly use etharp_output() here to save a function call. + * You can instead declare your own function an call etharp_output() + * from it if you have to do some checks before sending (e.g. if link + * is available...) */ + netif->output = etharp_output; +#if LWIP_IPV6 + netif->output_ip6 = ethip6_output; +#endif /* LWIP_IPV6 */ + netif->linkoutput = low_level_output; + + ethernetif->ethaddr = (struct eth_addr *)&(netif->hwaddr[0]); + + /* initialize the hardware */ + low_level_init(netif); + + return ERR_OK; +} + +#endif /* 0 */ diff --git a/components/lwip/netif/lowpan6.c b/components/lwip/netif/lowpan6.c new file mode 100755 index 0000000000..15d10278fd --- /dev/null +++ b/components/lwip/netif/lowpan6.c @@ -0,0 +1,1196 @@ +/** + * @file + * + * 6LowPAN output for IPv6. Uses ND tables for link-layer addressing. Fragments packets to 6LowPAN units. + */ + +/* + * Copyright (c) 2015 Inico Technologies Ltd. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Ivan Delamer + * + * + * Please coordinate changes and requests with Ivan Delamer + * + */ + +#include "netif/lowpan6.h" + +#if LWIP_IPV6 && LWIP_6LOWPAN + +#include "lwip/ip.h" +#include "lwip/pbuf.h" +#include "lwip/ip_addr.h" +#include "lwip/netif.h" +#include "lwip/nd6.h" +#include "lwip/mem.h" +#include "lwip/udp.h" +#include "lwip/tcpip.h" +#include "lwip/snmp.h" + +#include + +struct ieee_802154_addr { + u8_t addr_len; + u8_t addr[8]; +}; + +/** This is a helper struct. + */ +struct lowpan6_reass_helper { + struct pbuf *pbuf; + struct lowpan6_reass_helper *next_packet; + u8_t timer; + struct ieee_802154_addr sender_addr; + u16_t datagram_size; + u16_t datagram_tag; +}; + +static struct lowpan6_reass_helper * reass_list; + +#if LWIP_6LOWPAN_NUM_CONTEXTS > 0 +static ip6_addr_t lowpan6_context[LWIP_6LOWPAN_NUM_CONTEXTS]; +#endif + +static u16_t ieee_802154_pan_id; + +static const struct ieee_802154_addr ieee_802154_broadcast = {2, {0xff, 0xff}}; + +#if LWIP_6LOWPAN_INFER_SHORT_ADDRESS +static struct ieee_802154_addr short_mac_addr = {2, {0,0}}; +#endif /* LWIP_6LOWPAN_INFER_SHORT_ADDRESS */ + +static err_t dequeue_datagram(struct lowpan6_reass_helper *lrh); + +/** + * Periodic timer for 6LowPAN functions: + * + * - Remove incomplete/old packets + */ +void +lowpan6_tmr(void) +{ + struct lowpan6_reass_helper *lrh, *lrh_temp; + + lrh = reass_list; + while (lrh != NULL) { + lrh_temp = lrh->next_packet; + if ((--lrh->timer) == 0) { + dequeue_datagram(lrh); + pbuf_free(lrh->pbuf); + mem_free(lrh); + } + lrh = lrh_temp; + } +} + +/** + * Removes a datagram from the reassembly queue. + **/ +static err_t +dequeue_datagram(struct lowpan6_reass_helper *lrh) +{ + struct lowpan6_reass_helper *lrh_temp; + + if (reass_list == lrh) { + reass_list = reass_list->next_packet; + } else { + lrh_temp = reass_list; + while (lrh_temp != NULL) { + if (lrh_temp->next_packet == lrh) { + lrh_temp->next_packet = lrh->next_packet; + break; + } + lrh_temp = lrh_temp->next_packet; + } + } + + return ERR_OK; +} + +static s8_t +lowpan6_context_lookup(const ip6_addr_t *ip6addr) +{ + s8_t i; + + for (i = 0; i < LWIP_6LOWPAN_NUM_CONTEXTS; i++) { + if (ip6_addr_netcmp(&lowpan6_context[i], ip6addr)) { + return i; + } + } + + return -1; +} + +/* Determine compression mode for unicast address. */ +static s8_t +lowpan6_get_address_mode(const ip6_addr_t *ip6addr, const struct ieee_802154_addr *mac_addr) +{ + if (mac_addr->addr_len == 2) { + if ((ip6addr->addr[2] == (u32_t)PP_HTONL(0x000000ff)) && + ((ip6addr->addr[3] & PP_HTONL(0xffff0000)) == PP_NTOHL(0xfe000000))) { + if ((ip6addr->addr[3] & PP_HTONL(0x0000ffff)) == ntohl((mac_addr->addr[0] << 8) | mac_addr->addr[1])) { + return 3; + } + } + } else if (mac_addr->addr_len == 8) { + if ((ip6addr->addr[2] == ntohl(((mac_addr->addr[0] ^ 2) << 24) | (mac_addr->addr[1] << 16) | mac_addr->addr[2] << 8 | mac_addr->addr[3])) && + (ip6addr->addr[3] == ntohl((mac_addr->addr[4] << 24) | (mac_addr->addr[5] << 16) | mac_addr->addr[6] << 8 | mac_addr->addr[7]))) { + return 3; + } + } + + if ((ip6addr->addr[2] == PP_HTONL(0x000000ffUL)) && + ((ip6addr->addr[3] & PP_HTONL(0xffff0000)) == PP_NTOHL(0xfe000000UL))) { + return 2; + } + + return 1; +} + +/* Determine compression mode for multicast address. */ +static s8_t +lowpan6_get_address_mode_mc(const ip6_addr_t *ip6addr) +{ + if ((ip6addr->addr[0] == PP_HTONL(0xff020000)) && + (ip6addr->addr[1] == 0) && + (ip6addr->addr[2] == 0) && + ((ip6addr->addr[3] & PP_HTONL(0xffffff00)) == 0)) { + return 3; + } else if (((ip6addr->addr[0] & PP_HTONL(0xff00ffff)) == PP_HTONL(0xff000000)) && + (ip6addr->addr[1] == 0)) { + if ((ip6addr->addr[2] == 0) && + ((ip6addr->addr[3] & PP_HTONL(0xff000000)) == 0)) { + return 2; + } else if ((ip6addr->addr[2] & PP_HTONL(0xffffff00)) == 0) { + return 1; + } + } + + return 0; +} + +/* + * Encapsulates data into IEEE 802.15.4 frames. + * Fragments an IPv6 datagram into 6LowPAN units, which fit into IEEE 802.15.4 frames. + * If configured, will compress IPv6 and or UDP headers. + * */ +static err_t +lowpan6_frag(struct netif *netif, struct pbuf *p, const struct ieee_802154_addr *src, const struct ieee_802154_addr *dst) +{ + struct pbuf * p_frag; + u16_t frag_len, remaining_len; + u8_t * buffer; + u8_t ieee_header_len; + u8_t lowpan6_header_len; + s8_t i; + static u8_t frame_seq_num; + static u16_t datagram_tag; + u16_t datagram_offset; + err_t err = ERR_IF; + + /* We'll use a dedicated pbuf for building 6LowPAN fragments. */ + p_frag = pbuf_alloc(PBUF_RAW, 127, PBUF_RAM); + if (p_frag == NULL) { + MIB2_STATS_NETIF_INC(netif, ifoutdiscards); + return ERR_MEM; + } + + /* Write IEEE 802.15.4 header. */ + buffer = (u8_t*)p_frag->payload; + ieee_header_len = 0; + if (dst == &ieee_802154_broadcast) { + buffer[ieee_header_len++] = 0x01; /* data packet, no ack required. */ + } else { + buffer[ieee_header_len++] = 0x21; /* data packet, ack required. */ + } + buffer[ieee_header_len] = (0x00 << 4); /* 2003 frame version */ + buffer[ieee_header_len] |= (dst->addr_len == 2) ? (0x02 << 2) : (0x03 << 2); /* destination addressing mode */ + buffer[ieee_header_len] |= (src->addr_len == 2) ? (0x02 << 6) : (0x03 << 6); /* source addressing mode */ + ieee_header_len++; + buffer[ieee_header_len++] = frame_seq_num++; + + buffer[ieee_header_len++] = ieee_802154_pan_id & 0xff; /* pan id */ + buffer[ieee_header_len++] = (ieee_802154_pan_id >> 8) & 0xff; /* pan id */ + i = dst->addr_len; + while (i-- > 0) { + buffer[ieee_header_len++] = dst->addr[i]; + } + + buffer[ieee_header_len++] = ieee_802154_pan_id & 0xff; /* pan id */ + buffer[ieee_header_len++] = (ieee_802154_pan_id >> 8) & 0xff; /* pan id */ + i = src->addr_len; + while (i-- > 0) { + buffer[ieee_header_len++] = src->addr[i]; + } + +#if LWIP_6LOWPAN_IPHC + /* Perform 6LowPAN IPv6 header compression according to RFC 6282 */ + { + struct ip6_hdr *ip6hdr; + + /* Point to ip6 header and align copies of src/dest addresses. */ + ip6hdr = (struct ip6_hdr *)p->payload; + ip_addr_copy_from_ip6(ip_data.current_iphdr_dest, ip6hdr->dest); + ip_addr_copy_from_ip6(ip_data.current_iphdr_src, ip6hdr->src); + + /* Basic length of 6LowPAN header, set dispatch and clear fields. */ + lowpan6_header_len = 2; + buffer[ieee_header_len] = 0x60; + buffer[ieee_header_len + 1] = 0; + + /* Determine whether there will be a Context Identifier Extension byte or not. + * If so, set it already. */ +#if LWIP_6LOWPAN_NUM_CONTEXTS > 0 + buffer[ieee_header_len + 2] = 0; + + i = lowpan6_context_lookup(ip_2_ip6(&ip_data.current_iphdr_src)); + if (i >= 0) { + /* Stateful source address compression. */ + buffer[ieee_header_len + 1] |= 0x40; + buffer[ieee_header_len + 2] |= (i & 0x0f) << 4; + } + + i = lowpan6_context_lookup(ip_2_ip6(&ip_data.current_iphdr_dest)); + if (i >= 0) { + /* Stateful destination address compression. */ + buffer[ieee_header_len + 1] |= 0x04; + buffer[ieee_header_len + 2] |= i & 0x0f; + } + + if (buffer[ieee_header_len + 2] != 0x00) { + /* Context identifier extension byte is appended. */ + buffer[ieee_header_len + 1] |= 0x80; + lowpan6_header_len++; + } +#endif /* LWIP_6LOWPAN_NUM_CONTEXTS > 0 */ + + /* Determine TF field: Traffic Class, Flow Label */ + if (IP6H_FL(ip6hdr) == 0) { + /* Flow label is elided. */ + buffer[ieee_header_len] |= 0x10; + if (IP6H_TC(ip6hdr) == 0) { + /* Traffic class (ECN+DSCP) elided too. */ + buffer[ieee_header_len] |= 0x08; + } else { + /* Traffic class (ECN+DSCP) appended. */ + buffer[ieee_header_len + lowpan6_header_len++] = IP6H_TC(ip6hdr); + } + } else { + if (((IP6H_TC(ip6hdr) & 0x3f) == 0)) { + /* DSCP portion of Traffic Class is elided, ECN and FL are appended (3 bytes) */ + buffer[ieee_header_len] |= 0x08; + + buffer[ieee_header_len + lowpan6_header_len] = IP6H_TC(ip6hdr) & 0xc0; + buffer[ieee_header_len + lowpan6_header_len++] |= (IP6H_FL(ip6hdr) >> 16) & 0x0f; + buffer[ieee_header_len + lowpan6_header_len++] = (IP6H_FL(ip6hdr) >> 8) & 0xff; + buffer[ieee_header_len + lowpan6_header_len++] = IP6H_FL(ip6hdr) & 0xff; + } else { + /* Traffic class and flow label are appended (4 bytes) */ + buffer[ieee_header_len + lowpan6_header_len++] = IP6H_TC(ip6hdr); + buffer[ieee_header_len + lowpan6_header_len++] = (IP6H_FL(ip6hdr) >> 16) & 0x0f; + buffer[ieee_header_len + lowpan6_header_len++] = (IP6H_FL(ip6hdr) >> 8) & 0xff; + buffer[ieee_header_len + lowpan6_header_len++] = IP6H_FL(ip6hdr) & 0xff; + } + } + + /* Compress NH? + * Only if UDP for now. TODO support other NH compression. */ + if (IP6H_NEXTH(ip6hdr) == IP6_NEXTH_UDP) { + buffer[ieee_header_len] |= 0x04; + } else { + /* append nexth. */ + buffer[ieee_header_len + lowpan6_header_len++] = IP6H_NEXTH(ip6hdr); + } + + /* Compress hop limit? */ + if (IP6H_HOPLIM(ip6hdr) == 255) { + buffer[ieee_header_len] |= 0x03; + } else if (IP6H_HOPLIM(ip6hdr) == 64) { + buffer[ieee_header_len] |= 0x02; + } else if (IP6H_HOPLIM(ip6hdr) == 1) { + buffer[ieee_header_len] |= 0x01; + } else { + /* append hop limit */ + buffer[ieee_header_len + lowpan6_header_len++] = IP6H_HOPLIM(ip6hdr); + } + + /* Compress source address */ + if (((buffer[ieee_header_len + 1] & 0x40) != 0) || + (ip6_addr_islinklocal(ip_2_ip6(&ip_data.current_iphdr_src)))) { + /* Context-based or link-local source address compression. */ + i = lowpan6_get_address_mode(ip_2_ip6(&ip_data.current_iphdr_src), src); + buffer[ieee_header_len + 1] |= (i & 0x03) << 4; + if (i == 1) { + MEMCPY(buffer + ieee_header_len + lowpan6_header_len, (u8_t*)p->payload + 16, 8); + lowpan6_header_len += 8; + } else if (i == 2) { + MEMCPY(buffer + ieee_header_len + lowpan6_header_len, (u8_t*)p->payload + 22, 2); + lowpan6_header_len += 2; + } + } else if (ip6_addr_isany(ip_2_ip6(&ip_data.current_iphdr_src))) { + /* Special case: mark SAC and leave SAM=0 */ + buffer[ieee_header_len + 1] |= 0x40; + } else { + /* Append full address. */ + MEMCPY(buffer + ieee_header_len + lowpan6_header_len, (u8_t*)p->payload + 8, 16); + lowpan6_header_len += 16; + } + + /* Compress destination address */ + if (ip6_addr_ismulticast(ip_2_ip6(&ip_data.current_iphdr_dest))) { + /* TODO support stateful multicast address compression */ + + buffer[ieee_header_len + 1] |= 0x08; + + i = lowpan6_get_address_mode_mc(ip_2_ip6(&ip_data.current_iphdr_dest)); + buffer[ieee_header_len + 1] |= i & 0x03; + if (i == 0) { + MEMCPY(buffer + ieee_header_len + lowpan6_header_len, (u8_t*)p->payload + 24, 16); + lowpan6_header_len += 16; + } else if (i == 1) { + buffer[ieee_header_len + lowpan6_header_len++] = ((u8_t *)p->payload)[25]; + MEMCPY(buffer + ieee_header_len + lowpan6_header_len, (u8_t*)p->payload + 35, 5); + lowpan6_header_len += 5; + } else if (i == 2) { + buffer[ieee_header_len + lowpan6_header_len++] = ((u8_t *)p->payload)[25]; + MEMCPY(buffer + ieee_header_len + lowpan6_header_len, (u8_t*)p->payload + 37, 3); + lowpan6_header_len += 3; + } else if (i == 3) { + buffer[ieee_header_len + lowpan6_header_len++] = ((u8_t *)p->payload)[39]; + } + } else if (((buffer[ieee_header_len + 1] & 0x04) != 0) || + (ip6_addr_islinklocal(ip_2_ip6(&ip_data.current_iphdr_dest)))) { + /* Context-based or link-local destination address compression. */ + i = lowpan6_get_address_mode(ip_2_ip6(&ip_data.current_iphdr_dest), dst); + buffer[ieee_header_len + 1] |= i & 0x03; + if (i == 1) { + MEMCPY(buffer + ieee_header_len + lowpan6_header_len, (u8_t*)p->payload + 32, 8); + lowpan6_header_len += 8; + } else if (i == 2) { + MEMCPY(buffer + ieee_header_len + lowpan6_header_len, (u8_t*)p->payload + 38, 2); + lowpan6_header_len += 2; + } + } else { + /* Append full address. */ + MEMCPY(buffer + ieee_header_len + lowpan6_header_len, (u8_t*)p->payload + 24, 16); + lowpan6_header_len += 16; + } + + /* Move to payload. */ + pbuf_header(p, -IP6_HLEN); + + /* Compress UDP header? */ + if (IP6H_NEXTH(ip6hdr) == IP6_NEXTH_UDP) { + /* TODO support optional checksum compression */ + + buffer[ieee_header_len + lowpan6_header_len] = 0xf0; + + /* determine port compression mode. */ + if ((((u8_t *)p->payload)[0] == 0xf0) && ((((u8_t *)p->payload)[1] & 0xf0) == 0xb0) && + (((u8_t *)p->payload)[2] == 0xf0) && ((((u8_t *)p->payload)[3] & 0xf0) == 0xb0)) { + /* Compress source and dest ports. */ + buffer[ieee_header_len + lowpan6_header_len++] |= 0x03; + buffer[ieee_header_len + lowpan6_header_len++] = ((((u8_t *)p->payload)[1] & 0x0f) << 4) | (((u8_t *)p->payload)[3] & 0x0f); + } else if (((u8_t *)p->payload)[0] == 0xf0) { + /* Compress source port. */ + buffer[ieee_header_len + lowpan6_header_len++] |= 0x02; + buffer[ieee_header_len + lowpan6_header_len++] = ((u8_t *)p->payload)[1]; + buffer[ieee_header_len + lowpan6_header_len++] = ((u8_t *)p->payload)[2]; + buffer[ieee_header_len + lowpan6_header_len++] = ((u8_t *)p->payload)[3]; + } else if (((u8_t *)p->payload)[2] == 0xf0) { + /* Compress dest port. */ + buffer[ieee_header_len + lowpan6_header_len++] |= 0x01; + buffer[ieee_header_len + lowpan6_header_len++] = ((u8_t *)p->payload)[0]; + buffer[ieee_header_len + lowpan6_header_len++] = ((u8_t *)p->payload)[1]; + buffer[ieee_header_len + lowpan6_header_len++] = ((u8_t *)p->payload)[3]; + } else { + /* append full ports. */ + lowpan6_header_len++; + buffer[ieee_header_len + lowpan6_header_len++] = ((u8_t *)p->payload)[0]; + buffer[ieee_header_len + lowpan6_header_len++] = ((u8_t *)p->payload)[1]; + buffer[ieee_header_len + lowpan6_header_len++] = ((u8_t *)p->payload)[2]; + buffer[ieee_header_len + lowpan6_header_len++] = ((u8_t *)p->payload)[3]; + } + + /* elide length and copy checksum */ + buffer[ieee_header_len + lowpan6_header_len++] = ((u8_t *)p->payload)[6]; + buffer[ieee_header_len + lowpan6_header_len++] = ((u8_t *)p->payload)[7]; + + pbuf_header(p, -UDP_HLEN); + } + } + +#else /* LWIP_6LOWPAN_HC */ + /* Send uncompressed IPv6 header with appropriate dispatch byte. */ + lowpan6_header_len = 1; + buffer[ieee_header_len] = 0x41; /* IPv6 dispatch */ +#endif /* LWIP_6LOWPAN_HC */ + + /* Calculate remaining packet length */ + remaining_len = p->tot_len; + + if (remaining_len > 0x7FF) { + MIB2_STATS_NETIF_INC(netif, ifoutdiscards); + /* datagram_size must fit into 11 bit */ + pbuf_free(p_frag); + return ERR_VAL; + } + + /* Fragment, or 1 packet? */ + if (remaining_len > (127 - ieee_header_len - lowpan6_header_len - 3)) { /* 127 - header - 1 byte dispatch - 2 bytes CRC */ + /* We must move the 6LowPAN header to make room for the FRAG header. */ + i = lowpan6_header_len; + while (i-- != 0) { + buffer[ieee_header_len + i + 4] = buffer[ieee_header_len + i]; + } + + /* Now we need to fragment the packet. FRAG1 header first */ + buffer[ieee_header_len] = 0xc0 | (((p->tot_len + lowpan6_header_len) >> 8) & 0x7); + buffer[ieee_header_len + 1] = (p->tot_len + lowpan6_header_len) & 0xff; + + datagram_tag++; + buffer[ieee_header_len + 2] = datagram_tag & 0xff; + buffer[ieee_header_len + 3] = (datagram_tag >> 8) & 0xff; + + /* Fragment follows. */ + frag_len = (127 - ieee_header_len - 4 - 2) & 0xf8; + + pbuf_copy_partial(p, buffer + ieee_header_len + lowpan6_header_len + 4, frag_len - lowpan6_header_len, 0); + remaining_len -= frag_len - lowpan6_header_len; + datagram_offset = frag_len; + + /* 2 bytes CRC */ +#if LWIP_6LOWPAN_HW_CRC + /* Leave blank, will be filled by HW. */ +#else /* LWIP_6LOWPAN_HW_CRC */ + /* TODO calculate CRC */ +#endif /* LWIP_6LOWPAN_HW_CRC */ + + /* Calculate frame length */ + p_frag->len = p_frag->tot_len = ieee_header_len + 4 + frag_len + 2; /* add 2 dummy bytes for crc*/ + + /* send the packet */ + MIB2_STATS_NETIF_ADD(netif, ifoutoctets, p_frag->tot_len); + LWIP_DEBUGF(LOWPAN6_DEBUG | LWIP_DBG_TRACE, ("lowpan6_send: sending packet %p\n", (void *)p)); + err = netif->linkoutput(netif, p_frag); + + while ((remaining_len > 0) && (err == ERR_OK)) { + /* new frame, new seq num for ACK */ + buffer[2] = frame_seq_num++; + + buffer[ieee_header_len] |= 0x20; /* Change FRAG1 to FRAGN */ + + buffer[ieee_header_len + 4] = (u8_t)(datagram_offset >> 3); /* datagram offset in FRAGN header (datagram_offset is max. 11 bit) */ + + frag_len = (127 - ieee_header_len - 5 - 2) & 0xf8; + if (frag_len > remaining_len) { + frag_len = remaining_len; + } + + pbuf_copy_partial(p, buffer + ieee_header_len + 5, frag_len, p->tot_len - remaining_len); + remaining_len -= frag_len; + datagram_offset += frag_len; + + /* 2 bytes CRC */ +#if LWIP_6LOWPAN_HW_CRC + /* Leave blank, will be filled by HW. */ +#else /* LWIP_6LOWPAN_HW_CRC */ + /* TODO calculate CRC */ +#endif /* LWIP_6LOWPAN_HW_CRC */ + + /* Calculate frame length */ + p_frag->len = p_frag->tot_len = frag_len + 5 + ieee_header_len + 2; + + /* send the packet */ + MIB2_STATS_NETIF_ADD(netif, ifoutoctets, p_frag->tot_len); + LWIP_DEBUGF(LOWPAN6_DEBUG | LWIP_DBG_TRACE, ("lowpan6_send: sending packet %p\n", (void *)p)); + err = netif->linkoutput(netif, p_frag); + } + } else { + /* It fits in one frame. */ + frag_len = remaining_len; + + /* Copy IPv6 packet */ + pbuf_copy_partial(p, buffer + ieee_header_len + lowpan6_header_len, frag_len, 0); + remaining_len = 0; + + /* 2 bytes CRC */ +#if LWIP_6LOWPAN_HW_CRC + /* Leave blank, will be filled by HW. */ +#else /* LWIP_6LOWPAN_HW_CRC */ + /* TODO calculate CRC */ +#endif /* LWIP_6LOWPAN_HW_CRC */ + + /* Calculate frame length */ + p_frag->len = p_frag->tot_len = frag_len + lowpan6_header_len + ieee_header_len + 2; + + /* send the packet */ + MIB2_STATS_NETIF_ADD(netif, ifoutoctets, p_frag->tot_len); + LWIP_DEBUGF(LOWPAN6_DEBUG | LWIP_DBG_TRACE, ("lowpan6_send: sending packet %p\n", (void *)p)); + err = netif->linkoutput(netif, p_frag); + } + + pbuf_free(p_frag); + + return err; +} + +err_t +lowpan6_set_context(u8_t idx, const ip6_addr_t * context) +{ + if (idx >= LWIP_6LOWPAN_NUM_CONTEXTS) { + return ERR_ARG; + } + + ip6_addr_set(&lowpan6_context[idx], context); + + return ERR_OK; +} + +#if LWIP_6LOWPAN_INFER_SHORT_ADDRESS +err_t +lowpan6_set_short_addr(u8_t addr_high, u8_t addr_low) +{ + short_mac_addr.addr[0] = addr_high; + short_mac_addr.addr[1] = addr_low; + + return ERR_OK; +} +#endif /* LWIP_6LOWPAN_INFER_SHORT_ADDRESS */ + +#if LWIP_IPV4 +err_t +lowpan4_output(struct netif *netif, struct pbuf *q, const ip4_addr_t *ipaddr) +{ + (void)netif; + (void)q; + (void)ipaddr; + + return ERR_IF; +} +#endif /* LWIP_IPV4 */ + +/** + * Resolve and fill-in IEEE 802.15.4 address header for outgoing IPv6 packet. + * + * Perform Header Compression and fragment if necessary. + * + * @param netif The lwIP network interface which the IP packet will be sent on. + * @param q The pbuf(s) containing the IP packet to be sent. + * @param ip6addr The IP address of the packet destination. + * + * @return + */ +err_t +lowpan6_output(struct netif *netif, struct pbuf *q, const ip6_addr_t *ip6addr) +{ + s8_t i; + struct ieee_802154_addr src, dest; +#if LWIP_6LOWPAN_INFER_SHORT_ADDRESS + ip6_addr_t ip6_src; + struct ip6_hdr * ip6_hdr; +#endif /* LWIP_6LOWPAN_INFER_SHORT_ADDRESS */ + +#if LWIP_6LOWPAN_INFER_SHORT_ADDRESS + /* Check if we can compress source address (use aligned copy) */ + ip6_hdr = (struct ip6_hdr *)q->payload; + ip6_addr_set(&ip6_src, &ip6_hdr->src); + if (lowpan6_get_address_mode(&ip6_src, &short_mac_addr) == 3) { + src.addr_len = 2; + src.addr[0] = short_mac_addr.addr[0]; + src.addr[1] = short_mac_addr.addr[1]; + } else +#endif /* LWIP_6LOWPAN_INFER_SHORT_ADDRESS */ + { + src.addr_len = netif->hwaddr_len; + SMEMCPY(src.addr, netif->hwaddr, netif->hwaddr_len); + } + + /* multicast destination IP address? */ + if (ip6_addr_ismulticast(ip6addr)) { + MIB2_STATS_NETIF_INC(netif, ifoutnucastpkts); + /* We need to send to the broadcast address.*/ + return lowpan6_frag(netif, q, &src, &ieee_802154_broadcast); + } + + /* We have a unicast destination IP address */ + /* TODO anycast? */ + +#if LWIP_6LOWPAN_INFER_SHORT_ADDRESS + if (src.addr_len == 2) { + /* If source address was compressable to short_mac_addr, and dest has same subnet and + * is also compressable to 2-bytes, assume we can infer dest as a short address too. */ + dest.addr_len = 2; + dest.addr[0] = ((u8_t *)q->payload)[38]; + dest.addr[1] = ((u8_t *)q->payload)[39]; + if ((src.addr_len == 2) && (ip6_addr_netcmp(&ip6_hdr->src, &ip6_hdr->dest)) && + (lowpan6_get_address_mode(ip6addr, &dest) == 3)) { + MIB2_STATS_NETIF_INC(netif, ifoutucastpkts); + return lowpan6_frag(netif, q, &src, &dest); + } + } +#endif /* LWIP_6LOWPAN_INFER_SHORT_ADDRESS */ + + + /* Get next hop record. */ + i = nd6_get_next_hop_entry(ip6addr, netif); + if (i < 0) { + MIB2_STATS_NETIF_INC(netif, ifoutdiscards); + /* failed to get a next hop neighbor record. */ + return ERR_MEM; + } + + /* Now that we have a destination record, send or queue the packet. */ + if (neighbor_cache[i].state == ND6_STALE) { + /* Switch to delay state. */ + neighbor_cache[i].state = ND6_DELAY; + neighbor_cache[i].counter.delay_time = LWIP_ND6_DELAY_FIRST_PROBE_TIME; + } + /* TODO should we send or queue if PROBE? send for now, to let unicast NS pass. */ + if ((neighbor_cache[i].state == ND6_REACHABLE) || + (neighbor_cache[i].state == ND6_DELAY) || + (neighbor_cache[i].state == ND6_PROBE)) { + + /* Send out. */ + dest.addr_len = netif->hwaddr_len; + SMEMCPY(dest.addr, neighbor_cache[i].lladdr, netif->hwaddr_len); + MIB2_STATS_NETIF_INC(netif, ifoutucastpkts); + return lowpan6_frag(netif, q, &src, &dest); + } + + /* We should queue packet on this interface. */ + return nd6_queue_packet(i, q); +} + +static struct pbuf * +lowpan6_decompress(struct pbuf * p, struct ieee_802154_addr * src, struct ieee_802154_addr * dest) +{ + struct pbuf * q; + u8_t * lowpan6_buffer; + s8_t lowpan6_offset; + struct ip6_hdr *ip6hdr; + s8_t i; + s8_t ip6_offset = IP6_HLEN; + + + q = pbuf_alloc(PBUF_IP, p->len + IP6_HLEN + UDP_HLEN, PBUF_POOL); + if (q == NULL) { + pbuf_free(p); + return NULL; + } + + lowpan6_buffer = (u8_t *)p->payload; + ip6hdr = (struct ip6_hdr *)q->payload; + + lowpan6_offset = 2; + if (lowpan6_buffer[1] & 0x80) { + lowpan6_offset++; + } + + /* Set IPv6 version, traffic class and flow label. */ + if ((lowpan6_buffer[0] & 0x18) == 0x00) { + IP6H_VTCFL_SET(ip6hdr, 6, lowpan6_buffer[lowpan6_offset], ((lowpan6_buffer[lowpan6_offset+1] & 0x0f) << 16) | (lowpan6_buffer[lowpan6_offset + 2] << 8) | lowpan6_buffer[lowpan6_offset+3]); + lowpan6_offset += 4; + } else if ((lowpan6_buffer[0] & 0x18) == 0x08) { + IP6H_VTCFL_SET(ip6hdr, 6, lowpan6_buffer[lowpan6_offset] & 0xc0, ((lowpan6_buffer[lowpan6_offset] & 0x0f) << 16) | (lowpan6_buffer[lowpan6_offset + 1] << 8) | lowpan6_buffer[lowpan6_offset+2]); + lowpan6_offset += 3; + } else if ((lowpan6_buffer[0] & 0x18) == 0x10) { + IP6H_VTCFL_SET(ip6hdr, 6, lowpan6_buffer[lowpan6_offset],0); + lowpan6_offset += 1; + } else if ((lowpan6_buffer[0] & 0x18) == 0x18) { + IP6H_VTCFL_SET(ip6hdr, 6, 0, 0); + } + + /* Set Next Header */ + if ((lowpan6_buffer[0] & 0x04) == 0x00) { + IP6H_NEXTH_SET(ip6hdr, lowpan6_buffer[lowpan6_offset++]); + } else { + /* We should fill this later with NHC decoding */ + IP6H_NEXTH_SET(ip6hdr, 0); + } + + /* Set Hop Limit */ + if ((lowpan6_buffer[0] & 0x03) == 0x00) { + IP6H_HOPLIM_SET(ip6hdr, lowpan6_buffer[lowpan6_offset++]); + } else if ((lowpan6_buffer[0] & 0x03) == 0x01) { + IP6H_HOPLIM_SET(ip6hdr, 1); + } else if ((lowpan6_buffer[0] & 0x03) == 0x02) { + IP6H_HOPLIM_SET(ip6hdr, 64); + } else if ((lowpan6_buffer[0] & 0x03) == 0x03) { + IP6H_HOPLIM_SET(ip6hdr, 255); + } + + /* Source address decoding. */ + if ((lowpan6_buffer[1] & 0x40) == 0x00) { + /* Stateless compression */ + if ((lowpan6_buffer[1] & 0x30) == 0x00) { + /* copy full address */ + MEMCPY(&ip6hdr->src.addr[0], lowpan6_buffer + lowpan6_offset, 16); + lowpan6_offset += 16; + } else if ((lowpan6_buffer[1] & 0x30) == 0x10) { + ip6hdr->src.addr[0] = PP_HTONL(0xfe800000UL); + ip6hdr->src.addr[1] = 0; + MEMCPY(&ip6hdr->src.addr[2], lowpan6_buffer + lowpan6_offset, 8); + lowpan6_offset += 8; + } else if ((lowpan6_buffer[1] & 0x30) == 0x20) { + ip6hdr->src.addr[0] = PP_HTONL(0xfe800000UL); + ip6hdr->src.addr[1] = 0; + ip6hdr->src.addr[2] = PP_HTONL(0x000000ffUL); + ip6hdr->src.addr[3] = htonl(0xfe000000UL | (lowpan6_buffer[lowpan6_offset] << 8) | + lowpan6_buffer[lowpan6_offset+1]); + lowpan6_offset += 2; + } else if ((lowpan6_buffer[1] & 0x30) == 0x30) { + ip6hdr->src.addr[0] = PP_HTONL(0xfe800000UL); + ip6hdr->src.addr[1] = 0; + if (src->addr_len == 2) { + ip6hdr->src.addr[2] = PP_HTONL(0x000000ffUL); + ip6hdr->src.addr[3] = htonl(0xfe000000UL | (src->addr[0] << 8) | src->addr[1]); + } else { + ip6hdr->src.addr[2] = htonl(((src->addr[0] ^ 2) << 24) | (src->addr[1] << 16) | + (src->addr[2] << 8) | src->addr[3]); + ip6hdr->src.addr[3] = htonl((src->addr[4] << 24) | (src->addr[5] << 16) | + (src->addr[6] << 8) | src->addr[7]); + } + } + } else { + /* Stateful compression */ + if ((lowpan6_buffer[1] & 0x30) == 0x00) { + /* ANY address */ + ip6hdr->src.addr[0] = 0; + ip6hdr->src.addr[1] = 0; + ip6hdr->src.addr[2] = 0; + ip6hdr->src.addr[3] = 0; + } else { + /* Set prefix from context info */ + if (lowpan6_buffer[1] & 0x80) { + i = (lowpan6_buffer[2] >> 4) & 0x0f; + } else { + i = 0; + } + if (i >= LWIP_6LOWPAN_NUM_CONTEXTS) { + /* Error */ + pbuf_free(p); + pbuf_free(q); + return NULL; + } + + ip6hdr->src.addr[0] = lowpan6_context[i].addr[0]; + ip6hdr->src.addr[1] = lowpan6_context[i].addr[1]; + } + + if ((lowpan6_buffer[1] & 0x30) == 0x10) { + MEMCPY(&ip6hdr->src.addr[2], lowpan6_buffer + lowpan6_offset, 8); + lowpan6_offset += 8; + } else if ((lowpan6_buffer[1] & 0x30) == 0x20) { + ip6hdr->src.addr[2] = PP_HTONL(0x000000ffUL); + ip6hdr->src.addr[3] = htonl(0xfe000000UL | (lowpan6_buffer[lowpan6_offset] << 8) | lowpan6_buffer[lowpan6_offset+1]); + lowpan6_offset += 2; + } else if ((lowpan6_buffer[1] & 0x30) == 0x30) { + if (src->addr_len == 2) { + ip6hdr->src.addr[2] = PP_HTONL(0x000000ffUL); + ip6hdr->src.addr[3] = htonl(0xfe000000UL | (src->addr[0] << 8) | src->addr[1]); + } else { + ip6hdr->src.addr[2] = htonl(((src->addr[0] ^ 2) << 24) | (src->addr[1] << 16) | (src->addr[2] << 8) | src->addr[3]); + ip6hdr->src.addr[3] = htonl((src->addr[4] << 24) | (src->addr[5] << 16) | (src->addr[6] << 8) | src->addr[7]); + } + } + } + + /* Destination address decoding. */ + if (lowpan6_buffer[1] & 0x08) { + /* Multicast destination */ + if (lowpan6_buffer[1] & 0x04) { + /* TODO support stateful multicast addressing */ + pbuf_free(p); + pbuf_free(q); + return NULL; + } + + if ((lowpan6_buffer[1] & 0x03) == 0x00) { + /* copy full address */ + MEMCPY(&ip6hdr->dest.addr[0], lowpan6_buffer + lowpan6_offset, 16); + lowpan6_offset += 16; + } else if ((lowpan6_buffer[1] & 0x03) == 0x01) { + ip6hdr->dest.addr[0] = htonl(0xff000000UL | (lowpan6_buffer[lowpan6_offset++] << 16)); + ip6hdr->dest.addr[1] = 0; + ip6hdr->dest.addr[2] = htonl(lowpan6_buffer[lowpan6_offset++]); + ip6hdr->dest.addr[3] = htonl((lowpan6_buffer[lowpan6_offset] << 24) | (lowpan6_buffer[lowpan6_offset + 1] << 16) | (lowpan6_buffer[lowpan6_offset + 2] << 8) | lowpan6_buffer[lowpan6_offset + 3]); + lowpan6_offset += 4; + } else if ((lowpan6_buffer[1] & 0x03) == 0x02) { + ip6hdr->dest.addr[0] = htonl(0xff000000UL | lowpan6_buffer[lowpan6_offset++]); + ip6hdr->dest.addr[1] = 0; + ip6hdr->dest.addr[2] = 0; + ip6hdr->dest.addr[3] = htonl((lowpan6_buffer[lowpan6_offset] << 16) | (lowpan6_buffer[lowpan6_offset + 1] << 8) | lowpan6_buffer[lowpan6_offset + 2]); + lowpan6_offset += 3; + } else if ((lowpan6_buffer[1] & 0x03) == 0x03) { + ip6hdr->dest.addr[0] = PP_HTONL(0xff020000UL); + ip6hdr->dest.addr[1] = 0; + ip6hdr->dest.addr[2] = 0; + ip6hdr->dest.addr[3] = htonl(lowpan6_buffer[lowpan6_offset++]); + } + + } else { + if (lowpan6_buffer[1] & 0x04) { + /* Stateful destination compression */ + /* Set prefix from context info */ + if (lowpan6_buffer[1] & 0x80) { + i = lowpan6_buffer[2] & 0x0f; + } else { + i = 0; + } + if (i >= LWIP_6LOWPAN_NUM_CONTEXTS) { + /* Error */ + pbuf_free(p); + pbuf_free(q); + return NULL; + } + + ip6hdr->dest.addr[0] = lowpan6_context[i].addr[0]; + ip6hdr->dest.addr[1] = lowpan6_context[i].addr[1]; + } else { + /* Link local address compression */ + ip6hdr->dest.addr[0] = PP_HTONL(0xfe800000UL); + ip6hdr->dest.addr[1] = 0; + } + + if ((lowpan6_buffer[1] & 0x03) == 0x00) { + /* copy full address */ + MEMCPY(&ip6hdr->dest.addr[0], lowpan6_buffer + lowpan6_offset, 16); + lowpan6_offset += 16; + } else if ((lowpan6_buffer[1] & 0x03) == 0x01) { + MEMCPY(&ip6hdr->dest.addr[2], lowpan6_buffer + lowpan6_offset, 8); + lowpan6_offset += 8; + } else if ((lowpan6_buffer[1] & 0x03) == 0x02) { + ip6hdr->dest.addr[2] = PP_HTONL(0x000000ffUL); + ip6hdr->dest.addr[3] = htonl(0xfe000000UL | (lowpan6_buffer[lowpan6_offset] << 8) | lowpan6_buffer[lowpan6_offset + 1]); + lowpan6_offset += 2; + } else if ((lowpan6_buffer[1] & 0x03) == 0x03) { + if (dest->addr_len == 2) { + ip6hdr->dest.addr[2] = PP_HTONL(0x000000ffUL); + ip6hdr->dest.addr[3] = htonl(0xfe000000UL | (dest->addr[0] << 8) | dest->addr[1]); + } else { + ip6hdr->dest.addr[2] = htonl(((dest->addr[0] ^ 2) << 24) | (dest->addr[1] << 16) | dest->addr[2] << 8 | dest->addr[3]); + ip6hdr->dest.addr[3] = htonl((dest->addr[4] << 24) | (dest->addr[5] << 16) | dest->addr[6] << 8 | dest->addr[7]); + } + } + } + + + /* Next Header Compression (NHC) decoding? */ + if (lowpan6_buffer[0] & 0x04) { + if ((lowpan6_buffer[lowpan6_offset] & 0xf8) == 0xf0) { + struct udp_hdr *udphdr; + + /* UDP compression */ + IP6H_NEXTH_SET(ip6hdr, IP6_NEXTH_UDP); + udphdr = (struct udp_hdr *)((u8_t *)q->payload + ip6_offset); + + if (lowpan6_buffer[lowpan6_offset] & 0x04) { + /* TODO support checksum decompress */ + pbuf_free(p); + pbuf_free(q); + return NULL; + } + + /* Decompress ports */ + i = lowpan6_buffer[lowpan6_offset++] & 0x03; + if (i == 0) { + udphdr->src = htons(lowpan6_buffer[lowpan6_offset] << 8 | lowpan6_buffer[lowpan6_offset + 1]); + udphdr->dest = htons(lowpan6_buffer[lowpan6_offset + 2] << 8 | lowpan6_buffer[lowpan6_offset + 3]); + lowpan6_offset += 4; + } else if (i == 0x01) { + udphdr->src = htons(lowpan6_buffer[lowpan6_offset] << 8 | lowpan6_buffer[lowpan6_offset + 1]); + udphdr->dest = htons(0xf000 | lowpan6_buffer[lowpan6_offset + 2]); + lowpan6_offset += 3; + } else if (i == 0x02) { + udphdr->src = htons(0xf000 | lowpan6_buffer[lowpan6_offset]); + udphdr->dest = htons(lowpan6_buffer[lowpan6_offset + 1] << 8 | lowpan6_buffer[lowpan6_offset + 2]); + lowpan6_offset += 3; + } else if (i == 0x03) { + udphdr->src = htons(0xf0b0 | ((lowpan6_buffer[lowpan6_offset] >> 4) & 0x0f)); + udphdr->dest = htons(0xf0b0 | (lowpan6_buffer[lowpan6_offset] & 0x0f)); + lowpan6_offset += 1; + } + + udphdr->chksum = htons(lowpan6_buffer[lowpan6_offset] << 8 | lowpan6_buffer[lowpan6_offset + 1]); + lowpan6_offset += 2; + udphdr->len = htons(p->tot_len - lowpan6_offset + UDP_HLEN); + + ip6_offset += UDP_HLEN; + } else { + /* TODO support NHC other than UDP */ + pbuf_free(p); + pbuf_free(q); + return NULL; + } + } + + /* Now we copy leftover contents from p to q, so we have all L2 and L3 headers (and L4?) in a single PBUF. + * Replace p with q, and free p */ + pbuf_header(p, -lowpan6_offset); + MEMCPY((u8_t*)q->payload + ip6_offset, p->payload, p->len); + q->len = q->tot_len = ip6_offset + p->len; + if (p->next != NULL) { + pbuf_cat(q, p->next); + } + p->next = NULL; + pbuf_free(p); + + /* Infer IPv6 payload length for header */ + IP6H_PLEN_SET(ip6hdr, q->tot_len - IP6_HLEN); + + /* all done */ + return q; +} + +err_t +lowpan6_input(struct pbuf * p, struct netif *netif) +{ + u8_t * puc; + s8_t i; + struct ieee_802154_addr src, dest; + u16_t datagram_size, datagram_offset, datagram_tag; + struct lowpan6_reass_helper *lrh, *lrh_temp; + + MIB2_STATS_NETIF_ADD(netif, ifinoctets, p->tot_len); + + /* Analyze header. TODO validate. */ + puc = (u8_t*)p->payload; + datagram_offset = 5; + if ((puc[1] & 0x0c) == 0x0c) { + dest.addr_len = 8; + for (i = 0; i < 8; i++) { + dest.addr[i] = puc[datagram_offset + 7 - i]; + } + datagram_offset += 8; + } else { + dest.addr_len = 2; + dest.addr[0] = puc[datagram_offset + 1]; + dest.addr[1] = puc[datagram_offset]; + datagram_offset += 2; + } + + datagram_offset += 2; /* skip PAN ID. */ + + if ((puc[1] & 0xc0) == 0xc0) { + src.addr_len = 8; + for (i = 0; i < 8; i++) { + src.addr[i] = puc[datagram_offset + 7 - i]; + } + datagram_offset += 8; + } else { + src.addr_len = 2; + src.addr[0] = puc[datagram_offset + 1]; + src.addr[1] = puc[datagram_offset]; + datagram_offset += 2; + } + + pbuf_header(p, -datagram_offset); /* hide IEEE802.15.4 header. */ + + /* Check dispatch. */ + puc = (u8_t*)p->payload; + + if ((*puc & 0xf8) == 0xc0) { + /* FRAG1 dispatch. add this packet to reassembly list. */ + datagram_size = ((u16_t)(puc[0] & 0x07) << 8) | (u16_t)puc[1]; + datagram_tag = ((u16_t)puc[2] << 8) | (u16_t)puc[3]; + + /* check for duplicate */ + lrh = reass_list; + while (lrh != NULL) { + if ((lrh->sender_addr.addr_len == src.addr_len) && + (memcmp(lrh->sender_addr.addr, src.addr, src.addr_len) == 0)) { + /* address match with packet in reassembly. */ + if ((datagram_tag == lrh->datagram_tag) && (datagram_size == lrh->datagram_size)) { + MIB2_STATS_NETIF_INC(netif, ifindiscards); + /* duplicate fragment. */ + pbuf_free(p); + return ERR_OK; + } else { + /* We are receiving the start of a new datagram. Discard old one (incomplete). */ + lrh_temp = lrh->next_packet; + dequeue_datagram(lrh); + pbuf_free(lrh->pbuf); + mem_free(lrh); + + /* Check next datagram in queue. */ + lrh = lrh_temp; + } + } else { + /* Check next datagram in queue. */ + lrh = lrh->next_packet; + } + } + + pbuf_header(p, -4); /* hide frag1 dispatch */ + + lrh = (struct lowpan6_reass_helper *) mem_malloc(sizeof(struct lowpan6_reass_helper)); + if (lrh == NULL) { + MIB2_STATS_NETIF_INC(netif, ifindiscards); + pbuf_free(p); + return ERR_MEM; + } + + lrh->sender_addr.addr_len = src.addr_len; + for (i = 0; i < src.addr_len; i++) { + lrh->sender_addr.addr[i] = src.addr[i]; + } + lrh->datagram_size = datagram_size; + lrh->datagram_tag = datagram_tag; + lrh->pbuf = p; + lrh->next_packet = reass_list; + lrh->timer = 2; + reass_list = lrh; + + return ERR_OK; + } else if ((*puc & 0xf8) == 0xe0) { + /* FRAGN dispatch, find packet being reassembled. */ + datagram_size = ((u16_t)(puc[0] & 0x07) << 8) | (u16_t)puc[1]; + datagram_tag = ((u16_t)puc[2] << 8) | (u16_t)puc[3]; + datagram_offset = (u16_t)puc[4] << 3; + pbuf_header(p, -5); /* hide frag1 dispatch */ + + for (lrh = reass_list; lrh != NULL; lrh = lrh->next_packet) { + if ((lrh->sender_addr.addr_len == src.addr_len) && + (memcmp(lrh->sender_addr.addr, src.addr, src.addr_len) == 0) && + (datagram_tag == lrh->datagram_tag) && + (datagram_size == lrh->datagram_size)) { + break; + } + } + if (lrh == NULL) { + /* rogue fragment */ + MIB2_STATS_NETIF_INC(netif, ifindiscards); + pbuf_free(p); + return ERR_OK; + } + + if (lrh->pbuf->tot_len < datagram_offset) { + /* duplicate, ignore. */ + pbuf_free(p); + return ERR_OK; + } else if (lrh->pbuf->tot_len > datagram_offset) { + MIB2_STATS_NETIF_INC(netif, ifindiscards); + /* We have missed a fragment. Delete whole reassembly. */ + dequeue_datagram(lrh); + pbuf_free(lrh->pbuf); + mem_free(lrh); + pbuf_free(p); + return ERR_OK; + } + pbuf_cat(lrh->pbuf, p); + p = NULL; + + /* is packet now complete?*/ + if (lrh->pbuf->tot_len >= lrh->datagram_size) { + /* dequeue from reass list. */ + dequeue_datagram(lrh); + + /* get pbuf */ + p = lrh->pbuf; + + /* release helper */ + mem_free(lrh); + } else { + return ERR_OK; + } + } + + if (p == NULL) { + return ERR_OK; + } + + /* We have a complete packet, check dispatch for headers. */ + puc = (u8_t*)p->payload; + + if (*puc == 0x41) { + /* This is a complete IPv6 packet, just skip dispatch byte. */ + pbuf_header(p, -1); /* hide dispatch byte. */ + } else if ((*puc & 0xe0 )== 0x60) { + /* IPv6 headers are compressed using IPHC. */ + p = lowpan6_decompress(p, &src, &dest); + if (p == NULL) { + MIB2_STATS_NETIF_INC(netif, ifindiscards); + return ERR_OK; + } + } else { + MIB2_STATS_NETIF_INC(netif, ifindiscards); + pbuf_free(p); + return ERR_OK; + } + + /* @todo: distinguish unicast/multicast */ + MIB2_STATS_NETIF_INC(netif, ifinucastpkts); + + return ip6_input(p, netif); +} + +err_t +lowpan6_if_init(struct netif *netif) +{ + netif->name[0] = 'L'; + netif->name[1] = '6'; +#if LWIP_IPV4 + netif->output = lowpan4_output; +#endif /* LWIP_IPV4 */ + netif->output_ip6 = lowpan6_output; + + MIB2_INIT_NETIF(netif, snmp_ifType_other, 0); + + /* maximum transfer unit */ + netif->mtu = 1280; + + /* broadcast capability */ + netif->flags = NETIF_FLAG_BROADCAST /* | NETIF_FLAG_LOWPAN6 */; + + return ERR_OK; +} + +err_t +lowpan6_set_pan_id(u16_t pan_id) +{ + ieee_802154_pan_id = pan_id; + + return ERR_OK; +} + +/** + * Pass a received packet to tcpip_thread for input processing + * + * @param p the received packet, p->payload pointing to the + * IEEE 802.15.4 header. + * @param inp the network interface on which the packet was received + */ +err_t +tcpip_6lowpan_input(struct pbuf *p, struct netif *inp) +{ + return tcpip_inpkt(p, inp, lowpan6_input); +} + +#endif /* LWIP_IPV6 && LWIP_6LOWPAN */ diff --git a/components/lwip/netif/ppp/PPPD_FOLLOWUP b/components/lwip/netif/ppp/PPPD_FOLLOWUP new file mode 100755 index 0000000000..4a82915db4 --- /dev/null +++ b/components/lwip/netif/ppp/PPPD_FOLLOWUP @@ -0,0 +1,382 @@ +The lwIP PPP support is based from pppd 2.4.5 (http://ppp.samba.org) with +huge changes to match code size and memory requirements for embedded devices. + +Anyway, pppd has a mature codebase for years and the average commit count +is getting low on their Git repositories, meaning that we can follow what +is happening on their side and merge what is relevant for lwIP. + +So, here is the pppd follow up, so that we don't get away too far from pppd. + + +== Patch fetched from from pppd Debian packages == + +This has nothing to do with pppd, but we merged some good patch from +Debian and this is a good place to be. + +- LCP adaptive echo, so that we don't send LCP echo request if we + are receiving data from peer, can be enabled by setting PPP_LCP_ADAPTIVE + to true. + +- IPCP no/replace default route option, were added in the early stage of + the ppp port, but it wasn't really helpful and was disabled when adding + the new API ppp_set_default() call, which gives the lwIP user control over + which one is the default interface, it was actually a requirement if you + are doing PPP over PPP (i.e. PPPoL2TP, VPN link, over PPPoE, ADSL link). + +- using rp-pppoe pppd exits with EXIT_OK after receiving a timeout waiting + for PADO due to no modem attached, bug reported to pppd bug tracker, fixed + in Debian but not in the latest (at the time when the port were started) + pppd release. + + +== Commits on pppd == + +2010-03-06 - Document +ipv6 and ipv6cp-accept-local + e7537958aee79b3f653c601e903cb31d78fb7dcc + +Don't care. + + +2010-03-06 - Install pppol2tp plugins with sane permissions + 406215672cfadc03017341fe03802d1c7294b903 + +Don't care. + + +2010-03-07 - pppd: Terminate correctly if lcp_lowerup delayed calling + fsm_lowerup + 3eb9e810cfa515543655659b72dde30c54fea0a5 + +Merged 2012-05-17. + + +2010-03-07 - rp_pppoe: Copy acName and pppd_pppoe_service after option parsing + cab58617fd9d328029fffabc788020264b4fa91f + +Don't care, is a patch for pppd/plugins/rp-pppoe/plugin.c which is not part +of the port. + + +2010-08-23 - set and reset options to control environment variables + for scripts. + 2b6310fd24dba8e0fca8999916a162f0a1842a84 + +We can't fork processes in embedded, therefore all the pppd process run +feature is disabled in the port, so we don't care about the new +"environment variables" pppd feature. + + +2010-08-23 - Nit: use _exit when exec fails and restrict values to 0-255 + per POSIX. + 2b4ea140432eeba5a007c0d4e6236bd0e0c12ba4 + +Again, we are not running as a heavy process, so all exit() or _exit() calls +were removed. + + +2010-08-23 - Fix quote handling in configuration files to be more like shell + quoting. + 3089132cdf5b58dbdfc2daf08ec5c08eb47f8aca + +We are not parsing config file, all the filesystem I/O stuff were disabled +in our port. + + +2010-08-24 - rp-pppoe: allow MTU to be increased up to 1500 + fd1dcdf758418f040da3ed801ab001b5e46854e7 + +Only concern changes on RP-PPPoE plugin, which we don't use. + + +2010-09-11 - chat: Allow TIMEOUT value to come from environment variable + ae80bf833e48a6202f44a935a68083ae52ad3824 + +See 2b6310fd24dba8e0fca8999916a162f0a1842a84. + + +2011-03-05 - pppdump: Fix printfs with insufficient arguments + 7b8db569642c83ba3283745034f2e2c95e459423 + +pppdump is a ppp tool outside pppd source tree. + + +2012-05-06 - pppd: Don't unconditionally disable VJ compression under Linux + d8a66adf98a0e525cf38031b42098d539da6eeb6 + +Patch for sys-linux.c, which we don't use. + + +2012-05-20 - Remove old version of Linux if_pppol2tp.h + c41092dd4c49267f232f6cba3d31c6c68bfdf68d + +Not in the port. + + +2012-05-20 - pppd: Make MSCHAP-v2 cope better with packet loss + 08ef47ca532294eb428238c831616748940e24a2 + +This is an interesting patch. However it consumes much more memory for +MSCHAP and I am not sure if the benefit worth it. The PPP client can +always start the authentication again if it failed for whatever reason. + + +2012-05-20 - scripts: Make poff ignore extra arguments to pppd + 18f515f32c9f5723a9c2c912601e04335106534b + +Again, we are not running scripts. + + +2012-05-20 - rp-pppoe plugin: Print leading zeros in MAC address + f5dda0cfc220c4b52e26144096d729e27b30f0f7 + +Again, we are not using the RP-PPPoE plugin. + + +2012-05-20 - pppd: Notify IPv6 up/down as we do for IPv4 + 845cda8fa18939cf56e60b073f63a7efa65336fc + +This is just a patch that adds plugins hooks for IPv6, the plugin interface +was disabled because we don't have .so plugins in embedded. + + +2012-05-20 - pppd: Enable IPV6 by default and fix some warnings + 0b6118239615e98959f7e0b4e746bdd197533248 + +Change on Makefile for IPv6, warnings were already cleared during port. + + +2012-05-20 - contrib: Fix pppgetpass.gtk compilation + 80a8e2ce257ca12cce723519a0f20ea1d663b14a + +Change on Makefile, don't care. + + +2012-05-20 - pppd: Don't crash if crypt() returns NULL + 04c4348108d847e034dd91066cc6843f60d71731 + +We are using the PolarSSL DES implementation that does not return NULL. + + +2012-05-20 - pppd: Eliminate some warnings + c44ae5e6a7338c96eb463881fe709b2dfaffe568 + +Again, we are handling compilation warnings on our own. + + +2012-05-20 - rp-pppoe plugin: Import some fixes from rp-pppoe-3.10 + 1817d83e51a411044e730ba89ebdb0480e1c8cd4 + +Once more, we are not using the RP-PPPoE plugin. + + +2013-01-23 - pppd: Clarify circumstances where DNS1/DNS2 environment variables are set + cf2f5c9538b9400ade23446a194729b0a4113b3a + +Documentation only. + + +2013-02-03 - ppp: ignore unrecognised radiusclient configuration directives + 7f736dde0da3c19855997d9e67370e351e15e923 + +Radius plugin, not in the port. + + +2013-02-03 - pppd: Take out unused %r conversion completely + 356d8d558d844412119aa18c8e5a113bc6459c7b + +Merged 2014-04-15. + + +2013-02-03 - pppd: Arrange to use logwtmp from libutil on Linux + 9617a7eb137f4fee62799a677a9ecf8d834db3f5 + +Patch for sys-linux.c, which we don't use. + + +2013-02-03 - pppdump: Eliminate some compiler warnings + 3e3acf1ba2b3046c072a42c19164788a9e419bd1 + +pppdump is a ppp tool outside pppd source tree. + + +2013-02-03 - chat: Correct spelling errors in the man page + 8dea1b969d266ccbf6f3a8c5474eb6dcd8838e3b + +Documentation only. + + +2013-02-03 - pppd: Fix spelling errors in man page + 9e05a25d76b3f83096c661678010320df673df6b + +Documentation only. + + +2013-02-03 - plugins/passprompt: Fix potential out-of-bounds array reference + 8edb889b753056a691a3e4b217a110a35f9fdedb + +Plugin patch, we do not have plugins. + + +2013-02-03 - chat: Fix *roff errors in the man page + a7c3489eeaf44e83ce592143c7c8a5b5c29f4c48 + +Documentation only. + + +2013-03-02 - pppd: Fix man page description of case when remote IP address isn't known + 224841f4799f4f1e2e71bc490c54448d66740f4f + +Documentation only. + + +2013-03-02 - pppd: Add master_detach option + 398ed2585640d198c53e736ee5bbd67f7ce8168e + +Option for multilink support, we do not support multilink and this option +is about detaching from the terminal, which is out of the embedded scope. + + +2013-03-11 - pppd: Default exit status to EXIT_CONNECT_FAILED during connection phase + 225361d64ae737afdc8cb57579a2f33525461bc9 + +Commented out in our port, and already fixed by a previously applied Debian patch. + + +2013-03-11 - pppstats: Fix undefined macro in man page + d16a3985eade5280b8e171f5dd0670a91cba0d39 + +Documentation only. + + +2013-05-11 - plugins/radius: Handle bindaddr keyword in radiusclient.conf + d883b2dbafeed3ebd9d7a56ab1469373bd001a3b + +Radius plugin, not in the port. + + +2013-06-09 - pppoatm: Remove explicit loading of pppoatm kernel module + 52cd43a84bea524033b918b603698104f221bbb7 + +PPPoATM plugin, not in the port. + + +2013-06-09 - pppd: Fix segfault in update_db_entry() + 37476164f15a45015310b9d4b197c2d7db1f7f8f + +We do not use the samba db. + + +2013-06-09 - chat: Fix some text that was intended to be literal + cd9683676618adcee8add2c3cfa3382341b5a1f6 + +Documentation only. + + +2013-06-09 - README.pppoe: Minor semantic fix + b5b8898af6fd3d44e873cfc66810ace5f1f47e17 + +Documentation only. + + +2013-06-10 - radius: Handle additional attributes + 2f581cd986a56f2ec4a95abad4f8297a1b10d7e2 + +Radius plugin, not in the port. + + +2013-06-10 - chat, pppd: Use \e instead of \\ in man pages + 8d6942415d22f6ca4377340ca26e345c3f5fa5db + +Documentation only. + + +2014-01-02 - pppd: Don't crash if NULL pointer passed to vslprintf for %q or %v + 906814431bddeb2061825fa1ebad1a967b6d87a9 + +Merged 2014-04-15. + + +2014-01-02 - pppd: Accept IPCP ConfAck packets containing MS-WINS options + a243f217f1c6ac1aa7793806bc88590d077f490a + +Merged 2014-04-15. + + +2014-01-02 - config: Update Solaris compiler options and enable CHAPMS and IPV6 + 99c46caaed01b7edba87962aa52b77fad61bfd7b + +Solaris port, don't care. + + +2014-01-02 - Update README and patchlevel for 2.4.6 release + 4043750fca36e7e0eb90d702e048ad1da4929418 + +Just release stuff. + + +2014-02-18 - pppd: Add option "stop-bits" to set number of serial port stop bits. + ad993a20ee485f0d0e2ac4105221641b200da6e2 + +Low level serial port, not in the port. + + +2014-03-09 - pppd: Separate IPv6 handling for sifup/sifdown + b04d2dc6df5c6b5650fea44250d58757ee3dac4a + +Reimplemented. + + +2014-03-09 - pppol2tp: Connect up/down events to notifiers and add IPv6 ones + fafbe50251efc7d6b4a8be652d085316e112b34f + +Not in the port. + + +2014-03-09 - pppd: Add declarations to eliminate compile warnings + 50967962addebe15c7a7e63116ff46a0441dc464 + +We are handling compilation warnings on our own + + +2014-03-09 - pppd: Eliminate some unnecessary ifdefs + de8da14d845ee6db9236ccfddabf1d8ebf045ddb + +We mostly did that previously. Anyway, merged 2014-12-24. + + +2014-08-01 - radius: Fix realms-config-file option + 880a81be7c8e0fe8567227bc17a1bff3ea035943 + +Radius plugin, not in the port. + + +2014-08-01 - pppd: Eliminate potential integer overflow in option parsing + 7658e8257183f062dc01f87969c140707c7e52cb + +pppd config file parser, not in the port. + + +2014-08-01 - pppd: Eliminate memory leak with multiple instances of a string option + b94b7fbbaa0589aa6ec5fdc733aeb9ff294d2656 + +pppd config file parser, not in the port. + + +2014-08-01 - pppd: Fix a stack variable overflow in MSCHAP-v2 + 36733a891fb56594fcee580f667b33a64b990981 + +This fixes a bug introduced in 08ef47ca ("pppd: Make MSCHAP-v2 cope better with packet loss"). + +We didn't merge 08ef47ca ;-) + + +2014-08-01 - winbind plugin: Add -DMPPE=1 to eliminate compiler warnings + 2b05e22c62095e97dd0a97e4b5588402c2185071 + +Linux plugin, not in the port. + + +2014-08-09 - Update README and patchlevel for 2.4.7 release + 6e8eaa7a78b31cdab2edf140a9c8afdb02ffaca5 + +Just release stuff. diff --git a/components/lwip/netif/ppp/auth.c b/components/lwip/netif/ppp/auth.c new file mode 100755 index 0000000000..2f611d571a --- /dev/null +++ b/components/lwip/netif/ppp/auth.c @@ -0,0 +1,2497 @@ +/* + * auth.c - PPP authentication and phase control. + * + * Copyright (c) 1993-2002 Paul Mackerras. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. The name(s) of the authors of this software must not be used to + * endorse or promote products derived from this software without + * prior written permission. + * + * 3. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by Paul Mackerras + * ". + * + * THE AUTHORS OF THIS SOFTWARE DISCLAIM ALL WARRANTIES WITH REGARD TO + * THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS, IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY + * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN + * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING + * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * Derived from main.c, which is: + * + * Copyright (c) 1984-2000 Carnegie Mellon University. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. The name "Carnegie Mellon University" must not be used to + * endorse or promote products derived from this software without + * prior written permission. For permission or any legal + * details, please contact + * Office of Technology Transfer + * Carnegie Mellon University + * 5000 Forbes Avenue + * Pittsburgh, PA 15213-3890 + * (412) 268-4387, fax: (412) 268-7395 + * tech-transfer@andrew.cmu.edu + * + * 4. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by Computing Services + * at Carnegie Mellon University (http://www.cmu.edu/computing/)." + * + * CARNEGIE MELLON UNIVERSITY DISCLAIMS ALL WARRANTIES WITH REGARD TO + * THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS, IN NO EVENT SHALL CARNEGIE MELLON UNIVERSITY BE LIABLE + * FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN + * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING + * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include "lwip/opt.h" +#if PPP_SUPPORT /* don't build if not configured for use in lwipopts.h */ + +#if 0 /* UNUSED */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#if defined(_PATH_LASTLOG) && defined(__linux__) +#include +#endif + +#include +#include +#include + +#ifdef HAS_SHADOW +#include +#ifndef PW_PPP +#define PW_PPP PW_LOGIN +#endif +#endif + +#include +#endif /* UNUSED */ + +#include "netif/ppp/ppp_impl.h" + +#include "netif/ppp/fsm.h" +#include "netif/ppp/lcp.h" +#if CCP_SUPPORT +#include "netif/ppp/ccp.h" +#endif /* CCP_SUPPORT */ +#if ECP_SUPPORT +#include "netif/ppp/ecp.h" +#endif /* ECP_SUPPORT */ +#include "netif/ppp/ipcp.h" +#if PAP_SUPPORT +#include "netif/ppp/upap.h" +#endif /* PAP_SUPPORT */ +#if CHAP_SUPPORT +#include "netif/ppp/chap-new.h" +#endif /* CHAP_SUPPORT */ +#if EAP_SUPPORT +#include "netif/ppp/eap.h" +#endif /* EAP_SUPPORT */ +#if CBCP_SUPPORT +#include "netif/ppp/cbcp.h" +#endif + +#if 0 /* UNUSED */ +#include "session.h" +#endif /* UNUSED */ + +#if 0 /* UNUSED */ +/* Bits in scan_authfile return value */ +#define NONWILD_SERVER 1 +#define NONWILD_CLIENT 2 + +#define ISWILD(word) (word[0] == '*' && word[1] == 0) +#endif /* UNUSED */ + +#if 0 /* UNUSED */ +/* List of addresses which the peer may use. */ +static struct permitted_ip *addresses[NUM_PPP]; + +/* Wordlist giving addresses which the peer may use + without authenticating itself. */ +static struct wordlist *noauth_addrs; + +/* Remote telephone number, if available */ +char remote_number[MAXNAMELEN]; + +/* Wordlist giving remote telephone numbers which may connect. */ +static struct wordlist *permitted_numbers; + +/* Extra options to apply, from the secrets file entry for the peer. */ +static struct wordlist *extra_options; +#endif /* UNUSED */ + +#if 0 /* UNUSED */ +/* Set if we require authentication only because we have a default route. */ +static bool default_auth; + +/* Hook to enable a plugin to control the idle time limit */ +int (*idle_time_hook) (struct ppp_idle *) = NULL; + +/* Hook for a plugin to say whether we can possibly authenticate any peer */ +int (*pap_check_hook) (void) = NULL; + +/* Hook for a plugin to check the PAP user and password */ +int (*pap_auth_hook) (char *user, char *passwd, char **msgp, + struct wordlist **paddrs, + struct wordlist **popts) = NULL; + +/* Hook for a plugin to know about the PAP user logout */ +void (*pap_logout_hook) (void) = NULL; + +/* Hook for a plugin to get the PAP password for authenticating us */ +int (*pap_passwd_hook) (char *user, char *passwd) = NULL; + +/* Hook for a plugin to say if we can possibly authenticate a peer using CHAP */ +int (*chap_check_hook) (void) = NULL; + +/* Hook for a plugin to get the CHAP password for authenticating us */ +int (*chap_passwd_hook) (char *user, char *passwd) = NULL; + +/* Hook for a plugin to say whether it is OK if the peer + refuses to authenticate. */ +int (*null_auth_hook) (struct wordlist **paddrs, + struct wordlist **popts) = NULL; + +int (*allowed_address_hook) (u32_t addr) = NULL; +#endif /* UNUSED */ + +#ifdef HAVE_MULTILINK +/* Hook for plugin to hear when an interface joins a multilink bundle */ +void (*multilink_join_hook) (void) = NULL; +#endif + +#if PPP_NOTIFY +/* A notifier for when the peer has authenticated itself, + and we are proceeding to the network phase. */ +struct notifier *auth_up_notifier = NULL; + +/* A notifier for when the link goes down. */ +struct notifier *link_down_notifier = NULL; +#endif /* PPP_NOTIFY */ + +/* + * Option variables. + */ +#if 0 /* MOVED TO ppp_settings */ +bool uselogin = 0; /* Use /etc/passwd for checking PAP */ +bool session_mgmt = 0; /* Do session management (login records) */ +bool cryptpap = 0; /* Passwords in pap-secrets are encrypted */ +bool refuse_pap = 0; /* Don't wanna auth. ourselves with PAP */ +bool refuse_chap = 0; /* Don't wanna auth. ourselves with CHAP */ +bool refuse_eap = 0; /* Don't wanna auth. ourselves with EAP */ +#if MSCHAP_SUPPORT +bool refuse_mschap = 0; /* Don't wanna auth. ourselves with MS-CHAP */ +bool refuse_mschap_v2 = 0; /* Don't wanna auth. ourselves with MS-CHAPv2 */ +#else /* MSCHAP_SUPPORT */ +bool refuse_mschap = 1; /* Don't wanna auth. ourselves with MS-CHAP */ +bool refuse_mschap_v2 = 1; /* Don't wanna auth. ourselves with MS-CHAPv2 */ +#endif /* MSCHAP_SUPPORT */ +bool usehostname = 0; /* Use hostname for our_name */ +bool auth_required = 0; /* Always require authentication from peer */ +bool allow_any_ip = 0; /* Allow peer to use any IP address */ +bool explicit_remote = 0; /* User specified explicit remote name */ +bool explicit_user = 0; /* Set if "user" option supplied */ +bool explicit_passwd = 0; /* Set if "password" option supplied */ +char remote_name[MAXNAMELEN]; /* Peer's name for authentication */ +static char *uafname; /* name of most recent +ua file */ + +extern char *crypt (const char *, const char *); +#endif /* UNUSED */ +/* Prototypes for procedures local to this file. */ + +static void network_phase(ppp_pcb *pcb); +#if PPP_IDLETIMELIMIT +static void check_idle(void *arg); +#endif /* PPP_IDLETIMELIMIT */ +#if PPP_MAXCONNECT +static void connect_time_expired(void *arg); +#endif /* PPP_MAXCONNECT */ +#if 0 /* UNUSED */ +static int null_login (int); +/* static int get_pap_passwd (char *); */ +static int have_pap_secret (int *); +static int have_chap_secret (char *, char *, int, int *); +static int have_srp_secret (char *client, char *server, int need_ip, + int *lacks_ipp); +static int ip_addr_check (u32_t, struct permitted_ip *); +static int scan_authfile (FILE *, char *, char *, char *, + struct wordlist **, struct wordlist **, + char *, int); +static void free_wordlist (struct wordlist *); +static void set_allowed_addrs (int, struct wordlist *, struct wordlist *); +static int some_ip_ok (struct wordlist *); +static int setupapfile (char **); +static int privgroup (char **); +static int set_noauth_addr (char **); +static int set_permitted_number (char **); +static void check_access (FILE *, char *); +static int wordlist_count (struct wordlist *); +#endif /* UNUSED */ + +#ifdef MAXOCTETS +static void check_maxoctets (void *); +#endif + +#if PPP_OPTIONS +/* + * Authentication-related options. + */ +option_t auth_options[] = { + { "auth", o_bool, &auth_required, + "Require authentication from peer", OPT_PRIO | 1 }, + { "noauth", o_bool, &auth_required, + "Don't require peer to authenticate", OPT_PRIOSUB | OPT_PRIV, + &allow_any_ip }, + { "require-pap", o_bool, &lcp_wantoptions[0].neg_upap, + "Require PAP authentication from peer", + OPT_PRIOSUB | 1, &auth_required }, + { "+pap", o_bool, &lcp_wantoptions[0].neg_upap, + "Require PAP authentication from peer", + OPT_ALIAS | OPT_PRIOSUB | 1, &auth_required }, + { "require-chap", o_bool, &auth_required, + "Require CHAP authentication from peer", + OPT_PRIOSUB | OPT_A2OR | MDTYPE_MD5, + &lcp_wantoptions[0].chap_mdtype }, + { "+chap", o_bool, &auth_required, + "Require CHAP authentication from peer", + OPT_ALIAS | OPT_PRIOSUB | OPT_A2OR | MDTYPE_MD5, + &lcp_wantoptions[0].chap_mdtype }, +#if MSCHAP_SUPPORT + { "require-mschap", o_bool, &auth_required, + "Require MS-CHAP authentication from peer", + OPT_PRIOSUB | OPT_A2OR | MDTYPE_MICROSOFT, + &lcp_wantoptions[0].chap_mdtype }, + { "+mschap", o_bool, &auth_required, + "Require MS-CHAP authentication from peer", + OPT_ALIAS | OPT_PRIOSUB | OPT_A2OR | MDTYPE_MICROSOFT, + &lcp_wantoptions[0].chap_mdtype }, + { "require-mschap-v2", o_bool, &auth_required, + "Require MS-CHAPv2 authentication from peer", + OPT_PRIOSUB | OPT_A2OR | MDTYPE_MICROSOFT_V2, + &lcp_wantoptions[0].chap_mdtype }, + { "+mschap-v2", o_bool, &auth_required, + "Require MS-CHAPv2 authentication from peer", + OPT_ALIAS | OPT_PRIOSUB | OPT_A2OR | MDTYPE_MICROSOFT_V2, + &lcp_wantoptions[0].chap_mdtype }, +#endif /* MSCHAP_SUPPORT */ +#if 0 + { "refuse-pap", o_bool, &refuse_pap, + "Don't agree to auth to peer with PAP", 1 }, + { "-pap", o_bool, &refuse_pap, + "Don't allow PAP authentication with peer", OPT_ALIAS | 1 }, + { "refuse-chap", o_bool, &refuse_chap, + "Don't agree to auth to peer with CHAP", + OPT_A2CLRB | MDTYPE_MD5, + &lcp_allowoptions[0].chap_mdtype }, + { "-chap", o_bool, &refuse_chap, + "Don't allow CHAP authentication with peer", + OPT_ALIAS | OPT_A2CLRB | MDTYPE_MD5, + &lcp_allowoptions[0].chap_mdtype }, +#endif +#if MSCHAP_SUPPORT +#if 0 + { "refuse-mschap", o_bool, &refuse_mschap, + "Don't agree to auth to peer with MS-CHAP", + OPT_A2CLRB | MDTYPE_MICROSOFT, + &lcp_allowoptions[0].chap_mdtype }, + { "-mschap", o_bool, &refuse_mschap, + "Don't allow MS-CHAP authentication with peer", + OPT_ALIAS | OPT_A2CLRB | MDTYPE_MICROSOFT, + &lcp_allowoptions[0].chap_mdtype }, + { "refuse-mschap-v2", o_bool, &refuse_mschap_v2, + "Don't agree to auth to peer with MS-CHAPv2", + OPT_A2CLRB | MDTYPE_MICROSOFT_V2, + &lcp_allowoptions[0].chap_mdtype }, + { "-mschap-v2", o_bool, &refuse_mschap_v2, + "Don't allow MS-CHAPv2 authentication with peer", + OPT_ALIAS | OPT_A2CLRB | MDTYPE_MICROSOFT_V2, + &lcp_allowoptions[0].chap_mdtype }, +#endif +#endif /* MSCHAP_SUPPORT*/ +#if EAP_SUPPORT + { "require-eap", o_bool, &lcp_wantoptions[0].neg_eap, + "Require EAP authentication from peer", OPT_PRIOSUB | 1, + &auth_required }, +#if 0 + { "refuse-eap", o_bool, &refuse_eap, + "Don't agree to authenticate to peer with EAP", 1 }, +#endif +#endif /* EAP_SUPPORT */ + { "name", o_string, our_name, + "Set local name for authentication", + OPT_PRIO | OPT_PRIV | OPT_STATIC, NULL, MAXNAMELEN }, + + { "+ua", o_special, (void *)setupapfile, + "Get PAP user and password from file", + OPT_PRIO | OPT_A2STRVAL, &uafname }, + +#if 0 + { "user", o_string, user, + "Set name for auth with peer", OPT_PRIO | OPT_STATIC, + &explicit_user, MAXNAMELEN }, + + { "password", o_string, passwd, + "Password for authenticating us to the peer", + OPT_PRIO | OPT_STATIC | OPT_HIDE, + &explicit_passwd, MAXSECRETLEN }, +#endif + + { "usehostname", o_bool, &usehostname, + "Must use hostname for authentication", 1 }, + + { "remotename", o_string, remote_name, + "Set remote name for authentication", OPT_PRIO | OPT_STATIC, + &explicit_remote, MAXNAMELEN }, + + { "login", o_bool, &uselogin, + "Use system password database for PAP", OPT_A2COPY | 1 , + &session_mgmt }, + { "enable-session", o_bool, &session_mgmt, + "Enable session accounting for remote peers", OPT_PRIV | 1 }, + + { "papcrypt", o_bool, &cryptpap, + "PAP passwords are encrypted", 1 }, + + { "privgroup", o_special, (void *)privgroup, + "Allow group members to use privileged options", OPT_PRIV | OPT_A2LIST }, + + { "allow-ip", o_special, (void *)set_noauth_addr, + "Set IP address(es) which can be used without authentication", + OPT_PRIV | OPT_A2LIST }, + + { "remotenumber", o_string, remote_number, + "Set remote telephone number for authentication", OPT_PRIO | OPT_STATIC, + NULL, MAXNAMELEN }, + + { "allow-number", o_special, (void *)set_permitted_number, + "Set telephone number(s) which are allowed to connect", + OPT_PRIV | OPT_A2LIST }, + + { NULL } +}; +#endif /* PPP_OPTIONS */ + +#if 0 /* UNUSED */ +/* + * setupapfile - specifies UPAP info for authenticating with peer. + */ +static int +setupapfile(argv) + char **argv; +{ + FILE *ufile; + int l; + uid_t euid; + char u[MAXNAMELEN], p[MAXSECRETLEN]; + char *fname; + + lcp_allowoptions[0].neg_upap = 1; + + /* open user info file */ + fname = strdup(*argv); + if (fname == NULL) + novm("+ua file name"); + euid = geteuid(); + if (seteuid(getuid()) == -1) { + option_error("unable to reset uid before opening %s: %m", fname); + return 0; + } + ufile = fopen(fname, "r"); + if (seteuid(euid) == -1) + fatal("unable to regain privileges: %m"); + if (ufile == NULL) { + option_error("unable to open user login data file %s", fname); + return 0; + } + check_access(ufile, fname); + uafname = fname; + + /* get username */ + if (fgets(u, MAXNAMELEN - 1, ufile) == NULL + || fgets(p, MAXSECRETLEN - 1, ufile) == NULL) { + fclose(ufile); + option_error("unable to read user login data file %s", fname); + return 0; + } + fclose(ufile); + + /* get rid of newlines */ + l = strlen(u); + if (l > 0 && u[l-1] == '\n') + u[l-1] = 0; + l = strlen(p); + if (l > 0 && p[l-1] == '\n') + p[l-1] = 0; + + if (override_value("user", option_priority, fname)) { + strlcpy(ppp_settings.user, u, sizeof(ppp_settings.user)); + explicit_user = 1; + } + if (override_value("passwd", option_priority, fname)) { + strlcpy(ppp_settings.passwd, p, sizeof(ppp_settings.passwd)); + explicit_passwd = 1; + } + + return (1); +} + +/* + * privgroup - allow members of the group to have privileged access. + */ +static int +privgroup(argv) + char **argv; +{ + struct group *g; + int i; + + g = getgrnam(*argv); + if (g == 0) { + option_error("group %s is unknown", *argv); + return 0; + } + for (i = 0; i < ngroups; ++i) { + if (groups[i] == g->gr_gid) { + privileged = 1; + break; + } + } + return 1; +} + + +/* + * set_noauth_addr - set address(es) that can be used without authentication. + * Equivalent to specifying an entry like `"" * "" addr' in pap-secrets. + */ +static int +set_noauth_addr(argv) + char **argv; +{ + char *addr = *argv; + int l = strlen(addr) + 1; + struct wordlist *wp; + + wp = (struct wordlist *) malloc(sizeof(struct wordlist) + l); + if (wp == NULL) + novm("allow-ip argument"); + wp->word = (char *) (wp + 1); + wp->next = noauth_addrs; + MEMCPY(wp->word, addr, l); + noauth_addrs = wp; + return 1; +} + + +/* + * set_permitted_number - set remote telephone number(s) that may connect. + */ +static int +set_permitted_number(argv) + char **argv; +{ + char *number = *argv; + int l = strlen(number) + 1; + struct wordlist *wp; + + wp = (struct wordlist *) malloc(sizeof(struct wordlist) + l); + if (wp == NULL) + novm("allow-number argument"); + wp->word = (char *) (wp + 1); + wp->next = permitted_numbers; + MEMCPY(wp->word, number, l); + permitted_numbers = wp; + return 1; +} +#endif + +/* + * An Open on LCP has requested a change from Dead to Establish phase. + */ +void link_required(ppp_pcb *pcb) { + LWIP_UNUSED_ARG(pcb); +} + +#if 0 +/* + * Bring the link up to the point of being able to do ppp. + */ +void start_link(unit) + int unit; +{ + ppp_pcb *pcb = &ppp_pcb_list[unit]; + char *msg; + + status = EXIT_NEGOTIATION_FAILED; + new_phase(pcb, PPP_PHASE_SERIALCONN); + + hungup = 0; + devfd = the_channel->connect(); + msg = "Connect script failed"; + if (devfd < 0) + goto fail; + + /* set up the serial device as a ppp interface */ + /* + * N.B. we used to do tdb_writelock/tdb_writeunlock around this + * (from establish_ppp to set_ifunit). However, we won't be + * doing the set_ifunit in multilink mode, which is the only time + * we need the atomicity that the tdb_writelock/tdb_writeunlock + * gives us. Thus we don't need the tdb_writelock/tdb_writeunlock. + */ + fd_ppp = the_channel->establish_ppp(devfd); + msg = "ppp establishment failed"; + if (fd_ppp < 0) { + status = EXIT_FATAL_ERROR; + goto disconnect; + } + + if (!demand && ifunit >= 0) + set_ifunit(1); + + /* + * Start opening the connection and wait for + * incoming events (reply, timeout, etc.). + */ + if (ifunit >= 0) + ppp_notice("Connect: %s <--> %s", ifname, ppp_devnam); + else + ppp_notice("Starting negotiation on %s", ppp_devnam); + add_fd(fd_ppp); + + new_phase(pcb, PPP_PHASE_ESTABLISH); + + lcp_lowerup(pcb); + return; + + disconnect: + new_phase(pcb, PPP_PHASE_DISCONNECT); + if (the_channel->disconnect) + the_channel->disconnect(); + + fail: + new_phase(pcb, PPP_PHASE_DEAD); + if (the_channel->cleanup) + (*the_channel->cleanup)(); +} +#endif + +/* + * LCP has terminated the link; go to the Dead phase and take the + * physical layer down. + */ +void link_terminated(ppp_pcb *pcb) { + if (pcb->phase == PPP_PHASE_DEAD || pcb->phase == PPP_PHASE_MASTER) + return; + new_phase(pcb, PPP_PHASE_DISCONNECT); + +#if 0 /* UNUSED */ + if (pap_logout_hook) { + pap_logout_hook(); + } + session_end(devnam); +#endif /* UNUSED */ + + if (!doing_multilink) { + ppp_notice("Connection terminated."); +#if PPP_STATS_SUPPORT + print_link_stats(); +#endif /* PPP_STATS_SUPPORT */ + } else + ppp_notice("Link terminated."); + + lcp_lowerdown(pcb); + + new_phase(pcb, PPP_PHASE_DEAD); + ppp_link_terminated(pcb); +#if 0 + /* + * Delete pid files before disestablishing ppp. Otherwise it + * can happen that another pppd gets the same unit and then + * we delete its pid file. + */ + if (!doing_multilink && !demand) + remove_pidfiles(); + + /* + * If we may want to bring the link up again, transfer + * the ppp unit back to the loopback. Set the + * real serial device back to its normal mode of operation. + */ + if (fd_ppp >= 0) { + remove_fd(fd_ppp); + clean_check(); + the_channel->disestablish_ppp(devfd); + if (doing_multilink) + mp_exit_bundle(); + fd_ppp = -1; + } + if (!hungup) + lcp_lowerdown(pcb); + if (!doing_multilink && !demand) + script_unsetenv("IFNAME"); + + /* + * Run disconnector script, if requested. + * XXX we may not be able to do this if the line has hung up! + */ + if (devfd >= 0 && the_channel->disconnect) { + the_channel->disconnect(); + devfd = -1; + } + if (the_channel->cleanup) + (*the_channel->cleanup)(); + + if (doing_multilink && multilink_master) { + if (!bundle_terminating) + new_phase(pcb, PPP_PHASE_MASTER); + else + mp_bundle_terminated(); + } else + new_phase(pcb, PPP_PHASE_DEAD); +#endif +} + +/* + * LCP has gone down; it will either die or try to re-establish. + */ +void link_down(ppp_pcb *pcb) { +#if PPP_NOTIFY + notify(link_down_notifier, 0); +#endif /* PPP_NOTIFY */ + + if (!doing_multilink) { + upper_layers_down(pcb); + if (pcb->phase != PPP_PHASE_DEAD && pcb->phase != PPP_PHASE_MASTER) + new_phase(pcb, PPP_PHASE_ESTABLISH); + } + /* XXX if doing_multilink, should do something to stop + network-layer traffic on the link */ +} + +void upper_layers_down(ppp_pcb *pcb) { + int i; + const struct protent *protp; + + for (i = 0; (protp = protocols[i]) != NULL; ++i) { + if (protp->protocol != PPP_LCP && protp->lowerdown != NULL) + (*protp->lowerdown)(pcb); + if (protp->protocol < 0xC000 && protp->close != NULL) + (*protp->close)(pcb, "LCP down"); + } + pcb->num_np_open = 0; + pcb->num_np_up = 0; +} + +/* + * The link is established. + * Proceed to the Dead, Authenticate or Network phase as appropriate. + */ +void link_established(ppp_pcb *pcb) { +#if PPP_AUTH_SUPPORT + int auth; +#if PPP_SERVER + lcp_options *wo = &pcb->lcp_wantoptions; + lcp_options *go = &pcb->lcp_gotoptions; +#endif /* PPP_SERVER */ + lcp_options *ho = &pcb->lcp_hisoptions; +#endif /* PPP_AUTH_SUPPORT */ + int i; + const struct protent *protp; + + /* + * Tell higher-level protocols that LCP is up. + */ + if (!doing_multilink) { + for (i = 0; (protp = protocols[i]) != NULL; ++i) + if (protp->protocol != PPP_LCP + && protp->lowerup != NULL) + (*protp->lowerup)(pcb); + } + +#if PPP_AUTH_SUPPORT +#if PPP_SERVER +#if PPP_ALLOWED_ADDRS + if (!auth_required && noauth_addrs != NULL) + set_allowed_addrs(unit, NULL, NULL); +#endif /* PPP_ALLOWED_ADDRS */ + + if (pcb->settings.auth_required && !(0 +#if PAP_SUPPORT + || go->neg_upap +#endif /* PAP_SUPPORT */ +#if CHAP_SUPPORT + || go->neg_chap +#endif /* CHAP_SUPPORT */ +#if EAP_SUPPORT + || go->neg_eap +#endif /* EAP_SUPPORT */ + )) { + +#if PPP_ALLOWED_ADDRS + /* + * We wanted the peer to authenticate itself, and it refused: + * if we have some address(es) it can use without auth, fine, + * otherwise treat it as though it authenticated with PAP using + * a username of "" and a password of "". If that's not OK, + * boot it out. + */ + if (noauth_addrs != NULL) { + set_allowed_addrs(unit, NULL, NULL); + } else +#endif /* PPP_ALLOWED_ADDRS */ + if (!wo->neg_upap || !pcb->settings.null_login) { + ppp_warn("peer refused to authenticate: terminating link"); +#if 0 /* UNUSED */ + status = EXIT_PEER_AUTH_FAILED; +#endif /* UNUSED */ + pcb->err_code = PPPERR_AUTHFAIL; + lcp_close(pcb, "peer refused to authenticate"); + return; + } + } +#endif /* PPP_SERVER */ + + new_phase(pcb, PPP_PHASE_AUTHENTICATE); + auth = 0; +#if PPP_SERVER +#if EAP_SUPPORT + if (go->neg_eap) { + eap_authpeer(pcb, PPP_OUR_NAME); + auth |= EAP_PEER; + } else +#endif /* EAP_SUPPORT */ +#if CHAP_SUPPORT + if (go->neg_chap) { + chap_auth_peer(pcb, PPP_OUR_NAME, CHAP_DIGEST(go->chap_mdtype)); + auth |= CHAP_PEER; + } else +#endif /* CHAP_SUPPORT */ +#if PAP_SUPPORT + if (go->neg_upap) { + upap_authpeer(pcb); + auth |= PAP_PEER; + } else +#endif /* PAP_SUPPORT */ + {} +#endif /* PPP_SERVER */ + +#if EAP_SUPPORT + if (ho->neg_eap) { + eap_authwithpeer(pcb, pcb->settings.user); + auth |= EAP_WITHPEER; + } else +#endif /* EAP_SUPPORT */ +#if CHAP_SUPPORT + if (ho->neg_chap) { + chap_auth_with_peer(pcb, pcb->settings.user, CHAP_DIGEST(ho->chap_mdtype)); + auth |= CHAP_WITHPEER; + } else +#endif /* CHAP_SUPPORT */ +#if PAP_SUPPORT + if (ho->neg_upap) { + upap_authwithpeer(pcb, pcb->settings.user, pcb->settings.passwd); + auth |= PAP_WITHPEER; + } else +#endif /* PAP_SUPPORT */ + {} + + pcb->auth_pending = auth; + pcb->auth_done = 0; + + if (!auth) +#endif /* PPP_AUTH_SUPPORT */ + network_phase(pcb); +} + +/* + * Proceed to the network phase. + */ +static void network_phase(ppp_pcb *pcb) { +#if CBCP_SUPPORT + ppp_pcb *pcb = &ppp_pcb_list[unit]; +#endif +#if 0 /* UNUSED */ + lcp_options *go = &lcp_gotoptions[unit]; +#endif /* UNUSED */ + +#if 0 /* UNUSED */ + /* Log calling number. */ + if (*remote_number) + ppp_notice("peer from calling number %q authorized", remote_number); +#endif /* UNUSED */ + +#if PPP_NOTIFY + /* + * If the peer had to authenticate, notify it now. + */ + if (0 +#if CHAP_SUPPORT + || go->neg_chap +#endif /* CHAP_SUPPORT */ +#if PAP_SUPPORT + || go->neg_upap +#endif /* PAP_SUPPORT */ +#if EAP_SUPPORT + || go->neg_eap +#endif /* EAP_SUPPORT */ + ) { + notify(auth_up_notifier, 0); + } +#endif /* PPP_NOTIFY */ + +#if CBCP_SUPPORT + /* + * If we negotiated callback, do it now. + */ + if (go->neg_cbcp) { + new_phase(pcb, PPP_PHASE_CALLBACK); + (*cbcp_protent.open)(pcb); + return; + } +#endif + +#if PPP_OPTIONS + /* + * Process extra options from the secrets file + */ + if (extra_options) { + options_from_list(extra_options, 1); + free_wordlist(extra_options); + extra_options = 0; + } +#endif /* PPP_OPTIONS */ + start_networks(pcb); +} + +void start_networks(ppp_pcb *pcb) { +#if CCP_SUPPORT || ECP_SUPPORT + int i; + const struct protent *protp; +#endif /* CCP_SUPPORT || ECP_SUPPORT */ + + new_phase(pcb, PPP_PHASE_NETWORK); + +#ifdef HAVE_MULTILINK + if (multilink) { + if (mp_join_bundle()) { + if (multilink_join_hook) + (*multilink_join_hook)(); + if (updetach && !nodetach) + detach(); + return; + } + } +#endif /* HAVE_MULTILINK */ + +#ifdef PPP_FILTER + if (!demand) + set_filters(&pass_filter, &active_filter); +#endif +#if CCP_SUPPORT || ECP_SUPPORT + /* Start CCP and ECP */ + for (i = 0; (protp = protocols[i]) != NULL; ++i) + if ( + (0 +#if ECP_SUPPORT + || protp->protocol == PPP_ECP +#endif /* ECP_SUPPORT */ +#if CCP_SUPPORT + || protp->protocol == PPP_CCP +#endif /* CCP_SUPPORT */ + ) + && protp->open != NULL) + (*protp->open)(pcb); +#endif /* CCP_SUPPORT || ECP_SUPPORT */ + + /* + * Bring up other network protocols iff encryption is not required. + */ + if (1 +#if ECP_SUPPORT + && !ecp_gotoptions[unit].required +#endif /* ECP_SUPPORT */ +#if MPPE_SUPPORT + && !pcb->ccp_gotoptions.mppe +#endif /* MPPE_SUPPORT */ + ) + continue_networks(pcb); +} + +void continue_networks(ppp_pcb *pcb) { + int i; + const struct protent *protp; + + /* + * Start the "real" network protocols. + */ + for (i = 0; (protp = protocols[i]) != NULL; ++i) + if (protp->protocol < 0xC000 +#if CCP_SUPPORT + && protp->protocol != PPP_CCP +#endif /* CCP_SUPPORT */ +#if ECP_SUPPORT + && protp->protocol != PPP_ECP +#endif /* ECP_SUPPORT */ + && protp->open != NULL) { + (*protp->open)(pcb); + ++pcb->num_np_open; + } + + if (pcb->num_np_open == 0) + /* nothing to do */ + lcp_close(pcb, "No network protocols running"); +} + +#if PPP_AUTH_SUPPORT +#if PPP_SERVER +/* + * auth_check_passwd - Check the user name and passwd against configuration. + * + * returns: + * 0: Authentication failed. + * 1: Authentication succeeded. + * In either case, msg points to an appropriate message and msglen to the message len. + */ +int auth_check_passwd(ppp_pcb *pcb, char *auser, int userlen, char *apasswd, int passwdlen, const char **msg, int *msglen) { + int secretuserlen; + int secretpasswdlen; + + if (pcb->settings.user && pcb->settings.passwd) { + secretuserlen = (int)strlen(pcb->settings.user); + secretpasswdlen = (int)strlen(pcb->settings.passwd); + if (secretuserlen == userlen + && secretpasswdlen == passwdlen + && !memcmp(auser, pcb->settings.user, userlen) + && !memcmp(apasswd, pcb->settings.passwd, passwdlen) ) { + *msg = "Login ok"; + *msglen = sizeof("Login ok")-1; + return 1; + } + } + + *msg = "Login incorrect"; + *msglen = sizeof("Login incorrect")-1; + return 0; +} + +/* + * The peer has failed to authenticate himself using `protocol'. + */ +void auth_peer_fail(ppp_pcb *pcb, int protocol) { + LWIP_UNUSED_ARG(protocol); + /* + * Authentication failure: take the link down + */ +#if 0 /* UNUSED */ + status = EXIT_PEER_AUTH_FAILED; +#endif /* UNUSED */ + pcb->err_code = PPPERR_AUTHFAIL; + lcp_close(pcb, "Authentication failed"); +} + +/* + * The peer has been successfully authenticated using `protocol'. + */ +void auth_peer_success(ppp_pcb *pcb, int protocol, int prot_flavor, const char *name, int namelen) { + int bit; +#ifndef HAVE_MULTILINK + LWIP_UNUSED_ARG(name); + LWIP_UNUSED_ARG(namelen); +#endif /* HAVE_MULTILINK */ + + switch (protocol) { +#if CHAP_SUPPORT + case PPP_CHAP: + bit = CHAP_PEER; + switch (prot_flavor) { + case CHAP_MD5: + bit |= CHAP_MD5_PEER; + break; +#if MSCHAP_SUPPORT + case CHAP_MICROSOFT: + bit |= CHAP_MS_PEER; + break; + case CHAP_MICROSOFT_V2: + bit |= CHAP_MS2_PEER; + break; +#endif /* MSCHAP_SUPPORT */ + default: + break; + } + break; +#endif /* CHAP_SUPPORT */ +#if PAP_SUPPORT + case PPP_PAP: + bit = PAP_PEER; + break; +#endif /* PAP_SUPPORT */ +#if EAP_SUPPORT + case PPP_EAP: + bit = EAP_PEER; + break; +#endif /* EAP_SUPPORT */ + default: + ppp_warn("auth_peer_success: unknown protocol %x", protocol); + return; + } + +#ifdef HAVE_MULTILINK + /* + * Save the authenticated name of the peer for later. + */ + if (namelen > (int)sizeof(pcb->peer_authname) - 1) + namelen = (int)sizeof(pcb->peer_authname) - 1; + MEMCPY(pcb->peer_authname, name, namelen); + pcb->peer_authname[namelen] = 0; +#endif /* HAVE_MULTILINK */ +#if 0 /* UNUSED */ + script_setenv("PEERNAME", , 0); +#endif /* UNUSED */ + + /* Save the authentication method for later. */ + pcb->auth_done |= bit; + + /* + * If there is no more authentication still to be done, + * proceed to the network (or callback) phase. + */ + if ((pcb->auth_pending &= ~bit) == 0) + network_phase(pcb); +} +#endif /* PPP_SERVER */ + +/* + * We have failed to authenticate ourselves to the peer using `protocol'. + */ +void auth_withpeer_fail(ppp_pcb *pcb, int protocol) { + LWIP_UNUSED_ARG(protocol); + /* + * We've failed to authenticate ourselves to our peer. + * + * Some servers keep sending CHAP challenges, but there + * is no point in persisting without any way to get updated + * authentication secrets. + * + * He'll probably take the link down, and there's not much + * we can do except wait for that. + */ + pcb->err_code = PPPERR_AUTHFAIL; + lcp_close(pcb, "Failed to authenticate ourselves to peer"); +} + +/* + * We have successfully authenticated ourselves with the peer using `protocol'. + */ +void auth_withpeer_success(ppp_pcb *pcb, int protocol, int prot_flavor) { + int bit; + const char *prot = ""; + + switch (protocol) { +#if CHAP_SUPPORT + case PPP_CHAP: + bit = CHAP_WITHPEER; + prot = "CHAP"; + switch (prot_flavor) { + case CHAP_MD5: + bit |= CHAP_MD5_WITHPEER; + break; +#if MSCHAP_SUPPORT + case CHAP_MICROSOFT: + bit |= CHAP_MS_WITHPEER; + break; + case CHAP_MICROSOFT_V2: + bit |= CHAP_MS2_WITHPEER; + break; +#endif /* MSCHAP_SUPPORT */ + default: + break; + } + break; +#endif /* CHAP_SUPPORT */ +#if PAP_SUPPORT + case PPP_PAP: + bit = PAP_WITHPEER; + prot = "PAP"; + break; +#endif /* PAP_SUPPORT */ +#if EAP_SUPPORT + case PPP_EAP: + bit = EAP_WITHPEER; + prot = "EAP"; + break; +#endif /* EAP_SUPPORT */ + default: + ppp_warn("auth_withpeer_success: unknown protocol %x", protocol); + bit = 0; + /* no break */ + } + + ppp_notice("%s authentication succeeded", prot); + + /* Save the authentication method for later. */ + pcb->auth_done |= bit; + + /* + * If there is no more authentication still being done, + * proceed to the network (or callback) phase. + */ + if ((pcb->auth_pending &= ~bit) == 0) + network_phase(pcb); +} +#endif /* PPP_AUTH_SUPPORT */ + + +/* + * np_up - a network protocol has come up. + */ +void np_up(ppp_pcb *pcb, int proto) { +#if PPP_IDLETIMELIMIT + int tlim; +#endif /* PPP_IDLETIMELIMIT */ + LWIP_UNUSED_ARG(proto); + + if (pcb->num_np_up == 0) { + /* + * At this point we consider that the link has come up successfully. + */ + new_phase(pcb, PPP_PHASE_RUNNING); + +#if PPP_IDLETIMELIMIT +#if 0 /* UNUSED */ + if (idle_time_hook != 0) + tlim = (*idle_time_hook)(NULL); + else +#endif /* UNUSED */ + tlim = pcb->settings.idle_time_limit; + if (tlim > 0) + TIMEOUT(check_idle, (void*)pcb, tlim); +#endif /* PPP_IDLETIMELIMIT */ + +#if PPP_MAXCONNECT + /* + * Set a timeout to close the connection once the maximum + * connect time has expired. + */ + if (pcb->settings.maxconnect > 0) + TIMEOUT(connect_time_expired, (void*)pcb, pcb->settings.maxconnect); +#endif /* PPP_MAXCONNECT */ + +#ifdef MAXOCTETS + if (maxoctets > 0) + TIMEOUT(check_maxoctets, NULL, maxoctets_timeout); +#endif + +#if 0 /* Unused */ + /* + * Detach now, if the updetach option was given. + */ + if (updetach && !nodetach) + detach(); +#endif /* Unused */ + } + ++pcb->num_np_up; +} + +/* + * np_down - a network protocol has gone down. + */ +void np_down(ppp_pcb *pcb, int proto) { + LWIP_UNUSED_ARG(proto); + if (--pcb->num_np_up == 0) { +#if PPP_IDLETIMELIMIT + UNTIMEOUT(check_idle, (void*)pcb); +#endif /* PPP_IDLETIMELIMIT */ +#if PPP_MAXCONNECT + UNTIMEOUT(connect_time_expired, NULL); +#endif /* PPP_MAXCONNECT */ +#ifdef MAXOCTETS + UNTIMEOUT(check_maxoctets, NULL); +#endif + new_phase(pcb, PPP_PHASE_NETWORK); + } +} + +/* + * np_finished - a network protocol has finished using the link. + */ +void np_finished(ppp_pcb *pcb, int proto) { + LWIP_UNUSED_ARG(proto); + if (--pcb->num_np_open <= 0) { + /* no further use for the link: shut up shop. */ + lcp_close(pcb, "No network protocols running"); + } +} + +#ifdef MAXOCTETS +static void +check_maxoctets(arg) + void *arg; +{ +#if PPP_STATS_SUPPORT + unsigned int used; + + update_link_stats(ifunit); + link_stats_valid=0; + + switch(maxoctets_dir) { + case PPP_OCTETS_DIRECTION_IN: + used = link_stats.bytes_in; + break; + case PPP_OCTETS_DIRECTION_OUT: + used = link_stats.bytes_out; + break; + case PPP_OCTETS_DIRECTION_MAXOVERAL: + case PPP_OCTETS_DIRECTION_MAXSESSION: + used = (link_stats.bytes_in > link_stats.bytes_out) ? link_stats.bytes_in : link_stats.bytes_out; + break; + default: + used = link_stats.bytes_in+link_stats.bytes_out; + break; + } + if (used > maxoctets) { + ppp_notice("Traffic limit reached. Limit: %u Used: %u", maxoctets, used); + status = EXIT_TRAFFIC_LIMIT; + lcp_close(pcb, "Traffic limit"); +#if 0 /* UNUSED */ + need_holdoff = 0; +#endif /* UNUSED */ + } else { + TIMEOUT(check_maxoctets, NULL, maxoctets_timeout); + } +#endif /* PPP_STATS_SUPPORT */ +} +#endif /* MAXOCTETS */ + +#if PPP_IDLETIMELIMIT +/* + * check_idle - check whether the link has been idle for long + * enough that we can shut it down. + */ +static void check_idle(void *arg) { + ppp_pcb *pcb = (ppp_pcb*)arg; + struct ppp_idle idle; + time_t itime; + int tlim; + + if (!get_idle_time(pcb, &idle)) + return; +#if 0 /* UNUSED */ + if (idle_time_hook != 0) { + tlim = idle_time_hook(&idle); + } else { +#endif /* UNUSED */ + itime = LWIP_MIN(idle.xmit_idle, idle.recv_idle); + tlim = pcb->settings.idle_time_limit - itime; +#if 0 /* UNUSED */ + } +#endif /* UNUSED */ + if (tlim <= 0) { + /* link is idle: shut it down. */ + ppp_notice("Terminating connection due to lack of activity."); + pcb->err_code = PPPERR_IDLETIMEOUT; + lcp_close(pcb, "Link inactive"); +#if 0 /* UNUSED */ + need_holdoff = 0; +#endif /* UNUSED */ + } else { + TIMEOUT(check_idle, (void*)pcb, tlim); + } +} +#endif /* PPP_IDLETIMELIMIT */ + +#if PPP_MAXCONNECT +/* + * connect_time_expired - log a message and close the connection. + */ +static void connect_time_expired(void *arg) { + ppp_pcb *pcb = (ppp_pcb*)arg; + ppp_info("Connect time expired"); + pcb->err_code = PPPERR_CONNECTTIME; + lcp_close(pcb, "Connect time expired"); /* Close connection */ +} +#endif /* PPP_MAXCONNECT */ + +#if PPP_OPTIONS +/* + * auth_check_options - called to check authentication options. + */ +void +auth_check_options() +{ + lcp_options *wo = &lcp_wantoptions[0]; + int can_auth; + int lacks_ip; + + /* Default our_name to hostname, and user to our_name */ + if (our_name[0] == 0 || usehostname) + strlcpy(our_name, hostname, sizeof(our_name)); + /* If a blank username was explicitly given as an option, trust + the user and don't use our_name */ + if (ppp_settings.user[0] == 0 && !explicit_user) + strlcpy(ppp_settings.user, our_name, sizeof(ppp_settings.user)); + + /* + * If we have a default route, require the peer to authenticate + * unless the noauth option was given or the real user is root. + */ + if (!auth_required && !allow_any_ip && have_route_to(0) && !privileged) { + auth_required = 1; + default_auth = 1; + } + +#if CHAP_SUPPORT + /* If we selected any CHAP flavors, we should probably negotiate it. :-) */ + if (wo->chap_mdtype) + wo->neg_chap = 1; +#endif /* CHAP_SUPPORT */ + + /* If authentication is required, ask peer for CHAP, PAP, or EAP. */ + if (auth_required) { + allow_any_ip = 0; + if (1 +#if CHAP_SUPPORT + && !wo->neg_chap +#endif /* CHAP_SUPPORT */ +#if PAP_SUPPORT + && !wo->neg_upap +#endif /* PAP_SUPPORT */ +#if EAP_SUPPORT + && !wo->neg_eap +#endif /* EAP_SUPPORT */ + ) { +#if CHAP_SUPPORT + wo->neg_chap = CHAP_MDTYPE_SUPPORTED != MDTYPE_NONE; + wo->chap_mdtype = CHAP_MDTYPE_SUPPORTED; +#endif /* CHAP_SUPPORT */ +#if PAP_SUPPORT + wo->neg_upap = 1; +#endif /* PAP_SUPPORT */ +#if EAP_SUPPORT + wo->neg_eap = 1; +#endif /* EAP_SUPPORT */ + } + } else { +#if CHAP_SUPPORT + wo->neg_chap = 0; + wo->chap_mdtype = MDTYPE_NONE; +#endif /* CHAP_SUPPORT */ +#if PAP_SUPPORT + wo->neg_upap = 0; +#endif /* PAP_SUPPORT */ +#if EAP_SUPPORT + wo->neg_eap = 0; +#endif /* EAP_SUPPORT */ + } + + /* + * Check whether we have appropriate secrets to use + * to authenticate the peer. Note that EAP can authenticate by way + * of a CHAP-like exchanges as well as SRP. + */ + lacks_ip = 0; +#if PAP_SUPPORT + can_auth = wo->neg_upap && (uselogin || have_pap_secret(&lacks_ip)); +#else + can_auth = 0; +#endif /* PAP_SUPPORT */ + if (!can_auth && (0 +#if CHAP_SUPPORT + || wo->neg_chap +#endif /* CHAP_SUPPORT */ +#if EAP_SUPPORT + || wo->neg_eap +#endif /* EAP_SUPPORT */ + )) { +#if CHAP_SUPPORT + can_auth = have_chap_secret((explicit_remote? remote_name: NULL), + our_name, 1, &lacks_ip); +#else + can_auth = 0; +#endif + } + if (!can_auth +#if EAP_SUPPORT + && wo->neg_eap +#endif /* EAP_SUPPORT */ + ) { + can_auth = have_srp_secret((explicit_remote? remote_name: NULL), + our_name, 1, &lacks_ip); + } + + if (auth_required && !can_auth && noauth_addrs == NULL) { + if (default_auth) { + option_error( +"By default the remote system is required to authenticate itself"); + option_error( +"(because this system has a default route to the internet)"); + } else if (explicit_remote) + option_error( +"The remote system (%s) is required to authenticate itself", + remote_name); + else + option_error( +"The remote system is required to authenticate itself"); + option_error( +"but I couldn't find any suitable secret (password) for it to use to do so."); + if (lacks_ip) + option_error( +"(None of the available passwords would let it use an IP address.)"); + + exit(1); + } + + /* + * Early check for remote number authorization. + */ + if (!auth_number()) { + ppp_warn("calling number %q is not authorized", remote_number); + exit(EXIT_CNID_AUTH_FAILED); + } +} +#endif /* PPP_OPTIONS */ + +#if 0 /* UNUSED */ +/* + * auth_reset - called when LCP is starting negotiations to recheck + * authentication options, i.e. whether we have appropriate secrets + * to use for authenticating ourselves and/or the peer. + */ +void +auth_reset(unit) + int unit; +{ + lcp_options *go = &lcp_gotoptions[unit]; + lcp_options *ao = &lcp_allowoptions[unit]; + int hadchap; + + hadchap = -1; + ao->neg_upap = !refuse_pap && (passwd[0] != 0 || get_pap_passwd(NULL)); + ao->neg_chap = (!refuse_chap || !refuse_mschap || !refuse_mschap_v2) + && (passwd[0] != 0 || + (hadchap = have_chap_secret(user, (explicit_remote? remote_name: + NULL), 0, NULL))); + ao->neg_eap = !refuse_eap && ( + passwd[0] != 0 || + (hadchap == 1 || (hadchap == -1 && have_chap_secret(user, + (explicit_remote? remote_name: NULL), 0, NULL))) || + have_srp_secret(user, (explicit_remote? remote_name: NULL), 0, NULL)); + + hadchap = -1; + if (go->neg_upap && !uselogin && !have_pap_secret(NULL)) + go->neg_upap = 0; + if (go->neg_chap) { + if (!(hadchap = have_chap_secret((explicit_remote? remote_name: NULL), + our_name, 1, NULL))) + go->neg_chap = 0; + } + if (go->neg_eap && + (hadchap == 0 || (hadchap == -1 && + !have_chap_secret((explicit_remote? remote_name: NULL), our_name, + 1, NULL))) && + !have_srp_secret((explicit_remote? remote_name: NULL), our_name, 1, + NULL)) + go->neg_eap = 0; +} + +/* + * check_passwd - Check the user name and passwd against the PAP secrets + * file. If requested, also check against the system password database, + * and login the user if OK. + * + * returns: + * UPAP_AUTHNAK: Authentication failed. + * UPAP_AUTHACK: Authentication succeeded. + * In either case, msg points to an appropriate message. + */ +int +check_passwd(unit, auser, userlen, apasswd, passwdlen, msg) + int unit; + char *auser; + int userlen; + char *apasswd; + int passwdlen; + char **msg; +{ + return UPAP_AUTHNAK; + int ret; + char *filename; + FILE *f; + struct wordlist *addrs = NULL, *opts = NULL; + char passwd[256], user[256]; + char secret[MAXWORDLEN]; + static int attempts = 0; + + /* + * Make copies of apasswd and auser, then null-terminate them. + * If there are unprintable characters in the password, make + * them visible. + */ + slprintf(ppp_settings.passwd, sizeof(ppp_settings.passwd), "%.*v", passwdlen, apasswd); + slprintf(ppp_settings.user, sizeof(ppp_settings.user), "%.*v", userlen, auser); + *msg = ""; + + /* + * Check if a plugin wants to handle this. + */ + if (pap_auth_hook) { + ret = (*pap_auth_hook)(ppp_settings.user, ppp_settings.passwd, msg, &addrs, &opts); + if (ret >= 0) { + /* note: set_allowed_addrs() saves opts (but not addrs): + don't free it! */ + if (ret) + set_allowed_addrs(unit, addrs, opts); + else if (opts != 0) + free_wordlist(opts); + if (addrs != 0) + free_wordlist(addrs); + BZERO(ppp_settings.passwd, sizeof(ppp_settings.passwd)); + return ret? UPAP_AUTHACK: UPAP_AUTHNAK; + } + } + + /* + * Open the file of pap secrets and scan for a suitable secret + * for authenticating this user. + */ + filename = _PATH_UPAPFILE; + addrs = opts = NULL; + ret = UPAP_AUTHNAK; + f = fopen(filename, "r"); + if (f == NULL) { + ppp_error("Can't open PAP password file %s: %m", filename); + + } else { + check_access(f, filename); + if (scan_authfile(f, ppp_settings.user, our_name, secret, &addrs, &opts, filename, 0) < 0) { + ppp_warn("no PAP secret found for %s", user); + } else { + /* + * If the secret is "@login", it means to check + * the password against the login database. + */ + int login_secret = strcmp(secret, "@login") == 0; + ret = UPAP_AUTHACK; + if (uselogin || login_secret) { + /* login option or secret is @login */ + if (session_full(ppp_settings.user, ppp_settings.passwd, devnam, msg) == 0) { + ret = UPAP_AUTHNAK; + } + } else if (session_mgmt) { + if (session_check(ppp_settings.user, NULL, devnam, NULL) == 0) { + ppp_warn("Peer %q failed PAP Session verification", user); + ret = UPAP_AUTHNAK; + } + } + if (secret[0] != 0 && !login_secret) { + /* password given in pap-secrets - must match */ + if ((cryptpap || strcmp(ppp_settings.passwd, secret) != 0) + && strcmp(crypt(ppp_settings.passwd, secret), secret) != 0) + ret = UPAP_AUTHNAK; + } + } + fclose(f); + } + + if (ret == UPAP_AUTHNAK) { + if (**msg == 0) + *msg = "Login incorrect"; + /* + * XXX can we ever get here more than once?? + * Frustrate passwd stealer programs. + * Allow 10 tries, but start backing off after 3 (stolen from login). + * On 10'th, drop the connection. + */ + if (attempts++ >= 10) { + ppp_warn("%d LOGIN FAILURES ON %s, %s", attempts, devnam, user); + lcp_close(pcb, "login failed"); + } + if (attempts > 3) + sleep((u_int) (attempts - 3) * 5); + if (opts != NULL) + free_wordlist(opts); + + } else { + attempts = 0; /* Reset count */ + if (**msg == 0) + *msg = "Login ok"; + set_allowed_addrs(unit, addrs, opts); + } + + if (addrs != NULL) + free_wordlist(addrs); + BZERO(ppp_settings.passwd, sizeof(ppp_settings.passwd)); + BZERO(secret, sizeof(secret)); + + return ret; +} + +/* + * null_login - Check if a username of "" and a password of "" are + * acceptable, and iff so, set the list of acceptable IP addresses + * and return 1. + */ +static int +null_login(unit) + int unit; +{ + char *filename; + FILE *f; + int i, ret; + struct wordlist *addrs, *opts; + char secret[MAXWORDLEN]; + + /* + * Check if a plugin wants to handle this. + */ + ret = -1; + if (null_auth_hook) + ret = (*null_auth_hook)(&addrs, &opts); + + /* + * Open the file of pap secrets and scan for a suitable secret. + */ + if (ret <= 0) { + filename = _PATH_UPAPFILE; + addrs = NULL; + f = fopen(filename, "r"); + if (f == NULL) + return 0; + check_access(f, filename); + + i = scan_authfile(f, "", our_name, secret, &addrs, &opts, filename, 0); + ret = i >= 0 && secret[0] == 0; + BZERO(secret, sizeof(secret)); + fclose(f); + } + + if (ret) + set_allowed_addrs(unit, addrs, opts); + else if (opts != 0) + free_wordlist(opts); + if (addrs != 0) + free_wordlist(addrs); + + return ret; +} + +/* + * get_pap_passwd - get a password for authenticating ourselves with + * our peer using PAP. Returns 1 on success, 0 if no suitable password + * could be found. + * Assumes passwd points to MAXSECRETLEN bytes of space (if non-null). + */ +static int +get_pap_passwd(passwd) + char *passwd; +{ + char *filename; + FILE *f; + int ret; + char secret[MAXWORDLEN]; + + /* + * Check whether a plugin wants to supply this. + */ + if (pap_passwd_hook) { + ret = (*pap_passwd_hook)(ppp_settings,user, ppp_settings.passwd); + if (ret >= 0) + return ret; + } + + filename = _PATH_UPAPFILE; + f = fopen(filename, "r"); + if (f == NULL) + return 0; + check_access(f, filename); + ret = scan_authfile(f, user, + (remote_name[0]? remote_name: NULL), + secret, NULL, NULL, filename, 0); + fclose(f); + if (ret < 0) + return 0; + if (passwd != NULL) + strlcpy(passwd, secret, MAXSECRETLEN); + BZERO(secret, sizeof(secret)); + return 1; +} + +/* + * have_pap_secret - check whether we have a PAP file with any + * secrets that we could possibly use for authenticating the peer. + */ +static int +have_pap_secret(lacks_ipp) + int *lacks_ipp; +{ + FILE *f; + int ret; + char *filename; + struct wordlist *addrs; + + /* let the plugin decide, if there is one */ + if (pap_check_hook) { + ret = (*pap_check_hook)(); + if (ret >= 0) + return ret; + } + + filename = _PATH_UPAPFILE; + f = fopen(filename, "r"); + if (f == NULL) + return 0; + + ret = scan_authfile(f, (explicit_remote? remote_name: NULL), our_name, + NULL, &addrs, NULL, filename, 0); + fclose(f); + if (ret >= 0 && !some_ip_ok(addrs)) { + if (lacks_ipp != 0) + *lacks_ipp = 1; + ret = -1; + } + if (addrs != 0) + free_wordlist(addrs); + + return ret >= 0; +} + +/* + * have_chap_secret - check whether we have a CHAP file with a + * secret that we could possibly use for authenticating `client' + * on `server'. Either can be the null string, meaning we don't + * know the identity yet. + */ +static int +have_chap_secret(client, server, need_ip, lacks_ipp) + char *client; + char *server; + int need_ip; + int *lacks_ipp; +{ + FILE *f; + int ret; + char *filename; + struct wordlist *addrs; + + if (chap_check_hook) { + ret = (*chap_check_hook)(); + if (ret >= 0) { + return ret; + } + } + + filename = _PATH_CHAPFILE; + f = fopen(filename, "r"); + if (f == NULL) + return 0; + + if (client != NULL && client[0] == 0) + client = NULL; + else if (server != NULL && server[0] == 0) + server = NULL; + + ret = scan_authfile(f, client, server, NULL, &addrs, NULL, filename, 0); + fclose(f); + if (ret >= 0 && need_ip && !some_ip_ok(addrs)) { + if (lacks_ipp != 0) + *lacks_ipp = 1; + ret = -1; + } + if (addrs != 0) + free_wordlist(addrs); + + return ret >= 0; +} + +/* + * have_srp_secret - check whether we have a SRP file with a + * secret that we could possibly use for authenticating `client' + * on `server'. Either can be the null string, meaning we don't + * know the identity yet. + */ +static int +have_srp_secret(client, server, need_ip, lacks_ipp) + char *client; + char *server; + int need_ip; + int *lacks_ipp; +{ + FILE *f; + int ret; + char *filename; + struct wordlist *addrs; + + filename = _PATH_SRPFILE; + f = fopen(filename, "r"); + if (f == NULL) + return 0; + + if (client != NULL && client[0] == 0) + client = NULL; + else if (server != NULL && server[0] == 0) + server = NULL; + + ret = scan_authfile(f, client, server, NULL, &addrs, NULL, filename, 0); + fclose(f); + if (ret >= 0 && need_ip && !some_ip_ok(addrs)) { + if (lacks_ipp != 0) + *lacks_ipp = 1; + ret = -1; + } + if (addrs != 0) + free_wordlist(addrs); + + return ret >= 0; +} +#endif /* UNUSED */ + +#if PPP_AUTH_SUPPORT +/* + * get_secret - open the CHAP secret file and return the secret + * for authenticating the given client on the given server. + * (We could be either client or server). + */ +int get_secret(ppp_pcb *pcb, const char *client, const char *server, char *secret, int *secret_len, int am_server) { + int len; + LWIP_UNUSED_ARG(server); + LWIP_UNUSED_ARG(am_server); + + if (!client || !client[0] || !pcb->settings.user || !pcb->settings.passwd || strcmp(client, pcb->settings.user)) { + return 0; + } + + len = (int)strlen(pcb->settings.passwd); + if (len > MAXSECRETLEN) { + ppp_error("Secret for %s on %s is too long", client, server); + len = MAXSECRETLEN; + } + + MEMCPY(secret, pcb->settings.passwd, len); + *secret_len = len; + return 1; + +#if 0 /* UNUSED */ + FILE *f; + int ret, len; + char *filename; + struct wordlist *addrs, *opts; + char secbuf[MAXWORDLEN]; + struct wordlist *addrs; + addrs = NULL; + + if (!am_server && ppp_settings.passwd[0] != 0) { + strlcpy(secbuf, ppp_settings.passwd, sizeof(secbuf)); + } else if (!am_server && chap_passwd_hook) { + if ( (*chap_passwd_hook)(client, secbuf) < 0) { + ppp_error("Unable to obtain CHAP password for %s on %s from plugin", + client, server); + return 0; + } + } else { + filename = _PATH_CHAPFILE; + addrs = NULL; + secbuf[0] = 0; + + f = fopen(filename, "r"); + if (f == NULL) { + ppp_error("Can't open chap secret file %s: %m", filename); + return 0; + } + check_access(f, filename); + + ret = scan_authfile(f, client, server, secbuf, &addrs, &opts, filename, 0); + fclose(f); + if (ret < 0) + return 0; + + if (am_server) + set_allowed_addrs(unit, addrs, opts); + else if (opts != 0) + free_wordlist(opts); + if (addrs != 0) + free_wordlist(addrs); + } + + len = strlen(secbuf); + if (len > MAXSECRETLEN) { + ppp_error("Secret for %s on %s is too long", client, server); + len = MAXSECRETLEN; + } + MEMCPY(secret, secbuf, len); + BZERO(secbuf, sizeof(secbuf)); + *secret_len = len; + + return 1; +#endif /* UNUSED */ +} +#endif /* PPP_AUTH_SUPPORT */ + + +#if 0 /* UNUSED */ +/* + * get_srp_secret - open the SRP secret file and return the secret + * for authenticating the given client on the given server. + * (We could be either client or server). + */ +int +get_srp_secret(unit, client, server, secret, am_server) + int unit; + char *client; + char *server; + char *secret; + int am_server; +{ + FILE *fp; + int ret; + char *filename; + struct wordlist *addrs, *opts; + + if (!am_server && ppp_settings.passwd[0] != '\0') { + strlcpy(secret, ppp_settings.passwd, MAXWORDLEN); + } else { + filename = _PATH_SRPFILE; + addrs = NULL; + + fp = fopen(filename, "r"); + if (fp == NULL) { + ppp_error("Can't open srp secret file %s: %m", filename); + return 0; + } + check_access(fp, filename); + + secret[0] = '\0'; + ret = scan_authfile(fp, client, server, secret, &addrs, &opts, + filename, am_server); + fclose(fp); + if (ret < 0) + return 0; + + if (am_server) + set_allowed_addrs(unit, addrs, opts); + else if (opts != NULL) + free_wordlist(opts); + if (addrs != NULL) + free_wordlist(addrs); + } + + return 1; +} + +/* + * set_allowed_addrs() - set the list of allowed addresses. + * Also looks for `--' indicating options to apply for this peer + * and leaves the following words in extra_options. + */ +static void +set_allowed_addrs(unit, addrs, opts) + int unit; + struct wordlist *addrs; + struct wordlist *opts; +{ + int n; + struct wordlist *ap, **plink; + struct permitted_ip *ip; + char *ptr_word, *ptr_mask; + struct hostent *hp; + struct netent *np; + u32_t a, mask, ah, offset; + struct ipcp_options *wo = &ipcp_wantoptions[unit]; + u32_t suggested_ip = 0; + + if (addresses[unit] != NULL) + free(addresses[unit]); + addresses[unit] = NULL; + if (extra_options != NULL) + free_wordlist(extra_options); + extra_options = opts; + + /* + * Count the number of IP addresses given. + */ + n = wordlist_count(addrs) + wordlist_count(noauth_addrs); + if (n == 0) + return; + ip = (struct permitted_ip *) malloc((n + 1) * sizeof(struct permitted_ip)); + if (ip == 0) + return; + + /* temporarily append the noauth_addrs list to addrs */ + for (plink = &addrs; *plink != NULL; plink = &(*plink)->next) + ; + *plink = noauth_addrs; + + n = 0; + for (ap = addrs; ap != NULL; ap = ap->next) { + /* "-" means no addresses authorized, "*" means any address allowed */ + ptr_word = ap->word; + if (strcmp(ptr_word, "-") == 0) + break; + if (strcmp(ptr_word, "*") == 0) { + ip[n].permit = 1; + ip[n].base = ip[n].mask = 0; + ++n; + break; + } + + ip[n].permit = 1; + if (*ptr_word == '!') { + ip[n].permit = 0; + ++ptr_word; + } + + mask = ~ (u32_t) 0; + offset = 0; + ptr_mask = strchr (ptr_word, '/'); + if (ptr_mask != NULL) { + int bit_count; + char *endp; + + bit_count = (int) strtol (ptr_mask+1, &endp, 10); + if (bit_count <= 0 || bit_count > 32) { + ppp_warn("invalid address length %v in auth. address list", + ptr_mask+1); + continue; + } + bit_count = 32 - bit_count; /* # bits in host part */ + if (*endp == '+') { + offset = ifunit + 1; + ++endp; + } + if (*endp != 0) { + ppp_warn("invalid address length syntax: %v", ptr_mask+1); + continue; + } + *ptr_mask = '\0'; + mask <<= bit_count; + } + + hp = gethostbyname(ptr_word); + if (hp != NULL && hp->h_addrtype == AF_INET) { + a = *(u32_t *)hp->h_addr; + } else { + np = getnetbyname (ptr_word); + if (np != NULL && np->n_addrtype == AF_INET) { + a = htonl ((u32_t)np->n_net); + if (ptr_mask == NULL) { + /* calculate appropriate mask for net */ + ah = ntohl(a); + if (IN_CLASSA(ah)) + mask = IN_CLASSA_NET; + else if (IN_CLASSB(ah)) + mask = IN_CLASSB_NET; + else if (IN_CLASSC(ah)) + mask = IN_CLASSC_NET; + } + } else { + a = inet_addr (ptr_word); + } + } + + if (ptr_mask != NULL) + *ptr_mask = '/'; + + if (a == (u32_t)-1L) { + ppp_warn("unknown host %s in auth. address list", ap->word); + continue; + } + if (offset != 0) { + if (offset >= ~mask) { + ppp_warn("interface unit %d too large for subnet %v", + ifunit, ptr_word); + continue; + } + a = htonl((ntohl(a) & mask) + offset); + mask = ~(u32_t)0; + } + ip[n].mask = htonl(mask); + ip[n].base = a & ip[n].mask; + ++n; + if (~mask == 0 && suggested_ip == 0) + suggested_ip = a; + } + *plink = NULL; + + ip[n].permit = 0; /* make the last entry forbid all addresses */ + ip[n].base = 0; /* to terminate the list */ + ip[n].mask = 0; + + addresses[unit] = ip; + + /* + * If the address given for the peer isn't authorized, or if + * the user hasn't given one, AND there is an authorized address + * which is a single host, then use that if we find one. + */ + if (suggested_ip != 0 + && (wo->hisaddr == 0 || !auth_ip_addr(unit, wo->hisaddr))) { + wo->hisaddr = suggested_ip; + /* + * Do we insist on this address? No, if there are other + * addresses authorized than the suggested one. + */ + if (n > 1) + wo->accept_remote = 1; + } +} + +/* + * auth_ip_addr - check whether the peer is authorized to use + * a given IP address. Returns 1 if authorized, 0 otherwise. + */ +int +auth_ip_addr(unit, addr) + int unit; + u32_t addr; +{ + int ok; + + /* don't allow loopback or multicast address */ + if (bad_ip_adrs(addr)) + return 0; + + if (allowed_address_hook) { + ok = allowed_address_hook(addr); + if (ok >= 0) return ok; + } + + if (addresses[unit] != NULL) { + ok = ip_addr_check(addr, addresses[unit]); + if (ok >= 0) + return ok; + } + + if (auth_required) + return 0; /* no addresses authorized */ + return allow_any_ip || privileged || !have_route_to(addr); +} + +static int +ip_addr_check(addr, addrs) + u32_t addr; + struct permitted_ip *addrs; +{ + for (; ; ++addrs) + if ((addr & addrs->mask) == addrs->base) + return addrs->permit; +} + +/* + * bad_ip_adrs - return 1 if the IP address is one we don't want + * to use, such as an address in the loopback net or a multicast address. + * addr is in network byte order. + */ +int +bad_ip_adrs(addr) + u32_t addr; +{ + addr = ntohl(addr); + return (addr >> IN_CLASSA_NSHIFT) == IN_LOOPBACKNET + || IN_MULTICAST(addr) || IN_BADCLASS(addr); +} + +/* + * some_ip_ok - check a wordlist to see if it authorizes any + * IP address(es). + */ +static int +some_ip_ok(addrs) + struct wordlist *addrs; +{ + for (; addrs != 0; addrs = addrs->next) { + if (addrs->word[0] == '-') + break; + if (addrs->word[0] != '!') + return 1; /* some IP address is allowed */ + } + return 0; +} + +/* + * auth_number - check whether the remote number is allowed to connect. + * Returns 1 if authorized, 0 otherwise. + */ +int +auth_number() +{ + struct wordlist *wp = permitted_numbers; + int l; + + /* Allow all if no authorization list. */ + if (!wp) + return 1; + + /* Allow if we have a match in the authorization list. */ + while (wp) { + /* trailing '*' wildcard */ + l = strlen(wp->word); + if ((wp->word)[l - 1] == '*') + l--; + if (!strncasecmp(wp->word, remote_number, l)) + return 1; + wp = wp->next; + } + + return 0; +} + +/* + * check_access - complain if a secret file has too-liberal permissions. + */ +static void +check_access(f, filename) + FILE *f; + char *filename; +{ + struct stat sbuf; + + if (fstat(fileno(f), &sbuf) < 0) { + ppp_warn("cannot stat secret file %s: %m", filename); + } else if ((sbuf.st_mode & (S_IRWXG | S_IRWXO)) != 0) { + ppp_warn("Warning - secret file %s has world and/or group access", + filename); + } +} + +/* + * scan_authfile - Scan an authorization file for a secret suitable + * for authenticating `client' on `server'. The return value is -1 + * if no secret is found, otherwise >= 0. The return value has + * NONWILD_CLIENT set if the secret didn't have "*" for the client, and + * NONWILD_SERVER set if the secret didn't have "*" for the server. + * Any following words on the line up to a "--" (i.e. address authorization + * info) are placed in a wordlist and returned in *addrs. Any + * following words (extra options) are placed in a wordlist and + * returned in *opts. + * We assume secret is NULL or points to MAXWORDLEN bytes of space. + * Flags are non-zero if we need two colons in the secret in order to + * match. + */ +static int +scan_authfile(f, client, server, secret, addrs, opts, filename, flags) + FILE *f; + char *client; + char *server; + char *secret; + struct wordlist **addrs; + struct wordlist **opts; + char *filename; + int flags; +{ + int newline, xxx; + int got_flag, best_flag; + FILE *sf; + struct wordlist *ap, *addr_list, *alist, **app; + char word[MAXWORDLEN]; + char atfile[MAXWORDLEN]; + char lsecret[MAXWORDLEN]; + char *cp; + + if (addrs != NULL) + *addrs = NULL; + if (opts != NULL) + *opts = NULL; + addr_list = NULL; + if (!getword(f, word, &newline, filename)) + return -1; /* file is empty??? */ + newline = 1; + best_flag = -1; + for (;;) { + /* + * Skip until we find a word at the start of a line. + */ + while (!newline && getword(f, word, &newline, filename)) + ; + if (!newline) + break; /* got to end of file */ + + /* + * Got a client - check if it's a match or a wildcard. + */ + got_flag = 0; + if (client != NULL && strcmp(word, client) != 0 && !ISWILD(word)) { + newline = 0; + continue; + } + if (!ISWILD(word)) + got_flag = NONWILD_CLIENT; + + /* + * Now get a server and check if it matches. + */ + if (!getword(f, word, &newline, filename)) + break; + if (newline) + continue; + if (!ISWILD(word)) { + if (server != NULL && strcmp(word, server) != 0) + continue; + got_flag |= NONWILD_SERVER; + } + + /* + * Got some sort of a match - see if it's better than what + * we have already. + */ + if (got_flag <= best_flag) + continue; + + /* + * Get the secret. + */ + if (!getword(f, word, &newline, filename)) + break; + if (newline) + continue; + + /* + * SRP-SHA1 authenticator should never be reading secrets from + * a file. (Authenticatee may, though.) + */ + if (flags && ((cp = strchr(word, ':')) == NULL || + strchr(cp + 1, ':') == NULL)) + continue; + + if (secret != NULL) { + /* + * Special syntax: @/pathname means read secret from file. + */ + if (word[0] == '@' && word[1] == '/') { + strlcpy(atfile, word+1, sizeof(atfile)); + if ((sf = fopen(atfile, "r")) == NULL) { + ppp_warn("can't open indirect secret file %s", atfile); + continue; + } + check_access(sf, atfile); + if (!getword(sf, word, &xxx, atfile)) { + ppp_warn("no secret in indirect secret file %s", atfile); + fclose(sf); + continue; + } + fclose(sf); + } + strlcpy(lsecret, word, sizeof(lsecret)); + } + + /* + * Now read address authorization info and make a wordlist. + */ + app = &alist; + for (;;) { + if (!getword(f, word, &newline, filename) || newline) + break; + ap = (struct wordlist *) + malloc(sizeof(struct wordlist) + strlen(word) + 1); + if (ap == NULL) + novm("authorized addresses"); + ap->word = (char *) (ap + 1); + strcpy(ap->word, word); + *app = ap; + app = &ap->next; + } + *app = NULL; + + /* + * This is the best so far; remember it. + */ + best_flag = got_flag; + if (addr_list) + free_wordlist(addr_list); + addr_list = alist; + if (secret != NULL) + strlcpy(secret, lsecret, MAXWORDLEN); + + if (!newline) + break; + } + + /* scan for a -- word indicating the start of options */ + for (app = &addr_list; (ap = *app) != NULL; app = &ap->next) + if (strcmp(ap->word, "--") == 0) + break; + /* ap = start of options */ + if (ap != NULL) { + ap = ap->next; /* first option */ + free(*app); /* free the "--" word */ + *app = NULL; /* terminate addr list */ + } + if (opts != NULL) + *opts = ap; + else if (ap != NULL) + free_wordlist(ap); + if (addrs != NULL) + *addrs = addr_list; + else if (addr_list != NULL) + free_wordlist(addr_list); + + return best_flag; +} + +/* + * wordlist_count - return the number of items in a wordlist + */ +static int +wordlist_count(wp) + struct wordlist *wp; +{ + int n; + + for (n = 0; wp != NULL; wp = wp->next) + ++n; + return n; +} + +/* + * free_wordlist - release memory allocated for a wordlist. + */ +static void +free_wordlist(wp) + struct wordlist *wp; +{ + struct wordlist *next; + + while (wp != NULL) { + next = wp->next; + free(wp); + wp = next; + } +} +#endif /* UNUSED */ + +#endif /* PPP_SUPPORT */ diff --git a/components/lwip/netif/ppp/ccp.c b/components/lwip/netif/ppp/ccp.c new file mode 100755 index 0000000000..873cd68a41 --- /dev/null +++ b/components/lwip/netif/ppp/ccp.c @@ -0,0 +1,1741 @@ +/* + * ccp.c - PPP Compression Control Protocol. + * + * Copyright (c) 1994-2002 Paul Mackerras. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. The name(s) of the authors of this software must not be used to + * endorse or promote products derived from this software without + * prior written permission. + * + * 3. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by Paul Mackerras + * ". + * + * THE AUTHORS OF THIS SOFTWARE DISCLAIM ALL WARRANTIES WITH REGARD TO + * THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS, IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY + * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN + * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING + * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include "lwip/opt.h" +#if PPP_SUPPORT && CCP_SUPPORT /* don't build if not configured for use in lwipopts.h */ + +#include +#include + +#include "netif/ppp/ppp_impl.h" + +#include "netif/ppp/fsm.h" +#include "netif/ppp/ccp.h" + +#if MPPE_SUPPORT +#include "netif/ppp/lcp.h" /* lcp_close(), lcp_fsm */ +#include "netif/ppp/mppe.h" /* mppe_init() */ +#endif /* MPPE_SUPPORT */ + +/* + * Unfortunately there is a bug in zlib which means that using a + * size of 8 (window size = 256) for Deflate compression will cause + * buffer overruns and kernel crashes in the deflate module. + * Until this is fixed we only accept sizes in the range 9 .. 15. + * Thanks to James Carlson for pointing this out. + */ +#define DEFLATE_MIN_WORKS 9 + +/* + * Command-line options. + */ +#if PPP_OPTIONS +static int setbsdcomp (char **); +static int setdeflate (char **); +static char bsd_value[8]; +static char deflate_value[8]; + +/* + * Option variables. + */ +#if MPPE_SUPPORT +bool refuse_mppe_stateful = 1; /* Allow stateful mode? */ +#endif /* MPPE_SUPPORT */ + +static option_t ccp_option_list[] = { + { "noccp", o_bool, &ccp_protent.enabled_flag, + "Disable CCP negotiation" }, + { "-ccp", o_bool, &ccp_protent.enabled_flag, + "Disable CCP negotiation", OPT_ALIAS }, + + { "bsdcomp", o_special, (void *)setbsdcomp, + "Request BSD-Compress packet compression", + OPT_PRIO | OPT_A2STRVAL | OPT_STATIC, bsd_value }, + { "nobsdcomp", o_bool, &ccp_wantoptions[0].bsd_compress, + "don't allow BSD-Compress", OPT_PRIOSUB | OPT_A2CLR, + &ccp_allowoptions[0].bsd_compress }, + { "-bsdcomp", o_bool, &ccp_wantoptions[0].bsd_compress, + "don't allow BSD-Compress", OPT_ALIAS | OPT_PRIOSUB | OPT_A2CLR, + &ccp_allowoptions[0].bsd_compress }, + + { "deflate", o_special, (void *)setdeflate, + "request Deflate compression", + OPT_PRIO | OPT_A2STRVAL | OPT_STATIC, deflate_value }, + { "nodeflate", o_bool, &ccp_wantoptions[0].deflate, + "don't allow Deflate compression", OPT_PRIOSUB | OPT_A2CLR, + &ccp_allowoptions[0].deflate }, + { "-deflate", o_bool, &ccp_wantoptions[0].deflate, + "don't allow Deflate compression", OPT_ALIAS | OPT_PRIOSUB | OPT_A2CLR, + &ccp_allowoptions[0].deflate }, + + { "nodeflatedraft", o_bool, &ccp_wantoptions[0].deflate_draft, + "don't use draft deflate #", OPT_A2COPY, + &ccp_allowoptions[0].deflate_draft }, + + { "predictor1", o_bool, &ccp_wantoptions[0].predictor_1, + "request Predictor-1", OPT_PRIO | 1 }, + { "nopredictor1", o_bool, &ccp_wantoptions[0].predictor_1, + "don't allow Predictor-1", OPT_PRIOSUB | OPT_A2CLR, + &ccp_allowoptions[0].predictor_1 }, + { "-predictor1", o_bool, &ccp_wantoptions[0].predictor_1, + "don't allow Predictor-1", OPT_ALIAS | OPT_PRIOSUB | OPT_A2CLR, + &ccp_allowoptions[0].predictor_1 }, + +#if MPPE_SUPPORT + /* MPPE options are symmetrical ... we only set wantoptions here */ + { "require-mppe", o_bool, &ccp_wantoptions[0].mppe, + "require MPPE encryption", + OPT_PRIO | MPPE_OPT_40 | MPPE_OPT_128 }, + { "+mppe", o_bool, &ccp_wantoptions[0].mppe, + "require MPPE encryption", + OPT_ALIAS | OPT_PRIO | MPPE_OPT_40 | MPPE_OPT_128 }, + { "nomppe", o_bool, &ccp_wantoptions[0].mppe, + "don't allow MPPE encryption", OPT_PRIO }, + { "-mppe", o_bool, &ccp_wantoptions[0].mppe, + "don't allow MPPE encryption", OPT_ALIAS | OPT_PRIO }, + + /* We use ccp_allowoptions[0].mppe as a junk var ... it is reset later */ + { "require-mppe-40", o_bool, &ccp_allowoptions[0].mppe, + "require MPPE 40-bit encryption", OPT_PRIO | OPT_A2OR | MPPE_OPT_40, + &ccp_wantoptions[0].mppe }, + { "+mppe-40", o_bool, &ccp_allowoptions[0].mppe, + "require MPPE 40-bit encryption", OPT_PRIO | OPT_A2OR | MPPE_OPT_40, + &ccp_wantoptions[0].mppe }, + { "nomppe-40", o_bool, &ccp_allowoptions[0].mppe, + "don't allow MPPE 40-bit encryption", + OPT_PRIOSUB | OPT_A2CLRB | MPPE_OPT_40, &ccp_wantoptions[0].mppe }, + { "-mppe-40", o_bool, &ccp_allowoptions[0].mppe, + "don't allow MPPE 40-bit encryption", + OPT_ALIAS | OPT_PRIOSUB | OPT_A2CLRB | MPPE_OPT_40, + &ccp_wantoptions[0].mppe }, + + { "require-mppe-128", o_bool, &ccp_allowoptions[0].mppe, + "require MPPE 128-bit encryption", OPT_PRIO | OPT_A2OR | MPPE_OPT_128, + &ccp_wantoptions[0].mppe }, + { "+mppe-128", o_bool, &ccp_allowoptions[0].mppe, + "require MPPE 128-bit encryption", + OPT_ALIAS | OPT_PRIO | OPT_A2OR | MPPE_OPT_128, + &ccp_wantoptions[0].mppe }, + { "nomppe-128", o_bool, &ccp_allowoptions[0].mppe, + "don't allow MPPE 128-bit encryption", + OPT_PRIOSUB | OPT_A2CLRB | MPPE_OPT_128, &ccp_wantoptions[0].mppe }, + { "-mppe-128", o_bool, &ccp_allowoptions[0].mppe, + "don't allow MPPE 128-bit encryption", + OPT_ALIAS | OPT_PRIOSUB | OPT_A2CLRB | MPPE_OPT_128, + &ccp_wantoptions[0].mppe }, + + /* strange one; we always request stateless, but will we allow stateful? */ + { "mppe-stateful", o_bool, &refuse_mppe_stateful, + "allow MPPE stateful mode", OPT_PRIO }, + { "nomppe-stateful", o_bool, &refuse_mppe_stateful, + "disallow MPPE stateful mode", OPT_PRIO | 1 }, +#endif /* MPPE_SUPPORT */ + + { NULL } +}; +#endif /* PPP_OPTIONS */ + +/* + * Protocol entry points from main code. + */ +static void ccp_init(ppp_pcb *pcb); +static void ccp_open(ppp_pcb *pcb); +static void ccp_close(ppp_pcb *pcb, const char *reason); +static void ccp_lowerup(ppp_pcb *pcb); +static void ccp_lowerdown(ppp_pcb *pcb); +static void ccp_input(ppp_pcb *pcb, u_char *pkt, int len); +static void ccp_protrej(ppp_pcb *pcb); +#if PRINTPKT_SUPPORT +static int ccp_printpkt(const u_char *p, int plen, void (*printer) (void *, const char *, ...), void *arg); +#endif /* PRINTPKT_SUPPORT */ +#if PPP_DATAINPUT +static void ccp_datainput(ppp_pcb *pcb, u_char *pkt, int len); +#endif /* PPP_DATAINPUT */ + +const struct protent ccp_protent = { + PPP_CCP, + ccp_init, + ccp_input, + ccp_protrej, + ccp_lowerup, + ccp_lowerdown, + ccp_open, + ccp_close, +#if PRINTPKT_SUPPORT + ccp_printpkt, +#endif /* PRINTPKT_SUPPORT */ +#if PPP_DATAINPUT + ccp_datainput, +#endif /* PPP_DATAINPUT */ +#if PRINTPKT_SUPPORT + "CCP", + "Compressed", +#endif /* PRINTPKT_SUPPORT */ +#if PPP_OPTIONS + ccp_option_list, + NULL, +#endif /* PPP_OPTIONS */ +#if DEMAND_SUPPORT + NULL, + NULL +#endif /* DEMAND_SUPPORT */ +}; + +/* + * Callbacks for fsm code. + */ +static void ccp_resetci (fsm *); +static int ccp_cilen (fsm *); +static void ccp_addci (fsm *, u_char *, int *); +static int ccp_ackci (fsm *, u_char *, int); +static int ccp_nakci (fsm *, u_char *, int, int); +static int ccp_rejci (fsm *, u_char *, int); +static int ccp_reqci (fsm *, u_char *, int *, int); +static void ccp_up (fsm *); +static void ccp_down (fsm *); +static int ccp_extcode (fsm *, int, int, u_char *, int); +static void ccp_rack_timeout (void *); +static const char *method_name (ccp_options *, ccp_options *); + +static const fsm_callbacks ccp_callbacks = { + ccp_resetci, + ccp_cilen, + ccp_addci, + ccp_ackci, + ccp_nakci, + ccp_rejci, + ccp_reqci, + ccp_up, + ccp_down, + NULL, + NULL, + NULL, + NULL, + ccp_extcode, + "CCP" +}; + +/* + * Do we want / did we get any compression? + */ +static int ccp_anycompress(ccp_options *opt) { + return (0 +#if DEFLATE_SUPPORT + || (opt)->deflate +#endif /* DEFLATE_SUPPORT */ +#if BSDCOMPRESS_SUPPORT + || (opt)->bsd_compress +#endif /* BSDCOMPRESS_SUPPORT */ +#if PREDICTOR_SUPPORT + || (opt)->predictor_1 || (opt)->predictor_2 +#endif /* PREDICTOR_SUPPORT */ +#if MPPE_SUPPORT + || (opt)->mppe +#endif /* MPPE_SUPPORT */ + ); +} + +/* + * Local state (mainly for handling reset-reqs and reset-acks). + */ +#define RACK_PENDING 1 /* waiting for reset-ack */ +#define RREQ_REPEAT 2 /* send another reset-req if no reset-ack */ + +#define RACKTIMEOUT 1 /* second */ + +#if PPP_OPTIONS +/* + * Option parsing + */ +static int +setbsdcomp(argv) + char **argv; +{ + int rbits, abits; + char *str, *endp; + + str = *argv; + abits = rbits = strtol(str, &endp, 0); + if (endp != str && *endp == ',') { + str = endp + 1; + abits = strtol(str, &endp, 0); + } + if (*endp != 0 || endp == str) { + option_error("invalid parameter '%s' for bsdcomp option", *argv); + return 0; + } + if ((rbits != 0 && (rbits < BSD_MIN_BITS || rbits > BSD_MAX_BITS)) + || (abits != 0 && (abits < BSD_MIN_BITS || abits > BSD_MAX_BITS))) { + option_error("bsdcomp option values must be 0 or %d .. %d", + BSD_MIN_BITS, BSD_MAX_BITS); + return 0; + } + if (rbits > 0) { + ccp_wantoptions[0].bsd_compress = 1; + ccp_wantoptions[0].bsd_bits = rbits; + } else + ccp_wantoptions[0].bsd_compress = 0; + if (abits > 0) { + ccp_allowoptions[0].bsd_compress = 1; + ccp_allowoptions[0].bsd_bits = abits; + } else + ccp_allowoptions[0].bsd_compress = 0; + ppp_slprintf(bsd_value, sizeof(bsd_value), + rbits == abits? "%d": "%d,%d", rbits, abits); + + return 1; +} + +static int +setdeflate(argv) + char **argv; +{ + int rbits, abits; + char *str, *endp; + + str = *argv; + abits = rbits = strtol(str, &endp, 0); + if (endp != str && *endp == ',') { + str = endp + 1; + abits = strtol(str, &endp, 0); + } + if (*endp != 0 || endp == str) { + option_error("invalid parameter '%s' for deflate option", *argv); + return 0; + } + if ((rbits != 0 && (rbits < DEFLATE_MIN_SIZE || rbits > DEFLATE_MAX_SIZE)) + || (abits != 0 && (abits < DEFLATE_MIN_SIZE + || abits > DEFLATE_MAX_SIZE))) { + option_error("deflate option values must be 0 or %d .. %d", + DEFLATE_MIN_SIZE, DEFLATE_MAX_SIZE); + return 0; + } + if (rbits == DEFLATE_MIN_SIZE || abits == DEFLATE_MIN_SIZE) { + if (rbits == DEFLATE_MIN_SIZE) + rbits = DEFLATE_MIN_WORKS; + if (abits == DEFLATE_MIN_SIZE) + abits = DEFLATE_MIN_WORKS; + warn("deflate option value of %d changed to %d to avoid zlib bug", + DEFLATE_MIN_SIZE, DEFLATE_MIN_WORKS); + } + if (rbits > 0) { + ccp_wantoptions[0].deflate = 1; + ccp_wantoptions[0].deflate_size = rbits; + } else + ccp_wantoptions[0].deflate = 0; + if (abits > 0) { + ccp_allowoptions[0].deflate = 1; + ccp_allowoptions[0].deflate_size = abits; + } else + ccp_allowoptions[0].deflate = 0; + ppp_slprintf(deflate_value, sizeof(deflate_value), + rbits == abits? "%d": "%d,%d", rbits, abits); + + return 1; +} +#endif /* PPP_OPTIONS */ + +/* + * ccp_init - initialize CCP. + */ +static void ccp_init(ppp_pcb *pcb) { + fsm *f = &pcb->ccp_fsm; + ccp_options *wo = &pcb->ccp_wantoptions; + ccp_options *ao = &pcb->ccp_allowoptions; + + f->pcb = pcb; + f->protocol = PPP_CCP; + f->callbacks = &ccp_callbacks; + fsm_init(f); + +#if 0 /* Not necessary, everything is cleared in ppp_clear() */ + memset(wo, 0, sizeof(*wo)); + memset(go, 0, sizeof(*go)); + memset(ao, 0, sizeof(*ao)); + memset(ho, 0, sizeof(*ho)); +#endif /* 0 */ + +#if DEFLATE_SUPPORT + wo->deflate = 1; + wo->deflate_size = DEFLATE_MAX_SIZE; + wo->deflate_correct = 1; + wo->deflate_draft = 1; + ao->deflate = 1; + ao->deflate_size = DEFLATE_MAX_SIZE; + ao->deflate_correct = 1; + ao->deflate_draft = 1; +#endif /* DEFLATE_SUPPORT */ + +#if BSDCOMPRESS_SUPPORT + wo->bsd_compress = 1; + wo->bsd_bits = BSD_MAX_BITS; + ao->bsd_compress = 1; + ao->bsd_bits = BSD_MAX_BITS; +#endif /* BSDCOMPRESS_SUPPORT */ + +#if PREDICTOR_SUPPORT + ao->predictor_1 = 1; +#endif /* PREDICTOR_SUPPORT */ + +#if MPPE_SUPPORT + if (pcb->settings.require_mppe) { + wo->mppe = ao->mppe = + (pcb->settings.refuse_mppe_40 ? 0 : MPPE_OPT_40) + | (pcb->settings.refuse_mppe_128 ? 0 : MPPE_OPT_128); + } +#endif /* MPPE_SUPPORT */ +} + +/* + * ccp_open - CCP is allowed to come up. + */ +static void ccp_open(ppp_pcb *pcb) { + fsm *f = &pcb->ccp_fsm; + ccp_options *go = &pcb->ccp_gotoptions; + + if (f->state != PPP_FSM_OPENED) + ccp_set(pcb, 1, 0, 0, 0); + + /* + * Find out which compressors the kernel supports before + * deciding whether to open in silent mode. + */ + ccp_resetci(f); + if (!ccp_anycompress(go)) + f->flags |= OPT_SILENT; + + fsm_open(f); +} + +/* + * ccp_close - Terminate CCP. + */ +static void ccp_close(ppp_pcb *pcb, const char *reason) { + fsm *f = &pcb->ccp_fsm; + ccp_set(pcb, 0, 0, 0, 0); + fsm_close(f, reason); +} + +/* + * ccp_lowerup - we may now transmit CCP packets. + */ +static void ccp_lowerup(ppp_pcb *pcb) { + fsm *f = &pcb->ccp_fsm; + fsm_lowerup(f); +} + +/* + * ccp_lowerdown - we may not transmit CCP packets. + */ +static void ccp_lowerdown(ppp_pcb *pcb) { + fsm *f = &pcb->ccp_fsm; + fsm_lowerdown(f); +} + +/* + * ccp_input - process a received CCP packet. + */ +static void ccp_input(ppp_pcb *pcb, u_char *p, int len) { + fsm *f = &pcb->ccp_fsm; + ccp_options *go = &pcb->ccp_gotoptions; + int oldstate; + + /* + * Check for a terminate-request so we can print a message. + */ + oldstate = f->state; + fsm_input(f, p, len); + if (oldstate == PPP_FSM_OPENED && p[0] == TERMREQ && f->state != PPP_FSM_OPENED) { + ppp_notice("Compression disabled by peer."); +#if MPPE_SUPPORT + if (go->mppe) { + ppp_error("MPPE disabled, closing LCP"); + lcp_close(pcb, "MPPE disabled by peer"); + } +#endif /* MPPE_SUPPORT */ + } + + /* + * If we get a terminate-ack and we're not asking for compression, + * close CCP. + */ + if (oldstate == PPP_FSM_REQSENT && p[0] == TERMACK + && !ccp_anycompress(go)) + ccp_close(pcb, "No compression negotiated"); +} + +/* + * Handle a CCP-specific code. + */ +static int ccp_extcode(fsm *f, int code, int id, u_char *p, int len) { + ppp_pcb *pcb = f->pcb; + LWIP_UNUSED_ARG(p); + LWIP_UNUSED_ARG(len); + + switch (code) { + case CCP_RESETREQ: + if (f->state != PPP_FSM_OPENED) + break; + ccp_reset_comp(pcb); + /* send a reset-ack, which the transmitter will see and + reset its compression state. */ + fsm_sdata(f, CCP_RESETACK, id, NULL, 0); + break; + + case CCP_RESETACK: + if ((pcb->ccp_localstate & RACK_PENDING) && id == f->reqid) { + pcb->ccp_localstate &= ~(RACK_PENDING | RREQ_REPEAT); + UNTIMEOUT(ccp_rack_timeout, f); + ccp_reset_decomp(pcb); + } + break; + + default: + return 0; + } + + return 1; +} + +/* + * ccp_protrej - peer doesn't talk CCP. + */ +static void ccp_protrej(ppp_pcb *pcb) { + fsm *f = &pcb->ccp_fsm; +#if MPPE_SUPPORT + ccp_options *go = &pcb->ccp_gotoptions; +#endif /* MPPE_SUPPORT */ + + ccp_set(pcb, 0, 0, 0, 0); + fsm_lowerdown(f); + +#if MPPE_SUPPORT + if (go->mppe) { + ppp_error("MPPE required but peer negotiation failed"); + lcp_close(pcb, "MPPE required but peer negotiation failed"); + } +#endif /* MPPE_SUPPORT */ + +} + +/* + * ccp_resetci - initialize at start of negotiation. + */ +static void ccp_resetci(fsm *f) { + ppp_pcb *pcb = f->pcb; + ccp_options *go = &pcb->ccp_gotoptions; + ccp_options *wo = &pcb->ccp_wantoptions; +#if DEFLATE_SUPPORT || BSDCOMPRESS_SUPPORT || PREDICTOR_SUPPORT + u_char opt_buf[CCP_MAX_OPTION_LENGTH]; +#endif /* DEFLATE_SUPPORT || BSDCOMPRESS_SUPPORT || PREDICTOR_SUPPORT */ +#if DEFLATE_SUPPORT || BSDCOMPRESS_SUPPORT + int res; +#endif /* DEFLATE_SUPPORT || BSDCOMPRESS_SUPPORT */ + + *go = *wo; + pcb->ccp_all_rejected = 0; + +#if MPPE_SUPPORT + if (go->mppe) { + ccp_options *ao = &pcb->ccp_allowoptions; + int auth_mschap_bits = pcb->auth_done; + int numbits; + + /* + * Start with a basic sanity check: mschap[v2] auth must be in + * exactly one direction. RFC 3079 says that the keys are + * 'derived from the credentials of the peer that initiated the call', + * however the PPP protocol doesn't have such a concept, and pppd + * cannot get this info externally. Instead we do the best we can. + * NB: If MPPE is required, all other compression opts are invalid. + * So, we return right away if we can't do it. + */ + + /* Leave only the mschap auth bits set */ + auth_mschap_bits &= (CHAP_MS_WITHPEER | CHAP_MS_PEER | + CHAP_MS2_WITHPEER | CHAP_MS2_PEER); + /* Count the mschap auths */ + auth_mschap_bits >>= CHAP_MS_SHIFT; + numbits = 0; + do { + numbits += auth_mschap_bits & 1; + auth_mschap_bits >>= 1; + } while (auth_mschap_bits); + if (numbits > 1) { + ppp_error("MPPE required, but auth done in both directions."); + lcp_close(pcb, "MPPE required but not available"); + return; + } + if (!numbits) { + ppp_error("MPPE required, but MS-CHAP[v2] auth not performed."); + lcp_close(pcb, "MPPE required but not available"); + return; + } + + /* A plugin (eg radius) may not have obtained key material. */ + if (!pcb->mppe_keys_set) { + ppp_error("MPPE required, but keys are not available. " + "Possible plugin problem?"); + lcp_close(pcb, "MPPE required but not available"); + return; + } + + /* LM auth not supported for MPPE */ + if (pcb->auth_done & (CHAP_MS_WITHPEER | CHAP_MS_PEER)) { + /* This might be noise */ + if (go->mppe & MPPE_OPT_40) { + ppp_notice("Disabling 40-bit MPPE; MS-CHAP LM not supported"); + go->mppe &= ~MPPE_OPT_40; + wo->mppe &= ~MPPE_OPT_40; + } + } + + /* Last check: can we actually negotiate something? */ + if (!(go->mppe & (MPPE_OPT_40 | MPPE_OPT_128))) { + /* Could be misconfig, could be 40-bit disabled above. */ + ppp_error("MPPE required, but both 40-bit and 128-bit disabled."); + lcp_close(pcb, "MPPE required but not available"); + return; + } + + /* sync options */ + ao->mppe = go->mppe; + /* MPPE is not compatible with other compression types */ +#if BSDCOMPRESS_SUPPORT + ao->bsd_compress = go->bsd_compress = 0; +#endif /* BSDCOMPRESS_SUPPORT */ +#if PREDICTOR_SUPPORT + ao->predictor_1 = go->predictor_1 = 0; + ao->predictor_2 = go->predictor_2 = 0; +#endif /* PREDICTOR_SUPPORT */ +#if DEFLATE_SUPPORT + ao->deflate = go->deflate = 0; +#endif /* DEFLATE_SUPPORT */ + } +#endif /* MPPE_SUPPORT */ + + /* + * Check whether the kernel knows about the various + * compression methods we might request. + */ +#if BSDCOMPRESS_SUPPORT + /* FIXME: we don't need to test if BSD compress is available + * if BSDCOMPRESS_SUPPORT is set, it is. + */ + if (go->bsd_compress) { + opt_buf[0] = CI_BSD_COMPRESS; + opt_buf[1] = CILEN_BSD_COMPRESS; + for (;;) { + if (go->bsd_bits < BSD_MIN_BITS) { + go->bsd_compress = 0; + break; + } + opt_buf[2] = BSD_MAKE_OPT(BSD_CURRENT_VERSION, go->bsd_bits); + res = ccp_test(pcb, opt_buf, CILEN_BSD_COMPRESS, 0); + if (res > 0) { + break; + } else if (res < 0) { + go->bsd_compress = 0; + break; + } + go->bsd_bits--; + } + } +#endif /* BSDCOMPRESS_SUPPORT */ +#if DEFLATE_SUPPORT + /* FIXME: we don't need to test if deflate is available + * if DEFLATE_SUPPORT is set, it is. + */ + if (go->deflate) { + if (go->deflate_correct) { + opt_buf[0] = CI_DEFLATE; + opt_buf[1] = CILEN_DEFLATE; + opt_buf[3] = DEFLATE_CHK_SEQUENCE; + for (;;) { + if (go->deflate_size < DEFLATE_MIN_WORKS) { + go->deflate_correct = 0; + break; + } + opt_buf[2] = DEFLATE_MAKE_OPT(go->deflate_size); + res = ccp_test(pcb, opt_buf, CILEN_DEFLATE, 0); + if (res > 0) { + break; + } else if (res < 0) { + go->deflate_correct = 0; + break; + } + go->deflate_size--; + } + } + if (go->deflate_draft) { + opt_buf[0] = CI_DEFLATE_DRAFT; + opt_buf[1] = CILEN_DEFLATE; + opt_buf[3] = DEFLATE_CHK_SEQUENCE; + for (;;) { + if (go->deflate_size < DEFLATE_MIN_WORKS) { + go->deflate_draft = 0; + break; + } + opt_buf[2] = DEFLATE_MAKE_OPT(go->deflate_size); + res = ccp_test(pcb, opt_buf, CILEN_DEFLATE, 0); + if (res > 0) { + break; + } else if (res < 0) { + go->deflate_draft = 0; + break; + } + go->deflate_size--; + } + } + if (!go->deflate_correct && !go->deflate_draft) + go->deflate = 0; + } +#endif /* DEFLATE_SUPPORT */ +#if PREDICTOR_SUPPORT + /* FIXME: we don't need to test if predictor is available, + * if PREDICTOR_SUPPORT is set, it is. + */ + if (go->predictor_1) { + opt_buf[0] = CI_PREDICTOR_1; + opt_buf[1] = CILEN_PREDICTOR_1; + if (ccp_test(pcb, opt_buf, CILEN_PREDICTOR_1, 0) <= 0) + go->predictor_1 = 0; + } + if (go->predictor_2) { + opt_buf[0] = CI_PREDICTOR_2; + opt_buf[1] = CILEN_PREDICTOR_2; + if (ccp_test(pcb, opt_buf, CILEN_PREDICTOR_2, 0) <= 0) + go->predictor_2 = 0; + } +#endif /* PREDICTOR_SUPPORT */ +} + +/* + * ccp_cilen - Return total length of our configuration info. + */ +static int ccp_cilen(fsm *f) { + ppp_pcb *pcb = f->pcb; + ccp_options *go = &pcb->ccp_gotoptions; + + return 0 +#if BSDCOMPRESS_SUPPORT + + (go->bsd_compress? CILEN_BSD_COMPRESS: 0) +#endif /* BSDCOMPRESS_SUPPORT */ +#if DEFLATE_SUPPORT + + (go->deflate && go->deflate_correct? CILEN_DEFLATE: 0) + + (go->deflate && go->deflate_draft? CILEN_DEFLATE: 0) +#endif /* DEFLATE_SUPPORT */ +#if PREDICTOR_SUPPORT + + (go->predictor_1? CILEN_PREDICTOR_1: 0) + + (go->predictor_2? CILEN_PREDICTOR_2: 0) +#endif /* PREDICTOR_SUPPORT */ +#if MPPE_SUPPORT + + (go->mppe? CILEN_MPPE: 0) +#endif /* MPPE_SUPPORT */ + ; +} + +/* + * ccp_addci - put our requests in a packet. + */ +static void ccp_addci(fsm *f, u_char *p, int *lenp) { + ppp_pcb *pcb = f->pcb; + ccp_options *go = &pcb->ccp_gotoptions; + u_char *p0 = p; + + /* + * Add the compression types that we can receive, in decreasing + * preference order. + */ +#if MPPE_SUPPORT + if (go->mppe) { + p[0] = CI_MPPE; + p[1] = CILEN_MPPE; + MPPE_OPTS_TO_CI(go->mppe, &p[2]); + mppe_init(pcb, &pcb->mppe_decomp, go->mppe); + p += CILEN_MPPE; + } +#endif /* MPPE_SUPPORT */ +#if DEFLATE_SUPPORT + if (go->deflate) { + if (go->deflate_correct) { + p[0] = CI_DEFLATE; + p[1] = CILEN_DEFLATE; + p[2] = DEFLATE_MAKE_OPT(go->deflate_size); + p[3] = DEFLATE_CHK_SEQUENCE; + p += CILEN_DEFLATE; + } + if (go->deflate_draft) { + p[0] = CI_DEFLATE_DRAFT; + p[1] = CILEN_DEFLATE; + p[2] = p[2 - CILEN_DEFLATE]; + p[3] = DEFLATE_CHK_SEQUENCE; + p += CILEN_DEFLATE; + } + } +#endif /* DEFLATE_SUPPORT */ +#if BSDCOMPRESS_SUPPORT + if (go->bsd_compress) { + p[0] = CI_BSD_COMPRESS; + p[1] = CILEN_BSD_COMPRESS; + p[2] = BSD_MAKE_OPT(BSD_CURRENT_VERSION, go->bsd_bits); + p += CILEN_BSD_COMPRESS; + } +#endif /* BSDCOMPRESS_SUPPORT */ +#if PREDICTOR_SUPPORT + /* XXX Should Predictor 2 be preferable to Predictor 1? */ + if (go->predictor_1) { + p[0] = CI_PREDICTOR_1; + p[1] = CILEN_PREDICTOR_1; + p += CILEN_PREDICTOR_1; + } + if (go->predictor_2) { + p[0] = CI_PREDICTOR_2; + p[1] = CILEN_PREDICTOR_2; + p += CILEN_PREDICTOR_2; + } +#endif /* PREDICTOR_SUPPORT */ + + go->method = (p > p0)? p0[0]: 0; + + *lenp = p - p0; +} + +/* + * ccp_ackci - process a received configure-ack, and return + * 1 iff the packet was OK. + */ +static int ccp_ackci(fsm *f, u_char *p, int len) { + ppp_pcb *pcb = f->pcb; + ccp_options *go = &pcb->ccp_gotoptions; +#if BSDCOMPRESS_SUPPORT || PREDICTOR_SUPPORT + u_char *p0 = p; +#endif /* BSDCOMPRESS_SUPPORT || PREDICTOR_SUPPORT */ + +#if MPPE_SUPPORT + if (go->mppe) { + u_char opt_buf[CILEN_MPPE]; + + opt_buf[0] = CI_MPPE; + opt_buf[1] = CILEN_MPPE; + MPPE_OPTS_TO_CI(go->mppe, &opt_buf[2]); + if (len < CILEN_MPPE || memcmp(opt_buf, p, CILEN_MPPE)) + return 0; + p += CILEN_MPPE; + len -= CILEN_MPPE; + /* XXX Cope with first/fast ack */ + if (len == 0) + return 1; + } +#endif /* MPPE_SUPPORT */ +#if DEFLATE_SUPPORT + if (go->deflate) { + if (len < CILEN_DEFLATE + || p[0] != (go->deflate_correct? CI_DEFLATE: CI_DEFLATE_DRAFT) + || p[1] != CILEN_DEFLATE + || p[2] != DEFLATE_MAKE_OPT(go->deflate_size) + || p[3] != DEFLATE_CHK_SEQUENCE) + return 0; + p += CILEN_DEFLATE; + len -= CILEN_DEFLATE; + /* XXX Cope with first/fast ack */ + if (len == 0) + return 1; + if (go->deflate_correct && go->deflate_draft) { + if (len < CILEN_DEFLATE + || p[0] != CI_DEFLATE_DRAFT + || p[1] != CILEN_DEFLATE + || p[2] != DEFLATE_MAKE_OPT(go->deflate_size) + || p[3] != DEFLATE_CHK_SEQUENCE) + return 0; + p += CILEN_DEFLATE; + len -= CILEN_DEFLATE; + } + } +#endif /* DEFLATE_SUPPORT */ +#if BSDCOMPRESS_SUPPORT + if (go->bsd_compress) { + if (len < CILEN_BSD_COMPRESS + || p[0] != CI_BSD_COMPRESS || p[1] != CILEN_BSD_COMPRESS + || p[2] != BSD_MAKE_OPT(BSD_CURRENT_VERSION, go->bsd_bits)) + return 0; + p += CILEN_BSD_COMPRESS; + len -= CILEN_BSD_COMPRESS; + /* XXX Cope with first/fast ack */ + if (p == p0 && len == 0) + return 1; + } +#endif /* BSDCOMPRESS_SUPPORT */ +#if PREDICTOR_SUPPORT + if (go->predictor_1) { + if (len < CILEN_PREDICTOR_1 + || p[0] != CI_PREDICTOR_1 || p[1] != CILEN_PREDICTOR_1) + return 0; + p += CILEN_PREDICTOR_1; + len -= CILEN_PREDICTOR_1; + /* XXX Cope with first/fast ack */ + if (p == p0 && len == 0) + return 1; + } + if (go->predictor_2) { + if (len < CILEN_PREDICTOR_2 + || p[0] != CI_PREDICTOR_2 || p[1] != CILEN_PREDICTOR_2) + return 0; + p += CILEN_PREDICTOR_2; + len -= CILEN_PREDICTOR_2; + /* XXX Cope with first/fast ack */ + if (p == p0 && len == 0) + return 1; + } +#endif /* PREDICTOR_SUPPORT */ + + if (len != 0) + return 0; + return 1; +} + +/* + * ccp_nakci - process received configure-nak. + * Returns 1 iff the nak was OK. + */ +static int ccp_nakci(fsm *f, u_char *p, int len, int treat_as_reject) { + ppp_pcb *pcb = f->pcb; + ccp_options *go = &pcb->ccp_gotoptions; + ccp_options no; /* options we've seen already */ + ccp_options try_; /* options to ask for next time */ + LWIP_UNUSED_ARG(treat_as_reject); +#if !MPPE_SUPPORT && !DEFLATE_SUPPORT && !BSDCOMPRESS_SUPPORT + LWIP_UNUSED_ARG(p); + LWIP_UNUSED_ARG(len); +#endif /* !MPPE_SUPPORT && !DEFLATE_SUPPORT && !BSDCOMPRESS_SUPPORT */ + + memset(&no, 0, sizeof(no)); + try_ = *go; + +#if MPPE_SUPPORT + if (go->mppe && len >= CILEN_MPPE + && p[0] == CI_MPPE && p[1] == CILEN_MPPE) { + no.mppe = 1; + /* + * Peer wants us to use a different strength or other setting. + * Fail if we aren't willing to use his suggestion. + */ + MPPE_CI_TO_OPTS(&p[2], try_.mppe); + if ((try_.mppe & MPPE_OPT_STATEFUL) && pcb->settings.refuse_mppe_stateful) { + ppp_error("Refusing MPPE stateful mode offered by peer"); + try_.mppe = 0; + } else if (((go->mppe | MPPE_OPT_STATEFUL) & try_.mppe) != try_.mppe) { + /* Peer must have set options we didn't request (suggest) */ + try_.mppe = 0; + } + + if (!try_.mppe) { + ppp_error("MPPE required but peer negotiation failed"); + lcp_close(pcb, "MPPE required but peer negotiation failed"); + } + } +#endif /* MPPE_SUPPORT */ +#if DEFLATE_SUPPORT + if (go->deflate && len >= CILEN_DEFLATE + && p[0] == (go->deflate_correct? CI_DEFLATE: CI_DEFLATE_DRAFT) + && p[1] == CILEN_DEFLATE) { + no.deflate = 1; + /* + * Peer wants us to use a different code size or something. + * Stop asking for Deflate if we don't understand his suggestion. + */ + if (DEFLATE_METHOD(p[2]) != DEFLATE_METHOD_VAL + || DEFLATE_SIZE(p[2]) < DEFLATE_MIN_WORKS + || p[3] != DEFLATE_CHK_SEQUENCE) + try_.deflate = 0; + else if (DEFLATE_SIZE(p[2]) < go->deflate_size) + try_.deflate_size = DEFLATE_SIZE(p[2]); + p += CILEN_DEFLATE; + len -= CILEN_DEFLATE; + if (go->deflate_correct && go->deflate_draft + && len >= CILEN_DEFLATE && p[0] == CI_DEFLATE_DRAFT + && p[1] == CILEN_DEFLATE) { + p += CILEN_DEFLATE; + len -= CILEN_DEFLATE; + } + } +#endif /* DEFLATE_SUPPORT */ +#if BSDCOMPRESS_SUPPORT + if (go->bsd_compress && len >= CILEN_BSD_COMPRESS + && p[0] == CI_BSD_COMPRESS && p[1] == CILEN_BSD_COMPRESS) { + no.bsd_compress = 1; + /* + * Peer wants us to use a different number of bits + * or a different version. + */ + if (BSD_VERSION(p[2]) != BSD_CURRENT_VERSION) + try_.bsd_compress = 0; + else if (BSD_NBITS(p[2]) < go->bsd_bits) + try_.bsd_bits = BSD_NBITS(p[2]); + p += CILEN_BSD_COMPRESS; + len -= CILEN_BSD_COMPRESS; + } +#endif /* BSDCOMPRESS_SUPPORT */ + + /* + * Predictor-1 and 2 have no options, so they can't be Naked. + * + * There may be remaining options but we ignore them. + */ + + if (f->state != PPP_FSM_OPENED) + *go = try_; + return 1; +} + +/* + * ccp_rejci - reject some of our suggested compression methods. + */ +static int ccp_rejci(fsm *f, u_char *p, int len) { + ppp_pcb *pcb = f->pcb; + ccp_options *go = &pcb->ccp_gotoptions; + ccp_options try_; /* options to request next time */ + + try_ = *go; + + /* + * Cope with empty configure-rejects by ceasing to send + * configure-requests. + */ + if (len == 0 && pcb->ccp_all_rejected) + return -1; + +#if MPPE_SUPPORT + if (go->mppe && len >= CILEN_MPPE + && p[0] == CI_MPPE && p[1] == CILEN_MPPE) { + ppp_error("MPPE required but peer refused"); + lcp_close(pcb, "MPPE required but peer refused"); + p += CILEN_MPPE; + len -= CILEN_MPPE; + } +#endif /* MPPE_SUPPORT */ +#if DEFLATE_SUPPORT + if (go->deflate_correct && len >= CILEN_DEFLATE + && p[0] == CI_DEFLATE && p[1] == CILEN_DEFLATE) { + if (p[2] != DEFLATE_MAKE_OPT(go->deflate_size) + || p[3] != DEFLATE_CHK_SEQUENCE) + return 0; /* Rej is bad */ + try_.deflate_correct = 0; + p += CILEN_DEFLATE; + len -= CILEN_DEFLATE; + } + if (go->deflate_draft && len >= CILEN_DEFLATE + && p[0] == CI_DEFLATE_DRAFT && p[1] == CILEN_DEFLATE) { + if (p[2] != DEFLATE_MAKE_OPT(go->deflate_size) + || p[3] != DEFLATE_CHK_SEQUENCE) + return 0; /* Rej is bad */ + try_.deflate_draft = 0; + p += CILEN_DEFLATE; + len -= CILEN_DEFLATE; + } + if (!try_.deflate_correct && !try_.deflate_draft) + try_.deflate = 0; +#endif /* DEFLATE_SUPPORT */ +#if BSDCOMPRESS_SUPPORT + if (go->bsd_compress && len >= CILEN_BSD_COMPRESS + && p[0] == CI_BSD_COMPRESS && p[1] == CILEN_BSD_COMPRESS) { + if (p[2] != BSD_MAKE_OPT(BSD_CURRENT_VERSION, go->bsd_bits)) + return 0; + try_.bsd_compress = 0; + p += CILEN_BSD_COMPRESS; + len -= CILEN_BSD_COMPRESS; + } +#endif /* BSDCOMPRESS_SUPPORT */ +#if PREDICTOR_SUPPORT + if (go->predictor_1 && len >= CILEN_PREDICTOR_1 + && p[0] == CI_PREDICTOR_1 && p[1] == CILEN_PREDICTOR_1) { + try_.predictor_1 = 0; + p += CILEN_PREDICTOR_1; + len -= CILEN_PREDICTOR_1; + } + if (go->predictor_2 && len >= CILEN_PREDICTOR_2 + && p[0] == CI_PREDICTOR_2 && p[1] == CILEN_PREDICTOR_2) { + try_.predictor_2 = 0; + p += CILEN_PREDICTOR_2; + len -= CILEN_PREDICTOR_2; + } +#endif /* PREDICTOR_SUPPORT */ + + if (len != 0) + return 0; + + if (f->state != PPP_FSM_OPENED) + *go = try_; + + return 1; +} + +/* + * ccp_reqci - processed a received configure-request. + * Returns CONFACK, CONFNAK or CONFREJ and the packet modified + * appropriately. + */ +static int ccp_reqci(fsm *f, u_char *p, int *lenp, int dont_nak) { + ppp_pcb *pcb = f->pcb; + ccp_options *ho = &pcb->ccp_hisoptions; + ccp_options *ao = &pcb->ccp_allowoptions; + int ret, newret; +#if DEFLATE_SUPPORT || BSDCOMPRESS_SUPPORT + int res; + int nb; +#endif /* DEFLATE_SUPPORT || BSDCOMPRESS_SUPPORT */ + u_char *p0, *retp; + int len, clen, type; +#if MPPE_SUPPORT + u8_t rej_for_ci_mppe = 1; /* Are we rejecting based on a bad/missing */ + /* CI_MPPE, or due to other options? */ +#endif /* MPPE_SUPPORT */ + + ret = CONFACK; + retp = p0 = p; + len = *lenp; + + memset(ho, 0, sizeof(ccp_options)); + ho->method = (len > 0)? p[0]: 0; + + while (len > 0) { + newret = CONFACK; + if (len < 2 || p[1] < 2 || p[1] > len) { + /* length is bad */ + clen = len; + newret = CONFREJ; + + } else { + type = p[0]; + clen = p[1]; + + switch (type) { +#if MPPE_SUPPORT + case CI_MPPE: + if (!ao->mppe || clen != CILEN_MPPE) { + newret = CONFREJ; + break; + } + MPPE_CI_TO_OPTS(&p[2], ho->mppe); + + /* Nak if anything unsupported or unknown are set. */ + if (ho->mppe & MPPE_OPT_UNSUPPORTED) { + newret = CONFNAK; + ho->mppe &= ~MPPE_OPT_UNSUPPORTED; + } + if (ho->mppe & MPPE_OPT_UNKNOWN) { + newret = CONFNAK; + ho->mppe &= ~MPPE_OPT_UNKNOWN; + } + + /* Check state opt */ + if (ho->mppe & MPPE_OPT_STATEFUL) { + /* + * We can Nak and request stateless, but it's a + * lot easier to just assume the peer will request + * it if he can do it; stateful mode is bad over + * the Internet -- which is where we expect MPPE. + */ + if (pcb->settings.refuse_mppe_stateful) { + ppp_error("Refusing MPPE stateful mode offered by peer"); + newret = CONFREJ; + break; + } + } + + /* Find out which of {S,L} are set. */ + if ((ho->mppe & MPPE_OPT_128) + && (ho->mppe & MPPE_OPT_40)) { + /* Both are set, negotiate the strongest. */ + newret = CONFNAK; + if (ao->mppe & MPPE_OPT_128) + ho->mppe &= ~MPPE_OPT_40; + else if (ao->mppe & MPPE_OPT_40) + ho->mppe &= ~MPPE_OPT_128; + else { + newret = CONFREJ; + break; + } + } else if (ho->mppe & MPPE_OPT_128) { + if (!(ao->mppe & MPPE_OPT_128)) { + newret = CONFREJ; + break; + } + } else if (ho->mppe & MPPE_OPT_40) { + if (!(ao->mppe & MPPE_OPT_40)) { + newret = CONFREJ; + break; + } + } else { + /* Neither are set. */ + /* We cannot accept this. */ + newret = CONFNAK; + /* Give the peer our idea of what can be used, + so it can choose and confirm */ + ho->mppe = ao->mppe; + } + + /* rebuild the opts */ + MPPE_OPTS_TO_CI(ho->mppe, &p[2]); + if (newret == CONFACK) { + int mtu; + + mppe_init(pcb, &pcb->mppe_comp, ho->mppe); + /* + * We need to decrease the interface MTU by MPPE_PAD + * because MPPE frames **grow**. The kernel [must] + * allocate MPPE_PAD extra bytes in xmit buffers. + */ + mtu = netif_get_mtu(pcb); + if (mtu) + netif_set_mtu(pcb, mtu - MPPE_PAD); + else + newret = CONFREJ; + } + + /* + * We have accepted MPPE or are willing to negotiate + * MPPE parameters. A CONFREJ is due to subsequent + * (non-MPPE) processing. + */ + rej_for_ci_mppe = 0; + break; +#endif /* MPPE_SUPPORT */ +#if DEFLATE_SUPPORT + case CI_DEFLATE: + case CI_DEFLATE_DRAFT: + if (!ao->deflate || clen != CILEN_DEFLATE + || (!ao->deflate_correct && type == CI_DEFLATE) + || (!ao->deflate_draft && type == CI_DEFLATE_DRAFT)) { + newret = CONFREJ; + break; + } + + ho->deflate = 1; + ho->deflate_size = nb = DEFLATE_SIZE(p[2]); + if (DEFLATE_METHOD(p[2]) != DEFLATE_METHOD_VAL + || p[3] != DEFLATE_CHK_SEQUENCE + || nb > ao->deflate_size || nb < DEFLATE_MIN_WORKS) { + newret = CONFNAK; + if (!dont_nak) { + p[2] = DEFLATE_MAKE_OPT(ao->deflate_size); + p[3] = DEFLATE_CHK_SEQUENCE; + /* fall through to test this #bits below */ + } else + break; + } + + /* + * Check whether we can do Deflate with the window + * size they want. If the window is too big, reduce + * it until the kernel can cope and nak with that. + * We only check this for the first option. + */ + if (p == p0) { + for (;;) { + res = ccp_test(pcb, p, CILEN_DEFLATE, 1); + if (res > 0) + break; /* it's OK now */ + if (res < 0 || nb == DEFLATE_MIN_WORKS || dont_nak) { + newret = CONFREJ; + p[2] = DEFLATE_MAKE_OPT(ho->deflate_size); + break; + } + newret = CONFNAK; + --nb; + p[2] = DEFLATE_MAKE_OPT(nb); + } + } + break; +#endif /* DEFLATE_SUPPORT */ +#if BSDCOMPRESS_SUPPORT + case CI_BSD_COMPRESS: + if (!ao->bsd_compress || clen != CILEN_BSD_COMPRESS) { + newret = CONFREJ; + break; + } + + ho->bsd_compress = 1; + ho->bsd_bits = nb = BSD_NBITS(p[2]); + if (BSD_VERSION(p[2]) != BSD_CURRENT_VERSION + || nb > ao->bsd_bits || nb < BSD_MIN_BITS) { + newret = CONFNAK; + if (!dont_nak) { + p[2] = BSD_MAKE_OPT(BSD_CURRENT_VERSION, ao->bsd_bits); + /* fall through to test this #bits below */ + } else + break; + } + + /* + * Check whether we can do BSD-Compress with the code + * size they want. If the code size is too big, reduce + * it until the kernel can cope and nak with that. + * We only check this for the first option. + */ + if (p == p0) { + for (;;) { + res = ccp_test(pcb, p, CILEN_BSD_COMPRESS, 1); + if (res > 0) + break; + if (res < 0 || nb == BSD_MIN_BITS || dont_nak) { + newret = CONFREJ; + p[2] = BSD_MAKE_OPT(BSD_CURRENT_VERSION, + ho->bsd_bits); + break; + } + newret = CONFNAK; + --nb; + p[2] = BSD_MAKE_OPT(BSD_CURRENT_VERSION, nb); + } + } + break; +#endif /* BSDCOMPRESS_SUPPORT */ +#if PREDICTOR_SUPPORT + case CI_PREDICTOR_1: + if (!ao->predictor_1 || clen != CILEN_PREDICTOR_1) { + newret = CONFREJ; + break; + } + + ho->predictor_1 = 1; + if (p == p0 + && ccp_test(pcb, p, CILEN_PREDICTOR_1, 1) <= 0) { + newret = CONFREJ; + } + break; + + case CI_PREDICTOR_2: + if (!ao->predictor_2 || clen != CILEN_PREDICTOR_2) { + newret = CONFREJ; + break; + } + + ho->predictor_2 = 1; + if (p == p0 + && ccp_test(pcb, p, CILEN_PREDICTOR_2, 1) <= 0) { + newret = CONFREJ; + } + break; +#endif /* PREDICTOR_SUPPORT */ + + default: + newret = CONFREJ; + } + } + + if (newret == CONFNAK && dont_nak) + newret = CONFREJ; + if (!(newret == CONFACK || (newret == CONFNAK && ret == CONFREJ))) { + /* we're returning this option */ + if (newret == CONFREJ && ret == CONFNAK) + retp = p0; + ret = newret; + if (p != retp) + MEMCPY(retp, p, clen); + retp += clen; + } + + p += clen; + len -= clen; + } + + if (ret != CONFACK) { + if (ret == CONFREJ && *lenp == retp - p0) + pcb->ccp_all_rejected = 1; + else + *lenp = retp - p0; + } +#if MPPE_SUPPORT + if (ret == CONFREJ && ao->mppe && rej_for_ci_mppe) { + ppp_error("MPPE required but peer negotiation failed"); + lcp_close(pcb, "MPPE required but peer negotiation failed"); + } +#endif /* MPPE_SUPPORT */ + return ret; +} + +/* + * Make a string name for a compression method (or 2). + */ +static const char *method_name(ccp_options *opt, ccp_options *opt2) { + static char result[64]; +#if !DEFLATE_SUPPORT && !BSDCOMPRESS_SUPPORT + LWIP_UNUSED_ARG(opt2); +#endif /* !DEFLATE_SUPPORT && !BSDCOMPRESS_SUPPORT */ + + if (!ccp_anycompress(opt)) + return "(none)"; + switch (opt->method) { +#if MPPE_SUPPORT + case CI_MPPE: + { + char *p = result; + char *q = result + sizeof(result); /* 1 past result */ + + ppp_slprintf(p, q - p, "MPPE "); + p += 5; + if (opt->mppe & MPPE_OPT_128) { + ppp_slprintf(p, q - p, "128-bit "); + p += 8; + } + if (opt->mppe & MPPE_OPT_40) { + ppp_slprintf(p, q - p, "40-bit "); + p += 7; + } + if (opt->mppe & MPPE_OPT_STATEFUL) + ppp_slprintf(p, q - p, "stateful"); + else + ppp_slprintf(p, q - p, "stateless"); + + break; + } +#endif /* MPPE_SUPPORT */ +#if DEFLATE_SUPPORT + case CI_DEFLATE: + case CI_DEFLATE_DRAFT: + if (opt2 != NULL && opt2->deflate_size != opt->deflate_size) + ppp_slprintf(result, sizeof(result), "Deflate%s (%d/%d)", + (opt->method == CI_DEFLATE_DRAFT? "(old#)": ""), + opt->deflate_size, opt2->deflate_size); + else + ppp_slprintf(result, sizeof(result), "Deflate%s (%d)", + (opt->method == CI_DEFLATE_DRAFT? "(old#)": ""), + opt->deflate_size); + break; +#endif /* DEFLATE_SUPPORT */ +#if BSDCOMPRESS_SUPPORT + case CI_BSD_COMPRESS: + if (opt2 != NULL && opt2->bsd_bits != opt->bsd_bits) + ppp_slprintf(result, sizeof(result), "BSD-Compress (%d/%d)", + opt->bsd_bits, opt2->bsd_bits); + else + ppp_slprintf(result, sizeof(result), "BSD-Compress (%d)", + opt->bsd_bits); + break; +#endif /* BSDCOMPRESS_SUPPORT */ +#if PREDICTOR_SUPPORT + case CI_PREDICTOR_1: + return "Predictor 1"; + case CI_PREDICTOR_2: + return "Predictor 2"; +#endif /* PREDICTOR_SUPPORT */ + default: + ppp_slprintf(result, sizeof(result), "Method %d", opt->method); + } + return result; +} + +/* + * CCP has come up - inform the kernel driver and log a message. + */ +static void ccp_up(fsm *f) { + ppp_pcb *pcb = f->pcb; + ccp_options *go = &pcb->ccp_gotoptions; + ccp_options *ho = &pcb->ccp_hisoptions; + char method1[64]; + + ccp_set(pcb, 1, 1, go->method, ho->method); + if (ccp_anycompress(go)) { + if (ccp_anycompress(ho)) { + if (go->method == ho->method) { + ppp_notice("%s compression enabled", method_name(go, ho)); + } else { + ppp_strlcpy(method1, method_name(go, NULL), sizeof(method1)); + ppp_notice("%s / %s compression enabled", + method1, method_name(ho, NULL)); + } + } else + ppp_notice("%s receive compression enabled", method_name(go, NULL)); + } else if (ccp_anycompress(ho)) + ppp_notice("%s transmit compression enabled", method_name(ho, NULL)); +#if MPPE_SUPPORT + if (go->mppe) { + continue_networks(pcb); /* Bring up IP et al */ + } +#endif /* MPPE_SUPPORT */ +} + +/* + * CCP has gone down - inform the kernel driver. + */ +static void ccp_down(fsm *f) { + ppp_pcb *pcb = f->pcb; +#if MPPE_SUPPORT + ccp_options *go = &pcb->ccp_gotoptions; +#endif /* MPPE_SUPPORT */ + + if (pcb->ccp_localstate & RACK_PENDING) + UNTIMEOUT(ccp_rack_timeout, f); + pcb->ccp_localstate = 0; + ccp_set(pcb, 1, 0, 0, 0); +#if MPPE_SUPPORT + if (go->mppe) { + go->mppe = 0; + if (pcb->lcp_fsm.state == PPP_FSM_OPENED) { + /* If LCP is not already going down, make sure it does. */ + ppp_error("MPPE disabled"); + lcp_close(pcb, "MPPE disabled"); + } + } +#endif /* MPPE_SUPPORT */ +} + +#if PRINTPKT_SUPPORT +/* + * Print the contents of a CCP packet. + */ +static const char* const ccp_codenames[] = { + "ConfReq", "ConfAck", "ConfNak", "ConfRej", + "TermReq", "TermAck", "CodeRej", + NULL, NULL, NULL, NULL, NULL, NULL, + "ResetReq", "ResetAck", +}; + +static int ccp_printpkt(const u_char *p, int plen, void (*printer) (void *, const char *, ...), void *arg) { + const u_char *p0, *optend; + int code, id, len; + int optlen; + + p0 = p; + if (plen < HEADERLEN) + return 0; + code = p[0]; + id = p[1]; + len = (p[2] << 8) + p[3]; + if (len < HEADERLEN || len > plen) + return 0; + + if (code >= 1 && code <= (int)(sizeof(ccp_codenames) / sizeof(char *)) + && ccp_codenames[code-1] != NULL) + printer(arg, " %s", ccp_codenames[code-1]); + else + printer(arg, " code=0x%x", code); + printer(arg, " id=0x%x", id); + len -= HEADERLEN; + p += HEADERLEN; + + switch (code) { + case CONFREQ: + case CONFACK: + case CONFNAK: + case CONFREJ: + /* print list of possible compression methods */ + while (len >= 2) { + code = p[0]; + optlen = p[1]; + if (optlen < 2 || optlen > len) + break; + printer(arg, " <"); + len -= optlen; + optend = p + optlen; + switch (code) { +#if MPPE_SUPPORT + case CI_MPPE: + if (optlen >= CILEN_MPPE) { + u_char mppe_opts; + + MPPE_CI_TO_OPTS(&p[2], mppe_opts); + printer(arg, "mppe %s %s %s %s %s %s%s", + (p[2] & MPPE_H_BIT)? "+H": "-H", + (p[5] & MPPE_M_BIT)? "+M": "-M", + (p[5] & MPPE_S_BIT)? "+S": "-S", + (p[5] & MPPE_L_BIT)? "+L": "-L", + (p[5] & MPPE_D_BIT)? "+D": "-D", + (p[5] & MPPE_C_BIT)? "+C": "-C", + (mppe_opts & MPPE_OPT_UNKNOWN)? " +U": ""); + if (mppe_opts & MPPE_OPT_UNKNOWN) + printer(arg, " (%.2x %.2x %.2x %.2x)", + p[2], p[3], p[4], p[5]); + p += CILEN_MPPE; + } + break; +#endif /* MPPE_SUPPORT */ +#if DEFLATE_SUPPORT + case CI_DEFLATE: + case CI_DEFLATE_DRAFT: + if (optlen >= CILEN_DEFLATE) { + printer(arg, "deflate%s %d", + (code == CI_DEFLATE_DRAFT? "(old#)": ""), + DEFLATE_SIZE(p[2])); + if (DEFLATE_METHOD(p[2]) != DEFLATE_METHOD_VAL) + printer(arg, " method %d", DEFLATE_METHOD(p[2])); + if (p[3] != DEFLATE_CHK_SEQUENCE) + printer(arg, " check %d", p[3]); + p += CILEN_DEFLATE; + } + break; +#endif /* DEFLATE_SUPPORT */ +#if BSDCOMPRESS_SUPPORT + case CI_BSD_COMPRESS: + if (optlen >= CILEN_BSD_COMPRESS) { + printer(arg, "bsd v%d %d", BSD_VERSION(p[2]), + BSD_NBITS(p[2])); + p += CILEN_BSD_COMPRESS; + } + break; +#endif /* BSDCOMPRESS_SUPPORT */ +#if PREDICTOR_SUPPORT + case CI_PREDICTOR_1: + if (optlen >= CILEN_PREDICTOR_1) { + printer(arg, "predictor 1"); + p += CILEN_PREDICTOR_1; + } + break; + case CI_PREDICTOR_2: + if (optlen >= CILEN_PREDICTOR_2) { + printer(arg, "predictor 2"); + p += CILEN_PREDICTOR_2; + } + break; +#endif /* PREDICTOR_SUPPORT */ + default: + break; + } + while (p < optend) + printer(arg, " %.2x", *p++); + printer(arg, ">"); + } + break; + + case TERMACK: + case TERMREQ: + if (len > 0 && *p >= ' ' && *p < 0x7f) { + ppp_print_string(p, len, printer, arg); + p += len; + len = 0; + } + break; + default: + break; + } + + /* dump out the rest of the packet in hex */ + while (--len >= 0) + printer(arg, " %.2x", *p++); + + return p - p0; +} +#endif /* PRINTPKT_SUPPORT */ + +#if PPP_DATAINPUT +/* + * We have received a packet that the decompressor failed to + * decompress. Here we would expect to issue a reset-request, but + * Motorola has a patent on resetting the compressor as a result of + * detecting an error in the decompressed data after decompression. + * (See US patent 5,130,993; international patent publication number + * WO 91/10289; Australian patent 73296/91.) + * + * So we ask the kernel whether the error was detected after + * decompression; if it was, we take CCP down, thus disabling + * compression :-(, otherwise we issue the reset-request. + */ +static void ccp_datainput(ppp_pcb *pcb, u_char *pkt, int len) { + fsm *f; +#if MPPE_SUPPORT + ccp_options *go = &pcb->ccp_gotoptions; +#endif /* MPPE_SUPPORT */ + LWIP_UNUSED_ARG(pkt); + LWIP_UNUSED_ARG(len); + + f = &pcb->ccp_fsm; + if (f->state == PPP_FSM_OPENED) { + if (ccp_fatal_error(pcb)) { + /* + * Disable compression by taking CCP down. + */ + ppp_error("Lost compression sync: disabling compression"); + ccp_close(pcb, "Lost compression sync"); +#if MPPE_SUPPORT + /* + * If we were doing MPPE, we must also take the link down. + */ + if (go->mppe) { + ppp_error("Too many MPPE errors, closing LCP"); + lcp_close(pcb, "Too many MPPE errors"); + } +#endif /* MPPE_SUPPORT */ + } else { + /* + * Send a reset-request to reset the peer's compressor. + * We don't do that if we are still waiting for an + * acknowledgement to a previous reset-request. + */ + if (!(pcb->ccp_localstate & RACK_PENDING)) { + fsm_sdata(f, CCP_RESETREQ, f->reqid = ++f->id, NULL, 0); + TIMEOUT(ccp_rack_timeout, f, RACKTIMEOUT); + pcb->ccp_localstate |= RACK_PENDING; + } else + pcb->ccp_localstate |= RREQ_REPEAT; + } + } +} +#endif /* PPP_DATAINPUT */ + +/* + * We have received a packet that the decompressor failed to + * decompress. Issue a reset-request. + */ +void ccp_resetrequest(ppp_pcb *pcb) { + fsm *f = &pcb->ccp_fsm; + + if (f->state != PPP_FSM_OPENED) + return; + + /* + * Send a reset-request to reset the peer's compressor. + * We don't do that if we are still waiting for an + * acknowledgement to a previous reset-request. + */ + if (!(pcb->ccp_localstate & RACK_PENDING)) { + fsm_sdata(f, CCP_RESETREQ, f->reqid = ++f->id, NULL, 0); + TIMEOUT(ccp_rack_timeout, f, RACKTIMEOUT); + pcb->ccp_localstate |= RACK_PENDING; + } else + pcb->ccp_localstate |= RREQ_REPEAT; +} + +/* + * Timeout waiting for reset-ack. + */ +static void ccp_rack_timeout(void *arg) { + fsm *f = (fsm*)arg; + ppp_pcb *pcb = f->pcb; + + if (f->state == PPP_FSM_OPENED && (pcb->ccp_localstate & RREQ_REPEAT)) { + fsm_sdata(f, CCP_RESETREQ, f->reqid, NULL, 0); + TIMEOUT(ccp_rack_timeout, f, RACKTIMEOUT); + pcb->ccp_localstate &= ~RREQ_REPEAT; + } else + pcb->ccp_localstate &= ~RACK_PENDING; +} + +#endif /* PPP_SUPPORT && CCP_SUPPORT */ diff --git a/components/lwip/netif/ppp/chap-md5.c b/components/lwip/netif/ppp/chap-md5.c new file mode 100755 index 0000000000..6e3a9d7c21 --- /dev/null +++ b/components/lwip/netif/ppp/chap-md5.c @@ -0,0 +1,127 @@ +/* + * chap-md5.c - New CHAP/MD5 implementation. + * + * Copyright (c) 2003 Paul Mackerras. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. The name(s) of the authors of this software must not be used to + * endorse or promote products derived from this software without + * prior written permission. + * + * 3. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by Paul Mackerras + * ". + * + * THE AUTHORS OF THIS SOFTWARE DISCLAIM ALL WARRANTIES WITH REGARD TO + * THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS, IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY + * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN + * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING + * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include "lwip/opt.h" +#if PPP_SUPPORT && CHAP_SUPPORT /* don't build if not configured for use in lwipopts.h */ + +#if 0 /* UNUSED */ +#include +#include +#endif /* UNUSED */ + +#include "netif/ppp/ppp_impl.h" + +#include "netif/ppp/chap-new.h" +#include "netif/ppp/chap-md5.h" +#include "netif/ppp/magic.h" + +#if LWIP_INCLUDED_POLARSSL_MD5 +#include "netif/ppp/polarssl/md5.h" +#else +#include "polarssl/md5.h" +#endif + +#define MD5_HASH_SIZE 16 +#define MD5_MIN_CHALLENGE 17 +#define MD5_MAX_CHALLENGE 24 +#define MD5_MIN_MAX_POWER_OF_TWO_CHALLENGE 3 /* 2^3-1 = 7, 17+7 = 24 */ + +#if PPP_SERVER +static void chap_md5_generate_challenge(ppp_pcb *pcb, unsigned char *cp) { + int clen; + LWIP_UNUSED_ARG(pcb); + + clen = MD5_MIN_CHALLENGE + magic_pow(MD5_MIN_MAX_POWER_OF_TWO_CHALLENGE); + *cp++ = clen; + magic_random_bytes(cp, clen); +} + +static int chap_md5_verify_response(ppp_pcb *pcb, int id, const char *name, + const unsigned char *secret, int secret_len, + const unsigned char *challenge, const unsigned char *response, + char *message, int message_space) { + md5_context ctx; + unsigned char idbyte = id; + unsigned char hash[MD5_HASH_SIZE]; + int challenge_len, response_len; + LWIP_UNUSED_ARG(name); + LWIP_UNUSED_ARG(pcb); + + challenge_len = *challenge++; + response_len = *response++; + if (response_len == MD5_HASH_SIZE) { + /* Generate hash of ID, secret, challenge */ + md5_starts(&ctx); + md5_update(&ctx, &idbyte, 1); + md5_update(&ctx, secret, secret_len); + md5_update(&ctx, challenge, challenge_len); + md5_finish(&ctx, hash); + + /* Test if our hash matches the peer's response */ + if (memcmp(hash, response, MD5_HASH_SIZE) == 0) { + ppp_slprintf(message, message_space, "Access granted"); + return 1; + } + } + ppp_slprintf(message, message_space, "Access denied"); + return 0; +} +#endif /* PPP_SERVER */ + +static void chap_md5_make_response(ppp_pcb *pcb, unsigned char *response, int id, const char *our_name, + const unsigned char *challenge, const char *secret, int secret_len, + unsigned char *private_) { + md5_context ctx; + unsigned char idbyte = id; + int challenge_len = *challenge++; + LWIP_UNUSED_ARG(our_name); + LWIP_UNUSED_ARG(private_); + LWIP_UNUSED_ARG(pcb); + + md5_starts(&ctx); + md5_update(&ctx, &idbyte, 1); + md5_update(&ctx, (const u_char *)secret, secret_len); + md5_update(&ctx, challenge, challenge_len); + md5_finish(&ctx, &response[1]); + response[0] = MD5_HASH_SIZE; +} + +const struct chap_digest_type md5_digest = { + CHAP_MD5, /* code */ +#if PPP_SERVER + chap_md5_generate_challenge, + chap_md5_verify_response, +#endif /* PPP_SERVER */ + chap_md5_make_response, + NULL, /* check_success */ + NULL, /* handle_failure */ +}; + +#endif /* PPP_SUPPORT && CHAP_SUPPORT */ diff --git a/components/lwip/netif/ppp/chap-new.c b/components/lwip/netif/ppp/chap-new.c new file mode 100755 index 0000000000..f0753976a9 --- /dev/null +++ b/components/lwip/netif/ppp/chap-new.c @@ -0,0 +1,677 @@ +/* + * chap-new.c - New CHAP implementation. + * + * Copyright (c) 2003 Paul Mackerras. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. The name(s) of the authors of this software must not be used to + * endorse or promote products derived from this software without + * prior written permission. + * + * 3. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by Paul Mackerras + * ". + * + * THE AUTHORS OF THIS SOFTWARE DISCLAIM ALL WARRANTIES WITH REGARD TO + * THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS, IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY + * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN + * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING + * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include "lwip/opt.h" +#if PPP_SUPPORT && CHAP_SUPPORT /* don't build if not configured for use in lwipopts.h */ + +#if 0 /* UNUSED */ +#include +#include +#endif /* UNUSED */ + +#include "netif/ppp/ppp_impl.h" + +#if 0 /* UNUSED */ +#include "session.h" +#endif /* UNUSED */ + +#include "netif/ppp/chap-new.h" +#include "netif/ppp/chap-md5.h" +#if MSCHAP_SUPPORT +#include "netif/ppp/chap_ms.h" +#endif +#include "netif/ppp/magic.h" + +#if 0 /* UNUSED */ +/* Hook for a plugin to validate CHAP challenge */ +int (*chap_verify_hook)(const char *name, const char *ourname, int id, + const struct chap_digest_type *digest, + const unsigned char *challenge, const unsigned char *response, + char *message, int message_space) = NULL; +#endif /* UNUSED */ + +#if PPP_OPTIONS +/* + * Command-line options. + */ +static option_t chap_option_list[] = { + { "chap-restart", o_int, &chap_timeout_time, + "Set timeout for CHAP", OPT_PRIO }, + { "chap-max-challenge", o_int, &pcb->settings.chap_max_transmits, + "Set max #xmits for challenge", OPT_PRIO }, + { "chap-interval", o_int, &pcb->settings.chap_rechallenge_time, + "Set interval for rechallenge", OPT_PRIO }, + { NULL } +}; +#endif /* PPP_OPTIONS */ + + +/* Values for flags in chap_client_state and chap_server_state */ +#define LOWERUP 1 +#define AUTH_STARTED 2 +#define AUTH_DONE 4 +#define AUTH_FAILED 8 +#define TIMEOUT_PENDING 0x10 +#define CHALLENGE_VALID 0x20 + +/* + * Prototypes. + */ +static void chap_init(ppp_pcb *pcb); +static void chap_lowerup(ppp_pcb *pcb); +static void chap_lowerdown(ppp_pcb *pcb); +#if PPP_SERVER +static void chap_timeout(void *arg); +static void chap_generate_challenge(ppp_pcb *pcb); +static void chap_handle_response(ppp_pcb *pcb, int code, + unsigned char *pkt, int len); +static int chap_verify_response(ppp_pcb *pcb, const char *name, const char *ourname, int id, + const struct chap_digest_type *digest, + const unsigned char *challenge, const unsigned char *response, + char *message, int message_space); +#endif /* PPP_SERVER */ +static void chap_respond(ppp_pcb *pcb, int id, + unsigned char *pkt, int len); +static void chap_handle_status(ppp_pcb *pcb, int code, int id, + unsigned char *pkt, int len); +static void chap_protrej(ppp_pcb *pcb); +static void chap_input(ppp_pcb *pcb, unsigned char *pkt, int pktlen); +#if PRINTPKT_SUPPORT +static int chap_print_pkt(const unsigned char *p, int plen, + void (*printer) (void *, const char *, ...), void *arg); +#endif /* PRINTPKT_SUPPORT */ + +/* List of digest types that we know about */ +static const struct chap_digest_type* const chap_digests[] = { + &md5_digest, +#if MSCHAP_SUPPORT + &chapms_digest, + &chapms2_digest, +#endif /* MSCHAP_SUPPORT */ + NULL +}; + +/* + * chap_init - reset to initial state. + */ +static void chap_init(ppp_pcb *pcb) { + LWIP_UNUSED_ARG(pcb); + +#if 0 /* Not necessary, everything is cleared in ppp_clear() */ + memset(&pcb->chap_client, 0, sizeof(chap_client_state)); +#if PPP_SERVER + memset(&pcb->chap_server, 0, sizeof(chap_server_state)); +#endif /* PPP_SERVER */ +#endif /* 0 */ +} + +/* + * chap_lowerup - we can start doing stuff now. + */ +static void chap_lowerup(ppp_pcb *pcb) { + + pcb->chap_client.flags |= LOWERUP; +#if PPP_SERVER + pcb->chap_server.flags |= LOWERUP; + if (pcb->chap_server.flags & AUTH_STARTED) + chap_timeout(pcb); +#endif /* PPP_SERVER */ +} + +static void chap_lowerdown(ppp_pcb *pcb) { + + pcb->chap_client.flags = 0; +#if PPP_SERVER + if (pcb->chap_server.flags & TIMEOUT_PENDING) + UNTIMEOUT(chap_timeout, pcb); + pcb->chap_server.flags = 0; +#endif /* PPP_SERVER */ +} + +#if PPP_SERVER +/* + * chap_auth_peer - Start authenticating the peer. + * If the lower layer is already up, we start sending challenges, + * otherwise we wait for the lower layer to come up. + */ +void chap_auth_peer(ppp_pcb *pcb, const char *our_name, int digest_code) { + const struct chap_digest_type *dp; + int i; + + if (pcb->chap_server.flags & AUTH_STARTED) { + ppp_error("CHAP: peer authentication already started!"); + return; + } + for (i = 0; (dp = chap_digests[i]) != NULL; ++i) + if (dp->code == digest_code) + break; + if (dp == NULL) + ppp_fatal("CHAP digest 0x%x requested but not available", + digest_code); + + pcb->chap_server.digest = dp; + pcb->chap_server.name = our_name; + /* Start with a random ID value */ + pcb->chap_server.id = magic(); + pcb->chap_server.flags |= AUTH_STARTED; + if (pcb->chap_server.flags & LOWERUP) + chap_timeout(pcb); +} +#endif /* PPP_SERVER */ + +/* + * chap_auth_with_peer - Prepare to authenticate ourselves to the peer. + * There isn't much to do until we receive a challenge. + */ +void chap_auth_with_peer(ppp_pcb *pcb, const char *our_name, int digest_code) { + const struct chap_digest_type *dp; + int i; + + if(NULL == our_name) + return; + + if (pcb->chap_client.flags & AUTH_STARTED) { + ppp_error("CHAP: authentication with peer already started!"); + return; + } + for (i = 0; (dp = chap_digests[i]) != NULL; ++i) + if (dp->code == digest_code) + break; + + if (dp == NULL) + ppp_fatal("CHAP digest 0x%x requested but not available", + digest_code); + + pcb->chap_client.digest = dp; + pcb->chap_client.name = our_name; + pcb->chap_client.flags |= AUTH_STARTED; +} + +#if PPP_SERVER +/* + * chap_timeout - It's time to send another challenge to the peer. + * This could be either a retransmission of a previous challenge, + * or a new challenge to start re-authentication. + */ +static void chap_timeout(void *arg) { + ppp_pcb *pcb = (ppp_pcb*)arg; + struct pbuf *p; + + pcb->chap_server.flags &= ~TIMEOUT_PENDING; + if ((pcb->chap_server.flags & CHALLENGE_VALID) == 0) { + pcb->chap_server.challenge_xmits = 0; + chap_generate_challenge(pcb); + pcb->chap_server.flags |= CHALLENGE_VALID; + } else if (pcb->chap_server.challenge_xmits >= pcb->settings.chap_max_transmits) { + pcb->chap_server.flags &= ~CHALLENGE_VALID; + pcb->chap_server.flags |= AUTH_DONE | AUTH_FAILED; + auth_peer_fail(pcb, PPP_CHAP); + return; + } + + p = pbuf_alloc(PBUF_RAW, (u16_t)(pcb->chap_server.challenge_pktlen), PPP_CTRL_PBUF_TYPE); + if(NULL == p) + return; + if(p->tot_len != p->len) { + pbuf_free(p); + return; + } + MEMCPY(p->payload, pcb->chap_server.challenge, pcb->chap_server.challenge_pktlen); + ppp_write(pcb, p); + ++pcb->chap_server.challenge_xmits; + pcb->chap_server.flags |= TIMEOUT_PENDING; + TIMEOUT(chap_timeout, arg, pcb->settings.chap_timeout_time); +} + +/* + * chap_generate_challenge - generate a challenge string and format + * the challenge packet in pcb->chap_server.challenge_pkt. + */ +static void chap_generate_challenge(ppp_pcb *pcb) { + int clen = 1, nlen, len; + unsigned char *p; + + p = pcb->chap_server.challenge; + MAKEHEADER(p, PPP_CHAP); + p += CHAP_HDRLEN; + pcb->chap_server.digest->generate_challenge(pcb, p); + clen = *p; + nlen = strlen(pcb->chap_server.name); + memcpy(p + 1 + clen, pcb->chap_server.name, nlen); + + len = CHAP_HDRLEN + 1 + clen + nlen; + pcb->chap_server.challenge_pktlen = PPP_HDRLEN + len; + + p = pcb->chap_server.challenge + PPP_HDRLEN; + p[0] = CHAP_CHALLENGE; + p[1] = ++pcb->chap_server.id; + p[2] = len >> 8; + p[3] = len; +} + +/* + * chap_handle_response - check the response to our challenge. + */ +static void chap_handle_response(ppp_pcb *pcb, int id, + unsigned char *pkt, int len) { + int response_len, ok, mlen; + const unsigned char *response; + unsigned char *outp; + struct pbuf *p; + const char *name = NULL; /* initialized to shut gcc up */ +#if 0 /* UNUSED */ + int (*verifier)(const char *, const char *, int, const struct chap_digest_type *, + const unsigned char *, const unsigned char *, char *, int); +#endif /* UNUSED */ + char rname[MAXNAMELEN+1]; + char message[256]; + + if ((pcb->chap_server.flags & LOWERUP) == 0) + return; + if (id != pcb->chap_server.challenge[PPP_HDRLEN+1] || len < 2) + return; + if (pcb->chap_server.flags & CHALLENGE_VALID) { + response = pkt; + GETCHAR(response_len, pkt); + len -= response_len + 1; /* length of name */ + name = (char *)pkt + response_len; + if (len < 0) + return; + + if (pcb->chap_server.flags & TIMEOUT_PENDING) { + pcb->chap_server.flags &= ~TIMEOUT_PENDING; + UNTIMEOUT(chap_timeout, pcb); + } +#if PPP_REMOTENAME + if (pcb->settings.explicit_remote) { + name = pcb->remote_name; + } else +#endif /* PPP_REMOTENAME */ + { + /* Null terminate and clean remote name. */ + ppp_slprintf(rname, sizeof(rname), "%.*v", len, name); + name = rname; + } + +#if 0 /* UNUSED */ + if (chap_verify_hook) + verifier = chap_verify_hook; + else + verifier = chap_verify_response; + ok = (*verifier)(name, pcb->chap_server.name, id, pcb->chap_server.digest, + pcb->chap_server.challenge + PPP_HDRLEN + CHAP_HDRLEN, + response, pcb->chap_server.message, sizeof(pcb->chap_server.message)); +#endif /* UNUSED */ + ok = chap_verify_response(pcb, name, pcb->chap_server.name, id, pcb->chap_server.digest, + pcb->chap_server.challenge + PPP_HDRLEN + CHAP_HDRLEN, + response, message, sizeof(message)); +#if 0 /* UNUSED */ + if (!ok || !auth_number()) { +#endif /* UNUSED */ + if (!ok) { + pcb->chap_server.flags |= AUTH_FAILED; + ppp_warn("Peer %q failed CHAP authentication", name); + } + } else if ((pcb->chap_server.flags & AUTH_DONE) == 0) + return; + + /* send the response */ + mlen = strlen(message); + len = CHAP_HDRLEN + mlen; + p = pbuf_alloc(PBUF_RAW, (u16_t)(PPP_HDRLEN +len), PPP_CTRL_PBUF_TYPE); + if(NULL == p) + return; + if(p->tot_len != p->len) { + pbuf_free(p); + return; + } + + outp = (unsigned char *)p->payload; + MAKEHEADER(outp, PPP_CHAP); + + outp[0] = (pcb->chap_server.flags & AUTH_FAILED)? CHAP_FAILURE: CHAP_SUCCESS; + outp[1] = id; + outp[2] = len >> 8; + outp[3] = len; + if (mlen > 0) + memcpy(outp + CHAP_HDRLEN, message, mlen); + ppp_write(pcb, p); + + if (pcb->chap_server.flags & CHALLENGE_VALID) { + pcb->chap_server.flags &= ~CHALLENGE_VALID; + if (!(pcb->chap_server.flags & AUTH_DONE) && !(pcb->chap_server.flags & AUTH_FAILED)) { + +#if 0 /* UNUSED */ + /* + * Auth is OK, so now we need to check session restrictions + * to ensure everything is OK, but only if we used a + * plugin, and only if we're configured to check. This + * allows us to do PAM checks on PPP servers that + * authenticate against ActiveDirectory, and use AD for + * account info (like when using Winbind integrated with + * PAM). + */ + if (session_mgmt && + session_check(name, NULL, devnam, NULL) == 0) { + pcb->chap_server.flags |= AUTH_FAILED; + ppp_warn("Peer %q failed CHAP Session verification", name); + } +#endif /* UNUSED */ + + } + if (pcb->chap_server.flags & AUTH_FAILED) { + auth_peer_fail(pcb, PPP_CHAP); + } else { + if ((pcb->chap_server.flags & AUTH_DONE) == 0) + auth_peer_success(pcb, PPP_CHAP, + pcb->chap_server.digest->code, + name, strlen(name)); + if (pcb->settings.chap_rechallenge_time) { + pcb->chap_server.flags |= TIMEOUT_PENDING; + TIMEOUT(chap_timeout, pcb, + pcb->settings.chap_rechallenge_time); + } + } + pcb->chap_server.flags |= AUTH_DONE; + } +} + +/* + * chap_verify_response - check whether the peer's response matches + * what we think it should be. Returns 1 if it does (authentication + * succeeded), or 0 if it doesn't. + */ +static int chap_verify_response(ppp_pcb *pcb, const char *name, const char *ourname, int id, + const struct chap_digest_type *digest, + const unsigned char *challenge, const unsigned char *response, + char *message, int message_space) { + int ok; + unsigned char secret[MAXSECRETLEN]; + int secret_len; + + /* Get the secret that the peer is supposed to know */ + if (!get_secret(pcb, name, ourname, (char *)secret, &secret_len, 1)) { + ppp_error("No CHAP secret found for authenticating %q", name); + return 0; + } + ok = digest->verify_response(pcb, id, name, secret, secret_len, challenge, + response, message, message_space); + memset(secret, 0, sizeof(secret)); + + return ok; +} +#endif /* PPP_SERVER */ + +/* + * chap_respond - Generate and send a response to a challenge. + */ +static void chap_respond(ppp_pcb *pcb, int id, + unsigned char *pkt, int len) { + int clen, nlen; + int secret_len; + struct pbuf *p; + u_char *outp; + char rname[MAXNAMELEN+1]; + char secret[MAXSECRETLEN+1]; + + p = pbuf_alloc(PBUF_RAW, (u16_t)(RESP_MAX_PKTLEN), PPP_CTRL_PBUF_TYPE); + if(NULL == p) + return; + if(p->tot_len != p->len) { + pbuf_free(p); + return; + } + + if ((pcb->chap_client.flags & (LOWERUP | AUTH_STARTED)) != (LOWERUP | AUTH_STARTED)) + return; /* not ready */ + if (len < 2 || len < pkt[0] + 1) + return; /* too short */ + clen = pkt[0]; + nlen = len - (clen + 1); + + /* Null terminate and clean remote name. */ + ppp_slprintf(rname, sizeof(rname), "%.*v", nlen, pkt + clen + 1); + +#if PPP_REMOTENAME + /* Microsoft doesn't send their name back in the PPP packet */ + if (pcb->settings.explicit_remote || (pcb->settings.remote_name[0] != 0 && rname[0] == 0)) + strlcpy(rname, pcb->settings.remote_name, sizeof(rname)); +#endif /* PPP_REMOTENAME */ + + /* get secret for authenticating ourselves with the specified host */ + if (!get_secret(pcb, pcb->chap_client.name, rname, secret, &secret_len, 0)) { + secret_len = 0; /* assume null secret if can't find one */ + ppp_warn("No CHAP secret found for authenticating us to %q", rname); + } + + outp = (u_char*)p->payload; + MAKEHEADER(outp, PPP_CHAP); + outp += CHAP_HDRLEN; + + pcb->chap_client.digest->make_response(pcb, outp, id, pcb->chap_client.name, pkt, + secret, secret_len, pcb->chap_client.priv); + memset(secret, 0, secret_len); + + clen = *outp; + nlen = strlen(pcb->chap_client.name); + memcpy(outp + clen + 1, pcb->chap_client.name, nlen); + + outp = (u_char*)p->payload + PPP_HDRLEN; + len = CHAP_HDRLEN + clen + 1 + nlen; + outp[0] = CHAP_RESPONSE; + outp[1] = id; + outp[2] = len >> 8; + outp[3] = len; + + pbuf_realloc(p, PPP_HDRLEN + len); + ppp_write(pcb, p); +} + +static void chap_handle_status(ppp_pcb *pcb, int code, int id, + unsigned char *pkt, int len) { + const char *msg = NULL; + LWIP_UNUSED_ARG(id); + + if ((pcb->chap_client.flags & (AUTH_DONE|AUTH_STARTED|LOWERUP)) + != (AUTH_STARTED|LOWERUP)) + return; + pcb->chap_client.flags |= AUTH_DONE; + + if (code == CHAP_SUCCESS) { + /* used for MS-CHAP v2 mutual auth, yuck */ + if (pcb->chap_client.digest->check_success != NULL) { + if (!(*pcb->chap_client.digest->check_success)(pcb, pkt, len, pcb->chap_client.priv)) + code = CHAP_FAILURE; + } else + msg = "CHAP authentication succeeded"; + } else { + if (pcb->chap_client.digest->handle_failure != NULL) + (*pcb->chap_client.digest->handle_failure)(pcb, pkt, len); + else + msg = "CHAP authentication failed"; + } + if (msg) { + if (len > 0) + ppp_info("%s: %.*v", msg, len, pkt); + else + ppp_info("%s", msg); + } + if (code == CHAP_SUCCESS) + auth_withpeer_success(pcb, PPP_CHAP, pcb->chap_client.digest->code); + else { + pcb->chap_client.flags |= AUTH_FAILED; + ppp_error("CHAP authentication failed"); + auth_withpeer_fail(pcb, PPP_CHAP); + } +} + +static void chap_input(ppp_pcb *pcb, unsigned char *pkt, int pktlen) { + unsigned char code, id; + int len; + + if (pktlen < CHAP_HDRLEN) + return; + GETCHAR(code, pkt); + GETCHAR(id, pkt); + GETSHORT(len, pkt); + if (len < CHAP_HDRLEN || len > pktlen) + return; + len -= CHAP_HDRLEN; + + switch (code) { + case CHAP_CHALLENGE: + chap_respond(pcb, id, pkt, len); + break; +#if PPP_SERVER + case CHAP_RESPONSE: + chap_handle_response(pcb, id, pkt, len); + break; +#endif /* PPP_SERVER */ + case CHAP_FAILURE: + case CHAP_SUCCESS: + chap_handle_status(pcb, code, id, pkt, len); + break; + default: + break; + } +} + +static void chap_protrej(ppp_pcb *pcb) { + +#if PPP_SERVER + if (pcb->chap_server.flags & TIMEOUT_PENDING) { + pcb->chap_server.flags &= ~TIMEOUT_PENDING; + UNTIMEOUT(chap_timeout, pcb); + } + if (pcb->chap_server.flags & AUTH_STARTED) { + pcb->chap_server.flags = 0; + auth_peer_fail(pcb, PPP_CHAP); + } +#endif /* PPP_SERVER */ + if ((pcb->chap_client.flags & (AUTH_STARTED|AUTH_DONE)) == AUTH_STARTED) { + pcb->chap_client.flags &= ~AUTH_STARTED; + ppp_error("CHAP authentication failed due to protocol-reject"); + auth_withpeer_fail(pcb, PPP_CHAP); + } +} + +#if PRINTPKT_SUPPORT +/* + * chap_print_pkt - print the contents of a CHAP packet. + */ +static const char* const chap_code_names[] = { + "Challenge", "Response", "Success", "Failure" +}; + +static int chap_print_pkt(const unsigned char *p, int plen, + void (*printer) (void *, const char *, ...), void *arg) { + int code, id, len; + int clen, nlen; + unsigned char x; + + if (plen < CHAP_HDRLEN) + return 0; + GETCHAR(code, p); + GETCHAR(id, p); + GETSHORT(len, p); + if (len < CHAP_HDRLEN || len > plen) + return 0; + + if (code >= 1 && code <= (int)sizeof(chap_code_names) / (int)sizeof(char *)) + printer(arg, " %s", chap_code_names[code-1]); + else + printer(arg, " code=0x%x", code); + printer(arg, " id=0x%x", id); + len -= CHAP_HDRLEN; + switch (code) { + case CHAP_CHALLENGE: + case CHAP_RESPONSE: + if (len < 1) + break; + clen = p[0]; + if (len < clen + 1) + break; + ++p; + nlen = len - clen - 1; + printer(arg, " <"); + for (; clen > 0; --clen) { + GETCHAR(x, p); + printer(arg, "%.2x", x); + } + printer(arg, ">, name = "); + ppp_print_string(p, nlen, printer, arg); + break; + case CHAP_FAILURE: + case CHAP_SUCCESS: + printer(arg, " "); + ppp_print_string(p, len, printer, arg); + break; + default: + for (clen = len; clen > 0; --clen) { + GETCHAR(x, p); + printer(arg, " %.2x", x); + } + /* no break */ + } + + return len + CHAP_HDRLEN; +} +#endif /* PRINTPKT_SUPPORT */ + +const struct protent chap_protent = { + PPP_CHAP, + chap_init, + chap_input, + chap_protrej, + chap_lowerup, + chap_lowerdown, + NULL, /* open */ + NULL, /* close */ +#if PRINTPKT_SUPPORT + chap_print_pkt, +#endif /* PRINTPKT_SUPPORT */ +#if PPP_DATAINPUT + NULL, /* datainput */ +#endif /* PPP_DATAINPUT */ +#if PRINTPKT_SUPPORT + "CHAP", /* name */ + NULL, /* data_name */ +#endif /* PRINTPKT_SUPPORT */ +#if PPP_OPTIONS + chap_option_list, + NULL, /* check_options */ +#endif /* PPP_OPTIONS */ +#if DEMAND_SUPPORT + NULL, + NULL +#endif /* DEMAND_SUPPORT */ +}; + +#endif /* PPP_SUPPORT && CHAP_SUPPORT */ diff --git a/components/lwip/netif/ppp/chap_ms.c b/components/lwip/netif/ppp/chap_ms.c new file mode 100755 index 0000000000..550c95d120 --- /dev/null +++ b/components/lwip/netif/ppp/chap_ms.c @@ -0,0 +1,954 @@ +/* + * chap_ms.c - Microsoft MS-CHAP compatible implementation. + * + * Copyright (c) 1995 Eric Rosenquist. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. The name(s) of the authors of this software must not be used to + * endorse or promote products derived from this software without + * prior written permission. + * + * THE AUTHORS OF THIS SOFTWARE DISCLAIM ALL WARRANTIES WITH REGARD TO + * THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS, IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY + * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN + * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING + * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * Modifications by Lauri Pesonen / lpesonen@clinet.fi, april 1997 + * + * Implemented LANManager type password response to MS-CHAP challenges. + * Now pppd provides both NT style and LANMan style blocks, and the + * prefered is set by option "ms-lanman". Default is to use NT. + * The hash text (StdText) was taken from Win95 RASAPI32.DLL. + * + * You should also use DOMAIN\\USERNAME as described in README.MSCHAP80 + */ + +/* + * Modifications by Frank Cusack, frank@google.com, March 2002. + * + * Implemented MS-CHAPv2 functionality, heavily based on sample + * implementation in RFC 2759. Implemented MPPE functionality, + * heavily based on sample implementation in RFC 3079. + * + * Copyright (c) 2002 Google, Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. The name(s) of the authors of this software must not be used to + * endorse or promote products derived from this software without + * prior written permission. + * + * THE AUTHORS OF THIS SOFTWARE DISCLAIM ALL WARRANTIES WITH REGARD TO + * THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS, IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY + * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN + * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING + * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + */ + +#include "lwip/opt.h" +#if PPP_SUPPORT && MSCHAP_SUPPORT /* don't build if not configured for use in lwipopts.h */ + +#if 0 /* UNUSED */ +#include +#include +#include +#include +#include +#include +#include +#endif /* UNUSED */ + +#include "netif/ppp/ppp_impl.h" + +#include "netif/ppp/chap-new.h" +#include "netif/ppp/chap_ms.h" +#include "netif/ppp/pppcrypt.h" +#include "netif/ppp/magic.h" +#if MPPE_SUPPORT +#include "netif/ppp/mppe.h" /* For mppe_sha1_pad*, mppe_set_key() */ +#endif /* MPPE_SUPPORT */ + +#if LWIP_INCLUDED_POLARSSL_MD4 +#include "netif/ppp/polarssl/md4.h" +#else +#include "polarssl/md4.h" +#endif + +#if LWIP_INCLUDED_POLARSSL_SHA1 +#include "netif/ppp/polarssl/sha1.h" +#else +#include "polarssl/sha1.h" +#endif + +#if LWIP_INCLUDED_POLARSSL_DES +#include "netif/ppp/polarssl/des.h" +#else +#include "polarssl/des.h" +#endif + +#define SHA1_SIGNATURE_SIZE 20 +#define MD4_SIGNATURE_SIZE 16 /* 16 bytes in a MD4 message digest */ +#define MAX_NT_PASSWORD 256 /* Max (Unicode) chars in an NT pass */ + +#define MS_CHAP_RESPONSE_LEN 49 /* Response length for MS-CHAP */ +#define MS_CHAP2_RESPONSE_LEN 49 /* Response length for MS-CHAPv2 */ +#define MS_AUTH_RESPONSE_LENGTH 40 /* MS-CHAPv2 authenticator response, */ + /* as ASCII */ + +/* Error codes for MS-CHAP failure messages. */ +#define MS_CHAP_ERROR_RESTRICTED_LOGON_HOURS 646 +#define MS_CHAP_ERROR_ACCT_DISABLED 647 +#define MS_CHAP_ERROR_PASSWD_EXPIRED 648 +#define MS_CHAP_ERROR_NO_DIALIN_PERMISSION 649 +#define MS_CHAP_ERROR_AUTHENTICATION_FAILURE 691 +#define MS_CHAP_ERROR_CHANGING_PASSWORD 709 + +/* + * Offsets within the response field for MS-CHAP + */ +#define MS_CHAP_LANMANRESP 0 +#define MS_CHAP_LANMANRESP_LEN 24 +#define MS_CHAP_NTRESP 24 +#define MS_CHAP_NTRESP_LEN 24 +#define MS_CHAP_USENT 48 + +/* + * Offsets within the response field for MS-CHAP2 + */ +#define MS_CHAP2_PEER_CHALLENGE 0 +#define MS_CHAP2_PEER_CHAL_LEN 16 +#define MS_CHAP2_RESERVED_LEN 8 +#define MS_CHAP2_NTRESP 24 +#define MS_CHAP2_NTRESP_LEN 24 +#define MS_CHAP2_FLAGS 48 + +#if MPPE_SUPPORT +#if 0 /* UNUSED */ +/* These values are the RADIUS attribute values--see RFC 2548. */ +#define MPPE_ENC_POL_ENC_ALLOWED 1 +#define MPPE_ENC_POL_ENC_REQUIRED 2 +#define MPPE_ENC_TYPES_RC4_40 2 +#define MPPE_ENC_TYPES_RC4_128 4 + +/* used by plugins (using above values) */ +extern void set_mppe_enc_types(int, int); +#endif /* UNUSED */ +#endif /* MPPE_SUPPORT */ + +/* Are we the authenticator or authenticatee? For MS-CHAPv2 key derivation. */ +#define MS_CHAP2_AUTHENTICATEE 0 +#define MS_CHAP2_AUTHENTICATOR 1 + +static void ascii2unicode (const char[], int, u_char[]); +static void NTPasswordHash (u_char *, int, u_char[MD4_SIGNATURE_SIZE]); +static void ChallengeResponse (const u_char *, const u_char *, u_char[24]); +static void ChallengeHash (const u_char[16], const u_char *, const char *, u_char[8]); +static void ChapMS_NT (const u_char *, const char *, int, u_char[24]); +static void ChapMS2_NT (const u_char *, const u_char[16], const char *, const char *, int, + u_char[24]); +static void GenerateAuthenticatorResponsePlain + (const char*, int, u_char[24], const u_char[16], const u_char *, + const char *, u_char[41]); +#ifdef MSLANMAN +static void ChapMS_LANMan (u_char *, char *, int, u_char *); +#endif + +static void GenerateAuthenticatorResponse(const u_char PasswordHashHash[MD4_SIGNATURE_SIZE], + u_char NTResponse[24], const u_char PeerChallenge[16], + const u_char *rchallenge, const char *username, + u_char authResponse[MS_AUTH_RESPONSE_LENGTH+1]); + +#if MPPE_SUPPORT +static void Set_Start_Key (ppp_pcb *pcb, const u_char *, const char *, int); +static void SetMasterKeys (ppp_pcb *pcb, const char *, int, u_char[24], int); +#endif /* MPPE_SUPPORT */ + +static void ChapMS (ppp_pcb *pcb, const u_char *, const char *, int, u_char *); +static void ChapMS2 (ppp_pcb *pcb, const u_char *, const u_char *, const char *, const char *, int, + u_char *, u_char[MS_AUTH_RESPONSE_LENGTH+1], int); + +#ifdef MSLANMAN +bool ms_lanman = 0; /* Use LanMan password instead of NT */ + /* Has meaning only with MS-CHAP challenges */ +#endif + +#if MPPE_SUPPORT +#ifdef DEBUGMPPEKEY +/* For MPPE debug */ +/* Use "[]|}{?/><,`!2&&(" (sans quotes) for RFC 3079 MS-CHAPv2 test value */ +static char *mschap_challenge = NULL; +/* Use "!@\#$%^&*()_+:3|~" (sans quotes, backslash is to escape #) for ... */ +static char *mschap2_peer_challenge = NULL; +#endif + +#include "netif/ppp/fsm.h" /* Need to poke MPPE options */ +#include "netif/ppp/ccp.h" +#endif /* MPPE_SUPPORT */ + +#if PPP_OPTIONS +/* + * Command-line options. + */ +static option_t chapms_option_list[] = { +#ifdef MSLANMAN + { "ms-lanman", o_bool, &ms_lanman, + "Use LanMan passwd when using MS-CHAP", 1 }, +#endif +#ifdef DEBUGMPPEKEY + { "mschap-challenge", o_string, &mschap_challenge, + "specify CHAP challenge" }, + { "mschap2-peer-challenge", o_string, &mschap2_peer_challenge, + "specify CHAP peer challenge" }, +#endif + { NULL } +}; +#endif /* PPP_OPTIONS */ + +#if PPP_SERVER +/* + * chapms_generate_challenge - generate a challenge for MS-CHAP. + * For MS-CHAP the challenge length is fixed at 8 bytes. + * The length goes in challenge[0] and the actual challenge starts + * at challenge[1]. + */ +static void chapms_generate_challenge(ppp_pcb *pcb, unsigned char *challenge) { + LWIP_UNUSED_ARG(pcb); + + *challenge++ = 8; +#ifdef DEBUGMPPEKEY + if (mschap_challenge && strlen(mschap_challenge) == 8) + memcpy(challenge, mschap_challenge, 8); + else +#endif + magic_random_bytes(challenge, 8); +} + +static void chapms2_generate_challenge(ppp_pcb *pcb, unsigned char *challenge) { + LWIP_UNUSED_ARG(pcb); + + *challenge++ = 16; +#ifdef DEBUGMPPEKEY + if (mschap_challenge && strlen(mschap_challenge) == 16) + memcpy(challenge, mschap_challenge, 16); + else +#endif + magic_random_bytes(challenge, 16); +} + +static int chapms_verify_response(ppp_pcb *pcb, int id, const char *name, + const unsigned char *secret, int secret_len, + const unsigned char *challenge, const unsigned char *response, + char *message, int message_space) { + unsigned char md[MS_CHAP_RESPONSE_LEN]; + int diff; + int challenge_len, response_len; + LWIP_UNUSED_ARG(id); + LWIP_UNUSED_ARG(name); + + challenge_len = *challenge++; /* skip length, is 8 */ + response_len = *response++; + if (response_len != MS_CHAP_RESPONSE_LEN) + goto bad; + +#ifndef MSLANMAN + if (!response[MS_CHAP_USENT]) { + /* Should really propagate this into the error packet. */ + ppp_notice("Peer request for LANMAN auth not supported"); + goto bad; + } +#endif + + /* Generate the expected response. */ + ChapMS(pcb, (const u_char *)challenge, (const char *)secret, secret_len, md); + +#ifdef MSLANMAN + /* Determine which part of response to verify against */ + if (!response[MS_CHAP_USENT]) + diff = memcmp(&response[MS_CHAP_LANMANRESP], + &md[MS_CHAP_LANMANRESP], MS_CHAP_LANMANRESP_LEN); + else +#endif + diff = memcmp(&response[MS_CHAP_NTRESP], &md[MS_CHAP_NTRESP], + MS_CHAP_NTRESP_LEN); + + if (diff == 0) { + ppp_slprintf(message, message_space, "Access granted"); + return 1; + } + + bad: + /* See comments below for MS-CHAP V2 */ + ppp_slprintf(message, message_space, "E=691 R=1 C=%0.*B V=0", + challenge_len, challenge); + return 0; +} + +static int chapms2_verify_response(ppp_pcb *pcb, int id, const char *name, + const unsigned char *secret, int secret_len, + const unsigned char *challenge, const unsigned char *response, + char *message, int message_space) { + unsigned char md[MS_CHAP2_RESPONSE_LEN]; + char saresponse[MS_AUTH_RESPONSE_LENGTH+1]; + int challenge_len, response_len; + LWIP_UNUSED_ARG(id); + + challenge_len = *challenge++; /* skip length, is 16 */ + response_len = *response++; + if (response_len != MS_CHAP2_RESPONSE_LEN) + goto bad; /* not even the right length */ + + /* Generate the expected response and our mutual auth. */ + ChapMS2(pcb, (const u_char*)challenge, (const u_char*)&response[MS_CHAP2_PEER_CHALLENGE], name, + (const char *)secret, secret_len, md, + (unsigned char *)saresponse, MS_CHAP2_AUTHENTICATOR); + + /* compare MDs and send the appropriate status */ + /* + * Per RFC 2759, success message must be formatted as + * "S= M=" + * where + * is the Authenticator Response (mutual auth) + * is a text message + * + * However, some versions of Windows (win98 tested) do not know + * about the M= part (required per RFC 2759) and flag + * it as an error (reported incorrectly as an encryption error + * to the user). Since the RFC requires it, and it can be + * useful information, we supply it if the peer is a conforming + * system. Luckily (?), win98 sets the Flags field to 0x04 + * (contrary to RFC requirements) so we can use that to + * distinguish between conforming and non-conforming systems. + * + * Special thanks to Alex Swiridov for + * help debugging this. + */ + if (memcmp(&md[MS_CHAP2_NTRESP], &response[MS_CHAP2_NTRESP], + MS_CHAP2_NTRESP_LEN) == 0) { + if (response[MS_CHAP2_FLAGS]) + ppp_slprintf(message, message_space, "S=%s", saresponse); + else + ppp_slprintf(message, message_space, "S=%s M=%s", + saresponse, "Access granted"); + return 1; + } + + bad: + /* + * Failure message must be formatted as + * "E=e R=r C=c V=v M=m" + * where + * e = error code (we use 691, ERROR_AUTHENTICATION_FAILURE) + * r = retry (we use 1, ok to retry) + * c = challenge to use for next response, we reuse previous + * v = Change Password version supported, we use 0 + * m = text message + * + * The M=m part is only for MS-CHAPv2. Neither win2k nor + * win98 (others untested) display the message to the user anyway. + * They also both ignore the E=e code. + * + * Note that it's safe to reuse the same challenge as we don't + * actually accept another response based on the error message + * (and no clients try to resend a response anyway). + * + * Basically, this whole bit is useless code, even the small + * implementation here is only because of overspecification. + */ + ppp_slprintf(message, message_space, "E=691 R=1 C=%0.*B V=0 M=%s", + challenge_len, challenge, "Access denied"); + return 0; +} +#endif /* PPP_SERVER */ + +static void chapms_make_response(ppp_pcb *pcb, unsigned char *response, int id, const char *our_name, + const unsigned char *challenge, const char *secret, int secret_len, + unsigned char *private_) { + LWIP_UNUSED_ARG(id); + LWIP_UNUSED_ARG(our_name); + LWIP_UNUSED_ARG(private_); + challenge++; /* skip length, should be 8 */ + *response++ = MS_CHAP_RESPONSE_LEN; + ChapMS(pcb, challenge, secret, secret_len, response); +} + +static void chapms2_make_response(ppp_pcb *pcb, unsigned char *response, int id, const char *our_name, + const unsigned char *challenge, const char *secret, int secret_len, + unsigned char *private_) { + LWIP_UNUSED_ARG(id); + challenge++; /* skip length, should be 16 */ + *response++ = MS_CHAP2_RESPONSE_LEN; + ChapMS2(pcb, challenge, +#ifdef DEBUGMPPEKEY + mschap2_peer_challenge, +#else + NULL, +#endif + our_name, secret, secret_len, response, private_, + MS_CHAP2_AUTHENTICATEE); +} + +static int chapms2_check_success(ppp_pcb *pcb, unsigned char *msg, int len, unsigned char *private_) { + LWIP_UNUSED_ARG(pcb); + + if ((len < MS_AUTH_RESPONSE_LENGTH + 2) || + strncmp((char *)msg, "S=", 2) != 0) { + /* Packet does not start with "S=" */ + ppp_error("MS-CHAPv2 Success packet is badly formed."); + return 0; + } + msg += 2; + len -= 2; + if (len < MS_AUTH_RESPONSE_LENGTH + || memcmp(msg, private_, MS_AUTH_RESPONSE_LENGTH)) { + /* Authenticator Response did not match expected. */ + ppp_error("MS-CHAPv2 mutual authentication failed."); + return 0; + } + /* Authenticator Response matches. */ + msg += MS_AUTH_RESPONSE_LENGTH; /* Eat it */ + len -= MS_AUTH_RESPONSE_LENGTH; + if ((len >= 3) && !strncmp((char *)msg, " M=", 3)) { + msg += 3; /* Eat the delimiter */ + } else if (len) { + /* Packet has extra text which does not begin " M=" */ + ppp_error("MS-CHAPv2 Success packet is badly formed."); + return 0; + } + return 1; +} + +static void chapms_handle_failure(ppp_pcb *pcb, unsigned char *inp, int len) { + int err; + const char *p; + char msg[64]; + LWIP_UNUSED_ARG(pcb); + + /* We want a null-terminated string for strxxx(). */ + len = LWIP_MIN(len, 63); + MEMCPY(msg, inp, len); + msg[len] = 0; + p = msg; + + /* + * Deal with MS-CHAP formatted failure messages; just print the + * M= part (if any). For MS-CHAP we're not really supposed + * to use M=, but it shouldn't hurt. See + * chapms[2]_verify_response. + */ + if (!strncmp(p, "E=", 2)) + err = strtol(p+2, NULL, 10); /* Remember the error code. */ + else + goto print_msg; /* Message is badly formatted. */ + + if (len && ((p = strstr(p, " M=")) != NULL)) { + /* M= field found. */ + p += 3; + } else { + /* No M=; use the error code. */ + switch (err) { + case MS_CHAP_ERROR_RESTRICTED_LOGON_HOURS: + p = "E=646 Restricted logon hours"; + break; + + case MS_CHAP_ERROR_ACCT_DISABLED: + p = "E=647 Account disabled"; + break; + + case MS_CHAP_ERROR_PASSWD_EXPIRED: + p = "E=648 Password expired"; + break; + + case MS_CHAP_ERROR_NO_DIALIN_PERMISSION: + p = "E=649 No dialin permission"; + break; + + case MS_CHAP_ERROR_AUTHENTICATION_FAILURE: + p = "E=691 Authentication failure"; + break; + + case MS_CHAP_ERROR_CHANGING_PASSWORD: + /* Should never see this, we don't support Change Password. */ + p = "E=709 Error changing password"; + break; + + default: + ppp_error("Unknown MS-CHAP authentication failure: %.*v", + len, inp); + return; + } + } +print_msg: + if (p != NULL) + ppp_error("MS-CHAP authentication failed: %v", p); +} + +static void ChallengeResponse(const u_char *challenge, + const u_char PasswordHash[MD4_SIGNATURE_SIZE], + u_char response[24]) { + u_char ZPasswordHash[21]; + des_context des; + u_char des_key[8]; + + BZERO(ZPasswordHash, sizeof(ZPasswordHash)); + MEMCPY(ZPasswordHash, PasswordHash, MD4_SIGNATURE_SIZE); + +#if 0 + dbglog("ChallengeResponse - ZPasswordHash %.*B", + sizeof(ZPasswordHash), ZPasswordHash); +#endif + + pppcrypt_56_to_64_bit_key(ZPasswordHash + 0, des_key); + des_setkey_enc(&des, des_key); + des_crypt_ecb(&des, challenge, response +0); + + pppcrypt_56_to_64_bit_key(ZPasswordHash + 7, des_key); + des_setkey_enc(&des, des_key); + des_crypt_ecb(&des, challenge, response +8); + + pppcrypt_56_to_64_bit_key(ZPasswordHash + 14, des_key); + des_setkey_enc(&des, des_key); + des_crypt_ecb(&des, challenge, response +16); + +#if 0 + dbglog("ChallengeResponse - response %.24B", response); +#endif +} + +static void ChallengeHash(const u_char PeerChallenge[16], const u_char *rchallenge, + const char *username, u_char Challenge[8]) { + sha1_context sha1Context; + u_char sha1Hash[SHA1_SIGNATURE_SIZE]; + const char *user; + + /* remove domain from "domain\username" */ + if ((user = strrchr(username, '\\')) != NULL) + ++user; + else + user = username; + + sha1_starts(&sha1Context); + sha1_update(&sha1Context, PeerChallenge, 16); + sha1_update(&sha1Context, rchallenge, 16); + sha1_update(&sha1Context, (const unsigned char*)user, strlen(user)); + sha1_finish(&sha1Context, sha1Hash); + + MEMCPY(Challenge, sha1Hash, 8); +} + +/* + * Convert the ASCII version of the password to Unicode. + * This implicitly supports 8-bit ISO8859/1 characters. + * This gives us the little-endian representation, which + * is assumed by all M$ CHAP RFCs. (Unicode byte ordering + * is machine-dependent.) + */ +static void ascii2unicode(const char ascii[], int ascii_len, u_char unicode[]) { + int i; + + BZERO(unicode, ascii_len * 2); + for (i = 0; i < ascii_len; i++) + unicode[i * 2] = (u_char) ascii[i]; +} + +static void NTPasswordHash(u_char *secret, int secret_len, u_char hash[MD4_SIGNATURE_SIZE]) { + md4_context md4Context; + + md4_starts(&md4Context); + md4_update(&md4Context, secret, secret_len); + md4_finish(&md4Context, hash); +} + +static void ChapMS_NT(const u_char *rchallenge, const char *secret, int secret_len, + u_char NTResponse[24]) { + u_char unicodePassword[MAX_NT_PASSWORD * 2]; + u_char PasswordHash[MD4_SIGNATURE_SIZE]; + + /* Hash the Unicode version of the secret (== password). */ + ascii2unicode(secret, secret_len, unicodePassword); + NTPasswordHash(unicodePassword, secret_len * 2, PasswordHash); + + ChallengeResponse(rchallenge, PasswordHash, NTResponse); +} + +static void ChapMS2_NT(const u_char *rchallenge, const u_char PeerChallenge[16], const char *username, + const char *secret, int secret_len, u_char NTResponse[24]) { + u_char unicodePassword[MAX_NT_PASSWORD * 2]; + u_char PasswordHash[MD4_SIGNATURE_SIZE]; + u_char Challenge[8]; + + ChallengeHash(PeerChallenge, rchallenge, username, Challenge); + + /* Hash the Unicode version of the secret (== password). */ + ascii2unicode(secret, secret_len, unicodePassword); + NTPasswordHash(unicodePassword, secret_len * 2, PasswordHash); + + ChallengeResponse(Challenge, PasswordHash, NTResponse); +} + +#ifdef MSLANMAN +static u_char *StdText = (u_char *)"KGS!@#$%"; /* key from rasapi32.dll */ + +static void ChapMS_LANMan(u_char *rchallenge, char *secret, int secret_len, + unsigned char *response) { + int i; + u_char UcasePassword[MAX_NT_PASSWORD]; /* max is actually 14 */ + u_char PasswordHash[MD4_SIGNATURE_SIZE]; + des_context des; + u_char des_key[8]; + + /* LANMan password is case insensitive */ + BZERO(UcasePassword, sizeof(UcasePassword)); + for (i = 0; i < secret_len; i++) + UcasePassword[i] = (u_char)toupper(secret[i]); + + pppcrypt_56_to_64_bit_key(UcasePassword +0, des_key); + des_setkey_enc(&des, des_key); + des_crypt_ecb(&des, StdText, PasswordHash +0); + + pppcrypt_56_to_64_bit_key(UcasePassword +7, des_key); + des_setkey_enc(&des, des_key); + des_crypt_ecb(&des, StdText, PasswordHash +8); + + ChallengeResponse(rchallenge, PasswordHash, &response[MS_CHAP_LANMANRESP]); +} +#endif + + +static void GenerateAuthenticatorResponse(const u_char PasswordHashHash[MD4_SIGNATURE_SIZE], + u_char NTResponse[24], const u_char PeerChallenge[16], + const u_char *rchallenge, const char *username, + u_char authResponse[MS_AUTH_RESPONSE_LENGTH+1]) { + /* + * "Magic" constants used in response generation, from RFC 2759. + */ + static const u_char Magic1[39] = /* "Magic server to client signing constant" */ + { 0x4D, 0x61, 0x67, 0x69, 0x63, 0x20, 0x73, 0x65, 0x72, 0x76, + 0x65, 0x72, 0x20, 0x74, 0x6F, 0x20, 0x63, 0x6C, 0x69, 0x65, + 0x6E, 0x74, 0x20, 0x73, 0x69, 0x67, 0x6E, 0x69, 0x6E, 0x67, + 0x20, 0x63, 0x6F, 0x6E, 0x73, 0x74, 0x61, 0x6E, 0x74 }; + static const u_char Magic2[41] = /* "Pad to make it do more than one iteration" */ + { 0x50, 0x61, 0x64, 0x20, 0x74, 0x6F, 0x20, 0x6D, 0x61, 0x6B, + 0x65, 0x20, 0x69, 0x74, 0x20, 0x64, 0x6F, 0x20, 0x6D, 0x6F, + 0x72, 0x65, 0x20, 0x74, 0x68, 0x61, 0x6E, 0x20, 0x6F, 0x6E, + 0x65, 0x20, 0x69, 0x74, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6F, + 0x6E }; + + int i; + sha1_context sha1Context; + u_char Digest[SHA1_SIGNATURE_SIZE]; + u_char Challenge[8]; + + sha1_starts(&sha1Context); + sha1_update(&sha1Context, PasswordHashHash, MD4_SIGNATURE_SIZE); + sha1_update(&sha1Context, NTResponse, 24); + sha1_update(&sha1Context, Magic1, sizeof(Magic1)); + sha1_finish(&sha1Context, Digest); + + ChallengeHash(PeerChallenge, rchallenge, username, Challenge); + + sha1_starts(&sha1Context); + sha1_update(&sha1Context, Digest, sizeof(Digest)); + sha1_update(&sha1Context, Challenge, sizeof(Challenge)); + sha1_update(&sha1Context, Magic2, sizeof(Magic2)); + sha1_finish(&sha1Context, Digest); + + /* Convert to ASCII hex string. */ + for (i = 0; i < LWIP_MAX((MS_AUTH_RESPONSE_LENGTH / 2), (int)sizeof(Digest)); i++) + sprintf((char *)&authResponse[i * 2], "%02X", Digest[i]); +} + + +static void GenerateAuthenticatorResponsePlain( + const char *secret, int secret_len, + u_char NTResponse[24], const u_char PeerChallenge[16], + const u_char *rchallenge, const char *username, + u_char authResponse[MS_AUTH_RESPONSE_LENGTH+1]) { + u_char unicodePassword[MAX_NT_PASSWORD * 2]; + u_char PasswordHash[MD4_SIGNATURE_SIZE]; + u_char PasswordHashHash[MD4_SIGNATURE_SIZE]; + + /* Hash (x2) the Unicode version of the secret (== password). */ + ascii2unicode(secret, secret_len, unicodePassword); + NTPasswordHash(unicodePassword, secret_len * 2, PasswordHash); + NTPasswordHash(PasswordHash, sizeof(PasswordHash), + PasswordHashHash); + + GenerateAuthenticatorResponse(PasswordHashHash, NTResponse, PeerChallenge, + rchallenge, username, authResponse); +} + + +#if MPPE_SUPPORT +/* + * Set mppe_xxxx_key from MS-CHAP credentials. (see RFC 3079) + */ +static void Set_Start_Key(ppp_pcb *pcb, const u_char *rchallenge, const char *secret, int secret_len) { + u_char unicodePassword[MAX_NT_PASSWORD * 2]; + u_char PasswordHash[MD4_SIGNATURE_SIZE]; + u_char PasswordHashHash[MD4_SIGNATURE_SIZE]; + sha1_context sha1Context; + u_char Digest[SHA1_SIGNATURE_SIZE]; /* >= MPPE_MAX_KEY_LEN */ + + /* Hash (x2) the Unicode version of the secret (== password). */ + ascii2unicode(secret, secret_len, unicodePassword); + NTPasswordHash(unicodePassword, secret_len * 2, PasswordHash); + NTPasswordHash(PasswordHash, sizeof(PasswordHash), PasswordHashHash); + + sha1_starts(&sha1Context); + sha1_update(&sha1Context, PasswordHashHash, MD4_SIGNATURE_SIZE); + sha1_update(&sha1Context, PasswordHashHash, MD4_SIGNATURE_SIZE); + sha1_update(&sha1Context, rchallenge, 8); + sha1_finish(&sha1Context, Digest); + + /* Same key in both directions. */ + mppe_set_key(pcb, &pcb->mppe_comp, Digest); + mppe_set_key(pcb, &pcb->mppe_decomp, Digest); + + pcb->mppe_keys_set = 1; +} + +/* + * Set mppe_xxxx_key from MS-CHAPv2 credentials. (see RFC 3079) + */ +static void SetMasterKeys(ppp_pcb *pcb, const char *secret, int secret_len, u_char NTResponse[24], int IsServer) { + u_char unicodePassword[MAX_NT_PASSWORD * 2]; + u_char PasswordHash[MD4_SIGNATURE_SIZE]; + u_char PasswordHashHash[MD4_SIGNATURE_SIZE]; + sha1_context sha1Context; + u_char MasterKey[SHA1_SIGNATURE_SIZE]; /* >= MPPE_MAX_KEY_LEN */ + u_char Digest[SHA1_SIGNATURE_SIZE]; /* >= MPPE_MAX_KEY_LEN */ + const u_char *s; + + /* "This is the MPPE Master Key" */ + static const u_char Magic1[27] = + { 0x54, 0x68, 0x69, 0x73, 0x20, 0x69, 0x73, 0x20, 0x74, + 0x68, 0x65, 0x20, 0x4d, 0x50, 0x50, 0x45, 0x20, 0x4d, + 0x61, 0x73, 0x74, 0x65, 0x72, 0x20, 0x4b, 0x65, 0x79 }; + /* "On the client side, this is the send key; " + "on the server side, it is the receive key." */ + static const u_char Magic2[84] = + { 0x4f, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x63, 0x6c, 0x69, + 0x65, 0x6e, 0x74, 0x20, 0x73, 0x69, 0x64, 0x65, 0x2c, 0x20, + 0x74, 0x68, 0x69, 0x73, 0x20, 0x69, 0x73, 0x20, 0x74, 0x68, + 0x65, 0x20, 0x73, 0x65, 0x6e, 0x64, 0x20, 0x6b, 0x65, 0x79, + 0x3b, 0x20, 0x6f, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x73, + 0x65, 0x72, 0x76, 0x65, 0x72, 0x20, 0x73, 0x69, 0x64, 0x65, + 0x2c, 0x20, 0x69, 0x74, 0x20, 0x69, 0x73, 0x20, 0x74, 0x68, + 0x65, 0x20, 0x72, 0x65, 0x63, 0x65, 0x69, 0x76, 0x65, 0x20, + 0x6b, 0x65, 0x79, 0x2e }; + /* "On the client side, this is the receive key; " + "on the server side, it is the send key." */ + static const u_char Magic3[84] = + { 0x4f, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x63, 0x6c, 0x69, + 0x65, 0x6e, 0x74, 0x20, 0x73, 0x69, 0x64, 0x65, 0x2c, 0x20, + 0x74, 0x68, 0x69, 0x73, 0x20, 0x69, 0x73, 0x20, 0x74, 0x68, + 0x65, 0x20, 0x72, 0x65, 0x63, 0x65, 0x69, 0x76, 0x65, 0x20, + 0x6b, 0x65, 0x79, 0x3b, 0x20, 0x6f, 0x6e, 0x20, 0x74, 0x68, + 0x65, 0x20, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x20, 0x73, + 0x69, 0x64, 0x65, 0x2c, 0x20, 0x69, 0x74, 0x20, 0x69, 0x73, + 0x20, 0x74, 0x68, 0x65, 0x20, 0x73, 0x65, 0x6e, 0x64, 0x20, + 0x6b, 0x65, 0x79, 0x2e }; + + /* Hash (x2) the Unicode version of the secret (== password). */ + ascii2unicode(secret, secret_len, unicodePassword); + NTPasswordHash(unicodePassword, secret_len * 2, PasswordHash); + NTPasswordHash(PasswordHash, sizeof(PasswordHash), PasswordHashHash); + + sha1_starts(&sha1Context); + sha1_update(&sha1Context, PasswordHashHash, MD4_SIGNATURE_SIZE); + sha1_update(&sha1Context, NTResponse, 24); + sha1_update(&sha1Context, Magic1, sizeof(Magic1)); + sha1_finish(&sha1Context, MasterKey); + + /* + * generate send key + */ + if (IsServer) + s = Magic3; + else + s = Magic2; + sha1_starts(&sha1Context); + sha1_update(&sha1Context, MasterKey, 16); + sha1_update(&sha1Context, mppe_sha1_pad1, SHA1_PAD_SIZE); + sha1_update(&sha1Context, s, 84); + sha1_update(&sha1Context, mppe_sha1_pad2, SHA1_PAD_SIZE); + sha1_finish(&sha1Context, Digest); + + mppe_set_key(pcb, &pcb->mppe_comp, Digest); + + /* + * generate recv key + */ + if (IsServer) + s = Magic2; + else + s = Magic3; + sha1_starts(&sha1Context); + sha1_update(&sha1Context, MasterKey, 16); + sha1_update(&sha1Context, mppe_sha1_pad1, SHA1_PAD_SIZE); + sha1_update(&sha1Context, s, 84); + sha1_update(&sha1Context, mppe_sha1_pad2, SHA1_PAD_SIZE); + sha1_finish(&sha1Context, Digest); + + mppe_set_key(pcb, &pcb->mppe_decomp, Digest); + + pcb->mppe_keys_set = 1; +} + +#endif /* MPPE_SUPPORT */ + + +static void ChapMS(ppp_pcb *pcb, const u_char *rchallenge, const char *secret, int secret_len, + unsigned char *response) { +#if !MPPE_SUPPORT + LWIP_UNUSED_ARG(pcb); +#endif /* !MPPE_SUPPORT */ + BZERO(response, MS_CHAP_RESPONSE_LEN); + + ChapMS_NT(rchallenge, secret, secret_len, &response[MS_CHAP_NTRESP]); + +#ifdef MSLANMAN + ChapMS_LANMan(rchallenge, secret, secret_len, + &response[MS_CHAP_LANMANRESP]); + + /* preferred method is set by option */ + response[MS_CHAP_USENT] = !ms_lanman; +#else + response[MS_CHAP_USENT] = 1; +#endif + +#if MPPE_SUPPORT + Set_Start_Key(pcb, rchallenge, secret, secret_len); +#endif /* MPPE_SUPPORT */ +} + + +/* + * If PeerChallenge is NULL, one is generated and the PeerChallenge + * field of response is filled in. Call this way when generating a response. + * If PeerChallenge is supplied, it is copied into the PeerChallenge field. + * Call this way when verifying a response (or debugging). + * Do not call with PeerChallenge = response. + * + * The PeerChallenge field of response is then used for calculation of the + * Authenticator Response. + */ +static void ChapMS2(ppp_pcb *pcb, const u_char *rchallenge, const u_char *PeerChallenge, + const char *user, const char *secret, int secret_len, unsigned char *response, + u_char authResponse[], int authenticator) { + /* ARGSUSED */ + LWIP_UNUSED_ARG(authenticator); +#if !MPPE_SUPPORT + LWIP_UNUSED_ARG(pcb); +#endif /* !MPPE_SUPPORT */ + + BZERO(response, MS_CHAP2_RESPONSE_LEN); + + /* Generate the Peer-Challenge if requested, or copy it if supplied. */ + if (!PeerChallenge) + magic_random_bytes(&response[MS_CHAP2_PEER_CHALLENGE], MS_CHAP2_PEER_CHAL_LEN); + else + MEMCPY(&response[MS_CHAP2_PEER_CHALLENGE], PeerChallenge, + MS_CHAP2_PEER_CHAL_LEN); + + /* Generate the NT-Response */ + ChapMS2_NT(rchallenge, &response[MS_CHAP2_PEER_CHALLENGE], user, + secret, secret_len, &response[MS_CHAP2_NTRESP]); + + /* Generate the Authenticator Response. */ + GenerateAuthenticatorResponsePlain(secret, secret_len, + &response[MS_CHAP2_NTRESP], + &response[MS_CHAP2_PEER_CHALLENGE], + rchallenge, user, authResponse); + +#if MPPE_SUPPORT + SetMasterKeys(pcb, secret, secret_len, + &response[MS_CHAP2_NTRESP], authenticator); +#endif /* MPPE_SUPPORT */ +} + +#if 0 /* UNUSED */ +#if MPPE_SUPPORT +/* + * Set MPPE options from plugins. + */ +void set_mppe_enc_types(int policy, int types) { + /* Early exit for unknown policies. */ + if (policy != MPPE_ENC_POL_ENC_ALLOWED || + policy != MPPE_ENC_POL_ENC_REQUIRED) + return; + + /* Don't modify MPPE if it's optional and wasn't already configured. */ + if (policy == MPPE_ENC_POL_ENC_ALLOWED && !ccp_wantoptions[0].mppe) + return; + + /* + * Disable undesirable encryption types. Note that we don't ENABLE + * any encryption types, to avoid overriding manual configuration. + */ + switch(types) { + case MPPE_ENC_TYPES_RC4_40: + ccp_wantoptions[0].mppe &= ~MPPE_OPT_128; /* disable 128-bit */ + break; + case MPPE_ENC_TYPES_RC4_128: + ccp_wantoptions[0].mppe &= ~MPPE_OPT_40; /* disable 40-bit */ + break; + default: + break; + } +} +#endif /* MPPE_SUPPORT */ +#endif /* UNUSED */ + +const struct chap_digest_type chapms_digest = { + CHAP_MICROSOFT, /* code */ +#if PPP_SERVER + chapms_generate_challenge, + chapms_verify_response, +#endif /* PPP_SERVER */ + chapms_make_response, + NULL, /* check_success */ + chapms_handle_failure, +}; + +const struct chap_digest_type chapms2_digest = { + CHAP_MICROSOFT_V2, /* code */ +#if PPP_SERVER + chapms2_generate_challenge, + chapms2_verify_response, +#endif /* PPP_SERVER */ + chapms2_make_response, + chapms2_check_success, + chapms_handle_failure, +}; + +#endif /* PPP_SUPPORT && MSCHAP_SUPPORT */ diff --git a/components/lwip/netif/ppp/demand.c b/components/lwip/netif/ppp/demand.c new file mode 100755 index 0000000000..1cd9b6145e --- /dev/null +++ b/components/lwip/netif/ppp/demand.c @@ -0,0 +1,465 @@ +/* + * demand.c - Support routines for demand-dialling. + * + * Copyright (c) 1996-2002 Paul Mackerras. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. The name(s) of the authors of this software must not be used to + * endorse or promote products derived from this software without + * prior written permission. + * + * 3. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by Paul Mackerras + * ". + * + * THE AUTHORS OF THIS SOFTWARE DISCLAIM ALL WARRANTIES WITH REGARD TO + * THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS, IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY + * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN + * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING + * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include "lwip/opt.h" +#if PPP_SUPPORT && DEMAND_SUPPORT /* don't build if not configured for use in lwipopts.h */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#ifdef PPP_FILTER +#include +#endif + +#include "netif/ppp/ppp_impl.h" + +#include "netif/ppp/fsm.h" +#include "netif/ppp/ipcp.h" +#include "netif/ppp/lcp.h" + +char *frame; +int framelen; +int framemax; +int escape_flag; +int flush_flag; +int fcs; + +struct packet { + int length; + struct packet *next; + unsigned char data[1]; +}; + +struct packet *pend_q; +struct packet *pend_qtail; + +static int active_packet (unsigned char *, int); + +/* + * demand_conf - configure the interface for doing dial-on-demand. + */ +void +demand_conf() +{ + int i; + const struct protent *protp; + +/* framemax = lcp_allowoptions[0].mru; + if (framemax < PPP_MRU) */ + framemax = PPP_MRU; + framemax += PPP_HDRLEN + PPP_FCSLEN; + frame = malloc(framemax); + if (frame == NULL) + novm("demand frame"); + framelen = 0; + pend_q = NULL; + escape_flag = 0; + flush_flag = 0; + fcs = PPP_INITFCS; + + netif_set_mtu(pcb, LWIP_MIN(lcp_allowoptions[0].mru, PPP_MRU)); + if (ppp_send_config(pcb, PPP_MRU, (u32_t) 0, 0, 0) < 0 + || ppp_recv_config(pcb, PPP_MRU, (u32_t) 0, 0, 0) < 0) + fatal("Couldn't set up demand-dialled PPP interface: %m"); + +#ifdef PPP_FILTER + set_filters(&pass_filter, &active_filter); +#endif + + /* + * Call the demand_conf procedure for each protocol that's got one. + */ + for (i = 0; (protp = protocols[i]) != NULL; ++i) + if (protp->demand_conf != NULL) + ((*protp->demand_conf)(pcb)); +/* FIXME: find a way to die() here */ +#if 0 + if (!((*protp->demand_conf)(pcb))) + die(1); +#endif +} + + +/* + * demand_block - set each network protocol to block further packets. + */ +void +demand_block() +{ + int i; + const struct protent *protp; + + for (i = 0; (protp = protocols[i]) != NULL; ++i) + if (protp->demand_conf != NULL) + sifnpmode(pcb, protp->protocol & ~0x8000, NPMODE_QUEUE); + get_loop_output(); +} + +/* + * demand_discard - set each network protocol to discard packets + * with an error. + */ +void +demand_discard() +{ + struct packet *pkt, *nextpkt; + int i; + const struct protent *protp; + + for (i = 0; (protp = protocols[i]) != NULL; ++i) + if (protp->demand_conf != NULL) + sifnpmode(pcb, protp->protocol & ~0x8000, NPMODE_ERROR); + get_loop_output(); + + /* discard all saved packets */ + for (pkt = pend_q; pkt != NULL; pkt = nextpkt) { + nextpkt = pkt->next; + free(pkt); + } + pend_q = NULL; + framelen = 0; + flush_flag = 0; + escape_flag = 0; + fcs = PPP_INITFCS; +} + +/* + * demand_unblock - set each enabled network protocol to pass packets. + */ +void +demand_unblock() +{ + int i; + const struct protent *protp; + + for (i = 0; (protp = protocols[i]) != NULL; ++i) + if (protp->demand_conf != NULL) + sifnpmode(pcb, protp->protocol & ~0x8000, NPMODE_PASS); +} + +/* + * FCS lookup table as calculated by genfcstab. + */ +static u_short fcstab[256] = { + 0x0000, 0x1189, 0x2312, 0x329b, 0x4624, 0x57ad, 0x6536, 0x74bf, + 0x8c48, 0x9dc1, 0xaf5a, 0xbed3, 0xca6c, 0xdbe5, 0xe97e, 0xf8f7, + 0x1081, 0x0108, 0x3393, 0x221a, 0x56a5, 0x472c, 0x75b7, 0x643e, + 0x9cc9, 0x8d40, 0xbfdb, 0xae52, 0xdaed, 0xcb64, 0xf9ff, 0xe876, + 0x2102, 0x308b, 0x0210, 0x1399, 0x6726, 0x76af, 0x4434, 0x55bd, + 0xad4a, 0xbcc3, 0x8e58, 0x9fd1, 0xeb6e, 0xfae7, 0xc87c, 0xd9f5, + 0x3183, 0x200a, 0x1291, 0x0318, 0x77a7, 0x662e, 0x54b5, 0x453c, + 0xbdcb, 0xac42, 0x9ed9, 0x8f50, 0xfbef, 0xea66, 0xd8fd, 0xc974, + 0x4204, 0x538d, 0x6116, 0x709f, 0x0420, 0x15a9, 0x2732, 0x36bb, + 0xce4c, 0xdfc5, 0xed5e, 0xfcd7, 0x8868, 0x99e1, 0xab7a, 0xbaf3, + 0x5285, 0x430c, 0x7197, 0x601e, 0x14a1, 0x0528, 0x37b3, 0x263a, + 0xdecd, 0xcf44, 0xfddf, 0xec56, 0x98e9, 0x8960, 0xbbfb, 0xaa72, + 0x6306, 0x728f, 0x4014, 0x519d, 0x2522, 0x34ab, 0x0630, 0x17b9, + 0xef4e, 0xfec7, 0xcc5c, 0xddd5, 0xa96a, 0xb8e3, 0x8a78, 0x9bf1, + 0x7387, 0x620e, 0x5095, 0x411c, 0x35a3, 0x242a, 0x16b1, 0x0738, + 0xffcf, 0xee46, 0xdcdd, 0xcd54, 0xb9eb, 0xa862, 0x9af9, 0x8b70, + 0x8408, 0x9581, 0xa71a, 0xb693, 0xc22c, 0xd3a5, 0xe13e, 0xf0b7, + 0x0840, 0x19c9, 0x2b52, 0x3adb, 0x4e64, 0x5fed, 0x6d76, 0x7cff, + 0x9489, 0x8500, 0xb79b, 0xa612, 0xd2ad, 0xc324, 0xf1bf, 0xe036, + 0x18c1, 0x0948, 0x3bd3, 0x2a5a, 0x5ee5, 0x4f6c, 0x7df7, 0x6c7e, + 0xa50a, 0xb483, 0x8618, 0x9791, 0xe32e, 0xf2a7, 0xc03c, 0xd1b5, + 0x2942, 0x38cb, 0x0a50, 0x1bd9, 0x6f66, 0x7eef, 0x4c74, 0x5dfd, + 0xb58b, 0xa402, 0x9699, 0x8710, 0xf3af, 0xe226, 0xd0bd, 0xc134, + 0x39c3, 0x284a, 0x1ad1, 0x0b58, 0x7fe7, 0x6e6e, 0x5cf5, 0x4d7c, + 0xc60c, 0xd785, 0xe51e, 0xf497, 0x8028, 0x91a1, 0xa33a, 0xb2b3, + 0x4a44, 0x5bcd, 0x6956, 0x78df, 0x0c60, 0x1de9, 0x2f72, 0x3efb, + 0xd68d, 0xc704, 0xf59f, 0xe416, 0x90a9, 0x8120, 0xb3bb, 0xa232, + 0x5ac5, 0x4b4c, 0x79d7, 0x685e, 0x1ce1, 0x0d68, 0x3ff3, 0x2e7a, + 0xe70e, 0xf687, 0xc41c, 0xd595, 0xa12a, 0xb0a3, 0x8238, 0x93b1, + 0x6b46, 0x7acf, 0x4854, 0x59dd, 0x2d62, 0x3ceb, 0x0e70, 0x1ff9, + 0xf78f, 0xe606, 0xd49d, 0xc514, 0xb1ab, 0xa022, 0x92b9, 0x8330, + 0x7bc7, 0x6a4e, 0x58d5, 0x495c, 0x3de3, 0x2c6a, 0x1ef1, 0x0f78 +}; + +/* + * loop_chars - process characters received from the loopback. + * Calls loop_frame when a complete frame has been accumulated. + * Return value is 1 if we need to bring up the link, 0 otherwise. + */ +int +loop_chars(p, n) + unsigned char *p; + int n; +{ + int c, rv; + + rv = 0; + +/* check for synchronous connection... */ + + if ( (p[0] == 0xFF) && (p[1] == 0x03) ) { + rv = loop_frame(p,n); + return rv; + } + + for (; n > 0; --n) { + c = *p++; + if (c == PPP_FLAG) { + if (!escape_flag && !flush_flag + && framelen > 2 && fcs == PPP_GOODFCS) { + framelen -= 2; + if (loop_frame((unsigned char *)frame, framelen)) + rv = 1; + } + framelen = 0; + flush_flag = 0; + escape_flag = 0; + fcs = PPP_INITFCS; + continue; + } + if (flush_flag) + continue; + if (escape_flag) { + c ^= PPP_TRANS; + escape_flag = 0; + } else if (c == PPP_ESCAPE) { + escape_flag = 1; + continue; + } + if (framelen >= framemax) { + flush_flag = 1; + continue; + } + frame[framelen++] = c; + fcs = PPP_FCS(fcs, c); + } + return rv; +} + +/* + * loop_frame - given a frame obtained from the loopback, + * decide whether to bring up the link or not, and, if we want + * to transmit this frame later, put it on the pending queue. + * Return value is 1 if we need to bring up the link, 0 otherwise. + * We assume that the kernel driver has already applied the + * pass_filter, so we won't get packets it rejected. + * We apply the active_filter to see if we want this packet to + * bring up the link. + */ +int +loop_frame(frame, len) + unsigned char *frame; + int len; +{ + struct packet *pkt; + + /* dbglog("from loop: %P", frame, len); */ + if (len < PPP_HDRLEN) + return 0; + if ((PPP_PROTOCOL(frame) & 0x8000) != 0) + return 0; /* shouldn't get any of these anyway */ + if (!active_packet(frame, len)) + return 0; + + pkt = (struct packet *) malloc(sizeof(struct packet) + len); + if (pkt != NULL) { + pkt->length = len; + pkt->next = NULL; + memcpy(pkt->data, frame, len); + if (pend_q == NULL) + pend_q = pkt; + else + pend_qtail->next = pkt; + pend_qtail = pkt; + } + return 1; +} + +/* + * demand_rexmit - Resend all those frames which we got via the + * loopback, now that the real serial link is up. + */ +void +demand_rexmit(proto, newip) + int proto; + u32_t newip; +{ + struct packet *pkt, *prev, *nextpkt; + unsigned short checksum; + unsigned short pkt_checksum = 0; + unsigned iphdr; + struct timeval tv; + char cv = 0; + char ipstr[16]; + + prev = NULL; + pkt = pend_q; + pend_q = NULL; + tv.tv_sec = 1; + tv.tv_usec = 0; + select(0,NULL,NULL,NULL,&tv); /* Sleep for 1 Seconds */ + for (; pkt != NULL; pkt = nextpkt) { + nextpkt = pkt->next; + if (PPP_PROTOCOL(pkt->data) == proto) { + if ( (proto == PPP_IP) && newip ) { + /* Get old checksum */ + + iphdr = (pkt->data[4] & 15) << 2; + checksum = *((unsigned short *) (pkt->data+14)); + if (checksum == 0xFFFF) { + checksum = 0; + } + + + if (pkt->data[13] == 17) { + pkt_checksum = *((unsigned short *) (pkt->data+10+iphdr)); + if (pkt_checksum) { + cv = 1; + if (pkt_checksum == 0xFFFF) { + pkt_checksum = 0; + } + } + else { + cv = 0; + } + } + + if (pkt->data[13] == 6) { + pkt_checksum = *((unsigned short *) (pkt->data+20+iphdr)); + cv = 1; + if (pkt_checksum == 0xFFFF) { + pkt_checksum = 0; + } + } + + /* Delete old Source-IP-Address */ + checksum -= *((unsigned short *) (pkt->data+16)) ^ 0xFFFF; + checksum -= *((unsigned short *) (pkt->data+18)) ^ 0xFFFF; + + pkt_checksum -= *((unsigned short *) (pkt->data+16)) ^ 0xFFFF; + pkt_checksum -= *((unsigned short *) (pkt->data+18)) ^ 0xFFFF; + + /* Change Source-IP-Address */ + * ((u32_t *) (pkt->data + 16)) = newip; + + /* Add new Source-IP-Address */ + checksum += *((unsigned short *) (pkt->data+16)) ^ 0xFFFF; + checksum += *((unsigned short *) (pkt->data+18)) ^ 0xFFFF; + + pkt_checksum += *((unsigned short *) (pkt->data+16)) ^ 0xFFFF; + pkt_checksum += *((unsigned short *) (pkt->data+18)) ^ 0xFFFF; + + /* Write new checksum */ + if (!checksum) { + checksum = 0xFFFF; + } + *((unsigned short *) (pkt->data+14)) = checksum; + if (pkt->data[13] == 6) { + *((unsigned short *) (pkt->data+20+iphdr)) = pkt_checksum; + } + if (cv && (pkt->data[13] == 17) ) { + *((unsigned short *) (pkt->data+10+iphdr)) = pkt_checksum; + } + + /* Log Packet */ + strcpy(ipstr,inet_ntoa(*( (struct in_addr *) (pkt->data+16)))); + if (pkt->data[13] == 1) { + syslog(LOG_INFO,"Open ICMP %s -> %s\n", + ipstr, + inet_ntoa(*( (struct in_addr *) (pkt->data+20)))); + } else { + syslog(LOG_INFO,"Open %s %s:%d -> %s:%d\n", + pkt->data[13] == 6 ? "TCP" : "UDP", + ipstr, + ntohs(*( (short *) (pkt->data+iphdr+4))), + inet_ntoa(*( (struct in_addr *) (pkt->data+20))), + ntohs(*( (short *) (pkt->data+iphdr+6)))); + } + } + output(pcb, pkt->data, pkt->length); + free(pkt); + } else { + if (prev == NULL) + pend_q = pkt; + else + prev->next = pkt; + prev = pkt; + } + } + pend_qtail = prev; + if (prev != NULL) + prev->next = NULL; +} + +/* + * Scan a packet to decide whether it is an "active" packet, + * that is, whether it is worth bringing up the link for. + */ +static int +active_packet(p, len) + unsigned char *p; + int len; +{ + int proto, i; + const struct protent *protp; + + if (len < PPP_HDRLEN) + return 0; + proto = PPP_PROTOCOL(p); +#ifdef PPP_FILTER + p[0] = 1; /* outbound packet indicator */ + if ((pass_filter.bf_len != 0 + && bpf_filter(pass_filter.bf_insns, p, len, len) == 0) + || (active_filter.bf_len != 0 + && bpf_filter(active_filter.bf_insns, p, len, len) == 0)) { + p[0] = 0xff; + return 0; + } + p[0] = 0xff; +#endif + for (i = 0; (protp = protocols[i]) != NULL; ++i) { + if (protp->protocol < 0xC000 && (protp->protocol & ~0x8000) == proto) { + if (protp->active_pkt == NULL) + return 1; + return (*protp->active_pkt)(p, len); + } + } + return 0; /* not a supported protocol !!?? */ +} + +#endif /* PPP_SUPPORT && DEMAND_SUPPORT */ diff --git a/components/lwip/netif/ppp/eap.c b/components/lwip/netif/ppp/eap.c new file mode 100755 index 0000000000..5882065242 --- /dev/null +++ b/components/lwip/netif/ppp/eap.c @@ -0,0 +1,2429 @@ +/* + * eap.c - Extensible Authentication Protocol for PPP (RFC 2284) + * + * Copyright (c) 2001 by Sun Microsystems, Inc. + * All rights reserved. + * + * Non-exclusive rights to redistribute, modify, translate, and use + * this software in source and binary forms, in whole or in part, is + * hereby granted, provided that the above copyright notice is + * duplicated in any source form, and that neither the name of the + * copyright holder nor the author is used to endorse or promote + * products derived from this software. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED + * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. + * + * Original version by James Carlson + * + * This implementation of EAP supports MD5-Challenge and SRP-SHA1 + * authentication styles. Note that support of MD5-Challenge is a + * requirement of RFC 2284, and that it's essentially just a + * reimplementation of regular RFC 1994 CHAP using EAP messages. + * + * As an authenticator ("server"), there are multiple phases for each + * style. In the first phase of each style, the unauthenticated peer + * name is queried using the EAP Identity request type. If the + * "remotename" option is used, then this phase is skipped, because + * the peer's name is presumed to be known. + * + * For MD5-Challenge, there are two phases, and the second phase + * consists of sending the challenge itself and handling the + * associated response. + * + * For SRP-SHA1, there are four phases. The second sends 's', 'N', + * and 'g'. The reply contains 'A'. The third sends 'B', and the + * reply contains 'M1'. The forth sends the 'M2' value. + * + * As an authenticatee ("client"), there's just a single phase -- + * responding to the queries generated by the peer. EAP is an + * authenticator-driven protocol. + * + * Based on draft-ietf-pppext-eap-srp-03.txt. + */ + +#include "lwip/opt.h" +#if PPP_SUPPORT && EAP_SUPPORT /* don't build if not configured for use in lwipopts.h */ + +#include "netif/ppp/ppp_impl.h" + +#if LWIP_INCLUDED_POLARSSL_MD5 +#include "netif/ppp/polarssl/md5.h" +#else +#include "polarssl/md5.h" +#endif + +#include "netif/ppp/eap.h" +#include "netif/ppp/magic.h" + +#ifdef USE_SRP +#include +#include +#include +#include "netif/ppp/pppcrypt.h" +#endif /* USE_SRP */ + +#ifndef SHA_DIGESTSIZE +#define SHA_DIGESTSIZE 20 +#endif + +#ifdef USE_SRP +static char *pn_secret = NULL; /* Pseudonym generating secret */ +#endif + +#if PPP_OPTIONS +/* + * Command-line options. + */ +static option_t eap_option_list[] = { + { "eap-restart", o_int, &eap_states[0].es_server.ea_timeout, + "Set retransmit timeout for EAP Requests (server)" }, + { "eap-max-sreq", o_int, &eap_states[0].es_server.ea_maxrequests, + "Set max number of EAP Requests sent (server)" }, + { "eap-timeout", o_int, &eap_states[0].es_client.ea_timeout, + "Set time limit for peer EAP authentication" }, + { "eap-max-rreq", o_int, &eap_states[0].es_client.ea_maxrequests, + "Set max number of EAP Requests allows (client)" }, + { "eap-interval", o_int, &eap_states[0].es_rechallenge, + "Set interval for EAP rechallenge" }, +#ifdef USE_SRP + { "srp-interval", o_int, &eap_states[0].es_lwrechallenge, + "Set interval for SRP lightweight rechallenge" }, + { "srp-pn-secret", o_string, &pn_secret, + "Long term pseudonym generation secret" }, + { "srp-use-pseudonym", o_bool, &eap_states[0].es_usepseudo, + "Use pseudonym if offered one by server", 1 }, +#endif + { NULL } +}; +#endif /* PPP_OPTIONS */ + +/* + * Protocol entry points. + */ +static void eap_init(ppp_pcb *pcb); +static void eap_input(ppp_pcb *pcb, u_char *inp, int inlen); +static void eap_protrej(ppp_pcb *pcb); +static void eap_lowerup(ppp_pcb *pcb); +static void eap_lowerdown(ppp_pcb *pcb); +#if PRINTPKT_SUPPORT +static int eap_printpkt(const u_char *inp, int inlen, + void (*)(void *arg, const char *fmt, ...), void *arg); +#endif /* PRINTPKT_SUPPORT */ + +const struct protent eap_protent = { + PPP_EAP, /* protocol number */ + eap_init, /* initialization procedure */ + eap_input, /* process a received packet */ + eap_protrej, /* process a received protocol-reject */ + eap_lowerup, /* lower layer has gone up */ + eap_lowerdown, /* lower layer has gone down */ + NULL, /* open the protocol */ + NULL, /* close the protocol */ +#if PRINTPKT_SUPPORT + eap_printpkt, /* print a packet in readable form */ +#endif /* PRINTPKT_SUPPORT */ +#if PPP_DATAINPUT + NULL, /* process a received data packet */ +#endif /* PPP_DATAINPUT */ +#if PRINTPKT_SUPPORT + "EAP", /* text name of protocol */ + NULL, /* text name of corresponding data protocol */ +#endif /* PRINTPKT_SUPPORT */ +#if PPP_OPTIONS + eap_option_list, /* list of command-line options */ + NULL, /* check requested options; assign defaults */ +#endif /* PPP_OPTIONS */ +#if DEMAND_SUPPORT + NULL, /* configure interface for demand-dial */ + NULL /* say whether to bring up link for this pkt */ +#endif /* DEMAND_SUPPORT */ +}; + +#ifdef USE_SRP +/* + * A well-known 2048 bit modulus. + */ +static const u_char wkmodulus[] = { + 0xAC, 0x6B, 0xDB, 0x41, 0x32, 0x4A, 0x9A, 0x9B, + 0xF1, 0x66, 0xDE, 0x5E, 0x13, 0x89, 0x58, 0x2F, + 0xAF, 0x72, 0xB6, 0x65, 0x19, 0x87, 0xEE, 0x07, + 0xFC, 0x31, 0x92, 0x94, 0x3D, 0xB5, 0x60, 0x50, + 0xA3, 0x73, 0x29, 0xCB, 0xB4, 0xA0, 0x99, 0xED, + 0x81, 0x93, 0xE0, 0x75, 0x77, 0x67, 0xA1, 0x3D, + 0xD5, 0x23, 0x12, 0xAB, 0x4B, 0x03, 0x31, 0x0D, + 0xCD, 0x7F, 0x48, 0xA9, 0xDA, 0x04, 0xFD, 0x50, + 0xE8, 0x08, 0x39, 0x69, 0xED, 0xB7, 0x67, 0xB0, + 0xCF, 0x60, 0x95, 0x17, 0x9A, 0x16, 0x3A, 0xB3, + 0x66, 0x1A, 0x05, 0xFB, 0xD5, 0xFA, 0xAA, 0xE8, + 0x29, 0x18, 0xA9, 0x96, 0x2F, 0x0B, 0x93, 0xB8, + 0x55, 0xF9, 0x79, 0x93, 0xEC, 0x97, 0x5E, 0xEA, + 0xA8, 0x0D, 0x74, 0x0A, 0xDB, 0xF4, 0xFF, 0x74, + 0x73, 0x59, 0xD0, 0x41, 0xD5, 0xC3, 0x3E, 0xA7, + 0x1D, 0x28, 0x1E, 0x44, 0x6B, 0x14, 0x77, 0x3B, + 0xCA, 0x97, 0xB4, 0x3A, 0x23, 0xFB, 0x80, 0x16, + 0x76, 0xBD, 0x20, 0x7A, 0x43, 0x6C, 0x64, 0x81, + 0xF1, 0xD2, 0xB9, 0x07, 0x87, 0x17, 0x46, 0x1A, + 0x5B, 0x9D, 0x32, 0xE6, 0x88, 0xF8, 0x77, 0x48, + 0x54, 0x45, 0x23, 0xB5, 0x24, 0xB0, 0xD5, 0x7D, + 0x5E, 0xA7, 0x7A, 0x27, 0x75, 0xD2, 0xEC, 0xFA, + 0x03, 0x2C, 0xFB, 0xDB, 0xF5, 0x2F, 0xB3, 0x78, + 0x61, 0x60, 0x27, 0x90, 0x04, 0xE5, 0x7A, 0xE6, + 0xAF, 0x87, 0x4E, 0x73, 0x03, 0xCE, 0x53, 0x29, + 0x9C, 0xCC, 0x04, 0x1C, 0x7B, 0xC3, 0x08, 0xD8, + 0x2A, 0x56, 0x98, 0xF3, 0xA8, 0xD0, 0xC3, 0x82, + 0x71, 0xAE, 0x35, 0xF8, 0xE9, 0xDB, 0xFB, 0xB6, + 0x94, 0xB5, 0xC8, 0x03, 0xD8, 0x9F, 0x7A, 0xE4, + 0x35, 0xDE, 0x23, 0x6D, 0x52, 0x5F, 0x54, 0x75, + 0x9B, 0x65, 0xE3, 0x72, 0xFC, 0xD6, 0x8E, 0xF2, + 0x0F, 0xA7, 0x11, 0x1F, 0x9E, 0x4A, 0xFF, 0x73 +}; +#endif + +#if PPP_SERVER +/* Local forward declarations. */ +static void eap_server_timeout(void *arg); +#endif /* PPP_SERVER */ + +/* + * Convert EAP state code to printable string for debug. + */ +static const char * eap_state_name(enum eap_state_code esc) +{ + static const char *state_names[] = { EAP_STATES }; + + return (state_names[(int)esc]); +} + +/* + * eap_init - Initialize state for an EAP user. This is currently + * called once by main() during start-up. + */ +static void eap_init(ppp_pcb *pcb) { + + BZERO(&pcb->eap, sizeof(eap_state)); +#if PPP_SERVER + pcb->eap.es_server.ea_id = magic(); +#endif /* PPP_SERVER */ +} + +/* + * eap_client_timeout - Give up waiting for the peer to send any + * Request messages. + */ +static void eap_client_timeout(void *arg) { + ppp_pcb *pcb = (ppp_pcb*)arg; + + if (!eap_client_active(pcb)) + return; + + ppp_error("EAP: timeout waiting for Request from peer"); + auth_withpeer_fail(pcb, PPP_EAP); + pcb->eap.es_client.ea_state = eapBadAuth; +} + +/* + * eap_authwithpeer - Authenticate to our peer (behave as client). + * + * Start client state and wait for requests. This is called only + * after eap_lowerup. + */ +void eap_authwithpeer(ppp_pcb *pcb, const char *localname) { + + if(NULL == localname) + return; + + /* Save the peer name we're given */ + pcb->eap.es_client.ea_name = localname; + pcb->eap.es_client.ea_namelen = strlen(localname); + + pcb->eap.es_client.ea_state = eapListen; + + /* + * Start a timer so that if the other end just goes + * silent, we don't sit here waiting forever. + */ + if (pcb->settings.eap_req_time > 0) + TIMEOUT(eap_client_timeout, pcb, + pcb->settings.eap_req_time); +} + +#if PPP_SERVER +/* + * Format a standard EAP Failure message and send it to the peer. + * (Server operation) + */ +static void eap_send_failure(ppp_pcb *pcb) { + struct pbuf *p; + u_char *outp; + + p = pbuf_alloc(PBUF_RAW, (u16_t)(PPP_HDRLEN + EAP_HEADERLEN), PPP_CTRL_PBUF_TYPE); + if(NULL == p) + return; + if(p->tot_len != p->len) { + pbuf_free(p); + return; + } + + outp = (u_char*)p->payload; + + MAKEHEADER(outp, PPP_EAP); + + PUTCHAR(EAP_FAILURE, outp); + pcb->eap.es_server.ea_id++; + PUTCHAR(pcb->eap.es_server.ea_id, outp); + PUTSHORT(EAP_HEADERLEN, outp); + + ppp_write(pcb, p); + + pcb->eap.es_server.ea_state = eapBadAuth; + auth_peer_fail(pcb, PPP_EAP); +} + +/* + * Format a standard EAP Success message and send it to the peer. + * (Server operation) + */ +static void eap_send_success(ppp_pcb *pcb) { + struct pbuf *p; + u_char *outp; + + p = pbuf_alloc(PBUF_RAW, (u16_t)(PPP_HDRLEN + EAP_HEADERLEN), PPP_CTRL_PBUF_TYPE); + if(NULL == p) + return; + if(p->tot_len != p->len) { + pbuf_free(p); + return; + } + + outp = (u_char*)p->payload; + + MAKEHEADER(outp, PPP_EAP); + + PUTCHAR(EAP_SUCCESS, outp); + pcb->eap.es_server.ea_id++; + PUTCHAR(pcb->eap.es_server.ea_id, outp); + PUTSHORT(EAP_HEADERLEN, outp); + + ppp_write(pcb, p); + + auth_peer_success(pcb, PPP_EAP, 0, + pcb->eap.es_server.ea_peer, pcb->eap.es_server.ea_peerlen); +} +#endif /* PPP_SERVER */ + +#ifdef USE_SRP +/* + * Set DES key according to pseudonym-generating secret and current + * date. + */ +static bool +pncrypt_setkey(int timeoffs) +{ + struct tm *tp; + char tbuf[9]; + SHA1_CTX ctxt; + u_char dig[SHA_DIGESTSIZE]; + time_t reftime; + + if (pn_secret == NULL) + return (0); + reftime = time(NULL) + timeoffs; + tp = localtime(&reftime); + SHA1Init(&ctxt); + SHA1Update(&ctxt, pn_secret, strlen(pn_secret)); + strftime(tbuf, sizeof (tbuf), "%Y%m%d", tp); + SHA1Update(&ctxt, tbuf, strlen(tbuf)); + SHA1Final(dig, &ctxt); + /* FIXME: if we want to do SRP, we need to find a way to pass the PolarSSL des_context instead of using static memory */ + return (DesSetkey(dig)); +} + +static char base64[] = +"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; + +struct b64state { + u32_t bs_bits; + int bs_offs; +}; + +static int +b64enc(bs, inp, inlen, outp) +struct b64state *bs; +u_char *inp; +int inlen; +u_char *outp; +{ + int outlen = 0; + + while (inlen > 0) { + bs->bs_bits = (bs->bs_bits << 8) | *inp++; + inlen--; + bs->bs_offs += 8; + if (bs->bs_offs >= 24) { + *outp++ = base64[(bs->bs_bits >> 18) & 0x3F]; + *outp++ = base64[(bs->bs_bits >> 12) & 0x3F]; + *outp++ = base64[(bs->bs_bits >> 6) & 0x3F]; + *outp++ = base64[bs->bs_bits & 0x3F]; + outlen += 4; + bs->bs_offs = 0; + bs->bs_bits = 0; + } + } + return (outlen); +} + +static int +b64flush(bs, outp) +struct b64state *bs; +u_char *outp; +{ + int outlen = 0; + + if (bs->bs_offs == 8) { + *outp++ = base64[(bs->bs_bits >> 2) & 0x3F]; + *outp++ = base64[(bs->bs_bits << 4) & 0x3F]; + outlen = 2; + } else if (bs->bs_offs == 16) { + *outp++ = base64[(bs->bs_bits >> 10) & 0x3F]; + *outp++ = base64[(bs->bs_bits >> 4) & 0x3F]; + *outp++ = base64[(bs->bs_bits << 2) & 0x3F]; + outlen = 3; + } + bs->bs_offs = 0; + bs->bs_bits = 0; + return (outlen); +} + +static int +b64dec(bs, inp, inlen, outp) +struct b64state *bs; +u_char *inp; +int inlen; +u_char *outp; +{ + int outlen = 0; + char *cp; + + while (inlen > 0) { + if ((cp = strchr(base64, *inp++)) == NULL) + break; + bs->bs_bits = (bs->bs_bits << 6) | (cp - base64); + inlen--; + bs->bs_offs += 6; + if (bs->bs_offs >= 8) { + *outp++ = bs->bs_bits >> (bs->bs_offs - 8); + outlen++; + bs->bs_offs -= 8; + } + } + return (outlen); +} +#endif /* USE_SRP */ + +#if PPP_SERVER +/* + * Assume that current waiting server state is complete and figure + * next state to use based on available authentication data. 'status' + * indicates if there was an error in handling the last query. It is + * 0 for success and non-zero for failure. + */ +static void eap_figure_next_state(ppp_pcb *pcb, int status) { +#ifdef USE_SRP + unsigned char secbuf[MAXSECRETLEN], clear[8], *sp, *dp; + struct t_pw tpw; + struct t_confent *tce, mytce; + char *cp, *cp2; + struct t_server *ts; + int id, i, plen, toffs; + u_char vals[2]; + struct b64state bs; +#endif /* USE_SRP */ + + pcb->settings.eap_timeout_time = pcb->eap.es_savedtime; + switch (pcb->eap.es_server.ea_state) { + case eapBadAuth: + return; + + case eapIdentify: +#ifdef USE_SRP + /* Discard any previous session. */ + ts = (struct t_server *)pcb->eap.es_server.ea_session; + if (ts != NULL) { + t_serverclose(ts); + pcb->eap.es_server.ea_session = NULL; + pcb->eap.es_server.ea_skey = NULL; + } +#endif /* USE_SRP */ + if (status != 0) { + pcb->eap.es_server.ea_state = eapBadAuth; + break; + } +#ifdef USE_SRP + /* If we've got a pseudonym, try to decode to real name. */ + if (pcb->eap.es_server.ea_peerlen > SRP_PSEUDO_LEN && + strncmp(pcb->eap.es_server.ea_peer, SRP_PSEUDO_ID, + SRP_PSEUDO_LEN) == 0 && + (pcb->eap.es_server.ea_peerlen - SRP_PSEUDO_LEN) * 3 / 4 < + sizeof (secbuf)) { + BZERO(&bs, sizeof (bs)); + plen = b64dec(&bs, + pcb->eap.es_server.ea_peer + SRP_PSEUDO_LEN, + pcb->eap.es_server.ea_peerlen - SRP_PSEUDO_LEN, + secbuf); + toffs = 0; + for (i = 0; i < 5; i++) { + pncrypt_setkey(toffs); + toffs -= 86400; + /* FIXME: if we want to do SRP, we need to find a way to pass the PolarSSL des_context instead of using static memory */ + if (!DesDecrypt(secbuf, clear)) { + ppp_dbglog("no DES here; cannot decode " + "pseudonym"); + return; + } + id = *(unsigned char *)clear; + if (id + 1 <= plen && id + 9 > plen) + break; + } + if (plen % 8 == 0 && i < 5) { + /* + * Note that this is always shorter than the + * original stored string, so there's no need + * to realloc. + */ + if ((i = plen = *(unsigned char *)clear) > 7) + i = 7; + pcb->eap.es_server.ea_peerlen = plen; + dp = (unsigned char *)pcb->eap.es_server.ea_peer; + MEMCPY(dp, clear + 1, i); + plen -= i; + dp += i; + sp = secbuf + 8; + while (plen > 0) { + /* FIXME: if we want to do SRP, we need to find a way to pass the PolarSSL des_context instead of using static memory */ + (void) DesDecrypt(sp, dp); + sp += 8; + dp += 8; + plen -= 8; + } + pcb->eap.es_server.ea_peer[ + pcb->eap.es_server.ea_peerlen] = '\0'; + ppp_dbglog("decoded pseudonym to \"%.*q\"", + pcb->eap.es_server.ea_peerlen, + pcb->eap.es_server.ea_peer); + } else { + ppp_dbglog("failed to decode real name"); + /* Stay in eapIdentfy state; requery */ + break; + } + } + /* Look up user in secrets database. */ + if (get_srp_secret(pcb->eap.es_unit, pcb->eap.es_server.ea_peer, + pcb->eap.es_server.ea_name, (char *)secbuf, 1) != 0) { + /* Set up default in case SRP entry is bad */ + pcb->eap.es_server.ea_state = eapMD5Chall; + /* Get t_confent based on index in srp-secrets */ + id = strtol((char *)secbuf, &cp, 10); + if (*cp++ != ':' || id < 0) + break; + if (id == 0) { + mytce.index = 0; + mytce.modulus.data = (u_char *)wkmodulus; + mytce.modulus.len = sizeof (wkmodulus); + mytce.generator.data = (u_char *)"\002"; + mytce.generator.len = 1; + tce = &mytce; + } else if ((tce = gettcid(id)) != NULL) { + /* + * Client will have to verify this modulus/ + * generator combination, and that will take + * a while. Lengthen the timeout here. + */ + if (pcb->settings.eap_timeout_time > 0 && + pcb->settings.eap_timeout_time < 30) + pcb->settings.eap_timeout_time = 30; + } else { + break; + } + if ((cp2 = strchr(cp, ':')) == NULL) + break; + *cp2++ = '\0'; + tpw.pebuf.name = pcb->eap.es_server.ea_peer; + tpw.pebuf.password.len = t_fromb64((char *)tpw.pwbuf, + cp); + tpw.pebuf.password.data = tpw.pwbuf; + tpw.pebuf.salt.len = t_fromb64((char *)tpw.saltbuf, + cp2); + tpw.pebuf.salt.data = tpw.saltbuf; + if ((ts = t_serveropenraw(&tpw.pebuf, tce)) == NULL) + break; + pcb->eap.es_server.ea_session = (void *)ts; + pcb->eap.es_server.ea_state = eapSRP1; + vals[0] = pcb->eap.es_server.ea_id + 1; + vals[1] = EAPT_SRP; + t_serveraddexdata(ts, vals, 2); + /* Generate B; must call before t_servergetkey() */ + t_servergenexp(ts); + break; + } +#endif /* USE_SRP */ + pcb->eap.es_server.ea_state = eapMD5Chall; + break; + + case eapSRP1: +#ifdef USE_SRP + ts = (struct t_server *)pcb->eap.es_server.ea_session; + if (ts != NULL && status != 0) { + t_serverclose(ts); + pcb->eap.es_server.ea_session = NULL; + pcb->eap.es_server.ea_skey = NULL; + } +#endif /* USE_SRP */ + if (status == 1) { + pcb->eap.es_server.ea_state = eapMD5Chall; + } else if (status != 0 || pcb->eap.es_server.ea_session == NULL) { + pcb->eap.es_server.ea_state = eapBadAuth; + } else { + pcb->eap.es_server.ea_state = eapSRP2; + } + break; + + case eapSRP2: +#ifdef USE_SRP + ts = (struct t_server *)pcb->eap.es_server.ea_session; + if (ts != NULL && status != 0) { + t_serverclose(ts); + pcb->eap.es_server.ea_session = NULL; + pcb->eap.es_server.ea_skey = NULL; + } +#endif /* USE_SRP */ + if (status != 0 || pcb->eap.es_server.ea_session == NULL) { + pcb->eap.es_server.ea_state = eapBadAuth; + } else { + pcb->eap.es_server.ea_state = eapSRP3; + } + break; + + case eapSRP3: + case eapSRP4: +#ifdef USE_SRP + ts = (struct t_server *)pcb->eap.es_server.ea_session; + if (ts != NULL && status != 0) { + t_serverclose(ts); + pcb->eap.es_server.ea_session = NULL; + pcb->eap.es_server.ea_skey = NULL; + } +#endif /* USE_SRP */ + if (status != 0 || pcb->eap.es_server.ea_session == NULL) { + pcb->eap.es_server.ea_state = eapBadAuth; + } else { + pcb->eap.es_server.ea_state = eapOpen; + } + break; + + case eapMD5Chall: + if (status != 0) { + pcb->eap.es_server.ea_state = eapBadAuth; + } else { + pcb->eap.es_server.ea_state = eapOpen; + } + break; + + default: + pcb->eap.es_server.ea_state = eapBadAuth; + break; + } + if (pcb->eap.es_server.ea_state == eapBadAuth) + eap_send_failure(pcb); +} + +/* + * Format an EAP Request message and send it to the peer. Message + * type depends on current state. (Server operation) + */ +static void eap_send_request(ppp_pcb *pcb) { + struct pbuf *p; + u_char *outp; + u_char *lenloc; + int outlen; + int len; + const char *str; +#ifdef USE_SRP + struct t_server *ts; + u_char clear[8], cipher[8], dig[SHA_DIGESTSIZE], *optr, *cp; + int i, j; + struct b64state b64; + SHA1_CTX ctxt; +#endif /* USE_SRP */ + + /* Handle both initial auth and restart */ + if (pcb->eap.es_server.ea_state < eapIdentify && + pcb->eap.es_server.ea_state != eapInitial) { + pcb->eap.es_server.ea_state = eapIdentify; +#if PPP_REMOTENAME + if (pcb->settings.explicit_remote && pcb->remote_name) { + /* + * If we already know the peer's + * unauthenticated name, then there's no + * reason to ask. Go to next state instead. + */ + int len = (int)strlen(pcb->remote_name); + if (len > MAXNAMELEN) { + len = MAXNAMELEN; + } + MEMCPY(pcb->eap.es_server.ea_peer, pcb->remote_name, len); + pcb->eap.es_server.ea_peer[len] = '\0'; + pcb->eap.es_server.ea_peerlen = len; + eap_figure_next_state(pcb, 0); + } +#endif /* PPP_REMOTENAME */ + } + + if (pcb->settings.eap_max_transmits > 0 && + pcb->eap.es_server.ea_requests >= pcb->settings.eap_max_transmits) { + if (pcb->eap.es_server.ea_responses > 0) + ppp_error("EAP: too many Requests sent"); + else + ppp_error("EAP: no response to Requests"); + eap_send_failure(pcb); + return; + } + + p = pbuf_alloc(PBUF_RAW, (u16_t)(PPP_CTRL_PBUF_MAX_SIZE), PPP_CTRL_PBUF_TYPE); + if(NULL == p) + return; + if(p->tot_len != p->len) { + pbuf_free(p); + return; + } + + outp = (u_char*)p->payload; + + MAKEHEADER(outp, PPP_EAP); + + PUTCHAR(EAP_REQUEST, outp); + PUTCHAR(pcb->eap.es_server.ea_id, outp); + lenloc = outp; + INCPTR(2, outp); + + switch (pcb->eap.es_server.ea_state) { + case eapIdentify: + PUTCHAR(EAPT_IDENTITY, outp); + str = "Name"; + len = strlen(str); + MEMCPY(outp, str, len); + INCPTR(len, outp); + break; + + case eapMD5Chall: + PUTCHAR(EAPT_MD5CHAP, outp); + /* + * pick a random challenge length between + * EAP_MIN_CHALLENGE_LENGTH and EAP_MAX_CHALLENGE_LENGTH + */ + pcb->eap.es_challen = EAP_MIN_CHALLENGE_LENGTH + + magic_pow(EAP_MIN_MAX_POWER_OF_TWO_CHALLENGE_LENGTH); + PUTCHAR(pcb->eap.es_challen, outp); + magic_random_bytes(pcb->eap.es_challenge, pcb->eap.es_challen); + MEMCPY(outp, pcb->eap.es_challenge, pcb->eap.es_challen); + INCPTR(pcb->eap.es_challen, outp); + MEMCPY(outp, pcb->eap.es_server.ea_name, pcb->eap.es_server.ea_namelen); + INCPTR(pcb->eap.es_server.ea_namelen, outp); + break; + +#ifdef USE_SRP + case eapSRP1: + PUTCHAR(EAPT_SRP, outp); + PUTCHAR(EAPSRP_CHALLENGE, outp); + + PUTCHAR(pcb->eap.es_server.ea_namelen, outp); + MEMCPY(outp, pcb->eap.es_server.ea_name, pcb->eap.es_server.ea_namelen); + INCPTR(pcb->eap.es_server.ea_namelen, outp); + + ts = (struct t_server *)pcb->eap.es_server.ea_session; + assert(ts != NULL); + PUTCHAR(ts->s.len, outp); + MEMCPY(outp, ts->s.data, ts->s.len); + INCPTR(ts->s.len, outp); + + if (ts->g.len == 1 && ts->g.data[0] == 2) { + PUTCHAR(0, outp); + } else { + PUTCHAR(ts->g.len, outp); + MEMCPY(outp, ts->g.data, ts->g.len); + INCPTR(ts->g.len, outp); + } + + if (ts->n.len != sizeof (wkmodulus) || + BCMP(ts->n.data, wkmodulus, sizeof (wkmodulus)) != 0) { + MEMCPY(outp, ts->n.data, ts->n.len); + INCPTR(ts->n.len, outp); + } + break; + + case eapSRP2: + PUTCHAR(EAPT_SRP, outp); + PUTCHAR(EAPSRP_SKEY, outp); + + ts = (struct t_server *)pcb->eap.es_server.ea_session; + assert(ts != NULL); + MEMCPY(outp, ts->B.data, ts->B.len); + INCPTR(ts->B.len, outp); + break; + + case eapSRP3: + PUTCHAR(EAPT_SRP, outp); + PUTCHAR(EAPSRP_SVALIDATOR, outp); + PUTLONG(SRPVAL_EBIT, outp); + ts = (struct t_server *)pcb->eap.es_server.ea_session; + assert(ts != NULL); + MEMCPY(outp, t_serverresponse(ts), SHA_DIGESTSIZE); + INCPTR(SHA_DIGESTSIZE, outp); + + if (pncrypt_setkey(0)) { + /* Generate pseudonym */ + optr = outp; + cp = (unsigned char *)pcb->eap.es_server.ea_peer; + if ((j = i = pcb->eap.es_server.ea_peerlen) > 7) + j = 7; + clear[0] = i; + MEMCPY(clear + 1, cp, j); + i -= j; + cp += j; + /* FIXME: if we want to do SRP, we need to find a way to pass the PolarSSL des_context instead of using static memory */ + if (!DesEncrypt(clear, cipher)) { + ppp_dbglog("no DES here; not generating pseudonym"); + break; + } + BZERO(&b64, sizeof (b64)); + outp++; /* space for pseudonym length */ + outp += b64enc(&b64, cipher, 8, outp); + while (i >= 8) { + /* FIXME: if we want to do SRP, we need to find a way to pass the PolarSSL des_context instead of using static memory */ + (void) DesEncrypt(cp, cipher); + outp += b64enc(&b64, cipher, 8, outp); + cp += 8; + i -= 8; + } + if (i > 0) { + MEMCPY(clear, cp, i); + cp += i; + magic_random_bytes(cp, 8-i); + /* FIXME: if we want to do SRP, we need to find a way to pass the PolarSSL des_context instead of using static memory */ + (void) DesEncrypt(clear, cipher); + outp += b64enc(&b64, cipher, 8, outp); + } + outp += b64flush(&b64, outp); + + /* Set length and pad out to next 20 octet boundary */ + i = outp - optr - 1; + *optr = i; + i %= SHA_DIGESTSIZE; + if (i != 0) { + magic_random_bytes(outp, SHA_DIGESTSIZE-i); + INCPTR(SHA_DIGESTSIZE-i, outp); + } + + /* Obscure the pseudonym with SHA1 hash */ + SHA1Init(&ctxt); + SHA1Update(&ctxt, &pcb->eap.es_server.ea_id, 1); + SHA1Update(&ctxt, pcb->eap.es_server.ea_skey, + SESSION_KEY_LEN); + SHA1Update(&ctxt, pcb->eap.es_server.ea_peer, + pcb->eap.es_server.ea_peerlen); + while (optr < outp) { + SHA1Final(dig, &ctxt); + cp = dig; + while (cp < dig + SHA_DIGESTSIZE) + *optr++ ^= *cp++; + SHA1Init(&ctxt); + SHA1Update(&ctxt, &pcb->eap.es_server.ea_id, 1); + SHA1Update(&ctxt, pcb->eap.es_server.ea_skey, + SESSION_KEY_LEN); + SHA1Update(&ctxt, optr - SHA_DIGESTSIZE, + SHA_DIGESTSIZE); + } + } + break; + + case eapSRP4: + PUTCHAR(EAPT_SRP, outp); + PUTCHAR(EAPSRP_LWRECHALLENGE, outp); + pcb->eap.es_challen = EAP_MIN_CHALLENGE_LENGTH + + magic_pow(EAP_MIN_MAX_POWER_OF_TWO_CHALLENGE_LENGTH); + magic_random_bytes(pcb->eap.es_challenge, pcb->eap.es_challen); + MEMCPY(outp, pcb->eap.es_challenge, pcb->eap.es_challen); + INCPTR(pcb->eap.es_challen, outp); + break; +#endif /* USE_SRP */ + + default: + return; + } + + outlen = (outp - (unsigned char*)p->payload) - PPP_HDRLEN; + PUTSHORT(outlen, lenloc); + + pbuf_realloc(p, outlen + PPP_HDRLEN); + ppp_write(pcb, p); + + pcb->eap.es_server.ea_requests++; + + if (pcb->settings.eap_timeout_time > 0) + TIMEOUT(eap_server_timeout, pcb, pcb->settings.eap_timeout_time); +} + +/* + * eap_authpeer - Authenticate our peer (behave as server). + * + * Start server state and send first request. This is called only + * after eap_lowerup. + */ +void eap_authpeer(ppp_pcb *pcb, const char *localname) { + + /* Save the name we're given. */ + pcb->eap.es_server.ea_name = localname; + pcb->eap.es_server.ea_namelen = strlen(localname); + + pcb->eap.es_savedtime = pcb->settings.eap_timeout_time; + + /* Lower layer up yet? */ + if (pcb->eap.es_server.ea_state == eapInitial || + pcb->eap.es_server.ea_state == eapPending) { + pcb->eap.es_server.ea_state = eapPending; + return; + } + + pcb->eap.es_server.ea_state = eapPending; + + /* ID number not updated here intentionally; hashed into M1 */ + eap_send_request(pcb); +} + +/* + * eap_server_timeout - Retransmission timer for sending Requests + * expired. + */ +static void eap_server_timeout(void *arg) { + ppp_pcb *pcb = (ppp_pcb*)arg; + + if (!eap_server_active(pcb)) + return; + + /* EAP ID number must not change on timeout. */ + eap_send_request(pcb); +} + +/* + * When it's time to send rechallenge the peer, this timeout is + * called. Once the rechallenge is successful, the response handler + * will restart the timer. If it fails, then the link is dropped. + */ +static void eap_rechallenge(void *arg) { + ppp_pcb *pcb = (ppp_pcb*)arg; + + if (pcb->eap.es_server.ea_state != eapOpen && + pcb->eap.es_server.ea_state != eapSRP4) + return; + + pcb->eap.es_server.ea_requests = 0; + pcb->eap.es_server.ea_state = eapIdentify; + eap_figure_next_state(pcb, 0); + pcb->eap.es_server.ea_id++; + eap_send_request(pcb); +} + +static void srp_lwrechallenge(void *arg) { + ppp_pcb *pcb = (ppp_pcb*)arg; + + if (pcb->eap.es_server.ea_state != eapOpen || + pcb->eap.es_server.ea_type != EAPT_SRP) + return; + + pcb->eap.es_server.ea_requests = 0; + pcb->eap.es_server.ea_state = eapSRP4; + pcb->eap.es_server.ea_id++; + eap_send_request(pcb); +} +#endif /* PPP_SERVER */ + +/* + * eap_lowerup - The lower layer is now up. + * + * This is called before either eap_authpeer or eap_authwithpeer. See + * link_established() in auth.c. All that's necessary here is to + * return to closed state so that those two routines will do the right + * thing. + */ +static void eap_lowerup(ppp_pcb *pcb) { + pcb->eap.es_client.ea_state = eapClosed; +#if PPP_SERVER + pcb->eap.es_server.ea_state = eapClosed; +#endif /* PPP_SERVER */ +} + +/* + * eap_lowerdown - The lower layer is now down. + * + * Cancel all timeouts and return to initial state. + */ +static void eap_lowerdown(ppp_pcb *pcb) { + + if (eap_client_active(pcb) && pcb->settings.eap_req_time > 0) { + UNTIMEOUT(eap_client_timeout, pcb); + } +#if PPP_SERVER + if (eap_server_active(pcb)) { + if (pcb->settings.eap_timeout_time > 0) { + UNTIMEOUT(eap_server_timeout, pcb); + } + } else { + if ((pcb->eap.es_server.ea_state == eapOpen || + pcb->eap.es_server.ea_state == eapSRP4) && + pcb->eap.es_rechallenge > 0) { + UNTIMEOUT(eap_rechallenge, (void *)pcb); + } + if (pcb->eap.es_server.ea_state == eapOpen && + pcb->eap.es_lwrechallenge > 0) { + UNTIMEOUT(srp_lwrechallenge, (void *)pcb); + } + } + + pcb->eap.es_client.ea_state = pcb->eap.es_server.ea_state = eapInitial; + pcb->eap.es_client.ea_requests = pcb->eap.es_server.ea_requests = 0; +#endif /* PPP_SERVER */ +} + +/* + * eap_protrej - Peer doesn't speak this protocol. + * + * This shouldn't happen. If it does, it represents authentication + * failure. + */ +static void eap_protrej(ppp_pcb *pcb) { + + if (eap_client_active(pcb)) { + ppp_error("EAP authentication failed due to Protocol-Reject"); + auth_withpeer_fail(pcb, PPP_EAP); + } +#if PPP_SERVER + if (eap_server_active(pcb)) { + ppp_error("EAP authentication of peer failed on Protocol-Reject"); + auth_peer_fail(pcb, PPP_EAP); + } +#endif /* PPP_SERVER */ + eap_lowerdown(pcb); +} + +/* + * Format and send a regular EAP Response message. + */ +static void eap_send_response(ppp_pcb *pcb, u_char id, u_char typenum, const u_char *str, int lenstr) { + struct pbuf *p; + u_char *outp; + int msglen; + + msglen = EAP_HEADERLEN + sizeof (u_char) + lenstr; + p = pbuf_alloc(PBUF_RAW, (u16_t)(PPP_HDRLEN + msglen), PPP_CTRL_PBUF_TYPE); + if(NULL == p) + return; + if(p->tot_len != p->len) { + pbuf_free(p); + return; + } + + outp = (u_char*)p->payload; + + MAKEHEADER(outp, PPP_EAP); + + PUTCHAR(EAP_RESPONSE, outp); + PUTCHAR(id, outp); + pcb->eap.es_client.ea_id = id; + PUTSHORT(msglen, outp); + PUTCHAR(typenum, outp); + if (lenstr > 0) { + MEMCPY(outp, str, lenstr); + } + + ppp_write(pcb, p); +} + +/* + * Format and send an MD5-Challenge EAP Response message. + */ +static void eap_chap_response(ppp_pcb *pcb, u_char id, u_char *hash, const char *name, int namelen) { + struct pbuf *p; + u_char *outp; + int msglen; + + msglen = EAP_HEADERLEN + 2 * sizeof (u_char) + MD5_SIGNATURE_SIZE + + namelen; + p = pbuf_alloc(PBUF_RAW, (u16_t)(PPP_HDRLEN + msglen), PPP_CTRL_PBUF_TYPE); + if(NULL == p) + return; + if(p->tot_len != p->len) { + pbuf_free(p); + return; + } + + outp = (u_char*)p->payload; + + MAKEHEADER(outp, PPP_EAP); + + PUTCHAR(EAP_RESPONSE, outp); + PUTCHAR(id, outp); + pcb->eap.es_client.ea_id = id; + PUTSHORT(msglen, outp); + PUTCHAR(EAPT_MD5CHAP, outp); + PUTCHAR(MD5_SIGNATURE_SIZE, outp); + MEMCPY(outp, hash, MD5_SIGNATURE_SIZE); + INCPTR(MD5_SIGNATURE_SIZE, outp); + if (namelen > 0) { + MEMCPY(outp, name, namelen); + } + + ppp_write(pcb, p); +} + +#ifdef USE_SRP +/* + * Format and send a SRP EAP Response message. + */ +static void +eap_srp_response(esp, id, subtypenum, str, lenstr) +eap_state *esp; +u_char id; +u_char subtypenum; +u_char *str; +int lenstr; +{ + ppp_pcb *pcb = &ppp_pcb_list[pcb->eap.es_unit]; + struct pbuf *p; + u_char *outp; + int msglen; + + msglen = EAP_HEADERLEN + 2 * sizeof (u_char) + lenstr; + p = pbuf_alloc(PBUF_RAW, (u16_t)(PPP_HDRLEN + msglen), PPP_CTRL_PBUF_TYPE); + if(NULL == p) + return; + if(p->tot_len != p->len) { + pbuf_free(p); + return; + } + + outp = p->payload; + + MAKEHEADER(outp, PPP_EAP); + + PUTCHAR(EAP_RESPONSE, outp); + PUTCHAR(id, outp); + pcb->eap.es_client.ea_id = id; + PUTSHORT(msglen, outp); + PUTCHAR(EAPT_SRP, outp); + PUTCHAR(subtypenum, outp); + if (lenstr > 0) { + MEMCPY(outp, str, lenstr); + } + + ppp_write(pcb, p); +} + +/* + * Format and send a SRP EAP Client Validator Response message. + */ +static void +eap_srpval_response(esp, id, flags, str) +eap_state *esp; +u_char id; +u32_t flags; +u_char *str; +{ + ppp_pcb *pcb = &ppp_pcb_list[pcb->eap.es_unit]; + struct pbuf *p; + u_char *outp; + int msglen; + + msglen = EAP_HEADERLEN + 2 * sizeof (u_char) + sizeof (u32_t) + + SHA_DIGESTSIZE; + p = pbuf_alloc(PBUF_RAW, (u16_t)(PPP_HDRLEN + msglen), PPP_CTRL_PBUF_TYPE); + if(NULL == p) + return; + if(p->tot_len != p->len) { + pbuf_free(p); + return; + } + + outp = p->payload; + + MAKEHEADER(outp, PPP_EAP); + + PUTCHAR(EAP_RESPONSE, outp); + PUTCHAR(id, outp); + pcb->eap.es_client.ea_id = id; + PUTSHORT(msglen, outp); + PUTCHAR(EAPT_SRP, outp); + PUTCHAR(EAPSRP_CVALIDATOR, outp); + PUTLONG(flags, outp); + MEMCPY(outp, str, SHA_DIGESTSIZE); + + ppp_write(pcb, p); +} +#endif /* USE_SRP */ + +static void eap_send_nak(ppp_pcb *pcb, u_char id, u_char type) { + struct pbuf *p; + u_char *outp; + int msglen; + + msglen = EAP_HEADERLEN + 2 * sizeof (u_char); + p = pbuf_alloc(PBUF_RAW, (u16_t)(PPP_HDRLEN + msglen), PPP_CTRL_PBUF_TYPE); + if(NULL == p) + return; + if(p->tot_len != p->len) { + pbuf_free(p); + return; + } + + outp = (u_char*)p->payload; + + MAKEHEADER(outp, PPP_EAP); + + PUTCHAR(EAP_RESPONSE, outp); + PUTCHAR(id, outp); + pcb->eap.es_client.ea_id = id; + PUTSHORT(msglen, outp); + PUTCHAR(EAPT_NAK, outp); + PUTCHAR(type, outp); + + ppp_write(pcb, p); +} + +#ifdef USE_SRP +static char * +name_of_pn_file() +{ + char *user, *path, *file; + struct passwd *pw; + size_t pl; + static bool pnlogged = 0; + + pw = getpwuid(getuid()); + if (pw == NULL || (user = pw->pw_dir) == NULL || user[0] == 0) { + errno = EINVAL; + return (NULL); + } + file = _PATH_PSEUDONYM; + pl = strlen(user) + strlen(file) + 2; + path = malloc(pl); + if (path == NULL) + return (NULL); + (void) slprintf(path, pl, "%s/%s", user, file); + if (!pnlogged) { + ppp_dbglog("pseudonym file: %s", path); + pnlogged = 1; + } + return (path); +} + +static int +open_pn_file(modebits) +mode_t modebits; +{ + char *path; + int fd, err; + + if ((path = name_of_pn_file()) == NULL) + return (-1); + fd = open(path, modebits, S_IRUSR | S_IWUSR); + err = errno; + free(path); + errno = err; + return (fd); +} + +static void +remove_pn_file() +{ + char *path; + + if ((path = name_of_pn_file()) != NULL) { + (void) unlink(path); + (void) free(path); + } +} + +static void +write_pseudonym(esp, inp, len, id) +eap_state *esp; +u_char *inp; +int len, id; +{ + u_char val; + u_char *datp, *digp; + SHA1_CTX ctxt; + u_char dig[SHA_DIGESTSIZE]; + int dsize, fd, olen = len; + + /* + * Do the decoding by working backwards. This eliminates the need + * to save the decoded output in a separate buffer. + */ + val = id; + while (len > 0) { + if ((dsize = len % SHA_DIGESTSIZE) == 0) + dsize = SHA_DIGESTSIZE; + len -= dsize; + datp = inp + len; + SHA1Init(&ctxt); + SHA1Update(&ctxt, &val, 1); + SHA1Update(&ctxt, pcb->eap.es_client.ea_skey, SESSION_KEY_LEN); + if (len > 0) { + SHA1Update(&ctxt, datp, SHA_DIGESTSIZE); + } else { + SHA1Update(&ctxt, pcb->eap.es_client.ea_name, + pcb->eap.es_client.ea_namelen); + } + SHA1Final(dig, &ctxt); + for (digp = dig; digp < dig + SHA_DIGESTSIZE; digp++) + *datp++ ^= *digp; + } + + /* Now check that the result is sane */ + if (olen <= 0 || *inp + 1 > olen) { + ppp_dbglog("EAP: decoded pseudonym is unusable <%.*B>", olen, inp); + return; + } + + /* Save it away */ + fd = open_pn_file(O_WRONLY | O_CREAT | O_TRUNC); + if (fd < 0) { + ppp_dbglog("EAP: error saving pseudonym: %m"); + return; + } + len = write(fd, inp + 1, *inp); + if (close(fd) != -1 && len == *inp) { + ppp_dbglog("EAP: saved pseudonym"); + pcb->eap.es_usedpseudo = 0; + } else { + ppp_dbglog("EAP: failed to save pseudonym"); + remove_pn_file(); + } +} +#endif /* USE_SRP */ + +/* + * eap_request - Receive EAP Request message (client mode). + */ +static void eap_request(ppp_pcb *pcb, u_char *inp, int id, int len) { + u_char typenum; + u_char vallen; + int secret_len; + char secret[MAXSECRETLEN]; + char rhostname[MAXNAMELEN]; + md5_context mdContext; + u_char hash[MD5_SIGNATURE_SIZE]; +#ifdef USE_SRP + struct t_client *tc; + struct t_num sval, gval, Nval, *Ap, Bval; + u_char vals[2]; + SHA1_CTX ctxt; + u_char dig[SHA_DIGESTSIZE]; + int fd; +#endif /* USE_SRP */ + + /* + * Note: we update es_client.ea_id *only if* a Response + * message is being generated. Otherwise, we leave it the + * same for duplicate detection purposes. + */ + + pcb->eap.es_client.ea_requests++; + if (pcb->settings.eap_allow_req != 0 && + pcb->eap.es_client.ea_requests > pcb->settings.eap_allow_req) { + ppp_info("EAP: received too many Request messages"); + if (pcb->settings.eap_req_time > 0) { + UNTIMEOUT(eap_client_timeout, pcb); + } + auth_withpeer_fail(pcb, PPP_EAP); + return; + } + + if (len <= 0) { + ppp_error("EAP: empty Request message discarded"); + return; + } + + GETCHAR(typenum, inp); + len--; + + switch (typenum) { + case EAPT_IDENTITY: + if (len > 0) + ppp_info("EAP: Identity prompt \"%.*q\"", len, inp); +#ifdef USE_SRP + if (pcb->eap.es_usepseudo && + (pcb->eap.es_usedpseudo == 0 || + (pcb->eap.es_usedpseudo == 1 && + id == pcb->eap.es_client.ea_id))) { + pcb->eap.es_usedpseudo = 1; + /* Try to get a pseudonym */ + if ((fd = open_pn_file(O_RDONLY)) >= 0) { + strcpy(rhostname, SRP_PSEUDO_ID); + len = read(fd, rhostname + SRP_PSEUDO_LEN, + sizeof (rhostname) - SRP_PSEUDO_LEN); + /* XXX NAI unsupported */ + if (len > 0) { + eap_send_response(pcb, id, typenum, + rhostname, len + SRP_PSEUDO_LEN); + } + (void) close(fd); + if (len > 0) + break; + } + } + /* Stop using pseudonym now. */ + if (pcb->eap.es_usepseudo && pcb->eap.es_usedpseudo != 2) { + remove_pn_file(); + pcb->eap.es_usedpseudo = 2; + } +#endif /* USE_SRP */ + eap_send_response(pcb, id, typenum, (const u_char*)pcb->eap.es_client.ea_name, + pcb->eap.es_client.ea_namelen); + break; + + case EAPT_NOTIFICATION: + if (len > 0) + ppp_info("EAP: Notification \"%.*q\"", len, inp); + eap_send_response(pcb, id, typenum, NULL, 0); + break; + + case EAPT_NAK: + /* + * Avoid the temptation to send Response Nak in reply + * to Request Nak here. It can only lead to trouble. + */ + ppp_warn("EAP: unexpected Nak in Request; ignored"); + /* Return because we're waiting for something real. */ + return; + + case EAPT_MD5CHAP: + if (len < 1) { + ppp_error("EAP: received MD5-Challenge with no data"); + /* Bogus request; wait for something real. */ + return; + } + GETCHAR(vallen, inp); + len--; + if (vallen < 8 || vallen > len) { + ppp_error("EAP: MD5-Challenge with bad length %d (8..%d)", + vallen, len); + /* Try something better. */ + eap_send_nak(pcb, id, EAPT_SRP); + break; + } + + /* Not so likely to happen. */ + if (vallen >= len + sizeof (rhostname)) { + ppp_dbglog("EAP: trimming really long peer name down"); + MEMCPY(rhostname, inp + vallen, sizeof (rhostname) - 1); + rhostname[sizeof (rhostname) - 1] = '\0'; + } else { + MEMCPY(rhostname, inp + vallen, len - vallen); + rhostname[len - vallen] = '\0'; + } + +#if PPP_REMOTENAME + /* In case the remote doesn't give us his name. */ + if (pcb->settings.explicit_remote || + (pcb->settings.remote_name[0] != '\0' && vallen == len)) + strlcpy(rhostname, pcb->settings.remote_name, sizeof (rhostname)); +#endif /* PPP_REMOTENAME */ + + /* + * Get the secret for authenticating ourselves with + * the specified host. + */ + if (!get_secret(pcb, pcb->eap.es_client.ea_name, + rhostname, secret, &secret_len, 0)) { + ppp_dbglog("EAP: no MD5 secret for auth to %q", rhostname); + eap_send_nak(pcb, id, EAPT_SRP); + break; + } + md5_starts(&mdContext); + typenum = id; + md5_update(&mdContext, &typenum, 1); + md5_update(&mdContext, (u_char *)secret, secret_len); + BZERO(secret, sizeof (secret)); + md5_update(&mdContext, inp, vallen); + md5_finish(&mdContext, hash); + eap_chap_response(pcb, id, hash, pcb->eap.es_client.ea_name, + pcb->eap.es_client.ea_namelen); + break; + +#ifdef USE_SRP + case EAPT_SRP: + if (len < 1) { + ppp_error("EAP: received empty SRP Request"); + /* Bogus request; wait for something real. */ + return; + } + + /* Get subtype */ + GETCHAR(vallen, inp); + len--; + switch (vallen) { + case EAPSRP_CHALLENGE: + tc = NULL; + if (pcb->eap.es_client.ea_session != NULL) { + tc = (struct t_client *)pcb->eap.es_client. + ea_session; + /* + * If this is a new challenge, then start + * over with a new client session context. + * Otherwise, just resend last response. + */ + if (id != pcb->eap.es_client.ea_id) { + t_clientclose(tc); + pcb->eap.es_client.ea_session = NULL; + tc = NULL; + } + } + /* No session key just yet */ + pcb->eap.es_client.ea_skey = NULL; + if (tc == NULL) { + int rhostnamelen; + + GETCHAR(vallen, inp); + len--; + if (vallen >= len) { + ppp_error("EAP: badly-formed SRP Challenge" + " (name)"); + /* Ignore badly-formed messages */ + return; + } + MEMCPY(rhostname, inp, vallen); + rhostname[vallen] = '\0'; + INCPTR(vallen, inp); + len -= vallen; + + /* + * In case the remote doesn't give us his name, + * use configured name. + */ + if (explicit_remote || + (remote_name[0] != '\0' && vallen == 0)) { + strlcpy(rhostname, remote_name, + sizeof (rhostname)); + } + + rhostnamelen = (int)strlen(rhostname); + if (rhostnamelen > MAXNAMELEN) { + rhostnamelen = MAXNAMELEN; + } + MEMCPY(pcb->eap.es_client.ea_peer, rhostname, rhostnamelen); + pcb->eap.es_client.ea_peer[rhostnamelen] = '\0'; + pcb->eap.es_client.ea_peerlen = rhostnamelen; + + GETCHAR(vallen, inp); + len--; + if (vallen >= len) { + ppp_error("EAP: badly-formed SRP Challenge" + " (s)"); + /* Ignore badly-formed messages */ + return; + } + sval.data = inp; + sval.len = vallen; + INCPTR(vallen, inp); + len -= vallen; + + GETCHAR(vallen, inp); + len--; + if (vallen > len) { + ppp_error("EAP: badly-formed SRP Challenge" + " (g)"); + /* Ignore badly-formed messages */ + return; + } + /* If no generator present, then use value 2 */ + if (vallen == 0) { + gval.data = (u_char *)"\002"; + gval.len = 1; + } else { + gval.data = inp; + gval.len = vallen; + } + INCPTR(vallen, inp); + len -= vallen; + + /* + * If no modulus present, then use well-known + * value. + */ + if (len == 0) { + Nval.data = (u_char *)wkmodulus; + Nval.len = sizeof (wkmodulus); + } else { + Nval.data = inp; + Nval.len = len; + } + tc = t_clientopen(pcb->eap.es_client.ea_name, + &Nval, &gval, &sval); + if (tc == NULL) { + eap_send_nak(pcb, id, EAPT_MD5CHAP); + break; + } + pcb->eap.es_client.ea_session = (void *)tc; + + /* Add Challenge ID & type to verifier */ + vals[0] = id; + vals[1] = EAPT_SRP; + t_clientaddexdata(tc, vals, 2); + } + Ap = t_clientgenexp(tc); + eap_srp_response(esp, id, EAPSRP_CKEY, Ap->data, + Ap->len); + break; + + case EAPSRP_SKEY: + tc = (struct t_client *)pcb->eap.es_client.ea_session; + if (tc == NULL) { + ppp_warn("EAP: peer sent Subtype 2 without 1"); + eap_send_nak(pcb, id, EAPT_MD5CHAP); + break; + } + if (pcb->eap.es_client.ea_skey != NULL) { + /* + * ID number should not change here. Warn + * if it does (but otherwise ignore). + */ + if (id != pcb->eap.es_client.ea_id) { + ppp_warn("EAP: ID changed from %d to %d " + "in SRP Subtype 2 rexmit", + pcb->eap.es_client.ea_id, id); + } + } else { + if (get_srp_secret(pcb->eap.es_unit, + pcb->eap.es_client.ea_name, + pcb->eap.es_client.ea_peer, secret, 0) == 0) { + /* + * Can't work with this peer because + * the secret is missing. Just give + * up. + */ + eap_send_nak(pcb, id, EAPT_MD5CHAP); + break; + } + Bval.data = inp; + Bval.len = len; + t_clientpasswd(tc, secret); + BZERO(secret, sizeof (secret)); + pcb->eap.es_client.ea_skey = + t_clientgetkey(tc, &Bval); + if (pcb->eap.es_client.ea_skey == NULL) { + /* Server is rogue; stop now */ + ppp_error("EAP: SRP server is rogue"); + goto client_failure; + } + } + eap_srpval_response(esp, id, SRPVAL_EBIT, + t_clientresponse(tc)); + break; + + case EAPSRP_SVALIDATOR: + tc = (struct t_client *)pcb->eap.es_client.ea_session; + if (tc == NULL || pcb->eap.es_client.ea_skey == NULL) { + ppp_warn("EAP: peer sent Subtype 3 without 1/2"); + eap_send_nak(pcb, id, EAPT_MD5CHAP); + break; + } + /* + * If we're already open, then this ought to be a + * duplicate. Otherwise, check that the server is + * who we think it is. + */ + if (pcb->eap.es_client.ea_state == eapOpen) { + if (id != pcb->eap.es_client.ea_id) { + ppp_warn("EAP: ID changed from %d to %d " + "in SRP Subtype 3 rexmit", + pcb->eap.es_client.ea_id, id); + } + } else { + len -= sizeof (u32_t) + SHA_DIGESTSIZE; + if (len < 0 || t_clientverify(tc, inp + + sizeof (u32_t)) != 0) { + ppp_error("EAP: SRP server verification " + "failed"); + goto client_failure; + } + GETLONG(pcb->eap.es_client.ea_keyflags, inp); + /* Save pseudonym if user wants it. */ + if (len > 0 && pcb->eap.es_usepseudo) { + INCPTR(SHA_DIGESTSIZE, inp); + write_pseudonym(esp, inp, len, id); + } + } + /* + * We've verified our peer. We're now mostly done, + * except for waiting on the regular EAP Success + * message. + */ + eap_srp_response(esp, id, EAPSRP_ACK, NULL, 0); + break; + + case EAPSRP_LWRECHALLENGE: + if (len < 4) { + ppp_warn("EAP: malformed Lightweight rechallenge"); + return; + } + SHA1Init(&ctxt); + vals[0] = id; + SHA1Update(&ctxt, vals, 1); + SHA1Update(&ctxt, pcb->eap.es_client.ea_skey, + SESSION_KEY_LEN); + SHA1Update(&ctxt, inp, len); + SHA1Update(&ctxt, pcb->eap.es_client.ea_name, + pcb->eap.es_client.ea_namelen); + SHA1Final(dig, &ctxt); + eap_srp_response(esp, id, EAPSRP_LWRECHALLENGE, dig, + SHA_DIGESTSIZE); + break; + + default: + ppp_error("EAP: unknown SRP Subtype %d", vallen); + eap_send_nak(pcb, id, EAPT_MD5CHAP); + break; + } + break; +#endif /* USE_SRP */ + + default: + ppp_info("EAP: unknown authentication type %d; Naking", typenum); + eap_send_nak(pcb, id, EAPT_SRP); + break; + } + + if (pcb->settings.eap_req_time > 0) { + UNTIMEOUT(eap_client_timeout, pcb); + TIMEOUT(eap_client_timeout, pcb, + pcb->settings.eap_req_time); + } + return; + +#ifdef USE_SRP +client_failure: + pcb->eap.es_client.ea_state = eapBadAuth; + if (pcb->settings.eap_req_time > 0) { + UNTIMEOUT(eap_client_timeout, (void *)esp); + } + pcb->eap.es_client.ea_session = NULL; + t_clientclose(tc); + auth_withpeer_fail(pcb, PPP_EAP); +#endif /* USE_SRP */ +} + +#if PPP_SERVER +/* + * eap_response - Receive EAP Response message (server mode). + */ +static void eap_response(ppp_pcb *pcb, u_char *inp, int id, int len) { + u_char typenum; + u_char vallen; + int secret_len; + char secret[MAXSECRETLEN]; + char rhostname[MAXNAMELEN]; + md5_context mdContext; + u_char hash[MD5_SIGNATURE_SIZE]; +#ifdef USE_SRP + struct t_server *ts; + struct t_num A; + SHA1_CTX ctxt; + u_char dig[SHA_DIGESTSIZE]; +#endif /* USE_SRP */ + + if (pcb->eap.es_server.ea_id != id) { + ppp_dbglog("EAP: discarding Response %d; expected ID %d", id, + pcb->eap.es_server.ea_id); + return; + } + + pcb->eap.es_server.ea_responses++; + + if (len <= 0) { + ppp_error("EAP: empty Response message discarded"); + return; + } + + GETCHAR(typenum, inp); + len--; + + switch (typenum) { + case EAPT_IDENTITY: + if (pcb->eap.es_server.ea_state != eapIdentify) { + ppp_dbglog("EAP discarding unwanted Identify \"%.q\"", len, + inp); + break; + } + ppp_info("EAP: unauthenticated peer name \"%.*q\"", len, inp); + if (len > MAXNAMELEN) { + len = MAXNAMELEN; + } + MEMCPY(pcb->eap.es_server.ea_peer, inp, len); + pcb->eap.es_server.ea_peer[len] = '\0'; + pcb->eap.es_server.ea_peerlen = len; + eap_figure_next_state(pcb, 0); + break; + + case EAPT_NOTIFICATION: + ppp_dbglog("EAP unexpected Notification; response discarded"); + break; + + case EAPT_NAK: + if (len < 1) { + ppp_info("EAP: Nak Response with no suggested protocol"); + eap_figure_next_state(pcb, 1); + break; + } + + GETCHAR(vallen, inp); + len--; + + if ( +#if PPP_REMOTENAME + !pcb->explicit_remote && +#endif /* PPP_REMOTENAME */ + pcb->eap.es_server.ea_state == eapIdentify){ + /* Peer cannot Nak Identify Request */ + eap_figure_next_state(pcb, 1); + break; + } + + switch (vallen) { + case EAPT_SRP: + /* Run through SRP validator selection again. */ + pcb->eap.es_server.ea_state = eapIdentify; + eap_figure_next_state(pcb, 0); + break; + + case EAPT_MD5CHAP: + pcb->eap.es_server.ea_state = eapMD5Chall; + break; + + default: + ppp_dbglog("EAP: peer requesting unknown Type %d", vallen); + switch (pcb->eap.es_server.ea_state) { + case eapSRP1: + case eapSRP2: + case eapSRP3: + pcb->eap.es_server.ea_state = eapMD5Chall; + break; + case eapMD5Chall: + case eapSRP4: + pcb->eap.es_server.ea_state = eapIdentify; + eap_figure_next_state(pcb, 0); + break; + default: + break; + } + break; + } + break; + + case EAPT_MD5CHAP: + if (pcb->eap.es_server.ea_state != eapMD5Chall) { + ppp_error("EAP: unexpected MD5-Response"); + eap_figure_next_state(pcb, 1); + break; + } + if (len < 1) { + ppp_error("EAP: received MD5-Response with no data"); + eap_figure_next_state(pcb, 1); + break; + } + GETCHAR(vallen, inp); + len--; + if (vallen != 16 || vallen > len) { + ppp_error("EAP: MD5-Response with bad length %d", vallen); + eap_figure_next_state(pcb, 1); + break; + } + + /* Not so likely to happen. */ + if (vallen >= len + sizeof (rhostname)) { + ppp_dbglog("EAP: trimming really long peer name down"); + MEMCPY(rhostname, inp + vallen, sizeof (rhostname) - 1); + rhostname[sizeof (rhostname) - 1] = '\0'; + } else { + MEMCPY(rhostname, inp + vallen, len - vallen); + rhostname[len - vallen] = '\0'; + } + +#if PPP_REMOTENAME + /* In case the remote doesn't give us his name. */ + if (explicit_remote || + (remote_name[0] != '\0' && vallen == len)) + strlcpy(rhostname, remote_name, sizeof (rhostname)); +#endif /* PPP_REMOTENAME */ + + /* + * Get the secret for authenticating the specified + * host. + */ + if (!get_secret(pcb, rhostname, + pcb->eap.es_server.ea_name, secret, &secret_len, 1)) { + ppp_dbglog("EAP: no MD5 secret for auth of %q", rhostname); + eap_send_failure(pcb); + break; + } + md5_starts(&mdContext); + md5_update(&mdContext, &pcb->eap.es_server.ea_id, 1); + md5_update(&mdContext, (u_char *)secret, secret_len); + BZERO(secret, sizeof (secret)); + md5_update(&mdContext, pcb->eap.es_challenge, pcb->eap.es_challen); + md5_finish(&mdContext, hash); + if (BCMP(hash, inp, MD5_SIGNATURE_SIZE) != 0) { + eap_send_failure(pcb); + break; + } + pcb->eap.es_server.ea_type = EAPT_MD5CHAP; + eap_send_success(pcb); + eap_figure_next_state(pcb, 0); + if (pcb->eap.es_rechallenge != 0) + TIMEOUT(eap_rechallenge, pcb, pcb->eap.es_rechallenge); + break; + +#ifdef USE_SRP + case EAPT_SRP: + if (len < 1) { + ppp_error("EAP: empty SRP Response"); + eap_figure_next_state(pcb, 1); + break; + } + GETCHAR(typenum, inp); + len--; + switch (typenum) { + case EAPSRP_CKEY: + if (pcb->eap.es_server.ea_state != eapSRP1) { + ppp_error("EAP: unexpected SRP Subtype 1 Response"); + eap_figure_next_state(pcb, 1); + break; + } + A.data = inp; + A.len = len; + ts = (struct t_server *)pcb->eap.es_server.ea_session; + assert(ts != NULL); + pcb->eap.es_server.ea_skey = t_servergetkey(ts, &A); + if (pcb->eap.es_server.ea_skey == NULL) { + /* Client's A value is bogus; terminate now */ + ppp_error("EAP: bogus A value from client"); + eap_send_failure(pcb); + } else { + eap_figure_next_state(pcb, 0); + } + break; + + case EAPSRP_CVALIDATOR: + if (pcb->eap.es_server.ea_state != eapSRP2) { + ppp_error("EAP: unexpected SRP Subtype 2 Response"); + eap_figure_next_state(pcb, 1); + break; + } + if (len < sizeof (u32_t) + SHA_DIGESTSIZE) { + ppp_error("EAP: M1 length %d < %d", len, + sizeof (u32_t) + SHA_DIGESTSIZE); + eap_figure_next_state(pcb, 1); + break; + } + GETLONG(pcb->eap.es_server.ea_keyflags, inp); + ts = (struct t_server *)pcb->eap.es_server.ea_session; + assert(ts != NULL); + if (t_serververify(ts, inp)) { + ppp_info("EAP: unable to validate client identity"); + eap_send_failure(pcb); + break; + } + eap_figure_next_state(pcb, 0); + break; + + case EAPSRP_ACK: + if (pcb->eap.es_server.ea_state != eapSRP3) { + ppp_error("EAP: unexpected SRP Subtype 3 Response"); + eap_send_failure(esp); + break; + } + pcb->eap.es_server.ea_type = EAPT_SRP; + eap_send_success(pcb, esp); + eap_figure_next_state(pcb, 0); + if (pcb->eap.es_rechallenge != 0) + TIMEOUT(eap_rechallenge, pcb, + pcb->eap.es_rechallenge); + if (pcb->eap.es_lwrechallenge != 0) + TIMEOUT(srp_lwrechallenge, pcb, + pcb->eap.es_lwrechallenge); + break; + + case EAPSRP_LWRECHALLENGE: + if (pcb->eap.es_server.ea_state != eapSRP4) { + ppp_info("EAP: unexpected SRP Subtype 4 Response"); + return; + } + if (len != SHA_DIGESTSIZE) { + ppp_error("EAP: bad Lightweight rechallenge " + "response"); + return; + } + SHA1Init(&ctxt); + vallen = id; + SHA1Update(&ctxt, &vallen, 1); + SHA1Update(&ctxt, pcb->eap.es_server.ea_skey, + SESSION_KEY_LEN); + SHA1Update(&ctxt, pcb->eap.es_challenge, pcb->eap.es_challen); + SHA1Update(&ctxt, pcb->eap.es_server.ea_peer, + pcb->eap.es_server.ea_peerlen); + SHA1Final(dig, &ctxt); + if (BCMP(dig, inp, SHA_DIGESTSIZE) != 0) { + ppp_error("EAP: failed Lightweight rechallenge"); + eap_send_failure(pcb); + break; + } + pcb->eap.es_server.ea_state = eapOpen; + if (pcb->eap.es_lwrechallenge != 0) + TIMEOUT(srp_lwrechallenge, esp, + pcb->eap.es_lwrechallenge); + break; + } + break; +#endif /* USE_SRP */ + + default: + /* This can't happen. */ + ppp_error("EAP: unknown Response type %d; ignored", typenum); + return; + } + + if (pcb->settings.eap_timeout_time > 0) { + UNTIMEOUT(eap_server_timeout, pcb); + } + + if (pcb->eap.es_server.ea_state != eapBadAuth && + pcb->eap.es_server.ea_state != eapOpen) { + pcb->eap.es_server.ea_id++; + eap_send_request(pcb); + } +} +#endif /* PPP_SERVER */ + +/* + * eap_success - Receive EAP Success message (client mode). + */ +static void eap_success(ppp_pcb *pcb, u_char *inp, int id, int len) { + LWIP_UNUSED_ARG(id); + + if (pcb->eap.es_client.ea_state != eapOpen && !eap_client_active(pcb)) { + ppp_dbglog("EAP unexpected success message in state %s (%d)", + eap_state_name(pcb->eap.es_client.ea_state), + pcb->eap.es_client.ea_state); + return; + } + + if (pcb->settings.eap_req_time > 0) { + UNTIMEOUT(eap_client_timeout, pcb); + } + + if (len > 0) { + /* This is odd. The spec doesn't allow for this. */ + PRINTMSG(inp, len); + } + + pcb->eap.es_client.ea_state = eapOpen; + auth_withpeer_success(pcb, PPP_EAP, 0); +} + +/* + * eap_failure - Receive EAP Failure message (client mode). + */ +static void eap_failure(ppp_pcb *pcb, u_char *inp, int id, int len) { + LWIP_UNUSED_ARG(id); + + if (!eap_client_active(pcb)) { + ppp_dbglog("EAP unexpected failure message in state %s (%d)", + eap_state_name(pcb->eap.es_client.ea_state), + pcb->eap.es_client.ea_state); + } + + if (pcb->settings.eap_req_time > 0) { + UNTIMEOUT(eap_client_timeout, pcb); + } + + if (len > 0) { + /* This is odd. The spec doesn't allow for this. */ + PRINTMSG(inp, len); + } + + pcb->eap.es_client.ea_state = eapBadAuth; + + ppp_error("EAP: peer reports authentication failure"); + auth_withpeer_fail(pcb, PPP_EAP); +} + +/* + * eap_input - Handle received EAP message. + */ +static void eap_input(ppp_pcb *pcb, u_char *inp, int inlen) { + u_char code, id; + int len; + + /* + * Parse header (code, id and length). If packet too short, + * drop it. + */ + if (inlen < EAP_HEADERLEN) { + ppp_error("EAP: packet too short: %d < %d", inlen, EAP_HEADERLEN); + return; + } + GETCHAR(code, inp); + GETCHAR(id, inp); + GETSHORT(len, inp); + if (len < EAP_HEADERLEN || len > inlen) { + ppp_error("EAP: packet has illegal length field %d (%d..%d)", len, + EAP_HEADERLEN, inlen); + return; + } + len -= EAP_HEADERLEN; + + /* Dispatch based on message code */ + switch (code) { + case EAP_REQUEST: + eap_request(pcb, inp, id, len); + break; + +#if PPP_SERVER + case EAP_RESPONSE: + eap_response(pcb, inp, id, len); + break; +#endif /* PPP_SERVER */ + + case EAP_SUCCESS: + eap_success(pcb, inp, id, len); + break; + + case EAP_FAILURE: + eap_failure(pcb, inp, id, len); + break; + + default: /* XXX Need code reject */ + /* Note: it's not legal to send EAP Nak here. */ + ppp_warn("EAP: unknown code %d received", code); + break; + } +} + +#if PRINTPKT_SUPPORT +/* + * eap_printpkt - print the contents of an EAP packet. + */ +static const char* const eap_codenames[] = { + "Request", "Response", "Success", "Failure" +}; + +static const char* const eap_typenames[] = { + "Identity", "Notification", "Nak", "MD5-Challenge", + "OTP", "Generic-Token", NULL, NULL, + "RSA", "DSS", "KEA", "KEA-Validate", + "TLS", "Defender", "Windows 2000", "Arcot", + "Cisco", "Nokia", "SRP" +}; + +static int eap_printpkt(const u_char *inp, int inlen, void (*printer) (void *, const char *, ...), void *arg) { + int code, id, len, rtype, vallen; + const u_char *pstart; + u32_t uval; + + if (inlen < EAP_HEADERLEN) + return (0); + pstart = inp; + GETCHAR(code, inp); + GETCHAR(id, inp); + GETSHORT(len, inp); + if (len < EAP_HEADERLEN || len > inlen) + return (0); + + if (code >= 1 && code <= (int)sizeof(eap_codenames) / (int)sizeof(char *)) + printer(arg, " %s", eap_codenames[code-1]); + else + printer(arg, " code=0x%x", code); + printer(arg, " id=0x%x", id); + len -= EAP_HEADERLEN; + switch (code) { + case EAP_REQUEST: + if (len < 1) { + printer(arg, " "); + break; + } + GETCHAR(rtype, inp); + len--; + if (rtype >= 1 && + rtype <= (int)sizeof (eap_typenames) / (int)sizeof (char *)) + printer(arg, " %s", eap_typenames[rtype-1]); + else + printer(arg, " type=0x%x", rtype); + switch (rtype) { + case EAPT_IDENTITY: + case EAPT_NOTIFICATION: + if (len > 0) { + printer(arg, " "); + INCPTR(len, inp); + len = 0; + } else { + printer(arg, " "); + } + break; + + case EAPT_MD5CHAP: + if (len <= 0) + break; + GETCHAR(vallen, inp); + len--; + if (vallen > len) + goto truncated; + printer(arg, " ", vallen, inp); + INCPTR(vallen, inp); + len -= vallen; + if (len > 0) { + printer(arg, " "); + INCPTR(len, inp); + len = 0; + } else { + printer(arg, " "); + } + break; + + case EAPT_SRP: + if (len < 3) + goto truncated; + GETCHAR(vallen, inp); + len--; + printer(arg, "-%d", vallen); + switch (vallen) { + case EAPSRP_CHALLENGE: + GETCHAR(vallen, inp); + len--; + if (vallen >= len) + goto truncated; + if (vallen > 0) { + printer(arg, " "); + } else { + printer(arg, " "); + } + INCPTR(vallen, inp); + len -= vallen; + GETCHAR(vallen, inp); + len--; + if (vallen >= len) + goto truncated; + printer(arg, " ", vallen, inp); + INCPTR(vallen, inp); + len -= vallen; + GETCHAR(vallen, inp); + len--; + if (vallen > len) + goto truncated; + if (vallen == 0) { + printer(arg, " "); + } else { + printer(arg, " ", vallen, inp); + } + INCPTR(vallen, inp); + len -= vallen; + if (len == 0) { + printer(arg, " "); + } else { + printer(arg, " ", len, inp); + INCPTR(len, inp); + len = 0; + } + break; + + case EAPSRP_SKEY: + printer(arg, " ", len, inp); + INCPTR(len, inp); + len = 0; + break; + + case EAPSRP_SVALIDATOR: + if (len < (int)sizeof (u32_t)) + break; + GETLONG(uval, inp); + len -= sizeof (u32_t); + if (uval & SRPVAL_EBIT) { + printer(arg, " E"); + uval &= ~SRPVAL_EBIT; + } + if (uval != 0) { + printer(arg, " f<%X>", uval); + } + if ((vallen = len) > SHA_DIGESTSIZE) + vallen = SHA_DIGESTSIZE; + printer(arg, " ", len, inp, + len < SHA_DIGESTSIZE ? "?" : ""); + INCPTR(vallen, inp); + len -= vallen; + if (len > 0) { + printer(arg, " ", len, inp); + INCPTR(len, inp); + len = 0; + } + break; + + case EAPSRP_LWRECHALLENGE: + printer(arg, " ", len, inp); + INCPTR(len, inp); + len = 0; + break; + default: + break; + } + break; + default: + break; + } + break; + + case EAP_RESPONSE: + if (len < 1) + break; + GETCHAR(rtype, inp); + len--; + if (rtype >= 1 && + rtype <= (int)sizeof (eap_typenames) / (int)sizeof (char *)) + printer(arg, " %s", eap_typenames[rtype-1]); + else + printer(arg, " type=0x%x", rtype); + switch (rtype) { + case EAPT_IDENTITY: + if (len > 0) { + printer(arg, " "); + INCPTR(len, inp); + len = 0; + } + break; + + case EAPT_NAK: + if (len <= 0) { + printer(arg, " "); + break; + } + GETCHAR(rtype, inp); + len--; + printer(arg, " = 1 && + rtype < (int)sizeof (eap_typenames) / (int)sizeof (char *)) + printer(arg, " (%s)", eap_typenames[rtype-1]); + printer(arg, ">"); + break; + + case EAPT_MD5CHAP: + if (len <= 0) { + printer(arg, " "); + break; + } + GETCHAR(vallen, inp); + len--; + if (vallen > len) + goto truncated; + printer(arg, " ", vallen, inp); + INCPTR(vallen, inp); + len -= vallen; + if (len > 0) { + printer(arg, " "); + INCPTR(len, inp); + len = 0; + } else { + printer(arg, " "); + } + break; + + case EAPT_SRP: + if (len < 1) + goto truncated; + GETCHAR(vallen, inp); + len--; + printer(arg, "-%d", vallen); + switch (vallen) { + case EAPSRP_CKEY: + printer(arg, " ", len, inp); + INCPTR(len, inp); + len = 0; + break; + + case EAPSRP_CVALIDATOR: + if (len < (int)sizeof (u32_t)) + break; + GETLONG(uval, inp); + len -= sizeof (u32_t); + if (uval & SRPVAL_EBIT) { + printer(arg, " E"); + uval &= ~SRPVAL_EBIT; + } + if (uval != 0) { + printer(arg, " f<%X>", uval); + } + printer(arg, " ", len, inp, + len == SHA_DIGESTSIZE ? "" : "?"); + INCPTR(len, inp); + len = 0; + break; + + case EAPSRP_ACK: + break; + + case EAPSRP_LWRECHALLENGE: + printer(arg, " ", len, inp, + len == SHA_DIGESTSIZE ? "" : "?"); + if ((vallen = len) > SHA_DIGESTSIZE) + vallen = SHA_DIGESTSIZE; + INCPTR(vallen, inp); + len -= vallen; + break; + default: + break; + } + break; + default: + break; + } + break; + + case EAP_SUCCESS: /* No payload expected for these! */ + case EAP_FAILURE: + default: + break; + + truncated: + printer(arg, " "); + break; + } + + if (len > 8) + printer(arg, "%8B...", inp); + else if (len > 0) + printer(arg, "%.*B", len, inp); + INCPTR(len, inp); + + return (inp - pstart); +} +#endif /* PRINTPKT_SUPPORT */ + +#endif /* PPP_SUPPORT && EAP_SUPPORT */ diff --git a/components/lwip/netif/ppp/ecp.c b/components/lwip/netif/ppp/ecp.c new file mode 100755 index 0000000000..4f1dee3339 --- /dev/null +++ b/components/lwip/netif/ppp/ecp.c @@ -0,0 +1,191 @@ +/* + * ecp.c - PPP Encryption Control Protocol. + * + * Copyright (c) 2002 Google, Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. The name(s) of the authors of this software must not be used to + * endorse or promote products derived from this software without + * prior written permission. + * + * THE AUTHORS OF THIS SOFTWARE DISCLAIM ALL WARRANTIES WITH REGARD TO + * THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS, IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY + * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN + * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING + * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * Derived from ccp.c, which is: + * + * Copyright (c) 1994-2002 Paul Mackerras. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. The name(s) of the authors of this software must not be used to + * endorse or promote products derived from this software without + * prior written permission. + * + * 3. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by Paul Mackerras + * ". + * + * THE AUTHORS OF THIS SOFTWARE DISCLAIM ALL WARRANTIES WITH REGARD TO + * THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS, IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY + * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN + * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING + * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include "lwip/opt.h" +#if PPP_SUPPORT && ECP_SUPPORT /* don't build if not configured for use in lwipopts.h */ + +#include + +#include "netif/ppp/ppp_impl.h" + +#include "netif/ppp/fsm.h" +#include "netif/ppp/ecp.h" + +#if PPP_OPTIONS +static option_t ecp_option_list[] = { + { "noecp", o_bool, &ecp_protent.enabled_flag, + "Disable ECP negotiation" }, + { "-ecp", o_bool, &ecp_protent.enabled_flag, + "Disable ECP negotiation", OPT_ALIAS }, + + { NULL } +}; +#endif /* PPP_OPTIONS */ + +/* + * Protocol entry points from main code. + */ +static void ecp_init (int unit); +/* +static void ecp_open (int unit); +static void ecp_close (int unit, char *); +static void ecp_lowerup (int unit); +static void ecp_lowerdown (int); +static void ecp_input (int unit, u_char *pkt, int len); +static void ecp_protrej (int unit); +*/ +#if PRINTPKT_SUPPORT +static int ecp_printpkt (const u_char *pkt, int len, + void (*printer) (void *, char *, ...), + void *arg); +#endif /* PRINTPKT_SUPPORT */ +/* +static void ecp_datainput (int unit, u_char *pkt, int len); +*/ + +const struct protent ecp_protent = { + PPP_ECP, + ecp_init, + NULL, /* ecp_input, */ + NULL, /* ecp_protrej, */ + NULL, /* ecp_lowerup, */ + NULL, /* ecp_lowerdown, */ + NULL, /* ecp_open, */ + NULL, /* ecp_close, */ +#if PRINTPKT_SUPPORT + ecp_printpkt, +#endif /* PRINTPKT_SUPPORT */ +#if PPP_DATAINPUT + NULL, /* ecp_datainput, */ +#endif /* PPP_DATAINPUT */ +#if PRINTPKT_SUPPORT + "ECP", + "Encrypted", +#endif /* PRINTPKT_SUPPORT */ +#if PPP_OPTIONS + ecp_option_list, + NULL, +#endif /* PPP_OPTIONS */ +#if DEMAND_SUPPORT + NULL, + NULL +#endif /* DEMAND_SUPPORT */ +}; + +fsm ecp_fsm[NUM_PPP]; +ecp_options ecp_wantoptions[NUM_PPP]; /* what to request the peer to use */ +ecp_options ecp_gotoptions[NUM_PPP]; /* what the peer agreed to do */ +ecp_options ecp_allowoptions[NUM_PPP]; /* what we'll agree to do */ +ecp_options ecp_hisoptions[NUM_PPP]; /* what we agreed to do */ + +static const fsm_callbacks ecp_callbacks = { + NULL, /* ecp_resetci, */ + NULL, /* ecp_cilen, */ + NULL, /* ecp_addci, */ + NULL, /* ecp_ackci, */ + NULL, /* ecp_nakci, */ + NULL, /* ecp_rejci, */ + NULL, /* ecp_reqci, */ + NULL, /* ecp_up, */ + NULL, /* ecp_down, */ + NULL, + NULL, + NULL, + NULL, + NULL, /* ecp_extcode, */ + "ECP" +}; + +/* + * ecp_init - initialize ECP. + */ +static void +ecp_init(unit) + int unit; +{ + fsm *f = &ecp_fsm[unit]; + + f->unit = unit; + f->protocol = PPP_ECP; + f->callbacks = &ecp_callbacks; + fsm_init(f); + +#if 0 /* Not necessary, everything is cleared in ppp_clear() */ + memset(&ecp_wantoptions[unit], 0, sizeof(ecp_options)); + memset(&ecp_gotoptions[unit], 0, sizeof(ecp_options)); + memset(&ecp_allowoptions[unit], 0, sizeof(ecp_options)); + memset(&ecp_hisoptions[unit], 0, sizeof(ecp_options)); +#endif /* 0 */ + +} + + +#if PRINTPKT_SUPPORT +static int +ecp_printpkt(p, plen, printer, arg) + const u_char *p; + int plen; + void (*printer) (void *, char *, ...); + void *arg; +{ + return 0; +} +#endif /* PRINTPKT_SUPPORT */ + +#endif /* PPP_SUPPORT && ECP_SUPPORT */ diff --git a/components/lwip/netif/ppp/eui64.c b/components/lwip/netif/ppp/eui64.c new file mode 100755 index 0000000000..e042eb4cbc --- /dev/null +++ b/components/lwip/netif/ppp/eui64.c @@ -0,0 +1,56 @@ +/* + * eui64.c - EUI64 routines for IPv6CP. + * + * Copyright (c) 1999 Tommi Komulainen. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. The name(s) of the authors of this software must not be used to + * endorse or promote products derived from this software without + * prior written permission. + * + * 4. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by Tommi Komulainen + * ". + * + * THE AUTHORS OF THIS SOFTWARE DISCLAIM ALL WARRANTIES WITH REGARD TO + * THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS, IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY + * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN + * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING + * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * $Id: eui64.c,v 1.6 2002/12/04 23:03:32 paulus Exp $ + */ + +#include "lwip/opt.h" +#if PPP_SUPPORT && PPP_IPV6_SUPPORT /* don't build if not configured for use in lwipopts.h */ + +#include "netif/ppp/ppp_impl.h" +#include "netif/ppp/eui64.h" + +/* + * eui64_ntoa - Make an ascii representation of an interface identifier + */ +char *eui64_ntoa(eui64_t e) { + static char buf[20]; + + sprintf(buf, "%02x%02x:%02x%02x:%02x%02x:%02x%02x", + e.e8[0], e.e8[1], e.e8[2], e.e8[3], + e.e8[4], e.e8[5], e.e8[6], e.e8[7]); + return buf; +} + +#endif /* PPP_SUPPORT && PPP_IPV6_SUPPORT */ diff --git a/components/lwip/netif/ppp/fsm.c b/components/lwip/netif/ppp/fsm.c new file mode 100755 index 0000000000..d7c514224f --- /dev/null +++ b/components/lwip/netif/ppp/fsm.c @@ -0,0 +1,799 @@ +/* + * fsm.c - {Link, IP} Control Protocol Finite State Machine. + * + * Copyright (c) 1984-2000 Carnegie Mellon University. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. The name "Carnegie Mellon University" must not be used to + * endorse or promote products derived from this software without + * prior written permission. For permission or any legal + * details, please contact + * Office of Technology Transfer + * Carnegie Mellon University + * 5000 Forbes Avenue + * Pittsburgh, PA 15213-3890 + * (412) 268-4387, fax: (412) 268-7395 + * tech-transfer@andrew.cmu.edu + * + * 4. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by Computing Services + * at Carnegie Mellon University (http://www.cmu.edu/computing/)." + * + * CARNEGIE MELLON UNIVERSITY DISCLAIMS ALL WARRANTIES WITH REGARD TO + * THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS, IN NO EVENT SHALL CARNEGIE MELLON UNIVERSITY BE LIABLE + * FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN + * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING + * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include "lwip/opt.h" +#if PPP_SUPPORT /* don't build if not configured for use in lwipopts.h */ + +/* + * TODO: + * Randomize fsm id on link/init. + * Deal with variable outgoing MTU. + */ + +#if 0 /* UNUSED */ +#include +#include +#include +#endif /* UNUSED */ + +#include "netif/ppp/ppp_impl.h" + +#include "netif/ppp/fsm.h" + +static void fsm_timeout (void *); +static void fsm_rconfreq(fsm *f, u_char id, u_char *inp, int len); +static void fsm_rconfack(fsm *f, int id, u_char *inp, int len); +static void fsm_rconfnakrej(fsm *f, int code, int id, u_char *inp, int len); +static void fsm_rtermreq(fsm *f, int id, u_char *p, int len); +static void fsm_rtermack(fsm *f); +static void fsm_rcoderej(fsm *f, u_char *inp, int len); +static void fsm_sconfreq(fsm *f, int retransmit); + +#define PROTO_NAME(f) ((f)->callbacks->proto_name) + +/* + * fsm_init - Initialize fsm. + * + * Initialize fsm state. + */ +void fsm_init(fsm *f) { + ppp_pcb *pcb = f->pcb; + f->state = PPP_FSM_INITIAL; + f->flags = 0; + f->id = 0; /* XXX Start with random id? */ + f->maxnakloops = pcb->settings.fsm_max_nak_loops; + f->term_reason_len = 0; +} + + +/* + * fsm_lowerup - The lower layer is up. + */ +void fsm_lowerup(fsm *f) { + switch( f->state ){ + case PPP_FSM_INITIAL: + f->state = PPP_FSM_CLOSED; + break; + + case PPP_FSM_STARTING: + if( f->flags & OPT_SILENT ) + f->state = PPP_FSM_STOPPED; + else { + /* Send an initial configure-request */ + fsm_sconfreq(f, 0); + f->state = PPP_FSM_REQSENT; + } + break; + + default: + FSMDEBUG(("%s: Up event in state %d!", PROTO_NAME(f), f->state)); + /* no break */ + } +} + + +/* + * fsm_lowerdown - The lower layer is down. + * + * Cancel all timeouts and inform upper layers. + */ +void fsm_lowerdown(fsm *f) { + switch( f->state ){ + case PPP_FSM_CLOSED: + f->state = PPP_FSM_INITIAL; + break; + + case PPP_FSM_STOPPED: + f->state = PPP_FSM_STARTING; + if( f->callbacks->starting ) + (*f->callbacks->starting)(f); + break; + + case PPP_FSM_CLOSING: + f->state = PPP_FSM_INITIAL; + UNTIMEOUT(fsm_timeout, f); /* Cancel timeout */ + break; + + case PPP_FSM_STOPPING: + case PPP_FSM_REQSENT: + case PPP_FSM_ACKRCVD: + case PPP_FSM_ACKSENT: + f->state = PPP_FSM_STARTING; + UNTIMEOUT(fsm_timeout, f); /* Cancel timeout */ + break; + + case PPP_FSM_OPENED: + if( f->callbacks->down ) + (*f->callbacks->down)(f); + f->state = PPP_FSM_STARTING; + break; + + default: + FSMDEBUG(("%s: Down event in state %d!", PROTO_NAME(f), f->state)); + /* no break */ + } +} + + +/* + * fsm_open - Link is allowed to come up. + */ +void fsm_open(fsm *f) { + switch( f->state ){ + case PPP_FSM_INITIAL: + f->state = PPP_FSM_STARTING; + if( f->callbacks->starting ) + (*f->callbacks->starting)(f); + break; + + case PPP_FSM_CLOSED: + if( f->flags & OPT_SILENT ) + f->state = PPP_FSM_STOPPED; + else { + /* Send an initial configure-request */ + fsm_sconfreq(f, 0); + f->state = PPP_FSM_REQSENT; + } + break; + + case PPP_FSM_CLOSING: + f->state = PPP_FSM_STOPPING; + /* fall through */ + /* no break */ + case PPP_FSM_STOPPED: + case PPP_FSM_OPENED: + if( f->flags & OPT_RESTART ){ + fsm_lowerdown(f); + fsm_lowerup(f); + } + break; + default: + break; + } +} + +/* + * terminate_layer - Start process of shutting down the FSM + * + * Cancel any timeout running, notify upper layers we're done, and + * send a terminate-request message as configured. + */ +static void terminate_layer(fsm *f, int nextstate) { + ppp_pcb *pcb = f->pcb; + + if( f->state != PPP_FSM_OPENED ) + UNTIMEOUT(fsm_timeout, f); /* Cancel timeout */ + else if( f->callbacks->down ) + (*f->callbacks->down)(f); /* Inform upper layers we're down */ + + /* Init restart counter and send Terminate-Request */ + f->retransmits = pcb->settings.fsm_max_term_transmits; + fsm_sdata(f, TERMREQ, f->reqid = ++f->id, + (const u_char *) f->term_reason, f->term_reason_len); + + if (f->retransmits == 0) { + /* + * User asked for no terminate requests at all; just close it. + * We've already fired off one Terminate-Request just to be nice + * to the peer, but we're not going to wait for a reply. + */ + f->state = nextstate == PPP_FSM_CLOSING ? PPP_FSM_CLOSED : PPP_FSM_STOPPED; + if( f->callbacks->finished ) + (*f->callbacks->finished)(f); + return; + } + + TIMEOUT(fsm_timeout, f, pcb->settings.fsm_timeout_time); + --f->retransmits; + + f->state = nextstate; +} + +/* + * fsm_close - Start closing connection. + * + * Cancel timeouts and either initiate close or possibly go directly to + * the PPP_FSM_CLOSED state. + */ +void fsm_close(fsm *f, const char *reason) { + f->term_reason = reason; + f->term_reason_len = (reason == NULL? 0: LWIP_MIN(strlen(reason), 0xFF) ); + switch( f->state ){ + case PPP_FSM_STARTING: + f->state = PPP_FSM_INITIAL; + break; + case PPP_FSM_STOPPED: + f->state = PPP_FSM_CLOSED; + break; + case PPP_FSM_STOPPING: + f->state = PPP_FSM_CLOSING; + break; + + case PPP_FSM_REQSENT: + case PPP_FSM_ACKRCVD: + case PPP_FSM_ACKSENT: + case PPP_FSM_OPENED: + terminate_layer(f, PPP_FSM_CLOSING); + break; + default: + break; + } +} + + +/* + * fsm_timeout - Timeout expired. + */ +static void fsm_timeout(void *arg) { + fsm *f = (fsm *) arg; + ppp_pcb *pcb = f->pcb; + + switch (f->state) { + case PPP_FSM_CLOSING: + case PPP_FSM_STOPPING: + if( f->retransmits <= 0 ){ + /* + * We've waited for an ack long enough. Peer probably heard us. + */ + f->state = (f->state == PPP_FSM_CLOSING)? PPP_FSM_CLOSED: PPP_FSM_STOPPED; + if( f->callbacks->finished ) + (*f->callbacks->finished)(f); + } else { + /* Send Terminate-Request */ + fsm_sdata(f, TERMREQ, f->reqid = ++f->id, + (const u_char *) f->term_reason, f->term_reason_len); + TIMEOUT(fsm_timeout, f, pcb->settings.fsm_timeout_time); + --f->retransmits; + } + break; + + case PPP_FSM_REQSENT: + case PPP_FSM_ACKRCVD: + case PPP_FSM_ACKSENT: + if (f->retransmits <= 0) { + ppp_warn("%s: timeout sending Config-Requests", PROTO_NAME(f)); + f->state = PPP_FSM_STOPPED; + if( (f->flags & OPT_PASSIVE) == 0 && f->callbacks->finished ) + (*f->callbacks->finished)(f); + + } else { + /* Retransmit the configure-request */ + if (f->callbacks->retransmit) + (*f->callbacks->retransmit)(f); + fsm_sconfreq(f, 1); /* Re-send Configure-Request */ + if( f->state == PPP_FSM_ACKRCVD ) + f->state = PPP_FSM_REQSENT; + } + break; + + default: + FSMDEBUG(("%s: Timeout event in state %d!", PROTO_NAME(f), f->state)); + /* no break */ + } +} + + +/* + * fsm_input - Input packet. + */ +void fsm_input(fsm *f, u_char *inpacket, int l) { + u_char *inp; + u_char code, id; + int len; + + /* + * Parse header (code, id and length). + * If packet too short, drop it. + */ + inp = inpacket; + if (l < HEADERLEN) { + FSMDEBUG(("fsm_input(%x): Rcvd short header.", f->protocol)); + return; + } + GETCHAR(code, inp); + GETCHAR(id, inp); + GETSHORT(len, inp); + if (len < HEADERLEN) { + FSMDEBUG(("fsm_input(%x): Rcvd illegal length.", f->protocol)); + return; + } + if (len > l) { + FSMDEBUG(("fsm_input(%x): Rcvd short packet.", f->protocol)); + return; + } + len -= HEADERLEN; /* subtract header length */ + + if( f->state == PPP_FSM_INITIAL || f->state == PPP_FSM_STARTING ){ + FSMDEBUG(("fsm_input(%x): Rcvd packet in state %d.", + f->protocol, f->state)); + return; + } + + /* + * Action depends on code. + */ + switch (code) { + case CONFREQ: + fsm_rconfreq(f, id, inp, len); + break; + + case CONFACK: + fsm_rconfack(f, id, inp, len); + break; + + case CONFNAK: + case CONFREJ: + fsm_rconfnakrej(f, code, id, inp, len); + break; + + case TERMREQ: + fsm_rtermreq(f, id, inp, len); + break; + + case TERMACK: + fsm_rtermack(f); + break; + + case CODEREJ: + fsm_rcoderej(f, inp, len); + break; + + default: + if( !f->callbacks->extcode + || !(*f->callbacks->extcode)(f, code, id, inp, len) ) + fsm_sdata(f, CODEREJ, ++f->id, inpacket, len + HEADERLEN); + break; + } +} + + +/* + * fsm_rconfreq - Receive Configure-Request. + */ +static void fsm_rconfreq(fsm *f, u_char id, u_char *inp, int len) { + int code, reject_if_disagree; + + switch( f->state ){ + case PPP_FSM_CLOSED: + /* Go away, we're closed */ + fsm_sdata(f, TERMACK, id, NULL, 0); + return; + case PPP_FSM_CLOSING: + case PPP_FSM_STOPPING: + return; + + case PPP_FSM_OPENED: + /* Go down and restart negotiation */ + if( f->callbacks->down ) + (*f->callbacks->down)(f); /* Inform upper layers */ + fsm_sconfreq(f, 0); /* Send initial Configure-Request */ + f->state = PPP_FSM_REQSENT; + break; + + case PPP_FSM_STOPPED: + /* Negotiation started by our peer */ + fsm_sconfreq(f, 0); /* Send initial Configure-Request */ + f->state = PPP_FSM_REQSENT; + break; + default: + break; + } + + /* + * Pass the requested configuration options + * to protocol-specific code for checking. + */ + if (f->callbacks->reqci){ /* Check CI */ + reject_if_disagree = (f->nakloops >= f->maxnakloops); + code = (*f->callbacks->reqci)(f, inp, &len, reject_if_disagree); + } else if (len) + code = CONFREJ; /* Reject all CI */ + else + code = CONFACK; + + /* send the Ack, Nak or Rej to the peer */ + fsm_sdata(f, code, id, inp, len); + + if (code == CONFACK) { + if (f->state == PPP_FSM_ACKRCVD) { + UNTIMEOUT(fsm_timeout, f); /* Cancel timeout */ + f->state = PPP_FSM_OPENED; + if (f->callbacks->up) + (*f->callbacks->up)(f); /* Inform upper layers */ + } else + f->state = PPP_FSM_ACKSENT; + f->nakloops = 0; + + } else { + /* we sent CONFACK or CONFREJ */ + if (f->state != PPP_FSM_ACKRCVD) + f->state = PPP_FSM_REQSENT; + if( code == CONFNAK ) + ++f->nakloops; + } +} + + +/* + * fsm_rconfack - Receive Configure-Ack. + */ +static void fsm_rconfack(fsm *f, int id, u_char *inp, int len) { + ppp_pcb *pcb = f->pcb; + + if (id != f->reqid || f->seen_ack) /* Expected id? */ + return; /* Nope, toss... */ + if( !(f->callbacks->ackci? (*f->callbacks->ackci)(f, inp, len): + (len == 0)) ){ + /* Ack is bad - ignore it */ + ppp_error("Received bad configure-ack: %P", inp, len); + return; + } + f->seen_ack = 1; + f->rnakloops = 0; + + switch (f->state) { + case PPP_FSM_CLOSED: + case PPP_FSM_STOPPED: + fsm_sdata(f, TERMACK, id, NULL, 0); + break; + + case PPP_FSM_REQSENT: + f->state = PPP_FSM_ACKRCVD; + f->retransmits = pcb->settings.fsm_max_conf_req_transmits; + break; + + case PPP_FSM_ACKRCVD: + /* Huh? an extra valid Ack? oh well... */ + UNTIMEOUT(fsm_timeout, f); /* Cancel timeout */ + fsm_sconfreq(f, 0); + f->state = PPP_FSM_REQSENT; + break; + + case PPP_FSM_ACKSENT: + UNTIMEOUT(fsm_timeout, f); /* Cancel timeout */ + f->state = PPP_FSM_OPENED; + f->retransmits = pcb->settings.fsm_max_conf_req_transmits; + if (f->callbacks->up) + (*f->callbacks->up)(f); /* Inform upper layers */ + break; + + case PPP_FSM_OPENED: + /* Go down and restart negotiation */ + if (f->callbacks->down) + (*f->callbacks->down)(f); /* Inform upper layers */ + fsm_sconfreq(f, 0); /* Send initial Configure-Request */ + f->state = PPP_FSM_REQSENT; + break; + default: + break; + } +} + + +/* + * fsm_rconfnakrej - Receive Configure-Nak or Configure-Reject. + */ +static void fsm_rconfnakrej(fsm *f, int code, int id, u_char *inp, int len) { + int ret; + int treat_as_reject; + + if (id != f->reqid || f->seen_ack) /* Expected id? */ + return; /* Nope, toss... */ + + if (code == CONFNAK) { + ++f->rnakloops; + treat_as_reject = (f->rnakloops >= f->maxnakloops); + if (f->callbacks->nakci == NULL + || !(ret = f->callbacks->nakci(f, inp, len, treat_as_reject))) { + ppp_error("Received bad configure-nak: %P", inp, len); + return; + } + } else { + f->rnakloops = 0; + if (f->callbacks->rejci == NULL + || !(ret = f->callbacks->rejci(f, inp, len))) { + ppp_error("Received bad configure-rej: %P", inp, len); + return; + } + } + + f->seen_ack = 1; + + switch (f->state) { + case PPP_FSM_CLOSED: + case PPP_FSM_STOPPED: + fsm_sdata(f, TERMACK, id, NULL, 0); + break; + + case PPP_FSM_REQSENT: + case PPP_FSM_ACKSENT: + /* They didn't agree to what we wanted - try another request */ + UNTIMEOUT(fsm_timeout, f); /* Cancel timeout */ + if (ret < 0) + f->state = PPP_FSM_STOPPED; /* kludge for stopping CCP */ + else + fsm_sconfreq(f, 0); /* Send Configure-Request */ + break; + + case PPP_FSM_ACKRCVD: + /* Got a Nak/reject when we had already had an Ack?? oh well... */ + UNTIMEOUT(fsm_timeout, f); /* Cancel timeout */ + fsm_sconfreq(f, 0); + f->state = PPP_FSM_REQSENT; + break; + + case PPP_FSM_OPENED: + /* Go down and restart negotiation */ + if (f->callbacks->down) + (*f->callbacks->down)(f); /* Inform upper layers */ + fsm_sconfreq(f, 0); /* Send initial Configure-Request */ + f->state = PPP_FSM_REQSENT; + break; + default: + break; + } +} + + +/* + * fsm_rtermreq - Receive Terminate-Req. + */ +static void fsm_rtermreq(fsm *f, int id, u_char *p, int len) { + ppp_pcb *pcb = f->pcb; + + switch (f->state) { + case PPP_FSM_ACKRCVD: + case PPP_FSM_ACKSENT: + f->state = PPP_FSM_REQSENT; /* Start over but keep trying */ + break; + + case PPP_FSM_OPENED: + if (len > 0) { + ppp_info("%s terminated by peer (%0.*v)", PROTO_NAME(f), len, p); + } else + ppp_info("%s terminated by peer", PROTO_NAME(f)); + f->retransmits = 0; + f->state = PPP_FSM_STOPPING; + if (f->callbacks->down) + (*f->callbacks->down)(f); /* Inform upper layers */ + TIMEOUT(fsm_timeout, f, pcb->settings.fsm_timeout_time); + break; + default: + break; + } + + fsm_sdata(f, TERMACK, id, NULL, 0); +} + + +/* + * fsm_rtermack - Receive Terminate-Ack. + */ +static void fsm_rtermack(fsm *f) { + switch (f->state) { + case PPP_FSM_CLOSING: + UNTIMEOUT(fsm_timeout, f); + f->state = PPP_FSM_CLOSED; + if( f->callbacks->finished ) + (*f->callbacks->finished)(f); + break; + case PPP_FSM_STOPPING: + UNTIMEOUT(fsm_timeout, f); + f->state = PPP_FSM_STOPPED; + if( f->callbacks->finished ) + (*f->callbacks->finished)(f); + break; + + case PPP_FSM_ACKRCVD: + f->state = PPP_FSM_REQSENT; + break; + + case PPP_FSM_OPENED: + if (f->callbacks->down) + (*f->callbacks->down)(f); /* Inform upper layers */ + fsm_sconfreq(f, 0); + f->state = PPP_FSM_REQSENT; + break; + default: + break; + } +} + + +/* + * fsm_rcoderej - Receive an Code-Reject. + */ +static void fsm_rcoderej(fsm *f, u_char *inp, int len) { + u_char code, id; + + if (len < HEADERLEN) { + FSMDEBUG(("fsm_rcoderej: Rcvd short Code-Reject packet!")); + return; + } + GETCHAR(code, inp); + GETCHAR(id, inp); + ppp_warn("%s: Rcvd Code-Reject for code %d, id %d", PROTO_NAME(f), code, id); + + if( f->state == PPP_FSM_ACKRCVD ) + f->state = PPP_FSM_REQSENT; +} + + +/* + * fsm_protreject - Peer doesn't speak this protocol. + * + * Treat this as a catastrophic error (RXJ-). + */ +void fsm_protreject(fsm *f) { + switch( f->state ){ + case PPP_FSM_CLOSING: + UNTIMEOUT(fsm_timeout, f); /* Cancel timeout */ + /* fall through */ + /* no break */ + case PPP_FSM_CLOSED: + f->state = PPP_FSM_CLOSED; + if( f->callbacks->finished ) + (*f->callbacks->finished)(f); + break; + + case PPP_FSM_STOPPING: + case PPP_FSM_REQSENT: + case PPP_FSM_ACKRCVD: + case PPP_FSM_ACKSENT: + UNTIMEOUT(fsm_timeout, f); /* Cancel timeout */ + /* fall through */ + /* no break */ + case PPP_FSM_STOPPED: + f->state = PPP_FSM_STOPPED; + if( f->callbacks->finished ) + (*f->callbacks->finished)(f); + break; + + case PPP_FSM_OPENED: + terminate_layer(f, PPP_FSM_STOPPING); + break; + + default: + FSMDEBUG(("%s: Protocol-reject event in state %d!", + PROTO_NAME(f), f->state)); + /* no break */ + } +} + + +/* + * fsm_sconfreq - Send a Configure-Request. + */ +static void fsm_sconfreq(fsm *f, int retransmit) { + ppp_pcb *pcb = f->pcb; + struct pbuf *p; + u_char *outp; + int cilen; + + if( f->state != PPP_FSM_REQSENT && f->state != PPP_FSM_ACKRCVD && f->state != PPP_FSM_ACKSENT ){ + /* Not currently negotiating - reset options */ + if( f->callbacks->resetci ) + (*f->callbacks->resetci)(f); + f->nakloops = 0; + f->rnakloops = 0; + } + + if( !retransmit ){ + /* New request - reset retransmission counter, use new ID */ + f->retransmits = pcb->settings.fsm_max_conf_req_transmits; + f->reqid = ++f->id; + } + + f->seen_ack = 0; + + /* + * Make up the request packet + */ + if( f->callbacks->cilen && f->callbacks->addci ){ + cilen = (*f->callbacks->cilen)(f); + if( cilen > pcb->peer_mru - HEADERLEN ) + cilen = pcb->peer_mru - HEADERLEN; + } else + cilen = 0; + + p = pbuf_alloc(PBUF_RAW, (u16_t)(cilen + HEADERLEN + PPP_HDRLEN), PPP_CTRL_PBUF_TYPE); + if(NULL == p) + return; + if(p->tot_len != p->len) { + pbuf_free(p); + return; + } + + /* send the request to our peer */ + outp = (u_char*)p->payload; + MAKEHEADER(outp, f->protocol); + PUTCHAR(CONFREQ, outp); + PUTCHAR(f->reqid, outp); + PUTSHORT(cilen + HEADERLEN, outp); + if (cilen != 0) { + (*f->callbacks->addci)(f, outp, &cilen); + LWIP_ASSERT("cilen == p->len - HEADERLEN - PPP_HDRLEN", cilen == p->len - HEADERLEN - PPP_HDRLEN); + } + + ppp_write(pcb, p); + + /* start the retransmit timer */ + --f->retransmits; + TIMEOUT(fsm_timeout, f, pcb->settings.fsm_timeout_time); +} + + +/* + * fsm_sdata - Send some data. + * + * Used for all packets sent to our peer by this module. + */ +void fsm_sdata(fsm *f, u_char code, u_char id, const u_char *data, int datalen) { + ppp_pcb *pcb = f->pcb; + struct pbuf *p; + u_char *outp; + int outlen; + + /* Adjust length to be smaller than MTU */ + if (datalen > pcb->peer_mru - HEADERLEN) + datalen = pcb->peer_mru - HEADERLEN; + outlen = datalen + HEADERLEN; + + p = pbuf_alloc(PBUF_RAW, (u16_t)(outlen + PPP_HDRLEN), PPP_CTRL_PBUF_TYPE); + if(NULL == p) + return; + if(p->tot_len != p->len) { + pbuf_free(p); + return; + } + + outp = (u_char*)p->payload; + if (datalen) /* && data != outp + PPP_HDRLEN + HEADERLEN) -- was only for fsm_sconfreq() */ + MEMCPY(outp + PPP_HDRLEN + HEADERLEN, data, datalen); + MAKEHEADER(outp, f->protocol); + PUTCHAR(code, outp); + PUTCHAR(id, outp); + PUTSHORT(outlen, outp); + ppp_write(pcb, p); +} + +#endif /* PPP_SUPPORT */ diff --git a/components/lwip/netif/ppp/ipcp.c b/components/lwip/netif/ppp/ipcp.c new file mode 100755 index 0000000000..5dc65f6f56 --- /dev/null +++ b/components/lwip/netif/ppp/ipcp.c @@ -0,0 +1,2408 @@ +/* + * ipcp.c - PPP IP Control Protocol. + * + * Copyright (c) 1984-2000 Carnegie Mellon University. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. The name "Carnegie Mellon University" must not be used to + * endorse or promote products derived from this software without + * prior written permission. For permission or any legal + * details, please contact + * Office of Technology Transfer + * Carnegie Mellon University + * 5000 Forbes Avenue + * Pittsburgh, PA 15213-3890 + * (412) 268-4387, fax: (412) 268-7395 + * tech-transfer@andrew.cmu.edu + * + * 4. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by Computing Services + * at Carnegie Mellon University (http://www.cmu.edu/computing/)." + * + * CARNEGIE MELLON UNIVERSITY DISCLAIMS ALL WARRANTIES WITH REGARD TO + * THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS, IN NO EVENT SHALL CARNEGIE MELLON UNIVERSITY BE LIABLE + * FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN + * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING + * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include "lwip/opt.h" +#if PPP_SUPPORT && PPP_IPV4_SUPPORT /* don't build if not configured for use in lwipopts.h */ + +/* + * TODO: + */ + +#if 0 /* UNUSED */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#endif /* UNUSED */ + +#include "netif/ppp/ppp_impl.h" + +#include "netif/ppp/fsm.h" +#include "netif/ppp/ipcp.h" + +#if 0 /* UNUSED */ +/* global vars */ +u32_t netmask = 0; /* IP netmask to set on interface */ +#endif /* UNUSED */ + +#if 0 /* UNUSED */ +bool disable_defaultip = 0; /* Don't use hostname for default IP adrs */ +#endif /* UNUSED */ + +#if 0 /* moved to ppp_settings */ +bool noremoteip = 0; /* Let him have no IP address */ +#endif /* moved to ppp_setting */ + +#if 0 /* UNUSED */ +/* Hook for a plugin to know when IP protocol has come up */ +void (*ip_up_hook) (void) = NULL; + +/* Hook for a plugin to know when IP protocol has come down */ +void (*ip_down_hook) (void) = NULL; + +/* Hook for a plugin to choose the remote IP address */ +void (*ip_choose_hook) (u32_t *) = NULL; +#endif /* UNUSED */ + +#if PPP_NOTIFY +/* Notifiers for when IPCP goes up and down */ +struct notifier *ip_up_notifier = NULL; +struct notifier *ip_down_notifier = NULL; +#endif /* PPP_NOTIFY */ + +/* local vars */ +#if 0 /* moved to ppp_pcb */ +static int default_route_set[NUM_PPP]; /* Have set up a default route */ +static int proxy_arp_set[NUM_PPP]; /* Have created proxy arp entry */ +static int ipcp_is_up; /* have called np_up() */ +static int ipcp_is_open; /* haven't called np_finished() */ +static bool ask_for_local; /* request our address from peer */ +#endif /* moved to ppp_pcb */ +#if 0 /* UNUSED */ +static char vj_value[8]; /* string form of vj option value */ +static char netmask_str[20]; /* string form of netmask value */ +#endif /* UNUSED */ + +/* + * Callbacks for fsm code. (CI = Configuration Information) + */ +static void ipcp_resetci(fsm *f); /* Reset our CI */ +static int ipcp_cilen(fsm *f); /* Return length of our CI */ +static void ipcp_addci(fsm *f, u_char *ucp, int *lenp); /* Add our CI */ +static int ipcp_ackci(fsm *f, u_char *p, int len); /* Peer ack'd our CI */ +static int ipcp_nakci(fsm *f, u_char *p, int len, int treat_as_reject);/* Peer nak'd our CI */ +static int ipcp_rejci(fsm *f, u_char *p, int len); /* Peer rej'd our CI */ +static int ipcp_reqci(fsm *f, u_char *inp, int *len, int reject_if_disagree); /* Rcv CI */ +static void ipcp_up(fsm *f); /* We're UP */ +static void ipcp_down(fsm *f); /* We're DOWN */ +static void ipcp_finished(fsm *f); /* Don't need lower layer */ + +static const fsm_callbacks ipcp_callbacks = { /* IPCP callback routines */ + ipcp_resetci, /* Reset our Configuration Information */ + ipcp_cilen, /* Length of our Configuration Information */ + ipcp_addci, /* Add our Configuration Information */ + ipcp_ackci, /* ACK our Configuration Information */ + ipcp_nakci, /* NAK our Configuration Information */ + ipcp_rejci, /* Reject our Configuration Information */ + ipcp_reqci, /* Request peer's Configuration Information */ + ipcp_up, /* Called when fsm reaches OPENED state */ + ipcp_down, /* Called when fsm leaves OPENED state */ + NULL, /* Called when we want the lower layer up */ + ipcp_finished, /* Called when we want the lower layer down */ + NULL, /* Called when Protocol-Reject received */ + NULL, /* Retransmission is necessary */ + NULL, /* Called to handle protocol-specific codes */ + "IPCP" /* String name of protocol */ +}; + +/* + * Command-line options. + */ +#if PPP_OPTIONS +static int setvjslots (char **); +static int setdnsaddr (char **); +static int setwinsaddr (char **); +static int setnetmask (char **); +int setipaddr (char *, char **, int); + +static void printipaddr (option_t *, void (*)(void *, char *,...),void *); + +static option_t ipcp_option_list[] = { + { "noip", o_bool, &ipcp_protent.enabled_flag, + "Disable IP and IPCP" }, + { "-ip", o_bool, &ipcp_protent.enabled_flag, + "Disable IP and IPCP", OPT_ALIAS }, + + { "novj", o_bool, &ipcp_wantoptions[0].neg_vj, + "Disable VJ compression", OPT_A2CLR, &ipcp_allowoptions[0].neg_vj }, + { "-vj", o_bool, &ipcp_wantoptions[0].neg_vj, + "Disable VJ compression", OPT_ALIAS | OPT_A2CLR, + &ipcp_allowoptions[0].neg_vj }, + + { "novjccomp", o_bool, &ipcp_wantoptions[0].cflag, + "Disable VJ connection-ID compression", OPT_A2CLR, + &ipcp_allowoptions[0].cflag }, + { "-vjccomp", o_bool, &ipcp_wantoptions[0].cflag, + "Disable VJ connection-ID compression", OPT_ALIAS | OPT_A2CLR, + &ipcp_allowoptions[0].cflag }, + + { "vj-max-slots", o_special, (void *)setvjslots, + "Set maximum VJ header slots", + OPT_PRIO | OPT_A2STRVAL | OPT_STATIC, vj_value }, + + { "ipcp-accept-local", o_bool, &ipcp_wantoptions[0].accept_local, + "Accept peer's address for us", 1 }, + { "ipcp-accept-remote", o_bool, &ipcp_wantoptions[0].accept_remote, + "Accept peer's address for it", 1 }, + + { "ipparam", o_string, &ipparam, + "Set ip script parameter", OPT_PRIO }, + + { "noipdefault", o_bool, &disable_defaultip, + "Don't use name for default IP adrs", 1 }, + + { "ms-dns", 1, (void *)setdnsaddr, + "DNS address for the peer's use" }, + { "ms-wins", 1, (void *)setwinsaddr, + "Nameserver for SMB over TCP/IP for peer" }, + + { "ipcp-restart", o_int, &ipcp_fsm[0].timeouttime, + "Set timeout for IPCP", OPT_PRIO }, + { "ipcp-max-terminate", o_int, &ipcp_fsm[0].maxtermtransmits, + "Set max #xmits for term-reqs", OPT_PRIO }, + { "ipcp-max-configure", o_int, &ipcp_fsm[0].maxconfreqtransmits, + "Set max #xmits for conf-reqs", OPT_PRIO }, + { "ipcp-max-failure", o_int, &ipcp_fsm[0].maxnakloops, + "Set max #conf-naks for IPCP", OPT_PRIO }, + + { "defaultroute", o_bool, &ipcp_wantoptions[0].default_route, + "Add default route", OPT_ENABLE|1, &ipcp_allowoptions[0].default_route }, + { "nodefaultroute", o_bool, &ipcp_allowoptions[0].default_route, + "disable defaultroute option", OPT_A2CLR, + &ipcp_wantoptions[0].default_route }, + { "-defaultroute", o_bool, &ipcp_allowoptions[0].default_route, + "disable defaultroute option", OPT_ALIAS | OPT_A2CLR, + &ipcp_wantoptions[0].default_route }, + + { "replacedefaultroute", o_bool, + &ipcp_wantoptions[0].replace_default_route, + "Replace default route", 1 + }, + { "noreplacedefaultroute", o_bool, + &ipcp_allowoptions[0].replace_default_route, + "Never replace default route", OPT_A2COPY, + &ipcp_wantoptions[0].replace_default_route }, + { "proxyarp", o_bool, &ipcp_wantoptions[0].proxy_arp, + "Add proxy ARP entry", OPT_ENABLE|1, &ipcp_allowoptions[0].proxy_arp }, + { "noproxyarp", o_bool, &ipcp_allowoptions[0].proxy_arp, + "disable proxyarp option", OPT_A2CLR, + &ipcp_wantoptions[0].proxy_arp }, + { "-proxyarp", o_bool, &ipcp_allowoptions[0].proxy_arp, + "disable proxyarp option", OPT_ALIAS | OPT_A2CLR, + &ipcp_wantoptions[0].proxy_arp }, + + { "usepeerdns", o_bool, &usepeerdns, + "Ask peer for DNS address(es)", 1 }, + + { "netmask", o_special, (void *)setnetmask, + "set netmask", OPT_PRIO | OPT_A2STRVAL | OPT_STATIC, netmask_str }, + + { "ipcp-no-addresses", o_bool, &ipcp_wantoptions[0].old_addrs, + "Disable old-style IP-Addresses usage", OPT_A2CLR, + &ipcp_allowoptions[0].old_addrs }, + { "ipcp-no-address", o_bool, &ipcp_wantoptions[0].neg_addr, + "Disable IP-Address usage", OPT_A2CLR, + &ipcp_allowoptions[0].neg_addr }, + + { "noremoteip", o_bool, &noremoteip, + "Allow peer to have no IP address", 1 }, + + { "nosendip", o_bool, &ipcp_wantoptions[0].neg_addr, + "Don't send our IP address to peer", OPT_A2CLR, + &ipcp_wantoptions[0].old_addrs}, + + { "IP addresses", o_wild, (void *) &setipaddr, + "set local and remote IP addresses", + OPT_NOARG | OPT_A2PRINTER, (void *) &printipaddr }, + + { NULL } +}; +#endif /* PPP_OPTIONS */ + +/* + * Protocol entry points from main code. + */ +static void ipcp_init(ppp_pcb *pcb); +static void ipcp_open(ppp_pcb *pcb); +static void ipcp_close(ppp_pcb *pcb, const char *reason); +static void ipcp_lowerup(ppp_pcb *pcb); +static void ipcp_lowerdown(ppp_pcb *pcb); +static void ipcp_input(ppp_pcb *pcb, u_char *p, int len); +static void ipcp_protrej(ppp_pcb *pcb); +#if PRINTPKT_SUPPORT +static int ipcp_printpkt(const u_char *p, int plen, + void (*printer) (void *, const char *, ...), void *arg); +#endif /* PRINTPKT_SUPPORT */ +#if PPP_OPTIONS +static void ip_check_options (void); +#endif /* PPP_OPTIONS */ +#if DEMAND_SUPPORT +static int ip_demand_conf (int); +static int ip_active_pkt (u_char *, int); +#endif /* DEMAND_SUPPORT */ +#if 0 /* UNUSED */ +static void create_resolv (u32_t, u32_t); +#endif /* UNUSED */ + +const struct protent ipcp_protent = { + PPP_IPCP, + ipcp_init, + ipcp_input, + ipcp_protrej, + ipcp_lowerup, + ipcp_lowerdown, + ipcp_open, + ipcp_close, +#if PRINTPKT_SUPPORT + ipcp_printpkt, +#endif /* PRINTPKT_SUPPORT */ +#if PPP_DATAINPUT + NULL, +#endif /* PPP_DATAINPUT */ +#if PRINTPKT_SUPPORT + "IPCP", + "IP", +#endif /* PRINTPKT_SUPPORT */ +#if PPP_OPTIONS + ipcp_option_list, + ip_check_options, +#endif /* PPP_OPTIONS */ +#if DEMAND_SUPPORT + ip_demand_conf, + ip_active_pkt +#endif /* DEMAND_SUPPORT */ +}; + +static void ipcp_clear_addrs(ppp_pcb *pcb, u32_t ouraddr, u32_t hisaddr, u8_t replacedefaultroute); + +/* + * Lengths of configuration options. + */ +#define CILEN_VOID 2 +#define CILEN_COMPRESS 4 /* min length for compression protocol opt. */ +#define CILEN_VJ 6 /* length for RFC1332 Van-Jacobson opt. */ +#define CILEN_ADDR 6 /* new-style single address option */ +#define CILEN_ADDRS 10 /* old-style dual address option */ + + +#define CODENAME(x) ((x) == CONFACK ? "ACK" : \ + (x) == CONFNAK ? "NAK" : "REJ") + +#if 0 /* UNUSED, already defined by lwIP */ +/* + * Make a string representation of a network IP address. + */ +char * +ip_ntoa(ipaddr) +u32_t ipaddr; +{ + static char b[64]; + + slprintf(b, sizeof(b), "%I", ipaddr); + return b; +} +#endif /* UNUSED, already defined by lwIP */ + +/* + * Option parsing. + */ +#if PPP_OPTIONS +/* + * setvjslots - set maximum number of connection slots for VJ compression + */ +static int +setvjslots(argv) + char **argv; +{ + int value; + +/* FIXME: found what int_option() did */ +#if PPP_OPTIONS + if (!int_option(*argv, &value)) + return 0; +#endif /* PPP_OPTIONS */ + + if (value < 2 || value > 16) { + option_error("vj-max-slots value must be between 2 and 16"); + return 0; + } + ipcp_wantoptions [0].maxslotindex = + ipcp_allowoptions[0].maxslotindex = value - 1; + slprintf(vj_value, sizeof(vj_value), "%d", value); + return 1; +} + +/* + * setdnsaddr - set the dns address(es) + */ +static int +setdnsaddr(argv) + char **argv; +{ + u32_t dns; + struct hostent *hp; + + dns = inet_addr(*argv); + if (dns == (u32_t) -1) { + if ((hp = gethostbyname(*argv)) == NULL) { + option_error("invalid address parameter '%s' for ms-dns option", + *argv); + return 0; + } + dns = *(u32_t *)hp->h_addr; + } + + /* We take the last 2 values given, the 2nd-last as the primary + and the last as the secondary. If only one is given it + becomes both primary and secondary. */ + if (ipcp_allowoptions[0].dnsaddr[1] == 0) + ipcp_allowoptions[0].dnsaddr[0] = dns; + else + ipcp_allowoptions[0].dnsaddr[0] = ipcp_allowoptions[0].dnsaddr[1]; + + /* always set the secondary address value. */ + ipcp_allowoptions[0].dnsaddr[1] = dns; + + return (1); +} + +/* + * setwinsaddr - set the wins address(es) + * This is primrarly used with the Samba package under UNIX or for pointing + * the caller to the existing WINS server on a Windows NT platform. + */ +static int +setwinsaddr(argv) + char **argv; +{ + u32_t wins; + struct hostent *hp; + + wins = inet_addr(*argv); + if (wins == (u32_t) -1) { + if ((hp = gethostbyname(*argv)) == NULL) { + option_error("invalid address parameter '%s' for ms-wins option", + *argv); + return 0; + } + wins = *(u32_t *)hp->h_addr; + } + + /* We take the last 2 values given, the 2nd-last as the primary + and the last as the secondary. If only one is given it + becomes both primary and secondary. */ + if (ipcp_allowoptions[0].winsaddr[1] == 0) + ipcp_allowoptions[0].winsaddr[0] = wins; + else + ipcp_allowoptions[0].winsaddr[0] = ipcp_allowoptions[0].winsaddr[1]; + + /* always set the secondary address value. */ + ipcp_allowoptions[0].winsaddr[1] = wins; + + return (1); +} + +/* + * setipaddr - Set the IP address + * If doit is 0, the call is to check whether this option is + * potentially an IP address specification. + * Not static so that plugins can call it to set the addresses + */ +int +setipaddr(arg, argv, doit) + char *arg; + char **argv; + int doit; +{ + struct hostent *hp; + char *colon; + u32_t local, remote; + ipcp_options *wo = &ipcp_wantoptions[0]; + static int prio_local = 0, prio_remote = 0; + + /* + * IP address pair separated by ":". + */ + if ((colon = strchr(arg, ':')) == NULL) + return 0; + if (!doit) + return 1; + + /* + * If colon first character, then no local addr. + */ + if (colon != arg && option_priority >= prio_local) { + *colon = '\0'; + if ((local = inet_addr(arg)) == (u32_t) -1) { + if ((hp = gethostbyname(arg)) == NULL) { + option_error("unknown host: %s", arg); + return 0; + } + local = *(u32_t *)hp->h_addr; + } + if (bad_ip_adrs(local)) { + option_error("bad local IP address %s", ip_ntoa(local)); + return 0; + } + if (local != 0) + wo->ouraddr = local; + *colon = ':'; + prio_local = option_priority; + } + + /* + * If colon last character, then no remote addr. + */ + if (*++colon != '\0' && option_priority >= prio_remote) { + if ((remote = inet_addr(colon)) == (u32_t) -1) { + if ((hp = gethostbyname(colon)) == NULL) { + option_error("unknown host: %s", colon); + return 0; + } + remote = *(u32_t *)hp->h_addr; + if (remote_name[0] == 0) + strlcpy(remote_name, colon, sizeof(remote_name)); + } + if (bad_ip_adrs(remote)) { + option_error("bad remote IP address %s", ip_ntoa(remote)); + return 0; + } + if (remote != 0) + wo->hisaddr = remote; + prio_remote = option_priority; + } + + return 1; +} + +static void +printipaddr(opt, printer, arg) + option_t *opt; + void (*printer) (void *, char *, ...); + void *arg; +{ + ipcp_options *wo = &ipcp_wantoptions[0]; + + if (wo->ouraddr != 0) + printer(arg, "%I", wo->ouraddr); + printer(arg, ":"); + if (wo->hisaddr != 0) + printer(arg, "%I", wo->hisaddr); +} + +/* + * setnetmask - set the netmask to be used on the interface. + */ +static int +setnetmask(argv) + char **argv; +{ + u32_t mask; + int n; + char *p; + + /* + * Unfortunately, if we use inet_addr, we can't tell whether + * a result of all 1s is an error or a valid 255.255.255.255. + */ + p = *argv; + n = parse_dotted_ip(p, &mask); + + mask = htonl(mask); + + if (n == 0 || p[n] != 0 || (netmask & ~mask) != 0) { + option_error("invalid netmask value '%s'", *argv); + return 0; + } + + netmask = mask; + slprintf(netmask_str, sizeof(netmask_str), "%I", mask); + + return (1); +} + +int +parse_dotted_ip(p, vp) + char *p; + u32_t *vp; +{ + int n; + u32_t v, b; + char *endp, *p0 = p; + + v = 0; + for (n = 3;; --n) { + b = strtoul(p, &endp, 0); + if (endp == p) + return 0; + if (b > 255) { + if (n < 3) + return 0; + /* accept e.g. 0xffffff00 */ + *vp = b; + return endp - p0; + } + v |= b << (n * 8); + p = endp; + if (n == 0) + break; + if (*p != '.') + return 0; + ++p; + } + *vp = v; + return p - p0; +} +#endif /* PPP_OPTIONS */ + +/* + * ipcp_init - Initialize IPCP. + */ +static void ipcp_init(ppp_pcb *pcb) { + fsm *f = &pcb->ipcp_fsm; + + ipcp_options *wo = &pcb->ipcp_wantoptions; + ipcp_options *ao = &pcb->ipcp_allowoptions; + + f->pcb = pcb; + f->protocol = PPP_IPCP; + f->callbacks = &ipcp_callbacks; + fsm_init(f); + + /* + * Some 3G modems use repeated IPCP NAKs as a way of stalling + * until they can contact a server on the network, so we increase + * the default number of NAKs we accept before we start treating + * them as rejects. + */ + f->maxnakloops = 100; + +#if 0 /* Not necessary, everything is cleared in ppp_clear() */ + memset(wo, 0, sizeof(*wo)); + memset(ao, 0, sizeof(*ao)); +#endif /* 0 */ + + wo->neg_addr = wo->old_addrs = 1; +#if VJ_SUPPORT + wo->neg_vj = 1; + wo->vj_protocol = IPCP_VJ_COMP; + wo->maxslotindex = MAX_STATES - 1; /* really max index */ + wo->cflag = 1; +#endif /* VJ_SUPPORT */ + +#if 0 /* UNUSED */ + /* wanting default route by default */ + wo->default_route = 1; +#endif /* UNUSED */ + + ao->neg_addr = ao->old_addrs = 1; +#if VJ_SUPPORT + /* max slots and slot-id compression are currently hardwired in */ + /* ppp_if.c to 16 and 1, this needs to be changed (among other */ + /* things) gmc */ + + ao->neg_vj = 1; + ao->maxslotindex = MAX_STATES - 1; + ao->cflag = 1; +#endif /* #if VJ_SUPPORT */ + +#if 0 /* UNUSED */ + /* + * XXX These control whether the user may use the proxyarp + * and defaultroute options. + */ + ao->proxy_arp = 1; + ao->default_route = 1; +#endif /* UNUSED */ +} + + +/* + * ipcp_open - IPCP is allowed to come up. + */ +static void ipcp_open(ppp_pcb *pcb) { + fsm *f = &pcb->ipcp_fsm; + fsm_open(f); + pcb->ipcp_is_open = 1; +} + + +/* + * ipcp_close - Take IPCP down. + */ +static void ipcp_close(ppp_pcb *pcb, const char *reason) { + fsm *f = &pcb->ipcp_fsm; + fsm_close(f, reason); +} + + +/* + * ipcp_lowerup - The lower layer is up. + */ +static void ipcp_lowerup(ppp_pcb *pcb) { + fsm *f = &pcb->ipcp_fsm; + fsm_lowerup(f); +} + + +/* + * ipcp_lowerdown - The lower layer is down. + */ +static void ipcp_lowerdown(ppp_pcb *pcb) { + fsm *f = &pcb->ipcp_fsm; + fsm_lowerdown(f); +} + + +/* + * ipcp_input - Input IPCP packet. + */ +static void ipcp_input(ppp_pcb *pcb, u_char *p, int len) { + fsm *f = &pcb->ipcp_fsm; + fsm_input(f, p, len); +} + + +/* + * ipcp_protrej - A Protocol-Reject was received for IPCP. + * + * Pretend the lower layer went down, so we shut up. + */ +static void ipcp_protrej(ppp_pcb *pcb) { + fsm *f = &pcb->ipcp_fsm; + fsm_lowerdown(f); +} + + +/* + * ipcp_resetci - Reset our CI. + * Called by fsm_sconfreq, Send Configure Request. + */ +static void ipcp_resetci(fsm *f) { + ppp_pcb *pcb = f->pcb; + ipcp_options *wo = &pcb->ipcp_wantoptions; + ipcp_options *go = &pcb->ipcp_gotoptions; + ipcp_options *ao = &pcb->ipcp_allowoptions; + + wo->req_addr = (wo->neg_addr || wo->old_addrs) && + (ao->neg_addr || ao->old_addrs); + if (wo->ouraddr == 0) + wo->accept_local = 1; + if (wo->hisaddr == 0) + wo->accept_remote = 1; +#if LWIP_DNS + wo->req_dns1 = wo->req_dns2 = pcb->settings.usepeerdns; /* Request DNS addresses from the peer */ +#endif /* LWIP_DNS */ + *go = *wo; +#if 0 /* UNUSED */ + /* We don't need ask_for_local, this is only useful for setup which + * can determine the local IP address from the system hostname. + */ + if (!ask_for_local) + go->ouraddr = 0; +#endif /* UNUSED */ +#if 0 /* UNUSED */ + if (ip_choose_hook) { + ip_choose_hook(&wo->hisaddr); + if (wo->hisaddr) { + wo->accept_remote = 0; + } + } +#endif /* UNUSED */ + BZERO(&pcb->ipcp_hisoptions, sizeof(ipcp_options)); +} + + +/* + * ipcp_cilen - Return length of our CI. + * Called by fsm_sconfreq, Send Configure Request. + */ +static int ipcp_cilen(fsm *f) { + ppp_pcb *pcb = f->pcb; + ipcp_options *go = &pcb->ipcp_gotoptions; +#if VJ_SUPPORT + ipcp_options *wo = &pcb->ipcp_wantoptions; +#endif /* VJ_SUPPORT */ + ipcp_options *ho = &pcb->ipcp_hisoptions; + +#define LENCIADDRS(neg) (neg ? CILEN_ADDRS : 0) +#if VJ_SUPPORT +#define LENCIVJ(neg, old) (neg ? (old? CILEN_COMPRESS : CILEN_VJ) : 0) +#endif /* VJ_SUPPORT */ +#define LENCIADDR(neg) (neg ? CILEN_ADDR : 0) +#if LWIP_DNS +#define LENCIDNS(neg) LENCIADDR(neg) +#endif /* LWIP_DNS */ +#if 0 /* UNUSED - WINS */ +#define LENCIWINS(neg) LENCIADDR(neg) +#endif /* UNUSED - WINS */ + + /* + * First see if we want to change our options to the old + * forms because we have received old forms from the peer. + */ + if (go->neg_addr && go->old_addrs && !ho->neg_addr && ho->old_addrs) + go->neg_addr = 0; + +#if VJ_SUPPORT + if (wo->neg_vj && !go->neg_vj && !go->old_vj) { + /* try an older style of VJ negotiation */ + /* use the old style only if the peer did */ + if (ho->neg_vj && ho->old_vj) { + go->neg_vj = 1; + go->old_vj = 1; + go->vj_protocol = ho->vj_protocol; + } + } +#endif /* VJ_SUPPORT */ + + return (LENCIADDRS(!go->neg_addr && go->old_addrs) + +#if VJ_SUPPORT + LENCIVJ(go->neg_vj, go->old_vj) + +#endif /* VJ_SUPPORT */ + LENCIADDR(go->neg_addr) + +#if LWIP_DNS + LENCIDNS(go->req_dns1) + + LENCIDNS(go->req_dns2) + +#endif /* LWIP_DNS */ +#if 0 /* UNUSED - WINS */ + LENCIWINS(go->winsaddr[0]) + + LENCIWINS(go->winsaddr[1]) + +#endif /* UNUSED - WINS */ + 0); +} + + +/* + * ipcp_addci - Add our desired CIs to a packet. + * Called by fsm_sconfreq, Send Configure Request. + */ +static void ipcp_addci(fsm *f, u_char *ucp, int *lenp) { + ppp_pcb *pcb = f->pcb; + ipcp_options *go = &pcb->ipcp_gotoptions; + int len = *lenp; + +#define ADDCIADDRS(opt, neg, val1, val2) \ + if (neg) { \ + if (len >= CILEN_ADDRS) { \ + u32_t l; \ + PUTCHAR(opt, ucp); \ + PUTCHAR(CILEN_ADDRS, ucp); \ + l = ntohl(val1); \ + PUTLONG(l, ucp); \ + l = ntohl(val2); \ + PUTLONG(l, ucp); \ + len -= CILEN_ADDRS; \ + } else \ + go->old_addrs = 0; \ + } + +#if VJ_SUPPORT +#define ADDCIVJ(opt, neg, val, old, maxslotindex, cflag) \ + if (neg) { \ + int vjlen = old? CILEN_COMPRESS : CILEN_VJ; \ + if (len >= vjlen) { \ + PUTCHAR(opt, ucp); \ + PUTCHAR(vjlen, ucp); \ + PUTSHORT(val, ucp); \ + if (!old) { \ + PUTCHAR(maxslotindex, ucp); \ + PUTCHAR(cflag, ucp); \ + } \ + len -= vjlen; \ + } else \ + neg = 0; \ + } +#endif /* VJ_SUPPORT */ + +#define ADDCIADDR(opt, neg, val) \ + if (neg) { \ + if (len >= CILEN_ADDR) { \ + u32_t l; \ + PUTCHAR(opt, ucp); \ + PUTCHAR(CILEN_ADDR, ucp); \ + l = ntohl(val); \ + PUTLONG(l, ucp); \ + len -= CILEN_ADDR; \ + } else \ + neg = 0; \ + } + +#if LWIP_DNS +#define ADDCIDNS(opt, neg, addr) \ + if (neg) { \ + if (len >= CILEN_ADDR) { \ + u32_t l; \ + PUTCHAR(opt, ucp); \ + PUTCHAR(CILEN_ADDR, ucp); \ + l = ntohl(addr); \ + PUTLONG(l, ucp); \ + len -= CILEN_ADDR; \ + } else \ + neg = 0; \ + } +#endif /* LWIP_DNS */ + +#if 0 /* UNUSED - WINS */ +#define ADDCIWINS(opt, addr) \ + if (addr) { \ + if (len >= CILEN_ADDR) { \ + u32_t l; \ + PUTCHAR(opt, ucp); \ + PUTCHAR(CILEN_ADDR, ucp); \ + l = ntohl(addr); \ + PUTLONG(l, ucp); \ + len -= CILEN_ADDR; \ + } else \ + addr = 0; \ + } +#endif /* UNUSED - WINS */ + + ADDCIADDRS(CI_ADDRS, !go->neg_addr && go->old_addrs, go->ouraddr, + go->hisaddr); + +#if VJ_SUPPORT + ADDCIVJ(CI_COMPRESSTYPE, go->neg_vj, go->vj_protocol, go->old_vj, + go->maxslotindex, go->cflag); +#endif /* VJ_SUPPORT */ + + ADDCIADDR(CI_ADDR, go->neg_addr, go->ouraddr); + +#if LWIP_DNS + ADDCIDNS(CI_MS_DNS1, go->req_dns1, go->dnsaddr[0]); + + ADDCIDNS(CI_MS_DNS2, go->req_dns2, go->dnsaddr[1]); +#endif /* LWIP_DNS */ + +#if 0 /* UNUSED - WINS */ + ADDCIWINS(CI_MS_WINS1, go->winsaddr[0]); + + ADDCIWINS(CI_MS_WINS2, go->winsaddr[1]); +#endif /* UNUSED - WINS */ + + *lenp -= len; +} + + +/* + * ipcp_ackci - Ack our CIs. + * Called by fsm_rconfack, Receive Configure ACK. + * + * Returns: + * 0 - Ack was bad. + * 1 - Ack was good. + */ +static int ipcp_ackci(fsm *f, u_char *p, int len) { + ppp_pcb *pcb = f->pcb; + ipcp_options *go = &pcb->ipcp_gotoptions; + u_short cilen, citype; + u32_t cilong; +#if VJ_SUPPORT + u_short cishort; + u_char cimaxslotindex, cicflag; +#endif /* VJ_SUPPORT */ + + /* + * CIs must be in exactly the same order that we sent... + * Check packet length and CI length at each step. + * If we find any deviations, then this packet is bad. + */ + +#define ACKCIADDRS(opt, neg, val1, val2) \ + if (neg) { \ + u32_t l; \ + if ((len -= CILEN_ADDRS) < 0) \ + goto bad; \ + GETCHAR(citype, p); \ + GETCHAR(cilen, p); \ + if (cilen != CILEN_ADDRS || \ + citype != opt) \ + goto bad; \ + GETLONG(l, p); \ + cilong = htonl(l); \ + if (val1 != cilong) \ + goto bad; \ + GETLONG(l, p); \ + cilong = htonl(l); \ + if (val2 != cilong) \ + goto bad; \ + } + +#if VJ_SUPPORT +#define ACKCIVJ(opt, neg, val, old, maxslotindex, cflag) \ + if (neg) { \ + int vjlen = old? CILEN_COMPRESS : CILEN_VJ; \ + if ((len -= vjlen) < 0) \ + goto bad; \ + GETCHAR(citype, p); \ + GETCHAR(cilen, p); \ + if (cilen != vjlen || \ + citype != opt) \ + goto bad; \ + GETSHORT(cishort, p); \ + if (cishort != val) \ + goto bad; \ + if (!old) { \ + GETCHAR(cimaxslotindex, p); \ + if (cimaxslotindex != maxslotindex) \ + goto bad; \ + GETCHAR(cicflag, p); \ + if (cicflag != cflag) \ + goto bad; \ + } \ + } +#endif /* VJ_SUPPORT */ + +#define ACKCIADDR(opt, neg, val) \ + if (neg) { \ + u32_t l; \ + if ((len -= CILEN_ADDR) < 0) \ + goto bad; \ + GETCHAR(citype, p); \ + GETCHAR(cilen, p); \ + if (cilen != CILEN_ADDR || \ + citype != opt) \ + goto bad; \ + GETLONG(l, p); \ + cilong = htonl(l); \ + if (val != cilong) \ + goto bad; \ + } + +#if LWIP_DNS +#define ACKCIDNS(opt, neg, addr) \ + if (neg) { \ + u32_t l; \ + if ((len -= CILEN_ADDR) < 0) \ + goto bad; \ + GETCHAR(citype, p); \ + GETCHAR(cilen, p); \ + if (cilen != CILEN_ADDR || citype != opt) \ + goto bad; \ + GETLONG(l, p); \ + cilong = htonl(l); \ + if (addr != cilong) \ + goto bad; \ + } +#endif /* LWIP_DNS */ + +#if 0 /* UNUSED - WINS */ +#define ACKCIWINS(opt, addr) \ + if (addr) { \ + u32_t l; \ + if ((len -= CILEN_ADDR) < 0) \ + goto bad; \ + GETCHAR(citype, p); \ + GETCHAR(cilen, p); \ + if (cilen != CILEN_ADDR || citype != opt) \ + goto bad; \ + GETLONG(l, p); \ + cilong = htonl(l); \ + if (addr != cilong) \ + goto bad; \ + } +#endif /* UNUSED - WINS */ + + ACKCIADDRS(CI_ADDRS, !go->neg_addr && go->old_addrs, go->ouraddr, + go->hisaddr); + +#if VJ_SUPPORT + ACKCIVJ(CI_COMPRESSTYPE, go->neg_vj, go->vj_protocol, go->old_vj, + go->maxslotindex, go->cflag); +#endif /* VJ_SUPPORT */ + + ACKCIADDR(CI_ADDR, go->neg_addr, go->ouraddr); + +#if LWIP_DNS + ACKCIDNS(CI_MS_DNS1, go->req_dns1, go->dnsaddr[0]); + + ACKCIDNS(CI_MS_DNS2, go->req_dns2, go->dnsaddr[1]); +#endif /* LWIP_DNS */ + +#if 0 /* UNUSED - WINS */ + ACKCIWINS(CI_MS_WINS1, go->winsaddr[0]); + + ACKCIWINS(CI_MS_WINS2, go->winsaddr[1]); +#endif /* UNUSED - WINS */ + + /* + * If there are any remaining CIs, then this packet is bad. + */ + if (len != 0) + goto bad; + return (1); + +bad: + IPCPDEBUG(("ipcp_ackci: received bad Ack!")); + return (0); +} + +/* + * ipcp_nakci - Peer has sent a NAK for some of our CIs. + * This should not modify any state if the Nak is bad + * or if IPCP is in the OPENED state. + * Calback from fsm_rconfnakrej - Receive Configure-Nak or Configure-Reject. + * + * Returns: + * 0 - Nak was bad. + * 1 - Nak was good. + */ +static int ipcp_nakci(fsm *f, u_char *p, int len, int treat_as_reject) { + ppp_pcb *pcb = f->pcb; + ipcp_options *go = &pcb->ipcp_gotoptions; + u_char citype, cilen, *next; +#if VJ_SUPPORT + u_char cimaxslotindex, cicflag; + u_short cishort; +#endif /* VJ_SUPPORT */ + u32_t ciaddr1, ciaddr2, l; +#if LWIP_DNS + u32_t cidnsaddr; +#endif /* LWIP_DNS */ + ipcp_options no; /* options we've seen Naks for */ + ipcp_options try_; /* options to request next time */ + + BZERO(&no, sizeof(no)); + try_ = *go; + + /* + * Any Nak'd CIs must be in exactly the same order that we sent. + * Check packet length and CI length at each step. + * If we find any deviations, then this packet is bad. + */ +#define NAKCIADDRS(opt, neg, code) \ + if ((neg) && \ + (cilen = p[1]) == CILEN_ADDRS && \ + len >= cilen && \ + p[0] == opt) { \ + len -= cilen; \ + INCPTR(2, p); \ + GETLONG(l, p); \ + ciaddr1 = htonl(l); \ + GETLONG(l, p); \ + ciaddr2 = htonl(l); \ + no.old_addrs = 1; \ + code \ + } + +#if VJ_SUPPORT +#define NAKCIVJ(opt, neg, code) \ + if (go->neg && \ + ((cilen = p[1]) == CILEN_COMPRESS || cilen == CILEN_VJ) && \ + len >= cilen && \ + p[0] == opt) { \ + len -= cilen; \ + INCPTR(2, p); \ + GETSHORT(cishort, p); \ + no.neg = 1; \ + code \ + } +#endif /* VJ_SUPPORT */ + +#define NAKCIADDR(opt, neg, code) \ + if (go->neg && \ + (cilen = p[1]) == CILEN_ADDR && \ + len >= cilen && \ + p[0] == opt) { \ + len -= cilen; \ + INCPTR(2, p); \ + GETLONG(l, p); \ + ciaddr1 = htonl(l); \ + no.neg = 1; \ + code \ + } + +#if LWIP_DNS +#define NAKCIDNS(opt, neg, code) \ + if (go->neg && \ + ((cilen = p[1]) == CILEN_ADDR) && \ + len >= cilen && \ + p[0] == opt) { \ + len -= cilen; \ + INCPTR(2, p); \ + GETLONG(l, p); \ + cidnsaddr = htonl(l); \ + no.neg = 1; \ + code \ + } +#endif /* LWIP_DNS */ + + /* + * Accept the peer's idea of {our,his} address, if different + * from our idea, only if the accept_{local,remote} flag is set. + */ + NAKCIADDRS(CI_ADDRS, !go->neg_addr && go->old_addrs, + if (treat_as_reject) { + try_.old_addrs = 0; + } else { + if (go->accept_local && ciaddr1) { + /* take his idea of our address */ + try_.ouraddr = ciaddr1; + } + if (go->accept_remote && ciaddr2) { + /* take his idea of his address */ + try_.hisaddr = ciaddr2; + } + } + ); + +#if VJ_SUPPORT + /* + * Accept the peer's value of maxslotindex provided that it + * is less than what we asked for. Turn off slot-ID compression + * if the peer wants. Send old-style compress-type option if + * the peer wants. + */ + NAKCIVJ(CI_COMPRESSTYPE, neg_vj, + if (treat_as_reject) { + try_.neg_vj = 0; + } else if (cilen == CILEN_VJ) { + GETCHAR(cimaxslotindex, p); + GETCHAR(cicflag, p); + if (cishort == IPCP_VJ_COMP) { + try_.old_vj = 0; + if (cimaxslotindex < go->maxslotindex) + try_.maxslotindex = cimaxslotindex; + if (!cicflag) + try_.cflag = 0; + } else { + try_.neg_vj = 0; + } + } else { + if (cishort == IPCP_VJ_COMP || cishort == IPCP_VJ_COMP_OLD) { + try_.old_vj = 1; + try_.vj_protocol = cishort; + } else { + try_.neg_vj = 0; + } + } + ); +#endif /* VJ_SUPPORT */ + + NAKCIADDR(CI_ADDR, neg_addr, + if (treat_as_reject) { + try_.neg_addr = 0; + try_.old_addrs = 0; + } else if (go->accept_local && ciaddr1) { + /* take his idea of our address */ + try_.ouraddr = ciaddr1; + } + ); + +#if LWIP_DNS + NAKCIDNS(CI_MS_DNS1, req_dns1, + if (treat_as_reject) { + try_.req_dns1 = 0; + } else { + try_.dnsaddr[0] = cidnsaddr; + } + ); + + NAKCIDNS(CI_MS_DNS2, req_dns2, + if (treat_as_reject) { + try_.req_dns2 = 0; + } else { + try_.dnsaddr[1] = cidnsaddr; + } + ); +#endif /* #if LWIP_DNS */ + + /* + * There may be remaining CIs, if the peer is requesting negotiation + * on an option that we didn't include in our request packet. + * If they want to negotiate about IP addresses, we comply. + * If they want us to ask for compression, we refuse. + * If they want us to ask for ms-dns, we do that, since some + * peers get huffy if we don't. + */ + while (len >= CILEN_VOID) { + GETCHAR(citype, p); + GETCHAR(cilen, p); + if ( cilen < CILEN_VOID || (len -= cilen) < 0 ) + goto bad; + next = p + cilen - 2; + + switch (citype) { +#if VJ_SUPPORT + case CI_COMPRESSTYPE: + if (go->neg_vj || no.neg_vj || + (cilen != CILEN_VJ && cilen != CILEN_COMPRESS)) + goto bad; + no.neg_vj = 1; + break; +#endif /* VJ_SUPPORT */ + case CI_ADDRS: + if ((!go->neg_addr && go->old_addrs) || no.old_addrs + || cilen != CILEN_ADDRS) + goto bad; + try_.neg_addr = 0; + GETLONG(l, p); + ciaddr1 = htonl(l); + if (ciaddr1 && go->accept_local) + try_.ouraddr = ciaddr1; + GETLONG(l, p); + ciaddr2 = htonl(l); + if (ciaddr2 && go->accept_remote) + try_.hisaddr = ciaddr2; + no.old_addrs = 1; + break; + case CI_ADDR: + if (go->neg_addr || no.neg_addr || cilen != CILEN_ADDR) + goto bad; + try_.old_addrs = 0; + GETLONG(l, p); + ciaddr1 = htonl(l); + if (ciaddr1 && go->accept_local) + try_.ouraddr = ciaddr1; + if (try_.ouraddr != 0) + try_.neg_addr = 1; + no.neg_addr = 1; + break; +#if LWIP_DNS + case CI_MS_DNS1: + if (go->req_dns1 || no.req_dns1 || cilen != CILEN_ADDR) + goto bad; + GETLONG(l, p); + try_.dnsaddr[0] = htonl(l); + try_.req_dns1 = 1; + no.req_dns1 = 1; + break; + case CI_MS_DNS2: + if (go->req_dns2 || no.req_dns2 || cilen != CILEN_ADDR) + goto bad; + GETLONG(l, p); + try_.dnsaddr[1] = htonl(l); + try_.req_dns2 = 1; + no.req_dns2 = 1; + break; +#endif /* LWIP_DNS */ +#if 0 /* UNUSED - WINS */ + case CI_MS_WINS1: + case CI_MS_WINS2: + if (cilen != CILEN_ADDR) + goto bad; + GETLONG(l, p); + ciaddr1 = htonl(l); + if (ciaddr1) + try_.winsaddr[citype == CI_MS_WINS2] = ciaddr1; + break; +#endif /* UNUSED - WINS */ + default: + break; + } + p = next; + } + + /* + * OK, the Nak is good. Now we can update state. + * If there are any remaining options, we ignore them. + */ + if (f->state != PPP_FSM_OPENED) + *go = try_; + + return 1; + +bad: + IPCPDEBUG(("ipcp_nakci: received bad Nak!")); + return 0; +} + + +/* + * ipcp_rejci - Reject some of our CIs. + * Callback from fsm_rconfnakrej. + */ +static int ipcp_rejci(fsm *f, u_char *p, int len) { + ppp_pcb *pcb = f->pcb; + ipcp_options *go = &pcb->ipcp_gotoptions; + u_char cilen; +#if VJ_SUPPORT + u_char cimaxslotindex, ciflag; + u_short cishort; +#endif /* VJ_SUPPORT */ + u32_t cilong; + ipcp_options try_; /* options to request next time */ + + try_ = *go; + /* + * Any Rejected CIs must be in exactly the same order that we sent. + * Check packet length and CI length at each step. + * If we find any deviations, then this packet is bad. + */ +#define REJCIADDRS(opt, neg, val1, val2) \ + if ((neg) && \ + (cilen = p[1]) == CILEN_ADDRS && \ + len >= cilen && \ + p[0] == opt) { \ + u32_t l; \ + len -= cilen; \ + INCPTR(2, p); \ + GETLONG(l, p); \ + cilong = htonl(l); \ + /* Check rejected value. */ \ + if (cilong != val1) \ + goto bad; \ + GETLONG(l, p); \ + cilong = htonl(l); \ + /* Check rejected value. */ \ + if (cilong != val2) \ + goto bad; \ + try_.old_addrs = 0; \ + } + +#if VJ_SUPPORT +#define REJCIVJ(opt, neg, val, old, maxslot, cflag) \ + if (go->neg && \ + p[1] == (old? CILEN_COMPRESS : CILEN_VJ) && \ + len >= p[1] && \ + p[0] == opt) { \ + len -= p[1]; \ + INCPTR(2, p); \ + GETSHORT(cishort, p); \ + /* Check rejected value. */ \ + if (cishort != val) \ + goto bad; \ + if (!old) { \ + GETCHAR(cimaxslotindex, p); \ + if (cimaxslotindex != maxslot) \ + goto bad; \ + GETCHAR(ciflag, p); \ + if (ciflag != cflag) \ + goto bad; \ + } \ + try_.neg = 0; \ + } +#endif /* VJ_SUPPORT */ + +#define REJCIADDR(opt, neg, val) \ + if (go->neg && \ + (cilen = p[1]) == CILEN_ADDR && \ + len >= cilen && \ + p[0] == opt) { \ + u32_t l; \ + len -= cilen; \ + INCPTR(2, p); \ + GETLONG(l, p); \ + cilong = htonl(l); \ + /* Check rejected value. */ \ + if (cilong != val) \ + goto bad; \ + try_.neg = 0; \ + } + +#if LWIP_DNS +#define REJCIDNS(opt, neg, dnsaddr) \ + if (go->neg && \ + ((cilen = p[1]) == CILEN_ADDR) && \ + len >= cilen && \ + p[0] == opt) { \ + u32_t l; \ + len -= cilen; \ + INCPTR(2, p); \ + GETLONG(l, p); \ + cilong = htonl(l); \ + /* Check rejected value. */ \ + if (cilong != dnsaddr) \ + goto bad; \ + try_.neg = 0; \ + } +#endif /* LWIP_DNS */ + +#if 0 /* UNUSED - WINS */ +#define REJCIWINS(opt, addr) \ + if (addr && \ + ((cilen = p[1]) == CILEN_ADDR) && \ + len >= cilen && \ + p[0] == opt) { \ + u32_t l; \ + len -= cilen; \ + INCPTR(2, p); \ + GETLONG(l, p); \ + cilong = htonl(l); \ + /* Check rejected value. */ \ + if (cilong != addr) \ + goto bad; \ + try_.winsaddr[opt == CI_MS_WINS2] = 0; \ + } +#endif /* UNUSED - WINS */ + + REJCIADDRS(CI_ADDRS, !go->neg_addr && go->old_addrs, + go->ouraddr, go->hisaddr); + +#if VJ_SUPPORT + REJCIVJ(CI_COMPRESSTYPE, neg_vj, go->vj_protocol, go->old_vj, + go->maxslotindex, go->cflag); +#endif /* VJ_SUPPORT */ + + REJCIADDR(CI_ADDR, neg_addr, go->ouraddr); + +#if LWIP_DNS + REJCIDNS(CI_MS_DNS1, req_dns1, go->dnsaddr[0]); + + REJCIDNS(CI_MS_DNS2, req_dns2, go->dnsaddr[1]); +#endif /* LWIP_DNS */ + +#if 0 /* UNUSED - WINS */ + REJCIWINS(CI_MS_WINS1, go->winsaddr[0]); + + REJCIWINS(CI_MS_WINS2, go->winsaddr[1]); +#endif /* UNUSED - WINS */ + + /* + * If there are any remaining CIs, then this packet is bad. + */ + if (len != 0) + goto bad; + /* + * Now we can update state. + */ + if (f->state != PPP_FSM_OPENED) + *go = try_; + return 1; + +bad: + IPCPDEBUG(("ipcp_rejci: received bad Reject!")); + return 0; +} + + +/* + * ipcp_reqci - Check the peer's requested CIs and send appropriate response. + * Callback from fsm_rconfreq, Receive Configure Request + * + * Returns: CONFACK, CONFNAK or CONFREJ and input packet modified + * appropriately. If reject_if_disagree is non-zero, doesn't return + * CONFNAK; returns CONFREJ if it can't return CONFACK. + * + * inp = Requested CIs + * len = Length of requested CIs + */ +static int ipcp_reqci(fsm *f, u_char *inp, int *len, int reject_if_disagree) { + ppp_pcb *pcb = f->pcb; + ipcp_options *wo = &pcb->ipcp_wantoptions; + ipcp_options *ho = &pcb->ipcp_hisoptions; + ipcp_options *ao = &pcb->ipcp_allowoptions; + u_char *cip, *next; /* Pointer to current and next CIs */ + u_short cilen, citype; /* Parsed len, type */ +#if VJ_SUPPORT + u_short cishort; /* Parsed short value */ +#endif /* VJ_SUPPORT */ + u32_t tl, ciaddr1, ciaddr2;/* Parsed address values */ + int rc = CONFACK; /* Final packet return code */ + int orc; /* Individual option return code */ + u_char *p; /* Pointer to next char to parse */ + u_char *ucp = inp; /* Pointer to current output char */ + int l = *len; /* Length left */ +#if VJ_SUPPORT + u_char maxslotindex, cflag; +#endif /* VJ_SUPPORT */ +#if LWIP_DNS + int d; +#endif /* LWIP_DNS */ + + /* + * Reset all his options. + */ + BZERO(ho, sizeof(*ho)); + + /* + * Process all his options. + */ + next = inp; + while (l) { + orc = CONFACK; /* Assume success */ + cip = p = next; /* Remember begining of CI */ + if (l < 2 || /* Not enough data for CI header or */ + p[1] < 2 || /* CI length too small or */ + p[1] > l) { /* CI length too big? */ + IPCPDEBUG(("ipcp_reqci: bad CI length!")); + orc = CONFREJ; /* Reject bad CI */ + cilen = l; /* Reject till end of packet */ + l = 0; /* Don't loop again */ + goto endswitch; + } + GETCHAR(citype, p); /* Parse CI type */ + GETCHAR(cilen, p); /* Parse CI length */ + l -= cilen; /* Adjust remaining length */ + next += cilen; /* Step to next CI */ + + switch (citype) { /* Check CI type */ + case CI_ADDRS: + if (!ao->old_addrs || ho->neg_addr || + cilen != CILEN_ADDRS) { /* Check CI length */ + orc = CONFREJ; /* Reject CI */ + break; + } + + /* + * If he has no address, or if we both have his address but + * disagree about it, then NAK it with our idea. + * In particular, if we don't know his address, but he does, + * then accept it. + */ + GETLONG(tl, p); /* Parse source address (his) */ + ciaddr1 = htonl(tl); + if (ciaddr1 != wo->hisaddr + && (ciaddr1 == 0 || !wo->accept_remote)) { + orc = CONFNAK; + if (!reject_if_disagree) { + DECPTR(sizeof(u32_t), p); + tl = ntohl(wo->hisaddr); + PUTLONG(tl, p); + } + } else if (ciaddr1 == 0 && wo->hisaddr == 0) { + /* + * If neither we nor he knows his address, reject the option. + */ + orc = CONFREJ; + wo->req_addr = 0; /* don't NAK with 0.0.0.0 later */ + break; + } + + /* + * If he doesn't know our address, or if we both have our address + * but disagree about it, then NAK it with our idea. + */ + GETLONG(tl, p); /* Parse desination address (ours) */ + ciaddr2 = htonl(tl); + if (ciaddr2 != wo->ouraddr) { + if (ciaddr2 == 0 || !wo->accept_local) { + orc = CONFNAK; + if (!reject_if_disagree) { + DECPTR(sizeof(u32_t), p); + tl = ntohl(wo->ouraddr); + PUTLONG(tl, p); + } + } else { + wo->ouraddr = ciaddr2; /* accept peer's idea */ + } + } + + ho->old_addrs = 1; + ho->hisaddr = ciaddr1; + ho->ouraddr = ciaddr2; + break; + + case CI_ADDR: + if (!ao->neg_addr || ho->old_addrs || + cilen != CILEN_ADDR) { /* Check CI length */ + orc = CONFREJ; /* Reject CI */ + break; + } + + /* + * If he has no address, or if we both have his address but + * disagree about it, then NAK it with our idea. + * In particular, if we don't know his address, but he does, + * then accept it. + */ + GETLONG(tl, p); /* Parse source address (his) */ + ciaddr1 = htonl(tl); + if (ciaddr1 != wo->hisaddr + && (ciaddr1 == 0 || !wo->accept_remote)) { + orc = CONFNAK; + if (!reject_if_disagree) { + DECPTR(sizeof(u32_t), p); + tl = ntohl(wo->hisaddr); + PUTLONG(tl, p); + } + } else if (ciaddr1 == 0 && wo->hisaddr == 0) { + /* + * Don't ACK an address of 0.0.0.0 - reject it instead. + */ + orc = CONFREJ; + wo->req_addr = 0; /* don't NAK with 0.0.0.0 later */ + break; + } + + ho->neg_addr = 1; + ho->hisaddr = ciaddr1; + break; + +#if LWIP_DNS + case CI_MS_DNS1: + case CI_MS_DNS2: + /* Microsoft primary or secondary DNS request */ + d = citype == CI_MS_DNS2; + + /* If we do not have a DNS address then we cannot send it */ + if (ao->dnsaddr[d] == 0 || + cilen != CILEN_ADDR) { /* Check CI length */ + orc = CONFREJ; /* Reject CI */ + break; + } + GETLONG(tl, p); + if (htonl(tl) != ao->dnsaddr[d]) { + DECPTR(sizeof(u32_t), p); + tl = ntohl(ao->dnsaddr[d]); + PUTLONG(tl, p); + orc = CONFNAK; + } + break; +#endif /* LWIP_DNS */ + +#if 0 /* UNUSED - WINS */ + case CI_MS_WINS1: + case CI_MS_WINS2: + /* Microsoft primary or secondary WINS request */ + d = citype == CI_MS_WINS2; + + /* If we do not have a DNS address then we cannot send it */ + if (ao->winsaddr[d] == 0 || + cilen != CILEN_ADDR) { /* Check CI length */ + orc = CONFREJ; /* Reject CI */ + break; + } + GETLONG(tl, p); + if (htonl(tl) != ao->winsaddr[d]) { + DECPTR(sizeof(u32_t), p); + tl = ntohl(ao->winsaddr[d]); + PUTLONG(tl, p); + orc = CONFNAK; + } + break; +#endif /* UNUSED - WINS */ + +#if VJ_SUPPORT + case CI_COMPRESSTYPE: + if (!ao->neg_vj || + (cilen != CILEN_VJ && cilen != CILEN_COMPRESS)) { + orc = CONFREJ; + break; + } + GETSHORT(cishort, p); + + if (!(cishort == IPCP_VJ_COMP || + (cishort == IPCP_VJ_COMP_OLD && cilen == CILEN_COMPRESS))) { + orc = CONFREJ; + break; + } + + ho->neg_vj = 1; + ho->vj_protocol = cishort; + if (cilen == CILEN_VJ) { + GETCHAR(maxslotindex, p); + if (maxslotindex > ao->maxslotindex) { + orc = CONFNAK; + if (!reject_if_disagree){ + DECPTR(1, p); + PUTCHAR(ao->maxslotindex, p); + } + } + GETCHAR(cflag, p); + if (cflag && !ao->cflag) { + orc = CONFNAK; + if (!reject_if_disagree){ + DECPTR(1, p); + PUTCHAR(wo->cflag, p); + } + } + ho->maxslotindex = maxslotindex; + ho->cflag = cflag; + } else { + ho->old_vj = 1; + ho->maxslotindex = MAX_STATES - 1; + ho->cflag = 1; + } + break; +#endif /* VJ_SUPPORT */ + + default: + orc = CONFREJ; + break; + } +endswitch: + if (orc == CONFACK && /* Good CI */ + rc != CONFACK) /* but prior CI wasnt? */ + continue; /* Don't send this one */ + + if (orc == CONFNAK) { /* Nak this CI? */ + if (reject_if_disagree) /* Getting fed up with sending NAKs? */ + orc = CONFREJ; /* Get tough if so */ + else { + if (rc == CONFREJ) /* Rejecting prior CI? */ + continue; /* Don't send this one */ + if (rc == CONFACK) { /* Ack'd all prior CIs? */ + rc = CONFNAK; /* Not anymore... */ + ucp = inp; /* Backup */ + } + } + } + + if (orc == CONFREJ && /* Reject this CI */ + rc != CONFREJ) { /* but no prior ones? */ + rc = CONFREJ; + ucp = inp; /* Backup */ + } + + /* Need to move CI? */ + if (ucp != cip) + MEMCPY(ucp, cip, cilen); /* Move it */ + + /* Update output pointer */ + INCPTR(cilen, ucp); + } + + /* + * If we aren't rejecting this packet, and we want to negotiate + * their address, and they didn't send their address, then we + * send a NAK with a CI_ADDR option appended. We assume the + * input buffer is long enough that we can append the extra + * option safely. + */ + if (rc != CONFREJ && !ho->neg_addr && !ho->old_addrs && + wo->req_addr && !reject_if_disagree && !pcb->settings.noremoteip) { + if (rc == CONFACK) { + rc = CONFNAK; + ucp = inp; /* reset pointer */ + wo->req_addr = 0; /* don't ask again */ + } + PUTCHAR(CI_ADDR, ucp); + PUTCHAR(CILEN_ADDR, ucp); + tl = ntohl(wo->hisaddr); + PUTLONG(tl, ucp); + } + + *len = ucp - inp; /* Compute output length */ + IPCPDEBUG(("ipcp: returning Configure-%s", CODENAME(rc))); + return (rc); /* Return final code */ +} + + +#if 0 /* UNUSED */ +/* + * ip_check_options - check that any IP-related options are OK, + * and assign appropriate defaults. + */ +static void +ip_check_options() +{ + struct hostent *hp; + u32_t local; + ipcp_options *wo = &ipcp_wantoptions[0]; + + /* + * Default our local IP address based on our hostname. + * If local IP address already given, don't bother. + */ + if (wo->ouraddr == 0 && !disable_defaultip) { + /* + * Look up our hostname (possibly with domain name appended) + * and take the first IP address as our local IP address. + * If there isn't an IP address for our hostname, too bad. + */ + wo->accept_local = 1; /* don't insist on this default value */ + if ((hp = gethostbyname(hostname)) != NULL) { + local = *(u32_t *)hp->h_addr; + if (local != 0 && !bad_ip_adrs(local)) + wo->ouraddr = local; + } + } + ask_for_local = wo->ouraddr != 0 || !disable_defaultip; +} +#endif /* UNUSED */ + +#if DEMAND_SUPPORT +/* + * ip_demand_conf - configure the interface as though + * IPCP were up, for use with dial-on-demand. + */ +static int +ip_demand_conf(u) + int u; +{ + ppp_pcb *pcb = &ppp_pcb_list[u]; + ipcp_options *wo = &ipcp_wantoptions[u]; + + if (wo->hisaddr == 0 && !pcb->settings.noremoteip) { + /* make up an arbitrary address for the peer */ + wo->hisaddr = htonl(0x0a707070 + ifunit); + wo->accept_remote = 1; + } + if (wo->ouraddr == 0) { + /* make up an arbitrary address for us */ + wo->ouraddr = htonl(0x0a404040 + ifunit); + wo->accept_local = 1; + ask_for_local = 0; /* don't tell the peer this address */ + } + if (!sifaddr(pcb, wo->ouraddr, wo->hisaddr, get_mask(wo->ouraddr))) + return 0; + if (!sifup(pcb)) + return 0; + if (!sifnpmode(pcb, PPP_IP, NPMODE_QUEUE)) + return 0; +#if 0 /* UNUSED */ + if (wo->default_route) + if (sifdefaultroute(pcb, wo->ouraddr, wo->hisaddr, + wo->replace_default_route)) + default_route_set[u] = 1; +#endif /* UNUSED */ +#if 0 /* UNUSED - PROXY ARP */ + if (wo->proxy_arp) + if (sifproxyarp(pcb, wo->hisaddr)) + proxy_arp_set[u] = 1; +#endif /* UNUSED - PROXY ARP */ + + ppp_notice("local IP address %I", wo->ouraddr); + if (wo->hisaddr) + ppp_notice("remote IP address %I", wo->hisaddr); + + return 1; +} +#endif /* DEMAND_SUPPORT */ + +/* + * ipcp_up - IPCP has come UP. + * + * Configure the IP network interface appropriately and bring it up. + */ +static void ipcp_up(fsm *f) { + ppp_pcb *pcb = f->pcb; + u32_t mask; + ipcp_options *ho = &pcb->ipcp_hisoptions; + ipcp_options *go = &pcb->ipcp_gotoptions; + ipcp_options *wo = &pcb->ipcp_wantoptions; + + IPCPDEBUG(("ipcp: up")); + + /* + * We must have a non-zero IP address for both ends of the link. + */ + if (!ho->neg_addr && !ho->old_addrs) + ho->hisaddr = wo->hisaddr; + + if (!(go->neg_addr || go->old_addrs) && (wo->neg_addr || wo->old_addrs) + && wo->ouraddr != 0) { + ppp_error("Peer refused to agree to our IP address"); + ipcp_close(f->pcb, "Refused our IP address"); + return; + } + if (go->ouraddr == 0) { + ppp_error("Could not determine local IP address"); + ipcp_close(f->pcb, "Could not determine local IP address"); + return; + } + if (ho->hisaddr == 0 && !pcb->settings.noremoteip) { + ho->hisaddr = htonl(0x0a404040); + ppp_warn("Could not determine remote IP address: defaulting to %I", + ho->hisaddr); + } +#if 0 /* UNUSED */ + script_setenv("IPLOCAL", ip_ntoa(go->ouraddr), 0); + if (ho->hisaddr != 0) + script_setenv("IPREMOTE", ip_ntoa(ho->hisaddr), 1); +#endif /* UNUSED */ + +#if LWIP_DNS + if (!go->req_dns1) + go->dnsaddr[0] = 0; + if (!go->req_dns2) + go->dnsaddr[1] = 0; +#if 0 /* UNUSED */ + if (go->dnsaddr[0]) + script_setenv("DNS1", ip_ntoa(go->dnsaddr[0]), 0); + if (go->dnsaddr[1]) + script_setenv("DNS2", ip_ntoa(go->dnsaddr[1]), 0); +#endif /* UNUSED */ + if (pcb->settings.usepeerdns && (go->dnsaddr[0] || go->dnsaddr[1])) { + sdns(pcb, go->dnsaddr[0], go->dnsaddr[1]); +#if 0 /* UNUSED */ + script_setenv("USEPEERDNS", "1", 0); + create_resolv(go->dnsaddr[0], go->dnsaddr[1]); +#endif /* UNUSED */ + } +#endif /* LWIP_DNS */ + +/* FIXME: check why it fails, just to know */ +#if 0 /* Unused */ + /* + * Check that the peer is allowed to use the IP address it wants. + */ + if (ho->hisaddr != 0 && !auth_ip_addr(f->unit, ho->hisaddr)) { + ppp_error("Peer is not authorized to use remote address %I", ho->hisaddr); + ipcp_close(f->unit, "Unauthorized remote IP address"); + return; + } +#endif /* Unused */ + +#if VJ_SUPPORT + /* set tcp compression */ + sifvjcomp(pcb, ho->neg_vj, ho->cflag, ho->maxslotindex); +#endif /* VJ_SUPPORT */ + +#if DEMAND_SUPPORT + /* + * If we are doing dial-on-demand, the interface is already + * configured, so we put out any saved-up packets, then set the + * interface to pass IP packets. + */ + if (demand) { + if (go->ouraddr != wo->ouraddr || ho->hisaddr != wo->hisaddr) { + ipcp_clear_addrs(f->unit, wo->ouraddr, wo->hisaddr, + wo->replace_default_route); + if (go->ouraddr != wo->ouraddr) { + ppp_warn("Local IP address changed to %I", go->ouraddr); + script_setenv("OLDIPLOCAL", ip_ntoa(wo->ouraddr), 0); + wo->ouraddr = go->ouraddr; + } else + script_unsetenv("OLDIPLOCAL"); + if (ho->hisaddr != wo->hisaddr && wo->hisaddr != 0) { + ppp_warn("Remote IP address changed to %I", ho->hisaddr); + script_setenv("OLDIPREMOTE", ip_ntoa(wo->hisaddr), 0); + wo->hisaddr = ho->hisaddr; + } else + script_unsetenv("OLDIPREMOTE"); + + /* Set the interface to the new addresses */ + mask = get_mask(go->ouraddr); + if (!sifaddr(pcb, go->ouraddr, ho->hisaddr, mask)) { +#if PPP_DEBUG + ppp_warn("Interface configuration failed"); +#endif /* PPP_DEBUG */ + ipcp_close(f->unit, "Interface configuration failed"); + return; + } + + /* assign a default route through the interface if required */ + if (ipcp_wantoptions[f->unit].default_route) + if (sifdefaultroute(pcb, go->ouraddr, ho->hisaddr, + wo->replace_default_route)) + default_route_set[f->unit] = 1; + +#if 0 /* UNUSED - PROXY ARP */ + /* Make a proxy ARP entry if requested. */ + if (ho->hisaddr != 0 && ipcp_wantoptions[f->unit].proxy_arp) + if (sifproxyarp(pcb, ho->hisaddr)) + proxy_arp_set[f->unit] = 1; +#endif /* UNUSED - PROXY ARP */ + + } + demand_rexmit(PPP_IP,go->ouraddr); + sifnpmode(pcb, PPP_IP, NPMODE_PASS); + + } else +#endif /* DEMAND_SUPPORT */ + { + /* + * Set IP addresses and (if specified) netmask. + */ + mask = get_mask(go->ouraddr); + +#if !(defined(SVR4) && (defined(SNI) || defined(__USLC__))) + if (!sifaddr(pcb, go->ouraddr, ho->hisaddr, mask)) { +#if PPP_DEBUG + ppp_warn("Interface configuration failed"); +#endif /* PPP_DEBUG */ + ipcp_close(f->pcb, "Interface configuration failed"); + return; + } +#endif + + /* bring the interface up for IP */ + if (!sifup(pcb)) { +#if PPP_DEBUG + ppp_warn("Interface failed to come up"); +#endif /* PPP_DEBUG */ + ipcp_close(f->pcb, "Interface configuration failed"); + return; + } + +#if (defined(SVR4) && (defined(SNI) || defined(__USLC__))) + if (!sifaddr(pcb, go->ouraddr, ho->hisaddr, mask)) { +#if PPP_DEBUG + ppp_warn("Interface configuration failed"); +#endif /* PPP_DEBUG */ + ipcp_close(f->unit, "Interface configuration failed"); + return; + } +#endif +#if DEMAND_SUPPORT + sifnpmode(pcb, PPP_IP, NPMODE_PASS); +#endif /* DEMAND_SUPPORT */ + +#if 0 /* UNUSED */ + /* assign a default route through the interface if required */ + if (wo->default_route) + if (sifdefaultroute(pcb, go->ouraddr, ho->hisaddr, + wo->replace_default_route)) + pcb->default_route_set = 1; +#endif /* UNUSED */ + +#if 0 /* UNUSED - PROXY ARP */ + /* Make a proxy ARP entry if requested. */ + if (ho->hisaddr != 0 && wo->proxy_arp) + if (sifproxyarp(pcb, ho->hisaddr)) + pcb->proxy_arp_set = 1; +#endif /* UNUSED - PROXY ARP */ + + wo->ouraddr = go->ouraddr; + + ppp_notice("local IP address %I", go->ouraddr); + if (ho->hisaddr != 0) + ppp_notice("remote IP address %I", ho->hisaddr); +#if LWIP_DNS + if (go->dnsaddr[0]) + ppp_notice("primary DNS address %I", go->dnsaddr[0]); + if (go->dnsaddr[1]) + ppp_notice("secondary DNS address %I", go->dnsaddr[1]); +#endif /* LWIP_DNS */ + } + +#if PPP_STATS_SUPPORT + reset_link_stats(f->unit); +#endif /* PPP_STATS_SUPPORT */ + + np_up(pcb, PPP_IP); + pcb->ipcp_is_up = 1; + +#if PPP_NOTIFY + notify(ip_up_notifier, 0); +#endif /* PPP_NOTIFY */ +#if 0 /* UNUSED */ + if (ip_up_hook) + ip_up_hook(); +#endif /* UNUSED */ +} + + +/* + * ipcp_down - IPCP has gone DOWN. + * + * Take the IP network interface down, clear its addresses + * and delete routes through it. + */ +static void ipcp_down(fsm *f) { + ppp_pcb *pcb = f->pcb; + ipcp_options *ho = &pcb->ipcp_hisoptions; + ipcp_options *go = &pcb->ipcp_gotoptions; + + IPCPDEBUG(("ipcp: down")); +#if PPP_STATS_SUPPORT + /* XXX a bit IPv4-centric here, we only need to get the stats + * before the interface is marked down. */ + /* XXX more correct: we must get the stats before running the notifiers, + * at least for the radius plugin */ + update_link_stats(f->unit); +#endif /* PPP_STATS_SUPPORT */ +#if PPP_NOTIFY + notify(ip_down_notifier, 0); +#endif /* PPP_NOTIFY */ +#if 0 /* UNUSED */ + if (ip_down_hook) + ip_down_hook(); +#endif /* UNUSED */ + if (pcb->ipcp_is_up) { + pcb->ipcp_is_up = 0; + np_down(pcb, PPP_IP); + } +#if VJ_SUPPORT + sifvjcomp(pcb, 0, 0, 0); +#endif /* VJ_SUPPORT */ + +#if PPP_STATS_SUPPORT + print_link_stats(); /* _after_ running the notifiers and ip_down_hook(), + * because print_link_stats() sets link_stats_valid + * to 0 (zero) */ +#endif /* PPP_STATS_SUPPORT */ + +#if DEMAND_SUPPORT + /* + * If we are doing dial-on-demand, set the interface + * to queue up outgoing packets (for now). + */ + if (demand) { + sifnpmode(pcb, PPP_IP, NPMODE_QUEUE); + } else +#endif /* DEMAND_SUPPORT */ + { +#if DEMAND_SUPPORT + sifnpmode(pcb, PPP_IP, NPMODE_DROP); +#endif /* DEMAND_SUPPORT */ + sifdown(pcb); + ipcp_clear_addrs(pcb, go->ouraddr, + ho->hisaddr, 0); +#if LWIP_DNS + cdns(pcb, go->dnsaddr[0], go->dnsaddr[1]); +#endif /* LWIP_DNS */ + } +} + + +/* + * ipcp_clear_addrs() - clear the interface addresses, routes, + * proxy arp entries, etc. + */ +static void ipcp_clear_addrs(ppp_pcb *pcb, u32_t ouraddr, u32_t hisaddr, u8_t replacedefaultroute) { + LWIP_UNUSED_ARG(replacedefaultroute); + +#if 0 /* UNUSED - PROXY ARP */ + if (pcb->proxy_arp_set) { + cifproxyarp(pcb, hisaddr); + pcb->proxy_arp_set = 0; + } +#endif /* UNUSED - PROXY ARP */ +#if 0 /* UNUSED */ + /* If replacedefaultroute, sifdefaultroute will be called soon + * with replacedefaultroute set and that will overwrite the current + * default route. This is the case only when doing demand, otherwise + * during demand, this cifdefaultroute would restore the old default + * route which is not what we want in this case. In the non-demand + * case, we'll delete the default route and restore the old if there + * is one saved by an sifdefaultroute with replacedefaultroute. + */ + if (!replacedefaultroute && pcb->default_route_set) { + cifdefaultroute(pcb, ouraddr, hisaddr); + pcb->default_route_set = 0; + } +#endif /* UNUSED */ + cifaddr(pcb, ouraddr, hisaddr); +} + + +/* + * ipcp_finished - possibly shut down the lower layers. + */ +static void ipcp_finished(fsm *f) { + ppp_pcb *pcb = f->pcb; + if (pcb->ipcp_is_open) { + pcb->ipcp_is_open = 0; + np_finished(pcb, PPP_IP); + } +} + + +#if 0 /* UNUSED */ +/* + * create_resolv - create the replacement resolv.conf file + */ +static void +create_resolv(peerdns1, peerdns2) + u32_t peerdns1, peerdns2; +{ + +} +#endif /* UNUSED */ + +#if PRINTPKT_SUPPORT +/* + * ipcp_printpkt - print the contents of an IPCP packet. + */ +static const char* const ipcp_codenames[] = { + "ConfReq", "ConfAck", "ConfNak", "ConfRej", + "TermReq", "TermAck", "CodeRej" +}; + +static int ipcp_printpkt(const u_char *p, int plen, + void (*printer) (void *, const char *, ...), void *arg) { + int code, id, len, olen; + const u_char *pstart, *optend; +#if VJ_SUPPORT + u_short cishort; +#endif /* VJ_SUPPORT */ + u32_t cilong; + + if (plen < HEADERLEN) + return 0; + pstart = p; + GETCHAR(code, p); + GETCHAR(id, p); + GETSHORT(len, p); + if (len < HEADERLEN || len > plen) + return 0; + + if (code >= 1 && code <= (int)sizeof(ipcp_codenames) / (int)sizeof(char *)) + printer(arg, " %s", ipcp_codenames[code-1]); + else + printer(arg, " code=0x%x", code); + printer(arg, " id=0x%x", id); + len -= HEADERLEN; + switch (code) { + case CONFREQ: + case CONFACK: + case CONFNAK: + case CONFREJ: + /* print option list */ + while (len >= 2) { + GETCHAR(code, p); + GETCHAR(olen, p); + p -= 2; + if (olen < 2 || olen > len) { + break; + } + printer(arg, " <"); + len -= olen; + optend = p + olen; + switch (code) { + case CI_ADDRS: + if (olen == CILEN_ADDRS) { + p += 2; + GETLONG(cilong, p); + printer(arg, "addrs %I", htonl(cilong)); + GETLONG(cilong, p); + printer(arg, " %I", htonl(cilong)); + } + break; +#if VJ_SUPPORT + case CI_COMPRESSTYPE: + if (olen >= CILEN_COMPRESS) { + p += 2; + GETSHORT(cishort, p); + printer(arg, "compress "); + switch (cishort) { + case IPCP_VJ_COMP: + printer(arg, "VJ"); + break; + case IPCP_VJ_COMP_OLD: + printer(arg, "old-VJ"); + break; + default: + printer(arg, "0x%x", cishort); + } + } + break; +#endif /* VJ_SUPPORT */ + case CI_ADDR: + if (olen == CILEN_ADDR) { + p += 2; + GETLONG(cilong, p); + printer(arg, "addr %I", htonl(cilong)); + } + break; +#if LWIP_DNS + case CI_MS_DNS1: + case CI_MS_DNS2: + p += 2; + GETLONG(cilong, p); + printer(arg, "ms-dns%d %I", (code == CI_MS_DNS1? 1: 2), + htonl(cilong)); + break; +#endif /* LWIP_DNS */ +#if 0 /* UNUSED - WINS */ + case CI_MS_WINS1: + case CI_MS_WINS2: + p += 2; + GETLONG(cilong, p); + printer(arg, "ms-wins %I", htonl(cilong)); + break; +#endif /* UNUSED - WINS */ + default: + break; + } + while (p < optend) { + GETCHAR(code, p); + printer(arg, " %.2x", code); + } + printer(arg, ">"); + } + break; + + case TERMACK: + case TERMREQ: + if (len > 0 && *p >= ' ' && *p < 0x7f) { + printer(arg, " "); + ppp_print_string(p, len, printer, arg); + p += len; + len = 0; + } + break; + default: + break; + } + + /* print the rest of the bytes in the packet */ + for (; len > 0; --len) { + GETCHAR(code, p); + printer(arg, " %.2x", code); + } + + return p - pstart; +} +#endif /* PRINTPKT_SUPPORT */ + +#if DEMAND_SUPPORT +/* + * ip_active_pkt - see if this IP packet is worth bringing the link up for. + * We don't bring the link up for IP fragments or for TCP FIN packets + * with no data. + */ +#define IP_HDRLEN 20 /* bytes */ +#define IP_OFFMASK 0x1fff +#ifndef IPPROTO_TCP +#define IPPROTO_TCP 6 +#endif +#define TCP_HDRLEN 20 +#define TH_FIN 0x01 + +/* + * We use these macros because the IP header may be at an odd address, + * and some compilers might use word loads to get th_off or ip_hl. + */ + +#define net_short(x) (((x)[0] << 8) + (x)[1]) +#define get_iphl(x) (((unsigned char *)(x))[0] & 0xF) +#define get_ipoff(x) net_short((unsigned char *)(x) + 6) +#define get_ipproto(x) (((unsigned char *)(x))[9]) +#define get_tcpoff(x) (((unsigned char *)(x))[12] >> 4) +#define get_tcpflags(x) (((unsigned char *)(x))[13]) + +static int +ip_active_pkt(pkt, len) + u_char *pkt; + int len; +{ + u_char *tcp; + int hlen; + + len -= PPP_HDRLEN; + pkt += PPP_HDRLEN; + if (len < IP_HDRLEN) + return 0; + if ((get_ipoff(pkt) & IP_OFFMASK) != 0) + return 0; + if (get_ipproto(pkt) != IPPROTO_TCP) + return 1; + hlen = get_iphl(pkt) * 4; + if (len < hlen + TCP_HDRLEN) + return 0; + tcp = pkt + hlen; + if ((get_tcpflags(tcp) & TH_FIN) != 0 && len == hlen + get_tcpoff(tcp) * 4) + return 0; + return 1; +} +#endif /* DEMAND_SUPPORT */ + +#endif /* PPP_SUPPORT && PPP_IPV4_SUPPORT */ diff --git a/components/lwip/netif/ppp/ipv6cp.c b/components/lwip/netif/ppp/ipv6cp.c new file mode 100755 index 0000000000..71ac9d7d3b --- /dev/null +++ b/components/lwip/netif/ppp/ipv6cp.c @@ -0,0 +1,1533 @@ +/* + * ipv6cp.c - PPP IPV6 Control Protocol. + * + * Copyright (c) 1999 Tommi Komulainen. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. The name(s) of the authors of this software must not be used to + * endorse or promote products derived from this software without + * prior written permission. + * + * 4. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by Tommi Komulainen + * ". + * + * THE AUTHORS OF THIS SOFTWARE DISCLAIM ALL WARRANTIES WITH REGARD TO + * THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS, IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY + * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN + * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING + * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + */ + +/* Original version, based on RFC2023 : + + Copyright (c) 1995, 1996, 1997 Francis.Dupont@inria.fr, INRIA Rocquencourt, + Alain.Durand@imag.fr, IMAG, + Jean-Luc.Richier@imag.fr, IMAG-LSR. + + Copyright (c) 1998, 1999 Francis.Dupont@inria.fr, GIE DYADE, + Alain.Durand@imag.fr, IMAG, + Jean-Luc.Richier@imag.fr, IMAG-LSR. + + Ce travail a été fait au sein du GIE DYADE (Groupement d'Intérêt + Économique ayant pour membres BULL S.A. et l'INRIA). + + Ce logiciel informatique est disponible aux conditions + usuelles dans la recherche, c'est-à-dire qu'il peut + être utilisé, copié, modifié, distribué à l'unique + condition que ce texte soit conservé afin que + l'origine de ce logiciel soit reconnue. + + Le nom de l'Institut National de Recherche en Informatique + et en Automatique (INRIA), de l'IMAG, ou d'une personne morale + ou physique ayant participé à l'élaboration de ce logiciel ne peut + être utilisé sans son accord préalable explicite. + + Ce logiciel est fourni tel quel sans aucune garantie, + support ou responsabilité d'aucune sorte. + Ce logiciel est dérivé de sources d'origine + "University of California at Berkeley" et + "Digital Equipment Corporation" couvertes par des copyrights. + + L'Institut d'Informatique et de Mathématiques Appliquées de Grenoble (IMAG) + est une fédération d'unités mixtes de recherche du CNRS, de l'Institut National + Polytechnique de Grenoble et de l'Université Joseph Fourier regroupant + sept laboratoires dont le laboratoire Logiciels, Systèmes, Réseaux (LSR). + + This work has been done in the context of GIE DYADE (joint R & D venture + between BULL S.A. and INRIA). + + This software is available with usual "research" terms + with the aim of retain credits of the software. + Permission to use, copy, modify and distribute this software for any + purpose and without fee is hereby granted, provided that the above + copyright notice and this permission notice appear in all copies, + and the name of INRIA, IMAG, or any contributor not be used in advertising + or publicity pertaining to this material without the prior explicit + permission. The software is provided "as is" without any + warranties, support or liabilities of any kind. + This software is derived from source code from + "University of California at Berkeley" and + "Digital Equipment Corporation" protected by copyrights. + + Grenoble's Institute of Computer Science and Applied Mathematics (IMAG) + is a federation of seven research units funded by the CNRS, National + Polytechnic Institute of Grenoble and University Joseph Fourier. + The research unit in Software, Systems, Networks (LSR) is member of IMAG. +*/ + +/* + * Derived from : + * + * + * ipcp.c - PPP IP Control Protocol. + * + * Copyright (c) 1984-2000 Carnegie Mellon University. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. The name "Carnegie Mellon University" must not be used to + * endorse or promote products derived from this software without + * prior written permission. For permission or any legal + * details, please contact + * Office of Technology Transfer + * Carnegie Mellon University + * 5000 Forbes Avenue + * Pittsburgh, PA 15213-3890 + * (412) 268-4387, fax: (412) 268-7395 + * tech-transfer@andrew.cmu.edu + * + * 4. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by Computing Services + * at Carnegie Mellon University (http://www.cmu.edu/computing/)." + * + * CARNEGIE MELLON UNIVERSITY DISCLAIMS ALL WARRANTIES WITH REGARD TO + * THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS, IN NO EVENT SHALL CARNEGIE MELLON UNIVERSITY BE LIABLE + * FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN + * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING + * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * $Id: ipv6cp.c,v 1.21 2005/08/25 23:59:34 paulus Exp $ + */ + +/* + * TODO: + * + * Proxy Neighbour Discovery. + * + * Better defines for selecting the ordering of + * interface up / set address. + */ + +#include "lwip/opt.h" +#if PPP_SUPPORT && PPP_IPV6_SUPPORT /* don't build if not configured for use in lwipopts.h */ + +#if 0 /* UNUSED */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#endif /* UNUSED */ + +#include "netif/ppp/ppp_impl.h" +#include "netif/ppp/fsm.h" +#include "netif/ppp/ipcp.h" +#include "netif/ppp/ipv6cp.h" +#include "netif/ppp/magic.h" + +/* global vars */ +#if 0 /* UNUSED */ +int no_ifaceid_neg = 0; +#endif /* UNUSED */ + +/* + * Callbacks for fsm code. (CI = Configuration Information) + */ +static void ipv6cp_resetci(fsm *f); /* Reset our CI */ +static int ipv6cp_cilen(fsm *f); /* Return length of our CI */ +static void ipv6cp_addci(fsm *f, u_char *ucp, int *lenp); /* Add our CI */ +static int ipv6cp_ackci(fsm *f, u_char *p, int len); /* Peer ack'd our CI */ +static int ipv6cp_nakci(fsm *f, u_char *p, int len, int treat_as_reject); /* Peer nak'd our CI */ +static int ipv6cp_rejci(fsm *f, u_char *p, int len); /* Peer rej'd our CI */ +static int ipv6cp_reqci(fsm *f, u_char *inp, int *len, int reject_if_disagree); /* Rcv CI */ +static void ipv6cp_up(fsm *f); /* We're UP */ +static void ipv6cp_down(fsm *f); /* We're DOWN */ +static void ipv6cp_finished(fsm *f); /* Don't need lower layer */ + +static const fsm_callbacks ipv6cp_callbacks = { /* IPV6CP callback routines */ + ipv6cp_resetci, /* Reset our Configuration Information */ + ipv6cp_cilen, /* Length of our Configuration Information */ + ipv6cp_addci, /* Add our Configuration Information */ + ipv6cp_ackci, /* ACK our Configuration Information */ + ipv6cp_nakci, /* NAK our Configuration Information */ + ipv6cp_rejci, /* Reject our Configuration Information */ + ipv6cp_reqci, /* Request peer's Configuration Information */ + ipv6cp_up, /* Called when fsm reaches OPENED state */ + ipv6cp_down, /* Called when fsm leaves OPENED state */ + NULL, /* Called when we want the lower layer up */ + ipv6cp_finished, /* Called when we want the lower layer down */ + NULL, /* Called when Protocol-Reject received */ + NULL, /* Retransmission is necessary */ + NULL, /* Called to handle protocol-specific codes */ + "IPV6CP" /* String name of protocol */ +}; + +#if PPP_OPTIONS +/* + * Command-line options. + */ +static int setifaceid(char **arg)); +static void printifaceid(option_t *, + void (*)(void *, char *, ...), void *)); + +static option_t ipv6cp_option_list[] = { + { "ipv6", o_special, (void *)setifaceid, + "Set interface identifiers for IPV6", + OPT_A2PRINTER, (void *)printifaceid }, + + { "+ipv6", o_bool, &ipv6cp_protent.enabled_flag, + "Enable IPv6 and IPv6CP", OPT_PRIO | 1 }, + { "noipv6", o_bool, &ipv6cp_protent.enabled_flag, + "Disable IPv6 and IPv6CP", OPT_PRIOSUB }, + { "-ipv6", o_bool, &ipv6cp_protent.enabled_flag, + "Disable IPv6 and IPv6CP", OPT_PRIOSUB | OPT_ALIAS }, + + { "ipv6cp-accept-local", o_bool, &ipv6cp_allowoptions[0].accept_local, + "Accept peer's interface identifier for us", 1 }, + + { "ipv6cp-use-ipaddr", o_bool, &ipv6cp_allowoptions[0].use_ip, + "Use (default) IPv4 address as interface identifier", 1 }, + + { "ipv6cp-use-persistent", o_bool, &ipv6cp_wantoptions[0].use_persistent, + "Use uniquely-available persistent value for link local address", 1 }, + + { "ipv6cp-restart", o_int, &ipv6cp_fsm[0].timeouttime, + "Set timeout for IPv6CP", OPT_PRIO }, + { "ipv6cp-max-terminate", o_int, &ipv6cp_fsm[0].maxtermtransmits, + "Set max #xmits for term-reqs", OPT_PRIO }, + { "ipv6cp-max-configure", o_int, &ipv6cp_fsm[0].maxconfreqtransmits, + "Set max #xmits for conf-reqs", OPT_PRIO }, + { "ipv6cp-max-failure", o_int, &ipv6cp_fsm[0].maxnakloops, + "Set max #conf-naks for IPv6CP", OPT_PRIO }, + + { NULL } +}; +#endif /* PPP_OPTIONS */ + +/* + * Protocol entry points from main code. + */ +static void ipv6cp_init(ppp_pcb *pcb); +static void ipv6cp_open(ppp_pcb *pcb); +static void ipv6cp_close(ppp_pcb *pcb, const char *reason); +static void ipv6cp_lowerup(ppp_pcb *pcb); +static void ipv6cp_lowerdown(ppp_pcb *pcb); +static void ipv6cp_input(ppp_pcb *pcb, u_char *p, int len); +static void ipv6cp_protrej(ppp_pcb *pcb); +#if PPP_OPTIONS +static void ipv6_check_options(void); +#endif /* PPP_OPTIONS */ +#if DEMAND_SUPPORT +static int ipv6_demand_conf(int u); +#endif /* DEMAND_SUPPORT */ +#if PRINTPKT_SUPPORT +static int ipv6cp_printpkt(const u_char *p, int plen, + void (*printer)(void *, const char *, ...), void *arg); +#endif /* PRINTPKT_SUPPORT */ +#if DEMAND_SUPPORT +static int ipv6_active_pkt(u_char *pkt, int len); +#endif /* DEMAND_SUPPORT */ + +const struct protent ipv6cp_protent = { + PPP_IPV6CP, + ipv6cp_init, + ipv6cp_input, + ipv6cp_protrej, + ipv6cp_lowerup, + ipv6cp_lowerdown, + ipv6cp_open, + ipv6cp_close, +#if PRINTPKT_SUPPORT + ipv6cp_printpkt, +#endif /* PRINTPKT_SUPPORT */ +#if PPP_DATAINPUT + NULL, +#endif /* PPP_DATAINPUT */ +#if PRINTPKT_SUPPORT + "IPV6CP", + "IPV6", +#endif /* PRINTPKT_SUPPORT */ +#if PPP_OPTIONS + ipv6cp_option_list, + ipv6_check_options, +#endif /* PPP_OPTIONS */ +#if DEMAND_SUPPORT + ipv6_demand_conf, + ipv6_active_pkt +#endif /* DEMAND_SUPPORT */ +}; + +static void ipv6cp_clear_addrs(ppp_pcb *pcb, eui64_t ourid, eui64_t hisid); +#if 0 /* UNUSED */ +static void ipv6cp_script(char *)); +static void ipv6cp_script_done(void *)); +#endif /* UNUSED */ + +/* + * Lengths of configuration options. + */ +#define CILEN_VOID 2 +#define CILEN_COMPRESS 4 /* length for RFC2023 compress opt. */ +#define CILEN_IFACEID 10 /* RFC2472, interface identifier */ + +#define CODENAME(x) ((x) == CONFACK ? "ACK" : \ + (x) == CONFNAK ? "NAK" : "REJ") + +#if 0 /* UNUSED */ +/* + * This state variable is used to ensure that we don't + * run an ipcp-up/down script while one is already running. + */ +static enum script_state { + s_down, + s_up, +} ipv6cp_script_state; +static pid_t ipv6cp_script_pid; +#endif /* UNUSED */ + +static char *llv6_ntoa(eui64_t ifaceid); + +#if PPP_OPTIONS +/* + * setifaceid - set the interface identifiers manually + */ +static int +setifaceid(argv) + char **argv; +{ + char *comma, *arg, c; + ipv6cp_options *wo = &ipv6cp_wantoptions[0]; + struct in6_addr addr; + static int prio_local, prio_remote; + +#define VALIDID(a) ( (((a).s6_addr32[0] == 0) && ((a).s6_addr32[1] == 0)) && \ + (((a).s6_addr32[2] != 0) || ((a).s6_addr32[3] != 0)) ) + + arg = *argv; + if ((comma = strchr(arg, ',')) == NULL) + comma = arg + strlen(arg); + + /* + * If comma first character, then no local identifier + */ + if (comma != arg) { + c = *comma; + *comma = '\0'; + + if (inet_pton(AF_INET6, arg, &addr) == 0 || !VALIDID(addr)) { + option_error("Illegal interface identifier (local): %s", arg); + return 0; + } + + if (option_priority >= prio_local) { + eui64_copy(addr.s6_addr32[2], wo->ourid); + wo->opt_local = 1; + prio_local = option_priority; + } + *comma = c; + } + + /* + * If comma last character, the no remote identifier + */ + if (*comma != 0 && *++comma != '\0') { + if (inet_pton(AF_INET6, comma, &addr) == 0 || !VALIDID(addr)) { + option_error("Illegal interface identifier (remote): %s", comma); + return 0; + } + if (option_priority >= prio_remote) { + eui64_copy(addr.s6_addr32[2], wo->hisid); + wo->opt_remote = 1; + prio_remote = option_priority; + } + } + + if (override_value("+ipv6", option_priority, option_source)) + ipv6cp_protent.enabled_flag = 1; + return 1; +} + +static void +printifaceid(opt, printer, arg) + option_t *opt; + void (*printer)(void *, char *, ...)); + void *arg; +{ + ipv6cp_options *wo = &ipv6cp_wantoptions[0]; + + if (wo->opt_local) + printer(arg, "%s", llv6_ntoa(wo->ourid)); + printer(arg, ","); + if (wo->opt_remote) + printer(arg, "%s", llv6_ntoa(wo->hisid)); +} +#endif /* PPP_OPTIONS */ + +/* + * Make a string representation of a network address. + */ +static char * +llv6_ntoa(eui64_t ifaceid) +{ + static char b[26]; + + sprintf(b, "fe80::%02x%02x:%02x%02x:%02x%02x:%02x%02x", + ifaceid.e8[0], ifaceid.e8[1], ifaceid.e8[2], ifaceid.e8[3], + ifaceid.e8[4], ifaceid.e8[5], ifaceid.e8[6], ifaceid.e8[7]); + + return b; +} + + +/* + * ipv6cp_init - Initialize IPV6CP. + */ +static void ipv6cp_init(ppp_pcb *pcb) { + fsm *f = &pcb->ipv6cp_fsm; + ipv6cp_options *wo = &pcb->ipv6cp_wantoptions; + ipv6cp_options *ao = &pcb->ipv6cp_allowoptions; + + f->pcb = pcb; + f->protocol = PPP_IPV6CP; + f->callbacks = &ipv6cp_callbacks; + fsm_init(f); + +#if 0 /* Not necessary, everything is cleared in ppp_clear() */ + memset(wo, 0, sizeof(*wo)); + memset(ao, 0, sizeof(*ao)); +#endif /* 0 */ + + wo->accept_local = 1; + wo->neg_ifaceid = 1; + ao->neg_ifaceid = 1; + +#ifdef IPV6CP_COMP + wo->neg_vj = 1; + ao->neg_vj = 1; + wo->vj_protocol = IPV6CP_COMP; +#endif + +} + + +/* + * ipv6cp_open - IPV6CP is allowed to come up. + */ +static void ipv6cp_open(ppp_pcb *pcb) { + fsm_open(&pcb->ipv6cp_fsm); +} + + +/* + * ipv6cp_close - Take IPV6CP down. + */ +static void ipv6cp_close(ppp_pcb *pcb, const char *reason) { + fsm_close(&pcb->ipv6cp_fsm, reason); +} + + +/* + * ipv6cp_lowerup - The lower layer is up. + */ +static void ipv6cp_lowerup(ppp_pcb *pcb) { + fsm_lowerup(&pcb->ipv6cp_fsm); +} + + +/* + * ipv6cp_lowerdown - The lower layer is down. + */ +static void ipv6cp_lowerdown(ppp_pcb *pcb) { + fsm_lowerdown(&pcb->ipv6cp_fsm); +} + + +/* + * ipv6cp_input - Input IPV6CP packet. + */ +static void ipv6cp_input(ppp_pcb *pcb, u_char *p, int len) { + fsm_input(&pcb->ipv6cp_fsm, p, len); +} + + +/* + * ipv6cp_protrej - A Protocol-Reject was received for IPV6CP. + * + * Pretend the lower layer went down, so we shut up. + */ +static void ipv6cp_protrej(ppp_pcb *pcb) { + fsm_lowerdown(&pcb->ipv6cp_fsm); +} + + +/* + * ipv6cp_resetci - Reset our CI. + */ +static void ipv6cp_resetci(fsm *f) { + ppp_pcb *pcb = f->pcb; + ipv6cp_options *wo = &pcb->ipv6cp_wantoptions; + ipv6cp_options *go = &pcb->ipv6cp_gotoptions; + ipv6cp_options *ao = &pcb->ipv6cp_allowoptions; + + wo->req_ifaceid = wo->neg_ifaceid && ao->neg_ifaceid; + + if (!wo->opt_local) { + eui64_magic_nz(wo->ourid); + } + + *go = *wo; + eui64_zero(go->hisid); /* last proposed interface identifier */ +} + + +/* + * ipv6cp_cilen - Return length of our CI. + */ +static int ipv6cp_cilen(fsm *f) { + ppp_pcb *pcb = f->pcb; + ipv6cp_options *go = &pcb->ipv6cp_gotoptions; + +#ifdef IPV6CP_COMP +#define LENCIVJ(neg) (neg ? CILEN_COMPRESS : 0) +#endif /* IPV6CP_COMP */ +#define LENCIIFACEID(neg) (neg ? CILEN_IFACEID : 0) + + return (LENCIIFACEID(go->neg_ifaceid) + +#ifdef IPV6CP_COMP + LENCIVJ(go->neg_vj) + +#endif /* IPV6CP_COMP */ + 0); +} + + +/* + * ipv6cp_addci - Add our desired CIs to a packet. + */ +static void ipv6cp_addci(fsm *f, u_char *ucp, int *lenp) { + ppp_pcb *pcb = f->pcb; + ipv6cp_options *go = &pcb->ipv6cp_gotoptions; + int len = *lenp; + +#ifdef IPV6CP_COMP +#define ADDCIVJ(opt, neg, val) \ + if (neg) { \ + int vjlen = CILEN_COMPRESS; \ + if (len >= vjlen) { \ + PUTCHAR(opt, ucp); \ + PUTCHAR(vjlen, ucp); \ + PUTSHORT(val, ucp); \ + len -= vjlen; \ + } else \ + neg = 0; \ + } +#endif /* IPV6CP_COMP */ + +#define ADDCIIFACEID(opt, neg, val1) \ + if (neg) { \ + int idlen = CILEN_IFACEID; \ + if (len >= idlen) { \ + PUTCHAR(opt, ucp); \ + PUTCHAR(idlen, ucp); \ + eui64_put(val1, ucp); \ + len -= idlen; \ + } else \ + neg = 0; \ + } + + ADDCIIFACEID(CI_IFACEID, go->neg_ifaceid, go->ourid); + +#ifdef IPV6CP_COMP + ADDCIVJ(CI_COMPRESSTYPE, go->neg_vj, go->vj_protocol); +#endif /* IPV6CP_COMP */ + + *lenp -= len; +} + + +/* + * ipv6cp_ackci - Ack our CIs. + * + * Returns: + * 0 - Ack was bad. + * 1 - Ack was good. + */ +static int ipv6cp_ackci(fsm *f, u_char *p, int len) { + ppp_pcb *pcb = f->pcb; + ipv6cp_options *go = &pcb->ipv6cp_gotoptions; + u_short cilen, citype; +#ifdef IPV6CP_COMP + u_short cishort; +#endif /* IPV6CP_COMP */ + eui64_t ifaceid; + + /* + * CIs must be in exactly the same order that we sent... + * Check packet length and CI length at each step. + * If we find any deviations, then this packet is bad. + */ + +#ifdef IPV6CP_COMP +#define ACKCIVJ(opt, neg, val) \ + if (neg) { \ + int vjlen = CILEN_COMPRESS; \ + if ((len -= vjlen) < 0) \ + goto bad; \ + GETCHAR(citype, p); \ + GETCHAR(cilen, p); \ + if (cilen != vjlen || \ + citype != opt) \ + goto bad; \ + GETSHORT(cishort, p); \ + if (cishort != val) \ + goto bad; \ + } +#endif /* IPV6CP_COMP */ + +#define ACKCIIFACEID(opt, neg, val1) \ + if (neg) { \ + int idlen = CILEN_IFACEID; \ + if ((len -= idlen) < 0) \ + goto bad; \ + GETCHAR(citype, p); \ + GETCHAR(cilen, p); \ + if (cilen != idlen || \ + citype != opt) \ + goto bad; \ + eui64_get(ifaceid, p); \ + if (! eui64_equals(val1, ifaceid)) \ + goto bad; \ + } + + ACKCIIFACEID(CI_IFACEID, go->neg_ifaceid, go->ourid); + +#ifdef IPV6CP_COMP + ACKCIVJ(CI_COMPRESSTYPE, go->neg_vj, go->vj_protocol); +#endif /* IPV6CP_COMP */ + + /* + * If there are any remaining CIs, then this packet is bad. + */ + if (len != 0) + goto bad; + return (1); + +bad: + IPV6CPDEBUG(("ipv6cp_ackci: received bad Ack!")); + return (0); +} + +/* + * ipv6cp_nakci - Peer has sent a NAK for some of our CIs. + * This should not modify any state if the Nak is bad + * or if IPV6CP is in the OPENED state. + * + * Returns: + * 0 - Nak was bad. + * 1 - Nak was good. + */ +static int ipv6cp_nakci(fsm *f, u_char *p, int len, int treat_as_reject) { + ppp_pcb *pcb = f->pcb; + ipv6cp_options *go = &pcb->ipv6cp_gotoptions; + u_char citype, cilen, *next; +#ifdef IPV6CP_COMP + u_short cishort; +#endif /* IPV6CP_COMP */ + eui64_t ifaceid; + ipv6cp_options no; /* options we've seen Naks for */ + ipv6cp_options try_; /* options to request next time */ + + BZERO(&no, sizeof(no)); + try_ = *go; + + /* + * Any Nak'd CIs must be in exactly the same order that we sent. + * Check packet length and CI length at each step. + * If we find any deviations, then this packet is bad. + */ +#define NAKCIIFACEID(opt, neg, code) \ + if (go->neg && \ + len >= (cilen = CILEN_IFACEID) && \ + p[1] == cilen && \ + p[0] == opt) { \ + len -= cilen; \ + INCPTR(2, p); \ + eui64_get(ifaceid, p); \ + no.neg = 1; \ + code \ + } + +#ifdef IPV6CP_COMP +#define NAKCIVJ(opt, neg, code) \ + if (go->neg && \ + ((cilen = p[1]) == CILEN_COMPRESS) && \ + len >= cilen && \ + p[0] == opt) { \ + len -= cilen; \ + INCPTR(2, p); \ + GETSHORT(cishort, p); \ + no.neg = 1; \ + code \ + } +#endif /* IPV6CP_COMP */ + + /* + * Accept the peer's idea of {our,his} interface identifier, if different + * from our idea, only if the accept_{local,remote} flag is set. + */ + NAKCIIFACEID(CI_IFACEID, neg_ifaceid, + if (treat_as_reject) { + try_.neg_ifaceid = 0; + } else if (go->accept_local) { + while (eui64_iszero(ifaceid) || + eui64_equals(ifaceid, go->hisid)) /* bad luck */ + eui64_magic(ifaceid); + try_.ourid = ifaceid; + IPV6CPDEBUG(("local LL address %s", llv6_ntoa(ifaceid))); + } + ); + +#ifdef IPV6CP_COMP + NAKCIVJ(CI_COMPRESSTYPE, neg_vj, + { + if (cishort == IPV6CP_COMP && !treat_as_reject) { + try_.vj_protocol = cishort; + } else { + try_.neg_vj = 0; + } + } + ); +#endif /* IPV6CP_COMP */ + + /* + * There may be remaining CIs, if the peer is requesting negotiation + * on an option that we didn't include in our request packet. + * If they want to negotiate about interface identifier, we comply. + * If they want us to ask for compression, we refuse. + */ + while (len >= CILEN_VOID) { + GETCHAR(citype, p); + GETCHAR(cilen, p); + if ( cilen < CILEN_VOID || (len -= cilen) < 0 ) + goto bad; + next = p + cilen - 2; + + switch (citype) { +#ifdef IPV6CP_COMP + case CI_COMPRESSTYPE: + if (go->neg_vj || no.neg_vj || + (cilen != CILEN_COMPRESS)) + goto bad; + no.neg_vj = 1; + break; +#endif /* IPV6CP_COMP */ + case CI_IFACEID: + if (go->neg_ifaceid || no.neg_ifaceid || cilen != CILEN_IFACEID) + goto bad; + try_.neg_ifaceid = 1; + eui64_get(ifaceid, p); + if (go->accept_local) { + while (eui64_iszero(ifaceid) || + eui64_equals(ifaceid, go->hisid)) /* bad luck */ + eui64_magic(ifaceid); + try_.ourid = ifaceid; + } + no.neg_ifaceid = 1; + break; + default: + break; + } + p = next; + } + + /* If there is still anything left, this packet is bad. */ + if (len != 0) + goto bad; + + /* + * OK, the Nak is good. Now we can update state. + */ + if (f->state != PPP_FSM_OPENED) + *go = try_; + + return 1; + +bad: + IPV6CPDEBUG(("ipv6cp_nakci: received bad Nak!")); + return 0; +} + + +/* + * ipv6cp_rejci - Reject some of our CIs. + */ +static int ipv6cp_rejci(fsm *f, u_char *p, int len) { + ppp_pcb *pcb = f->pcb; + ipv6cp_options *go = &pcb->ipv6cp_gotoptions; + u_char cilen; +#ifdef IPV6CP_COMP + u_short cishort; +#endif /* IPV6CP_COMP */ + eui64_t ifaceid; + ipv6cp_options try_; /* options to request next time */ + + try_ = *go; + /* + * Any Rejected CIs must be in exactly the same order that we sent. + * Check packet length and CI length at each step. + * If we find any deviations, then this packet is bad. + */ +#define REJCIIFACEID(opt, neg, val1) \ + if (go->neg && \ + len >= (cilen = CILEN_IFACEID) && \ + p[1] == cilen && \ + p[0] == opt) { \ + len -= cilen; \ + INCPTR(2, p); \ + eui64_get(ifaceid, p); \ + /* Check rejected value. */ \ + if (! eui64_equals(ifaceid, val1)) \ + goto bad; \ + try_.neg = 0; \ + } + +#ifdef IPV6CP_COMP +#define REJCIVJ(opt, neg, val) \ + if (go->neg && \ + p[1] == CILEN_COMPRESS && \ + len >= p[1] && \ + p[0] == opt) { \ + len -= p[1]; \ + INCPTR(2, p); \ + GETSHORT(cishort, p); \ + /* Check rejected value. */ \ + if (cishort != val) \ + goto bad; \ + try_.neg = 0; \ + } +#endif /* IPV6CP_COMP */ + + REJCIIFACEID(CI_IFACEID, neg_ifaceid, go->ourid); + +#ifdef IPV6CP_COMP + REJCIVJ(CI_COMPRESSTYPE, neg_vj, go->vj_protocol); +#endif /* IPV6CP_COMP */ + + /* + * If there are any remaining CIs, then this packet is bad. + */ + if (len != 0) + goto bad; + /* + * Now we can update state. + */ + if (f->state != PPP_FSM_OPENED) + *go = try_; + return 1; + +bad: + IPV6CPDEBUG(("ipv6cp_rejci: received bad Reject!")); + return 0; +} + + +/* + * ipv6cp_reqci - Check the peer's requested CIs and send appropriate response. + * + * Returns: CONFACK, CONFNAK or CONFREJ and input packet modified + * appropriately. If reject_if_disagree is non-zero, doesn't return + * CONFNAK; returns CONFREJ if it can't return CONFACK. + * + * inp = Requested CIs + * len = Length of requested CIs + * + */ +static int ipv6cp_reqci(fsm *f, u_char *inp, int *len, int reject_if_disagree) { + ppp_pcb *pcb = f->pcb; + ipv6cp_options *wo = &pcb->ipv6cp_wantoptions; + ipv6cp_options *ho = &pcb->ipv6cp_hisoptions; + ipv6cp_options *ao = &pcb->ipv6cp_allowoptions; + ipv6cp_options *go = &pcb->ipv6cp_gotoptions; + u_char *cip, *next; /* Pointer to current and next CIs */ + u_short cilen, citype; /* Parsed len, type */ +#ifdef IPV6CP_COMP + u_short cishort; /* Parsed short value */ +#endif /* IPV6CP_COMP */ + eui64_t ifaceid; /* Parsed interface identifier */ + int rc = CONFACK; /* Final packet return code */ + int orc; /* Individual option return code */ + u_char *p; /* Pointer to next char to parse */ + u_char *ucp = inp; /* Pointer to current output char */ + int l = *len; /* Length left */ + + /* + * Reset all his options. + */ + BZERO(ho, sizeof(*ho)); + + /* + * Process all his options. + */ + next = inp; + while (l) { + orc = CONFACK; /* Assume success */ + cip = p = next; /* Remember begining of CI */ + if (l < 2 || /* Not enough data for CI header or */ + p[1] < 2 || /* CI length too small or */ + p[1] > l) { /* CI length too big? */ + IPV6CPDEBUG(("ipv6cp_reqci: bad CI length!")); + orc = CONFREJ; /* Reject bad CI */ + cilen = l; /* Reject till end of packet */ + l = 0; /* Don't loop again */ + goto endswitch; + } + GETCHAR(citype, p); /* Parse CI type */ + GETCHAR(cilen, p); /* Parse CI length */ + l -= cilen; /* Adjust remaining length */ + next += cilen; /* Step to next CI */ + + switch (citype) { /* Check CI type */ + case CI_IFACEID: + IPV6CPDEBUG(("ipv6cp: received interface identifier ")); + + if (!ao->neg_ifaceid || + cilen != CILEN_IFACEID) { /* Check CI length */ + orc = CONFREJ; /* Reject CI */ + break; + } + + /* + * If he has no interface identifier, or if we both have same + * identifier then NAK it with new idea. + * In particular, if we don't know his identifier, but he does, + * then accept it. + */ + eui64_get(ifaceid, p); + IPV6CPDEBUG(("(%s)", llv6_ntoa(ifaceid))); + if (eui64_iszero(ifaceid) && eui64_iszero(go->ourid)) { + orc = CONFREJ; /* Reject CI */ + break; + } + if (!eui64_iszero(wo->hisid) && + !eui64_equals(ifaceid, wo->hisid) && + eui64_iszero(go->hisid)) { + + orc = CONFNAK; + ifaceid = wo->hisid; + go->hisid = ifaceid; + DECPTR(sizeof(ifaceid), p); + eui64_put(ifaceid, p); + } else + if (eui64_iszero(ifaceid) || eui64_equals(ifaceid, go->ourid)) { + orc = CONFNAK; + if (eui64_iszero(go->hisid)) /* first time, try option */ + ifaceid = wo->hisid; + while (eui64_iszero(ifaceid) || + eui64_equals(ifaceid, go->ourid)) /* bad luck */ + eui64_magic(ifaceid); + go->hisid = ifaceid; + DECPTR(sizeof(ifaceid), p); + eui64_put(ifaceid, p); + } + + ho->neg_ifaceid = 1; + ho->hisid = ifaceid; + break; + +#ifdef IPV6CP_COMP + case CI_COMPRESSTYPE: + IPV6CPDEBUG(("ipv6cp: received COMPRESSTYPE ")); + if (!ao->neg_vj || + (cilen != CILEN_COMPRESS)) { + orc = CONFREJ; + break; + } + GETSHORT(cishort, p); + IPV6CPDEBUG(("(%d)", cishort)); + + if (!(cishort == IPV6CP_COMP)) { + orc = CONFREJ; + break; + } + + ho->neg_vj = 1; + ho->vj_protocol = cishort; + break; +#endif /* IPV6CP_COMP */ + + default: + orc = CONFREJ; + break; + } + +endswitch: + IPV6CPDEBUG((" (%s)\n", CODENAME(orc))); + + if (orc == CONFACK && /* Good CI */ + rc != CONFACK) /* but prior CI wasnt? */ + continue; /* Don't send this one */ + + if (orc == CONFNAK) { /* Nak this CI? */ + if (reject_if_disagree) /* Getting fed up with sending NAKs? */ + orc = CONFREJ; /* Get tough if so */ + else { + if (rc == CONFREJ) /* Rejecting prior CI? */ + continue; /* Don't send this one */ + if (rc == CONFACK) { /* Ack'd all prior CIs? */ + rc = CONFNAK; /* Not anymore... */ + ucp = inp; /* Backup */ + } + } + } + + if (orc == CONFREJ && /* Reject this CI */ + rc != CONFREJ) { /* but no prior ones? */ + rc = CONFREJ; + ucp = inp; /* Backup */ + } + + /* Need to move CI? */ + if (ucp != cip) + MEMCPY(ucp, cip, cilen); /* Move it */ + + /* Update output pointer */ + INCPTR(cilen, ucp); + } + + /* + * If we aren't rejecting this packet, and we want to negotiate + * their identifier and they didn't send their identifier, then we + * send a NAK with a CI_IFACEID option appended. We assume the + * input buffer is long enough that we can append the extra + * option safely. + */ + if (rc != CONFREJ && !ho->neg_ifaceid && + wo->req_ifaceid && !reject_if_disagree) { + if (rc == CONFACK) { + rc = CONFNAK; + ucp = inp; /* reset pointer */ + wo->req_ifaceid = 0; /* don't ask again */ + } + PUTCHAR(CI_IFACEID, ucp); + PUTCHAR(CILEN_IFACEID, ucp); + eui64_put(wo->hisid, ucp); + } + + *len = ucp - inp; /* Compute output length */ + IPV6CPDEBUG(("ipv6cp: returning Configure-%s", CODENAME(rc))); + return (rc); /* Return final code */ +} + +#if PPP_OPTIONS +/* + * ipv6_check_options - check that any IP-related options are OK, + * and assign appropriate defaults. + */ +static void ipv6_check_options() { + ipv6cp_options *wo = &ipv6cp_wantoptions[0]; + + if (!ipv6cp_protent.enabled_flag) + return; + + /* + * Persistent link-local id is only used when user has not explicitly + * configure/hard-code the id + */ + if ((wo->use_persistent) && (!wo->opt_local) && (!wo->opt_remote)) { + + /* + * On systems where there are no Ethernet interfaces used, there + * may be other ways to obtain a persistent id. Right now, it + * will fall back to using magic [see eui64_magic] below when + * an EUI-48 from MAC address can't be obtained. Other possibilities + * include obtaining EEPROM serial numbers, or some other unique + * yet persistent number. On Sparc platforms, this is possible, + * but too bad there's no standards yet for x86 machines. + */ + if (ether_to_eui64(&wo->ourid)) { + wo->opt_local = 1; + } + } + + if (!wo->opt_local) { /* init interface identifier */ + if (wo->use_ip && eui64_iszero(wo->ourid)) { + eui64_setlo32(wo->ourid, ntohl(ipcp_wantoptions[0].ouraddr)); + if (!eui64_iszero(wo->ourid)) + wo->opt_local = 1; + } + + while (eui64_iszero(wo->ourid)) + eui64_magic(wo->ourid); + } + + if (!wo->opt_remote) { + if (wo->use_ip && eui64_iszero(wo->hisid)) { + eui64_setlo32(wo->hisid, ntohl(ipcp_wantoptions[0].hisaddr)); + if (!eui64_iszero(wo->hisid)) + wo->opt_remote = 1; + } + } + + if (demand && (eui64_iszero(wo->ourid) || eui64_iszero(wo->hisid))) { + option_error("local/remote LL address required for demand-dialling\n"); + exit(1); + } +} +#endif /* PPP_OPTIONS */ + +#if DEMAND_SUPPORT +/* + * ipv6_demand_conf - configure the interface as though + * IPV6CP were up, for use with dial-on-demand. + */ +static int ipv6_demand_conf(int u) { + ipv6cp_options *wo = &ipv6cp_wantoptions[u]; + + if (!sif6up(u)) + return 0; + + if (!sif6addr(u, wo->ourid, wo->hisid)) + return 0; + + if (!sifnpmode(u, PPP_IPV6, NPMODE_QUEUE)) + return 0; + + ppp_notice("ipv6_demand_conf"); + ppp_notice("local LL address %s", llv6_ntoa(wo->ourid)); + ppp_notice("remote LL address %s", llv6_ntoa(wo->hisid)); + + return 1; +} +#endif /* DEMAND_SUPPORT */ + + +/* + * ipv6cp_up - IPV6CP has come UP. + * + * Configure the IPv6 network interface appropriately and bring it up. + */ +static void ipv6cp_up(fsm *f) { + ppp_pcb *pcb = f->pcb; + ipv6cp_options *wo = &pcb->ipv6cp_wantoptions; + ipv6cp_options *ho = &pcb->ipv6cp_hisoptions; + ipv6cp_options *go = &pcb->ipv6cp_gotoptions; + + IPV6CPDEBUG(("ipv6cp: up")); + + /* + * We must have a non-zero LL address for both ends of the link. + */ + if (!ho->neg_ifaceid) + ho->hisid = wo->hisid; + +#if 0 /* UNUSED */ + if(!no_ifaceid_neg) { +#endif /* UNUSED */ + if (eui64_iszero(ho->hisid)) { + ppp_error("Could not determine remote LL address"); + ipv6cp_close(f->pcb, "Could not determine remote LL address"); + return; + } + if (eui64_iszero(go->ourid)) { + ppp_error("Could not determine local LL address"); + ipv6cp_close(f->pcb, "Could not determine local LL address"); + return; + } + if (eui64_equals(go->ourid, ho->hisid)) { + ppp_error("local and remote LL addresses are equal"); + ipv6cp_close(f->pcb, "local and remote LL addresses are equal"); + return; + } +#if 0 /* UNUSED */ + } +#endif /* UNUSED */ +#if 0 /* UNUSED */ + script_setenv("LLLOCAL", llv6_ntoa(go->ourid), 0); + script_setenv("LLREMOTE", llv6_ntoa(ho->hisid), 0); +#endif /* UNUSED */ + +#ifdef IPV6CP_COMP + /* set tcp compression */ + sif6comp(f->unit, ho->neg_vj); +#endif + +#if DEMAND_SUPPORT + /* + * If we are doing dial-on-demand, the interface is already + * configured, so we put out any saved-up packets, then set the + * interface to pass IPv6 packets. + */ + if (demand) { + if (! eui64_equals(go->ourid, wo->ourid) || + ! eui64_equals(ho->hisid, wo->hisid)) { + if (! eui64_equals(go->ourid, wo->ourid)) + warn("Local LL address changed to %s", + llv6_ntoa(go->ourid)); + if (! eui64_equals(ho->hisid, wo->hisid)) + warn("Remote LL address changed to %s", + llv6_ntoa(ho->hisid)); + ipv6cp_clear_addrs(f->pcb, go->ourid, ho->hisid); + + /* Set the interface to the new addresses */ + if (!sif6addr(f->pcb, go->ourid, ho->hisid)) { + if (debug) + warn("sif6addr failed"); + ipv6cp_close(f->unit, "Interface configuration failed"); + return; + } + + } + demand_rexmit(PPP_IPV6); + sifnpmode(f->unit, PPP_IPV6, NPMODE_PASS); + + } else +#endif /* DEMAND_SUPPORT */ + { + /* + * Set LL addresses + */ + if (!sif6addr(f->pcb, go->ourid, ho->hisid)) { + PPPDEBUG(LOG_DEBUG, ("sif6addr failed")); + ipv6cp_close(f->pcb, "Interface configuration failed"); + return; + } + + /* bring the interface up for IPv6 */ + if (!sif6up(f->pcb)) { + PPPDEBUG(LOG_DEBUG, ("sif6up failed (IPV6)")); + ipv6cp_close(f->pcb, "Interface configuration failed"); + return; + } +#if DEMAND_SUPPORT + sifnpmode(f->pcb, PPP_IPV6, NPMODE_PASS); +#endif /* DEMAND_SUPPORT */ + + ppp_notice("local LL address %s", llv6_ntoa(go->ourid)); + ppp_notice("remote LL address %s", llv6_ntoa(ho->hisid)); + } + + np_up(f->pcb, PPP_IPV6); + pcb->ipv6cp_is_up = 1; + +#if 0 /* UNUSED */ + /* + * Execute the ipv6-up script, like this: + * /etc/ppp/ipv6-up interface tty speed local-LL remote-LL + */ + if (ipv6cp_script_state == s_down && ipv6cp_script_pid == 0) { + ipv6cp_script_state = s_up; + ipv6cp_script(_PATH_IPV6UP); + } +#endif /* UNUSED */ +} + + +/* + * ipv6cp_down - IPV6CP has gone DOWN. + * + * Take the IPv6 network interface down, clear its addresses + * and delete routes through it. + */ +static void ipv6cp_down(fsm *f) { + ppp_pcb *pcb = f->pcb; + ipv6cp_options *go = &pcb->ipv6cp_gotoptions; + ipv6cp_options *ho = &pcb->ipv6cp_hisoptions; + + IPV6CPDEBUG(("ipv6cp: down")); +#if PPP_STATS_SUPPORT + update_link_stats(f->unit); +#endif /* PPP_STATS_SUPPORT */ + if (pcb->ipv6cp_is_up) { + pcb->ipv6cp_is_up = 0; + np_down(f->pcb, PPP_IPV6); + } +#ifdef IPV6CP_COMP + sif6comp(f->unit, 0); +#endif + +#if DEMAND_SUPPORT + /* + * If we are doing dial-on-demand, set the interface + * to queue up outgoing packets (for now). + */ + if (demand) { + sifnpmode(f->pcb, PPP_IPV6, NPMODE_QUEUE); + } else +#endif /* DEMAND_SUPPORT */ + { +#if DEMAND_SUPPORT + sifnpmode(f->pcb, PPP_IPV6, NPMODE_DROP); +#endif /* DEMAND_SUPPORT */ + ipv6cp_clear_addrs(f->pcb, + go->ourid, + ho->hisid); + sif6down(f->pcb); + } + +#if 0 /* UNUSED */ + /* Execute the ipv6-down script */ + if (ipv6cp_script_state == s_up && ipv6cp_script_pid == 0) { + ipv6cp_script_state = s_down; + ipv6cp_script(_PATH_IPV6DOWN); + } +#endif /* UNUSED */ +} + + +/* + * ipv6cp_clear_addrs() - clear the interface addresses, routes, + * proxy neighbour discovery entries, etc. + */ +static void ipv6cp_clear_addrs(ppp_pcb *pcb, eui64_t ourid, eui64_t hisid) { + cif6addr(pcb, ourid, hisid); +} + + +/* + * ipv6cp_finished - possibly shut down the lower layers. + */ +static void ipv6cp_finished(fsm *f) { + np_finished(f->pcb, PPP_IPV6); +} + + +#if 0 /* UNUSED */ +/* + * ipv6cp_script_done - called when the ipv6-up or ipv6-down script + * has finished. + */ +static void +ipv6cp_script_done(arg) + void *arg; +{ + ipv6cp_script_pid = 0; + switch (ipv6cp_script_state) { + case s_up: + if (ipv6cp_fsm[0].state != PPP_FSM_OPENED) { + ipv6cp_script_state = s_down; + ipv6cp_script(_PATH_IPV6DOWN); + } + break; + case s_down: + if (ipv6cp_fsm[0].state == PPP_FSM_OPENED) { + ipv6cp_script_state = s_up; + ipv6cp_script(_PATH_IPV6UP); + } + break; + } +} + + +/* + * ipv6cp_script - Execute a script with arguments + * interface-name tty-name speed local-LL remote-LL. + */ +static void +ipv6cp_script(script) + char *script; +{ + char strspeed[32], strlocal[32], strremote[32]; + char *argv[8]; + + sprintf(strspeed, "%d", baud_rate); + strcpy(strlocal, llv6_ntoa(ipv6cp_gotoptions[0].ourid)); + strcpy(strremote, llv6_ntoa(ipv6cp_hisoptions[0].hisid)); + + argv[0] = script; + argv[1] = ifname; + argv[2] = devnam; + argv[3] = strspeed; + argv[4] = strlocal; + argv[5] = strremote; + argv[6] = ipparam; + argv[7] = NULL; + + ipv6cp_script_pid = run_program(script, argv, 0, ipv6cp_script_done, + NULL, 0); +} +#endif /* UNUSED */ + +#if PRINTPKT_SUPPORT +/* + * ipv6cp_printpkt - print the contents of an IPV6CP packet. + */ +static const char* const ipv6cp_codenames[] = { + "ConfReq", "ConfAck", "ConfNak", "ConfRej", + "TermReq", "TermAck", "CodeRej" +}; + +static int ipv6cp_printpkt(const u_char *p, int plen, + void (*printer)(void *, const char *, ...), void *arg) { + int code, id, len, olen; + const u_char *pstart, *optend; +#ifdef IPV6CP_COMP + u_short cishort; +#endif /* IPV6CP_COMP */ + eui64_t ifaceid; + + if (plen < HEADERLEN) + return 0; + pstart = p; + GETCHAR(code, p); + GETCHAR(id, p); + GETSHORT(len, p); + if (len < HEADERLEN || len > plen) + return 0; + + if (code >= 1 && code <= (int)sizeof(ipv6cp_codenames) / (int)sizeof(char *)) + printer(arg, " %s", ipv6cp_codenames[code-1]); + else + printer(arg, " code=0x%x", code); + printer(arg, " id=0x%x", id); + len -= HEADERLEN; + switch (code) { + case CONFREQ: + case CONFACK: + case CONFNAK: + case CONFREJ: + /* print option list */ + while (len >= 2) { + GETCHAR(code, p); + GETCHAR(olen, p); + p -= 2; + if (olen < 2 || olen > len) { + break; + } + printer(arg, " <"); + len -= olen; + optend = p + olen; + switch (code) { +#ifdef IPV6CP_COMP + case CI_COMPRESSTYPE: + if (olen >= CILEN_COMPRESS) { + p += 2; + GETSHORT(cishort, p); + printer(arg, "compress "); + printer(arg, "0x%x", cishort); + } + break; +#endif /* IPV6CP_COMP */ + case CI_IFACEID: + if (olen == CILEN_IFACEID) { + p += 2; + eui64_get(ifaceid, p); + printer(arg, "addr %s", llv6_ntoa(ifaceid)); + } + break; + default: + break; + } + while (p < optend) { + GETCHAR(code, p); + printer(arg, " %.2x", code); + } + printer(arg, ">"); + } + break; + + case TERMACK: + case TERMREQ: + if (len > 0 && *p >= ' ' && *p < 0x7f) { + printer(arg, " "); + ppp_print_string(p, len, printer, arg); + p += len; + len = 0; + } + break; + default: + break; + } + + /* print the rest of the bytes in the packet */ + for (; len > 0; --len) { + GETCHAR(code, p); + printer(arg, " %.2x", code); + } + + return p - pstart; +} +#endif /* PRINTPKT_SUPPORT */ + +#if DEMAND_SUPPORT +/* + * ipv6_active_pkt - see if this IP packet is worth bringing the link up for. + * We don't bring the link up for IP fragments or for TCP FIN packets + * with no data. + */ +#define IP6_HDRLEN 40 /* bytes */ +#define IP6_NHDR_FRAG 44 /* fragment IPv6 header */ +#define TCP_HDRLEN 20 +#define TH_FIN 0x01 + +/* + * We use these macros because the IP header may be at an odd address, + * and some compilers might use word loads to get th_off or ip_hl. + */ + +#define get_ip6nh(x) (((unsigned char *)(x))[6]) +#define get_tcpoff(x) (((unsigned char *)(x))[12] >> 4) +#define get_tcpflags(x) (((unsigned char *)(x))[13]) + +static int ipv6_active_pkt(u_char *pkt, int len) { + u_char *tcp; + + len -= PPP_HDRLEN; + pkt += PPP_HDRLEN; + if (len < IP6_HDRLEN) + return 0; + if (get_ip6nh(pkt) == IP6_NHDR_FRAG) + return 0; + if (get_ip6nh(pkt) != IPPROTO_TCP) + return 1; + if (len < IP6_HDRLEN + TCP_HDRLEN) + return 0; + tcp = pkt + IP6_HDRLEN; + if ((get_tcpflags(tcp) & TH_FIN) != 0 && len == IP6_HDRLEN + get_tcpoff(tcp) * 4) + return 0; + return 1; +} +#endif /* DEMAND_SUPPORT */ + +#endif /* PPP_SUPPORT && PPP_IPV6_SUPPORT */ diff --git a/components/lwip/netif/ppp/lcp.c b/components/lwip/netif/ppp/lcp.c new file mode 100755 index 0000000000..1e4798064e --- /dev/null +++ b/components/lwip/netif/ppp/lcp.c @@ -0,0 +1,2786 @@ +/* + * lcp.c - PPP Link Control Protocol. + * + * Copyright (c) 1984-2000 Carnegie Mellon University. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. The name "Carnegie Mellon University" must not be used to + * endorse or promote products derived from this software without + * prior written permission. For permission or any legal + * details, please contact + * Office of Technology Transfer + * Carnegie Mellon University + * 5000 Forbes Avenue + * Pittsburgh, PA 15213-3890 + * (412) 268-4387, fax: (412) 268-7395 + * tech-transfer@andrew.cmu.edu + * + * 4. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by Computing Services + * at Carnegie Mellon University (http://www.cmu.edu/computing/)." + * + * CARNEGIE MELLON UNIVERSITY DISCLAIMS ALL WARRANTIES WITH REGARD TO + * THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS, IN NO EVENT SHALL CARNEGIE MELLON UNIVERSITY BE LIABLE + * FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN + * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING + * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include "lwip/opt.h" +#if PPP_SUPPORT /* don't build if not configured for use in lwipopts.h */ + +/* + * TODO: + */ + +#if 0 /* UNUSED */ +#include +#include +#include +#endif /* UNUSED */ + +#include "netif/ppp/ppp_impl.h" + +#include "netif/ppp/fsm.h" +#include "netif/ppp/lcp.h" +#if CHAP_SUPPORT +#include "netif/ppp/chap-new.h" +#endif /* CHAP_SUPPORT */ +#include "netif/ppp/magic.h" + +/* + * When the link comes up we want to be able to wait for a short while, + * or until seeing some input from the peer, before starting to send + * configure-requests. We do this by delaying the fsm_lowerup call. + */ +/* steal a bit in fsm flags word */ +#define DELAYED_UP 0x80 + +static void lcp_delayed_up(void *arg); + +/* + * LCP-related command-line options. + */ +#if 0 /* UNUSED */ +int lcp_echo_interval = 0; /* Interval between LCP echo-requests */ +int lcp_echo_fails = 0; /* Tolerance to unanswered echo-requests */ +#endif /* UNUSED */ + +#if 0 /* UNUSED */ +/* options */ +static u_int lcp_echo_interval = LCP_ECHOINTERVAL; /* Interval between LCP echo-requests */ +static u_int lcp_echo_fails = LCP_MAXECHOFAILS; /* Tolerance to unanswered echo-requests */ +#endif /* UNUSED */ + +#if 0 /* UNUSED */ +#if PPP_LCP_ADAPTIVE +bool lcp_echo_adaptive = 0; /* request echo only if the link was idle */ +#endif +bool lax_recv = 0; /* accept control chars in asyncmap */ +bool noendpoint = 0; /* don't send/accept endpoint discriminator */ +#endif /* UNUSED */ + +#if PPP_OPTIONS +static int noopt (char **); +#endif /* PPP_OPTIONS */ + +#ifdef HAVE_MULTILINK +static int setendpoint (char **); +static void printendpoint (option_t *, void (*)(void *, char *, ...), + void *); +#endif /* HAVE_MULTILINK */ + +#if PPP_OPTIONS +static option_t lcp_option_list[] = { + /* LCP options */ + { "-all", o_special_noarg, (void *)noopt, + "Don't request/allow any LCP options" }, + + { "noaccomp", o_bool, &lcp_wantoptions[0].neg_accompression, + "Disable address/control compression", + OPT_A2CLR, &lcp_allowoptions[0].neg_accompression }, + { "-ac", o_bool, &lcp_wantoptions[0].neg_accompression, + "Disable address/control compression", + OPT_ALIAS | OPT_A2CLR, &lcp_allowoptions[0].neg_accompression }, + + { "asyncmap", o_uint32, &lcp_wantoptions[0].asyncmap, + "Set asyncmap (for received packets)", + OPT_OR, &lcp_wantoptions[0].neg_asyncmap }, + { "-as", o_uint32, &lcp_wantoptions[0].asyncmap, + "Set asyncmap (for received packets)", + OPT_ALIAS | OPT_OR, &lcp_wantoptions[0].neg_asyncmap }, + { "default-asyncmap", o_uint32, &lcp_wantoptions[0].asyncmap, + "Disable asyncmap negotiation", + OPT_OR | OPT_NOARG | OPT_VAL(~0U) | OPT_A2CLR, + &lcp_allowoptions[0].neg_asyncmap }, + { "-am", o_uint32, &lcp_wantoptions[0].asyncmap, + "Disable asyncmap negotiation", + OPT_ALIAS | OPT_OR | OPT_NOARG | OPT_VAL(~0U) | OPT_A2CLR, + &lcp_allowoptions[0].neg_asyncmap }, + + { "nomagic", o_bool, &lcp_wantoptions[0].neg_magicnumber, + "Disable magic number negotiation (looped-back line detection)", + OPT_A2CLR, &lcp_allowoptions[0].neg_magicnumber }, + { "-mn", o_bool, &lcp_wantoptions[0].neg_magicnumber, + "Disable magic number negotiation (looped-back line detection)", + OPT_ALIAS | OPT_A2CLR, &lcp_allowoptions[0].neg_magicnumber }, + + { "mru", o_int, &lcp_wantoptions[0].mru, + "Set MRU (maximum received packet size) for negotiation", + OPT_PRIO, &lcp_wantoptions[0].neg_mru }, + { "default-mru", o_bool, &lcp_wantoptions[0].neg_mru, + "Disable MRU negotiation (use default 1500)", + OPT_PRIOSUB | OPT_A2CLR, &lcp_allowoptions[0].neg_mru }, + { "-mru", o_bool, &lcp_wantoptions[0].neg_mru, + "Disable MRU negotiation (use default 1500)", + OPT_ALIAS | OPT_PRIOSUB | OPT_A2CLR, &lcp_allowoptions[0].neg_mru }, + + { "mtu", o_int, &lcp_allowoptions[0].mru, + "Set our MTU", OPT_LIMITS, NULL, MAXMRU, MINMRU }, + + { "nopcomp", o_bool, &lcp_wantoptions[0].neg_pcompression, + "Disable protocol field compression", + OPT_A2CLR, &lcp_allowoptions[0].neg_pcompression }, + { "-pc", o_bool, &lcp_wantoptions[0].neg_pcompression, + "Disable protocol field compression", + OPT_ALIAS | OPT_A2CLR, &lcp_allowoptions[0].neg_pcompression }, + + { "passive", o_bool, &lcp_wantoptions[0].passive, + "Set passive mode", 1 }, + { "-p", o_bool, &lcp_wantoptions[0].passive, + "Set passive mode", OPT_ALIAS | 1 }, + + { "silent", o_bool, &lcp_wantoptions[0].silent, + "Set silent mode", 1 }, + + { "lcp-echo-failure", o_int, &lcp_echo_fails, + "Set number of consecutive echo failures to indicate link failure", + OPT_PRIO }, + { "lcp-echo-interval", o_int, &lcp_echo_interval, + "Set time in seconds between LCP echo requests", OPT_PRIO }, +#if PPP_LCP_ADAPTIVE + { "lcp-echo-adaptive", o_bool, &lcp_echo_adaptive, + "Suppress LCP echo requests if traffic was received", 1 }, +#endif + { "lcp-restart", o_int, &lcp_fsm[0].timeouttime, + "Set time in seconds between LCP retransmissions", OPT_PRIO }, + { "lcp-max-terminate", o_int, &lcp_fsm[0].maxtermtransmits, + "Set maximum number of LCP terminate-request transmissions", OPT_PRIO }, + { "lcp-max-configure", o_int, &lcp_fsm[0].maxconfreqtransmits, + "Set maximum number of LCP configure-request transmissions", OPT_PRIO }, + { "lcp-max-failure", o_int, &lcp_fsm[0].maxnakloops, + "Set limit on number of LCP configure-naks", OPT_PRIO }, + + { "receive-all", o_bool, &lax_recv, + "Accept all received control characters", 1 }, + +#ifdef HAVE_MULTILINK + { "mrru", o_int, &lcp_wantoptions[0].mrru, + "Maximum received packet size for multilink bundle", + OPT_PRIO, &lcp_wantoptions[0].neg_mrru }, + + { "mpshortseq", o_bool, &lcp_wantoptions[0].neg_ssnhf, + "Use short sequence numbers in multilink headers", + OPT_PRIO | 1, &lcp_allowoptions[0].neg_ssnhf }, + { "nompshortseq", o_bool, &lcp_wantoptions[0].neg_ssnhf, + "Don't use short sequence numbers in multilink headers", + OPT_PRIOSUB | OPT_A2CLR, &lcp_allowoptions[0].neg_ssnhf }, + + { "endpoint", o_special, (void *) setendpoint, + "Endpoint discriminator for multilink", + OPT_PRIO | OPT_A2PRINTER, (void *) printendpoint }, +#endif /* HAVE_MULTILINK */ + + { "noendpoint", o_bool, &noendpoint, + "Don't send or accept multilink endpoint discriminator", 1 }, + + {NULL} +}; +#endif /* PPP_OPTIONS */ + +/* + * Callbacks for fsm code. (CI = Configuration Information) + */ +static void lcp_resetci(fsm *f); /* Reset our CI */ +static int lcp_cilen(fsm *f); /* Return length of our CI */ +static void lcp_addci(fsm *f, u_char *ucp, int *lenp); /* Add our CI to pkt */ +static int lcp_ackci(fsm *f, u_char *p, int len); /* Peer ack'd our CI */ +static int lcp_nakci(fsm *f, u_char *p, int len, int treat_as_reject); /* Peer nak'd our CI */ +static int lcp_rejci(fsm *f, u_char *p, int len); /* Peer rej'd our CI */ +static int lcp_reqci(fsm *f, u_char *inp, int *lenp, int reject_if_disagree); /* Rcv peer CI */ +static void lcp_up(fsm *f); /* We're UP */ +static void lcp_down(fsm *f); /* We're DOWN */ +static void lcp_starting (fsm *); /* We need lower layer up */ +static void lcp_finished (fsm *); /* We need lower layer down */ +static int lcp_extcode(fsm *f, int code, int id, u_char *inp, int len); +static void lcp_rprotrej(fsm *f, u_char *inp, int len); + +/* + * routines to send LCP echos to peer + */ + +static void lcp_echo_lowerup(ppp_pcb *pcb); +static void lcp_echo_lowerdown(ppp_pcb *pcb); +static void LcpEchoTimeout(void *arg); +static void lcp_received_echo_reply(fsm *f, int id, u_char *inp, int len); +static void LcpSendEchoRequest(fsm *f); +static void LcpLinkFailure(fsm *f); +static void LcpEchoCheck(fsm *f); + +static const fsm_callbacks lcp_callbacks = { /* LCP callback routines */ + lcp_resetci, /* Reset our Configuration Information */ + lcp_cilen, /* Length of our Configuration Information */ + lcp_addci, /* Add our Configuration Information */ + lcp_ackci, /* ACK our Configuration Information */ + lcp_nakci, /* NAK our Configuration Information */ + lcp_rejci, /* Reject our Configuration Information */ + lcp_reqci, /* Request peer's Configuration Information */ + lcp_up, /* Called when fsm reaches OPENED state */ + lcp_down, /* Called when fsm leaves OPENED state */ + lcp_starting, /* Called when we want the lower layer up */ + lcp_finished, /* Called when we want the lower layer down */ + NULL, /* Called when Protocol-Reject received */ + NULL, /* Retransmission is necessary */ + lcp_extcode, /* Called to handle LCP-specific codes */ + "LCP" /* String name of protocol */ +}; + +/* + * Protocol entry points. + * Some of these are called directly. + */ + +static void lcp_init(ppp_pcb *pcb); +static void lcp_input(ppp_pcb *pcb, u_char *p, int len); +static void lcp_protrej(ppp_pcb *pcb); +#if PRINTPKT_SUPPORT +static int lcp_printpkt(const u_char *p, int plen, + void (*printer) (void *, const char *, ...), void *arg); +#endif /* PRINTPKT_SUPPORT */ + +const struct protent lcp_protent = { + PPP_LCP, + lcp_init, + lcp_input, + lcp_protrej, + lcp_lowerup, + lcp_lowerdown, + lcp_open, + lcp_close, +#if PRINTPKT_SUPPORT + lcp_printpkt, +#endif /* PRINTPKT_SUPPORT */ +#if PPP_DATAINPUT + NULL, +#endif /* PPP_DATAINPUT */ +#if PRINTPKT_SUPPORT + "LCP", + NULL, +#endif /* PRINTPKT_SUPPORT */ +#if PPP_OPTIONS + lcp_option_list, + NULL, +#endif /* PPP_OPTIONS */ +#if DEMAND_SUPPORT + NULL, + NULL +#endif /* DEMAND_SUPPORT */ +}; + +/* + * Length of each type of configuration option (in octets) + */ +#define CILEN_VOID 2 +#define CILEN_CHAR 3 +#define CILEN_SHORT 4 /* CILEN_VOID + 2 */ +#if CHAP_SUPPORT +#define CILEN_CHAP 5 /* CILEN_VOID + 2 + 1 */ +#endif /* CHAP_SUPPORT */ +#define CILEN_LONG 6 /* CILEN_VOID + 4 */ +#if LQR_SUPPORT +#define CILEN_LQR 8 /* CILEN_VOID + 2 + 4 */ +#endif /* LQR_SUPPORT */ +#define CILEN_CBCP 3 + +#define CODENAME(x) ((x) == CONFACK ? "ACK" : \ + (x) == CONFNAK ? "NAK" : "REJ") + +#if PPP_OPTIONS +/* + * noopt - Disable all options (why?). + */ +static int +noopt(argv) + char **argv; +{ + BZERO((char *) &lcp_wantoptions[0], sizeof (struct lcp_options)); + BZERO((char *) &lcp_allowoptions[0], sizeof (struct lcp_options)); + + return (1); +} +#endif /* PPP_OPTIONS */ + +#ifdef HAVE_MULTILINK +static int +setendpoint(argv) + char **argv; +{ + if (str_to_epdisc(&lcp_wantoptions[0].endpoint, *argv)) { + lcp_wantoptions[0].neg_endpoint = 1; + return 1; + } + option_error("Can't parse '%s' as an endpoint discriminator", *argv); + return 0; +} + +static void +printendpoint(opt, printer, arg) + option_t *opt; + void (*printer) (void *, char *, ...); + void *arg; +{ + printer(arg, "%s", epdisc_to_str(&lcp_wantoptions[0].endpoint)); +} +#endif /* HAVE_MULTILINK */ + +/* + * lcp_init - Initialize LCP. + */ +static void lcp_init(ppp_pcb *pcb) { + fsm *f = &pcb->lcp_fsm; + lcp_options *wo = &pcb->lcp_wantoptions; + lcp_options *ao = &pcb->lcp_allowoptions; + + f->pcb = pcb; + f->protocol = PPP_LCP; + f->callbacks = &lcp_callbacks; + + fsm_init(f); + + BZERO(wo, sizeof(*wo)); + wo->neg_mru = 1; + wo->mru = PPP_DEFMRU; + wo->neg_asyncmap = 1; + wo->neg_magicnumber = 1; + wo->neg_pcompression = 1; + wo->neg_accompression = 1; + + BZERO(ao, sizeof(*ao)); + ao->neg_mru = 1; + ao->mru = PPP_MAXMRU; + ao->neg_asyncmap = 1; +#if CHAP_SUPPORT + ao->neg_chap = 1; + ao->chap_mdtype = CHAP_MDTYPE_SUPPORTED; +#endif /* CHAP_SUPPORT */ +#if PAP_SUPPORT + ao->neg_upap = 1; +#endif /* PAP_SUPPORT */ +#if EAP_SUPPORT + ao->neg_eap = 1; +#endif /* EAP_SUPPORT */ + ao->neg_magicnumber = 1; + ao->neg_pcompression = 1; + ao->neg_accompression = 1; + ao->neg_endpoint = 1; +} + + +/* + * lcp_open - LCP is allowed to come up. + */ +void lcp_open(ppp_pcb *pcb) { + fsm *f = &pcb->lcp_fsm; + lcp_options *wo = &pcb->lcp_wantoptions; + + f->flags &= ~(OPT_PASSIVE | OPT_SILENT); + if (wo->passive) + f->flags |= OPT_PASSIVE; + if (wo->silent) + f->flags |= OPT_SILENT; + fsm_open(f); +} + + +/* + * lcp_close - Take LCP down. + */ +void lcp_close(ppp_pcb *pcb, const char *reason) { + fsm *f = &pcb->lcp_fsm; + int oldstate; + + if (pcb->phase != PPP_PHASE_DEAD && pcb->phase != PPP_PHASE_MASTER) + new_phase(pcb, PPP_PHASE_TERMINATE); + + if (f->flags & DELAYED_UP) { + UNTIMEOUT(lcp_delayed_up, f); + f->state = PPP_FSM_STOPPED; + } + oldstate = f->state; + + fsm_close(f, reason); + if (oldstate == PPP_FSM_STOPPED && (f->flags & (OPT_PASSIVE|OPT_SILENT|DELAYED_UP))) { + /* + * This action is not strictly according to the FSM in RFC1548, + * but it does mean that the program terminates if you do a + * lcp_close() when a connection hasn't been established + * because we are in passive/silent mode or because we have + * delayed the fsm_lowerup() call and it hasn't happened yet. + */ + f->flags &= ~DELAYED_UP; + lcp_finished(f); + } +} + + +/* + * lcp_lowerup - The lower layer is up. + */ +void lcp_lowerup(ppp_pcb *pcb) { + lcp_options *wo = &pcb->lcp_wantoptions; + fsm *f = &pcb->lcp_fsm; + /* + * Don't use A/C or protocol compression on transmission, + * but accept A/C and protocol compressed packets + * if we are going to ask for A/C and protocol compression. + */ + if (ppp_send_config(pcb, PPP_MRU, 0xffffffff, 0, 0) < 0 + || ppp_recv_config(pcb, PPP_MRU, (pcb->settings.lax_recv? 0: 0xffffffff), + wo->neg_pcompression, wo->neg_accompression) < 0) + return; + pcb->peer_mru = PPP_MRU; + + if (pcb->settings.listen_time != 0) { + f->flags |= DELAYED_UP; + TIMEOUTMS(lcp_delayed_up, f, pcb->settings.listen_time); + } else + fsm_lowerup(f); +} + + +/* + * lcp_lowerdown - The lower layer is down. + */ +void lcp_lowerdown(ppp_pcb *pcb) { + fsm *f = &pcb->lcp_fsm; + + if (f->flags & DELAYED_UP) { + f->flags &= ~DELAYED_UP; + UNTIMEOUT(lcp_delayed_up, f); + } else + fsm_lowerdown(f); +} + + +/* + * lcp_delayed_up - Bring the lower layer up now. + */ +static void lcp_delayed_up(void *arg) { + fsm *f = (fsm*)arg; + + if (f->flags & DELAYED_UP) { + f->flags &= ~DELAYED_UP; + fsm_lowerup(f); + } +} + + +/* + * lcp_input - Input LCP packet. + */ +static void lcp_input(ppp_pcb *pcb, u_char *p, int len) { + fsm *f = &pcb->lcp_fsm; + + if (f->flags & DELAYED_UP) { + f->flags &= ~DELAYED_UP; + UNTIMEOUT(lcp_delayed_up, f); + fsm_lowerup(f); + } + fsm_input(f, p, len); +} + +/* + * lcp_extcode - Handle a LCP-specific code. + */ +static int lcp_extcode(fsm *f, int code, int id, u_char *inp, int len) { + ppp_pcb *pcb = f->pcb; + lcp_options *go = &pcb->lcp_gotoptions; + u_char *magp; + + switch( code ){ + case PROTREJ: + lcp_rprotrej(f, inp, len); + break; + + case ECHOREQ: + if (f->state != PPP_FSM_OPENED) + break; + magp = inp; + PUTLONG(go->magicnumber, magp); + fsm_sdata(f, ECHOREP, id, inp, len); + break; + + case ECHOREP: + lcp_received_echo_reply(f, id, inp, len); + break; + + case DISCREQ: + case IDENTIF: + case TIMEREM: + break; + + default: + return 0; + } + return 1; +} + + +/* + * lcp_rprotrej - Receive an Protocol-Reject. + * + * Figure out which protocol is rejected and inform it. + */ +static void lcp_rprotrej(fsm *f, u_char *inp, int len) { + int i; + const struct protent *protp; + u_short prot; +#if PPP_PROTOCOLNAME + const char *pname; +#endif /* PPP_PROTOCOLNAME */ + + if (len < 2) { + LCPDEBUG(("lcp_rprotrej: Rcvd short Protocol-Reject packet!")); + return; + } + + GETSHORT(prot, inp); + + /* + * Protocol-Reject packets received in any state other than the LCP + * OPENED state SHOULD be silently discarded. + */ + if( f->state != PPP_FSM_OPENED ){ + LCPDEBUG(("Protocol-Reject discarded: LCP in state %d", f->state)); + return; + } + +#if PPP_PROTOCOLNAME + pname = protocol_name(prot); +#endif /* PPP_PROTOCOLNAME */ + + /* + * Upcall the proper Protocol-Reject routine. + */ + for (i = 0; (protp = protocols[i]) != NULL; ++i) + if (protp->protocol == prot) { +#if PPP_PROTOCOLNAME + if (pname != NULL) + ppp_dbglog("Protocol-Reject for '%s' (0x%x) received", pname, + prot); + else +#endif /* PPP_PROTOCOLNAME */ + ppp_dbglog("Protocol-Reject for 0x%x received", prot); + (*protp->protrej)(f->pcb); + return; + } + +#if PPP_PROTOCOLNAME + if (pname != NULL) + ppp_warn("Protocol-Reject for unsupported protocol '%s' (0x%x)", pname, + prot); + else +#endif /* #if PPP_PROTOCOLNAME */ + ppp_warn("Protocol-Reject for unsupported protocol 0x%x", prot); +} + + +/* + * lcp_protrej - A Protocol-Reject was received. + */ +/*ARGSUSED*/ +static void lcp_protrej(ppp_pcb *pcb) { + /* + * Can't reject LCP! + */ + ppp_error("Received Protocol-Reject for LCP!"); + fsm_protreject(&pcb->lcp_fsm); +} + + +/* + * lcp_sprotrej - Send a Protocol-Reject for some protocol. + */ +void lcp_sprotrej(ppp_pcb *pcb, u_char *p, int len) { + fsm *f = &pcb->lcp_fsm; + /* + * Send back the protocol and the information field of the + * rejected packet. We only get here if LCP is in the OPENED state. + */ +#if 0 + p += 2; + len -= 2; +#endif + + fsm_sdata(f, PROTREJ, ++f->id, + p, len); +} + + +/* + * lcp_resetci - Reset our CI. + */ +static void lcp_resetci(fsm *f) { + ppp_pcb *pcb = f->pcb; + lcp_options *wo = &pcb->lcp_wantoptions; + lcp_options *go = &pcb->lcp_gotoptions; + lcp_options *ao = &pcb->lcp_allowoptions; + +#if PPP_AUTH_SUPPORT + + /* note: default value is true for allow options */ + if (pcb->settings.user && pcb->settings.passwd) { +#if PAP_SUPPORT + if (pcb->settings.refuse_pap) { + ao->neg_upap = 0; + } +#endif /* PAP_SUPPORT */ +#if CHAP_SUPPORT + if (pcb->settings.refuse_chap) { + ao->chap_mdtype &= ~MDTYPE_MD5; + } +#if MSCHAP_SUPPORT + if (pcb->settings.refuse_mschap) { + ao->chap_mdtype &= ~MDTYPE_MICROSOFT; + } + if (pcb->settings.refuse_mschap_v2) { + ao->chap_mdtype &= ~MDTYPE_MICROSOFT_V2; + } +#endif /* MSCHAP_SUPPORT */ + ao->neg_chap = (ao->chap_mdtype != MDTYPE_NONE); +#endif /* CHAP_SUPPORT */ +#if EAP_SUPPORT + if (pcb->settings.refuse_eap) { + ao->neg_eap = 0; + } +#endif /* EAP_SUPPORT */ + +#if PPP_SERVER + /* note: default value is false for wanted options */ + if (pcb->settings.auth_required) { +#if PAP_SUPPORT + if (!pcb->settings.refuse_pap) { + wo->neg_upap = 1; + } +#endif /* PAP_SUPPORT */ +#if CHAP_SUPPORT + if (!pcb->settings.refuse_chap) { + wo->chap_mdtype |= MDTYPE_MD5; + } +#if MSCHAP_SUPPORT + if (!pcb->settings.refuse_mschap) { + wo->chap_mdtype |= MDTYPE_MICROSOFT; + } + if (!pcb->settings.refuse_mschap_v2) { + wo->chap_mdtype |= MDTYPE_MICROSOFT_V2; + } +#endif /* MSCHAP_SUPPORT */ + wo->neg_chap = (wo->chap_mdtype != MDTYPE_NONE); +#endif /* CHAP_SUPPORT */ +#if EAP_SUPPORT + if (!pcb->settings.refuse_eap) { + wo->neg_eap = 1; + } +#endif /* EAP_SUPPORT */ + } +#endif /* PPP_SERVER */ + + } else { +#if PAP_SUPPORT + ao->neg_upap = 0; +#endif /* PAP_SUPPORT */ +#if CHAP_SUPPORT + ao->neg_chap = 0; + ao->chap_mdtype = MDTYPE_NONE; +#endif /* CHAP_SUPPORT */ +#if EAP_SUPPORT + ao->neg_eap = 0; +#endif /* EAP_SUPPORT */ + } + + PPPDEBUG(LOG_DEBUG, ("ppp: auth protocols:")); +#if PAP_SUPPORT + PPPDEBUG(LOG_DEBUG, (" PAP=%d", ao->neg_upap)); +#endif /* PAP_SUPPORT */ +#if CHAP_SUPPORT + PPPDEBUG(LOG_DEBUG, (" CHAP=%d CHAP_MD5=%d", ao->neg_chap, !!(ao->chap_mdtype&MDTYPE_MD5))); +#if MSCHAP_SUPPORT + PPPDEBUG(LOG_DEBUG, (" CHAP_MS=%d CHAP_MS2=%d", !!(ao->chap_mdtype&MDTYPE_MICROSOFT), !!(ao->chap_mdtype&MDTYPE_MICROSOFT_V2))); +#endif /* MSCHAP_SUPPORT */ +#endif /* CHAP_SUPPORT */ +#if EAP_SUPPORT + PPPDEBUG(LOG_DEBUG, (" EAP=%d", ao->neg_eap)); +#endif /* EAP_SUPPORT */ + PPPDEBUG(LOG_DEBUG, ("\n")); + +#endif /* PPP_AUTH_SUPPORT */ + + wo->magicnumber = magic(); + wo->numloops = 0; + *go = *wo; +#ifdef HAVE_MULTILINK + if (!multilink) { + go->neg_mrru = 0; +#endif /* HAVE_MULTILINK */ + go->neg_ssnhf = 0; + go->neg_endpoint = 0; +#ifdef HAVE_MULTILINK + } +#endif /* HAVE_MULTILINK */ + if (pcb->settings.noendpoint) + ao->neg_endpoint = 0; + pcb->peer_mru = PPP_MRU; +#if 0 /* UNUSED */ + auth_reset(pcb); +#endif /* UNUSED */ +} + + +/* + * lcp_cilen - Return length of our CI. + */ +static int lcp_cilen(fsm *f) { + ppp_pcb *pcb = f->pcb; + lcp_options *go = &pcb->lcp_gotoptions; + +#define LENCIVOID(neg) ((neg) ? CILEN_VOID : 0) +#if CHAP_SUPPORT +#define LENCICHAP(neg) ((neg) ? CILEN_CHAP : 0) +#endif /* CHAP_SUPPORT */ +#define LENCISHORT(neg) ((neg) ? CILEN_SHORT : 0) +#define LENCILONG(neg) ((neg) ? CILEN_LONG : 0) +#if LQR_SUPPORT +#define LENCILQR(neg) ((neg) ? CILEN_LQR: 0) +#endif /* LQR_SUPPORT */ +#define LENCICBCP(neg) ((neg) ? CILEN_CBCP: 0) + /* + * NB: we only ask for one of CHAP, UPAP, or EAP, even if we will + * accept more than one. We prefer EAP first, then CHAP, then + * PAP. + */ + return (LENCISHORT(go->neg_mru && go->mru != PPP_DEFMRU) + + LENCILONG(go->neg_asyncmap && go->asyncmap != 0xFFFFFFFF) + +#if EAP_SUPPORT + LENCISHORT(go->neg_eap) + +#endif /* EAP_SUPPORT */ +#if CHAP_SUPPORT /* cannot be improved, embedding a directive within macro arguments is not portable */ +#if EAP_SUPPORT + LENCICHAP(!go->neg_eap && go->neg_chap) + +#endif /* EAP_SUPPORT */ +#if !EAP_SUPPORT + LENCICHAP(go->neg_chap) + +#endif /* !EAP_SUPPORT */ +#endif /* CHAP_SUPPORT */ +#if PAP_SUPPORT /* cannot be improved, embedding a directive within macro arguments is not portable */ +#if EAP_SUPPORT && CHAP_SUPPORT + LENCISHORT(!go->neg_eap && !go->neg_chap && go->neg_upap) + +#endif /* EAP_SUPPORT && CHAP_SUPPORT */ +#if EAP_SUPPORT && !CHAP_SUPPORT + LENCISHORT(!go->neg_eap && go->neg_upap) + +#endif /* EAP_SUPPORT && !CHAP_SUPPORT */ +#if !EAP_SUPPORT && CHAP_SUPPORT + LENCISHORT(!go->neg_chap && go->neg_upap) + +#endif /* !EAP_SUPPORT && CHAP_SUPPORT */ +#if !EAP_SUPPORT && !CHAP_SUPPORT + LENCISHORT(go->neg_upap) + +#endif /* !EAP_SUPPORT && !CHAP_SUPPORT */ +#endif /* PAP_SUPPORT */ +#if LQR_SUPPORT + LENCILQR(go->neg_lqr) + +#endif /* LQR_SUPPORT */ + LENCICBCP(go->neg_cbcp) + + LENCILONG(go->neg_magicnumber) + + LENCIVOID(go->neg_pcompression) + + LENCIVOID(go->neg_accompression) + +#ifdef HAVE_MULTILINK + LENCISHORT(go->neg_mrru) + +#endif /* HAVE_MULTILINK */ + LENCIVOID(go->neg_ssnhf) + + (go->neg_endpoint? CILEN_CHAR + go->endpoint.length: 0)); +} + + +/* + * lcp_addci - Add our desired CIs to a packet. + */ +static void lcp_addci(fsm *f, u_char *ucp, int *lenp) { + ppp_pcb *pcb = f->pcb; + lcp_options *go = &pcb->lcp_gotoptions; + u_char *start_ucp = ucp; + +#define ADDCIVOID(opt, neg) \ + if (neg) { \ + PUTCHAR(opt, ucp); \ + PUTCHAR(CILEN_VOID, ucp); \ + } +#define ADDCISHORT(opt, neg, val) \ + if (neg) { \ + PUTCHAR(opt, ucp); \ + PUTCHAR(CILEN_SHORT, ucp); \ + PUTSHORT(val, ucp); \ + } +#if CHAP_SUPPORT +#define ADDCICHAP(opt, neg, val) \ + if (neg) { \ + PUTCHAR((opt), ucp); \ + PUTCHAR(CILEN_CHAP, ucp); \ + PUTSHORT(PPP_CHAP, ucp); \ + PUTCHAR((CHAP_DIGEST(val)), ucp); \ + } +#endif /* CHAP_SUPPORT */ +#define ADDCILONG(opt, neg, val) \ + if (neg) { \ + PUTCHAR(opt, ucp); \ + PUTCHAR(CILEN_LONG, ucp); \ + PUTLONG(val, ucp); \ + } +#if LQR_SUPPORT +#define ADDCILQR(opt, neg, val) \ + if (neg) { \ + PUTCHAR(opt, ucp); \ + PUTCHAR(CILEN_LQR, ucp); \ + PUTSHORT(PPP_LQR, ucp); \ + PUTLONG(val, ucp); \ + } +#endif /* LQR_SUPPORT */ +#define ADDCICHAR(opt, neg, val) \ + if (neg) { \ + PUTCHAR(opt, ucp); \ + PUTCHAR(CILEN_CHAR, ucp); \ + PUTCHAR(val, ucp); \ + } +#define ADDCIENDP(opt, neg, class, val, len) \ + if (neg) { \ + int i; \ + PUTCHAR(opt, ucp); \ + PUTCHAR(CILEN_CHAR + len, ucp); \ + PUTCHAR(class, ucp); \ + for (i = 0; i < len; ++i) \ + PUTCHAR(val[i], ucp); \ + } + + ADDCISHORT(CI_MRU, go->neg_mru && go->mru != PPP_DEFMRU, go->mru); + ADDCILONG(CI_ASYNCMAP, go->neg_asyncmap && go->asyncmap != 0xFFFFFFFF, + go->asyncmap); +#if EAP_SUPPORT + ADDCISHORT(CI_AUTHTYPE, go->neg_eap, PPP_EAP); +#endif /* EAP_SUPPORT */ +#if CHAP_SUPPORT /* cannot be improved, embedding a directive within macro arguments is not portable */ +#if EAP_SUPPORT + ADDCICHAP(CI_AUTHTYPE, !go->neg_eap && go->neg_chap, go->chap_mdtype); +#endif /* EAP_SUPPORT */ +#if !EAP_SUPPORT + ADDCICHAP(CI_AUTHTYPE, go->neg_chap, go->chap_mdtype); +#endif /* !EAP_SUPPORT */ +#endif /* CHAP_SUPPORT */ +#if PAP_SUPPORT /* cannot be improved, embedding a directive within macro arguments is not portable */ +#if EAP_SUPPORT && CHAP_SUPPORT + ADDCISHORT(CI_AUTHTYPE, !go->neg_eap && !go->neg_chap && go->neg_upap, PPP_PAP); +#endif /* EAP_SUPPORT && CHAP_SUPPORT */ +#if EAP_SUPPORT && !CHAP_SUPPORT + ADDCISHORT(CI_AUTHTYPE, !go->neg_eap && go->neg_upap, PPP_PAP); +#endif /* EAP_SUPPORT && !CHAP_SUPPORT */ +#if !EAP_SUPPORT && CHAP_SUPPORT + ADDCISHORT(CI_AUTHTYPE, !go->neg_chap && go->neg_upap, PPP_PAP); +#endif /* !EAP_SUPPORT && CHAP_SUPPORT */ +#if !EAP_SUPPORT && !CHAP_SUPPORT + ADDCISHORT(CI_AUTHTYPE, go->neg_upap, PPP_PAP); +#endif /* !EAP_SUPPORT && !CHAP_SUPPORT */ +#endif /* PAP_SUPPORT */ +#if LQR_SUPPORT + ADDCILQR(CI_QUALITY, go->neg_lqr, go->lqr_period); +#endif /* LQR_SUPPORT */ + ADDCICHAR(CI_CALLBACK, go->neg_cbcp, CBCP_OPT); + ADDCILONG(CI_MAGICNUMBER, go->neg_magicnumber, go->magicnumber); + ADDCIVOID(CI_PCOMPRESSION, go->neg_pcompression); + ADDCIVOID(CI_ACCOMPRESSION, go->neg_accompression); +#ifdef HAVE_MULTILINK + ADDCISHORT(CI_MRRU, go->neg_mrru, go->mrru); +#endif + ADDCIVOID(CI_SSNHF, go->neg_ssnhf); + ADDCIENDP(CI_EPDISC, go->neg_endpoint, go->endpoint.class_, + go->endpoint.value, go->endpoint.length); + + if (ucp - start_ucp != *lenp) { + /* this should never happen, because peer_mtu should be 1500 */ + ppp_error("Bug in lcp_addci: wrong length"); + } +} + + +/* + * lcp_ackci - Ack our CIs. + * This should not modify any state if the Ack is bad. + * + * Returns: + * 0 - Ack was bad. + * 1 - Ack was good. + */ +static int lcp_ackci(fsm *f, u_char *p, int len) { + ppp_pcb *pcb = f->pcb; + lcp_options *go = &pcb->lcp_gotoptions; + u_char cilen, citype, cichar; + u_short cishort; + u32_t cilong; + + /* + * CIs must be in exactly the same order that we sent. + * Check packet length and CI length at each step. + * If we find any deviations, then this packet is bad. + */ +#define ACKCIVOID(opt, neg) \ + if (neg) { \ + if ((len -= CILEN_VOID) < 0) \ + goto bad; \ + GETCHAR(citype, p); \ + GETCHAR(cilen, p); \ + if (cilen != CILEN_VOID || \ + citype != opt) \ + goto bad; \ + } +#define ACKCISHORT(opt, neg, val) \ + if (neg) { \ + if ((len -= CILEN_SHORT) < 0) \ + goto bad; \ + GETCHAR(citype, p); \ + GETCHAR(cilen, p); \ + if (cilen != CILEN_SHORT || \ + citype != opt) \ + goto bad; \ + GETSHORT(cishort, p); \ + if (cishort != val) \ + goto bad; \ + } +#define ACKCICHAR(opt, neg, val) \ + if (neg) { \ + if ((len -= CILEN_CHAR) < 0) \ + goto bad; \ + GETCHAR(citype, p); \ + GETCHAR(cilen, p); \ + if (cilen != CILEN_CHAR || \ + citype != opt) \ + goto bad; \ + GETCHAR(cichar, p); \ + if (cichar != val) \ + goto bad; \ + } +#if CHAP_SUPPORT +#define ACKCICHAP(opt, neg, val) \ + if (neg) { \ + if ((len -= CILEN_CHAP) < 0) \ + goto bad; \ + GETCHAR(citype, p); \ + GETCHAR(cilen, p); \ + if (cilen != CILEN_CHAP || \ + citype != (opt)) \ + goto bad; \ + GETSHORT(cishort, p); \ + if (cishort != PPP_CHAP) \ + goto bad; \ + GETCHAR(cichar, p); \ + if (cichar != (CHAP_DIGEST(val))) \ + goto bad; \ + } +#endif /* CHAP_SUPPORT */ +#define ACKCILONG(opt, neg, val) \ + if (neg) { \ + if ((len -= CILEN_LONG) < 0) \ + goto bad; \ + GETCHAR(citype, p); \ + GETCHAR(cilen, p); \ + if (cilen != CILEN_LONG || \ + citype != opt) \ + goto bad; \ + GETLONG(cilong, p); \ + if (cilong != val) \ + goto bad; \ + } +#if LQR_SUPPORT +#define ACKCILQR(opt, neg, val) \ + if (neg) { \ + if ((len -= CILEN_LQR) < 0) \ + goto bad; \ + GETCHAR(citype, p); \ + GETCHAR(cilen, p); \ + if (cilen != CILEN_LQR || \ + citype != opt) \ + goto bad; \ + GETSHORT(cishort, p); \ + if (cishort != PPP_LQR) \ + goto bad; \ + GETLONG(cilong, p); \ + if (cilong != val) \ + goto bad; \ + } +#endif /* LQR_SUPPORT */ +#define ACKCIENDP(opt, neg, class, val, vlen) \ + if (neg) { \ + int i; \ + if ((len -= CILEN_CHAR + vlen) < 0) \ + goto bad; \ + GETCHAR(citype, p); \ + GETCHAR(cilen, p); \ + if (cilen != CILEN_CHAR + vlen || \ + citype != opt) \ + goto bad; \ + GETCHAR(cichar, p); \ + if (cichar != class) \ + goto bad; \ + for (i = 0; i < vlen; ++i) { \ + GETCHAR(cichar, p); \ + if (cichar != val[i]) \ + goto bad; \ + } \ + } + + ACKCISHORT(CI_MRU, go->neg_mru && go->mru != PPP_DEFMRU, go->mru); + ACKCILONG(CI_ASYNCMAP, go->neg_asyncmap && go->asyncmap != 0xFFFFFFFF, + go->asyncmap); +#if EAP_SUPPORT + ACKCISHORT(CI_AUTHTYPE, go->neg_eap, PPP_EAP); +#endif /* EAP_SUPPORT */ +#if CHAP_SUPPORT /* cannot be improved, embedding a directive within macro arguments is not portable */ +#if EAP_SUPPORT + ACKCICHAP(CI_AUTHTYPE, !go->neg_eap && go->neg_chap, go->chap_mdtype); +#endif /* EAP_SUPPORT */ +#if !EAP_SUPPORT + ACKCICHAP(CI_AUTHTYPE, go->neg_chap, go->chap_mdtype); +#endif /* !EAP_SUPPORT */ +#endif /* CHAP_SUPPORT */ +#if PAP_SUPPORT /* cannot be improved, embedding a directive within macro arguments is not portable */ +#if EAP_SUPPORT && CHAP_SUPPORT + ACKCISHORT(CI_AUTHTYPE, !go->neg_eap && !go->neg_chap && go->neg_upap, PPP_PAP); +#endif /* EAP_SUPPORT && CHAP_SUPPORT */ +#if EAP_SUPPORT && !CHAP_SUPPORT + ACKCISHORT(CI_AUTHTYPE, !go->neg_eap && go->neg_upap, PPP_PAP); +#endif /* EAP_SUPPORT && !CHAP_SUPPORT */ +#if !EAP_SUPPORT && CHAP_SUPPORT + ACKCISHORT(CI_AUTHTYPE, !go->neg_chap && go->neg_upap, PPP_PAP); +#endif /* !EAP_SUPPORT && CHAP_SUPPORT */ +#if !EAP_SUPPORT && !CHAP_SUPPORT + ACKCISHORT(CI_AUTHTYPE, go->neg_upap, PPP_PAP); +#endif /* !EAP_SUPPORT && !CHAP_SUPPORT */ +#endif /* PAP_SUPPORT */ +#if LQR_SUPPORT + ACKCILQR(CI_QUALITY, go->neg_lqr, go->lqr_period); +#endif /* LQR_SUPPORT */ + ACKCICHAR(CI_CALLBACK, go->neg_cbcp, CBCP_OPT); + ACKCILONG(CI_MAGICNUMBER, go->neg_magicnumber, go->magicnumber); + ACKCIVOID(CI_PCOMPRESSION, go->neg_pcompression); + ACKCIVOID(CI_ACCOMPRESSION, go->neg_accompression); +#ifdef HAVE_MULTILINK + ACKCISHORT(CI_MRRU, go->neg_mrru, go->mrru); +#endif /* HAVE_MULTILINK */ + ACKCIVOID(CI_SSNHF, go->neg_ssnhf); + ACKCIENDP(CI_EPDISC, go->neg_endpoint, go->endpoint.class_, + go->endpoint.value, go->endpoint.length); + + /* + * If there are any remaining CIs, then this packet is bad. + */ + if (len != 0) + goto bad; + return (1); +bad: + LCPDEBUG(("lcp_acki: received bad Ack!")); + return (0); +} + + +/* + * lcp_nakci - Peer has sent a NAK for some of our CIs. + * This should not modify any state if the Nak is bad + * or if LCP is in the OPENED state. + * + * Returns: + * 0 - Nak was bad. + * 1 - Nak was good. + */ +static int lcp_nakci(fsm *f, u_char *p, int len, int treat_as_reject) { + ppp_pcb *pcb = f->pcb; + lcp_options *go = &pcb->lcp_gotoptions; + lcp_options *wo = &pcb->lcp_wantoptions; + u_char citype, cichar, *next; + u_short cishort; + u32_t cilong; + lcp_options no; /* options we've seen Naks for */ + lcp_options try_; /* options to request next time */ + int looped_back = 0; + int cilen; + + BZERO(&no, sizeof(no)); + try_ = *go; + + /* + * Any Nak'd CIs must be in exactly the same order that we sent. + * Check packet length and CI length at each step. + * If we find any deviations, then this packet is bad. + */ +#define NAKCIVOID(opt, neg) \ + if (go->neg && \ + len >= CILEN_VOID && \ + p[1] == CILEN_VOID && \ + p[0] == opt) { \ + len -= CILEN_VOID; \ + INCPTR(CILEN_VOID, p); \ + no.neg = 1; \ + try_.neg = 0; \ + } +#if CHAP_SUPPORT +#define NAKCICHAP(opt, neg, code) \ + if (go->neg && \ + len >= CILEN_CHAP && \ + p[1] == CILEN_CHAP && \ + p[0] == opt) { \ + len -= CILEN_CHAP; \ + INCPTR(2, p); \ + GETSHORT(cishort, p); \ + GETCHAR(cichar, p); \ + no.neg = 1; \ + code \ + } +#endif /* CHAP_SUPPORT */ +#define NAKCICHAR(opt, neg, code) \ + if (go->neg && \ + len >= CILEN_CHAR && \ + p[1] == CILEN_CHAR && \ + p[0] == opt) { \ + len -= CILEN_CHAR; \ + INCPTR(2, p); \ + GETCHAR(cichar, p); \ + no.neg = 1; \ + code \ + } +#define NAKCISHORT(opt, neg, code) \ + if (go->neg && \ + len >= CILEN_SHORT && \ + p[1] == CILEN_SHORT && \ + p[0] == opt) { \ + len -= CILEN_SHORT; \ + INCPTR(2, p); \ + GETSHORT(cishort, p); \ + no.neg = 1; \ + code \ + } +#define NAKCILONG(opt, neg, code) \ + if (go->neg && \ + len >= CILEN_LONG && \ + p[1] == CILEN_LONG && \ + p[0] == opt) { \ + len -= CILEN_LONG; \ + INCPTR(2, p); \ + GETLONG(cilong, p); \ + no.neg = 1; \ + code \ + } +#if LQR_SUPPORT +#define NAKCILQR(opt, neg, code) \ + if (go->neg && \ + len >= CILEN_LQR && \ + p[1] == CILEN_LQR && \ + p[0] == opt) { \ + len -= CILEN_LQR; \ + INCPTR(2, p); \ + GETSHORT(cishort, p); \ + GETLONG(cilong, p); \ + no.neg = 1; \ + code \ + } +#endif /* LQR_SUPPORT */ +#define NAKCIENDP(opt, neg) \ + if (go->neg && \ + len >= CILEN_CHAR && \ + p[0] == opt && \ + p[1] >= CILEN_CHAR && \ + p[1] <= len) { \ + len -= p[1]; \ + INCPTR(p[1], p); \ + no.neg = 1; \ + try_.neg = 0; \ + } + + /* + * NOTE! There must be no assignments to individual fields of *go in + * the code below. Any such assignment is a BUG! + */ + /* + * We don't care if they want to send us smaller packets than + * we want. Therefore, accept any MRU less than what we asked for, + * but then ignore the new value when setting the MRU in the kernel. + * If they send us a bigger MRU than what we asked, accept it, up to + * the limit of the default MRU we'd get if we didn't negotiate. + */ + if (go->neg_mru && go->mru != PPP_DEFMRU) { + NAKCISHORT(CI_MRU, neg_mru, + if (cishort <= wo->mru || cishort <= PPP_DEFMRU) + try_.mru = cishort; + ); + } + + /* + * Add any characters they want to our (receive-side) asyncmap. + */ + if (go->neg_asyncmap && go->asyncmap != 0xFFFFFFFF) { + NAKCILONG(CI_ASYNCMAP, neg_asyncmap, + try_.asyncmap = go->asyncmap | cilong; + ); + } + + /* + * If they've nak'd our authentication-protocol, check whether + * they are proposing a different protocol, or a different + * hash algorithm for CHAP. + */ + if ((0 +#if CHAP_SUPPORT + || go->neg_chap +#endif /* CHAP_SUPPORT */ +#if PAP_SUPPORT + || go->neg_upap +#endif /* PAP_SUPPORT */ +#if EAP_SUPPORT + || go->neg_eap +#endif /* EAP_SUPPORT */ + ) + && len >= CILEN_SHORT + && p[0] == CI_AUTHTYPE && p[1] >= CILEN_SHORT && p[1] <= len) { + cilen = p[1]; + len -= cilen; +#if CHAP_SUPPORT + no.neg_chap = go->neg_chap; +#endif /* CHAP_SUPPORT */ +#if PAP_SUPPORT + no.neg_upap = go->neg_upap; +#endif /* PAP_SUPPORT */ +#if EAP_SUPPORT + no.neg_eap = go->neg_eap; +#endif /* EAP_SUPPORT */ + INCPTR(2, p); + GETSHORT(cishort, p); + +#if PAP_SUPPORT + if (cishort == PPP_PAP && cilen == CILEN_SHORT) { +#if EAP_SUPPORT + /* If we were asking for EAP, then we need to stop that. */ + if (go->neg_eap) + try_.neg_eap = 0; + else +#endif /* EAP_SUPPORT */ + +#if CHAP_SUPPORT + /* If we were asking for CHAP, then we need to stop that. */ + if (go->neg_chap) + try_.neg_chap = 0; + else +#endif /* CHAP_SUPPORT */ + + /* + * If we weren't asking for CHAP or EAP, then we were asking for + * PAP, in which case this Nak is bad. + */ + goto bad; + } else +#endif /* PAP_SUPPORT */ + +#if CHAP_SUPPORT + if (cishort == PPP_CHAP && cilen == CILEN_CHAP) { + GETCHAR(cichar, p); +#if EAP_SUPPORT + /* Stop asking for EAP, if we were. */ + if (go->neg_eap) { + try_.neg_eap = 0; + /* Try to set up to use their suggestion, if possible */ + if (CHAP_CANDIGEST(go->chap_mdtype, cichar)) + try_.chap_mdtype = CHAP_MDTYPE_D(cichar); + } else +#endif /* EAP_SUPPORT */ + if (go->neg_chap) { + /* + * We were asking for our preferred algorithm, they must + * want something different. + */ + if (cichar != CHAP_DIGEST(go->chap_mdtype)) { + if (CHAP_CANDIGEST(go->chap_mdtype, cichar)) { + /* Use their suggestion if we support it ... */ + try_.chap_mdtype = CHAP_MDTYPE_D(cichar); + } else { + /* ... otherwise, try our next-preferred algorithm. */ + try_.chap_mdtype &= ~(CHAP_MDTYPE(try_.chap_mdtype)); + if (try_.chap_mdtype == MDTYPE_NONE) /* out of algos */ + try_.neg_chap = 0; + } + } else { + /* + * Whoops, they Nak'd our algorithm of choice + * but then suggested it back to us. + */ + goto bad; + } + } else { + /* + * Stop asking for PAP if we were asking for it. + */ +#if PAP_SUPPORT + try_.neg_upap = 0; +#endif /* PAP_SUPPORT */ + } + + } else +#endif /* CHAP_SUPPORT */ + { + +#if EAP_SUPPORT + /* + * If we were asking for EAP, and they're Conf-Naking EAP, + * well, that's just strange. Nobody should do that. + */ + if (cishort == PPP_EAP && cilen == CILEN_SHORT && go->neg_eap) + ppp_dbglog("Unexpected Conf-Nak for EAP"); + + /* + * We don't recognize what they're suggesting. + * Stop asking for what we were asking for. + */ + if (go->neg_eap) + try_.neg_eap = 0; + else +#endif /* EAP_SUPPORT */ + +#if CHAP_SUPPORT + if (go->neg_chap) + try_.neg_chap = 0; + else +#endif /* CHAP_SUPPORT */ + +#if PAP_SUPPORT + if(1) + try_.neg_upap = 0; + else +#endif /* PAP_SUPPORT */ + {} + + p += cilen - CILEN_SHORT; + } + } + +#if LQR_SUPPORT + /* + * If they can't cope with our link quality protocol, we'll have + * to stop asking for LQR. We haven't got any other protocol. + * If they Nak the reporting period, take their value XXX ? + */ + NAKCILQR(CI_QUALITY, neg_lqr, + if (cishort != PPP_LQR) + try_.neg_lqr = 0; + else + try_.lqr_period = cilong; + ); +#endif /* LQR_SUPPORT */ + + /* + * Only implementing CBCP...not the rest of the callback options + */ + NAKCICHAR(CI_CALLBACK, neg_cbcp, + try_.neg_cbcp = 0; + (void)cichar; /* if CHAP support is not compiled, cichar is set but not used, which makes some compilers complaining */ + ); + + /* + * Check for a looped-back line. + */ + NAKCILONG(CI_MAGICNUMBER, neg_magicnumber, + try_.magicnumber = magic(); + looped_back = 1; + ); + + /* + * Peer shouldn't send Nak for protocol compression or + * address/control compression requests; they should send + * a Reject instead. If they send a Nak, treat it as a Reject. + */ + NAKCIVOID(CI_PCOMPRESSION, neg_pcompression); + NAKCIVOID(CI_ACCOMPRESSION, neg_accompression); + +#ifdef HAVE_MULTILINK + /* + * Nak for MRRU option - accept their value if it is smaller + * than the one we want. + */ + if (go->neg_mrru) { + NAKCISHORT(CI_MRRU, neg_mrru, + if (treat_as_reject) + try_.neg_mrru = 0; + else if (cishort <= wo->mrru) + try_.mrru = cishort; + ); + } +#else /* HAVE_MULTILINK */ + LWIP_UNUSED_ARG(treat_as_reject); +#endif /* HAVE_MULTILINK */ + + /* + * Nak for short sequence numbers shouldn't be sent, treat it + * like a reject. + */ + NAKCIVOID(CI_SSNHF, neg_ssnhf); + + /* + * Nak of the endpoint discriminator option is not permitted, + * treat it like a reject. + */ + NAKCIENDP(CI_EPDISC, neg_endpoint); + + /* + * There may be remaining CIs, if the peer is requesting negotiation + * on an option that we didn't include in our request packet. + * If we see an option that we requested, or one we've already seen + * in this packet, then this packet is bad. + * If we wanted to respond by starting to negotiate on the requested + * option(s), we could, but we don't, because except for the + * authentication type and quality protocol, if we are not negotiating + * an option, it is because we were told not to. + * For the authentication type, the Nak from the peer means + * `let me authenticate myself with you' which is a bit pointless. + * For the quality protocol, the Nak means `ask me to send you quality + * reports', but if we didn't ask for them, we don't want them. + * An option we don't recognize represents the peer asking to + * negotiate some option we don't support, so ignore it. + */ + while (len >= CILEN_VOID) { + GETCHAR(citype, p); + GETCHAR(cilen, p); + if (cilen < CILEN_VOID || (len -= cilen) < 0) + goto bad; + next = p + cilen - 2; + + switch (citype) { + case CI_MRU: + if ((go->neg_mru && go->mru != PPP_DEFMRU) + || no.neg_mru || cilen != CILEN_SHORT) + goto bad; + GETSHORT(cishort, p); + if (cishort < PPP_DEFMRU) { + try_.neg_mru = 1; + try_.mru = cishort; + } + break; + case CI_ASYNCMAP: + if ((go->neg_asyncmap && go->asyncmap != 0xFFFFFFFF) + || no.neg_asyncmap || cilen != CILEN_LONG) + goto bad; + break; + case CI_AUTHTYPE: + if (0 +#if CHAP_SUPPORT + || go->neg_chap || no.neg_chap +#endif /* CHAP_SUPPORT */ +#if PAP_SUPPORT + || go->neg_upap || no.neg_upap +#endif /* PAP_SUPPORT */ +#if EAP_SUPPORT + || go->neg_eap || no.neg_eap +#endif /* EAP_SUPPORT */ + ) + goto bad; + break; + case CI_MAGICNUMBER: + if (go->neg_magicnumber || no.neg_magicnumber || + cilen != CILEN_LONG) + goto bad; + break; + case CI_PCOMPRESSION: + if (go->neg_pcompression || no.neg_pcompression + || cilen != CILEN_VOID) + goto bad; + break; + case CI_ACCOMPRESSION: + if (go->neg_accompression || no.neg_accompression + || cilen != CILEN_VOID) + goto bad; + break; +#if LQR_SUPPORT + case CI_QUALITY: + if (go->neg_lqr || no.neg_lqr || cilen != CILEN_LQR) + goto bad; + break; +#endif /* LQR_SUPPORT */ +#ifdef HAVE_MULTILINK + case CI_MRRU: + if (go->neg_mrru || no.neg_mrru || cilen != CILEN_SHORT) + goto bad; + break; +#endif /* HAVE_MULTILINK */ + case CI_SSNHF: + if (go->neg_ssnhf || no.neg_ssnhf || cilen != CILEN_VOID) + goto bad; + try_.neg_ssnhf = 1; + break; + case CI_EPDISC: + if (go->neg_endpoint || no.neg_endpoint || cilen < CILEN_CHAR) + goto bad; + break; + default: + break; + } + p = next; + } + + /* + * OK, the Nak is good. Now we can update state. + * If there are any options left we ignore them. + */ + if (f->state != PPP_FSM_OPENED) { + if (looped_back) { + if (++try_.numloops >= pcb->settings.lcp_loopbackfail) { + ppp_notice("Serial line is looped back."); + pcb->err_code = PPPERR_LOOPBACK; + lcp_close(f->pcb, "Loopback detected"); + } + } else + try_.numloops = 0; + *go = try_; + } + + return 1; + +bad: + LCPDEBUG(("lcp_nakci: received bad Nak!")); + return 0; +} + + +/* + * lcp_rejci - Peer has Rejected some of our CIs. + * This should not modify any state if the Reject is bad + * or if LCP is in the OPENED state. + * + * Returns: + * 0 - Reject was bad. + * 1 - Reject was good. + */ +static int lcp_rejci(fsm *f, u_char *p, int len) { + ppp_pcb *pcb = f->pcb; + lcp_options *go = &pcb->lcp_gotoptions; + u_char cichar; + u_short cishort; + u32_t cilong; + lcp_options try_; /* options to request next time */ + + try_ = *go; + + /* + * Any Rejected CIs must be in exactly the same order that we sent. + * Check packet length and CI length at each step. + * If we find any deviations, then this packet is bad. + */ +#define REJCIVOID(opt, neg) \ + if (go->neg && \ + len >= CILEN_VOID && \ + p[1] == CILEN_VOID && \ + p[0] == opt) { \ + len -= CILEN_VOID; \ + INCPTR(CILEN_VOID, p); \ + try_.neg = 0; \ + } +#define REJCISHORT(opt, neg, val) \ + if (go->neg && \ + len >= CILEN_SHORT && \ + p[1] == CILEN_SHORT && \ + p[0] == opt) { \ + len -= CILEN_SHORT; \ + INCPTR(2, p); \ + GETSHORT(cishort, p); \ + /* Check rejected value. */ \ + if (cishort != val) \ + goto bad; \ + try_.neg = 0; \ + } + +#if CHAP_SUPPORT && EAP_SUPPORT && PAP_SUPPORT +#define REJCICHAP(opt, neg, val) \ + if (go->neg && \ + len >= CILEN_CHAP && \ + p[1] == CILEN_CHAP && \ + p[0] == opt) { \ + len -= CILEN_CHAP; \ + INCPTR(2, p); \ + GETSHORT(cishort, p); \ + GETCHAR(cichar, p); \ + /* Check rejected value. */ \ + if ((cishort != PPP_CHAP) || (cichar != (CHAP_DIGEST(val)))) \ + goto bad; \ + try_.neg = 0; \ + try_.neg_eap = try_.neg_upap = 0; \ + } +#endif /* CHAP_SUPPORT && EAP_SUPPORT && PAP_SUPPORT */ + +#if CHAP_SUPPORT && !EAP_SUPPORT && PAP_SUPPORT +#define REJCICHAP(opt, neg, val) \ + if (go->neg && \ + len >= CILEN_CHAP && \ + p[1] == CILEN_CHAP && \ + p[0] == opt) { \ + len -= CILEN_CHAP; \ + INCPTR(2, p); \ + GETSHORT(cishort, p); \ + GETCHAR(cichar, p); \ + /* Check rejected value. */ \ + if ((cishort != PPP_CHAP) || (cichar != (CHAP_DIGEST(val)))) \ + goto bad; \ + try_.neg = 0; \ + try_.neg_upap = 0; \ + } +#endif /* CHAP_SUPPORT && !EAP_SUPPORT && PAP_SUPPORT */ + +#if CHAP_SUPPORT && EAP_SUPPORT && !PAP_SUPPORT +#define REJCICHAP(opt, neg, val) \ + if (go->neg && \ + len >= CILEN_CHAP && \ + p[1] == CILEN_CHAP && \ + p[0] == opt) { \ + len -= CILEN_CHAP; \ + INCPTR(2, p); \ + GETSHORT(cishort, p); \ + GETCHAR(cichar, p); \ + /* Check rejected value. */ \ + if ((cishort != PPP_CHAP) || (cichar != (CHAP_DIGEST(val)))) \ + goto bad; \ + try_.neg = 0; \ + try_.neg_eap = 0; \ + } +#endif /* CHAP_SUPPORT && EAP_SUPPORT && !PAP_SUPPORT */ + +#if CHAP_SUPPORT && !EAP_SUPPORT && !PAP_SUPPORT +#define REJCICHAP(opt, neg, val) \ + if (go->neg && \ + len >= CILEN_CHAP && \ + p[1] == CILEN_CHAP && \ + p[0] == opt) { \ + len -= CILEN_CHAP; \ + INCPTR(2, p); \ + GETSHORT(cishort, p); \ + GETCHAR(cichar, p); \ + /* Check rejected value. */ \ + if ((cishort != PPP_CHAP) || (cichar != (CHAP_DIGEST(val)))) \ + goto bad; \ + try_.neg = 0; \ + } +#endif /* CHAP_SUPPORT && !EAP_SUPPORT && !PAP_SUPPORT */ + +#define REJCILONG(opt, neg, val) \ + if (go->neg && \ + len >= CILEN_LONG && \ + p[1] == CILEN_LONG && \ + p[0] == opt) { \ + len -= CILEN_LONG; \ + INCPTR(2, p); \ + GETLONG(cilong, p); \ + /* Check rejected value. */ \ + if (cilong != val) \ + goto bad; \ + try_.neg = 0; \ + } +#if LQR_SUPPORT +#define REJCILQR(opt, neg, val) \ + if (go->neg && \ + len >= CILEN_LQR && \ + p[1] == CILEN_LQR && \ + p[0] == opt) { \ + len -= CILEN_LQR; \ + INCPTR(2, p); \ + GETSHORT(cishort, p); \ + GETLONG(cilong, p); \ + /* Check rejected value. */ \ + if (cishort != PPP_LQR || cilong != val) \ + goto bad; \ + try_.neg = 0; \ + } +#endif /* LQR_SUPPORT */ +#define REJCICBCP(opt, neg, val) \ + if (go->neg && \ + len >= CILEN_CBCP && \ + p[1] == CILEN_CBCP && \ + p[0] == opt) { \ + len -= CILEN_CBCP; \ + INCPTR(2, p); \ + GETCHAR(cichar, p); \ + /* Check rejected value. */ \ + if (cichar != val) \ + goto bad; \ + try_.neg = 0; \ + } +#define REJCIENDP(opt, neg, class, val, vlen) \ + if (go->neg && \ + len >= CILEN_CHAR + vlen && \ + p[0] == opt && \ + p[1] == CILEN_CHAR + vlen) { \ + int i; \ + len -= CILEN_CHAR + vlen; \ + INCPTR(2, p); \ + GETCHAR(cichar, p); \ + if (cichar != class) \ + goto bad; \ + for (i = 0; i < vlen; ++i) { \ + GETCHAR(cichar, p); \ + if (cichar != val[i]) \ + goto bad; \ + } \ + try_.neg = 0; \ + } + + REJCISHORT(CI_MRU, neg_mru, go->mru); + REJCILONG(CI_ASYNCMAP, neg_asyncmap, go->asyncmap); +#if EAP_SUPPORT + REJCISHORT(CI_AUTHTYPE, neg_eap, PPP_EAP); + if (!go->neg_eap) { +#endif /* EAP_SUPPORT */ +#if CHAP_SUPPORT + REJCICHAP(CI_AUTHTYPE, neg_chap, go->chap_mdtype); + if (!go->neg_chap) { +#endif /* CHAP_SUPPORT */ +#if PAP_SUPPORT + REJCISHORT(CI_AUTHTYPE, neg_upap, PPP_PAP); +#endif /* PAP_SUPPORT */ +#if CHAP_SUPPORT + } +#endif /* CHAP_SUPPORT */ +#if EAP_SUPPORT + } +#endif /* EAP_SUPPORT */ +#if LQR_SUPPORT + REJCILQR(CI_QUALITY, neg_lqr, go->lqr_period); +#endif /* LQR_SUPPORT */ + REJCICBCP(CI_CALLBACK, neg_cbcp, CBCP_OPT); + REJCILONG(CI_MAGICNUMBER, neg_magicnumber, go->magicnumber); + REJCIVOID(CI_PCOMPRESSION, neg_pcompression); + REJCIVOID(CI_ACCOMPRESSION, neg_accompression); +#ifdef HAVE_MULTILINK + REJCISHORT(CI_MRRU, neg_mrru, go->mrru); +#endif /* HAVE_MULTILINK */ + REJCIVOID(CI_SSNHF, neg_ssnhf); + REJCIENDP(CI_EPDISC, neg_endpoint, go->endpoint.class_, + go->endpoint.value, go->endpoint.length); + + /* + * If there are any remaining CIs, then this packet is bad. + */ + if (len != 0) + goto bad; + /* + * Now we can update state. + */ + if (f->state != PPP_FSM_OPENED) + *go = try_; + return 1; + +bad: + LCPDEBUG(("lcp_rejci: received bad Reject!")); + return 0; +} + + +/* + * lcp_reqci - Check the peer's requested CIs and send appropriate response. + * + * Returns: CONFACK, CONFNAK or CONFREJ and input packet modified + * appropriately. If reject_if_disagree is non-zero, doesn't return + * CONFNAK; returns CONFREJ if it can't return CONFACK. + * + * inp = Requested CIs + * lenp = Length of requested CIs + */ +static int lcp_reqci(fsm *f, u_char *inp, int *lenp, int reject_if_disagree) { + ppp_pcb *pcb = f->pcb; + lcp_options *go = &pcb->lcp_gotoptions; + lcp_options *ho = &pcb->lcp_hisoptions; + lcp_options *ao = &pcb->lcp_allowoptions; + u_char *cip, *next; /* Pointer to current and next CIs */ + int cilen, citype, cichar; /* Parsed len, type, char value */ + u_short cishort; /* Parsed short value */ + u32_t cilong; /* Parse long value */ + int rc = CONFACK; /* Final packet return code */ + int orc; /* Individual option return code */ + u_char *p; /* Pointer to next char to parse */ + u_char *rejp; /* Pointer to next char in reject frame */ + struct pbuf *nakp; /* Nak buffer */ + u_char *nakoutp; /* Pointer to next char in Nak frame */ + int l = *lenp; /* Length left */ + + /* + * Reset all his options. + */ + BZERO(ho, sizeof(*ho)); + + /* + * Process all his options. + */ + next = inp; + nakp = pbuf_alloc(PBUF_RAW, (u16_t)(PPP_CTRL_PBUF_MAX_SIZE), PPP_CTRL_PBUF_TYPE); + if(NULL == nakp) + return 0; + if(nakp->tot_len != nakp->len) { + pbuf_free(nakp); + return 0; + } + + nakoutp = (u_char*)nakp->payload; + rejp = inp; + while (l) { + orc = CONFACK; /* Assume success */ + cip = p = next; /* Remember begining of CI */ + if (l < 2 || /* Not enough data for CI header or */ + p[1] < 2 || /* CI length too small or */ + p[1] > l) { /* CI length too big? */ + LCPDEBUG(("lcp_reqci: bad CI length!")); + orc = CONFREJ; /* Reject bad CI */ + cilen = l; /* Reject till end of packet */ + l = 0; /* Don't loop again */ + citype = 0; + goto endswitch; + } + GETCHAR(citype, p); /* Parse CI type */ + GETCHAR(cilen, p); /* Parse CI length */ + l -= cilen; /* Adjust remaining length */ + next += cilen; /* Step to next CI */ + + switch (citype) { /* Check CI type */ + case CI_MRU: + if (!ao->neg_mru || /* Allow option? */ + cilen != CILEN_SHORT) { /* Check CI length */ + orc = CONFREJ; /* Reject CI */ + break; + } + GETSHORT(cishort, p); /* Parse MRU */ + + /* + * He must be able to receive at least our minimum. + * No need to check a maximum. If he sends a large number, + * we'll just ignore it. + */ + if (cishort < PPP_MINMRU) { + orc = CONFNAK; /* Nak CI */ + PUTCHAR(CI_MRU, nakoutp); + PUTCHAR(CILEN_SHORT, nakoutp); + PUTSHORT(PPP_MINMRU, nakoutp); /* Give him a hint */ + break; + } + ho->neg_mru = 1; /* Remember he sent MRU */ + ho->mru = cishort; /* And remember value */ + break; + + case CI_ASYNCMAP: + if (!ao->neg_asyncmap || + cilen != CILEN_LONG) { + orc = CONFREJ; + break; + } + GETLONG(cilong, p); + + /* + * Asyncmap must have set at least the bits + * which are set in lcp_allowoptions[unit].asyncmap. + */ + if ((ao->asyncmap & ~cilong) != 0) { + orc = CONFNAK; + PUTCHAR(CI_ASYNCMAP, nakoutp); + PUTCHAR(CILEN_LONG, nakoutp); + PUTLONG(ao->asyncmap | cilong, nakoutp); + break; + } + ho->neg_asyncmap = 1; + ho->asyncmap = cilong; + break; + + case CI_AUTHTYPE: + if (cilen < CILEN_SHORT || + !(0 +#if PAP_SUPPORT + || ao->neg_upap +#endif /* PAP_SUPPORT */ +#if CHAP_SUPPORT + || ao->neg_chap +#endif /* CHAP_SUPPORT */ +#if EAP_SUPPORT + || ao->neg_eap +#endif /* EAP_SUPPORT */ + )) { + /* + * Reject the option if we're not willing to authenticate. + */ + ppp_dbglog("No auth is possible"); + orc = CONFREJ; + break; + } + GETSHORT(cishort, p); + + /* + * Authtype must be PAP, CHAP, or EAP. + * + * Note: if more than one of ao->neg_upap, ao->neg_chap, and + * ao->neg_eap are set, and the peer sends a Configure-Request + * with two or more authenticate-protocol requests, then we will + * reject the second request. + * Whether we end up doing CHAP, UPAP, or EAP depends then on + * the ordering of the CIs in the peer's Configure-Request. + */ + +#if PAP_SUPPORT + if (cishort == PPP_PAP) { + /* we've already accepted CHAP or EAP */ + if (0 +#if CHAP_SUPPORT + || ho->neg_chap +#endif /* CHAP_SUPPORT */ +#if EAP_SUPPORT + || ho->neg_eap +#endif /* EAP_SUPPORT */ + || cilen != CILEN_SHORT) { + LCPDEBUG(("lcp_reqci: rcvd AUTHTYPE PAP, rejecting...")); + orc = CONFREJ; + break; + } + if (!ao->neg_upap) { /* we don't want to do PAP */ + orc = CONFNAK; /* NAK it and suggest CHAP or EAP */ + PUTCHAR(CI_AUTHTYPE, nakoutp); +#if EAP_SUPPORT + if (ao->neg_eap) { + PUTCHAR(CILEN_SHORT, nakoutp); + PUTSHORT(PPP_EAP, nakoutp); + } else { +#endif /* EAP_SUPPORT */ +#if CHAP_SUPPORT + PUTCHAR(CILEN_CHAP, nakoutp); + PUTSHORT(PPP_CHAP, nakoutp); + PUTCHAR(CHAP_DIGEST(ao->chap_mdtype), nakoutp); +#endif /* CHAP_SUPPORT */ +#if EAP_SUPPORT + } +#endif /* EAP_SUPPORT */ + break; + } + ho->neg_upap = 1; + break; + } +#endif /* PAP_SUPPORT */ +#if CHAP_SUPPORT + if (cishort == PPP_CHAP) { + /* we've already accepted PAP or EAP */ + if ( +#if PAP_SUPPORT + ho->neg_upap || +#endif /* PAP_SUPPORT */ +#if EAP_SUPPORT + ho->neg_eap || +#endif /* EAP_SUPPORT */ + cilen != CILEN_CHAP) { + LCPDEBUG(("lcp_reqci: rcvd AUTHTYPE CHAP, rejecting...")); + orc = CONFREJ; + break; + } + if (!ao->neg_chap) { /* we don't want to do CHAP */ + orc = CONFNAK; /* NAK it and suggest EAP or PAP */ + PUTCHAR(CI_AUTHTYPE, nakoutp); + PUTCHAR(CILEN_SHORT, nakoutp); +#if EAP_SUPPORT + if (ao->neg_eap) { + PUTSHORT(PPP_EAP, nakoutp); + } else +#endif /* EAP_SUPPORT */ +#if PAP_SUPPORT + if(1) { + PUTSHORT(PPP_PAP, nakoutp); + } + else +#endif /* PAP_SUPPORT */ + {} + break; + } + GETCHAR(cichar, p); /* get digest type */ + if (!(CHAP_CANDIGEST(ao->chap_mdtype, cichar))) { + /* + * We can't/won't do the requested type, + * suggest something else. + */ + orc = CONFNAK; + PUTCHAR(CI_AUTHTYPE, nakoutp); + PUTCHAR(CILEN_CHAP, nakoutp); + PUTSHORT(PPP_CHAP, nakoutp); + PUTCHAR(CHAP_DIGEST(ao->chap_mdtype), nakoutp); + break; + } + ho->chap_mdtype = CHAP_MDTYPE_D(cichar); /* save md type */ + ho->neg_chap = 1; + break; + } +#endif /* CHAP_SUPPORT */ +#if EAP_SUPPORT + if (cishort == PPP_EAP) { + /* we've already accepted CHAP or PAP */ + if ( +#if CHAP_SUPPORT + ho->neg_chap || +#endif /* CHAP_SUPPORT */ +#if PAP_SUPPORT + ho->neg_upap || +#endif /* PAP_SUPPORT */ + cilen != CILEN_SHORT) { + LCPDEBUG(("lcp_reqci: rcvd AUTHTYPE EAP, rejecting...")); + orc = CONFREJ; + break; + } + if (!ao->neg_eap) { /* we don't want to do EAP */ + orc = CONFNAK; /* NAK it and suggest CHAP or PAP */ + PUTCHAR(CI_AUTHTYPE, nakoutp); +#if CHAP_SUPPORT + if (ao->neg_chap) { + PUTCHAR(CILEN_CHAP, nakoutp); + PUTSHORT(PPP_CHAP, nakoutp); + PUTCHAR(CHAP_DIGEST(ao->chap_mdtype), nakoutp); + } else +#endif /* CHAP_SUPPORT */ +#if PAP_SUPPORT + if(1) { + PUTCHAR(CILEN_SHORT, nakoutp); + PUTSHORT(PPP_PAP, nakoutp); + } else +#endif /* PAP_SUPPORT */ + {} + break; + } + ho->neg_eap = 1; + break; + } +#endif /* EAP_SUPPORT */ + + /* + * We don't recognize the protocol they're asking for. + * Nak it with something we're willing to do. + * (At this point we know ao->neg_upap || ao->neg_chap || + * ao->neg_eap.) + */ + orc = CONFNAK; + PUTCHAR(CI_AUTHTYPE, nakoutp); + +#if EAP_SUPPORT + if (ao->neg_eap) { + PUTCHAR(CILEN_SHORT, nakoutp); + PUTSHORT(PPP_EAP, nakoutp); + } else +#endif /* EAP_SUPPORT */ +#if CHAP_SUPPORT + if (ao->neg_chap) { + PUTCHAR(CILEN_CHAP, nakoutp); + PUTSHORT(PPP_CHAP, nakoutp); + PUTCHAR(CHAP_DIGEST(ao->chap_mdtype), nakoutp); + } else +#endif /* CHAP_SUPPORT */ +#if PAP_SUPPORT + if(1) { + PUTCHAR(CILEN_SHORT, nakoutp); + PUTSHORT(PPP_PAP, nakoutp); + } else +#endif /* PAP_SUPPORT */ + {} + break; + +#if LQR_SUPPORT + case CI_QUALITY: + if (!ao->neg_lqr || + cilen != CILEN_LQR) { + orc = CONFREJ; + break; + } + + GETSHORT(cishort, p); + GETLONG(cilong, p); + + /* + * Check the protocol and the reporting period. + * XXX When should we Nak this, and what with? + */ + if (cishort != PPP_LQR) { + orc = CONFNAK; + PUTCHAR(CI_QUALITY, nakoutp); + PUTCHAR(CILEN_LQR, nakoutp); + PUTSHORT(PPP_LQR, nakoutp); + PUTLONG(ao->lqr_period, nakoutp); + break; + } + break; +#endif /* LQR_SUPPORT */ + + case CI_MAGICNUMBER: + if (!(ao->neg_magicnumber || go->neg_magicnumber) || + cilen != CILEN_LONG) { + orc = CONFREJ; + break; + } + GETLONG(cilong, p); + + /* + * He must have a different magic number. + */ + if (go->neg_magicnumber && + cilong == go->magicnumber) { + cilong = magic(); /* Don't put magic() inside macro! */ + orc = CONFNAK; + PUTCHAR(CI_MAGICNUMBER, nakoutp); + PUTCHAR(CILEN_LONG, nakoutp); + PUTLONG(cilong, nakoutp); + break; + } + ho->neg_magicnumber = 1; + ho->magicnumber = cilong; + break; + + + case CI_PCOMPRESSION: + if (!ao->neg_pcompression || + cilen != CILEN_VOID) { + orc = CONFREJ; + break; + } + ho->neg_pcompression = 1; + break; + + case CI_ACCOMPRESSION: + if (!ao->neg_accompression || + cilen != CILEN_VOID) { + orc = CONFREJ; + break; + } + ho->neg_accompression = 1; + break; + +#ifdef HAVE_MULTILINK + case CI_MRRU: + if (!ao->neg_mrru + || !multilink + || cilen != CILEN_SHORT) { + orc = CONFREJ; + break; + } + + GETSHORT(cishort, p); + /* possibly should insist on a minimum/maximum MRRU here */ + ho->neg_mrru = 1; + ho->mrru = cishort; + break; +#endif /* HAVE_MULTILINK */ + + case CI_SSNHF: + if (!ao->neg_ssnhf +#ifdef HAVE_MULTILINK + || !multilink +#endif /* HAVE_MULTILINK */ + || cilen != CILEN_VOID) { + orc = CONFREJ; + break; + } + ho->neg_ssnhf = 1; + break; + + case CI_EPDISC: + if (!ao->neg_endpoint || + cilen < CILEN_CHAR || + cilen > CILEN_CHAR + MAX_ENDP_LEN) { + orc = CONFREJ; + break; + } + GETCHAR(cichar, p); + cilen -= CILEN_CHAR; + ho->neg_endpoint = 1; + ho->endpoint.class_ = cichar; + ho->endpoint.length = cilen; + MEMCPY(ho->endpoint.value, p, cilen); + INCPTR(cilen, p); + break; + + default: + LCPDEBUG(("lcp_reqci: rcvd unknown option %d", citype)); + orc = CONFREJ; + break; + } + +endswitch: + if (orc == CONFACK && /* Good CI */ + rc != CONFACK) /* but prior CI wasnt? */ + continue; /* Don't send this one */ + + if (orc == CONFNAK) { /* Nak this CI? */ + if (reject_if_disagree /* Getting fed up with sending NAKs? */ + && citype != CI_MAGICNUMBER) { + orc = CONFREJ; /* Get tough if so */ + } else { + if (rc == CONFREJ) /* Rejecting prior CI? */ + continue; /* Don't send this one */ + rc = CONFNAK; + } + } + if (orc == CONFREJ) { /* Reject this CI */ + rc = CONFREJ; + if (cip != rejp) /* Need to move rejected CI? */ + MEMCPY(rejp, cip, cilen); /* Move it */ + INCPTR(cilen, rejp); /* Update output pointer */ + } + } + + /* + * If we wanted to send additional NAKs (for unsent CIs), the + * code would go here. The extra NAKs would go at *nakoutp. + * At present there are no cases where we want to ask the + * peer to negotiate an option. + */ + + switch (rc) { + case CONFACK: + *lenp = next - inp; + break; + case CONFNAK: + /* + * Copy the Nak'd options from the nak buffer to the caller's buffer. + */ + *lenp = nakoutp - (u_char*)nakp->payload; + MEMCPY(inp, nakp->payload, *lenp); + break; + case CONFREJ: + *lenp = rejp - inp; + break; + default: + break; + } + + pbuf_free(nakp); + LCPDEBUG(("lcp_reqci: returning CONF%s.", CODENAME(rc))); + return (rc); /* Return final code */ +} + + +/* + * lcp_up - LCP has come UP. + */ +static void lcp_up(fsm *f) { + ppp_pcb *pcb = f->pcb; + lcp_options *wo = &pcb->lcp_wantoptions; + lcp_options *ho = &pcb->lcp_hisoptions; + lcp_options *go = &pcb->lcp_gotoptions; + lcp_options *ao = &pcb->lcp_allowoptions; + int mtu, mru; + + if (!go->neg_magicnumber) + go->magicnumber = 0; + if (!ho->neg_magicnumber) + ho->magicnumber = 0; + + /* + * Set our MTU to the smaller of the MTU we wanted and + * the MRU our peer wanted. If we negotiated an MRU, + * set our MRU to the larger of value we wanted and + * the value we got in the negotiation. + * Note on the MTU: the link MTU can be the MRU the peer wanted, + * the interface MTU is set to the lowest of that, the + * MTU we want to use, and our link MRU. + */ + mtu = ho->neg_mru? ho->mru: PPP_MRU; + mru = go->neg_mru? LWIP_MAX(wo->mru, go->mru): PPP_MRU; +#ifdef HAVE_MULTILINK + if (!(multilink && go->neg_mrru && ho->neg_mrru)) +#endif /* HAVE_MULTILINK */ + netif_set_mtu(pcb, LWIP_MIN(LWIP_MIN(mtu, mru), ao->mru)); + ppp_send_config(pcb, mtu, + (ho->neg_asyncmap? ho->asyncmap: 0xffffffff), + ho->neg_pcompression, ho->neg_accompression); + ppp_recv_config(pcb, mru, + (pcb->settings.lax_recv? 0: go->neg_asyncmap? go->asyncmap: 0xffffffff), + go->neg_pcompression, go->neg_accompression); + + if (ho->neg_mru) + pcb->peer_mru = ho->mru; + + lcp_echo_lowerup(f->pcb); /* Enable echo messages */ + + link_established(pcb); +} + + +/* + * lcp_down - LCP has gone DOWN. + * + * Alert other protocols. + */ +static void lcp_down(fsm *f) { + ppp_pcb *pcb = f->pcb; + lcp_options *go = &pcb->lcp_gotoptions; + + lcp_echo_lowerdown(f->pcb); + + link_down(pcb); + + ppp_send_config(pcb, PPP_MRU, 0xffffffff, 0, 0); + ppp_recv_config(pcb, PPP_MRU, + (go->neg_asyncmap? go->asyncmap: 0xffffffff), + go->neg_pcompression, go->neg_accompression); + pcb->peer_mru = PPP_MRU; +} + + +/* + * lcp_starting - LCP needs the lower layer up. + */ +static void lcp_starting(fsm *f) { + ppp_pcb *pcb = f->pcb; + link_required(pcb); +} + + +/* + * lcp_finished - LCP has finished with the lower layer. + */ +static void lcp_finished(fsm *f) { + ppp_pcb *pcb = f->pcb; + link_terminated(pcb); +} + + +#if PRINTPKT_SUPPORT +/* + * lcp_printpkt - print the contents of an LCP packet. + */ +static const char* const lcp_codenames[] = { + "ConfReq", "ConfAck", "ConfNak", "ConfRej", + "TermReq", "TermAck", "CodeRej", "ProtRej", + "EchoReq", "EchoRep", "DiscReq", "Ident", + "TimeRem" +}; + +static int lcp_printpkt(const u_char *p, int plen, + void (*printer) (void *, const char *, ...), void *arg) { + int code, id, len, olen, i; + const u_char *pstart, *optend; + u_short cishort; + u32_t cilong; + + if (plen < HEADERLEN) + return 0; + pstart = p; + GETCHAR(code, p); + GETCHAR(id, p); + GETSHORT(len, p); + if (len < HEADERLEN || len > plen) + return 0; + + if (code >= 1 && code <= (int)sizeof(lcp_codenames) / (int)sizeof(char *)) + printer(arg, " %s", lcp_codenames[code-1]); + else + printer(arg, " code=0x%x", code); + printer(arg, " id=0x%x", id); + len -= HEADERLEN; + switch (code) { + case CONFREQ: + case CONFACK: + case CONFNAK: + case CONFREJ: + /* print option list */ + while (len >= 2) { + GETCHAR(code, p); + GETCHAR(olen, p); + p -= 2; + if (olen < 2 || olen > len) { + break; + } + printer(arg, " <"); + len -= olen; + optend = p + olen; + switch (code) { + case CI_MRU: + if (olen == CILEN_SHORT) { + p += 2; + GETSHORT(cishort, p); + printer(arg, "mru %d", cishort); + } + break; + case CI_ASYNCMAP: + if (olen == CILEN_LONG) { + p += 2; + GETLONG(cilong, p); + printer(arg, "asyncmap 0x%x", cilong); + } + break; + case CI_AUTHTYPE: + if (olen >= CILEN_SHORT) { + p += 2; + printer(arg, "auth "); + GETSHORT(cishort, p); + switch (cishort) { +#if PAP_SUPPORT + case PPP_PAP: + printer(arg, "pap"); + break; +#endif /* PAP_SUPPORT */ +#if CHAP_SUPPORT + case PPP_CHAP: + printer(arg, "chap"); + if (p < optend) { + switch (*p) { + case CHAP_MD5: + printer(arg, " MD5"); + ++p; + break; +#if MSCHAP_SUPPORT + case CHAP_MICROSOFT: + printer(arg, " MS"); + ++p; + break; + + case CHAP_MICROSOFT_V2: + printer(arg, " MS-v2"); + ++p; + break; +#endif /* MSCHAP_SUPPORT */ + default: + break; + } + } + break; +#endif /* CHAP_SUPPORT */ +#if EAP_SUPPORT + case PPP_EAP: + printer(arg, "eap"); + break; +#endif /* EAP_SUPPORT */ + default: + printer(arg, "0x%x", cishort); + } + } + break; +#if LQR_SUPPORT + case CI_QUALITY: + if (olen >= CILEN_SHORT) { + p += 2; + printer(arg, "quality "); + GETSHORT(cishort, p); + switch (cishort) { + case PPP_LQR: + printer(arg, "lqr"); + break; + default: + printer(arg, "0x%x", cishort); + } + } + break; +#endif /* LQR_SUPPORT */ + case CI_CALLBACK: + if (olen >= CILEN_CHAR) { + p += 2; + printer(arg, "callback "); + GETCHAR(cishort, p); + switch (cishort) { + case CBCP_OPT: + printer(arg, "CBCP"); + break; + default: + printer(arg, "0x%x", cishort); + } + } + break; + case CI_MAGICNUMBER: + if (olen == CILEN_LONG) { + p += 2; + GETLONG(cilong, p); + printer(arg, "magic 0x%x", cilong); + } + break; + case CI_PCOMPRESSION: + if (olen == CILEN_VOID) { + p += 2; + printer(arg, "pcomp"); + } + break; + case CI_ACCOMPRESSION: + if (olen == CILEN_VOID) { + p += 2; + printer(arg, "accomp"); + } + break; + case CI_MRRU: + if (olen == CILEN_SHORT) { + p += 2; + GETSHORT(cishort, p); + printer(arg, "mrru %d", cishort); + } + break; + case CI_SSNHF: + if (olen == CILEN_VOID) { + p += 2; + printer(arg, "ssnhf"); + } + break; + case CI_EPDISC: +#ifdef HAVE_MULTILINK + if (olen >= CILEN_CHAR) { + struct epdisc epd; + p += 2; + GETCHAR(epd.class, p); + epd.length = olen - CILEN_CHAR; + if (epd.length > MAX_ENDP_LEN) + epd.length = MAX_ENDP_LEN; + if (epd.length > 0) { + MEMCPY(epd.value, p, epd.length); + p += epd.length; + } + printer(arg, "endpoint [%s]", epdisc_to_str(&epd)); + } +#else + printer(arg, "endpoint"); +#endif + break; + default: + break; + } + while (p < optend) { + GETCHAR(code, p); + printer(arg, " %.2x", code); + } + printer(arg, ">"); + } + break; + + case TERMACK: + case TERMREQ: + if (len > 0 && *p >= ' ' && *p < 0x7f) { + printer(arg, " "); + ppp_print_string(p, len, printer, arg); + p += len; + len = 0; + } + break; + + case ECHOREQ: + case ECHOREP: + case DISCREQ: + if (len >= 4) { + GETLONG(cilong, p); + printer(arg, " magic=0x%x", cilong); + len -= 4; + } + break; + + case IDENTIF: + case TIMEREM: + if (len >= 4) { + GETLONG(cilong, p); + printer(arg, " magic=0x%x", cilong); + len -= 4; + } + if (code == TIMEREM) { + if (len < 4) + break; + GETLONG(cilong, p); + printer(arg, " seconds=%u", cilong); + len -= 4; + } + if (len > 0) { + printer(arg, " "); + ppp_print_string(p, len, printer, arg); + p += len; + len = 0; + } + break; + default: + break; + } + + /* print the rest of the bytes in the packet */ + for (i = 0; i < len && i < 32; ++i) { + GETCHAR(code, p); + printer(arg, " %.2x", code); + } + if (i < len) { + printer(arg, " ..."); + p += len - i; + } + + return p - pstart; +} +#endif /* PRINTPKT_SUPPORT */ + +/* + * Time to shut down the link because there is nothing out there. + */ + +static void LcpLinkFailure(fsm *f) { + ppp_pcb *pcb = f->pcb; + if (f->state == PPP_FSM_OPENED) { + ppp_info("No response to %d echo-requests", pcb->lcp_echos_pending); + ppp_notice("Serial link appears to be disconnected."); + pcb->err_code = PPPERR_PEERDEAD; + lcp_close(pcb, "Peer not responding"); + } +} + +/* + * Timer expired for the LCP echo requests from this process. + */ + +static void LcpEchoCheck(fsm *f) { + ppp_pcb *pcb = f->pcb; + + LcpSendEchoRequest (f); + if (f->state != PPP_FSM_OPENED) + return; + + /* + * Start the timer for the next interval. + */ + if (pcb->lcp_echo_timer_running) + ppp_warn("assertion lcp_echo_timer_running==0 failed"); + TIMEOUT (LcpEchoTimeout, f, pcb->settings.lcp_echo_interval); + pcb->lcp_echo_timer_running = 1; +} + +/* + * LcpEchoTimeout - Timer expired on the LCP echo + */ + +static void LcpEchoTimeout(void *arg) { + fsm *f = (fsm*)arg; + ppp_pcb *pcb = f->pcb; + if (pcb->lcp_echo_timer_running != 0) { + pcb->lcp_echo_timer_running = 0; + LcpEchoCheck ((fsm *) arg); + } +} + +/* + * LcpEchoReply - LCP has received a reply to the echo + */ + +static void lcp_received_echo_reply(fsm *f, int id, u_char *inp, int len) { + ppp_pcb *pcb = f->pcb; + lcp_options *go = &pcb->lcp_gotoptions; + u32_t magic_val; + LWIP_UNUSED_ARG(id); + + /* Check the magic number - don't count replies from ourselves. */ + if (len < 4) { + ppp_dbglog("lcp: received short Echo-Reply, length %d", len); + return; + } + GETLONG(magic_val, inp); + if (go->neg_magicnumber + && magic_val == go->magicnumber) { + ppp_warn("appear to have received our own echo-reply!"); + return; + } + + /* Reset the number of outstanding echo frames */ + pcb->lcp_echos_pending = 0; +} + +/* + * LcpSendEchoRequest - Send an echo request frame to the peer + */ + +static void LcpSendEchoRequest(fsm *f) { + ppp_pcb *pcb = f->pcb; + lcp_options *go = &pcb->lcp_gotoptions; + u32_t lcp_magic; + u_char pkt[4], *pktp; + + /* + * Detect the failure of the peer at this point. + */ + if (pcb->settings.lcp_echo_fails != 0) { + if (pcb->lcp_echos_pending >= pcb->settings.lcp_echo_fails) { + LcpLinkFailure(f); + pcb->lcp_echos_pending = 0; + } + } + +#if PPP_LCP_ADAPTIVE + /* + * If adaptive echos have been enabled, only send the echo request if + * no traffic was received since the last one. + */ + if (pcb->settings.lcp_echo_adaptive) { + static unsigned int last_pkts_in = 0; + +#if PPP_STATS_SUPPORT + update_link_stats(f->unit); + link_stats_valid = 0; +#endif /* PPP_STATS_SUPPORT */ + + if (link_stats.pkts_in != last_pkts_in) { + last_pkts_in = link_stats.pkts_in; + return; + } + } +#endif + + /* + * Make and send the echo request frame. + */ + if (f->state == PPP_FSM_OPENED) { + lcp_magic = go->magicnumber; + pktp = pkt; + PUTLONG(lcp_magic, pktp); + fsm_sdata(f, ECHOREQ, pcb->lcp_echo_number++, pkt, pktp - pkt); + ++pcb->lcp_echos_pending; + } +} + +/* + * lcp_echo_lowerup - Start the timer for the LCP frame + */ + +static void lcp_echo_lowerup(ppp_pcb *pcb) { + fsm *f = &pcb->lcp_fsm; + + /* Clear the parameters for generating echo frames */ + pcb->lcp_echos_pending = 0; + pcb->lcp_echo_number = 0; + pcb->lcp_echo_timer_running = 0; + + /* If a timeout interval is specified then start the timer */ + if (pcb->settings.lcp_echo_interval != 0) + LcpEchoCheck (f); +} + +/* + * lcp_echo_lowerdown - Stop the timer for the LCP frame + */ + +static void lcp_echo_lowerdown(ppp_pcb *pcb) { + fsm *f = &pcb->lcp_fsm; + + if (pcb->lcp_echo_timer_running != 0) { + UNTIMEOUT (LcpEchoTimeout, f); + pcb->lcp_echo_timer_running = 0; + } +} + +#endif /* PPP_SUPPORT */ diff --git a/components/lwip/netif/ppp/magic.c b/components/lwip/netif/ppp/magic.c new file mode 100755 index 0000000000..826386cf1b --- /dev/null +++ b/components/lwip/netif/ppp/magic.c @@ -0,0 +1,294 @@ +/* + * magic.c - PPP Magic Number routines. + * + * Copyright (c) 1984-2000 Carnegie Mellon University. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. The name "Carnegie Mellon University" must not be used to + * endorse or promote products derived from this software without + * prior written permission. For permission or any legal + * details, please contact + * Office of Technology Transfer + * Carnegie Mellon University + * 5000 Forbes Avenue + * Pittsburgh, PA 15213-3890 + * (412) 268-4387, fax: (412) 268-7395 + * tech-transfer@andrew.cmu.edu + * + * 4. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by Computing Services + * at Carnegie Mellon University (http://www.cmu.edu/computing/)." + * + * CARNEGIE MELLON UNIVERSITY DISCLAIMS ALL WARRANTIES WITH REGARD TO + * THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS, IN NO EVENT SHALL CARNEGIE MELLON UNIVERSITY BE LIABLE + * FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN + * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING + * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ +/***************************************************************************** +* randm.c - Random number generator program file. +* +* Copyright (c) 2003 by Marc Boucher, Services Informatiques (MBSI) inc. +* Copyright (c) 1998 by Global Election Systems Inc. +* +* The authors hereby grant permission to use, copy, modify, distribute, +* and license this software and its documentation for any purpose, provided +* that existing copyright notices are retained in all copies and that this +* notice and the following disclaimer are included verbatim in any +* distributions. No written agreement, license, or royalty fee is required +* for any of the authorized uses. +* +* THIS SOFTWARE IS PROVIDED BY THE CONTRIBUTORS *AS IS* AND ANY EXPRESS OR +* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES +* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +* IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF +* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +* +****************************************************************************** +* REVISION HISTORY +* +* 03-01-01 Marc Boucher +* Ported to lwIP. +* 98-06-03 Guy Lancaster , Global Election Systems Inc. +* Extracted from avos. +*****************************************************************************/ + +#include "lwip/opt.h" +#if PPP_SUPPORT /* don't build if not configured for use in lwipopts.h */ + +#include "netif/ppp/ppp_impl.h" +#include "netif/ppp/magic.h" + +#if PPP_MD5_RANDM /* Using MD5 for better randomness if enabled */ + +#if LWIP_INCLUDED_POLARSSL_MD5 +#include "netif/ppp/polarssl/md5.h" +#else +#include "polarssl/md5.h" +#endif + +#define MD5_HASH_SIZE 16 +static char magic_randpool[MD5_HASH_SIZE]; /* Pool of randomness. */ +static long magic_randcount; /* Pseudo-random incrementer */ +static u32_t magic_randomseed; /* Seed used for random number generation. */ + +/* + * Churn the randomness pool on a random event. Call this early and often + * on random and semi-random system events to build randomness in time for + * usage. For randomly timed events, pass a null pointer and a zero length + * and this will use the system timer and other sources to add randomness. + * If new random data is available, pass a pointer to that and it will be + * included. + * + * Ref: Applied Cryptography 2nd Ed. by Bruce Schneier p. 427 + */ +static void magic_churnrand(char *rand_data, u32_t rand_len) { + md5_context md5_ctx; + + /* LWIP_DEBUGF(LOG_INFO, ("magic_churnrand: %u@%P\n", rand_len, rand_data)); */ + md5_starts(&md5_ctx); + md5_update(&md5_ctx, (u_char *)magic_randpool, sizeof(magic_randpool)); + if (rand_data) { + md5_update(&md5_ctx, (u_char *)rand_data, rand_len); + } else { + struct { + /* INCLUDE fields for any system sources of randomness */ + u32_t jiffies; +#ifdef LWIP_RAND + u32_t rand; +#endif /* LWIP_RAND */ + } sys_data; + magic_randomseed += sys_jiffies(); + sys_data.jiffies = magic_randomseed; +#ifdef LWIP_RAND + sys_data.rand = LWIP_RAND(); +#endif /* LWIP_RAND */ + /* Load sys_data fields here. */ + md5_update(&md5_ctx, (u_char *)&sys_data, sizeof(sys_data)); + } + md5_finish(&md5_ctx, (u_char *)magic_randpool); +/* LWIP_DEBUGF(LOG_INFO, ("magic_churnrand: -> 0\n")); */ +} + +/* + * Initialize the random number generator. + */ +void magic_init(void) { + magic_churnrand(NULL, 0); +} + +/* + * Randomize our random seed value. + */ +void magic_randomize(void) { + magic_churnrand(NULL, 0); +} + +/* + * magic_random_bytes - Fill a buffer with random bytes. + * + * Use the random pool to generate random data. This degrades to pseudo + * random when used faster than randomness is supplied using magic_churnrand(). + * Note: It's important that there be sufficient randomness in magic_randpool + * before this is called for otherwise the range of the result may be + * narrow enough to make a search feasible. + * + * Ref: Applied Cryptography 2nd Ed. by Bruce Schneier p. 427 + * + * XXX Why does he not just call magic_churnrand() for each block? Probably + * so that you don't ever publish the seed which could possibly help + * predict future values. + * XXX Why don't we preserve md5 between blocks and just update it with + * magic_randcount each time? Probably there is a weakness but I wish that + * it was documented. + */ +void magic_random_bytes(unsigned char *buf, u32_t buf_len) { + md5_context md5_ctx; + u_char tmp[MD5_HASH_SIZE]; + u32_t n; + + while (buf_len > 0) { + md5_starts(&md5_ctx); + md5_update(&md5_ctx, (u_char *)magic_randpool, sizeof(magic_randpool)); + md5_update(&md5_ctx, (u_char *)&magic_randcount, sizeof(magic_randcount)); + md5_finish(&md5_ctx, tmp); + magic_randcount++; + n = LWIP_MIN(buf_len, MD5_HASH_SIZE); + MEMCPY(buf, tmp, n); + buf += n; + buf_len -= n; + } +} + +/* + * Return a new random number. + */ +u32_t magic(void) { + u32_t new_rand; + + magic_random_bytes((unsigned char *)&new_rand, sizeof(new_rand)); + + return new_rand; +} + +#else /* PPP_MD5_RANDM */ + +/*****************************/ +/*** LOCAL DATA STRUCTURES ***/ +/*****************************/ +#ifndef LWIP_RAND +static int magic_randomized; /* Set when truely randomized. */ +#endif /* LWIP_RAND */ +static u32_t magic_randomseed; /* Seed used for random number generation. */ + + +/***********************************/ +/*** PUBLIC FUNCTION DEFINITIONS ***/ +/***********************************/ + +/* + * Initialize the random number generator. + * + * Here we attempt to compute a random number seed but even if + * it isn't random, we'll randomize it later. + * + * The current method uses the fields from the real time clock, + * the idle process counter, the millisecond counter, and the + * hardware timer tick counter. When this is invoked + * in startup(), then the idle counter and timer values may + * repeat after each boot and the real time clock may not be + * operational. Thus we call it again on the first random + * event. + */ +void magic_init(void) { + magic_randomseed += sys_jiffies(); +#ifndef LWIP_RAND + /* Initialize the Borland random number generator. */ + srand((unsigned)magic_randomseed); +#endif /* LWIP_RAND */ +} + +/* + * magic_init - Initialize the magic number generator. + * + * Randomize our random seed value. Here we use the fact that + * this function is called at *truely random* times by the polling + * and network functions. Here we only get 16 bits of new random + * value but we use the previous value to randomize the other 16 + * bits. + */ +void magic_randomize(void) { +#ifndef LWIP_RAND + if (!magic_randomized) { + magic_randomized = !0; + magic_init(); + /* The initialization function also updates the seed. */ + } else { +#endif /* LWIP_RAND */ + magic_randomseed += sys_jiffies(); +#ifndef LWIP_RAND + } +#endif /* LWIP_RAND */ +} + +/* + * Return a new random number. + * + * Here we use the Borland rand() function to supply a pseudo random + * number which we make truely random by combining it with our own + * seed which is randomized by truely random events. + * Thus the numbers will be truely random unless there have been no + * operator or network events in which case it will be pseudo random + * seeded by the real time clock. + */ +u32_t magic(void) { +#ifdef LWIP_RAND + return LWIP_RAND() + magic_randomseed; +#else /* LWIP_RAND */ + return ((u32_t)rand() << 16) + (u32_t)rand() + magic_randomseed; +#endif /* LWIP_RAND */ +} + +/* + * magic_random_bytes - Fill a buffer with random bytes. + */ +void magic_random_bytes(unsigned char *buf, u32_t buf_len) { + u32_t new_rand, n; + + while (buf_len > 0) { + new_rand = magic(); + n = LWIP_MIN(buf_len, sizeof(new_rand)); + MEMCPY(buf, &new_rand, n); + buf += n; + buf_len -= n; + } +} +#endif /* PPP_MD5_RANDM */ + +/* + * Return a new random number between 0 and (2^pow)-1 included. + */ +u32_t magic_pow(u8_t pow) { + return magic() & ~(~0UL<. + * Copyright (c) 2002,2003,2004 Google, Inc. + * All rights reserved. + * + * License: + * Permission to use, copy, modify, and distribute this software and its + * documentation is hereby granted, provided that the above copyright + * notice appears in all copies. This software is provided without any + * warranty, express or implied. + * + * Changelog: + * 08/12/05 - Matt Domsch + * Only need extra skb padding on transmit, not receive. + * 06/18/04 - Matt Domsch , Oleg Makarenko + * Use Linux kernel 2.6 arc4 and sha1 routines rather than + * providing our own. + * 2/15/04 - TS: added #include and testing for Kernel + * version before using + * MOD_DEC_USAGE_COUNT/MOD_INC_USAGE_COUNT which are + * deprecated in 2.6 + */ + +#include "lwip/opt.h" +#if PPP_SUPPORT && MPPE_SUPPORT /* don't build if not configured for use in lwipopts.h */ + +#include + +#include "lwip/err.h" + +#include "netif/ppp/ppp_impl.h" +#include "netif/ppp/ccp.h" +#include "netif/ppp/mppe.h" +#include "netif/ppp/pppdebug.h" + +#if LWIP_INCLUDED_POLARSSL_SHA1 +#include "netif/ppp/polarssl/sha1.h" +#else +#include "polarssl/sha1.h" +#endif + +#if LWIP_INCLUDED_POLARSSL_ARC4 +#include "netif/ppp/polarssl/arc4.h" +#else +#include "polarssl/arc4.h" +#endif + +#define SHA1_SIGNATURE_SIZE 20 + +/* ppp_mppe_state.bits definitions */ +#define MPPE_BIT_A 0x80 /* Encryption table were (re)inititalized */ +#define MPPE_BIT_B 0x40 /* MPPC only (not implemented) */ +#define MPPE_BIT_C 0x20 /* MPPC only (not implemented) */ +#define MPPE_BIT_D 0x10 /* This is an encrypted frame */ + +#define MPPE_BIT_FLUSHED MPPE_BIT_A +#define MPPE_BIT_ENCRYPTED MPPE_BIT_D + +#define MPPE_BITS(p) ((p)[0] & 0xf0) +#define MPPE_CCOUNT(p) ((((p)[0] & 0x0f) << 8) + (p)[1]) +#define MPPE_CCOUNT_SPACE 0x1000 /* The size of the ccount space */ + +#define MPPE_OVHD 2 /* MPPE overhead/packet */ +#define SANITY_MAX 1600 /* Max bogon factor we will tolerate */ + +/* + * Perform the MPPE rekey algorithm, from RFC 3078, sec. 7.3. + * Well, not what's written there, but rather what they meant. + */ +static void mppe_rekey(ppp_mppe_state * state, int initial_key) +{ + sha1_context sha1_ctx; + u8_t sha1_digest[SHA1_SIGNATURE_SIZE]; + + /* + * Key Derivation, from RFC 3078, RFC 3079. + * Equivalent to Get_Key() for MS-CHAP as described in RFC 3079. + */ + sha1_starts(&sha1_ctx); + sha1_update(&sha1_ctx, state->master_key, state->keylen); + sha1_update(&sha1_ctx, mppe_sha1_pad1, SHA1_PAD_SIZE); + sha1_update(&sha1_ctx, state->session_key, state->keylen); + sha1_update(&sha1_ctx, mppe_sha1_pad2, SHA1_PAD_SIZE); + sha1_finish(&sha1_ctx, sha1_digest); + MEMCPY(state->session_key, sha1_digest, state->keylen); + + if (!initial_key) { + arc4_setup(&state->arc4, sha1_digest, state->keylen); + arc4_crypt(&state->arc4, state->session_key, state->keylen); + } + if (state->keylen == 8) { + /* See RFC 3078 */ + state->session_key[0] = 0xd1; + state->session_key[1] = 0x26; + state->session_key[2] = 0x9e; + } + arc4_setup(&state->arc4, state->session_key, state->keylen); +} + +/* + * Set key, used by MSCHAP before mppe_init() is actually called by CCP so we + * don't have to keep multiple copies of keys. + */ +void mppe_set_key(ppp_pcb *pcb, ppp_mppe_state *state, u8_t *key) { + LWIP_UNUSED_ARG(pcb); + MEMCPY(state->master_key, key, MPPE_MAX_KEY_LEN); +} + +/* + * Initialize (de)compressor state. + */ +void +mppe_init(ppp_pcb *pcb, ppp_mppe_state *state, u8_t options) +{ +#if PPP_DEBUG + const u8_t *debugstr = (const u8_t*)"mppe_comp_init"; + if (&pcb->mppe_decomp == state) { + debugstr = (const u8_t*)"mppe_decomp_init"; + } +#endif /* PPP_DEBUG */ + + /* Save keys. */ + MEMCPY(state->session_key, state->master_key, sizeof(state->master_key)); + + if (options & MPPE_OPT_128) + state->keylen = 16; + else if (options & MPPE_OPT_40) + state->keylen = 8; + else { + PPPDEBUG(LOG_DEBUG, ("%s[%d]: unknown key length\n", debugstr, + pcb->netif->num)); + lcp_close(pcb, "MPPE required but peer negotiation failed"); + return; + } + if (options & MPPE_OPT_STATEFUL) + state->stateful = 1; + + /* Generate the initial session key. */ + mppe_rekey(state, 1); + +#if PPP_DEBUG + { + int i; + char mkey[sizeof(state->master_key) * 2 + 1]; + char skey[sizeof(state->session_key) * 2 + 1]; + + PPPDEBUG(LOG_DEBUG, ("%s[%d]: initialized with %d-bit %s mode\n", + debugstr, pcb->netif->num, (state->keylen == 16) ? 128 : 40, + (state->stateful) ? "stateful" : "stateless")); + + for (i = 0; i < (int)sizeof(state->master_key); i++) + sprintf(mkey + i * 2, "%02x", state->master_key[i]); + for (i = 0; i < (int)sizeof(state->session_key); i++) + sprintf(skey + i * 2, "%02x", state->session_key[i]); + PPPDEBUG(LOG_DEBUG, + ("%s[%d]: keys: master: %s initial session: %s\n", + debugstr, pcb->netif->num, mkey, skey)); + } +#endif /* PPP_DEBUG */ + + /* + * Initialize the coherency count. The initial value is not specified + * in RFC 3078, but we can make a reasonable assumption that it will + * start at 0. Setting it to the max here makes the comp/decomp code + * do the right thing (determined through experiment). + */ + state->ccount = MPPE_CCOUNT_SPACE - 1; + + /* + * Note that even though we have initialized the key table, we don't + * set the FLUSHED bit. This is contrary to RFC 3078, sec. 3.1. + */ + state->bits = MPPE_BIT_ENCRYPTED; +} + +/* + * We received a CCP Reset-Request (actually, we are sending a Reset-Ack), + * tell the compressor to rekey. Note that we MUST NOT rekey for + * every CCP Reset-Request; we only rekey on the next xmit packet. + * We might get multiple CCP Reset-Requests if our CCP Reset-Ack is lost. + * So, rekeying for every CCP Reset-Request is broken as the peer will not + * know how many times we've rekeyed. (If we rekey and THEN get another + * CCP Reset-Request, we must rekey again.) + */ +void mppe_comp_reset(ppp_pcb *pcb, ppp_mppe_state *state) +{ + LWIP_UNUSED_ARG(pcb); + state->bits |= MPPE_BIT_FLUSHED; +} + +/* + * Compress (encrypt) a packet. + * It's strange to call this a compressor, since the output is always + * MPPE_OVHD + 2 bytes larger than the input. + */ +err_t +mppe_compress(ppp_pcb *pcb, ppp_mppe_state *state, struct pbuf **pb, u16_t protocol) +{ + struct pbuf *n, *np; + u8_t *pl; + err_t err; + + LWIP_UNUSED_ARG(pcb); + + /* TCP stack requires that we don't change the packet payload, therefore we copy + * the whole packet before encryption. + */ + np = pbuf_alloc(PBUF_RAW, MPPE_OVHD + sizeof(protocol) + (*pb)->tot_len, PBUF_POOL); + if (!np) { + return ERR_MEM; + } + + /* Hide MPPE header + protocol */ + pbuf_header(np, -(s16_t)(MPPE_OVHD + sizeof(protocol))); + + if ((err = pbuf_copy(np, *pb)) != ERR_OK) { + pbuf_free(np); + return err; + } + + /* Reveal MPPE header + protocol */ + pbuf_header(np, (s16_t)(MPPE_OVHD + sizeof(protocol))); + + *pb = np; + pl = (u8_t*)np->payload; + + state->ccount = (state->ccount + 1) % MPPE_CCOUNT_SPACE; + PPPDEBUG(LOG_DEBUG, ("mppe_compress[%d]: ccount %d\n", pcb->netif->num, state->ccount)); + /* FIXME: use PUT* macros */ + pl[0] = state->ccount>>8; + pl[1] = state->ccount; + + if (!state->stateful || /* stateless mode */ + ((state->ccount & 0xff) == 0xff) || /* "flag" packet */ + (state->bits & MPPE_BIT_FLUSHED)) { /* CCP Reset-Request */ + /* We must rekey */ + if (state->stateful) { + PPPDEBUG(LOG_DEBUG, ("mppe_compress[%d]: rekeying\n", pcb->netif->num)); + } + mppe_rekey(state, 0); + state->bits |= MPPE_BIT_FLUSHED; + } + pl[0] |= state->bits; + state->bits &= ~MPPE_BIT_FLUSHED; /* reset for next xmit */ + pl += MPPE_OVHD; + + /* Add protocol */ + /* FIXME: add PFC support */ + pl[0] = protocol >> 8; + pl[1] = protocol; + + /* Hide MPPE header */ + pbuf_header(np, -(s16_t)MPPE_OVHD); + + /* Encrypt packet */ + for (n = np; n != NULL; n = n->next) { + arc4_crypt(&state->arc4, (u8_t*)n->payload, n->len); + if (n->tot_len == n->len) { + break; + } + } + + /* Reveal MPPE header */ + pbuf_header(np, (s16_t)MPPE_OVHD); + + return ERR_OK; +} + +/* + * We received a CCP Reset-Ack. Just ignore it. + */ +void mppe_decomp_reset(ppp_pcb *pcb, ppp_mppe_state *state) +{ + LWIP_UNUSED_ARG(pcb); + LWIP_UNUSED_ARG(state); + return; +} + +/* + * Decompress (decrypt) an MPPE packet. + */ +err_t +mppe_decompress(ppp_pcb *pcb, ppp_mppe_state *state, struct pbuf **pb) +{ + struct pbuf *n0 = *pb, *n; + u8_t *pl; + u16_t ccount; + u8_t flushed; + + /* MPPE Header */ + if (n0->len < MPPE_OVHD) { + PPPDEBUG(LOG_DEBUG, + ("mppe_decompress[%d]: short pkt (%d)\n", + pcb->netif->num, n0->len)); + state->sanity_errors += 100; + goto sanity_error; + } + + pl = (u8_t*)n0->payload; + flushed = MPPE_BITS(pl) & MPPE_BIT_FLUSHED; + ccount = MPPE_CCOUNT(pl); + PPPDEBUG(LOG_DEBUG, ("mppe_decompress[%d]: ccount %d\n", + pcb->netif->num, ccount)); + + /* sanity checks -- terminate with extreme prejudice */ + if (!(MPPE_BITS(pl) & MPPE_BIT_ENCRYPTED)) { + PPPDEBUG(LOG_DEBUG, + ("mppe_decompress[%d]: ENCRYPTED bit not set!\n", + pcb->netif->num)); + state->sanity_errors += 100; + goto sanity_error; + } + if (!state->stateful && !flushed) { + PPPDEBUG(LOG_DEBUG, ("mppe_decompress[%d]: FLUSHED bit not set in " + "stateless mode!\n", pcb->netif->num)); + state->sanity_errors += 100; + goto sanity_error; + } + if (state->stateful && ((ccount & 0xff) == 0xff) && !flushed) { + PPPDEBUG(LOG_DEBUG, ("mppe_decompress[%d]: FLUSHED bit not set on " + "flag packet!\n", pcb->netif->num)); + state->sanity_errors += 100; + goto sanity_error; + } + + /* + * Check the coherency count. + */ + + if (!state->stateful) { + /* Discard late packet */ + if ((ccount - state->ccount) % MPPE_CCOUNT_SPACE > MPPE_CCOUNT_SPACE / 2) { + state->sanity_errors++; + goto sanity_error; + } + + /* RFC 3078, sec 8.1. Rekey for every packet. */ + while (state->ccount != ccount) { + mppe_rekey(state, 0); + state->ccount = (state->ccount + 1) % MPPE_CCOUNT_SPACE; + } + } else { + /* RFC 3078, sec 8.2. */ + if (!state->discard) { + /* normal state */ + state->ccount = (state->ccount + 1) % MPPE_CCOUNT_SPACE; + if (ccount != state->ccount) { + /* + * (ccount > state->ccount) + * Packet loss detected, enter the discard state. + * Signal the peer to rekey (by sending a CCP Reset-Request). + */ + state->discard = 1; + ccp_resetrequest(pcb); + return ERR_BUF; + } + } else { + /* discard state */ + if (!flushed) { + /* ccp.c will be silent (no additional CCP Reset-Requests). */ + return ERR_BUF; + } else { + /* Rekey for every missed "flag" packet. */ + while ((ccount & ~0xff) != + (state->ccount & ~0xff)) { + mppe_rekey(state, 0); + state->ccount = + (state->ccount + + 256) % MPPE_CCOUNT_SPACE; + } + + /* reset */ + state->discard = 0; + state->ccount = ccount; + /* + * Another problem with RFC 3078 here. It implies that the + * peer need not send a Reset-Ack packet. But RFC 1962 + * requires it. Hopefully, M$ does send a Reset-Ack; even + * though it isn't required for MPPE synchronization, it is + * required to reset CCP state. + */ + } + } + if (flushed) + mppe_rekey(state, 0); + } + + /* Hide MPPE header */ + pbuf_header(n0, -(s16_t)(MPPE_OVHD)); + + /* Decrypt the packet. */ + for (n = n0; n != NULL; n = n->next) { + arc4_crypt(&state->arc4, (u8_t*)n->payload, n->len); + if (n->tot_len == n->len) { + break; + } + } + + /* good packet credit */ + state->sanity_errors >>= 1; + + return ERR_OK; + +sanity_error: + if (state->sanity_errors >= SANITY_MAX) { + /* + * Take LCP down if the peer is sending too many bogons. + * We don't want to do this for a single or just a few + * instances since it could just be due to packet corruption. + */ + lcp_close(pcb, "Too many MPPE errors"); + } + return ERR_BUF; +} + +#endif /* PPP_SUPPORT && MPPE_SUPPORT */ diff --git a/components/lwip/netif/ppp/multilink.c b/components/lwip/netif/ppp/multilink.c new file mode 100755 index 0000000000..3bea516a57 --- /dev/null +++ b/components/lwip/netif/ppp/multilink.c @@ -0,0 +1,609 @@ +/* + * multilink.c - support routines for multilink. + * + * Copyright (c) 2000-2002 Paul Mackerras. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. The name(s) of the authors of this software must not be used to + * endorse or promote products derived from this software without + * prior written permission. + * + * 3. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by Paul Mackerras + * ". + * + * THE AUTHORS OF THIS SOFTWARE DISCLAIM ALL WARRANTIES WITH REGARD TO + * THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS, IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY + * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN + * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING + * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include "lwip/opt.h" +#if PPP_SUPPORT && defined(HAVE_MULTILINK) /* don't build if not configured for use in lwipopts.h */ + +/* Multilink support + * + * Multilink uses Samba TDB (Trivial Database Library), which + * we cannot port, because it needs a filesystem. + * + * We have to choose between doing a memory-shared TDB-clone, + * or dropping multilink support at all. + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "netif/ppp/ppp_impl.h" + +#include "netif/ppp/fsm.h" +#include "netif/ppp/lcp.h" +#include "netif/ppp/tdb.h" + +bool endpoint_specified; /* user gave explicit endpoint discriminator */ +char *bundle_id; /* identifier for our bundle */ +char *blinks_id; /* key for the list of links */ +bool doing_multilink; /* multilink was enabled and agreed to */ +bool multilink_master; /* we own the multilink bundle */ + +extern TDB_CONTEXT *pppdb; +extern char db_key[]; + +static void make_bundle_links (int append); +static void remove_bundle_link (void); +static void iterate_bundle_links (void (*func) (char *)); + +static int get_default_epdisc (struct epdisc *); +static int parse_num (char *str, const char *key, int *valp); +static int owns_unit (TDB_DATA pid, int unit); + +#define set_ip_epdisc(ep, addr) do { \ + ep->length = 4; \ + ep->value[0] = addr >> 24; \ + ep->value[1] = addr >> 16; \ + ep->value[2] = addr >> 8; \ + ep->value[3] = addr; \ +} while (0) + +#define LOCAL_IP_ADDR(addr) \ + (((addr) & 0xff000000) == 0x0a000000 /* 10.x.x.x */ \ + || ((addr) & 0xfff00000) == 0xac100000 /* 172.16.x.x */ \ + || ((addr) & 0xffff0000) == 0xc0a80000) /* 192.168.x.x */ + +#define process_exists(n) (kill((n), 0) == 0 || errno != ESRCH) + +void +mp_check_options() +{ + lcp_options *wo = &lcp_wantoptions[0]; + lcp_options *ao = &lcp_allowoptions[0]; + + doing_multilink = 0; + if (!multilink) + return; + /* if we're doing multilink, we have to negotiate MRRU */ + if (!wo->neg_mrru) { + /* mrru not specified, default to mru */ + wo->mrru = wo->mru; + wo->neg_mrru = 1; + } + ao->mrru = ao->mru; + ao->neg_mrru = 1; + + if (!wo->neg_endpoint && !noendpoint) { + /* get a default endpoint value */ + wo->neg_endpoint = get_default_epdisc(&wo->endpoint); + } +} + +/* + * Make a new bundle or join us to an existing bundle + * if we are doing multilink. + */ +int +mp_join_bundle() +{ + lcp_options *go = &lcp_gotoptions[0]; + lcp_options *ho = &lcp_hisoptions[0]; + lcp_options *ao = &lcp_allowoptions[0]; + int unit, pppd_pid; + int l, mtu; + char *p; + TDB_DATA key, pid, rec; + + if (doing_multilink) { + /* have previously joined a bundle */ + if (!go->neg_mrru || !ho->neg_mrru) { + notice("oops, didn't get multilink on renegotiation"); + lcp_close(pcb, "multilink required"); + return 0; + } + /* XXX should check the peer_authname and ho->endpoint + are the same as previously */ + return 0; + } + + if (!go->neg_mrru || !ho->neg_mrru) { + /* not doing multilink */ + if (go->neg_mrru) + notice("oops, multilink negotiated only for receive"); + mtu = ho->neg_mru? ho->mru: PPP_MRU; + if (mtu > ao->mru) + mtu = ao->mru; + if (demand) { + /* already have a bundle */ + cfg_bundle(0, 0, 0, 0); + netif_set_mtu(pcb, mtu); + return 0; + } + make_new_bundle(0, 0, 0, 0); + set_ifunit(1); + netif_set_mtu(pcb, mtu); + return 0; + } + + doing_multilink = 1; + + /* + * Find the appropriate bundle or join a new one. + * First we make up a name for the bundle. + * The length estimate is worst-case assuming every + * character has to be quoted. + */ + l = 4 * strlen(peer_authname) + 10; + if (ho->neg_endpoint) + l += 3 * ho->endpoint.length + 8; + if (bundle_name) + l += 3 * strlen(bundle_name) + 2; + bundle_id = malloc(l); + if (bundle_id == 0) + novm("bundle identifier"); + + p = bundle_id; + p += slprintf(p, l-1, "BUNDLE=\"%q\"", peer_authname); + if (ho->neg_endpoint || bundle_name) + *p++ = '/'; + if (ho->neg_endpoint) + p += slprintf(p, bundle_id+l-p, "%s", + epdisc_to_str(&ho->endpoint)); + if (bundle_name) + p += slprintf(p, bundle_id+l-p, "/%v", bundle_name); + + /* Make the key for the list of links belonging to the bundle */ + l = p - bundle_id; + blinks_id = malloc(l + 7); + if (blinks_id == NULL) + novm("bundle links key"); + slprintf(blinks_id, l + 7, "BUNDLE_LINKS=%s", bundle_id + 7); + + /* + * For demand mode, we only need to configure the bundle + * and attach the link. + */ + mtu = LWIP_MIN(ho->mrru, ao->mru); + if (demand) { + cfg_bundle(go->mrru, ho->mrru, go->neg_ssnhf, ho->neg_ssnhf); + netif_set_mtu(pcb, mtu); + script_setenv("BUNDLE", bundle_id + 7, 1); + return 0; + } + + /* + * Check if the bundle ID is already in the database. + */ + unit = -1; + lock_db(); + key.dptr = bundle_id; + key.dsize = p - bundle_id; + pid = tdb_fetch(pppdb, key); + if (pid.dptr != NULL) { + /* bundle ID exists, see if the pppd record exists */ + rec = tdb_fetch(pppdb, pid); + if (rec.dptr != NULL && rec.dsize > 0) { + /* make sure the string is null-terminated */ + rec.dptr[rec.dsize-1] = 0; + /* parse the interface number */ + parse_num(rec.dptr, "IFNAME=ppp", &unit); + /* check the pid value */ + if (!parse_num(rec.dptr, "PPPD_PID=", &pppd_pid) + || !process_exists(pppd_pid) + || !owns_unit(pid, unit)) + unit = -1; + free(rec.dptr); + } + free(pid.dptr); + } + + if (unit >= 0) { + /* attach to existing unit */ + if (bundle_attach(unit)) { + set_ifunit(0); + script_setenv("BUNDLE", bundle_id + 7, 0); + make_bundle_links(1); + unlock_db(); + info("Link attached to %s", ifname); + return 1; + } + /* attach failed because bundle doesn't exist */ + } + + /* we have to make a new bundle */ + make_new_bundle(go->mrru, ho->mrru, go->neg_ssnhf, ho->neg_ssnhf); + set_ifunit(1); + netif_set_mtu(pcb, mtu); + script_setenv("BUNDLE", bundle_id + 7, 1); + make_bundle_links(pcb); + unlock_db(); + info("New bundle %s created", ifname); + multilink_master = 1; + return 0; +} + +void mp_exit_bundle() +{ + lock_db(); + remove_bundle_link(); + unlock_db(); +} + +static void sendhup(char *str) +{ + int pid; + + if (parse_num(str, "PPPD_PID=", &pid) && pid != getpid()) { + if (debug) + dbglog("sending SIGHUP to process %d", pid); + kill(pid, SIGHUP); + } +} + +void mp_bundle_terminated() +{ + TDB_DATA key; + + bundle_terminating = 1; + upper_layers_down(pcb); + notice("Connection terminated."); +#if PPP_STATS_SUPPORT + print_link_stats(); +#endif /* PPP_STATS_SUPPORT */ + if (!demand) { + remove_pidfiles(); + script_unsetenv("IFNAME"); + } + + lock_db(); + destroy_bundle(); + iterate_bundle_links(sendhup); + key.dptr = blinks_id; + key.dsize = strlen(blinks_id); + tdb_delete(pppdb, key); + unlock_db(); + + new_phase(PPP_PHASE_DEAD); + + doing_multilink = 0; + multilink_master = 0; +} + +static void make_bundle_links(int append) +{ + TDB_DATA key, rec; + char *p; + char entry[32]; + int l; + + key.dptr = blinks_id; + key.dsize = strlen(blinks_id); + slprintf(entry, sizeof(entry), "%s;", db_key); + p = entry; + if (append) { + rec = tdb_fetch(pppdb, key); + if (rec.dptr != NULL && rec.dsize > 0) { + rec.dptr[rec.dsize-1] = 0; + if (strstr(rec.dptr, db_key) != NULL) { + /* already in there? strange */ + warn("link entry already exists in tdb"); + return; + } + l = rec.dsize + strlen(entry); + p = malloc(l); + if (p == NULL) + novm("bundle link list"); + slprintf(p, l, "%s%s", rec.dptr, entry); + } else { + warn("bundle link list not found"); + } + if (rec.dptr != NULL) + free(rec.dptr); + } + rec.dptr = p; + rec.dsize = strlen(p) + 1; + if (tdb_store(pppdb, key, rec, TDB_REPLACE)) + error("couldn't %s bundle link list", + append? "update": "create"); + if (p != entry) + free(p); +} + +static void remove_bundle_link() +{ + TDB_DATA key, rec; + char entry[32]; + char *p, *q; + int l; + + key.dptr = blinks_id; + key.dsize = strlen(blinks_id); + slprintf(entry, sizeof(entry), "%s;", db_key); + + rec = tdb_fetch(pppdb, key); + if (rec.dptr == NULL || rec.dsize <= 0) { + if (rec.dptr != NULL) + free(rec.dptr); + return; + } + rec.dptr[rec.dsize-1] = 0; + p = strstr(rec.dptr, entry); + if (p != NULL) { + q = p + strlen(entry); + l = strlen(q) + 1; + memmove(p, q, l); + rec.dsize = p - rec.dptr + l; + if (tdb_store(pppdb, key, rec, TDB_REPLACE)) + error("couldn't update bundle link list (removal)"); + } + free(rec.dptr); +} + +static void iterate_bundle_links(void (*func)(char *)) +{ + TDB_DATA key, rec, pp; + char *p, *q; + + key.dptr = blinks_id; + key.dsize = strlen(blinks_id); + rec = tdb_fetch(pppdb, key); + if (rec.dptr == NULL || rec.dsize <= 0) { + error("bundle link list not found (iterating list)"); + if (rec.dptr != NULL) + free(rec.dptr); + return; + } + p = rec.dptr; + p[rec.dsize-1] = 0; + while ((q = strchr(p, ';')) != NULL) { + *q = 0; + key.dptr = p; + key.dsize = q - p; + pp = tdb_fetch(pppdb, key); + if (pp.dptr != NULL && pp.dsize > 0) { + pp.dptr[pp.dsize-1] = 0; + func(pp.dptr); + } + if (pp.dptr != NULL) + free(pp.dptr); + p = q + 1; + } + free(rec.dptr); +} + +static int +parse_num(str, key, valp) + char *str; + const char *key; + int *valp; +{ + char *p, *endp; + int i; + + p = strstr(str, key); + if (p != 0) { + p += strlen(key); + i = strtol(p, &endp, 10); + if (endp != p && (*endp == 0 || *endp == ';')) { + *valp = i; + return 1; + } + } + return 0; +} + +/* + * Check whether the pppd identified by `key' still owns ppp unit `unit'. + */ +static int +owns_unit(key, unit) + TDB_DATA key; + int unit; +{ + char ifkey[32]; + TDB_DATA kd, vd; + int ret = 0; + + slprintf(ifkey, sizeof(ifkey), "IFNAME=ppp%d", unit); + kd.dptr = ifkey; + kd.dsize = strlen(ifkey); + vd = tdb_fetch(pppdb, kd); + if (vd.dptr != NULL) { + ret = vd.dsize == key.dsize + && memcmp(vd.dptr, key.dptr, vd.dsize) == 0; + free(vd.dptr); + } + return ret; +} + +static int +get_default_epdisc(ep) + struct epdisc *ep; +{ + char *p; + struct hostent *hp; + u32_t addr; + + /* First try for an ethernet MAC address */ + p = get_first_ethernet(); + if (p != 0 && get_if_hwaddr(ep->value, p) >= 0) { + ep->class = EPD_MAC; + ep->length = 6; + return 1; + } + + /* see if our hostname corresponds to a reasonable IP address */ + hp = gethostbyname(hostname); + if (hp != NULL) { + addr = *(u32_t *)hp->h_addr; + if (!bad_ip_adrs(addr)) { + addr = ntohl(addr); + if (!LOCAL_IP_ADDR(addr)) { + ep->class = EPD_IP; + set_ip_epdisc(ep, addr); + return 1; + } + } + } + + return 0; +} + +/* + * epdisc_to_str - make a printable string from an endpoint discriminator. + */ + +static char *endp_class_names[] = { + "null", "local", "IP", "MAC", "magic", "phone" +}; + +char * +epdisc_to_str(ep) + struct epdisc *ep; +{ + static char str[MAX_ENDP_LEN*3+8]; + u_char *p = ep->value; + int i, mask = 0; + char *q, c, c2; + + if (ep->class == EPD_NULL && ep->length == 0) + return "null"; + if (ep->class == EPD_IP && ep->length == 4) { + u32_t addr; + + GETLONG(addr, p); + slprintf(str, sizeof(str), "IP:%I", htonl(addr)); + return str; + } + + c = ':'; + c2 = '.'; + if (ep->class == EPD_MAC && ep->length == 6) + c2 = ':'; + else if (ep->class == EPD_MAGIC && (ep->length % 4) == 0) + mask = 3; + q = str; + if (ep->class <= EPD_PHONENUM) + q += slprintf(q, sizeof(str)-1, "%s", + endp_class_names[ep->class]); + else + q += slprintf(q, sizeof(str)-1, "%d", ep->class); + c = ':'; + for (i = 0; i < ep->length && i < MAX_ENDP_LEN; ++i) { + if ((i & mask) == 0) { + *q++ = c; + c = c2; + } + q += slprintf(q, str + sizeof(str) - q, "%.2x", ep->value[i]); + } + return str; +} + +static int hexc_val(int c) +{ + if (c >= 'a') + return c - 'a' + 10; + if (c >= 'A') + return c - 'A' + 10; + return c - '0'; +} + +int +str_to_epdisc(ep, str) + struct epdisc *ep; + char *str; +{ + int i, l; + char *p, *endp; + + for (i = EPD_NULL; i <= EPD_PHONENUM; ++i) { + int sl = strlen(endp_class_names[i]); + if (strncasecmp(str, endp_class_names[i], sl) == 0) { + str += sl; + break; + } + } + if (i > EPD_PHONENUM) { + /* not a class name, try a decimal class number */ + i = strtol(str, &endp, 10); + if (endp == str) + return 0; /* can't parse class number */ + str = endp; + } + ep->class = i; + if (*str == 0) { + ep->length = 0; + return 1; + } + if (*str != ':' && *str != '.') + return 0; + ++str; + + if (i == EPD_IP) { + u32_t addr; + i = parse_dotted_ip(str, &addr); + if (i == 0 || str[i] != 0) + return 0; + set_ip_epdisc(ep, addr); + return 1; + } + if (i == EPD_MAC && get_if_hwaddr(ep->value, str) >= 0) { + ep->length = 6; + return 1; + } + + p = str; + for (l = 0; l < MAX_ENDP_LEN; ++l) { + if (*str == 0) + break; + if (p <= str) + for (p = str; isxdigit(*p); ++p) + ; + i = p - str; + if (i == 0) + return 0; + ep->value[l] = hexc_val(*str++); + if ((i & 1) == 0) + ep->value[l] = (ep->value[l] << 4) + hexc_val(*str++); + if (*str == ':' || *str == '.') + ++str; + } + if (*str != 0 || (ep->class == EPD_MAC && l != 6)) + return 0; + ep->length = l; + return 1; +} + +#endif /* PPP_SUPPORT && HAVE_MULTILINK */ diff --git a/components/lwip/netif/ppp/polarssl/README b/components/lwip/netif/ppp/polarssl/README new file mode 100755 index 0000000000..ff6e44db21 --- /dev/null +++ b/components/lwip/netif/ppp/polarssl/README @@ -0,0 +1,33 @@ +About PolarSSL files into lwIP PPP support +------------------------------------------ + +This folder contains some files fetched from the latest BSD release of +the PolarSSL project for ciphers and encryption methods we need for lwIP +PPP support. + +The PolarSSL files were cleaned to contain only the necessary struct +fields and functions needed for lwIP. + + +The PolarSSL API was not changed at all, so if you are already using +PolarSSL you can choose to skip the compilation of the included PolarSSL +library into lwIP: + +The following defines are available for flexibility: + +LWIP_INCLUDED_POLARSSL_MD4 ; Use lwIP internal PolarSSL for MD4 +LWIP_INCLUDED_POLARSSL_MD5 ; Use lwIP internal PolarSSL for MD5 +LWIP_INCLUDED_POLARSSL_SHA1 ; Use lwIP internal PolarSSL for SHA1 +LWIP_INCLUDED_POLARSSL_DES ; Use lwIP internal PolarSSL for DES +LWIP_INCLUDED_POLARSSL_ARC4 ; Use lwIP internal PolarSSL for ARC4 + +If set (=1), the default if required by another enabled PPP feature unless +explicitly set to 0, using included lwIP PolarSSL. + +If clear (=0), not needed or using external PolarSSL. + +Beware of the stack requirements which can be a lot larger if you are not +using our cleaned PolarSSL library. + + +PolarSSL project website: http://polarssl.org/ diff --git a/components/lwip/netif/ppp/polarssl/arc4.c b/components/lwip/netif/ppp/polarssl/arc4.c new file mode 100755 index 0000000000..ca5000e7fe --- /dev/null +++ b/components/lwip/netif/ppp/polarssl/arc4.c @@ -0,0 +1,101 @@ +/* + * An implementation of the ARCFOUR algorithm + * + * Based on XySSL: Copyright (C) 2006-2008 Christophe Devine + * + * Copyright (C) 2009 Paul Bakker + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the names of PolarSSL or XySSL nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED + * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +/* + * The ARCFOUR algorithm was publicly disclosed on 94/09. + * + * http://groups.google.com/group/sci.crypt/msg/10a300c9d21afca0 + */ + +#include "lwip/opt.h" +#if PPP_SUPPORT && LWIP_INCLUDED_POLARSSL_ARC4 + +#include "netif/ppp/polarssl/arc4.h" +/* + * ARC4 key schedule + */ +void arc4_setup( arc4_context *ctx, unsigned char *key, int keylen ) +{ + int i, j, k, a; + unsigned char *m; + + ctx->x = 0; + ctx->y = 0; + m = ctx->m; + + for( i = 0; i < 256; i++ ) + m[i] = (unsigned char) i; + + j = k = 0; + + for( i = 0; i < 256; i++, k++ ) + { + if( k >= keylen ) k = 0; + + a = m[i]; + j = ( j + a + key[k] ) & 0xFF; + m[i] = m[j]; + m[j] = (unsigned char) a; + } +} + +/* + * ARC4 cipher function + */ +void arc4_crypt( arc4_context *ctx, unsigned char *buf, int buflen ) +{ + int i, x, y, a, b; + unsigned char *m; + + x = ctx->x; + y = ctx->y; + m = ctx->m; + + for( i = 0; i < buflen; i++ ) + { + x = ( x + 1 ) & 0xFF; a = m[x]; + y = ( y + a ) & 0xFF; b = m[y]; + + m[x] = (unsigned char) b; + m[y] = (unsigned char) a; + + buf[i] = (unsigned char) + ( buf[i] ^ m[(unsigned char)( a + b )] ); + } + + ctx->x = x; + ctx->y = y; +} + +#endif /* PPP_SUPPORT && LWIP_INCLUDED_POLARSSL_DES */ diff --git a/components/lwip/netif/ppp/polarssl/des.c b/components/lwip/netif/ppp/polarssl/des.c new file mode 100755 index 0000000000..0d6af84961 --- /dev/null +++ b/components/lwip/netif/ppp/polarssl/des.c @@ -0,0 +1,422 @@ +/* + * FIPS-46-3 compliant Triple-DES implementation + * + * Based on XySSL: Copyright (C) 2006-2008 Christophe Devine + * + * Copyright (C) 2009 Paul Bakker + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the names of PolarSSL or XySSL nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED + * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +/* + * DES, on which TDES is based, was originally designed by Horst Feistel + * at IBM in 1974, and was adopted as a standard by NIST (formerly NBS). + * + * http://csrc.nist.gov/publications/fips/fips46-3/fips46-3.pdf + */ + +#include "lwip/opt.h" +#if PPP_SUPPORT && LWIP_INCLUDED_POLARSSL_DES + +#include "netif/ppp/polarssl/des.h" + +/* + * 32-bit integer manipulation macros (big endian) + */ +#ifndef GET_ULONG_BE +#define GET_ULONG_BE(n,b,i) \ +{ \ + (n) = ( (unsigned long) (b)[(i) ] << 24 ) \ + | ( (unsigned long) (b)[(i) + 1] << 16 ) \ + | ( (unsigned long) (b)[(i) + 2] << 8 ) \ + | ( (unsigned long) (b)[(i) + 3] ); \ +} +#endif + +#ifndef PUT_ULONG_BE +#define PUT_ULONG_BE(n,b,i) \ +{ \ + (b)[(i) ] = (unsigned char) ( (n) >> 24 ); \ + (b)[(i) + 1] = (unsigned char) ( (n) >> 16 ); \ + (b)[(i) + 2] = (unsigned char) ( (n) >> 8 ); \ + (b)[(i) + 3] = (unsigned char) ( (n) ); \ +} +#endif + +/* + * Expanded DES S-boxes + */ +static const unsigned long SB1[64] = +{ + 0x01010400, 0x00000000, 0x00010000, 0x01010404, + 0x01010004, 0x00010404, 0x00000004, 0x00010000, + 0x00000400, 0x01010400, 0x01010404, 0x00000400, + 0x01000404, 0x01010004, 0x01000000, 0x00000004, + 0x00000404, 0x01000400, 0x01000400, 0x00010400, + 0x00010400, 0x01010000, 0x01010000, 0x01000404, + 0x00010004, 0x01000004, 0x01000004, 0x00010004, + 0x00000000, 0x00000404, 0x00010404, 0x01000000, + 0x00010000, 0x01010404, 0x00000004, 0x01010000, + 0x01010400, 0x01000000, 0x01000000, 0x00000400, + 0x01010004, 0x00010000, 0x00010400, 0x01000004, + 0x00000400, 0x00000004, 0x01000404, 0x00010404, + 0x01010404, 0x00010004, 0x01010000, 0x01000404, + 0x01000004, 0x00000404, 0x00010404, 0x01010400, + 0x00000404, 0x01000400, 0x01000400, 0x00000000, + 0x00010004, 0x00010400, 0x00000000, 0x01010004 +}; + +static const unsigned long SB2[64] = +{ + 0x80108020, 0x80008000, 0x00008000, 0x00108020, + 0x00100000, 0x00000020, 0x80100020, 0x80008020, + 0x80000020, 0x80108020, 0x80108000, 0x80000000, + 0x80008000, 0x00100000, 0x00000020, 0x80100020, + 0x00108000, 0x00100020, 0x80008020, 0x00000000, + 0x80000000, 0x00008000, 0x00108020, 0x80100000, + 0x00100020, 0x80000020, 0x00000000, 0x00108000, + 0x00008020, 0x80108000, 0x80100000, 0x00008020, + 0x00000000, 0x00108020, 0x80100020, 0x00100000, + 0x80008020, 0x80100000, 0x80108000, 0x00008000, + 0x80100000, 0x80008000, 0x00000020, 0x80108020, + 0x00108020, 0x00000020, 0x00008000, 0x80000000, + 0x00008020, 0x80108000, 0x00100000, 0x80000020, + 0x00100020, 0x80008020, 0x80000020, 0x00100020, + 0x00108000, 0x00000000, 0x80008000, 0x00008020, + 0x80000000, 0x80100020, 0x80108020, 0x00108000 +}; + +static const unsigned long SB3[64] = +{ + 0x00000208, 0x08020200, 0x00000000, 0x08020008, + 0x08000200, 0x00000000, 0x00020208, 0x08000200, + 0x00020008, 0x08000008, 0x08000008, 0x00020000, + 0x08020208, 0x00020008, 0x08020000, 0x00000208, + 0x08000000, 0x00000008, 0x08020200, 0x00000200, + 0x00020200, 0x08020000, 0x08020008, 0x00020208, + 0x08000208, 0x00020200, 0x00020000, 0x08000208, + 0x00000008, 0x08020208, 0x00000200, 0x08000000, + 0x08020200, 0x08000000, 0x00020008, 0x00000208, + 0x00020000, 0x08020200, 0x08000200, 0x00000000, + 0x00000200, 0x00020008, 0x08020208, 0x08000200, + 0x08000008, 0x00000200, 0x00000000, 0x08020008, + 0x08000208, 0x00020000, 0x08000000, 0x08020208, + 0x00000008, 0x00020208, 0x00020200, 0x08000008, + 0x08020000, 0x08000208, 0x00000208, 0x08020000, + 0x00020208, 0x00000008, 0x08020008, 0x00020200 +}; + +static const unsigned long SB4[64] = +{ + 0x00802001, 0x00002081, 0x00002081, 0x00000080, + 0x00802080, 0x00800081, 0x00800001, 0x00002001, + 0x00000000, 0x00802000, 0x00802000, 0x00802081, + 0x00000081, 0x00000000, 0x00800080, 0x00800001, + 0x00000001, 0x00002000, 0x00800000, 0x00802001, + 0x00000080, 0x00800000, 0x00002001, 0x00002080, + 0x00800081, 0x00000001, 0x00002080, 0x00800080, + 0x00002000, 0x00802080, 0x00802081, 0x00000081, + 0x00800080, 0x00800001, 0x00802000, 0x00802081, + 0x00000081, 0x00000000, 0x00000000, 0x00802000, + 0x00002080, 0x00800080, 0x00800081, 0x00000001, + 0x00802001, 0x00002081, 0x00002081, 0x00000080, + 0x00802081, 0x00000081, 0x00000001, 0x00002000, + 0x00800001, 0x00002001, 0x00802080, 0x00800081, + 0x00002001, 0x00002080, 0x00800000, 0x00802001, + 0x00000080, 0x00800000, 0x00002000, 0x00802080 +}; + +static const unsigned long SB5[64] = +{ + 0x00000100, 0x02080100, 0x02080000, 0x42000100, + 0x00080000, 0x00000100, 0x40000000, 0x02080000, + 0x40080100, 0x00080000, 0x02000100, 0x40080100, + 0x42000100, 0x42080000, 0x00080100, 0x40000000, + 0x02000000, 0x40080000, 0x40080000, 0x00000000, + 0x40000100, 0x42080100, 0x42080100, 0x02000100, + 0x42080000, 0x40000100, 0x00000000, 0x42000000, + 0x02080100, 0x02000000, 0x42000000, 0x00080100, + 0x00080000, 0x42000100, 0x00000100, 0x02000000, + 0x40000000, 0x02080000, 0x42000100, 0x40080100, + 0x02000100, 0x40000000, 0x42080000, 0x02080100, + 0x40080100, 0x00000100, 0x02000000, 0x42080000, + 0x42080100, 0x00080100, 0x42000000, 0x42080100, + 0x02080000, 0x00000000, 0x40080000, 0x42000000, + 0x00080100, 0x02000100, 0x40000100, 0x00080000, + 0x00000000, 0x40080000, 0x02080100, 0x40000100 +}; + +static const unsigned long SB6[64] = +{ + 0x20000010, 0x20400000, 0x00004000, 0x20404010, + 0x20400000, 0x00000010, 0x20404010, 0x00400000, + 0x20004000, 0x00404010, 0x00400000, 0x20000010, + 0x00400010, 0x20004000, 0x20000000, 0x00004010, + 0x00000000, 0x00400010, 0x20004010, 0x00004000, + 0x00404000, 0x20004010, 0x00000010, 0x20400010, + 0x20400010, 0x00000000, 0x00404010, 0x20404000, + 0x00004010, 0x00404000, 0x20404000, 0x20000000, + 0x20004000, 0x00000010, 0x20400010, 0x00404000, + 0x20404010, 0x00400000, 0x00004010, 0x20000010, + 0x00400000, 0x20004000, 0x20000000, 0x00004010, + 0x20000010, 0x20404010, 0x00404000, 0x20400000, + 0x00404010, 0x20404000, 0x00000000, 0x20400010, + 0x00000010, 0x00004000, 0x20400000, 0x00404010, + 0x00004000, 0x00400010, 0x20004010, 0x00000000, + 0x20404000, 0x20000000, 0x00400010, 0x20004010 +}; + +static const unsigned long SB7[64] = +{ + 0x00200000, 0x04200002, 0x04000802, 0x00000000, + 0x00000800, 0x04000802, 0x00200802, 0x04200800, + 0x04200802, 0x00200000, 0x00000000, 0x04000002, + 0x00000002, 0x04000000, 0x04200002, 0x00000802, + 0x04000800, 0x00200802, 0x00200002, 0x04000800, + 0x04000002, 0x04200000, 0x04200800, 0x00200002, + 0x04200000, 0x00000800, 0x00000802, 0x04200802, + 0x00200800, 0x00000002, 0x04000000, 0x00200800, + 0x04000000, 0x00200800, 0x00200000, 0x04000802, + 0x04000802, 0x04200002, 0x04200002, 0x00000002, + 0x00200002, 0x04000000, 0x04000800, 0x00200000, + 0x04200800, 0x00000802, 0x00200802, 0x04200800, + 0x00000802, 0x04000002, 0x04200802, 0x04200000, + 0x00200800, 0x00000000, 0x00000002, 0x04200802, + 0x00000000, 0x00200802, 0x04200000, 0x00000800, + 0x04000002, 0x04000800, 0x00000800, 0x00200002 +}; + +static const unsigned long SB8[64] = +{ + 0x10001040, 0x00001000, 0x00040000, 0x10041040, + 0x10000000, 0x10001040, 0x00000040, 0x10000000, + 0x00040040, 0x10040000, 0x10041040, 0x00041000, + 0x10041000, 0x00041040, 0x00001000, 0x00000040, + 0x10040000, 0x10000040, 0x10001000, 0x00001040, + 0x00041000, 0x00040040, 0x10040040, 0x10041000, + 0x00001040, 0x00000000, 0x00000000, 0x10040040, + 0x10000040, 0x10001000, 0x00041040, 0x00040000, + 0x00041040, 0x00040000, 0x10041000, 0x00001000, + 0x00000040, 0x10040040, 0x00001000, 0x00041040, + 0x10001000, 0x00000040, 0x10000040, 0x10040000, + 0x10040040, 0x10000000, 0x00040000, 0x10001040, + 0x00000000, 0x10041040, 0x00040040, 0x10000040, + 0x10040000, 0x10001000, 0x10001040, 0x00000000, + 0x10041040, 0x00041000, 0x00041000, 0x00001040, + 0x00001040, 0x00040040, 0x10000000, 0x10041000 +}; + +/* + * PC1: left and right halves bit-swap + */ +static const unsigned long LHs[16] = +{ + 0x00000000, 0x00000001, 0x00000100, 0x00000101, + 0x00010000, 0x00010001, 0x00010100, 0x00010101, + 0x01000000, 0x01000001, 0x01000100, 0x01000101, + 0x01010000, 0x01010001, 0x01010100, 0x01010101 +}; + +static const unsigned long RHs[16] = +{ + 0x00000000, 0x01000000, 0x00010000, 0x01010000, + 0x00000100, 0x01000100, 0x00010100, 0x01010100, + 0x00000001, 0x01000001, 0x00010001, 0x01010001, + 0x00000101, 0x01000101, 0x00010101, 0x01010101, +}; + +/* + * Initial Permutation macro + */ +#define DES_IP(X,Y) \ +{ \ + T = ((X >> 4) ^ Y) & 0x0F0F0F0F; Y ^= T; X ^= (T << 4); \ + T = ((X >> 16) ^ Y) & 0x0000FFFF; Y ^= T; X ^= (T << 16); \ + T = ((Y >> 2) ^ X) & 0x33333333; X ^= T; Y ^= (T << 2); \ + T = ((Y >> 8) ^ X) & 0x00FF00FF; X ^= T; Y ^= (T << 8); \ + Y = ((Y << 1) | (Y >> 31)) & 0xFFFFFFFF; \ + T = (X ^ Y) & 0xAAAAAAAA; Y ^= T; X ^= T; \ + X = ((X << 1) | (X >> 31)) & 0xFFFFFFFF; \ +} + +/* + * Final Permutation macro + */ +#define DES_FP(X,Y) \ +{ \ + X = ((X << 31) | (X >> 1)) & 0xFFFFFFFF; \ + T = (X ^ Y) & 0xAAAAAAAA; X ^= T; Y ^= T; \ + Y = ((Y << 31) | (Y >> 1)) & 0xFFFFFFFF; \ + T = ((Y >> 8) ^ X) & 0x00FF00FF; X ^= T; Y ^= (T << 8); \ + T = ((Y >> 2) ^ X) & 0x33333333; X ^= T; Y ^= (T << 2); \ + T = ((X >> 16) ^ Y) & 0x0000FFFF; Y ^= T; X ^= (T << 16); \ + T = ((X >> 4) ^ Y) & 0x0F0F0F0F; Y ^= T; X ^= (T << 4); \ +} + +/* + * DES round macro + */ +#define DES_ROUND(X,Y) \ +{ \ + T = *SK++ ^ X; \ + Y ^= SB8[ (T ) & 0x3F ] ^ \ + SB6[ (T >> 8) & 0x3F ] ^ \ + SB4[ (T >> 16) & 0x3F ] ^ \ + SB2[ (T >> 24) & 0x3F ]; \ + \ + T = *SK++ ^ ((X << 28) | (X >> 4)); \ + Y ^= SB7[ (T ) & 0x3F ] ^ \ + SB5[ (T >> 8) & 0x3F ] ^ \ + SB3[ (T >> 16) & 0x3F ] ^ \ + SB1[ (T >> 24) & 0x3F ]; \ +} + +#define SWAP(a,b) { unsigned long t = a; a = b; b = t; t = 0; } + +static void des_setkey( unsigned long SK[32], unsigned char key[8] ) +{ + int i; + unsigned long X, Y, T; + + GET_ULONG_BE( X, key, 0 ); + GET_ULONG_BE( Y, key, 4 ); + + /* + * Permuted Choice 1 + */ + T = ((Y >> 4) ^ X) & 0x0F0F0F0F; X ^= T; Y ^= (T << 4); + T = ((Y ) ^ X) & 0x10101010; X ^= T; Y ^= (T ); + + X = (LHs[ (X ) & 0xF] << 3) | (LHs[ (X >> 8) & 0xF ] << 2) + | (LHs[ (X >> 16) & 0xF] << 1) | (LHs[ (X >> 24) & 0xF ] ) + | (LHs[ (X >> 5) & 0xF] << 7) | (LHs[ (X >> 13) & 0xF ] << 6) + | (LHs[ (X >> 21) & 0xF] << 5) | (LHs[ (X >> 29) & 0xF ] << 4); + + Y = (RHs[ (Y >> 1) & 0xF] << 3) | (RHs[ (Y >> 9) & 0xF ] << 2) + | (RHs[ (Y >> 17) & 0xF] << 1) | (RHs[ (Y >> 25) & 0xF ] ) + | (RHs[ (Y >> 4) & 0xF] << 7) | (RHs[ (Y >> 12) & 0xF ] << 6) + | (RHs[ (Y >> 20) & 0xF] << 5) | (RHs[ (Y >> 28) & 0xF ] << 4); + + X &= 0x0FFFFFFF; + Y &= 0x0FFFFFFF; + + /* + * calculate subkeys + */ + for( i = 0; i < 16; i++ ) + { + if( i < 2 || i == 8 || i == 15 ) + { + X = ((X << 1) | (X >> 27)) & 0x0FFFFFFF; + Y = ((Y << 1) | (Y >> 27)) & 0x0FFFFFFF; + } + else + { + X = ((X << 2) | (X >> 26)) & 0x0FFFFFFF; + Y = ((Y << 2) | (Y >> 26)) & 0x0FFFFFFF; + } + + *SK++ = ((X << 4) & 0x24000000) | ((X << 28) & 0x10000000) + | ((X << 14) & 0x08000000) | ((X << 18) & 0x02080000) + | ((X << 6) & 0x01000000) | ((X << 9) & 0x00200000) + | ((X >> 1) & 0x00100000) | ((X << 10) & 0x00040000) + | ((X << 2) & 0x00020000) | ((X >> 10) & 0x00010000) + | ((Y >> 13) & 0x00002000) | ((Y >> 4) & 0x00001000) + | ((Y << 6) & 0x00000800) | ((Y >> 1) & 0x00000400) + | ((Y >> 14) & 0x00000200) | ((Y ) & 0x00000100) + | ((Y >> 5) & 0x00000020) | ((Y >> 10) & 0x00000010) + | ((Y >> 3) & 0x00000008) | ((Y >> 18) & 0x00000004) + | ((Y >> 26) & 0x00000002) | ((Y >> 24) & 0x00000001); + + *SK++ = ((X << 15) & 0x20000000) | ((X << 17) & 0x10000000) + | ((X << 10) & 0x08000000) | ((X << 22) & 0x04000000) + | ((X >> 2) & 0x02000000) | ((X << 1) & 0x01000000) + | ((X << 16) & 0x00200000) | ((X << 11) & 0x00100000) + | ((X << 3) & 0x00080000) | ((X >> 6) & 0x00040000) + | ((X << 15) & 0x00020000) | ((X >> 4) & 0x00010000) + | ((Y >> 2) & 0x00002000) | ((Y << 8) & 0x00001000) + | ((Y >> 14) & 0x00000808) | ((Y >> 9) & 0x00000400) + | ((Y ) & 0x00000200) | ((Y << 7) & 0x00000100) + | ((Y >> 7) & 0x00000020) | ((Y >> 3) & 0x00000011) + | ((Y << 2) & 0x00000004) | ((Y >> 21) & 0x00000002); + } +} + +/* + * DES key schedule (56-bit, encryption) + */ +void des_setkey_enc( des_context *ctx, unsigned char key[8] ) +{ + des_setkey( ctx->sk, key ); +} + +/* + * DES key schedule (56-bit, decryption) + */ +void des_setkey_dec( des_context *ctx, unsigned char key[8] ) +{ + int i; + + des_setkey( ctx->sk, key ); + + for( i = 0; i < 16; i += 2 ) + { + SWAP( ctx->sk[i ], ctx->sk[30 - i] ); + SWAP( ctx->sk[i + 1], ctx->sk[31 - i] ); + } +} + +/* + * DES-ECB block encryption/decryption + */ +void des_crypt_ecb( des_context *ctx, + const unsigned char input[8], + unsigned char output[8] ) +{ + int i; + unsigned long X, Y, T, *SK; + + SK = ctx->sk; + + GET_ULONG_BE( X, input, 0 ); + GET_ULONG_BE( Y, input, 4 ); + + DES_IP( X, Y ); + + for( i = 0; i < 8; i++ ) + { + DES_ROUND( Y, X ); + DES_ROUND( X, Y ); + } + + DES_FP( Y, X ); + + PUT_ULONG_BE( Y, output, 0 ); + PUT_ULONG_BE( X, output, 4 ); +} + +#endif /* PPP_SUPPORT && LWIP_INCLUDED_POLARSSL_DES */ diff --git a/components/lwip/netif/ppp/polarssl/md4.c b/components/lwip/netif/ppp/polarssl/md4.c new file mode 100755 index 0000000000..b134cba924 --- /dev/null +++ b/components/lwip/netif/ppp/polarssl/md4.c @@ -0,0 +1,281 @@ +/* + * RFC 1186/1320 compliant MD4 implementation + * + * Based on XySSL: Copyright (C) 2006-2008 Christophe Devine + * + * Copyright (C) 2009 Paul Bakker + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the names of PolarSSL or XySSL nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED + * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +/* + * The MD4 algorithm was designed by Ron Rivest in 1990. + * + * http://www.ietf.org/rfc/rfc1186.txt + * http://www.ietf.org/rfc/rfc1320.txt + */ + +#include "lwip/opt.h" +#if PPP_SUPPORT && LWIP_INCLUDED_POLARSSL_MD4 + +#include "netif/ppp/polarssl/md4.h" + +#include + +/* + * 32-bit integer manipulation macros (little endian) + */ +#ifndef GET_ULONG_LE +#define GET_ULONG_LE(n,b,i) \ +{ \ + (n) = ( (unsigned long) (b)[(i) ] ) \ + | ( (unsigned long) (b)[(i) + 1] << 8 ) \ + | ( (unsigned long) (b)[(i) + 2] << 16 ) \ + | ( (unsigned long) (b)[(i) + 3] << 24 ); \ +} +#endif + +#ifndef PUT_ULONG_LE +#define PUT_ULONG_LE(n,b,i) \ +{ \ + (b)[(i) ] = (unsigned char) ( (n) ); \ + (b)[(i) + 1] = (unsigned char) ( (n) >> 8 ); \ + (b)[(i) + 2] = (unsigned char) ( (n) >> 16 ); \ + (b)[(i) + 3] = (unsigned char) ( (n) >> 24 ); \ +} +#endif + +/* + * MD4 context setup + */ +void md4_starts( md4_context *ctx ) +{ + ctx->total[0] = 0; + ctx->total[1] = 0; + + ctx->state[0] = 0x67452301; + ctx->state[1] = 0xEFCDAB89; + ctx->state[2] = 0x98BADCFE; + ctx->state[3] = 0x10325476; +} + +static void md4_process( md4_context *ctx, const unsigned char data[64] ) +{ + unsigned long X[16], A, B, C, D; + + GET_ULONG_LE( X[ 0], data, 0 ); + GET_ULONG_LE( X[ 1], data, 4 ); + GET_ULONG_LE( X[ 2], data, 8 ); + GET_ULONG_LE( X[ 3], data, 12 ); + GET_ULONG_LE( X[ 4], data, 16 ); + GET_ULONG_LE( X[ 5], data, 20 ); + GET_ULONG_LE( X[ 6], data, 24 ); + GET_ULONG_LE( X[ 7], data, 28 ); + GET_ULONG_LE( X[ 8], data, 32 ); + GET_ULONG_LE( X[ 9], data, 36 ); + GET_ULONG_LE( X[10], data, 40 ); + GET_ULONG_LE( X[11], data, 44 ); + GET_ULONG_LE( X[12], data, 48 ); + GET_ULONG_LE( X[13], data, 52 ); + GET_ULONG_LE( X[14], data, 56 ); + GET_ULONG_LE( X[15], data, 60 ); + +#define S(x,n) ((x << n) | ((x & 0xFFFFFFFF) >> (32 - n))) + + A = ctx->state[0]; + B = ctx->state[1]; + C = ctx->state[2]; + D = ctx->state[3]; + +#define F(x, y, z) ((x & y) | ((~x) & z)) +#define P(a,b,c,d,x,s) { a += F(b,c,d) + x; a = S(a,s); } + + P( A, B, C, D, X[ 0], 3 ); + P( D, A, B, C, X[ 1], 7 ); + P( C, D, A, B, X[ 2], 11 ); + P( B, C, D, A, X[ 3], 19 ); + P( A, B, C, D, X[ 4], 3 ); + P( D, A, B, C, X[ 5], 7 ); + P( C, D, A, B, X[ 6], 11 ); + P( B, C, D, A, X[ 7], 19 ); + P( A, B, C, D, X[ 8], 3 ); + P( D, A, B, C, X[ 9], 7 ); + P( C, D, A, B, X[10], 11 ); + P( B, C, D, A, X[11], 19 ); + P( A, B, C, D, X[12], 3 ); + P( D, A, B, C, X[13], 7 ); + P( C, D, A, B, X[14], 11 ); + P( B, C, D, A, X[15], 19 ); + +#undef P +#undef F + +#define F(x,y,z) ((x & y) | (x & z) | (y & z)) +#define P(a,b,c,d,x,s) { a += F(b,c,d) + x + 0x5A827999; a = S(a,s); } + + P( A, B, C, D, X[ 0], 3 ); + P( D, A, B, C, X[ 4], 5 ); + P( C, D, A, B, X[ 8], 9 ); + P( B, C, D, A, X[12], 13 ); + P( A, B, C, D, X[ 1], 3 ); + P( D, A, B, C, X[ 5], 5 ); + P( C, D, A, B, X[ 9], 9 ); + P( B, C, D, A, X[13], 13 ); + P( A, B, C, D, X[ 2], 3 ); + P( D, A, B, C, X[ 6], 5 ); + P( C, D, A, B, X[10], 9 ); + P( B, C, D, A, X[14], 13 ); + P( A, B, C, D, X[ 3], 3 ); + P( D, A, B, C, X[ 7], 5 ); + P( C, D, A, B, X[11], 9 ); + P( B, C, D, A, X[15], 13 ); + +#undef P +#undef F + +#define F(x,y,z) (x ^ y ^ z) +#define P(a,b,c,d,x,s) { a += F(b,c,d) + x + 0x6ED9EBA1; a = S(a,s); } + + P( A, B, C, D, X[ 0], 3 ); + P( D, A, B, C, X[ 8], 9 ); + P( C, D, A, B, X[ 4], 11 ); + P( B, C, D, A, X[12], 15 ); + P( A, B, C, D, X[ 2], 3 ); + P( D, A, B, C, X[10], 9 ); + P( C, D, A, B, X[ 6], 11 ); + P( B, C, D, A, X[14], 15 ); + P( A, B, C, D, X[ 1], 3 ); + P( D, A, B, C, X[ 9], 9 ); + P( C, D, A, B, X[ 5], 11 ); + P( B, C, D, A, X[13], 15 ); + P( A, B, C, D, X[ 3], 3 ); + P( D, A, B, C, X[11], 9 ); + P( C, D, A, B, X[ 7], 11 ); + P( B, C, D, A, X[15], 15 ); + +#undef F +#undef P + + ctx->state[0] += A; + ctx->state[1] += B; + ctx->state[2] += C; + ctx->state[3] += D; +} + +/* + * MD4 process buffer + */ +void md4_update( md4_context *ctx, const unsigned char *input, int ilen ) +{ + int fill; + unsigned long left; + + if( ilen <= 0 ) + return; + + left = ctx->total[0] & 0x3F; + fill = 64 - left; + + ctx->total[0] += ilen; + ctx->total[0] &= 0xFFFFFFFF; + + if( ctx->total[0] < (unsigned long) ilen ) + ctx->total[1]++; + + if( left && ilen >= fill ) + { + MEMCPY( (void *) (ctx->buffer + left), + input, fill ); + md4_process( ctx, ctx->buffer ); + input += fill; + ilen -= fill; + left = 0; + } + + while( ilen >= 64 ) + { + md4_process( ctx, input ); + input += 64; + ilen -= 64; + } + + if( ilen > 0 ) + { + MEMCPY( (void *) (ctx->buffer + left), + input, ilen ); + } +} + +static const unsigned char md4_padding[64] = +{ + 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +/* + * MD4 final digest + */ +void md4_finish( md4_context *ctx, unsigned char output[16] ) +{ + unsigned long last, padn; + unsigned long high, low; + unsigned char msglen[8]; + + high = ( ctx->total[0] >> 29 ) + | ( ctx->total[1] << 3 ); + low = ( ctx->total[0] << 3 ); + + PUT_ULONG_LE( low, msglen, 0 ); + PUT_ULONG_LE( high, msglen, 4 ); + + last = ctx->total[0] & 0x3F; + padn = ( last < 56 ) ? ( 56 - last ) : ( 120 - last ); + + md4_update( ctx, md4_padding, padn ); + md4_update( ctx, msglen, 8 ); + + PUT_ULONG_LE( ctx->state[0], output, 0 ); + PUT_ULONG_LE( ctx->state[1], output, 4 ); + PUT_ULONG_LE( ctx->state[2], output, 8 ); + PUT_ULONG_LE( ctx->state[3], output, 12 ); +} + +/* + * output = MD4( input buffer ) + */ +void md4( unsigned char *input, int ilen, unsigned char output[16] ) +{ + md4_context ctx; + + md4_starts( &ctx ); + md4_update( &ctx, input, ilen ); + md4_finish( &ctx, output ); +} + +#endif /* PPP_SUPPORT && LWIP_INCLUDED_POLARSSL_MD4 */ diff --git a/components/lwip/netif/ppp/polarssl/md5.c b/components/lwip/netif/ppp/polarssl/md5.c new file mode 100755 index 0000000000..ba103c4c25 --- /dev/null +++ b/components/lwip/netif/ppp/polarssl/md5.c @@ -0,0 +1,300 @@ +/* + * RFC 1321 compliant MD5 implementation + * + * Based on XySSL: Copyright (C) 2006-2008 Christophe Devine + * + * Copyright (C) 2009 Paul Bakker + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the names of PolarSSL or XySSL nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED + * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +/* + * The MD5 algorithm was designed by Ron Rivest in 1991. + * + * http://www.ietf.org/rfc/rfc1321.txt + */ + +#include "lwip/opt.h" +#if PPP_SUPPORT && LWIP_INCLUDED_POLARSSL_MD5 + +#include "netif/ppp/polarssl/md5.h" + +#include + +/* + * 32-bit integer manipulation macros (little endian) + */ +#ifndef GET_ULONG_LE +#define GET_ULONG_LE(n,b,i) \ +{ \ + (n) = ( (unsigned long) (b)[(i) ] ) \ + | ( (unsigned long) (b)[(i) + 1] << 8 ) \ + | ( (unsigned long) (b)[(i) + 2] << 16 ) \ + | ( (unsigned long) (b)[(i) + 3] << 24 ); \ +} +#endif + +#ifndef PUT_ULONG_LE +#define PUT_ULONG_LE(n,b,i) \ +{ \ + (b)[(i) ] = (unsigned char) ( (n) ); \ + (b)[(i) + 1] = (unsigned char) ( (n) >> 8 ); \ + (b)[(i) + 2] = (unsigned char) ( (n) >> 16 ); \ + (b)[(i) + 3] = (unsigned char) ( (n) >> 24 ); \ +} +#endif + +/* + * MD5 context setup + */ +void md5_starts( md5_context *ctx ) +{ + ctx->total[0] = 0; + ctx->total[1] = 0; + + ctx->state[0] = 0x67452301; + ctx->state[1] = 0xEFCDAB89; + ctx->state[2] = 0x98BADCFE; + ctx->state[3] = 0x10325476; +} + +static void md5_process( md5_context *ctx, const unsigned char data[64] ) +{ + unsigned long X[16], A, B, C, D; + + GET_ULONG_LE( X[ 0], data, 0 ); + GET_ULONG_LE( X[ 1], data, 4 ); + GET_ULONG_LE( X[ 2], data, 8 ); + GET_ULONG_LE( X[ 3], data, 12 ); + GET_ULONG_LE( X[ 4], data, 16 ); + GET_ULONG_LE( X[ 5], data, 20 ); + GET_ULONG_LE( X[ 6], data, 24 ); + GET_ULONG_LE( X[ 7], data, 28 ); + GET_ULONG_LE( X[ 8], data, 32 ); + GET_ULONG_LE( X[ 9], data, 36 ); + GET_ULONG_LE( X[10], data, 40 ); + GET_ULONG_LE( X[11], data, 44 ); + GET_ULONG_LE( X[12], data, 48 ); + GET_ULONG_LE( X[13], data, 52 ); + GET_ULONG_LE( X[14], data, 56 ); + GET_ULONG_LE( X[15], data, 60 ); + +#define S(x,n) ((x << n) | ((x & 0xFFFFFFFF) >> (32 - n))) + +#define P(a,b,c,d,k,s,t) \ +{ \ + a += F(b,c,d) + X[k] + t; a = S(a,s) + b; \ +} + + A = ctx->state[0]; + B = ctx->state[1]; + C = ctx->state[2]; + D = ctx->state[3]; + +#define F(x,y,z) (z ^ (x & (y ^ z))) + + P( A, B, C, D, 0, 7, 0xD76AA478 ); + P( D, A, B, C, 1, 12, 0xE8C7B756 ); + P( C, D, A, B, 2, 17, 0x242070DB ); + P( B, C, D, A, 3, 22, 0xC1BDCEEE ); + P( A, B, C, D, 4, 7, 0xF57C0FAF ); + P( D, A, B, C, 5, 12, 0x4787C62A ); + P( C, D, A, B, 6, 17, 0xA8304613 ); + P( B, C, D, A, 7, 22, 0xFD469501 ); + P( A, B, C, D, 8, 7, 0x698098D8 ); + P( D, A, B, C, 9, 12, 0x8B44F7AF ); + P( C, D, A, B, 10, 17, 0xFFFF5BB1 ); + P( B, C, D, A, 11, 22, 0x895CD7BE ); + P( A, B, C, D, 12, 7, 0x6B901122 ); + P( D, A, B, C, 13, 12, 0xFD987193 ); + P( C, D, A, B, 14, 17, 0xA679438E ); + P( B, C, D, A, 15, 22, 0x49B40821 ); + +#undef F + +#define F(x,y,z) (y ^ (z & (x ^ y))) + + P( A, B, C, D, 1, 5, 0xF61E2562 ); + P( D, A, B, C, 6, 9, 0xC040B340 ); + P( C, D, A, B, 11, 14, 0x265E5A51 ); + P( B, C, D, A, 0, 20, 0xE9B6C7AA ); + P( A, B, C, D, 5, 5, 0xD62F105D ); + P( D, A, B, C, 10, 9, 0x02441453 ); + P( C, D, A, B, 15, 14, 0xD8A1E681 ); + P( B, C, D, A, 4, 20, 0xE7D3FBC8 ); + P( A, B, C, D, 9, 5, 0x21E1CDE6 ); + P( D, A, B, C, 14, 9, 0xC33707D6 ); + P( C, D, A, B, 3, 14, 0xF4D50D87 ); + P( B, C, D, A, 8, 20, 0x455A14ED ); + P( A, B, C, D, 13, 5, 0xA9E3E905 ); + P( D, A, B, C, 2, 9, 0xFCEFA3F8 ); + P( C, D, A, B, 7, 14, 0x676F02D9 ); + P( B, C, D, A, 12, 20, 0x8D2A4C8A ); + +#undef F + +#define F(x,y,z) (x ^ y ^ z) + + P( A, B, C, D, 5, 4, 0xFFFA3942 ); + P( D, A, B, C, 8, 11, 0x8771F681 ); + P( C, D, A, B, 11, 16, 0x6D9D6122 ); + P( B, C, D, A, 14, 23, 0xFDE5380C ); + P( A, B, C, D, 1, 4, 0xA4BEEA44 ); + P( D, A, B, C, 4, 11, 0x4BDECFA9 ); + P( C, D, A, B, 7, 16, 0xF6BB4B60 ); + P( B, C, D, A, 10, 23, 0xBEBFBC70 ); + P( A, B, C, D, 13, 4, 0x289B7EC6 ); + P( D, A, B, C, 0, 11, 0xEAA127FA ); + P( C, D, A, B, 3, 16, 0xD4EF3085 ); + P( B, C, D, A, 6, 23, 0x04881D05 ); + P( A, B, C, D, 9, 4, 0xD9D4D039 ); + P( D, A, B, C, 12, 11, 0xE6DB99E5 ); + P( C, D, A, B, 15, 16, 0x1FA27CF8 ); + P( B, C, D, A, 2, 23, 0xC4AC5665 ); + +#undef F + +#define F(x,y,z) (y ^ (x | ~z)) + + P( A, B, C, D, 0, 6, 0xF4292244 ); + P( D, A, B, C, 7, 10, 0x432AFF97 ); + P( C, D, A, B, 14, 15, 0xAB9423A7 ); + P( B, C, D, A, 5, 21, 0xFC93A039 ); + P( A, B, C, D, 12, 6, 0x655B59C3 ); + P( D, A, B, C, 3, 10, 0x8F0CCC92 ); + P( C, D, A, B, 10, 15, 0xFFEFF47D ); + P( B, C, D, A, 1, 21, 0x85845DD1 ); + P( A, B, C, D, 8, 6, 0x6FA87E4F ); + P( D, A, B, C, 15, 10, 0xFE2CE6E0 ); + P( C, D, A, B, 6, 15, 0xA3014314 ); + P( B, C, D, A, 13, 21, 0x4E0811A1 ); + P( A, B, C, D, 4, 6, 0xF7537E82 ); + P( D, A, B, C, 11, 10, 0xBD3AF235 ); + P( C, D, A, B, 2, 15, 0x2AD7D2BB ); + P( B, C, D, A, 9, 21, 0xEB86D391 ); + +#undef F + + ctx->state[0] += A; + ctx->state[1] += B; + ctx->state[2] += C; + ctx->state[3] += D; +} + +/* + * MD5 process buffer + */ +void md5_update( md5_context *ctx, const unsigned char *input, int ilen ) +{ + int fill; + unsigned long left; + + if( ilen <= 0 ) + return; + + left = ctx->total[0] & 0x3F; + fill = 64 - left; + + ctx->total[0] += ilen; + ctx->total[0] &= 0xFFFFFFFF; + + if( ctx->total[0] < (unsigned long) ilen ) + ctx->total[1]++; + + if( left && ilen >= fill ) + { + MEMCPY( (void *) (ctx->buffer + left), + input, fill ); + md5_process( ctx, ctx->buffer ); + input += fill; + ilen -= fill; + left = 0; + } + + while( ilen >= 64 ) + { + md5_process( ctx, input ); + input += 64; + ilen -= 64; + } + + if( ilen > 0 ) + { + MEMCPY( (void *) (ctx->buffer + left), + input, ilen ); + } +} + +static const unsigned char md5_padding[64] = +{ + 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +/* + * MD5 final digest + */ +void md5_finish( md5_context *ctx, unsigned char output[16] ) +{ + unsigned long last, padn; + unsigned long high, low; + unsigned char msglen[8]; + + high = ( ctx->total[0] >> 29 ) + | ( ctx->total[1] << 3 ); + low = ( ctx->total[0] << 3 ); + + PUT_ULONG_LE( low, msglen, 0 ); + PUT_ULONG_LE( high, msglen, 4 ); + + last = ctx->total[0] & 0x3F; + padn = ( last < 56 ) ? ( 56 - last ) : ( 120 - last ); + + md5_update( ctx, md5_padding, padn ); + md5_update( ctx, msglen, 8 ); + + PUT_ULONG_LE( ctx->state[0], output, 0 ); + PUT_ULONG_LE( ctx->state[1], output, 4 ); + PUT_ULONG_LE( ctx->state[2], output, 8 ); + PUT_ULONG_LE( ctx->state[3], output, 12 ); +} + +/* + * output = MD5( input buffer ) + */ +void md5( unsigned char *input, int ilen, unsigned char output[16] ) +{ + md5_context ctx; + + md5_starts( &ctx ); + md5_update( &ctx, input, ilen ); + md5_finish( &ctx, output ); +} + +#endif /* PPP_SUPPORT && LWIP_INCLUDED_POLARSSL_MD5 */ diff --git a/components/lwip/netif/ppp/polarssl/sha1.c b/components/lwip/netif/ppp/polarssl/sha1.c new file mode 100755 index 0000000000..313b756477 --- /dev/null +++ b/components/lwip/netif/ppp/polarssl/sha1.c @@ -0,0 +1,335 @@ +/* + * FIPS-180-1 compliant SHA-1 implementation + * + * Based on XySSL: Copyright (C) 2006-2008 Christophe Devine + * + * Copyright (C) 2009 Paul Bakker + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the names of PolarSSL or XySSL nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED + * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +/* + * The SHA-1 standard was published by NIST in 1993. + * + * http://www.itl.nist.gov/fipspubs/fip180-1.htm + */ + +#include "lwip/opt.h" +#if PPP_SUPPORT && LWIP_INCLUDED_POLARSSL_SHA1 + +#include "netif/ppp/polarssl/sha1.h" + +#include + +/* + * 32-bit integer manipulation macros (big endian) + */ +#ifndef GET_ULONG_BE +#define GET_ULONG_BE(n,b,i) \ +{ \ + (n) = ( (unsigned long) (b)[(i) ] << 24 ) \ + | ( (unsigned long) (b)[(i) + 1] << 16 ) \ + | ( (unsigned long) (b)[(i) + 2] << 8 ) \ + | ( (unsigned long) (b)[(i) + 3] ); \ +} +#endif + +#ifndef PUT_ULONG_BE +#define PUT_ULONG_BE(n,b,i) \ +{ \ + (b)[(i) ] = (unsigned char) ( (n) >> 24 ); \ + (b)[(i) + 1] = (unsigned char) ( (n) >> 16 ); \ + (b)[(i) + 2] = (unsigned char) ( (n) >> 8 ); \ + (b)[(i) + 3] = (unsigned char) ( (n) ); \ +} +#endif + +/* + * SHA-1 context setup + */ +void sha1_starts( sha1_context *ctx ) +{ + ctx->total[0] = 0; + ctx->total[1] = 0; + + ctx->state[0] = 0x67452301; + ctx->state[1] = 0xEFCDAB89; + ctx->state[2] = 0x98BADCFE; + ctx->state[3] = 0x10325476; + ctx->state[4] = 0xC3D2E1F0; +} + +static void sha1_process( sha1_context *ctx, const unsigned char data[64] ) +{ + unsigned long temp, W[16], A, B, C, D, E; + + GET_ULONG_BE( W[ 0], data, 0 ); + GET_ULONG_BE( W[ 1], data, 4 ); + GET_ULONG_BE( W[ 2], data, 8 ); + GET_ULONG_BE( W[ 3], data, 12 ); + GET_ULONG_BE( W[ 4], data, 16 ); + GET_ULONG_BE( W[ 5], data, 20 ); + GET_ULONG_BE( W[ 6], data, 24 ); + GET_ULONG_BE( W[ 7], data, 28 ); + GET_ULONG_BE( W[ 8], data, 32 ); + GET_ULONG_BE( W[ 9], data, 36 ); + GET_ULONG_BE( W[10], data, 40 ); + GET_ULONG_BE( W[11], data, 44 ); + GET_ULONG_BE( W[12], data, 48 ); + GET_ULONG_BE( W[13], data, 52 ); + GET_ULONG_BE( W[14], data, 56 ); + GET_ULONG_BE( W[15], data, 60 ); + +#define S(x,n) ((x << n) | ((x & 0xFFFFFFFF) >> (32 - n))) + +#define R(t) \ +( \ + temp = W[(t - 3) & 0x0F] ^ W[(t - 8) & 0x0F] ^ \ + W[(t - 14) & 0x0F] ^ W[ t & 0x0F], \ + ( W[t & 0x0F] = S(temp,1) ) \ +) + +#define P(a,b,c,d,e,x) \ +{ \ + e += S(a,5) + F(b,c,d) + K + x; b = S(b,30); \ +} + + A = ctx->state[0]; + B = ctx->state[1]; + C = ctx->state[2]; + D = ctx->state[3]; + E = ctx->state[4]; + +#define F(x,y,z) (z ^ (x & (y ^ z))) +#define K 0x5A827999 + + P( A, B, C, D, E, W[0] ); + P( E, A, B, C, D, W[1] ); + P( D, E, A, B, C, W[2] ); + P( C, D, E, A, B, W[3] ); + P( B, C, D, E, A, W[4] ); + P( A, B, C, D, E, W[5] ); + P( E, A, B, C, D, W[6] ); + P( D, E, A, B, C, W[7] ); + P( C, D, E, A, B, W[8] ); + P( B, C, D, E, A, W[9] ); + P( A, B, C, D, E, W[10] ); + P( E, A, B, C, D, W[11] ); + P( D, E, A, B, C, W[12] ); + P( C, D, E, A, B, W[13] ); + P( B, C, D, E, A, W[14] ); + P( A, B, C, D, E, W[15] ); + P( E, A, B, C, D, R(16) ); + P( D, E, A, B, C, R(17) ); + P( C, D, E, A, B, R(18) ); + P( B, C, D, E, A, R(19) ); + +#undef K +#undef F + +#define F(x,y,z) (x ^ y ^ z) +#define K 0x6ED9EBA1 + + P( A, B, C, D, E, R(20) ); + P( E, A, B, C, D, R(21) ); + P( D, E, A, B, C, R(22) ); + P( C, D, E, A, B, R(23) ); + P( B, C, D, E, A, R(24) ); + P( A, B, C, D, E, R(25) ); + P( E, A, B, C, D, R(26) ); + P( D, E, A, B, C, R(27) ); + P( C, D, E, A, B, R(28) ); + P( B, C, D, E, A, R(29) ); + P( A, B, C, D, E, R(30) ); + P( E, A, B, C, D, R(31) ); + P( D, E, A, B, C, R(32) ); + P( C, D, E, A, B, R(33) ); + P( B, C, D, E, A, R(34) ); + P( A, B, C, D, E, R(35) ); + P( E, A, B, C, D, R(36) ); + P( D, E, A, B, C, R(37) ); + P( C, D, E, A, B, R(38) ); + P( B, C, D, E, A, R(39) ); + +#undef K +#undef F + +#define F(x,y,z) ((x & y) | (z & (x | y))) +#define K 0x8F1BBCDC + + P( A, B, C, D, E, R(40) ); + P( E, A, B, C, D, R(41) ); + P( D, E, A, B, C, R(42) ); + P( C, D, E, A, B, R(43) ); + P( B, C, D, E, A, R(44) ); + P( A, B, C, D, E, R(45) ); + P( E, A, B, C, D, R(46) ); + P( D, E, A, B, C, R(47) ); + P( C, D, E, A, B, R(48) ); + P( B, C, D, E, A, R(49) ); + P( A, B, C, D, E, R(50) ); + P( E, A, B, C, D, R(51) ); + P( D, E, A, B, C, R(52) ); + P( C, D, E, A, B, R(53) ); + P( B, C, D, E, A, R(54) ); + P( A, B, C, D, E, R(55) ); + P( E, A, B, C, D, R(56) ); + P( D, E, A, B, C, R(57) ); + P( C, D, E, A, B, R(58) ); + P( B, C, D, E, A, R(59) ); + +#undef K +#undef F + +#define F(x,y,z) (x ^ y ^ z) +#define K 0xCA62C1D6 + + P( A, B, C, D, E, R(60) ); + P( E, A, B, C, D, R(61) ); + P( D, E, A, B, C, R(62) ); + P( C, D, E, A, B, R(63) ); + P( B, C, D, E, A, R(64) ); + P( A, B, C, D, E, R(65) ); + P( E, A, B, C, D, R(66) ); + P( D, E, A, B, C, R(67) ); + P( C, D, E, A, B, R(68) ); + P( B, C, D, E, A, R(69) ); + P( A, B, C, D, E, R(70) ); + P( E, A, B, C, D, R(71) ); + P( D, E, A, B, C, R(72) ); + P( C, D, E, A, B, R(73) ); + P( B, C, D, E, A, R(74) ); + P( A, B, C, D, E, R(75) ); + P( E, A, B, C, D, R(76) ); + P( D, E, A, B, C, R(77) ); + P( C, D, E, A, B, R(78) ); + P( B, C, D, E, A, R(79) ); + +#undef K +#undef F + + ctx->state[0] += A; + ctx->state[1] += B; + ctx->state[2] += C; + ctx->state[3] += D; + ctx->state[4] += E; +} + +/* + * SHA-1 process buffer + */ +void sha1_update( sha1_context *ctx, const unsigned char *input, int ilen ) +{ + int fill; + unsigned long left; + + if( ilen <= 0 ) + return; + + left = ctx->total[0] & 0x3F; + fill = 64 - left; + + ctx->total[0] += ilen; + ctx->total[0] &= 0xFFFFFFFF; + + if( ctx->total[0] < (unsigned long) ilen ) + ctx->total[1]++; + + if( left && ilen >= fill ) + { + MEMCPY( (void *) (ctx->buffer + left), + input, fill ); + sha1_process( ctx, ctx->buffer ); + input += fill; + ilen -= fill; + left = 0; + } + + while( ilen >= 64 ) + { + sha1_process( ctx, input ); + input += 64; + ilen -= 64; + } + + if( ilen > 0 ) + { + MEMCPY( (void *) (ctx->buffer + left), + input, ilen ); + } +} + +static const unsigned char sha1_padding[64] = +{ + 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +/* + * SHA-1 final digest + */ +void sha1_finish( sha1_context *ctx, unsigned char output[20] ) +{ + unsigned long last, padn; + unsigned long high, low; + unsigned char msglen[8]; + + high = ( ctx->total[0] >> 29 ) + | ( ctx->total[1] << 3 ); + low = ( ctx->total[0] << 3 ); + + PUT_ULONG_BE( high, msglen, 0 ); + PUT_ULONG_BE( low, msglen, 4 ); + + last = ctx->total[0] & 0x3F; + padn = ( last < 56 ) ? ( 56 - last ) : ( 120 - last ); + + sha1_update( ctx, sha1_padding, padn ); + sha1_update( ctx, msglen, 8 ); + + PUT_ULONG_BE( ctx->state[0], output, 0 ); + PUT_ULONG_BE( ctx->state[1], output, 4 ); + PUT_ULONG_BE( ctx->state[2], output, 8 ); + PUT_ULONG_BE( ctx->state[3], output, 12 ); + PUT_ULONG_BE( ctx->state[4], output, 16 ); +} + +/* + * output = SHA-1( input buffer ) + */ +void sha1( unsigned char *input, int ilen, unsigned char output[20] ) +{ + sha1_context ctx; + + sha1_starts( &ctx ); + sha1_update( &ctx, input, ilen ); + sha1_finish( &ctx, output ); +} + +#endif /* PPP_SUPPORT && LWIP_INCLUDED_POLARSSL_SHA1 */ diff --git a/components/lwip/netif/ppp/ppp.c b/components/lwip/netif/ppp/ppp.c new file mode 100755 index 0000000000..031556ad06 --- /dev/null +++ b/components/lwip/netif/ppp/ppp.c @@ -0,0 +1,1600 @@ +/***************************************************************************** +* ppp.c - Network Point to Point Protocol program file. +* +* Copyright (c) 2003 by Marc Boucher, Services Informatiques (MBSI) inc. +* portions Copyright (c) 1997 by Global Election Systems Inc. +* +* The authors hereby grant permission to use, copy, modify, distribute, +* and license this software and its documentation for any purpose, provided +* that existing copyright notices are retained in all copies and that this +* notice and the following disclaimer are included verbatim in any +* distributions. No written agreement, license, or royalty fee is required +* for any of the authorized uses. +* +* THIS SOFTWARE IS PROVIDED BY THE CONTRIBUTORS *AS IS* AND ANY EXPRESS OR +* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES +* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +* IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF +* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +* +****************************************************************************** +* REVISION HISTORY +* +* 03-01-01 Marc Boucher +* Ported to lwIP. +* 97-11-05 Guy Lancaster , Global Election Systems Inc. +* Original. +*****************************************************************************/ + +/* + * ppp_defs.h - PPP definitions. + * + * if_pppvar.h - private structures and declarations for PPP. + * + * Copyright (c) 1994 The Australian National University. + * All rights reserved. + * + * Permission to use, copy, modify, and distribute this software and its + * documentation is hereby granted, provided that the above copyright + * notice appears in all copies. This software is provided without any + * warranty, express or implied. The Australian National University + * makes no representations about the suitability of this software for + * any purpose. + * + * IN NO EVENT SHALL THE AUSTRALIAN NATIONAL UNIVERSITY BE LIABLE TO ANY + * PARTY FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES + * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF + * THE AUSTRALIAN NATIONAL UNIVERSITY HAVE BEEN ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * THE AUSTRALIAN NATIONAL UNIVERSITY SPECIFICALLY DISCLAIMS ANY WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS + * ON AN "AS IS" BASIS, AND THE AUSTRALIAN NATIONAL UNIVERSITY HAS NO + * OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, + * OR MODIFICATIONS. + */ + +/* + * if_ppp.h - Point-to-Point Protocol definitions. + * + * Copyright (c) 1989 Carnegie Mellon University. + * All rights reserved. + * + * Redistribution and use in source and binary forms are permitted + * provided that the above copyright notice and this paragraph are + * duplicated in all such forms and that any documentation, + * advertising materials, and other materials related to such + * distribution and use acknowledge that the software was developed + * by Carnegie Mellon University. The name of the + * University may not be used to endorse or promote products derived + * from this software without specific prior written permission. + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. + */ + +#include "lwip/opt.h" +#if PPP_SUPPORT /* don't build if not configured for use in lwipopts.h */ + +#include "lwip/pbuf.h" +#include "lwip/stats.h" +#include "lwip/sys.h" +#include "lwip/tcpip.h" +#include "lwip/api.h" +#include "lwip/snmp.h" +#include "lwip/sio.h" +#include "lwip/sys.h" +#include "lwip/ip4.h" /* for ip4_input() */ +#if PPP_IPV6_SUPPORT +#include "lwip/ip6.h" /* for ip6_input() */ +#endif /* PPP_IPV6_SUPPORT */ +#include "lwip/dns.h" + +#include "netif/ppp/ppp_impl.h" +#include "netif/ppp/pppos.h" + +#include "netif/ppp/fsm.h" +#include "netif/ppp/lcp.h" +#include "netif/ppp/magic.h" + +#if PAP_SUPPORT +#include "netif/ppp/upap.h" +#endif /* PAP_SUPPORT */ +#if CHAP_SUPPORT +#include "netif/ppp/chap-new.h" +#endif /* CHAP_SUPPORT */ +#if EAP_SUPPORT +#include "netif/ppp/eap.h" +#endif /* EAP_SUPPORT */ +#if CCP_SUPPORT +#include "netif/ppp/ccp.h" +#endif /* CCP_SUPPORT */ +#if MPPE_SUPPORT +#include "netif/ppp/mppe.h" +#endif /* MPPE_SUPPORT */ +#if ECP_SUPPORT +#include "netif/ppp/ecp.h" +#endif /* EAP_SUPPORT */ +#if VJ_SUPPORT +#include "netif/ppp/vj.h" +#endif /* VJ_SUPPORT */ +#if PPP_IPV4_SUPPORT +#include "netif/ppp/ipcp.h" +#endif /* PPP_IPV4_SUPPORT */ +#if PPP_IPV6_SUPPORT +#include "netif/ppp/ipv6cp.h" +#endif /* PPP_IPV6_SUPPORT */ + +/*************************/ +/*** LOCAL DEFINITIONS ***/ +/*************************/ + +/* FIXME: add stats per PPP session */ +#if PPP_STATS_SUPPORT +static struct timeval start_time; /* Time when link was started. */ +static struct pppd_stats old_link_stats; +struct pppd_stats link_stats; +unsigned link_connect_time; +int link_stats_valid; +#endif /* PPP_STATS_SUPPORT */ + +/* + * PPP Data Link Layer "protocol" table. + * One entry per supported protocol. + * The last entry must be NULL. + */ +const struct protent* const protocols[] = { + &lcp_protent, +#if PAP_SUPPORT + &pap_protent, +#endif /* PAP_SUPPORT */ +#if CHAP_SUPPORT + &chap_protent, +#endif /* CHAP_SUPPORT */ +#if CBCP_SUPPORT + &cbcp_protent, +#endif /* CBCP_SUPPORT */ +#if PPP_IPV4_SUPPORT + &ipcp_protent, +#endif /* PPP_IPV4_SUPPORT */ +#if PPP_IPV6_SUPPORT + &ipv6cp_protent, +#endif /* PPP_IPV6_SUPPORT */ +#if CCP_SUPPORT + &ccp_protent, +#endif /* CCP_SUPPORT */ +#if ECP_SUPPORT + &ecp_protent, +#endif /* ECP_SUPPORT */ +#ifdef AT_CHANGE + &atcp_protent, +#endif /* AT_CHANGE */ +#if EAP_SUPPORT + &eap_protent, +#endif /* EAP_SUPPORT */ + NULL +}; + +/* Prototypes for procedures local to this file. */ +static void ppp_do_connect(void *arg); +static err_t ppp_netif_init_cb(struct netif *netif); +#if LWIP_IPV4 +static err_t ppp_netif_output_ip4(struct netif *netif, struct pbuf *pb, const ip4_addr_t *ipaddr); +#endif /* LWIP_IPV4 */ +#if PPP_IPV6_SUPPORT +static err_t ppp_netif_output_ip6(struct netif *netif, struct pbuf *pb, const ip6_addr_t *ipaddr); +#endif /* PPP_IPV6_SUPPORT */ +static err_t ppp_netif_output(struct netif *netif, struct pbuf *pb, u16_t protocol); + +/***********************************/ +/*** PUBLIC FUNCTION DEFINITIONS ***/ +/***********************************/ +void ppp_set_auth(ppp_pcb *pcb, u8_t authtype, const char *user, const char *passwd) { +#if PPP_AUTH_SUPPORT +#if PAP_SUPPORT + pcb->settings.refuse_pap = !(authtype & PPPAUTHTYPE_PAP); +#endif /* PAP_SUPPORT */ +#if CHAP_SUPPORT + pcb->settings.refuse_chap = !(authtype & PPPAUTHTYPE_CHAP); +#if MSCHAP_SUPPORT + pcb->settings.refuse_mschap = !(authtype & PPPAUTHTYPE_MSCHAP); + pcb->settings.refuse_mschap_v2 = !(authtype & PPPAUTHTYPE_MSCHAP_V2); +#endif /* MSCHAP_SUPPORT */ +#endif /* CHAP_SUPPORT */ +#if EAP_SUPPORT + pcb->settings.refuse_eap = !(authtype & PPPAUTHTYPE_EAP); +#endif /* EAP_SUPPORT */ + pcb->settings.user = user; + pcb->settings.passwd = passwd; +#else /* PPP_AUTH_SUPPORT */ + LWIP_UNUSED_ARG(pcb); + LWIP_UNUSED_ARG(authtype); + LWIP_UNUSED_ARG(user); + LWIP_UNUSED_ARG(passwd); +#endif /* PPP_AUTH_SUPPORT */ +} + +#if PPP_NOTIFY_PHASE +void ppp_set_notify_phase_callback(ppp_pcb *pcb, ppp_notify_phase_cb_fn notify_phase_cb) { + pcb->notify_phase_cb = notify_phase_cb; + notify_phase_cb(pcb, pcb->phase, pcb->ctx_cb); +} +#endif /* PPP_NOTIFY_PHASE */ + +/* + * Initiate a PPP connection. + * + * This can only be called if PPP is in the dead phase. + * + * Holdoff is the time to wait (in seconds) before initiating + * the connection. + * + * If this port connects to a modem, the modem connection must be + * established before calling this. + */ +err_t ppp_connect(ppp_pcb *pcb, u16_t holdoff) { + if (pcb->phase != PPP_PHASE_DEAD) { + return ERR_ALREADY; + } + + PPPDEBUG(LOG_DEBUG, ("ppp_connect[%d]: holdoff=%d\n", pcb->netif->num, holdoff)); + + if (holdoff == 0) { + return pcb->link_cb->connect(pcb, pcb->link_ctx_cb); + } + + new_phase(pcb, PPP_PHASE_HOLDOFF); + sys_timeout((u32_t)(holdoff*1000), ppp_do_connect, pcb); + return ERR_OK; +} + +#if PPP_SERVER +/* + * Listen for an incoming PPP connection. + * + * This can only be called if PPP is in the dead phase. + * + * Local and remote interface IP addresses, as well as DNS are + * provided through a previously filled struct ppp_addrs. + * + * If this port connects to a modem, the modem connection must be + * established before calling this. + */ +err_t ppp_listen(ppp_pcb *pcb, struct ppp_addrs *addrs) { + if (pcb->phase != PPP_PHASE_DEAD) { + return ERR_ALREADY; + } + + PPPDEBUG(LOG_DEBUG, ("ppp_listen[%d]\n", pcb->netif->num)); + + if (pcb->link_cb->listen) { + return pcb->link_cb->listen(pcb, pcb->link_ctx_cb, addrs); + } + return ERR_IF; +} +#endif /* PPP_SERVER */ + +/* + * Initiate the end of a PPP connection. + * Any outstanding packets in the queues are dropped. + * + * Setting nocarrier to 1 close the PPP connection without initiating the + * shutdown procedure. Always using nocarrier = 0 is still recommended, + * this is going to take a little longer time if your link is down, but + * is a safer choice for the PPP state machine. + * + * Return 0 on success, an error code on failure. + */ +err_t +ppp_close(ppp_pcb *pcb, u8_t nocarrier) +{ + pcb->err_code = PPPERR_USER; + + /* holdoff phase, cancel the reconnection */ + if (pcb->phase == PPP_PHASE_HOLDOFF) { + sys_untimeout(ppp_do_connect, pcb); + new_phase(pcb, PPP_PHASE_DEAD); + } + + /* dead phase, nothing to do, call the status callback to be consistent */ + if (pcb->phase == PPP_PHASE_DEAD) { + pcb->link_status_cb(pcb, pcb->err_code, pcb->ctx_cb); + return ERR_OK; + } + + /* + * Only accept carrier lost signal on the stable running phase in order + * to prevent changing the PPP phase FSM in transition phases. + * + * Always using nocarrier = 0 is still recommended, this is going to + * take a little longer time, but is a safer choice from FSM point of view. + */ + if (nocarrier && pcb->phase == PPP_PHASE_RUNNING) { + PPPDEBUG(LOG_DEBUG, ("ppp_close[%d]: carrier lost -> lcp_lowerdown\n", pcb->netif->num)); + lcp_lowerdown(pcb); + /* forced link termination, this will leave us at PPP_PHASE_DEAD. */ + link_terminated(pcb); + return ERR_OK; + } + + /* Disconnect */ + PPPDEBUG(LOG_DEBUG, ("ppp_close[%d]: kill_link -> lcp_close\n", pcb->netif->num)); + /* LCP close request, this will leave us at PPP_PHASE_DEAD. */ + lcp_close(pcb, "User request"); + return ERR_OK; +} + +/* + * Release the control block. + * + * This can only be called if PPP is in the dead phase. + * + * You must use ppp_close() before if you wish to terminate + * an established PPP session. + * + * Return 0 on success, an error code on failure. + */ +err_t ppp_free(ppp_pcb *pcb) { + err_t err; + if (pcb->phase != PPP_PHASE_DEAD) { + return ERR_CONN; + } + + PPPDEBUG(LOG_DEBUG, ("ppp_free[%d]\n", pcb->netif->num)); + + netif_remove(pcb->netif); + + err = pcb->link_cb->free(pcb, pcb->link_ctx_cb); + + memp_free(MEMP_PPP_PCB, pcb); + return err; +} + +/* Get and set parameters for the given connection. + * Return 0 on success, an error code on failure. */ +err_t +ppp_ioctl(ppp_pcb *pcb, u8_t cmd, void *arg) +{ + if (pcb == NULL) { + return ERR_VAL; + } + + switch(cmd) { + case PPPCTLG_UPSTATUS: /* Get the PPP up status. */ + if (!arg) { + goto fail; + } + *(int *)arg = (int)(0 +#if PPP_IPV4_SUPPORT + || pcb->if4_up +#endif /* PPP_IPV4_SUPPORT */ +#if PPP_IPV6_SUPPORT + || pcb->if6_up +#endif /* PPP_IPV6_SUPPORT */ + ); + return ERR_OK; + + case PPPCTLG_ERRCODE: /* Get the PPP error code. */ + if (!arg) { + goto fail; + } + *(int *)arg = (int)(pcb->err_code); + return ERR_OK; + + default: + goto fail; + } + +fail: + return ERR_VAL; +} + + +/**********************************/ +/*** LOCAL FUNCTION DEFINITIONS ***/ +/**********************************/ + +static void ppp_do_connect(void *arg) { + ppp_pcb *pcb = (ppp_pcb*)arg; + + LWIP_ASSERT("pcb->phase == PPP_PHASE_DEAD || pcb->phase == PPP_PHASE_HOLDOFF", pcb->phase == PPP_PHASE_DEAD || pcb->phase == PPP_PHASE_HOLDOFF); + + pcb->link_cb->connect(pcb, pcb->link_ctx_cb); +} + +/* + * ppp_netif_init_cb - netif init callback + */ +static err_t ppp_netif_init_cb(struct netif *netif) { + netif->name[0] = 'p'; + netif->name[1] = 'p'; +#if LWIP_IPV4 + /* FIXME: change that when netif_null_output_ip4() will materialize */ + netif->output = ppp_netif_output_ip4; +#endif /* LWIP_IPV4 */ +#if PPP_IPV6_SUPPORT + netif->output_ip6 = ppp_netif_output_ip6; +#endif /* PPP_IPV6_SUPPORT */ + netif->flags = NETIF_FLAG_UP; +#if LWIP_NETIF_HOSTNAME + /* @todo: Initialize interface hostname */ + /* netif_set_hostname(netif, "lwip"); */ +#endif /* LWIP_NETIF_HOSTNAME */ + return ERR_OK; +} + +#if LWIP_IPV4 +/* + * Send an IPv4 packet on the given connection. + */ +static err_t ppp_netif_output_ip4(struct netif *netif, struct pbuf *pb, const ip4_addr_t *ipaddr) { + LWIP_UNUSED_ARG(ipaddr); +#if PPP_IPV4_SUPPORT + return ppp_netif_output(netif, pb, PPP_IP); +#else /* PPP_IPV4_SUPPORT */ + LWIP_UNUSED_ARG(netif); + LWIP_UNUSED_ARG(pb); + return ERR_IF; +#endif /* PPP_IPV4_SUPPORT */ +} +#endif /* LWIP_IPV4 */ + +#if PPP_IPV6_SUPPORT +/* + * Send an IPv6 packet on the given connection. + */ +static err_t ppp_netif_output_ip6(struct netif *netif, struct pbuf *pb, const ip6_addr_t *ipaddr) { + LWIP_UNUSED_ARG(ipaddr); + return ppp_netif_output(netif, pb, PPP_IPV6); +} +#endif /* PPP_IPV6_SUPPORT */ + +static err_t ppp_netif_output(struct netif *netif, struct pbuf *pb, u16_t protocol) { + ppp_pcb *pcb = (ppp_pcb*)netif->state; + err_t err; + struct pbuf *fpb = NULL; + + /* Check that the link is up. */ + if (0 +#if PPP_IPV4_SUPPORT + || (protocol == PPP_IP && !pcb->if4_up) +#endif /* PPP_IPV4_SUPPORT */ +#if PPP_IPV6_SUPPORT + || (protocol == PPP_IPV6 && !pcb->if6_up) +#endif /* PPP_IPV6_SUPPORT */ + ) { + PPPDEBUG(LOG_ERR, ("ppp_netif_output[%d]: link not up\n", pcb->netif->num)); + goto err_rte_drop; + } + +#if MPPE_SUPPORT + /* If MPPE is required, refuse any IP packet until we are able to crypt them. */ + if (pcb->settings.require_mppe && pcb->ccp_transmit_method != CI_MPPE) { + PPPDEBUG(LOG_ERR, ("ppp_netif_output[%d]: MPPE required, not up\n", pcb->netif->num)); + goto err_rte_drop; + } +#endif /* MPPE_SUPPORT */ + +#if VJ_SUPPORT && LWIP_TCP + /* + * Attempt Van Jacobson header compression if VJ is configured and + * this is an IP packet. + */ + if (protocol == PPP_IP && pcb->vj_enabled) { + switch (vj_compress_tcp(&pcb->vj_comp, &pb)) { + case TYPE_IP: + /* No change... + protocol = PPP_IP; */ + break; + case TYPE_COMPRESSED_TCP: + /* vj_compress_tcp() returns a new allocated pbuf, indicate we should free + * our duplicated pbuf later */ + fpb = pb; + protocol = PPP_VJC_COMP; + break; + case TYPE_UNCOMPRESSED_TCP: + /* vj_compress_tcp() returns a new allocated pbuf, indicate we should free + * our duplicated pbuf later */ + fpb = pb; + protocol = PPP_VJC_UNCOMP; + break; + default: + PPPDEBUG(LOG_WARNING, ("ppp_netif_output[%d]: bad IP packet\n", pcb->netif->num)); + LINK_STATS_INC(link.proterr); + LINK_STATS_INC(link.drop); + MIB2_STATS_NETIF_INC(pcb->netif, ifoutdiscards); + return ERR_VAL; + } + } +#endif /* VJ_SUPPORT && LWIP_TCP */ + +#if CCP_SUPPORT + switch (pcb->ccp_transmit_method) { + case 0: + break; /* Don't compress */ +#if MPPE_SUPPORT + case CI_MPPE: + if ((err = mppe_compress(pcb, &pcb->mppe_comp, &pb, protocol)) != ERR_OK) { + LINK_STATS_INC(link.memerr); + LINK_STATS_INC(link.drop); + MIB2_STATS_NETIF_INC(netif, ifoutdiscards); + goto err; + } + /* if VJ compressor returned a new allocated pbuf, free it */ + if (fpb) { + pbuf_free(fpb); + } + /* mppe_compress() returns a new allocated pbuf, indicate we should free + * our duplicated pbuf later */ + fpb = pb; + protocol = PPP_COMP; + break; +#endif /* MPPE_SUPPORT */ + default: + PPPDEBUG(LOG_ERR, ("ppp_netif_output[%d]: bad CCP transmit method\n", pcb->netif->num)); + goto err_rte_drop; /* Cannot really happen, we only negotiate what we are able to do */ + } +#endif /* CCP_SUPPORT */ + + err = pcb->link_cb->netif_output(pcb, pcb->link_ctx_cb, pb, protocol); + goto err; + +err_rte_drop: + err = ERR_RTE; + LINK_STATS_INC(link.rterr); + LINK_STATS_INC(link.drop); + MIB2_STATS_NETIF_INC(netif, ifoutdiscards); +err: + if (fpb) { + pbuf_free(fpb); + } + return err; +} + +/************************************/ +/*** PRIVATE FUNCTION DEFINITIONS ***/ +/************************************/ + +/* Initialize the PPP subsystem. */ +int ppp_init(void) { + + /* + * Initialize magic number generator now so that protocols may + * use magic numbers in initialization. + */ + magic_init(); + + return 0; +} + +/* + * Create a new PPP control block. + * + * This initializes the PPP control block but does not + * attempt to negotiate the LCP session. + * + * Return a new PPP connection control block pointer + * on success or a null pointer on failure. + */ +ppp_pcb *ppp_new(struct netif *pppif, const struct link_callbacks *callbacks, void *link_ctx_cb, ppp_link_status_cb_fn link_status_cb, void *ctx_cb) { + ppp_pcb *pcb; + + /* PPP is single-threaded: without a callback, + * there is no way to know when the link is up. */ + if (link_status_cb == NULL) { + return NULL; + } + + pcb = (ppp_pcb*)memp_malloc(MEMP_PPP_PCB); + if (pcb == NULL) { + return NULL; + } + + memset(pcb, 0, sizeof(ppp_pcb)); + + /* default configuration */ +#if LWIP_DNS + pcb->settings.usepeerdns = 1; +#endif /* LWIP_DNS */ + +#if PAP_SUPPORT + pcb->settings.pap_timeout_time = UPAP_DEFTIMEOUT; + pcb->settings.pap_max_transmits = UPAP_DEFTRANSMITS; +#if PPP_SERVER + pcb->settings.pap_req_timeout = UPAP_DEFREQTIME; +#endif /* PPP_SERVER */ +#endif /* PAP_SUPPORT */ + +#if CHAP_SUPPORT + pcb->settings.chap_timeout_time = CHAP_DEFTIMEOUT; + pcb->settings.chap_max_transmits = CHAP_DEFTRANSMITS; +#if PPP_SERVER + pcb->settings.chap_rechallenge_time = CHAP_DEFRECHALLENGETIME; +#endif /* PPP_SERVER */ +#endif /* CHAP_SUPPPORT */ + +#if EAP_SUPPORT + pcb->settings.eap_req_time = EAP_DEFREQTIME; + pcb->settings.eap_allow_req = EAP_DEFALLOWREQ; +#if PPP_SERVER + pcb->settings.eap_timeout_time = EAP_DEFTIMEOUT; + pcb->settings.eap_max_transmits = EAP_DEFTRANSMITS; +#endif /* PPP_SERVER */ +#endif /* EAP_SUPPORT */ + +#if MPPE_SUPPORT + pcb->settings.refuse_mppe_stateful = 1; +#endif /* MPPE_SUPPORT */ + + pcb->settings.lcp_loopbackfail = LCP_DEFLOOPBACKFAIL; + pcb->settings.lcp_echo_interval = LCP_ECHOINTERVAL; + pcb->settings.lcp_echo_fails = LCP_MAXECHOFAILS; + + pcb->settings.fsm_timeout_time = FSM_DEFTIMEOUT; + pcb->settings.fsm_max_conf_req_transmits = FSM_DEFMAXCONFREQS; + pcb->settings.fsm_max_term_transmits = FSM_DEFMAXTERMREQS; + pcb->settings.fsm_max_nak_loops = FSM_DEFMAXNAKLOOPS; + + pcb->netif = pppif; + MIB2_INIT_NETIF(pppif, snmp_ifType_ppp, 0); + if (!netif_add(pcb->netif, +#if LWIP_IPV4 + IP4_ADDR_ANY, IP4_ADDR_BROADCAST, IP4_ADDR_ANY, +#endif /* LWIP_IPV4 */ + (void *)pcb, ppp_netif_init_cb, NULL)) { + memp_free(MEMP_PPP_PCB, pcb); + PPPDEBUG(LOG_ERR, ("ppp_new: netif_add failed\n")); + return NULL; + } + + pcb->link_cb = callbacks; + pcb->link_ctx_cb = link_ctx_cb; + pcb->link_status_cb = link_status_cb; + pcb->ctx_cb = ctx_cb; + new_phase(pcb, PPP_PHASE_DEAD); + return pcb; +} + +/* Set a PPP PCB to its initial state */ +void ppp_clear(ppp_pcb *pcb) { + const struct protent *protp; + int i; + + LWIP_ASSERT("pcb->phase == PPP_PHASE_DEAD || pcb->phase == PPP_PHASE_HOLDOFF", pcb->phase == PPP_PHASE_DEAD || pcb->phase == PPP_PHASE_HOLDOFF); + +#if PPP_STATS_SUPPORT + link_stats_valid = 0; +#endif /* PPP_STATS_SUPPORT */ + + memset(&pcb->phase, 0, sizeof(ppp_pcb) - ( (char*)&((ppp_pcb*)0)->phase - (char*)0 ) ); + + /* + * Initialize each protocol. + */ + for (i = 0; (protp = protocols[i]) != NULL; ++i) { + (*protp->init)(pcb); + } + +#if VJ_SUPPORT && LWIP_TCP + vj_compress_init(&pcb->vj_comp); +#endif /* VJ_SUPPORT && LWIP_TCP */ + + new_phase(pcb, PPP_PHASE_INITIALIZE); +} + +/** Initiate LCP open request */ +void ppp_start(ppp_pcb *pcb) { + PPPDEBUG(LOG_DEBUG, ("ppp_start[%d]\n", pcb->netif->num)); + lcp_open(pcb); /* Start protocol */ + lcp_lowerup(pcb); + PPPDEBUG(LOG_DEBUG, ("ppp_start[%d]: finished\n", pcb->netif->num)); +} + +/** Called when link failed to setup */ +void ppp_link_failed(ppp_pcb *pcb) { + PPPDEBUG(LOG_DEBUG, ("ppp_failed[%d]\n", pcb->netif->num)); + new_phase(pcb, PPP_PHASE_DEAD); + pcb->err_code = PPPERR_OPEN; + pcb->link_status_cb(pcb, pcb->err_code, pcb->ctx_cb); +} + +/** Called when link is normally down (i.e. it was asked to end) */ +void ppp_link_end(ppp_pcb *pcb) { + PPPDEBUG(LOG_DEBUG, ("ppp_end[%d]\n", pcb->netif->num)); + if (pcb->err_code == PPPERR_NONE) { + pcb->err_code = PPPERR_CONNECT; + } + pcb->link_status_cb(pcb, pcb->err_code, pcb->ctx_cb); +} + +/* + * Pass the processed input packet to the appropriate handler. + * This function and all handlers run in the context of the tcpip_thread + */ +void ppp_input(ppp_pcb *pcb, struct pbuf *pb) { + u16_t protocol; +#if PPP_DEBUG && PPP_PROTOCOLNAME + const char *pname; +#endif /* PPP_DEBUG && PPP_PROTOCOLNAME */ + + magic_randomize(); + + if (pb->len < 2) { + PPPDEBUG(LOG_ERR, ("ppp_input[%d]: packet too short\n", pcb->netif->num)); + goto drop; + } + protocol = (((u8_t *)pb->payload)[0] << 8) | ((u8_t*)pb->payload)[1]; + +#if PRINTPKT_SUPPORT + ppp_dump_packet("rcvd", (unsigned char *)pb->payload, pb->len); +#endif /* PRINTPKT_SUPPORT */ + + pbuf_header(pb, -(s16_t)sizeof(protocol)); + + LINK_STATS_INC(link.recv); + MIB2_STATS_NETIF_INC(pcb->netif, ifinucastpkts); + MIB2_STATS_NETIF_ADD(pcb->netif, ifinoctets, pb->tot_len); + + /* + * Toss all non-LCP packets unless LCP is OPEN. + */ + if (protocol != PPP_LCP && pcb->lcp_fsm.state != PPP_FSM_OPENED) { + ppp_dbglog("Discarded non-LCP packet when LCP not open"); + goto drop; + } + + /* + * Until we get past the authentication phase, toss all packets + * except LCP, LQR and authentication packets. + */ + if (pcb->phase <= PPP_PHASE_AUTHENTICATE + && !(protocol == PPP_LCP +#if LQR_SUPPORT + || protocol == PPP_LQR +#endif /* LQR_SUPPORT */ +#if PAP_SUPPORT + || protocol == PPP_PAP +#endif /* PAP_SUPPORT */ +#if CHAP_SUPPORT + || protocol == PPP_CHAP +#endif /* CHAP_SUPPORT */ +#if EAP_SUPPORT + || protocol == PPP_EAP +#endif /* EAP_SUPPORT */ + )) { + ppp_dbglog("discarding proto 0x%x in phase %d", protocol, pcb->phase); + goto drop; + } + +#if CCP_SUPPORT +#if MPPE_SUPPORT + /* + * MPPE is required and unencrypted data has arrived (this + * should never happen!). We should probably drop the link if + * the protocol is in the range of what should be encrypted. + * At the least, we drop this packet. + */ + if (pcb->settings.require_mppe && protocol != PPP_COMP && protocol < 0x8000) { + PPPDEBUG(LOG_ERR, ("ppp_input[%d]: MPPE required, received unencrypted data!\n", pcb->netif->num)); + goto drop; + } +#endif /* MPPE_SUPPORT */ + + if (protocol == PPP_COMP) { + u8_t *pl; + + switch (pcb->ccp_receive_method) { +#if MPPE_SUPPORT + case CI_MPPE: + if (mppe_decompress(pcb, &pcb->mppe_decomp, &pb) != ERR_OK) { + goto drop; + } + break; +#endif /* MPPE_SUPPORT */ + default: + PPPDEBUG(LOG_ERR, ("ppp_input[%d]: bad CCP receive method\n", pcb->netif->num)); + goto drop; /* Cannot really happen, we only negotiate what we are able to do */ + } + + /* Assume no PFC */ + if (pb->len < 2) { + goto drop; + } + + /* Extract and hide protocol (do PFC decompression if necessary) */ + pl = (u8_t*)pb->payload; + if (pl[0] & 0x01) { + protocol = pl[0]; + pbuf_header(pb, -(s16_t)1); + } else { + protocol = (pl[0] << 8) | pl[1]; + pbuf_header(pb, -(s16_t)2); + } + } +#endif /* CCP_SUPPORT */ + + switch(protocol) { + +#if PPP_IPV4_SUPPORT + case PPP_IP: /* Internet Protocol */ + PPPDEBUG(LOG_INFO, ("ppp_input[%d]: ip in pbuf len=%d\n", pcb->netif->num, pb->tot_len)); + ip4_input(pb, pcb->netif); + return; +#endif /* PPP_IPV4_SUPPORT */ + +#if PPP_IPV6_SUPPORT + case PPP_IPV6: /* Internet Protocol Version 6 */ + PPPDEBUG(LOG_INFO, ("ppp_input[%d]: ip6 in pbuf len=%d\n", pcb->netif->num, pb->tot_len)); + ip6_input(pb, pcb->netif); + return; +#endif /* PPP_IPV6_SUPPORT */ + +#if VJ_SUPPORT && LWIP_TCP + case PPP_VJC_COMP: /* VJ compressed TCP */ + /* + * Clip off the VJ header and prepend the rebuilt TCP/IP header and + * pass the result to IP. + */ + PPPDEBUG(LOG_INFO, ("ppp_input[%d]: vj_comp in pbuf len=%d\n", pcb->netif->num, pb->tot_len)); + if (pcb->vj_enabled && vj_uncompress_tcp(&pb, &pcb->vj_comp) >= 0) { + ip4_input(pb, pcb->netif); + return; + } + /* Something's wrong so drop it. */ + PPPDEBUG(LOG_WARNING, ("ppp_input[%d]: Dropping VJ compressed\n", pcb->netif->num)); + break; + + case PPP_VJC_UNCOMP: /* VJ uncompressed TCP */ + /* + * Process the TCP/IP header for VJ header compression and then pass + * the packet to IP. + */ + PPPDEBUG(LOG_INFO, ("ppp_input[%d]: vj_un in pbuf len=%d\n", pcb->netif->num, pb->tot_len)); + if (pcb->vj_enabled && vj_uncompress_uncomp(pb, &pcb->vj_comp) >= 0) { + ip4_input(pb, pcb->netif); + return; + } + /* Something's wrong so drop it. */ + PPPDEBUG(LOG_WARNING, ("ppp_input[%d]: Dropping VJ uncompressed\n", pcb->netif->num)); + break; +#endif /* VJ_SUPPORT && LWIP_TCP */ + + default: { + int i; + const struct protent *protp; + + /* + * Upcall the proper protocol input routine. + */ + for (i = 0; (protp = protocols[i]) != NULL; ++i) { + if (protp->protocol == protocol) { + pb = ppp_singlebuf(pb); + (*protp->input)(pcb, (u8_t*)pb->payload, pb->len); + goto out; + } +#if 0 /* UNUSED + * + * This is actually a (hacked?) way for the Linux kernel to pass a data + * packet to pppd. pppd in normal condition only do signaling + * (LCP, PAP, CHAP, IPCP, ...) and does not handle any data packet at all. + * + * We don't even need this interface, which is only there because of PPP + * interface limitation between Linux kernel and pppd. For MPPE, which uses + * CCP to negotiate although it is not really a (de)compressor, we added + * ccp_resetrequest() in CCP and MPPE input data flow is calling either + * ccp_resetrequest() or lcp_close() if the issue is, respectively, non-fatal + * or fatal, this is what ccp_datainput() really do. + */ + if (protocol == (protp->protocol & ~0x8000) + && protp->datainput != NULL) { + (*protp->datainput)(pcb, pb->payload, pb->len); + goto out; + } +#endif /* UNUSED */ + } + +#if PPP_DEBUG +#if PPP_PROTOCOLNAME + pname = protocol_name(protocol); + if (pname != NULL) { + ppp_warn("Unsupported protocol '%s' (0x%x) received", pname, protocol); + } else +#endif /* PPP_PROTOCOLNAME */ + ppp_warn("Unsupported protocol 0x%x received", protocol); +#endif /* PPP_DEBUG */ + pbuf_header(pb, (s16_t)sizeof(protocol)); + lcp_sprotrej(pcb, (u8_t*)pb->payload, pb->len); + } + break; + } + +drop: + LINK_STATS_INC(link.drop); + MIB2_STATS_NETIF_INC(pcb->netif, ifindiscards); + +out: + pbuf_free(pb); +} + +/* merge a pbuf chain into one pbuf */ +struct pbuf *ppp_singlebuf(struct pbuf *p) { + struct pbuf *q, *b; + u8_t *pl; + + if(p->tot_len == p->len) { + return p; + } + + q = pbuf_alloc(PBUF_RAW, p->tot_len, PBUF_RAM); + if(!q) { + PPPDEBUG(LOG_ERR, + ("ppp_singlebuf: unable to alloc new buf (%d)\n", p->tot_len)); + return p; /* live dangerously */ + } + + for(b = p, pl = (u8_t*)q->payload; b != NULL; b = b->next) { + MEMCPY(pl, b->payload, b->len); + pl += b->len; + } + + pbuf_free(p); + + return q; +} + +/* + * Write a pbuf to a ppp link, only used from PPP functions + * to send PPP packets. + * + * IPv4 and IPv6 packets from lwIP are sent, respectively, + * with ppp_netif_output_ip4() and ppp_netif_output_ip6() + * functions (which are callbacks of the netif PPP interface). + * + * RETURN: >= 0 Number of characters written + * -1 Failed to write to device + */ +err_t ppp_write(ppp_pcb *pcb, struct pbuf *p) { +#if PRINTPKT_SUPPORT + ppp_dump_packet("sent", (unsigned char *)p->payload+2, p->len-2); +#endif /* PRINTPKT_SUPPORT */ + return pcb->link_cb->write(pcb, pcb->link_ctx_cb, p); +} + +void ppp_link_terminated(ppp_pcb *pcb) { + PPPDEBUG(LOG_DEBUG, ("ppp_link_terminated[%d]\n", pcb->netif->num)); + pcb->link_cb->disconnect(pcb, pcb->link_ctx_cb); + PPPDEBUG(LOG_DEBUG, ("ppp_link_terminated[%d]: finished.\n", pcb->netif->num)); +} + + +/************************************************************************ + * Functions called by various PPP subsystems to configure + * the PPP interface or change the PPP phase. + */ + +/* + * new_phase - signal the start of a new phase of pppd's operation. + */ +void new_phase(ppp_pcb *pcb, int p) { + pcb->phase = p; + PPPDEBUG(LOG_DEBUG, ("ppp phase changed[%d]: phase=%d\n", pcb->netif->num, pcb->phase)); +#if PPP_NOTIFY_PHASE + if (pcb->notify_phase_cb != NULL) { + pcb->notify_phase_cb(pcb, p, pcb->ctx_cb); + } +#endif /* PPP_NOTIFY_PHASE */ +} + +/* + * ppp_send_config - configure the transmit-side characteristics of + * the ppp interface. + */ +int ppp_send_config(ppp_pcb *pcb, int mtu, u32_t accm, int pcomp, int accomp) { + LWIP_UNUSED_ARG(mtu); + /* pcb->mtu = mtu; -- set correctly with netif_set_mtu */ + + if (pcb->link_cb->send_config) { + pcb->link_cb->send_config(pcb, pcb->link_ctx_cb, accm, pcomp, accomp); + } + + PPPDEBUG(LOG_INFO, ("ppp_send_config[%d]\n", pcb->netif->num) ); + return 0; +} + +/* + * ppp_recv_config - configure the receive-side characteristics of + * the ppp interface. + */ +int ppp_recv_config(ppp_pcb *pcb, int mru, u32_t accm, int pcomp, int accomp) { + LWIP_UNUSED_ARG(mru); + + if (pcb->link_cb->recv_config) { + pcb->link_cb->recv_config(pcb, pcb->link_ctx_cb, accm, pcomp, accomp); + } + + PPPDEBUG(LOG_INFO, ("ppp_recv_config[%d]\n", pcb->netif->num)); + return 0; +} + +#if PPP_IPV4_SUPPORT +/* + * sifaddr - Config the interface IP addresses and netmask. + */ +int sifaddr(ppp_pcb *pcb, u32_t our_adr, u32_t his_adr, u32_t netmask) { + ip4_addr_t ip, nm, gw; + + ip4_addr_set_u32(&ip, our_adr); + ip4_addr_set_u32(&nm, netmask); + ip4_addr_set_u32(&gw, his_adr); + netif_set_addr(pcb->netif, &ip, &nm, &gw); + return 1; +} + +/******************************************************************** + * + * cifaddr - Clear the interface IP addresses, and delete routes + * through the interface if possible. + */ +int cifaddr(ppp_pcb *pcb, u32_t our_adr, u32_t his_adr) { + LWIP_UNUSED_ARG(our_adr); + LWIP_UNUSED_ARG(his_adr); + + netif_set_addr(pcb->netif, IP4_ADDR_ANY, IP4_ADDR_BROADCAST, IP4_ADDR_ANY); + return 1; +} + +#if 0 /* UNUSED - PROXY ARP */ +/******************************************************************** + * + * sifproxyarp - Make a proxy ARP entry for the peer. + */ + +int sifproxyarp(ppp_pcb *pcb, u32_t his_adr) { + LWIP_UNUSED_ARG(pcb); + LWIP_UNUSED_ARG(his_adr); + return 0; +} + +/******************************************************************** + * + * cifproxyarp - Delete the proxy ARP entry for the peer. + */ + +int cifproxyarp(ppp_pcb *pcb, u32_t his_adr) { + LWIP_UNUSED_ARG(pcb); + LWIP_UNUSED_ARG(his_adr); + return 0; +} +#endif /* UNUSED - PROXY ARP */ + +#if LWIP_DNS +/* + * sdns - Config the DNS servers + */ +int sdns(ppp_pcb *pcb, u32_t ns1, u32_t ns2) { + ip_addr_t ns; + LWIP_UNUSED_ARG(pcb); + + ip_addr_set_ip4_u32(&ns, ns1); + dns_setserver(0, &ns); + ip_addr_set_ip4_u32(&ns, ns2); + dns_setserver(1, &ns); + return 1; +} + +/******************************************************************** + * + * cdns - Clear the DNS servers + */ +int cdns(ppp_pcb *pcb, u32_t ns1, u32_t ns2) { + ip_addr_t nsa, nsb; + LWIP_UNUSED_ARG(pcb); + + nsa = dns_getserver(0); + ip_addr_set_ip4_u32(&nsb, ns1); + if (ip_addr_cmp(&nsa, &nsb)) { + dns_setserver(0, IP_ADDR_ANY); + } + nsa = dns_getserver(1); + ip_addr_set_ip4_u32(&nsb, ns2); + if (ip_addr_cmp(&nsa, &nsb)) { + dns_setserver(1, IP_ADDR_ANY); + } + return 1; +} +#endif /* LWIP_DNS */ + +#if VJ_SUPPORT +/******************************************************************** + * + * sifvjcomp - config tcp header compression + */ +int sifvjcomp(ppp_pcb *pcb, int vjcomp, int cidcomp, int maxcid) { + pcb->vj_enabled = vjcomp; + pcb->vj_comp.compressSlot = cidcomp; + pcb->vj_comp.maxSlotIndex = maxcid; + PPPDEBUG(LOG_INFO, ("sifvjcomp[%d]: VJ compress enable=%d slot=%d max slot=%d\n", + pcb->netif->num, vjcomp, cidcomp, maxcid)); + return 0; +} +#endif /* VJ_SUPPORT */ + +/* + * sifup - Config the interface up and enable IP packets to pass. + */ +int sifup(ppp_pcb *pcb) { + pcb->if4_up = 1; + pcb->err_code = PPPERR_NONE; + netif_set_link_up(pcb->netif); + + PPPDEBUG(LOG_DEBUG, ("sifup[%d]: err_code=%d\n", pcb->netif->num, pcb->err_code)); + pcb->link_status_cb(pcb, pcb->err_code, pcb->ctx_cb); + return 1; +} + +/******************************************************************** + * + * sifdown - Disable the indicated protocol and config the interface + * down if there are no remaining protocols. + */ +int sifdown(ppp_pcb *pcb) { + + pcb->if4_up = 0; + + if (1 +#if PPP_IPV6_SUPPORT + /* set the interface down if IPv6 is down as well */ + && !pcb->if6_up +#endif /* PPP_IPV6_SUPPORT */ + ) { + /* make sure the netif link callback is called */ + netif_set_link_down(pcb->netif); + } + PPPDEBUG(LOG_DEBUG, ("sifdown[%d]: err_code=%d\n", pcb->netif->num, pcb->err_code)); + return 1; +} + +/******************************************************************** + * + * Return user specified netmask, modified by any mask we might determine + * for address `addr' (in network byte order). + * Here we scan through the system's list of interfaces, looking for + * any non-point-to-point interfaces which might appear to be on the same + * network as `addr'. If we find any, we OR in their netmask to the + * user-specified netmask. + */ +u32_t get_mask(u32_t addr) { +#if 0 + u32_t mask, nmask; + + addr = htonl(addr); + if (IP_CLASSA(addr)) { /* determine network mask for address class */ + nmask = IP_CLASSA_NET; + } else if (IP_CLASSB(addr)) { + nmask = IP_CLASSB_NET; + } else { + nmask = IP_CLASSC_NET; + } + + /* class D nets are disallowed by bad_ip_adrs */ + mask = PP_HTONL(0xffffff00UL) | htonl(nmask); + + /* XXX + * Scan through the system's network interfaces. + * Get each netmask and OR them into our mask. + */ + /* return mask; */ + return mask; +#endif /* 0 */ + LWIP_UNUSED_ARG(addr); + return IPADDR_BROADCAST; +} +#endif /* PPP_IPV4_SUPPORT */ + +#if PPP_IPV6_SUPPORT +#define IN6_LLADDR_FROM_EUI64(ip6, eui64) do { \ + ip6.addr[0] = PP_HTONL(0xfe800000); \ + ip6.addr[1] = 0; \ + eui64_copy(eui64, ip6.addr[2]); \ + } while (0) + +/******************************************************************** + * + * sif6addr - Config the interface with an IPv6 link-local address + */ +int sif6addr(ppp_pcb *pcb, eui64_t our_eui64, eui64_t his_eui64) { + ip6_addr_t ip6; + LWIP_UNUSED_ARG(his_eui64); + + IN6_LLADDR_FROM_EUI64(ip6, our_eui64); + netif_ip6_addr_set(pcb->netif, 0, &ip6); + netif_ip6_addr_set_state(pcb->netif, 0, IP6_ADDR_PREFERRED); + /* FIXME: should we add an IPv6 static neighbor using his_eui64 ? */ + return 1; +} + +/******************************************************************** + * + * cif6addr - Remove IPv6 address from interface + */ +int cif6addr(ppp_pcb *pcb, eui64_t our_eui64, eui64_t his_eui64) { + LWIP_UNUSED_ARG(our_eui64); + LWIP_UNUSED_ARG(his_eui64); + + netif_ip6_addr_set(pcb->netif, 0, IP6_ADDR_ANY6); + netif_ip6_addr_set_state(pcb->netif, 0, IP6_ADDR_INVALID); + return 1; +} + +/* + * sif6up - Config the interface up and enable IPv6 packets to pass. + */ +int sif6up(ppp_pcb *pcb) { + + pcb->if6_up = 1; + pcb->err_code = PPPERR_NONE; + netif_set_link_up(pcb->netif); + + PPPDEBUG(LOG_DEBUG, ("sif6up[%d]: err_code=%d\n", pcb->netif->num, pcb->err_code)); + pcb->link_status_cb(pcb, pcb->err_code, pcb->ctx_cb); + return 1; +} + +/******************************************************************** + * + * sif6down - Disable the indicated protocol and config the interface + * down if there are no remaining protocols. + */ +int sif6down(ppp_pcb *pcb) { + + pcb->if6_up = 0; + + if (1 +#if PPP_IPV4_SUPPORT + /* set the interface down if IPv4 is down as well */ + && !pcb->if4_up +#endif /* PPP_IPV4_SUPPORT */ + ) { + /* make sure the netif link callback is called */ + netif_set_link_down(pcb->netif); + } + PPPDEBUG(LOG_DEBUG, ("sif6down[%d]: err_code=%d\n", pcb->netif->num, pcb->err_code)); + return 1; +} +#endif /* PPP_IPV6_SUPPORT */ + +#if DEMAND_SUPPORT +/* + * sifnpmode - Set the mode for handling packets for a given NP. + */ +int sifnpmode(ppp_pcb *pcb, int proto, enum NPmode mode) { + LWIP_UNUSED_ARG(pcb); + LWIP_UNUSED_ARG(proto); + LWIP_UNUSED_ARG(mode); + return 0; +} +#endif /* DEMAND_SUPPORT */ + +/* + * netif_set_mtu - set the MTU on the PPP network interface. + */ +void netif_set_mtu(ppp_pcb *pcb, int mtu) { + + pcb->netif->mtu = mtu; + PPPDEBUG(LOG_INFO, ("netif_set_mtu[%d]: mtu=%d\n", pcb->netif->num, mtu)); +} + +/* + * netif_get_mtu - get PPP interface MTU + */ +int netif_get_mtu(ppp_pcb *pcb) { + + return pcb->netif->mtu; +} + +#if CCP_SUPPORT +#if 0 /* unused */ +/* + * ccp_test - whether a given compression method is acceptable for use. + */ +int +ccp_test(ppp_pcb *pcb, u_char *opt_ptr, int opt_len, int for_transmit) +{ + LWIP_UNUSED_ARG(pcb); + LWIP_UNUSED_ARG(opt_ptr); + LWIP_UNUSED_ARG(opt_len); + LWIP_UNUSED_ARG(for_transmit); + return -1; +} +#endif /* unused */ + +/* + * ccp_set - inform about the current state of CCP. + */ +void +ccp_set(ppp_pcb *pcb, u8_t isopen, u8_t isup, u8_t receive_method, u8_t transmit_method) +{ + LWIP_UNUSED_ARG(isopen); + LWIP_UNUSED_ARG(isup); + pcb->ccp_receive_method = receive_method; + pcb->ccp_transmit_method = transmit_method; + PPPDEBUG(LOG_DEBUG, ("ccp_set[%d]: is_open=%d, is_up=%d, receive_method=%u, transmit_method=%u\n", + pcb->netif->num, isopen, isup, receive_method, transmit_method)); +} + +void +ccp_reset_comp(ppp_pcb *pcb) +{ + switch (pcb->ccp_transmit_method) { +#if MPPE_SUPPORT + case CI_MPPE: + mppe_comp_reset(pcb, &pcb->mppe_comp); + break; +#endif /* MPPE_SUPPORT */ + default: + break; + } +} + +void +ccp_reset_decomp(ppp_pcb *pcb) +{ + switch (pcb->ccp_receive_method) { +#if MPPE_SUPPORT + case CI_MPPE: + mppe_decomp_reset(pcb, &pcb->mppe_decomp); + break; +#endif /* MPPE_SUPPORT */ + default: + break; + } +} + +#if 0 /* unused */ +/* + * ccp_fatal_error - returns 1 if decompression was disabled as a + * result of an error detected after decompression of a packet, + * 0 otherwise. This is necessary because of patent nonsense. + */ +int +ccp_fatal_error(ppp_pcb *pcb) +{ + LWIP_UNUSED_ARG(pcb); + return 1; +} +#endif /* unused */ +#endif /* CCP_SUPPORT */ + +#if PPP_IDLETIMELIMIT +/******************************************************************** + * + * get_idle_time - return how long the link has been idle. + */ +int get_idle_time(ppp_pcb *pcb, struct ppp_idle *ip) { + /* FIXME: add idle time support and make it optional */ + LWIP_UNUSED_ARG(pcb); + LWIP_UNUSED_ARG(ip); + return 1; +} +#endif /* PPP_IDLETIMELIMIT */ + +#if DEMAND_SUPPORT +/******************************************************************** + * + * get_loop_output - get outgoing packets from the ppp device, + * and detect when we want to bring the real link up. + * Return value is 1 if we need to bring up the link, 0 otherwise. + */ +int get_loop_output(void) { + return 0; +} +#endif /* DEMAND_SUPPORT */ + +#if PPP_PROTOCOLNAME +/* List of protocol names, to make our messages a little more informative. */ +struct protocol_list { + u_short proto; + const char *name; +} protocol_list[] = { + { 0x21, "IP" }, + { 0x23, "OSI Network Layer" }, + { 0x25, "Xerox NS IDP" }, + { 0x27, "DECnet Phase IV" }, + { 0x29, "Appletalk" }, + { 0x2b, "Novell IPX" }, + { 0x2d, "VJ compressed TCP/IP" }, + { 0x2f, "VJ uncompressed TCP/IP" }, + { 0x31, "Bridging PDU" }, + { 0x33, "Stream Protocol ST-II" }, + { 0x35, "Banyan Vines" }, + { 0x39, "AppleTalk EDDP" }, + { 0x3b, "AppleTalk SmartBuffered" }, + { 0x3d, "Multi-Link" }, + { 0x3f, "NETBIOS Framing" }, + { 0x41, "Cisco Systems" }, + { 0x43, "Ascom Timeplex" }, + { 0x45, "Fujitsu Link Backup and Load Balancing (LBLB)" }, + { 0x47, "DCA Remote Lan" }, + { 0x49, "Serial Data Transport Protocol (PPP-SDTP)" }, + { 0x4b, "SNA over 802.2" }, + { 0x4d, "SNA" }, + { 0x4f, "IP6 Header Compression" }, + { 0x51, "KNX Bridging Data" }, + { 0x53, "Encryption" }, + { 0x55, "Individual Link Encryption" }, + { 0x57, "IPv6" }, + { 0x59, "PPP Muxing" }, + { 0x5b, "Vendor-Specific Network Protocol" }, + { 0x61, "RTP IPHC Full Header" }, + { 0x63, "RTP IPHC Compressed TCP" }, + { 0x65, "RTP IPHC Compressed non-TCP" }, + { 0x67, "RTP IPHC Compressed UDP 8" }, + { 0x69, "RTP IPHC Compressed RTP 8" }, + { 0x6f, "Stampede Bridging" }, + { 0x73, "MP+" }, + { 0xc1, "NTCITS IPI" }, + { 0xfb, "single-link compression" }, + { 0xfd, "Compressed Datagram" }, + { 0x0201, "802.1d Hello Packets" }, + { 0x0203, "IBM Source Routing BPDU" }, + { 0x0205, "DEC LANBridge100 Spanning Tree" }, + { 0x0207, "Cisco Discovery Protocol" }, + { 0x0209, "Netcs Twin Routing" }, + { 0x020b, "STP - Scheduled Transfer Protocol" }, + { 0x020d, "EDP - Extreme Discovery Protocol" }, + { 0x0211, "Optical Supervisory Channel Protocol" }, + { 0x0213, "Optical Supervisory Channel Protocol" }, + { 0x0231, "Luxcom" }, + { 0x0233, "Sigma Network Systems" }, + { 0x0235, "Apple Client Server Protocol" }, + { 0x0281, "MPLS Unicast" }, + { 0x0283, "MPLS Multicast" }, + { 0x0285, "IEEE p1284.4 standard - data packets" }, + { 0x0287, "ETSI TETRA Network Protocol Type 1" }, + { 0x0289, "Multichannel Flow Treatment Protocol" }, + { 0x2063, "RTP IPHC Compressed TCP No Delta" }, + { 0x2065, "RTP IPHC Context State" }, + { 0x2067, "RTP IPHC Compressed UDP 16" }, + { 0x2069, "RTP IPHC Compressed RTP 16" }, + { 0x4001, "Cray Communications Control Protocol" }, + { 0x4003, "CDPD Mobile Network Registration Protocol" }, + { 0x4005, "Expand accelerator protocol" }, + { 0x4007, "ODSICP NCP" }, + { 0x4009, "DOCSIS DLL" }, + { 0x400B, "Cetacean Network Detection Protocol" }, + { 0x4021, "Stacker LZS" }, + { 0x4023, "RefTek Protocol" }, + { 0x4025, "Fibre Channel" }, + { 0x4027, "EMIT Protocols" }, + { 0x405b, "Vendor-Specific Protocol (VSP)" }, + { 0x8021, "Internet Protocol Control Protocol" }, + { 0x8023, "OSI Network Layer Control Protocol" }, + { 0x8025, "Xerox NS IDP Control Protocol" }, + { 0x8027, "DECnet Phase IV Control Protocol" }, + { 0x8029, "Appletalk Control Protocol" }, + { 0x802b, "Novell IPX Control Protocol" }, + { 0x8031, "Bridging NCP" }, + { 0x8033, "Stream Protocol Control Protocol" }, + { 0x8035, "Banyan Vines Control Protocol" }, + { 0x803d, "Multi-Link Control Protocol" }, + { 0x803f, "NETBIOS Framing Control Protocol" }, + { 0x8041, "Cisco Systems Control Protocol" }, + { 0x8043, "Ascom Timeplex" }, + { 0x8045, "Fujitsu LBLB Control Protocol" }, + { 0x8047, "DCA Remote Lan Network Control Protocol (RLNCP)" }, + { 0x8049, "Serial Data Control Protocol (PPP-SDCP)" }, + { 0x804b, "SNA over 802.2 Control Protocol" }, + { 0x804d, "SNA Control Protocol" }, + { 0x804f, "IP6 Header Compression Control Protocol" }, + { 0x8051, "KNX Bridging Control Protocol" }, + { 0x8053, "Encryption Control Protocol" }, + { 0x8055, "Individual Link Encryption Control Protocol" }, + { 0x8057, "IPv6 Control Protocol" }, + { 0x8059, "PPP Muxing Control Protocol" }, + { 0x805b, "Vendor-Specific Network Control Protocol (VSNCP)" }, + { 0x806f, "Stampede Bridging Control Protocol" }, + { 0x8073, "MP+ Control Protocol" }, + { 0x80c1, "NTCITS IPI Control Protocol" }, + { 0x80fb, "Single Link Compression Control Protocol" }, + { 0x80fd, "Compression Control Protocol" }, + { 0x8207, "Cisco Discovery Protocol Control" }, + { 0x8209, "Netcs Twin Routing" }, + { 0x820b, "STP - Control Protocol" }, + { 0x820d, "EDPCP - Extreme Discovery Protocol Ctrl Prtcl" }, + { 0x8235, "Apple Client Server Protocol Control" }, + { 0x8281, "MPLSCP" }, + { 0x8285, "IEEE p1284.4 standard - Protocol Control" }, + { 0x8287, "ETSI TETRA TNP1 Control Protocol" }, + { 0x8289, "Multichannel Flow Treatment Protocol" }, + { 0xc021, "Link Control Protocol" }, + { 0xc023, "Password Authentication Protocol" }, + { 0xc025, "Link Quality Report" }, + { 0xc027, "Shiva Password Authentication Protocol" }, + { 0xc029, "CallBack Control Protocol (CBCP)" }, + { 0xc02b, "BACP Bandwidth Allocation Control Protocol" }, + { 0xc02d, "BAP" }, + { 0xc05b, "Vendor-Specific Authentication Protocol (VSAP)" }, + { 0xc081, "Container Control Protocol" }, + { 0xc223, "Challenge Handshake Authentication Protocol" }, + { 0xc225, "RSA Authentication Protocol" }, + { 0xc227, "Extensible Authentication Protocol" }, + { 0xc229, "Mitsubishi Security Info Exch Ptcl (SIEP)" }, + { 0xc26f, "Stampede Bridging Authorization Protocol" }, + { 0xc281, "Proprietary Authentication Protocol" }, + { 0xc283, "Proprietary Authentication Protocol" }, + { 0xc481, "Proprietary Node ID Authentication Protocol" }, + { 0, NULL }, +}; + +/* + * protocol_name - find a name for a PPP protocol. + */ +const char * protocol_name(int proto) { + struct protocol_list *lp; + + for (lp = protocol_list; lp->proto != 0; ++lp) { + if (proto == lp->proto) { + return lp->name; + } + } + return NULL; +} +#endif /* PPP_PROTOCOLNAME */ + +#if PPP_STATS_SUPPORT + +/* ---- Note on PPP Stats support ---- + * + * The one willing link stats support should add the get_ppp_stats() + * to fetch statistics from lwIP. + */ + +/* + * reset_link_stats - "reset" stats when link goes up. + */ +void reset_link_stats(int u) { + if (!get_ppp_stats(u, &old_link_stats)) { + return; + } + gettimeofday(&start_time, NULL); +} + +/* + * update_link_stats - get stats at link termination. + */ +void update_link_stats(int u) { + struct timeval now; + char numbuf[32]; + + if (!get_ppp_stats(u, &link_stats) || gettimeofday(&now, NULL) < 0) { + return; + } + link_connect_time = now.tv_sec - start_time.tv_sec; + link_stats_valid = 1; + + link_stats.bytes_in -= old_link_stats.bytes_in; + link_stats.bytes_out -= old_link_stats.bytes_out; + link_stats.pkts_in -= old_link_stats.pkts_in; + link_stats.pkts_out -= old_link_stats.pkts_out; +} + +void print_link_stats() { + /* + * Print connect time and statistics. + */ + if (link_stats_valid) { + int t = (link_connect_time + 5) / 6; /* 1/10ths of minutes */ + info("Connect time %d.%d minutes.", t/10, t%10); + info("Sent %u bytes, received %u bytes.", link_stats.bytes_out, link_stats.bytes_in); + link_stats_valid = 0; + } +} +#endif /* PPP_STATS_SUPPORT */ + +#endif /* PPP_SUPPORT */ diff --git a/components/lwip/netif/ppp/pppcrypt.c b/components/lwip/netif/ppp/pppcrypt.c new file mode 100755 index 0000000000..097f702b3d --- /dev/null +++ b/components/lwip/netif/ppp/pppcrypt.c @@ -0,0 +1,66 @@ +/* + * pppcrypt.c - PPP/DES linkage for MS-CHAP and EAP SRP-SHA1 + * + * Extracted from chap_ms.c by James Carlson. + * + * Copyright (c) 1995 Eric Rosenquist. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. The name(s) of the authors of this software must not be used to + * endorse or promote products derived from this software without + * prior written permission. + * + * THE AUTHORS OF THIS SOFTWARE DISCLAIM ALL WARRANTIES WITH REGARD TO + * THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS, IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY + * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN + * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING + * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include "lwip/opt.h" +#if PPP_SUPPORT && MSCHAP_SUPPORT /* don't build if not necessary */ + +#include "netif/ppp/ppp_impl.h" + +#include "netif/ppp/pppcrypt.h" + + +static u_char pppcrypt_get_7bits(u_char *input, int startBit) { + unsigned int word; + + word = (unsigned)input[startBit / 8] << 8; + word |= (unsigned)input[startBit / 8 + 1]; + + word >>= 15 - (startBit % 8 + 7); + + return word & 0xFE; +} + +/* IN 56 bit DES key missing parity bits + * OUT 64 bit DES key with parity bits added + */ +void pppcrypt_56_to_64_bit_key(u_char *key, u_char * des_key) { + des_key[0] = pppcrypt_get_7bits(key, 0); + des_key[1] = pppcrypt_get_7bits(key, 7); + des_key[2] = pppcrypt_get_7bits(key, 14); + des_key[3] = pppcrypt_get_7bits(key, 21); + des_key[4] = pppcrypt_get_7bits(key, 28); + des_key[5] = pppcrypt_get_7bits(key, 35); + des_key[6] = pppcrypt_get_7bits(key, 42); + des_key[7] = pppcrypt_get_7bits(key, 49); +} + +#endif /* PPP_SUPPORT && MSCHAP_SUPPORT */ diff --git a/components/lwip/netif/ppp/pppoe.c b/components/lwip/netif/ppp/pppoe.c new file mode 100755 index 0000000000..586708b5ea --- /dev/null +++ b/components/lwip/netif/ppp/pppoe.c @@ -0,0 +1,1250 @@ +/***************************************************************************** +* pppoe.c - PPP Over Ethernet implementation for lwIP. +* +* Copyright (c) 2006 by Marc Boucher, Services Informatiques (MBSI) inc. +* +* The authors hereby grant permission to use, copy, modify, distribute, +* and license this software and its documentation for any purpose, provided +* that existing copyright notices are retained in all copies and that this +* notice and the following disclaimer are included verbatim in any +* distributions. No written agreement, license, or royalty fee is required +* for any of the authorized uses. +* +* THIS SOFTWARE IS PROVIDED BY THE CONTRIBUTORS *AS IS* AND ANY EXPRESS OR +* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES +* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +* IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF +* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +* +****************************************************************************** +* REVISION HISTORY +* +* 06-01-01 Marc Boucher +* Ported to lwIP. +*****************************************************************************/ + + + +/* based on NetBSD: if_pppoe.c,v 1.64 2006/01/31 23:50:15 martin Exp */ + +/*- + * Copyright (c) 2002 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by Martin Husemann . + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the NetBSD + * Foundation, Inc. and its contributors. + * 4. Neither the name of The NetBSD Foundation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#include "lwip/opt.h" +#if PPP_SUPPORT && PPPOE_SUPPORT /* don't build if not configured for use in lwipopts.h */ + +#if 0 /* UNUSED */ +#include +#include +#endif /* UNUSED */ + +#include "lwip/timers.h" +#include "lwip/memp.h" +#include "lwip/stats.h" +#include "lwip/snmp.h" + +#include "netif/ppp/ppp_impl.h" +#include "netif/ppp/lcp.h" +#include "netif/ppp/ipcp.h" +#include "netif/ppp/pppoe.h" + +/* Add a 16 bit unsigned value to a buffer pointed to by PTR */ +#define PPPOE_ADD_16(PTR, VAL) \ + *(PTR)++ = (u8_t)((VAL) / 256); \ + *(PTR)++ = (u8_t)((VAL) % 256) + +/* Add a complete PPPoE header to the buffer pointed to by PTR */ +#define PPPOE_ADD_HEADER(PTR, CODE, SESS, LEN) \ + *(PTR)++ = PPPOE_VERTYPE; \ + *(PTR)++ = (CODE); \ + PPPOE_ADD_16(PTR, SESS); \ + PPPOE_ADD_16(PTR, LEN) + +#define PPPOE_DISC_TIMEOUT (5*1000) /* base for quick timeout calculation */ +#define PPPOE_SLOW_RETRY (60*1000) /* persistent retry interval */ +#define PPPOE_DISC_MAXPADI 4 /* retry PADI four times (quickly) */ +#define PPPOE_DISC_MAXPADR 2 /* retry PADR twice */ + +#ifdef PPPOE_SERVER +#error "PPPOE_SERVER is not yet supported under lwIP!" +/* from if_spppsubr.c */ +#define IFF_PASSIVE IFF_LINK0 /* wait passively for connection */ +#endif + +#define PPPOE_ERRORSTRING_LEN 64 + + +/* callbacks called from PPP core */ +static err_t pppoe_write(ppp_pcb *ppp, void *ctx, struct pbuf *p); +static err_t pppoe_netif_output(ppp_pcb *ppp, void *ctx, struct pbuf *p, u_short protocol); +static err_t pppoe_connect(ppp_pcb *ppp, void *ctx); +static void pppoe_disconnect(ppp_pcb *ppp, void *ctx); +static err_t pppoe_destroy(ppp_pcb *ppp, void *ctx); + +/* management routines */ +static void pppoe_abort_connect(struct pppoe_softc *); +#if 0 /* UNUSED */ +static void pppoe_clear_softc(struct pppoe_softc *, const char *); +#endif /* UNUSED */ + +/* internal timeout handling */ +static void pppoe_timeout(void *); + +/* sending actual protocol controll packets */ +static err_t pppoe_send_padi(struct pppoe_softc *); +static err_t pppoe_send_padr(struct pppoe_softc *); +#ifdef PPPOE_SERVER +static err_t pppoe_send_pado(struct pppoe_softc *); +static err_t pppoe_send_pads(struct pppoe_softc *); +#endif +static err_t pppoe_send_padt(struct netif *, u_int, const u8_t *); + +/* internal helper functions */ +static err_t pppoe_xmit(struct pppoe_softc *sc, struct pbuf *pb); +static struct pppoe_softc* pppoe_find_softc_by_session(u_int session, struct netif *rcvif); +static struct pppoe_softc* pppoe_find_softc_by_hunique(u8_t *token, size_t len, struct netif *rcvif); + +/** linked list of created pppoe interfaces */ +static struct pppoe_softc *pppoe_softc_list; + +/* Callbacks structure for PPP core */ +static const struct link_callbacks pppoe_callbacks = { + pppoe_connect, +#if PPP_SERVER + NULL, +#endif /* PPP_SERVER */ + pppoe_disconnect, + pppoe_destroy, + pppoe_write, + pppoe_netif_output, + NULL, + NULL +}; + +/* + * Create a new PPP Over Ethernet (PPPoE) connection. + * + * Return 0 on success, an error code on failure. + */ +ppp_pcb *pppoe_create(struct netif *pppif, + struct netif *ethif, + const char *service_name, const char *concentrator_name, + ppp_link_status_cb_fn link_status_cb, void *ctx_cb) +{ + ppp_pcb *ppp; + struct pppoe_softc *sc; + LWIP_UNUSED_ARG(service_name); + LWIP_UNUSED_ARG(concentrator_name); + + sc = (struct pppoe_softc *)memp_malloc(MEMP_PPPOE_IF); + if (sc == NULL) { + return NULL; + } + + ppp = ppp_new(pppif, &pppoe_callbacks, sc, link_status_cb, ctx_cb); + if (ppp == NULL) { + memp_free(MEMP_PPPOE_IF, sc); + return NULL; + } + + memset(sc, 0, sizeof(struct pppoe_softc)); + /* changed to real address later */ + MEMCPY(&sc->sc_dest, ethbroadcast.addr, sizeof(sc->sc_dest)); + sc->pcb = ppp; + sc->sc_ethif = ethif; + /* put the new interface at the head of the list */ + sc->next = pppoe_softc_list; + pppoe_softc_list = sc; + return ppp; +} + +/* Called by PPP core */ +static err_t pppoe_write(ppp_pcb *ppp, void *ctx, struct pbuf *p) { + struct pppoe_softc *sc = (struct pppoe_softc *)ctx; + struct pbuf *ph; /* Ethernet + PPPoE header */ + err_t ret; +#if MIB2_STATS + u16_t tot_len; +#else /* MIB2_STATS */ + LWIP_UNUSED_ARG(ppp); +#endif /* MIB2_STATS */ + + /* skip address & flags */ + pbuf_header(p, -(s16_t)2); + + ph = pbuf_alloc(PBUF_LINK, (u16_t)(PPPOE_HEADERLEN), PBUF_RAM); + if(!ph) { + LINK_STATS_INC(link.memerr); + LINK_STATS_INC(link.proterr); + MIB2_STATS_NETIF_INC(ppp->netif, ifoutdiscards); + pbuf_free(p); + return ERR_MEM; + } + + pbuf_header(ph, -(s16_t)PPPOE_HEADERLEN); /* hide PPPoE header */ + pbuf_cat(ph, p); +#if MIB2_STATS + tot_len = ph->tot_len; +#endif /* MIB2_STATS */ + + ret = pppoe_xmit(sc, ph); + if (ret != ERR_OK) { + LINK_STATS_INC(link.err); + MIB2_STATS_NETIF_INC(ppp->netif, ifoutdiscards); + return ret; + } + + MIB2_STATS_NETIF_ADD(ppp->netif, ifoutoctets, (u16_t)tot_len); + MIB2_STATS_NETIF_INC(ppp->netif, ifoutucastpkts); + LINK_STATS_INC(link.xmit); + return ERR_OK; +} + +/* Called by PPP core */ +static err_t pppoe_netif_output(ppp_pcb *ppp, void *ctx, struct pbuf *p, u_short protocol) { + struct pppoe_softc *sc = (struct pppoe_softc *)ctx; + struct pbuf *pb; + u8_t *pl; + err_t err; +#if MIB2_STATS + u16_t tot_len; +#else /* MIB2_STATS */ + LWIP_UNUSED_ARG(ppp); +#endif /* MIB2_STATS */ + + /* @todo: try to use pbuf_header() here! */ + pb = pbuf_alloc(PBUF_LINK, PPPOE_HEADERLEN + sizeof(protocol), PBUF_RAM); + if(!pb) { + LINK_STATS_INC(link.memerr); + LINK_STATS_INC(link.proterr); + MIB2_STATS_NETIF_INC(ppp->netif, ifoutdiscards); + return ERR_MEM; + } + + pbuf_header(pb, -(s16_t)PPPOE_HEADERLEN); + + pl = (u8_t*)pb->payload; + PUTSHORT(protocol, pl); + + pbuf_chain(pb, p); +#if MIB2_STATS + tot_len = pb->tot_len; +#endif /* MIB2_STATS */ + + if( (err = pppoe_xmit(sc, pb)) != ERR_OK) { + LINK_STATS_INC(link.err); + MIB2_STATS_NETIF_INC(ppp->netif, ifoutdiscards); + return err; + } + + MIB2_STATS_NETIF_ADD(ppp->netif, ifoutoctets, tot_len); + MIB2_STATS_NETIF_INC(ppp->netif, ifoutucastpkts); + LINK_STATS_INC(link.xmit); + return ERR_OK; +} + +static err_t +pppoe_destroy(ppp_pcb *ppp, void *ctx) +{ + struct pppoe_softc *sc = (struct pppoe_softc *)ctx; + struct pppoe_softc **copp, *freep; + LWIP_UNUSED_ARG(ppp); + + sys_untimeout(pppoe_timeout, sc); + + /* remove interface from list */ + for (copp = &pppoe_softc_list; (freep = *copp); copp = &freep->next) { + if (freep == sc) { + *copp = freep->next; + break; + } + } + +#ifdef PPPOE_TODO + if (sc->sc_concentrator_name) { + mem_free(sc->sc_concentrator_name); + } + if (sc->sc_service_name) { + mem_free(sc->sc_service_name); + } +#endif /* PPPOE_TODO */ + memp_free(MEMP_PPPOE_IF, sc); + + return ERR_OK; +} + +/* + * Find the interface handling the specified session. + * Note: O(number of sessions open), this is a client-side only, mean + * and lean implementation, so number of open sessions typically should + * be 1. + */ +static struct pppoe_softc* pppoe_find_softc_by_session(u_int session, struct netif *rcvif) { + struct pppoe_softc *sc; + + if (session == 0) { + return NULL; + } + + for (sc = pppoe_softc_list; sc != NULL; sc = sc->next) { + if (sc->sc_state == PPPOE_STATE_SESSION + && sc->sc_session == session + && sc->sc_ethif == rcvif) { + return sc; + } + } + return NULL; +} + +/* Check host unique token passed and return appropriate softc pointer, + * or NULL if token is bogus. */ +static struct pppoe_softc* pppoe_find_softc_by_hunique(u8_t *token, size_t len, struct netif *rcvif) { + struct pppoe_softc *sc, *t; + + if (pppoe_softc_list == NULL) { + return NULL; + } + + if (len != sizeof sc) { + return NULL; + } + MEMCPY(&t, token, len); + + for (sc = pppoe_softc_list; sc != NULL; sc = sc->next) { + if (sc == t) { + break; + } + } + + if (sc == NULL) { + PPPDEBUG(LOG_DEBUG, ("pppoe: alien host unique tag, no session found\n")); + return NULL; + } + + /* should be safe to access *sc now */ + if (sc->sc_state < PPPOE_STATE_PADI_SENT || sc->sc_state >= PPPOE_STATE_SESSION) { + PPPDEBUG(LOG_DEBUG, ("%c%c%"U16_F": host unique tag found, but it belongs to a connection in state %d\n", + sc->sc_ethif->name[0], sc->sc_ethif->name[1], sc->sc_ethif->num, sc->sc_state)); + return NULL; + } + if (sc->sc_ethif != rcvif) { + PPPDEBUG(LOG_DEBUG, ("%c%c%"U16_F": wrong interface, not accepting host unique\n", + sc->sc_ethif->name[0], sc->sc_ethif->name[1], sc->sc_ethif->num)); + return NULL; + } + return sc; +} + +/* analyze and handle a single received packet while not in session state */ +void +pppoe_disc_input(struct netif *netif, struct pbuf *pb) +{ + u16_t tag, len; + u16_t session, plen; + struct pppoe_softc *sc; +#if PPP_DEBUG + const char *err_msg = NULL; +#endif /* PPP_DEBUG */ + u8_t *ac_cookie; + u16_t ac_cookie_len; +#ifdef PPPOE_SERVER + u8_t *hunique; + size_t hunique_len; +#endif + struct pppoehdr *ph; + struct pppoetag pt; + int off, err; + struct eth_hdr *ethhdr; + + /* don't do anything if there is not a single PPPoE instance */ + if (pppoe_softc_list == NULL) { + pbuf_free(pb); + return; + } + + pb = ppp_singlebuf(pb); + + if (pb->len < sizeof(*ethhdr)) { + goto done; + } + ethhdr = (struct eth_hdr *)pb->payload; + off = sizeof(*ethhdr); + + ac_cookie = NULL; + ac_cookie_len = 0; +#ifdef PPPOE_SERVER + hunique = NULL; + hunique_len = 0; +#endif + session = 0; + if (pb->len - off < (u16_t)PPPOE_HEADERLEN) { + PPPDEBUG(LOG_DEBUG, ("pppoe: packet too short: %d\n", pb->len)); + goto done; + } + + ph = (struct pppoehdr *) (ethhdr + 1); + if (ph->vertype != PPPOE_VERTYPE) { + PPPDEBUG(LOG_DEBUG, ("pppoe: unknown version/type packet: 0x%x\n", ph->vertype)); + goto done; + } + session = ntohs(ph->session); + plen = ntohs(ph->plen); + off += sizeof(*ph); + + if (plen + off > pb->len) { + PPPDEBUG(LOG_DEBUG, ("pppoe: packet content does not fit: data available = %d, packet size = %u\n", + pb->len - off, plen)); + goto done; + } + if(pb->tot_len == pb->len) { + pb->tot_len = pb->len = (u16_t)off + plen; /* ignore trailing garbage */ + } + tag = 0; + len = 0; + sc = NULL; + while (off + sizeof(pt) <= pb->len) { + MEMCPY(&pt, (u8_t*)pb->payload + off, sizeof(pt)); + tag = ntohs(pt.tag); + len = ntohs(pt.len); + if (off + sizeof(pt) + len > pb->len) { + PPPDEBUG(LOG_DEBUG, ("pppoe: tag 0x%x len 0x%x is too long\n", tag, len)); + goto done; + } + switch (tag) { + case PPPOE_TAG_EOL: + goto breakbreak; + case PPPOE_TAG_SNAME: + break; /* ignored */ + case PPPOE_TAG_ACNAME: + break; /* ignored */ + case PPPOE_TAG_HUNIQUE: + if (sc != NULL) { + break; + } +#ifdef PPPOE_SERVER + hunique = (u8_t*)pb->payload + off + sizeof(pt); + hunique_len = len; +#endif + sc = pppoe_find_softc_by_hunique((u8_t*)pb->payload + off + sizeof(pt), len, netif); + break; + case PPPOE_TAG_ACCOOKIE: + if (ac_cookie == NULL) { + ac_cookie = (u8_t*)pb->payload + off + sizeof(pt); + ac_cookie_len = len; + } + break; +#if PPP_DEBUG + case PPPOE_TAG_SNAME_ERR: + err_msg = "SERVICE NAME ERROR"; + break; + case PPPOE_TAG_ACSYS_ERR: + err_msg = "AC SYSTEM ERROR"; + break; + case PPPOE_TAG_GENERIC_ERR: + err_msg = "GENERIC ERROR"; + break; +#endif /* PPP_DEBUG */ + default: + break; + } +#if PPP_DEBUG + if (err_msg != NULL) { + char error_tmp[PPPOE_ERRORSTRING_LEN]; + u16_t error_len = LWIP_MIN(len, sizeof(error_tmp)-1); + strncpy(error_tmp, (char*)pb->payload + off + sizeof(pt), error_len); + error_tmp[error_len] = '\0'; + if (sc) { + PPPDEBUG(LOG_DEBUG, ("pppoe: %c%c%"U16_F": %s: %s\n", sc->sc_ethif->name[0], sc->sc_ethif->name[1], sc->sc_ethif->num, err_msg, error_tmp)); + } else { + PPPDEBUG(LOG_DEBUG, ("pppoe: %s: %s\n", err_msg, error_tmp)); + } + } +#endif /* PPP_DEBUG */ + off += sizeof(pt) + len; + } + +breakbreak:; + switch (ph->code) { + case PPPOE_CODE_PADI: +#ifdef PPPOE_SERVER + /* + * got service name, concentrator name, and/or host unique. + * ignore if we have no interfaces with IFF_PASSIVE|IFF_UP. + */ + if (LIST_EMPTY(&pppoe_softc_list)) { + goto done; + } + LIST_FOREACH(sc, &pppoe_softc_list, sc_list) { + if (!(sc->sc_sppp.pp_if.if_flags & IFF_UP)) { + continue; + } + if (!(sc->sc_sppp.pp_if.if_flags & IFF_PASSIVE)) { + continue; + } + if (sc->sc_state == PPPOE_STATE_INITIAL) { + break; + } + } + if (sc == NULL) { + /* PPPDEBUG(LOG_DEBUG, ("pppoe: free passive interface is not found\n")); */ + goto done; + } + if (hunique) { + if (sc->sc_hunique) { + mem_free(sc->sc_hunique); + } + sc->sc_hunique = mem_malloc(hunique_len); + if (sc->sc_hunique == NULL) { + goto done; + } + sc->sc_hunique_len = hunique_len; + MEMCPY(sc->sc_hunique, hunique, hunique_len); + } + MEMCPY(&sc->sc_dest, eh->ether_shost, sizeof sc->sc_dest); + sc->sc_state = PPPOE_STATE_PADO_SENT; + pppoe_send_pado(sc); + break; +#endif /* PPPOE_SERVER */ + case PPPOE_CODE_PADR: +#ifdef PPPOE_SERVER + /* + * get sc from ac_cookie if IFF_PASSIVE + */ + if (ac_cookie == NULL) { + /* be quiet if there is not a single pppoe instance */ + PPPDEBUG(LOG_DEBUG, ("pppoe: received PADR but not includes ac_cookie\n")); + goto done; + } + sc = pppoe_find_softc_by_hunique(ac_cookie, ac_cookie_len, netif); + if (sc == NULL) { + /* be quiet if there is not a single pppoe instance */ + if (!LIST_EMPTY(&pppoe_softc_list)) { + PPPDEBUG(LOG_DEBUG, ("pppoe: received PADR but could not find request for it\n")); + } + goto done; + } + if (sc->sc_state != PPPOE_STATE_PADO_SENT) { + PPPDEBUG(LOG_DEBUG, ("%c%c%"U16_F": received unexpected PADR\n", sc->sc_ethif->name[0], sc->sc_ethif->name[1], sc->sc_ethif->num)); + goto done; + } + if (hunique) { + if (sc->sc_hunique) { + mem_free(sc->sc_hunique); + } + sc->sc_hunique = mem_malloc(hunique_len); + if (sc->sc_hunique == NULL) { + goto done; + } + sc->sc_hunique_len = hunique_len; + MEMCPY(sc->sc_hunique, hunique, hunique_len); + } + pppoe_send_pads(sc); + sc->sc_state = PPPOE_STATE_SESSION; + ppp_start(sc->pcb); /* notify upper layers */ + break; +#else + /* ignore, we are no access concentrator */ + goto done; +#endif /* PPPOE_SERVER */ + case PPPOE_CODE_PADO: + if (sc == NULL) { + /* be quiet if there is not a single pppoe instance */ + if (pppoe_softc_list != NULL) { + PPPDEBUG(LOG_DEBUG, ("pppoe: received PADO but could not find request for it\n")); + } + goto done; + } + if (sc->sc_state != PPPOE_STATE_PADI_SENT) { + PPPDEBUG(LOG_DEBUG, ("%c%c%"U16_F": received unexpected PADO\n", sc->sc_ethif->name[0], sc->sc_ethif->name[1], sc->sc_ethif->num)); + goto done; + } + if (ac_cookie) { + sc->sc_ac_cookie_len = ac_cookie_len; + MEMCPY(sc->sc_ac_cookie, ac_cookie, ac_cookie_len); + } + MEMCPY(&sc->sc_dest, ethhdr->src.addr, sizeof(sc->sc_dest.addr)); + sys_untimeout(pppoe_timeout, sc); + sc->sc_padr_retried = 0; + sc->sc_state = PPPOE_STATE_PADR_SENT; + if ((err = pppoe_send_padr(sc)) != 0) { + PPPDEBUG(LOG_DEBUG, ("pppoe: %c%c%"U16_F": failed to send PADR, error=%d\n", sc->sc_ethif->name[0], sc->sc_ethif->name[1], sc->sc_ethif->num, err)); + } + sys_timeout(PPPOE_DISC_TIMEOUT * (1 + sc->sc_padr_retried), pppoe_timeout, sc); + break; + case PPPOE_CODE_PADS: + if (sc == NULL) { + goto done; + } + sc->sc_session = session; + sys_untimeout(pppoe_timeout, sc); + PPPDEBUG(LOG_DEBUG, ("pppoe: %c%c%"U16_F": session 0x%x connected\n", sc->sc_ethif->name[0], sc->sc_ethif->name[1], sc->sc_ethif->num, session)); + sc->sc_state = PPPOE_STATE_SESSION; + ppp_start(sc->pcb); /* notify upper layers */ + break; + case PPPOE_CODE_PADT: + /* Don't disconnect here, we let the LCP Echo/Reply find the fact + * that PPP session is down. Asking the PPP stack to end the session + * require strict checking about the PPP phase to prevent endless + * disconnection loops. + */ +#if 0 /* UNUSED */ + if (sc == NULL) { /* PADT frames are rarely sent with a hunique tag, this is actually almost always true */ + goto done; + } + pppoe_clear_softc(sc, "received PADT"); +#endif /* UNUSED */ + break; + default: + if(sc) { + PPPDEBUG(LOG_DEBUG, ("%c%c%"U16_F": unknown code (0x%"X16_F") session = 0x%"X16_F"\n", + sc->sc_ethif->name[0], sc->sc_ethif->name[1], sc->sc_ethif->num, + (u16_t)ph->code, session)); + } else { + PPPDEBUG(LOG_DEBUG, ("pppoe: unknown code (0x%"X16_F") session = 0x%"X16_F"\n", (u16_t)ph->code, session)); + } + break; + } + +done: + pbuf_free(pb); + return; +} + +void +pppoe_data_input(struct netif *netif, struct pbuf *pb) +{ + u16_t session, plen; + struct pppoe_softc *sc; + struct pppoehdr *ph; +#ifdef PPPOE_TERM_UNKNOWN_SESSIONS + u8_t shost[ETHER_ADDR_LEN]; +#endif + +#ifdef PPPOE_TERM_UNKNOWN_SESSIONS + MEMCPY(shost, ((struct eth_hdr *)pb->payload)->src.addr, sizeof(shost)); +#endif + if (pbuf_header(pb, -(s16_t)sizeof(struct eth_hdr)) != 0) { + /* bail out */ + PPPDEBUG(LOG_ERR, ("pppoe_data_input: pbuf_header failed\n")); + LINK_STATS_INC(link.lenerr); + goto drop; + } + + if (pb->len < sizeof(*ph)) { + PPPDEBUG(LOG_DEBUG, ("pppoe_data_input: could not get PPPoE header\n")); + goto drop; + } + ph = (struct pppoehdr *)pb->payload; + + if (ph->vertype != PPPOE_VERTYPE) { + PPPDEBUG(LOG_DEBUG, ("pppoe (data): unknown version/type packet: 0x%x\n", ph->vertype)); + goto drop; + } + if (ph->code != 0) { + goto drop; + } + + session = ntohs(ph->session); + sc = pppoe_find_softc_by_session(session, netif); + if (sc == NULL) { +#ifdef PPPOE_TERM_UNKNOWN_SESSIONS + PPPDEBUG(LOG_DEBUG, ("pppoe: input for unknown session 0x%x, sending PADT\n", session)); + pppoe_send_padt(netif, session, shost); +#endif + goto drop; + } + + plen = ntohs(ph->plen); + + if (pbuf_header(pb, -(s16_t)(PPPOE_HEADERLEN)) != 0) { + /* bail out */ + PPPDEBUG(LOG_ERR, ("pppoe_data_input: pbuf_header PPPOE_HEADERLEN failed\n")); + LINK_STATS_INC(link.lenerr); + goto drop; + } + + PPPDEBUG(LOG_DEBUG, ("pppoe_data_input: %c%c%"U16_F": pkthdr.len=%d, pppoe.len=%d\n", + sc->sc_ethif->name[0], sc->sc_ethif->name[1], sc->sc_ethif->num, + pb->len, plen)); + + if (pb->tot_len < plen) { + goto drop; + } + + /* Dispatch the packet thereby consuming it. */ + ppp_input(sc->pcb, pb); + return; + +drop: + pbuf_free(pb); +} + +static err_t +pppoe_output(struct pppoe_softc *sc, struct pbuf *pb) +{ + struct eth_hdr *ethhdr; + u16_t etype; + err_t res; + + if (!sc->sc_ethif) { + pbuf_free(pb); + return ERR_IF; + } + + /* make room for Ethernet header - should not fail */ + if (pbuf_header(pb, (s16_t)(sizeof(struct eth_hdr))) != 0) { + /* bail out */ + PPPDEBUG(LOG_ERR, ("pppoe: %c%c%"U16_F": pppoe_output: could not allocate room for Ethernet header\n", sc->sc_ethif->name[0], sc->sc_ethif->name[1], sc->sc_ethif->num)); + LINK_STATS_INC(link.lenerr); + pbuf_free(pb); + return ERR_BUF; + } + ethhdr = (struct eth_hdr *)pb->payload; + etype = sc->sc_state == PPPOE_STATE_SESSION ? ETHTYPE_PPPOE : ETHTYPE_PPPOEDISC; + ethhdr->type = htons(etype); + MEMCPY(ðhdr->dest.addr, &sc->sc_dest.addr, sizeof(ethhdr->dest.addr)); + MEMCPY(ðhdr->src.addr, &sc->sc_ethif->hwaddr, sizeof(ethhdr->src.addr)); + + PPPDEBUG(LOG_DEBUG, ("pppoe: %c%c%"U16_F" (%x) state=%d, session=0x%x output -> %02"X16_F":%02"X16_F":%02"X16_F":%02"X16_F":%02"X16_F":%02"X16_F", len=%d\n", + sc->sc_ethif->name[0], sc->sc_ethif->name[1], sc->sc_ethif->num, etype, + sc->sc_state, sc->sc_session, + sc->sc_dest.addr[0], sc->sc_dest.addr[1], sc->sc_dest.addr[2], sc->sc_dest.addr[3], sc->sc_dest.addr[4], sc->sc_dest.addr[5], + pb->tot_len)); + + res = sc->sc_ethif->linkoutput(sc->sc_ethif, pb); + + pbuf_free(pb); + + return res; +} + +static err_t +pppoe_send_padi(struct pppoe_softc *sc) +{ + struct pbuf *pb; + u8_t *p; + int len; +#ifdef PPPOE_TODO + int l1 = 0, l2 = 0; /* XXX: gcc */ +#endif /* PPPOE_TODO */ + + if (sc->sc_state >PPPOE_STATE_PADI_SENT) { + PPPDEBUG(LOG_ERR, ("ERROR: pppoe_send_padi in state %d", sc->sc_state)); + } + + /* calculate length of frame (excluding ethernet header + pppoe header) */ + len = 2 + 2 + 2 + 2 + sizeof sc; /* service name tag is required, host unique is send too */ +#ifdef PPPOE_TODO + if (sc->sc_service_name != NULL) { + l1 = (int)strlen(sc->sc_service_name); + len += l1; + } + if (sc->sc_concentrator_name != NULL) { + l2 = (int)strlen(sc->sc_concentrator_name); + len += 2 + 2 + l2; + } +#endif /* PPPOE_TODO */ + LWIP_ASSERT("sizeof(struct eth_hdr) + PPPOE_HEADERLEN + len <= 0xffff", + sizeof(struct eth_hdr) + PPPOE_HEADERLEN + len <= 0xffff); + + /* allocate a buffer */ + pb = pbuf_alloc(PBUF_LINK, (u16_t)(PPPOE_HEADERLEN + len), PBUF_RAM); + if (!pb) { + return ERR_MEM; + } + LWIP_ASSERT("pb->tot_len == pb->len", pb->tot_len == pb->len); + + p = (u8_t*)pb->payload; + /* fill in pkt */ + PPPOE_ADD_HEADER(p, PPPOE_CODE_PADI, 0, (u16_t)len); + PPPOE_ADD_16(p, PPPOE_TAG_SNAME); +#ifdef PPPOE_TODO + if (sc->sc_service_name != NULL) { + PPPOE_ADD_16(p, l1); + MEMCPY(p, sc->sc_service_name, l1); + p += l1; + } else +#endif /* PPPOE_TODO */ + { + PPPOE_ADD_16(p, 0); + } +#ifdef PPPOE_TODO + if (sc->sc_concentrator_name != NULL) { + PPPOE_ADD_16(p, PPPOE_TAG_ACNAME); + PPPOE_ADD_16(p, l2); + MEMCPY(p, sc->sc_concentrator_name, l2); + p += l2; + } +#endif /* PPPOE_TODO */ + PPPOE_ADD_16(p, PPPOE_TAG_HUNIQUE); + PPPOE_ADD_16(p, sizeof(sc)); + MEMCPY(p, &sc, sizeof sc); + + /* send pkt */ + return pppoe_output(sc, pb); +} + +static void +pppoe_timeout(void *arg) +{ + u32_t retry_wait; + int err; + struct pppoe_softc *sc = (struct pppoe_softc*)arg; + + PPPDEBUG(LOG_DEBUG, ("pppoe: %c%c%"U16_F": timeout\n", sc->sc_ethif->name[0], sc->sc_ethif->name[1], sc->sc_ethif->num)); + + switch (sc->sc_state) { + case PPPOE_STATE_PADI_SENT: + /* + * We have two basic ways of retrying: + * - Quick retry mode: try a few times in short sequence + * - Slow retry mode: we already had a connection successfully + * established and will try infinitely (without user + * intervention) + * We only enter slow retry mode if IFF_LINK1 (aka autodial) + * is not set. + */ + if (sc->sc_padi_retried < 0xff) { + sc->sc_padi_retried++; + } + if (!sc->pcb->settings.persist && sc->sc_padi_retried >= PPPOE_DISC_MAXPADI) { +#if 0 + if ((sc->sc_sppp.pp_if.if_flags & IFF_LINK1) == 0) { + /* slow retry mode */ + retry_wait = PPPOE_SLOW_RETRY; + } else +#endif + { + pppoe_abort_connect(sc); + return; + } + } + /* initialize for quick retry mode */ + retry_wait = LWIP_MIN(PPPOE_DISC_TIMEOUT * sc->sc_padi_retried, PPPOE_SLOW_RETRY); + if ((err = pppoe_send_padi(sc)) != 0) { + sc->sc_padi_retried--; + PPPDEBUG(LOG_DEBUG, ("pppoe: %c%c%"U16_F": failed to transmit PADI, error=%d\n", sc->sc_ethif->name[0], sc->sc_ethif->name[1], sc->sc_ethif->num, err)); + } + sys_timeout(retry_wait, pppoe_timeout, sc); + break; + + case PPPOE_STATE_PADR_SENT: + sc->sc_padr_retried++; + if (sc->sc_padr_retried >= PPPOE_DISC_MAXPADR) { + MEMCPY(&sc->sc_dest, ethbroadcast.addr, sizeof(sc->sc_dest)); + sc->sc_state = PPPOE_STATE_PADI_SENT; + sc->sc_padr_retried = 0; + if ((err = pppoe_send_padi(sc)) != 0) { + PPPDEBUG(LOG_DEBUG, ("pppoe: %c%c%"U16_F": failed to send PADI, error=%d\n", sc->sc_ethif->name[0], sc->sc_ethif->name[1], sc->sc_ethif->num, err)); + } + sys_timeout(PPPOE_DISC_TIMEOUT * (1 + sc->sc_padi_retried), pppoe_timeout, sc); + return; + } + if ((err = pppoe_send_padr(sc)) != 0) { + sc->sc_padr_retried--; + PPPDEBUG(LOG_DEBUG, ("pppoe: %c%c%"U16_F": failed to send PADR, error=%d\n", sc->sc_ethif->name[0], sc->sc_ethif->name[1], sc->sc_ethif->num, err)); + } + sys_timeout(PPPOE_DISC_TIMEOUT * (1 + sc->sc_padr_retried), pppoe_timeout, sc); + break; + default: + return; /* all done, work in peace */ + } +} + +/* Start a connection (i.e. initiate discovery phase) */ +static err_t +pppoe_connect(ppp_pcb *ppp, void *ctx) +{ + int err; + struct pppoe_softc *sc = (struct pppoe_softc *)ctx; + lcp_options *lcp_wo; + lcp_options *lcp_ao; +#if PPP_IPV4_SUPPORT && VJ_SUPPORT + ipcp_options *ipcp_wo; + ipcp_options *ipcp_ao; +#endif /* PPP_IPV4_SUPPORT && VJ_SUPPORT */ + + if (sc->sc_state != PPPOE_STATE_INITIAL) { + return EBUSY; + } + + /* stop any timer */ + sys_untimeout(pppoe_timeout, sc); + sc->sc_session = 0; + sc->sc_padi_retried = 0; + sc->sc_padr_retried = 0; +#ifdef PPPOE_SERVER + /* wait PADI if IFF_PASSIVE */ + if ((sc->sc_sppp.pp_if.if_flags & IFF_PASSIVE)) { + return 0; + } +#endif + + ppp_clear(ppp); + + lcp_wo = &ppp->lcp_wantoptions; + lcp_wo->mru = sc->sc_ethif->mtu-PPPOE_HEADERLEN-2; /* two byte PPP protocol discriminator, then IP data */ + lcp_wo->neg_asyncmap = 0; + lcp_wo->neg_pcompression = 0; + lcp_wo->neg_accompression = 0; + + lcp_ao = &ppp->lcp_allowoptions; + lcp_ao->mru = sc->sc_ethif->mtu-PPPOE_HEADERLEN-2; /* two byte PPP protocol discriminator, then IP data */ + lcp_ao->neg_asyncmap = 0; + lcp_ao->neg_pcompression = 0; + lcp_ao->neg_accompression = 0; + +#if PPP_IPV4_SUPPORT && VJ_SUPPORT + ipcp_wo = &ppp->ipcp_wantoptions; + ipcp_wo->neg_vj = 0; + ipcp_wo->old_vj = 0; + + ipcp_ao = &ppp->ipcp_allowoptions; + ipcp_ao->neg_vj = 0; + ipcp_ao->old_vj = 0; +#endif /* PPP_IPV4_SUPPORT && VJ_SUPPORT */ + + /* save state, in case we fail to send PADI */ + sc->sc_state = PPPOE_STATE_PADI_SENT; + if ((err = pppoe_send_padi(sc)) != 0) { + PPPDEBUG(LOG_DEBUG, ("pppoe: %c%c%"U16_F": failed to send PADI, error=%d\n", sc->sc_ethif->name[0], sc->sc_ethif->name[1], sc->sc_ethif->num, err)); + } + sys_timeout(PPPOE_DISC_TIMEOUT, pppoe_timeout, sc); + return err; +} + +/* disconnect */ +static void +pppoe_disconnect(ppp_pcb *ppp, void *ctx) +{ + struct pppoe_softc *sc = (struct pppoe_softc *)ctx; + + if (sc->sc_state < PPPOE_STATE_SESSION) { + return; + } + + PPPDEBUG(LOG_DEBUG, ("pppoe: %c%c%"U16_F": disconnecting\n", sc->sc_ethif->name[0], sc->sc_ethif->name[1], sc->sc_ethif->num)); + pppoe_send_padt(sc->sc_ethif, sc->sc_session, (const u8_t *)&sc->sc_dest); + + /* cleanup softc */ + sc->sc_state = PPPOE_STATE_INITIAL; + MEMCPY(&sc->sc_dest, ethbroadcast.addr, sizeof(sc->sc_dest)); + sc->sc_ac_cookie_len = 0; +#ifdef PPPOE_SERVER + if (sc->sc_hunique) { + mem_free(sc->sc_hunique); + sc->sc_hunique = NULL; + } + sc->sc_hunique_len = 0; +#endif + sc->sc_session = 0; + sc->sc_padi_retried = 0; + sc->sc_padr_retried = 0; + + ppp_link_end(ppp); /* notify upper layers */ + return; +} + +/* Connection attempt aborted */ +static void +pppoe_abort_connect(struct pppoe_softc *sc) +{ + PPPDEBUG(LOG_DEBUG, ("%c%c%"U16_F": could not establish connection\n", sc->sc_ethif->name[0], sc->sc_ethif->name[1], sc->sc_ethif->num)); + + /* clear connection state */ + sc->sc_state = PPPOE_STATE_INITIAL; + MEMCPY(&sc->sc_dest, ethbroadcast.addr, sizeof(sc->sc_dest)); + sc->sc_ac_cookie_len = 0; + sc->sc_session = 0; + sc->sc_padi_retried = 0; + sc->sc_padr_retried = 0; + + ppp_link_failed(sc->pcb); /* notify upper layers */ +} + +/* Send a PADR packet */ +static err_t +pppoe_send_padr(struct pppoe_softc *sc) +{ + struct pbuf *pb; + u8_t *p; + size_t len; +#ifdef PPPOE_TODO + size_t l1 = 0; /* XXX: gcc */ +#endif /* PPPOE_TODO */ + + if (sc->sc_state != PPPOE_STATE_PADR_SENT) { + return ERR_CONN; + } + + len = 2 + 2 + 2 + 2 + sizeof(sc); /* service name, host unique */ +#ifdef PPPOE_TODO + if (sc->sc_service_name != NULL) { /* service name tag maybe empty */ + l1 = strlen(sc->sc_service_name); + len += l1; + } +#endif /* PPPOE_TODO */ + if (sc->sc_ac_cookie_len > 0) { + len += 2 + 2 + sc->sc_ac_cookie_len; /* AC cookie */ + } + LWIP_ASSERT("sizeof(struct eth_hdr) + PPPOE_HEADERLEN + len <= 0xffff", + sizeof(struct eth_hdr) + PPPOE_HEADERLEN + len <= 0xffff); + pb = pbuf_alloc(PBUF_LINK, (u16_t)(PPPOE_HEADERLEN + len), PBUF_RAM); + if (!pb) { + return ERR_MEM; + } + LWIP_ASSERT("pb->tot_len == pb->len", pb->tot_len == pb->len); + p = (u8_t*)pb->payload; + PPPOE_ADD_HEADER(p, PPPOE_CODE_PADR, 0, len); + PPPOE_ADD_16(p, PPPOE_TAG_SNAME); +#ifdef PPPOE_TODO + if (sc->sc_service_name != NULL) { + PPPOE_ADD_16(p, l1); + MEMCPY(p, sc->sc_service_name, l1); + p += l1; + } else +#endif /* PPPOE_TODO */ + { + PPPOE_ADD_16(p, 0); + } + if (sc->sc_ac_cookie_len > 0) { + PPPOE_ADD_16(p, PPPOE_TAG_ACCOOKIE); + PPPOE_ADD_16(p, sc->sc_ac_cookie_len); + MEMCPY(p, sc->sc_ac_cookie, sc->sc_ac_cookie_len); + p += sc->sc_ac_cookie_len; + } + PPPOE_ADD_16(p, PPPOE_TAG_HUNIQUE); + PPPOE_ADD_16(p, sizeof(sc)); + MEMCPY(p, &sc, sizeof sc); + + return pppoe_output(sc, pb); +} + +/* send a PADT packet */ +static err_t +pppoe_send_padt(struct netif *outgoing_if, u_int session, const u8_t *dest) +{ + struct pbuf *pb; + struct eth_hdr *ethhdr; + err_t res; + u8_t *p; + + pb = pbuf_alloc(PBUF_LINK, (u16_t)(PPPOE_HEADERLEN), PBUF_RAM); + if (!pb) { + return ERR_MEM; + } + LWIP_ASSERT("pb->tot_len == pb->len", pb->tot_len == pb->len); + + pbuf_header(pb, (s16_t)sizeof(struct eth_hdr)); + ethhdr = (struct eth_hdr *)pb->payload; + ethhdr->type = PP_HTONS(ETHTYPE_PPPOEDISC); + MEMCPY(ðhdr->dest.addr, dest, sizeof(ethhdr->dest.addr)); + MEMCPY(ðhdr->src.addr, &outgoing_if->hwaddr, sizeof(ethhdr->src.addr)); + + p = (u8_t*)(ethhdr + 1); + PPPOE_ADD_HEADER(p, PPPOE_CODE_PADT, session, 0); + + res = outgoing_if->linkoutput(outgoing_if, pb); + + pbuf_free(pb); + + return res; +} + +#ifdef PPPOE_SERVER +static err_t +pppoe_send_pado(struct pppoe_softc *sc) +{ + struct pbuf *pb; + u8_t *p; + size_t len; + + if (sc->sc_state != PPPOE_STATE_PADO_SENT) { + return ERR_CONN; + } + + /* calc length */ + len = 0; + /* include ac_cookie */ + len += 2 + 2 + sizeof(sc); + /* include hunique */ + len += 2 + 2 + sc->sc_hunique_len; + pb = pbuf_alloc(PBUF_LINK, (u16_t)(PPPOE_HEADERLEN + len), PBUF_RAM); + if (!pb) { + return ERR_MEM; + } + LWIP_ASSERT("pb->tot_len == pb->len", pb->tot_len == pb->len); + p = (u8_t*)pb->payload; + PPPOE_ADD_HEADER(p, PPPOE_CODE_PADO, 0, len); + PPPOE_ADD_16(p, PPPOE_TAG_ACCOOKIE); + PPPOE_ADD_16(p, sizeof(sc)); + MEMCPY(p, &sc, sizeof(sc)); + p += sizeof(sc); + PPPOE_ADD_16(p, PPPOE_TAG_HUNIQUE); + PPPOE_ADD_16(p, sc->sc_hunique_len); + MEMCPY(p, sc->sc_hunique, sc->sc_hunique_len); + return pppoe_output(sc, pb); +} + +static err_t +pppoe_send_pads(struct pppoe_softc *sc) +{ + struct pbuf *pb; + u8_t *p; + size_t len, l1 = 0; /* XXX: gcc */ + + if (sc->sc_state != PPPOE_STATE_PADO_SENT) { + return ERR_CONN; + } + + sc->sc_session = mono_time.tv_sec % 0xff + 1; + /* calc length */ + len = 0; + /* include hunique */ + len += 2 + 2 + 2 + 2 + sc->sc_hunique_len; /* service name, host unique*/ + if (sc->sc_service_name != NULL) { /* service name tag maybe empty */ + l1 = strlen(sc->sc_service_name); + len += l1; + } + pb = pbuf_alloc(PBUF_LINK, (u16_t)(PPPOE_HEADERLEN + len), PBUF_RAM); + if (!pb) { + return ERR_MEM; + } + LWIP_ASSERT("pb->tot_len == pb->len", pb->tot_len == pb->len); + p = (u8_t*)pb->payload; + PPPOE_ADD_HEADER(p, PPPOE_CODE_PADS, sc->sc_session, len); + PPPOE_ADD_16(p, PPPOE_TAG_SNAME); + if (sc->sc_service_name != NULL) { + PPPOE_ADD_16(p, l1); + MEMCPY(p, sc->sc_service_name, l1); + p += l1; + } else { + PPPOE_ADD_16(p, 0); + } + PPPOE_ADD_16(p, PPPOE_TAG_HUNIQUE); + PPPOE_ADD_16(p, sc->sc_hunique_len); + MEMCPY(p, sc->sc_hunique, sc->sc_hunique_len); + return pppoe_output(sc, pb); +} +#endif + +static err_t +pppoe_xmit(struct pppoe_softc *sc, struct pbuf *pb) +{ + u8_t *p; + size_t len; + + /* are we ready to process data yet? */ + if (sc->sc_state < PPPOE_STATE_SESSION) { + /*sppp_flush(&sc->sc_sppp.pp_if);*/ + pbuf_free(pb); + return ERR_CONN; + } + + len = pb->tot_len; + + /* make room for PPPoE header - should not fail */ + if (pbuf_header(pb, (s16_t)(PPPOE_HEADERLEN)) != 0) { + /* bail out */ + PPPDEBUG(LOG_ERR, ("pppoe: %c%c%"U16_F": pppoe_xmit: could not allocate room for PPPoE header\n", sc->sc_ethif->name[0], sc->sc_ethif->name[1], sc->sc_ethif->num)); + LINK_STATS_INC(link.lenerr); + pbuf_free(pb); + return ERR_BUF; + } + + p = (u8_t*)pb->payload; + PPPOE_ADD_HEADER(p, 0, sc->sc_session, len); + + return pppoe_output(sc, pb); +} + +#if 0 /*def PFIL_HOOKS*/ +static int +pppoe_ifattach_hook(void *arg, struct pbuf **mp, struct netif *ifp, int dir) +{ + struct pppoe_softc *sc; + int s; + + if (mp != (struct pbuf **)PFIL_IFNET_DETACH) { + return 0; + } + + LIST_FOREACH(sc, &pppoe_softc_list, sc_list) { + if (sc->sc_ethif != ifp) { + continue; + } + if (sc->sc_sppp.pp_if.if_flags & IFF_UP) { + sc->sc_sppp.pp_if.if_flags &= ~(IFF_UP|IFF_RUNNING); + PPPDEBUG(LOG_DEBUG, ("%c%c%"U16_F": ethernet interface detached, going down\n", + sc->sc_ethif->name[0], sc->sc_ethif->name[1], sc->sc_ethif->num)); + } + sc->sc_ethif = NULL; + pppoe_clear_softc(sc, "ethernet interface detached"); + } + + return 0; +} +#endif + +#if 0 /* UNUSED */ +static void +pppoe_clear_softc(struct pppoe_softc *sc, const char *message) +{ + LWIP_UNUSED_ARG(message); + + /* stop timer */ + sys_untimeout(pppoe_timeout, sc); + PPPDEBUG(LOG_DEBUG, ("pppoe: %c%c%"U16_F": session 0x%x terminated, %s\n", sc->sc_ethif->name[0], sc->sc_ethif->name[1], sc->sc_ethif->num, sc->sc_session, message)); + /* fix our state */ + sc->sc_state = PPPOE_STATE_INITIAL; + + /* notify upper layers */ + ppp_link_end(sc->pcb); /* /!\ dangerous /!\ */ + + /* clean up softc */ + MEMCPY(&sc->sc_dest, ethbroadcast.addr, sizeof(sc->sc_dest)); + sc->sc_ac_cookie_len = 0; + sc->sc_session = 0; + sc->sc_padi_retried = 0; + sc->sc_padr_retried = 0; +} +#endif /* UNUSED */ +#endif /* PPP_SUPPORT && PPPOE_SUPPORT */ diff --git a/components/lwip/netif/ppp/pppol2tp.c b/components/lwip/netif/ppp/pppol2tp.c new file mode 100755 index 0000000000..99b4e5fdab --- /dev/null +++ b/components/lwip/netif/ppp/pppol2tp.c @@ -0,0 +1,1151 @@ +/** + * @file + * Network Point to Point Protocol over Layer 2 Tunneling Protocol program file. + * + */ + +/* + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + */ + +/* + * L2TP Support status: + * + * Supported: + * - L2TPv2 (PPP over L2TP, a.k.a. UDP tunnels) + * - LAC + * + * Not supported: + * - LNS (require PPP server support) + * - L2TPv3 ethernet pseudowires + * - L2TPv3 VLAN pseudowire + * - L2TPv3 PPP pseudowires + * - L2TPv3 IP encapsulation + * - L2TPv3 IP pseudowire + * - L2TP tunnel switching - http://tools.ietf.org/html/draft-ietf-l2tpext-tunnel-switching-08 + * - Multiple tunnels per UDP socket, as well as multiple sessions per tunnel + * - Hidden AVPs + */ + +#include "lwip/opt.h" +#if PPP_SUPPORT && PPPOL2TP_SUPPORT /* don't build if not configured for use in lwipopts.h */ + +#include "lwip/err.h" +#include "lwip/memp.h" +#include "lwip/netif.h" +#include "lwip/udp.h" +#include "lwip/snmp.h" + +#include "netif/ppp/ppp_impl.h" +#include "netif/ppp/lcp.h" +#include "netif/ppp/ipcp.h" +#include "netif/ppp/pppol2tp.h" + +#include "netif/ppp/magic.h" + +#if PPPOL2TP_AUTH_SUPPORT +#if LWIP_INCLUDED_POLARSSL_MD5 +#include "netif/ppp/polarssl/md5.h" +#else +#include "polarssl/md5.h" +#endif +#endif /* PPPOL2TP_AUTH_SUPPORT */ + +/* callbacks called from PPP core */ +static err_t pppol2tp_write(ppp_pcb *ppp, void *ctx, struct pbuf *p); +static err_t pppol2tp_netif_output(ppp_pcb *ppp, void *ctx, struct pbuf *p, u_short protocol); +static err_t pppol2tp_destroy(ppp_pcb *ppp, void *ctx); /* Destroy a L2TP control block */ +static err_t pppol2tp_connect(ppp_pcb *ppp, void *ctx); /* Be a LAC, connect to a LNS. */ +static void pppol2tp_disconnect(ppp_pcb *ppp, void *ctx); /* Disconnect */ + + /* Prototypes for procedures local to this file. */ +static void pppol2tp_input(void *arg, struct udp_pcb *pcb, struct pbuf *p, const ip_addr_t *addr, u16_t port); +static void pppol2tp_dispatch_control_packet(pppol2tp_pcb *l2tp, u16_t port, struct pbuf *p, u16_t ns, u16_t nr); +static void pppol2tp_timeout(void *arg); +static void pppol2tp_abort_connect(pppol2tp_pcb *l2tp); +static void pppol2tp_clear(pppol2tp_pcb *l2tp); +static err_t pppol2tp_send_sccrq(pppol2tp_pcb *l2tp); +static err_t pppol2tp_send_scccn(pppol2tp_pcb *l2tp, u16_t ns); +static err_t pppol2tp_send_icrq(pppol2tp_pcb *l2tp, u16_t ns); +static err_t pppol2tp_send_iccn(pppol2tp_pcb *l2tp, u16_t ns); +static err_t pppol2tp_send_zlb(pppol2tp_pcb *l2tp, u16_t ns); +static err_t pppol2tp_send_stopccn(pppol2tp_pcb *l2tp, u16_t ns); +static err_t pppol2tp_xmit(pppol2tp_pcb *l2tp, struct pbuf *pb); +static err_t pppol2tp_udp_send(pppol2tp_pcb *l2tp, struct pbuf *pb); + +/* Callbacks structure for PPP core */ +static const struct link_callbacks pppol2tp_callbacks = { + pppol2tp_connect, +#if PPP_SERVER + NULL, +#endif /* PPP_SERVER */ + pppol2tp_disconnect, + pppol2tp_destroy, + pppol2tp_write, + pppol2tp_netif_output, + NULL, + NULL +}; + + +/* Create a new L2TP session. */ +ppp_pcb *pppol2tp_create(struct netif *pppif, + struct netif *netif, ip_addr_t *ipaddr, u16_t port, + const u8_t *secret, u8_t secret_len, + ppp_link_status_cb_fn link_status_cb, void *ctx_cb) { + ppp_pcb *ppp; + pppol2tp_pcb *l2tp; + struct udp_pcb *udp; + + if (ipaddr == NULL) { + goto ipaddr_check_failed; + } + + l2tp = (pppol2tp_pcb *)memp_malloc(MEMP_PPPOL2TP_PCB); + if (l2tp == NULL) { + goto memp_malloc_l2tp_failed; + } + + udp = udp_new_ip_type(IP_GET_TYPE(ipaddr)); + if (udp == NULL) { + goto udp_new_failed; + } + udp_recv(udp, pppol2tp_input, l2tp); + + ppp = ppp_new(pppif, &pppol2tp_callbacks, l2tp, link_status_cb, ctx_cb); + if (ppp == NULL) { + goto ppp_new_failed; + } + + memset(l2tp, 0, sizeof(pppol2tp_pcb)); + l2tp->phase = PPPOL2TP_STATE_INITIAL; + l2tp->ppp = ppp; + l2tp->udp = udp; + l2tp->netif = netif; + ip_addr_copy(l2tp->remote_ip, *ipaddr); + l2tp->remote_port = port; +#if PPPOL2TP_AUTH_SUPPORT + l2tp->secret = secret; + l2tp->secret_len = secret_len; +#endif /* PPPOL2TP_AUTH_SUPPORT */ + + return ppp; + +ppp_new_failed: + udp_remove(udp); +udp_new_failed: + memp_free(MEMP_PPPOL2TP_PCB, l2tp); +memp_malloc_l2tp_failed: +ipaddr_check_failed: + return NULL; +} + +/* Called by PPP core */ +static err_t pppol2tp_write(ppp_pcb *ppp, void *ctx, struct pbuf *p) { + pppol2tp_pcb *l2tp = (pppol2tp_pcb *)ctx; + struct pbuf *ph; /* UDP + L2TP header */ + err_t ret; +#if MIB2_STATS + u16_t tot_len; +#else /* MIB2_STATS */ + LWIP_UNUSED_ARG(ppp); +#endif /* MIB2_STATS */ + + ph = pbuf_alloc(PBUF_TRANSPORT, (u16_t)(PPPOL2TP_OUTPUT_DATA_HEADER_LEN), PBUF_RAM); + if(!ph) { + LINK_STATS_INC(link.memerr); + LINK_STATS_INC(link.proterr); + MIB2_STATS_NETIF_INC(ppp->netif, ifoutdiscards); + pbuf_free(p); + return ERR_MEM; + } + + pbuf_header(ph, -(s16_t)PPPOL2TP_OUTPUT_DATA_HEADER_LEN); /* hide L2TP header */ + pbuf_cat(ph, p); +#if MIB2_STATS + tot_len = ph->tot_len; +#endif /* MIB2_STATS */ + + ret = pppol2tp_xmit(l2tp, ph); + if (ret != ERR_OK) { + LINK_STATS_INC(link.err); + MIB2_STATS_NETIF_INC(ppp->netif, ifoutdiscards); + return ret; + } + + MIB2_STATS_NETIF_ADD(ppp->netif, ifoutoctets, (u16_t)tot_len); + MIB2_STATS_NETIF_INC(ppp->netif, ifoutucastpkts); + LINK_STATS_INC(link.xmit); + return ERR_OK; +} + +/* Called by PPP core */ +static err_t pppol2tp_netif_output(ppp_pcb *ppp, void *ctx, struct pbuf *p, u_short protocol) { + pppol2tp_pcb *l2tp = (pppol2tp_pcb *)ctx; + struct pbuf *pb; + u8_t *pl; + err_t err; +#if MIB2_STATS + u16_t tot_len; +#else /* MIB2_STATS */ + LWIP_UNUSED_ARG(ppp); +#endif /* MIB2_STATS */ + + /* @todo: try to use pbuf_header() here! */ + pb = pbuf_alloc(PBUF_TRANSPORT, PPPOL2TP_OUTPUT_DATA_HEADER_LEN + sizeof(protocol), PBUF_RAM); + if(!pb) { + LINK_STATS_INC(link.memerr); + LINK_STATS_INC(link.proterr); + MIB2_STATS_NETIF_INC(ppp->netif, ifoutdiscards); + return ERR_MEM; + } + + pbuf_header(pb, -(s16_t)PPPOL2TP_OUTPUT_DATA_HEADER_LEN); + + pl = (u8_t*)pb->payload; + PUTSHORT(protocol, pl); + + pbuf_chain(pb, p); +#if MIB2_STATS + tot_len = pb->tot_len; +#endif /* MIB2_STATS */ + + if( (err = pppol2tp_xmit(l2tp, pb)) != ERR_OK) { + LINK_STATS_INC(link.err); + MIB2_STATS_NETIF_INC(ppp->netif, ifoutdiscards); + return err; + } + + MIB2_STATS_NETIF_ADD(ppp->netif, ifoutoctets, tot_len); + MIB2_STATS_NETIF_INC(ppp->netif, ifoutucastpkts); + LINK_STATS_INC(link.xmit); + return ERR_OK; +} + +/* Destroy a L2TP control block */ +static err_t pppol2tp_destroy(ppp_pcb *ppp, void *ctx) { + pppol2tp_pcb *l2tp = (pppol2tp_pcb *)ctx; + LWIP_UNUSED_ARG(ppp); + + sys_untimeout(pppol2tp_timeout, l2tp); + if (l2tp->udp != NULL) { + udp_remove(l2tp->udp); + } + memp_free(MEMP_PPPOL2TP_PCB, l2tp); + return ERR_OK; +} + +/* Be a LAC, connect to a LNS. */ +static err_t pppol2tp_connect(ppp_pcb *ppp, void *ctx) { + err_t err; + pppol2tp_pcb *l2tp = (pppol2tp_pcb *)ctx; + lcp_options *lcp_wo; + lcp_options *lcp_ao; +#if PPP_IPV4_SUPPORT && VJ_SUPPORT + ipcp_options *ipcp_wo; + ipcp_options *ipcp_ao; +#endif /* PPP_IPV4_SUPPORT && VJ_SUPPORT */ + + if (l2tp->phase != PPPOL2TP_STATE_INITIAL) { + return ERR_VAL; + } + + pppol2tp_clear(l2tp); + + ppp_clear(ppp); + + lcp_wo = &ppp->lcp_wantoptions; + lcp_wo->mru = PPPOL2TP_DEFMRU; + lcp_wo->neg_asyncmap = 0; + lcp_wo->neg_pcompression = 0; + lcp_wo->neg_accompression = 0; + + lcp_ao = &ppp->lcp_allowoptions; + lcp_ao->mru = PPPOL2TP_DEFMRU; + lcp_ao->neg_asyncmap = 0; + lcp_ao->neg_pcompression = 0; + lcp_ao->neg_accompression = 0; + +#if PPP_IPV4_SUPPORT && VJ_SUPPORT + ipcp_wo = &ppp->ipcp_wantoptions; + ipcp_wo->neg_vj = 0; + ipcp_wo->old_vj = 0; + + ipcp_ao = &ppp->ipcp_allowoptions; + ipcp_ao->neg_vj = 0; + ipcp_ao->old_vj = 0; +#endif /* PPP_IPV4_SUPPORT && VJ_SUPPORT */ + + /* Listen to a random source port, we need to do that instead of using udp_connect() + * because the L2TP LNS might answer with its own random source port (!= 1701) + */ +#if LWIP_IPV6 + if (IP_IS_V6_VAL(l2tp->udp->local_ip)) { + udp_bind(l2tp->udp, IP6_ADDR_ANY, 0); + } else +#endif /* LWIP_IPV6 */ + udp_bind(l2tp->udp, IP_ADDR_ANY, 0); + +#if PPPOL2TP_AUTH_SUPPORT + /* Generate random vector */ + if (l2tp->secret != NULL) { + magic_random_bytes(l2tp->secret_rv, sizeof(l2tp->secret_rv)); + } +#endif /* PPPOL2TP_AUTH_SUPPORT */ + + do { + l2tp->remote_tunnel_id = magic(); + } while(l2tp->remote_tunnel_id == 0); + /* save state, in case we fail to send SCCRQ */ + l2tp->sccrq_retried = 0; + l2tp->phase = PPPOL2TP_STATE_SCCRQ_SENT; + if ((err = pppol2tp_send_sccrq(l2tp)) != 0) { + PPPDEBUG(LOG_DEBUG, ("pppol2tp: failed to send SCCRQ, error=%d\n", err)); + } + sys_timeout(PPPOL2TP_CONTROL_TIMEOUT, pppol2tp_timeout, l2tp); + return err; +} + +/* Disconnect */ +static void pppol2tp_disconnect(ppp_pcb *ppp, void *ctx) { + pppol2tp_pcb *l2tp = (pppol2tp_pcb *)ctx; + + if (l2tp->phase < PPPOL2TP_STATE_DATA) { + return; + } + + l2tp->our_ns++; + pppol2tp_send_stopccn(l2tp, l2tp->our_ns); + + pppol2tp_clear(l2tp); + ppp_link_end(ppp); /* notify upper layers */ +} + +/* UDP Callback for incoming IPv4 L2TP frames */ +static void pppol2tp_input(void *arg, struct udp_pcb *pcb, struct pbuf *p, const ip_addr_t *addr, u16_t port) { + pppol2tp_pcb *l2tp = (pppol2tp_pcb*)arg; + u16_t hflags, hlen, len=0, tunnel_id=0, session_id=0, ns=0, nr=0, offset=0; + u8_t *inp; + LWIP_UNUSED_ARG(pcb); + + if (l2tp->phase < PPPOL2TP_STATE_SCCRQ_SENT) { + goto free_and_return; + } + + if (!ip_addr_cmp(&l2tp->remote_ip, addr)) { + goto free_and_return; + } + + /* discard packet if port mismatch, but only if we received a SCCRP */ + if (l2tp->phase > PPPOL2TP_STATE_SCCRQ_SENT && l2tp->tunnel_port != port) { + goto free_and_return; + } + + /* printf("-----------\nL2TP INPUT, %d\n", p->len); */ + + /* L2TP header */ + if (p->len < sizeof(hflags) + sizeof(tunnel_id) + sizeof(session_id) ) { + goto packet_too_short; + } + + inp = (u8_t*)p->payload; + GETSHORT(hflags, inp); + + if (hflags & PPPOL2TP_HEADERFLAG_CONTROL) { + /* check mandatory flags for a control packet */ + if ( (hflags & PPPOL2TP_HEADERFLAG_CONTROL_MANDATORY) != PPPOL2TP_HEADERFLAG_CONTROL_MANDATORY ) { + PPPDEBUG(LOG_DEBUG, ("pppol2tp: mandatory header flags for control packet not set\n")); + goto free_and_return; + } + /* check forbidden flags for a control packet */ + if (hflags & PPPOL2TP_HEADERFLAG_CONTROL_FORBIDDEN) { + PPPDEBUG(LOG_DEBUG, ("pppol2tp: forbidden header flags for control packet found\n")); + goto free_and_return; + } + } else { + /* check mandatory flags for a data packet */ + if ( (hflags & PPPOL2TP_HEADERFLAG_DATA_MANDATORY) != PPPOL2TP_HEADERFLAG_DATA_MANDATORY) { + PPPDEBUG(LOG_DEBUG, ("pppol2tp: mandatory header flags for data packet not set\n")); + goto free_and_return; + } + } + + /* Expected header size */ + hlen = sizeof(hflags) + sizeof(tunnel_id) + sizeof(session_id); + if (hflags & PPPOL2TP_HEADERFLAG_LENGTH) { + hlen += sizeof(len); + } + if (hflags & PPPOL2TP_HEADERFLAG_SEQUENCE) { + hlen += sizeof(ns) + sizeof(nr); + } + if (hflags & PPPOL2TP_HEADERFLAG_OFFSET) { + hlen += sizeof(offset); + } + if (p->len < hlen) { + goto packet_too_short; + } + + if (hflags & PPPOL2TP_HEADERFLAG_LENGTH) { + GETSHORT(len, inp); + if (p->len < len || len < hlen) { + goto packet_too_short; + } + } + GETSHORT(tunnel_id, inp); + GETSHORT(session_id, inp); + if (hflags & PPPOL2TP_HEADERFLAG_SEQUENCE) { + GETSHORT(ns, inp); + GETSHORT(nr, inp); + } + if (hflags & PPPOL2TP_HEADERFLAG_OFFSET) { + GETSHORT(offset, inp) + if (offset > 4096) { /* don't be fooled with large offset which might overflow hlen */ + PPPDEBUG(LOG_DEBUG, ("pppol2tp: strange packet received, offset=%d\n", offset)); + goto free_and_return; + } + hlen += offset; + if (p->len < hlen) { + goto packet_too_short; + } + INCPTR(offset, inp); + } + + /* printf("HLEN = %d\n", hlen); */ + + /* skip L2TP header */ + if (pbuf_header(p, -(s16_t)hlen) != 0) { + goto free_and_return; + } + + /* printf("LEN=%d, TUNNEL_ID=%d, SESSION_ID=%d, NS=%d, NR=%d, OFFSET=%d\n", len, tunnel_id, session_id, ns, nr, offset); */ + PPPDEBUG(LOG_DEBUG, ("pppol2tp: input packet, len=%"U16_F", tunnel=%"U16_F", session=%"U16_F", ns=%"U16_F", nr=%"U16_F"\n", + len, tunnel_id, session_id, ns, nr)); + + /* Control packet */ + if (hflags & PPPOL2TP_HEADERFLAG_CONTROL) { + pppol2tp_dispatch_control_packet(l2tp, port, p, ns, nr); + goto free_and_return; + } + + /* Data packet */ + if(l2tp->phase != PPPOL2TP_STATE_DATA) { + goto free_and_return; + } + if(tunnel_id != l2tp->remote_tunnel_id) { + PPPDEBUG(LOG_DEBUG, ("pppol2tp: tunnel ID mismatch, assigned=%d, received=%d\n", l2tp->remote_tunnel_id, tunnel_id)); + goto free_and_return; + } + if(session_id != l2tp->remote_session_id) { + PPPDEBUG(LOG_DEBUG, ("pppol2tp: session ID mismatch, assigned=%d, received=%d\n", l2tp->remote_session_id, session_id)); + goto free_and_return; + } + /* + * skip address & flags if necessary + * + * RFC 2661 does not specify whether the PPP frame in the L2TP payload should + * have a HDLC header or not. We handle both cases for compatibility. + */ + if (p->len >= 2) { + GETSHORT(hflags, inp); + if (hflags == 0xff03) { + pbuf_header(p, -(s16_t)2); + } + } + /* Dispatch the packet thereby consuming it. */ + ppp_input(l2tp->ppp, p); + return; + +packet_too_short: + PPPDEBUG(LOG_DEBUG, ("pppol2tp: packet too short: %d\n", p->len)); +free_and_return: + pbuf_free(p); +} + +/* L2TP Control packet entry point */ +static void pppol2tp_dispatch_control_packet(pppol2tp_pcb *l2tp, u16_t port, struct pbuf *p, u16_t ns, u16_t nr) { + u8_t *inp; + u16_t avplen, avpflags, vendorid, attributetype, messagetype=0; + err_t err; +#if PPPOL2TP_AUTH_SUPPORT + md5_context md5_ctx; + u8_t md5_hash[16]; + u8_t challenge_id = 0; +#endif /* PPPOL2TP_AUTH_SUPPORT */ + + l2tp->peer_nr = nr; + l2tp->peer_ns = ns; + /* printf("L2TP CTRL INPUT, ns=%d, nr=%d, len=%d\n", ns, nr, p->len); */ + + /* Handle the special case of the ICCN acknowledge */ + if (l2tp->phase == PPPOL2TP_STATE_ICCN_SENT && l2tp->peer_nr > l2tp->our_ns) { + l2tp->phase = PPPOL2TP_STATE_DATA; + } + + /* ZLB packets */ + if (p->tot_len == 0) { + return; + } + + p = ppp_singlebuf(p); + inp = (u8_t*)p->payload; + /* Decode AVPs */ + while (p->len > 0) { + if (p->len < sizeof(avpflags) + sizeof(vendorid) + sizeof(attributetype) ) { + goto packet_too_short; + } + GETSHORT(avpflags, inp); + avplen = avpflags & PPPOL2TP_AVPHEADERFLAG_LENGTHMASK; + /* printf("AVPLEN = %d\n", avplen); */ + if (p->len < avplen || avplen < sizeof(avpflags) + sizeof(vendorid) + sizeof(attributetype)) { + goto packet_too_short; + } + GETSHORT(vendorid, inp); + GETSHORT(attributetype, inp); + avplen -= sizeof(avpflags) + sizeof(vendorid) + sizeof(attributetype); + + /* Message type must be the first AVP */ + if (messagetype == 0) { + if (attributetype != 0 || vendorid != 0 || avplen != sizeof(messagetype) ) { + PPPDEBUG(LOG_DEBUG, ("pppol2tp: message type must be the first AVP\n")); + return; + } + GETSHORT(messagetype, inp); + /* printf("Message type = %d\n", messagetype); */ + switch(messagetype) { + /* Start Control Connection Reply */ + case PPPOL2TP_MESSAGETYPE_SCCRP: + /* Only accept SCCRP packet if we sent a SCCRQ */ + if (l2tp->phase != PPPOL2TP_STATE_SCCRQ_SENT) { + goto send_zlb; + } + break; + /* Incoming Call Reply */ + case PPPOL2TP_MESSAGETYPE_ICRP: + /* Only accept ICRP packet if we sent a IRCQ */ + if (l2tp->phase != PPPOL2TP_STATE_ICRQ_SENT) { + goto send_zlb; + } + break; + /* Stop Control Connection Notification */ + case PPPOL2TP_MESSAGETYPE_STOPCCN: + pppol2tp_send_zlb(l2tp, l2tp->our_ns); /* Ack the StopCCN before we switch to down state */ + if (l2tp->phase < PPPOL2TP_STATE_DATA) { + pppol2tp_abort_connect(l2tp); + } else if (l2tp->phase == PPPOL2TP_STATE_DATA) { + /* Don't disconnect here, we let the LCP Echo/Reply find the fact + * that PPP session is down. Asking the PPP stack to end the session + * require strict checking about the PPP phase to prevent endless + * disconnection loops. + */ + } + return; + default: + break; + } + goto nextavp; + } + + /* Skip proprietary L2TP extensions */ + if (vendorid != 0) { + goto skipavp; + } + + switch (messagetype) { + /* Start Control Connection Reply */ + case PPPOL2TP_MESSAGETYPE_SCCRP: + switch (attributetype) { + case PPPOL2TP_AVPTYPE_TUNNELID: + if (avplen != sizeof(l2tp->source_tunnel_id) ) { + PPPDEBUG(LOG_DEBUG, ("pppol2tp: AVP Assign tunnel ID length check failed\n")); + return; + } + GETSHORT(l2tp->source_tunnel_id, inp); + PPPDEBUG(LOG_DEBUG, ("pppol2tp: Assigned tunnel ID %"U16_F"\n", l2tp->source_tunnel_id)); + goto nextavp; +#if PPPOL2TP_AUTH_SUPPORT + case PPPOL2TP_AVPTYPE_CHALLENGE: + if (avplen == 0) { + PPPDEBUG(LOG_DEBUG, ("pppol2tp: Challenge length check failed\n")); + return; + } + if (l2tp->secret == NULL) { + PPPDEBUG(LOG_DEBUG, ("pppol2tp: Received challenge from peer and no secret key available\n")); + pppol2tp_abort_connect(l2tp); + return; + } + /* Generate hash of ID, secret, challenge */ + md5_starts(&md5_ctx); + challenge_id = PPPOL2TP_MESSAGETYPE_SCCCN; + md5_update(&md5_ctx, &challenge_id, 1); + md5_update(&md5_ctx, l2tp->secret, l2tp->secret_len); + md5_update(&md5_ctx, inp, avplen); + md5_finish(&md5_ctx, l2tp->challenge_hash); + l2tp->send_challenge = 1; + goto skipavp; + case PPPOL2TP_AVPTYPE_CHALLENGERESPONSE: + if (avplen != PPPOL2TP_AVPTYPE_CHALLENGERESPONSE_SIZE) { + PPPDEBUG(LOG_DEBUG, ("pppol2tp: AVP Challenge Response length check failed\n")); + return; + } + /* Generate hash of ID, secret, challenge */ + md5_starts(&md5_ctx); + challenge_id = PPPOL2TP_MESSAGETYPE_SCCRP; + md5_update(&md5_ctx, &challenge_id, 1); + md5_update(&md5_ctx, l2tp->secret, l2tp->secret_len); + md5_update(&md5_ctx, l2tp->secret_rv, sizeof(l2tp->secret_rv)); + md5_finish(&md5_ctx, md5_hash); + if ( memcmp(inp, md5_hash, sizeof(md5_hash)) ) { + PPPDEBUG(LOG_DEBUG, ("pppol2tp: Received challenge response from peer and secret key do not match\n")); + pppol2tp_abort_connect(l2tp); + return; + } + goto skipavp; +#endif /* PPPOL2TP_AUTH_SUPPORT */ + default: + break; + } + break; + /* Incoming Call Reply */ + case PPPOL2TP_MESSAGETYPE_ICRP: + switch (attributetype) { + case PPPOL2TP_AVPTYPE_SESSIONID: + if (avplen != sizeof(l2tp->source_session_id) ) { + PPPDEBUG(LOG_DEBUG, ("pppol2tp: AVP Assign session ID length check failed\n")); + return; + } + GETSHORT(l2tp->source_session_id, inp); + PPPDEBUG(LOG_DEBUG, ("pppol2tp: Assigned session ID %"U16_F"\n", l2tp->source_session_id)); + goto nextavp; + default: + break; + } + break; + default: + break; + } + +skipavp: + INCPTR(avplen, inp); +nextavp: + /* printf("AVP Found, vendor=%d, attribute=%d, len=%d\n", vendorid, attributetype, avplen); */ + /* next AVP */ + if (pbuf_header(p, -(s16_t)(avplen + sizeof(avpflags) + sizeof(vendorid) + sizeof(attributetype)) ) != 0) { + return; + } + } + + switch(messagetype) { + /* Start Control Connection Reply */ + case PPPOL2TP_MESSAGETYPE_SCCRP: + do { + l2tp->remote_session_id = magic(); + } while(l2tp->remote_session_id == 0); + l2tp->tunnel_port = port; /* LNS server might have chosen its own local port */ + l2tp->icrq_retried = 0; + l2tp->phase = PPPOL2TP_STATE_ICRQ_SENT; + l2tp->our_ns++; + if ((err = pppol2tp_send_scccn(l2tp, l2tp->our_ns)) != 0) { + PPPDEBUG(LOG_DEBUG, ("pppol2tp: failed to send SCCCN, error=%d\n", err)); + } + l2tp->our_ns++; + if ((err = pppol2tp_send_icrq(l2tp, l2tp->our_ns)) != 0) { + PPPDEBUG(LOG_DEBUG, ("pppol2tp: failed to send ICRQ, error=%d\n", err)); + } + sys_untimeout(pppol2tp_timeout, l2tp); + sys_timeout(PPPOL2TP_CONTROL_TIMEOUT, pppol2tp_timeout, l2tp); + break; + /* Incoming Call Reply */ + case PPPOL2TP_MESSAGETYPE_ICRP: + l2tp->iccn_retried = 0; + l2tp->phase = PPPOL2TP_STATE_ICCN_SENT; + l2tp->our_ns++; + ppp_start(l2tp->ppp); /* notify upper layers */ + if ((err = pppol2tp_send_iccn(l2tp, l2tp->our_ns)) != 0) { + PPPDEBUG(LOG_DEBUG, ("pppol2tp: failed to send ICCN, error=%d\n", err)); + } + sys_untimeout(pppol2tp_timeout, l2tp); + sys_timeout(PPPOL2TP_CONTROL_TIMEOUT, pppol2tp_timeout, l2tp); + break; + /* Unhandled packet, send ZLB ACK */ + default: + goto send_zlb; + } + return; + +send_zlb: + pppol2tp_send_zlb(l2tp, l2tp->our_ns); + return; +packet_too_short: + PPPDEBUG(LOG_DEBUG, ("pppol2tp: packet too short: %d\n", p->len)); +} + +/* L2TP Timeout handler */ +static void pppol2tp_timeout(void *arg) { + pppol2tp_pcb *l2tp = (pppol2tp_pcb*)arg; + err_t err; + u32_t retry_wait; + + PPPDEBUG(LOG_DEBUG, ("pppol2tp: timeout\n")); + + switch (l2tp->phase) { + case PPPOL2TP_STATE_SCCRQ_SENT: + /* backoff wait */ + if (l2tp->sccrq_retried < 0xff) { + l2tp->sccrq_retried++; + } + if (!l2tp->ppp->settings.persist && l2tp->sccrq_retried >= PPPOL2TP_MAXSCCRQ) { + pppol2tp_abort_connect(l2tp); + return; + } + retry_wait = LWIP_MIN(PPPOL2TP_CONTROL_TIMEOUT * l2tp->sccrq_retried, PPPOL2TP_SLOW_RETRY); + PPPDEBUG(LOG_DEBUG, ("pppol2tp: sccrq_retried=%d\n", l2tp->sccrq_retried)); + if ((err = pppol2tp_send_sccrq(l2tp)) != 0) { + l2tp->sccrq_retried--; + PPPDEBUG(LOG_DEBUG, ("pppol2tp: failed to send SCCRQ, error=%d\n", err)); + } + sys_timeout(retry_wait, pppol2tp_timeout, l2tp); + break; + + case PPPOL2TP_STATE_ICRQ_SENT: + l2tp->icrq_retried++; + if (l2tp->icrq_retried >= PPPOL2TP_MAXICRQ) { + pppol2tp_abort_connect(l2tp); + return; + } + PPPDEBUG(LOG_DEBUG, ("pppol2tp: icrq_retried=%d\n", l2tp->icrq_retried)); + if (l2tp->peer_nr <= l2tp->our_ns -1) { /* the SCCCN was not acknowledged */ + if ((err = pppol2tp_send_scccn(l2tp, l2tp->our_ns -1)) != 0) { + l2tp->icrq_retried--; + PPPDEBUG(LOG_DEBUG, ("pppol2tp: failed to send SCCCN, error=%d\n", err)); + sys_timeout(PPPOL2TP_CONTROL_TIMEOUT, pppol2tp_timeout, l2tp); + break; + } + } + if ((err = pppol2tp_send_icrq(l2tp, l2tp->our_ns)) != 0) { + l2tp->icrq_retried--; + PPPDEBUG(LOG_DEBUG, ("pppol2tp: failed to send ICRQ, error=%d\n", err)); + } + sys_timeout(PPPOL2TP_CONTROL_TIMEOUT, pppol2tp_timeout, l2tp); + break; + + case PPPOL2TP_STATE_ICCN_SENT: + l2tp->iccn_retried++; + if (l2tp->iccn_retried >= PPPOL2TP_MAXICCN) { + pppol2tp_abort_connect(l2tp); + return; + } + PPPDEBUG(LOG_DEBUG, ("pppol2tp: iccn_retried=%d\n", l2tp->iccn_retried)); + if ((err = pppol2tp_send_iccn(l2tp, l2tp->our_ns)) != 0) { + l2tp->iccn_retried--; + PPPDEBUG(LOG_DEBUG, ("pppol2tp: failed to send ICCN, error=%d\n", err)); + } + sys_timeout(PPPOL2TP_CONTROL_TIMEOUT, pppol2tp_timeout, l2tp); + break; + + default: + return; /* all done, work in peace */ + } +} + +/* Connection attempt aborted */ +static void pppol2tp_abort_connect(pppol2tp_pcb *l2tp) { + PPPDEBUG(LOG_DEBUG, ("pppol2tp: could not establish connection\n")); + pppol2tp_clear(l2tp); + ppp_link_failed(l2tp->ppp); /* notify upper layers */ +} + +/* Reset L2TP control block to its initial state */ +static void pppol2tp_clear(pppol2tp_pcb *l2tp) { + /* stop any timer */ + sys_untimeout(pppol2tp_timeout, l2tp); + l2tp->phase = PPPOL2TP_STATE_INITIAL; + l2tp->tunnel_port = l2tp->remote_port; + l2tp->our_ns = 0; + l2tp->peer_nr = 0; + l2tp->peer_ns = 0; + l2tp->source_tunnel_id = 0; + l2tp->remote_tunnel_id = 0; + l2tp->source_session_id = 0; + l2tp->remote_session_id = 0; + /* l2tp->*_retried are cleared when used */ +} + +/* Initiate a new tunnel */ +static err_t pppol2tp_send_sccrq(pppol2tp_pcb *l2tp) { + struct pbuf *pb; + u8_t *p; + u16_t len; + + /* calculate UDP packet length */ + len = 12 +8 +8 +10 +10 +6+sizeof(PPPOL2TP_HOSTNAME)-1 +6+sizeof(PPPOL2TP_VENDORNAME)-1 +8 +8; +#if PPPOL2TP_AUTH_SUPPORT + if (l2tp->secret != NULL) { + len += 6 + sizeof(l2tp->secret_rv); + } +#endif /* PPPOL2TP_AUTH_SUPPORT */ + + /* allocate a buffer */ + pb = pbuf_alloc(PBUF_TRANSPORT, len, PBUF_RAM); + if (pb == NULL) { + return ERR_MEM; + } + LWIP_ASSERT("pb->tot_len == pb->len", pb->tot_len == pb->len); + + p = (u8_t*)pb->payload; + /* fill in pkt */ + /* L2TP control header */ + PUTSHORT(PPPOL2TP_HEADERFLAG_CONTROL_MANDATORY, p); + PUTSHORT(len, p); /* Length */ + PUTSHORT(0, p); /* Tunnel Id */ + PUTSHORT(0, p); /* Session Id */ + PUTSHORT(0, p); /* NS Sequence number - to peer */ + PUTSHORT(0, p); /* NR Sequence number - expected for peer */ + + /* AVP - Message type */ + PUTSHORT(PPPOL2TP_AVPHEADERFLAG_MANDATORY + 8, p); /* Mandatory flag + len field */ + PUTSHORT(0, p); /* Vendor ID */ + PUTSHORT(PPPOL2TP_AVPTYPE_MESSAGE, p); /* Attribute type: Message Type */ + PUTSHORT(PPPOL2TP_MESSAGETYPE_SCCRQ, p); /* Attribute value: Message type: SCCRQ */ + + /* AVP - L2TP Version */ + PUTSHORT(PPPOL2TP_AVPHEADERFLAG_MANDATORY + 8, p); /* Mandatory flag + len field */ + PUTSHORT(0, p); /* Vendor ID */ + PUTSHORT(PPPOL2TP_AVPTYPE_VERSION, p); /* Attribute type: Version */ + PUTSHORT(PPPOL2TP_VERSION, p); /* Attribute value: L2TP Version */ + + /* AVP - Framing capabilities */ + PUTSHORT(PPPOL2TP_AVPHEADERFLAG_MANDATORY + 10, p); /* Mandatory flag + len field */ + PUTSHORT(0, p); /* Vendor ID */ + PUTSHORT(PPPOL2TP_AVPTYPE_FRAMINGCAPABILITIES, p); /* Attribute type: Framing capabilities */ + PUTLONG(PPPOL2TP_FRAMINGCAPABILITIES, p); /* Attribute value: Framing capabilities */ + + /* AVP - Bearer capabilities */ + PUTSHORT(PPPOL2TP_AVPHEADERFLAG_MANDATORY + 10, p); /* Mandatory flag + len field */ + PUTSHORT(0, p); /* Vendor ID */ + PUTSHORT(PPPOL2TP_AVPTYPE_BEARERCAPABILITIES, p); /* Attribute type: Bearer capabilities */ + PUTLONG(PPPOL2TP_BEARERCAPABILITIES, p); /* Attribute value: Bearer capabilities */ + + /* AVP - Host name */ + PUTSHORT(PPPOL2TP_AVPHEADERFLAG_MANDATORY + 6+sizeof(PPPOL2TP_HOSTNAME)-1, p); /* Mandatory flag + len field */ + PUTSHORT(0, p); /* Vendor ID */ + PUTSHORT(PPPOL2TP_AVPTYPE_HOSTNAME, p); /* Attribute type: Hostname */ + MEMCPY(p, PPPOL2TP_HOSTNAME, sizeof(PPPOL2TP_HOSTNAME)-1); /* Attribute value: Hostname */ + INCPTR(sizeof(PPPOL2TP_HOSTNAME)-1, p); + + /* AVP - Vendor name */ + PUTSHORT(6+sizeof(PPPOL2TP_VENDORNAME)-1, p); /* len field */ + PUTSHORT(0, p); /* Vendor ID */ + PUTSHORT(PPPOL2TP_AVPTYPE_VENDORNAME, p); /* Attribute type: Vendor name */ + MEMCPY(p, PPPOL2TP_VENDORNAME, sizeof(PPPOL2TP_VENDORNAME)-1); /* Attribute value: Vendor name */ + INCPTR(sizeof(PPPOL2TP_VENDORNAME)-1, p); + + /* AVP - Assign tunnel ID */ + PUTSHORT(PPPOL2TP_AVPHEADERFLAG_MANDATORY + 8, p); /* Mandatory flag + len field */ + PUTSHORT(0, p); /* Vendor ID */ + PUTSHORT(PPPOL2TP_AVPTYPE_TUNNELID, p); /* Attribute type: Tunnel ID */ + PUTSHORT(l2tp->remote_tunnel_id, p); /* Attribute value: Tunnel ID */ + + /* AVP - Receive window size */ + PUTSHORT(PPPOL2TP_AVPHEADERFLAG_MANDATORY + 8, p); /* Mandatory flag + len field */ + PUTSHORT(0, p); /* Vendor ID */ + PUTSHORT(PPPOL2TP_AVPTYPE_RECEIVEWINDOWSIZE, p); /* Attribute type: Receive window size */ + PUTSHORT(PPPOL2TP_RECEIVEWINDOWSIZE, p); /* Attribute value: Receive window size */ + +#if PPPOL2TP_AUTH_SUPPORT + /* AVP - Challenge */ + if (l2tp->secret != NULL) { + PUTSHORT(PPPOL2TP_AVPHEADERFLAG_MANDATORY + 6 + sizeof(l2tp->secret_rv), p); /* Mandatory flag + len field */ + PUTSHORT(0, p); /* Vendor ID */ + PUTSHORT(PPPOL2TP_AVPTYPE_CHALLENGE, p); /* Attribute type: Challenge */ + MEMCPY(p, l2tp->secret_rv, sizeof(l2tp->secret_rv)); /* Attribute value: Random vector */ + INCPTR(sizeof(l2tp->secret_rv), p); + } +#endif /* PPPOL2TP_AUTH_SUPPORT */ + + return pppol2tp_udp_send(l2tp, pb); +} + +/* Complete tunnel establishment */ +static err_t pppol2tp_send_scccn(pppol2tp_pcb *l2tp, u16_t ns) { + struct pbuf *pb; + u8_t *p; + u16_t len; + + /* calculate UDP packet length */ + len = 12 +8; +#if PPPOL2TP_AUTH_SUPPORT + if (l2tp->send_challenge) { + len += 6 + sizeof(l2tp->challenge_hash); + } +#endif /* PPPOL2TP_AUTH_SUPPORT */ + + /* allocate a buffer */ + pb = pbuf_alloc(PBUF_TRANSPORT, len, PBUF_RAM); + if (pb == NULL) { + return ERR_MEM; + } + LWIP_ASSERT("pb->tot_len == pb->len", pb->tot_len == pb->len); + + p = (u8_t*)pb->payload; + /* fill in pkt */ + /* L2TP control header */ + PUTSHORT(PPPOL2TP_HEADERFLAG_CONTROL_MANDATORY, p); + PUTSHORT(len, p); /* Length */ + PUTSHORT(l2tp->source_tunnel_id, p); /* Tunnel Id */ + PUTSHORT(0, p); /* Session Id */ + PUTSHORT(ns, p); /* NS Sequence number - to peer */ + PUTSHORT(l2tp->peer_ns+1, p); /* NR Sequence number - expected for peer */ + + /* AVP - Message type */ + PUTSHORT(PPPOL2TP_AVPHEADERFLAG_MANDATORY + 8, p); /* Mandatory flag + len field */ + PUTSHORT(0, p); /* Vendor ID */ + PUTSHORT(PPPOL2TP_AVPTYPE_MESSAGE, p); /* Attribute type: Message Type */ + PUTSHORT(PPPOL2TP_MESSAGETYPE_SCCCN, p); /* Attribute value: Message type: SCCCN */ + +#if PPPOL2TP_AUTH_SUPPORT + /* AVP - Challenge response */ + if (l2tp->send_challenge) { + PUTSHORT(PPPOL2TP_AVPHEADERFLAG_MANDATORY + 6 + sizeof(l2tp->challenge_hash), p); /* Mandatory flag + len field */ + PUTSHORT(0, p); /* Vendor ID */ + PUTSHORT(PPPOL2TP_AVPTYPE_CHALLENGERESPONSE, p); /* Attribute type: Challenge response */ + MEMCPY(p, l2tp->challenge_hash, sizeof(l2tp->challenge_hash)); /* Attribute value: Computed challenge */ + INCPTR(sizeof(l2tp->challenge_hash), p); + } +#endif /* PPPOL2TP_AUTH_SUPPORT */ + + return pppol2tp_udp_send(l2tp, pb); +} + +/* Initiate a new session */ +static err_t pppol2tp_send_icrq(pppol2tp_pcb *l2tp, u16_t ns) { + struct pbuf *pb; + u8_t *p; + u16_t len; + u32_t serialnumber; + + /* calculate UDP packet length */ + len = 12 +8 +8 +10; + + /* allocate a buffer */ + pb = pbuf_alloc(PBUF_TRANSPORT, len, PBUF_RAM); + if (pb == NULL) { + return ERR_MEM; + } + LWIP_ASSERT("pb->tot_len == pb->len", pb->tot_len == pb->len); + + p = (u8_t*)pb->payload; + /* fill in pkt */ + /* L2TP control header */ + PUTSHORT(PPPOL2TP_HEADERFLAG_CONTROL_MANDATORY, p); + PUTSHORT(len, p); /* Length */ + PUTSHORT(l2tp->source_tunnel_id, p); /* Tunnel Id */ + PUTSHORT(0, p); /* Session Id */ + PUTSHORT(ns, p); /* NS Sequence number - to peer */ + PUTSHORT(l2tp->peer_ns+1, p); /* NR Sequence number - expected for peer */ + + /* AVP - Message type */ + PUTSHORT(PPPOL2TP_AVPHEADERFLAG_MANDATORY + 8, p); /* Mandatory flag + len field */ + PUTSHORT(0, p); /* Vendor ID */ + PUTSHORT(PPPOL2TP_AVPTYPE_MESSAGE, p); /* Attribute type: Message Type */ + PUTSHORT(PPPOL2TP_MESSAGETYPE_ICRQ, p); /* Attribute value: Message type: ICRQ */ + + /* AVP - Assign session ID */ + PUTSHORT(PPPOL2TP_AVPHEADERFLAG_MANDATORY + 8, p); /* Mandatory flag + len field */ + PUTSHORT(0, p); /* Vendor ID */ + PUTSHORT(PPPOL2TP_AVPTYPE_SESSIONID, p); /* Attribute type: Session ID */ + PUTSHORT(l2tp->remote_session_id, p); /* Attribute value: Session ID */ + + /* AVP - Call Serial Number */ + PUTSHORT(PPPOL2TP_AVPHEADERFLAG_MANDATORY + 10, p); /* Mandatory flag + len field */ + PUTSHORT(0, p); /* Vendor ID */ + PUTSHORT(PPPOL2TP_AVPTYPE_CALLSERIALNUMBER, p); /* Attribute type: Serial number */ + serialnumber = magic(); + PUTLONG(serialnumber, p); /* Attribute value: Serial number */ + + return pppol2tp_udp_send(l2tp, pb); +} + +/* Complete tunnel establishment */ +static err_t pppol2tp_send_iccn(pppol2tp_pcb *l2tp, u16_t ns) { + struct pbuf *pb; + u8_t *p; + u16_t len; + + /* calculate UDP packet length */ + len = 12 +8 +10 +10; + + /* allocate a buffer */ + pb = pbuf_alloc(PBUF_TRANSPORT, len, PBUF_RAM); + if (pb == NULL) { + return ERR_MEM; + } + LWIP_ASSERT("pb->tot_len == pb->len", pb->tot_len == pb->len); + + p = (u8_t*)pb->payload; + /* fill in pkt */ + /* L2TP control header */ + PUTSHORT(PPPOL2TP_HEADERFLAG_CONTROL_MANDATORY, p); + PUTSHORT(len, p); /* Length */ + PUTSHORT(l2tp->source_tunnel_id, p); /* Tunnel Id */ + PUTSHORT(l2tp->source_session_id, p); /* Session Id */ + PUTSHORT(ns, p); /* NS Sequence number - to peer */ + PUTSHORT(l2tp->peer_ns+1, p); /* NR Sequence number - expected for peer */ + + /* AVP - Message type */ + PUTSHORT(PPPOL2TP_AVPHEADERFLAG_MANDATORY + 8, p); /* Mandatory flag + len field */ + PUTSHORT(0, p); /* Vendor ID */ + PUTSHORT(PPPOL2TP_AVPTYPE_MESSAGE, p); /* Attribute type: Message Type */ + PUTSHORT(PPPOL2TP_MESSAGETYPE_ICCN, p); /* Attribute value: Message type: ICCN */ + + /* AVP - Framing type */ + PUTSHORT(PPPOL2TP_AVPHEADERFLAG_MANDATORY + 10, p); /* Mandatory flag + len field */ + PUTSHORT(0, p); /* Vendor ID */ + PUTSHORT(PPPOL2TP_AVPTYPE_FRAMINGTYPE, p); /* Attribute type: Framing type */ + PUTLONG(PPPOL2TP_FRAMINGTYPE, p); /* Attribute value: Framing type */ + + /* AVP - TX Connect speed */ + PUTSHORT(PPPOL2TP_AVPHEADERFLAG_MANDATORY + 10, p); /* Mandatory flag + len field */ + PUTSHORT(0, p); /* Vendor ID */ + PUTSHORT(PPPOL2TP_AVPTYPE_TXCONNECTSPEED, p); /* Attribute type: TX Connect speed */ + PUTLONG(PPPOL2TP_TXCONNECTSPEED, p); /* Attribute value: TX Connect speed */ + + return pppol2tp_udp_send(l2tp, pb); +} + +/* Send a ZLB ACK packet */ +static err_t pppol2tp_send_zlb(pppol2tp_pcb *l2tp, u16_t ns) { + struct pbuf *pb; + u8_t *p; + u16_t len; + + /* calculate UDP packet length */ + len = 12; + + /* allocate a buffer */ + pb = pbuf_alloc(PBUF_TRANSPORT, len, PBUF_RAM); + if (pb == NULL) { + return ERR_MEM; + } + LWIP_ASSERT("pb->tot_len == pb->len", pb->tot_len == pb->len); + + p = (u8_t*)pb->payload; + /* fill in pkt */ + /* L2TP control header */ + PUTSHORT(PPPOL2TP_HEADERFLAG_CONTROL_MANDATORY, p); + PUTSHORT(len, p); /* Length */ + PUTSHORT(l2tp->source_tunnel_id, p); /* Tunnel Id */ + PUTSHORT(0, p); /* Session Id */ + PUTSHORT(ns, p); /* NS Sequence number - to peer */ + PUTSHORT(l2tp->peer_ns+1, p); /* NR Sequence number - expected for peer */ + + return pppol2tp_udp_send(l2tp, pb); +} + +/* Send a StopCCN packet */ +static err_t pppol2tp_send_stopccn(pppol2tp_pcb *l2tp, u16_t ns) { + struct pbuf *pb; + u8_t *p; + u16_t len; + + /* calculate UDP packet length */ + len = 12 +8 +8 +8; + + /* allocate a buffer */ + pb = pbuf_alloc(PBUF_TRANSPORT, len, PBUF_RAM); + if (pb == NULL) { + return ERR_MEM; + } + LWIP_ASSERT("pb->tot_len == pb->len", pb->tot_len == pb->len); + + p = (u8_t*)pb->payload; + /* fill in pkt */ + /* L2TP control header */ + PUTSHORT(PPPOL2TP_HEADERFLAG_CONTROL_MANDATORY, p); + PUTSHORT(len, p); /* Length */ + PUTSHORT(l2tp->source_tunnel_id, p); /* Tunnel Id */ + PUTSHORT(0, p); /* Session Id */ + PUTSHORT(ns, p); /* NS Sequence number - to peer */ + PUTSHORT(l2tp->peer_ns+1, p); /* NR Sequence number - expected for peer */ + + /* AVP - Message type */ + PUTSHORT(PPPOL2TP_AVPHEADERFLAG_MANDATORY + 8, p); /* Mandatory flag + len field */ + PUTSHORT(0, p); /* Vendor ID */ + PUTSHORT(PPPOL2TP_AVPTYPE_MESSAGE, p); /* Attribute type: Message Type */ + PUTSHORT(PPPOL2TP_MESSAGETYPE_STOPCCN, p); /* Attribute value: Message type: StopCCN */ + + /* AVP - Assign tunnel ID */ + PUTSHORT(PPPOL2TP_AVPHEADERFLAG_MANDATORY + 8, p); /* Mandatory flag + len field */ + PUTSHORT(0, p); /* Vendor ID */ + PUTSHORT(PPPOL2TP_AVPTYPE_TUNNELID, p); /* Attribute type: Tunnel ID */ + PUTSHORT(l2tp->remote_tunnel_id, p); /* Attribute value: Tunnel ID */ + + /* AVP - Result code */ + PUTSHORT(PPPOL2TP_AVPHEADERFLAG_MANDATORY + 8, p); /* Mandatory flag + len field */ + PUTSHORT(0, p); /* Vendor ID */ + PUTSHORT(PPPOL2TP_AVPTYPE_RESULTCODE, p); /* Attribute type: Result code */ + PUTSHORT(PPPOL2TP_RESULTCODE, p); /* Attribute value: Result code */ + + return pppol2tp_udp_send(l2tp, pb); +} + +static err_t pppol2tp_xmit(pppol2tp_pcb *l2tp, struct pbuf *pb) { + u8_t *p; + + /* are we ready to process data yet? */ + if (l2tp->phase < PPPOL2TP_STATE_DATA) { + pbuf_free(pb); + return ERR_CONN; + } + + /* make room for L2TP header - should not fail */ + if (pbuf_header(pb, (s16_t)PPPOL2TP_OUTPUT_DATA_HEADER_LEN) != 0) { + /* bail out */ + PPPDEBUG(LOG_ERR, ("pppol2tp: pppol2tp_pcb: could not allocate room for L2TP header\n")); + LINK_STATS_INC(link.lenerr); + pbuf_free(pb); + return ERR_BUF; + } + + p = (u8_t*)pb->payload; + PUTSHORT(PPPOL2TP_HEADERFLAG_DATA_MANDATORY, p); + PUTSHORT(l2tp->source_tunnel_id, p); /* Tunnel Id */ + PUTSHORT(l2tp->source_session_id, p); /* Session Id */ + + return pppol2tp_udp_send(l2tp, pb); +} + +static err_t pppol2tp_udp_send(pppol2tp_pcb *l2tp, struct pbuf *pb) { + err_t err; + if (l2tp->netif) { + err = udp_sendto_if(l2tp->udp, pb, &l2tp->remote_ip, l2tp->tunnel_port, l2tp->netif); + } else { + err = udp_sendto(l2tp->udp, pb, &l2tp->remote_ip, l2tp->tunnel_port); + } + pbuf_free(pb); + return err; +} + +#endif /* PPP_SUPPORT && PPPOL2TP_SUPPORT */ diff --git a/components/lwip/netif/ppp/pppos.c b/components/lwip/netif/ppp/pppos.c new file mode 100755 index 0000000000..b24e7fa671 --- /dev/null +++ b/components/lwip/netif/ppp/pppos.c @@ -0,0 +1,899 @@ +/** + * @file + * Network Point to Point Protocol over Serial file. + * + */ + +/* + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + */ + +#include "lwip/opt.h" +#if PPP_SUPPORT && PPPOS_SUPPORT /* don't build if not configured for use in lwipopts.h */ + +#include + +#include "lwip/err.h" +#include "lwip/pbuf.h" +#include "lwip/sys.h" +#include "lwip/memp.h" +#include "lwip/netif.h" +#include "lwip/snmp.h" +#include "lwip/priv/tcpip_priv.h" +#include "lwip/api.h" +#include "lwip/ip4.h" /* for ip4_input() */ + +#include "netif/ppp/ppp_impl.h" +#include "netif/ppp/pppos.h" +#include "netif/ppp/vj.h" + +/* callbacks called from PPP core */ +static err_t pppos_write(ppp_pcb *ppp, void *ctx, struct pbuf *p); +static err_t pppos_netif_output(ppp_pcb *ppp, void *ctx, struct pbuf *pb, u16_t protocol); +static err_t pppos_connect(ppp_pcb *ppp, void *ctx); +#if PPP_SERVER +static err_t pppos_listen(ppp_pcb *ppp, void *ctx, struct ppp_addrs *addrs); +#endif /* PPP_SERVER */ +static void pppos_disconnect(ppp_pcb *ppp, void *ctx); +static err_t pppos_destroy(ppp_pcb *ppp, void *ctx); +static void pppos_send_config(ppp_pcb *ppp, void *ctx, u32_t accm, int pcomp, int accomp); +static void pppos_recv_config(ppp_pcb *ppp, void *ctx, u32_t accm, int pcomp, int accomp); + +/* Prototypes for procedures local to this file. */ +#if PPP_INPROC_IRQ_SAFE +static void pppos_input_callback(void *arg); +#endif /* PPP_INPROC_IRQ_SAFE */ +static void pppos_input_free_current_packet(pppos_pcb *pppos); +static void pppos_input_drop(pppos_pcb *pppos); +static err_t pppos_output_append(pppos_pcb *pppos, err_t err, struct pbuf *nb, u8_t c, u8_t accm, u16_t *fcs); +static err_t pppos_output_last(pppos_pcb *pppos, err_t err, struct pbuf *nb, u16_t *fcs); + +/* Callbacks structure for PPP core */ +static const struct link_callbacks pppos_callbacks = { + pppos_connect, +#if PPP_SERVER + pppos_listen, +#endif /* PPP_SERVER */ + pppos_disconnect, + pppos_destroy, + pppos_write, + pppos_netif_output, + pppos_send_config, + pppos_recv_config +}; + +/* PPP's Asynchronous-Control-Character-Map. The mask array is used + * to select the specific bit for a character. */ +#define ESCAPE_P(accm, c) ((accm)[(c) >> 3] & 1 << (c & 0x07)) + +#if PPP_FCS_TABLE +/* + * FCS lookup table as calculated by genfcstab. + */ +static const u16_t fcstab[256] = { + 0x0000, 0x1189, 0x2312, 0x329b, 0x4624, 0x57ad, 0x6536, 0x74bf, + 0x8c48, 0x9dc1, 0xaf5a, 0xbed3, 0xca6c, 0xdbe5, 0xe97e, 0xf8f7, + 0x1081, 0x0108, 0x3393, 0x221a, 0x56a5, 0x472c, 0x75b7, 0x643e, + 0x9cc9, 0x8d40, 0xbfdb, 0xae52, 0xdaed, 0xcb64, 0xf9ff, 0xe876, + 0x2102, 0x308b, 0x0210, 0x1399, 0x6726, 0x76af, 0x4434, 0x55bd, + 0xad4a, 0xbcc3, 0x8e58, 0x9fd1, 0xeb6e, 0xfae7, 0xc87c, 0xd9f5, + 0x3183, 0x200a, 0x1291, 0x0318, 0x77a7, 0x662e, 0x54b5, 0x453c, + 0xbdcb, 0xac42, 0x9ed9, 0x8f50, 0xfbef, 0xea66, 0xd8fd, 0xc974, + 0x4204, 0x538d, 0x6116, 0x709f, 0x0420, 0x15a9, 0x2732, 0x36bb, + 0xce4c, 0xdfc5, 0xed5e, 0xfcd7, 0x8868, 0x99e1, 0xab7a, 0xbaf3, + 0x5285, 0x430c, 0x7197, 0x601e, 0x14a1, 0x0528, 0x37b3, 0x263a, + 0xdecd, 0xcf44, 0xfddf, 0xec56, 0x98e9, 0x8960, 0xbbfb, 0xaa72, + 0x6306, 0x728f, 0x4014, 0x519d, 0x2522, 0x34ab, 0x0630, 0x17b9, + 0xef4e, 0xfec7, 0xcc5c, 0xddd5, 0xa96a, 0xb8e3, 0x8a78, 0x9bf1, + 0x7387, 0x620e, 0x5095, 0x411c, 0x35a3, 0x242a, 0x16b1, 0x0738, + 0xffcf, 0xee46, 0xdcdd, 0xcd54, 0xb9eb, 0xa862, 0x9af9, 0x8b70, + 0x8408, 0x9581, 0xa71a, 0xb693, 0xc22c, 0xd3a5, 0xe13e, 0xf0b7, + 0x0840, 0x19c9, 0x2b52, 0x3adb, 0x4e64, 0x5fed, 0x6d76, 0x7cff, + 0x9489, 0x8500, 0xb79b, 0xa612, 0xd2ad, 0xc324, 0xf1bf, 0xe036, + 0x18c1, 0x0948, 0x3bd3, 0x2a5a, 0x5ee5, 0x4f6c, 0x7df7, 0x6c7e, + 0xa50a, 0xb483, 0x8618, 0x9791, 0xe32e, 0xf2a7, 0xc03c, 0xd1b5, + 0x2942, 0x38cb, 0x0a50, 0x1bd9, 0x6f66, 0x7eef, 0x4c74, 0x5dfd, + 0xb58b, 0xa402, 0x9699, 0x8710, 0xf3af, 0xe226, 0xd0bd, 0xc134, + 0x39c3, 0x284a, 0x1ad1, 0x0b58, 0x7fe7, 0x6e6e, 0x5cf5, 0x4d7c, + 0xc60c, 0xd785, 0xe51e, 0xf497, 0x8028, 0x91a1, 0xa33a, 0xb2b3, + 0x4a44, 0x5bcd, 0x6956, 0x78df, 0x0c60, 0x1de9, 0x2f72, 0x3efb, + 0xd68d, 0xc704, 0xf59f, 0xe416, 0x90a9, 0x8120, 0xb3bb, 0xa232, + 0x5ac5, 0x4b4c, 0x79d7, 0x685e, 0x1ce1, 0x0d68, 0x3ff3, 0x2e7a, + 0xe70e, 0xf687, 0xc41c, 0xd595, 0xa12a, 0xb0a3, 0x8238, 0x93b1, + 0x6b46, 0x7acf, 0x4854, 0x59dd, 0x2d62, 0x3ceb, 0x0e70, 0x1ff9, + 0xf78f, 0xe606, 0xd49d, 0xc514, 0xb1ab, 0xa022, 0x92b9, 0x8330, + 0x7bc7, 0x6a4e, 0x58d5, 0x495c, 0x3de3, 0x2c6a, 0x1ef1, 0x0f78 +}; +#define PPP_FCS(fcs, c) (((fcs) >> 8) ^ fcstab[((fcs) ^ (c)) & 0xff]) +#else /* PPP_FCS_TABLE */ +/* The HDLC polynomial: X**0 + X**5 + X**12 + X**16 (0x8408) */ +#define PPP_FCS_POLYNOMIAL 0x8408 +static u16_t +ppp_get_fcs(u8_t byte) +{ + unsigned int octet; + int bit; + octet = byte; + for (bit = 8; bit-- > 0; ) { + octet = (octet & 0x01) ? ((octet >> 1) ^ PPP_FCS_POLYNOMIAL) : (octet >> 1); + } + return octet & 0xffff; +} +#define PPP_FCS(fcs, c) (((fcs) >> 8) ^ ppp_get_fcs(((fcs) ^ (c)) & 0xff)) +#endif /* PPP_FCS_TABLE */ + +/* + * Values for FCS calculations. + */ +#define PPP_INITFCS 0xffff /* Initial FCS value */ +#define PPP_GOODFCS 0xf0b8 /* Good final FCS value */ + +#if PPP_INPROC_IRQ_SAFE +#define PPPOS_DECL_PROTECT(lev) SYS_ARCH_DECL_PROTECT(lev) +#define PPPOS_PROTECT(lev) SYS_ARCH_PROTECT(lev) +#define PPPOS_UNPROTECT(lev) SYS_ARCH_UNPROTECT(lev) +#else +#define PPPOS_DECL_PROTECT(lev) +#define PPPOS_PROTECT(lev) +#define PPPOS_UNPROTECT(lev) +#endif /* PPP_INPROC_IRQ_SAFE */ + + +/* + * Create a new PPP connection using the given serial I/O device. + * + * Return 0 on success, an error code on failure. + */ +ppp_pcb *pppos_create(struct netif *pppif, pppos_output_cb_fn output_cb, + ppp_link_status_cb_fn link_status_cb, void *ctx_cb) +{ + pppos_pcb *pppos; + ppp_pcb *ppp; + + pppos = (pppos_pcb *)memp_malloc(MEMP_PPPOS_PCB); + if (pppos == NULL) { + return NULL; + } + + ppp = ppp_new(pppif, &pppos_callbacks, pppos, link_status_cb, ctx_cb); + if (ppp == NULL) { + memp_free(MEMP_PPPOS_PCB, pppos); + return NULL; + } + + memset(pppos, 0, sizeof(pppos_pcb)); + pppos->ppp = ppp; + pppos->output_cb = output_cb; + return ppp; +} + +/* Called by PPP core */ +static err_t +pppos_write(ppp_pcb *ppp, void *ctx, struct pbuf *p) +{ + pppos_pcb *pppos = (pppos_pcb *)ctx; + u8_t *s; + struct pbuf *nb; + u16_t n; + u16_t fcs_out; + err_t err; + LWIP_UNUSED_ARG(ppp); + + /* Grab an output buffer. */ + nb = pbuf_alloc(PBUF_RAW, 0, PBUF_POOL); + if (nb == NULL) { + PPPDEBUG(LOG_WARNING, ("pppos_write[%d]: alloc fail\n", ppp->netif->num)); + LINK_STATS_INC(link.memerr); + LINK_STATS_INC(link.drop); + MIB2_STATS_NETIF_INC(ppp->netif, ifoutdiscards); + pbuf_free(p); + return ERR_MEM; + } + + /* If the link has been idle, we'll send a fresh flag character to + * flush any noise. */ + err = ERR_OK; + if ((sys_now() - pppos->last_xmit) >= PPP_MAXIDLEFLAG) { + err = pppos_output_append(pppos, err, nb, PPP_FLAG, 0, NULL); + } + + /* Load output buffer. */ + fcs_out = PPP_INITFCS; + s = (u8_t*)p->payload; + n = p->len; + while (n-- > 0) { + err = pppos_output_append(pppos, err, nb, *s++, 1, &fcs_out); + } + + err = pppos_output_last(pppos, err, nb, &fcs_out); + if (err == ERR_OK) { + PPPDEBUG(LOG_INFO, ("pppos_write[%d]: len=%d\n", ppp->netif->num, p->len)); + } else { + PPPDEBUG(LOG_WARNING, ("pppos_write[%d]: output failed len=%d\n", ppp->netif->num, p->len)); + } + pbuf_free(p); + return err; +} + +/* Called by PPP core */ +static err_t +pppos_netif_output(ppp_pcb *ppp, void *ctx, struct pbuf *pb, u16_t protocol) +{ + pppos_pcb *pppos = (pppos_pcb *)ctx; + struct pbuf *nb, *p; + u16_t fcs_out; + err_t err; + LWIP_UNUSED_ARG(ppp); + + /* Grab an output buffer. */ + nb = pbuf_alloc(PBUF_RAW, 0, PBUF_POOL); + if (nb == NULL) { + PPPDEBUG(LOG_WARNING, ("pppos_netif_output[%d]: alloc fail\n", ppp->netif->num)); + LINK_STATS_INC(link.memerr); + LINK_STATS_INC(link.drop); + MIB2_STATS_NETIF_INC(ppp->netif, ifoutdiscards); + return ERR_MEM; + } + + /* If the link has been idle, we'll send a fresh flag character to + * flush any noise. */ + err = ERR_OK; + if ((sys_now() - pppos->last_xmit) >= PPP_MAXIDLEFLAG) { + err = pppos_output_append(pppos, err, nb, PPP_FLAG, 0, NULL); + } + + fcs_out = PPP_INITFCS; + if (!pppos->accomp) { + err = pppos_output_append(pppos, err, nb, PPP_ALLSTATIONS, 1, &fcs_out); + err = pppos_output_append(pppos, err, nb, PPP_UI, 1, &fcs_out); + } + if (!pppos->pcomp || protocol > 0xFF) { + err = pppos_output_append(pppos, err, nb, (protocol >> 8) & 0xFF, 1, &fcs_out); + } + err = pppos_output_append(pppos, err, nb, protocol & 0xFF, 1, &fcs_out); + + /* Load packet. */ + for(p = pb; p; p = p->next) { + u16_t n = p->len; + u8_t *s = (u8_t*)p->payload; + + while (n-- > 0) { + err = pppos_output_append(pppos, err, nb, *s++, 1, &fcs_out); + } + } + + err = pppos_output_last(pppos, err, nb, &fcs_out); + if (err == ERR_OK) { + PPPDEBUG(LOG_INFO, ("pppos_netif_output[%d]: proto=0x%"X16_F", len = %d\n", ppp->netif->num, protocol, pb->tot_len)); + } else { + PPPDEBUG(LOG_WARNING, ("pppos_netif_output[%d]: output failed proto=0x%"X16_F", len = %d\n", ppp->netif->num, protocol, pb->tot_len)); + } + return err; +} + +static err_t +pppos_connect(ppp_pcb *ppp, void *ctx) +{ + pppos_pcb *pppos = (pppos_pcb *)ctx; + PPPOS_DECL_PROTECT(lev); + +#if PPP_INPROC_IRQ_SAFE + /* input pbuf left over from last session? */ + pppos_input_free_current_packet(pppos); +#endif /* PPP_INPROC_IRQ_SAFE */ + + ppp_clear(ppp); + /* reset PPPoS control block to its initial state */ + memset(&pppos->last_xmit, 0, sizeof(pppos_pcb) - ( (char*)&((pppos_pcb*)0)->last_xmit - (char*)0 ) ); + + /* + * Default the in and out accm so that escape and flag characters + * are always escaped. + */ + pppos->in_accm[15] = 0x60; /* no need to protect since RX is not running */ + pppos->out_accm[15] = 0x60; + PPPOS_PROTECT(lev); + pppos->open = 1; + PPPOS_UNPROTECT(lev); + + /* + * Start the connection and handle incoming events (packet or timeout). + */ + PPPDEBUG(LOG_INFO, ("pppos_connect: unit %d: connecting\n", ppp->netif->num)); + ppp_start(ppp); /* notify upper layers */ + return ERR_OK; +} + +#if PPP_SERVER +static err_t +pppos_listen(ppp_pcb *ppp, void *ctx, struct ppp_addrs *addrs) +{ + pppos_pcb *pppos = (pppos_pcb *)ctx; +#if PPP_IPV4_SUPPORT + ipcp_options *ipcp_wo; +#endif /* PPP_IPV4_SUPPORT */ + lcp_options *lcp_wo; + PPPOS_DECL_PROTECT(lev); + +#if PPP_INPROC_IRQ_SAFE + /* input pbuf left over from last session? */ + pppos_input_free_current_packet(pppos); +#endif /* PPP_INPROC_IRQ_SAFE */ + + ppp_clear(ppp); + /* reset PPPoS control block to its initial state */ + memset(&pppos->last_xmit, 0, sizeof(pppos_pcb) - ( (char*)&((pppos_pcb*)0)->last_xmit - (char*)0 ) ); + + /* Wait passively */ + lcp_wo = &ppp->lcp_wantoptions; + lcp_wo->silent = 1; + +#if PPP_AUTH_SUPPORT + if (ppp->settings.user && ppp->settings.passwd) { + ppp->settings.auth_required = 1; + } +#endif /* PPP_AUTH_SUPPORT */ + +#if PPP_IPV4_SUPPORT + ipcp_wo = &ppp->ipcp_wantoptions; + ipcp_wo->ouraddr = ip4_addr_get_u32(&addrs->our_ipaddr); + ipcp_wo->hisaddr = ip4_addr_get_u32(&addrs->his_ipaddr); +#if LWIP_DNS + ipcp_wo->dnsaddr[0] = ip4_addr_get_u32(&addrs->dns1); + ipcp_wo->dnsaddr[1] = ip4_addr_get_u32(&addrs->dns2); +#endif /* LWIP_DNS */ +#else /* PPP_IPV4_SUPPORT */ + LWIP_UNUSED_ARG(addrs); +#endif /* PPP_IPV4_SUPPORT */ + + /* + * Default the in and out accm so that escape and flag characters + * are always escaped. + */ + pppos->in_accm[15] = 0x60; /* no need to protect since RX is not running */ + pppos->out_accm[15] = 0x60; + PPPOS_PROTECT(lev); + pppos->open = 1; + PPPOS_UNPROTECT(lev); + + /* + * Wait for something to happen. + */ + PPPDEBUG(LOG_INFO, ("pppos_listen: unit %d: listening\n", ppp->netif->num)); + ppp_start(ppp); /* notify upper layers */ + return ERR_OK; +} +#endif /* PPP_SERVER */ + +static void +pppos_disconnect(ppp_pcb *ppp, void *ctx) +{ + pppos_pcb *pppos = (pppos_pcb *)ctx; + PPPOS_DECL_PROTECT(lev); + + PPPOS_PROTECT(lev); + pppos->open = 0; + PPPOS_UNPROTECT(lev); + + /* If PPP_INPROC_IRQ_SAFE is used we cannot call + * pppos_input_free_current_packet() here because + * rx IRQ might still call pppos_input(). + */ +#if !PPP_INPROC_IRQ_SAFE + /* input pbuf left ? */ + pppos_input_free_current_packet(pppos); +#endif /* !PPP_INPROC_IRQ_SAFE */ + + ppp_link_end(ppp); /* notify upper layers */ +} + +static err_t +pppos_destroy(ppp_pcb *ppp, void *ctx) +{ + pppos_pcb *pppos = (pppos_pcb *)ctx; + LWIP_UNUSED_ARG(ppp); + +#if PPP_INPROC_IRQ_SAFE + /* input pbuf left ? */ + pppos_input_free_current_packet(pppos); +#endif /* PPP_INPROC_IRQ_SAFE */ + + memp_free(MEMP_PPPOS_PCB, pppos); + return ERR_OK; +} + +#if !NO_SYS && !PPP_INPROC_IRQ_SAFE +/** Pass received raw characters to PPPoS to be decoded through lwIP TCPIP thread. + * + * @param pcb PPP descriptor index, returned by pppos_create() + * @param data received data + * @param len length of received data + */ +err_t +pppos_input_tcpip(ppp_pcb *ppp, u8_t *s, int l) +{ + struct pbuf *p; + err_t err; + + p = pbuf_alloc(PBUF_RAW, l, PBUF_POOL); + if (!p) { + return ERR_MEM; + } + pbuf_take(p, s, l); + + err = tcpip_inpkt(p, ppp_netif(ppp), pppos_input_sys); + if (err != ERR_OK) { + pbuf_free(p); + } + return err; +} + +/* called from TCPIP thread */ +err_t pppos_input_sys(struct pbuf *p, struct netif *inp) { + ppp_pcb *ppp = (ppp_pcb*)inp->state; + struct pbuf *n; + + for (n = p; n; n = n->next) { + pppos_input(ppp, (u8_t*)n->payload, n->len); + } + pbuf_free(p); + return ERR_OK; +} +#endif /* !NO_SYS && !PPP_INPROC_IRQ_SAFE */ + +/** PPPoS input helper struct, must be packed since it is stored + * to pbuf->payload, which might be unaligned. */ +#if PPP_INPROC_IRQ_SAFE +#ifdef PACK_STRUCT_USE_INCLUDES +# include "arch/bpstruct.h" +#endif +PACK_STRUCT_BEGIN +struct pppos_input_header { + PACK_STRUCT_FIELD(ppp_pcb *ppp); +} PACK_STRUCT_STRUCT; +PACK_STRUCT_END +#ifdef PACK_STRUCT_USE_INCLUDES +# include "arch/epstruct.h" +#endif +#endif /* PPP_INPROC_IRQ_SAFE */ + +/** Pass received raw characters to PPPoS to be decoded. + * + * @param pcb PPP descriptor index, returned by pppos_create() + * @param data received data + * @param len length of received data + */ +void +pppos_input(ppp_pcb *ppp, u8_t *s, int l) +{ + pppos_pcb *pppos = (pppos_pcb *)ppp->link_ctx_cb; + struct pbuf *next_pbuf; + u8_t cur_char; + u8_t escaped; + PPPOS_DECL_PROTECT(lev); + + PPPOS_PROTECT(lev); + if (!pppos->open) { + PPPOS_UNPROTECT(lev); + return; + } + PPPOS_UNPROTECT(lev); + + PPPDEBUG(LOG_DEBUG, ("pppos_input[%d]: got %d bytes\n", ppp->netif->num, l)); + while (l-- > 0) { + cur_char = *s++; + + PPPOS_PROTECT(lev); + escaped = ESCAPE_P(pppos->in_accm, cur_char); + PPPOS_UNPROTECT(lev); + /* Handle special characters. */ + if (escaped) { + /* Check for escape sequences. */ + /* XXX Note that this does not handle an escaped 0x5d character which + * would appear as an escape character. Since this is an ASCII ']' + * and there is no reason that I know of to escape it, I won't complicate + * the code to handle this case. GLL */ + if (cur_char == PPP_ESCAPE) { + pppos->in_escaped = 1; + /* Check for the flag character. */ + } else if (cur_char == PPP_FLAG) { + /* If this is just an extra flag character, ignore it. */ + if (pppos->in_state <= PDADDRESS) { + /* ignore it */; + /* If we haven't received the packet header, drop what has come in. */ + } else if (pppos->in_state < PDDATA) { + PPPDEBUG(LOG_WARNING, + ("pppos_input[%d]: Dropping incomplete packet %d\n", + ppp->netif->num, pppos->in_state)); + LINK_STATS_INC(link.lenerr); + pppos_input_drop(pppos); + /* If the fcs is invalid, drop the packet. */ + } else if (pppos->in_fcs != PPP_GOODFCS) { + PPPDEBUG(LOG_INFO, + ("pppos_input[%d]: Dropping bad fcs 0x%"X16_F" proto=0x%"X16_F"\n", + ppp->netif->num, pppos->in_fcs, pppos->in_protocol)); + /* Note: If you get lots of these, check for UART frame errors or try different baud rate */ + LINK_STATS_INC(link.chkerr); + pppos_input_drop(pppos); + /* Otherwise it's a good packet so pass it on. */ + } else { + struct pbuf *inp; + /* Trim off the checksum. */ + if(pppos->in_tail->len > 2) { + pppos->in_tail->len -= 2; + + pppos->in_tail->tot_len = pppos->in_tail->len; + if (pppos->in_tail != pppos->in_head) { + pbuf_cat(pppos->in_head, pppos->in_tail); + } + } else { + pppos->in_tail->tot_len = pppos->in_tail->len; + if (pppos->in_tail != pppos->in_head) { + pbuf_cat(pppos->in_head, pppos->in_tail); + } + + pbuf_realloc(pppos->in_head, pppos->in_head->tot_len - 2); + } + + /* Dispatch the packet thereby consuming it. */ + inp = pppos->in_head; + /* Packet consumed, release our references. */ + pppos->in_head = NULL; + pppos->in_tail = NULL; +#if IP_FORWARD || LWIP_IPV6_FORWARD + /* hide the room for Ethernet forwarding header */ + pbuf_header(inp, -(s16_t)(PBUF_LINK_ENCAPSULATION_HLEN + PBUF_LINK_HLEN)); +#endif /* IP_FORWARD || LWIP_IPV6_FORWARD */ +#if PPP_INPROC_IRQ_SAFE + if(tcpip_callback_with_block(pppos_input_callback, inp, 0) != ERR_OK) { + PPPDEBUG(LOG_ERR, ("pppos_input[%d]: tcpip_callback() failed, dropping packet\n", ppp->netif->num)); + pbuf_free(inp); + LINK_STATS_INC(link.drop); + MIB2_STATS_NETIF_INC(ppp->netif, ifindiscards); + } +#else /* PPP_INPROC_IRQ_SAFE */ + ppp_input(ppp, inp); +#endif /* PPP_INPROC_IRQ_SAFE */ + } + + /* Prepare for a new packet. */ + pppos->in_fcs = PPP_INITFCS; + pppos->in_state = PDADDRESS; + pppos->in_escaped = 0; + /* Other characters are usually control characters that may have + * been inserted by the physical layer so here we just drop them. */ + } else { + PPPDEBUG(LOG_WARNING, + ("pppos_input[%d]: Dropping ACCM char <%d>\n", ppp->netif->num, cur_char)); + } + /* Process other characters. */ + } else { + /* Unencode escaped characters. */ + if (pppos->in_escaped) { + pppos->in_escaped = 0; + cur_char ^= PPP_TRANS; + } + + /* Process character relative to current state. */ + switch(pppos->in_state) { + case PDIDLE: /* Idle state - waiting. */ + /* Drop the character if it's not 0xff + * we would have processed a flag character above. */ + if (cur_char != PPP_ALLSTATIONS) { + break; + } + /* no break */ + /* Fall through */ + + case PDSTART: /* Process start flag. */ + /* Prepare for a new packet. */ + pppos->in_fcs = PPP_INITFCS; + /* no break */ + /* Fall through */ + + case PDADDRESS: /* Process address field. */ + if (cur_char == PPP_ALLSTATIONS) { + pppos->in_state = PDCONTROL; + break; + } + /* no break */ + + /* Else assume compressed address and control fields so + * fall through to get the protocol... */ + case PDCONTROL: /* Process control field. */ + /* If we don't get a valid control code, restart. */ + if (cur_char == PPP_UI) { + pppos->in_state = PDPROTOCOL1; + break; + } + /* no break */ + +#if 0 + else { + PPPDEBUG(LOG_WARNING, + ("pppos_input[%d]: Invalid control <%d>\n", ppp->netif->num, cur_char)); + pppos->in_state = PDSTART; + } +#endif + case PDPROTOCOL1: /* Process protocol field 1. */ + /* If the lower bit is set, this is the end of the protocol + * field. */ + if (cur_char & 1) { + pppos->in_protocol = cur_char; + pppos->in_state = PDDATA; + } else { + pppos->in_protocol = (u16_t)cur_char << 8; + pppos->in_state = PDPROTOCOL2; + } + break; + case PDPROTOCOL2: /* Process protocol field 2. */ + pppos->in_protocol |= cur_char; + pppos->in_state = PDDATA; + break; + case PDDATA: /* Process data byte. */ + /* Make space to receive processed data. */ + if (pppos->in_tail == NULL || pppos->in_tail->len == PBUF_POOL_BUFSIZE) { + u16_t pbuf_alloc_len; + if (pppos->in_tail != NULL) { + pppos->in_tail->tot_len = pppos->in_tail->len; + if (pppos->in_tail != pppos->in_head) { + pbuf_cat(pppos->in_head, pppos->in_tail); + /* give up the in_tail reference now */ + pppos->in_tail = NULL; + } + } + /* If we haven't started a packet, we need a packet header. */ + pbuf_alloc_len = 0; +#if IP_FORWARD || LWIP_IPV6_FORWARD + /* If IP forwarding is enabled we are reserving PBUF_LINK_ENCAPSULATION_HLEN + * + PBUF_LINK_HLEN bytes so the packet is being allocated with enough header + * space to be forwarded (to Ethernet for example). + */ + if (pppos->in_head == NULL) { + pbuf_alloc_len = PBUF_LINK_ENCAPSULATION_HLEN + PBUF_LINK_HLEN; + } +#endif /* IP_FORWARD || LWIP_IPV6_FORWARD */ + next_pbuf = pbuf_alloc(PBUF_RAW, pbuf_alloc_len, PBUF_POOL); + if (next_pbuf == NULL) { + /* No free buffers. Drop the input packet and let the + * higher layers deal with it. Continue processing + * the received pbuf chain in case a new packet starts. */ + PPPDEBUG(LOG_ERR, ("pppos_input[%d]: NO FREE PBUFS!\n", ppp->netif->num)); + LINK_STATS_INC(link.memerr); + pppos_input_drop(pppos); + pppos->in_state = PDSTART; /* Wait for flag sequence. */ + break; + } + if (pppos->in_head == NULL) { + u8_t *payload = ((u8_t*)next_pbuf->payload) + pbuf_alloc_len; +#if PPP_INPROC_IRQ_SAFE + ((struct pppos_input_header*)payload)->ppp = ppp; + payload += sizeof(struct pppos_input_header); + next_pbuf->len += sizeof(struct pppos_input_header); +#endif /* PPP_INPROC_IRQ_SAFE */ + next_pbuf->len += sizeof(pppos->in_protocol); + *(payload++) = pppos->in_protocol >> 8; + *(payload) = pppos->in_protocol & 0xFF; + pppos->in_head = next_pbuf; + } + pppos->in_tail = next_pbuf; + } + /* Load character into buffer. */ + ((u8_t*)pppos->in_tail->payload)[pppos->in_tail->len++] = cur_char; + break; + default: + break; + } + + /* update the frame check sequence number. */ + pppos->in_fcs = PPP_FCS(pppos->in_fcs, cur_char); + } + } /* while (l-- > 0), all bytes processed */ +} + +#if PPP_INPROC_IRQ_SAFE +/* PPPoS input callback using one input pointer + */ +static void pppos_input_callback(void *arg) { + struct pbuf *pb = (struct pbuf*)arg; + ppp_pcb *ppp; + + ppp = ((struct pppos_input_header*)pb->payload)->ppp; + if(pbuf_header(pb, -(s16_t)sizeof(struct pppos_input_header))) { + LWIP_ASSERT("pbuf_header failed\n", 0); + goto drop; + } + + /* Dispatch the packet thereby consuming it. */ + ppp_input(ppp, pb); + return; + +drop: + LINK_STATS_INC(link.drop); + MIB2_STATS_NETIF_INC(ppp->netif, ifindiscards); + pbuf_free(pb); +} +#endif /* PPP_INPROC_IRQ_SAFE */ + +static void +pppos_send_config(ppp_pcb *ppp, void *ctx, u32_t accm, int pcomp, int accomp) +{ + int i; + pppos_pcb *pppos = (pppos_pcb *)ctx; + LWIP_UNUSED_ARG(ppp); + + pppos->pcomp = pcomp; + pppos->accomp = accomp; + + /* Load the ACCM bits for the 32 control codes. */ + for (i = 0; i < 32/8; i++) { + pppos->out_accm[i] = (u8_t)((accm >> (8 * i)) & 0xFF); + } + + PPPDEBUG(LOG_INFO, ("pppos_send_config[%d]: out_accm=%X %X %X %X\n", + pppos->ppp->netif->num, + pppos->out_accm[0], pppos->out_accm[1], pppos->out_accm[2], pppos->out_accm[3])); +} + +static void +pppos_recv_config(ppp_pcb *ppp, void *ctx, u32_t accm, int pcomp, int accomp) +{ + int i; + pppos_pcb *pppos = (pppos_pcb *)ctx; + PPPOS_DECL_PROTECT(lev); + LWIP_UNUSED_ARG(ppp); + LWIP_UNUSED_ARG(pcomp); + LWIP_UNUSED_ARG(accomp); + + /* Load the ACCM bits for the 32 control codes. */ + PPPOS_PROTECT(lev); + for (i = 0; i < 32 / 8; i++) { + pppos->in_accm[i] = (u8_t)(accm >> (i * 8)); + } + PPPOS_UNPROTECT(lev); + + PPPDEBUG(LOG_INFO, ("pppos_recv_config[%d]: in_accm=%X %X %X %X\n", + pppos->ppp->netif->num, + pppos->in_accm[0], pppos->in_accm[1], pppos->in_accm[2], pppos->in_accm[3])); +} + +/* + * Drop the input packet. + */ +static void +pppos_input_free_current_packet(pppos_pcb *pppos) +{ + if (pppos->in_head != NULL) { + if (pppos->in_tail && (pppos->in_tail != pppos->in_head)) { + pbuf_free(pppos->in_tail); + } + pbuf_free(pppos->in_head); + pppos->in_head = NULL; + } + pppos->in_tail = NULL; +} + +/* + * Drop the input packet and increase error counters. + */ +static void +pppos_input_drop(pppos_pcb *pppos) +{ + if (pppos->in_head != NULL) { +#if 0 + PPPDEBUG(LOG_INFO, ("pppos_input_drop: %d:%.*H\n", pppos->in_head->len, min(60, pppos->in_head->len * 2), pppos->in_head->payload)); +#endif + PPPDEBUG(LOG_INFO, ("pppos_input_drop: pbuf len=%d, addr %p\n", pppos->in_head->len, (void*)pppos->in_head)); + } + pppos_input_free_current_packet(pppos); +#if VJ_SUPPORT && LWIP_TCP + vj_uncompress_err(&pppos->ppp->vj_comp); +#endif /* VJ_SUPPORT && LWIP_TCP */ + + LINK_STATS_INC(link.drop); + MIB2_STATS_NETIF_INC(pppos->ppp->netif, ifindiscards); +} + +/* + * pppos_output_append - append given character to end of given pbuf. + * If out_accm is not 0 and the character needs to be escaped, do so. + * If pbuf is full, send the pbuf and reuse it. + * Return the current pbuf. + */ +static err_t +pppos_output_append(pppos_pcb *pppos, err_t err, struct pbuf *nb, u8_t c, u8_t accm, u16_t *fcs) +{ + if (err != ERR_OK) { + return err; + } + + /* Make sure there is room for the character and an escape code. + * Sure we don't quite fill the buffer if the character doesn't + * get escaped but is one character worth complicating this? */ + if ((PBUF_POOL_BUFSIZE - nb->len) < 2) { + u32_t l = pppos->output_cb(pppos->ppp, (u8_t*)nb->payload, nb->len, pppos->ppp->ctx_cb); + if (l != nb->len) { + return ERR_IF; + } + nb->len = 0; + } + + /* Update FCS before checking for special characters. */ + if (fcs) { + *fcs = PPP_FCS(*fcs, c); + } + + /* Copy to output buffer escaping special characters. */ + if (accm && ESCAPE_P(pppos->out_accm, c)) { + *((u8_t*)nb->payload + nb->len++) = PPP_ESCAPE; + *((u8_t*)nb->payload + nb->len++) = c ^ PPP_TRANS; + } else { + *((u8_t*)nb->payload + nb->len++) = c; + } + + return ERR_OK; +} + +static err_t +pppos_output_last(pppos_pcb *pppos, err_t err, struct pbuf *nb, u16_t *fcs) +{ + ppp_pcb *ppp = pppos->ppp; + + /* Add FCS and trailing flag. */ + err = pppos_output_append(pppos, err, nb, ~(*fcs) & 0xFF, 1, NULL); + err = pppos_output_append(pppos, err, nb, (~(*fcs) >> 8) & 0xFF, 1, NULL); + err = pppos_output_append(pppos, err, nb, PPP_FLAG, 0, NULL); + + if (err != ERR_OK) { + goto failed; + } + + /* Send remaining buffer if not empty */ + if (nb->len > 0) { + u32_t l = pppos->output_cb(ppp, (u8_t*)nb->payload, nb->len, ppp->ctx_cb); + if (l != nb->len) { + err = ERR_IF; + goto failed; + } + } + + pppos->last_xmit = sys_now(); + MIB2_STATS_NETIF_ADD(ppp->netif, ifoutoctets, nb->tot_len); + MIB2_STATS_NETIF_INC(ppp->netif, ifoutucastpkts); + LINK_STATS_INC(link.xmit); + pbuf_free(nb); + return ERR_OK; + +failed: + pppos->last_xmit = 0; /* prepend PPP_FLAG to next packet */ + LINK_STATS_INC(link.err); + LINK_STATS_INC(link.drop); + MIB2_STATS_NETIF_INC(ppp->netif, ifoutdiscards); + pbuf_free(nb); + return err; +} + +#endif /* PPP_SUPPORT && PPPOS_SUPPORT */ diff --git a/components/lwip/netif/ppp/upap.c b/components/lwip/netif/ppp/upap.c new file mode 100755 index 0000000000..470303a21b --- /dev/null +++ b/components/lwip/netif/ppp/upap.c @@ -0,0 +1,677 @@ +/* + * upap.c - User/Password Authentication Protocol. + * + * Copyright (c) 1984-2000 Carnegie Mellon University. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. The name "Carnegie Mellon University" must not be used to + * endorse or promote products derived from this software without + * prior written permission. For permission or any legal + * details, please contact + * Office of Technology Transfer + * Carnegie Mellon University + * 5000 Forbes Avenue + * Pittsburgh, PA 15213-3890 + * (412) 268-4387, fax: (412) 268-7395 + * tech-transfer@andrew.cmu.edu + * + * 4. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by Computing Services + * at Carnegie Mellon University (http://www.cmu.edu/computing/)." + * + * CARNEGIE MELLON UNIVERSITY DISCLAIMS ALL WARRANTIES WITH REGARD TO + * THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS, IN NO EVENT SHALL CARNEGIE MELLON UNIVERSITY BE LIABLE + * FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN + * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING + * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include "lwip/opt.h" +#if PPP_SUPPORT && PAP_SUPPORT /* don't build if not configured for use in lwipopts.h */ + +/* + * TODO: + */ + +#if 0 /* UNUSED */ +#include +#include +#endif /* UNUSED */ + +#include "netif/ppp/ppp_impl.h" + +#include "netif/ppp/upap.h" + +#if PPP_OPTIONS +/* + * Command-line options. + */ +static option_t pap_option_list[] = { + { "hide-password", o_bool, &hide_password, + "Don't output passwords to log", OPT_PRIO | 1 }, + { "show-password", o_bool, &hide_password, + "Show password string in debug log messages", OPT_PRIOSUB | 0 }, + + { "pap-restart", o_int, &upap[0].us_timeouttime, + "Set retransmit timeout for PAP", OPT_PRIO }, + { "pap-max-authreq", o_int, &upap[0].us_maxtransmits, + "Set max number of transmissions for auth-reqs", OPT_PRIO }, + { "pap-timeout", o_int, &upap[0].us_reqtimeout, + "Set time limit for peer PAP authentication", OPT_PRIO }, + + { NULL } +}; +#endif /* PPP_OPTIONS */ + +/* + * Protocol entry points. + */ +static void upap_init(ppp_pcb *pcb); +static void upap_lowerup(ppp_pcb *pcb); +static void upap_lowerdown(ppp_pcb *pcb); +static void upap_input(ppp_pcb *pcb, u_char *inpacket, int l); +static void upap_protrej(ppp_pcb *pcb); +#if PRINTPKT_SUPPORT +static int upap_printpkt(const u_char *p, int plen, void (*printer) (void *, const char *, ...), void *arg); +#endif /* PRINTPKT_SUPPORT */ + +const struct protent pap_protent = { + PPP_PAP, + upap_init, + upap_input, + upap_protrej, + upap_lowerup, + upap_lowerdown, + NULL, + NULL, +#if PRINTPKT_SUPPORT + upap_printpkt, +#endif /* PRINTPKT_SUPPORT */ +#if PPP_DATAINPUT + NULL, +#endif /* PPP_DATAINPUT */ +#if PRINTPKT_SUPPORT + "PAP", + NULL, +#endif /* PRINTPKT_SUPPORT */ +#if PPP_OPTIONS + pap_option_list, + NULL, +#endif /* PPP_OPTIONS */ +#if DEMAND_SUPPORT + NULL, + NULL +#endif /* DEMAND_SUPPORT */ +}; + +static void upap_timeout(void *arg); +#if PPP_SERVER +static void upap_reqtimeout(void *arg); +static void upap_rauthreq(ppp_pcb *pcb, u_char *inp, int id, int len); +#endif /* PPP_SERVER */ +static void upap_rauthack(ppp_pcb *pcb, u_char *inp, int id, int len); +static void upap_rauthnak(ppp_pcb *pcb, u_char *inp, int id, int len); +static void upap_sauthreq(ppp_pcb *pcb); +#if PPP_SERVER +static void upap_sresp(ppp_pcb *pcb, u_char code, u_char id, const char *msg, int msglen); +#endif /* PPP_SERVER */ + + +/* + * upap_init - Initialize a UPAP unit. + */ +static void upap_init(ppp_pcb *pcb) { + pcb->upap.us_user = NULL; + pcb->upap.us_userlen = 0; + pcb->upap.us_passwd = NULL; + pcb->upap.us_passwdlen = 0; + pcb->upap.us_clientstate = UPAPCS_INITIAL; +#if PPP_SERVER + pcb->upap.us_serverstate = UPAPSS_INITIAL; +#endif /* PPP_SERVER */ + pcb->upap.us_id = 0; +} + + +/* + * upap_authwithpeer - Authenticate us with our peer (start client). + * + * Set new state and send authenticate's. + */ +void upap_authwithpeer(ppp_pcb *pcb, const char *user, const char *password) { + + if(!user || !password) + return; + + /* Save the username and password we're given */ + pcb->upap.us_user = user; + pcb->upap.us_userlen = LWIP_MIN(strlen(user), 0xff); + pcb->upap.us_passwd = password; + pcb->upap.us_passwdlen = LWIP_MIN(strlen(password), 0xff); + pcb->upap.us_transmits = 0; + + /* Lower layer up yet? */ + if (pcb->upap.us_clientstate == UPAPCS_INITIAL || + pcb->upap.us_clientstate == UPAPCS_PENDING) { + pcb->upap.us_clientstate = UPAPCS_PENDING; + return; + } + + upap_sauthreq(pcb); /* Start protocol */ +} + +#if PPP_SERVER +/* + * upap_authpeer - Authenticate our peer (start server). + * + * Set new state. + */ +void upap_authpeer(ppp_pcb *pcb) { + + /* Lower layer up yet? */ + if (pcb->upap.us_serverstate == UPAPSS_INITIAL || + pcb->upap.us_serverstate == UPAPSS_PENDING) { + pcb->upap.us_serverstate = UPAPSS_PENDING; + return; + } + + pcb->upap.us_serverstate = UPAPSS_LISTEN; + if (pcb->settings.pap_req_timeout > 0) + TIMEOUT(upap_reqtimeout, pcb, pcb->settings.pap_req_timeout); +} +#endif /* PPP_SERVER */ + +/* + * upap_timeout - Retransmission timer for sending auth-reqs expired. + */ +static void upap_timeout(void *arg) { + ppp_pcb *pcb = (ppp_pcb*)arg; + + if (pcb->upap.us_clientstate != UPAPCS_AUTHREQ) + return; + + if (pcb->upap.us_transmits >= pcb->settings.pap_max_transmits) { + /* give up in disgust */ + ppp_error("No response to PAP authenticate-requests"); + pcb->upap.us_clientstate = UPAPCS_BADAUTH; + auth_withpeer_fail(pcb, PPP_PAP); + return; + } + + upap_sauthreq(pcb); /* Send Authenticate-Request */ +} + + +#if PPP_SERVER +/* + * upap_reqtimeout - Give up waiting for the peer to send an auth-req. + */ +static void upap_reqtimeout(void *arg) { + ppp_pcb *pcb = (ppp_pcb*)arg; + + if (pcb->upap.us_serverstate != UPAPSS_LISTEN) + return; /* huh?? */ + + auth_peer_fail(pcb, PPP_PAP); + pcb->upap.us_serverstate = UPAPSS_BADAUTH; +} +#endif /* PPP_SERVER */ + + +/* + * upap_lowerup - The lower layer is up. + * + * Start authenticating if pending. + */ +static void upap_lowerup(ppp_pcb *pcb) { + + if (pcb->upap.us_clientstate == UPAPCS_INITIAL) + pcb->upap.us_clientstate = UPAPCS_CLOSED; + else if (pcb->upap.us_clientstate == UPAPCS_PENDING) { + upap_sauthreq(pcb); /* send an auth-request */ + } + +#if PPP_SERVER + if (pcb->upap.us_serverstate == UPAPSS_INITIAL) + pcb->upap.us_serverstate = UPAPSS_CLOSED; + else if (pcb->upap.us_serverstate == UPAPSS_PENDING) { + pcb->upap.us_serverstate = UPAPSS_LISTEN; + if (pcb->settings.pap_req_timeout > 0) + TIMEOUT(upap_reqtimeout, pcb, pcb->settings.pap_req_timeout); + } +#endif /* PPP_SERVER */ +} + + +/* + * upap_lowerdown - The lower layer is down. + * + * Cancel all timeouts. + */ +static void upap_lowerdown(ppp_pcb *pcb) { + + if (pcb->upap.us_clientstate == UPAPCS_AUTHREQ) /* Timeout pending? */ + UNTIMEOUT(upap_timeout, pcb); /* Cancel timeout */ +#if PPP_SERVER + if (pcb->upap.us_serverstate == UPAPSS_LISTEN && pcb->settings.pap_req_timeout > 0) + UNTIMEOUT(upap_reqtimeout, pcb); +#endif /* PPP_SERVER */ + + pcb->upap.us_clientstate = UPAPCS_INITIAL; +#if PPP_SERVER + pcb->upap.us_serverstate = UPAPSS_INITIAL; +#endif /* PPP_SERVER */ +} + + +/* + * upap_protrej - Peer doesn't speak this protocol. + * + * This shouldn't happen. In any case, pretend lower layer went down. + */ +static void upap_protrej(ppp_pcb *pcb) { + + if (pcb->upap.us_clientstate == UPAPCS_AUTHREQ) { + ppp_error("PAP authentication failed due to protocol-reject"); + auth_withpeer_fail(pcb, PPP_PAP); + } +#if PPP_SERVER + if (pcb->upap.us_serverstate == UPAPSS_LISTEN) { + ppp_error("PAP authentication of peer failed (protocol-reject)"); + auth_peer_fail(pcb, PPP_PAP); + } +#endif /* PPP_SERVER */ + upap_lowerdown(pcb); +} + + +/* + * upap_input - Input UPAP packet. + */ +static void upap_input(ppp_pcb *pcb, u_char *inpacket, int l) { + u_char *inp; + u_char code, id; + int len; + + /* + * Parse header (code, id and length). + * If packet too short, drop it. + */ + inp = inpacket; + if (l < UPAP_HEADERLEN) { + UPAPDEBUG(("pap_input: rcvd short header.")); + return; + } + GETCHAR(code, inp); + GETCHAR(id, inp); + GETSHORT(len, inp); + if (len < UPAP_HEADERLEN) { + UPAPDEBUG(("pap_input: rcvd illegal length.")); + return; + } + if (len > l) { + UPAPDEBUG(("pap_input: rcvd short packet.")); + return; + } + len -= UPAP_HEADERLEN; + + /* + * Action depends on code. + */ + switch (code) { + case UPAP_AUTHREQ: +#if PPP_SERVER + upap_rauthreq(pcb, inp, id, len); +#endif /* PPP_SERVER */ + break; + + case UPAP_AUTHACK: + upap_rauthack(pcb, inp, id, len); + break; + + case UPAP_AUTHNAK: + upap_rauthnak(pcb, inp, id, len); + break; + + default: /* XXX Need code reject */ + break; + } +} + +#if PPP_SERVER +/* + * upap_rauth - Receive Authenticate. + */ +static void upap_rauthreq(ppp_pcb *pcb, u_char *inp, int id, int len) { + u_char ruserlen, rpasswdlen; + char *ruser; + char *rpasswd; + char rhostname[256]; + int retcode; + const char *msg; + int msglen; + + if (pcb->upap.us_serverstate < UPAPSS_LISTEN) + return; + + /* + * If we receive a duplicate authenticate-request, we are + * supposed to return the same status as for the first request. + */ + if (pcb->upap.us_serverstate == UPAPSS_OPEN) { + upap_sresp(pcb, UPAP_AUTHACK, id, "", 0); /* return auth-ack */ + return; + } + if (pcb->upap.us_serverstate == UPAPSS_BADAUTH) { + upap_sresp(pcb, UPAP_AUTHNAK, id, "", 0); /* return auth-nak */ + return; + } + + /* + * Parse user/passwd. + */ + if (len < 1) { + UPAPDEBUG(("pap_rauth: rcvd short packet.")); + return; + } + GETCHAR(ruserlen, inp); + len -= sizeof (u_char) + ruserlen + sizeof (u_char); + if (len < 0) { + UPAPDEBUG(("pap_rauth: rcvd short packet.")); + return; + } + ruser = (char *) inp; + INCPTR(ruserlen, inp); + GETCHAR(rpasswdlen, inp); + if (len < rpasswdlen) { + UPAPDEBUG(("pap_rauth: rcvd short packet.")); + return; + } + + rpasswd = (char *) inp; + + /* + * Check the username and password given. + */ + retcode = UPAP_AUTHNAK; + if (auth_check_passwd(pcb, ruser, ruserlen, rpasswd, rpasswdlen, &msg, &msglen)) { + retcode = UPAP_AUTHACK; + } + BZERO(rpasswd, rpasswdlen); + +#if 0 /* UNUSED */ + /* + * Check remote number authorization. A plugin may have filled in + * the remote number or added an allowed number, and rather than + * return an authenticate failure, is leaving it for us to verify. + */ + if (retcode == UPAP_AUTHACK) { + if (!auth_number()) { + /* We do not want to leak info about the pap result. */ + retcode = UPAP_AUTHNAK; /* XXX exit value will be "wrong" */ + warn("calling number %q is not authorized", remote_number); + } + } + + msglen = strlen(msg); + if (msglen > 255) + msglen = 255; +#endif /* UNUSED */ + + upap_sresp(pcb, retcode, id, msg, msglen); + + /* Null terminate and clean remote name. */ + ppp_slprintf(rhostname, sizeof(rhostname), "%.*v", ruserlen, ruser); + + if (retcode == UPAP_AUTHACK) { + pcb->upap.us_serverstate = UPAPSS_OPEN; + ppp_notice("PAP peer authentication succeeded for %q", rhostname); + auth_peer_success(pcb, PPP_PAP, 0, ruser, ruserlen); + } else { + pcb->upap.us_serverstate = UPAPSS_BADAUTH; + ppp_warn("PAP peer authentication failed for %q", rhostname); + auth_peer_fail(pcb, PPP_PAP); + } + + if (pcb->settings.pap_req_timeout > 0) + UNTIMEOUT(upap_reqtimeout, pcb); +} +#endif /* PPP_SERVER */ + +/* + * upap_rauthack - Receive Authenticate-Ack. + */ +static void upap_rauthack(ppp_pcb *pcb, u_char *inp, int id, int len) { + u_char msglen; + char *msg; + LWIP_UNUSED_ARG(id); + + if (pcb->upap.us_clientstate != UPAPCS_AUTHREQ) /* XXX */ + return; + + /* + * Parse message. + */ + if (len < 1) { + UPAPDEBUG(("pap_rauthack: ignoring missing msg-length.")); + } else { + GETCHAR(msglen, inp); + if (msglen > 0) { + len -= sizeof (u_char); + if (len < msglen) { + UPAPDEBUG(("pap_rauthack: rcvd short packet.")); + return; + } + msg = (char *) inp; + PRINTMSG(msg, msglen); + } + } + + pcb->upap.us_clientstate = UPAPCS_OPEN; + + auth_withpeer_success(pcb, PPP_PAP, 0); +} + + +/* + * upap_rauthnak - Receive Authenticate-Nak. + */ +static void upap_rauthnak(ppp_pcb *pcb, u_char *inp, int id, int len) { + u_char msglen; + char *msg; + LWIP_UNUSED_ARG(id); + + if (pcb->upap.us_clientstate != UPAPCS_AUTHREQ) /* XXX */ + return; + + /* + * Parse message. + */ + if (len < 1) { + UPAPDEBUG(("pap_rauthnak: ignoring missing msg-length.")); + } else { + GETCHAR(msglen, inp); + if (msglen > 0) { + len -= sizeof (u_char); + if (len < msglen) { + UPAPDEBUG(("pap_rauthnak: rcvd short packet.")); + return; + } + msg = (char *) inp; + PRINTMSG(msg, msglen); + } + } + + pcb->upap.us_clientstate = UPAPCS_BADAUTH; + + ppp_error("PAP authentication failed"); + auth_withpeer_fail(pcb, PPP_PAP); +} + + +/* + * upap_sauthreq - Send an Authenticate-Request. + */ +static void upap_sauthreq(ppp_pcb *pcb) { + struct pbuf *p; + u_char *outp; + int outlen; + + outlen = UPAP_HEADERLEN + 2 * sizeof (u_char) + + pcb->upap.us_userlen + pcb->upap.us_passwdlen; + p = pbuf_alloc(PBUF_RAW, (u16_t)(PPP_HDRLEN +outlen), PPP_CTRL_PBUF_TYPE); + if(NULL == p) + return; + if(p->tot_len != p->len) { + pbuf_free(p); + return; + } + + outp = (u_char*)p->payload; + MAKEHEADER(outp, PPP_PAP); + + PUTCHAR(UPAP_AUTHREQ, outp); + PUTCHAR(++pcb->upap.us_id, outp); + PUTSHORT(outlen, outp); + PUTCHAR(pcb->upap.us_userlen, outp); + MEMCPY(outp, pcb->upap.us_user, pcb->upap.us_userlen); + INCPTR(pcb->upap.us_userlen, outp); + PUTCHAR(pcb->upap.us_passwdlen, outp); + MEMCPY(outp, pcb->upap.us_passwd, pcb->upap.us_passwdlen); + + ppp_write(pcb, p); + + TIMEOUT(upap_timeout, pcb, pcb->settings.pap_timeout_time); + ++pcb->upap.us_transmits; + pcb->upap.us_clientstate = UPAPCS_AUTHREQ; +} + +#if PPP_SERVER +/* + * upap_sresp - Send a response (ack or nak). + */ +static void upap_sresp(ppp_pcb *pcb, u_char code, u_char id, const char *msg, int msglen) { + struct pbuf *p; + u_char *outp; + int outlen; + + outlen = UPAP_HEADERLEN + sizeof (u_char) + msglen; + p = pbuf_alloc(PBUF_RAW, (u16_t)(PPP_HDRLEN +outlen), PPP_CTRL_PBUF_TYPE); + if(NULL == p) + return; + if(p->tot_len != p->len) { + pbuf_free(p); + return; + } + + outp = (u_char*)p->payload; + MAKEHEADER(outp, PPP_PAP); + + PUTCHAR(code, outp); + PUTCHAR(id, outp); + PUTSHORT(outlen, outp); + PUTCHAR(msglen, outp); + MEMCPY(outp, msg, msglen); + + ppp_write(pcb, p); +} +#endif /* PPP_SERVER */ + +#if PRINTPKT_SUPPORT +/* + * upap_printpkt - print the contents of a PAP packet. + */ +static const char* const upap_codenames[] = { + "AuthReq", "AuthAck", "AuthNak" +}; + +static int upap_printpkt(const u_char *p, int plen, void (*printer) (void *, const char *, ...), void *arg) { + int code, id, len; + int mlen, ulen, wlen; + const u_char *user, *pwd, *msg; + const u_char *pstart; + + if (plen < UPAP_HEADERLEN) + return 0; + pstart = p; + GETCHAR(code, p); + GETCHAR(id, p); + GETSHORT(len, p); + if (len < UPAP_HEADERLEN || len > plen) + return 0; + + if (code >= 1 && code <= (int)sizeof(upap_codenames) / (int)sizeof(char *)) + printer(arg, " %s", upap_codenames[code-1]); + else + printer(arg, " code=0x%x", code); + printer(arg, " id=0x%x", id); + len -= UPAP_HEADERLEN; + switch (code) { + case UPAP_AUTHREQ: + if (len < 1) + break; + ulen = p[0]; + if (len < ulen + 2) + break; + wlen = p[ulen + 1]; + if (len < ulen + wlen + 2) + break; + user = (const u_char *) (p + 1); + pwd = (const u_char *) (p + ulen + 2); + p += ulen + wlen + 2; + len -= ulen + wlen + 2; + printer(arg, " user="); + ppp_print_string(user, ulen, printer, arg); + printer(arg, " password="); +/* FIXME: require ppp_pcb struct as printpkt() argument */ +#if 0 + if (!pcb->settings.hide_password) +#endif + ppp_print_string(pwd, wlen, printer, arg); +#if 0 + else + printer(arg, ""); +#endif + break; + case UPAP_AUTHACK: + case UPAP_AUTHNAK: + if (len < 1) + break; + mlen = p[0]; + if (len < mlen + 1) + break; + msg = (const u_char *) (p + 1); + p += mlen + 1; + len -= mlen + 1; + printer(arg, " "); + ppp_print_string(msg, mlen, printer, arg); + break; + default: + break; + } + + /* print the rest of the bytes in the packet */ + for (; len > 0; --len) { + GETCHAR(code, p); + printer(arg, " %.2x", code); + } + + return p - pstart; +} +#endif /* PRINTPKT_SUPPORT */ + +#endif /* PPP_SUPPORT && PAP_SUPPORT */ diff --git a/components/lwip/netif/ppp/utils.c b/components/lwip/netif/ppp/utils.c new file mode 100755 index 0000000000..c1d797ae73 --- /dev/null +++ b/components/lwip/netif/ppp/utils.c @@ -0,0 +1,961 @@ +/* + * utils.c - various utility functions used in pppd. + * + * Copyright (c) 1999-2002 Paul Mackerras. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. The name(s) of the authors of this software must not be used to + * endorse or promote products derived from this software without + * prior written permission. + * + * 3. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by Paul Mackerras + * ". + * + * THE AUTHORS OF THIS SOFTWARE DISCLAIM ALL WARRANTIES WITH REGARD TO + * THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS, IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY + * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN + * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING + * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include "lwip/opt.h" +#if PPP_SUPPORT /* don't build if not configured for use in lwipopts.h */ + +#if 0 /* UNUSED */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#ifdef SVR4 +#include +#endif +#endif /* UNUSED */ + +#include /* isdigit() */ + +#include "netif/ppp/ppp_impl.h" + +#include "netif/ppp/fsm.h" +#include "netif/ppp/lcp.h" + +#if defined(SUNOS4) +extern char *strerror(); +#endif + +static void ppp_logit(int level, const char *fmt, va_list args); +static void ppp_log_write(int level, char *buf); +#if PRINTPKT_SUPPORT +static void ppp_vslp_printer(void *arg, const char *fmt, ...); +static void ppp_format_packet(const u_char *p, int len, + void (*printer) (void *, const char *, ...), void *arg); + +struct buffer_info { + char *ptr; + int len; +}; +#endif /* PRINTPKT_SUPPORT */ + +/* + * ppp_strlcpy - like strcpy/strncpy, doesn't overflow destination buffer, + * always leaves destination null-terminated (for len > 0). + */ +size_t ppp_strlcpy(char *dest, const char *src, size_t len) { + size_t ret = strlen(src); + + if (len != 0) { + if (ret < len) + strcpy(dest, src); + else { + strncpy(dest, src, len - 1); + dest[len-1] = 0; + } + } + return ret; +} + +/* + * ppp_strlcat - like strcat/strncat, doesn't overflow destination buffer, + * always leaves destination null-terminated (for len > 0). + */ +size_t ppp_strlcat(char *dest, const char *src, size_t len) { + size_t dlen = strlen(dest); + + return dlen + ppp_strlcpy(dest + dlen, src, (len > dlen? len - dlen: 0)); +} + + +/* + * ppp_slprintf - format a message into a buffer. Like sprintf except we + * also specify the length of the output buffer, and we handle + * %m (error message), %v (visible string), + * %q (quoted string), %t (current time) and %I (IP address) formats. + * Doesn't do floating-point formats. + * Returns the number of chars put into buf. + */ +int ppp_slprintf(char *buf, int buflen, const char *fmt, ...) { + va_list args; + int n; + + va_start(args, fmt); + n = ppp_vslprintf(buf, buflen, fmt, args); + va_end(args); + return n; +} + +/* + * ppp_vslprintf - like ppp_slprintf, takes a va_list instead of a list of args. + */ +#define OUTCHAR(c) (buflen > 0? (--buflen, *buf++ = (c)): 0) + +int ppp_vslprintf(char *buf, int buflen, const char *fmt, va_list args) { + int c, i, n; + int width, prec, fillch; + int base, len, neg, quoted; + unsigned long val = 0; + const char *f; + char *str, *buf0; + const unsigned char *p; + char num[32]; +#if 0 /* need port */ + time_t t; +#endif /* need port */ + u32_t ip; + static char hexchars[] = "0123456789abcdef"; +#if PRINTPKT_SUPPORT + struct buffer_info bufinfo; +#endif /* PRINTPKT_SUPPORT */ + + buf0 = buf; + --buflen; + while (buflen > 0) { + for (f = fmt; *f != '%' && *f != 0; ++f) + ; + if (f > fmt) { + len = f - fmt; + if (len > buflen) + len = buflen; + memcpy(buf, fmt, len); + buf += len; + buflen -= len; + fmt = f; + } + if (*fmt == 0) + break; + c = *++fmt; + width = 0; + prec = -1; + fillch = ' '; + if (c == '0') { + fillch = '0'; + c = *++fmt; + } + if (c == '*') { + width = va_arg(args, int); + c = *++fmt; + } else { + while (isdigit(c)) { + width = width * 10 + c - '0'; + c = *++fmt; + } + } + if (c == '.') { + c = *++fmt; + if (c == '*') { + prec = va_arg(args, int); + c = *++fmt; + } else { + prec = 0; + while (isdigit(c)) { + prec = prec * 10 + c - '0'; + c = *++fmt; + } + } + } + str = 0; + base = 0; + neg = 0; + ++fmt; + switch (c) { + case 'l': + c = *fmt++; + switch (c) { + case 'd': + val = va_arg(args, long); + if ((long)val < 0) { + neg = 1; + val = (unsigned long)-(long)val; + } + base = 10; + break; + case 'u': + val = va_arg(args, unsigned long); + base = 10; + break; + default: + OUTCHAR('%'); + OUTCHAR('l'); + --fmt; /* so %lz outputs %lz etc. */ + continue; + } + break; + case 'd': + i = va_arg(args, int); + if (i < 0) { + neg = 1; + val = -i; + } else + val = i; + base = 10; + break; + case 'u': + val = va_arg(args, unsigned int); + base = 10; + break; + case 'o': + val = va_arg(args, unsigned int); + base = 8; + break; + case 'x': + case 'X': + val = va_arg(args, unsigned int); + base = 16; + break; + case 'p': + val = (unsigned long) va_arg(args, void *); + base = 16; + neg = 2; + break; + case 's': + str = va_arg(args, char *); + break; + case 'c': + num[0] = va_arg(args, int); + num[1] = 0; + str = num; + break; +#if 0 /* do we always have strerror() in embedded ? */ + case 'm': + str = strerror(errno); + break; +#endif /* do we always have strerror() in embedded ? */ + case 'I': + ip = va_arg(args, u32_t); + ip = ntohl(ip); + ppp_slprintf(num, sizeof(num), "%d.%d.%d.%d", (ip >> 24) & 0xff, + (ip >> 16) & 0xff, (ip >> 8) & 0xff, ip & 0xff); + str = num; + break; +#if 0 /* need port */ + case 't': + time(&t); + str = ctime(&t); + str += 4; /* chop off the day name */ + str[15] = 0; /* chop off year and newline */ + break; +#endif /* need port */ + case 'v': /* "visible" string */ + case 'q': /* quoted string */ + quoted = c == 'q'; + p = va_arg(args, unsigned char *); + if (p == NULL) + p = (const unsigned char *)""; + if (fillch == '0' && prec >= 0) { + n = prec; + } else { + n = strlen((const char *)p); + if (prec >= 0 && n > prec) + n = prec; + } + while (n > 0 && buflen > 0) { + c = *p++; + --n; + if (!quoted && c >= 0x80) { + OUTCHAR('M'); + OUTCHAR('-'); + c -= 0x80; + } + if (quoted && (c == '"' || c == '\\')) + OUTCHAR('\\'); + if (c < 0x20 || (0x7f <= c && c < 0xa0)) { + if (quoted) { + OUTCHAR('\\'); + switch (c) { + case '\t': OUTCHAR('t'); break; + case '\n': OUTCHAR('n'); break; + case '\b': OUTCHAR('b'); break; + case '\f': OUTCHAR('f'); break; + default: + OUTCHAR('x'); + OUTCHAR(hexchars[c >> 4]); + OUTCHAR(hexchars[c & 0xf]); + } + } else { + if (c == '\t') + OUTCHAR(c); + else { + OUTCHAR('^'); + OUTCHAR(c ^ 0x40); + } + } + } else + OUTCHAR(c); + } + continue; +#if PRINTPKT_SUPPORT + case 'P': /* print PPP packet */ + bufinfo.ptr = buf; + bufinfo.len = buflen + 1; + p = va_arg(args, unsigned char *); + n = va_arg(args, int); + ppp_format_packet(p, n, ppp_vslp_printer, &bufinfo); + buf = bufinfo.ptr; + buflen = bufinfo.len - 1; + continue; +#endif /* PRINTPKT_SUPPORT */ + case 'B': + p = va_arg(args, unsigned char *); + for (n = prec; n > 0; --n) { + c = *p++; + if (fillch == ' ') + OUTCHAR(' '); + OUTCHAR(hexchars[(c >> 4) & 0xf]); + OUTCHAR(hexchars[c & 0xf]); + } + continue; + default: + *buf++ = '%'; + if (c != '%') + --fmt; /* so %z outputs %z etc. */ + --buflen; + continue; + } + if (base != 0) { + str = num + sizeof(num); + *--str = 0; + while (str > num + neg) { + *--str = hexchars[val % base]; + val = val / base; + if (--prec <= 0 && val == 0) + break; + } + switch (neg) { + case 1: + *--str = '-'; + break; + case 2: + *--str = 'x'; + *--str = '0'; + break; + default: + break; + } + len = num + sizeof(num) - 1 - str; + } else { + len = strlen(str); + if (prec >= 0 && len > prec) + len = prec; + } + if (width > 0) { + if (width > buflen) + width = buflen; + if ((n = width - len) > 0) { + buflen -= n; + for (; n > 0; --n) + *buf++ = fillch; + } + } + if (len > buflen) + len = buflen; + memcpy(buf, str, len); + buf += len; + buflen -= len; + } + *buf = 0; + return buf - buf0; +} + +#if PRINTPKT_SUPPORT +/* + * vslp_printer - used in processing a %P format + */ +static void ppp_vslp_printer(void *arg, const char *fmt, ...) { + int n; + va_list pvar; + struct buffer_info *bi; + + va_start(pvar, fmt); + bi = (struct buffer_info *) arg; + n = ppp_vslprintf(bi->ptr, bi->len, fmt, pvar); + va_end(pvar); + + bi->ptr += n; + bi->len -= n; +} +#endif /* PRINTPKT_SUPPORT */ + +#if 0 /* UNUSED */ +/* + * log_packet - format a packet and log it. + */ + +void +log_packet(p, len, prefix, level) + u_char *p; + int len; + char *prefix; + int level; +{ + init_pr_log(prefix, level); + ppp_format_packet(p, len, pr_log, &level); + end_pr_log(); +} +#endif /* UNUSED */ + +#if PRINTPKT_SUPPORT +/* + * ppp_format_packet - make a readable representation of a packet, + * calling `printer(arg, format, ...)' to output it. + */ +static void ppp_format_packet(const u_char *p, int len, + void (*printer) (void *, const char *, ...), void *arg) { + int i, n; + u_short proto; + const struct protent *protp; + + if (len >= 2) { + GETSHORT(proto, p); + len -= 2; + for (i = 0; (protp = protocols[i]) != NULL; ++i) + if (proto == protp->protocol) + break; + if (protp != NULL) { + printer(arg, "[%s", protp->name); + n = (*protp->printpkt)(p, len, printer, arg); + printer(arg, "]"); + p += n; + len -= n; + } else { + for (i = 0; (protp = protocols[i]) != NULL; ++i) + if (proto == (protp->protocol & ~0x8000)) + break; + if (protp != 0 && protp->data_name != 0) { + printer(arg, "[%s data]", protp->data_name); + if (len > 8) + printer(arg, "%.8B ...", p); + else + printer(arg, "%.*B", len, p); + len = 0; + } else + printer(arg, "[proto=0x%x]", proto); + } + } + + if (len > 32) + printer(arg, "%.32B ...", p); + else + printer(arg, "%.*B", len, p); +} +#endif /* PRINTPKT_SUPPORT */ + +#if 0 /* UNUSED */ +/* + * init_pr_log, end_pr_log - initialize and finish use of pr_log. + */ + +static char line[256]; /* line to be logged accumulated here */ +static char *linep; /* current pointer within line */ +static int llevel; /* level for logging */ + +void +init_pr_log(prefix, level) + const char *prefix; + int level; +{ + linep = line; + if (prefix != NULL) { + ppp_strlcpy(line, prefix, sizeof(line)); + linep = line + strlen(line); + } + llevel = level; +} + +void +end_pr_log() +{ + if (linep != line) { + *linep = 0; + ppp_log_write(llevel, line); + } +} + +/* + * pr_log - printer routine for outputting to log + */ +void +pr_log (void *arg, const char *fmt, ...) +{ + int l, n; + va_list pvar; + char *p, *eol; + char buf[256]; + + va_start(pvar, fmt); + n = ppp_vslprintf(buf, sizeof(buf), fmt, pvar); + va_end(pvar); + + p = buf; + eol = strchr(buf, '\n'); + if (linep != line) { + l = (eol == NULL)? n: eol - buf; + if (linep + l < line + sizeof(line)) { + if (l > 0) { + memcpy(linep, buf, l); + linep += l; + } + if (eol == NULL) + return; + p = eol + 1; + eol = strchr(p, '\n'); + } + *linep = 0; + ppp_log_write(llevel, line); + linep = line; + } + + while (eol != NULL) { + *eol = 0; + ppp_log_write(llevel, p); + p = eol + 1; + eol = strchr(p, '\n'); + } + + /* assumes sizeof(buf) <= sizeof(line) */ + l = buf + n - p; + if (l > 0) { + memcpy(line, p, n); + linep = line + l; + } +} +#endif /* UNUSED */ + +/* + * ppp_print_string - print a readable representation of a string using + * printer. + */ +void ppp_print_string(const u_char *p, int len, void (*printer) (void *, const char *, ...), void *arg) { + int c; + + printer(arg, "\""); + for (; len > 0; --len) { + c = *p++; + if (' ' <= c && c <= '~') { + if (c == '\\' || c == '"') + printer(arg, "\\"); + printer(arg, "%c", c); + } else { + switch (c) { + case '\n': + printer(arg, "\\n"); + break; + case '\r': + printer(arg, "\\r"); + break; + case '\t': + printer(arg, "\\t"); + break; + default: + printer(arg, "\\%.3o", c); + /* no break */ + } + } + } + printer(arg, "\""); +} + +/* + * ppp_logit - does the hard work for fatal et al. + */ +static void ppp_logit(int level, const char *fmt, va_list args) { + char buf[1024]; + + ppp_vslprintf(buf, sizeof(buf), fmt, args); + ppp_log_write(level, buf); +} + +static void ppp_log_write(int level, char *buf) { + LWIP_UNUSED_ARG(level); /* necessary if PPPDEBUG is defined to an empty function */ + LWIP_UNUSED_ARG(buf); + PPPDEBUG(level, ("%s\n", buf) ); +#if 0 + if (log_to_fd >= 0 && (level != LOG_DEBUG || debug)) { + int n = strlen(buf); + + if (n > 0 && buf[n-1] == '\n') + --n; + if (write(log_to_fd, buf, n) != n + || write(log_to_fd, "\n", 1) != 1) + log_to_fd = -1; + } +#endif +} + +/* + * ppp_fatal - log an error message and die horribly. + */ +void ppp_fatal(const char *fmt, ...) { + va_list pvar; + + va_start(pvar, fmt); + ppp_logit(LOG_ERR, fmt, pvar); + va_end(pvar); + + LWIP_ASSERT("ppp_fatal", 0); /* as promised */ +} + +/* + * ppp_error - log an error message. + */ +void ppp_error(const char *fmt, ...) { + va_list pvar; + + va_start(pvar, fmt); + ppp_logit(LOG_ERR, fmt, pvar); + va_end(pvar); +#if 0 /* UNUSED */ + ++error_count; +#endif /* UNUSED */ +} + +/* + * ppp_warn - log a warning message. + */ +void ppp_warn(const char *fmt, ...) { + va_list pvar; + + va_start(pvar, fmt); + ppp_logit(LOG_WARNING, fmt, pvar); + va_end(pvar); +} + +/* + * ppp_notice - log a notice-level message. + */ +void ppp_notice(const char *fmt, ...) { + va_list pvar; + + va_start(pvar, fmt); + ppp_logit(LOG_NOTICE, fmt, pvar); + va_end(pvar); +} + +/* + * ppp_info - log an informational message. + */ +void ppp_info(const char *fmt, ...) { + va_list pvar; + + va_start(pvar, fmt); + ppp_logit(LOG_INFO, fmt, pvar); + va_end(pvar); +} + +/* + * ppp_dbglog - log a debug message. + */ +void ppp_dbglog(const char *fmt, ...) { + va_list pvar; + + va_start(pvar, fmt); + ppp_logit(LOG_DEBUG, fmt, pvar); + va_end(pvar); +} + +#if PRINTPKT_SUPPORT +/* + * ppp_dump_packet - print out a packet in readable form if it is interesting. + * Assumes len >= PPP_HDRLEN. + */ +void ppp_dump_packet(const char *tag, unsigned char *p, int len) { + int proto; + + /* + * don't print IPv4 and IPv6 packets. + */ + proto = (p[0] << 8) + p[1]; + if (proto == PPP_IP) + return; +#if PPP_IPV6_SUPPORT + if (proto == PPP_IPV6) + return; +#endif + + /* + * don't print LCP echo request/reply packets if the link is up. + */ + if (proto == PPP_LCP && len >= 2 + HEADERLEN) { + unsigned char *lcp = p + 2; + int l = (lcp[2] << 8) + lcp[3]; + + if ((lcp[0] == ECHOREQ || lcp[0] == ECHOREP) + && l >= HEADERLEN && l <= len - 2) + return; + } + + ppp_dbglog("%s %P", tag, p, len); +} +#endif /* PRINTPKT_SUPPORT */ + +#if 0 /* Unused */ + +/* + * complete_read - read a full `count' bytes from fd, + * unless end-of-file or an error other than EINTR is encountered. + */ +ssize_t +complete_read(int fd, void *buf, size_t count) +{ + size_t done; + ssize_t nb; + char *ptr = buf; + + for (done = 0; done < count; ) { + nb = read(fd, ptr, count - done); + if (nb < 0) { + if (errno == EINTR) + continue; + return -1; + } + if (nb == 0) + break; + done += nb; + ptr += nb; + } + return done; +} + +/* Procedures for locking the serial device using a lock file. */ +#ifndef LOCK_DIR +#ifdef __linux__ +#define LOCK_DIR "/var/lock" +#else +#ifdef SVR4 +#define LOCK_DIR "/var/spool/locks" +#else +#define LOCK_DIR "/var/spool/lock" +#endif +#endif +#endif /* LOCK_DIR */ + +static char lock_file[MAXPATHLEN]; + +/* + * lock - create a lock file for the named device + */ +int +lock(dev) + char *dev; +{ +#ifdef LOCKLIB + int result; + + result = mklock (dev, (void *) 0); + if (result == 0) { + ppp_strlcpy(lock_file, dev, sizeof(lock_file)); + return 0; + } + + if (result > 0) + ppp_notice("Device %s is locked by pid %d", dev, result); + else + ppp_error("Can't create lock file %s", lock_file); + return -1; + +#else /* LOCKLIB */ + + char lock_buffer[12]; + int fd, pid, n; + +#ifdef SVR4 + struct stat sbuf; + + if (stat(dev, &sbuf) < 0) { + ppp_error("Can't get device number for %s: %m", dev); + return -1; + } + if ((sbuf.st_mode & S_IFMT) != S_IFCHR) { + ppp_error("Can't lock %s: not a character device", dev); + return -1; + } + ppp_slprintf(lock_file, sizeof(lock_file), "%s/LK.%03d.%03d.%03d", + LOCK_DIR, major(sbuf.st_dev), + major(sbuf.st_rdev), minor(sbuf.st_rdev)); +#else + char *p; + char lockdev[MAXPATHLEN]; + + if ((p = strstr(dev, "dev/")) != NULL) { + dev = p + 4; + strncpy(lockdev, dev, MAXPATHLEN-1); + lockdev[MAXPATHLEN-1] = 0; + while ((p = strrchr(lockdev, '/')) != NULL) { + *p = '_'; + } + dev = lockdev; + } else + if ((p = strrchr(dev, '/')) != NULL) + dev = p + 1; + + ppp_slprintf(lock_file, sizeof(lock_file), "%s/LCK..%s", LOCK_DIR, dev); +#endif + + while ((fd = open(lock_file, O_EXCL | O_CREAT | O_RDWR, 0644)) < 0) { + if (errno != EEXIST) { + ppp_error("Can't create lock file %s: %m", lock_file); + break; + } + + /* Read the lock file to find out who has the device locked. */ + fd = open(lock_file, O_RDONLY, 0); + if (fd < 0) { + if (errno == ENOENT) /* This is just a timing problem. */ + continue; + ppp_error("Can't open existing lock file %s: %m", lock_file); + break; + } +#ifndef LOCK_BINARY + n = read(fd, lock_buffer, 11); +#else + n = read(fd, &pid, sizeof(pid)); +#endif /* LOCK_BINARY */ + close(fd); + fd = -1; + if (n <= 0) { + ppp_error("Can't read pid from lock file %s", lock_file); + break; + } + + /* See if the process still exists. */ +#ifndef LOCK_BINARY + lock_buffer[n] = 0; + pid = atoi(lock_buffer); +#endif /* LOCK_BINARY */ + if (pid == getpid()) + return 1; /* somebody else locked it for us */ + if (pid == 0 + || (kill(pid, 0) == -1 && errno == ESRCH)) { + if (unlink (lock_file) == 0) { + ppp_notice("Removed stale lock on %s (pid %d)", dev, pid); + continue; + } + ppp_warn("Couldn't remove stale lock on %s", dev); + } else + ppp_notice("Device %s is locked by pid %d", dev, pid); + break; + } + + if (fd < 0) { + lock_file[0] = 0; + return -1; + } + + pid = getpid(); +#ifndef LOCK_BINARY + ppp_slprintf(lock_buffer, sizeof(lock_buffer), "%10d\n", pid); + write (fd, lock_buffer, 11); +#else + write(fd, &pid, sizeof (pid)); +#endif + close(fd); + return 0; + +#endif +} + +/* + * relock - called to update our lockfile when we are about to detach, + * thus changing our pid (we fork, the child carries on, and the parent dies). + * Note that this is called by the parent, with pid equal to the pid + * of the child. This avoids a potential race which would exist if + * we had the child rewrite the lockfile (the parent might die first, + * and another process could think the lock was stale if it checked + * between when the parent died and the child rewrote the lockfile). + */ +int +relock(pid) + int pid; +{ +#ifdef LOCKLIB + /* XXX is there a way to do this? */ + return -1; +#else /* LOCKLIB */ + + int fd; + char lock_buffer[12]; + + if (lock_file[0] == 0) + return -1; + fd = open(lock_file, O_WRONLY, 0); + if (fd < 0) { + ppp_error("Couldn't reopen lock file %s: %m", lock_file); + lock_file[0] = 0; + return -1; + } + +#ifndef LOCK_BINARY + ppp_slprintf(lock_buffer, sizeof(lock_buffer), "%10d\n", pid); + write (fd, lock_buffer, 11); +#else + write(fd, &pid, sizeof(pid)); +#endif /* LOCK_BINARY */ + close(fd); + return 0; + +#endif /* LOCKLIB */ +} + +/* + * unlock - remove our lockfile + */ +void +unlock() +{ + if (lock_file[0]) { +#ifdef LOCKLIB + (void) rmlock(lock_file, (void *) 0); +#else + unlink(lock_file); +#endif + lock_file[0] = 0; + } +} + +#endif /* Unused */ + +#endif /* PPP_SUPPORT */ diff --git a/components/lwip/netif/ppp/vj.c b/components/lwip/netif/ppp/vj.c new file mode 100755 index 0000000000..19d8a2f8ae --- /dev/null +++ b/components/lwip/netif/ppp/vj.c @@ -0,0 +1,670 @@ +/* + * Routines to compress and uncompess tcp packets (for transmission + * over low speed serial lines. + * + * Copyright (c) 1989 Regents of the University of California. + * All rights reserved. + * + * Redistribution and use in source and binary forms are permitted + * provided that the above copyright notice and this paragraph are + * duplicated in all such forms and that any documentation, + * advertising materials, and other materials related to such + * distribution and use acknowledge that the software was developed + * by the University of California, Berkeley. The name of the + * University may not be used to endorse or promote products derived + * from this software without specific prior written permission. + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED + * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. + * + * Van Jacobson (van@helios.ee.lbl.gov), Dec 31, 1989: + * Initial distribution. + * + * Modified June 1993 by Paul Mackerras, paulus@cs.anu.edu.au, + * so that the entire packet being decompressed doesn't have + * to be in contiguous memory (just the compressed header). + * + * Modified March 1998 by Guy Lancaster, glanca@gesn.com, + * for a 16 bit processor. + */ + +#include "lwip/opt.h" +#if PPP_SUPPORT && VJ_SUPPORT && LWIP_TCP /* don't build if not configured for use in lwipopts.h */ + +#include "netif/ppp/ppp_impl.h" +#include "netif/ppp/pppdebug.h" + +#include "netif/ppp/vj.h" + +#include + +#if LINK_STATS +#define INCR(counter) ++comp->stats.counter +#else +#define INCR(counter) +#endif + +void +vj_compress_init(struct vjcompress *comp) +{ + u8_t i; + struct cstate *tstate = comp->tstate; + +#if MAX_SLOTS == 0 + memset((char *)comp, 0, sizeof(*comp)); +#endif + comp->maxSlotIndex = MAX_SLOTS - 1; + comp->compressSlot = 0; /* Disable slot ID compression by default. */ + for (i = MAX_SLOTS - 1; i > 0; --i) { + tstate[i].cs_id = i; + tstate[i].cs_next = &tstate[i - 1]; + } + tstate[0].cs_next = &tstate[MAX_SLOTS - 1]; + tstate[0].cs_id = 0; + comp->last_cs = &tstate[0]; + comp->last_recv = 255; + comp->last_xmit = 255; + comp->flags = VJF_TOSS; +} + + +/* ENCODE encodes a number that is known to be non-zero. ENCODEZ + * checks for zero (since zero has to be encoded in the long, 3 byte + * form). + */ +#define ENCODE(n) { \ + if ((u16_t)(n) >= 256) { \ + *cp++ = 0; \ + cp[1] = (u8_t)(n); \ + cp[0] = (u8_t)((n) >> 8); \ + cp += 2; \ + } else { \ + *cp++ = (u8_t)(n); \ + } \ +} +#define ENCODEZ(n) { \ + if ((u16_t)(n) >= 256 || (u16_t)(n) == 0) { \ + *cp++ = 0; \ + cp[1] = (u8_t)(n); \ + cp[0] = (u8_t)((n) >> 8); \ + cp += 2; \ + } else { \ + *cp++ = (u8_t)(n); \ + } \ +} + +#define DECODEL(f) { \ + if (*cp == 0) {\ + u32_t tmp_ = ntohl(f) + ((cp[1] << 8) | cp[2]); \ + (f) = htonl(tmp_); \ + cp += 3; \ + } else { \ + u32_t tmp_ = ntohl(f) + (u32_t)*cp++; \ + (f) = htonl(tmp_); \ + } \ +} + +#define DECODES(f) { \ + if (*cp == 0) {\ + u16_t tmp_ = ntohs(f) + (((u16_t)cp[1] << 8) | cp[2]); \ + (f) = htons(tmp_); \ + cp += 3; \ + } else { \ + u16_t tmp_ = ntohs(f) + (u16_t)*cp++; \ + (f) = htons(tmp_); \ + } \ +} + +#define DECODEU(f) { \ + if (*cp == 0) {\ + (f) = htons(((u16_t)cp[1] << 8) | cp[2]); \ + cp += 3; \ + } else { \ + (f) = htons((u16_t)*cp++); \ + } \ +} + +/* + * vj_compress_tcp - Attempt to do Van Jacobson header compression on a + * packet. This assumes that nb and comp are not null and that the first + * buffer of the chain contains a valid IP header. + * Return the VJ type code indicating whether or not the packet was + * compressed. + */ +u8_t +vj_compress_tcp(struct vjcompress *comp, struct pbuf **pb) +{ + struct pbuf *np = *pb; + struct ip_hdr *ip = (struct ip_hdr *)np->payload; + struct cstate *cs = comp->last_cs->cs_next; + u16_t ilen = IPH_HL(ip); + u16_t hlen; + struct tcp_hdr *oth; + struct tcp_hdr *th; + u16_t deltaS, deltaA = 0; + u32_t deltaL; + u32_t changes = 0; + u8_t new_seq[16]; + u8_t *cp = new_seq; + + /* + * Check that the packet is IP proto TCP. + */ + if (IPH_PROTO(ip) != IP_PROTO_TCP) { + return (TYPE_IP); + } + + /* + * Bail if this is an IP fragment or if the TCP packet isn't + * `compressible' (i.e., ACK isn't set or some other control bit is + * set). + */ + if ((IPH_OFFSET(ip) & PP_HTONS(0x3fff)) || np->tot_len < 40) { + return (TYPE_IP); + } + th = (struct tcp_hdr *)&((u32_t*)ip)[ilen]; + if ((TCPH_FLAGS(th) & (TCP_SYN|TCP_FIN|TCP_RST|TCP_ACK)) != TCP_ACK) { + return (TYPE_IP); + } + + /* Check that the TCP/IP headers are contained in the first buffer. */ + hlen = ilen + TCPH_HDRLEN(th); + hlen <<= 2; + if (np->len < hlen) { + PPPDEBUG(LOG_INFO, ("vj_compress_tcp: header len %d spans buffers\n", hlen)); + return (TYPE_IP); + } + + /* TCP stack requires that we don't change the packet payload, therefore we copy + * the whole packet before compression. */ + np = pbuf_alloc(PBUF_RAW, np->tot_len, PBUF_POOL); + if (!np) { + return (TYPE_IP); + } + + if (pbuf_copy(np, *pb) != ERR_OK) { + pbuf_free(np); + return (TYPE_IP); + } + + *pb = np; + ip = (struct ip_hdr *)np->payload; + + /* + * Packet is compressible -- we're going to send either a + * COMPRESSED_TCP or UNCOMPRESSED_TCP packet. Either way we need + * to locate (or create) the connection state. Special case the + * most recently used connection since it's most likely to be used + * again & we don't have to do any reordering if it's used. + */ + INCR(vjs_packets); + if (!ip4_addr_cmp(&ip->src, &cs->cs_ip.src) + || !ip4_addr_cmp(&ip->dest, &cs->cs_ip.dest) + || *(u32_t*)th != ((u32_t*)&cs->cs_ip)[IPH_HL(&cs->cs_ip)]) { + /* + * Wasn't the first -- search for it. + * + * States are kept in a circularly linked list with + * last_cs pointing to the end of the list. The + * list is kept in lru order by moving a state to the + * head of the list whenever it is referenced. Since + * the list is short and, empirically, the connection + * we want is almost always near the front, we locate + * states via linear search. If we don't find a state + * for the datagram, the oldest state is (re-)used. + */ + struct cstate *lcs; + struct cstate *lastcs = comp->last_cs; + + do { + lcs = cs; cs = cs->cs_next; + INCR(vjs_searches); + if (ip4_addr_cmp(&ip->src, &cs->cs_ip.src) + && ip4_addr_cmp(&ip->dest, &cs->cs_ip.dest) + && *(u32_t*)th == ((u32_t*)&cs->cs_ip)[IPH_HL(&cs->cs_ip)]) { + goto found; + } + } while (cs != lastcs); + + /* + * Didn't find it -- re-use oldest cstate. Send an + * uncompressed packet that tells the other side what + * connection number we're using for this conversation. + * Note that since the state list is circular, the oldest + * state points to the newest and we only need to set + * last_cs to update the lru linkage. + */ + INCR(vjs_misses); + comp->last_cs = lcs; + goto uncompressed; + + found: + /* + * Found it -- move to the front on the connection list. + */ + if (cs == lastcs) { + comp->last_cs = lcs; + } else { + lcs->cs_next = cs->cs_next; + cs->cs_next = lastcs->cs_next; + lastcs->cs_next = cs; + } + } + + oth = (struct tcp_hdr *)&((u32_t*)&cs->cs_ip)[ilen]; + deltaS = ilen; + + /* + * Make sure that only what we expect to change changed. The first + * line of the `if' checks the IP protocol version, header length & + * type of service. The 2nd line checks the "Don't fragment" bit. + * The 3rd line checks the time-to-live and protocol (the protocol + * check is unnecessary but costless). The 4th line checks the TCP + * header length. The 5th line checks IP options, if any. The 6th + * line checks TCP options, if any. If any of these things are + * different between the previous & current datagram, we send the + * current datagram `uncompressed'. + */ + if (((u16_t*)ip)[0] != ((u16_t*)&cs->cs_ip)[0] + || ((u16_t*)ip)[3] != ((u16_t*)&cs->cs_ip)[3] + || ((u16_t*)ip)[4] != ((u16_t*)&cs->cs_ip)[4] + || TCPH_HDRLEN(th) != TCPH_HDRLEN(oth) + || (deltaS > 5 && BCMP(ip + 1, &cs->cs_ip + 1, (deltaS - 5) << 2)) + || (TCPH_HDRLEN(th) > 5 && BCMP(th + 1, oth + 1, (TCPH_HDRLEN(th) - 5) << 2))) { + goto uncompressed; + } + + /* + * Figure out which of the changing fields changed. The + * receiver expects changes in the order: urgent, window, + * ack, seq (the order minimizes the number of temporaries + * needed in this section of code). + */ + if (TCPH_FLAGS(th) & TCP_URG) { + deltaS = ntohs(th->urgp); + ENCODEZ(deltaS); + changes |= NEW_U; + } else if (th->urgp != oth->urgp) { + /* argh! URG not set but urp changed -- a sensible + * implementation should never do this but RFC793 + * doesn't prohibit the change so we have to deal + * with it. */ + goto uncompressed; + } + + if ((deltaS = (u16_t)(ntohs(th->wnd) - ntohs(oth->wnd))) != 0) { + ENCODE(deltaS); + changes |= NEW_W; + } + + if ((deltaL = ntohl(th->ackno) - ntohl(oth->ackno)) != 0) { + if (deltaL > 0xffff) { + goto uncompressed; + } + deltaA = (u16_t)deltaL; + ENCODE(deltaA); + changes |= NEW_A; + } + + if ((deltaL = ntohl(th->seqno) - ntohl(oth->seqno)) != 0) { + if (deltaL > 0xffff) { + goto uncompressed; + } + deltaS = (u16_t)deltaL; + ENCODE(deltaS); + changes |= NEW_S; + } + + switch(changes) { + case 0: + /* + * Nothing changed. If this packet contains data and the + * last one didn't, this is probably a data packet following + * an ack (normal on an interactive connection) and we send + * it compressed. Otherwise it's probably a retransmit, + * retransmitted ack or window probe. Send it uncompressed + * in case the other side missed the compressed version. + */ + if (IPH_LEN(ip) != IPH_LEN(&cs->cs_ip) && + ntohs(IPH_LEN(&cs->cs_ip)) == hlen) { + break; + } + /* no break */ + /* fall through */ + + case SPECIAL_I: + case SPECIAL_D: + /* + * actual changes match one of our special case encodings -- + * send packet uncompressed. + */ + goto uncompressed; + + case NEW_S|NEW_A: + if (deltaS == deltaA && deltaS == ntohs(IPH_LEN(&cs->cs_ip)) - hlen) { + /* special case for echoed terminal traffic */ + changes = SPECIAL_I; + cp = new_seq; + } + break; + + case NEW_S: + if (deltaS == ntohs(IPH_LEN(&cs->cs_ip)) - hlen) { + /* special case for data xfer */ + changes = SPECIAL_D; + cp = new_seq; + } + break; + default: + break; + } + + deltaS = (u16_t)(ntohs(IPH_ID(ip)) - ntohs(IPH_ID(&cs->cs_ip))); + if (deltaS != 1) { + ENCODEZ(deltaS); + changes |= NEW_I; + } + if (TCPH_FLAGS(th) & TCP_PSH) { + changes |= TCP_PUSH_BIT; + } + /* + * Grab the cksum before we overwrite it below. Then update our + * state with this packet's header. + */ + deltaA = ntohs(th->chksum); + MEMCPY(&cs->cs_ip, ip, hlen); + + /* + * We want to use the original packet as our compressed packet. + * (cp - new_seq) is the number of bytes we need for compressed + * sequence numbers. In addition we need one byte for the change + * mask, one for the connection id and two for the tcp checksum. + * So, (cp - new_seq) + 4 bytes of header are needed. hlen is how + * many bytes of the original packet to toss so subtract the two to + * get the new packet size. + */ + deltaS = (u16_t)(cp - new_seq); + if (!comp->compressSlot || comp->last_xmit != cs->cs_id) { + comp->last_xmit = cs->cs_id; + hlen -= deltaS + 4; + if (pbuf_header(np, -(s16_t)hlen)){ + /* Can we cope with this failing? Just assert for now */ + LWIP_ASSERT("pbuf_header failed\n", 0); + } + cp = (u8_t*)np->payload; + *cp++ = (u8_t)(changes | NEW_C); + *cp++ = cs->cs_id; + } else { + hlen -= deltaS + 3; + if (pbuf_header(np, -(s16_t)hlen)) { + /* Can we cope with this failing? Just assert for now */ + LWIP_ASSERT("pbuf_header failed\n", 0); + } + cp = (u8_t*)np->payload; + *cp++ = (u8_t)changes; + } + *cp++ = (u8_t)(deltaA >> 8); + *cp++ = (u8_t)deltaA; + MEMCPY(cp, new_seq, deltaS); + INCR(vjs_compressed); + return (TYPE_COMPRESSED_TCP); + + /* + * Update connection state cs & send uncompressed packet (that is, + * a regular ip/tcp packet but with the 'conversation id' we hope + * to use on future compressed packets in the protocol field). + */ +uncompressed: + MEMCPY(&cs->cs_ip, ip, hlen); + IPH_PROTO_SET(ip, cs->cs_id); + comp->last_xmit = cs->cs_id; + return (TYPE_UNCOMPRESSED_TCP); +} + +/* + * Called when we may have missed a packet. + */ +void +vj_uncompress_err(struct vjcompress *comp) +{ + comp->flags |= VJF_TOSS; + INCR(vjs_errorin); +} + +/* + * "Uncompress" a packet of type TYPE_UNCOMPRESSED_TCP. + * Return 0 on success, -1 on failure. + */ +int +vj_uncompress_uncomp(struct pbuf *nb, struct vjcompress *comp) +{ + u32_t hlen; + struct cstate *cs; + struct ip_hdr *ip; + + ip = (struct ip_hdr *)nb->payload; + hlen = IPH_HL(ip) << 2; + if (IPH_PROTO(ip) >= MAX_SLOTS + || hlen + sizeof(struct tcp_hdr) > nb->len + || (hlen += TCPH_HDRLEN(((struct tcp_hdr *)&((char *)ip)[hlen])) << 2) + > nb->len + || hlen > MAX_HDR) { + PPPDEBUG(LOG_INFO, ("vj_uncompress_uncomp: bad cid=%d, hlen=%d buflen=%d\n", + IPH_PROTO(ip), hlen, nb->len)); + comp->flags |= VJF_TOSS; + INCR(vjs_errorin); + return -1; + } + cs = &comp->rstate[comp->last_recv = IPH_PROTO(ip)]; + comp->flags &=~ VJF_TOSS; + IPH_PROTO_SET(ip, IP_PROTO_TCP); + MEMCPY(&cs->cs_ip, ip, hlen); + cs->cs_hlen = (u16_t)hlen; + INCR(vjs_uncompressedin); + return 0; +} + +/* + * Uncompress a packet of type TYPE_COMPRESSED_TCP. + * The packet is composed of a buffer chain and the first buffer + * must contain an accurate chain length. + * The first buffer must include the entire compressed TCP/IP header. + * This procedure replaces the compressed header with the uncompressed + * header and returns the length of the VJ header. + */ +int +vj_uncompress_tcp(struct pbuf **nb, struct vjcompress *comp) +{ + u8_t *cp; + struct tcp_hdr *th; + struct cstate *cs; + u16_t *bp; + struct pbuf *n0 = *nb; + u32_t tmp; + u32_t vjlen, hlen, changes; + + INCR(vjs_compressedin); + cp = (u8_t*)n0->payload; + changes = *cp++; + if (changes & NEW_C) { + /* + * Make sure the state index is in range, then grab the state. + * If we have a good state index, clear the 'discard' flag. + */ + if (*cp >= MAX_SLOTS) { + PPPDEBUG(LOG_INFO, ("vj_uncompress_tcp: bad cid=%d\n", *cp)); + goto bad; + } + + comp->flags &=~ VJF_TOSS; + comp->last_recv = *cp++; + } else { + /* + * this packet has an implicit state index. If we've + * had a line error since the last time we got an + * explicit state index, we have to toss the packet. + */ + if (comp->flags & VJF_TOSS) { + PPPDEBUG(LOG_INFO, ("vj_uncompress_tcp: tossing\n")); + INCR(vjs_tossed); + return (-1); + } + } + cs = &comp->rstate[comp->last_recv]; + hlen = IPH_HL(&cs->cs_ip) << 2; + th = (struct tcp_hdr *)&((u8_t*)&cs->cs_ip)[hlen]; + th->chksum = htons((*cp << 8) | cp[1]); + cp += 2; + if (changes & TCP_PUSH_BIT) { + TCPH_SET_FLAG(th, TCP_PSH); + } else { + TCPH_UNSET_FLAG(th, TCP_PSH); + } + + switch (changes & SPECIALS_MASK) { + case SPECIAL_I: + { + u32_t i = ntohs(IPH_LEN(&cs->cs_ip)) - cs->cs_hlen; + /* some compilers can't nest inline assembler.. */ + tmp = ntohl(th->ackno) + i; + th->ackno = htonl(tmp); + tmp = ntohl(th->seqno) + i; + th->seqno = htonl(tmp); + } + break; + + case SPECIAL_D: + /* some compilers can't nest inline assembler.. */ + tmp = ntohl(th->seqno) + ntohs(IPH_LEN(&cs->cs_ip)) - cs->cs_hlen; + th->seqno = htonl(tmp); + break; + + default: + if (changes & NEW_U) { + TCPH_SET_FLAG(th, TCP_URG); + DECODEU(th->urgp); + } else { + TCPH_UNSET_FLAG(th, TCP_URG); + } + if (changes & NEW_W) { + DECODES(th->wnd); + } + if (changes & NEW_A) { + DECODEL(th->ackno); + } + if (changes & NEW_S) { + DECODEL(th->seqno); + } + break; + } + if (changes & NEW_I) { + DECODES(cs->cs_ip._id); + } else { + IPH_ID_SET(&cs->cs_ip, ntohs(IPH_ID(&cs->cs_ip)) + 1); + IPH_ID_SET(&cs->cs_ip, htons(IPH_ID(&cs->cs_ip))); + } + + /* + * At this point, cp points to the first byte of data in the + * packet. Fill in the IP total length and update the IP + * header checksum. + */ + vjlen = (u16_t)(cp - (u8_t*)n0->payload); + if (n0->len < vjlen) { + /* + * We must have dropped some characters (crc should detect + * this but the old slip framing won't) + */ + PPPDEBUG(LOG_INFO, ("vj_uncompress_tcp: head buffer %d too short %d\n", + n0->len, vjlen)); + goto bad; + } + +#if BYTE_ORDER == LITTLE_ENDIAN + tmp = n0->tot_len - vjlen + cs->cs_hlen; + IPH_LEN_SET(&cs->cs_ip, htons((u16_t)tmp)); +#else + IPH_LEN_SET(&cs->cs_ip, htons(n0->tot_len - vjlen + cs->cs_hlen)); +#endif + + /* recompute the ip header checksum */ + bp = (u16_t*) &cs->cs_ip; + IPH_CHKSUM_SET(&cs->cs_ip, 0); + for (tmp = 0; hlen > 0; hlen -= 2) { + tmp += *bp++; + } + tmp = (tmp & 0xffff) + (tmp >> 16); + tmp = (tmp & 0xffff) + (tmp >> 16); + IPH_CHKSUM_SET(&cs->cs_ip, (u16_t)(~tmp)); + + /* Remove the compressed header and prepend the uncompressed header. */ + if (pbuf_header(n0, -(s16_t)vjlen)) { + /* Can we cope with this failing? Just assert for now */ + LWIP_ASSERT("pbuf_header failed\n", 0); + goto bad; + } + + if(LWIP_MEM_ALIGN(n0->payload) != n0->payload) { + struct pbuf *np, *q; + u8_t *bufptr; + +#if IP_FORWARD + /* If IP forwarding is enabled we are using a PBUF_LINK packet type so + * the packet is being allocated with enough header space to be + * forwarded (to Ethernet for example). + */ + np = pbuf_alloc(PBUF_LINK, n0->len + cs->cs_hlen, PBUF_POOL); +#else /* IP_FORWARD */ + np = pbuf_alloc(PBUF_RAW, n0->len + cs->cs_hlen, PBUF_POOL); +#endif /* IP_FORWARD */ + if(!np) { + PPPDEBUG(LOG_WARNING, ("vj_uncompress_tcp: realign failed\n")); + goto bad; + } + + if (pbuf_header(np, -(s16_t)cs->cs_hlen)) { + /* Can we cope with this failing? Just assert for now */ + LWIP_ASSERT("pbuf_header failed\n", 0); + goto bad; + } + + bufptr = (u8_t*)n0->payload; + for(q = np; q != NULL; q = q->next) { + MEMCPY(q->payload, bufptr, q->len); + bufptr += q->len; + } + + if(n0->next) { + pbuf_chain(np, n0->next); + pbuf_dechain(n0); + } + pbuf_free(n0); + n0 = np; + } + + if (pbuf_header(n0, (s16_t)cs->cs_hlen)) { + struct pbuf *np; + + LWIP_ASSERT("vj_uncompress_tcp: cs->cs_hlen <= PBUF_POOL_BUFSIZE", cs->cs_hlen <= PBUF_POOL_BUFSIZE); + np = pbuf_alloc(PBUF_RAW, cs->cs_hlen, PBUF_POOL); + if(!np) { + PPPDEBUG(LOG_WARNING, ("vj_uncompress_tcp: prepend failed\n")); + goto bad; + } + pbuf_cat(np, n0); + n0 = np; + } + LWIP_ASSERT("n0->len >= cs->cs_hlen", n0->len >= cs->cs_hlen); + MEMCPY(n0->payload, &cs->cs_ip, cs->cs_hlen); + + *nb = n0; + + return vjlen; + +bad: + comp->flags |= VJF_TOSS; + INCR(vjs_errorin); + return (-1); +} + +#endif /* PPP_SUPPORT && VJ_SUPPORT && LWIP_TCP */ diff --git a/components/lwip/netif/slipif.c b/components/lwip/netif/slipif.c new file mode 100755 index 0000000000..bf02475eb0 --- /dev/null +++ b/components/lwip/netif/slipif.c @@ -0,0 +1,555 @@ +/** + * @file + * SLIP Interface + * + */ + +/* + * Copyright (c) 2001-2004 Swedish Institute of Computer Science. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * This file is built upon the file: src/arch/rtxc/netif/sioslip.c + * + * Author: Magnus Ivarsson + * Simon Goldschmidt + * + * Usage: This netif can be used in three ways: + * 1) For NO_SYS==0, an RX thread can be used which blocks on sio_read() + * until data is received. + * 2) In your main loop, call slipif_poll() to check for new RX bytes, + * completed packets are fed into netif->input(). + * 3) Call slipif_received_byte[s]() from your serial RX ISR and + * slipif_process_rxqueue() from your main loop. ISR level decodes + * packets and puts completed packets on a queue which is fed into + * the stack from the main loop (needs SYS_LIGHTWEIGHT_PROT for + * pbuf_alloc to work on ISR level!). + * + */ + +/* + * This is an arch independent SLIP netif. The specific serial hooks must be + * provided by another file. They are sio_open, sio_read/sio_tryread and sio_send + */ + +#include "netif/slipif.h" +#include "lwip/opt.h" + +#if LWIP_HAVE_SLIPIF + +#include "lwip/def.h" +#include "lwip/pbuf.h" +#include "lwip/stats.h" +#include "lwip/snmp.h" +#include "lwip/sys.h" +#include "lwip/sio.h" + +#define SLIP_END 0xC0 /* 0300: start and end of every packet */ +#define SLIP_ESC 0xDB /* 0333: escape start (one byte escaped data follows) */ +#define SLIP_ESC_END 0xDC /* 0334: following escape: original byte is 0xC0 (END) */ +#define SLIP_ESC_ESC 0xDD /* 0335: following escape: original byte is 0xDB (ESC) */ + +/** Maximum packet size that is received by this netif */ +#ifndef SLIP_MAX_SIZE +#define SLIP_MAX_SIZE 1500 +#endif + +/** Define this to the interface speed for SNMP + * (sio_fd is the sio_fd_t returned by sio_open). + * The default value of zero means 'unknown'. + */ +#ifndef SLIP_SIO_SPEED +#define SLIP_SIO_SPEED(sio_fd) 0 +#endif + +enum slipif_recv_state { + SLIP_RECV_NORMAL, + SLIP_RECV_ESCAPE +}; + +struct slipif_priv { + sio_fd_t sd; + /* q is the whole pbuf chain for a packet, p is the current pbuf in the chain */ + struct pbuf *p, *q; + u8_t state; + u16_t i, recved; +#if SLIP_RX_FROM_ISR + struct pbuf *rxpackets; +#endif +}; + +/** + * Send a pbuf doing the necessary SLIP encapsulation + * + * Uses the serial layer's sio_send() + * + * @param netif the lwip network interface structure for this slipif + * @param p the pbuf chain packet to send + * @return always returns ERR_OK since the serial layer does not provide return values + */ +static err_t +slipif_output(struct netif *netif, struct pbuf *p) +{ + struct slipif_priv *priv; + struct pbuf *q; + u16_t i; + u8_t c; + + LWIP_ASSERT("netif != NULL", (netif != NULL)); + LWIP_ASSERT("netif->state != NULL", (netif->state != NULL)); + LWIP_ASSERT("p != NULL", (p != NULL)); + + LWIP_DEBUGF(SLIP_DEBUG, ("slipif_output(%"U16_F"): sending %"U16_F" bytes\n", (u16_t)netif->num, p->tot_len)); + priv = (struct slipif_priv *)netif->state; + + /* Send pbuf out on the serial I/O device. */ + /* Start with packet delimiter. */ + sio_send(SLIP_END, priv->sd); + + for (q = p; q != NULL; q = q->next) { + for (i = 0; i < q->len; i++) { + c = ((u8_t *)q->payload)[i]; + switch (c) { + case SLIP_END: + /* need to escape this byte (0xC0 -> 0xDB, 0xDC) */ + sio_send(SLIP_ESC, priv->sd); + sio_send(SLIP_ESC_END, priv->sd); + break; + case SLIP_ESC: + /* need to escape this byte (0xDB -> 0xDB, 0xDD) */ + sio_send(SLIP_ESC, priv->sd); + sio_send(SLIP_ESC_ESC, priv->sd); + break; + default: + /* normal byte - no need for escaping */ + sio_send(c, priv->sd); + break; + } + } + } + /* End with packet delimiter. */ + sio_send(SLIP_END, priv->sd); + return ERR_OK; +} + +#if LWIP_IPV4 +/** + * Send a pbuf doing the necessary SLIP encapsulation + * + * Uses the serial layer's sio_send() + * + * @param netif the lwip network interface structure for this slipif + * @param p the pbuf chain packet to send + * @param ipaddr the ip address to send the packet to (not used for slipif) + * @return always returns ERR_OK since the serial layer does not provide return values + */ +static err_t +slipif_output_v4(struct netif *netif, struct pbuf *p, const ip4_addr_t *ipaddr) +{ + LWIP_UNUSED_ARG(ipaddr); + return slipif_output(netif, p); +} +#endif /* LWIP_IPV4 */ + +#if LWIP_IPV6 +/** + * Send a pbuf doing the necessary SLIP encapsulation + * + * Uses the serial layer's sio_send() + * + * @param netif the lwip network interface structure for this slipif + * @param p the pbuf chain packet to send + * @param ipaddr the ip address to send the packet to (not used for slipif) + * @return always returns ERR_OK since the serial layer does not provide return values + */ +static err_t +slipif_output_v6(struct netif *netif, struct pbuf *p, const ip6_addr_t *ipaddr) +{ + LWIP_UNUSED_ARG(ipaddr); + return slipif_output(netif, p); +} +#endif /* LWIP_IPV6 */ + +/** + * Handle the incoming SLIP stream character by character + * + * @param netif the lwip network interface structure for this slipif + * @param c received character (multiple calls to this function will + * return a complete packet, NULL is returned before - used for polling) + * @return The IP packet when SLIP_END is received + */ +static struct pbuf* +slipif_rxbyte(struct netif *netif, u8_t c) +{ + struct slipif_priv *priv; + struct pbuf *t; + + LWIP_ASSERT("netif != NULL", (netif != NULL)); + LWIP_ASSERT("netif->state != NULL", (netif->state != NULL)); + + priv = (struct slipif_priv *)netif->state; + + switch (priv->state) { + case SLIP_RECV_NORMAL: + switch (c) { + case SLIP_END: + if (priv->recved > 0) { + /* Received whole packet. */ + /* Trim the pbuf to the size of the received packet. */ + pbuf_realloc(priv->q, priv->recved); + + LINK_STATS_INC(link.recv); + + LWIP_DEBUGF(SLIP_DEBUG, ("slipif: Got packet (%"U16_F" bytes)\n", priv->recved)); + t = priv->q; + priv->p = priv->q = NULL; + priv->i = priv->recved = 0; + return t; + } + return NULL; + case SLIP_ESC: + priv->state = SLIP_RECV_ESCAPE; + return NULL; + default: + break; + } /* end switch (c) */ + break; + case SLIP_RECV_ESCAPE: + /* un-escape END or ESC bytes, leave other bytes + (although that would be a protocol error) */ + switch (c) { + case SLIP_ESC_END: + c = SLIP_END; + break; + case SLIP_ESC_ESC: + c = SLIP_ESC; + break; + default: + break; + } + priv->state = SLIP_RECV_NORMAL; + break; + default: + break; + } /* end switch (priv->state) */ + + /* byte received, packet not yet completely received */ + if (priv->p == NULL) { + /* allocate a new pbuf */ + LWIP_DEBUGF(SLIP_DEBUG, ("slipif_input: alloc\n")); + priv->p = pbuf_alloc(PBUF_LINK, (PBUF_POOL_BUFSIZE - PBUF_LINK_HLEN - PBUF_LINK_ENCAPSULATION_HLEN), PBUF_POOL); + + if (priv->p == NULL) { + LINK_STATS_INC(link.drop); + LWIP_DEBUGF(SLIP_DEBUG, ("slipif_input: no new pbuf! (DROP)\n")); + /* don't process any further since we got no pbuf to receive to */ + return NULL; + } + + if (priv->q != NULL) { + /* 'chain' the pbuf to the existing chain */ + pbuf_cat(priv->q, priv->p); + } else { + /* p is the first pbuf in the chain */ + priv->q = priv->p; + } + } + + /* this automatically drops bytes if > SLIP_MAX_SIZE */ + if ((priv->p != NULL) && (priv->recved <= SLIP_MAX_SIZE)) { + ((u8_t *)priv->p->payload)[priv->i] = c; + priv->recved++; + priv->i++; + if (priv->i >= priv->p->len) { + /* on to the next pbuf */ + priv->i = 0; + if (priv->p->next != NULL && priv->p->next->len > 0) { + /* p is a chain, on to the next in the chain */ + priv->p = priv->p->next; + } else { + /* p is a single pbuf, set it to NULL so next time a new + * pbuf is allocated */ + priv->p = NULL; + } + } + } + return NULL; +} + +/** Like slipif_rxbyte, but passes completed packets to netif->input + * + * @param netif The lwip network interface structure for this slipif + * @param data received character + */ +static void +slipif_rxbyte_input(struct netif *netif, u8_t c) +{ + struct pbuf *p; + p = slipif_rxbyte(netif, c); + if (p != NULL) { + if (netif->input(p, netif) != ERR_OK) { + pbuf_free(p); + } + } +} + +#if SLIP_USE_RX_THREAD +/** + * The SLIP input thread. + * + * Feed the IP layer with incoming packets + * + * @param nf the lwip network interface structure for this slipif + */ +static void +slipif_loop_thread(void *nf) +{ + u8_t c; + struct netif *netif = (struct netif *)nf; + struct slipif_priv *priv = (struct slipif_priv *)netif->state; + + while (1) { + if (sio_read(priv->sd, &c, 1) > 0) { + slipif_rxbyte_input(netif, c); + } + } +} +#endif /* SLIP_USE_RX_THREAD */ + +/** + * SLIP netif initialization + * + * Call the arch specific sio_open and remember + * the opened device in the state field of the netif. + * + * @param netif the lwip network interface structure for this slipif + * @return ERR_OK if serial line could be opened, + * ERR_MEM if no memory could be allocated, + * ERR_IF is serial line couldn't be opened + * + * @note netif->num must contain the number of the serial port to open + * (0 by default). If netif->state is != NULL, it is interpreted as an + * u8_t pointer pointing to the serial port number instead of netif->num. + * + */ +err_t +slipif_init(struct netif *netif) +{ + struct slipif_priv *priv; + u8_t sio_num; + + LWIP_DEBUGF(SLIP_DEBUG, ("slipif_init: netif->num=%"U16_F"\n", (u16_t)netif->num)); + + /* Allocate private data */ + priv = (struct slipif_priv *)mem_malloc(sizeof(struct slipif_priv)); + if (!priv) { + return ERR_MEM; + } + + netif->name[0] = 's'; + netif->name[1] = 'l'; +#if LWIP_IPV4 + netif->output = slipif_output_v4; +#endif /* LWIP_IPV4 */ +#if LWIP_IPV6 + netif->output_ip6 = slipif_output_v6; +#endif /* LWIP_IPV6 */ + netif->mtu = SLIP_MAX_SIZE; + + /* netif->state or netif->num contain the port number */ + if (netif->state != NULL) { + sio_num = *(u8_t*)netif->state; + } else { + sio_num = netif->num; + } + /* Try to open the serial port. */ + priv->sd = sio_open(sio_num); + if (!priv->sd) { + /* Opening the serial port failed. */ + mem_free(priv); + return ERR_IF; + } + + /* Initialize private data */ + priv->p = NULL; + priv->q = NULL; + priv->state = SLIP_RECV_NORMAL; + priv->i = 0; + priv->recved = 0; +#if SLIP_RX_FROM_ISR + priv->rxpackets = NULL; +#endif + + netif->state = priv; + + /* initialize the snmp variables and counters inside the struct netif */ + MIB2_INIT_NETIF(netif, snmp_ifType_slip, SLIP_SIO_SPEED(priv->sd)); + +#if SLIP_USE_RX_THREAD + /* Create a thread to poll the serial line. */ + sys_thread_new(SLIPIF_THREAD_NAME, slipif_loop_thread, netif, + SLIPIF_THREAD_STACKSIZE, SLIPIF_THREAD_PRIO); +#endif /* SLIP_USE_RX_THREAD */ + return ERR_OK; +} + +/** + * Polls the serial device and feeds the IP layer with incoming packets. + * + * @param netif The lwip network interface structure for this slipif + */ +void +slipif_poll(struct netif *netif) +{ + u8_t c; + struct slipif_priv *priv; + + LWIP_ASSERT("netif != NULL", (netif != NULL)); + LWIP_ASSERT("netif->state != NULL", (netif->state != NULL)); + + priv = (struct slipif_priv *)netif->state; + + while (sio_tryread(priv->sd, &c, 1) > 0) { + slipif_rxbyte_input(netif, c); + } +} + +#if SLIP_RX_FROM_ISR +/** + * Feeds the IP layer with incoming packets that were receive + * + * @param netif The lwip network interface structure for this slipif + */ +void +slipif_process_rxqueue(struct netif *netif) +{ + struct slipif_priv *priv; + SYS_ARCH_DECL_PROTECT(old_level); + + LWIP_ASSERT("netif != NULL", (netif != NULL)); + LWIP_ASSERT("netif->state != NULL", (netif->state != NULL)); + + priv = (struct slipif_priv *)netif->state; + + SYS_ARCH_PROTECT(old_level); + while (priv->rxpackets != NULL) { + struct pbuf *p = priv->rxpackets; +#if SLIP_RX_QUEUE + /* dequeue packet */ + struct pbuf *q = p; + while ((q->len != q->tot_len) && (q->next != NULL)) { + q = q->next; + } + priv->rxpackets = q->next; + q->next = NULL; +#else /* SLIP_RX_QUEUE */ + priv->rxpackets = NULL; +#endif /* SLIP_RX_QUEUE */ + SYS_ARCH_UNPROTECT(old_level); + if (netif->input(p, netif) != ERR_OK) { + pbuf_free(p); + } + SYS_ARCH_PROTECT(old_level); + } +} + +/** Like slipif_rxbyte, but queues completed packets. + * + * @param netif The lwip network interface structure for this slipif + * @param data Received serial byte + */ +static void +slipif_rxbyte_enqueue(struct netif *netif, u8_t data) +{ + struct pbuf *p; + struct slipif_priv *priv = (struct slipif_priv *)netif->state; + SYS_ARCH_DECL_PROTECT(old_level); + + p = slipif_rxbyte(netif, data); + if (p != NULL) { + SYS_ARCH_PROTECT(old_level); + if (priv->rxpackets != NULL) { +#if SLIP_RX_QUEUE + /* queue multiple pbufs */ + struct pbuf *q = p; + while (q->next != NULL) { + q = q->next; + } + q->next = p; + } else { +#else /* SLIP_RX_QUEUE */ + pbuf_free(priv->rxpackets); + } + { +#endif /* SLIP_RX_QUEUE */ + priv->rxpackets = p; + } + SYS_ARCH_UNPROTECT(old_level); + } +} + +/** + * Process a received byte, completed packets are put on a queue that is + * fed into IP through slipif_process_rxqueue(). + * + * This function can be called from ISR if SYS_LIGHTWEIGHT_PROT is enabled. + * + * @param netif The lwip network interface structure for this slipif + * @param data received character + */ +void +slipif_received_byte(struct netif *netif, u8_t data) +{ + LWIP_ASSERT("netif != NULL", (netif != NULL)); + LWIP_ASSERT("netif->state != NULL", (netif->state != NULL)); + slipif_rxbyte_enqueue(netif, data); +} + +/** + * Process multiple received byte, completed packets are put on a queue that is + * fed into IP through slipif_process_rxqueue(). + * + * This function can be called from ISR if SYS_LIGHTWEIGHT_PROT is enabled. + * + * @param netif The lwip network interface structure for this slipif + * @param data received character + * @param len Number of received characters + */ +void +slipif_received_bytes(struct netif *netif, u8_t *data, u8_t len) +{ + u8_t i; + u8_t *rxdata = data; + LWIP_ASSERT("netif != NULL", (netif != NULL)); + LWIP_ASSERT("netif->state != NULL", (netif->state != NULL)); + + for (i = 0; i < len; i++, rxdata++) { + slipif_rxbyte_enqueue(netif, *rxdata); + } +} +#endif /* SLIP_RX_FROM_ISR */ + +#endif /* LWIP_HAVE_SLIPIF */ diff --git a/components/lwip/port/freertos/sys_arch.c b/components/lwip/port/freertos/sys_arch.c new file mode 100755 index 0000000000..caa6d1a3a9 --- /dev/null +++ b/components/lwip/port/freertos/sys_arch.c @@ -0,0 +1,494 @@ +/* + * Copyright (c) 2001-2003 Swedish Institute of Computer Science. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + * + */ + +/* lwIP includes. */ + +#include "lwip/debug.h" +#include "lwip/def.h" +#include "lwip/sys.h" +#include "lwip/mem.h" +#include "arch/sys_arch.h" + +/* This is the number of threads that can be started with sys_thread_new() */ +#define SYS_THREAD_MAX 4 + +#if !LWIP_COMPAT_MUTEX +/** Create a new mutex + * @param mutex pointer to the mutex to create + * @return a new mutex */ +err_t +sys_mutex_new(sys_mutex_t *pxMutex) +{ + err_t xReturn = ERR_MEM; + + *pxMutex = xSemaphoreCreateMutex(); + + if (*pxMutex != NULL) { + xReturn = ERR_OK; + } + + LWIP_DEBUGF(THREAD_SAFE_DEBUG, ("sys_mutex_new: m=%p\n", *pxMutex)); + + return xReturn; +} + +/** Lock a mutex + * @param mutex the mutex to lock */ +void +sys_mutex_lock(sys_mutex_t *pxMutex) +{ + while (xSemaphoreTake(*pxMutex, portMAX_DELAY) != pdPASS); +} + +err_t +sys_mutex_trylock(sys_mutex_t *pxMutex) +{ + if (xSemaphoreTake(*pxMutex, 0) == pdPASS) return 0; + else return -1; +} + +/** Unlock a mutex + * @param mutex the mutex to unlock */ +void +sys_mutex_unlock(sys_mutex_t *pxMutex) +{ + xSemaphoreGive(*pxMutex); +} + +/** Delete a semaphore + * @param mutex the mutex to delete */ +void +sys_mutex_free(sys_mutex_t *pxMutex) +{ + LWIP_DEBUGF(THREAD_SAFE_DEBUG, ("sys_mutex_free: m=%p\n", *pxMutex)); + vQueueDelete(*pxMutex); +} +#endif + +/*-----------------------------------------------------------------------------------*/ +// Creates and returns a new semaphore. The "count" argument specifies +// the initial state of the semaphore. TBD finish and test +err_t +sys_sem_new(sys_sem_t *sem, u8_t count) +{ + err_t xReturn = ERR_MEM; + vSemaphoreCreateBinary(*sem); + + if ((*sem) != NULL) { + if (count == 0) { // Means it can't be taken + xSemaphoreTake(*sem, 1); + } + + xReturn = ERR_OK; + } else { + ; // TBD need assert + } + + return xReturn; +} + +/*-----------------------------------------------------------------------------------*/ +// Signals a semaphore +void +sys_sem_signal(sys_sem_t *sem) +{ + xSemaphoreGive(*sem); +} + +/*-----------------------------------------------------------------------------------*/ +/* + Blocks the thread while waiting for the semaphore to be + signaled. If the "timeout" argument is non-zero, the thread should + only be blocked for the specified time (measured in + milliseconds). + + If the timeout argument is non-zero, the return value is the number of + milliseconds spent waiting for the semaphore to be signaled. If the + semaphore wasn't signaled within the specified time, the return value is + SYS_ARCH_TIMEOUT. If the thread didn't have to wait for the semaphore + (i.e., it was already signaled), the function may return zero. + + Notice that lwIP implements a function with a similar name, + sys_sem_wait(), that uses the sys_arch_sem_wait() function. +*/ +u32_t +sys_arch_sem_wait(sys_sem_t *sem, u32_t timeout) +{ + portTickType StartTime, EndTime, Elapsed; + unsigned long ulReturn; + + StartTime = xTaskGetTickCount(); + + if (timeout != 0) { + if (xSemaphoreTake(*sem, timeout / portTICK_RATE_MS) == pdTRUE) { + EndTime = xTaskGetTickCount(); + Elapsed = (EndTime - StartTime) * portTICK_RATE_MS; + + if (Elapsed == 0) { + Elapsed = 1; + } + + ulReturn = Elapsed; + } else { + ulReturn = SYS_ARCH_TIMEOUT; + } + } else { // must block without a timeout + while (xSemaphoreTake(*sem, portMAX_DELAY) != pdTRUE); + + EndTime = xTaskGetTickCount(); + Elapsed = (EndTime - StartTime) * portTICK_RATE_MS; + + if (Elapsed == 0) { + Elapsed = 1; + } + + ulReturn = Elapsed; + } + + return ulReturn ; // return time blocked +} + +/*-----------------------------------------------------------------------------------*/ +// Deallocates a semaphore +void +sys_sem_free(sys_sem_t *sem) +{ + vSemaphoreDelete(*sem); +} + +/*-----------------------------------------------------------------------------------*/ +// Creates an empty mailbox. +err_t +sys_mbox_new(sys_mbox_t *mbox, int size) +{ + *mbox = malloc(sizeof(struct sys_mbox_s)); + if (*mbox == NULL){ + LWIP_DEBUGF(THREAD_SAFE_DEBUG, ("fail to new *mbox\n")); + return ERR_MEM; + } + + (*mbox)->os_mbox = xQueueCreate(size, sizeof(void *)); + + if ((*mbox)->os_mbox == NULL) { + LWIP_DEBUGF(THREAD_SAFE_DEBUG, ("fail to new *mbox->os_mbox\n")); + free(*mbox); + return ERR_MEM; + } + + if (sys_mutex_new(&((*mbox)->lock)) != ERR_OK){ + LWIP_DEBUGF(THREAD_SAFE_DEBUG, ("fail to new *mbox->lock\n")); + vQueueDelete((*mbox)->os_mbox); + free(*mbox); + return ERR_MEM; + } + + (*mbox)->alive = true; + + LWIP_DEBUGF(THREAD_SAFE_DEBUG, ("new *mbox ok\n")); + return ERR_OK; +} + +/*-----------------------------------------------------------------------------------*/ +// Posts the "msg" to the mailbox. +void +sys_mbox_post(sys_mbox_t *mbox, void *msg) +{ + while (xQueueSendToBack((*mbox)->os_mbox, &msg, portMAX_DELAY) != pdTRUE); +} + +/*-----------------------------------------------------------------------------------*/ +err_t +sys_mbox_trypost(sys_mbox_t *mbox, void *msg) +{ + err_t xReturn; + + if (xQueueSend((*mbox)->os_mbox, &msg, (portTickType)0) == pdPASS) { + xReturn = ERR_OK; + } else { + xReturn = ERR_MEM; + } + + return xReturn; +} + +/*-----------------------------------------------------------------------------------*/ +/* + Blocks the thread until a message arrives in the mailbox, but does + not block the thread longer than "timeout" milliseconds (similar to + the sys_arch_sem_wait() function). The "msg" argument is a result + parameter that is set by the function (i.e., by doing "*msg = + ptr"). The "msg" parameter maybe NULL to indicate that the message + should be dropped. + + The return values are the same as for the sys_arch_sem_wait() function: + Number of milliseconds spent waiting or SYS_ARCH_TIMEOUT if there was a + timeout. + + Note that a function with a similar name, sys_mbox_fetch(), is + implemented by lwIP. +*/ +u32_t +sys_arch_mbox_fetch(sys_mbox_t *mbox, void **msg, u32_t timeout) +{ + void *dummyptr; + portTickType StartTime, EndTime, Elapsed; + unsigned long ulReturn; + + StartTime = xTaskGetTickCount(); + if (msg == NULL) { + msg = &dummyptr; + } + + if (*mbox == NULL){ + *msg = NULL; + LWIP_DEBUGF(THREAD_SAFE_DEBUG, ("sys_arch_mbox_fetch: null mbox\n")); + return -1; + } + + sys_mutex_lock(&(*mbox)->lock); + + if (timeout != 0) { + if (pdTRUE == xQueueReceive((*mbox)->os_mbox, &(*msg), timeout / portTICK_RATE_MS)) { + EndTime = xTaskGetTickCount(); + Elapsed = (EndTime - StartTime) * portTICK_RATE_MS; + + if (Elapsed == 0) { + Elapsed = 1; + } + + ulReturn = Elapsed; + } else { // timed out blocking for message + *msg = NULL; + ulReturn = SYS_ARCH_TIMEOUT; + } + } else { // block forever for a message. + while (1){ + + if (pdTRUE == xQueueReceive((*mbox)->os_mbox, &(*msg), portMAX_DELAY)){ + break; + } + + if ((*mbox)->alive == false){ + LWIP_DEBUGF(THREAD_SAFE_DEBUG, ("sys_arch_mbox_fetch:mbox not alive\n")); + *msg = NULL; + break; + } + } + + EndTime = xTaskGetTickCount(); + Elapsed = (EndTime - StartTime) * portTICK_RATE_MS; + + if (Elapsed == 0) { + Elapsed = 1; + } + + ulReturn = Elapsed; + } + + sys_mutex_unlock(&(*mbox)->lock); + + return ulReturn ; // return time blocked TBD test +} + +/*-----------------------------------------------------------------------------------*/ +u32_t +sys_arch_mbox_tryfetch(sys_mbox_t *mbox, void **msg) +{ + void *pvDummy; + unsigned long ulReturn; + + if (msg == NULL) { + msg = &pvDummy; + } + + if (pdTRUE == xQueueReceive((*mbox)->os_mbox, &(*msg), 0)) { + ulReturn = ERR_OK; + } else { + ulReturn = SYS_MBOX_EMPTY; + } + + return ulReturn; +} + +/*-----------------------------------------------------------------------------------*/ +/* + Deallocates a mailbox. If there are messages still present in the + mailbox when the mailbox is deallocated, it is an indication of a + programming error in lwIP and the developer should be notified. +*/ +void +sys_mbox_free(sys_mbox_t *mbox) +{ + uint8_t count = 0; + bool post_null = true; + + LWIP_DEBUGF(THREAD_SAFE_DEBUG, ("sys_mbox_free: set alive false\n")); + (*mbox)->alive = false; + + while ( count++ < 10 ){ + LWIP_DEBUGF(THREAD_SAFE_DEBUG, ("sys_mbox_free:try lock=%d\n", count)); + if (!sys_mutex_trylock( &(*mbox)->lock )){ + LWIP_DEBUGF(THREAD_SAFE_DEBUG, ("sys_mbox_free:get lock ok %d\n", count)); + sys_mutex_unlock( &(*mbox)->lock ); + break; + } + + if (post_null){ + LWIP_DEBUGF(THREAD_SAFE_DEBUG, ("sys_mbox_free: post null to mbox\n")); + if (sys_mbox_trypost( mbox, NULL) != ERR_OK){ + LWIP_DEBUGF(THREAD_SAFE_DEBUG, ("sys_mbox_free: post null mbox fail\n")); + } else { + post_null = false; + LWIP_DEBUGF(THREAD_SAFE_DEBUG, ("sys_mbox_free: post null mbox ok\n")); + } + } + + if (count == 10){ + printf("WARNING: mbox %p had a consumer who never unblocked. Leaking!\n", (*mbox)->os_mbox); + } + sys_delay_ms(20); + } + + LWIP_DEBUGF(THREAD_SAFE_DEBUG, ("sys_mbox_free:free mbox\n")); + + if (uxQueueMessagesWaiting((*mbox)->os_mbox)) { + xQueueReset((*mbox)->os_mbox); + /* Line for breakpoint. Should never break here! */ + __asm__ volatile ("nop"); + } + + vQueueDelete((*mbox)->os_mbox); + sys_mutex_free(&(*mbox)->lock); + free(*mbox); + *mbox = NULL; +} + +/*-----------------------------------------------------------------------------------*/ +/* + Starts a new thread with priority "prio" that will begin its execution in the + function "thread()". The "arg" argument will be passed as an argument to the + thread() function. The id of the new thread is returned. Both the id and + the priority are system dependent. +*/ +sys_thread_t +sys_thread_new(const char *name, lwip_thread_fn thread, void *arg, int stacksize, int prio) +{ + xTaskHandle CreatedTask; + portBASE_TYPE result; + + result = xTaskCreate(thread, name, stacksize, arg, prio, &CreatedTask); + + if (result == pdPASS) { + return CreatedTask; + } else { + return NULL; + } +} + +/*-----------------------------------------------------------------------------------*/ +// Initialize sys arch +void +sys_init(void) +{ +} + +/*-----------------------------------------------------------------------------------*/ +u32_t +sys_now(void) +{ + return xTaskGetTickCount(); +} + +/* + This optional function does a "fast" critical region protection and returns + the previous protection level. This function is only called during very short + critical regions. An embedded system which supports ISR-based drivers might + want to implement this function by disabling interrupts. Task-based systems + might want to implement this by using a mutex or disabling tasking. This + function should support recursive calls from the same task or interrupt. In + other words, sys_arch_protect() could be called while already protected. In + that case the return value indicates that it is already protected. + + sys_arch_protect() is only required if your port is supporting an operating + system. +*/ +sys_prot_t +sys_arch_protect(void) +{ +// vTaskEnterCritical(); + return (sys_prot_t) 1; +} + +/*-----------------------------------------------------------------------------------*/ +/* + This optional function does a "fast" set of critical region protection to the + value specified by pval. See the documentation for sys_arch_protect() for + more information. This function is only required if your port is supporting + an operating system. +*/ +void +sys_arch_unprotect(sys_prot_t pval) +{ + (void) pval; +// vTaskExitCritical(); +} + +/*-----------------------------------------------------------------------------------*/ +/* + * Prints an assertion messages and aborts execution. + */ +void +sys_arch_assert(const char *file, int line) +{ + printf("\nAssertion: %d in %s\n", line, file); + +// vTaskEnterCritical(); + while(1); +} + +/* This is a super hacky thread-local-storage repository + FreeRTOS 8.2.3 & up have thread local storage in the + OS, which is how we should do this. Once we upgrade FreeRTOS, + we can drop this hacky store and use the FreeRTOS TLS API. +*/ +sys_sem_t* sys_thread_sem(void) +{ + extern void* xTaskGetLwipSem(void); + return (sys_sem_t*)(xTaskGetLwipSem()); +} + +void sys_delay_ms(uint32_t ms) +{ + vTaskDelay(ms/portTICK_RATE_MS); +} + + diff --git a/components/lwip/port/netif/wlanif.c b/components/lwip/port/netif/wlanif.c new file mode 100755 index 0000000000..0b87656c8b --- /dev/null +++ b/components/lwip/port/netif/wlanif.c @@ -0,0 +1,284 @@ +/** + * @file + * Ethernet Interface Skeleton + * + */ + +/* + * Copyright (c) 2001-2004 Swedish Institute of Computer Science. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + * + */ + +#include "lwip/opt.h" + +#include "lwip/def.h" +#include "lwip/mem.h" +#include "lwip/pbuf.h" +#include "lwip/stats.h" +#include "lwip/snmp.h" +#include "lwip/ethip6.h" +#include "netif/etharp.h" +#include "netif/wlanif.h" + +#include +#include + +#include "tcpip_adapter.h" + +/* Define those to better describe your network interface. */ +#define IFNAME0 'e' +#define IFNAME1 'n' + +#ifdef LWIP_ESP8266 +//TO_DO +//char *hostname; +//bool default_hostname = 1; + +static char hostname[16]; +#else +static char hostname[16]; +#endif +#ifdef PERF +uint32 g_rx_alloc_pbuf_fail_cnt = 0; +#endif + +/** + * In this function, the hardware should be initialized. + * Called from ethernetif_init(). + * + * @param netif the already initialized lwip network interface structure + * for this ethernetif + */ +static void +low_level_init(struct netif *netif) +{ + + + + + /* set MAC hardware address length */ + netif->hwaddr_len = ETHARP_HWADDR_LEN; + + /* set MAC hardware address */ + + /* maximum transfer unit */ + netif->mtu = 1500; + + /* device capabilities */ + /* don't set NETIF_FLAG_ETHARP if this device is not an ethernet one */ + netif->flags = NETIF_FLAG_BROADCAST | NETIF_FLAG_ETHARP | NETIF_FLAG_LINK_UP; + +#ifdef LWIP_ESP8266 + +#if LWIP_IGMP + + netif->flags |= NETIF_FLAG_IGMP; +#endif + + + #endif + + /* Do whatever else is needed to initialize interface. */ +} + +/** + * This function should do the actual transmission of the packet. The packet is + * contained in the pbuf that is passed to the function. This pbuf + * might be chained. + * + * @param netif the lwip network interface structure for this ethernetif + * @param p the MAC packet to send (e.g. IP packet including MAC addresses and type) + * @return ERR_OK if the packet could be sent + * an err_t value if the packet couldn't be sent + * + * @note Returning ERR_MEM here if a DMA queue of your MAC is full can lead to + * strange results. You might consider waiting for space in the DMA queue + * to become availale since the stack doesn't retry to send a packet + * dropped because of memory failure (except for the TCP timers). + */ +static err_t +low_level_output(struct netif *netif, struct pbuf *p) +{ + struct pbuf *q; + wifi_interface_t wifi_if = tcpip_adapter_get_wifi_if(netif); + + if (wifi_if >= WIFI_IF_MAX) { + return ERR_IF; + } + +#ifdef LWIP_ESP8266 + q = p; + u16_t pbuf_x_len = 0; + pbuf_x_len = q->len; + if(q->next !=NULL) + { + //char cnt = 0; + struct pbuf *tmp = q->next; + while(tmp != NULL) + { + memcpy( (u8_t *)( (u8_t *)(q->payload) + pbuf_x_len), (u8_t *)tmp->payload , tmp->len ); + pbuf_x_len += tmp->len; + //cnt++; + tmp = tmp->next; + } + } + + ieee80211_output(wifi_if, q->payload, pbuf_x_len); + return ERR_OK; + +#else + for(q = p; q != NULL; q = q->next) { + ieee80211_output(wifi_if, q->payload, q->len); + } +#endif + + return ERR_OK; +} + +/** + * This function should be called when a packet is ready to be read + * from the interface. It uses the function low_level_input() that + * should handle the actual reception of bytes from the network + * interface. Then the type of the received packet is determined and + * the appropriate input function is called. + * + * @param netif the lwip network interface structure for this ethernetif + */ +void +#ifdef LWIP_ESP8266 +wlanif_input(struct netif *netif, void *buffer, u16_t len, void* eb) +#else +wlanif_input(struct netif *netif, void *buffer, uint16 len) +#endif +{ + struct pbuf *p; + +#ifdef LWIP_ESP8266 + if(buffer== NULL) + goto _exit; + if(netif == NULL) + goto _exit; +#endif + +#ifdef LWIP_ESP8266 + p = pbuf_alloc(PBUF_RAW, len, PBUF_REF); + if (p == NULL){ +#ifdef PERF + g_rx_alloc_pbuf_fail_cnt++; +#endif + return; + } + p->payload = buffer; + p->eb = eb; +#else + p = pbuf_alloc(PBUF_IP, len, PBUF_POOL); + if (p == NULL) { + return; + } + memcpy(p->payload, buffer, len); +#endif + + + /* full packet send to tcpip_thread to process */ + if (netif->input(p, netif) != ERR_OK) { + LWIP_DEBUGF(NETIF_DEBUG, ("ethernetif_input: IP input error\n")); + pbuf_free(p); + } + +_exit: +; +} + +/** + * Should be called at the beginning of the program to set up the + * network interface. It calls the function low_level_init() to do the + * actual setup of the hardware. + * + * This function should be passed as a parameter to netif_add(). + * + * @param netif the lwip network interface structure for this ethernetif + * @return ERR_OK if the loopif is initialized + * ERR_MEM if private data couldn't be allocated + * any other err_t on error + */ +err_t +wlanif_init(struct netif *netif) +{ + LWIP_ASSERT("netif != NULL", (netif != NULL)); + +#if LWIP_NETIF_HOSTNAME + /* Initialize interface hostname */ + +#ifdef LWIP_ESP8266 +//TO_DO +/* + if ((struct netif *)wifi_get_netif(STATION_IF) == netif) { + if (default_hostname == 1) { + wifi_station_set_default_hostname(netif->hwaddr); + } + netif->hostname = hostname; + } else { + netif->hostname = NULL; + } +*/ + sprintf(hostname, "ESP_%02X%02X%02X", netif->hwaddr[3], netif->hwaddr[4], netif->hwaddr[5]); + netif->hostname = hostname; + +#else + sprintf(hostname, "ESP_%02X%02X%02X", netif->hwaddr[3], netif->hwaddr[4], netif->hwaddr[5]); + netif->hostname = hostname; +#endif + +#endif /* LWIP_NETIF_HOSTNAME */ + + /* + * Initialize the snmp variables and counters inside the struct netif. + * The last argument should be replaced with your link speed, in units + * of bits per second. + */ + NETIF_INIT_SNMP(netif, snmp_ifType_ethernet_csmacd, LINK_SPEED_OF_YOUR_NETIF_IN_BPS); + + netif->name[0] = IFNAME0; + netif->name[1] = IFNAME1; + /* We directly use etharp_output() here to save a function call. + * You can instead declare your own function an call etharp_output() + * from it if you have to do some checks before sending (e.g. if link + * is available...) */ + netif->output = etharp_output; +#if LWIP_IPV6 + netif->output_ip6 = ethip6_output; +#endif /* LWIP_IPV6 */ + netif->linkoutput = low_level_output; + + /* initialize the hardware */ + low_level_init(netif); + + return ERR_OK; +} diff --git a/components/newlib/.gitignore b/components/newlib/.gitignore new file mode 100644 index 0000000000..99c1e5325c --- /dev/null +++ b/components/newlib/.gitignore @@ -0,0 +1,2 @@ +.build +*.syms diff --git a/components/newlib/.gitmodules b/components/newlib/.gitmodules new file mode 100644 index 0000000000..1a3930d13f --- /dev/null +++ b/components/newlib/.gitmodules @@ -0,0 +1,4 @@ +[submodule "newlib_xtensa-2.2.0"] + path = newlib_xtensa-2.2.0 + url = ssh://git@gitlab.espressif.cn:27227/igrokhotkov/newlib_xtensa-2.2.0.git + ignore = dirty diff --git a/components/newlib/COPYING.NEWLIB b/components/newlib/COPYING.NEWLIB new file mode 100644 index 0000000000..0655d35497 --- /dev/null +++ b/components/newlib/COPYING.NEWLIB @@ -0,0 +1,953 @@ +The newlib subdirectory is a collection of software from several sources. + +Each file may have its own copyright/license that is embedded in the source +file. Unless otherwise noted in the body of the source file(s), the following copyright +notices will apply to the contents of the newlib subdirectory: + +(1) Red Hat Incorporated + +Copyright (c) 1994-2009 Red Hat, Inc. All rights reserved. + +This copyrighted material is made available to anyone wishing to use, +modify, copy, or redistribute it subject to the terms and conditions +of the BSD License. This program is distributed in the hope that +it will be useful, but WITHOUT ANY WARRANTY expressed or implied, +including the implied warranties of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. A copy of this license is available at +http://www.opensource.org/licenses. Any Red Hat trademarks that are +incorporated in the source code or documentation are not subject to +the BSD License and may only be used or replicated with the express +permission of Red Hat, Inc. + +(2) University of California, Berkeley + +Copyright (c) 1981-2000 The Regents of the University of California. +All rights reserved. + +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + * Neither the name of the University nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. + +(3) David M. Gay (AT&T 1991, Lucent 1998) + +The author of this software is David M. Gay. + +Copyright (c) 1991 by AT&T. + +Permission to use, copy, modify, and distribute this software for any +purpose without fee is hereby granted, provided that this entire notice +is included in all copies of any software which is or includes a copy +or modification of this software and in all copies of the supporting +documentation for such software. + +THIS SOFTWARE IS BEING PROVIDED "AS IS", WITHOUT ANY EXPRESS OR IMPLIED +WARRANTY. IN PARTICULAR, NEITHER THE AUTHOR NOR AT&T MAKES ANY +REPRESENTATION OR WARRANTY OF ANY KIND CONCERNING THE MERCHANTABILITY +OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR PURPOSE. + +------------------------------------------------------------------- + +The author of this software is David M. Gay. + +Copyright (C) 1998-2001 by Lucent Technologies +All Rights Reserved + +Permission to use, copy, modify, and distribute this software and +its documentation for any purpose and without fee is hereby +granted, provided that the above copyright notice appear in all +copies and that both that the copyright notice and this +permission notice and warranty disclaimer appear in supporting +documentation, and that the name of Lucent or any of its entities +not be used in advertising or publicity pertaining to +distribution of the software without specific, written prior +permission. + +LUCENT DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, +INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. +IN NO EVENT SHALL LUCENT OR ANY OF ITS ENTITIES BE LIABLE FOR ANY +SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER +IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, +ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF +THIS SOFTWARE. + + +(4) Advanced Micro Devices + +Copyright 1989, 1990 Advanced Micro Devices, Inc. + +This software is the property of Advanced Micro Devices, Inc (AMD) which +specifically grants the user the right to modify, use and distribute this +software provided this notice is not removed or altered. All other rights +are reserved by AMD. + +AMD MAKES NO WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, WITH REGARD TO THIS +SOFTWARE. IN NO EVENT SHALL AMD BE LIABLE FOR INCIDENTAL OR CONSEQUENTIAL +DAMAGES IN CONNECTION WITH OR ARISING FROM THE FURNISHING, PERFORMANCE, OR +USE OF THIS SOFTWARE. + +So that all may benefit from your experience, please report any problems +or suggestions about this software to the 29K Technical Support Center at +800-29-29-AMD (800-292-9263) in the USA, or 0800-89-1131 in the UK, or +0031-11-1129 in Japan, toll free. The direct dial number is 512-462-4118. + +Advanced Micro Devices, Inc. +29K Support Products +Mail Stop 573 +5900 E. Ben White Blvd. +Austin, TX 78741 +800-292-9263 + +(5) + +(6) + +(7) Sun Microsystems + +Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. + +Developed at SunPro, a Sun Microsystems, Inc. business. +Permission to use, copy, modify, and distribute this +software is freely granted, provided that this notice is preserved. + +(8) Hewlett Packard + +(c) Copyright 1986 HEWLETT-PACKARD COMPANY + +To anyone who acknowledges that this file is provided "AS IS" +without any express or implied warranty: + permission to use, copy, modify, and distribute this file +for any purpose is hereby granted without fee, provided that +the above copyright notice and this notice appears in all +copies, and that the name of Hewlett-Packard Company not be +used in advertising or publicity pertaining to distribution +of the software without specific, written prior permission. +Hewlett-Packard Company makes no representations about the +suitability of this software for any purpose. + +(9) Hans-Peter Nilsson + +Copyright (C) 2001 Hans-Peter Nilsson + +Permission to use, copy, modify, and distribute this software is +freely granted, provided that the above copyright notice, this notice +and the following disclaimer are preserved with no changes. + +THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR +IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +PURPOSE. + +(10) Stephane Carrez (m68hc11-elf/m68hc12-elf targets only) + +Copyright (C) 1999, 2000, 2001, 2002 Stephane Carrez (stcarrez@nerim.fr) + +The authors hereby grant permission to use, copy, modify, distribute, +and license this software and its documentation for any purpose, provided +that existing copyright notices are retained in all copies and that this +notice is included verbatim in any distributions. No written agreement, +license, or royalty fee is required for any of the authorized uses. +Modifications to this software may be copyrighted by their authors +and need not follow the licensing terms described here, provided that +the new terms are clearly indicated on the first page of each file where +they apply. + +(11) Christopher G. Demetriou + +Copyright (c) 2001 Christopher G. Demetriou +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions +are met: +1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. +2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. +3. The name of the author may not be used to endorse or promote products + derived from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR +IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES +OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, +INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF +THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +(12) SuperH, Inc. + +Copyright 2002 SuperH, Inc. All rights reserved + +This software is the property of SuperH, Inc (SuperH) which specifically +grants the user the right to modify, use and distribute this software +provided this notice is not removed or altered. All other rights are +reserved by SuperH. + +SUPERH MAKES NO WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, WITH REGARD TO +THIS SOFTWARE. IN NO EVENT SHALL SUPERH BE LIABLE FOR INDIRECT, SPECIAL, +INCIDENTAL OR CONSEQUENTIAL DAMAGES IN CONNECTION WITH OR ARISING FROM +THE FURNISHING, PERFORMANCE, OR USE OF THIS SOFTWARE. + +So that all may benefit from your experience, please report any problems +or suggestions about this software to the SuperH Support Center via +e-mail at softwaresupport@superh.com . + +SuperH, Inc. +405 River Oaks Parkway +San Jose +CA 95134 +USA + +(13) Royal Institute of Technology + +Copyright (c) 1999 Kungliga Tekniska Högskolan +(Royal Institute of Technology, Stockholm, Sweden). +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions +are met: + +1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + +2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + +3. Neither the name of KTH nor the names of its contributors may be + used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY KTH AND ITS CONTRIBUTORS ``AS IS'' AND ANY +EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL KTH OR ITS CONTRIBUTORS BE +LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR +BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR +OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF +ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +(14) Alexey Zelkin + +Copyright (c) 2000, 2001 Alexey Zelkin +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions +are met: +1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. +2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + +THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +SUCH DAMAGE. + +(15) Andrey A. Chernov + +Copyright (C) 1997 by Andrey A. Chernov, Moscow, Russia. +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions +are met: +1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. +2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + +THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +SUCH DAMAGE. + +(16) FreeBSD + +Copyright (c) 1997-2002 FreeBSD Project. +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions +are met: +1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. +2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + +THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +SUCH DAMAGE. + +(17) S. L. Moshier + +Author: S. L. Moshier. + +Copyright (c) 1984,2000 S.L. Moshier + +Permission to use, copy, modify, and distribute this software for any +purpose without fee is hereby granted, provided that this entire notice +is included in all copies of any software which is or includes a copy +or modification of this software and in all copies of the supporting +documentation for such software. + +THIS SOFTWARE IS BEING PROVIDED "AS IS", WITHOUT ANY EXPRESS OR IMPLIED +WARRANTY. IN PARTICULAR, THE AUTHOR MAKES NO REPRESENTATION +OR WARRANTY OF ANY KIND CONCERNING THE MERCHANTABILITY OF THIS +SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR PURPOSE. + +(18) Citrus Project + +Copyright (c)1999 Citrus Project, +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions +are met: +1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. +2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + +THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +SUCH DAMAGE. + +(19) Todd C. Miller + +Copyright (c) 1998 Todd C. Miller +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions +are met: +1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. +2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. +3. The name of the author may not be used to endorse or promote products + derived from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, +INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY +AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL +THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; +OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR +OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF +ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +(20) DJ Delorie (i386) +Copyright (C) 1991 DJ Delorie +All rights reserved. + +Redistribution, modification, and use in source and binary forms is permitted +provided that the above copyright notice and following paragraph are +duplicated in all such forms. + +This file is distributed WITHOUT ANY WARRANTY; without even the implied +warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + +(21) Free Software Foundation LGPL License (*-linux* targets only) + + Copyright (C) 1990-1999, 2000, 2001 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Mark Kettenis , 1997. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + 02110-1301 USA. + +(22) Xavier Leroy LGPL License (i[3456]86-*-linux* targets only) + +Copyright (C) 1996 Xavier Leroy (Xavier.Leroy@inria.fr) + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU Library General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU Library General Public License for more details. + +(23) Intel (i960) + +Copyright (c) 1993 Intel Corporation + +Intel hereby grants you permission to copy, modify, and distribute this +software and its documentation. Intel grants this permission provided +that the above copyright notice appears in all copies and that both the +copyright notice and this permission notice appear in supporting +documentation. In addition, Intel grants this permission provided that +you prominently mark as "not part of the original" any modifications +made to this software or documentation, and that the name of Intel +Corporation not be used in advertising or publicity pertaining to +distribution of the software or the documentation without specific, +written prior permission. + +Intel Corporation provides this AS IS, WITHOUT ANY WARRANTY, EXPRESS OR +IMPLIED, INCLUDING, WITHOUT LIMITATION, ANY WARRANTY OF MERCHANTABILITY +OR FITNESS FOR A PARTICULAR PURPOSE. Intel makes no guarantee or +representations regarding the use of, or the results of the use of, +the software and documentation in terms of correctness, accuracy, +reliability, currentness, or otherwise; and you rely on the software, +documentation and results solely at your own risk. + +IN NO EVENT SHALL INTEL BE LIABLE FOR ANY LOSS OF USE, LOSS OF BUSINESS, +LOSS OF PROFITS, INDIRECT, INCIDENTAL, SPECIAL OR CONSEQUENTIAL DAMAGES +OF ANY KIND. IN NO EVENT SHALL INTEL'S TOTAL LIABILITY EXCEED THE SUM +PAID TO INTEL FOR THE PRODUCT LICENSED HEREUNDER. + +(24) Hewlett-Packard (hppa targets only) + +(c) Copyright 1986 HEWLETT-PACKARD COMPANY + +To anyone who acknowledges that this file is provided "AS IS" +without any express or implied warranty: + permission to use, copy, modify, and distribute this file +for any purpose is hereby granted without fee, provided that +the above copyright notice and this notice appears in all +copies, and that the name of Hewlett-Packard Company not be +used in advertising or publicity pertaining to distribution +of the software without specific, written prior permission. +Hewlett-Packard Company makes no representations about the +suitability of this software for any purpose. + +(25) Henry Spencer (only *-linux targets) + +Copyright 1992, 1993, 1994 Henry Spencer. All rights reserved. +This software is not subject to any license of the American Telephone +and Telegraph Company or of the Regents of the University of California. + +Permission is granted to anyone to use this software for any purpose on +any computer system, and to alter it and redistribute it, subject +to the following restrictions: + +1. The author is not responsible for the consequences of use of this + software, no matter how awful, even if they arise from flaws in it. + +2. The origin of this software must not be misrepresented, either by + explicit claim or by omission. Since few users ever read sources, + credits must appear in the documentation. + +3. Altered versions must be plainly marked as such, and must not be + misrepresented as being the original software. Since few users + ever read sources, credits must appear in the documentation. + +4. This notice may not be removed or altered. + +(26) Mike Barcroft + +Copyright (c) 2001 Mike Barcroft +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions +are met: +1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. +2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + +THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +SUCH DAMAGE. + +(27) Konstantin Chuguev (--enable-newlib-iconv) + +Copyright (c) 1999, 2000 + Konstantin Chuguev. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions +are met: +1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. +2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + +THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +SUCH DAMAGE. + + iconv (Charset Conversion Library) v2.0 + +(28) Artem Bityuckiy (--enable-newlib-iconv) + +Copyright (c) 2003, Artem B. Bityuckiy, SoftMine Corporation. +Rights transferred to Franklin Electronic Publishers. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions +are met: +1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. +2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + +THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +SUCH DAMAGE. + +(29) IBM, Sony, Toshiba (only spu-* targets) + + (C) Copyright 2001,2006, + International Business Machines Corporation, + Sony Computer Entertainment, Incorporated, + Toshiba Corporation, + + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the names of the copyright holders nor the names of their + contributors may be used to endorse or promote products derived from this + software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + +(30) - Alex Tatmanjants (targets using libc/posix) + + Copyright (c) 1995 Alex Tatmanjants + at Electronni Visti IA, Kiev, Ukraine. + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND + ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + SUCH DAMAGE. + +(31) - M. Warner Losh (targets using libc/posix) + + Copyright (c) 1998, M. Warner Losh + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + SUCH DAMAGE. + +(32) - Andrey A. Chernov (targets using libc/posix) + + Copyright (C) 1996 by Andrey A. Chernov, Moscow, Russia. + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND + ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + SUCH DAMAGE. + +(33) - Daniel Eischen (targets using libc/posix) + + Copyright (c) 2001 Daniel Eischen . + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + SUCH DAMAGE. + + +(34) - Jon Beniston (only lm32-* targets) + + Contributed by Jon Beniston + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + SUCH DAMAGE. + + +(35) - ARM Ltd (arm and thumb variant targets only) + + Copyright (c) 2009 ARM Ltd + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + 3. The name of the company may not be used to endorse or promote + products derived from this software without specific prior written + permission. + + THIS SOFTWARE IS PROVIDED BY ARM LTD ``AS IS'' AND ANY EXPRESS OR IMPLIED + WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + IN NO EVENT SHALL ARM LTD BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED + TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +(36) - Xilinx, Inc. (microblaze-* and powerpc-* targets) + +Copyright (c) 2004, 2009 Xilinx, Inc. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + +1. Redistributions source code must retain the above copyright notice, +this list of conditions and the following disclaimer. + +2. Redistributions in binary form must reproduce the above copyright +notice, this list of conditions and the following disclaimer in the +documentation and/or other materials provided with the distribution. + +3. Neither the name of Xilinx nor the names of its contributors may be +used to endorse or promote products derived from this software without +specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER AND CONTRIBUTORS "AS +IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED +TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A +PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED +TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + +(37) Texas Instruments Incorporated (tic6x-*, *-tirtos targets) + +Copyright (c) 1996-2010,2014 Texas Instruments Incorporated +http://www.ti.com/ + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + + Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + + Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the + distribution. + + Neither the name of Texas Instruments Incorporated nor the names + of its contributors may be used to endorse or promote products + derived from this software without specific prior written + permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +(38) National Semiconductor (cr16-* and crx-* targets) + +Copyright (c) 2004 National Semiconductor Corporation + +The authors hereby grant permission to use, copy, modify, distribute, +and license this software and its documentation for any purpose, provided +that existing copyright notices are retained in all copies and that this +notice is included verbatim in any distributions. No written agreement, +license, or royalty fee is required for any of the authorized uses. +Modifications to this software may be copyrighted by their authors +and need not follow the licensing terms described here, provided that +the new terms are clearly indicated on the first page of each file where +they apply. + +(39) - Adapteva, Inc. (epiphany-* targets) + +Copyright (c) 2011, Adapteva, Inc. +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + * Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + * Neither the name of Adapteva nor the names of its contributors may be used + to endorse or promote products derived from this software without specific + prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +(40) - Altera Corportion (nios2-* targets) + +Copyright (c) 2003 Altera Corporation +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions +are met: + + o Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + o Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + o Neither the name of Altera Corporation nor the names of its + contributors may be used to endorse or promote products derived from + this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY ALTERA CORPORATION, THE COPYRIGHT HOLDER, +AND ITS CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, +INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY +AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL +THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS +OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR +TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE +USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +(41) Ed Schouten - Free BSD + +Copyright (c) 2008 Ed Schouten +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions +are met: +1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. +2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + +THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +SUCH DAMAGE. + diff --git a/components/newlib/Makefile b/components/newlib/Makefile new file mode 100644 index 0000000000..b9913d241e --- /dev/null +++ b/components/newlib/Makefile @@ -0,0 +1,8 @@ +COMPONENT_ADD_LDFLAGS := $(abspath lib/libc.a) $(abspath lib/libm.a) + + +define COMPONENT_BUILDRECIPE + #Nothing to do; this does not generate a library. +endef + +include $(SDK_PATH)/make/component.mk diff --git a/components/newlib/Makefile.old b/components/newlib/Makefile.old new file mode 100644 index 0000000000..a8fc8efd90 --- /dev/null +++ b/components/newlib/Makefile.old @@ -0,0 +1,47 @@ + + +TARGET_DIR=$(PWD)/.build +ROM_ELF_FILE ?= /tmp/eagle.pro.rom.out + +all: newlib check_common_syms + +newlib_xtensa-2.2.0: + git submodule update --init + +newlib: newlib_xtensa-2.2.0 + +newlib: + cd newlib_xtensa-2.2.0 && \ + ./configure \ + --with-newlib \ + --enable-multilib \ + --disable-newlib-io-c99-formats \ + --disable-newlib-supplied-syscalls \ + --enable-newlib-nano-formatted-io \ + --enable-newlib-reent-small \ + --enable-target-optspace \ + --program-transform-name="s&^&xtensa-esp108-elf-&" \ + --disable-option-checking \ + --with-target-subdir=xtensa-esp108-elf \ + --target=xtensa-esp108-elf \ + --prefix=$(TARGET_DIR) \ + && CROSS_CFLAGS="-DSIGNAL_PROVIDED -DABORT_PROVIDED -DMALLOC_PROVIDED" make all install || true + cp -r $(TARGET_DIR)/xtensa-esp108-elf/{include,lib} ./ + cp lib/libc.a lib/libc_rom.a + xtensa-esp108-elf-ar d lib/libc_rom.a lib_a-nano-vfprintf_float.o + xtensa-esp108-elf-ar d lib/libc_rom.a lib_a-nano-vfscanf_float.o + while read obj; do xtensa-esp108-elf-ar d lib/libc.a $$obj; done libc.syms + @# get symbols in ROM + @xtensa-esp108-elf-nm $(ROM_ELF_FILE) | grep -v -E '\W+U\W+' | awk '{print $$3}' | sort >rom.syms + @# check that there are no common symbols + @test $$(comm -12 rom.syms libc.syms | tee common.syms | wc -l) -eq 0 + +.PHONY: all clean newlib diff --git a/components/newlib/include/_ansi.h b/components/newlib/include/_ansi.h new file mode 100644 index 0000000000..5fb9907009 --- /dev/null +++ b/components/newlib/include/_ansi.h @@ -0,0 +1,140 @@ +/* Provide support for both ANSI and non-ANSI environments. */ + +/* Some ANSI environments are "broken" in the sense that __STDC__ cannot be + relied upon to have it's intended meaning. Therefore we must use our own + concoction: _HAVE_STDC. Always use _HAVE_STDC instead of __STDC__ in newlib + sources! + + To get a strict ANSI C environment, define macro __STRICT_ANSI__. This will + "comment out" the non-ANSI parts of the ANSI header files (non-ANSI header + files aren't affected). */ + +#ifndef _ANSIDECL_H_ +#define _ANSIDECL_H_ + +#include +#include + +/* First try to figure out whether we really are in an ANSI C environment. */ +/* FIXME: This probably needs some work. Perhaps sys/config.h can be + prevailed upon to give us a clue. */ + +#ifdef __STDC__ +#define _HAVE_STDC +#endif + +/* ISO C++. */ + +#ifdef __cplusplus +#if !(defined(_BEGIN_STD_C) && defined(_END_STD_C)) +#ifdef _HAVE_STD_CXX +#define _BEGIN_STD_C namespace std { extern "C" { +#define _END_STD_C } } +#else +#define _BEGIN_STD_C extern "C" { +#define _END_STD_C } +#endif +#if __GNUC_PREREQ (3, 3) +#define _NOTHROW __attribute__ ((__nothrow__)) +#else +#define _NOTHROW throw() +#endif +#endif +#else +#define _BEGIN_STD_C +#define _END_STD_C +#define _NOTHROW +#endif + +#ifdef _HAVE_STDC +#define _PTR void * +#define _AND , +#define _NOARGS void +#define _CONST const +#define _VOLATILE volatile +#define _SIGNED signed +#define _DOTS , ... +#define _VOID void +#ifdef __CYGWIN__ +#define _EXFUN_NOTHROW(name, proto) __cdecl name proto _NOTHROW +#define _EXFUN(name, proto) __cdecl name proto +#define _EXPARM(name, proto) (* __cdecl name) proto +#define _EXFNPTR(name, proto) (__cdecl * name) proto +#else +#define _EXFUN_NOTHROW(name, proto) name proto _NOTHROW +#define _EXFUN(name, proto) name proto +#define _EXPARM(name, proto) (* name) proto +#define _EXFNPTR(name, proto) (* name) proto +#endif +#define _DEFUN(name, arglist, args) name(args) +#define _DEFUN_VOID(name) name(_NOARGS) +#define _CAST_VOID (void) +#ifndef _LONG_DOUBLE +#define _LONG_DOUBLE long double +#endif +#ifndef _PARAMS +#define _PARAMS(paramlist) paramlist +#endif +#else +#define _PTR char * +#define _AND ; +#define _NOARGS +#define _CONST +#define _VOLATILE +#define _SIGNED +#define _DOTS +#define _VOID void +#define _EXFUN(name, proto) name() +#define _EXFUN_NOTHROW(name, proto) name() +#define _DEFUN(name, arglist, args) name arglist args; +#define _DEFUN_VOID(name) name() +#define _CAST_VOID +#define _LONG_DOUBLE double +#ifndef _PARAMS +#define _PARAMS(paramlist) () +#endif +#endif + +/* Support gcc's __attribute__ facility. */ + +#ifdef __GNUC__ +#define _ATTRIBUTE(attrs) __attribute__ (attrs) +#else +#define _ATTRIBUTE(attrs) +#endif + +/* The traditional meaning of 'extern inline' for GCC is not + to emit the function body unless the address is explicitly + taken. However this behaviour is changing to match the C99 + standard, which uses 'extern inline' to indicate that the + function body *must* be emitted. Likewise, a function declared + without either 'extern' or 'static' defaults to extern linkage + (C99 6.2.2p5), and the compiler may choose whether to use the + inline version or call the extern linkage version (6.7.4p6). + If we are using GCC, but do not have the new behaviour, we need + to use extern inline; if we are using a new GCC with the + C99-compatible behaviour, or a non-GCC compiler (which we will + have to hope is C99, since there is no other way to achieve the + effect of omitting the function if it isn't referenced) we use + 'static inline', which c99 defines to mean more-or-less the same + as the Gnu C 'extern inline'. */ +#if defined(__GNUC__) && !defined(__GNUC_STDC_INLINE__) +/* We're using GCC, but without the new C99-compatible behaviour. */ +#define _ELIDABLE_INLINE extern __inline__ _ATTRIBUTE ((__always_inline__)) +#else +/* We're using GCC in C99 mode, or an unknown compiler which + we just have to hope obeys the C99 semantics of inline. */ +#define _ELIDABLE_INLINE static __inline__ +#endif + +#if __GNUC_PREREQ (3, 1) +#define _NOINLINE __attribute__ ((__noinline__)) +#define _NOINLINE_STATIC _NOINLINE static +#else +/* On non-GNU compilers and GCC prior to version 3.1 the compiler can't be + trusted not to inline if it is static. */ +#define _NOINLINE +#define _NOINLINE_STATIC +#endif + +#endif /* _ANSIDECL_H_ */ diff --git a/components/newlib/include/_syslist.h b/components/newlib/include/_syslist.h new file mode 100644 index 0000000000..271644efa9 --- /dev/null +++ b/components/newlib/include/_syslist.h @@ -0,0 +1,40 @@ +/* internal use only -- mapping of "system calls" for libraries that lose + and only provide C names, so that we end up in violation of ANSI */ +#ifndef __SYSLIST_H +#define __SYSLIST_H + +#ifdef MISSING_SYSCALL_NAMES +#define _close close +#define _execve execve +#define _fcntl fcntl +#define _fork fork +#define _fstat fstat +#define _getpid getpid +#define _gettimeofday gettimeofday +#define _isatty isatty +#define _kill kill +#define _link link +#define _lseek lseek +#define _mkdir mkdir +#define _open open +#define _read read +#define _sbrk sbrk +#define _stat stat +#define _times times +#define _unlink unlink +#define _wait wait +#define _write write +#endif /* MISSING_SYSCALL_NAMES */ + +#if defined MISSING_SYSCALL_NAMES || !defined HAVE_OPENDIR +/* If the system call interface is missing opendir, readdir, and + closedir, there is an implementation of these functions in + libc/posix that is implemented using open, getdents, and close. + Note, these functions are currently not in the libc/syscalls + directory. */ +#define _opendir opendir +#define _readdir readdir +#define _closedir closedir +#endif /* MISSING_SYSCALL_NAMES || !HAVE_OPENDIR */ + +#endif /* !__SYSLIST_H_ */ diff --git a/components/newlib/include/alloca.h b/components/newlib/include/alloca.h new file mode 100644 index 0000000000..2ea0fd9b37 --- /dev/null +++ b/components/newlib/include/alloca.h @@ -0,0 +1,21 @@ +/* libc/include/alloca.h - Allocate memory on stack */ + +/* Written 2000 by Werner Almesberger */ +/* Rearranged for general inclusion by stdlib.h. + 2001, Corinna Vinschen */ + +#ifndef _NEWLIB_ALLOCA_H +#define _NEWLIB_ALLOCA_H + +#include "_ansi.h" +#include + +#undef alloca + +#ifdef __GNUC__ +#define alloca(size) __builtin_alloca(size) +#else +void * _EXFUN(alloca,(size_t)); +#endif + +#endif diff --git a/components/newlib/include/ar.h b/components/newlib/include/ar.h new file mode 100644 index 0000000000..ac2e4ca920 --- /dev/null +++ b/components/newlib/include/ar.h @@ -0,0 +1,69 @@ +/* $NetBSD: ar.h,v 1.4 1994/10/26 00:55:43 cgd Exp $ */ + +/*- + * Copyright (c) 1991, 1993 + * The Regents of the University of California. All rights reserved. + * (c) UNIX System Laboratories, Inc. + * All or some portions of this file are derived from material licensed + * to the University of California by American Telephone and Telegraph + * Co. or Unix System Laboratories, Inc. and are reproduced herein with + * the permission of UNIX System Laboratories, Inc. + * + * This code is derived from software contributed to Berkeley by + * Hugh Smith at The University of Guelph. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)ar.h 8.2 (Berkeley) 1/21/94 + */ + +#ifndef _AR_H_ +#define _AR_H_ + +/* Pre-4BSD archives had these magic numbers in them. */ +#define OARMAG1 0177555 +#define OARMAG2 0177545 + +#define ARMAG "!\n" /* ar "magic number" */ +#define SARMAG 8 /* strlen(ARMAG); */ + +#define AR_EFMT1 "#1/" /* extended format #1 */ + +struct ar_hdr { + char ar_name[16]; /* name */ + char ar_date[12]; /* modification time */ + char ar_uid[6]; /* user id */ + char ar_gid[6]; /* group id */ + char ar_mode[8]; /* octal file permissions */ + char ar_size[10]; /* size in bytes */ +#define ARFMAG "`\n" + char ar_fmag[2]; /* consistency check */ +}; + +#endif /* !_AR_H_ */ diff --git a/components/newlib/include/argz.h b/components/newlib/include/argz.h new file mode 100644 index 0000000000..02c9adbf3f --- /dev/null +++ b/components/newlib/include/argz.h @@ -0,0 +1,33 @@ +/* Copyright (C) 2002 by Red Hat, Incorporated. All rights reserved. + * + * Permission to use, copy, modify, and distribute this software + * is freely granted, provided that this notice is preserved. + */ + +#ifndef _ARGZ_H_ +#define _ARGZ_H_ + +#include +#include + +#include "_ansi.h" + +_BEGIN_STD_C + +/* The newlib implementation of these functions assumes that sizeof(char) == 1. */ +error_t argz_create (char *const argv[], char **argz, size_t *argz_len); +error_t argz_create_sep (const char *string, int sep, char **argz, size_t *argz_len); +size_t argz_count (const char *argz, size_t argz_len); +void argz_extract (char *argz, size_t argz_len, char **argv); +void argz_stringify (char *argz, size_t argz_len, int sep); +error_t argz_add (char **argz, size_t *argz_len, const char *str); +error_t argz_add_sep (char **argz, size_t *argz_len, const char *str, int sep); +error_t argz_append (char **argz, size_t *argz_len, const char *buf, size_t buf_len); +error_t argz_delete (char **argz, size_t *argz_len, char *entry); +error_t argz_insert (char **argz, size_t *argz_len, char *before, const char *entry); +char * argz_next (char *argz, size_t argz_len, const char *entry); +error_t argz_replace (char **argz, size_t *argz_len, const char *str, const char *with, unsigned *replace_count); + +_END_STD_C + +#endif /* _ARGZ_H_ */ diff --git a/components/newlib/include/assert.h b/components/newlib/include/assert.h new file mode 100644 index 0000000000..91bb040cab --- /dev/null +++ b/components/newlib/include/assert.h @@ -0,0 +1,50 @@ +/* + assert.h +*/ + +#ifdef __cplusplus +extern "C" { +#endif + +#include "_ansi.h" + +#undef assert + +#ifdef NDEBUG /* required by ANSI standard */ +# define assert(__e) ((void)0) +#else +# define assert(__e) ((__e) ? (void)0 : __assert_func (__FILE__, __LINE__, \ + __ASSERT_FUNC, #__e)) + +# ifndef __ASSERT_FUNC + /* Use g++'s demangled names in C++. */ +# if defined __cplusplus && defined __GNUC__ +# define __ASSERT_FUNC __PRETTY_FUNCTION__ + + /* C99 requires the use of __func__. */ +# elif __STDC_VERSION__ >= 199901L +# define __ASSERT_FUNC __func__ + + /* Older versions of gcc don't have __func__ but can use __FUNCTION__. */ +# elif __GNUC__ >= 2 +# define __ASSERT_FUNC __FUNCTION__ + + /* failed to detect __func__ support. */ +# else +# define __ASSERT_FUNC ((char *) 0) +# endif +# endif /* !__ASSERT_FUNC */ +#endif /* !NDEBUG */ + +void _EXFUN(__assert, (const char *, int, const char *) + _ATTRIBUTE ((__noreturn__))); +void _EXFUN(__assert_func, (const char *, int, const char *, const char *) + _ATTRIBUTE ((__noreturn__))); + +#if __STDC_VERSION__ >= 201112L && !defined __cplusplus +# define static_assert _Static_assert +#endif + +#ifdef __cplusplus +} +#endif diff --git a/components/newlib/include/complex.h b/components/newlib/include/complex.h new file mode 100644 index 0000000000..969b20e5f9 --- /dev/null +++ b/components/newlib/include/complex.h @@ -0,0 +1,124 @@ +/* $NetBSD: complex.h,v 1.3 2010/09/15 16:11:30 christos Exp $ */ + +/* + * Written by Matthias Drochner. + * Public domain. + */ + +#ifndef _COMPLEX_H +#define _COMPLEX_H + +#define complex _Complex +#define _Complex_I 1.0fi +#define I _Complex_I + +#include + +__BEGIN_DECLS + +/* 7.3.5 Trigonometric functions */ +/* 7.3.5.1 The cacos functions */ +double complex cacos(double complex); +float complex cacosf(float complex); + +/* 7.3.5.2 The casin functions */ +double complex casin(double complex); +float complex casinf(float complex); + +/* 7.3.5.1 The catan functions */ +double complex catan(double complex); +float complex catanf(float complex); + +/* 7.3.5.1 The ccos functions */ +double complex ccos(double complex); +float complex ccosf(float complex); + +/* 7.3.5.1 The csin functions */ +double complex csin(double complex); +float complex csinf(float complex); + +/* 7.3.5.1 The ctan functions */ +double complex ctan(double complex); +float complex ctanf(float complex); + +/* 7.3.6 Hyperbolic functions */ +/* 7.3.6.1 The cacosh functions */ +double complex cacosh(double complex); +float complex cacoshf(float complex); + +/* 7.3.6.2 The casinh functions */ +double complex casinh(double complex); +float complex casinhf(float complex); + +/* 7.3.6.3 The catanh functions */ +double complex catanh(double complex); +float complex catanhf(float complex); + +/* 7.3.6.4 The ccosh functions */ +double complex ccosh(double complex); +float complex ccoshf(float complex); + +/* 7.3.6.5 The csinh functions */ +double complex csinh(double complex); +float complex csinhf(float complex); + +/* 7.3.6.6 The ctanh functions */ +double complex ctanh(double complex); +float complex ctanhf(float complex); + +/* 7.3.7 Exponential and logarithmic functions */ +/* 7.3.7.1 The cexp functions */ +double complex cexp(double complex); +float complex cexpf(float complex); + +/* 7.3.7.2 The clog functions */ +double complex clog(double complex); +float complex clogf(float complex); + +/* 7.3.8 Power and absolute-value functions */ +/* 7.3.8.1 The cabs functions */ +/*#ifndef __LIBM0_SOURCE__ */ +/* avoid conflict with historical cabs(struct complex) */ +/* double cabs(double complex) __RENAME(__c99_cabs); + float cabsf(float complex) __RENAME(__c99_cabsf); + #endif +*/ +double cabs(double complex) ; +float cabsf(float complex) ; + +/* 7.3.8.2 The cpow functions */ +double complex cpow(double complex, double complex); +float complex cpowf(float complex, float complex); + +/* 7.3.8.3 The csqrt functions */ +double complex csqrt(double complex); +float complex csqrtf(float complex); + +/* 7.3.9 Manipulation functions */ +/* 7.3.9.1 The carg functions */ +double carg(double complex); +float cargf(float complex); + +/* 7.3.9.2 The cimag functions */ +double cimag(double complex); +float cimagf(float complex); +/*long double cimagl(long double complex); */ + +/* 7.3.9.3 The conj functions */ +double complex conj(double complex); +float complex conjf(float complex); +/*long double complex conjl(long double complex); */ + +/* 7.3.9.4 The cproj functions */ +double complex cproj(double complex); +float complex cprojf(float complex); +/*long double complex cprojl(long double complex); */ + +/* 7.3.9.5 The creal functions */ +double creal(double complex); +float crealf(float complex); +/*long double creall(long double complex); */ + +__END_DECLS + +#endif /* ! _COMPLEX_H */ diff --git a/components/newlib/include/config.h b/components/newlib/include/config.h new file mode 100644 index 0000000000..69d49adf95 --- /dev/null +++ b/components/newlib/include/config.h @@ -0,0 +1,28 @@ +#ifndef __SYS_CONFIG_H__ +#define __SYS_CONFIG_H__ + +#include /* floating point macros */ +#include /* POSIX defs */ + +#ifndef __EXPORT +#define __EXPORT +#endif + +#ifndef __IMPORT +#define __IMPORT +#endif + +/* Define return type of read/write routines. In POSIX, the return type + for read()/write() is "ssize_t" but legacy newlib code has been using + "int" for some time. If not specified, "int" is defaulted. */ +#ifndef _READ_WRITE_RETURN_TYPE +#define _READ_WRITE_RETURN_TYPE int +#endif +/* Define `count' parameter of read/write routines. In POSIX, the `count' + parameter is "size_t" but legacy newlib code has been using "int" for some + time. If not specified, "int" is defaulted. */ +#ifndef _READ_WRITE_BUFSIZE_TYPE +#define _READ_WRITE_BUFSIZE_TYPE int +#endif + +#endif /* __SYS_CONFIG_H__ */ diff --git a/components/newlib/include/ctype.h b/components/newlib/include/ctype.h new file mode 100644 index 0000000000..1eb3f787f8 --- /dev/null +++ b/components/newlib/include/ctype.h @@ -0,0 +1,113 @@ +#ifndef _CTYPE_H_ +#define _CTYPE_H_ + +#include "_ansi.h" + +_BEGIN_STD_C + +int _EXFUN(isalnum, (int __c)); +int _EXFUN(isalpha, (int __c)); +int _EXFUN(iscntrl, (int __c)); +int _EXFUN(isdigit, (int __c)); +int _EXFUN(isgraph, (int __c)); +int _EXFUN(islower, (int __c)); +int _EXFUN(isprint, (int __c)); +int _EXFUN(ispunct, (int __c)); +int _EXFUN(isspace, (int __c)); +int _EXFUN(isupper, (int __c)); +int _EXFUN(isxdigit,(int __c)); +int _EXFUN(tolower, (int __c)); +int _EXFUN(toupper, (int __c)); + +#if !defined(__STRICT_ANSI__) || defined(__cplusplus) || __STDC_VERSION__ >= 199901L +int _EXFUN(isblank, (int __c)); +#endif + +#ifndef __STRICT_ANSI__ +int _EXFUN(isascii, (int __c)); +int _EXFUN(toascii, (int __c)); +#define _tolower(__c) ((unsigned char)(__c) - 'A' + 'a') +#define _toupper(__c) ((unsigned char)(__c) - 'a' + 'A') +#endif + +#define _U 01 +#define _L 02 +#define _N 04 +#define _S 010 +#define _P 020 +#define _C 040 +#define _X 0100 +#define _B 0200 + +#ifndef _MB_CAPABLE +_CONST +#endif +extern __IMPORT char * _CONST __ctype_ptr__; + +#ifndef __cplusplus +/* These macros are intentionally written in a manner that will trigger + a gcc -Wall warning if the user mistakenly passes a 'char' instead + of an int containing an 'unsigned char'. Note that the sizeof will + always be 1, which is what we want for mapping EOF to __ctype_ptr__[0]; + the use of a raw index inside the sizeof triggers the gcc warning if + __c was of type char, and sizeof masks side effects of the extra __c. + Meanwhile, the real index to __ctype_ptr__+1 must be cast to int, + since isalpha(0x100000001LL) must equal isalpha(1), rather than being + an out-of-bounds reference on a 64-bit machine. */ +#define __ctype_lookup(__c) ((__ctype_ptr__+sizeof(""[__c]))[(int)(__c)]) + +#define isalpha(__c) (__ctype_lookup(__c)&(_U|_L)) +#define isupper(__c) ((__ctype_lookup(__c)&(_U|_L))==_U) +#define islower(__c) ((__ctype_lookup(__c)&(_U|_L))==_L) +#define isdigit(__c) (__ctype_lookup(__c)&_N) +#define isxdigit(__c) (__ctype_lookup(__c)&(_X|_N)) +#define isspace(__c) (__ctype_lookup(__c)&_S) +#define ispunct(__c) (__ctype_lookup(__c)&_P) +#define isalnum(__c) (__ctype_lookup(__c)&(_U|_L|_N)) +#define isprint(__c) (__ctype_lookup(__c)&(_P|_U|_L|_N|_B)) +#define isgraph(__c) (__ctype_lookup(__c)&(_P|_U|_L|_N)) +#define iscntrl(__c) (__ctype_lookup(__c)&_C) + +#if defined(__GNUC__) && \ + (!defined(__STRICT_ANSI__) || __STDC_VERSION__ >= 199901L) +#define isblank(__c) \ + __extension__ ({ __typeof__ (__c) __x = (__c); \ + (__ctype_lookup(__x)&_B) || (int) (__x) == '\t';}) +#endif + + +/* Non-gcc versions will get the library versions, and will be + slightly slower. These macros are not NLS-aware so they are + disabled if the system supports the extended character sets. */ +# if defined(__GNUC__) +# if !defined (_MB_EXTENDED_CHARSETS_ISO) && !defined (_MB_EXTENDED_CHARSETS_WINDOWS) +# define toupper(__c) \ + __extension__ ({ __typeof__ (__c) __x = (__c); \ + islower (__x) ? (int) __x - 'a' + 'A' : (int) __x;}) +# define tolower(__c) \ + __extension__ ({ __typeof__ (__c) __x = (__c); \ + isupper (__x) ? (int) __x - 'A' + 'a' : (int) __x;}) +# else /* _MB_EXTENDED_CHARSETS* */ +/* Allow a gcc warning if the user passed 'char', but defer to the + function. */ +# define toupper(__c) \ + __extension__ ({ __typeof__ (__c) __x = (__c); \ + (void) __ctype_ptr__[__x]; (toupper) (__x);}) +# define tolower(__c) \ + __extension__ ({ __typeof__ (__c) __x = (__c); \ + (void) __ctype_ptr__[__x]; (tolower) (__x);}) +# endif /* _MB_EXTENDED_CHARSETS* */ +# endif /* __GNUC__ */ +#endif /* !__cplusplus */ + +#ifndef __STRICT_ANSI__ +#define isascii(__c) ((unsigned)(__c)<=0177) +#define toascii(__c) ((__c)&0177) +#endif + +/* For C++ backward-compatibility only. */ +extern __IMPORT _CONST char _ctype_[]; + +_END_STD_C + +#endif /* _CTYPE_H_ */ diff --git a/components/newlib/include/dirent.h b/components/newlib/include/dirent.h new file mode 100644 index 0000000000..6fefc03cbd --- /dev/null +++ b/components/newlib/include/dirent.h @@ -0,0 +1,15 @@ +#ifndef _DIRENT_H_ +#define _DIRENT_H_ +#ifdef __cplusplus +extern "C" { +#endif +#include + +#if !defined(MAXNAMLEN) && !defined(_POSIX_SOURCE) +#define MAXNAMLEN 1024 +#endif + +#ifdef __cplusplus +} +#endif +#endif /*_DIRENT_H_*/ diff --git a/components/newlib/include/envlock.h b/components/newlib/include/envlock.h new file mode 100644 index 0000000000..9bb6a813ea --- /dev/null +++ b/components/newlib/include/envlock.h @@ -0,0 +1,15 @@ +/* envlock.h -- header file for env routines. */ + +#ifndef _INCLUDE_ENVLOCK_H_ +#define _INCLUDE_ENVLOCK_H_ + +#include <_ansi.h> +#include + +#define ENV_LOCK __env_lock(reent_ptr) +#define ENV_UNLOCK __env_unlock(reent_ptr) + +void _EXFUN(__env_lock,(struct _reent *reent)); +void _EXFUN(__env_unlock,(struct _reent *reent)); + +#endif /* _INCLUDE_ENVLOCK_H_ */ diff --git a/components/newlib/include/envz.h b/components/newlib/include/envz.h new file mode 100644 index 0000000000..e6a31c31d6 --- /dev/null +++ b/components/newlib/include/envz.h @@ -0,0 +1,16 @@ +/* Copyright (C) 2002 by Red Hat, Incorporated. All rights reserved. + * + * Permission to use, copy, modify, and distribute this software + * is freely granted, provided that this notice is preserved. + */ + +#include +#include + +/* The newlib implementation of these functions assumes that sizeof(char) == 1. */ +char * envz_entry (const char *envz, size_t envz_len, const char *name); +char * envz_get (const char *envz, size_t envz_len, const char *name); +error_t envz_add (char **envz, size_t *envz_len, const char *name, const char *value); +error_t envz_merge (char **envz, size_t *envz_len, const char *envz2, size_t envz2_len, int override); +void envz_remove(char **envz, size_t *envz_len, const char *name); +void envz_strip (char **envz, size_t *envz_len); diff --git a/components/newlib/include/errno.h b/components/newlib/include/errno.h new file mode 100644 index 0000000000..7cc2ca86f8 --- /dev/null +++ b/components/newlib/include/errno.h @@ -0,0 +1,11 @@ +#ifndef __ERRNO_H__ +#define __ERRNO_H__ + +#ifndef __error_t_defined +typedef int error_t; +#define __error_t_defined 1 +#endif + +#include + +#endif /* !__ERRNO_H__ */ diff --git a/components/newlib/include/fastmath.h b/components/newlib/include/fastmath.h new file mode 100644 index 0000000000..95eea5f342 --- /dev/null +++ b/components/newlib/include/fastmath.h @@ -0,0 +1,13 @@ +#ifndef _FASTMATH_H_ +#ifdef __cplusplus +extern "C" { +#endif +#define _FASTMATH_H_ + +#include +#include + +#ifdef __cplusplus +} +#endif +#endif /* _FASTMATH_H_ */ diff --git a/components/newlib/include/fcntl.h b/components/newlib/include/fcntl.h new file mode 100644 index 0000000000..86a9167757 --- /dev/null +++ b/components/newlib/include/fcntl.h @@ -0,0 +1 @@ +#include diff --git a/components/newlib/include/fenv.h b/components/newlib/include/fenv.h new file mode 100644 index 0000000000..2fa76f758d --- /dev/null +++ b/components/newlib/include/fenv.h @@ -0,0 +1,88 @@ +/* Copyright (c) 2011 Tensilica Inc. ALL RIGHTS RESERVED. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the following + disclaimer in the documentation and/or other materials provided + with the distribution. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL + TENSILICA INCORPORATED BE LIABLE FOR ANY DIRECT, INDIRECT, + INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + OF THE POSSIBILITY OF SUCH DAMAGE. */ + + +#ifndef _FENV_H +#define _FENV_H + +#ifdef __cplusplus +extern "C" { +#endif + +typedef unsigned long fenv_t; +typedef unsigned long fexcept_t; + +#define FE_DIVBYZERO 0x08 +#define FE_INEXACT 0x01 +#define FE_INVALID 0x10 +#define FE_OVERFLOW 0x04 +#define FE_UNDERFLOW 0x02 + +#define FE_ALL_EXCEPT \ + (FE_DIVBYZERO | \ + FE_INEXACT | \ + FE_INVALID | \ + FE_OVERFLOW | \ + FE_UNDERFLOW) + +#define FE_DOWNWARD 0x3 +#define FE_TONEAREST 0x0 +#define FE_TOWARDZERO 0x1 +#define FE_UPWARD 0x2 + +#define FE_DFL_ENV ((const fenv_t *) 0) + +int feclearexcept(int); +int fegetexceptflag(fexcept_t *, int); +int feraiseexcept(int); +int fesetexceptflag(const fexcept_t *, int); +int fetestexcept(int); +int fegetround(void); +int fesetround(int); +int fegetenv(fenv_t *); +int feholdexcept(fenv_t *); +int fesetenv(const fenv_t *); +int feupdateenv(const fenv_t *); + +/* glibc extensions */ +int feenableexcept(int excepts); +int fedisableexcept(int excepts); +int fegetexcept(void); + +#define _FE_EXCEPTION_FLAGS_OFFSET 7 +#define _FE_EXCEPTION_FLAG_MASK (FE_ALL_EXCEPT << _FE_EXCEPTION_FLAGS_OFFSET) +#define _FE_EXCEPTION_ENABLE_OFFSET 2 +#define _FE_EXCEPTION_ENABLE_MASK (FE_ALL_EXCEPT << _FE_EXCEPTION_ENABLE_OFFSET) +#define _FE_ROUND_MODE_OFFSET 0 +#define _FE_ROUND_MODE_MASK (0x3 << _FE_ROUND_MODE_OFFSET) +#define _FE_FLOATING_ENV_MASK (_FE_EXCEPTION_FLAG_MASK | _FE_EXCEPTION_ENABLE_MASK | _FE_ROUND_MODE_MASK) + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/components/newlib/include/fnmatch.h b/components/newlib/include/fnmatch.h new file mode 100644 index 0000000000..06311fc4b1 --- /dev/null +++ b/components/newlib/include/fnmatch.h @@ -0,0 +1,55 @@ +/*- + * Copyright (c) 1992, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $FreeBSD: src/include/fnmatch.h,v 1.10 2002/03/23 17:24:53 imp Exp $ + * @(#)fnmatch.h 8.1 (Berkeley) 6/2/93 + */ + +#ifndef _FNMATCH_H_ +#define _FNMATCH_H_ + +#define FNM_NOMATCH 1 /* Match failed. */ + +#define FNM_NOESCAPE 0x01 /* Disable backslash escaping. */ +#define FNM_PATHNAME 0x02 /* Slash must be matched by slash. */ +#define FNM_PERIOD 0x04 /* Period must be matched by period. */ + +#if defined(_GNU_SOURCE) || !defined(_ANSI_SOURCE) && !defined(_POSIX_SOURCE) +#define FNM_LEADING_DIR 0x08 /* Ignore / after Imatch. */ +#define FNM_CASEFOLD 0x10 /* Case insensitive search. */ +#define FNM_IGNORECASE FNM_CASEFOLD +#define FNM_FILE_NAME FNM_PATHNAME +#endif + +#include + +__BEGIN_DECLS +int fnmatch(const char *, const char *, int); +__END_DECLS + +#endif /* !_FNMATCH_H_ */ diff --git a/components/newlib/include/getopt.h b/components/newlib/include/getopt.h new file mode 100644 index 0000000000..e12d253d47 --- /dev/null +++ b/components/newlib/include/getopt.h @@ -0,0 +1,190 @@ +/**************************************************************************** + +getopt.h - Read command line options + +AUTHOR: Gregory Pietsch +CREATED Thu Jan 09 22:37:00 1997 + +DESCRIPTION: + +The getopt() function parses the command line arguments. Its arguments argc +and argv are the argument count and array as passed to the main() function +on program invocation. The argument optstring is a list of available option +characters. If such a character is followed by a colon (`:'), the option +takes an argument, which is placed in optarg. If such a character is +followed by two colons, the option takes an optional argument, which is +placed in optarg. If the option does not take an argument, optarg is NULL. + +The external variable optind is the index of the next array element of argv +to be processed; it communicates from one call to the next which element to +process. + +The getopt_long() function works like getopt() except that it also accepts +long options started by two dashes `--'. If these take values, it is either +in the form + +--arg=value + + or + +--arg value + +It takes the additional arguments longopts which is a pointer to the first +element of an array of type GETOPT_LONG_OPTION_T, defined below. The last +element of the array has to be filled with NULL for the name field. + +The longind pointer points to the index of the current long option relative +to longopts if it is non-NULL. + +The getopt() function returns the option character if the option was found +successfully, `:' if there was a missing parameter for one of the options, +`?' for an unknown option character, and EOF for the end of the option list. + +The getopt_long() function's return value is described below. + +The function getopt_long_only() is identical to getopt_long(), except that a +plus sign `+' can introduce long options as well as `--'. + +Describe how to deal with options that follow non-option ARGV-elements. + +If the caller did not specify anything, the default is REQUIRE_ORDER if the +environment variable POSIXLY_CORRECT is defined, PERMUTE otherwise. + +REQUIRE_ORDER means don't recognize them as options; stop option processing +when the first non-option is seen. This is what Unix does. This mode of +operation is selected by either setting the environment variable +POSIXLY_CORRECT, or using `+' as the first character of the optstring +parameter. + +PERMUTE is the default. We permute the contents of ARGV as we scan, so that +eventually all the non-options are at the end. This allows options to be +given in any order, even with programs that were not written to expect this. + +RETURN_IN_ORDER is an option available to programs that were written to +expect options and other ARGV-elements in any order and that care about the +ordering of the two. We describe each non-option ARGV-element as if it were +the argument of an option with character code 1. Using `-' as the first +character of the optstring parameter selects this mode of operation. + +The special argument `--' forces an end of option-scanning regardless of the +value of `ordering'. In the case of RETURN_IN_ORDER, only `--' can cause +getopt() and friends to return EOF with optind != argc. + +COPYRIGHT NOTICE AND DISCLAIMER: + +Copyright (C) 1997 Gregory Pietsch + +This file and the accompanying getopt.c implementation file are hereby +placed in the public domain without restrictions. Just give the author +credit, don't claim you wrote it or prevent anyone else from using it. + +Gregory Pietsch's current e-mail address: +gpietsch@comcast.net +****************************************************************************/ + +/* This is a glibc-extension header file. */ + +#ifndef GETOPT_H +#define GETOPT_H + +#include <_ansi.h> + +/* include files needed by this include file */ + +#define no_argument 0 +#define required_argument 1 +#define optional_argument 2 + +#ifdef __cplusplus +extern "C" +{ + +#endif /* __cplusplus */ + +/* types defined by this include file */ + struct option + { + const char *name; /* the name of the long option */ + int has_arg; /* one of the above macros */ + int *flag; /* determines if getopt_long() returns a + * value for a long option; if it is + * non-NULL, 0 is returned as a function + * value and the value of val is stored in + * the area pointed to by flag. Otherwise, + * val is returned. */ + int val; /* determines the value to return if flag is + * NULL. */ + + }; + +/* While getopt.h is a glibc extension, the following are newlib extensions. + * They are optionally included via the __need_getopt_newlib flag. */ + +#ifdef __need_getopt_newlib + + /* macros defined by this include file */ + #define NO_ARG no_argument + #define REQUIRED_ARG required_argument + #define OPTIONAL_ARG optional_argument + + /* The GETOPT_DATA_INITIALIZER macro is used to initialize a statically- + allocated variable of type struct getopt_data. */ + #define GETOPT_DATA_INITIALIZER {0,0,0,0,0} + + /* These #defines are to make accessing the reentrant functions easier. */ + #define getopt_r __getopt_r + #define getopt_long_r __getopt_long_r + #define getopt_long_only_r __getopt_long_only_r + + /* The getopt_data structure is for reentrancy. Its members are similar to + the externally-defined variables. */ + typedef struct getopt_data + { + char *optarg; + int optind, opterr, optopt, optwhere; + } getopt_data; + +#endif /* __need_getopt_newlib */ + + /* externally-defined variables */ + extern char *optarg; + extern int optind; + extern int opterr; + extern int optopt; + + /* function prototypes */ + int _EXFUN (getopt, + (int __argc, char *const __argv[], const char *__optstring)); + + int _EXFUN (getopt_long, + (int __argc, char *const __argv[], const char *__shortopts, + const struct option * __longopts, int *__longind)); + + int _EXFUN (getopt_long_only, + (int __argc, char *const __argv[], const char *__shortopts, + const struct option * __longopts, int *__longind)); + +#ifdef __need_getopt_newlib + int _EXFUN (__getopt_r, + (int __argc, char *const __argv[], const char *__optstring, + struct getopt_data * __data)); + + int _EXFUN (__getopt_long_r, + (int __argc, char *const __argv[], const char *__shortopts, + const struct option * __longopts, int *__longind, + struct getopt_data * __data)); + + int _EXFUN (__getopt_long_only_r, + (int __argc, char *const __argv[], const char *__shortopts, + const struct option * __longopts, int *__longind, + struct getopt_data * __data)); +#endif /* __need_getopt_newlib */ + +#ifdef __cplusplus +}; + +#endif /* __cplusplus */ + +#endif /* GETOPT_H */ + +/* END OF FILE getopt.h */ diff --git a/components/newlib/include/glob.h b/components/newlib/include/glob.h new file mode 100644 index 0000000000..7a300e69d4 --- /dev/null +++ b/components/newlib/include/glob.h @@ -0,0 +1,90 @@ +/* + * Copyright (c) 1989, 1993 + * The Regents of the University of California. All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Guido van Rossum. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)glob.h 8.1 (Berkeley) 6/2/93 + * $FreeBSD: src/include/glob.h,v 1.6 2002/03/23 17:24:53 imp Exp $ + */ + +#ifndef _GLOB_H_ +#define _GLOB_H_ + +#include + +struct stat; +typedef struct { + int gl_pathc; /* Count of total paths so far. */ + int gl_matchc; /* Count of paths matching pattern. */ + int gl_offs; /* Reserved at beginning of gl_pathv. */ + int gl_flags; /* Copy of flags parameter to glob. */ + char **gl_pathv; /* List of paths matching pattern. */ + /* Copy of errfunc parameter to glob. */ + int (*gl_errfunc)(const char *, int); + + /* + * Alternate filesystem access methods for glob; replacement + * versions of closedir(3), readdir(3), opendir(3), stat(2) + * and lstat(2). + */ + void (*gl_closedir)(void *); + struct dirent *(*gl_readdir)(void *); + void *(*gl_opendir)(const char *); + int (*gl_lstat)(const char *, struct stat *); + int (*gl_stat)(const char *, struct stat *); +} glob_t; + +#define GLOB_APPEND 0x0001 /* Append to output from previous call. */ +#define GLOB_DOOFFS 0x0002 /* Use gl_offs. */ +#define GLOB_ERR 0x0004 /* Return on error. */ +#define GLOB_MARK 0x0008 /* Append / to matching directories. */ +#define GLOB_NOCHECK 0x0010 /* Return pattern itself if nothing matches. */ +#define GLOB_NOSORT 0x0020 /* Don't sort. */ + +#define GLOB_ALTDIRFUNC 0x0040 /* Use alternately specified directory funcs. */ +#define GLOB_BRACE 0x0080 /* Expand braces ala csh. */ +#define GLOB_MAGCHAR 0x0100 /* Pattern had globbing characters. */ +#define GLOB_NOMAGIC 0x0200 /* GLOB_NOCHECK without magic chars (csh). */ +#define GLOB_QUOTE 0x0400 /* Quote special chars with \. */ +#define GLOB_TILDE 0x0800 /* Expand tilde names from the passwd file. */ +#define GLOB_LIMIT 0x1000 /* limit number of returned paths */ + +/* backwards compatibility, this is the old name for this option */ +#define GLOB_MAXPATH GLOB_LIMIT + +#define GLOB_NOSPACE (-1) /* Malloc call failed. */ +#define GLOB_ABEND (-2) /* Unignored error. */ + +__BEGIN_DECLS +int glob(const char *__restrict, int, int (*)(const char *, int), + glob_t *__restrict); +void globfree(glob_t *); +__END_DECLS + +#endif /* !_GLOB_H_ */ diff --git a/components/newlib/include/grp.h b/components/newlib/include/grp.h new file mode 100644 index 0000000000..c3a5a676c8 --- /dev/null +++ b/components/newlib/include/grp.h @@ -0,0 +1,95 @@ +/* $NetBSD: grp.h,v 1.7 1995/04/29 05:30:40 cgd Exp $ */ + +/*- + * Copyright (c) 1989, 1993 + * The Regents of the University of California. All rights reserved. + * (c) UNIX System Laboratories, Inc. + * All or some portions of this file are derived from material licensed + * to the University of California by American Telephone and Telegraph + * Co. or Unix System Laboratories, Inc. and are reproduced herein with + * the permission of UNIX System Laboratories, Inc. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)grp.h 8.2 (Berkeley) 1/21/94 + */ + +#ifndef _GRP_H_ +#define _GRP_H_ + +#include +#include +#ifdef __CYGWIN__ +#include +#endif + +#if !defined(_POSIX_SOURCE) && !defined(_XOPEN_SOURCE) +#define _PATH_GROUP "/etc/group" +#endif + +struct group { + char *gr_name; /* group name */ + char *gr_passwd; /* group password */ + gid_t gr_gid; /* group id */ + char **gr_mem; /* group members */ +}; + +#ifdef __cplusplus +extern "C" { +#endif + +#ifndef __INSIDE_CYGWIN__ +struct group *getgrgid (gid_t); +struct group *getgrnam (const char *); +int getgrnam_r (const char *, struct group *, + char *, size_t, struct group **); +int getgrgid_r (gid_t, struct group *, + char *, size_t, struct group **); +#ifndef _POSIX_SOURCE +struct group *getgrent (void); +void setgrent (void); +void endgrent (void); +#ifndef __CYGWIN__ +void setgrfile (const char *); +#endif /* !__CYGWIN__ */ +#ifndef _XOPEN_SOURCE +#ifndef __CYGWIN__ +char *group_from_gid (gid_t, int); +int setgroupent (int); +#endif /* !__CYGWIN__ */ +int initgroups (const char *, gid_t); +#endif /* !_XOPEN_SOURCE */ +#endif /* !_POSIX_SOURCE */ +#endif /* !__INSIDE_CYGWIN__ */ + +#ifdef __cplusplus +} +#endif + +#endif /* !_GRP_H_ */ diff --git a/components/newlib/include/iconv.h b/components/newlib/include/iconv.h new file mode 100644 index 0000000000..4c023e9df7 --- /dev/null +++ b/components/newlib/include/iconv.h @@ -0,0 +1,63 @@ +/* + * Copyright (c) 2003-2004, Artem B. Bityuckiy, SoftMine Corporation. + * Rights transferred to Franklin Electronic Publishers. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ +#ifndef _ICONV_H_ +#define _ICONV_H_ + +#include <_ansi.h> +#include +#include +#include + +/* iconv_t: charset conversion descriptor type */ +typedef _iconv_t iconv_t; + +_BEGIN_STD_C + +#ifndef _REENT_ONLY +iconv_t +_EXFUN(iconv_open, (_CONST char *, _CONST char *)); + +size_t +_EXFUN(iconv, (iconv_t, char **__restrict, size_t *__restrict, + char **__restrict, size_t *__restrict)); + +int +_EXFUN(iconv_close, (iconv_t)); +#endif + +iconv_t +_EXFUN(_iconv_open_r, (struct _reent *, _CONST char *, _CONST char *)); + +size_t +_EXFUN(_iconv_r, (struct _reent *, iconv_t, _CONST char **, + size_t *, char **, size_t *)); + +int +_EXFUN(_iconv_close_r, (struct _reent *, iconv_t)); + +_END_STD_C + +#endif /* #ifndef _ICONV_H_ */ diff --git a/components/newlib/include/ieeefp.h b/components/newlib/include/ieeefp.h new file mode 100644 index 0000000000..0b06fb7861 --- /dev/null +++ b/components/newlib/include/ieeefp.h @@ -0,0 +1,256 @@ +#ifndef _IEEE_FP_H_ +#define _IEEE_FP_H_ + +#include "_ansi.h" + +#include + +_BEGIN_STD_C + +/* FIXME FIXME FIXME: + Neither of __ieee_{float,double}_shape_tape seem to be used anywhere + except in libm/test. If that is the case, please delete these from here. + If that is not the case, please insert documentation here describing why + they're needed. */ + +#ifdef __IEEE_BIG_ENDIAN + +typedef union +{ + double value; + struct + { + unsigned int sign : 1; + unsigned int exponent: 11; + unsigned int fraction0:4; + unsigned int fraction1:16; + unsigned int fraction2:16; + unsigned int fraction3:16; + + } number; + struct + { + unsigned int sign : 1; + unsigned int exponent: 11; + unsigned int quiet:1; + unsigned int function0:3; + unsigned int function1:16; + unsigned int function2:16; + unsigned int function3:16; + } nan; + struct + { + unsigned long msw; + unsigned long lsw; + } parts; + long aslong[2]; +} __ieee_double_shape_type; + +#endif + +#ifdef __IEEE_LITTLE_ENDIAN + +typedef union +{ + double value; + struct + { +#ifdef __SMALL_BITFIELDS + unsigned int fraction3:16; + unsigned int fraction2:16; + unsigned int fraction1:16; + unsigned int fraction0: 4; +#else + unsigned int fraction1:32; + unsigned int fraction0:20; +#endif + unsigned int exponent :11; + unsigned int sign : 1; + } number; + struct + { +#ifdef __SMALL_BITFIELDS + unsigned int function3:16; + unsigned int function2:16; + unsigned int function1:16; + unsigned int function0:3; +#else + unsigned int function1:32; + unsigned int function0:19; +#endif + unsigned int quiet:1; + unsigned int exponent: 11; + unsigned int sign : 1; + } nan; + struct + { + unsigned long lsw; + unsigned long msw; + } parts; + + long aslong[2]; + +} __ieee_double_shape_type; + +#endif + +#ifdef __IEEE_BIG_ENDIAN + +typedef union +{ + float value; + struct + { + unsigned int sign : 1; + unsigned int exponent: 8; + unsigned int fraction0: 7; + unsigned int fraction1: 16; + } number; + struct + { + unsigned int sign:1; + unsigned int exponent:8; + unsigned int quiet:1; + unsigned int function0:6; + unsigned int function1:16; + } nan; + long p1; + +} __ieee_float_shape_type; + +#endif + +#ifdef __IEEE_LITTLE_ENDIAN + +typedef union +{ + float value; + struct + { + unsigned int fraction0: 7; + unsigned int fraction1: 16; + unsigned int exponent: 8; + unsigned int sign : 1; + } number; + struct + { + unsigned int function1:16; + unsigned int function0:6; + unsigned int quiet:1; + unsigned int exponent:8; + unsigned int sign:1; + } nan; + long p1; + +} __ieee_float_shape_type; + +#endif + + + + + +/* FLOATING ROUNDING */ + +typedef int fp_rnd; +#define FP_RN 0 /* Round to nearest */ +#define FP_RM 1 /* Round down */ +#define FP_RP 2 /* Round up */ +#define FP_RZ 3 /* Round to zero (trunate) */ + +fp_rnd _EXFUN(fpgetround,(void)); +fp_rnd _EXFUN(fpsetround, (fp_rnd)); + +/* EXCEPTIONS */ + +typedef int fp_except; +#define FP_X_INV 0x10 /* Invalid operation */ +#define FP_X_DX 0x80 /* Divide by zero */ +#define FP_X_OFL 0x04 /* Overflow exception */ +#define FP_X_UFL 0x02 /* Underflow exception */ +#define FP_X_IMP 0x01 /* imprecise exception */ + +fp_except _EXFUN(fpgetmask,(void)); +fp_except _EXFUN(fpsetmask,(fp_except)); +fp_except _EXFUN(fpgetsticky,(void)); +fp_except _EXFUN(fpsetsticky, (fp_except)); + +/* INTEGER ROUNDING */ + +typedef int fp_rdi; +#define FP_RDI_TOZ 0 /* Round to Zero */ +#define FP_RDI_RD 1 /* Follow float mode */ + +fp_rdi _EXFUN(fpgetroundtoi,(void)); +fp_rdi _EXFUN(fpsetroundtoi,(fp_rdi)); + +#undef isnan +#undef isinf + +int _EXFUN(isnan, (double)); +int _EXFUN(isinf, (double)); +int _EXFUN(finite, (double)); + + + +int _EXFUN(isnanf, (float)); +int _EXFUN(isinff, (float)); +int _EXFUN(finitef, (float)); + +#define __IEEE_DBL_EXPBIAS 1023 +#define __IEEE_FLT_EXPBIAS 127 + +#define __IEEE_DBL_EXPLEN 11 +#define __IEEE_FLT_EXPLEN 8 + + +#define __IEEE_DBL_FRACLEN (64 - (__IEEE_DBL_EXPLEN + 1)) +#define __IEEE_FLT_FRACLEN (32 - (__IEEE_FLT_EXPLEN + 1)) + +#define __IEEE_DBL_MAXPOWTWO ((double)(1L << 32 - 2) * (1L << (32-11) - 32 + 1)) +#define __IEEE_FLT_MAXPOWTWO ((float)(1L << (32-8) - 1)) + +#define __IEEE_DBL_NAN_EXP 0x7ff +#define __IEEE_FLT_NAN_EXP 0xff + +#ifndef __ieeefp_isnanf +#define __ieeefp_isnanf(x) (((*(long *)&(x) & 0x7f800000L)==0x7f800000L) && \ + ((*(long *)&(x) & 0x007fffffL)!=0000000000L)) +#endif +#define isnanf(x) __ieeefp_isnanf(x) + +#ifndef __ieeefp_isinff +#define __ieeefp_isinff(x) (((*(long *)&(x) & 0x7f800000L)==0x7f800000L) && \ + ((*(long *)&(x) & 0x007fffffL)==0000000000L)) +#endif +#define isinff(x) __ieeefp_isinff(x) + +#ifndef __ieeefp_finitef +#define __ieeefp_finitef(x) (((*(long *)&(x) & 0x7f800000L)!=0x7f800000L)) +#endif +#define finitef(x) __ieeefp_finitef(x) + +#ifdef _DOUBLE_IS_32BITS +#undef __IEEE_DBL_EXPBIAS +#define __IEEE_DBL_EXPBIAS __IEEE_FLT_EXPBIAS + +#undef __IEEE_DBL_EXPLEN +#define __IEEE_DBL_EXPLEN __IEEE_FLT_EXPLEN + +#undef __IEEE_DBL_FRACLEN +#define __IEEE_DBL_FRACLEN __IEEE_FLT_FRACLEN + +#undef __IEEE_DBL_MAXPOWTWO +#define __IEEE_DBL_MAXPOWTWO __IEEE_FLT_MAXPOWTWO + +#undef __IEEE_DBL_NAN_EXP +#define __IEEE_DBL_NAN_EXP __IEEE_FLT_NAN_EXP + +#undef __ieee_double_shape_type +#define __ieee_double_shape_type __ieee_float_shape_type + +#endif /* _DOUBLE_IS_32BITS */ + +_END_STD_C + +#endif /* _IEEE_FP_H_ */ diff --git a/components/newlib/include/inttypes.h b/components/newlib/include/inttypes.h new file mode 100644 index 0000000000..39bf135113 --- /dev/null +++ b/components/newlib/include/inttypes.h @@ -0,0 +1,319 @@ +/* + * Copyright (c) 2004, 2005 by + * Ralf Corsepius, Ulm/Germany. All rights reserved. + * + * Permission to use, copy, modify, and distribute this software + * is freely granted, provided that this notice is preserved. + */ + +/** + * @file inttypes.h + */ + +#ifndef _INTTYPES_H +#define _INTTYPES_H + +#include +#include +#include +#define __need_wchar_t +#include + +#define __STRINGIFY(a) #a + +/* 8-bit types */ +#define __PRI8(x) __STRINGIFY(x) + +/* NOTICE: scanning 8-bit types requires use of the hh specifier + * which is only supported on newlib platforms that + * are built with C99 I/O format support enabled. If the flag in + * newlib.h hasn't been set during configuration to indicate this, the 8-bit + * scanning format macros are disabled here as they result in undefined + * behaviour which can include memory overwrite. Overriding the flag after the + * library has been built is not recommended as it will expose the underlying + * undefined behaviour. + */ + +#if defined(_WANT_IO_C99_FORMATS) + #define __SCN8(x) __STRINGIFY(hh##x) +#endif /* _WANT_IO_C99_FORMATS */ + + +#define PRId8 __PRI8(d) +#define PRIi8 __PRI8(i) +#define PRIo8 __PRI8(o) +#define PRIu8 __PRI8(u) +#define PRIx8 __PRI8(x) +#define PRIX8 __PRI8(X) + +/* Macros below are only enabled for a newlib built with C99 I/O format support. */ +#if defined(_WANT_IO_C99_FORMATS) + +#define SCNd8 __SCN8(d) +#define SCNi8 __SCN8(i) +#define SCNo8 __SCN8(o) +#define SCNu8 __SCN8(u) +#define SCNx8 __SCN8(x) + +#endif /* _WANT_IO_C99_FORMATS */ + + +#define PRIdLEAST8 __PRI8(d) +#define PRIiLEAST8 __PRI8(i) +#define PRIoLEAST8 __PRI8(o) +#define PRIuLEAST8 __PRI8(u) +#define PRIxLEAST8 __PRI8(x) +#define PRIXLEAST8 __PRI8(X) + +/* Macros below are only enabled for a newlib built with C99 I/O format support. */ +#if defined(_WANT_IO_C99_FORMATS) + + #define SCNdLEAST8 __SCN8(d) + #define SCNiLEAST8 __SCN8(i) + #define SCNoLEAST8 __SCN8(o) + #define SCNuLEAST8 __SCN8(u) + #define SCNxLEAST8 __SCN8(x) + +#endif /* _WANT_IO_C99_FORMATS */ + +#define PRIdFAST8 __PRI8(d) +#define PRIiFAST8 __PRI8(i) +#define PRIoFAST8 __PRI8(o) +#define PRIuFAST8 __PRI8(u) +#define PRIxFAST8 __PRI8(x) +#define PRIXFAST8 __PRI8(X) + +/* Macros below are only enabled for a newlib built with C99 I/O format support. */ +#if defined(_WANT_IO_C99_FORMATS) + + #define SCNdFAST8 __SCN8(d) + #define SCNiFAST8 __SCN8(i) + #define SCNoFAST8 __SCN8(o) + #define SCNuFAST8 __SCN8(u) + #define SCNxFAST8 __SCN8(x) + +#endif /* _WANT_IO_C99_FORMATS */ + +/* 16-bit types */ +#define __PRI16(x) __STRINGIFY(x) +#define __SCN16(x) __STRINGIFY(h##x) + + +#define PRId16 __PRI16(d) +#define PRIi16 __PRI16(i) +#define PRIo16 __PRI16(o) +#define PRIu16 __PRI16(u) +#define PRIx16 __PRI16(x) +#define PRIX16 __PRI16(X) + +#define SCNd16 __SCN16(d) +#define SCNi16 __SCN16(i) +#define SCNo16 __SCN16(o) +#define SCNu16 __SCN16(u) +#define SCNx16 __SCN16(x) + + +#define PRIdLEAST16 __PRI16(d) +#define PRIiLEAST16 __PRI16(i) +#define PRIoLEAST16 __PRI16(o) +#define PRIuLEAST16 __PRI16(u) +#define PRIxLEAST16 __PRI16(x) +#define PRIXLEAST16 __PRI16(X) + +#define SCNdLEAST16 __SCN16(d) +#define SCNiLEAST16 __SCN16(i) +#define SCNoLEAST16 __SCN16(o) +#define SCNuLEAST16 __SCN16(u) +#define SCNxLEAST16 __SCN16(x) + + +#define PRIdFAST16 __PRI16(d) +#define PRIiFAST16 __PRI16(i) +#define PRIoFAST16 __PRI16(o) +#define PRIuFAST16 __PRI16(u) +#define PRIxFAST16 __PRI16(x) +#define PRIXFAST16 __PRI16(X) + +#define SCNdFAST16 __SCN16(d) +#define SCNiFAST16 __SCN16(i) +#define SCNoFAST16 __SCN16(o) +#define SCNuFAST16 __SCN16(u) +#define SCNxFAST16 __SCN16(x) + +/* 32-bit types */ +#if __have_long32 +#define __PRI32(x) __STRINGIFY(l##x) +#define __SCN32(x) __STRINGIFY(l##x) +#else +#define __PRI32(x) __STRINGIFY(x) +#define __SCN32(x) __STRINGIFY(x) +#endif + +#define PRId32 __PRI32(d) +#define PRIi32 __PRI32(i) +#define PRIo32 __PRI32(o) +#define PRIu32 __PRI32(u) +#define PRIx32 __PRI32(x) +#define PRIX32 __PRI32(X) + +#define SCNd32 __SCN32(d) +#define SCNi32 __SCN32(i) +#define SCNo32 __SCN32(o) +#define SCNu32 __SCN32(u) +#define SCNx32 __SCN32(x) + + +#define PRIdLEAST32 __PRI32(d) +#define PRIiLEAST32 __PRI32(i) +#define PRIoLEAST32 __PRI32(o) +#define PRIuLEAST32 __PRI32(u) +#define PRIxLEAST32 __PRI32(x) +#define PRIXLEAST32 __PRI32(X) + +#define SCNdLEAST32 __SCN32(d) +#define SCNiLEAST32 __SCN32(i) +#define SCNoLEAST32 __SCN32(o) +#define SCNuLEAST32 __SCN32(u) +#define SCNxLEAST32 __SCN32(x) + + +#define PRIdFAST32 __PRI32(d) +#define PRIiFAST32 __PRI32(i) +#define PRIoFAST32 __PRI32(o) +#define PRIuFAST32 __PRI32(u) +#define PRIxFAST32 __PRI32(x) +#define PRIXFAST32 __PRI32(X) + +#define SCNdFAST32 __SCN32(d) +#define SCNiFAST32 __SCN32(i) +#define SCNoFAST32 __SCN32(o) +#define SCNuFAST32 __SCN32(u) +#define SCNxFAST32 __SCN32(x) + + +/* 64-bit types */ +#if __have_long64 +#define __PRI64(x) __STRINGIFY(l##x) +#define __SCN64(x) __STRINGIFY(l##x) +#elif __have_longlong64 +#define __PRI64(x) __STRINGIFY(ll##x) +#define __SCN64(x) __STRINGIFY(ll##x) +#else +#define __PRI64(x) __STRINGIFY(x) +#define __SCN64(x) __STRINGIFY(x) +#endif + +#define PRId64 __PRI64(d) +#define PRIi64 __PRI64(i) +#define PRIo64 __PRI64(o) +#define PRIu64 __PRI64(u) +#define PRIx64 __PRI64(x) +#define PRIX64 __PRI64(X) + +#define SCNd64 __SCN64(d) +#define SCNi64 __SCN64(i) +#define SCNo64 __SCN64(o) +#define SCNu64 __SCN64(u) +#define SCNx64 __SCN64(x) + +#if __int64_t_defined +#define PRIdLEAST64 __PRI64(d) +#define PRIiLEAST64 __PRI64(i) +#define PRIoLEAST64 __PRI64(o) +#define PRIuLEAST64 __PRI64(u) +#define PRIxLEAST64 __PRI64(x) +#define PRIXLEAST64 __PRI64(X) + +#define SCNdLEAST64 __SCN64(d) +#define SCNiLEAST64 __SCN64(i) +#define SCNoLEAST64 __SCN64(o) +#define SCNuLEAST64 __SCN64(u) +#define SCNxLEAST64 __SCN64(x) + + +#define PRIdFAST64 __PRI64(d) +#define PRIiFAST64 __PRI64(i) +#define PRIoFAST64 __PRI64(o) +#define PRIuFAST64 __PRI64(u) +#define PRIxFAST64 __PRI64(x) +#define PRIXFAST64 __PRI64(X) + +#define SCNdFAST64 __SCN64(d) +#define SCNiFAST64 __SCN64(i) +#define SCNoFAST64 __SCN64(o) +#define SCNuFAST64 __SCN64(u) +#define SCNxFAST64 __SCN64(x) +#endif + +/* max-bit types */ +#if __have_long64 +#define __PRIMAX(x) __STRINGIFY(l##x) +#define __SCNMAX(x) __STRINGIFY(l##x) +#elif __have_longlong64 +#define __PRIMAX(x) __STRINGIFY(ll##x) +#define __SCNMAX(x) __STRINGIFY(ll##x) +#else +#define __PRIMAX(x) __STRINGIFY(x) +#define __SCNMAX(x) __STRINGIFY(x) +#endif + +#define PRIdMAX __PRIMAX(d) +#define PRIiMAX __PRIMAX(i) +#define PRIoMAX __PRIMAX(o) +#define PRIuMAX __PRIMAX(u) +#define PRIxMAX __PRIMAX(x) +#define PRIXMAX __PRIMAX(X) + +#define SCNdMAX __SCNMAX(d) +#define SCNiMAX __SCNMAX(i) +#define SCNoMAX __SCNMAX(o) +#define SCNuMAX __SCNMAX(u) +#define SCNxMAX __SCNMAX(x) + +/* ptr types */ +#if defined(_UINTPTR_EQ_ULONGLONG) +# define __PRIPTR(x) __STRINGIFY(ll##x) +# define __SCNPTR(x) __STRINGIFY(ll##x) +#elif defined(_UINTPTR_EQ_ULONG) +# define __PRIPTR(x) __STRINGIFY(l##x) +# define __SCNPTR(x) __STRINGIFY(l##x) +#else +# define __PRIPTR(x) __STRINGIFY(x) +# define __SCNPTR(x) __STRINGIFY(x) +#endif + +#define PRIdPTR __PRIPTR(d) +#define PRIiPTR __PRIPTR(i) +#define PRIoPTR __PRIPTR(o) +#define PRIuPTR __PRIPTR(u) +#define PRIxPTR __PRIPTR(x) +#define PRIXPTR __PRIPTR(X) + +#define SCNdPTR __SCNPTR(d) +#define SCNiPTR __SCNPTR(i) +#define SCNoPTR __SCNPTR(o) +#define SCNuPTR __SCNPTR(u) +#define SCNxPTR __SCNPTR(x) + + +typedef struct { + intmax_t quot; + intmax_t rem; +} imaxdiv_t; + +#ifdef __cplusplus +extern "C" { +#endif + +extern intmax_t imaxabs(intmax_t j); +extern imaxdiv_t imaxdiv(intmax_t numer, intmax_t denomer); +extern intmax_t strtoimax(const char *__restrict, char **__restrict, int); +extern uintmax_t strtoumax(const char *__restrict, char **__restrict, int); +extern intmax_t wcstoimax(const wchar_t *__restrict, wchar_t **__restrict, int); +extern uintmax_t wcstoumax(const wchar_t *__restrict, wchar_t **__restrict, int); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/components/newlib/include/langinfo.h b/components/newlib/include/langinfo.h new file mode 100644 index 0000000000..9040adeff5 --- /dev/null +++ b/components/newlib/include/langinfo.h @@ -0,0 +1,316 @@ +/*- + * Copyright (c) 2001 Alexey Zelkin + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $FreeBSD: src/include/langinfo.h,v 1.5 2002/03/23 17:24:53 imp Exp $ + */ + +#ifndef _LANGINFO_H_ +#define _LANGINFO_H_ + +#include +#include +#include + +typedef int nl_item; + +enum __nl_item +{ + /* POSIX and BSD defined items have to stick to the original values + to maintain backward compatibility. */ + _NL_CTYPE_CODESET_NAME = 0, /* codeset name */ +#define CODESET _NL_CTYPE_CODESET_NAME + D_T_FMT, /* string for formatting date and time */ +#define D_T_FMT D_T_FMT + D_FMT, /* date format string */ +#define D_FMT D_FMT + T_FMT, /* time format string */ +#define T_FMT T_FMT + T_FMT_AMPM, /* a.m. or p.m. time formatting string */ +#define T_FMT_AMPM T_FMT_AMPM + AM_STR, /* Ante Meridian affix */ +#define AM_STR AM_STR + PM_STR, /* Post Meridian affix */ +#define PM_STR PM_STR + +/* week day names */ + DAY_1, +#define DAY_1 DAY_1 + DAY_2, +#define DAY_2 DAY_2 + DAY_3, +#define DAY_3 DAY_3 + DAY_4, +#define DAY_4 DAY_4 + DAY_5, +#define DAY_5 DAY_5 + DAY_6, +#define DAY_6 DAY_6 + DAY_7, +#define DAY_7 DAY_7 + +/* abbreviated week day names */ + ABDAY_1, +#define ABDAY_1 ABDAY_1 + ABDAY_2, +#define ABDAY_2 ABDAY_2 + ABDAY_3, +#define ABDAY_3 ABDAY_3 + ABDAY_4, +#define ABDAY_4 ABDAY_4 + ABDAY_5, +#define ABDAY_5 ABDAY_5 + ABDAY_6, +#define ABDAY_6 ABDAY_6 + ABDAY_7, +#define ABDAY_7 ABDAY_7 + +/* month names */ + MON_1, +#define MON_1 MON_1 + MON_2, +#define MON_2 MON_2 + MON_3, +#define MON_3 MON_3 + MON_4, +#define MON_4 MON_4 + MON_5, +#define MON_5 MON_5 + MON_6, +#define MON_6 MON_6 + MON_7, +#define MON_7 MON_7 + MON_8, +#define MON_8 MON_8 + MON_9, +#define MON_9 MON_9 + MON_10, +#define MON_10 MON_10 + MON_11, +#define MON_11 MON_11 + MON_12, +#define MON_12 MON_12 + +/* abbreviated month names */ + ABMON_1, +#define ABMON_1 ABMON_1 + ABMON_2, +#define ABMON_2 ABMON_2 + ABMON_3, +#define ABMON_3 ABMON_3 + ABMON_4, +#define ABMON_4 ABMON_4 + ABMON_5, +#define ABMON_5 ABMON_5 + ABMON_6, +#define ABMON_6 ABMON_6 + ABMON_7, +#define ABMON_7 ABMON_7 + ABMON_8, +#define ABMON_8 ABMON_8 + ABMON_9, +#define ABMON_9 ABMON_9 + ABMON_10, +#define ABMON_10 ABMON_10 + ABMON_11, +#define ABMON_11 ABMON_11 + ABMON_12, +#define ABMON_12 ABMON_12 + + ERA, /* era description segments */ +#define ERA ERA + ERA_D_FMT, /* era date format string */ +#define ERA_D_FMT ERA_D_FMT + ERA_D_T_FMT, /* era date and time format string */ +#define ERA_D_T_FMT ERA_D_T_FMT + ERA_T_FMT, /* era time format string */ +#define ERA_T_FMT ERA_T_FMT + ALT_DIGITS, /* alternative symbols for digits */ +#define ALT_DIGITS ALT_DIGITS + + RADIXCHAR, /* radix char */ +#define RADIXCHAR RADIXCHAR + THOUSEP, /* separator for thousands */ +#define THOUSEP THOUSEP + + YESEXPR, /* affirmative response expression */ +#define YESEXPR YESEXPR + NOEXPR, /* negative response expression */ +#define NOEXPR NOEXPR + YESSTR, /* affirmative response for yes/no queries */ +#define YESSTR YESSTR + NOSTR, /* negative response for yes/no queries */ +#define NOSTR NOSTR + + CRNCYSTR, /* currency symbol */ +#define CRNCYSTR CRNCYSTR + + D_MD_ORDER, /* month/day order (BSD extension) */ +#define D_MD_ORDER D_MD_ORDER + + _NL_TIME_DATE_FMT = 84, /* date fmt used by date(1) (GNU extension) */ +#define _DATE_FMT _NL_TIME_DATE_FMT + +#ifdef __HAVE_LOCALE_INFO__ + _NL_CTYPE_MB_CUR_MAX, + _NL_MESSAGES_CODESET, + +#ifdef __HAVE_LOCALE_INFO_EXTENDED__ + + /* NOTE: + + Always maintain the order and position of existing entries! + Always append new entry to the list, prior to the definition + of _NL_LOCALE_EXTENDED_LAST_ENTRY. */ + + _NL_LOCALE_EXTENDED_FIRST_ENTRY, + + _NL_CTYPE_OUTDIGITS0_MB, + _NL_CTYPE_OUTDIGITS1_MB, + _NL_CTYPE_OUTDIGITS2_MB, + _NL_CTYPE_OUTDIGITS3_MB, + _NL_CTYPE_OUTDIGITS4_MB, + _NL_CTYPE_OUTDIGITS5_MB, + _NL_CTYPE_OUTDIGITS6_MB, + _NL_CTYPE_OUTDIGITS7_MB, + _NL_CTYPE_OUTDIGITS8_MB, + _NL_CTYPE_OUTDIGITS9_MB, + _NL_CTYPE_OUTDIGITS0_WC, + _NL_CTYPE_OUTDIGITS1_WC, + _NL_CTYPE_OUTDIGITS2_WC, + _NL_CTYPE_OUTDIGITS3_WC, + _NL_CTYPE_OUTDIGITS4_WC, + _NL_CTYPE_OUTDIGITS5_WC, + _NL_CTYPE_OUTDIGITS6_WC, + _NL_CTYPE_OUTDIGITS7_WC, + _NL_CTYPE_OUTDIGITS8_WC, + _NL_CTYPE_OUTDIGITS9_WC, + + _NL_TIME_CODESET, + _NL_TIME_WMON_1, + _NL_TIME_WMON_2, + _NL_TIME_WMON_3, + _NL_TIME_WMON_4, + _NL_TIME_WMON_5, + _NL_TIME_WMON_6, + _NL_TIME_WMON_7, + _NL_TIME_WMON_8, + _NL_TIME_WMON_9, + _NL_TIME_WMON_10, + _NL_TIME_WMON_11, + _NL_TIME_WMON_12, + _NL_TIME_WMONTH_1, + _NL_TIME_WMONTH_2, + _NL_TIME_WMONTH_3, + _NL_TIME_WMONTH_4, + _NL_TIME_WMONTH_5, + _NL_TIME_WMONTH_6, + _NL_TIME_WMONTH_7, + _NL_TIME_WMONTH_8, + _NL_TIME_WMONTH_9, + _NL_TIME_WMONTH_10, + _NL_TIME_WMONTH_11, + _NL_TIME_WMONTH_12, + _NL_TIME_WWDAY_1, + _NL_TIME_WWDAY_2, + _NL_TIME_WWDAY_3, + _NL_TIME_WWDAY_4, + _NL_TIME_WWDAY_5, + _NL_TIME_WWDAY_6, + _NL_TIME_WWDAY_7, + _NL_TIME_WWEEKDAY_1, + _NL_TIME_WWEEKDAY_2, + _NL_TIME_WWEEKDAY_3, + _NL_TIME_WWEEKDAY_4, + _NL_TIME_WWEEKDAY_5, + _NL_TIME_WWEEKDAY_6, + _NL_TIME_WWEEKDAY_7, + _NL_TIME_WT_FMT, + _NL_TIME_WD_FMT, + _NL_TIME_WD_T_FMT, + _NL_TIME_WAM_STR, + _NL_TIME_WPM_STR, + _NL_TIME_WDATE_FMT, + _NL_TIME_WT_FMT_AMPM, + _NL_TIME_WERA, + _NL_TIME_WERA_D_FMT, + _NL_TIME_WERA_D_T_FMT, + _NL_TIME_WERA_T_FMT, + _NL_TIME_WALT_DIGITS, + + _NL_NUMERIC_CODESET, + _NL_NUMERIC_GROUPING, + _NL_NUMERIC_DECIMAL_POINT_WC, + _NL_NUMERIC_THOUSANDS_SEP_WC, + + _NL_MONETARY_INT_CURR_SYMBOL, + _NL_MONETARY_CURRENCY_SYMBOL, + _NL_MONETARY_MON_DECIMAL_POINT, + _NL_MONETARY_MON_THOUSANDS_SEP, + _NL_MONETARY_MON_GROUPING, + _NL_MONETARY_POSITIVE_SIGN, + _NL_MONETARY_NEGATIVE_SIGN, + _NL_MONETARY_INT_FRAC_DIGITS, + _NL_MONETARY_FRAC_DIGITS, + _NL_MONETARY_P_CS_PRECEDES, + _NL_MONETARY_P_SEP_BY_SPACE, + _NL_MONETARY_N_CS_PRECEDES, + _NL_MONETARY_N_SEP_BY_SPACE, + _NL_MONETARY_P_SIGN_POSN, + _NL_MONETARY_N_SIGN_POSN, + _NL_MONETARY_INT_P_CS_PRECEDES, + _NL_MONETARY_INT_P_SEP_BY_SPACE, + _NL_MONETARY_INT_N_CS_PRECEDES, + _NL_MONETARY_INT_N_SEP_BY_SPACE, + _NL_MONETARY_INT_P_SIGN_POSN, + _NL_MONETARY_INT_N_SIGN_POSN, + _NL_MONETARY_CODESET, + _NL_MONETARY_WINT_CURR_SYMBOL, + _NL_MONETARY_WCURRENCY_SYMBOL, + _NL_MONETARY_WMON_DECIMAL_POINT, + _NL_MONETARY_WMON_THOUSANDS_SEP, + _NL_MONETARY_WPOSITIVE_SIGN, + _NL_MONETARY_WNEGATIVE_SIGN, + + _NL_MESSAGES_WYESEXPR, + _NL_MESSAGES_WNOEXPR, + _NL_MESSAGES_WYESSTR, + _NL_MESSAGES_WNOSTR, + + _NL_COLLATE_CODESET, + + /* This MUST be the last entry since it's used to check for an array + index in nl_langinfo(). */ + _NL_LOCALE_EXTENDED_LAST_ENTRY + +#endif /* __HAVE_LOCALE_INFO_EXTENDED__ */ +#endif /* __HAVE_LOCALE_INFO__ */ + +}; + +__BEGIN_DECLS +char *nl_langinfo(nl_item); +__END_DECLS + +#endif /* !_LANGINFO_H_ */ diff --git a/components/newlib/include/libgen.h b/components/newlib/include/libgen.h new file mode 100644 index 0000000000..abfab0e5c7 --- /dev/null +++ b/components/newlib/include/libgen.h @@ -0,0 +1,23 @@ +/* + * libgen.h - defined by XPG4 + */ + +#ifndef _LIBGEN_H_ +#define _LIBGEN_H_ + +#include "_ansi.h" +#include + +#ifdef __cplusplus +extern "C" { +#endif + +char *_EXFUN(basename, (char *)); +char *_EXFUN(dirname, (char *)); + +#ifdef __cplusplus +} +#endif + +#endif /* _LIBGEN_H_ */ + diff --git a/components/newlib/include/limits.h b/components/newlib/include/limits.h new file mode 100644 index 0000000000..190f1f783a --- /dev/null +++ b/components/newlib/include/limits.h @@ -0,0 +1,146 @@ +#ifndef _LIBC_LIMITS_H_ +# define _LIBC_LIMITS_H_ 1 + +#include + +# ifdef _MB_LEN_MAX +# define MB_LEN_MAX _MB_LEN_MAX +# else +# define MB_LEN_MAX 1 +# endif + +/* Maximum number of positional arguments, if _WANT_IO_POS_ARGS. */ +# ifndef NL_ARGMAX +# define NL_ARGMAX 32 +# endif + +/* if do not have #include_next support, then we + have to define the limits here. */ +# if !defined __GNUC__ || __GNUC__ < 2 + +# ifndef _LIMITS_H +# define _LIMITS_H 1 + +# include + +/* Number of bits in a `char'. */ +# undef CHAR_BIT +# define CHAR_BIT 8 + +/* Minimum and maximum values a `signed char' can hold. */ +# undef SCHAR_MIN +# define SCHAR_MIN (-128) +# undef SCHAR_MAX +# define SCHAR_MAX 127 + +/* Maximum value an `unsigned char' can hold. (Minimum is 0). */ +# undef UCHAR_MAX +# define UCHAR_MAX 255 + +/* Minimum and maximum values a `char' can hold. */ +# ifdef __CHAR_UNSIGNED__ +# undef CHAR_MIN +# define CHAR_MIN 0 +# undef CHAR_MAX +# define CHAR_MAX 255 +# else +# undef CHAR_MIN +# define CHAR_MIN (-128) +# undef CHAR_MAX +# define CHAR_MAX 127 +# endif + +/* Minimum and maximum values a `signed short int' can hold. */ +# undef SHRT_MIN +/* For the sake of 16 bit hosts, we may not use -32768 */ +# define SHRT_MIN (-32767-1) +# undef SHRT_MAX +# define SHRT_MAX 32767 + +/* Maximum value an `unsigned short int' can hold. (Minimum is 0). */ +# undef USHRT_MAX +# define USHRT_MAX 65535 + +/* Minimum and maximum values a `signed int' can hold. */ +# ifndef __INT_MAX__ +# define __INT_MAX__ 2147483647 +# endif +# undef INT_MIN +# define INT_MIN (-INT_MAX-1) +# undef INT_MAX +# define INT_MAX __INT_MAX__ + +/* Maximum value an `unsigned int' can hold. (Minimum is 0). */ +# undef UINT_MAX +# define UINT_MAX (INT_MAX * 2U + 1) + +/* Minimum and maximum values a `signed long int' can hold. + (Same as `int'). */ +# ifndef __LONG_MAX__ +# if defined (__alpha__) || (defined (__sparc__) && defined(__arch64__)) || defined (__sparcv9) +# define __LONG_MAX__ 9223372036854775807L +# else +# define __LONG_MAX__ 2147483647L +# endif /* __alpha__ || sparc64 */ +# endif +# undef LONG_MIN +# define LONG_MIN (-LONG_MAX-1) +# undef LONG_MAX +# define LONG_MAX __LONG_MAX__ + +/* Maximum value an `unsigned long int' can hold. (Minimum is 0). */ +# undef ULONG_MAX +# define ULONG_MAX (LONG_MAX * 2UL + 1) + +# ifndef __LONG_LONG_MAX__ +# define __LONG_LONG_MAX__ 9223372036854775807LL +# endif + +# if (defined (__STDC_VERSION__) && __STDC_VERSION__ >= 199901L) || \ + (defined(__cplusplus) && __cplusplus >= 201103L) +/* Minimum and maximum values a `signed long long int' can hold. */ +# undef LLONG_MIN +# define LLONG_MIN (-LLONG_MAX-1) +# undef LLONG_MAX +# define LLONG_MAX __LONG_LONG_MAX__ + +/* Maximum value an `unsigned long long int' can hold. (Minimum is 0). */ +# undef ULLONG_MAX +# define ULLONG_MAX (LLONG_MAX * 2ULL + 1) +# endif + +# if defined (__GNU_LIBRARY__) ? defined (__USE_GNU) : !defined (__STRICT_ANSI__) +/* Minimum and maximum values a `signed long long int' can hold. */ +# undef LONG_LONG_MIN +# define LONG_LONG_MIN (-LONG_LONG_MAX-1) +# undef LONG_LONG_MAX +# define LONG_LONG_MAX __LONG_LONG_MAX__ + +/* Maximum value an `unsigned long long int' can hold. (Minimum is 0). */ +# undef ULONG_LONG_MAX +# define ULONG_LONG_MAX (LONG_LONG_MAX * 2ULL + 1) +# endif + +# endif /* _LIMITS_H */ +# endif /* GCC 2. */ + +#endif /* !_LIBC_LIMITS_H_ */ + +#if defined __GNUC__ && !defined _GCC_LIMITS_H_ +/* `_GCC_LIMITS_H_' is what GCC's file defines. */ +# include_next +#endif /* __GNUC__ && !_GCC_LIMITS_H_ */ + +#ifndef _POSIX2_RE_DUP_MAX +/* The maximum number of repeated occurrences of a regular expression + * permitted when using the interval notation `\{M,N\}'. */ +#define _POSIX2_RE_DUP_MAX 255 +#endif /* _POSIX2_RE_DUP_MAX */ + +#ifndef ARG_MAX +#define ARG_MAX 4096 +#endif + +#ifndef PATH_MAX +#define PATH_MAX 4096 +#endif diff --git a/components/newlib/include/locale.h b/components/newlib/include/locale.h new file mode 100644 index 0000000000..cbd658e410 --- /dev/null +++ b/components/newlib/include/locale.h @@ -0,0 +1,64 @@ +/* + locale.h + Values appropriate for the formatting of monetary and other + numberic quantities. +*/ + +#ifndef _LOCALE_H_ +#define _LOCALE_H_ + +#include "_ansi.h" + +#define __need_NULL +#include + +#define LC_ALL 0 +#define LC_COLLATE 1 +#define LC_CTYPE 2 +#define LC_MONETARY 3 +#define LC_NUMERIC 4 +#define LC_TIME 5 +#define LC_MESSAGES 6 + +_BEGIN_STD_C + +struct lconv +{ + char *decimal_point; + char *thousands_sep; + char *grouping; + char *int_curr_symbol; + char *currency_symbol; + char *mon_decimal_point; + char *mon_thousands_sep; + char *mon_grouping; + char *positive_sign; + char *negative_sign; + char int_frac_digits; + char frac_digits; + char p_cs_precedes; + char p_sep_by_space; + char n_cs_precedes; + char n_sep_by_space; + char p_sign_posn; + char n_sign_posn; + char int_n_cs_precedes; + char int_n_sep_by_space; + char int_n_sign_posn; + char int_p_cs_precedes; + char int_p_sep_by_space; + char int_p_sign_posn; +}; + +#ifndef _REENT_ONLY +char *_EXFUN(setlocale,(int category, const char *locale)); +struct lconv *_EXFUN(localeconv,(void)); +#endif + +struct _reent; +char *_EXFUN(_setlocale_r,(struct _reent *, int category, const char *locale)); +struct lconv *_EXFUN(_localeconv_r,(struct _reent *)); + +_END_STD_C + +#endif /* _LOCALE_H_ */ diff --git a/components/newlib/include/machine/_default_types.h b/components/newlib/include/machine/_default_types.h new file mode 100644 index 0000000000..03bdc523e3 --- /dev/null +++ b/components/newlib/include/machine/_default_types.h @@ -0,0 +1,56 @@ +/* + * _default_types implementation for xtensa lx106 arch + * + * Simplified version of generic _default_types.h, ignores gcc + * built-in standard types. + */ + +#ifndef _MACHINE__DEFAULT_TYPES_H +#define _MACHINE__DEFAULT_TYPES_H + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +typedef signed char __int8_t ; +typedef unsigned char __uint8_t ; +#define ___int8_t_defined 1 + +typedef signed short __int16_t; +typedef unsigned short __uint16_t; +#define ___int16_t_defined 1 + +typedef signed int __int32_t; +typedef unsigned int __uint32_t; +#define ___int32_t_defined 1 + +typedef signed long long __int64_t; +typedef unsigned long long __uint64_t; +#define ___int64_t_defined 1 + +typedef __int8_t __int_least8_t; +typedef __uint8_t __uint_least8_t; +#define ___int_least8_t_defined + +typedef __int16_t __int_least16_t; +typedef __uint16_t __uint_least16_t; +#define ___int_least16_t_defined + +typedef __int32_t __int_least32_t; +typedef __uint32_t __uint_least32_t; +#define ___int_least32_t_defined + +typedef __int64_t __int_least64_t; +typedef __uint64_t __uint_least64_t; +#define ___int_least64_t_defined + +typedef __INTPTR_TYPE__ __intptr_t; +typedef __UINTPTR_TYPE__ __uintptr_t; + +#ifdef __cplusplus +} +#endif + +#endif /* _MACHINE__DEFAULT_TYPES_H */ diff --git a/components/newlib/include/machine/_types.h b/components/newlib/include/machine/_types.h new file mode 100644 index 0000000000..17e6d51e3d --- /dev/null +++ b/components/newlib/include/machine/_types.h @@ -0,0 +1,8 @@ +/* + * $Id$ + */ + +#ifndef _MACHINE__TYPES_H +#define _MACHINE__TYPES_H +#include +#endif diff --git a/components/newlib/include/machine/ansi.h b/components/newlib/include/machine/ansi.h new file mode 100644 index 0000000000..737b6d0666 --- /dev/null +++ b/components/newlib/include/machine/ansi.h @@ -0,0 +1 @@ +/* dummy header file to support BSD compiler */ diff --git a/components/newlib/include/machine/endian.h b/components/newlib/include/machine/endian.h new file mode 100644 index 0000000000..07ebc8f63a --- /dev/null +++ b/components/newlib/include/machine/endian.h @@ -0,0 +1,20 @@ +#ifndef __MACHINE_ENDIAN_H__ + +#include + +#ifndef BIG_ENDIAN +#define BIG_ENDIAN 4321 +#endif +#ifndef LITTLE_ENDIAN +#define LITTLE_ENDIAN 1234 +#endif + +#ifndef BYTE_ORDER +#if defined(__IEEE_LITTLE_ENDIAN) || defined(__IEEE_BYTES_LITTLE_ENDIAN) +#define BYTE_ORDER LITTLE_ENDIAN +#else +#define BYTE_ORDER BIG_ENDIAN +#endif +#endif + +#endif /* __MACHINE_ENDIAN_H__ */ diff --git a/components/newlib/include/machine/fastmath.h b/components/newlib/include/machine/fastmath.h new file mode 100644 index 0000000000..b13befa228 --- /dev/null +++ b/components/newlib/include/machine/fastmath.h @@ -0,0 +1,100 @@ +#ifdef __sysvnecv70_target +double EXFUN(fast_sin,(double)); +double EXFUN(fast_cos,(double)); +double EXFUN(fast_tan,(double)); + +double EXFUN(fast_asin,(double)); +double EXFUN(fast_acos,(double)); +double EXFUN(fast_atan,(double)); + +double EXFUN(fast_sinh,(double)); +double EXFUN(fast_cosh,(double)); +double EXFUN(fast_tanh,(double)); + +double EXFUN(fast_asinh,(double)); +double EXFUN(fast_acosh,(double)); +double EXFUN(fast_atanh,(double)); + +double EXFUN(fast_abs,(double)); +double EXFUN(fast_sqrt,(double)); +double EXFUN(fast_exp2,(double)); +double EXFUN(fast_exp10,(double)); +double EXFUN(fast_expe,(double)); +double EXFUN(fast_log10,(double)); +double EXFUN(fast_log2,(double)); +double EXFUN(fast_loge,(double)); + + +#define sin(x) fast_sin(x) +#define cos(x) fast_cos(x) +#define tan(x) fast_tan(x) +#define asin(x) fast_asin(x) +#define acos(x) fast_acos(x) +#define atan(x) fast_atan(x) +#define sinh(x) fast_sinh(x) +#define cosh(x) fast_cosh(x) +#define tanh(x) fast_tanh(x) +#define asinh(x) fast_asinh(x) +#define acosh(x) fast_acosh(x) +#define atanh(x) fast_atanh(x) +#define abs(x) fast_abs(x) +#define sqrt(x) fast_sqrt(x) +#define exp2(x) fast_exp2(x) +#define exp10(x) fast_exp10(x) +#define expe(x) fast_expe(x) +#define log10(x) fast_log10(x) +#define log2(x) fast_log2(x) +#define loge(x) fast_loge(x) + +#ifdef _HAVE_STDC +/* These functions are in assembler, they really do take floats. This + can only be used with a real ANSI compiler */ + +float EXFUN(fast_sinf,(float)); +float EXFUN(fast_cosf,(float)); +float EXFUN(fast_tanf,(float)); + +float EXFUN(fast_asinf,(float)); +float EXFUN(fast_acosf,(float)); +float EXFUN(fast_atanf,(float)); + +float EXFUN(fast_sinhf,(float)); +float EXFUN(fast_coshf,(float)); +float EXFUN(fast_tanhf,(float)); + +float EXFUN(fast_asinhf,(float)); +float EXFUN(fast_acoshf,(float)); +float EXFUN(fast_atanhf,(float)); + +float EXFUN(fast_absf,(float)); +float EXFUN(fast_sqrtf,(float)); +float EXFUN(fast_exp2f,(float)); +float EXFUN(fast_exp10f,(float)); +float EXFUN(fast_expef,(float)); +float EXFUN(fast_log10f,(float)); +float EXFUN(fast_log2f,(float)); +float EXFUN(fast_logef,(float)); +#define sinf(x) fast_sinf(x) +#define cosf(x) fast_cosf(x) +#define tanf(x) fast_tanf(x) +#define asinf(x) fast_asinf(x) +#define acosf(x) fast_acosf(x) +#define atanf(x) fast_atanf(x) +#define sinhf(x) fast_sinhf(x) +#define coshf(x) fast_coshf(x) +#define tanhf(x) fast_tanhf(x) +#define asinhf(x) fast_asinhf(x) +#define acoshf(x) fast_acoshf(x) +#define atanhf(x) fast_atanhf(x) +#define absf(x) fast_absf(x) +#define sqrtf(x) fast_sqrtf(x) +#define exp2f(x) fast_exp2f(x) +#define exp10f(x) fast_exp10f(x) +#define expef(x) fast_expef(x) +#define log10f(x) fast_log10f(x) +#define log2f(x) fast_log2f(x) +#define logef(x) fast_logef(x) +#endif +/* Override the functions defined in math.h */ +#endif /* __sysvnecv70_target */ + diff --git a/components/newlib/include/machine/ieeefp.h b/components/newlib/include/machine/ieeefp.h new file mode 100644 index 0000000000..f11dc05353 --- /dev/null +++ b/components/newlib/include/machine/ieeefp.h @@ -0,0 +1,434 @@ +#ifndef __IEEE_BIG_ENDIAN +#ifndef __IEEE_LITTLE_ENDIAN + +/* This file can define macros to choose variations of the IEEE float + format: + + _FLT_LARGEST_EXPONENT_IS_NORMAL + + Defined if the float format uses the largest exponent for finite + numbers rather than NaN and infinity representations. Such a + format cannot represent NaNs or infinities at all, but it's FLT_MAX + is twice the IEEE value. + + _FLT_NO_DENORMALS + + Defined if the float format does not support IEEE denormals. Every + float with a zero exponent is taken to be a zero representation. + + ??? At the moment, there are no equivalent macros above for doubles and + the macros are not fully supported by --enable-newlib-hw-fp. + + __IEEE_BIG_ENDIAN + + Defined if the float format is big endian. This is mutually exclusive + with __IEEE_LITTLE_ENDIAN. + + __IEEE_LITTLE_ENDIAN + + Defined if the float format is little endian. This is mutually exclusive + with __IEEE_BIG_ENDIAN. + + Note that one of __IEEE_BIG_ENDIAN or __IEEE_LITTLE_ENDIAN must be specified for a + platform or error will occur. + + __IEEE_BYTES_LITTLE_ENDIAN + + This flag is used in conjunction with __IEEE_BIG_ENDIAN to describe a situation + whereby multiple words of an IEEE floating point are in big endian order, but the + words themselves are little endian with respect to the bytes. + + _DOUBLE_IS_32BITS + + This is used on platforms that support double by using the 32-bit IEEE + float type. + + _FLOAT_ARG + + This represents what type a float arg is passed as. It is used when the type is + not promoted to double. + +*/ + +#if (defined(__arm__) || defined(__thumb__)) && !defined(__MAVERICK__) +/* ARM traditionally used big-endian words; and within those words the + byte ordering was big or little endian depending upon the target. + Modern floating-point formats are naturally ordered; in this case + __VFP_FP__ will be defined, even if soft-float. */ +#ifdef __VFP_FP__ +# ifdef __ARMEL__ +# define __IEEE_LITTLE_ENDIAN +# else +# define __IEEE_BIG_ENDIAN +# endif +#else +# define __IEEE_BIG_ENDIAN +# ifdef __ARMEL__ +# define __IEEE_BYTES_LITTLE_ENDIAN +# endif +#endif +#endif + +#if defined (__aarch64__) +#if defined (__AARCH64EL__) +#define __IEEE_LITTLE_ENDIAN +#else +#define __IEEE_BIG_ENDIAN +#endif +#endif + +#ifdef __epiphany__ +#define __IEEE_LITTLE_ENDIAN +#define Sudden_Underflow 1 +#endif + +#ifdef __hppa__ +#define __IEEE_BIG_ENDIAN +#endif + +#ifdef __nds32__ +#ifdef __big_endian__ +#define __IEEE_BIG_ENDIAN +#else +#define __IEEE_LITTLE_ENDIAN +#endif +#endif + +#ifdef __SPU__ +#define __IEEE_BIG_ENDIAN + +#define isfinite(__y) \ + (__extension__ ({int __cy; \ + (sizeof (__y) == sizeof (float)) ? (1) : \ + (__cy = fpclassify(__y)) != FP_INFINITE && __cy != FP_NAN;})) + +#define isinf(__x) ((sizeof (__x) == sizeof (float)) ? (0) : __isinfd(__x)) +#define isnan(__x) ((sizeof (__x) == sizeof (float)) ? (0) : __isnand(__x)) + +/* + * Macros for use in ieeefp.h. We can't just define the real ones here + * (like those above) as we have name space issues when this is *not* + * included via generic the ieeefp.h. + */ +#define __ieeefp_isnanf(x) 0 +#define __ieeefp_isinff(x) 0 +#define __ieeefp_finitef(x) 1 +#endif + +#ifdef __sparc__ +#ifdef __LITTLE_ENDIAN_DATA__ +#define __IEEE_LITTLE_ENDIAN +#else +#define __IEEE_BIG_ENDIAN +#endif +#endif + +#if defined(__m68k__) || defined(__mc68000__) +#define __IEEE_BIG_ENDIAN +#endif + +#if defined(__mc68hc11__) || defined(__mc68hc12__) || defined(__mc68hc1x__) +#define __IEEE_BIG_ENDIAN +#ifdef __HAVE_SHORT_DOUBLE__ +# define _DOUBLE_IS_32BITS +#endif +#endif + +#if defined (__H8300__) || defined (__H8300H__) || defined (__H8300S__) || defined (__H8500__) || defined (__H8300SX__) +#define __IEEE_BIG_ENDIAN +#define _FLOAT_ARG float +#define _DOUBLE_IS_32BITS +#endif + +#if defined (__xc16x__) || defined (__xc16xL__) || defined (__xc16xS__) +#define __IEEE_LITTLE_ENDIAN +#define _FLOAT_ARG float +#define _DOUBLE_IS_32BITS +#endif + + +#ifdef __sh__ +#ifdef __LITTLE_ENDIAN__ +#define __IEEE_LITTLE_ENDIAN +#else +#define __IEEE_BIG_ENDIAN +#endif +#if defined(__SH2E__) || defined(__SH3E__) || defined(__SH4_SINGLE_ONLY__) || defined(__SH2A_SINGLE_ONLY__) +#define _DOUBLE_IS_32BITS +#endif +#endif + +#ifdef _AM29K +#define __IEEE_BIG_ENDIAN +#endif + +#ifdef _WIN32 +#define __IEEE_LITTLE_ENDIAN +#endif + +#ifdef __i386__ +#define __IEEE_LITTLE_ENDIAN +#endif + +#ifdef __i960__ +#define __IEEE_LITTLE_ENDIAN +#endif + +#ifdef __lm32__ +#define __IEEE_BIG_ENDIAN +#endif + +#ifdef __M32R__ +#define __IEEE_BIG_ENDIAN +#endif + +#if defined(_C4x) || defined(_C3x) +#define __IEEE_BIG_ENDIAN +#define _DOUBLE_IS_32BITS +#endif + +#ifdef __TMS320C6X__ +#ifdef _BIG_ENDIAN +#define __IEEE_BIG_ENDIAN +#else +#define __IEEE_LITTLE_ENDIAN +#endif +#endif + +#ifdef __TIC80__ +#define __IEEE_LITTLE_ENDIAN +#endif + +#ifdef __MIPSEL__ +#define __IEEE_LITTLE_ENDIAN +#endif +#ifdef __MIPSEB__ +#define __IEEE_BIG_ENDIAN +#endif + +#ifdef __MMIX__ +#define __IEEE_BIG_ENDIAN +#endif + +#ifdef __D30V__ +#define __IEEE_BIG_ENDIAN +#endif + +/* necv70 was __IEEE_LITTLE_ENDIAN. */ + +#ifdef __W65__ +#define __IEEE_LITTLE_ENDIAN +#define _DOUBLE_IS_32BITS +#endif + +#if defined(__Z8001__) || defined(__Z8002__) +#define __IEEE_BIG_ENDIAN +#endif + +#ifdef __m88k__ +#define __IEEE_BIG_ENDIAN +#endif + +#ifdef __mn10300__ +#define __IEEE_LITTLE_ENDIAN +#endif + +#ifdef __mn10200__ +#define __IEEE_LITTLE_ENDIAN +#define _DOUBLE_IS_32BITS +#endif + +#ifdef __v800 +#define __IEEE_LITTLE_ENDIAN +#endif + +#ifdef __v850 +#define __IEEE_LITTLE_ENDIAN +#endif + +#ifdef __D10V__ +#define __IEEE_BIG_ENDIAN +#if __DOUBLE__ == 32 +#define _DOUBLE_IS_32BITS +#endif +#endif + +#ifdef __PPC__ +#if (defined(_BIG_ENDIAN) && _BIG_ENDIAN) || (defined(_AIX) && _AIX) +#define __IEEE_BIG_ENDIAN +#else +#if (defined(_LITTLE_ENDIAN) && _LITTLE_ENDIAN) || (defined(__sun__) && __sun__) || (defined(_WIN32) && _WIN32) +#define __IEEE_LITTLE_ENDIAN +#endif +#endif +#endif + +#ifdef __xstormy16__ +#define __IEEE_LITTLE_ENDIAN +#endif + +#ifdef __arc__ +#ifdef __big_endian__ +#define __IEEE_BIG_ENDIAN +#else +#define __IEEE_LITTLE_ENDIAN +#endif +#endif + +#ifdef __CRX__ +#define __IEEE_LITTLE_ENDIAN +#endif + +#ifdef __fr30__ +#define __IEEE_BIG_ENDIAN +#endif + +#ifdef __mcore__ +#define __IEEE_BIG_ENDIAN +#endif + +#ifdef __mt__ +#define __IEEE_BIG_ENDIAN +#endif + +#ifdef __frv__ +#define __IEEE_BIG_ENDIAN +#endif + +#ifdef __moxie__ +#ifdef __MOXIE_BIG_ENDIAN__ +#define __IEEE_BIG_ENDIAN +#else +#define __IEEE_LITTLE_ENDIAN +#endif +#endif + +#ifdef __ia64__ +#ifdef __BIG_ENDIAN__ +#define __IEEE_BIG_ENDIAN +#else +#define __IEEE_LITTLE_ENDIAN +#endif +#endif + +#ifdef __AVR__ +#define __IEEE_LITTLE_ENDIAN +#define _DOUBLE_IS_32BITS +#endif + +#if defined(__or1k__) || defined(__OR1K__) || defined(__OR1KND__) +#define __IEEE_BIG_ENDIAN +#endif + +#ifdef __IP2K__ +#define __IEEE_BIG_ENDIAN +#define __SMALL_BITFIELDS +#define _DOUBLE_IS_32BITS +#endif + +#ifdef __iq2000__ +#define __IEEE_BIG_ENDIAN +#endif + +#ifdef __MAVERICK__ +#ifdef __ARMEL__ +# define __IEEE_LITTLE_ENDIAN +#else /* must be __ARMEB__ */ +# define __IEEE_BIG_ENDIAN +#endif /* __ARMEL__ */ +#endif /* __MAVERICK__ */ + +#ifdef __m32c__ +#define __IEEE_LITTLE_ENDIAN +#define __SMALL_BITFIELDS +#endif + +#ifdef __CRIS__ +#define __IEEE_LITTLE_ENDIAN +#endif + +#ifdef __BFIN__ +#define __IEEE_LITTLE_ENDIAN +#endif + +#ifdef __x86_64__ +#define __IEEE_LITTLE_ENDIAN +#endif + +#ifdef __mep__ +#ifdef __LITTLE_ENDIAN__ +#define __IEEE_LITTLE_ENDIAN +#else +#define __IEEE_BIG_ENDIAN +#endif +#endif + +#ifdef __MICROBLAZE__ +#ifndef __MICROBLAZEEL__ +#define __IEEE_BIG_ENDIAN +#else +#define __IEEE_LITTLE_ENDIAN +#endif +#endif + +#ifdef __MSP430__ +#define __IEEE_LITTLE_ENDIAN +#define __SMALL_BITFIELDS /* 16 Bit INT */ +#endif + +#ifdef __RL78__ +#define __IEEE_LITTLE_ENDIAN +#define __SMALL_BITFIELDS /* 16 Bit INT */ +#ifndef __RL78_64BIT_DOUBLES__ +#define _DOUBLE_IS_32BITS +#endif +#endif + +#ifdef __RX__ + +#ifdef __RX_BIG_ENDIAN__ +#define __IEEE_BIG_ENDIAN +#else +#define __IEEE_LITTLE_ENDIAN +#endif + +#ifndef __RX_64BIT_DOUBLES__ +#define _DOUBLE_IS_32BITS +#endif + +#ifdef __RX_16BIT_INTS__ +#define __SMALL_BITFIELDS +#endif + +#endif + +#if (defined(__CR16__) || defined(__CR16C__) ||defined(__CR16CP__)) +#define __IEEE_LITTLE_ENDIAN +#define __SMALL_BITFIELDS /* 16 Bit INT */ +#endif + +#ifdef __NIOS2__ +# ifdef __nios2_big_endian__ +# define __IEEE_BIG_ENDIAN +# else +# define __IEEE_LITTLE_ENDIAN +# endif +#endif + +#if (defined(__XTENSA__)) +# ifdef __XTENSA_EB__ +# define __IEEE_BIG_ENDIAN +# else +# define __IEEE_LITTLE_ENDIAN +# endif +#endif + +#ifndef __IEEE_BIG_ENDIAN +#ifndef __IEEE_LITTLE_ENDIAN +#error Endianess not declared!! +#endif /* not __IEEE_LITTLE_ENDIAN */ +#endif /* not __IEEE_BIG_ENDIAN */ + +#endif /* not __IEEE_LITTLE_ENDIAN */ +#endif /* not __IEEE_BIG_ENDIAN */ + diff --git a/components/newlib/include/machine/malloc.h b/components/newlib/include/machine/malloc.h new file mode 100644 index 0000000000..fdada9ed7f --- /dev/null +++ b/components/newlib/include/machine/malloc.h @@ -0,0 +1,8 @@ +#ifndef _MACHMALLOC_H_ +#define _MACHMALLOC_H_ + +/* place holder so platforms may add malloc.h extensions */ + +#endif /* _MACHMALLOC_H_ */ + + diff --git a/components/newlib/include/machine/param.h b/components/newlib/include/machine/param.h new file mode 100644 index 0000000000..bdf8bf70f5 --- /dev/null +++ b/components/newlib/include/machine/param.h @@ -0,0 +1 @@ +/* Place holder for machine-specific param.h. */ diff --git a/components/newlib/include/machine/setjmp-dj.h b/components/newlib/include/machine/setjmp-dj.h new file mode 100644 index 0000000000..6ca5e65269 --- /dev/null +++ b/components/newlib/include/machine/setjmp-dj.h @@ -0,0 +1,43 @@ +/* + * Copyright (C) 1991 DJ Delorie + * All rights reserved. + * + * Redistribution, modification, and use in source and binary forms is permitted + * provided that the above copyright notice and following paragraph are + * duplicated in all such forms. + * + * This file is distributed WITHOUT ANY WARRANTY; without even the implied + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + */ + +/* Modified to use SETJMP_DJ_H rather than SETJMP_H to avoid + conflicting with setjmp.h. Ian Taylor, Cygnus support, April, + 1993. */ + +#ifndef _SETJMP_DJ_H_ +#define _SETJMP_DJ_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct { + unsigned long eax; + unsigned long ebx; + unsigned long ecx; + unsigned long edx; + unsigned long esi; + unsigned long edi; + unsigned long ebp; + unsigned long esp; + unsigned long eip; +} jmp_buf[1]; + +extern int setjmp(jmp_buf); +extern void longjmp(jmp_buf, int); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/components/newlib/include/machine/setjmp.h b/components/newlib/include/machine/setjmp.h new file mode 100644 index 0000000000..9f9d9e49b5 --- /dev/null +++ b/components/newlib/include/machine/setjmp.h @@ -0,0 +1,453 @@ + +_BEGIN_STD_C + +#if defined(__or1k__) || defined(__or1knd__) +#define _JBLEN 31 /* 32 GPRs - r0 */ +#define _JBTYPE unsigned long +#endif + +#if defined(__arm__) || defined(__thumb__) +/* + * All callee preserved registers: + * v1 - v7, fp, ip, sp, lr, f4, f5, f6, f7 + */ +#define _JBLEN 23 +#endif + +#if defined(__aarch64__) +#define _JBLEN 22 +#define _JBTYPE long long +#endif + +#if defined(__AVR__) +#define _JBLEN 24 +#endif + +#ifdef __sparc__ +/* + * onsstack,sigmask,sp,pc,npc,psr,g1,o0,wbcnt (sigcontext). + * All else recovered by under/over(flow) handling. + */ +#define _JBLEN 13 +#endif + +#ifdef __BFIN__ +#define _JBLEN 40 +#endif + +#ifdef __epiphany__ +/* All callee preserved registers: r4-r10,fp, sp, lr,r15, r32-r39 */ +#define _JBTYPE long long +#define _JBLEN 10 +#endif + +/* necv70 was 9 as well. */ + +#if defined(__m68k__) || defined(__mc68000__) +/* + * onsstack,sigmask,sp,pc,psl,d2-d7,a2-a6, + * fp2-fp7 for 68881. + * All else recovered by under/over(flow) handling. + */ +#define _JBLEN 34 +#endif + +#if defined(__mc68hc11__) || defined(__mc68hc12__) || defined(__mc68hc1x__) +/* + * D, X, Y are not saved. + * Only take into account the pseudo soft registers (max 32). + */ +#define _JBLEN 32 +#endif + +#ifdef __nds32__ +/* 17 words for GPRs, + 1 word for $fpcfg.freg and 30 words for FPUs + Reserved 2 words for aligement-adjustment. When storeing double-precision + floating-point register into memory, the address has to be + double-word-aligned. + Check libc/machine/nds32/setjmp.S for more information. */ +#if __NDS32_EXT_FPU_SP__ || __NDS32_EXT_FPU_DP__ +#define _JBLEN 50 +#else +#define _JBLEN 18 +#endif +#endif + +#if defined(__Z8001__) || defined(__Z8002__) +/* 16 regs + pc */ +#define _JBLEN 20 +#endif + +#ifdef _AM29K +/* + * onsstack,sigmask,sp,pc,npc,psr,g1,o0,wbcnt (sigcontext). + * All else recovered by under/over(flow) handling. + */ +#define _JBLEN 9 +#endif + +#ifdef __i386__ +# if defined(__CYGWIN__) && !defined (_JBLEN) +# define _JBLEN (13 * 4) +# elif defined(__unix__) || defined(__rtems__) +# define _JBLEN 9 +# else +# include "setjmp-dj.h" +# endif +#endif + +#ifdef __x86_64__ +# ifdef __CYGWIN__ +# define _JBTYPE long +# define _JBLEN 32 +# else +# define _JBTYPE long long +# define _JBLEN 8 +# endif +#endif + +#ifdef __i960__ +#define _JBLEN 35 +#endif + +#ifdef __M32R__ +/* Only 8 words are currently needed. 10 gives us some slop if we need + to expand. */ +#define _JBLEN 10 +#endif + +#ifdef __mips__ +# if defined(__mips64) +# define _JBTYPE long long +# endif +# ifdef __mips_soft_float +# define _JBLEN 11 +# else +# define _JBLEN 23 +# endif +#endif + +#ifdef __m88000__ +#define _JBLEN 21 +#endif + +#ifdef __H8300__ +#define _JBLEN 5 +#define _JBTYPE int +#endif + +#ifdef __H8300H__ +/* same as H8/300 but registers are twice as big */ +#define _JBLEN 5 +#define _JBTYPE long +#endif + +#if defined (__H8300S__) || defined (__H8300SX__) +/* same as H8/300 but registers are twice as big */ +#define _JBLEN 5 +#define _JBTYPE long +#endif + +#ifdef __H8500__ +#define _JBLEN 4 +#endif + +#ifdef __sh__ +#if __SH5__ +#define _JBLEN 50 +#define _JBTYPE long long +#else +#define _JBLEN 20 +#endif /* __SH5__ */ +#endif + +#ifdef __v800 +#define _JBLEN 28 +#endif + +#ifdef __PPC__ +#ifdef __ALTIVEC__ +#define _JBLEN 64 +#else +#define _JBLEN 32 +#endif +#define _JBTYPE double +#endif + +#ifdef __MICROBLAZE__ +#define _JBLEN 20 +#define _JBTYPE unsigned int +#endif + +#ifdef __hppa__ +/* %r30, %r2-%r18, %r27, pad, %fr12-%fr15. + Note space exists for the FP registers, but they are not + saved. */ +#define _JBLEN 28 +#endif + +#if defined(__mn10300__) || defined(__mn10200__) +#ifdef __AM33_2__ +#define _JBLEN 26 +#else +/* A guess */ +#define _JBLEN 10 +#endif +#endif + +#ifdef __v850 +/* I think our setjmp is saving 15 regs at the moment. Gives us one word + slop if we need to expand. */ +#define _JBLEN 16 +#endif + +#if defined(_C4x) +#define _JBLEN 10 +#endif +#if defined(_C3x) +#define _JBLEN 9 +#endif + +#ifdef __TMS320C6X__ +#define _JBLEN 13 +#endif + +#ifdef __TIC80__ +#define _JBLEN 13 +#endif + +#ifdef __D10V__ +#define _JBLEN 8 +#endif + +#ifdef __D30V__ +#define _JBLEN ((64 /* GPR */ + (2*2) /* ACs */ + 18 /* CRs */) / 2) +#define _JBTYPE double +#endif + +#ifdef __frv__ +#define _JBLEN (68/2) /* room for 68 32-bit regs */ +#define _JBTYPE double +#endif + +#ifdef __moxie__ +#define _JBLEN 16 +#endif + +#ifdef __CRX__ +#define _JBLEN 9 +#endif + +#if (defined(__CR16__) || defined(__CR16C__) ||defined(__CR16CP__)) +/* r6, r7, r8, r9, r10, r11, r12 (r12L, r12H), + * r13 (r13L, r13H), ra(raL, raH), sp(spL, spH) */ +#define _JBLEN 14 +#define _JBTYPE unsigned short +#endif + +#ifdef __fr30__ +#define _JBLEN 10 +#endif + +#ifdef __iq2000__ +#define _JBLEN 32 +#endif + +#ifdef __mcore__ +#define _JBLEN 16 +#endif + +#ifdef __MMIX__ +/* Using a layout compatible with GCC's built-in. */ +#define _JBLEN 5 +#define _JBTYPE unsigned long +#endif + +#ifdef __mt__ +#define _JBLEN 16 +#endif + +#ifdef __SPU__ +#define _JBLEN 50 +#define _JBTYPE __vector signed int +#endif + +#ifdef __xstormy16__ +/* 4 GPRs plus SP plus PC. */ +#define _JBLEN 8 +#endif + +#ifdef __XTENSA__ +#if __XTENSA_WINDOWED_ABI__ + +/* The jmp_buf structure for Xtensa windowed ABI holds the following + (where "proc" is the procedure that calls setjmp): 4-12 registers + from the window of proc, the 4 words from the save area at proc's $sp + (in case a subsequent alloca in proc moves $sp), and the return + address within proc. Everything else is saved on the stack in the + normal save areas. The jmp_buf structure is: + + struct jmp_buf { + int regs[12]; + int save[4]; + void *return_address; + } + + See the setjmp code for details. */ + +#define _JBLEN 17 /* 12 + 4 + 1 */ + +#else /* __XTENSA_CALL0_ABI__ */ + +#define _JBLEN 6 /* a0, a1, a12, a13, a14, a15 */ + +#endif /* __XTENSA_CALL0_ABI__ */ +#endif /* __XTENSA__ */ + +#ifdef __mep__ +/* 16 GPRs, pc, hi, lo */ +#define _JBLEN 19 +#endif + +#ifdef __CRIS__ +#define _JBLEN 18 +#endif + +#ifdef __lm32__ +#define _JBLEN 19 +#endif + +#ifdef __m32c__ +#if defined(__r8c_cpu__) || defined(__m16c_cpu__) +#define _JBLEN (22/2) +#else +#define _JBLEN (34/2) +#endif +#define _JBTYPE unsigned short +#endif /* __m32c__ */ + +#ifdef __MSP430__ +#define _JBLEN 9 + +#ifdef __MSP430X_LARGE__ +#define _JBTYPE unsigned long +#else +#define _JBTYPE unsigned short +#endif +#endif + +#ifdef __RL78__ +/* Three banks of registers, SP, CS, ES, PC */ +#define _JBLEN (8*3+8) +#define _JBTYPE unsigned char +#endif + +/* + * There are two versions of setjmp()/longjmp(): + * 1) Compiler (gcc) built-in versions. + * 2) Function-call versions. + * + * The built-in versions are used most of the time. When used, gcc replaces + * calls to setjmp()/longjmp() with inline assembly code. The built-in + * versions save/restore a variable number of registers. + + * _JBLEN is set to 40 to be ultra-safe with the built-in versions. + * It only needs to be 12 for the function-call versions + * but this data structure is used by both versions. + */ +#ifdef __NIOS2__ +#define _JBLEN 40 +#define _JBTYPE unsigned long +#endif + +#ifdef __RX__ +#define _JBLEN 0x44 +#endif + +#ifdef _JBLEN +#ifdef _JBTYPE +typedef _JBTYPE jmp_buf[_JBLEN]; +#else +typedef int jmp_buf[_JBLEN]; +#endif +#endif + +_END_STD_C + +#if defined(__CYGWIN__) || defined(__rtems__) +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/* POSIX sigsetjmp/siglongjmp macros */ +#ifdef _JBTYPE +typedef _JBTYPE sigjmp_buf[_JBLEN+1+((sizeof (_JBTYPE) + sizeof (sigset_t) - 1) + /sizeof (_JBTYPE))]; +#else +typedef int sigjmp_buf[_JBLEN+1+(sizeof (sigset_t)/sizeof (int))]; +#endif + +#define _SAVEMASK _JBLEN +#define _SIGMASK (_JBLEN+1) + +#ifdef __CYGWIN__ +# define _CYGWIN_WORKING_SIGSETJMP +#endif + +#ifdef _POSIX_THREADS +#define __SIGMASK_FUNC pthread_sigmask +#else +#define __SIGMASK_FUNC sigprocmask +#endif + +#if defined(__GNUC__) + +#define sigsetjmp(env, savemask) \ + __extension__ \ + ({ \ + sigjmp_buf *_sjbuf = &(env); \ + ((*_sjbuf)[_SAVEMASK] = savemask,\ + __SIGMASK_FUNC (SIG_SETMASK, 0, (sigset_t *)((*_sjbuf) + _SIGMASK)),\ + setjmp (*_sjbuf)); \ + }) + +#define siglongjmp(env, val) \ + __extension__ \ + ({ \ + sigjmp_buf *_sjbuf = &(env); \ + ((((*_sjbuf)[_SAVEMASK]) ? \ + __SIGMASK_FUNC (SIG_SETMASK, (sigset_t *)((*_sjbuf) + _SIGMASK), 0)\ + : 0), \ + longjmp (*_sjbuf, val)); \ + }) + +#else /* !__GNUC__ */ + +#define sigsetjmp(env, savemask) ((env)[_SAVEMASK] = savemask,\ + __SIGMASK_FUNC (SIG_SETMASK, 0, (sigset_t *) ((env) + _SIGMASK)),\ + setjmp (env)) + +#define siglongjmp(env, val) ((((env)[_SAVEMASK])?\ + __SIGMASK_FUNC (SIG_SETMASK, (sigset_t *) ((env) + _SIGMASK), 0):0),\ + longjmp (env, val)) + +#endif + +/* POSIX _setjmp/_longjmp, maintained for XSI compatibility. These + are equivalent to sigsetjmp/siglongjmp when not saving the signal mask. + New applications should use sigsetjmp/siglongjmp instead. */ +#ifdef __CYGWIN__ +extern void _longjmp(jmp_buf, int); +extern int _setjmp(jmp_buf); +#else +#define _setjmp(env) sigsetjmp ((env), 0) +#define _longjmp(env, val) siglongjmp ((env), (val)) +#endif + +#ifdef __cplusplus +} +#endif +#endif /* __CYGWIN__ or __rtems__ */ diff --git a/components/newlib/include/machine/stdlib.h b/components/newlib/include/machine/stdlib.h new file mode 100644 index 0000000000..fa3f3a1390 --- /dev/null +++ b/components/newlib/include/machine/stdlib.h @@ -0,0 +1,8 @@ +#ifndef _MACHSTDLIB_H_ +#define _MACHSTDLIB_H_ + +/* place holder so platforms may add stdlib.h extensions */ + +#endif /* _MACHSTDLIB_H_ */ + + diff --git a/components/newlib/include/machine/termios.h b/components/newlib/include/machine/termios.h new file mode 100644 index 0000000000..41fd459385 --- /dev/null +++ b/components/newlib/include/machine/termios.h @@ -0,0 +1 @@ +#define __MAX_BAUD B4000000 diff --git a/components/newlib/include/machine/time.h b/components/newlib/include/machine/time.h new file mode 100644 index 0000000000..06e2ccffb1 --- /dev/null +++ b/components/newlib/include/machine/time.h @@ -0,0 +1,19 @@ +#ifndef _MACHTIME_H_ +#define _MACHTIME_H_ + +#if defined(__rtems__) +#define _CLOCKS_PER_SEC_ sysconf(_SC_CLK_TCK) +#else /* !__rtems__ */ +#if defined(__aarch64__) || defined(__arm__) || defined(__thumb__) +#define _CLOCKS_PER_SEC_ 100 +#endif +#endif /* !__rtems__ */ + +#ifdef __SPU__ +#include +int nanosleep (const struct timespec *, struct timespec *); +#endif + +#endif /* _MACHTIME_H_ */ + + diff --git a/components/newlib/include/machine/types.h b/components/newlib/include/machine/types.h new file mode 100644 index 0000000000..40a75faa5b --- /dev/null +++ b/components/newlib/include/machine/types.h @@ -0,0 +1,30 @@ +#ifndef _MACHTYPES_H_ +#define _MACHTYPES_H_ + +/* + * The following section is RTEMS specific and is needed to more + * closely match the types defined in the BSD machine/types.h. + * This is needed to let the RTEMS/BSD TCP/IP stack compile. + */ +#if defined(__rtems__) +#include +#endif + +#define _CLOCK_T_ unsigned long /* clock() */ +#define _TIME_T_ long /* time() */ +#define _CLOCKID_T_ unsigned long +#define _TIMER_T_ unsigned long + +#ifndef _HAVE_SYSTYPES +typedef long int __off_t; +typedef int __pid_t; +#ifdef __GNUC__ +__extension__ typedef long long int __loff_t; +#else +typedef long int __loff_t; +#endif +#endif + +#endif /* _MACHTYPES_H_ */ + + diff --git a/components/newlib/include/malloc.h b/components/newlib/include/malloc.h new file mode 100644 index 0000000000..41b5efdc0a --- /dev/null +++ b/components/newlib/include/malloc.h @@ -0,0 +1,169 @@ +/* malloc.h -- header file for memory routines. */ + +#ifndef _INCLUDE_MALLOC_H_ +#define _INCLUDE_MALLOC_H_ + +#include <_ansi.h> +#include + +#define __need_size_t +#include + +/* include any machine-specific extensions */ +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/* This version of struct mallinfo must match the one in + libc/stdlib/mallocr.c. */ + +struct mallinfo { + size_t arena; /* total space allocated from system */ + size_t ordblks; /* number of non-inuse chunks */ + size_t smblks; /* unused -- always zero */ + size_t hblks; /* number of mmapped regions */ + size_t hblkhd; /* total space in mmapped regions */ + size_t usmblks; /* unused -- always zero */ + size_t fsmblks; /* unused -- always zero */ + size_t uordblks; /* total allocated space */ + size_t fordblks; /* total non-inuse space */ + size_t keepcost; /* top-most, releasable (via malloc_trim) space */ +}; + +/* The routines. */ + +extern _PTR malloc _PARAMS ((size_t)); +#ifdef __CYGWIN__ +#undef _malloc_r +#define _malloc_r(r, s) malloc (s) +#else +extern _PTR _malloc_r _PARAMS ((struct _reent *, size_t)); +#endif + +extern _VOID free _PARAMS ((_PTR)); +#ifdef __CYGWIN__ +#undef _free_r +#define _free_r(r, p) free (p) +#else +extern _VOID _free_r _PARAMS ((struct _reent *, _PTR)); +#endif + +extern _PTR realloc _PARAMS ((_PTR, size_t)); +#ifdef __CYGWIN__ +#undef _realloc_r +#define _realloc_r(r, p, s) realloc (p, s) +#else +extern _PTR _realloc_r _PARAMS ((struct _reent *, _PTR, size_t)); +#endif + +extern _PTR calloc _PARAMS ((size_t, size_t)); +#ifdef __CYGWIN__ +#undef _calloc_r +#define _calloc_r(r, s1, s2) calloc (s1, s2); +#else +extern _PTR _calloc_r _PARAMS ((struct _reent *, size_t, size_t)); +#endif + +extern _PTR memalign _PARAMS ((size_t, size_t)); +#ifdef __CYGWIN__ +#undef _memalign_r +#define _memalign_r(r, s1, s2) memalign (s1, s2); +#else +extern _PTR _memalign_r _PARAMS ((struct _reent *, size_t, size_t)); +#endif + +extern struct mallinfo mallinfo _PARAMS ((void)); +#ifdef __CYGWIN__ +#undef _mallinfo_r +#define _mallinfo_r(r) mallinfo () +#else +extern struct mallinfo _mallinfo_r _PARAMS ((struct _reent *)); +#endif + +extern void malloc_stats _PARAMS ((void)); +#ifdef __CYGWIN__ +#undef _malloc_stats_r +#define _malloc_stats_r(r) malloc_stats () +#else +extern void _malloc_stats_r _PARAMS ((struct _reent *)); +#endif + +extern int mallopt _PARAMS ((int, int)); +#ifdef __CYGWIN__ +#undef _mallopt_r +#define _mallopt_r(i1, i2) mallopt (i1, i2) +#else +extern int _mallopt_r _PARAMS ((struct _reent *, int, int)); +#endif + +extern size_t malloc_usable_size _PARAMS ((_PTR)); +#ifdef __CYGWIN__ +#undef _malloc_usable_size_r +#define _malloc_usable_size_r(r, p) malloc_usable_size (p) +#else +extern size_t _malloc_usable_size_r _PARAMS ((struct _reent *, _PTR)); +#endif + +/* These aren't too useful on an embedded system, but we define them + anyhow. */ + +extern _PTR valloc _PARAMS ((size_t)); +#ifdef __CYGWIN__ +#undef _valloc_r +#define _valloc_r(r, s) valloc (s) +#else +extern _PTR _valloc_r _PARAMS ((struct _reent *, size_t)); +#endif + +extern _PTR pvalloc _PARAMS ((size_t)); +#ifdef __CYGWIN__ +#undef _pvalloc_r +#define _pvalloc_r(r, s) pvalloc (s) +#else +extern _PTR _pvalloc_r _PARAMS ((struct _reent *, size_t)); +#endif + +extern int malloc_trim _PARAMS ((size_t)); +#ifdef __CYGWIN__ +#undef _malloc_trim_r +#define _malloc_trim_r(r, s) malloc_trim (s) +#else +extern int _malloc_trim_r _PARAMS ((struct _reent *, size_t)); +#endif + +/* A compatibility routine for an earlier version of the allocator. */ + +extern _VOID mstats _PARAMS ((char *)); +#ifdef __CYGWIN__ +#undef _mstats_r +#define _mstats_r(r, p) mstats (p) +#else +extern _VOID _mstats_r _PARAMS ((struct _reent *, char *)); +#endif + +/* SVID2/XPG mallopt options */ + +#define M_MXFAST 1 /* UNUSED in this malloc */ +#define M_NLBLKS 2 /* UNUSED in this malloc */ +#define M_GRAIN 3 /* UNUSED in this malloc */ +#define M_KEEP 4 /* UNUSED in this malloc */ + +/* mallopt options that actually do something */ + +#define M_TRIM_THRESHOLD -1 +#define M_TOP_PAD -2 +#define M_MMAP_THRESHOLD -3 +#define M_MMAP_MAX -4 + +#ifndef __CYGWIN__ +/* Some systems provide this, so do too for compatibility. */ +extern void cfree _PARAMS ((_PTR)); +#endif /* __CYGWIN__ */ + +#ifdef __cplusplus +} +#endif + +#endif /* _INCLUDE_MALLOC_H_ */ diff --git a/components/newlib/include/math.h b/components/newlib/include/math.h new file mode 100644 index 0000000000..d16ce30741 --- /dev/null +++ b/components/newlib/include/math.h @@ -0,0 +1,615 @@ +#ifndef _MATH_H_ + +#define _MATH_H_ + +#include +#include +#include "_ansi.h" + +_BEGIN_STD_C + +/* __dmath, __fmath, and __ldmath are only here for backwards compatibility + * in case any code used them. They are no longer used by Newlib, itself, + * other than legacy. */ +union __dmath +{ + double d; + __ULong i[2]; +}; + +union __fmath +{ + float f; + __ULong i[1]; +}; + +#if defined(_HAVE_LONG_DOUBLE) +union __ldmath +{ + long double ld; + __ULong i[4]; +}; +#endif + +/* Natural log of 2 */ +#define _M_LN2 0.693147180559945309417 + +#if __GNUC_PREREQ (3, 3) + /* gcc >= 3.3 implicitly defines builtins for HUGE_VALx values. */ + +# ifndef HUGE_VAL +# define HUGE_VAL (__builtin_huge_val()) +# endif + +# ifndef HUGE_VALF +# define HUGE_VALF (__builtin_huge_valf()) +# endif + +# ifndef HUGE_VALL +# define HUGE_VALL (__builtin_huge_vall()) +# endif + +# ifndef INFINITY +# define INFINITY (__builtin_inff()) +# endif + +# ifndef NAN +# define NAN (__builtin_nanf("")) +# endif + +#else /* !gcc >= 3.3 */ + + /* No builtins. Use fixed defines instead. (All 3 HUGE plus the INFINITY + * and NAN macros are required to be constant expressions. Using a variable-- + * even a static const--does not meet this requirement, as it cannot be + * evaluated at translation time.) + * The infinities are done using numbers that are far in excess of + * something that would be expected to be encountered in a floating-point + * implementation. (A more certain way uses values from float.h, but that is + * avoided because system includes are not supposed to include each other.) + * This method might produce warnings from some compilers. (It does in + * newer GCCs, but not for ones that would hit this #else.) If this happens, + * please report details to the Newlib mailing list. */ + + #ifndef HUGE_VAL + #define HUGE_VAL (1.0e999999999) + #endif + + #ifndef HUGE_VALF + #define HUGE_VALF (1.0e999999999F) + #endif + + #if !defined(HUGE_VALL) && defined(_HAVE_LONG_DOUBLE) + #define HUGE_VALL (1.0e999999999L) + #endif + + #if !defined(INFINITY) + #define INFINITY (HUGE_VALF) + #endif + + #if !defined(NAN) + #if defined(__GNUC__) && defined(__cplusplus) + /* Exception: older g++ versions warn about the divide by 0 used in the + * normal case (even though older gccs do not). This trick suppresses the + * warning, but causes errors for plain gcc, so is only used in the one + * special case. */ + static const union { __ULong __i[1]; float __d; } __Nanf = {0x7FC00000}; + #define NAN (__Nanf.__d) + #else + #define NAN (0.0F/0.0F) + #endif + #endif + +#endif /* !gcc >= 3.3 */ + +/* Reentrant ANSI C functions. */ + +#ifndef __math_68881 +extern double atan _PARAMS((double)); +extern double cos _PARAMS((double)); +extern double sin _PARAMS((double)); +extern double tan _PARAMS((double)); +extern double tanh _PARAMS((double)); +extern double frexp _PARAMS((double, int *)); +extern double modf _PARAMS((double, double *)); +extern double ceil _PARAMS((double)); +extern double fabs _PARAMS((double)); +extern double floor _PARAMS((double)); +#endif /* ! defined (__math_68881) */ + +/* Non reentrant ANSI C functions. */ + +#ifndef _REENT_ONLY +#ifndef __math_68881 +extern double acos _PARAMS((double)); +extern double asin _PARAMS((double)); +extern double atan2 _PARAMS((double, double)); +extern double cosh _PARAMS((double)); +extern double sinh _PARAMS((double)); +extern double exp _PARAMS((double)); +extern double ldexp _PARAMS((double, int)); +extern double log _PARAMS((double)); +extern double log10 _PARAMS((double)); +extern double pow _PARAMS((double, double)); +extern double sqrt _PARAMS((double)); +extern double fmod _PARAMS((double, double)); +#endif /* ! defined (__math_68881) */ +#endif /* ! defined (_REENT_ONLY) */ + +#if !defined(__STRICT_ANSI__) || defined(__cplusplus) || \ + (defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L) + +/* ISO C99 types and macros. */ + +/* FIXME: FLT_EVAL_METHOD should somehow be gotten from float.h (which is hard, + * considering that the standard says the includes it defines should not + * include other includes that it defines) and that value used. (This can be + * solved, but autoconf has a bug which makes the solution more difficult, so + * it has been skipped for now.) */ +#if !defined(FLT_EVAL_METHOD) && defined(__FLT_EVAL_METHOD__) + #define FLT_EVAL_METHOD __FLT_EVAL_METHOD__ + #define __TMP_FLT_EVAL_METHOD +#endif /* FLT_EVAL_METHOD */ +#if defined FLT_EVAL_METHOD + #if FLT_EVAL_METHOD == 0 + typedef float float_t; + typedef double double_t; + #elif FLT_EVAL_METHOD == 1 + typedef double float_t; + typedef double double_t; + #elif FLT_EVAL_METHOD == 2 + typedef long double float_t; + typedef long double double_t; + #else + /* Implementation-defined. Assume float_t and double_t have been + * defined previously for this configuration (e.g. config.h). */ + #endif +#else + /* Assume basic definitions. */ + typedef float float_t; + typedef double double_t; +#endif +#if defined(__TMP_FLT_EVAL_METHOD) + #undef FLT_EVAL_METHOD +#endif + +#define FP_NAN 0 +#define FP_INFINITE 1 +#define FP_ZERO 2 +#define FP_SUBNORMAL 3 +#define FP_NORMAL 4 + +#ifndef FP_ILOGB0 +# define FP_ILOGB0 (-INT_MAX) +#endif +#ifndef FP_ILOGBNAN +# define FP_ILOGBNAN INT_MAX +#endif + +#ifndef MATH_ERRNO +# define MATH_ERRNO 1 +#endif +#ifndef MATH_ERREXCEPT +# define MATH_ERREXCEPT 2 +#endif +#ifndef math_errhandling +# define math_errhandling MATH_ERRNO +#endif + +extern int __isinff (float x); +extern int __isinfd (double x); +extern int __isnanf (float x); +extern int __isnand (double x); +extern int __fpclassifyf (float x); +extern int __fpclassifyd (double x); +extern int __signbitf (float x); +extern int __signbitd (double x); + +#define fpclassify(__x) \ + ((sizeof(__x) == sizeof(float)) ? __fpclassifyf(__x) : \ + __fpclassifyd(__x)) + +#ifndef isfinite + #define isfinite(__y) \ + (__extension__ ({int __cy = fpclassify(__y); \ + __cy != FP_INFINITE && __cy != FP_NAN;})) +#endif + +/* Note: isinf and isnan were once functions in newlib that took double + * arguments. C99 specifies that these names are reserved for macros + * supporting multiple floating point types. Thus, they are + * now defined as macros. Implementations of the old functions + * taking double arguments still exist for compatibility purposes + * (prototypes for them are in ). */ +#ifndef isinf + #define isinf(y) (fpclassify(y) == FP_INFINITE) +#endif + +#ifndef isnan + #define isnan(y) (fpclassify(y) == FP_NAN) +#endif + +#define isnormal(y) (fpclassify(y) == FP_NORMAL) +#define signbit(__x) \ + ((sizeof(__x) == sizeof(float)) ? __signbitf(__x) : \ + __signbitd(__x)) + +#define isgreater(x,y) \ + (__extension__ ({__typeof__(x) __x = (x); __typeof__(y) __y = (y); \ + !isunordered(__x,__y) && (__x > __y);})) +#define isgreaterequal(x,y) \ + (__extension__ ({__typeof__(x) __x = (x); __typeof__(y) __y = (y); \ + !isunordered(__x,__y) && (__x >= __y);})) +#define isless(x,y) \ + (__extension__ ({__typeof__(x) __x = (x); __typeof__(y) __y = (y); \ + !isunordered(__x,__y) && (__x < __y);})) +#define islessequal(x,y) \ + (__extension__ ({__typeof__(x) __x = (x); __typeof__(y) __y = (y); \ + !isunordered(__x,__y) && (__x <= __y);})) +#define islessgreater(x,y) \ + (__extension__ ({__typeof__(x) __x = (x); __typeof__(y) __y = (y); \ + !isunordered(__x,__y) && (__x < __y || __x > __y);})) + +#define isunordered(a,b) \ + (__extension__ ({__typeof__(a) __a = (a); __typeof__(b) __b = (b); \ + fpclassify(__a) == FP_NAN || fpclassify(__b) == FP_NAN;})) + +/* Non ANSI double precision functions. */ + +extern double infinity _PARAMS((void)); +extern double nan _PARAMS((const char *)); +extern int finite _PARAMS((double)); +extern double copysign _PARAMS((double, double)); +extern double logb _PARAMS((double)); +extern int ilogb _PARAMS((double)); + +extern double asinh _PARAMS((double)); +extern double cbrt _PARAMS((double)); +extern double nextafter _PARAMS((double, double)); +extern double rint _PARAMS((double)); +extern double scalbn _PARAMS((double, int)); + +extern double exp2 _PARAMS((double)); +extern double scalbln _PARAMS((double, long int)); +extern double tgamma _PARAMS((double)); +extern double nearbyint _PARAMS((double)); +extern long int lrint _PARAMS((double)); +extern long long int llrint _PARAMS((double)); +extern double round _PARAMS((double)); +extern long int lround _PARAMS((double)); +extern long long int llround _PARAMS((double)); +extern double trunc _PARAMS((double)); +extern double remquo _PARAMS((double, double, int *)); +extern double fdim _PARAMS((double, double)); +extern double fmax _PARAMS((double, double)); +extern double fmin _PARAMS((double, double)); +extern double fma _PARAMS((double, double, double)); + +#ifndef __math_68881 +extern double log1p _PARAMS((double)); +extern double expm1 _PARAMS((double)); +#endif /* ! defined (__math_68881) */ + +#ifndef _REENT_ONLY +extern double acosh _PARAMS((double)); +extern double atanh _PARAMS((double)); +extern double remainder _PARAMS((double, double)); +extern double gamma _PARAMS((double)); +extern double lgamma _PARAMS((double)); +extern double erf _PARAMS((double)); +extern double erfc _PARAMS((double)); +extern double log2 _PARAMS((double)); +#if !defined(__cplusplus) +#define log2(x) (log (x) / _M_LN2) +#endif + +#ifndef __math_68881 +extern double hypot _PARAMS((double, double)); +#endif + +#endif /* ! defined (_REENT_ONLY) */ + +/* Single precision versions of ANSI functions. */ + +extern float atanf _PARAMS((float)); +extern float cosf _PARAMS((float)); +extern float sinf _PARAMS((float)); +extern float tanf _PARAMS((float)); +extern float tanhf _PARAMS((float)); +extern float frexpf _PARAMS((float, int *)); +extern float modff _PARAMS((float, float *)); +extern float ceilf _PARAMS((float)); +extern float fabsf _PARAMS((float)); +extern float floorf _PARAMS((float)); + +#ifndef _REENT_ONLY +extern float acosf _PARAMS((float)); +extern float asinf _PARAMS((float)); +extern float atan2f _PARAMS((float, float)); +extern float coshf _PARAMS((float)); +extern float sinhf _PARAMS((float)); +extern float expf _PARAMS((float)); +extern float ldexpf _PARAMS((float, int)); +extern float logf _PARAMS((float)); +extern float log10f _PARAMS((float)); +extern float powf _PARAMS((float, float)); +extern float sqrtf _PARAMS((float)); +extern float fmodf _PARAMS((float, float)); +#endif /* ! defined (_REENT_ONLY) */ + +/* Other single precision functions. */ + +extern float exp2f _PARAMS((float)); +extern float scalblnf _PARAMS((float, long int)); +extern float tgammaf _PARAMS((float)); +extern float nearbyintf _PARAMS((float)); +extern long int lrintf _PARAMS((float)); +extern long long int llrintf _PARAMS((float)); +extern float roundf _PARAMS((float)); +extern long int lroundf _PARAMS((float)); +extern long long int llroundf _PARAMS((float)); +extern float truncf _PARAMS((float)); +extern float remquof _PARAMS((float, float, int *)); +extern float fdimf _PARAMS((float, float)); +extern float fmaxf _PARAMS((float, float)); +extern float fminf _PARAMS((float, float)); +extern float fmaf _PARAMS((float, float, float)); + +extern float infinityf _PARAMS((void)); +extern float nanf _PARAMS((const char *)); +extern int finitef _PARAMS((float)); +extern float copysignf _PARAMS((float, float)); +extern float logbf _PARAMS((float)); +extern int ilogbf _PARAMS((float)); + +extern float asinhf _PARAMS((float)); +extern float cbrtf _PARAMS((float)); +extern float nextafterf _PARAMS((float, float)); +extern float rintf _PARAMS((float)); +extern float scalbnf _PARAMS((float, int)); +extern float log1pf _PARAMS((float)); +extern float expm1f _PARAMS((float)); + +#ifndef _REENT_ONLY +extern float acoshf _PARAMS((float)); +extern float atanhf _PARAMS((float)); +extern float remainderf _PARAMS((float, float)); +extern float gammaf _PARAMS((float)); +extern float lgammaf _PARAMS((float)); +extern float erff _PARAMS((float)); +extern float erfcf _PARAMS((float)); +extern float log2f _PARAMS((float)); +extern float hypotf _PARAMS((float, float)); +#endif /* ! defined (_REENT_ONLY) */ + +/* On platforms where long double equals double. */ +#ifdef _LDBL_EQ_DBL +/* Reentrant ANSI C functions. */ +#ifndef __math_68881 +extern long double atanl _PARAMS((long double)); +extern long double cosl _PARAMS((long double)); +extern long double sinl _PARAMS((long double)); +extern long double tanl _PARAMS((long double)); +extern long double tanhl _PARAMS((long double)); +extern long double frexpl _PARAMS((long double, int *)); +extern long double modfl _PARAMS((long double, long double *)); +extern long double ceill _PARAMS((long double)); +extern long double fabsl _PARAMS((long double)); +extern long double floorl _PARAMS((long double)); +extern long double log1pl _PARAMS((long double)); +extern long double expm1l _PARAMS((long double)); +#endif /* ! defined (__math_68881) */ +/* Non reentrant ANSI C functions. */ +#ifndef _REENT_ONLY +#ifndef __math_68881 +extern long double acosl _PARAMS((long double)); +extern long double asinl _PARAMS((long double)); +extern long double atan2l _PARAMS((long double, long double)); +extern long double coshl _PARAMS((long double)); +extern long double sinhl _PARAMS((long double)); +extern long double expl _PARAMS((long double)); +extern long double ldexpl _PARAMS((long double, int)); +extern long double logl _PARAMS((long double)); +extern long double log10l _PARAMS((long double)); +extern long double powl _PARAMS((long double, long double)); +extern long double sqrtl _PARAMS((long double)); +extern long double fmodl _PARAMS((long double, long double)); +extern long double hypotl _PARAMS((long double, long double)); +#endif /* ! defined (__math_68881) */ +#endif /* ! defined (_REENT_ONLY) */ +extern long double copysignl _PARAMS((long double, long double)); +extern long double nanl _PARAMS((const char *)); +extern int ilogbl _PARAMS((long double)); +extern long double asinhl _PARAMS((long double)); +extern long double cbrtl _PARAMS((long double)); +extern long double nextafterl _PARAMS((long double, long double)); +extern float nexttowardf _PARAMS((float, long double)); +extern double nexttoward _PARAMS((double, long double)); +extern long double nexttowardl _PARAMS((long double, long double)); +extern long double logbl _PARAMS((long double)); +extern long double log2l _PARAMS((long double)); +extern long double rintl _PARAMS((long double)); +extern long double scalbnl _PARAMS((long double, int)); +extern long double exp2l _PARAMS((long double)); +extern long double scalblnl _PARAMS((long double, long)); +extern long double tgammal _PARAMS((long double)); +extern long double nearbyintl _PARAMS((long double)); +extern long int lrintl _PARAMS((long double)); +extern long long int llrintl _PARAMS((long double)); +extern long double roundl _PARAMS((long double)); +extern long lroundl _PARAMS((long double)); +extern long long int llroundl _PARAMS((long double)); +extern long double truncl _PARAMS((long double)); +extern long double remquol _PARAMS((long double, long double, int *)); +extern long double fdiml _PARAMS((long double, long double)); +extern long double fmaxl _PARAMS((long double, long double)); +extern long double fminl _PARAMS((long double, long double)); +extern long double fmal _PARAMS((long double, long double, long double)); +#ifndef _REENT_ONLY +extern long double acoshl _PARAMS((long double)); +extern long double atanhl _PARAMS((long double)); +extern long double remainderl _PARAMS((long double, long double)); +extern long double lgammal _PARAMS((long double)); +extern long double erfl _PARAMS((long double)); +extern long double erfcl _PARAMS((long double)); +#endif /* ! defined (_REENT_ONLY) */ +#else /* !_LDBL_EQ_DBL */ +#ifdef __i386__ +/* Other long double precision functions. */ +extern _LONG_DOUBLE rintl _PARAMS((_LONG_DOUBLE)); +extern long int lrintl _PARAMS((_LONG_DOUBLE)); +extern long long int llrintl _PARAMS((_LONG_DOUBLE)); +#endif /* __i386__ */ +#endif /* !_LDBL_EQ_DBL */ + +#endif /* !defined (__STRICT_ANSI__) || defined(__cplusplus) || (defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L) */ + +#if !defined (__STRICT_ANSI__) || defined(__cplusplus) + +extern double drem _PARAMS((double, double)); +extern void sincos _PARAMS((double, double *, double *)); +extern double gamma_r _PARAMS((double, int *)); +extern double lgamma_r _PARAMS((double, int *)); + +extern double y0 _PARAMS((double)); +extern double y1 _PARAMS((double)); +extern double yn _PARAMS((int, double)); +extern double j0 _PARAMS((double)); +extern double j1 _PARAMS((double)); +extern double jn _PARAMS((int, double)); + +extern float dremf _PARAMS((float, float)); +extern void sincosf _PARAMS((float, float *, float *)); +extern float gammaf_r _PARAMS((float, int *)); +extern float lgammaf_r _PARAMS((float, int *)); + +extern float y0f _PARAMS((float)); +extern float y1f _PARAMS((float)); +extern float ynf _PARAMS((int, float)); +extern float j0f _PARAMS((float)); +extern float j1f _PARAMS((float)); +extern float jnf _PARAMS((int, float)); + +/* GNU extensions */ +# ifndef exp10 +extern double exp10 _PARAMS((double)); +# endif +# ifndef pow10 +extern double pow10 _PARAMS((double)); +# endif +# ifndef exp10f +extern float exp10f _PARAMS((float)); +# endif +# ifndef pow10f +extern float pow10f _PARAMS((float)); +# endif + +#endif /* !defined (__STRICT_ANSI__) || defined(__cplusplus) */ + +#ifndef __STRICT_ANSI__ + +/* The gamma functions use a global variable, signgam. */ +#ifndef _REENT_ONLY +#define signgam (*__signgam()) +extern int *__signgam _PARAMS((void)); +#endif /* ! defined (_REENT_ONLY) */ + +#define __signgam_r(ptr) _REENT_SIGNGAM(ptr) + +/* The exception structure passed to the matherr routine. */ +/* We have a problem when using C++ since `exception' is a reserved + name in C++. */ +#ifdef __cplusplus +struct __exception +#else +struct exception +#endif +{ + int type; + char *name; + double arg1; + double arg2; + double retval; + int err; +}; + +#ifdef __cplusplus +extern int matherr _PARAMS((struct __exception *e)); +#else +extern int matherr _PARAMS((struct exception *e)); +#endif + +/* Values for the type field of struct exception. */ + +#define DOMAIN 1 +#define SING 2 +#define OVERFLOW 3 +#define UNDERFLOW 4 +#define TLOSS 5 +#define PLOSS 6 + +#endif /* ! defined (__STRICT_ANSI__) */ + +/* Useful constants. */ + +#if !defined(__STRICT_ANSI__) || ((_XOPEN_SOURCE - 0) >= 500) + +#define MAXFLOAT 3.40282347e+38F + +#define M_E 2.7182818284590452354 +#define M_LOG2E 1.4426950408889634074 +#define M_LOG10E 0.43429448190325182765 +#define M_LN2 _M_LN2 +#define M_LN10 2.30258509299404568402 +#define M_PI 3.14159265358979323846 +#define M_PI_2 1.57079632679489661923 +#define M_PI_4 0.78539816339744830962 +#define M_1_PI 0.31830988618379067154 +#define M_2_PI 0.63661977236758134308 +#define M_2_SQRTPI 1.12837916709551257390 +#define M_SQRT2 1.41421356237309504880 +#define M_SQRT1_2 0.70710678118654752440 + +#endif + +#ifndef __STRICT_ANSI__ + +#define M_TWOPI (M_PI * 2.0) +#define M_3PI_4 2.3561944901923448370E0 +#define M_SQRTPI 1.77245385090551602792981 +#define M_LN2LO 1.9082149292705877000E-10 +#define M_LN2HI 6.9314718036912381649E-1 +#define M_SQRT3 1.73205080756887719000 +#define M_IVLN10 0.43429448190325182765 /* 1 / log(10) */ +#define M_LOG2_E _M_LN2 +#define M_INVLN2 1.4426950408889633870E0 /* 1 / log(2) */ + +/* Global control over fdlibm error handling. */ + +enum __fdlibm_version +{ + __fdlibm_ieee = -1, + __fdlibm_svid, + __fdlibm_xopen, + __fdlibm_posix +}; + +#define _LIB_VERSION_TYPE enum __fdlibm_version +#define _LIB_VERSION __fdlib_version + +extern __IMPORT _LIB_VERSION_TYPE _LIB_VERSION; + +#define _IEEE_ __fdlibm_ieee +#define _SVID_ __fdlibm_svid +#define _XOPEN_ __fdlibm_xopen +#define _POSIX_ __fdlibm_posix + +#endif /* ! defined (__STRICT_ANSI__) */ + +_END_STD_C + +#ifdef __FAST_MATH__ +#include +#endif + +#endif /* _MATH_H_ */ diff --git a/components/newlib/include/newlib.h b/components/newlib/include/newlib.h new file mode 100644 index 0000000000..e9bf566456 --- /dev/null +++ b/components/newlib/include/newlib.h @@ -0,0 +1,201 @@ +/* newlib.h. Generated from newlib.hin by configure. */ +/* newlib.hin. Manually edited from the output of autoheader to + remove all PACKAGE_ macros which will collide with any user + package using newlib header files and having its own package name, + version, etc... */ +#ifndef __NEWLIB_H__ + +#define __NEWLIB_H__ 1 + +/* EL/IX level */ +/* #undef _ELIX_LEVEL */ + +/* Newlib version */ +#define _NEWLIB_VERSION "2.2.0" + +/* C99 formats support (such as %a, %zu, ...) in IO functions like + * printf/scanf enabled */ +/* #undef _WANT_IO_C99_FORMATS */ + +/* long long type support in IO functions like printf/scanf enabled */ +/* #undef _WANT_IO_LONG_LONG */ + +/* Register application finalization function using atexit. */ +/* #undef _WANT_REGISTER_FINI */ + +/* long double type support in IO functions like printf/scanf enabled */ +/* #undef _WANT_IO_LONG_DOUBLE */ + +/* Positional argument support in printf functions enabled. */ +/* #undef _WANT_IO_POS_ARGS */ + +/* Optional reentrant struct support. Used mostly on platforms with + very restricted storage. */ +#define _WANT_REENT_SMALL 1 + +/* Multibyte supported */ +/* #undef _MB_CAPABLE */ + +/* MB_LEN_MAX */ +#define _MB_LEN_MAX 1 + +/* ICONV enabled */ +/* #undef _ICONV_ENABLED */ + +/* Enable ICONV external CCS files loading capabilities */ +/* #undef _ICONV_ENABLE_EXTERNAL_CCS */ + +/* Define if the linker supports .preinit_array/.init_array/.fini_array + * sections. */ +#define HAVE_INITFINI_ARRAY 1 + +/* True if atexit() may dynamically allocate space for cleanup + functions. */ +#define _ATEXIT_DYNAMIC_ALLOC 1 + +/* True if long double supported. */ +#define _HAVE_LONG_DOUBLE 1 + +/* Define if compiler supports -fno-tree-loop-distribute-patterns. */ +#define _HAVE_CC_INHIBIT_LOOP_TO_LIBCALL 1 + +/* True if long double supported and it is equal to double. */ +#define _LDBL_EQ_DBL 1 + +/* Define if uintptr_t is unsigned long on this architecture */ +/* #undef _UINTPTR_EQ_ULONG */ + +/* Define if uintptr_t is unsigned long long on this architecture */ +/* #undef _UINTPTR_EQ_ULONGLONG */ + +/* Define if ivo supported in streamio. */ +#define _FVWRITE_IN_STREAMIO 1 + +/* Define if fseek functions support seek optimization. */ +#define _FSEEK_OPTIMIZATION 1 + +/* Define if wide char orientation is supported. */ +#define _WIDE_ORIENT 1 + +/* Define if unbuffered stream file optimization is supported. */ +#define _UNBUF_STREAM_OPT 1 + +/* Define if lite version of exit supported. */ +/* #undef _LITE_EXIT */ + +/* Define if declare atexit data as global. */ +/* #undef _REENT_GLOBAL_ATEXIT */ + +/* Define if small footprint nano-formatted-IO implementation used. */ +#define _NANO_FORMATTED_IO 1 + +/* + * Iconv encodings enabled ("to" direction) + */ +/* #undef _ICONV_TO_ENCODING_BIG5 */ +/* #undef _ICONV_TO_ENCODING_CP775 */ +/* #undef _ICONV_TO_ENCODING_CP850 */ +/* #undef _ICONV_TO_ENCODING_CP852 */ +/* #undef _ICONV_TO_ENCODING_CP855 */ +/* #undef _ICONV_TO_ENCODING_CP866 */ +/* #undef _ICONV_TO_ENCODING_EUC_JP */ +/* #undef _ICONV_TO_ENCODING_EUC_TW */ +/* #undef _ICONV_TO_ENCODING_EUC_KR */ +/* #undef _ICONV_TO_ENCODING_ISO_8859_1 */ +/* #undef _ICONV_TO_ENCODING_ISO_8859_10 */ +/* #undef _ICONV_TO_ENCODING_ISO_8859_11 */ +/* #undef _ICONV_TO_ENCODING_ISO_8859_13 */ +/* #undef _ICONV_TO_ENCODING_ISO_8859_14 */ +/* #undef _ICONV_TO_ENCODING_ISO_8859_15 */ +/* #undef _ICONV_TO_ENCODING_ISO_8859_2 */ +/* #undef _ICONV_TO_ENCODING_ISO_8859_3 */ +/* #undef _ICONV_TO_ENCODING_ISO_8859_4 */ +/* #undef _ICONV_TO_ENCODING_ISO_8859_5 */ +/* #undef _ICONV_TO_ENCODING_ISO_8859_6 */ +/* #undef _ICONV_TO_ENCODING_ISO_8859_7 */ +/* #undef _ICONV_TO_ENCODING_ISO_8859_8 */ +/* #undef _ICONV_TO_ENCODING_ISO_8859_9 */ +/* #undef _ICONV_TO_ENCODING_ISO_IR_111 */ +/* #undef _ICONV_TO_ENCODING_KOI8_R */ +/* #undef _ICONV_TO_ENCODING_KOI8_RU */ +/* #undef _ICONV_TO_ENCODING_KOI8_U */ +/* #undef _ICONV_TO_ENCODING_KOI8_UNI */ +/* #undef _ICONV_TO_ENCODING_UCS_2 */ +/* #undef _ICONV_TO_ENCODING_UCS_2_INTERNAL */ +/* #undef _ICONV_TO_ENCODING_UCS_2BE */ +/* #undef _ICONV_TO_ENCODING_UCS_2LE */ +/* #undef _ICONV_TO_ENCODING_UCS_4 */ +/* #undef _ICONV_TO_ENCODING_UCS_4_INTERNAL */ +/* #undef _ICONV_TO_ENCODING_UCS_4BE */ +/* #undef _ICONV_TO_ENCODING_UCS_4LE */ +/* #undef _ICONV_TO_ENCODING_US_ASCII */ +/* #undef _ICONV_TO_ENCODING_UTF_16 */ +/* #undef _ICONV_TO_ENCODING_UTF_16BE */ +/* #undef _ICONV_TO_ENCODING_UTF_16LE */ +/* #undef _ICONV_TO_ENCODING_UTF_8 */ +/* #undef _ICONV_TO_ENCODING_WIN_1250 */ +/* #undef _ICONV_TO_ENCODING_WIN_1251 */ +/* #undef _ICONV_TO_ENCODING_WIN_1252 */ +/* #undef _ICONV_TO_ENCODING_WIN_1253 */ +/* #undef _ICONV_TO_ENCODING_WIN_1254 */ +/* #undef _ICONV_TO_ENCODING_WIN_1255 */ +/* #undef _ICONV_TO_ENCODING_WIN_1256 */ +/* #undef _ICONV_TO_ENCODING_WIN_1257 */ +/* #undef _ICONV_TO_ENCODING_WIN_1258 */ + +/* + * Iconv encodings enabled ("from" direction) + */ +/* #undef _ICONV_FROM_ENCODING_BIG5 */ +/* #undef _ICONV_FROM_ENCODING_CP775 */ +/* #undef _ICONV_FROM_ENCODING_CP850 */ +/* #undef _ICONV_FROM_ENCODING_CP852 */ +/* #undef _ICONV_FROM_ENCODING_CP855 */ +/* #undef _ICONV_FROM_ENCODING_CP866 */ +/* #undef _ICONV_FROM_ENCODING_EUC_JP */ +/* #undef _ICONV_FROM_ENCODING_EUC_TW */ +/* #undef _ICONV_FROM_ENCODING_EUC_KR */ +/* #undef _ICONV_FROM_ENCODING_ISO_8859_1 */ +/* #undef _ICONV_FROM_ENCODING_ISO_8859_10 */ +/* #undef _ICONV_FROM_ENCODING_ISO_8859_11 */ +/* #undef _ICONV_FROM_ENCODING_ISO_8859_13 */ +/* #undef _ICONV_FROM_ENCODING_ISO_8859_14 */ +/* #undef _ICONV_FROM_ENCODING_ISO_8859_15 */ +/* #undef _ICONV_FROM_ENCODING_ISO_8859_2 */ +/* #undef _ICONV_FROM_ENCODING_ISO_8859_3 */ +/* #undef _ICONV_FROM_ENCODING_ISO_8859_4 */ +/* #undef _ICONV_FROM_ENCODING_ISO_8859_5 */ +/* #undef _ICONV_FROM_ENCODING_ISO_8859_6 */ +/* #undef _ICONV_FROM_ENCODING_ISO_8859_7 */ +/* #undef _ICONV_FROM_ENCODING_ISO_8859_8 */ +/* #undef _ICONV_FROM_ENCODING_ISO_8859_9 */ +/* #undef _ICONV_FROM_ENCODING_ISO_IR_111 */ +/* #undef _ICONV_FROM_ENCODING_KOI8_R */ +/* #undef _ICONV_FROM_ENCODING_KOI8_RU */ +/* #undef _ICONV_FROM_ENCODING_KOI8_U */ +/* #undef _ICONV_FROM_ENCODING_KOI8_UNI */ +/* #undef _ICONV_FROM_ENCODING_UCS_2 */ +/* #undef _ICONV_FROM_ENCODING_UCS_2_INTERNAL */ +/* #undef _ICONV_FROM_ENCODING_UCS_2BE */ +/* #undef _ICONV_FROM_ENCODING_UCS_2LE */ +/* #undef _ICONV_FROM_ENCODING_UCS_4 */ +/* #undef _ICONV_FROM_ENCODING_UCS_4_INTERNAL */ +/* #undef _ICONV_FROM_ENCODING_UCS_4BE */ +/* #undef _ICONV_FROM_ENCODING_UCS_4LE */ +/* #undef _ICONV_FROM_ENCODING_US_ASCII */ +/* #undef _ICONV_FROM_ENCODING_UTF_16 */ +/* #undef _ICONV_FROM_ENCODING_UTF_16BE */ +/* #undef _ICONV_FROM_ENCODING_UTF_16LE */ +/* #undef _ICONV_FROM_ENCODING_UTF_8 */ +/* #undef _ICONV_FROM_ENCODING_WIN_1250 */ +/* #undef _ICONV_FROM_ENCODING_WIN_1251 */ +/* #undef _ICONV_FROM_ENCODING_WIN_1252 */ +/* #undef _ICONV_FROM_ENCODING_WIN_1253 */ +/* #undef _ICONV_FROM_ENCODING_WIN_1254 */ +/* #undef _ICONV_FROM_ENCODING_WIN_1255 */ +/* #undef _ICONV_FROM_ENCODING_WIN_1256 */ +/* #undef _ICONV_FROM_ENCODING_WIN_1257 */ +/* #undef _ICONV_FROM_ENCODING_WIN_1258 */ + +#endif /* !__NEWLIB_H__ */ + diff --git a/components/newlib/include/paths.h b/components/newlib/include/paths.h new file mode 100644 index 0000000000..b1c70f588a --- /dev/null +++ b/components/newlib/include/paths.h @@ -0,0 +1,9 @@ +#ifndef _PATHS_H_ +#define _PATHS_H_ + +#define _PATH_DEV "/dev/" +#define _PATH_DEVNULL "/dev/null" +#define _PATH_DEVZERO "/dev/zero" +#define _PATH_BSHELL "/bin/sh" + +#endif /* _PATHS_H_ */ diff --git a/components/newlib/include/pthread.h b/components/newlib/include/pthread.h new file mode 100644 index 0000000000..db1f9c1ca3 --- /dev/null +++ b/components/newlib/include/pthread.h @@ -0,0 +1,431 @@ +/* pthread.h + * + * Written by Joel Sherrill . + * + * COPYRIGHT (c) 1989-2013. + * On-Line Applications Research Corporation (OAR). + * + * Permission to use, copy, modify, and distribute this software for any + * purpose without fee is hereby granted, provided that this entire notice + * is included in all copies of any software which is or includes a copy + * or modification of this software. + * + * THIS SOFTWARE IS BEING PROVIDED "AS IS", WITHOUT ANY EXPRESS OR IMPLIED + * WARRANTY. IN PARTICULAR, THE AUTHOR MAKES NO REPRESENTATION + * OR WARRANTY OF ANY KIND CONCERNING THE MERCHANTABILITY OF THIS + * SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR PURPOSE. + * + * $Id$ + */ + +#ifndef __PTHREAD_h +#define __PTHREAD_h + +#ifdef __cplusplus +extern "C" { +#endif + +#include + +#if defined(_POSIX_THREADS) + +#include +#include +#include +#include + +struct _pthread_cleanup_context { + void (*_routine)(void *); + void *_arg; + int _canceltype; + struct _pthread_cleanup_context *_previous; +}; + +/* Register Fork Handlers */ +int _EXFUN(pthread_atfork,(void (*prepare)(void), void (*parent)(void), + void (*child)(void))); + +/* Mutex Initialization Attributes, P1003.1c/Draft 10, p. 81 */ + +int _EXFUN(pthread_mutexattr_init, (pthread_mutexattr_t *__attr)); +int _EXFUN(pthread_mutexattr_destroy, (pthread_mutexattr_t *__attr)); +int _EXFUN(pthread_mutexattr_getpshared, + (_CONST pthread_mutexattr_t *__attr, int *__pshared)); +int _EXFUN(pthread_mutexattr_setpshared, + (pthread_mutexattr_t *__attr, int __pshared)); + +#if defined(_UNIX98_THREAD_MUTEX_ATTRIBUTES) + +/* Single UNIX Specification 2 Mutex Attributes types */ + +int _EXFUN(pthread_mutexattr_gettype, + (_CONST pthread_mutexattr_t *__attr, int *__kind)); +int _EXFUN(pthread_mutexattr_settype, + (pthread_mutexattr_t *__attr, int __kind)); + +#endif + +/* Initializing and Destroying a Mutex, P1003.1c/Draft 10, p. 87 */ + +int _EXFUN(pthread_mutex_init, + (pthread_mutex_t *__mutex, _CONST pthread_mutexattr_t *__attr)); +int _EXFUN(pthread_mutex_destroy, (pthread_mutex_t *__mutex)); + +/* This is used to statically initialize a pthread_mutex_t. Example: + + pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER; + */ + +#define PTHREAD_MUTEX_INITIALIZER ((pthread_mutex_t) 0xFFFFFFFF) + +/* Locking and Unlocking a Mutex, P1003.1c/Draft 10, p. 93 + NOTE: P1003.4b/D8 adds pthread_mutex_timedlock(), p. 29 */ + +int _EXFUN(pthread_mutex_lock, (pthread_mutex_t *__mutex)); +int _EXFUN(pthread_mutex_trylock, (pthread_mutex_t *__mutex)); +int _EXFUN(pthread_mutex_unlock, (pthread_mutex_t *__mutex)); + +#if defined(_POSIX_TIMEOUTS) + +int _EXFUN(pthread_mutex_timedlock, + (pthread_mutex_t *__mutex, _CONST struct timespec *__timeout)); + +#endif /* _POSIX_TIMEOUTS */ + +/* Condition Variable Initialization Attributes, P1003.1c/Draft 10, p. 96 */ + +int _EXFUN(pthread_condattr_init, (pthread_condattr_t *__attr)); +int _EXFUN(pthread_condattr_destroy, (pthread_condattr_t *__attr)); +int _EXFUN(pthread_condattr_getpshared, + (_CONST pthread_condattr_t *__attr, int *__pshared)); +int _EXFUN(pthread_condattr_setpshared, + (pthread_condattr_t *__attr, int __pshared)); + +/* Initializing and Destroying a Condition Variable, P1003.1c/Draft 10, p. 87 */ + +int _EXFUN(pthread_cond_init, + (pthread_cond_t *__cond, _CONST pthread_condattr_t *__attr)); +int _EXFUN(pthread_cond_destroy, (pthread_cond_t *__mutex)); + +/* This is used to statically initialize a pthread_cond_t. Example: + + pthread_cond_t cond = PTHREAD_COND_INITIALIZER; + */ + +#define PTHREAD_COND_INITIALIZER ((pthread_cond_t) 0xFFFFFFFF) + +/* Broadcasting and Signaling a Condition, P1003.1c/Draft 10, p. 101 */ + +int _EXFUN(pthread_cond_signal, (pthread_cond_t *__cond)); +int _EXFUN(pthread_cond_broadcast, (pthread_cond_t *__cond)); + +/* Waiting on a Condition, P1003.1c/Draft 10, p. 105 */ + +int _EXFUN(pthread_cond_wait, + (pthread_cond_t *__cond, pthread_mutex_t *__mutex)); + +int _EXFUN(pthread_cond_timedwait, + (pthread_cond_t *__cond, pthread_mutex_t *__mutex, + _CONST struct timespec *__abstime)); + +#if defined(_POSIX_THREAD_PRIORITY_SCHEDULING) + +/* Thread Creation Scheduling Attributes, P1003.1c/Draft 10, p. 120 */ + +int _EXFUN(pthread_attr_setscope, + (pthread_attr_t *__attr, int __contentionscope)); +int _EXFUN(pthread_attr_getscope, + (_CONST pthread_attr_t *__attr, int *__contentionscope)); +int _EXFUN(pthread_attr_setinheritsched, + (pthread_attr_t *__attr, int __inheritsched)); +int _EXFUN(pthread_attr_getinheritsched, + (_CONST pthread_attr_t *__attr, int *__inheritsched)); +int _EXFUN(pthread_attr_setschedpolicy, + (pthread_attr_t *__attr, int __policy)); +int _EXFUN(pthread_attr_getschedpolicy, + (_CONST pthread_attr_t *__attr, int *__policy)); + +#endif /* defined(_POSIX_THREAD_PRIORITY_SCHEDULING) */ + +int _EXFUN(pthread_attr_setschedparam, + (pthread_attr_t *__attr, _CONST struct sched_param *__param)); +int _EXFUN(pthread_attr_getschedparam, + (_CONST pthread_attr_t *__attr, struct sched_param *__param)); + +#if defined(_POSIX_THREAD_PRIORITY_SCHEDULING) + +/* Dynamic Thread Scheduling Parameters Access, P1003.1c/Draft 10, p. 124 */ + +int _EXFUN(pthread_getschedparam, + (pthread_t __pthread, int *__policy, struct sched_param *__param)); +int _EXFUN(pthread_setschedparam, + (pthread_t __pthread, int __policy, struct sched_param *__param)); + +#endif /* defined(_POSIX_THREAD_PRIORITY_SCHEDULING) */ + +#if defined(_POSIX_THREAD_PRIO_INHERIT) || defined(_POSIX_THREAD_PRIO_PROTECT) + +/* Mutex Initialization Scheduling Attributes, P1003.1c/Draft 10, p. 128 */ + +int _EXFUN(pthread_mutexattr_setprotocol, + (pthread_mutexattr_t *__attr, int __protocol)); +int _EXFUN(pthread_mutexattr_getprotocol, + (_CONST pthread_mutexattr_t *__attr, int *__protocol)); +int _EXFUN(pthread_mutexattr_setprioceiling, + (pthread_mutexattr_t *__attr, int __prioceiling)); +int _EXFUN(pthread_mutexattr_getprioceiling, + (_CONST pthread_mutexattr_t *__attr, int *__prioceiling)); + +#endif /* _POSIX_THREAD_PRIO_INHERIT || _POSIX_THREAD_PRIO_PROTECT */ + +#if defined(_POSIX_THREAD_PRIO_PROTECT) + +/* Change the Priority Ceiling of a Mutex, P1003.1c/Draft 10, p. 131 */ + +int _EXFUN(pthread_mutex_setprioceiling, + (pthread_mutex_t *__mutex, int __prioceiling, int *__old_ceiling)); +int _EXFUN(pthread_mutex_getprioceiling, + (pthread_mutex_t *__mutex, int *__prioceiling)); + +#endif /* _POSIX_THREAD_PRIO_PROTECT */ + +/* Thread Creation Attributes, P1003.1c/Draft 10, p, 140 */ + +int _EXFUN(pthread_attr_init, (pthread_attr_t *__attr)); +int _EXFUN(pthread_attr_destroy, (pthread_attr_t *__attr)); +int _EXFUN(pthread_attr_setstack, (pthread_attr_t *attr, + void *__stackaddr, size_t __stacksize)); +int _EXFUN(pthread_attr_getstack, (_CONST pthread_attr_t *attr, + void **__stackaddr, size_t *__stacksize)); +int _EXFUN(pthread_attr_getstacksize, + (_CONST pthread_attr_t *__attr, size_t *__stacksize)); +int _EXFUN(pthread_attr_setstacksize, + (pthread_attr_t *__attr, size_t __stacksize)); +int _EXFUN(pthread_attr_getstackaddr, + (_CONST pthread_attr_t *__attr, void **__stackaddr)); +int _EXFUN(pthread_attr_setstackaddr, + (pthread_attr_t *__attr, void *__stackaddr)); +int _EXFUN(pthread_attr_getdetachstate, + (_CONST pthread_attr_t *__attr, int *__detachstate)); +int _EXFUN(pthread_attr_setdetachstate, + (pthread_attr_t *__attr, int __detachstate)); +int _EXFUN(pthread_attr_getguardsize, + (_CONST pthread_attr_t *__attr, size_t *__guardsize)); +int _EXFUN(pthread_attr_setguardsize, + (pthread_attr_t *__attr, size_t __guardsize)); + +/* POSIX thread APIs beyond the POSIX standard but provided + * in GNU/Linux. They may be provided by other OSes for + * compatibility. + */ +#if defined(__GNU_VISIBLE) +#if defined(__rtems__) +int _EXFUN(pthread_attr_setaffinity_np, + (pthread_attr_t *__attr, size_t __cpusetsize, + const cpu_set_t *__cpuset)); +int _EXFUN(pthread_attr_getaffinity_np, + (const pthread_attr_t *__attr, size_t __cpusetsize, + cpu_set_t *__cpuset)); + +int _EXFUN(pthread_setaffinity_np, + (pthread_t __id, size_t __cpusetsize, const cpu_set_t *__cpuset)); +int _EXFUN(pthread_getaffinity_np, + (const pthread_t __id, size_t __cpusetsize, cpu_set_t *__cpuset)); + +int _EXFUN(pthread_getattr_np, + (pthread_t __id, pthread_attr_t *__attr)); +#endif /* defined(__rtems__) */ +#endif /* defined(__GNU_VISIBLE) */ + +/* Thread Creation, P1003.1c/Draft 10, p. 144 */ + +int _EXFUN(pthread_create, + (pthread_t *__pthread, _CONST pthread_attr_t *__attr, + void *(*__start_routine)( void * ), void *__arg)); + +/* Wait for Thread Termination, P1003.1c/Draft 10, p. 147 */ + +int _EXFUN(pthread_join, (pthread_t __pthread, void **__value_ptr)); + +/* Detaching a Thread, P1003.1c/Draft 10, p. 149 */ + +int _EXFUN(pthread_detach, (pthread_t __pthread)); + +/* Thread Termination, p1003.1c/Draft 10, p. 150 */ + +void _EXFUN(pthread_exit, (void *__value_ptr)); + +/* Get Calling Thread's ID, p1003.1c/Draft 10, p. XXX */ + +pthread_t _EXFUN(pthread_self, (void)); + +/* Compare Thread IDs, p1003.1c/Draft 10, p. 153 */ + +int _EXFUN(pthread_equal, (pthread_t __t1, pthread_t __t2)); + +/* Dynamic Package Initialization */ + +/* This is used to statically initialize a pthread_once_t. Example: + + pthread_once_t once = PTHREAD_ONCE_INIT; + + NOTE: This is named inconsistently -- it should be INITIALIZER. */ + +#define PTHREAD_ONCE_INIT { 1, 0 } /* is initialized and not run */ + +int _EXFUN(pthread_once, + (pthread_once_t *__once_control, void (*__init_routine)(void))); + +/* Thread-Specific Data Key Create, P1003.1c/Draft 10, p. 163 */ + +int _EXFUN(pthread_key_create, + (pthread_key_t *__key, void (*__destructor)( void * ))); + +/* Thread-Specific Data Management, P1003.1c/Draft 10, p. 165 */ + +int _EXFUN(pthread_setspecific, + (pthread_key_t __key, _CONST void *__value)); +void * _EXFUN(pthread_getspecific, (pthread_key_t __key)); + +/* Thread-Specific Data Key Deletion, P1003.1c/Draft 10, p. 167 */ + +int _EXFUN(pthread_key_delete, (pthread_key_t __key)); + +/* Execution of a Thread, P1003.1c/Draft 10, p. 181 */ + +#define PTHREAD_CANCEL_ENABLE 0 +#define PTHREAD_CANCEL_DISABLE 1 + +#define PTHREAD_CANCEL_DEFERRED 0 +#define PTHREAD_CANCEL_ASYNCHRONOUS 1 + +#define PTHREAD_CANCELED ((void *) -1) + +int _EXFUN(pthread_cancel, (pthread_t __pthread)); + +/* Setting Cancelability State, P1003.1c/Draft 10, p. 183 */ + +int _EXFUN(pthread_setcancelstate, (int __state, int *__oldstate)); +int _EXFUN(pthread_setcanceltype, (int __type, int *__oldtype)); +void _EXFUN(pthread_testcancel, (void)); + +/* Establishing Cancellation Handlers, P1003.1c/Draft 10, p. 184 */ + +void _EXFUN(_pthread_cleanup_push, + (struct _pthread_cleanup_context *_context, + void (*_routine)(void *), void *_arg)); + +void _EXFUN(_pthread_cleanup_pop, + (struct _pthread_cleanup_context *_context, + int _execute)); + +/* It is intentional to open and close the scope in two different macros */ +#define pthread_cleanup_push(_routine, _arg) \ + do { \ + struct _pthread_cleanup_context _pthread_clup_ctx; \ + _pthread_cleanup_push(&_pthread_clup_ctx, (_routine), (_arg)) + +#define pthread_cleanup_pop(_execute) \ + _pthread_cleanup_pop(&_pthread_clup_ctx, (_execute)); \ + } while (0) + +#if defined(_GNU_SOURCE) +void _EXFUN(_pthread_cleanup_push_defer, + (struct _pthread_cleanup_context *_context, + void (*_routine)(void *), void *_arg)); + +void _EXFUN(_pthread_cleanup_pop_restore, + (struct _pthread_cleanup_context *_context, + int _execute)); + +/* It is intentional to open and close the scope in two different macros */ +#define pthread_cleanup_push_defer_np(_routine, _arg) \ + do { \ + struct _pthread_cleanup_context _pthread_clup_ctx; \ + _pthread_cleanup_push_defer(&_pthread_clup_ctx, (_routine), (_arg)) + +#define pthread_cleanup_pop_restore_np(_execute) \ + _pthread_cleanup_pop_restore(&_pthread_clup_ctx, (_execute)); \ + } while (0) +#endif /* defined(_GNU_SOURCE) */ + +#if defined(_POSIX_THREAD_CPUTIME) + +/* Accessing a Thread CPU-time Clock, P1003.4b/D8, p. 58 */ + +int _EXFUN(pthread_getcpuclockid, + (pthread_t __pthread_id, clockid_t *__clock_id)); + +#endif /* defined(_POSIX_THREAD_CPUTIME) */ + + +#endif /* defined(_POSIX_THREADS) */ + +#if defined(_POSIX_BARRIERS) + +int _EXFUN(pthread_barrierattr_init, (pthread_barrierattr_t *__attr)); +int _EXFUN(pthread_barrierattr_destroy, (pthread_barrierattr_t *__attr)); +int _EXFUN(pthread_barrierattr_getpshared, + (_CONST pthread_barrierattr_t *__attr, int *__pshared)); +int _EXFUN(pthread_barrierattr_setpshared, + (pthread_barrierattr_t *__attr, int __pshared)); + +#define PTHREAD_BARRIER_SERIAL_THREAD -1 + +int _EXFUN(pthread_barrier_init, + (pthread_barrier_t *__barrier, + _CONST pthread_barrierattr_t *__attr, unsigned __count)); +int _EXFUN(pthread_barrier_destroy, (pthread_barrier_t *__barrier)); +int _EXFUN(pthread_barrier_wait,(pthread_barrier_t *__barrier)); + +#endif /* defined(_POSIX_BARRIERS) */ + +#if defined(_POSIX_SPIN_LOCKS) + +int _EXFUN(pthread_spin_init, + (pthread_spinlock_t *__spinlock, int __pshared)); +int _EXFUN(pthread_spin_destroy, (pthread_spinlock_t *__spinlock)); +int _EXFUN(pthread_spin_lock, (pthread_spinlock_t *__spinlock)); +int _EXFUN(pthread_spin_trylock, (pthread_spinlock_t *__spinlock)); +int _EXFUN(pthread_spin_unlock, (pthread_spinlock_t *__spinlock)); + +#endif /* defined(_POSIX_SPIN_LOCKS) */ + +#if defined(_POSIX_READER_WRITER_LOCKS) + +/* This is used to statically initialize a pthread_rwlock_t. Example: + + pthread_mutex_t mutex = PTHREAD_RWLOCK_INITIALIZER; + */ + +#define PTHREAD_RWLOCK_INITIALIZER ((pthread_rwlock_t) 0xFFFFFFFF) + +int _EXFUN(pthread_rwlockattr_init, (pthread_rwlockattr_t *__attr)); +int _EXFUN(pthread_rwlockattr_destroy, (pthread_rwlockattr_t *__attr)); +int _EXFUN(pthread_rwlockattr_getpshared, + (_CONST pthread_rwlockattr_t *__attr, int *__pshared)); +int _EXFUN(pthread_rwlockattr_setpshared, + (pthread_rwlockattr_t *__attr, int __pshared)); + +int _EXFUN(pthread_rwlock_init, + (pthread_rwlock_t *__rwlock, _CONST pthread_rwlockattr_t *__attr)); +int _EXFUN(pthread_rwlock_destroy, (pthread_rwlock_t *__rwlock)); +int _EXFUN(pthread_rwlock_rdlock,(pthread_rwlock_t *__rwlock)); +int _EXFUN(pthread_rwlock_tryrdlock,(pthread_rwlock_t *__rwlock)); +int _EXFUN(pthread_rwlock_timedrdlock, + (pthread_rwlock_t *__rwlock, _CONST struct timespec *__abstime)); +int _EXFUN(pthread_rwlock_unlock,(pthread_rwlock_t *__rwlock)); +int _EXFUN(pthread_rwlock_wrlock,(pthread_rwlock_t *__rwlock)); +int _EXFUN(pthread_rwlock_trywrlock,(pthread_rwlock_t *__rwlock)); +int _EXFUN(pthread_rwlock_timedwrlock, + (pthread_rwlock_t *__rwlock, _CONST struct timespec *__abstime)); + +#endif /* defined(_POSIX_READER_WRITER_LOCKS) */ + + +#ifdef __cplusplus +} +#endif + +#endif +/* end of include file */ diff --git a/components/newlib/include/pwd.h b/components/newlib/include/pwd.h new file mode 100644 index 0000000000..3dea4ee2d1 --- /dev/null +++ b/components/newlib/include/pwd.h @@ -0,0 +1,87 @@ +/*- + * Copyright (c) 1989 The Regents of the University of California. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)pwd.h 5.13 (Berkeley) 5/28/91 + */ + +#ifndef _PWD_H_ +#ifdef __cplusplus +extern "C" { +#endif +#define _PWD_H_ + +#include +#include + +#if __BSD_VISIBLE +#define _PATH_PASSWD "/etc/passwd" + +#define _PASSWORD_LEN 128 /* max length, not counting NULL */ +#endif + +struct passwd { + char *pw_name; /* user name */ + char *pw_passwd; /* encrypted password */ + uid_t pw_uid; /* user uid */ + gid_t pw_gid; /* user gid */ + char *pw_comment; /* comment */ + char *pw_gecos; /* Honeywell login info */ + char *pw_dir; /* home directory */ + char *pw_shell; /* default shell */ +}; + +#ifndef __INSIDE_CYGWIN__ +struct passwd *getpwuid (uid_t); +struct passwd *getpwnam (const char *); + +#if __POSIX_VISIBLE >= 200112 || __XSI_VISIBLE >= 500 +int getpwnam_r (const char *, struct passwd *, + char *, size_t , struct passwd **); +int getpwuid_r (uid_t, struct passwd *, char *, + size_t, struct passwd **); +#endif + +#if __XSI_VISIBLE >= 500 +struct passwd *getpwent (void); +void setpwent (void); +void endpwent (void); +#endif + +#if __BSD_VISIBLE +int setpassent (int); +#endif +#endif /*!__INSIDE_CYGWIN__*/ + +#ifdef __cplusplus +} +#endif +#endif /* _PWD_H_ */ diff --git a/components/newlib/include/reent.h b/components/newlib/include/reent.h new file mode 100644 index 0000000000..861be71d35 --- /dev/null +++ b/components/newlib/include/reent.h @@ -0,0 +1,189 @@ +/* This header file provides the reentrancy. */ + +/* The reentrant system calls here serve two purposes: + + 1) Provide reentrant versions of the system calls the ANSI C library + requires. + 2) Provide these system calls in a namespace clean way. + + It is intended that *all* system calls that the ANSI C library needs + be declared here. It documents them all in one place. All library access + to the system is via some form of these functions. + + The target may provide the needed syscalls by any of the following: + + 1) Define the reentrant versions of the syscalls directly. + (eg: _open_r, _close_r, etc.). Please keep the namespace clean. + When you do this, set "syscall_dir" to "syscalls" and add + -DREENTRANT_SYSCALLS_PROVIDED to newlib_cflags in configure.host. + + 2) Define namespace clean versions of the system calls by prefixing + them with '_' (eg: _open, _close, etc.). Technically, there won't be + true reentrancy at the syscall level, but the library will be namespace + clean. + When you do this, set "syscall_dir" to "syscalls" in configure.host. + + 3) Define or otherwise provide the regular versions of the syscalls + (eg: open, close, etc.). The library won't be reentrant nor namespace + clean, but at least it will work. + When you do this, add -DMISSING_SYSCALL_NAMES to newlib_cflags in + configure.host. + + 4) Define or otherwise provide the regular versions of the syscalls, + and do not supply functional interfaces for any of the reentrant + calls. With this method, the reentrant syscalls are redefined to + directly call the regular system call without the reentrancy argument. + When you do this, specify both -DREENTRANT_SYSCALLS_PROVIDED and + -DMISSING_SYSCALL_NAMES via newlib_cflags in configure.host and do + not specify "syscall_dir". + + Stubs of the reentrant versions of the syscalls exist in the libc/reent + source directory and are provided if REENTRANT_SYSCALLS_PROVIDED isn't + defined. These stubs call the native system calls: _open, _close, etc. + if MISSING_SYSCALL_NAMES is *not* defined, otherwise they call the + non-underscored versions: open, close, etc. when MISSING_SYSCALL_NAMES + *is* defined. + + By default, newlib functions call the reentrant syscalls internally, + passing a reentrancy structure as an argument. This reentrancy structure + contains data that is thread-specific. For example, the errno value is + kept in the reentrancy structure. If multiple threads exist, each will + keep a separate errno value which is intuitive since the application flow + cannot check for failure reliably otherwise. + + The reentrant syscalls are either provided by the platform, by the + libc/reent stubs, or in the case of both MISSING_SYSCALL_NAMES and + REENTRANT_SYSCALLS_PROVIDED being defined, the calls are redefined to + simply call the regular syscalls with no reentrancy struct argument. + + A single-threaded application does not need to worry about the reentrancy + structure. It is used internally. + + A multi-threaded application needs either to manually manage reentrancy + structures or use dynamic reentrancy. + + Manually managing reentrancy structures entails calling special reentrant + versions of newlib functions that have an additional reentrancy argument. + For example, _printf_r. By convention, the first argument is the + reentrancy structure. By default, the normal version of the function + uses the default reentrancy structure: _REENT. The reentrancy structure + is passed internally, eventually to the reentrant syscalls themselves. + How the structures are stored and accessed in this model is up to the + application. + + Dynamic reentrancy is specified by the __DYNAMIC_REENT__ flag. This + flag denotes setting up a macro to replace _REENT with a function call + to __getreent(). This function needs to be implemented by the platform + and it is meant to return the reentrancy structure for the current + thread. When the regular C functions (e.g. printf) go to call internal + routines with the default _REENT structure, they end up calling with + the reentrancy structure for the thread. Thus, application code does not + need to call the _r routines nor worry about reentrancy structures. */ + +/* WARNING: All identifiers here must begin with an underscore. This file is + included by stdio.h and others and we therefore must only use identifiers + in the namespace allotted to us. */ + +#ifndef _REENT_H_ +#ifdef __cplusplus +extern "C" { +#endif +#define _REENT_H_ + +#include +#include +#include + +#define __need_size_t +#define __need_ptrdiff_t +#include + +/* FIXME: not namespace clean */ +struct stat; +struct tms; +struct timeval; +struct timezone; + +#if defined(REENTRANT_SYSCALLS_PROVIDED) && defined(MISSING_SYSCALL_NAMES) + +#define _close_r(__reent, __fd) close(__fd) +#define _execve_r(__reent, __f, __arg, __env) execve(__f, __arg, __env) +#define _fcntl_r(__reent, __fd, __cmd, __arg) fcntl(__fd, __cmd, __arg) +#define _fork_r(__reent) fork() +#define _fstat_r(__reent, __fdes, __stat) fstat(__fdes, __stat) +#define _getpid_r(__reent) getpid() +#define _isatty_r(__reent, __desc) isatty(__desc) +#define _kill_r(__reent, __pid, __signal) kill(__pid, __signal) +#define _link_r(__reent, __oldpath, __newpath) link(__oldpath, __newpath) +#define _lseek_r(__reent, __fdes, __off, __w) lseek(__fdes, __off, __w) +#define _mkdir_r(__reent, __path, __m) mkdir(__path, __m) +#define _open_r(__reent, __path, __flag, __m) open(__path, __flag, __m) +#define _read_r(__reent, __fd, __buff, __cnt) read(__fd, __buff, __cnt) +#define _rename_r(__reent, __old, __new) rename(__old, __new) +#define _sbrk_r(__reent, __incr) sbrk(__incr) +#define _stat_r(__reent, __path, __buff) stat(__path, __buff) +#define _times_r(__reent, __time) times(__time) +#define _unlink_r(__reent, __path) unlink(__path) +#define _wait_r(__reent, __status) wait(__status) +#define _write_r(__reent, __fd, __buff, __cnt) write(__fd, __buff, __cnt) +#define _gettimeofday_r(__reent, __tp, __tzp) gettimeofday(__tp, __tzp) + +#ifdef __LARGE64_FILES +#define _lseek64_r(__reent, __fd, __off, __w) lseek64(__fd, __off, __w) +#define _fstat64_r(__reent, __fd, __buff) fstat64(__fd, __buff) +#define _open64_r(__reent, __path, __flag, __m) open64(__path, __flag, __m) +#endif + +#else +/* Reentrant versions of system calls. */ + +extern int _close_r _PARAMS ((struct _reent *, int)); +extern int _execve_r _PARAMS ((struct _reent *, const char *, char *const *, char *const *)); +extern int _fcntl_r _PARAMS ((struct _reent *, int, int, int)); +extern int _fork_r _PARAMS ((struct _reent *)); +extern int _fstat_r _PARAMS ((struct _reent *, int, struct stat *)); +extern int _getpid_r _PARAMS ((struct _reent *)); +extern int _isatty_r _PARAMS ((struct _reent *, int)); +extern int _kill_r _PARAMS ((struct _reent *, int, int)); +extern int _link_r _PARAMS ((struct _reent *, const char *, const char *)); +extern _off_t _lseek_r _PARAMS ((struct _reent *, int, _off_t, int)); +extern int _mkdir_r _PARAMS ((struct _reent *, const char *, int)); +extern int _open_r _PARAMS ((struct _reent *, const char *, int, int)); +extern _ssize_t _read_r _PARAMS ((struct _reent *, int, void *, size_t)); +extern int _rename_r _PARAMS ((struct _reent *, const char *, const char *)); +extern void *_sbrk_r _PARAMS ((struct _reent *, ptrdiff_t)); +extern int _stat_r _PARAMS ((struct _reent *, const char *, struct stat *)); +extern _CLOCK_T_ _times_r _PARAMS ((struct _reent *, struct tms *)); +extern int _unlink_r _PARAMS ((struct _reent *, const char *)); +extern int _wait_r _PARAMS ((struct _reent *, int *)); +extern _ssize_t _write_r _PARAMS ((struct _reent *, int, const void *, size_t)); + +/* This one is not guaranteed to be available on all targets. */ +extern int _gettimeofday_r _PARAMS ((struct _reent *, struct timeval *__tp, void *__tzp)); + +#ifdef __LARGE64_FILES + + +#if defined(__CYGWIN__) +#define stat64 stat +#endif +struct stat64; + +extern _off64_t _lseek64_r _PARAMS ((struct _reent *, int, _off64_t, int)); +extern int _fstat64_r _PARAMS ((struct _reent *, int, struct stat64 *)); +extern int _open64_r _PARAMS ((struct _reent *, const char *, int, int)); +extern int _stat64_r _PARAMS ((struct _reent *, const char *, struct stat64 *)); + +/* Don't pollute namespace if not building newlib. */ +#if defined (__CYGWIN__) && !defined (_COMPILING_NEWLIB) +#undef stat64 +#endif + +#endif + +#endif + +#ifdef __cplusplus +} +#endif +#endif /* _REENT_H_ */ diff --git a/components/newlib/include/regdef.h b/components/newlib/include/regdef.h new file mode 100644 index 0000000000..8cf144b85f --- /dev/null +++ b/components/newlib/include/regdef.h @@ -0,0 +1,7 @@ +/* regdef.h -- define register names. */ + +/* This is a standard include file for MIPS targets. Other target + probably don't define it, and attempts to include this file will + fail. */ + +#include diff --git a/components/newlib/include/regex.h b/components/newlib/include/regex.h new file mode 100644 index 0000000000..fa3e26879a --- /dev/null +++ b/components/newlib/include/regex.h @@ -0,0 +1,103 @@ +/*- + * Copyright (c) 1992 Henry Spencer. + * Copyright (c) 1992, 1993 + * The Regents of the University of California. All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Henry Spencer of the University of Toronto. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)regex.h 8.2 (Berkeley) 1/3/94 + * $FreeBSD: src/include/regex.h,v 1.4 2002/03/23 17:24:53 imp Exp $ + */ + +#ifndef _REGEX_H_ +#define _REGEX_H_ + +#include + +/* types */ +typedef off_t regoff_t; + +typedef struct { + int re_magic; + size_t re_nsub; /* number of parenthesized subexpressions */ + __const char *re_endp; /* end pointer for REG_PEND */ + struct re_guts *re_g; /* none of your business :-) */ +} regex_t; + +typedef struct { + regoff_t rm_so; /* start of match */ + regoff_t rm_eo; /* end of match */ +} regmatch_t; + +/* regcomp() flags */ +#define REG_BASIC 0000 +#define REG_EXTENDED 0001 +#define REG_ICASE 0002 +#define REG_NOSUB 0004 +#define REG_NEWLINE 0010 +#define REG_NOSPEC 0020 +#define REG_PEND 0040 +#define REG_DUMP 0200 + +/* regerror() flags */ +#define REG_NOMATCH 1 +#define REG_BADPAT 2 +#define REG_ECOLLATE 3 +#define REG_ECTYPE 4 +#define REG_EESCAPE 5 +#define REG_ESUBREG 6 +#define REG_EBRACK 7 +#define REG_EPAREN 8 +#define REG_EBRACE 9 +#define REG_BADBR 10 +#define REG_ERANGE 11 +#define REG_ESPACE 12 +#define REG_BADRPT 13 +#define REG_EMPTY 14 +#define REG_ASSERT 15 +#define REG_INVARG 16 +#define REG_ATOI 255 /* convert name to number (!) */ +#define REG_ITOA 0400 /* convert number to name (!) */ + +/* regexec() flags */ +#define REG_NOTBOL 00001 +#define REG_NOTEOL 00002 +#define REG_STARTEND 00004 +#define REG_TRACE 00400 /* tracing of execution */ +#define REG_LARGE 01000 /* force large representation */ +#define REG_BACKR 02000 /* force use of backref code */ + +__BEGIN_DECLS +int regcomp(regex_t *__restrict, const char *__restrict, int); +size_t regerror(int, const regex_t *__restrict, char *__restrict, size_t); +int regexec(const regex_t *__restrict, const char *__restrict, + size_t, regmatch_t [__restrict], int); +void regfree(regex_t *); +__END_DECLS + +#endif /* !_REGEX_H_ */ diff --git a/components/newlib/include/sched.h b/components/newlib/include/sched.h new file mode 100644 index 0000000000..504ad5274a --- /dev/null +++ b/components/newlib/include/sched.h @@ -0,0 +1,97 @@ +/* + * Written by Joel Sherrill . + * + * COPYRIGHT (c) 1989-2010. + * On-Line Applications Research Corporation (OAR). + * + * Permission to use, copy, modify, and distribute this software for any + * purpose without fee is hereby granted, provided that this entire notice + * is included in all copies of any software which is or includes a copy + * or modification of this software. + * + * THIS SOFTWARE IS BEING PROVIDED "AS IS", WITHOUT ANY EXPRESS OR IMPLIED + * WARRANTY. IN PARTICULAR, THE AUTHOR MAKES NO REPRESENTATION + * OR WARRANTY OF ANY KIND CONCERNING THE MERCHANTABILITY OF THIS + * SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR PURPOSE. + * + * $Id$ + */ + +#ifndef _SCHED_H_ +#define _SCHED_H_ + +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +#if defined(_POSIX_PRIORITY_SCHEDULING) +/* + * XBD 13 - Set Scheduling Parameters, P1003.1b-2008, p. 1803 + */ +int sched_setparam( + pid_t __pid, + const struct sched_param *__param +); + +/* + * XBD 13 - Set Scheduling Parameters, P1003.1b-2008, p. 1800 + */ +int sched_getparam( + pid_t __pid, + struct sched_param *__param +); + +/* + * XBD 13 - Set Scheduling Policy and Scheduling Parameters, + * P1003.1b-2008, p. 1805 + */ +int sched_setscheduler( + pid_t __pid, + int __policy, + const struct sched_param *__param +); + +/* + * XBD 13 - Get Scheduling Policy, P1003.1b-2008, p. 1801 + */ +int sched_getscheduler( + pid_t __pid +); + +/* + * XBD 13 - Get Scheduling Parameter Limits, P1003.1b-2008, p. 1799 + */ +int sched_get_priority_max( + int __policy +); + +int sched_get_priority_min( + int __policy +); + +/* + * XBD 13 - Get Scheduling Parameter Limits, P1003.1b-2008, p. 1802 + */ +int sched_rr_get_interval( + pid_t __pid, + struct timespec *__interval +); +#endif /* _POSIX_PRIORITY_SCHEDULING */ + +#if defined(_POSIX_THREADS) || defined(_POSIX_PRIORITY_SCHEDULING) + +/* + * XBD 13 - Yield Processor, P1003.1b-2008, p. 1807 + */ +int sched_yield( void ); + +#endif /* _POSIX_THREADS or _POSIX_PRIORITY_SCHEDULING */ + +#ifdef __cplusplus +} +#endif + +#endif /* _SCHED_H_ */ diff --git a/components/newlib/include/search.h b/components/newlib/include/search.h new file mode 100644 index 0000000000..ed321b0f64 --- /dev/null +++ b/components/newlib/include/search.h @@ -0,0 +1,64 @@ +/* $NetBSD: search.h,v 1.12 1999/02/22 10:34:28 christos Exp $ */ +/* $FreeBSD: src/include/search.h,v 1.4 2002/03/23 17:24:53 imp Exp $ */ + +/* + * Written by J.T. Conklin + * Public domain. + */ + +#ifndef _SEARCH_H_ +#define _SEARCH_H_ + +#include +#include +#include + +typedef struct entry { + char *key; + void *data; +} ENTRY; + +typedef enum { + FIND, ENTER +} ACTION; + +typedef enum { + preorder, + postorder, + endorder, + leaf +} VISIT; + +#ifdef _SEARCH_PRIVATE +typedef struct node { + char *key; + struct node *llink, *rlink; +} node_t; +#endif + +struct hsearch_data +{ + struct internal_head *htable; + size_t htablesize; +}; + +#ifndef __compar_fn_t_defined +#define __compar_fn_t_defined +typedef int (*__compar_fn_t) (const void *, const void *); +#endif + +__BEGIN_DECLS +int hcreate(size_t); +void hdestroy(void); +ENTRY *hsearch(ENTRY, ACTION); +int hcreate_r(size_t, struct hsearch_data *); +void hdestroy_r(struct hsearch_data *); +int hsearch_r(ENTRY, ACTION, ENTRY **, struct hsearch_data *); +void *tdelete(const void *__restrict, void **__restrict, __compar_fn_t); +void tdestroy (void *, void (*)(void *)); +void *tfind(const void *, void **, __compar_fn_t); +void *tsearch(const void *, void **, __compar_fn_t); +void twalk(const void *, void (*)(const void *, VISIT, int)); +__END_DECLS + +#endif /* !_SEARCH_H_ */ diff --git a/components/newlib/include/setjmp.h b/components/newlib/include/setjmp.h new file mode 100644 index 0000000000..3d815d9b9b --- /dev/null +++ b/components/newlib/include/setjmp.h @@ -0,0 +1,27 @@ +/* + setjmp.h + stubs for future use. +*/ + +#ifndef _SETJMP_H_ +#define _SETJMP_H_ + +#include "_ansi.h" +#include + +_BEGIN_STD_C + +#ifdef __GNUC__ +void _EXFUN(longjmp,(jmp_buf __jmpb, int __retval)) + __attribute__ ((__noreturn__)); +#else +void _EXFUN(longjmp,(jmp_buf __jmpb, int __retval)); +#endif +int _EXFUN(setjmp,(jmp_buf __jmpb)); +#define setjmp(env) setjmp(env) + + +_END_STD_C + +#endif /* _SETJMP_H_ */ + diff --git a/components/newlib/include/signal.h b/components/newlib/include/signal.h new file mode 100644 index 0000000000..8c50a2eb30 --- /dev/null +++ b/components/newlib/include/signal.h @@ -0,0 +1,32 @@ +#ifndef _SIGNAL_H_ +#define _SIGNAL_H_ + +#include "_ansi.h" +#include + +_BEGIN_STD_C + +typedef int sig_atomic_t; /* Atomic entity type (ANSI) */ +#ifndef _POSIX_SOURCE +typedef _sig_func_ptr sig_t; /* BSD naming */ +typedef _sig_func_ptr sighandler_t; /* glibc naming */ +#endif /* !_POSIX_SOURCE */ + +#define SIG_DFL ((_sig_func_ptr)0) /* Default action */ +#define SIG_IGN ((_sig_func_ptr)1) /* Ignore action */ +#define SIG_ERR ((_sig_func_ptr)-1) /* Error return */ + +struct _reent; + +_sig_func_ptr _EXFUN(_signal_r, (struct _reent *, int, _sig_func_ptr)); +int _EXFUN(_raise_r, (struct _reent *, int)); + +#ifndef _REENT_ONLY +_sig_func_ptr _EXFUN(signal, (int, _sig_func_ptr)); +int _EXFUN(raise, (int)); +void _EXFUN(psignal, (int, const char *)); +#endif + +_END_STD_C + +#endif /* _SIGNAL_H_ */ diff --git a/components/newlib/include/spawn.h b/components/newlib/include/spawn.h new file mode 100644 index 0000000000..5a6692f115 --- /dev/null +++ b/components/newlib/include/spawn.h @@ -0,0 +1,119 @@ +/*- + * Copyright (c) 2008 Ed Schouten + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef _SPAWN_H_ +#define _SPAWN_H_ + +#include <_ansi.h> +#include +#include +#include +#define __need_sigset_t +#include + +struct sched_param; + +typedef struct __posix_spawnattr *posix_spawnattr_t; +typedef struct __posix_spawn_file_actions *posix_spawn_file_actions_t; + +#define POSIX_SPAWN_RESETIDS 0x01 +#define POSIX_SPAWN_SETPGROUP 0x02 +#define POSIX_SPAWN_SETSCHEDPARAM 0x04 +#define POSIX_SPAWN_SETSCHEDULER 0x08 +#define POSIX_SPAWN_SETSIGDEF 0x10 +#define POSIX_SPAWN_SETSIGMASK 0x20 + +_BEGIN_STD_C +/* + * Spawn routines + * + * XXX both arrays should be __restrict, but this does not work when GCC + * is invoked with -std=c99. + */ +int _EXFUN(posix_spawn, (pid_t * __restrict, const char * __restrict, + const posix_spawn_file_actions_t *, const posix_spawnattr_t * __restrict, + char * const [], char * const []) +); +int _EXFUN(posix_spawnp, (pid_t * __restrict, const char * __restrict, + const posix_spawn_file_actions_t *, const posix_spawnattr_t * __restrict, + char * const [], char * const []) +); + +/* + * File descriptor actions + */ +int _EXFUN(posix_spawn_file_actions_init, (posix_spawn_file_actions_t *)); +int _EXFUN(posix_spawn_file_actions_destroy, (posix_spawn_file_actions_t *)); + +int _EXFUN(posix_spawn_file_actions_addopen, + (posix_spawn_file_actions_t * __restrict, int, const char * __restrict, int, mode_t) +); +int _EXFUN(posix_spawn_file_actions_adddup2, + (posix_spawn_file_actions_t *, int, int) +); +int _EXFUN(posix_spawn_file_actions_addclose, + (posix_spawn_file_actions_t *, int) +); + +/* + * Spawn attributes + */ +int _EXFUN(posix_spawnattr_init, (posix_spawnattr_t *)); +int _EXFUN(posix_spawnattr_destroy, (posix_spawnattr_t *)); + +int _EXFUN(posix_spawnattr_getflags, + (const posix_spawnattr_t * __restrict, short * __restrict) +); +int _EXFUN(posix_spawnattr_getpgroup, + (const posix_spawnattr_t * __restrict, pid_t * __restrict)); +int _EXFUN(posix_spawnattr_getschedparam, + (const posix_spawnattr_t * __restrict, struct sched_param * __restrict) +); +int _EXFUN(posix_spawnattr_getschedpolicy, + (const posix_spawnattr_t * __restrict, int * __restrict) +); +int _EXFUN(posix_spawnattr_getsigdefault, + (const posix_spawnattr_t * __restrict, sigset_t * __restrict) +); +int _EXFUN(posix_spawnattr_getsigmask, + (const posix_spawnattr_t * __restrict, sigset_t * __restrict) +); + +int _EXFUN(posix_spawnattr_setflags, (posix_spawnattr_t *, short)); +int _EXFUN(posix_spawnattr_setpgroup, (posix_spawnattr_t *, pid_t)); +int _EXFUN(posix_spawnattr_setschedparam, + (posix_spawnattr_t * __restrict, const struct sched_param * __restrict) +); +int _EXFUN(posix_spawnattr_setschedpolicy, (posix_spawnattr_t *, int)); +int _EXFUN(posix_spawnattr_setsigdefault, + (posix_spawnattr_t * __restrict, const sigset_t * __restrict) +); +int _EXFUN(posix_spawnattr_setsigmask, + (posix_spawnattr_t * __restrict, const sigset_t * __restrict) +); +_END_STD_C + +#endif /* !_SPAWN_H_ */ diff --git a/components/newlib/include/stdatomic.h b/components/newlib/include/stdatomic.h new file mode 100644 index 0000000000..09c0cf73e0 --- /dev/null +++ b/components/newlib/include/stdatomic.h @@ -0,0 +1,413 @@ +/*- + * Copyright (c) 2011 Ed Schouten + * David Chisnall + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $FreeBSD$ + */ + +#ifndef _STDATOMIC_H_ +#define _STDATOMIC_H_ + +#include +#include + +#if __has_extension(c_atomic) || __has_extension(cxx_atomic) +#define __CLANG_ATOMICS +#elif __GNUC_PREREQ__(4, 7) +#define __GNUC_ATOMICS +#elif defined(__GNUC__) +#define __SYNC_ATOMICS +#else +#error "stdatomic.h does not support your compiler" +#endif + +/* + * 7.17.1 Atomic lock-free macros. + */ + +#ifdef __GCC_ATOMIC_BOOL_LOCK_FREE +#define ATOMIC_BOOL_LOCK_FREE __GCC_ATOMIC_BOOL_LOCK_FREE +#endif +#ifdef __GCC_ATOMIC_CHAR_LOCK_FREE +#define ATOMIC_CHAR_LOCK_FREE __GCC_ATOMIC_CHAR_LOCK_FREE +#endif +#ifdef __GCC_ATOMIC_CHAR16_T_LOCK_FREE +#define ATOMIC_CHAR16_T_LOCK_FREE __GCC_ATOMIC_CHAR16_T_LOCK_FREE +#endif +#ifdef __GCC_ATOMIC_CHAR32_T_LOCK_FREE +#define ATOMIC_CHAR32_T_LOCK_FREE __GCC_ATOMIC_CHAR32_T_LOCK_FREE +#endif +#ifdef __GCC_ATOMIC_WCHAR_T_LOCK_FREE +#define ATOMIC_WCHAR_T_LOCK_FREE __GCC_ATOMIC_WCHAR_T_LOCK_FREE +#endif +#ifdef __GCC_ATOMIC_SHORT_LOCK_FREE +#define ATOMIC_SHORT_LOCK_FREE __GCC_ATOMIC_SHORT_LOCK_FREE +#endif +#ifdef __GCC_ATOMIC_INT_LOCK_FREE +#define ATOMIC_INT_LOCK_FREE __GCC_ATOMIC_INT_LOCK_FREE +#endif +#ifdef __GCC_ATOMIC_LONG_LOCK_FREE +#define ATOMIC_LONG_LOCK_FREE __GCC_ATOMIC_LONG_LOCK_FREE +#endif +#ifdef __GCC_ATOMIC_LLONG_LOCK_FREE +#define ATOMIC_LLONG_LOCK_FREE __GCC_ATOMIC_LLONG_LOCK_FREE +#endif +#ifdef __GCC_ATOMIC_POINTER_LOCK_FREE +#define ATOMIC_POINTER_LOCK_FREE __GCC_ATOMIC_POINTER_LOCK_FREE +#endif + +/* + * 7.17.2 Initialization. + */ + +#if defined(__CLANG_ATOMICS) +#define ATOMIC_VAR_INIT(value) (value) +#define atomic_init(obj, value) __c11_atomic_init(obj, value) +#else +#define ATOMIC_VAR_INIT(value) { .__val = (value) } +#define atomic_init(obj, value) ((void)((obj)->__val = (value))) +#endif + +/* + * Clang and recent GCC both provide predefined macros for the memory + * orderings. If we are using a compiler that doesn't define them, use the + * clang values - these will be ignored in the fallback path. + */ + +#ifndef __ATOMIC_RELAXED +#define __ATOMIC_RELAXED 0 +#endif +#ifndef __ATOMIC_CONSUME +#define __ATOMIC_CONSUME 1 +#endif +#ifndef __ATOMIC_ACQUIRE +#define __ATOMIC_ACQUIRE 2 +#endif +#ifndef __ATOMIC_RELEASE +#define __ATOMIC_RELEASE 3 +#endif +#ifndef __ATOMIC_ACQ_REL +#define __ATOMIC_ACQ_REL 4 +#endif +#ifndef __ATOMIC_SEQ_CST +#define __ATOMIC_SEQ_CST 5 +#endif + +/* + * 7.17.3 Order and consistency. + * + * The memory_order_* constants that denote the barrier behaviour of the + * atomic operations. + */ + +typedef enum { + memory_order_relaxed = __ATOMIC_RELAXED, + memory_order_consume = __ATOMIC_CONSUME, + memory_order_acquire = __ATOMIC_ACQUIRE, + memory_order_release = __ATOMIC_RELEASE, + memory_order_acq_rel = __ATOMIC_ACQ_REL, + memory_order_seq_cst = __ATOMIC_SEQ_CST +} memory_order; + +/* + * 7.17.4 Fences. + */ + +static __inline void +atomic_thread_fence(memory_order __order __unused) +{ + +#ifdef __CLANG_ATOMICS + __c11_atomic_thread_fence(__order); +#elif defined(__GNUC_ATOMICS) + __atomic_thread_fence(__order); +#else + __sync_synchronize(); +#endif +} + +static __inline void +atomic_signal_fence(memory_order __order __unused) +{ + +#ifdef __CLANG_ATOMICS + __c11_atomic_signal_fence(__order); +#elif defined(__GNUC_ATOMICS) + __atomic_signal_fence(__order); +#else + __asm volatile ("" ::: "memory"); +#endif +} + +/* + * 7.17.5 Lock-free property. + */ + +#if defined(_KERNEL) +/* Atomics in kernelspace are always lock-free. */ +#define atomic_is_lock_free(obj) \ + ((void)(obj), (_Bool)1) +#elif defined(__CLANG_ATOMICS) +#define atomic_is_lock_free(obj) \ + __atomic_is_lock_free(sizeof(*(obj)), obj) +#elif defined(__GNUC_ATOMICS) +#define atomic_is_lock_free(obj) \ + __atomic_is_lock_free(sizeof((obj)->__val), &(obj)->__val) +#else +#define atomic_is_lock_free(obj) \ + ((void)(obj), sizeof((obj)->__val) <= sizeof(void *)) +#endif + +/* + * 7.17.6 Atomic integer types. + */ + +typedef _Atomic(_Bool) atomic_bool; +typedef _Atomic(char) atomic_char; +typedef _Atomic(signed char) atomic_schar; +typedef _Atomic(unsigned char) atomic_uchar; +typedef _Atomic(short) atomic_short; +typedef _Atomic(unsigned short) atomic_ushort; +typedef _Atomic(int) atomic_int; +typedef _Atomic(unsigned int) atomic_uint; +typedef _Atomic(long) atomic_long; +typedef _Atomic(unsigned long) atomic_ulong; +typedef _Atomic(long long) atomic_llong; +typedef _Atomic(unsigned long long) atomic_ullong; +#if 0 +typedef _Atomic(__char16_t) atomic_char16_t; +typedef _Atomic(__char32_t) atomic_char32_t; +#endif +typedef _Atomic(wchar_t) atomic_wchar_t; +typedef _Atomic(int_least8_t) atomic_int_least8_t; +typedef _Atomic(uint_least8_t) atomic_uint_least8_t; +typedef _Atomic(int_least16_t) atomic_int_least16_t; +typedef _Atomic(uint_least16_t) atomic_uint_least16_t; +typedef _Atomic(int_least32_t) atomic_int_least32_t; +typedef _Atomic(uint_least32_t) atomic_uint_least32_t; +typedef _Atomic(int_least64_t) atomic_int_least64_t; +typedef _Atomic(uint_least64_t) atomic_uint_least64_t; +typedef _Atomic(int_fast8_t) atomic_int_fast8_t; +typedef _Atomic(uint_fast8_t) atomic_uint_fast8_t; +typedef _Atomic(int_fast16_t) atomic_int_fast16_t; +typedef _Atomic(uint_fast16_t) atomic_uint_fast16_t; +typedef _Atomic(int_fast32_t) atomic_int_fast32_t; +typedef _Atomic(uint_fast32_t) atomic_uint_fast32_t; +typedef _Atomic(int_fast64_t) atomic_int_fast64_t; +typedef _Atomic(uint_fast64_t) atomic_uint_fast64_t; +typedef _Atomic(intptr_t) atomic_intptr_t; +typedef _Atomic(uintptr_t) atomic_uintptr_t; +typedef _Atomic(size_t) atomic_size_t; +typedef _Atomic(ptrdiff_t) atomic_ptrdiff_t; +typedef _Atomic(intmax_t) atomic_intmax_t; +typedef _Atomic(uintmax_t) atomic_uintmax_t; + +/* + * 7.17.7 Operations on atomic types. + */ + +/* + * Compiler-specific operations. + */ + +#if defined(__CLANG_ATOMICS) +#define atomic_compare_exchange_strong_explicit(object, expected, \ + desired, success, failure) \ + __c11_atomic_compare_exchange_strong(object, expected, desired, \ + success, failure) +#define atomic_compare_exchange_weak_explicit(object, expected, \ + desired, success, failure) \ + __c11_atomic_compare_exchange_weak(object, expected, desired, \ + success, failure) +#define atomic_exchange_explicit(object, desired, order) \ + __c11_atomic_exchange(object, desired, order) +#define atomic_fetch_add_explicit(object, operand, order) \ + __c11_atomic_fetch_add(object, operand, order) +#define atomic_fetch_and_explicit(object, operand, order) \ + __c11_atomic_fetch_and(object, operand, order) +#define atomic_fetch_or_explicit(object, operand, order) \ + __c11_atomic_fetch_or(object, operand, order) +#define atomic_fetch_sub_explicit(object, operand, order) \ + __c11_atomic_fetch_sub(object, operand, order) +#define atomic_fetch_xor_explicit(object, operand, order) \ + __c11_atomic_fetch_xor(object, operand, order) +#define atomic_load_explicit(object, order) \ + __c11_atomic_load(object, order) +#define atomic_store_explicit(object, desired, order) \ + __c11_atomic_store(object, desired, order) +#elif defined(__GNUC_ATOMICS) +#define atomic_compare_exchange_strong_explicit(object, expected, \ + desired, success, failure) \ + __atomic_compare_exchange_n(&(object)->__val, expected, \ + desired, 0, success, failure) +#define atomic_compare_exchange_weak_explicit(object, expected, \ + desired, success, failure) \ + __atomic_compare_exchange_n(&(object)->__val, expected, \ + desired, 1, success, failure) +#define atomic_exchange_explicit(object, desired, order) \ + __atomic_exchange_n(&(object)->__val, desired, order) +#define atomic_fetch_add_explicit(object, operand, order) \ + __atomic_fetch_add(&(object)->__val, operand, order) +#define atomic_fetch_and_explicit(object, operand, order) \ + __atomic_fetch_and(&(object)->__val, operand, order) +#define atomic_fetch_or_explicit(object, operand, order) \ + __atomic_fetch_or(&(object)->__val, operand, order) +#define atomic_fetch_sub_explicit(object, operand, order) \ + __atomic_fetch_sub(&(object)->__val, operand, order) +#define atomic_fetch_xor_explicit(object, operand, order) \ + __atomic_fetch_xor(&(object)->__val, operand, order) +#define atomic_load_explicit(object, order) \ + __atomic_load_n(&(object)->__val, order) +#define atomic_store_explicit(object, desired, order) \ + __atomic_store_n(&(object)->__val, desired, order) +#else +#define __atomic_apply_stride(object, operand) \ + (((__typeof__((object)->__val))0) + (operand)) +#define atomic_compare_exchange_strong_explicit(object, expected, \ + desired, success, failure) __extension__ ({ \ + __typeof__(expected) __ep = (expected); \ + __typeof__(*__ep) __e = *__ep; \ + (void)(success); (void)(failure); \ + (_Bool)((*__ep = __sync_val_compare_and_swap(&(object)->__val, \ + __e, desired)) == __e); \ +}) +#define atomic_compare_exchange_weak_explicit(object, expected, \ + desired, success, failure) \ + atomic_compare_exchange_strong_explicit(object, expected, \ + desired, success, failure) +#if __has_builtin(__sync_swap) +/* Clang provides a full-barrier atomic exchange - use it if available. */ +#define atomic_exchange_explicit(object, desired, order) \ + ((void)(order), __sync_swap(&(object)->__val, desired)) +#else +/* + * __sync_lock_test_and_set() is only an acquire barrier in theory (although in + * practice it is usually a full barrier) so we need an explicit barrier before + * it. + */ +#define atomic_exchange_explicit(object, desired, order) \ +__extension__ ({ \ + __typeof__(object) __o = (object); \ + __typeof__(desired) __d = (desired); \ + (void)(order); \ + __sync_synchronize(); \ + __sync_lock_test_and_set(&(__o)->__val, __d); \ +}) +#endif +#define atomic_fetch_add_explicit(object, operand, order) \ + ((void)(order), __sync_fetch_and_add(&(object)->__val, \ + __atomic_apply_stride(object, operand))) +#define atomic_fetch_and_explicit(object, operand, order) \ + ((void)(order), __sync_fetch_and_and(&(object)->__val, operand)) +#define atomic_fetch_or_explicit(object, operand, order) \ + ((void)(order), __sync_fetch_and_or(&(object)->__val, operand)) +#define atomic_fetch_sub_explicit(object, operand, order) \ + ((void)(order), __sync_fetch_and_sub(&(object)->__val, \ + __atomic_apply_stride(object, operand))) +#define atomic_fetch_xor_explicit(object, operand, order) \ + ((void)(order), __sync_fetch_and_xor(&(object)->__val, operand)) +#define atomic_load_explicit(object, order) \ + ((void)(order), __sync_fetch_and_add(&(object)->__val, 0)) +#define atomic_store_explicit(object, desired, order) \ + ((void)atomic_exchange_explicit(object, desired, order)) +#endif + +/* + * Convenience functions. + * + * Don't provide these in kernel space. In kernel space, we should be + * disciplined enough to always provide explicit barriers. + */ + +#ifndef _KERNEL +#define atomic_compare_exchange_strong(object, expected, desired) \ + atomic_compare_exchange_strong_explicit(object, expected, \ + desired, memory_order_seq_cst, memory_order_seq_cst) +#define atomic_compare_exchange_weak(object, expected, desired) \ + atomic_compare_exchange_weak_explicit(object, expected, \ + desired, memory_order_seq_cst, memory_order_seq_cst) +#define atomic_exchange(object, desired) \ + atomic_exchange_explicit(object, desired, memory_order_seq_cst) +#define atomic_fetch_add(object, operand) \ + atomic_fetch_add_explicit(object, operand, memory_order_seq_cst) +#define atomic_fetch_and(object, operand) \ + atomic_fetch_and_explicit(object, operand, memory_order_seq_cst) +#define atomic_fetch_or(object, operand) \ + atomic_fetch_or_explicit(object, operand, memory_order_seq_cst) +#define atomic_fetch_sub(object, operand) \ + atomic_fetch_sub_explicit(object, operand, memory_order_seq_cst) +#define atomic_fetch_xor(object, operand) \ + atomic_fetch_xor_explicit(object, operand, memory_order_seq_cst) +#define atomic_load(object) \ + atomic_load_explicit(object, memory_order_seq_cst) +#define atomic_store(object, desired) \ + atomic_store_explicit(object, desired, memory_order_seq_cst) +#endif /* !_KERNEL */ + +/* + * 7.17.8 Atomic flag type and operations. + * + * XXX: Assume atomic_bool can be used as an atomic_flag. Is there some + * kind of compiler built-in type we could use? + */ + +typedef struct { + atomic_bool __flag; +} atomic_flag; + +#define ATOMIC_FLAG_INIT { ATOMIC_VAR_INIT(0) } + +static __inline _Bool +atomic_flag_test_and_set_explicit(volatile atomic_flag *__object, + memory_order __order) +{ + return (atomic_exchange_explicit(&__object->__flag, 1, __order)); +} + +static __inline void +atomic_flag_clear_explicit(volatile atomic_flag *__object, memory_order __order) +{ + + atomic_store_explicit(&__object->__flag, 0, __order); +} + +#ifndef _KERNEL +static __inline _Bool +atomic_flag_test_and_set(volatile atomic_flag *__object) +{ + + return (atomic_flag_test_and_set_explicit(__object, + memory_order_seq_cst)); +} + +static __inline void +atomic_flag_clear(volatile atomic_flag *__object) +{ + + atomic_flag_clear_explicit(__object, memory_order_seq_cst); +} +#endif /* !_KERNEL */ + +#endif /* !_STDATOMIC_H_ */ diff --git a/components/newlib/include/stdint.h b/components/newlib/include/stdint.h new file mode 100644 index 0000000000..7386164b9d --- /dev/null +++ b/components/newlib/include/stdint.h @@ -0,0 +1,511 @@ +/* + * Copyright (c) 2004, 2005 by + * Ralf Corsepius, Ulm/Germany. All rights reserved. + * + * Permission to use, copy, modify, and distribute this software + * is freely granted, provided that this notice is preserved. + */ + +#ifndef _STDINT_H +#define _STDINT_H + +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +#ifdef ___int8_t_defined +typedef __int8_t int8_t ; +typedef __uint8_t uint8_t ; +#define __int8_t_defined 1 +#endif + +#ifdef ___int_least8_t_defined +typedef __int_least8_t int_least8_t; +typedef __uint_least8_t uint_least8_t; +#define __int_least8_t_defined 1 +#endif + +#ifdef ___int16_t_defined +typedef __int16_t int16_t ; +typedef __uint16_t uint16_t ; +#define __int16_t_defined 1 +#endif + +#ifdef ___int_least16_t_defined +typedef __int_least16_t int_least16_t; +typedef __uint_least16_t uint_least16_t; +#define __int_least16_t_defined 1 +#endif + +#ifdef ___int32_t_defined +typedef __int32_t int32_t ; +typedef __uint32_t uint32_t ; +#define __int32_t_defined 1 +#endif + +#ifdef ___int_least32_t_defined +typedef __int_least32_t int_least32_t; +typedef __uint_least32_t uint_least32_t; +#define __int_least32_t_defined 1 +#endif + +#ifdef ___int64_t_defined +typedef __int64_t int64_t ; +typedef __uint64_t uint64_t ; +#define __int64_t_defined 1 +#endif + +#ifdef ___int_least64_t_defined +typedef __int_least64_t int_least64_t; +typedef __uint_least64_t uint_least64_t; +#define __int_least64_t_defined 1 +#endif + +/* + * Fastest minimum-width integer types + * + * Assume int to be the fastest type for all types with a width + * less than __INT_MAX__ rsp. INT_MAX + */ +#ifdef __INT_FAST8_TYPE__ + typedef __INT_FAST8_TYPE__ int_fast8_t; + typedef __UINT_FAST8_TYPE__ uint_fast8_t; +#define __int_fast8_t_defined 1 +#elif __STDINT_EXP(INT_MAX) >= 0x7f + typedef signed int int_fast8_t; + typedef unsigned int uint_fast8_t; +#define __int_fast8_t_defined 1 +#endif + +#ifdef __INT_FAST16_TYPE__ + typedef __INT_FAST16_TYPE__ int_fast16_t; + typedef __UINT_FAST16_TYPE__ uint_fast16_t; +#define __int_fast16_t_defined 1 +#elif __STDINT_EXP(INT_MAX) >= 0x7fff + typedef signed int int_fast16_t; + typedef unsigned int uint_fast16_t; +#define __int_fast16_t_defined 1 +#endif + +#ifdef __INT_FAST32_TYPE__ + typedef __INT_FAST32_TYPE__ int_fast32_t; + typedef __UINT_FAST32_TYPE__ uint_fast32_t; +#define __int_fast32_t_defined 1 +#elif __STDINT_EXP(INT_MAX) >= 0x7fffffff + typedef signed int int_fast32_t; + typedef unsigned int uint_fast32_t; +#define __int_fast32_t_defined 1 +#endif + +#ifdef __INT_FAST64_TYPE__ + typedef __INT_FAST64_TYPE__ int_fast64_t; + typedef __UINT_FAST64_TYPE__ uint_fast64_t; +#define __int_fast64_t_defined 1 +#elif __STDINT_EXP(INT_MAX) > 0x7fffffff + typedef signed int int_fast64_t; + typedef unsigned int uint_fast64_t; +#define __int_fast64_t_defined 1 +#endif + +/* + * Fall back to [u]int_least_t for [u]int_fast_t types + * not having been defined, yet. + * Leave undefined, if [u]int_least_t should not be available. + */ +#if !__int_fast8_t_defined +#if __int_least8_t_defined + typedef int_least8_t int_fast8_t; + typedef uint_least8_t uint_fast8_t; +#define __int_fast8_t_defined 1 +#endif +#endif + +#if !__int_fast16_t_defined +#if __int_least16_t_defined + typedef int_least16_t int_fast16_t; + typedef uint_least16_t uint_fast16_t; +#define __int_fast16_t_defined 1 +#endif +#endif + +#if !__int_fast32_t_defined +#if __int_least32_t_defined + typedef int_least32_t int_fast32_t; + typedef uint_least32_t uint_fast32_t; +#define __int_fast32_t_defined 1 +#endif +#endif + +#if !__int_fast64_t_defined +#if __int_least64_t_defined + typedef int_least64_t int_fast64_t; + typedef uint_least64_t uint_fast64_t; +#define __int_fast64_t_defined 1 +#endif +#endif + +/* Greatest-width integer types */ +/* Modern GCCs provide __INTMAX_TYPE__ */ +#if defined(__INTMAX_TYPE__) + typedef __INTMAX_TYPE__ intmax_t; +#elif __have_longlong64 + typedef signed long long intmax_t; +#else + typedef signed long intmax_t; +#endif + +/* Modern GCCs provide __UINTMAX_TYPE__ */ +#if defined(__UINTMAX_TYPE__) + typedef __UINTMAX_TYPE__ uintmax_t; +#elif __have_longlong64 + typedef unsigned long long uintmax_t; +#else + typedef unsigned long uintmax_t; +#endif + +typedef __intptr_t intptr_t; +typedef __uintptr_t uintptr_t; + +#ifdef __INTPTR_TYPE__ +#define INTPTR_MIN (-__INTPTR_MAX__ - 1) +#define INTPTR_MAX __INTPTR_MAX__ +#define UINTPTR_MAX __UINTPTR_MAX__ +#elif defined(__PTRDIFF_TYPE__) +#define INTPTR_MAX PTRDIFF_MAX +#define INTPTR_MIN PTRDIFF_MIN +#ifdef __UINTPTR_MAX__ +#define UINTPTR_MAX __UINTPTR_MAX__ +#else +#define UINTPTR_MAX (2UL * PTRDIFF_MAX + 1) +#endif +#else +/* + * Fallback to hardcoded values, + * should be valid on cpu's with 32bit int/32bit void* + */ +#define INTPTR_MAX __STDINT_EXP(LONG_MAX) +#define INTPTR_MIN (-__STDINT_EXP(LONG_MAX) - 1) +#define UINTPTR_MAX (__STDINT_EXP(LONG_MAX) * 2UL + 1) +#endif + +/* Limits of Specified-Width Integer Types */ + +#ifdef __INT8_MAX__ +#define INT8_MIN (-__INT8_MAX__ - 1) +#define INT8_MAX __INT8_MAX__ +#define UINT8_MAX __UINT8_MAX__ +#elif defined(__int8_t_defined) +#define INT8_MIN -128 +#define INT8_MAX 127 +#define UINT8_MAX 255 +#endif + +#ifdef __INT_LEAST8_MAX__ +#define INT_LEAST8_MIN (-__INT_LEAST8_MAX__ - 1) +#define INT_LEAST8_MAX __INT_LEAST8_MAX__ +#define UINT_LEAST8_MAX __UINT_LEAST8_MAX__ +#elif defined(__int_least8_t_defined) +#define INT_LEAST8_MIN -128 +#define INT_LEAST8_MAX 127 +#define UINT_LEAST8_MAX 255 +#else +#error required type int_least8_t missing +#endif + +#ifdef __INT16_MAX__ +#define INT16_MIN (-__INT16_MAX__ - 1) +#define INT16_MAX __INT16_MAX__ +#define UINT16_MAX __UINT16_MAX__ +#elif defined(__int16_t_defined) +#define INT16_MIN -32768 +#define INT16_MAX 32767 +#define UINT16_MAX 65535 +#endif + +#ifdef __INT_LEAST16_MAX__ +#define INT_LEAST16_MIN (-__INT_LEAST16_MAX__ - 1) +#define INT_LEAST16_MAX __INT_LEAST16_MAX__ +#define UINT_LEAST16_MAX __UINT_LEAST16_MAX__ +#elif defined(__int_least16_t_defined) +#define INT_LEAST16_MIN -32768 +#define INT_LEAST16_MAX 32767 +#define UINT_LEAST16_MAX 65535 +#else +#error required type int_least16_t missing +#endif + +#ifdef __INT32_MAX__ +#define INT32_MIN (-__INT32_MAX__ - 1) +#define INT32_MAX __INT32_MAX__ +#define UINT32_MAX __UINT32_MAX__ +#elif defined(__int32_t_defined) +#if __have_long32 +#define INT32_MIN (-2147483647L-1) +#define INT32_MAX 2147483647L +#define UINT32_MAX 4294967295UL +#else +#define INT32_MIN (-2147483647-1) +#define INT32_MAX 2147483647 +#define UINT32_MAX 4294967295U +#endif +#endif + +#ifdef __INT_LEAST32_MAX__ +#define INT_LEAST32_MIN (-__INT_LEAST32_MAX__ - 1) +#define INT_LEAST32_MAX __INT_LEAST32_MAX__ +#define UINT_LEAST32_MAX __UINT_LEAST32_MAX__ +#elif defined(__int_least32_t_defined) +#if __have_long32 +#define INT_LEAST32_MIN (-2147483647L-1) +#define INT_LEAST32_MAX 2147483647L +#define UINT_LEAST32_MAX 4294967295UL +#else +#define INT_LEAST32_MIN (-2147483647-1) +#define INT_LEAST32_MAX 2147483647 +#define UINT_LEAST32_MAX 4294967295U +#endif +#else +#error required type int_least32_t missing +#endif + +#ifdef __INT64_MAX__ +#define INT64_MIN (-__INT64_MAX__ - 1) +#define INT64_MAX __INT64_MAX__ +#define UINT64_MAX __UINT64_MAX__ +#elif defined(__int64_t_defined) +#if __have_long64 +#define INT64_MIN (-9223372036854775807L-1L) +#define INT64_MAX 9223372036854775807L +#define UINT64_MAX 18446744073709551615U +#elif __have_longlong64 +#define INT64_MIN (-9223372036854775807LL-1LL) +#define INT64_MAX 9223372036854775807LL +#define UINT64_MAX 18446744073709551615ULL +#endif +#endif + +#ifdef __INT_LEAST64_MAX__ +#define INT_LEAST64_MIN (-__INT_LEAST64_MAX__ - 1) +#define INT_LEAST64_MAX __INT_LEAST64_MAX__ +#define UINT_LEAST64_MAX __UINT_LEAST64_MAX__ +#elif defined(__int_least64_t_defined) +#if __have_long64 +#define INT_LEAST64_MIN (-9223372036854775807L-1L) +#define INT_LEAST64_MAX 9223372036854775807L +#define UINT_LEAST64_MAX 18446744073709551615U +#elif __have_longlong64 +#define INT_LEAST64_MIN (-9223372036854775807LL-1LL) +#define INT_LEAST64_MAX 9223372036854775807LL +#define UINT_LEAST64_MAX 18446744073709551615ULL +#endif +#endif + +#ifdef __INT_FAST8_MAX__ +#define INT_FAST8_MIN (-__INT_FAST8_MAX__ - 1) +#define INT_FAST8_MAX __INT_FAST8_MAX__ +#define UINT_FAST8_MAX __UINT_FAST8_MAX__ +#elif defined(__int_fast8_t_defined) +#if __STDINT_EXP(INT_MAX) >= 0x7f +#define INT_FAST8_MIN (-__STDINT_EXP(INT_MAX)-1) +#define INT_FAST8_MAX __STDINT_EXP(INT_MAX) +#define UINT_FAST8_MAX (__STDINT_EXP(INT_MAX)*2U+1U) +#else +#define INT_FAST8_MIN INT_LEAST8_MIN +#define INT_FAST8_MAX INT_LEAST8_MAX +#define UINT_FAST8_MAX UINT_LEAST8_MAX +#endif +#endif + +#ifdef __INT_FAST16_MAX__ +#define INT_FAST16_MIN (-__INT_FAST16_MAX__ - 1) +#define INT_FAST16_MAX __INT_FAST16_MAX__ +#define UINT_FAST16_MAX __UINT_FAST16_MAX__ +#elif defined(__int_fast16_t_defined) +#if __STDINT_EXP(INT_MAX) >= 0x7fff +#define INT_FAST16_MIN (-__STDINT_EXP(INT_MAX)-1) +#define INT_FAST16_MAX __STDINT_EXP(INT_MAX) +#define UINT_FAST16_MAX (__STDINT_EXP(INT_MAX)*2U+1U) +#else +#define INT_FAST16_MIN INT_LEAST16_MIN +#define INT_FAST16_MAX INT_LEAST16_MAX +#define UINT_FAST16_MAX UINT_LEAST16_MAX +#endif +#endif + +#ifdef __INT_FAST32_MAX__ +#define INT_FAST32_MIN (-__INT_FAST32_MAX__ - 1) +#define INT_FAST32_MAX __INT_FAST32_MAX__ +#define UINT_FAST32_MAX __UINT_FAST32_MAX__ +#elif defined(__int_fast32_t_defined) +#if __STDINT_EXP(INT_MAX) >= 0x7fffffff +#define INT_FAST32_MIN (-__STDINT_EXP(INT_MAX)-1) +#define INT_FAST32_MAX __STDINT_EXP(INT_MAX) +#define UINT_FAST32_MAX (__STDINT_EXP(INT_MAX)*2U+1U) +#else +#define INT_FAST32_MIN INT_LEAST32_MIN +#define INT_FAST32_MAX INT_LEAST32_MAX +#define UINT_FAST32_MAX UINT_LEAST32_MAX +#endif +#endif + +#ifdef __INT_FAST64_MAX__ +#define INT_FAST64_MIN (-__INT_FAST64_MAX__ - 1) +#define INT_FAST64_MAX __INT_FAST64_MAX__ +#define UINT_FAST64_MAX __UINT_FAST64_MAX__ +#elif defined(__int_fast64_t_defined) +#if __STDINT_EXP(INT_MAX) > 0x7fffffff +#define INT_FAST64_MIN (-__STDINT_EXP(INT_MAX)-1) +#define INT_FAST64_MAX __STDINT_EXP(INT_MAX) +#define UINT_FAST64_MAX (__STDINT_EXP(INT_MAX)*2U+1U) +#else +#define INT_FAST64_MIN INT_LEAST64_MIN +#define INT_FAST64_MAX INT_LEAST64_MAX +#define UINT_FAST64_MAX UINT_LEAST64_MAX +#endif +#endif + +#ifdef __INTMAX_MAX__ +#define INTMAX_MAX __INTMAX_MAX__ +#define INTMAX_MIN (-INTMAX_MAX - 1) +#elif defined(__INTMAX_TYPE__) +/* All relevant GCC versions prefer long to long long for intmax_t. */ +#define INTMAX_MAX INT64_MAX +#define INTMAX_MIN INT64_MIN +#endif + +#ifdef __UINTMAX_MAX__ +#define UINTMAX_MAX __UINTMAX_MAX__ +#elif defined(__UINTMAX_TYPE__) +/* All relevant GCC versions prefer long to long long for intmax_t. */ +#define UINTMAX_MAX UINT64_MAX +#endif + +/* This must match size_t in stddef.h, currently long unsigned int */ +#ifdef __SIZE_MAX__ +#define SIZE_MAX __SIZE_MAX__ +#else +#define SIZE_MAX (__STDINT_EXP(LONG_MAX) * 2UL + 1) +#endif + +/* This must match sig_atomic_t in (currently int) */ +#define SIG_ATOMIC_MIN (-__STDINT_EXP(INT_MAX) - 1) +#define SIG_ATOMIC_MAX __STDINT_EXP(INT_MAX) + +/* This must match ptrdiff_t in (currently long int) */ +#ifdef __PTRDIFF_MAX__ +#define PTRDIFF_MAX __PTRDIFF_MAX__ +#else +#define PTRDIFF_MAX __STDINT_EXP(LONG_MAX) +#endif +#define PTRDIFF_MIN (-PTRDIFF_MAX - 1) + +/* This must match definition in */ +#ifndef WCHAR_MIN +#ifdef __WCHAR_MIN__ +#define WCHAR_MIN __WCHAR_MIN__ +#elif defined(__WCHAR_UNSIGNED__) || (L'\0' - 1 > 0) +#define WCHAR_MIN (0 + L'\0') +#else +#define WCHAR_MIN (-0x7fffffff - 1 + L'\0') +#endif +#endif + +/* This must match definition in */ +#ifndef WCHAR_MAX +#ifdef __WCHAR_MAX__ +#define WCHAR_MAX __WCHAR_MAX__ +#elif defined(__WCHAR_UNSIGNED__) || (L'\0' - 1 > 0) +#define WCHAR_MAX (0xffffffffu + L'\0') +#else +#define WCHAR_MAX (0x7fffffff + L'\0') +#endif +#endif + +/* wint_t is unsigned int on almost all GCC targets. */ +#ifdef __WINT_MAX__ +#define WINT_MAX __WINT_MAX__ +#else +#define WINT_MAX (__STDINT_EXP(INT_MAX) * 2U + 1U) +#endif +#ifdef __WINT_MIN__ +#define WINT_MIN __WINT_MIN__ +#else +#define WINT_MIN 0U +#endif + +/** Macros for minimum-width integer constant expressions */ +#ifdef __INT8_C +#define INT8_C(x) __INT8_C(x) +#define UINT8_C(x) __UINT8_C(x) +#else +#define INT8_C(x) x +#if __STDINT_EXP(INT_MAX) > 0x7f +#define UINT8_C(x) x +#else +#define UINT8_C(x) x##U +#endif +#endif + +#ifdef __INT16_C +#define INT16_C(x) __INT16_C(x) +#define UINT16_C(x) __UINT16_C(x) +#else +#define INT16_C(x) x +#if __STDINT_EXP(INT_MAX) > 0x7fff +#define UINT16_C(x) x +#else +#define UINT16_C(x) x##U +#endif +#endif + +#ifdef __INT32_C +#define INT32_C(x) __INT32_C(x) +#define UINT32_C(x) __UINT32_C(x) +#else +#if __have_long32 +#define INT32_C(x) x##L +#define UINT32_C(x) x##UL +#else +#define INT32_C(x) x +#define UINT32_C(x) x##U +#endif +#endif + +#ifdef __INT64_C +#define INT64_C(x) __INT64_C(x) +#define UINT64_C(x) __UINT64_C(x) +#else +#if __int64_t_defined +#if __have_long64 +#define INT64_C(x) x##L +#define UINT64_C(x) x##UL +#else +#define INT64_C(x) x##LL +#define UINT64_C(x) x##ULL +#endif +#endif +#endif + +/** Macros for greatest-width integer constant expression */ +#ifdef __INTMAX_C +#define INTMAX_C(x) __INTMAX_C(x) +#define UINTMAX_C(x) __UINTMAX_C(x) +#else +#if __have_long64 +#define INTMAX_C(x) x##L +#define UINTMAX_C(x) x##UL +#else +#define INTMAX_C(x) x##LL +#define UINTMAX_C(x) x##ULL +#endif +#endif + + +#ifdef __cplusplus +} +#endif + +#endif /* _STDINT_H */ diff --git a/components/newlib/include/stdio.h b/components/newlib/include/stdio.h new file mode 100644 index 0000000000..e336ee6eba --- /dev/null +++ b/components/newlib/include/stdio.h @@ -0,0 +1,727 @@ +/* + * Copyright (c) 1990 The Regents of the University of California. + * All rights reserved. + * + * Redistribution and use in source and binary forms are permitted + * provided that the above copyright notice and this paragraph are + * duplicated in all such forms and that any documentation, + * advertising materials, and other materials related to such + * distribution and use acknowledge that the software was developed + * by the University of California, Berkeley. The name of the + * University may not be used to endorse or promote products derived + * from this software without specific prior written permission. + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. + * + * @(#)stdio.h 5.3 (Berkeley) 3/15/86 + */ + +/* + * NB: to fit things in six character monocase externals, the + * stdio code uses the prefix `__s' for stdio objects, typically + * followed by a three-character attempt at a mnemonic. + */ + +#ifndef _STDIO_H_ +#define _STDIO_H_ + +#include "_ansi.h" + +#define _FSTDIO /* ``function stdio'' */ + +#define __need_size_t +#define __need_NULL +#include +#include + +#define __need___va_list +#include + +/* + * defines __FILE, _fpos_t. + * They must be defined there because struct _reent needs them (and we don't + * want reent.h to include this file. + */ + +#include +#include + +_BEGIN_STD_C + +typedef __FILE FILE; + +#ifdef __CYGWIN__ +typedef _fpos64_t fpos_t; +#else +typedef _fpos_t fpos_t; +#ifdef __LARGE64_FILES +typedef _fpos64_t fpos64_t; +#endif +#endif /* !__CYGWIN__ */ + +#include + +#define __SLBF 0x0001 /* line buffered */ +#define __SNBF 0x0002 /* unbuffered */ +#define __SRD 0x0004 /* OK to read */ +#define __SWR 0x0008 /* OK to write */ + /* RD and WR are never simultaneously asserted */ +#define __SRW 0x0010 /* open for reading & writing */ +#define __SEOF 0x0020 /* found EOF */ +#define __SERR 0x0040 /* found error */ +#define __SMBF 0x0080 /* _buf is from malloc */ +#define __SAPP 0x0100 /* fdopen()ed in append mode - so must write to end */ +#define __SSTR 0x0200 /* this is an sprintf/snprintf string */ +#define __SOPT 0x0400 /* do fseek() optimisation */ +#define __SNPT 0x0800 /* do not do fseek() optimisation */ +#define __SOFF 0x1000 /* set iff _offset is in fact correct */ +#define __SORD 0x2000 /* true => stream orientation (byte/wide) decided */ +#if defined(__CYGWIN__) +# define __SCLE 0x4000 /* convert line endings CR/LF <-> NL */ +#endif +#define __SL64 0x8000 /* is 64-bit offset large file */ + +/* _flags2 flags */ +#define __SNLK 0x0001 /* stdio functions do not lock streams themselves */ +#define __SWID 0x2000 /* true => stream orientation wide, false => byte, only valid if __SORD in _flags is true */ + +/* + * The following three definitions are for ANSI C, which took them + * from System V, which stupidly took internal interface macros and + * made them official arguments to setvbuf(), without renaming them. + * Hence, these ugly _IOxxx names are *supposed* to appear in user code. + * + * Although these happen to match their counterparts above, the + * implementation does not rely on that (so these could be renumbered). + */ +#define _IOFBF 0 /* setvbuf should set fully buffered */ +#define _IOLBF 1 /* setvbuf should set line buffered */ +#define _IONBF 2 /* setvbuf should set unbuffered */ + +#define EOF (-1) + +#ifdef __BUFSIZ__ +#define BUFSIZ __BUFSIZ__ +#else +#define BUFSIZ 1024 +#endif + +#ifdef __FOPEN_MAX__ +#define FOPEN_MAX __FOPEN_MAX__ +#else +#define FOPEN_MAX 20 +#endif + +#ifdef __FILENAME_MAX__ +#define FILENAME_MAX __FILENAME_MAX__ +#else +#define FILENAME_MAX 1024 +#endif + +#ifdef __L_tmpnam__ +#define L_tmpnam __L_tmpnam__ +#else +#define L_tmpnam FILENAME_MAX +#endif + +#ifndef __STRICT_ANSI__ +#define P_tmpdir "/tmp" +#endif + +#ifndef SEEK_SET +#define SEEK_SET 0 /* set file offset to offset */ +#endif +#ifndef SEEK_CUR +#define SEEK_CUR 1 /* set file offset to current plus offset */ +#endif +#ifndef SEEK_END +#define SEEK_END 2 /* set file offset to EOF plus offset */ +#endif + +#define TMP_MAX 26 + +#define stdin (_REENT->_stdin) +#define stdout (_REENT->_stdout) +#define stderr (_REENT->_stderr) + +#define _stdin_r(x) ((x)->_stdin) +#define _stdout_r(x) ((x)->_stdout) +#define _stderr_r(x) ((x)->_stderr) + +/* + * Functions defined in ANSI C standard. + */ + +#ifndef __VALIST +#ifdef __GNUC__ +#define __VALIST __gnuc_va_list +#else +#define __VALIST char* +#endif +#endif + +FILE * _EXFUN(tmpfile, (void)); +char * _EXFUN(tmpnam, (char *)); +#if __BSD_VISIBLE || __XSI_VISIBLE || __POSIX_VISIBLE >= 200112 +char * _EXFUN(tempnam, (const char *, const char *)); +#endif +int _EXFUN(fclose, (FILE *)); +int _EXFUN(fflush, (FILE *)); +FILE * _EXFUN(freopen, (const char *__restrict, const char *__restrict, FILE *__restrict)); +void _EXFUN(setbuf, (FILE *__restrict, char *__restrict)); +int _EXFUN(setvbuf, (FILE *__restrict, char *__restrict, int, size_t)); +int _EXFUN(fprintf, (FILE *__restrict, const char *__restrict, ...) + _ATTRIBUTE ((__format__ (__printf__, 2, 3)))); +int _EXFUN(fscanf, (FILE *__restrict, const char *__restrict, ...) + _ATTRIBUTE ((__format__ (__scanf__, 2, 3)))); +int _EXFUN(printf, (const char *__restrict, ...) + _ATTRIBUTE ((__format__ (__printf__, 1, 2)))); +int _EXFUN(scanf, (const char *__restrict, ...) + _ATTRIBUTE ((__format__ (__scanf__, 1, 2)))); +int _EXFUN(sscanf, (const char *__restrict, const char *__restrict, ...) + _ATTRIBUTE ((__format__ (__scanf__, 2, 3)))); +int _EXFUN(vfprintf, (FILE *__restrict, const char *__restrict, __VALIST) + _ATTRIBUTE ((__format__ (__printf__, 2, 0)))); +int _EXFUN(vprintf, (const char *, __VALIST) + _ATTRIBUTE ((__format__ (__printf__, 1, 0)))); +int _EXFUN(vsprintf, (char *__restrict, const char *__restrict, __VALIST) + _ATTRIBUTE ((__format__ (__printf__, 2, 0)))); +int _EXFUN(fgetc, (FILE *)); +char * _EXFUN(fgets, (char *__restrict, int, FILE *__restrict)); +int _EXFUN(fputc, (int, FILE *)); +int _EXFUN(fputs, (const char *__restrict, FILE *__restrict)); +int _EXFUN(getc, (FILE *)); +int _EXFUN(getchar, (void)); +char * _EXFUN(gets, (char *)); +int _EXFUN(putc, (int, FILE *)); +int _EXFUN(putchar, (int)); +int _EXFUN(puts, (const char *)); +int _EXFUN(ungetc, (int, FILE *)); +size_t _EXFUN(fread, (_PTR __restrict, size_t _size, size_t _n, FILE *__restrict)); +size_t _EXFUN(fwrite, (const _PTR __restrict , size_t _size, size_t _n, FILE *)); +#ifdef _COMPILING_NEWLIB +int _EXFUN(fgetpos, (FILE *, _fpos_t *)); +#else +int _EXFUN(fgetpos, (FILE *__restrict, fpos_t *__restrict)); +#endif +int _EXFUN(fseek, (FILE *, long, int)); +#ifdef _COMPILING_NEWLIB +int _EXFUN(fsetpos, (FILE *, const _fpos_t *)); +#else +int _EXFUN(fsetpos, (FILE *, const fpos_t *)); +#endif +long _EXFUN(ftell, ( FILE *)); +void _EXFUN(rewind, (FILE *)); +void _EXFUN(clearerr, (FILE *)); +int _EXFUN(feof, (FILE *)); +int _EXFUN(ferror, (FILE *)); +void _EXFUN(perror, (const char *)); +#ifndef _REENT_ONLY +FILE * _EXFUN(fopen, (const char *__restrict _name, const char *__restrict _type)); +int _EXFUN(sprintf, (char *__restrict, const char *__restrict, ...) + _ATTRIBUTE ((__format__ (__printf__, 2, 3)))); +int _EXFUN(remove, (const char *)); +int _EXFUN(rename, (const char *, const char *)); +#ifdef _COMPILING_NEWLIB +int _EXFUN(_rename, (const char *, const char *)); +#endif +#endif +#if !defined(__STRICT_ANSI__) || defined(__USE_XOPEN2K) +#ifdef _COMPILING_NEWLIB +int _EXFUN(fseeko, (FILE *, _off_t, int)); +_off_t _EXFUN(ftello, ( FILE *)); +#else +int _EXFUN(fseeko, (FILE *, off_t, int)); +off_t _EXFUN(ftello, ( FILE *)); +#endif +#endif +#if __GNU_VISIBLE +int _EXFUN(fcloseall, (_VOID)); +#endif +#if !defined(__STRICT_ANSI__) || (__STDC_VERSION__ >= 199901L) || (__cplusplus >= 201103L) +#ifndef _REENT_ONLY +int _EXFUN(asiprintf, (char **, const char *, ...) + _ATTRIBUTE ((__format__ (__printf__, 2, 3)))); +char * _EXFUN(asniprintf, (char *, size_t *, const char *, ...) + _ATTRIBUTE ((__format__ (__printf__, 3, 4)))); +char * _EXFUN(asnprintf, (char *__restrict, size_t *__restrict, const char *__restrict, ...) + _ATTRIBUTE ((__format__ (__printf__, 3, 4)))); +int _EXFUN(asprintf, (char **__restrict, const char *__restrict, ...) + _ATTRIBUTE ((__format__ (__printf__, 2, 3)))); +#ifndef diprintf +int _EXFUN(diprintf, (int, const char *, ...) + _ATTRIBUTE ((__format__ (__printf__, 2, 3)))); +#endif +int _EXFUN(fiprintf, (FILE *, const char *, ...) + _ATTRIBUTE ((__format__ (__printf__, 2, 3)))); +int _EXFUN(fiscanf, (FILE *, const char *, ...) + _ATTRIBUTE ((__format__ (__scanf__, 2, 3)))); +int _EXFUN(iprintf, (const char *, ...) + _ATTRIBUTE ((__format__ (__printf__, 1, 2)))); +int _EXFUN(iscanf, (const char *, ...) + _ATTRIBUTE ((__format__ (__scanf__, 1, 2)))); +int _EXFUN(siprintf, (char *, const char *, ...) + _ATTRIBUTE ((__format__ (__printf__, 2, 3)))); +int _EXFUN(siscanf, (const char *, const char *, ...) + _ATTRIBUTE ((__format__ (__scanf__, 2, 3)))); +int _EXFUN(snprintf, (char *__restrict, size_t, const char *__restrict, ...) + _ATTRIBUTE ((__format__ (__printf__, 3, 4)))); +int _EXFUN(sniprintf, (char *, size_t, const char *, ...) + _ATTRIBUTE ((__format__ (__printf__, 3, 4)))); +int _EXFUN(vasiprintf, (char **, const char *, __VALIST) + _ATTRIBUTE ((__format__ (__printf__, 2, 0)))); +char * _EXFUN(vasniprintf, (char *, size_t *, const char *, __VALIST) + _ATTRIBUTE ((__format__ (__printf__, 3, 0)))); +char * _EXFUN(vasnprintf, (char *, size_t *, const char *, __VALIST) + _ATTRIBUTE ((__format__ (__printf__, 3, 0)))); +int _EXFUN(vasprintf, (char **, const char *, __VALIST) + _ATTRIBUTE ((__format__ (__printf__, 2, 0)))); +int _EXFUN(vdiprintf, (int, const char *, __VALIST) + _ATTRIBUTE ((__format__ (__printf__, 2, 0)))); +int _EXFUN(vfiprintf, (FILE *, const char *, __VALIST) + _ATTRIBUTE ((__format__ (__printf__, 2, 0)))); +int _EXFUN(vfiscanf, (FILE *, const char *, __VALIST) + _ATTRIBUTE ((__format__ (__scanf__, 2, 0)))); +int _EXFUN(vfscanf, (FILE *__restrict, const char *__restrict, __VALIST) + _ATTRIBUTE ((__format__ (__scanf__, 2, 0)))); +int _EXFUN(viprintf, (const char *, __VALIST) + _ATTRIBUTE ((__format__ (__printf__, 1, 0)))); +int _EXFUN(viscanf, (const char *, __VALIST) + _ATTRIBUTE ((__format__ (__scanf__, 1, 0)))); +int _EXFUN(vscanf, (const char *, __VALIST) + _ATTRIBUTE ((__format__ (__scanf__, 1, 0)))); +int _EXFUN(vsiprintf, (char *, const char *, __VALIST) + _ATTRIBUTE ((__format__ (__printf__, 2, 0)))); +int _EXFUN(vsiscanf, (const char *, const char *, __VALIST) + _ATTRIBUTE ((__format__ (__scanf__, 2, 0)))); +int _EXFUN(vsniprintf, (char *, size_t, const char *, __VALIST) + _ATTRIBUTE ((__format__ (__printf__, 3, 0)))); +int _EXFUN(vsnprintf, (char *__restrict, size_t, const char *__restrict, __VALIST) + _ATTRIBUTE ((__format__ (__printf__, 3, 0)))); +int _EXFUN(vsscanf, (const char *__restrict, const char *__restrict, __VALIST) + _ATTRIBUTE ((__format__ (__scanf__, 2, 0)))); +#endif /* !_REENT_ONLY */ +#endif /* !__STRICT_ANSI__ */ + +/* + * Routines in POSIX 1003.1:2001. + */ + +#ifndef __STRICT_ANSI__ +#ifndef _REENT_ONLY +FILE * _EXFUN(fdopen, (int, const char *)); +#endif +int _EXFUN(fileno, (FILE *)); +int _EXFUN(getw, (FILE *)); +int _EXFUN(pclose, (FILE *)); +FILE * _EXFUN(popen, (const char *, const char *)); +int _EXFUN(putw, (int, FILE *)); +void _EXFUN(setbuffer, (FILE *, char *, int)); +int _EXFUN(setlinebuf, (FILE *)); +int _EXFUN(getc_unlocked, (FILE *)); +int _EXFUN(getchar_unlocked, (void)); +void _EXFUN(flockfile, (FILE *)); +int _EXFUN(ftrylockfile, (FILE *)); +void _EXFUN(funlockfile, (FILE *)); +int _EXFUN(putc_unlocked, (int, FILE *)); +int _EXFUN(putchar_unlocked, (int)); +#endif /* ! __STRICT_ANSI__ */ + +/* + * Routines in POSIX 1003.1:200x. + */ + +#ifndef __STRICT_ANSI__ +# ifndef _REENT_ONLY +# ifndef dprintf +int _EXFUN(dprintf, (int, const char *__restrict, ...) + _ATTRIBUTE ((__format__ (__printf__, 2, 3)))); +# endif +FILE * _EXFUN(fmemopen, (void *__restrict, size_t, const char *__restrict)); +/* getdelim - see __getdelim for now */ +/* getline - see __getline for now */ +FILE * _EXFUN(open_memstream, (char **, size_t *)); +#if __BSD_VISIBLE || __POSIX_VISIBLE >= 200809 +int _EXFUN(renameat, (int, const char *, int, const char *)); +#endif +int _EXFUN(vdprintf, (int, const char *__restrict, __VALIST) + _ATTRIBUTE ((__format__ (__printf__, 2, 0)))); +# endif +#endif + +/* + * Recursive versions of the above. + */ + +int _EXFUN(_asiprintf_r, (struct _reent *, char **, const char *, ...) + _ATTRIBUTE ((__format__ (__printf__, 3, 4)))); +char * _EXFUN(_asniprintf_r, (struct _reent *, char *, size_t *, const char *, ...) + _ATTRIBUTE ((__format__ (__printf__, 4, 5)))); +char * _EXFUN(_asnprintf_r, (struct _reent *, char *__restrict, size_t *__restrict, const char *__restrict, ...) + _ATTRIBUTE ((__format__ (__printf__, 4, 5)))); +int _EXFUN(_asprintf_r, (struct _reent *, char **__restrict, const char *__restrict, ...) + _ATTRIBUTE ((__format__ (__printf__, 3, 4)))); +int _EXFUN(_diprintf_r, (struct _reent *, int, const char *, ...) + _ATTRIBUTE ((__format__ (__printf__, 3, 4)))); +int _EXFUN(_dprintf_r, (struct _reent *, int, const char *__restrict, ...) + _ATTRIBUTE ((__format__ (__printf__, 3, 4)))); +int _EXFUN(_fclose_r, (struct _reent *, FILE *)); +int _EXFUN(_fcloseall_r, (struct _reent *)); +FILE * _EXFUN(_fdopen_r, (struct _reent *, int, const char *)); +int _EXFUN(_fflush_r, (struct _reent *, FILE *)); +int _EXFUN(_fgetc_r, (struct _reent *, FILE *)); +int _EXFUN(_fgetc_unlocked_r, (struct _reent *, FILE *)); +char * _EXFUN(_fgets_r, (struct _reent *, char *__restrict, int, FILE *__restrict)); +char * _EXFUN(_fgets_unlocked_r, (struct _reent *, char *__restrict, int, FILE *__restrict)); +#ifdef _COMPILING_NEWLIB +int _EXFUN(_fgetpos_r, (struct _reent *, FILE *__restrict, _fpos_t *__restrict)); +int _EXFUN(_fsetpos_r, (struct _reent *, FILE *, const _fpos_t *)); +#else +int _EXFUN(_fgetpos_r, (struct _reent *, FILE *, fpos_t *)); +int _EXFUN(_fsetpos_r, (struct _reent *, FILE *, const fpos_t *)); +#endif +int _EXFUN(_fiprintf_r, (struct _reent *, FILE *, const char *, ...) + _ATTRIBUTE ((__format__ (__printf__, 3, 4)))); +int _EXFUN(_fiscanf_r, (struct _reent *, FILE *, const char *, ...) + _ATTRIBUTE ((__format__ (__scanf__, 3, 4)))); +FILE * _EXFUN(_fmemopen_r, (struct _reent *, void *__restrict, size_t, const char *__restrict)); +FILE * _EXFUN(_fopen_r, (struct _reent *, const char *__restrict, const char *__restrict)); +FILE * _EXFUN(_freopen_r, (struct _reent *, const char *__restrict, const char *__restrict, FILE *__restrict)); +int _EXFUN(_fprintf_r, (struct _reent *, FILE *__restrict, const char *__restrict, ...) + _ATTRIBUTE ((__format__ (__printf__, 3, 4)))); +int _EXFUN(_fpurge_r, (struct _reent *, FILE *)); +int _EXFUN(_fputc_r, (struct _reent *, int, FILE *)); +int _EXFUN(_fputc_unlocked_r, (struct _reent *, int, FILE *)); +int _EXFUN(_fputs_r, (struct _reent *, const char *__restrict, FILE *__restrict)); +int _EXFUN(_fputs_unlocked_r, (struct _reent *, const char *__restrict, FILE *__restrict)); +size_t _EXFUN(_fread_r, (struct _reent *, _PTR __restrict, size_t _size, size_t _n, FILE *__restrict)); +size_t _EXFUN(_fread_unlocked_r, (struct _reent *, _PTR __restrict, size_t _size, size_t _n, FILE *__restrict)); +int _EXFUN(_fscanf_r, (struct _reent *, FILE *__restrict, const char *__restrict, ...) + _ATTRIBUTE ((__format__ (__scanf__, 3, 4)))); +int _EXFUN(_fseek_r, (struct _reent *, FILE *, long, int)); +int _EXFUN(_fseeko_r,(struct _reent *, FILE *, _off_t, int)); +long _EXFUN(_ftell_r, (struct _reent *, FILE *)); +_off_t _EXFUN(_ftello_r,(struct _reent *, FILE *)); +void _EXFUN(_rewind_r, (struct _reent *, FILE *)); +size_t _EXFUN(_fwrite_r, (struct _reent *, const _PTR __restrict, size_t _size, size_t _n, FILE *__restrict)); +size_t _EXFUN(_fwrite_unlocked_r, (struct _reent *, const _PTR __restrict, size_t _size, size_t _n, FILE *__restrict)); +int _EXFUN(_getc_r, (struct _reent *, FILE *)); +int _EXFUN(_getc_unlocked_r, (struct _reent *, FILE *)); +int _EXFUN(_getchar_r, (struct _reent *)); +int _EXFUN(_getchar_unlocked_r, (struct _reent *)); +char * _EXFUN(_gets_r, (struct _reent *, char *)); +int _EXFUN(_iprintf_r, (struct _reent *, const char *, ...) + _ATTRIBUTE ((__format__ (__printf__, 2, 3)))); +int _EXFUN(_iscanf_r, (struct _reent *, const char *, ...) + _ATTRIBUTE ((__format__ (__scanf__, 2, 3)))); +FILE * _EXFUN(_open_memstream_r, (struct _reent *, char **, size_t *)); +void _EXFUN(_perror_r, (struct _reent *, const char *)); +int _EXFUN(_printf_r, (struct _reent *, const char *__restrict, ...) + _ATTRIBUTE ((__format__ (__printf__, 2, 3)))); +int _EXFUN(_putc_r, (struct _reent *, int, FILE *)); +int _EXFUN(_putc_unlocked_r, (struct _reent *, int, FILE *)); +int _EXFUN(_putchar_unlocked_r, (struct _reent *, int)); +int _EXFUN(_putchar_r, (struct _reent *, int)); +int _EXFUN(_puts_r, (struct _reent *, const char *)); +int _EXFUN(_remove_r, (struct _reent *, const char *)); +int _EXFUN(_rename_r, (struct _reent *, + const char *_old, const char *_new)); +int _EXFUN(_scanf_r, (struct _reent *, const char *__restrict, ...) + _ATTRIBUTE ((__format__ (__scanf__, 2, 3)))); +int _EXFUN(_siprintf_r, (struct _reent *, char *, const char *, ...) + _ATTRIBUTE ((__format__ (__printf__, 3, 4)))); +int _EXFUN(_siscanf_r, (struct _reent *, const char *, const char *, ...) + _ATTRIBUTE ((__format__ (__scanf__, 3, 4)))); +int _EXFUN(_sniprintf_r, (struct _reent *, char *, size_t, const char *, ...) + _ATTRIBUTE ((__format__ (__printf__, 4, 5)))); +int _EXFUN(_snprintf_r, (struct _reent *, char *__restrict, size_t, const char *__restrict, ...) + _ATTRIBUTE ((__format__ (__printf__, 4, 5)))); +int _EXFUN(_sprintf_r, (struct _reent *, char *__restrict, const char *__restrict, ...) + _ATTRIBUTE ((__format__ (__printf__, 3, 4)))); +int _EXFUN(_sscanf_r, (struct _reent *, const char *__restrict, const char *__restrict, ...) + _ATTRIBUTE ((__format__ (__scanf__, 3, 4)))); +char * _EXFUN(_tempnam_r, (struct _reent *, const char *, const char *)); +FILE * _EXFUN(_tmpfile_r, (struct _reent *)); +char * _EXFUN(_tmpnam_r, (struct _reent *, char *)); +int _EXFUN(_ungetc_r, (struct _reent *, int, FILE *)); +int _EXFUN(_vasiprintf_r, (struct _reent *, char **, const char *, __VALIST) + _ATTRIBUTE ((__format__ (__printf__, 3, 0)))); +char * _EXFUN(_vasniprintf_r, (struct _reent*, char *, size_t *, const char *, __VALIST) + _ATTRIBUTE ((__format__ (__printf__, 4, 0)))); +char * _EXFUN(_vasnprintf_r, (struct _reent*, char *, size_t *, const char *, __VALIST) + _ATTRIBUTE ((__format__ (__printf__, 4, 0)))); +int _EXFUN(_vasprintf_r, (struct _reent *, char **, const char *, __VALIST) + _ATTRIBUTE ((__format__ (__printf__, 3, 0)))); +int _EXFUN(_vdiprintf_r, (struct _reent *, int, const char *, __VALIST) + _ATTRIBUTE ((__format__ (__printf__, 3, 0)))); +int _EXFUN(_vdprintf_r, (struct _reent *, int, const char *__restrict, __VALIST) + _ATTRIBUTE ((__format__ (__printf__, 3, 0)))); +int _EXFUN(_vfiprintf_r, (struct _reent *, FILE *, const char *, __VALIST) + _ATTRIBUTE ((__format__ (__printf__, 3, 0)))); +int _EXFUN(_vfiscanf_r, (struct _reent *, FILE *, const char *, __VALIST) + _ATTRIBUTE ((__format__ (__scanf__, 3, 0)))); +int _EXFUN(_vfprintf_r, (struct _reent *, FILE *__restrict, const char *__restrict, __VALIST) + _ATTRIBUTE ((__format__ (__printf__, 3, 0)))); +int _EXFUN(_vfscanf_r, (struct _reent *, FILE *__restrict, const char *__restrict, __VALIST) + _ATTRIBUTE ((__format__ (__scanf__, 3, 0)))); +int _EXFUN(_viprintf_r, (struct _reent *, const char *, __VALIST) + _ATTRIBUTE ((__format__ (__printf__, 2, 0)))); +int _EXFUN(_viscanf_r, (struct _reent *, const char *, __VALIST) + _ATTRIBUTE ((__format__ (__scanf__, 2, 0)))); +int _EXFUN(_vprintf_r, (struct _reent *, const char *__restrict, __VALIST) + _ATTRIBUTE ((__format__ (__printf__, 2, 0)))); +int _EXFUN(_vscanf_r, (struct _reent *, const char *__restrict, __VALIST) + _ATTRIBUTE ((__format__ (__scanf__, 2, 0)))); +int _EXFUN(_vsiprintf_r, (struct _reent *, char *, const char *, __VALIST) + _ATTRIBUTE ((__format__ (__printf__, 3, 0)))); +int _EXFUN(_vsiscanf_r, (struct _reent *, const char *, const char *, __VALIST) + _ATTRIBUTE ((__format__ (__scanf__, 3, 0)))); +int _EXFUN(_vsniprintf_r, (struct _reent *, char *, size_t, const char *, __VALIST) + _ATTRIBUTE ((__format__ (__printf__, 4, 0)))); +int _EXFUN(_vsnprintf_r, (struct _reent *, char *__restrict, size_t, const char *__restrict, __VALIST) + _ATTRIBUTE ((__format__ (__printf__, 4, 0)))); +int _EXFUN(_vsprintf_r, (struct _reent *, char *__restrict, const char *__restrict, __VALIST) + _ATTRIBUTE ((__format__ (__printf__, 3, 0)))); +int _EXFUN(_vsscanf_r, (struct _reent *, const char *__restrict, const char *__restrict, __VALIST) + _ATTRIBUTE ((__format__ (__scanf__, 3, 0)))); + +/* Other extensions. */ + +int _EXFUN(fpurge, (FILE *)); +ssize_t _EXFUN(__getdelim, (char **, size_t *, int, FILE *)); +ssize_t _EXFUN(__getline, (char **, size_t *, FILE *)); + +#if __BSD_VISIBLE +void _EXFUN(clearerr_unlocked, (FILE *)); +int _EXFUN(feof_unlocked, (FILE *)); +int _EXFUN(ferror_unlocked, (FILE *)); +int _EXFUN(fileno_unlocked, (FILE *)); +int _EXFUN(fflush_unlocked, (FILE *)); +int _EXFUN(fgetc_unlocked, (FILE *)); +int _EXFUN(fputc_unlocked, (int, FILE *)); +size_t _EXFUN(fread_unlocked, (_PTR __restrict, size_t _size, size_t _n, FILE *__restrict)); +size_t _EXFUN(fwrite_unlocked, (const _PTR __restrict , size_t _size, size_t _n, FILE *)); +#endif + +#if __GNU_VISIBLE +char * _EXFUN(fgets_unlocked, (char *__restrict, int, FILE *__restrict)); +int _EXFUN(fputs_unlocked, (const char *__restrict, FILE *__restrict)); +#endif + +#ifdef __LARGE64_FILES +#if !defined(__CYGWIN__) || defined(_COMPILING_NEWLIB) +FILE * _EXFUN(fdopen64, (int, const char *)); +FILE * _EXFUN(fopen64, (const char *, const char *)); +FILE * _EXFUN(freopen64, (_CONST char *, _CONST char *, FILE *)); +_off64_t _EXFUN(ftello64, (FILE *)); +_off64_t _EXFUN(fseeko64, (FILE *, _off64_t, int)); +int _EXFUN(fgetpos64, (FILE *, _fpos64_t *)); +int _EXFUN(fsetpos64, (FILE *, const _fpos64_t *)); +FILE * _EXFUN(tmpfile64, (void)); + +FILE * _EXFUN(_fdopen64_r, (struct _reent *, int, const char *)); +FILE * _EXFUN(_fopen64_r, (struct _reent *,const char *, const char *)); +FILE * _EXFUN(_freopen64_r, (struct _reent *, _CONST char *, _CONST char *, FILE *)); +_off64_t _EXFUN(_ftello64_r, (struct _reent *, FILE *)); +_off64_t _EXFUN(_fseeko64_r, (struct _reent *, FILE *, _off64_t, int)); +int _EXFUN(_fgetpos64_r, (struct _reent *, FILE *, _fpos64_t *)); +int _EXFUN(_fsetpos64_r, (struct _reent *, FILE *, const _fpos64_t *)); +FILE * _EXFUN(_tmpfile64_r, (struct _reent *)); +#endif /* !__CYGWIN__ */ +#endif /* __LARGE64_FILES */ + +/* + * Routines internal to the implementation. + */ + +int _EXFUN(__srget_r, (struct _reent *, FILE *)); +int _EXFUN(__swbuf_r, (struct _reent *, int, FILE *)); + +/* + * Stdio function-access interface. + */ + +#ifndef __STRICT_ANSI__ +# ifdef __LARGE64_FILES +FILE *_EXFUN(funopen,(const _PTR __cookie, + int (*__readfn)(_PTR __c, char *__buf, + _READ_WRITE_BUFSIZE_TYPE __n), + int (*__writefn)(_PTR __c, const char *__buf, + _READ_WRITE_BUFSIZE_TYPE __n), + _fpos64_t (*__seekfn)(_PTR __c, _fpos64_t __off, int __whence), + int (*__closefn)(_PTR __c))); +FILE *_EXFUN(_funopen_r,(struct _reent *, const _PTR __cookie, + int (*__readfn)(_PTR __c, char *__buf, + _READ_WRITE_BUFSIZE_TYPE __n), + int (*__writefn)(_PTR __c, const char *__buf, + _READ_WRITE_BUFSIZE_TYPE __n), + _fpos64_t (*__seekfn)(_PTR __c, _fpos64_t __off, int __whence), + int (*__closefn)(_PTR __c))); +# else +FILE *_EXFUN(funopen,(const _PTR __cookie, + int (*__readfn)(_PTR __cookie, char *__buf, + _READ_WRITE_BUFSIZE_TYPE __n), + int (*__writefn)(_PTR __cookie, const char *__buf, + _READ_WRITE_BUFSIZE_TYPE __n), + fpos_t (*__seekfn)(_PTR __cookie, fpos_t __off, int __whence), + int (*__closefn)(_PTR __cookie))); +FILE *_EXFUN(_funopen_r,(struct _reent *, const _PTR __cookie, + int (*__readfn)(_PTR __cookie, char *__buf, + _READ_WRITE_BUFSIZE_TYPE __n), + int (*__writefn)(_PTR __cookie, const char *__buf, + _READ_WRITE_BUFSIZE_TYPE __n), + fpos_t (*__seekfn)(_PTR __cookie, fpos_t __off, int __whence), + int (*__closefn)(_PTR __cookie))); +# endif /* !__LARGE64_FILES */ + +# define fropen(__cookie, __fn) funopen(__cookie, __fn, (int (*)())0, \ + (fpos_t (*)())0, (int (*)())0) +# define fwopen(__cookie, __fn) funopen(__cookie, (int (*)())0, __fn, \ + (fpos_t (*)())0, (int (*)())0) + +typedef ssize_t cookie_read_function_t(void *__cookie, char *__buf, size_t __n); +typedef ssize_t cookie_write_function_t(void *__cookie, const char *__buf, + size_t __n); +# ifdef __LARGE64_FILES +typedef int cookie_seek_function_t(void *__cookie, _off64_t *__off, + int __whence); +# else +typedef int cookie_seek_function_t(void *__cookie, off_t *__off, int __whence); +# endif /* !__LARGE64_FILES */ +typedef int cookie_close_function_t(void *__cookie); +typedef struct +{ + /* These four struct member names are dictated by Linux; hopefully, + they don't conflict with any macros. */ + cookie_read_function_t *read; + cookie_write_function_t *write; + cookie_seek_function_t *seek; + cookie_close_function_t *close; +} cookie_io_functions_t; +FILE *_EXFUN(fopencookie,(void *__cookie, + const char *__mode, cookie_io_functions_t __functions)); +FILE *_EXFUN(_fopencookie_r,(struct _reent *, void *__cookie, + const char *__mode, cookie_io_functions_t __functions)); +#endif /* ! __STRICT_ANSI__ */ + +#ifndef __CUSTOM_FILE_IO__ +/* + * The __sfoo macros are here so that we can + * define function versions in the C library. + */ +#define __sgetc_raw_r(__ptr, __f) (--(__f)->_r < 0 ? __srget_r(__ptr, __f) : (int)(*(__f)->_p++)) + +#ifdef __SCLE +/* For a platform with CR/LF, additional logic is required by + __sgetc_r which would otherwise simply be a macro; therefore we + use an inlined function. The function is only meant to be inlined + in place as used and the function body should never be emitted. + + There are two possible means to this end when compiling with GCC, + one when compiling with a standard C99 compiler, and for other + compilers we're just stuck. At the moment, this issue only + affects the Cygwin target, so we'll most likely be using GCC. */ + +_ELIDABLE_INLINE int __sgetc_r(struct _reent *__ptr, FILE *__p); + +_ELIDABLE_INLINE int __sgetc_r(struct _reent *__ptr, FILE *__p) + { + int __c = __sgetc_raw_r(__ptr, __p); + if ((__p->_flags & __SCLE) && (__c == '\r')) + { + int __c2 = __sgetc_raw_r(__ptr, __p); + if (__c2 == '\n') + __c = __c2; + else + ungetc(__c2, __p); + } + return __c; + } +#else +#define __sgetc_r(__ptr, __p) __sgetc_raw_r(__ptr, __p) +#endif + +#ifdef _never /* __GNUC__ */ +/* If this inline is actually used, then systems using coff debugging + info get hopelessly confused. 21sept93 rich@cygnus.com. */ +_ELIDABLE_INLINE int __sputc_r(struct _reent *_ptr, int _c, FILE *_p) { + if (--_p->_w >= 0 || (_p->_w >= _p->_lbfsize && (char)_c != '\n')) + return (*_p->_p++ = _c); + else + return (__swbuf_r(_ptr, _c, _p)); +} +#else +/* + * This has been tuned to generate reasonable code on the vax using pcc + */ +#define __sputc_raw_r(__ptr, __c, __p) \ + (--(__p)->_w < 0 ? \ + (__p)->_w >= (__p)->_lbfsize ? \ + (*(__p)->_p = (__c)), *(__p)->_p != '\n' ? \ + (int)*(__p)->_p++ : \ + __swbuf_r(__ptr, '\n', __p) : \ + __swbuf_r(__ptr, (int)(__c), __p) : \ + (*(__p)->_p = (__c), (int)*(__p)->_p++)) +#ifdef __SCLE +#define __sputc_r(__ptr, __c, __p) \ + ((((__p)->_flags & __SCLE) && ((__c) == '\n')) \ + ? __sputc_raw_r(__ptr, '\r', (__p)) : 0 , \ + __sputc_raw_r((__ptr), (__c), (__p))) +#else +#define __sputc_r(__ptr, __c, __p) __sputc_raw_r(__ptr, __c, __p) +#endif +#endif + +#define __sfeof(p) ((int)(((p)->_flags & __SEOF) != 0)) +#define __sferror(p) ((int)(((p)->_flags & __SERR) != 0)) +#define __sclearerr(p) ((void)((p)->_flags &= ~(__SERR|__SEOF))) +#define __sfileno(p) ((p)->_file) + +#ifndef _REENT_SMALL +#define feof(p) __sfeof(p) +#define ferror(p) __sferror(p) +#define clearerr(p) __sclearerr(p) + +#if __BSD_VISIBLE +#define feof_unlocked(p) __sfeof(p) +#define ferror_unlocked(p) __sferror(p) +#define clearerr_unlocked(p) __sclearerr(p) +#endif /* __BSD_VISIBLE */ +#endif /* _REENT_SMALL */ + +#if 0 /*ndef __STRICT_ANSI__ - FIXME: must initialize stdio first, use fn */ +#define fileno(p) __sfileno(p) +#endif + +#ifndef __CYGWIN__ +#ifndef lint +#define getc(fp) __sgetc_r(_REENT, fp) +#define putc(x, fp) __sputc_r(_REENT, x, fp) +#endif /* lint */ +#endif /* __CYGWIN__ */ + +#ifndef __STRICT_ANSI__ +/* fast always-buffered version, true iff error */ +#define fast_putc(x,p) (--(p)->_w < 0 ? \ + __swbuf_r(_REENT, (int)(x), p) == EOF : (*(p)->_p = (x), (p)->_p++, 0)) + +#define L_cuserid 9 /* posix says it goes in stdio.h :( */ +#ifdef __CYGWIN__ +#define L_ctermid 16 +#endif +#endif + +#endif /* !__CUSTOM_FILE_IO__ */ + +#define getchar() getc(stdin) +#define putchar(x) putc(x, stdout) + +#ifndef __STRICT_ANSI__ +#define getchar_unlocked() getc_unlocked(stdin) +#define putchar_unlocked(x) putc_unlocked(x, stdout) +#endif + +_END_STD_C + +#endif /* _STDIO_H_ */ diff --git a/components/newlib/include/stdio_ext.h b/components/newlib/include/stdio_ext.h new file mode 100644 index 0000000000..029ab02535 --- /dev/null +++ b/components/newlib/include/stdio_ext.h @@ -0,0 +1,79 @@ +/* + * stdio_ext.h + * + * Definitions for I/O internal operations, originally from Solaris. + */ + +#ifndef _STDIO_EXT_H_ +#define _STDIO_EXT_H_ + +#ifdef __rtems__ +#error " not supported" +#endif + +#include + +#define FSETLOCKING_QUERY 0 +#define FSETLOCKING_INTERNAL 1 +#define FSETLOCKING_BYCALLER 2 + +_BEGIN_STD_C + +void _EXFUN(__fpurge,(FILE *)); +int _EXFUN(__fsetlocking,(FILE *, int)); + +/* TODO: + + void _flushlbf (void); +*/ + +#ifdef __GNUC__ + +_ELIDABLE_INLINE size_t +__fbufsize (FILE *__fp) { return (size_t) __fp->_bf._size; } + +_ELIDABLE_INLINE int +__freading (FILE *__fp) { return (__fp->_flags & __SRD) != 0; } + +_ELIDABLE_INLINE int +__fwriting (FILE *__fp) { return (__fp->_flags & __SWR) != 0; } + +_ELIDABLE_INLINE int +__freadable (FILE *__fp) { return (__fp->_flags & (__SRD | __SRW)) != 0; } + +_ELIDABLE_INLINE int +__fwritable (FILE *__fp) { return (__fp->_flags & (__SWR | __SRW)) != 0; } + +_ELIDABLE_INLINE int +__flbf (FILE *__fp) { return (__fp->_flags & __SLBF) != 0; } + +_ELIDABLE_INLINE size_t +__fpending (FILE *__fp) { return __fp->_p - __fp->_bf._base; } + +#else + +size_t _EXFUN(__fbufsize,(FILE *)); +int _EXFUN(__freading,(FILE *)); +int _EXFUN(__fwriting,(FILE *)); +int _EXFUN(__freadable,(FILE *)); +int _EXFUN(__fwritable,(FILE *)); +int _EXFUN(__flbf,(FILE *)); +size_t _EXFUN(__fpending,(FILE *)); + +#ifndef __cplusplus + +#define __fbufsize(__fp) ((size_t) (__fp)->_bf._size) +#define __freading(__fp) (((__fp)->_flags & __SRD) != 0) +#define __fwriting(__fp) (((__fp)->_flags & __SWR) != 0) +#define __freadable(__fp) (((__fp)->_flags & (__SRD | __SRW)) != 0) +#define __fwritable(__fp) (((__fp)->_flags & (__SWR | __SRW)) != 0) +#define __flbf(__fp) (((__fp)->_flags & __SLBF) != 0) +#define __fpending(__fp) ((size_t) ((__fp)->_p - (__fp)->_bf._base)) + +#endif /* __cplusplus */ + +#endif /* __GNUC__ */ + +_END_STD_C + +#endif /* _STDIO_EXT_H_ */ diff --git a/components/newlib/include/stdlib.h b/components/newlib/include/stdlib.h new file mode 100644 index 0000000000..254ddd71f7 --- /dev/null +++ b/components/newlib/include/stdlib.h @@ -0,0 +1,297 @@ +/* + * stdlib.h + * + * Definitions for common types, variables, and functions. + */ + +#ifndef _STDLIB_H_ +#define _STDLIB_H_ + +#include +#include "_ansi.h" + +#define __need_size_t +#define __need_wchar_t +#define __need_NULL +#include + +#include +#include +#include +#ifndef __STRICT_ANSI__ +#include +#endif + +#ifdef __CYGWIN__ +#include +#endif + +_BEGIN_STD_C + +typedef struct +{ + int quot; /* quotient */ + int rem; /* remainder */ +} div_t; + +typedef struct +{ + long quot; /* quotient */ + long rem; /* remainder */ +} ldiv_t; + +#if !defined(__STRICT_ANSI__) || \ + (defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L) || \ + (defined(__cplusplus) && __cplusplus >= 201103L) +typedef struct +{ + long long int quot; /* quotient */ + long long int rem; /* remainder */ +} lldiv_t; +#endif + +#ifndef __compar_fn_t_defined +#define __compar_fn_t_defined +typedef int (*__compar_fn_t) (const _PTR, const _PTR); +#endif + +#ifndef NULL +#define NULL 0 +#endif + +#define EXIT_FAILURE 1 +#define EXIT_SUCCESS 0 + +#define RAND_MAX __RAND_MAX + +int _EXFUN(__locale_mb_cur_max,(_VOID)); + +#define MB_CUR_MAX __locale_mb_cur_max() + +_VOID _EXFUN(abort,(_VOID) _ATTRIBUTE ((__noreturn__))); +int _EXFUN(abs,(int)); +int _EXFUN(atexit,(_VOID (*__func)(_VOID))); +double _EXFUN(atof,(const char *__nptr)); +#ifndef __STRICT_ANSI__ +float _EXFUN(atoff,(const char *__nptr)); +#endif +int _EXFUN(atoi,(const char *__nptr)); +int _EXFUN(_atoi_r,(struct _reent *, const char *__nptr)); +long _EXFUN(atol,(const char *__nptr)); +long _EXFUN(_atol_r,(struct _reent *, const char *__nptr)); +_PTR _EXFUN(bsearch,(const _PTR __key, + const _PTR __base, + size_t __nmemb, + size_t __size, + __compar_fn_t _compar)); +_PTR _EXFUN_NOTHROW(calloc,(size_t __nmemb, size_t __size)); +div_t _EXFUN(div,(int __numer, int __denom)); +_VOID _EXFUN(exit,(int __status) _ATTRIBUTE ((__noreturn__))); +_VOID _EXFUN_NOTHROW(free,(_PTR)); +char * _EXFUN(getenv,(const char *__string)); +char * _EXFUN(_getenv_r,(struct _reent *, const char *__string)); +char * _EXFUN(_findenv,(_CONST char *, int *)); +char * _EXFUN(_findenv_r,(struct _reent *, _CONST char *, int *)); +#ifndef __STRICT_ANSI__ +extern char *suboptarg; /* getsubopt(3) external variable */ +int _EXFUN(getsubopt,(char **, char * const *, char **)); +#endif +long _EXFUN(labs,(long)); +ldiv_t _EXFUN(ldiv,(long __numer, long __denom)); +_PTR _EXFUN_NOTHROW(malloc,(size_t __size)); +int _EXFUN(mblen,(const char *, size_t)); +int _EXFUN(_mblen_r,(struct _reent *, const char *, size_t, _mbstate_t *)); +int _EXFUN(mbtowc,(wchar_t *__restrict, const char *__restrict, size_t)); +int _EXFUN(_mbtowc_r,(struct _reent *, wchar_t *__restrict, const char *__restrict, size_t, _mbstate_t *)); +int _EXFUN(wctomb,(char *, wchar_t)); +int _EXFUN(_wctomb_r,(struct _reent *, char *, wchar_t, _mbstate_t *)); +size_t _EXFUN(mbstowcs,(wchar_t *__restrict, const char *__restrict, size_t)); +size_t _EXFUN(_mbstowcs_r,(struct _reent *, wchar_t *__restrict, const char *__restrict, size_t, _mbstate_t *)); +size_t _EXFUN(wcstombs,(char *__restrict, const wchar_t *__restrict, size_t)); +size_t _EXFUN(_wcstombs_r,(struct _reent *, char *__restrict, const wchar_t *__restrict, size_t, _mbstate_t *)); +#ifndef __STRICT_ANSI__ +#ifndef _REENT_ONLY +char * _EXFUN(mkdtemp,(char *)); +int _EXFUN(mkostemp,(char *, int)); +int _EXFUN(mkostemps,(char *, int, int)); +int _EXFUN(mkstemp,(char *)); +int _EXFUN(mkstemps,(char *, int)); +#if (__GNUC__ < 4) || defined(__XTENSA__) +char * _EXFUN(mktemp,(char *)); +#else +char * _EXFUN(mktemp,(char *) _ATTRIBUTE ((__warning__ ("the use of `mktemp' is dangerous; use `mkstemp' instead")))); +#endif +#endif +char * _EXFUN(_mkdtemp_r, (struct _reent *, char *)); +int _EXFUN(_mkostemp_r, (struct _reent *, char *, int)); +int _EXFUN(_mkostemps_r, (struct _reent *, char *, int, int)); +int _EXFUN(_mkstemp_r, (struct _reent *, char *)); +int _EXFUN(_mkstemps_r, (struct _reent *, char *, int)); +#if (__GNUC__ < 4) || defined(__XTENSA__) +char * _EXFUN(_mktemp_r, (struct _reent *, char *)); +#else +char * _EXFUN(_mktemp_r, (struct _reent *, char *) _ATTRIBUTE ((__warning__ ("the use of `mktemp' is dangerous; use `mkstemp' instead")))); +#endif +#endif +_VOID _EXFUN(qsort,(_PTR __base, size_t __nmemb, size_t __size, __compar_fn_t _compar)); +int _EXFUN(rand,(_VOID)); +_PTR _EXFUN_NOTHROW(realloc,(_PTR __r, size_t __size)); +#ifndef __STRICT_ANSI__ +_PTR _EXFUN(reallocf,(_PTR __r, size_t __size)); +char * _EXFUN(realpath, (const char *__restrict path, char *__restrict resolved_path)); +#endif +_VOID _EXFUN(srand,(unsigned __seed)); +double _EXFUN(strtod,(const char *__restrict __n, char **__restrict __end_PTR)); +double _EXFUN(_strtod_r,(struct _reent *,const char *__restrict __n, char **__restrict __end_PTR)); +#if !defined(__STRICT_ANSI__) || \ + (defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L) || \ + (defined(__cplusplus) && __cplusplus >= 201103L) +float _EXFUN(strtof,(const char *__restrict __n, char **__restrict __end_PTR)); +#endif +#ifndef __STRICT_ANSI__ +/* the following strtodf interface is deprecated...use strtof instead */ +# ifndef strtodf +# define strtodf strtof +# endif +#endif +long _EXFUN(strtol,(const char *__restrict __n, char **__restrict __end_PTR, int __base)); +long _EXFUN(_strtol_r,(struct _reent *,const char *__restrict __n, char **__restrict __end_PTR, int __base)); +unsigned long _EXFUN(strtoul,(const char *__restrict __n, char **__restrict __end_PTR, int __base)); +unsigned long _EXFUN(_strtoul_r,(struct _reent *,const char *__restrict __n, char **__restrict __end_PTR, int __base)); + +int _EXFUN(system,(const char *__string)); + +#ifndef __STRICT_ANSI__ +long _EXFUN(a64l,(const char *__input)); +char * _EXFUN(l64a,(long __input)); +char * _EXFUN(_l64a_r,(struct _reent *,long __input)); +int _EXFUN(on_exit,(_VOID (*__func)(int, _PTR),_PTR __arg)); +#endif /* ! __STRICT_ANSI__ */ +#if !defined(__STRICT_ANSI__) || \ + (defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L) || \ + (defined(__cplusplus) && __cplusplus >= 201103L) +_VOID _EXFUN(_Exit,(int __status) _ATTRIBUTE ((__noreturn__))); +#endif +#ifndef __STRICT_ANSI__ +int _EXFUN(putenv,(char *__string)); +int _EXFUN(_putenv_r,(struct _reent *, char *__string)); +_PTR _EXFUN(_reallocf_r,(struct _reent *, _PTR, size_t)); +int _EXFUN(setenv,(const char *__string, const char *__value, int __overwrite)); +int _EXFUN(_setenv_r,(struct _reent *, const char *__string, const char *__value, int __overwrite)); + +char * _EXFUN(gcvt,(double,int,char *)); +char * _EXFUN(gcvtf,(float,int,char *)); +char * _EXFUN(fcvt,(double,int,int *,int *)); +char * _EXFUN(fcvtf,(float,int,int *,int *)); +char * _EXFUN(ecvt,(double,int,int *,int *)); +char * _EXFUN(ecvtbuf,(double, int, int*, int*, char *)); +char * _EXFUN(fcvtbuf,(double, int, int*, int*, char *)); +char * _EXFUN(ecvtf,(float,int,int *,int *)); +char * _EXFUN(dtoa,(double, int, int, int *, int*, char**)); +#endif +char * _EXFUN(__itoa,(int, char *, int)); +char * _EXFUN(__utoa,(unsigned, char *, int)); +#ifndef __STRICT_ANSI__ +char * _EXFUN(itoa,(int, char *, int)); +char * _EXFUN(utoa,(unsigned, char *, int)); +int _EXFUN(rand_r,(unsigned *__seed)); + +double _EXFUN(drand48,(_VOID)); +double _EXFUN(_drand48_r,(struct _reent *)); +double _EXFUN(erand48,(unsigned short [3])); +double _EXFUN(_erand48_r,(struct _reent *, unsigned short [3])); +long _EXFUN(jrand48,(unsigned short [3])); +long _EXFUN(_jrand48_r,(struct _reent *, unsigned short [3])); +_VOID _EXFUN(lcong48,(unsigned short [7])); +_VOID _EXFUN(_lcong48_r,(struct _reent *, unsigned short [7])); +long _EXFUN(lrand48,(_VOID)); +long _EXFUN(_lrand48_r,(struct _reent *)); +long _EXFUN(mrand48,(_VOID)); +long _EXFUN(_mrand48_r,(struct _reent *)); +long _EXFUN(nrand48,(unsigned short [3])); +long _EXFUN(_nrand48_r,(struct _reent *, unsigned short [3])); +unsigned short * + _EXFUN(seed48,(unsigned short [3])); +unsigned short * + _EXFUN(_seed48_r,(struct _reent *, unsigned short [3])); +_VOID _EXFUN(srand48,(long)); +_VOID _EXFUN(_srand48_r,(struct _reent *, long)); +#endif /* ! __STRICT_ANSI__ */ +#if !defined(__STRICT_ANSI__) || \ + (defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L) || \ + (defined(__cplusplus) && __cplusplus >= 201103L) +long long _EXFUN(atoll,(const char *__nptr)); +#endif +#ifndef __STRICT_ANSI__ +long long _EXFUN(_atoll_r,(struct _reent *, const char *__nptr)); +#endif /* ! __STRICT_ANSI__ */ +#if !defined(__STRICT_ANSI__) || \ + (defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L) || \ + (defined(__cplusplus) && __cplusplus >= 201103L) +long long _EXFUN(llabs,(long long)); +lldiv_t _EXFUN(lldiv,(long long __numer, long long __denom)); +long long _EXFUN(strtoll,(const char *__restrict __n, char **__restrict __end_PTR, int __base)); +#endif +#ifndef __STRICT_ANSI__ +long long _EXFUN(_strtoll_r,(struct _reent *, const char *__restrict __n, char **__restrict __end_PTR, int __base)); +#endif /* ! __STRICT_ANSI__ */ +#if !defined(__STRICT_ANSI__) || \ + (defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L) || \ + (defined(__cplusplus) && __cplusplus >= 201103L) +unsigned long long _EXFUN(strtoull,(const char *__restrict __n, char **__restrict __end_PTR, int __base)); +#endif +#ifndef __STRICT_ANSI__ +unsigned long long _EXFUN(_strtoull_r,(struct _reent *, const char *__restrict __n, char **__restrict __end_PTR, int __base)); + +#ifndef __CYGWIN__ +_VOID _EXFUN(cfree,(_PTR)); +int _EXFUN(unsetenv,(const char *__string)); +int _EXFUN(_unsetenv_r,(struct _reent *, const char *__string)); +#endif + +#ifdef __rtems__ +int _EXFUN(posix_memalign,(void **, size_t, size_t)); +#endif + +#endif /* ! __STRICT_ANSI__ */ + +char * _EXFUN(_dtoa_r,(struct _reent *, double, int, int, int *, int*, char**)); +#ifndef __CYGWIN__ +_PTR _EXFUN_NOTHROW(_malloc_r,(struct _reent *, size_t)); +_PTR _EXFUN_NOTHROW(_calloc_r,(struct _reent *, size_t, size_t)); +_VOID _EXFUN_NOTHROW(_free_r,(struct _reent *, _PTR)); +_PTR _EXFUN_NOTHROW(_realloc_r,(struct _reent *, _PTR, size_t)); +_VOID _EXFUN(_mstats_r,(struct _reent *, char *)); +#endif +int _EXFUN(_system_r,(struct _reent *, const char *)); + +_VOID _EXFUN(__eprintf,(const char *, const char *, unsigned int, const char *)); + +/* There are two common qsort_r variants. If you request + _BSD_SOURCE, you get the BSD version; otherwise you get the GNU + version. We want that #undef qsort_r will still let you + invoke the underlying function, but that requires gcc support. */ +#ifdef _BSD_SOURCE +# ifdef __GNUC__ +_VOID _EXFUN(qsort_r,(_PTR __base, size_t __nmemb, size_t __size, _PTR __thunk, int (*_compar)(_PTR, const _PTR, const _PTR))) + __asm__ (__ASMNAME ("__bsd_qsort_r")); +# else +_VOID _EXFUN(__bsd_qsort_r,(_PTR __base, size_t __nmemb, size_t __size, _PTR __thunk, int (*_compar)(_PTR, const _PTR, const _PTR))); +# define qsort_r __bsd_qsort_r +# endif +#elif __GNU_VISIBLE +_VOID _EXFUN(qsort_r,(_PTR __base, size_t __nmemb, size_t __size, int (*_compar)(const _PTR, const _PTR, _PTR), _PTR __thunk)); +#endif + +/* On platforms where long double equals double. */ +#ifdef _HAVE_LONG_DOUBLE +#if !defined(__STRICT_ANSI__) || \ + (defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L) || \ + (defined(__cplusplus) && __cplusplus >= 201103L) +extern long double strtold (const char *__restrict, char **__restrict); +#endif +#endif /* _HAVE_LONG_DOUBLE */ + +_END_STD_C + +#endif /* _STDLIB_H_ */ diff --git a/components/newlib/include/string.h b/components/newlib/include/string.h new file mode 100644 index 0000000000..af5c9da4d1 --- /dev/null +++ b/components/newlib/include/string.h @@ -0,0 +1,167 @@ +/* + * string.h + * + * Definitions for memory and string functions. + */ + +#ifndef _STRING_H_ +#define _STRING_H_ + +#include "_ansi.h" +#include +#include +#include + +#define __need_size_t +#define __need_NULL +#include + +_BEGIN_STD_C + +_PTR _EXFUN(memchr,(const _PTR, int, size_t)); +int _EXFUN(memcmp,(const _PTR, const _PTR, size_t)); +_PTR _EXFUN(memcpy,(_PTR __restrict, const _PTR __restrict, size_t)); +_PTR _EXFUN(memmove,(_PTR, const _PTR, size_t)); +_PTR _EXFUN(memset,(_PTR, int, size_t)); +char *_EXFUN(strcat,(char *__restrict, const char *__restrict)); +char *_EXFUN(strchr,(const char *, int)); +int _EXFUN(strcmp,(const char *, const char *)); +int _EXFUN(strcoll,(const char *, const char *)); +char *_EXFUN(strcpy,(char *__restrict, const char *__restrict)); +size_t _EXFUN(strcspn,(const char *, const char *)); +char *_EXFUN(strerror,(int)); +size_t _EXFUN(strlen,(const char *)); +char *_EXFUN(strncat,(char *__restrict, const char *__restrict, size_t)); +int _EXFUN(strncmp,(const char *, const char *, size_t)); +char *_EXFUN(strncpy,(char *__restrict, const char *__restrict, size_t)); +char *_EXFUN(strpbrk,(const char *, const char *)); +char *_EXFUN(strrchr,(const char *, int)); +size_t _EXFUN(strspn,(const char *, const char *)); +char *_EXFUN(strstr,(const char *, const char *)); +#ifndef _REENT_ONLY +char *_EXFUN(strtok,(char *__restrict, const char *__restrict)); +#endif +size_t _EXFUN(strxfrm,(char *__restrict, const char *__restrict, size_t)); + +#if __POSIX_VISIBLE +char *_EXFUN(strtok_r,(char *__restrict, const char *__restrict, char **__restrict)); +#endif +#if __BSD_VISIBLE +int _EXFUN(bcmp,(const void *, const void *, size_t)); +void _EXFUN(bcopy,(const void *, void *, size_t)); +void _EXFUN(bzero,(void *, size_t)); +int _EXFUN(ffs,(int)); +char *_EXFUN(index,(const char *, int)); +#endif +#if __BSD_VISIBLE || __XSI_VISIBLE +_PTR _EXFUN(memccpy,(_PTR __restrict, const _PTR __restrict, int, size_t)); +#endif +#if __GNU_VISIBLE +_PTR _EXFUN(mempcpy,(_PTR, const _PTR, size_t)); +_PTR _EXFUN(memmem, (const _PTR, size_t, const _PTR, size_t)); +#endif +_PTR _EXFUN(memrchr,(const _PTR, int, size_t)); +#if __GNU_VISIBLE +_PTR _EXFUN(rawmemchr,(const _PTR, int)); +#endif +#if __BSD_VISIBLE +char *_EXFUN(rindex,(const char *, int)); +#endif +char *_EXFUN(stpcpy,(char *__restrict, const char *__restrict)); +char *_EXFUN(stpncpy,(char *__restrict, const char *__restrict, size_t)); +#if __BSD_VISIBLE || __POSIX_VISIBLE +int _EXFUN(strcasecmp,(const char *, const char *)); +#endif +#if __GNU_VISIBLE +char *_EXFUN(strcasestr,(const char *, const char *)); +char *_EXFUN(strchrnul,(const char *, int)); +#endif +#if __XSI_VISIBLE >= 500 +char *_EXFUN(strdup,(const char *)); +#endif +#ifndef __STRICT_ANSI__ +char *_EXFUN(_strdup_r,(struct _reent *, const char *)); +#endif +#if __XSI_VISIBLE >= 700 +char *_EXFUN(strndup,(const char *, size_t)); +#endif + +#ifndef __STRICT_ANSI__ +char *_EXFUN(_strndup_r,(struct _reent *, const char *, size_t)); +#endif + +#if __GNU_VISIBLE +int _EXFUN(ffsl,(long)); +int _EXFUN(ffsll, (long long)); +#endif + +/* There are two common strerror_r variants. If you request + _GNU_SOURCE, you get the GNU version; otherwise you get the POSIX + version. POSIX requires that #undef strerror_r will still let you + invoke the underlying function, but that requires gcc support. */ +#if __GNU_VISIBLE +char *_EXFUN(strerror_r,(int, char *, size_t)); +#else +# ifdef __GNUC__ +int _EXFUN(strerror_r,(int, char *, size_t)) + __asm__ (__ASMNAME ("__xpg_strerror_r")); +# else +int _EXFUN(__xpg_strerror_r,(int, char *, size_t)); +# define strerror_r __xpg_strerror_r +# endif +#endif + +/* Reentrant version of strerror. */ +char * _EXFUN(_strerror_r, (struct _reent *, int, int, int *)); + +#if __BSD_VISIBLE +size_t _EXFUN(strlcat,(char *, const char *, size_t)); +size_t _EXFUN(strlcpy,(char *, const char *, size_t)); +#endif +#if __BSD_VISIBLE || __POSIX_VISIBLE +int _EXFUN(strncasecmp,(const char *, const char *, size_t)); +#endif +#if !defined(__STRICT_ANSI__) || __POSIX_VISIBLE >= 200809 || \ + __XSI_VISIBLE >= 700 +size_t _EXFUN(strnlen,(const char *, size_t)); +#endif +#if __BSD_VISIBLE +char *_EXFUN(strsep,(char **, const char *)); +#endif + +/* + * The origin of these is unknown to me so I am conditionalizing them + * on __STRICT_ANSI__. Finetuning this is definitely needed. --joel + */ +#if !defined(__STRICT_ANSI__) +char *_EXFUN(strlwr,(char *)); +char *_EXFUN(strupr,(char *)); +#endif + +#ifndef DEFS_H /* Kludge to work around problem compiling in gdb */ +char *_EXFUN(strsignal, (int __signo)); +#endif + +#ifdef __CYGWIN__ +int _EXFUN(strtosigno, (const char *__name)); +#endif + +#if defined _GNU_SOURCE && defined __GNUC__ +#define strdupa(__s) \ + (__extension__ ({const char *__in = (__s); \ + size_t __len = strlen (__in) + 1; \ + char * __out = (char *) __builtin_alloca (__len); \ + (char *) memcpy (__out, __in, __len);})) +#define strndupa(__s, __n) \ + (__extension__ ({const char *__in = (__s); \ + size_t __len = strnlen (__in, (__n)) + 1; \ + char *__out = (char *) __builtin_alloca (__len); \ + __out[__len-1] = '\0'; \ + (char *) memcpy (__out, __in, __len-1);})) +#endif /* _GNU_SOURCE && __GNUC__ */ + +#include + +_END_STD_C + +#endif /* _STRING_H_ */ diff --git a/components/newlib/include/strings.h b/components/newlib/include/strings.h new file mode 100644 index 0000000000..131d81d20c --- /dev/null +++ b/components/newlib/include/strings.h @@ -0,0 +1,35 @@ +/* + * strings.h + * + * Definitions for string operations. + */ + +#ifndef _STRINGS_H_ +#define _STRINGS_H_ + +#include "_ansi.h" +#include + +#include /* for size_t */ + +_BEGIN_STD_C + +#if !defined __STRICT_ANSI__ && _POSIX_VERSION < 200809L +/* + * Marked LEGACY in Open Group Base Specifications Issue 6/IEEE Std 1003.1-2004 + * Removed from Open Group Base Specifications Issue 7/IEEE Std 1003.1-2008 + */ +int _EXFUN(bcmp,(const void *, const void *, size_t)); +void _EXFUN(bcopy,(const void *, void *, size_t)); +void _EXFUN(bzero,(void *, size_t)); +char *_EXFUN(index,(const char *, int)); +char *_EXFUN(rindex,(const char *, int)); +#endif /* ! __STRICT_ANSI__ */ + +int _EXFUN(ffs,(int)); +int _EXFUN(strcasecmp,(const char *, const char *)); +int _EXFUN(strncasecmp,(const char *, const char *, size_t)); + +_END_STD_C + +#endif /* _STRINGS_H_ */ diff --git a/components/newlib/include/sys/_default_fcntl.h b/components/newlib/include/sys/_default_fcntl.h new file mode 100644 index 0000000000..eb674ae797 --- /dev/null +++ b/components/newlib/include/sys/_default_fcntl.h @@ -0,0 +1,213 @@ + +#ifndef _SYS__DEFAULT_FCNTL_H_ +#ifdef __cplusplus +extern "C" { +#endif +#define _SYS__DEFAULT_FCNTL_H_ +#include <_ansi.h> +#include +#define _FOPEN (-1) /* from sys/file.h, kernel use only */ +#define _FREAD 0x0001 /* read enabled */ +#define _FWRITE 0x0002 /* write enabled */ +#define _FAPPEND 0x0008 /* append (writes guaranteed at the end) */ +#define _FMARK 0x0010 /* internal; mark during gc() */ +#define _FDEFER 0x0020 /* internal; defer for next gc pass */ +#define _FASYNC 0x0040 /* signal pgrp when data ready */ +#define _FSHLOCK 0x0080 /* BSD flock() shared lock present */ +#define _FEXLOCK 0x0100 /* BSD flock() exclusive lock present */ +#define _FCREAT 0x0200 /* open with file create */ +#define _FTRUNC 0x0400 /* open with truncation */ +#define _FEXCL 0x0800 /* error on open if file exists */ +#define _FNBIO 0x1000 /* non blocking I/O (sys5 style) */ +#define _FSYNC 0x2000 /* do all writes synchronously */ +#define _FNONBLOCK 0x4000 /* non blocking I/O (POSIX style) */ +#define _FNDELAY _FNONBLOCK /* non blocking I/O (4.2 style) */ +#define _FNOCTTY 0x8000 /* don't assign a ctty on this open */ + +#define O_ACCMODE (O_RDONLY|O_WRONLY|O_RDWR) + +/* + * Flag values for open(2) and fcntl(2) + * The kernel adds 1 to the open modes to turn it into some + * combination of FREAD and FWRITE. + */ +#define O_RDONLY 0 /* +1 == FREAD */ +#define O_WRONLY 1 /* +1 == FWRITE */ +#define O_RDWR 2 /* +1 == FREAD|FWRITE */ +#define O_APPEND _FAPPEND +#define O_CREAT _FCREAT +#define O_TRUNC _FTRUNC +#define O_EXCL _FEXCL +#define O_SYNC _FSYNC +/* O_NDELAY _FNDELAY set in include/fcntl.h */ +/* O_NDELAY _FNBIO set in include/fcntl.h */ +#define O_NONBLOCK _FNONBLOCK +#define O_NOCTTY _FNOCTTY +/* For machines which care - */ +#if defined (__CYGWIN__) +#define _FBINARY 0x10000 +#define _FTEXT 0x20000 +#define _FNOINHERIT 0x40000 +#define _FDIRECT 0x80000 +#define _FNOFOLLOW 0x100000 +#define _FDIRECTORY 0x200000 +#define _FEXECSRCH 0x400000 + +#define O_BINARY _FBINARY +#define O_TEXT _FTEXT +#define O_CLOEXEC _FNOINHERIT +#define O_DIRECT _FDIRECT +#define O_NOFOLLOW _FNOFOLLOW +#define O_DSYNC _FSYNC +#define O_RSYNC _FSYNC +#define O_DIRECTORY _FDIRECTORY +#define O_EXEC _FEXECSRCH +#define O_SEARCH _FEXECSRCH +#endif + +#ifndef _POSIX_SOURCE + +/* + * Flags that work for fcntl(fd, F_SETFL, FXXXX) + */ +#define FAPPEND _FAPPEND +#define FSYNC _FSYNC +#define FASYNC _FASYNC +#define FNBIO _FNBIO +#define FNONBIO _FNONBLOCK /* XXX fix to be NONBLOCK everywhere */ +#define FNDELAY _FNDELAY + +/* + * Flags that are disallowed for fcntl's (FCNTLCANT); + * used for opens, internal state, or locking. + */ +#define FREAD _FREAD +#define FWRITE _FWRITE +#define FMARK _FMARK +#define FDEFER _FDEFER +#define FSHLOCK _FSHLOCK +#define FEXLOCK _FEXLOCK + +/* + * The rest of the flags, used only for opens + */ +#define FOPEN _FOPEN +#define FCREAT _FCREAT +#define FTRUNC _FTRUNC +#define FEXCL _FEXCL +#define FNOCTTY _FNOCTTY + +#endif /* !_POSIX_SOURCE */ + +/* XXX close on exec request; must match UF_EXCLOSE in user.h */ +#define FD_CLOEXEC 1 /* posix */ + +/* fcntl(2) requests */ +#define F_DUPFD 0 /* Duplicate fildes */ +#define F_GETFD 1 /* Get fildes flags (close on exec) */ +#define F_SETFD 2 /* Set fildes flags (close on exec) */ +#define F_GETFL 3 /* Get file flags */ +#define F_SETFL 4 /* Set file flags */ +#ifndef _POSIX_SOURCE +#define F_GETOWN 5 /* Get owner - for ASYNC */ +#define F_SETOWN 6 /* Set owner - for ASYNC */ +#endif /* !_POSIX_SOURCE */ +#define F_GETLK 7 /* Get record-locking information */ +#define F_SETLK 8 /* Set or Clear a record-lock (Non-Blocking) */ +#define F_SETLKW 9 /* Set or Clear a record-lock (Blocking) */ +#ifndef _POSIX_SOURCE +#define F_RGETLK 10 /* Test a remote lock to see if it is blocked */ +#define F_RSETLK 11 /* Set or unlock a remote lock */ +#define F_CNVT 12 /* Convert a fhandle to an open fd */ +#define F_RSETLKW 13 /* Set or Clear remote record-lock(Blocking) */ +#endif /* !_POSIX_SOURCE */ +#ifdef __CYGWIN__ +#define F_DUPFD_CLOEXEC 14 /* As F_DUPFD, but set close-on-exec flag */ +#endif + +/* fcntl(2) flags (l_type field of flock structure) */ +#define F_RDLCK 1 /* read lock */ +#define F_WRLCK 2 /* write lock */ +#define F_UNLCK 3 /* remove lock(s) */ +#ifndef _POSIX_SOURCE +#define F_UNLKSYS 4 /* remove remote locks for a given system */ +#endif /* !_POSIX_SOURCE */ + +#if __BSD_VISIBLE || __POSIX_VISIBLE >= 200809 || defined(__CYGWIN__) +/* Special descriptor value to denote the cwd in calls to openat(2) etc. */ +#define AT_FDCWD -2 + +/* Flag values for faccessat2) et al. */ +#define AT_EACCESS 1 +#define AT_SYMLINK_NOFOLLOW 2 +#define AT_SYMLINK_FOLLOW 4 +#define AT_REMOVEDIR 8 +#endif + +#if __BSD_VISIBLE +/* lock operations for flock(2) */ +#define LOCK_SH 0x01 /* shared file lock */ +#define LOCK_EX 0x02 /* exclusive file lock */ +#define LOCK_NB 0x04 /* don't block when locking */ +#define LOCK_UN 0x08 /* unlock file */ +#endif + +/*#include */ + +#ifndef __CYGWIN__ +/* file segment locking set data type - information passed to system by user */ +struct flock { + short l_type; /* F_RDLCK, F_WRLCK, or F_UNLCK */ + short l_whence; /* flag to choose starting offset */ + long l_start; /* relative offset, in bytes */ + long l_len; /* length, in bytes; 0 means lock to EOF */ + short l_pid; /* returned with F_GETLK */ + short l_xxx; /* reserved for future use */ +}; +#endif /* __CYGWIN__ */ + +#ifndef _POSIX_SOURCE +/* extended file segment locking set data type */ +struct eflock { + short l_type; /* F_RDLCK, F_WRLCK, or F_UNLCK */ + short l_whence; /* flag to choose starting offset */ + long l_start; /* relative offset, in bytes */ + long l_len; /* length, in bytes; 0 means lock to EOF */ + short l_pid; /* returned with F_GETLK */ + short l_xxx; /* reserved for future use */ + long l_rpid; /* Remote process id wanting this lock */ + long l_rsys; /* Remote system id wanting this lock */ +}; +#endif /* !_POSIX_SOURCE */ + +#include +#include /* sigh. for the mode bits for open/creat */ + +extern int open _PARAMS ((const char *, int, ...)); +#if __BSD_VISIBLE || __POSIX_VISIBLE >= 200809 || defined(__CYGWIN__) +extern int openat _PARAMS ((int, const char *, int, ...)); +#endif +extern int creat _PARAMS ((const char *, mode_t)); +extern int fcntl _PARAMS ((int, int, ...)); +#if __BSD_VISIBLE +extern int flock _PARAMS ((int, int)); +#endif +#ifdef __CYGWIN__ +#include +extern int futimesat _PARAMS ((int, const char *, const struct timeval *)); +#endif + +/* Provide _ prototypes for functions provided by some versions + of newlib. */ +#ifdef _COMPILING_NEWLIB +extern int _open _PARAMS ((const char *, int, ...)); +extern int _fcntl _PARAMS ((int, int, ...)); +#ifdef __LARGE64_FILES +extern int _open64 _PARAMS ((const char *, int, ...)); +#endif +#endif + +#ifdef __cplusplus +} +#endif +#endif /* !_SYS__DEFAULT_FCNTL_H_ */ diff --git a/components/newlib/include/sys/_intsup.h b/components/newlib/include/sys/_intsup.h new file mode 100644 index 0000000000..fa78426c52 --- /dev/null +++ b/components/newlib/include/sys/_intsup.h @@ -0,0 +1,20 @@ +/* + * Copyright (c) 2004, 2005 by + * Ralf Corsepius, Ulm/Germany. All rights reserved. + * + * Permission to use, copy, modify, and distribute this software + * is freely granted, provided that this notice is preserved. + * + * Modified for xtensa arch & non-long int32_t, removes automatic setting of __have_long32. + */ + +#ifndef _SYS__INTSUP_H +#define _SYS__INTSUP_H + +#include + +#define __STDINT_EXP(x) __##x##__ + +#define __have_longlong64 1 + +#endif /* _SYS__INTSUP_H */ diff --git a/components/newlib/include/sys/_types.h b/components/newlib/include/sys/_types.h new file mode 100644 index 0000000000..07bc27675a --- /dev/null +++ b/components/newlib/include/sys/_types.h @@ -0,0 +1,91 @@ +/* ANSI C namespace clean utility typedefs */ + +/* This file defines various typedefs needed by the system calls that support + the C library. Basically, they're just the POSIX versions with an '_' + prepended. This file lives in the `sys' directory so targets can provide + their own if desired (or they can put target dependant conditionals here). +*/ + +#ifndef _SYS__TYPES_H +#define _SYS__TYPES_H + +#include +#include + +#ifndef __off_t_defined +typedef long _off_t; +#endif + +#ifndef __dev_t_defined +typedef short __dev_t; +#endif + +#ifndef __uid_t_defined +typedef unsigned short __uid_t; +#endif +#ifndef __gid_t_defined +typedef unsigned short __gid_t; +#endif + +#ifndef __off64_t_defined +__extension__ typedef long long _off64_t; +#endif + +/* + * We need fpos_t for the following, but it doesn't have a leading "_", + * so we use _fpos_t instead. + */ +#ifndef __fpos_t_defined +typedef long _fpos_t; /* XXX must match off_t in */ + /* (and must be `long' for now) */ +#endif + +#ifdef __LARGE64_FILES +#ifndef __fpos64_t_defined +typedef _off64_t _fpos64_t; +#endif +#endif + +#ifndef __ssize_t_defined +#ifdef __SIZE_TYPE__ +/* If __SIZE_TYPE__ is defined (gcc) we define ssize_t based on size_t. + We simply change "unsigned" to "signed" for this single definition + to make sure ssize_t and size_t only differ by their signedness. */ +#define unsigned signed +typedef __SIZE_TYPE__ _ssize_t; +#undef unsigned +#else +#if defined(__INT_MAX__) && __INT_MAX__ == 2147483647 +typedef int _ssize_t; +#else +typedef long _ssize_t; +#endif +#endif +#endif + +#define __need_wint_t +#include + +#ifndef __mbstate_t_defined +/* Conversion state information. */ +typedef struct +{ + int __count; + union + { + wint_t __wch; + unsigned char __wchb[4]; + } __value; /* Value so far. */ +} _mbstate_t; +#endif + +#ifndef __flock_t_defined +typedef _LOCK_RECURSIVE_T _flock_t; +#endif + +#ifndef __iconv_t_defined +/* Iconv descriptor type */ +typedef void *_iconv_t; +#endif + +#endif /* _SYS__TYPES_H */ diff --git a/components/newlib/include/sys/cdefs.h b/components/newlib/include/sys/cdefs.h new file mode 100644 index 0000000000..a5e613c63c --- /dev/null +++ b/components/newlib/include/sys/cdefs.h @@ -0,0 +1,710 @@ +/* libc/sys/linux/sys/cdefs.h - Helper macros for K&R vs. ANSI C compat. */ + +/* Written 2000 by Werner Almesberger */ + +/*- + * Copyright (c) 1991, 1993 + * The Regents of the University of California. All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Berkeley Software Design, Inc. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)cdefs.h 8.8 (Berkeley) 1/9/95 + * $FreeBSD$ + */ + +#ifndef _SYS_CDEFS_H_ +#define _SYS_CDEFS_H_ + +#include +#include +#include + +#define __PMT(args) args +#define __DOTS , ... +#define __THROW + +#ifdef __GNUC__ +# define __ASMNAME(cname) __XSTRING (__USER_LABEL_PREFIX__) cname +#endif + +#define __ptr_t void * +#define __long_double_t long double + +#define __attribute_malloc__ +#define __attribute_pure__ +#define __attribute_format_strfmon__(a,b) +#define __flexarr [0] + +#ifndef __BOUNDED_POINTERS__ +# define __bounded /* nothing */ +# define __unbounded /* nothing */ +# define __ptrvalue /* nothing */ +#endif + +/* + * Testing against Clang-specific extensions. + */ + +#ifndef __has_extension +#define __has_extension __has_feature +#endif +#ifndef __has_feature +#define __has_feature(x) 0 +#endif +#ifndef __has_include +#define __has_include(x) 0 +#endif +#ifndef __has_builtin +#define __has_builtin(x) 0 +#endif + +#if defined(__cplusplus) +#define __BEGIN_DECLS extern "C" { +#define __END_DECLS } +#else +#define __BEGIN_DECLS +#define __END_DECLS +#endif + +/* + * This code has been put in place to help reduce the addition of + * compiler specific defines in FreeBSD code. It helps to aid in + * having a compiler-agnostic source tree. + */ + +#if defined(__GNUC__) || defined(__INTEL_COMPILER) + +#if __GNUC__ >= 3 || defined(__INTEL_COMPILER) +#define __GNUCLIKE_ASM 3 +#define __GNUCLIKE_MATH_BUILTIN_CONSTANTS +#else +#define __GNUCLIKE_ASM 2 +#endif +#define __GNUCLIKE___TYPEOF 1 +#define __GNUCLIKE___OFFSETOF 1 +#define __GNUCLIKE___SECTION 1 + +#ifndef __INTEL_COMPILER +# define __GNUCLIKE_CTOR_SECTION_HANDLING 1 +#endif + +#define __GNUCLIKE_BUILTIN_CONSTANT_P 1 +# if defined(__INTEL_COMPILER) && defined(__cplusplus) \ + && __INTEL_COMPILER < 800 +# undef __GNUCLIKE_BUILTIN_CONSTANT_P +# endif + +#if (__GNUC_MINOR__ > 95 || __GNUC__ >= 3) && !defined(__INTEL_COMPILER) +# define __GNUCLIKE_BUILTIN_VARARGS 1 +# define __GNUCLIKE_BUILTIN_STDARG 1 +# define __GNUCLIKE_BUILTIN_VAALIST 1 +#endif + +#if defined(__GNUC__) +# define __GNUC_VA_LIST_COMPATIBILITY 1 +#endif + +/* + * Compiler memory barriers, specific to gcc and clang. + */ +#if defined(__GNUC__) +#define __compiler_membar() __asm __volatile(" " : : : "memory") +#endif + +#ifndef __INTEL_COMPILER +# define __GNUCLIKE_BUILTIN_NEXT_ARG 1 +# define __GNUCLIKE_MATH_BUILTIN_RELOPS +#endif + +#define __GNUCLIKE_BUILTIN_MEMCPY 1 + +/* XXX: if __GNUC__ >= 2: not tested everywhere originally, where replaced */ +#define __CC_SUPPORTS_INLINE 1 +#define __CC_SUPPORTS___INLINE 1 +#define __CC_SUPPORTS___INLINE__ 1 + +#define __CC_SUPPORTS___FUNC__ 1 +#define __CC_SUPPORTS_WARNING 1 + +#define __CC_SUPPORTS_VARADIC_XXX 1 /* see varargs.h */ + +#define __CC_SUPPORTS_DYNAMIC_ARRAY_INIT 1 + +#endif /* __GNUC__ || __INTEL_COMPILER */ + +/* + * The __CONCAT macro is used to concatenate parts of symbol names, e.g. + * with "#define OLD(foo) __CONCAT(old,foo)", OLD(foo) produces oldfoo. + * The __CONCAT macro is a bit tricky to use if it must work in non-ANSI + * mode -- there must be no spaces between its arguments, and for nested + * __CONCAT's, all the __CONCAT's must be at the left. __CONCAT can also + * concatenate double-quoted strings produced by the __STRING macro, but + * this only works with ANSI C. + * + * __XSTRING is like __STRING, but it expands any macros in its argument + * first. It is only available with ANSI C. + */ +#if defined(__STDC__) || defined(__cplusplus) +#define __P(protos) protos /* full-blown ANSI C */ +#define __CONCAT1(x,y) x ## y +#define __CONCAT(x,y) __CONCAT1(x,y) +#define __STRING(x) #x /* stringify without expanding x */ +#define __XSTRING(x) __STRING(x) /* expand x, then stringify */ + +#define __const const /* define reserved names to standard */ +#define __signed signed +#define __volatile volatile +#if defined(__cplusplus) +#define __inline inline /* convert to C++ keyword */ +#else +#if !(defined(__CC_SUPPORTS___INLINE)) +#define __inline /* delete GCC keyword */ +#endif /* ! __CC_SUPPORTS___INLINE */ +#endif /* !__cplusplus */ + +#else /* !(__STDC__ || __cplusplus) */ +#define __P(protos) () /* traditional C preprocessor */ +#define __CONCAT(x,y) x/**/y +#define __STRING(x) "x" + +#if !defined(__CC_SUPPORTS___INLINE) +#define __const /* delete pseudo-ANSI C keywords */ +#define __inline +#define __signed +#define __volatile +/* + * In non-ANSI C environments, new programs will want ANSI-only C keywords + * deleted from the program and old programs will want them left alone. + * When using a compiler other than gcc, programs using the ANSI C keywords + * const, inline etc. as normal identifiers should define -DNO_ANSI_KEYWORDS. + * When using "gcc -traditional", we assume that this is the intent; if + * __GNUC__ is defined but __STDC__ is not, we leave the new keywords alone. + */ +#ifndef NO_ANSI_KEYWORDS +#define const /* delete ANSI C keywords */ +#define inline +#define signed +#define volatile +#endif /* !NO_ANSI_KEYWORDS */ +#endif /* !__CC_SUPPORTS___INLINE */ +#endif /* !(__STDC__ || __cplusplus) */ + +/* + * Compiler-dependent macros to help declare dead (non-returning) and + * pure (no side effects) functions, and unused variables. They are + * null except for versions of gcc that are known to support the features + * properly (old versions of gcc-2 supported the dead and pure features + * in a different (wrong) way). If we do not provide an implementation + * for a given compiler, let the compile fail if it is told to use + * a feature that we cannot live without. + */ +#ifdef lint +#define __dead2 +#define __pure2 +#define __unused +#define __packed +#define __aligned(x) +#define __section(x) +#else +#if !__GNUC_PREREQ__(2, 5) && !defined(__INTEL_COMPILER) +#define __dead2 +#define __pure2 +#define __unused +#endif +#if __GNUC__ == 2 && __GNUC_MINOR__ >= 5 && __GNUC_MINOR__ < 7 && !defined(__INTEL_COMPILER) +#define __dead2 __attribute__((__noreturn__)) +#define __pure2 __attribute__((__const__)) +#define __unused +/* XXX Find out what to do for __packed, __aligned and __section */ +#endif +#if __GNUC_PREREQ__(2, 7) +#define __dead2 __attribute__((__noreturn__)) +#define __pure2 __attribute__((__const__)) +#define __unused __attribute__((__unused__)) +#define __used __attribute__((__used__)) +#define __packed __attribute__((__packed__)) +#define __aligned(x) __attribute__((__aligned__(x))) +#define __section(x) __attribute__((__section__(x))) +#endif +#if defined(__INTEL_COMPILER) +#define __dead2 __attribute__((__noreturn__)) +#define __pure2 __attribute__((__const__)) +#define __unused __attribute__((__unused__)) +#define __used __attribute__((__used__)) +#define __packed __attribute__((__packed__)) +#define __aligned(x) __attribute__((__aligned__(x))) +#define __section(x) __attribute__((__section__(x))) +#endif +#endif + +#if !__GNUC_PREREQ__(2, 95) +#define __alignof(x) __offsetof(struct { char __a; x __b; }, __b) +#endif + +/* + * Keywords added in C11. + */ + +#if !defined(__STDC_VERSION__) || __STDC_VERSION__ < 201112L + +#if !__has_extension(c_alignas) +#if (defined(__cplusplus) && __cplusplus >= 201103L) || \ + __has_extension(cxx_alignas) +#define _Alignas(x) alignas(x) +#else +/* XXX: Only emulates _Alignas(constant-expression); not _Alignas(type-name). */ +#define _Alignas(x) __aligned(x) +#endif +#endif + +#if defined(__cplusplus) && __cplusplus >= 201103L +#define _Alignof(x) alignof(x) +#else +#define _Alignof(x) __alignof(x) +#endif + +#if !__has_extension(c_atomic) && !__has_extension(cxx_atomic) +/* + * No native support for _Atomic(). Place object in structure to prevent + * most forms of direct non-atomic access. + */ +#define _Atomic(T) struct { T volatile __val; } +#endif + +#if defined(__cplusplus) && __cplusplus >= 201103L +#define _Noreturn [[noreturn]] +#else +#define _Noreturn __dead2 +#endif + +#if __GNUC_PREREQ__(4, 6) && !defined(__cplusplus) +/* Do nothing: _Static_assert() works as per C11 */ +#elif !__has_extension(c_static_assert) +#if (defined(__cplusplus) && __cplusplus >= 201103L) || \ + __has_extension(cxx_static_assert) +#define _Static_assert(x, y) static_assert(x, y) +#elif defined(__COUNTER__) +#define _Static_assert(x, y) __Static_assert(x, __COUNTER__) +#define __Static_assert(x, y) ___Static_assert(x, y) +#define ___Static_assert(x, y) typedef char __assert_ ## y[(x) ? 1 : -1] +#else +#define _Static_assert(x, y) struct __hack +#endif +#endif + +#if !__has_extension(c_thread_local) +/* XXX: Change this to test against C++11 when clang in base supports it. */ +#if /* (defined(__cplusplus) && __cplusplus >= 201103L) || */ \ + __has_extension(cxx_thread_local) +#define _Thread_local thread_local +#else +#define _Thread_local __thread +#endif +#endif + +#endif /* __STDC_VERSION__ || __STDC_VERSION__ < 201112L */ + +/* + * Emulation of C11 _Generic(). Unlike the previously defined C11 + * keywords, it is not possible to implement this using exactly the same + * syntax. Therefore implement something similar under the name + * __generic(). Unlike _Generic(), this macro can only distinguish + * between a single type, so it requires nested invocations to + * distinguish multiple cases. + */ + +#if defined(__STDC_VERSION__) && __STDC_VERSION__ >= 201112L +#define __generic(expr, t, yes, no) \ + _Generic(expr, t: yes, default: no) +#elif __GNUC_PREREQ__(3, 1) && !defined(__cplusplus) +#define __generic(expr, t, yes, no) \ + __builtin_choose_expr( \ + __builtin_types_compatible_p(__typeof(expr), t), yes, no) +#endif + +#if __GNUC_PREREQ__(2, 96) +#define __malloc_like __attribute__((__malloc__)) +#define __pure __attribute__((__pure__)) +#else +#define __malloc_like +#define __pure +#endif + +#if __GNUC_PREREQ__(3, 1) || (defined(__INTEL_COMPILER) && __INTEL_COMPILER >= 800) +#define __always_inline __attribute__((__always_inline__)) +#else +#define __always_inline +#endif + +#if __GNUC_PREREQ__(3, 1) +#define __noinline __attribute__ ((__noinline__)) +#else +#define __noinline +#endif + +#if __GNUC_PREREQ__(3, 3) +#define __nonnull(x) __attribute__((__nonnull__(x))) +#else +#define __nonnull(x) +#endif + +#if __GNUC_PREREQ__(3, 4) +#define __fastcall __attribute__((__fastcall__)) +#else +#define __fastcall +#endif + +#if __GNUC_PREREQ__(4, 1) +#define __returns_twice __attribute__((__returns_twice__)) +#else +#define __returns_twice +#endif + +/* XXX: should use `#if __STDC_VERSION__ < 199901'. */ +#if !__GNUC_PREREQ__(2, 7) && !defined(__INTEL_COMPILER) +#define __func__ NULL +#endif + +/* + * GCC 2.95 provides `__restrict' as an extension to C90 to support the + * C99-specific `restrict' type qualifier. We happen to use `__restrict' as + * a way to define the `restrict' type qualifier without disturbing older + * software that is unaware of C99 keywords. + */ +#if !(__GNUC__ == 2 && __GNUC_MINOR__ == 95) +#if !defined(__STDC_VERSION__) || __STDC_VERSION__ < 199901 || defined(lint) +#define __restrict +#else +#define __restrict restrict +#endif +#endif + +/* + * GNU C version 2.96 adds explicit branch prediction so that + * the CPU back-end can hint the processor and also so that + * code blocks can be reordered such that the predicted path + * sees a more linear flow, thus improving cache behavior, etc. + * + * The following two macros provide us with a way to utilize this + * compiler feature. Use __predict_true() if you expect the expression + * to evaluate to true, and __predict_false() if you expect the + * expression to evaluate to false. + * + * A few notes about usage: + * + * * Generally, __predict_false() error condition checks (unless + * you have some _strong_ reason to do otherwise, in which case + * document it), and/or __predict_true() `no-error' condition + * checks, assuming you want to optimize for the no-error case. + * + * * Other than that, if you don't know the likelihood of a test + * succeeding from empirical or other `hard' evidence, don't + * make predictions. + * + * * These are meant to be used in places that are run `a lot'. + * It is wasteful to make predictions in code that is run + * seldomly (e.g. at subsystem initialization time) as the + * basic block reordering that this affects can often generate + * larger code. + */ +#if __GNUC_PREREQ__(2, 96) +#define __predict_true(exp) __builtin_expect((exp), 1) +#define __predict_false(exp) __builtin_expect((exp), 0) +#else +#define __predict_true(exp) (exp) +#define __predict_false(exp) (exp) +#endif + +#if __GNUC_PREREQ__(4, 2) +#define __hidden __attribute__((__visibility__("hidden"))) +#define __exported __attribute__((__visibility__("default"))) +#else +#define __hidden +#define __exported +#endif + +#define __offsetof(type, field) offsetof(type, field) +#define __rangeof(type, start, end) \ + (__offsetof(type, end) - __offsetof(type, start)) + +/* + * Given the pointer x to the member m of the struct s, return + * a pointer to the containing structure. When using GCC, we first + * assign pointer x to a local variable, to check that its type is + * compatible with member m. + */ +#if __GNUC_PREREQ__(3, 1) +#define __containerof(x, s, m) ({ \ + const volatile __typeof__(((s *)0)->m) *__x = (x); \ + __DEQUALIFY(s *, (const volatile char *)__x - __offsetof(s, m));\ +}) +#else +#define __containerof(x, s, m) \ + __DEQUALIFY(s *, (const volatile char *)(x) - __offsetof(s, m)) +#endif + +/* + * Compiler-dependent macros to declare that functions take printf-like + * or scanf-like arguments. They are null except for versions of gcc + * that are known to support the features properly (old versions of gcc-2 + * didn't permit keeping the keywords out of the application namespace). + */ +#if !__GNUC_PREREQ__(2, 7) && !defined(__INTEL_COMPILER) +#define __printflike(fmtarg, firstvararg) +#define __scanflike(fmtarg, firstvararg) +#define __format_arg(fmtarg) +#define __strfmonlike(fmtarg, firstvararg) +#define __strftimelike(fmtarg, firstvararg) +#else +#define __printflike(fmtarg, firstvararg) \ + __attribute__((__format__ (__printf__, fmtarg, firstvararg))) +#define __scanflike(fmtarg, firstvararg) \ + __attribute__((__format__ (__scanf__, fmtarg, firstvararg))) +#define __format_arg(fmtarg) __attribute__((__format_arg__ (fmtarg))) +#define __strfmonlike(fmtarg, firstvararg) \ + __attribute__((__format__ (__strfmon__, fmtarg, firstvararg))) +#define __strftimelike(fmtarg, firstvararg) \ + __attribute__((__format__ (__strftime__, fmtarg, firstvararg))) +#endif + +/* Compiler-dependent macros that rely on FreeBSD-specific extensions. */ +#if defined(__FreeBSD_cc_version) && __FreeBSD_cc_version >= 300001 && \ + defined(__GNUC__) && !defined(__INTEL_COMPILER) +#define __printf0like(fmtarg, firstvararg) \ + __attribute__((__format__ (__printf0__, fmtarg, firstvararg))) +#else +#define __printf0like(fmtarg, firstvararg) +#endif + +#if defined(__GNUC__) || defined(__INTEL_COMPILER) +#ifndef __INTEL_COMPILER +#define __strong_reference(sym,aliassym) \ + extern __typeof (sym) aliassym __attribute__ ((__alias__ (#sym))) +#endif +#ifdef __ELF__ +#ifdef __STDC__ +#define __weak_reference(sym,alias) \ + __asm__(".weak " #alias); \ + __asm__(".equ " #alias ", " #sym) +#define __warn_references(sym,msg) \ + __asm__(".section .gnu.warning." #sym); \ + __asm__(".asciz \"" msg "\""); \ + __asm__(".previous") +#define __sym_compat(sym,impl,verid) \ + __asm__(".symver " #impl ", " #sym "@" #verid) +#define __sym_default(sym,impl,verid) \ + __asm__(".symver " #impl ", " #sym "@@" #verid) +#else +#define __weak_reference(sym,alias) \ + __asm__(".weak alias"); \ + __asm__(".equ alias, sym") +#define __warn_references(sym,msg) \ + __asm__(".section .gnu.warning.sym"); \ + __asm__(".asciz \"msg\""); \ + __asm__(".previous") +#define __sym_compat(sym,impl,verid) \ + __asm__(".symver impl, sym@verid") +#define __sym_default(impl,sym,verid) \ + __asm__(".symver impl, sym@@verid") +#endif /* __STDC__ */ +#else /* !__ELF__ */ +#ifdef __STDC__ +#define __weak_reference(sym,alias) \ + __asm__(".stabs \"_" #alias "\",11,0,0,0"); \ + __asm__(".stabs \"_" #sym "\",1,0,0,0") +#define __warn_references(sym,msg) \ + __asm__(".stabs \"" msg "\",30,0,0,0"); \ + __asm__(".stabs \"_" #sym "\",1,0,0,0") +#else +#define __weak_reference(sym,alias) \ + __asm__(".stabs \"_/**/alias\",11,0,0,0"); \ + __asm__(".stabs \"_/**/sym\",1,0,0,0") +#define __warn_references(sym,msg) \ + __asm__(".stabs msg,30,0,0,0"); \ + __asm__(".stabs \"_/**/sym\",1,0,0,0") +#endif /* __STDC__ */ +#endif /* __ELF__ */ +#endif /* __GNUC__ || __INTEL_COMPILER */ + +#ifndef __FBSDID +#define __FBSDID(s) struct __hack +#endif + +#ifndef __RCSID +#define __RCSID(s) struct __hack +#endif + +#ifndef __RCSID_SOURCE +#define __RCSID_SOURCE(s) struct __hack +#endif + +#ifndef __SCCSID +#define __SCCSID(s) struct __hack +#endif + +#ifndef __COPYRIGHT +#define __COPYRIGHT(s) struct __hack +#endif + +#ifndef __DECONST +#define __DECONST(type, var) ((type)(__uintptr_t)(const void *)(var)) +#endif + +#ifndef __DEVOLATILE +#define __DEVOLATILE(type, var) ((type)(__uintptr_t)(volatile void *)(var)) +#endif + +#ifndef __DEQUALIFY +#define __DEQUALIFY(type, var) ((type)(__uintptr_t)(const volatile void *)(var)) +#endif + +/*- + * The following definitions are an extension of the behavior originally + * implemented in , but with a different level of granularity. + * POSIX.1 requires that the macros we test be defined before any standard + * header file is included. + * + * Here's a quick run-down of the versions: + * defined(_POSIX_SOURCE) 1003.1-1988 + * _POSIX_C_SOURCE == 1 1003.1-1990 + * _POSIX_C_SOURCE == 2 1003.2-1992 C Language Binding Option + * _POSIX_C_SOURCE == 199309 1003.1b-1993 + * _POSIX_C_SOURCE == 199506 1003.1c-1995, 1003.1i-1995, + * and the omnibus ISO/IEC 9945-1: 1996 + * _POSIX_C_SOURCE == 200112 1003.1-2001 + * _POSIX_C_SOURCE == 200809 1003.1-2008 + * + * In addition, the X/Open Portability Guide, which is now the Single UNIX + * Specification, defines a feature-test macro which indicates the version of + * that specification, and which subsumes _POSIX_C_SOURCE. + * + * Our macros begin with two underscores to avoid namespace screwage. + */ + +/* Deal with IEEE Std. 1003.1-1990, in which _POSIX_C_SOURCE == 1. */ +#if defined(_POSIX_C_SOURCE) && _POSIX_C_SOURCE == 1 +#undef _POSIX_C_SOURCE /* Probably illegal, but beyond caring now. */ +#define _POSIX_C_SOURCE 199009 +#endif + +/* Deal with IEEE Std. 1003.2-1992, in which _POSIX_C_SOURCE == 2. */ +#if defined(_POSIX_C_SOURCE) && _POSIX_C_SOURCE == 2 +#undef _POSIX_C_SOURCE +#define _POSIX_C_SOURCE 199209 +#endif + +/* Deal with various X/Open Portability Guides and Single UNIX Spec. */ +#ifdef _XOPEN_SOURCE +#if _XOPEN_SOURCE - 0 >= 700 +#define __XSI_VISIBLE 700 +#undef _POSIX_C_SOURCE +#define _POSIX_C_SOURCE 200809 +#elif _XOPEN_SOURCE - 0 >= 600 +#define __XSI_VISIBLE 600 +#undef _POSIX_C_SOURCE +#define _POSIX_C_SOURCE 200112 +#elif _XOPEN_SOURCE - 0 >= 500 +#define __XSI_VISIBLE 500 +#undef _POSIX_C_SOURCE +#define _POSIX_C_SOURCE 199506 +#endif +#endif + +/* + * Deal with all versions of POSIX. The ordering relative to the tests above is + * important. + */ +#if defined(_POSIX_SOURCE) && !defined(_POSIX_C_SOURCE) +#define _POSIX_C_SOURCE 198808 +#endif +#ifdef _POSIX_C_SOURCE +#if _POSIX_C_SOURCE >= 200809 +#define __POSIX_VISIBLE 200809 +#define __ISO_C_VISIBLE 1999 +#elif _POSIX_C_SOURCE >= 200112 +#define __POSIX_VISIBLE 200112 +#define __ISO_C_VISIBLE 1999 +#elif _POSIX_C_SOURCE >= 199506 +#define __POSIX_VISIBLE 199506 +#define __ISO_C_VISIBLE 1990 +#elif _POSIX_C_SOURCE >= 199309 +#define __POSIX_VISIBLE 199309 +#define __ISO_C_VISIBLE 1990 +#elif _POSIX_C_SOURCE >= 199209 +#define __POSIX_VISIBLE 199209 +#define __ISO_C_VISIBLE 1990 +#elif _POSIX_C_SOURCE >= 199009 +#define __POSIX_VISIBLE 199009 +#define __ISO_C_VISIBLE 1990 +#else +#define __POSIX_VISIBLE 198808 +#define __ISO_C_VISIBLE 0 +#endif /* _POSIX_C_SOURCE */ +#else +/*- + * Deal with _ANSI_SOURCE: + * If it is defined, and no other compilation environment is explicitly + * requested, then define our internal feature-test macros to zero. This + * makes no difference to the preprocessor (undefined symbols in preprocessing + * expressions are defined to have value zero), but makes it more convenient for + * a test program to print out the values. + * + * If a program mistakenly defines _ANSI_SOURCE and some other macro such as + * _POSIX_C_SOURCE, we will assume that it wants the broader compilation + * environment (and in fact we will never get here). + */ +#if defined(_ANSI_SOURCE) /* Hide almost everything. */ +#define __POSIX_VISIBLE 0 +#define __XSI_VISIBLE 0 +#define __BSD_VISIBLE 0 +#define __ISO_C_VISIBLE 1990 +#elif defined(_C99_SOURCE) /* Localism to specify strict C99 env. */ +#define __POSIX_VISIBLE 0 +#define __XSI_VISIBLE 0 +#define __BSD_VISIBLE 0 +#define __ISO_C_VISIBLE 1999 +#elif defined(_C11_SOURCE) /* Localism to specify strict C11 env. */ +#define __POSIX_VISIBLE 0 +#define __XSI_VISIBLE 0 +#define __BSD_VISIBLE 0 +#define __ISO_C_VISIBLE 2011 +#elif defined(_GNU_SOURCE) /* Everything and the kitchen sink. */ +#define __POSIX_VISIBLE 200809 +#define __XSI_VISIBLE 700 +#define __BSD_VISIBLE 1 +#define __ISO_C_VISIBLE 2011 +#define __GNU_VISIBLE 1 +#else /* Default: everything except __GNU_VISIBLE. */ +#define __POSIX_VISIBLE 200809 +#define __XSI_VISIBLE 700 +#define __BSD_VISIBLE 1 +#define __ISO_C_VISIBLE 2011 +#endif +#endif + +#endif /* !_SYS_CDEFS_H_ */ diff --git a/components/newlib/include/sys/config.h b/components/newlib/include/sys/config.h new file mode 100644 index 0000000000..b5adfe1025 --- /dev/null +++ b/components/newlib/include/sys/config.h @@ -0,0 +1,300 @@ +#ifndef __SYS_CONFIG_H__ +#define __SYS_CONFIG_H__ + +#include /* floating point macros */ +#include /* POSIX defs */ + +#ifdef __aarch64__ +#define MALLOC_ALIGNMENT 16 +#endif + +/* exceptions first */ +#if defined(__H8500__) || defined(__W65__) +#define __SMALL_BITFIELDS +/* ??? This conditional is true for the h8500 and the w65, defining H8300 + in those cases probably isn't the right thing to do. */ +#define H8300 1 +#endif + +/* 16 bit integer machines */ +#if defined(__Z8001__) || defined(__Z8002__) || defined(__H8500__) || defined(__W65__) || defined (__mn10200__) || defined (__AVR__) + +#undef INT_MAX +#undef UINT_MAX +#define INT_MAX 32767 +#define UINT_MAX 65535 +#endif + +#if defined (__H8300__) || defined (__H8300H__) || defined(__H8300S__) || defined (__H8300SX__) +#define __SMALL_BITFIELDS +#define H8300 1 +#undef INT_MAX +#undef UINT_MAX +#define INT_MAX __INT_MAX__ +#define UINT_MAX (__INT_MAX__ * 2U + 1) +#endif + +#if (defined(__CR16__) || defined(__CR16C__) ||defined(__CR16CP__)) +#ifndef __INT32__ +#define __SMALL_BITFIELDS +#undef INT_MAX +#undef UINT_MAX +#define INT_MAX 32767 +#define UINT_MAX (__INT_MAX__ * 2U + 1) +#else /* INT32 */ +#undef INT_MAX +#undef UINT_MAX +#define INT_MAX 2147483647 +#define UINT_MAX (__INT_MAX__ * 2U + 1) +#endif /* INT32 */ + +#endif /* CR16C */ + +#if defined (__xc16x__) || defined (__xc16xL__) || defined (__xc16xS__) +#define __SMALL_BITFIELDS +#endif + +#ifdef __W65__ +#define __SMALL_BITFIELDS +#endif + +#if defined(__D10V__) +#define __SMALL_BITFIELDS +#undef INT_MAX +#undef UINT_MAX +#define INT_MAX __INT_MAX__ +#define UINT_MAX (__INT_MAX__ * 2U + 1) +#define _POINTER_INT short +#endif + +#if defined(__mc68hc11__) || defined(__mc68hc12__) || defined(__mc68hc1x__) +#undef INT_MAX +#undef UINT_MAX +#define INT_MAX __INT_MAX__ +#define UINT_MAX (__INT_MAX__ * 2U + 1) +#define _POINTER_INT short +#endif + +#if defined(__m68k__) || defined(__mc68000__) +#define _READ_WRITE_RETURN_TYPE _ssize_t +#endif + +#ifdef ___AM29K__ +#define _FLOAT_RET double +#endif + +#ifdef __i386__ +#ifndef __unix__ +/* in other words, go32 */ +#define _FLOAT_RET double +#endif +#if defined(__linux__) || defined(__RDOS__) +/* we want the reentrancy structure to be returned by a function */ +#define __DYNAMIC_REENT__ +#define HAVE_GETDATE +#define _HAVE_SYSTYPES +#define _READ_WRITE_RETURN_TYPE _ssize_t +#define __LARGE64_FILES 1 +/* we use some glibc header files so turn on glibc large file feature */ +#define _LARGEFILE64_SOURCE 1 +#endif +#endif + +#ifdef __mn10200__ +#define __SMALL_BITFIELDS +#endif + +#ifdef __AVR__ +#define __SMALL_BITFIELDS +#define _POINTER_INT short +#endif + +#ifdef __v850 +#define __ATTRIBUTE_IMPURE_PTR__ __attribute__((__sda__)) +#endif + +/* For the PowerPC eabi, force the _impure_ptr to be in .sdata */ +#if defined(__PPC__) +#if defined(_CALL_SYSV) +#define __ATTRIBUTE_IMPURE_PTR__ __attribute__((__section__(".sdata"))) +#endif +#ifdef __SPE__ +#define _LONG_DOUBLE double +#endif +#endif + +/* Configure small REENT structure for Xilinx MicroBlaze platforms */ +#if defined (__MICROBLAZE__) +#ifndef _REENT_SMALL +#define _REENT_SMALL +#endif +/* Xilinx XMK uses Unix98 mutex */ +#ifdef __XMK__ +#define _UNIX98_THREAD_MUTEX_ATTRIBUTES +#endif +#endif + +#if defined(__mips__) && !defined(__rtems__) +#define __ATTRIBUTE_IMPURE_PTR__ __attribute__((__section__(".sdata"))) +#endif + +#ifdef __xstormy16__ +#define __SMALL_BITFIELDS +#undef INT_MAX +#undef UINT_MAX +#define INT_MAX __INT_MAX__ +#define UINT_MAX (__INT_MAX__ * 2U + 1) +#define MALLOC_ALIGNMENT 8 +#define _POINTER_INT short +#define __BUFSIZ__ 16 +#define _REENT_SMALL +#endif + +#if defined __MSP430__ +#ifndef _REENT_SMALL +#define _REENT_SMALL +#endif + +#define __SMALL_BITFIELDS + +#ifdef __MSP430X_LARGE__ +#define _POINTER_INT long +#else +#define _POINTER_INT int +#endif +#endif + +#ifdef __m32c__ +#define __SMALL_BITFIELDS +#undef INT_MAX +#undef UINT_MAX +#define INT_MAX __INT_MAX__ +#define UINT_MAX (__INT_MAX__ * 2U + 1) +#define MALLOC_ALIGNMENT 8 +#if defined(__r8c_cpu__) || defined(__m16c_cpu__) +#define _POINTER_INT short +#else +#define _POINTER_INT long +#endif +#define __BUFSIZ__ 16 +#define _REENT_SMALL +#endif /* __m32c__ */ + +#ifdef __SPU__ +#define MALLOC_ALIGNMENT 16 +#define __CUSTOM_FILE_IO__ +#endif + +#ifdef __XTENSA__ +#include +#define MALLOC_ALIGNMENT ((XCHAL_DATA_WIDTH) < 16 ? 16 : (XCHAL_DATA_WIDTH)) +/* esp8266-specific: shrink the default fd buffer size */ +#define __BUFSIZ__ 128 +#ifndef __DYNAMIC_REENT__ +#define __DYNAMIC_REENT__ +#endif +#ifndef _REENT_SMALL +#define _REENT_SMALL +#endif +#define HAVE_GETOPT +#endif + +/* This block should be kept in sync with GCC's limits.h. The point + of having these definitions here is to not include limits.h, which + would pollute the user namespace, while still using types of the + the correct widths when deciding how to define __int32_t and + __int64_t. */ +#ifndef __INT_MAX__ +# ifdef INT_MAX +# define __INT_MAX__ INT_MAX +# else +# define __INT_MAX__ 2147483647 +# endif +#endif + +#ifndef __LONG_MAX__ +# ifdef LONG_MAX +# define __LONG_MAX__ LONG_MAX +# else +# if defined (__alpha__) || (defined (__sparc__) && defined(__arch64__)) \ + || defined (__sparcv9) +# define __LONG_MAX__ 9223372036854775807L +# else +# define __LONG_MAX__ 2147483647L +# endif /* __alpha__ || sparc64 */ +# endif +#endif +/* End of block that should be kept in sync with GCC's limits.h. */ + +#ifndef _POINTER_INT +#define _POINTER_INT long +#endif + +#ifdef __frv__ +#define __ATTRIBUTE_IMPURE_PTR__ __attribute__((__section__(".sdata"))) +#endif +#undef __RAND_MAX +#if __INT_MAX__ == 32767 +#define __RAND_MAX 32767 +#else +#define __RAND_MAX 0x7fffffff +#endif + +#if defined(__CYGWIN__) +#include +#if !defined (__STRICT_ANSI__) || (__STDC_VERSION__ >= 199901L) +#define __USE_XOPEN2K 1 +#endif +#endif + +#if defined(__rtems__) +#define __FILENAME_MAX__ 255 +#define _READ_WRITE_RETURN_TYPE _ssize_t +#define __DYNAMIC_REENT__ +#define _REENT_GLOBAL_ATEXIT +#endif + +#ifndef __EXPORT +#define __EXPORT +#endif + +#ifndef __IMPORT +#define __IMPORT +#endif + +/* Define return type of read/write routines. In POSIX, the return type + for read()/write() is "ssize_t" but legacy newlib code has been using + "int" for some time. If not specified, "int" is defaulted. */ +#ifndef _READ_WRITE_RETURN_TYPE +#define _READ_WRITE_RETURN_TYPE int +#endif +/* Define `count' parameter of read/write routines. In POSIX, the `count' + parameter is "size_t" but legacy newlib code has been using "int" for some + time. If not specified, "int" is defaulted. */ +#ifndef _READ_WRITE_BUFSIZE_TYPE +#define _READ_WRITE_BUFSIZE_TYPE int +#endif + +#ifndef __WCHAR_MAX__ +#if __INT_MAX__ == 32767 || defined (_WIN32) +#define __WCHAR_MAX__ 0xffffu +#endif +#endif + +/* See if small reent asked for at configuration time and + is not chosen by the platform by default. */ +#ifdef _WANT_REENT_SMALL +#ifndef _REENT_SMALL +#define _REENT_SMALL +#endif +#endif + +/* If _MB_EXTENDED_CHARSETS_ALL is set, we want all of the extended + charsets. The extended charsets add a few functions and a couple + of tables of a few K each. */ +#ifdef _MB_EXTENDED_CHARSETS_ALL +#define _MB_EXTENDED_CHARSETS_ISO 1 +#define _MB_EXTENDED_CHARSETS_WINDOWS 1 +#endif + +#endif /* __SYS_CONFIG_H__ */ diff --git a/components/newlib/include/sys/custom_file.h b/components/newlib/include/sys/custom_file.h new file mode 100644 index 0000000000..96314fb916 --- /dev/null +++ b/components/newlib/include/sys/custom_file.h @@ -0,0 +1,2 @@ +#error System-specific custom_file.h is missing. + diff --git a/components/newlib/include/sys/dir.h b/components/newlib/include/sys/dir.h new file mode 100644 index 0000000000..220150dc95 --- /dev/null +++ b/components/newlib/include/sys/dir.h @@ -0,0 +1,10 @@ +/* BSD predecessor of POSIX.1 and struct dirent */ + +#ifndef _SYS_DIR_H_ +#define _SYS_DIR_H_ + +#include + +#define direct dirent + +#endif /*_SYS_DIR_H_*/ diff --git a/components/newlib/include/sys/dirent.h b/components/newlib/include/sys/dirent.h new file mode 100644 index 0000000000..a3fb5c02c5 --- /dev/null +++ b/components/newlib/include/sys/dirent.h @@ -0,0 +1,13 @@ +/* includes , which is this file. On a + system which supports , this file is overridden by + dirent.h in the libc/sys/.../sys directory. On a system which does + not support , we will get this file which uses #error to force + an error. */ + +#ifdef __cplusplus +extern "C" { +#endif +#error " not supported" +#ifdef __cplusplus +} +#endif diff --git a/components/newlib/include/sys/errno.h b/components/newlib/include/sys/errno.h new file mode 100644 index 0000000000..a72c37320a --- /dev/null +++ b/components/newlib/include/sys/errno.h @@ -0,0 +1,192 @@ +/* errno is not a global variable, because that would make using it + non-reentrant. Instead, its address is returned by the function + __errno. */ + +#ifndef _SYS_ERRNO_H_ +#ifdef __cplusplus +extern "C" { +#endif +#define _SYS_ERRNO_H_ + +#include + +#ifndef _REENT_ONLY +#define errno (*__errno()) +extern int *__errno _PARAMS ((void)); +#endif + +/* Please don't use these variables directly. + Use strerror instead. */ +extern __IMPORT _CONST char * _CONST _sys_errlist[]; +extern __IMPORT int _sys_nerr; +#ifdef __CYGWIN__ +extern __IMPORT const char * const sys_errlist[]; +extern __IMPORT int sys_nerr; +extern __IMPORT char *program_invocation_name; +extern __IMPORT char *program_invocation_short_name; +#endif + +#define __errno_r(ptr) ((ptr)->_errno) + +#define EPERM 1 /* Not owner */ +#define ENOENT 2 /* No such file or directory */ +#define ESRCH 3 /* No such process */ +#define EINTR 4 /* Interrupted system call */ +#define EIO 5 /* I/O error */ +#define ENXIO 6 /* No such device or address */ +#define E2BIG 7 /* Arg list too long */ +#define ENOEXEC 8 /* Exec format error */ +#define EBADF 9 /* Bad file number */ +#define ECHILD 10 /* No children */ +#define EAGAIN 11 /* No more processes */ +#define ENOMEM 12 /* Not enough space */ +#define EACCES 13 /* Permission denied */ +#define EFAULT 14 /* Bad address */ +#ifdef __LINUX_ERRNO_EXTENSIONS__ +#define ENOTBLK 15 /* Block device required */ +#endif +#define EBUSY 16 /* Device or resource busy */ +#define EEXIST 17 /* File exists */ +#define EXDEV 18 /* Cross-device link */ +#define ENODEV 19 /* No such device */ +#define ENOTDIR 20 /* Not a directory */ +#define EISDIR 21 /* Is a directory */ +#define EINVAL 22 /* Invalid argument */ +#define ENFILE 23 /* Too many open files in system */ +#define EMFILE 24 /* File descriptor value too large */ +#define ENOTTY 25 /* Not a character device */ +#define ETXTBSY 26 /* Text file busy */ +#define EFBIG 27 /* File too large */ +#define ENOSPC 28 /* No space left on device */ +#define ESPIPE 29 /* Illegal seek */ +#define EROFS 30 /* Read-only file system */ +#define EMLINK 31 /* Too many links */ +#define EPIPE 32 /* Broken pipe */ +#define EDOM 33 /* Mathematics argument out of domain of function */ +#define ERANGE 34 /* Result too large */ +#define ENOMSG 35 /* No message of desired type */ +#define EIDRM 36 /* Identifier removed */ +#ifdef __LINUX_ERRNO_EXTENSIONS__ +#define ECHRNG 37 /* Channel number out of range */ +#define EL2NSYNC 38 /* Level 2 not synchronized */ +#define EL3HLT 39 /* Level 3 halted */ +#define EL3RST 40 /* Level 3 reset */ +#define ELNRNG 41 /* Link number out of range */ +#define EUNATCH 42 /* Protocol driver not attached */ +#define ENOCSI 43 /* No CSI structure available */ +#define EL2HLT 44 /* Level 2 halted */ +#endif +#define EDEADLK 45 /* Deadlock */ +#define ENOLCK 46 /* No lock */ +#ifdef __LINUX_ERRNO_EXTENSIONS__ +#define EBADE 50 /* Invalid exchange */ +#define EBADR 51 /* Invalid request descriptor */ +#define EXFULL 52 /* Exchange full */ +#define ENOANO 53 /* No anode */ +#define EBADRQC 54 /* Invalid request code */ +#define EBADSLT 55 /* Invalid slot */ +#define EDEADLOCK 56 /* File locking deadlock error */ +#define EBFONT 57 /* Bad font file fmt */ +#endif +#define ENOSTR 60 /* Not a stream */ +#define ENODATA 61 /* No data (for no delay io) */ +#define ETIME 62 /* Stream ioctl timeout */ +#define ENOSR 63 /* No stream resources */ +#ifdef __LINUX_ERRNO_EXTENSIONS__ +#define ENONET 64 /* Machine is not on the network */ +#define ENOPKG 65 /* Package not installed */ +#define EREMOTE 66 /* The object is remote */ +#endif +#define ENOLINK 67 /* Virtual circuit is gone */ +#ifdef __LINUX_ERRNO_EXTENSIONS__ +#define EADV 68 /* Advertise error */ +#define ESRMNT 69 /* Srmount error */ +#define ECOMM 70 /* Communication error on send */ +#endif +#define EPROTO 71 /* Protocol error */ +#define EMULTIHOP 74 /* Multihop attempted */ +#ifdef __LINUX_ERRNO_EXTENSIONS__ +#define ELBIN 75 /* Inode is remote (not really error) */ +#define EDOTDOT 76 /* Cross mount point (not really error) */ +#endif +#define EBADMSG 77 /* Bad message */ +#define EFTYPE 79 /* Inappropriate file type or format */ +#ifdef __LINUX_ERRNO_EXTENSIONS__ +#define ENOTUNIQ 80 /* Given log. name not unique */ +#define EBADFD 81 /* f.d. invalid for this operation */ +#define EREMCHG 82 /* Remote address changed */ +#define ELIBACC 83 /* Can't access a needed shared lib */ +#define ELIBBAD 84 /* Accessing a corrupted shared lib */ +#define ELIBSCN 85 /* .lib section in a.out corrupted */ +#define ELIBMAX 86 /* Attempting to link in too many libs */ +#define ELIBEXEC 87 /* Attempting to exec a shared library */ +#endif +#define ENOSYS 88 /* Function not implemented */ +#ifdef __CYGWIN__ +#define ENMFILE 89 /* No more files */ +#endif +#define ENOTEMPTY 90 /* Directory not empty */ +#define ENAMETOOLONG 91 /* File or path name too long */ +#define ELOOP 92 /* Too many symbolic links */ +#define EOPNOTSUPP 95 /* Operation not supported on socket */ +#define EPFNOSUPPORT 96 /* Protocol family not supported */ +#define ECONNRESET 104 /* Connection reset by peer */ +#define ENOBUFS 105 /* No buffer space available */ +#define EAFNOSUPPORT 106 /* Address family not supported by protocol family */ +#define EPROTOTYPE 107 /* Protocol wrong type for socket */ +#define ENOTSOCK 108 /* Socket operation on non-socket */ +#define ENOPROTOOPT 109 /* Protocol not available */ +#ifdef __LINUX_ERRNO_EXTENSIONS__ +#define ESHUTDOWN 110 /* Can't send after socket shutdown */ +#endif +#define ECONNREFUSED 111 /* Connection refused */ +#define EADDRINUSE 112 /* Address already in use */ +#define ECONNABORTED 113 /* Software caused connection abort */ +#define ENETUNREACH 114 /* Network is unreachable */ +#define ENETDOWN 115 /* Network interface is not configured */ +#define ETIMEDOUT 116 /* Connection timed out */ +#define EHOSTDOWN 117 /* Host is down */ +#define EHOSTUNREACH 118 /* Host is unreachable */ +#define EINPROGRESS 119 /* Connection already in progress */ +#define EALREADY 120 /* Socket already connected */ +#define EDESTADDRREQ 121 /* Destination address required */ +#define EMSGSIZE 122 /* Message too long */ +#define EPROTONOSUPPORT 123 /* Unknown protocol */ +#ifdef __LINUX_ERRNO_EXTENSIONS__ +#define ESOCKTNOSUPPORT 124 /* Socket type not supported */ +#endif +#define EADDRNOTAVAIL 125 /* Address not available */ +#define ENETRESET 126 /* Connection aborted by network */ +#define EISCONN 127 /* Socket is already connected */ +#define ENOTCONN 128 /* Socket is not connected */ +#define ETOOMANYREFS 129 +#ifdef __LINUX_ERRNO_EXTENSIONS__ +#define EPROCLIM 130 +#define EUSERS 131 +#endif +#define EDQUOT 132 +#define ESTALE 133 +#define ENOTSUP 134 /* Not supported */ +#ifdef __LINUX_ERRNO_EXTENSIONS__ +#define ENOMEDIUM 135 /* No medium (in tape drive) */ +#endif +#ifdef __CYGWIN__ +#define ENOSHARE 136 /* No such host or network path */ +#define ECASECLASH 137 /* Filename exists with different case */ +#endif +#define EILSEQ 138 /* Illegal byte sequence */ +#define EOVERFLOW 139 /* Value too large for defined data type */ +#define ECANCELED 140 /* Operation canceled */ +#define ENOTRECOVERABLE 141 /* State not recoverable */ +#define EOWNERDEAD 142 /* Previous owner died */ +#ifdef __LINUX_ERRNO_EXTENSIONS__ +#define ESTRPIPE 143 /* Streams pipe error */ +#endif +#define EWOULDBLOCK EAGAIN /* Operation would block */ + +#define __ELASTERROR 2000 /* Users can add values starting here */ + +#ifdef __cplusplus +} +#endif +#endif /* _SYS_ERRNO_H */ diff --git a/components/newlib/include/sys/fcntl.h b/components/newlib/include/sys/fcntl.h new file mode 100644 index 0000000000..be85f40c1b --- /dev/null +++ b/components/newlib/include/sys/fcntl.h @@ -0,0 +1,4 @@ +#ifndef _SYS_FCNTL_H_ +#define _SYS_FCNTL_H_ +#include +#endif diff --git a/components/newlib/include/sys/features.h b/components/newlib/include/sys/features.h new file mode 100644 index 0000000000..1d90921af5 --- /dev/null +++ b/components/newlib/include/sys/features.h @@ -0,0 +1,235 @@ +/* + * Written by Joel Sherrill . + * + * COPYRIGHT (c) 1989-2000. + * + * On-Line Applications Research Corporation (OAR). + * + * Permission to use, copy, modify, and distribute this software for any + * purpose without fee is hereby granted, provided that this entire notice + * is included in all copies of any software which is or includes a copy + * or modification of this software. + * + * THIS SOFTWARE IS BEING PROVIDED "AS IS", WITHOUT ANY EXPRESS OR IMPLIED + * WARRANTY. IN PARTICULAR, THE AUTHOR MAKES NO REPRESENTATION + * OR WARRANTY OF ANY KIND CONCERNING THE MERCHANTABILITY OF THIS + * SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR PURPOSE. + * + * $Id$ + */ + +#ifndef _SYS_FEATURES_H +#define _SYS_FEATURES_H + +#ifdef __cplusplus +extern "C" { +#endif + +/* Macros to determine that newlib is being used. Put in this header to + * be similar to where glibc stores its version of these macros. + */ +#define __NEWLIB__ 2 +#define __NEWLIB_MINOR__ 1 + +/* Macro to test version of GCC. Returns 0 for non-GCC or too old GCC. */ +#ifndef __GNUC_PREREQ +# if defined __GNUC__ && defined __GNUC_MINOR__ +# define __GNUC_PREREQ(maj, min) \ + ((__GNUC__ << 16) + __GNUC_MINOR__ >= ((maj) << 16) + (min)) +# else +# define __GNUC_PREREQ(maj, min) 0 +# endif +#endif /* __GNUC_PREREQ */ +/* Version with trailing underscores for BSD compatibility. */ +#define __GNUC_PREREQ__(ma, mi) __GNUC_PREREQ(ma, mi) + +/* RTEMS adheres to POSIX -- 1003.1b with some features from annexes. */ + +#ifdef __rtems__ +#define _POSIX_JOB_CONTROL 1 +#define _POSIX_SAVED_IDS 1 +#define _POSIX_VERSION 199309L +#define _POSIX_ASYNCHRONOUS_IO 1 +#define _POSIX_FSYNC 1 +#define _POSIX_MAPPED_FILES 1 +#define _POSIX_MEMLOCK 1 +#define _POSIX_MEMLOCK_RANGE 1 +#define _POSIX_MEMORY_PROTECTION 1 +#define _POSIX_MESSAGE_PASSING 1 +#define _POSIX_MONOTONIC_CLOCK 200112L +#define _POSIX_PRIORITIZED_IO 1 +#define _POSIX_PRIORITY_SCHEDULING 1 +#define _POSIX_REALTIME_SIGNALS 1 +#define _POSIX_SEMAPHORES 1 +/* #define _POSIX_SHARED_MEMORY_OBJECTS 1 */ +#define _POSIX_SYNCHRONIZED_IO 1 +#define _POSIX_TIMERS 1 +#define _POSIX_BARRIERS 200112L +#define _POSIX_READER_WRITER_LOCKS 200112L +#define _POSIX_SPIN_LOCKS 200112L + + +/* In P1003.1b but defined by drafts at least as early as P1003.1c/D10 */ +#define _POSIX_THREADS 1 +#define _POSIX_THREAD_ATTR_STACKADDR 1 +#define _POSIX_THREAD_ATTR_STACKSIZE 1 +#define _POSIX_THREAD_PRIORITY_SCHEDULING 1 +#define _POSIX_THREAD_PRIO_INHERIT 1 +#define _POSIX_THREAD_PRIO_PROTECT 1 +#define _POSIX_THREAD_PROCESS_SHARED 1 +#define _POSIX_THREAD_SAFE_FUNCTIONS 1 + +/* P1003.4b/D8 defines the constants below this comment. */ +#define _POSIX_SPAWN 1 +#define _POSIX_TIMEOUTS 1 +#define _POSIX_CPUTIME 1 +#define _POSIX_THREAD_CPUTIME 1 +#define _POSIX_SPORADIC_SERVER 1 +#define _POSIX_THREAD_SPORADIC_SERVER 1 +#define _POSIX_DEVICE_CONTROL 1 +#define _POSIX_DEVCTL_DIRECTION 1 +#define _POSIX_INTERRUPT_CONTROL 1 +#define _POSIX_ADVISORY_INFO 1 + +/* UNIX98 added some new pthread mutex attributes */ +#define _UNIX98_THREAD_MUTEX_ATTRIBUTES 1 + +#endif + +/* XMK loosely adheres to POSIX -- 1003.1 */ +#ifdef __XMK__ +#define _POSIX_THREADS 1 +#define _POSIX_THREAD_PRIORITY_SCHEDULING 1 +#endif + + +#ifdef __svr4__ +# define _POSIX_JOB_CONTROL 1 +# define _POSIX_SAVED_IDS 1 +# define _POSIX_VERSION 199009L +#endif + +#ifdef __CYGWIN__ + +#if !defined(__STRICT_ANSI__) || defined(__cplusplus) || __STDC_VERSION__ >= 199901L +#define _POSIX_VERSION 200112L +#define _POSIX2_VERSION 200112L +#define _XOPEN_VERSION 600 + +#define _POSIX_ADVISORY_INFO 200112L +/* #define _POSIX_ASYNCHRONOUS_IO -1 */ +/* #define _POSIX_BARRIERS -1 */ +#define _POSIX_CHOWN_RESTRICTED 1 +#define _POSIX_CLOCK_SELECTION 200112L +#define _POSIX_CPUTIME 200112L +#define _POSIX_FSYNC 200112L +#define _POSIX_IPV6 200112L +#define _POSIX_JOB_CONTROL 1 +#define _POSIX_MAPPED_FILES 200112L +/* #define _POSIX_MEMLOCK -1 */ +#define _POSIX_MEMLOCK_RANGE 200112L +#define _POSIX_MEMORY_PROTECTION 200112L +#define _POSIX_MESSAGE_PASSING 200112L +#define _POSIX_MONOTONIC_CLOCK 200112L +#define _POSIX_NO_TRUNC 1 +/* #define _POSIX_PRIORITIZED_IO -1 */ +#define _POSIX_PRIORITY_SCHEDULING 200112L +#define _POSIX_RAW_SOCKETS 200112L +#define _POSIX_READER_WRITER_LOCKS 200112L +#define _POSIX_REALTIME_SIGNALS 200112L +#define _POSIX_REGEXP 1 +#define _POSIX_SAVED_IDS 1 +#define _POSIX_SEMAPHORES 200112L +#define _POSIX_SHARED_MEMORY_OBJECTS 200112L +#define _POSIX_SHELL 1 +/* #define _POSIX_SPAWN -1 */ +#define _POSIX_SPIN_LOCKS 200112L +/* #define _POSIX_SPORADIC_SERVER -1 */ +#define _POSIX_SYNCHRONIZED_IO 200112L +#define _POSIX_THREAD_ATTR_STACKADDR 200112L +#define _POSIX_THREAD_ATTR_STACKSIZE 200112L +#define _POSIX_THREAD_CPUTIME 200112L +/* #define _POSIX_THREAD_PRIO_INHERIT -1 */ +/* #define _POSIX_THREAD_PRIO_PROTECT -1 */ +#define _POSIX_THREAD_PRIORITY_SCHEDULING 200112L +#define _POSIX_THREAD_PROCESS_SHARED 200112L +#define _POSIX_THREAD_SAFE_FUNCTIONS 200112L +/* #define _POSIX_THREAD_SPORADIC_SERVER -1 */ +#define _POSIX_THREADS 200112L +/* #define _POSIX_TIMEOUTS -1 */ +#define _POSIX_TIMERS 1 +/* #define _POSIX_TRACE -1 */ +/* #define _POSIX_TRACE_EVENT_FILTER -1 */ +/* #define _POSIX_TRACE_INHERIT -1 */ +/* #define _POSIX_TRACE_LOG -1 */ +/* #define _POSIX_TYPED_MEMORY_OBJECTS -1 */ +#define _POSIX_VDISABLE '\0' +#define _POSIX2_C_BIND 200112L +#define _POSIX2_C_DEV 200112L +#define _POSIX2_CHAR_TERM 200112L +/* #define _POSIX2_FORT_DEV -1 */ +/* #define _POSIX2_FORT_RUN -1 */ +/* #define _POSIX2_LOCALEDEF -1 */ +/* #define _POSIX2_PBS -1 */ +/* #define _POSIX2_PBS_ACCOUNTING -1 */ +/* #define _POSIX2_PBS_CHECKPOINT -1 */ +/* #define _POSIX2_PBS_LOCATE -1 */ +/* #define _POSIX2_PBS_MESSAGE -1 */ +/* #define _POSIX2_PBS_TRACK -1 */ +#define _POSIX2_SW_DEV 200112L +#define _POSIX2_UPE 200112L +#define _POSIX_V6_ILP32_OFF32 -1 +#ifdef __LP64__ +#define _POSIX_V6_ILP32_OFFBIG -1 +#define _POSIX_V6_LP64_OFF64 1 +#define _POSIX_V6_LPBIG_OFFBIG 1 +#else +#define _POSIX_V6_ILP32_OFFBIG 1 +#define _POSIX_V6_LP64_OFF64 -1 +#define _POSIX_V6_LPBIG_OFFBIG -1 +#endif +#define _XBS5_ILP32_OFF32 _POSIX_V6_ILP32_OFF32 +#define _XBS5_ILP32_OFFBIG _POSIX_V6_ILP32_OFFBIG +#define _XBS5_LP64_OFF64 _POSIX_V6_LP64_OFF64 +#define _XBS5_LPBIG_OFFBIG _POSIX_V6_LPBIG_OFFBIG +#define _XOPEN_CRYPT 1 +#define _XOPEN_ENH_I18N 1 +/* #define _XOPEN_LEGACY -1 */ +/* #define _XOPEN_REALTIME -1 */ +/* #define _XOPEN_REALTIME_THREADS -1 */ +#define _XOPEN_SHM 1 +/* #define _XOPEN_STREAMS -1 */ +/* #define _XOPEN_UNIX -1 */ + +#endif /* !__STRICT_ANSI__ || __cplusplus || __STDC_VERSION__ >= 199901L */ + +/* The value corresponds to UNICODE version 4.0, which is the version + supported by XP. Newlib supports 5.2 (2011) but so far Cygwin needs + the MS conversions for double-byte charsets. */ +#define __STDC_ISO_10646__ 200305L + +#endif /* __CYGWIN__ */ + +/* Per the permission given in POSIX.1-2008 section 2.2.1, define + * _POSIX_C_SOURCE if _XOPEN_SOURCE is defined and _POSIX_C_SOURCE is not. + * (_XOPEN_SOURCE indicates that XSI extensions are desired by an application.) + * This permission is first granted in 2008, but use it for older ones, also. + * Allow for _XOPEN_SOURCE to be empty (from the earliest form of it, before it + * was required to have specific values). + */ +#if !defined(_POSIX_C_SOURCE) && defined(_XOPEN_SOURCE) + #if (_XOPEN_SOURCE - 0) == 700 /* POSIX.1-2008 */ + #define _POSIX_C_SOURCE 200809L + #elif (_XOPEN_SOURCE - 0) == 600 /* POSIX.1-2001 or 2004 */ + #define _POSIX_C_SOURCE 200112L + #elif (_XOPEN_SOURCE - 0) == 500 /* POSIX.1-1995 */ + #define _POSIX_C_SOURCE 199506L + #elif (_XOPEN_SOURCE - 0) < 500 /* really old */ + #define _POSIX_C_SOURCE 2 + #endif +#endif + +#ifdef __cplusplus +} +#endif +#endif /* _SYS_FEATURES_H */ diff --git a/components/newlib/include/sys/file.h b/components/newlib/include/sys/file.h new file mode 100644 index 0000000000..be88c6a5ad --- /dev/null +++ b/components/newlib/include/sys/file.h @@ -0,0 +1,33 @@ +/* Copyright (c) 2005-2006 Tensilica Inc. ALL RIGHTS RESERVED. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS + IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A + PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL TENSILICA + INCORPORATED BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ + +#include + +/* Alternate names for values for the WHENCE argument to `lseek'. + These are the same as SEEK_SET, SEEK_CUR, and SEEK_END, respectively. */ +#ifndef L_SET +#define L_SET 0 /* Seek from beginning of file. */ +#define L_INCR 1 /* Seek from current position. */ +#define L_XTND 2 /* Seek from end of file. */ +#endif diff --git a/components/newlib/include/sys/iconvnls.h b/components/newlib/include/sys/iconvnls.h new file mode 100644 index 0000000000..09ea183163 --- /dev/null +++ b/components/newlib/include/sys/iconvnls.h @@ -0,0 +1,77 @@ +/* + * Copyright (c) 2003-2004, Artem B. Bityuckiy. + * Rights transferred to Franklin Electronic Publishers. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * Funtions, macros, etc implimented in iconv library but used by other + * NLS-related subsystems too. + */ +#ifndef __SYS_ICONVNLS_H__ +#define __SYS_ICONVNLS_H__ + +#include <_ansi.h> +#include +#include +#include + +/* Iconv data path environment variable name */ +#define NLS_ENVVAR_NAME "NLSPATH" +/* Default NLSPATH value */ +#define ICONV_DEFAULT_NLSPATH "/usr/locale" +/* Direction markers */ +#define ICONV_NLS_FROM 0 +#define ICONV_NLS_TO 1 + +_VOID +_EXFUN(_iconv_nls_get_state, (iconv_t cd, mbstate_t *ps, int direction)); + +int +_EXFUN(_iconv_nls_set_state, (iconv_t cd, mbstate_t *ps, int direction)); + +int +_EXFUN(_iconv_nls_is_stateful, (iconv_t cd, int direction)); + +int +_EXFUN(_iconv_nls_get_mb_cur_max, (iconv_t cd, int direction)); + +size_t +_EXFUN(_iconv_nls_conv, (struct _reent *rptr, iconv_t cd, + _CONST char **inbuf, size_t *inbytesleft, + char **outbuf, size_t *outbytesleft)); + +_CONST char * +_EXFUN(_iconv_nls_construct_filename, (struct _reent *rptr, _CONST char *file, + _CONST char *dir, _CONST char *ext)); + + +int +_EXFUN(_iconv_nls_open, (struct _reent *rptr, _CONST char *encoding, + iconv_t *towc, iconv_t *fromwc, int flag)); + +char * +_EXFUN(_iconv_resolve_encoding_name, (struct _reent *rptr, _CONST char *ca)); + +#endif /* __SYS_ICONVNLS_H__ */ + diff --git a/components/newlib/include/sys/lock.h b/components/newlib/include/sys/lock.h new file mode 100644 index 0000000000..0ff3475836 --- /dev/null +++ b/components/newlib/include/sys/lock.h @@ -0,0 +1,50 @@ +#ifndef _XTENSA_LOCK_H__ +#define _XTENSA_LOCK_H__ + +/* generic lock implementation. + + Weak linked stub _lock functions in lock.c, can be + replaced with a lock implementation at link time. + + */ + +typedef int _lock_t; +typedef _lock_t _LOCK_RECURSIVE_T; +typedef _lock_t _LOCK_T; + +#include <_ansi.h> + +/* NOTE: some parts of newlib statically initialise locks via + __LOCK_INIT, some initialise at runtime via __lock_init. So need to + support possibility that a _lock_t is null during first call to + _lock_acquire or _lock_try_acquire. + + Lock functions all take a pointer to the _lock_t entry, so the + value stored there can be manipulated. +*/ +#define __LOCK_INIT(CLASS,NAME) CLASS _lock_t NAME = 0; +#define __LOCK_INIT_RECURSIVE(CLASS,NAME) CLASS _lock_t NAME = 0; + +void _lock_init(_lock_t *lock); +void _lock_init_recursive(_lock_t *lock); +void _lock_close(_lock_t *lock); +void _lock_close_recursive(_lock_t *lock); +void _lock_acquire(_lock_t *lock); +void _lock_acquire_recursive(_lock_t *lock); +int _lock_try_acquire(_lock_t *lock); +int _lock_try_acquire_recursive(_lock_t *lock); +void _lock_release(_lock_t *lock); +void _lock_release_recursive(_lock_t *lock); + +#define __lock_init(lock) _lock_init(&(lock)) +#define __lock_init_recursive(lock) _lock_init_recursive(&(lock)) +#define __lock_close(lock) _lock_close(&(lock)) +#define __lock_close_recursive(lock) _lock_close_recursive(&(lock)) +#define __lock_acquire(lock) _lock_acquire(&(lock)) +#define __lock_acquire_recursive(lock) _lock_acquire_recursive(&(lock)) +#define __lock_try_acquire(lock) _lock_try_acquire(&(lock)) +#define __lock_try_acquire_recursive(lock) _lock_try_acquire_recursive(&(lock)) +#define __lock_release(lock) _lock_release(&(lock)) +#define __lock_release_recursive(lock) _lock_release_recursive(&(lock)) + +#endif /* _XTENSA_LOCK_H__ */ diff --git a/components/newlib/include/sys/param.h b/components/newlib/include/sys/param.h new file mode 100644 index 0000000000..ef203d3ecf --- /dev/null +++ b/components/newlib/include/sys/param.h @@ -0,0 +1,28 @@ +/* This is a dummy file, not customized for any + particular system. If there is a param.h in libc/sys/SYSDIR/sys, + it will override this one. */ + +#ifndef _SYS_PARAM_H +# define _SYS_PARAM_H + +#include +#include +#include +#include + +#ifndef HZ +# define HZ (60) +#endif +#ifndef NOFILE +# define NOFILE (60) +#endif +#ifndef PATHSIZE +# define PATHSIZE (1024) +#endif + +#define MAXPATHLEN PATH_MAX + +#define MAX(a,b) ((a) > (b) ? (a) : (b)) +#define MIN(a,b) ((a) < (b) ? (a) : (b)) + +#endif diff --git a/components/newlib/include/sys/queue.h b/components/newlib/include/sys/queue.h new file mode 100644 index 0000000000..4bc7dac0ef --- /dev/null +++ b/components/newlib/include/sys/queue.h @@ -0,0 +1,691 @@ +/*- + * Copyright (c) 1991, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)queue.h 8.5 (Berkeley) 8/20/94 + * $FreeBSD$ + */ + +#ifndef _SYS_QUEUE_H_ +#define _SYS_QUEUE_H_ + +#include + +/* + * This file defines four types of data structures: singly-linked lists, + * singly-linked tail queues, lists and tail queues. + * + * A singly-linked list is headed by a single forward pointer. The elements + * are singly linked for minimum space and pointer manipulation overhead at + * the expense of O(n) removal for arbitrary elements. New elements can be + * added to the list after an existing element or at the head of the list. + * Elements being removed from the head of the list should use the explicit + * macro for this purpose for optimum efficiency. A singly-linked list may + * only be traversed in the forward direction. Singly-linked lists are ideal + * for applications with large datasets and few or no removals or for + * implementing a LIFO queue. + * + * A singly-linked tail queue is headed by a pair of pointers, one to the + * head of the list and the other to the tail of the list. The elements are + * singly linked for minimum space and pointer manipulation overhead at the + * expense of O(n) removal for arbitrary elements. New elements can be added + * to the list after an existing element, at the head of the list, or at the + * end of the list. Elements being removed from the head of the tail queue + * should use the explicit macro for this purpose for optimum efficiency. + * A singly-linked tail queue may only be traversed in the forward direction. + * Singly-linked tail queues are ideal for applications with large datasets + * and few or no removals or for implementing a FIFO queue. + * + * A list is headed by a single forward pointer (or an array of forward + * pointers for a hash table header). The elements are doubly linked + * so that an arbitrary element can be removed without a need to + * traverse the list. New elements can be added to the list before + * or after an existing element or at the head of the list. A list + * may be traversed in either direction. + * + * A tail queue is headed by a pair of pointers, one to the head of the + * list and the other to the tail of the list. The elements are doubly + * linked so that an arbitrary element can be removed without a need to + * traverse the list. New elements can be added to the list before or + * after an existing element, at the head of the list, or at the end of + * the list. A tail queue may be traversed in either direction. + * + * For details on the use of these macros, see the queue(3) manual page. + * + * + * SLIST LIST STAILQ TAILQ + * _HEAD + + + + + * _HEAD_INITIALIZER + + + + + * _ENTRY + + + + + * _INIT + + + + + * _EMPTY + + + + + * _FIRST + + + + + * _NEXT + + + + + * _PREV - + - + + * _LAST - - + + + * _FOREACH + + + + + * _FOREACH_SAFE + + + + + * _FOREACH_REVERSE - - - + + * _FOREACH_REVERSE_SAFE - - - + + * _INSERT_HEAD + + + + + * _INSERT_BEFORE - + - + + * _INSERT_AFTER + + + + + * _INSERT_TAIL - - + + + * _CONCAT - - + + + * _REMOVE_AFTER + - + - + * _REMOVE_HEAD + - + - + * _REMOVE + + + + + * _SWAP + + + + + * + */ +#ifdef QUEUE_MACRO_DEBUG +/* Store the last 2 places the queue element or head was altered */ +struct qm_trace { + unsigned long lastline; + unsigned long prevline; + const char *lastfile; + const char *prevfile; +}; + +#define TRACEBUF struct qm_trace trace; +#define TRACEBUF_INITIALIZER { __FILE__, __LINE__, NULL, 0 } , +#define TRASHIT(x) do {(x) = (void *)-1;} while (0) +#define QMD_SAVELINK(name, link) void **name = (void *)&(link) + +#define QMD_TRACE_HEAD(head) do { \ + (head)->trace.prevline = (head)->trace.lastline; \ + (head)->trace.prevfile = (head)->trace.lastfile; \ + (head)->trace.lastline = __LINE__; \ + (head)->trace.lastfile = __FILE__; \ +} while (0) + +#define QMD_TRACE_ELEM(elem) do { \ + (elem)->trace.prevline = (elem)->trace.lastline; \ + (elem)->trace.prevfile = (elem)->trace.lastfile; \ + (elem)->trace.lastline = __LINE__; \ + (elem)->trace.lastfile = __FILE__; \ +} while (0) + +#else +#define QMD_TRACE_ELEM(elem) +#define QMD_TRACE_HEAD(head) +#define QMD_SAVELINK(name, link) +#define TRACEBUF +#define TRACEBUF_INITIALIZER +#define TRASHIT(x) +#endif /* QUEUE_MACRO_DEBUG */ + +/* + * Singly-linked List declarations. + */ +#define SLIST_HEAD(name, type) \ +struct name { \ + struct type *slh_first; /* first element */ \ +} + +#define SLIST_HEAD_INITIALIZER(head) \ + { NULL } + +#define SLIST_ENTRY(type) \ +struct { \ + struct type *sle_next; /* next element */ \ +} + +/* + * Singly-linked List functions. + */ +#define SLIST_EMPTY(head) ((head)->slh_first == NULL) + +#define SLIST_FIRST(head) ((head)->slh_first) + +#define SLIST_FOREACH(var, head, field) \ + for ((var) = SLIST_FIRST((head)); \ + (var); \ + (var) = SLIST_NEXT((var), field)) + +#define SLIST_FOREACH_SAFE(var, head, field, tvar) \ + for ((var) = SLIST_FIRST((head)); \ + (var) && ((tvar) = SLIST_NEXT((var), field), 1); \ + (var) = (tvar)) + +#define SLIST_FOREACH_PREVPTR(var, varp, head, field) \ + for ((varp) = &SLIST_FIRST((head)); \ + ((var) = *(varp)) != NULL; \ + (varp) = &SLIST_NEXT((var), field)) + +#define SLIST_INIT(head) do { \ + SLIST_FIRST((head)) = NULL; \ +} while (0) + +#define SLIST_INSERT_AFTER(slistelm, elm, field) do { \ + SLIST_NEXT((elm), field) = SLIST_NEXT((slistelm), field); \ + SLIST_NEXT((slistelm), field) = (elm); \ +} while (0) + +#define SLIST_INSERT_HEAD(head, elm, field) do { \ + SLIST_NEXT((elm), field) = SLIST_FIRST((head)); \ + SLIST_FIRST((head)) = (elm); \ +} while (0) + +#define SLIST_NEXT(elm, field) ((elm)->field.sle_next) + +#define SLIST_REMOVE(head, elm, type, field) do { \ + QMD_SAVELINK(oldnext, (elm)->field.sle_next); \ + if (SLIST_FIRST((head)) == (elm)) { \ + SLIST_REMOVE_HEAD((head), field); \ + } \ + else { \ + struct type *curelm = SLIST_FIRST((head)); \ + while (SLIST_NEXT(curelm, field) != (elm)) \ + curelm = SLIST_NEXT(curelm, field); \ + SLIST_REMOVE_AFTER(curelm, field); \ + } \ + TRASHIT(*oldnext); \ +} while (0) + +#define SLIST_REMOVE_AFTER(elm, field) do { \ + SLIST_NEXT(elm, field) = \ + SLIST_NEXT(SLIST_NEXT(elm, field), field); \ +} while (0) + +#define SLIST_REMOVE_HEAD(head, field) do { \ + SLIST_FIRST((head)) = SLIST_NEXT(SLIST_FIRST((head)), field); \ +} while (0) + +#define SLIST_SWAP(head1, head2, type) do { \ + struct type *swap_first = SLIST_FIRST(head1); \ + SLIST_FIRST(head1) = SLIST_FIRST(head2); \ + SLIST_FIRST(head2) = swap_first; \ +} while (0) + +/* + * Singly-linked Tail queue declarations. + */ +#define STAILQ_HEAD(name, type) \ +struct name { \ + struct type *stqh_first;/* first element */ \ + struct type **stqh_last;/* addr of last next element */ \ +} + +#define STAILQ_HEAD_INITIALIZER(head) \ + { NULL, &(head).stqh_first } + +#define STAILQ_ENTRY(type) \ +struct { \ + struct type *stqe_next; /* next element */ \ +} + +/* + * Singly-linked Tail queue functions. + */ +#define STAILQ_CONCAT(head1, head2) do { \ + if (!STAILQ_EMPTY((head2))) { \ + *(head1)->stqh_last = (head2)->stqh_first; \ + (head1)->stqh_last = (head2)->stqh_last; \ + STAILQ_INIT((head2)); \ + } \ +} while (0) + +#define STAILQ_EMPTY(head) ((head)->stqh_first == NULL) + +#define STAILQ_FIRST(head) ((head)->stqh_first) + +#define STAILQ_FOREACH(var, head, field) \ + for((var) = STAILQ_FIRST((head)); \ + (var); \ + (var) = STAILQ_NEXT((var), field)) + + +#define STAILQ_FOREACH_SAFE(var, head, field, tvar) \ + for ((var) = STAILQ_FIRST((head)); \ + (var) && ((tvar) = STAILQ_NEXT((var), field), 1); \ + (var) = (tvar)) + +#define STAILQ_INIT(head) do { \ + STAILQ_FIRST((head)) = NULL; \ + (head)->stqh_last = &STAILQ_FIRST((head)); \ +} while (0) + +#define STAILQ_INSERT_AFTER(head, tqelm, elm, field) do { \ + if ((STAILQ_NEXT((elm), field) = STAILQ_NEXT((tqelm), field)) == NULL)\ + (head)->stqh_last = &STAILQ_NEXT((elm), field); \ + STAILQ_NEXT((tqelm), field) = (elm); \ +} while (0) + +#define STAILQ_INSERT_HEAD(head, elm, field) do { \ + if ((STAILQ_NEXT((elm), field) = STAILQ_FIRST((head))) == NULL) \ + (head)->stqh_last = &STAILQ_NEXT((elm), field); \ + STAILQ_FIRST((head)) = (elm); \ +} while (0) + +#define STAILQ_INSERT_TAIL(head, elm, field) do { \ + STAILQ_NEXT((elm), field) = NULL; \ + *(head)->stqh_last = (elm); \ + (head)->stqh_last = &STAILQ_NEXT((elm), field); \ +} while (0) + +#define STAILQ_LAST(head, type, field) \ + (STAILQ_EMPTY((head)) ? NULL : \ + __containerof((head)->stqh_last, struct type, field.stqe_next)) + +#define STAILQ_NEXT(elm, field) ((elm)->field.stqe_next) + +#define STAILQ_REMOVE(head, elm, type, field) do { \ + QMD_SAVELINK(oldnext, (elm)->field.stqe_next); \ + if (STAILQ_FIRST((head)) == (elm)) { \ + STAILQ_REMOVE_HEAD((head), field); \ + } \ + else { \ + struct type *curelm = STAILQ_FIRST((head)); \ + while (STAILQ_NEXT(curelm, field) != (elm)) \ + curelm = STAILQ_NEXT(curelm, field); \ + STAILQ_REMOVE_AFTER(head, curelm, field); \ + } \ + TRASHIT(*oldnext); \ +} while (0) + +#define STAILQ_REMOVE_AFTER(head, elm, field) do { \ + if ((STAILQ_NEXT(elm, field) = \ + STAILQ_NEXT(STAILQ_NEXT(elm, field), field)) == NULL) \ + (head)->stqh_last = &STAILQ_NEXT((elm), field); \ +} while (0) + +#define STAILQ_REMOVE_HEAD(head, field) do { \ + if ((STAILQ_FIRST((head)) = \ + STAILQ_NEXT(STAILQ_FIRST((head)), field)) == NULL) \ + (head)->stqh_last = &STAILQ_FIRST((head)); \ +} while (0) + +#define STAILQ_REMOVE_HEAD_UNTIL(head, elm, field) do { \ + if ((STAILQ_FIRST((head)) = STAILQ_NEXT((elm), field)) == NULL) \ + (head)->stqh_last = &STAILQ_FIRST((head)); \ +} while (0) + +#define STAILQ_SWAP(head1, head2, type) do { \ + struct type *swap_first = STAILQ_FIRST(head1); \ + struct type **swap_last = (head1)->stqh_last; \ + STAILQ_FIRST(head1) = STAILQ_FIRST(head2); \ + (head1)->stqh_last = (head2)->stqh_last; \ + STAILQ_FIRST(head2) = swap_first; \ + (head2)->stqh_last = swap_last; \ + if (STAILQ_EMPTY(head1)) \ + (head1)->stqh_last = &STAILQ_FIRST(head1); \ + if (STAILQ_EMPTY(head2)) \ + (head2)->stqh_last = &STAILQ_FIRST(head2); \ +} while (0) + + +/* + * List declarations. + */ +#define LIST_HEAD(name, type) \ +struct name { \ + struct type *lh_first; /* first element */ \ +} + +#define LIST_HEAD_INITIALIZER(head) \ + { NULL } + +#define LIST_ENTRY(type) \ +struct { \ + struct type *le_next; /* next element */ \ + struct type **le_prev; /* address of previous next element */ \ +} + +/* + * List functions. + */ + +#if (defined(_KERNEL) && defined(INVARIANTS)) +#define QMD_LIST_CHECK_HEAD(head, field) do { \ + if (LIST_FIRST((head)) != NULL && \ + LIST_FIRST((head))->field.le_prev != \ + &LIST_FIRST((head))) \ + panic("Bad list head %p first->prev != head", (head)); \ +} while (0) + +#define QMD_LIST_CHECK_NEXT(elm, field) do { \ + if (LIST_NEXT((elm), field) != NULL && \ + LIST_NEXT((elm), field)->field.le_prev != \ + &((elm)->field.le_next)) \ + panic("Bad link elm %p next->prev != elm", (elm)); \ +} while (0) + +#define QMD_LIST_CHECK_PREV(elm, field) do { \ + if (*(elm)->field.le_prev != (elm)) \ + panic("Bad link elm %p prev->next != elm", (elm)); \ +} while (0) +#else +#define QMD_LIST_CHECK_HEAD(head, field) +#define QMD_LIST_CHECK_NEXT(elm, field) +#define QMD_LIST_CHECK_PREV(elm, field) +#endif /* (_KERNEL && INVARIANTS) */ + +#define LIST_EMPTY(head) ((head)->lh_first == NULL) + +#define LIST_FIRST(head) ((head)->lh_first) + +#define LIST_FOREACH(var, head, field) \ + for ((var) = LIST_FIRST((head)); \ + (var); \ + (var) = LIST_NEXT((var), field)) + +#define LIST_FOREACH_SAFE(var, head, field, tvar) \ + for ((var) = LIST_FIRST((head)); \ + (var) && ((tvar) = LIST_NEXT((var), field), 1); \ + (var) = (tvar)) + +#define LIST_INIT(head) do { \ + LIST_FIRST((head)) = NULL; \ +} while (0) + +#define LIST_INSERT_AFTER(listelm, elm, field) do { \ + QMD_LIST_CHECK_NEXT(listelm, field); \ + if ((LIST_NEXT((elm), field) = LIST_NEXT((listelm), field)) != NULL)\ + LIST_NEXT((listelm), field)->field.le_prev = \ + &LIST_NEXT((elm), field); \ + LIST_NEXT((listelm), field) = (elm); \ + (elm)->field.le_prev = &LIST_NEXT((listelm), field); \ +} while (0) + +#define LIST_INSERT_BEFORE(listelm, elm, field) do { \ + QMD_LIST_CHECK_PREV(listelm, field); \ + (elm)->field.le_prev = (listelm)->field.le_prev; \ + LIST_NEXT((elm), field) = (listelm); \ + *(listelm)->field.le_prev = (elm); \ + (listelm)->field.le_prev = &LIST_NEXT((elm), field); \ +} while (0) + +#define LIST_INSERT_HEAD(head, elm, field) do { \ + QMD_LIST_CHECK_HEAD((head), field); \ + if ((LIST_NEXT((elm), field) = LIST_FIRST((head))) != NULL) \ + LIST_FIRST((head))->field.le_prev = &LIST_NEXT((elm), field);\ + LIST_FIRST((head)) = (elm); \ + (elm)->field.le_prev = &LIST_FIRST((head)); \ +} while (0) + +#define LIST_NEXT(elm, field) ((elm)->field.le_next) + +#define LIST_PREV(elm, head, type, field) \ + ((elm)->field.le_prev == &LIST_FIRST((head)) ? NULL : \ + __containerof((elm)->field.le_prev, struct type, field.le_next)) + +#define LIST_REMOVE(elm, field) do { \ + QMD_SAVELINK(oldnext, (elm)->field.le_next); \ + QMD_SAVELINK(oldprev, (elm)->field.le_prev); \ + QMD_LIST_CHECK_NEXT(elm, field); \ + QMD_LIST_CHECK_PREV(elm, field); \ + if (LIST_NEXT((elm), field) != NULL) \ + LIST_NEXT((elm), field)->field.le_prev = \ + (elm)->field.le_prev; \ + *(elm)->field.le_prev = LIST_NEXT((elm), field); \ + TRASHIT(*oldnext); \ + TRASHIT(*oldprev); \ +} while (0) + +#define LIST_SWAP(head1, head2, type, field) do { \ + struct type *swap_tmp = LIST_FIRST((head1)); \ + LIST_FIRST((head1)) = LIST_FIRST((head2)); \ + LIST_FIRST((head2)) = swap_tmp; \ + if ((swap_tmp = LIST_FIRST((head1))) != NULL) \ + swap_tmp->field.le_prev = &LIST_FIRST((head1)); \ + if ((swap_tmp = LIST_FIRST((head2))) != NULL) \ + swap_tmp->field.le_prev = &LIST_FIRST((head2)); \ +} while (0) + +/* + * Tail queue declarations. + */ +#define TAILQ_HEAD(name, type) \ +struct name { \ + struct type *tqh_first; /* first element */ \ + struct type **tqh_last; /* addr of last next element */ \ + TRACEBUF \ +} + +#define TAILQ_HEAD_INITIALIZER(head) \ + { NULL, &(head).tqh_first, TRACEBUF_INITIALIZER } + +#define TAILQ_ENTRY(type) \ +struct { \ + struct type *tqe_next; /* next element */ \ + struct type **tqe_prev; /* address of previous next element */ \ + TRACEBUF \ +} + +/* + * Tail queue functions. + */ +#if (defined(_KERNEL) && defined(INVARIANTS)) +#define QMD_TAILQ_CHECK_HEAD(head, field) do { \ + if (!TAILQ_EMPTY(head) && \ + TAILQ_FIRST((head))->field.tqe_prev != \ + &TAILQ_FIRST((head))) \ + panic("Bad tailq head %p first->prev != head", (head)); \ +} while (0) + +#define QMD_TAILQ_CHECK_TAIL(head, field) do { \ + if (*(head)->tqh_last != NULL) \ + panic("Bad tailq NEXT(%p->tqh_last) != NULL", (head)); \ +} while (0) + +#define QMD_TAILQ_CHECK_NEXT(elm, field) do { \ + if (TAILQ_NEXT((elm), field) != NULL && \ + TAILQ_NEXT((elm), field)->field.tqe_prev != \ + &((elm)->field.tqe_next)) \ + panic("Bad link elm %p next->prev != elm", (elm)); \ +} while (0) + +#define QMD_TAILQ_CHECK_PREV(elm, field) do { \ + if (*(elm)->field.tqe_prev != (elm)) \ + panic("Bad link elm %p prev->next != elm", (elm)); \ +} while (0) +#else +#define QMD_TAILQ_CHECK_HEAD(head, field) +#define QMD_TAILQ_CHECK_TAIL(head, headname) +#define QMD_TAILQ_CHECK_NEXT(elm, field) +#define QMD_TAILQ_CHECK_PREV(elm, field) +#endif /* (_KERNEL && INVARIANTS) */ + +#define TAILQ_CONCAT(head1, head2, field) do { \ + if (!TAILQ_EMPTY(head2)) { \ + *(head1)->tqh_last = (head2)->tqh_first; \ + (head2)->tqh_first->field.tqe_prev = (head1)->tqh_last; \ + (head1)->tqh_last = (head2)->tqh_last; \ + TAILQ_INIT((head2)); \ + QMD_TRACE_HEAD(head1); \ + QMD_TRACE_HEAD(head2); \ + } \ +} while (0) + +#define TAILQ_EMPTY(head) ((head)->tqh_first == NULL) + +#define TAILQ_FIRST(head) ((head)->tqh_first) + +#define TAILQ_FOREACH(var, head, field) \ + for ((var) = TAILQ_FIRST((head)); \ + (var); \ + (var) = TAILQ_NEXT((var), field)) + +#define TAILQ_FOREACH_SAFE(var, head, field, tvar) \ + for ((var) = TAILQ_FIRST((head)); \ + (var) && ((tvar) = TAILQ_NEXT((var), field), 1); \ + (var) = (tvar)) + +#define TAILQ_FOREACH_REVERSE(var, head, headname, field) \ + for ((var) = TAILQ_LAST((head), headname); \ + (var); \ + (var) = TAILQ_PREV((var), headname, field)) + +#define TAILQ_FOREACH_REVERSE_SAFE(var, head, headname, field, tvar) \ + for ((var) = TAILQ_LAST((head), headname); \ + (var) && ((tvar) = TAILQ_PREV((var), headname, field), 1); \ + (var) = (tvar)) + +#define TAILQ_INIT(head) do { \ + TAILQ_FIRST((head)) = NULL; \ + (head)->tqh_last = &TAILQ_FIRST((head)); \ + QMD_TRACE_HEAD(head); \ +} while (0) + +#define TAILQ_INSERT_AFTER(head, listelm, elm, field) do { \ + QMD_TAILQ_CHECK_NEXT(listelm, field); \ + if ((TAILQ_NEXT((elm), field) = TAILQ_NEXT((listelm), field)) != NULL)\ + TAILQ_NEXT((elm), field)->field.tqe_prev = \ + &TAILQ_NEXT((elm), field); \ + else { \ + (head)->tqh_last = &TAILQ_NEXT((elm), field); \ + QMD_TRACE_HEAD(head); \ + } \ + TAILQ_NEXT((listelm), field) = (elm); \ + (elm)->field.tqe_prev = &TAILQ_NEXT((listelm), field); \ + QMD_TRACE_ELEM(&(elm)->field); \ + QMD_TRACE_ELEM(&listelm->field); \ +} while (0) + +#define TAILQ_INSERT_BEFORE(listelm, elm, field) do { \ + QMD_TAILQ_CHECK_PREV(listelm, field); \ + (elm)->field.tqe_prev = (listelm)->field.tqe_prev; \ + TAILQ_NEXT((elm), field) = (listelm); \ + *(listelm)->field.tqe_prev = (elm); \ + (listelm)->field.tqe_prev = &TAILQ_NEXT((elm), field); \ + QMD_TRACE_ELEM(&(elm)->field); \ + QMD_TRACE_ELEM(&listelm->field); \ +} while (0) + +#define TAILQ_INSERT_HEAD(head, elm, field) do { \ + QMD_TAILQ_CHECK_HEAD(head, field); \ + if ((TAILQ_NEXT((elm), field) = TAILQ_FIRST((head))) != NULL) \ + TAILQ_FIRST((head))->field.tqe_prev = \ + &TAILQ_NEXT((elm), field); \ + else \ + (head)->tqh_last = &TAILQ_NEXT((elm), field); \ + TAILQ_FIRST((head)) = (elm); \ + (elm)->field.tqe_prev = &TAILQ_FIRST((head)); \ + QMD_TRACE_HEAD(head); \ + QMD_TRACE_ELEM(&(elm)->field); \ +} while (0) + +#define TAILQ_INSERT_TAIL(head, elm, field) do { \ + QMD_TAILQ_CHECK_TAIL(head, field); \ + TAILQ_NEXT((elm), field) = NULL; \ + (elm)->field.tqe_prev = (head)->tqh_last; \ + *(head)->tqh_last = (elm); \ + (head)->tqh_last = &TAILQ_NEXT((elm), field); \ + QMD_TRACE_HEAD(head); \ + QMD_TRACE_ELEM(&(elm)->field); \ +} while (0) + +#define TAILQ_LAST(head, headname) \ + (*(((struct headname *)((head)->tqh_last))->tqh_last)) + +#define TAILQ_NEXT(elm, field) ((elm)->field.tqe_next) + +#define TAILQ_PREV(elm, headname, field) \ + (*(((struct headname *)((elm)->field.tqe_prev))->tqh_last)) + +#define TAILQ_REMOVE(head, elm, field) do { \ + QMD_SAVELINK(oldnext, (elm)->field.tqe_next); \ + QMD_SAVELINK(oldprev, (elm)->field.tqe_prev); \ + QMD_TAILQ_CHECK_NEXT(elm, field); \ + QMD_TAILQ_CHECK_PREV(elm, field); \ + if ((TAILQ_NEXT((elm), field)) != NULL) \ + TAILQ_NEXT((elm), field)->field.tqe_prev = \ + (elm)->field.tqe_prev; \ + else { \ + (head)->tqh_last = (elm)->field.tqe_prev; \ + QMD_TRACE_HEAD(head); \ + } \ + *(elm)->field.tqe_prev = TAILQ_NEXT((elm), field); \ + TRASHIT(*oldnext); \ + TRASHIT(*oldprev); \ + QMD_TRACE_ELEM(&(elm)->field); \ +} while (0) + +#define TAILQ_SWAP(head1, head2, type, field) do { \ + struct type *swap_first = (head1)->tqh_first; \ + struct type **swap_last = (head1)->tqh_last; \ + (head1)->tqh_first = (head2)->tqh_first; \ + (head1)->tqh_last = (head2)->tqh_last; \ + (head2)->tqh_first = swap_first; \ + (head2)->tqh_last = swap_last; \ + if ((swap_first = (head1)->tqh_first) != NULL) \ + swap_first->field.tqe_prev = &(head1)->tqh_first; \ + else \ + (head1)->tqh_last = &(head1)->tqh_first; \ + if ((swap_first = (head2)->tqh_first) != NULL) \ + swap_first->field.tqe_prev = &(head2)->tqh_first; \ + else \ + (head2)->tqh_last = &(head2)->tqh_first; \ +} while (0) + +#ifdef _KERNEL + +/* + * XXX insque() and remque() are an old way of handling certain queues. + * They bogusly assumes that all queue heads look alike. + */ + +struct quehead { + struct quehead *qh_link; + struct quehead *qh_rlink; +}; + +#ifdef __GNUC__ + +static __inline void +insque(void *a, void *b) +{ + struct quehead *element = (struct quehead *)a, + *head = (struct quehead *)b; + + element->qh_link = head->qh_link; + element->qh_rlink = head; + head->qh_link = element; + element->qh_link->qh_rlink = element; +} + +static __inline void +remque(void *a) +{ + struct quehead *element = (struct quehead *)a; + + element->qh_link->qh_rlink = element->qh_rlink; + element->qh_rlink->qh_link = element->qh_link; + element->qh_rlink = 0; +} + +#else /* !__GNUC__ */ + +void insque(void *a, void *b); +void remque(void *a); + +#endif /* __GNUC__ */ + +#endif /* _KERNEL */ + +#endif /* !_SYS_QUEUE_H_ */ diff --git a/components/newlib/include/sys/reent.h b/components/newlib/include/sys/reent.h new file mode 100644 index 0000000000..bb52ae65f1 --- /dev/null +++ b/components/newlib/include/sys/reent.h @@ -0,0 +1,793 @@ +/* This header file provides the reentrancy. */ + +/* WARNING: All identifiers here must begin with an underscore. This file is + included by stdio.h and others and we therefore must only use identifiers + in the namespace allotted to us. */ + +#ifndef _SYS_REENT_H_ +#ifdef __cplusplus +extern "C" { +#endif +#define _SYS_REENT_H_ + +#include <_ansi.h> +#include +#include + +#define _NULL 0 + +#ifndef __Long +#if __LONG_MAX__ == 2147483647L +#define __Long long +typedef unsigned __Long __ULong; +#elif __INT_MAX__ == 2147483647 +#define __Long int +typedef unsigned __Long __ULong; +#endif +#endif + +#if !defined( __Long) +#include +#endif + +#ifndef __Long +#define __Long __int32_t +typedef __uint32_t __ULong; +#endif + +struct _reent; + +/* + * If _REENT_SMALL is defined, we make struct _reent as small as possible, + * by having nearly everything possible allocated at first use. + */ + +struct _Bigint +{ + struct _Bigint *_next; + int _k, _maxwds, _sign, _wds; + __ULong _x[1]; +}; + +/* needed by reentrant structure */ +struct __tm +{ + int __tm_sec; + int __tm_min; + int __tm_hour; + int __tm_mday; + int __tm_mon; + int __tm_year; + int __tm_wday; + int __tm_yday; + int __tm_isdst; +}; + +/* + * atexit() support. + */ + +#define _ATEXIT_SIZE 32 /* must be at least 32 to guarantee ANSI conformance */ + +struct _on_exit_args { + void * _fnargs[_ATEXIT_SIZE]; /* user fn args */ + void * _dso_handle[_ATEXIT_SIZE]; + /* Bitmask is set if user function takes arguments. */ + __ULong _fntypes; /* type of exit routine - + Must have at least _ATEXIT_SIZE bits */ + /* Bitmask is set if function was registered via __cxa_atexit. */ + __ULong _is_cxa; +}; + +#ifdef _REENT_SMALL +struct _atexit { + struct _atexit *_next; /* next in list */ + int _ind; /* next index in this table */ + void (*_fns[_ATEXIT_SIZE])(void); /* the table itself */ + struct _on_exit_args * _on_exit_args_ptr; +}; +# define _ATEXIT_INIT {_NULL, 0, {_NULL}, _NULL} +#else +struct _atexit { + struct _atexit *_next; /* next in list */ + int _ind; /* next index in this table */ + /* Some entries may already have been called, and will be NULL. */ + void (*_fns[_ATEXIT_SIZE])(void); /* the table itself */ + struct _on_exit_args _on_exit_args; +}; +# define _ATEXIT_INIT {_NULL, 0, {_NULL}, {{_NULL}, {_NULL}, 0, 0}} +#endif + +#ifdef _REENT_GLOBAL_ATEXIT +# define _REENT_INIT_ATEXIT +#else +# define _REENT_INIT_ATEXIT \ + _NULL, _ATEXIT_INIT, +#endif + +/* + * Stdio buffers. + * + * This and __FILE are defined here because we need them for struct _reent, + * but we don't want stdio.h included when stdlib.h is. + */ + +struct __sbuf { + unsigned char *_base; + int _size; +}; + +/* + * Stdio state variables. + * + * The following always hold: + * + * if (_flags&(__SLBF|__SWR)) == (__SLBF|__SWR), + * _lbfsize is -_bf._size, else _lbfsize is 0 + * if _flags&__SRD, _w is 0 + * if _flags&__SWR, _r is 0 + * + * This ensures that the getc and putc macros (or inline functions) never + * try to write or read from a file that is in `read' or `write' mode. + * (Moreover, they can, and do, automatically switch from read mode to + * write mode, and back, on "r+" and "w+" files.) + * + * _lbfsize is used only to make the inline line-buffered output stream + * code as compact as possible. + * + * _ub, _up, and _ur are used when ungetc() pushes back more characters + * than fit in the current _bf, or when ungetc() pushes back a character + * that does not match the previous one in _bf. When this happens, + * _ub._base becomes non-nil (i.e., a stream has ungetc() data iff + * _ub._base!=NULL) and _up and _ur save the current values of _p and _r. + */ + +#ifdef _REENT_SMALL +/* + * struct __sFILE_fake is the start of a struct __sFILE, with only the + * minimal fields allocated. In __sinit() we really allocate the 3 + * standard streams, etc., and point away from this fake. + */ +struct __sFILE_fake { + unsigned char *_p; /* current position in (some) buffer */ + int _r; /* read space left for getc() */ + int _w; /* write space left for putc() */ + short _flags; /* flags, below; this FILE is free if 0 */ + short _file; /* fileno, if Unix descriptor, else -1 */ + struct __sbuf _bf; /* the buffer (at least 1 byte, if !NULL) */ + int _lbfsize; /* 0 or -_bf._size, for inline putc */ + + struct _reent *_data; +}; + +/* Following is needed both in libc/stdio and libc/stdlib so we put it + * here instead of libc/stdio/local.h where it was previously. */ + +extern _VOID _EXFUN(__sinit,(struct _reent *)); + +# define _REENT_SMALL_CHECK_INIT(ptr) \ + do \ + { \ + if ((ptr) && !(ptr)->__sdidinit) \ + __sinit (ptr); \ + } \ + while (0) +#else +# define _REENT_SMALL_CHECK_INIT(ptr) /* nothing */ +#endif + +struct __sFILE { + unsigned char *_p; /* current position in (some) buffer */ + int _r; /* read space left for getc() */ + int _w; /* write space left for putc() */ + short _flags; /* flags, below; this FILE is free if 0 */ + short _file; /* fileno, if Unix descriptor, else -1 */ + struct __sbuf _bf; /* the buffer (at least 1 byte, if !NULL) */ + int _lbfsize; /* 0 or -_bf._size, for inline putc */ + +#ifdef _REENT_SMALL + struct _reent *_data; +#endif + + /* operations */ + _PTR _cookie; /* cookie passed to io functions */ + + _READ_WRITE_RETURN_TYPE _EXFNPTR(_read, (struct _reent *, _PTR, + char *, _READ_WRITE_BUFSIZE_TYPE)); + _READ_WRITE_RETURN_TYPE _EXFNPTR(_write, (struct _reent *, _PTR, + const char *, + _READ_WRITE_BUFSIZE_TYPE)); + _fpos_t _EXFNPTR(_seek, (struct _reent *, _PTR, _fpos_t, int)); + int _EXFNPTR(_close, (struct _reent *, _PTR)); + + /* separate buffer for long sequences of ungetc() */ + struct __sbuf _ub; /* ungetc buffer */ + unsigned char *_up; /* saved _p when _p is doing ungetc data */ + int _ur; /* saved _r when _r is counting ungetc data */ + + /* tricks to meet minimum requirements even when malloc() fails */ + unsigned char _ubuf[3]; /* guarantee an ungetc() buffer */ + unsigned char _nbuf[1]; /* guarantee a getc() buffer */ + + /* separate buffer for fgetline() when line crosses buffer boundary */ + struct __sbuf _lb; /* buffer for fgetline() */ + + /* Unix stdio files get aligned to block boundaries on fseek() */ + int _blksize; /* stat.st_blksize (may be != _bf._size) */ + _off_t _offset; /* current lseek offset */ + +#ifndef _REENT_SMALL + struct _reent *_data; /* Here for binary compatibility? Remove? */ +#endif + +#ifndef __SINGLE_THREAD__ + _flock_t _lock; /* for thread-safety locking */ +#endif + _mbstate_t _mbstate; /* for wide char stdio functions. */ + int _flags2; /* for future use */ +}; + +#ifdef __CUSTOM_FILE_IO__ + +/* Get custom _FILE definition. */ +#include + +#else /* !__CUSTOM_FILE_IO__ */ +#ifdef __LARGE64_FILES +struct __sFILE64 { + unsigned char *_p; /* current position in (some) buffer */ + int _r; /* read space left for getc() */ + int _w; /* write space left for putc() */ + short _flags; /* flags, below; this FILE is free if 0 */ + short _file; /* fileno, if Unix descriptor, else -1 */ + struct __sbuf _bf; /* the buffer (at least 1 byte, if !NULL) */ + int _lbfsize; /* 0 or -_bf._size, for inline putc */ + + struct _reent *_data; + + /* operations */ + _PTR _cookie; /* cookie passed to io functions */ + + _READ_WRITE_RETURN_TYPE _EXFNPTR(_read, (struct _reent *, _PTR, + char *, _READ_WRITE_BUFSIZE_TYPE)); + _READ_WRITE_RETURN_TYPE _EXFNPTR(_write, (struct _reent *, _PTR, + const char *, + _READ_WRITE_BUFSIZE_TYPE)); + _fpos_t _EXFNPTR(_seek, (struct _reent *, _PTR, _fpos_t, int)); + int _EXFNPTR(_close, (struct _reent *, _PTR)); + + /* separate buffer for long sequences of ungetc() */ + struct __sbuf _ub; /* ungetc buffer */ + unsigned char *_up; /* saved _p when _p is doing ungetc data */ + int _ur; /* saved _r when _r is counting ungetc data */ + + /* tricks to meet minimum requirements even when malloc() fails */ + unsigned char _ubuf[3]; /* guarantee an ungetc() buffer */ + unsigned char _nbuf[1]; /* guarantee a getc() buffer */ + + /* separate buffer for fgetline() when line crosses buffer boundary */ + struct __sbuf _lb; /* buffer for fgetline() */ + + /* Unix stdio files get aligned to block boundaries on fseek() */ + int _blksize; /* stat.st_blksize (may be != _bf._size) */ + int _flags2; /* for future use */ + + _off64_t _offset; /* current lseek offset */ + _fpos64_t _EXFNPTR(_seek64, (struct _reent *, _PTR, _fpos64_t, int)); + +#ifndef __SINGLE_THREAD__ + _flock_t _lock; /* for thread-safety locking */ +#endif + _mbstate_t _mbstate; /* for wide char stdio functions. */ +}; +typedef struct __sFILE64 __FILE; +#else +typedef struct __sFILE __FILE; +#endif /* __LARGE64_FILES */ +#endif /* !__CUSTOM_FILE_IO__ */ + +struct _glue +{ + struct _glue *_next; + int _niobs; + __FILE *_iobs; +}; + +/* + * rand48 family support + * + * Copyright (c) 1993 Martin Birgmeier + * All rights reserved. + * + * You may redistribute unmodified or modified versions of this source + * code provided that the above copyright notice and this and the + * following conditions are retained. + * + * This software is provided ``as is'', and comes with no warranties + * of any kind. I shall in no event be liable for anything that happens + * to anyone/anything when using this software. + */ +#define _RAND48_SEED_0 (0x330e) +#define _RAND48_SEED_1 (0xabcd) +#define _RAND48_SEED_2 (0x1234) +#define _RAND48_MULT_0 (0xe66d) +#define _RAND48_MULT_1 (0xdeec) +#define _RAND48_MULT_2 (0x0005) +#define _RAND48_ADD (0x000b) +struct _rand48 { + unsigned short _seed[3]; + unsigned short _mult[3]; + unsigned short _add; +#ifdef _REENT_SMALL + /* Put this in here as well, for good luck. */ + __extension__ unsigned long long _rand_next; +#endif +}; + +/* How big the some arrays are. */ +#define _REENT_EMERGENCY_SIZE 25 +#define _REENT_ASCTIME_SIZE 26 +#define _REENT_SIGNAL_SIZE 24 + +/* + * struct _reent + * + * This structure contains *all* globals needed by the library. + * It's raison d'etre is to facilitate threads by making all library routines + * reentrant. IE: All state information is contained here. + */ + +#ifdef _REENT_SMALL + +struct _mprec +{ + /* used by mprec routines */ + struct _Bigint *_result; + int _result_k; + struct _Bigint *_p5s; + struct _Bigint **_freelist; +}; + + +struct _misc_reent +{ + /* miscellaneous reentrant data */ + char *_strtok_last; + _mbstate_t _mblen_state; + _mbstate_t _wctomb_state; + _mbstate_t _mbtowc_state; + char _l64a_buf[8]; + int _getdate_err; + _mbstate_t _mbrlen_state; + _mbstate_t _mbrtowc_state; + _mbstate_t _mbsrtowcs_state; + _mbstate_t _wcrtomb_state; + _mbstate_t _wcsrtombs_state; +}; + +/* This version of _reent is laid out with "int"s in pairs, to help + * ports with 16-bit int's but 32-bit pointers, align nicely. */ +struct _reent +{ + /* As an exception to the above put _errno first for binary + compatibility with non _REENT_SMALL targets. */ + int _errno; /* local copy of errno */ + + /* FILE is a big struct and may change over time. To try to achieve binary + compatibility with future versions, put stdin,stdout,stderr here. + These are pointers into member __sf defined below. */ + __FILE *_stdin, *_stdout, *_stderr; /* XXX */ + + int _inc; /* used by tmpnam */ + + char *_emergency; + + int __sdidinit; /* 1 means stdio has been init'd */ + + int _current_category; /* unused */ + _CONST char *_current_locale; /* unused */ + + struct _mprec *_mp; + + void _EXFNPTR(__cleanup, (struct _reent *)); + + int _gamma_signgam; + + /* used by some fp conversion routines */ + int _cvtlen; /* should be size_t */ + char *_cvtbuf; + + struct _rand48 *_r48; + struct __tm *_localtime_buf; + char *_asctime_buf; + + /* signal info */ + void (**(_sig_func))(int); + +# ifndef _REENT_GLOBAL_ATEXIT + /* atexit stuff */ + struct _atexit *_atexit; + struct _atexit _atexit0; +# endif + + struct _glue __sglue; /* root of glue chain */ + __FILE *__sf; /* file descriptors */ + struct _misc_reent *_misc; /* strtok, multibyte states */ + char *_signal_buf; /* strsignal */ +}; + +extern const struct __sFILE_fake __sf_fake_stdin; +extern const struct __sFILE_fake __sf_fake_stdout; +extern const struct __sFILE_fake __sf_fake_stderr; + +# define _REENT_INIT(var) \ + { 0, \ + (__FILE *)&__sf_fake_stdin, \ + (__FILE *)&__sf_fake_stdout, \ + (__FILE *)&__sf_fake_stderr, \ + 0, \ + _NULL, \ + 0, \ + 0, \ + "C", \ + _NULL, \ + _NULL, \ + 0, \ + 0, \ + _NULL, \ + _NULL, \ + _NULL, \ + _NULL, \ + _NULL, \ + _REENT_INIT_ATEXIT \ + {_NULL, 0, _NULL}, \ + _NULL, \ + _NULL, \ + _NULL \ + } + +#define _REENT_INIT_PTR(var) \ + { memset((var), 0, sizeof(*(var))); \ + (var)->_stdin = (__FILE *)&__sf_fake_stdin; \ + (var)->_stdout = (__FILE *)&__sf_fake_stdout; \ + (var)->_stderr = (__FILE *)&__sf_fake_stderr; \ + (var)->_current_locale = "C"; \ + } + +/* Only built the assert() calls if we are built with debugging. */ +#if DEBUG +#include +#define __reent_assert(x) assert(x) +#else +#define __reent_assert(x) ((void)0) +#endif + +#ifdef __CUSTOM_FILE_IO__ +#error Custom FILE I/O and _REENT_SMALL not currently supported. +#endif + +/* Generic _REENT check macro. */ +#define _REENT_CHECK(var, what, type, size, init) do { \ + struct _reent *_r = (var); \ + if (_r->what == NULL) { \ + _r->what = (type)malloc(size); \ + __reent_assert(_r->what); \ + init; \ + } \ +} while (0) + +#define _REENT_CHECK_TM(var) \ + _REENT_CHECK(var, _localtime_buf, struct __tm *, sizeof *((var)->_localtime_buf), \ + /* nothing */) + +#define _REENT_CHECK_ASCTIME_BUF(var) \ + _REENT_CHECK(var, _asctime_buf, char *, _REENT_ASCTIME_SIZE, \ + memset((var)->_asctime_buf, 0, _REENT_ASCTIME_SIZE)) + +/* Handle the dynamically allocated rand48 structure. */ +#define _REENT_INIT_RAND48(var) do { \ + struct _reent *_r = (var); \ + _r->_r48->_seed[0] = _RAND48_SEED_0; \ + _r->_r48->_seed[1] = _RAND48_SEED_1; \ + _r->_r48->_seed[2] = _RAND48_SEED_2; \ + _r->_r48->_mult[0] = _RAND48_MULT_0; \ + _r->_r48->_mult[1] = _RAND48_MULT_1; \ + _r->_r48->_mult[2] = _RAND48_MULT_2; \ + _r->_r48->_add = _RAND48_ADD; \ + _r->_r48->_rand_next = 1; \ +} while (0) +#define _REENT_CHECK_RAND48(var) \ + _REENT_CHECK(var, _r48, struct _rand48 *, sizeof *((var)->_r48), _REENT_INIT_RAND48((var))) + +#define _REENT_INIT_MP(var) do { \ + struct _reent *_r = (var); \ + _r->_mp->_result_k = 0; \ + _r->_mp->_result = _r->_mp->_p5s = _NULL; \ + _r->_mp->_freelist = _NULL; \ +} while (0) +#define _REENT_CHECK_MP(var) \ + _REENT_CHECK(var, _mp, struct _mprec *, sizeof *((var)->_mp), _REENT_INIT_MP(var)) + +#define _REENT_CHECK_EMERGENCY(var) \ + _REENT_CHECK(var, _emergency, char *, _REENT_EMERGENCY_SIZE, /* nothing */) + +#define _REENT_INIT_MISC(var) do { \ + struct _reent *_r = (var); \ + _r->_misc->_strtok_last = _NULL; \ + _r->_misc->_mblen_state.__count = 0; \ + _r->_misc->_mblen_state.__value.__wch = 0; \ + _r->_misc->_wctomb_state.__count = 0; \ + _r->_misc->_wctomb_state.__value.__wch = 0; \ + _r->_misc->_mbtowc_state.__count = 0; \ + _r->_misc->_mbtowc_state.__value.__wch = 0; \ + _r->_misc->_mbrlen_state.__count = 0; \ + _r->_misc->_mbrlen_state.__value.__wch = 0; \ + _r->_misc->_mbrtowc_state.__count = 0; \ + _r->_misc->_mbrtowc_state.__value.__wch = 0; \ + _r->_misc->_mbsrtowcs_state.__count = 0; \ + _r->_misc->_mbsrtowcs_state.__value.__wch = 0; \ + _r->_misc->_wcrtomb_state.__count = 0; \ + _r->_misc->_wcrtomb_state.__value.__wch = 0; \ + _r->_misc->_wcsrtombs_state.__count = 0; \ + _r->_misc->_wcsrtombs_state.__value.__wch = 0; \ + _r->_misc->_l64a_buf[0] = '\0'; \ + _r->_misc->_getdate_err = 0; \ +} while (0) +#define _REENT_CHECK_MISC(var) \ + _REENT_CHECK(var, _misc, struct _misc_reent *, sizeof *((var)->_misc), _REENT_INIT_MISC(var)) + +#define _REENT_CHECK_SIGNAL_BUF(var) \ + _REENT_CHECK(var, _signal_buf, char *, _REENT_SIGNAL_SIZE, /* nothing */) + +#define _REENT_SIGNGAM(ptr) ((ptr)->_gamma_signgam) +#define _REENT_RAND_NEXT(ptr) ((ptr)->_r48->_rand_next) +#define _REENT_RAND48_SEED(ptr) ((ptr)->_r48->_seed) +#define _REENT_RAND48_MULT(ptr) ((ptr)->_r48->_mult) +#define _REENT_RAND48_ADD(ptr) ((ptr)->_r48->_add) +#define _REENT_MP_RESULT(ptr) ((ptr)->_mp->_result) +#define _REENT_MP_RESULT_K(ptr) ((ptr)->_mp->_result_k) +#define _REENT_MP_P5S(ptr) ((ptr)->_mp->_p5s) +#define _REENT_MP_FREELIST(ptr) ((ptr)->_mp->_freelist) +#define _REENT_ASCTIME_BUF(ptr) ((ptr)->_asctime_buf) +#define _REENT_TM(ptr) ((ptr)->_localtime_buf) +#define _REENT_EMERGENCY(ptr) ((ptr)->_emergency) +#define _REENT_STRTOK_LAST(ptr) ((ptr)->_misc->_strtok_last) +#define _REENT_MBLEN_STATE(ptr) ((ptr)->_misc->_mblen_state) +#define _REENT_MBTOWC_STATE(ptr)((ptr)->_misc->_mbtowc_state) +#define _REENT_WCTOMB_STATE(ptr)((ptr)->_misc->_wctomb_state) +#define _REENT_MBRLEN_STATE(ptr) ((ptr)->_misc->_mbrlen_state) +#define _REENT_MBRTOWC_STATE(ptr) ((ptr)->_misc->_mbrtowc_state) +#define _REENT_MBSRTOWCS_STATE(ptr) ((ptr)->_misc->_mbsrtowcs_state) +#define _REENT_WCRTOMB_STATE(ptr) ((ptr)->_misc->_wcrtomb_state) +#define _REENT_WCSRTOMBS_STATE(ptr) ((ptr)->_misc->_wcsrtombs_state) +#define _REENT_L64A_BUF(ptr) ((ptr)->_misc->_l64a_buf) +#define _REENT_GETDATE_ERR_P(ptr) (&((ptr)->_misc->_getdate_err)) +#define _REENT_SIGNAL_BUF(ptr) ((ptr)->_signal_buf) + +#else /* !_REENT_SMALL */ + +struct _reent +{ + int _errno; /* local copy of errno */ + + /* FILE is a big struct and may change over time. To try to achieve binary + compatibility with future versions, put stdin,stdout,stderr here. + These are pointers into member __sf defined below. */ + __FILE *_stdin, *_stdout, *_stderr; + + int _inc; /* used by tmpnam */ + char _emergency[_REENT_EMERGENCY_SIZE]; + + int _current_category; /* used by setlocale */ + _CONST char *_current_locale; + + int __sdidinit; /* 1 means stdio has been init'd */ + + void _EXFNPTR(__cleanup, (struct _reent *)); + + /* used by mprec routines */ + struct _Bigint *_result; + int _result_k; + struct _Bigint *_p5s; + struct _Bigint **_freelist; + + /* used by some fp conversion routines */ + int _cvtlen; /* should be size_t */ + char *_cvtbuf; + + union + { + struct + { + unsigned int _unused_rand; + char * _strtok_last; + char _asctime_buf[_REENT_ASCTIME_SIZE]; + struct __tm _localtime_buf; + int _gamma_signgam; + __extension__ unsigned long long _rand_next; + struct _rand48 _r48; + _mbstate_t _mblen_state; + _mbstate_t _mbtowc_state; + _mbstate_t _wctomb_state; + char _l64a_buf[8]; + char _signal_buf[_REENT_SIGNAL_SIZE]; + int _getdate_err; + _mbstate_t _mbrlen_state; + _mbstate_t _mbrtowc_state; + _mbstate_t _mbsrtowcs_state; + _mbstate_t _wcrtomb_state; + _mbstate_t _wcsrtombs_state; + int _h_errno; + } _reent; + /* Two next two fields were once used by malloc. They are no longer + used. They are used to preserve the space used before so as to + allow addition of new reent fields and keep binary compatibility. */ + struct + { +#define _N_LISTS 30 + unsigned char * _nextf[_N_LISTS]; + unsigned int _nmalloc[_N_LISTS]; + } _unused; + } _new; + +# ifndef _REENT_GLOBAL_ATEXIT + /* atexit stuff */ + struct _atexit *_atexit; /* points to head of LIFO stack */ + struct _atexit _atexit0; /* one guaranteed table, required by ANSI */ +# endif + + /* signal info */ + void (**(_sig_func))(int); + + /* These are here last so that __FILE can grow without changing the offsets + of the above members (on the off chance that future binary compatibility + would be broken otherwise). */ + struct _glue __sglue; /* root of glue chain */ + __FILE __sf[3]; /* first three file descriptors */ +}; + +#define _REENT_INIT(var) \ + { 0, \ + &(var).__sf[0], \ + &(var).__sf[1], \ + &(var).__sf[2], \ + 0, \ + "", \ + 0, \ + "C", \ + 0, \ + _NULL, \ + _NULL, \ + 0, \ + _NULL, \ + _NULL, \ + 0, \ + _NULL, \ + { \ + { \ + 0, \ + _NULL, \ + "", \ + {0, 0, 0, 0, 0, 0, 0, 0, 0}, \ + 0, \ + 1, \ + { \ + {_RAND48_SEED_0, _RAND48_SEED_1, _RAND48_SEED_2}, \ + {_RAND48_MULT_0, _RAND48_MULT_1, _RAND48_MULT_2}, \ + _RAND48_ADD \ + }, \ + {0, {0}}, \ + {0, {0}}, \ + {0, {0}}, \ + "", \ + "", \ + 0, \ + {0, {0}}, \ + {0, {0}}, \ + {0, {0}}, \ + {0, {0}}, \ + {0, {0}} \ + } \ + }, \ + _REENT_INIT_ATEXIT \ + _NULL, \ + {_NULL, 0, _NULL} \ + } + +#define _REENT_INIT_PTR(var) \ + { memset((var), 0, sizeof(*(var))); \ + (var)->_stdin = &(var)->__sf[0]; \ + (var)->_stdout = &(var)->__sf[1]; \ + (var)->_stderr = &(var)->__sf[2]; \ + (var)->_current_locale = "C"; \ + (var)->_new._reent._rand_next = 1; \ + (var)->_new._reent._r48._seed[0] = _RAND48_SEED_0; \ + (var)->_new._reent._r48._seed[1] = _RAND48_SEED_1; \ + (var)->_new._reent._r48._seed[2] = _RAND48_SEED_2; \ + (var)->_new._reent._r48._mult[0] = _RAND48_MULT_0; \ + (var)->_new._reent._r48._mult[1] = _RAND48_MULT_1; \ + (var)->_new._reent._r48._mult[2] = _RAND48_MULT_2; \ + (var)->_new._reent._r48._add = _RAND48_ADD; \ + } + +#define _REENT_CHECK_RAND48(ptr) /* nothing */ +#define _REENT_CHECK_MP(ptr) /* nothing */ +#define _REENT_CHECK_TM(ptr) /* nothing */ +#define _REENT_CHECK_ASCTIME_BUF(ptr) /* nothing */ +#define _REENT_CHECK_EMERGENCY(ptr) /* nothing */ +#define _REENT_CHECK_MISC(ptr) /* nothing */ +#define _REENT_CHECK_SIGNAL_BUF(ptr) /* nothing */ + +#define _REENT_SIGNGAM(ptr) ((ptr)->_new._reent._gamma_signgam) +#define _REENT_RAND_NEXT(ptr) ((ptr)->_new._reent._rand_next) +#define _REENT_RAND48_SEED(ptr) ((ptr)->_new._reent._r48._seed) +#define _REENT_RAND48_MULT(ptr) ((ptr)->_new._reent._r48._mult) +#define _REENT_RAND48_ADD(ptr) ((ptr)->_new._reent._r48._add) +#define _REENT_MP_RESULT(ptr) ((ptr)->_result) +#define _REENT_MP_RESULT_K(ptr) ((ptr)->_result_k) +#define _REENT_MP_P5S(ptr) ((ptr)->_p5s) +#define _REENT_MP_FREELIST(ptr) ((ptr)->_freelist) +#define _REENT_ASCTIME_BUF(ptr) ((ptr)->_new._reent._asctime_buf) +#define _REENT_TM(ptr) (&(ptr)->_new._reent._localtime_buf) +#define _REENT_EMERGENCY(ptr) ((ptr)->_emergency) +#define _REENT_STRTOK_LAST(ptr) ((ptr)->_new._reent._strtok_last) +#define _REENT_MBLEN_STATE(ptr) ((ptr)->_new._reent._mblen_state) +#define _REENT_MBTOWC_STATE(ptr)((ptr)->_new._reent._mbtowc_state) +#define _REENT_WCTOMB_STATE(ptr)((ptr)->_new._reent._wctomb_state) +#define _REENT_MBRLEN_STATE(ptr)((ptr)->_new._reent._mbrlen_state) +#define _REENT_MBRTOWC_STATE(ptr)((ptr)->_new._reent._mbrtowc_state) +#define _REENT_MBSRTOWCS_STATE(ptr)((ptr)->_new._reent._mbsrtowcs_state) +#define _REENT_WCRTOMB_STATE(ptr)((ptr)->_new._reent._wcrtomb_state) +#define _REENT_WCSRTOMBS_STATE(ptr)((ptr)->_new._reent._wcsrtombs_state) +#define _REENT_L64A_BUF(ptr) ((ptr)->_new._reent._l64a_buf) +#define _REENT_SIGNAL_BUF(ptr) ((ptr)->_new._reent._signal_buf) +#define _REENT_GETDATE_ERR_P(ptr) (&((ptr)->_new._reent._getdate_err)) + +#endif /* !_REENT_SMALL */ + +/* This value is used in stdlib/misc.c. reent/reent.c has to know it + as well to make sure the freelist is correctly free'd. Therefore + we define it here, rather than in stdlib/misc.c, as before. */ +#define _Kmax (sizeof (size_t) << 3) + +/* + * All references to struct _reent are via this pointer. + * Internally, newlib routines that need to reference it should use _REENT. + */ + +#ifndef __ATTRIBUTE_IMPURE_PTR__ +#define __ATTRIBUTE_IMPURE_PTR__ +#endif + +#if !defined(__DYNAMIC_REENT__) || defined(__SINGLE_THREAD__) +extern struct _reent *_impure_ptr __ATTRIBUTE_IMPURE_PTR__; +#endif + +extern struct _reent *_global_impure_ptr __ATTRIBUTE_IMPURE_PTR__; + +void _reclaim_reent _PARAMS ((struct _reent *)); + +/* #define _REENT_ONLY define this to get only reentrant routines */ + +#if defined(__DYNAMIC_REENT__) && !defined(__SINGLE_THREAD__) +#ifndef __getreent + struct _reent * _EXFUN(__getreent, (void)); +#endif +# define _REENT (__getreent()) +#else /* __SINGLE_THREAD__ || !__DYNAMIC_REENT__ */ +# define _REENT _impure_ptr +#endif /* __SINGLE_THREAD__ || !__DYNAMIC_REENT__ */ + +#define _GLOBAL_REENT _global_impure_ptr + +#ifdef _REENT_GLOBAL_ATEXIT +extern struct _atexit *_global_atexit; /* points to head of LIFO stack */ +# define _GLOBAL_ATEXIT _global_atexit +#else +# define _GLOBAL_ATEXIT (_GLOBAL_REENT->_atexit) +#endif + +#ifdef __cplusplus +} +#endif +#endif /* _SYS_REENT_H_ */ diff --git a/components/newlib/include/sys/resource.h b/components/newlib/include/sys/resource.h new file mode 100644 index 0000000000..c35ac2a465 --- /dev/null +++ b/components/newlib/include/sys/resource.h @@ -0,0 +1,17 @@ +#ifndef _SYS_RESOURCE_H_ +#define _SYS_RESOURCE_H_ + +#include + +#define RUSAGE_SELF 0 /* calling process */ +#define RUSAGE_CHILDREN -1 /* terminated child processes */ + +struct rusage { + struct timeval ru_utime; /* user time used */ + struct timeval ru_stime; /* system time used */ +}; + +int _EXFUN(getrusage, (int, struct rusage*)); + +#endif + diff --git a/components/newlib/include/sys/sched.h b/components/newlib/include/sys/sched.h new file mode 100644 index 0000000000..58f99d6823 --- /dev/null +++ b/components/newlib/include/sys/sched.h @@ -0,0 +1,67 @@ +/* + * Written by Joel Sherrill . + * + * COPYRIGHT (c) 1989-2010. + * On-Line Applications Research Corporation (OAR). + * + * Permission to use, copy, modify, and distribute this software for any + * purpose without fee is hereby granted, provided that this entire notice + * is included in all copies of any software which is or includes a copy + * or modification of this software. + * + * THIS SOFTWARE IS BEING PROVIDED "AS IS", WITHOUT ANY EXPRESS OR IMPLIED + * WARRANTY. IN PARTICULAR, THE AUTHOR MAKES NO REPRESENTATION + * OR WARRANTY OF ANY KIND CONCERNING THE MERCHANTABILITY OF THIS + * SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR PURPOSE. + * + * $Id$ + */ + + +#ifndef _SYS_SCHED_H_ +#define _SYS_SCHED_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +/* Scheduling Policies */ +/* Open Group Specifications Issue 6 */ +#if defined(__CYGWIN__) +#define SCHED_OTHER 3 +#else +#define SCHED_OTHER 0 +#endif + +#define SCHED_FIFO 1 +#define SCHED_RR 2 + +#if defined(_POSIX_SPORADIC_SERVER) +#define SCHED_SPORADIC 4 +#endif + +/* Scheduling Parameters */ +/* Open Group Specifications Issue 6 */ + +struct sched_param { + int sched_priority; /* Process execution scheduling priority */ + +#if defined(_POSIX_SPORADIC_SERVER) || defined(_POSIX_THREAD_SPORADIC_SERVER) + int sched_ss_low_priority; /* Low scheduling priority for sporadic */ + /* server */ + struct timespec sched_ss_repl_period; + /* Replenishment period for sporadic server */ + struct timespec sched_ss_init_budget; + /* Initial budget for sporadic server */ + int sched_ss_max_repl; /* Maximum pending replenishments for */ + /* sporadic server */ +#endif +}; + +#ifdef __cplusplus +} +#endif + +#endif +/* end of include file */ + diff --git a/components/newlib/include/sys/signal.h b/components/newlib/include/sys/signal.h new file mode 100644 index 0000000000..a29f525c1f --- /dev/null +++ b/components/newlib/include/sys/signal.h @@ -0,0 +1,357 @@ +/* sys/signal.h */ + +#ifndef _SYS_SIGNAL_H +#define _SYS_SIGNAL_H +#ifdef __cplusplus +extern "C" { +#endif + +#include "_ansi.h" +#include +#include + +/* #ifndef __STRICT_ANSI__*/ + +/* Cygwin defines it's own sigset_t in include/cygwin/signal.h */ +#ifndef __CYGWIN__ +typedef unsigned long sigset_t; +#endif + +#if defined(__rtems__) + +#if defined(_POSIX_REALTIME_SIGNALS) + +/* sigev_notify values + NOTE: P1003.1c/D10, p. 34 adds SIGEV_THREAD. */ + +#define SIGEV_NONE 1 /* No asynchronous notification shall be delivered */ + /* when the event of interest occurs. */ +#define SIGEV_SIGNAL 2 /* A queued signal, with an application defined */ + /* value, shall be delivered when the event of */ + /* interest occurs. */ +#define SIGEV_THREAD 3 /* A notification function shall be called to */ + /* perform notification. */ + +/* Signal Generation and Delivery, P1003.1b-1993, p. 63 + NOTE: P1003.1c/D10, p. 34 adds sigev_notify_function and + sigev_notify_attributes to the sigevent structure. */ + +union sigval { + int sival_int; /* Integer signal value */ + void *sival_ptr; /* Pointer signal value */ +}; + +struct sigevent { + int sigev_notify; /* Notification type */ + int sigev_signo; /* Signal number */ + union sigval sigev_value; /* Signal value */ + +#if defined(_POSIX_THREADS) + void (*sigev_notify_function)( union sigval ); + /* Notification function */ + pthread_attr_t *sigev_notify_attributes; /* Notification Attributes */ +#endif +}; + +/* Signal Actions, P1003.1b-1993, p. 64 */ +/* si_code values, p. 66 */ + +#define SI_USER 1 /* Sent by a user. kill(), abort(), etc */ +#define SI_QUEUE 2 /* Sent by sigqueue() */ +#define SI_TIMER 3 /* Sent by expiration of a timer_settime() timer */ +#define SI_ASYNCIO 4 /* Indicates completion of asycnhronous IO */ +#define SI_MESGQ 5 /* Indicates arrival of a message at an empty queue */ + +typedef struct { + int si_signo; /* Signal number */ + int si_code; /* Cause of the signal */ + union sigval si_value; /* Signal value */ +} siginfo_t; +#endif + +/* 3.3.8 Synchronously Accept a Signal, P1003.1b-1993, p. 76 */ + +#define SA_NOCLDSTOP 0x1 /* Do not generate SIGCHLD when children stop */ +#define SA_SIGINFO 0x2 /* Invoke the signal catching function with */ + /* three arguments instead of one. */ +#if __BSD_VISIBLE || __XSI_VISIBLE || __POSIX_VISIBLE >= 200112 +#define SA_ONSTACK 0x4 /* Signal delivery will be on a separate stack. */ +#endif + +/* struct sigaction notes from POSIX: + * + * (1) Routines stored in sa_handler should take a single int as + * their argument although the POSIX standard does not require this. + * This is not longer true since at least POSIX.1-2008 + * (2) The fields sa_handler and sa_sigaction may overlap, and a conforming + * application should not use both simultaneously. + */ + +typedef void (*_sig_func_ptr)(int); + +struct sigaction { + int sa_flags; /* Special flags to affect behavior of signal */ + sigset_t sa_mask; /* Additional set of signals to be blocked */ + /* during execution of signal-catching */ + /* function. */ + union { + _sig_func_ptr _handler; /* SIG_DFL, SIG_IGN, or pointer to a function */ +#if defined(_POSIX_REALTIME_SIGNALS) + void (*_sigaction)( int, siginfo_t *, void * ); +#endif + } _signal_handlers; +}; + +#define sa_handler _signal_handlers._handler +#if defined(_POSIX_REALTIME_SIGNALS) +#define sa_sigaction _signal_handlers._sigaction +#endif + +#if __BSD_VISIBLE || __XSI_VISIBLE || __POSIX_VISIBLE >= 200112 +/* + * Minimum and default signal stack constants. Allow for target overrides + * from . + */ +#ifndef MINSIGSTKSZ +#define MINSIGSTKSZ 2048 +#endif +#ifndef SIGSTKSZ +#define SIGSTKSZ 8192 +#endif + +/* + * Possible values for ss_flags in stack_t below. + */ +#define SS_ONSTACK 0x1 +#define SS_DISABLE 0x2 + +/* + * Structure used in sigaltstack call. + */ +typedef struct sigaltstack { + void *ss_sp; /* Stack base or pointer. */ + int ss_flags; /* Flags. */ + size_t ss_size; /* Stack size. */ +} stack_t; +#endif + +#elif defined(__CYGWIN__) +#include +#else +#define SA_NOCLDSTOP 1 /* only value supported now for sa_flags */ + +typedef void (*_sig_func_ptr)(int); + +struct sigaction +{ + _sig_func_ptr sa_handler; + sigset_t sa_mask; + int sa_flags; +}; +#endif /* defined(__rtems__) */ + +#define SIG_SETMASK 0 /* set mask with sigprocmask() */ +#define SIG_BLOCK 1 /* set of signals to block */ +#define SIG_UNBLOCK 2 /* set of signals to, well, unblock */ + +/* These depend upon the type of sigset_t, which right now + is always a long.. They're in the POSIX namespace, but + are not ANSI. */ +#define sigaddset(what,sig) (*(what) |= (1<<(sig)), 0) +#define sigdelset(what,sig) (*(what) &= ~(1<<(sig)), 0) +#define sigemptyset(what) (*(what) = 0, 0) +#define sigfillset(what) (*(what) = ~(0), 0) +#define sigismember(what,sig) (((*(what)) & (1<<(sig))) != 0) + +int _EXFUN(sigprocmask, (int how, const sigset_t *set, sigset_t *oset)); + +#if defined(_POSIX_THREADS) +int _EXFUN(pthread_sigmask, (int how, const sigset_t *set, sigset_t *oset)); +#endif + +#if defined(__CYGWIN__) || defined(__rtems__) +#undef sigaddset +#undef sigdelset +#undef sigemptyset +#undef sigfillset +#undef sigismember + +#ifdef _COMPILING_NEWLIB +int _EXFUN(_kill, (pid_t, int)); +#endif /* _COMPILING_NEWLIB */ +#endif /* __CYGWIN__ || __rtems__ */ +#if defined(__CYGWIN__) || defined(__rtems__) || defined(__SPU__) +int _EXFUN(kill, (pid_t, int)); +#endif /* __CYGWIN__ || __rtems__ || __SPU__ */ +#if defined(__CYGWIN__) || defined(__rtems__) +int _EXFUN(killpg, (pid_t, int)); +int _EXFUN(sigaction, (int, const struct sigaction *, struct sigaction *)); +int _EXFUN(sigaddset, (sigset_t *, const int)); +int _EXFUN(sigdelset, (sigset_t *, const int)); +int _EXFUN(sigismember, (const sigset_t *, int)); +int _EXFUN(sigfillset, (sigset_t *)); +int _EXFUN(sigemptyset, (sigset_t *)); +int _EXFUN(sigpending, (sigset_t *)); +int _EXFUN(sigsuspend, (const sigset_t *)); +int _EXFUN(sigpause, (int)); + +#ifdef __rtems__ +#if __BSD_VISIBLE || __XSI_VISIBLE || __POSIX_VISIBLE >= 200112 +int _EXFUN(sigaltstack, (const stack_t *__restrict, stack_t *__restrict)); +#endif +#endif + +#if defined(_POSIX_THREADS) +#ifdef __CYGWIN__ +# ifndef _CYGWIN_TYPES_H +# error You need the winsup sources or a cygwin installation to compile the cygwin version of newlib. +# endif +#endif +int _EXFUN(pthread_kill, (pthread_t thread, int sig)); +#endif + +#if defined(_POSIX_REALTIME_SIGNALS) + +/* 3.3.8 Synchronously Accept a Signal, P1003.1b-1993, p. 76 + NOTE: P1003.1c/D10, p. 39 adds sigwait(). */ + +int _EXFUN(sigwaitinfo, (const sigset_t *set, siginfo_t *info)); +int _EXFUN(sigtimedwait, + (const sigset_t *set, siginfo_t *info, const struct timespec *timeout) +); +int _EXFUN(sigwait, (const sigset_t *set, int *sig)); + +/* 3.3.9 Queue a Signal to a Process, P1003.1b-1993, p. 78 */ +int _EXFUN(sigqueue, (pid_t pid, int signo, const union sigval value)); + +#endif /* defined(_POSIX_REALTIME_SIGNALS) */ + +#endif /* defined(__CYGWIN__) || defined(__rtems__) */ + +/* #endif __STRICT_ANSI__ */ + +#if defined(___AM29K__) +/* These all need to be defined for ANSI C, but I don't think they are + meaningful. */ +#define SIGABRT 1 +#define SIGFPE 1 +#define SIGILL 1 +#define SIGINT 1 +#define SIGSEGV 1 +#define SIGTERM 1 +/* These need to be defined for POSIX, and some others do too. */ +#define SIGHUP 1 +#define SIGQUIT 1 +#define NSIG 2 +#elif defined(__GO32__) +#define SIGINT 1 +#define SIGKILL 2 +#define SIGPIPE 3 +#define SIGFPE 4 +#define SIGHUP 5 +#define SIGTERM 6 +#define SIGSEGV 7 +#define SIGTSTP 8 +#define SIGQUIT 9 +#define SIGTRAP 10 +#define SIGILL 11 +#define SIGEMT 12 +#define SIGALRM 13 +#define SIGBUS 14 +#define SIGLOST 15 +#define SIGSTOP 16 +#define SIGABRT 17 +#define SIGUSR1 18 +#define SIGUSR2 19 +#define NSIG 20 +#elif !defined(SIGTRAP) +#define SIGHUP 1 /* hangup */ +#define SIGINT 2 /* interrupt */ +#define SIGQUIT 3 /* quit */ +#define SIGILL 4 /* illegal instruction (not reset when caught) */ +#define SIGTRAP 5 /* trace trap (not reset when caught) */ +#define SIGIOT 6 /* IOT instruction */ +#define SIGABRT 6 /* used by abort, replace SIGIOT in the future */ +#define SIGEMT 7 /* EMT instruction */ +#define SIGFPE 8 /* floating point exception */ +#define SIGKILL 9 /* kill (cannot be caught or ignored) */ +#define SIGBUS 10 /* bus error */ +#define SIGSEGV 11 /* segmentation violation */ +#define SIGSYS 12 /* bad argument to system call */ +#define SIGPIPE 13 /* write on a pipe with no one to read it */ +#define SIGALRM 14 /* alarm clock */ +#define SIGTERM 15 /* software termination signal from kill */ + +#if defined(__rtems__) +#define SIGURG 16 /* urgent condition on IO channel */ +#define SIGSTOP 17 /* sendable stop signal not from tty */ +#define SIGTSTP 18 /* stop signal from tty */ +#define SIGCONT 19 /* continue a stopped process */ +#define SIGCHLD 20 /* to parent on child stop or exit */ +#define SIGCLD 20 /* System V name for SIGCHLD */ +#define SIGTTIN 21 /* to readers pgrp upon background tty read */ +#define SIGTTOU 22 /* like TTIN for output if (tp->t_local<OSTOP) */ +#define SIGIO 23 /* input/output possible signal */ +#define SIGPOLL SIGIO /* System V name for SIGIO */ +#define SIGWINCH 24 /* window changed */ +#define SIGUSR1 25 /* user defined signal 1 */ +#define SIGUSR2 26 /* user defined signal 2 */ + +/* Real-Time Signals Range, P1003.1b-1993, p. 61 + NOTE: By P1003.1b-1993, this should be at least RTSIG_MAX + (which is a minimum of 8) signals. + */ +#define SIGRTMIN 27 +#define SIGRTMAX 31 +#define __SIGFIRSTNOTRT SIGHUP +#define __SIGLASTNOTRT SIGUSR2 + +#define NSIG 32 /* signal 0 implied */ + +#elif defined(__svr4__) +/* svr4 specifics. different signals above 15, and sigaction. */ +#define SIGUSR1 16 +#define SIGUSR2 17 +#define SIGCLD 18 +#define SIGPWR 19 +#define SIGWINCH 20 +#define SIGPOLL 22 /* 20 for x.out binaries!!!! */ +#define SIGSTOP 23 /* sendable stop signal not from tty */ +#define SIGTSTP 24 /* stop signal from tty */ +#define SIGCONT 25 /* continue a stopped process */ +#define SIGTTIN 26 /* to readers pgrp upon background tty read */ +#define SIGTTOU 27 /* like TTIN for output if (tp->t_local<OSTOP) */ +#define NSIG 28 +#else +#define SIGURG 16 /* urgent condition on IO channel */ +#define SIGSTOP 17 /* sendable stop signal not from tty */ +#define SIGTSTP 18 /* stop signal from tty */ +#define SIGCONT 19 /* continue a stopped process */ +#define SIGCHLD 20 /* to parent on child stop or exit */ +#define SIGCLD 20 /* System V name for SIGCHLD */ +#define SIGTTIN 21 /* to readers pgrp upon background tty read */ +#define SIGTTOU 22 /* like TTIN for output if (tp->t_local<OSTOP) */ +#define SIGIO 23 /* input/output possible signal */ +#define SIGPOLL SIGIO /* System V name for SIGIO */ +#define SIGXCPU 24 /* exceeded CPU time limit */ +#define SIGXFSZ 25 /* exceeded file size limit */ +#define SIGVTALRM 26 /* virtual time alarm */ +#define SIGPROF 27 /* profiling time alarm */ +#define SIGWINCH 28 /* window changed */ +#define SIGLOST 29 /* resource lost (eg, record-lock lost) */ +#define SIGUSR1 30 /* user defined signal 1 */ +#define SIGUSR2 31 /* user defined signal 2 */ +#define NSIG 32 /* signal 0 implied */ +#endif +#endif + +#ifdef __cplusplus +} +#endif + +#ifndef _SIGNAL_H_ +/* Some applications take advantage of the fact that + * and are equivalent in glibc. Allow for that here. */ +#include +#endif +#endif /* _SYS_SIGNAL_H */ diff --git a/components/newlib/include/sys/stat.h b/components/newlib/include/sys/stat.h new file mode 100644 index 0000000000..11b9d8080f --- /dev/null +++ b/components/newlib/include/sys/stat.h @@ -0,0 +1,192 @@ +#ifndef _SYS_STAT_H +#define _SYS_STAT_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include <_ansi.h> +#include +#include +#include + +/* dj's stat defines _STAT_H_ */ +#ifndef _STAT_H_ + +/* It is intended that the layout of this structure not change when the + sizes of any of the basic types change (short, int, long) [via a compile + time option]. */ + +#ifdef __CYGWIN__ +#include +#ifdef _COMPILING_NEWLIB +#define stat64 stat +#endif +#else +struct stat +{ + dev_t st_dev; + ino_t st_ino; + mode_t st_mode; + nlink_t st_nlink; + uid_t st_uid; + gid_t st_gid; + dev_t st_rdev; + off_t st_size; +#if defined(__rtems__) + struct timespec st_atim; + struct timespec st_mtim; + struct timespec st_ctim; + blksize_t st_blksize; + blkcnt_t st_blocks; +#else + /* SysV/sco doesn't have the rest... But Solaris, eabi does. */ +#if defined(__svr4__) && !defined(__PPC__) && !defined(__sun__) + time_t st_atime; + time_t st_mtime; + time_t st_ctime; +#else + time_t st_atime; + long st_spare1; + time_t st_mtime; + long st_spare2; + time_t st_ctime; + long st_spare3; + long st_blksize; + long st_blocks; + long st_spare4[2]; +#endif +#endif +}; + +#if defined(__rtems__) +#define st_atime st_atim.tv_sec +#define st_ctime st_ctim.tv_sec +#define st_mtime st_mtim.tv_sec +#endif + +#endif + +#define _IFMT 0170000 /* type of file */ +#define _IFDIR 0040000 /* directory */ +#define _IFCHR 0020000 /* character special */ +#define _IFBLK 0060000 /* block special */ +#define _IFREG 0100000 /* regular */ +#define _IFLNK 0120000 /* symbolic link */ +#define _IFSOCK 0140000 /* socket */ +#define _IFIFO 0010000 /* fifo */ + +#define S_BLKSIZE 1024 /* size of a block */ + +#define S_ISUID 0004000 /* set user id on execution */ +#define S_ISGID 0002000 /* set group id on execution */ +#define S_ISVTX 0001000 /* save swapped text even after use */ +#ifndef _POSIX_SOURCE +#define S_IREAD 0000400 /* read permission, owner */ +#define S_IWRITE 0000200 /* write permission, owner */ +#define S_IEXEC 0000100 /* execute/search permission, owner */ +#define S_ENFMT 0002000 /* enforcement-mode locking */ +#endif /* !_POSIX_SOURCE */ + +#define S_IFMT _IFMT +#define S_IFDIR _IFDIR +#define S_IFCHR _IFCHR +#define S_IFBLK _IFBLK +#define S_IFREG _IFREG +#define S_IFLNK _IFLNK +#define S_IFSOCK _IFSOCK +#define S_IFIFO _IFIFO + +#ifdef _WIN32 +/* The Windows header files define _S_ forms of these, so we do too + for easier portability. */ +#define _S_IFMT _IFMT +#define _S_IFDIR _IFDIR +#define _S_IFCHR _IFCHR +#define _S_IFIFO _IFIFO +#define _S_IFREG _IFREG +#define _S_IREAD 0000400 +#define _S_IWRITE 0000200 +#define _S_IEXEC 0000100 +#endif + +#define S_IRWXU (S_IRUSR | S_IWUSR | S_IXUSR) +#define S_IRUSR 0000400 /* read permission, owner */ +#define S_IWUSR 0000200 /* write permission, owner */ +#define S_IXUSR 0000100/* execute/search permission, owner */ +#define S_IRWXG (S_IRGRP | S_IWGRP | S_IXGRP) +#define S_IRGRP 0000040 /* read permission, group */ +#define S_IWGRP 0000020 /* write permission, grougroup */ +#define S_IXGRP 0000010/* execute/search permission, group */ +#define S_IRWXO (S_IROTH | S_IWOTH | S_IXOTH) +#define S_IROTH 0000004 /* read permission, other */ +#define S_IWOTH 0000002 /* write permission, other */ +#define S_IXOTH 0000001/* execute/search permission, other */ + +#ifndef _POSIX_SOURCE +#define ACCESSPERMS (S_IRWXU | S_IRWXG | S_IRWXO) /* 0777 */ +#define ALLPERMS (S_ISUID | S_ISGID | S_ISVTX | S_IRWXU | S_IRWXG | S_IRWXO) /* 07777 */ +#define DEFFILEMODE (S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH) /* 0666 */ +#endif + +#define S_ISBLK(m) (((m)&_IFMT) == _IFBLK) +#define S_ISCHR(m) (((m)&_IFMT) == _IFCHR) +#define S_ISDIR(m) (((m)&_IFMT) == _IFDIR) +#define S_ISFIFO(m) (((m)&_IFMT) == _IFIFO) +#define S_ISREG(m) (((m)&_IFMT) == _IFREG) +#define S_ISLNK(m) (((m)&_IFMT) == _IFLNK) +#define S_ISSOCK(m) (((m)&_IFMT) == _IFSOCK) + +#if defined(__CYGWIN__) +/* Special tv_nsec values for futimens(2) and utimensat(2). */ +#define UTIME_NOW -2L +#define UTIME_OMIT -1L +#endif + +int _EXFUN(chmod,( const char *__path, mode_t __mode )); +int _EXFUN(fchmod,(int __fd, mode_t __mode)); +int _EXFUN(fstat,( int __fd, struct stat *__sbuf )); +int _EXFUN(mkdir,( const char *_path, mode_t __mode )); +int _EXFUN(mkfifo,( const char *__path, mode_t __mode )); +int _EXFUN(stat,( const char *__restrict __path, struct stat *__restrict __sbuf )); +mode_t _EXFUN(umask,( mode_t __mask )); + +#if defined (__SPU__) || defined(__rtems__) || defined(__CYGWIN__) && !defined(__INSIDE_CYGWIN__) +int _EXFUN(lstat,( const char *__restrict __path, struct stat *__restrict __buf )); +int _EXFUN(mknod,( const char *__path, mode_t __mode, dev_t __dev )); +#endif + +#if (__POSIX_VISIBLE >= 200809 || defined (__CYGWIN__)) && !defined(__INSIDE_CYGWIN__) +int _EXFUN(fchmodat, (int, const char *, mode_t, int)); +#endif +#if (__BSD_VISIBLE || __POSIX_VISIBLE >= 200809 || defined (__CYGWIN__)) && !defined(__INSIDE_CYGWIN__) +int _EXFUN(fstatat, (int, const char *__restrict , struct stat *__restrict, int)); +int _EXFUN(mkdirat, (int, const char *, mode_t)); +int _EXFUN(mkfifoat, (int, const char *, mode_t)); +#endif +#if (__BSD_VISIBLE || __XSI_VISIBLE >= 700 || defined (__CYGWIN__)) && !defined(__INSIDE_CYGWIN__) +int _EXFUN(mknodat, (int, const char *, mode_t, dev_t)); +#endif +#if (__BSD_VISIBLE || __POSIX_VISIBLE >= 200809 || defined (__CYGWIN__)) && !defined(__INSIDE_CYGWIN__) +int _EXFUN(utimensat, (int, const char *, const struct timespec *, int)); +int _EXFUN(futimens, (int, const struct timespec *)); +#endif + +/* Provide prototypes for most of the _ names that are + provided in newlib for some compilers. */ +#ifdef _COMPILING_NEWLIB +int _EXFUN(_fstat,( int __fd, struct stat *__sbuf )); +int _EXFUN(_stat,( const char *__restrict __path, struct stat *__restrict __sbuf )); +int _EXFUN(_mkdir,( const char *_path, mode_t __mode )); +#ifdef __LARGE64_FILES +struct stat64; +int _EXFUN(_stat64,( const char *__restrict __path, struct stat64 *__restrict __sbuf )); +int _EXFUN(_fstat64,( int __fd, struct stat64 *__sbuf )); +#endif +#endif + +#endif /* !_STAT_H_ */ +#ifdef __cplusplus +} +#endif +#endif /* _SYS_STAT_H */ diff --git a/components/newlib/include/sys/stdio.h b/components/newlib/include/sys/stdio.h new file mode 100644 index 0000000000..0918fe157d --- /dev/null +++ b/components/newlib/include/sys/stdio.h @@ -0,0 +1,27 @@ +#ifndef _NEWLIB_STDIO_H +#define _NEWLIB_STDIO_H + +#include +#include + +/* Internal locking macros, used to protect stdio functions. In the + general case, expand to nothing. Use __SSTR flag in FILE _flags to + detect if FILE is private to sprintf/sscanf class of functions; if + set then do nothing as lock is not initialised. */ +#if !defined(_flockfile) +#ifndef __SINGLE_THREAD__ +# define _flockfile(fp) (((fp)->_flags & __SSTR) ? 0 : __lock_acquire_recursive((fp)->_lock)) +#else +# define _flockfile(fp) (_CAST_VOID 0) +#endif +#endif + +#if !defined(_funlockfile) +#ifndef __SINGLE_THREAD__ +# define _funlockfile(fp) (((fp)->_flags & __SSTR) ? 0 : __lock_release_recursive((fp)->_lock)) +#else +# define _funlockfile(fp) (_CAST_VOID 0) +#endif +#endif + +#endif /* _NEWLIB_STDIO_H */ diff --git a/components/newlib/include/sys/string.h b/components/newlib/include/sys/string.h new file mode 100644 index 0000000000..ceedf4be10 --- /dev/null +++ b/components/newlib/include/sys/string.h @@ -0,0 +1,2 @@ +/* This is a dummy used as a placeholder for + systems that need to have a special header file. */ diff --git a/components/newlib/include/sys/syslimits.h b/components/newlib/include/sys/syslimits.h new file mode 100644 index 0000000000..ba9dbd6674 --- /dev/null +++ b/components/newlib/include/sys/syslimits.h @@ -0,0 +1,65 @@ +/* + * Copyright (c) 1988, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)syslimits.h 8.1 (Berkeley) 6/2/93 + * $FreeBSD: src/sys/sys/syslimits.h,v 1.10 2001/06/18 20:24:54 wollman Exp $ + */ + +#ifndef _SYS_SYSLIMITS_H_ +#define _SYS_SYSLIMITS_H_ + +#define ARG_MAX 65536 /* max bytes for an exec function */ +#ifndef CHILD_MAX +#define CHILD_MAX 40 /* max simultaneous processes */ +#endif +#define LINK_MAX 32767 /* max file link count */ +#define MAX_CANON 255 /* max bytes in term canon input line */ +#define MAX_INPUT 255 /* max bytes in terminal input */ +#define NAME_MAX 255 /* max bytes in a file name */ +#define NGROUPS_MAX 16 /* max supplemental group id's */ +#ifndef OPEN_MAX +#define OPEN_MAX 64 /* max open files per process */ +#endif +#define PATH_MAX 1024 /* max bytes in pathname */ +#define PIPE_BUF 512 /* max bytes for atomic pipe writes */ +#define IOV_MAX 1024 /* max elements in i/o vector */ + +#define BC_BASE_MAX 99 /* max ibase/obase values in bc(1) */ +#define BC_DIM_MAX 2048 /* max array elements in bc(1) */ +#define BC_SCALE_MAX 99 /* max scale value in bc(1) */ +#define BC_STRING_MAX 1000 /* max const string length in bc(1) */ +#define COLL_WEIGHTS_MAX 0 /* max weights for order keyword */ +#define EXPR_NEST_MAX 32 /* max expressions nested in expr(1) */ +#define LINE_MAX 2048 /* max bytes in an input line */ +#define RE_DUP_MAX 255 /* max RE's in interval notation */ + +#endif diff --git a/components/newlib/include/sys/time.h b/components/newlib/include/sys/time.h new file mode 100644 index 0000000000..be16497fc5 --- /dev/null +++ b/components/newlib/include/sys/time.h @@ -0,0 +1,91 @@ +/* time.h -- An implementation of the standard Unix file. + Written by Geoffrey Noer + Public domain; no rights reserved. */ + +#ifndef _SYS_TIME_H_ +#define _SYS_TIME_H_ + +#include <_ansi.h> +#include + +#ifdef __cplusplus +extern "C" { +#endif + +#ifndef _TIMEVAL_DEFINED +#define _TIMEVAL_DEFINED +struct timeval { + time_t tv_sec; + suseconds_t tv_usec; +}; + +/* BSD time macros used by RTEMS code */ +#if defined (__rtems__) || defined (__CYGWIN__) + +/* Convenience macros for operations on timevals. + NOTE: `timercmp' does not work for >= or <=. */ +#define timerisset(tvp) ((tvp)->tv_sec || (tvp)->tv_usec) +#define timerclear(tvp) ((tvp)->tv_sec = (tvp)->tv_usec = 0) +#define timercmp(a, b, CMP) \ + (((a)->tv_sec == (b)->tv_sec) ? \ + ((a)->tv_usec CMP (b)->tv_usec) : \ + ((a)->tv_sec CMP (b)->tv_sec)) +#define timeradd(a, b, result) \ + do { \ + (result)->tv_sec = (a)->tv_sec + (b)->tv_sec; \ + (result)->tv_usec = (a)->tv_usec + (b)->tv_usec; \ + if ((result)->tv_usec >= 1000000) \ + { \ + ++(result)->tv_sec; \ + (result)->tv_usec -= 1000000; \ + } \ + } while (0) +#define timersub(a, b, result) \ + do { \ + (result)->tv_sec = (a)->tv_sec - (b)->tv_sec; \ + (result)->tv_usec = (a)->tv_usec - (b)->tv_usec; \ + if ((result)->tv_usec < 0) { \ + --(result)->tv_sec; \ + (result)->tv_usec += 1000000; \ + } \ + } while (0) +#endif /* defined (__rtems__) || defined (__CYGWIN__) */ +#endif /* !_TIMEVAL_DEFINED */ + +struct timezone { + int tz_minuteswest; + int tz_dsttime; +}; + +#ifdef __CYGWIN__ +#include +#endif /* __CYGWIN__ */ + +#define ITIMER_REAL 0 +#define ITIMER_VIRTUAL 1 +#define ITIMER_PROF 2 + +struct itimerval { + struct timeval it_interval; + struct timeval it_value; +}; + +#ifdef _COMPILING_NEWLIB +int _EXFUN(_gettimeofday, (struct timeval *__p, void *__tz)); +#endif + +int _EXFUN(gettimeofday, (struct timeval *__restrict __p, + void *__restrict __tz)); +#if __BSD_VISIBLE +int _EXFUN(settimeofday, (const struct timeval *, const struct timezone *)); +int _EXFUN(adjtime, (const struct timeval *, struct timeval *)); +#endif +int _EXFUN(utimes, (const char *__path, const struct timeval *__tvp)); +int _EXFUN(getitimer, (int __which, struct itimerval *__value)); +int _EXFUN(setitimer, (int __which, const struct itimerval *__restrict __value, + struct itimerval *__restrict __ovalue)); + +#ifdef __cplusplus +} +#endif +#endif /* _SYS_TIME_H_ */ diff --git a/components/newlib/include/sys/timeb.h b/components/newlib/include/sys/timeb.h new file mode 100644 index 0000000000..0a2c3de8bd --- /dev/null +++ b/components/newlib/include/sys/timeb.h @@ -0,0 +1,39 @@ +/* timeb.h -- An implementation of the standard Unix file. + Written by Ian Lance Taylor + Public domain; no rights reserved. + + declares the structure used by the ftime function, as + well as the ftime function itself. Newlib does not provide an + implementation of ftime. */ + +#ifndef _SYS_TIMEB_H + +#ifdef __cplusplus +extern "C" { +#endif + +#define _SYS_TIMEB_H + +#include <_ansi.h> +#include + +#ifndef __time_t_defined +typedef _TIME_T_ time_t; +#define __time_t_defined +#endif + +struct timeb +{ + time_t time; + unsigned short millitm; + short timezone; + short dstflag; +}; + +extern int ftime _PARAMS ((struct timeb *)); + +#ifdef __cplusplus +} +#endif + +#endif /* ! defined (_SYS_TIMEB_H) */ diff --git a/components/newlib/include/sys/times.h b/components/newlib/include/sys/times.h new file mode 100644 index 0000000000..927812cb85 --- /dev/null +++ b/components/newlib/include/sys/times.h @@ -0,0 +1,31 @@ +#ifndef _SYS_TIMES_H +#ifdef __cplusplus +extern "C" { +#endif +#define _SYS_TIMES_H + +#include <_ansi.h> +#include + +#ifndef __clock_t_defined +typedef _CLOCK_T_ clock_t; +#define __clock_t_defined +#endif + +/* Get Process Times, P1003.1b-1993, p. 92 */ +struct tms { + clock_t tms_utime; /* user time */ + clock_t tms_stime; /* system time */ + clock_t tms_cutime; /* user time, children */ + clock_t tms_cstime; /* system time, children */ +}; + +clock_t _EXFUN(times,(struct tms *)); +#ifdef _COMPILING_NEWLIB +clock_t _EXFUN(_times,(struct tms *)); +#endif + +#ifdef __cplusplus +} +#endif +#endif /* !_SYS_TIMES_H */ diff --git a/components/newlib/include/sys/types.h b/components/newlib/include/sys/types.h new file mode 100644 index 0000000000..ed33e0a617 --- /dev/null +++ b/components/newlib/include/sys/types.h @@ -0,0 +1,521 @@ +/* unified sys/types.h: + start with sef's sysvi386 version. + merge go32 version -- a few ifdefs. + h8300hms, h8300xray, and sysvnecv70 disagree on the following types: + + typedef int gid_t; + typedef int uid_t; + typedef int dev_t; + typedef int ino_t; + typedef int mode_t; + typedef int caddr_t; + + however, these aren't "reasonable" values, the sysvi386 ones make far + more sense, and should work sufficiently well (in particular, h8300 + doesn't have a stat, and the necv70 doesn't matter.) -- eichin + */ + +#ifndef _SYS_TYPES_H + +#include <_ansi.h> + +#ifndef __INTTYPES_DEFINED__ +#define __INTTYPES_DEFINED__ + +#include + +#if defined(__rtems__) || defined(__XMK__) +/* + * The following section is RTEMS specific and is needed to more + * closely match the types defined in the BSD sys/types.h. + * This is needed to let the RTEMS/BSD TCP/IP stack compile. + */ + +/* deprecated */ +#if ___int8_t_defined +typedef __uint8_t u_int8_t; +#endif +#if ___int16_t_defined +typedef __uint16_t u_int16_t; +#endif +#if ___int32_t_defined +typedef __uint32_t u_int32_t; +#endif + +#if ___int64_t_defined +typedef __uint64_t u_int64_t; + +/* deprecated */ +typedef __uint64_t u_quad_t; +typedef __int64_t quad_t; +typedef quad_t * qaddr_t; +#endif + +#endif + +#endif /* ! __INTTYPES_DEFINED */ + +#ifndef __need_inttypes + +#define _SYS_TYPES_H +#include + +#ifdef __i386__ +#if defined (GO32) || defined (__MSDOS__) +#define __MS_types__ +#endif +#endif + +# include +# include + +/* To ensure the stat struct's layout doesn't change when sizeof(int), etc. + changes, we assume sizeof short and long never change and have all types + used to define struct stat use them and not int where possible. + Where not possible, _ST_INTxx are used. It would be preferable to not have + such assumptions, but until the extra fluff is necessary, it's avoided. + No 64 bit targets use stat yet. What to do about them is postponed + until necessary. */ +#ifdef __GNUC__ +#define _ST_INT32 __attribute__ ((__mode__ (__SI__))) +#else +#define _ST_INT32 +#endif + +# ifndef _POSIX_SOURCE + +# define physadr physadr_t +# define quad quad_t + +#ifndef _BSDTYPES_DEFINED +/* also defined in mingw/gmon.h and in w32api/winsock[2].h */ +#ifndef __u_char_defined +typedef unsigned char u_char; +#define __u_char_defined +#endif +#ifndef __u_short_defined +typedef unsigned short u_short; +#define __u_short_defined +#endif +#ifndef __u_int_defined +typedef unsigned int u_int; +#define __u_int_defined +#endif +#ifndef __u_long_defined +typedef unsigned long u_long; +#define __u_long_defined +#endif +#define _BSDTYPES_DEFINED +#endif + +typedef unsigned short ushort; /* System V compatibility */ +typedef unsigned int uint; /* System V compatibility */ +typedef unsigned long ulong; /* System V compatibility */ +# endif /*!_POSIX_SOURCE */ + +#ifndef __clock_t_defined +typedef _CLOCK_T_ clock_t; +#define __clock_t_defined +#endif + +#ifndef __time_t_defined +typedef _TIME_T_ time_t; +#define __time_t_defined +#endif + +#ifndef __timespec_defined +#define __timespec_defined +/* Time Value Specification Structures, P1003.1b-1993, p. 261 */ + +struct timespec { + time_t tv_sec; /* Seconds */ + long tv_nsec; /* Nanoseconds */ +}; +#endif + +struct itimerspec { + struct timespec it_interval; /* Timer period */ + struct timespec it_value; /* Timer expiration */ +}; + +#ifndef __daddr_t_defined +typedef long daddr_t; +#define __daddr_t_defined +#endif +#ifndef __caddr_t_defined +typedef char * caddr_t; +#define __caddr_t_defined +#endif + +#ifndef __CYGWIN__ +#if defined(__MS_types__) || defined(__rtems__) || \ + defined(__sparc__) || defined(__SPU__) +typedef unsigned long ino_t; +#else +typedef unsigned short ino_t; +#endif +#endif /*__CYGWIN__*/ + +#ifdef __MS_types__ +typedef unsigned long vm_offset_t; +typedef unsigned long vm_size_t; + +#define __BIT_TYPES_DEFINED__ + +typedef signed char int8_t; +typedef unsigned char u_int8_t; +typedef short int16_t; +typedef unsigned short u_int16_t; +typedef int int32_t; +typedef unsigned int u_int32_t; +typedef long long int64_t; +typedef unsigned long long u_int64_t; +typedef int32_t register_t; +#endif /* __MS_types__ */ + +/* + * All these should be machine specific - right now they are all broken. + * However, for all of Cygnus' embedded targets, we want them to all be + * the same. Otherwise things like sizeof (struct stat) might depend on + * how the file was compiled (e.g. -mint16 vs -mint32, etc.). + */ + +#ifndef __CYGWIN__ /* which defines these types in it's own types.h. */ +typedef _off_t off_t; +typedef __dev_t dev_t; +typedef __uid_t uid_t; +typedef __gid_t gid_t; +#endif + +#if defined(__XMK__) +typedef signed char pid_t; +#else +typedef int pid_t; +#endif + +#if defined(__rtems__) +typedef _mode_t mode_t; +#endif + +#ifndef __CYGWIN__ +typedef long key_t; +#endif +typedef _ssize_t ssize_t; + +#if !defined(__CYGWIN__) && !defined(__rtems__) +#ifdef __MS_types__ +typedef char * addr_t; +typedef int mode_t; +#else +#if defined (__sparc__) && !defined (__sparc_v9__) +#ifdef __svr4__ +typedef unsigned long mode_t; +#else +typedef unsigned short mode_t; +#endif +#else +typedef unsigned int mode_t _ST_INT32; +#endif +#endif /* ! __MS_types__ */ +#endif /*__CYGWIN__*/ + +typedef unsigned short nlink_t; + +/* We don't define fd_set and friends if we are compiling POSIX + source, or if we have included (or may include as indicated + by __USE_W32_SOCKETS) the W32api winsock[2].h header which + defines Windows versions of them. Note that a program which + includes the W32api winsock[2].h header must know what it is doing; + it must not call the cygwin32 select function. +*/ +# if !(defined (_POSIX_SOURCE) || defined (_WINSOCK_H) || defined (_WINSOCKAPI_) || defined (__USE_W32_SOCKETS)) +# define _SYS_TYPES_FD_SET +# define NBBY 8 /* number of bits in a byte */ +/* + * Select uses bit masks of file descriptors in longs. + * These macros manipulate such bit fields (the filesystem macros use chars). + * FD_SETSIZE may be defined by the user, but the default here + * should be >= NOFILE (param.h). + */ +# ifndef FD_SETSIZE +# define FD_SETSIZE 64 +# endif + +typedef long fd_mask; +# define NFDBITS (sizeof (fd_mask) * NBBY) /* bits per mask */ +# ifndef howmany +# define howmany(x,y) (((x)+((y)-1))/(y)) +# endif + +/* We use a macro for fd_set so that including Sockets.h afterwards + can work. */ +typedef struct _types_fd_set { + fd_mask fds_bits[howmany(FD_SETSIZE, NFDBITS)]; +} _types_fd_set; + +#define fd_set _types_fd_set + +# define FD_SET(n, p) ((p)->fds_bits[(n)/NFDBITS] |= (1L << ((n) % NFDBITS))) +# define FD_CLR(n, p) ((p)->fds_bits[(n)/NFDBITS] &= ~(1L << ((n) % NFDBITS))) +# define FD_ISSET(n, p) ((p)->fds_bits[(n)/NFDBITS] & (1L << ((n) % NFDBITS))) +# define FD_ZERO(p) (__extension__ (void)({ \ + size_t __i; \ + char *__tmp = (char *)p; \ + for (__i = 0; __i < sizeof (*(p)); ++__i) \ + *__tmp++ = 0; \ +})) + +# endif /* !(defined (_POSIX_SOURCE) || defined (_WINSOCK_H) || defined (_WINSOCKAPI_) || defined (__USE_W32_SOCKETS)) */ + +#undef __MS_types__ +#undef _ST_INT32 + + +#ifndef __clockid_t_defined +typedef _CLOCKID_T_ clockid_t; +#define __clockid_t_defined +#endif + +#ifndef __timer_t_defined +typedef _TIMER_T_ timer_t; +#define __timer_t_defined +#endif + +typedef unsigned long useconds_t; +typedef long suseconds_t; + +#include + + +/* Cygwin will probably never have full posix compliance due to little things + * like an inability to set the stackaddress. Cygwin is also using void * + * pointers rather than structs to ensure maximum binary compatability with + * previous releases. + * This means that we don't use the types defined here, but rather in + * + */ +#if defined(_POSIX_THREADS) && !defined(__CYGWIN__) + +#include + +/* + * 2.5 Primitive System Data Types, P1003.1c/D10, p. 19. + */ + +#if defined(__XMK__) +typedef unsigned int pthread_t; /* identify a thread */ +#else +typedef __uint32_t pthread_t; /* identify a thread */ +#endif + +/* P1003.1c/D10, p. 118-119 */ +#define PTHREAD_SCOPE_PROCESS 0 +#define PTHREAD_SCOPE_SYSTEM 1 + +/* P1003.1c/D10, p. 111 */ +#define PTHREAD_INHERIT_SCHED 1 /* scheduling policy and associated */ + /* attributes are inherited from */ + /* the calling thread. */ +#define PTHREAD_EXPLICIT_SCHED 2 /* set from provided attribute object */ + +/* P1003.1c/D10, p. 141 */ +#define PTHREAD_CREATE_DETACHED 0 +#define PTHREAD_CREATE_JOINABLE 1 + +#if defined(__rtems__) + #include +#endif + +#if defined(__XMK__) +typedef struct pthread_attr_s { + int contentionscope; + struct sched_param schedparam; + int detachstate; + void *stackaddr; + size_t stacksize; +} pthread_attr_t; + +#define PTHREAD_STACK_MIN 200 + +#else /* !defined(__XMK__) */ +typedef struct { + int is_initialized; + void *stackaddr; + int stacksize; + int contentionscope; + int inheritsched; + int schedpolicy; + struct sched_param schedparam; +#if defined(__rtems__) + size_t guardsize; +#endif + + /* P1003.4b/D8, p. 54 adds cputime_clock_allowed attribute. */ +#if defined(_POSIX_THREAD_CPUTIME) + int cputime_clock_allowed; /* see time.h */ +#endif + int detachstate; +#if defined(__rtems__) + size_t affinitysetsize; + cpu_set_t *affinityset; + cpu_set_t affinitysetpreallocated; +#endif +} pthread_attr_t; + +#endif /* !defined(__XMK__) */ + +#if defined(_POSIX_THREAD_PROCESS_SHARED) +/* NOTE: P1003.1c/D10, p. 81 defines following values for process_shared. */ + +#define PTHREAD_PROCESS_PRIVATE 0 /* visible within only the creating process */ +#define PTHREAD_PROCESS_SHARED 1 /* visible too all processes with access to */ + /* the memory where the resource is */ + /* located */ +#endif + +#if defined(_POSIX_THREAD_PRIO_PROTECT) +/* Mutexes */ + +/* Values for blocking protocol. */ + +#define PTHREAD_PRIO_NONE 0 +#define PTHREAD_PRIO_INHERIT 1 +#define PTHREAD_PRIO_PROTECT 2 +#endif + +#if defined(_UNIX98_THREAD_MUTEX_ATTRIBUTES) + +/* Values for mutex type */ + +/* The following defines are part of the X/Open System Interface (XSI). */ + +/* + * This type of mutex does not detect deadlock. A thread attempting to + * relock this mutex without first unlocking it shall deadlock. Attempting + * to unlock a mutex locked by a different thread results in undefined + * behavior. Attempting to unlock an unlocked mutex results in undefined + * behavior. + */ +#define PTHREAD_MUTEX_NORMAL 0 + +/* + * A thread attempting to relock this mutex without first unlocking + * it shall succeed in locking the mutex. The relocking deadlock which + * can occur with mutexes of type PTHREAD_MUTEX_NORMAL cannot occur with + * this type of mutex. Multiple locks of this mutex shall require the + * same number of unlocks to release the mutex before another thread can + * acquire the mutex. A thread attempting to unlock a mutex which another + * thread has locked shall return with an error. A thread attempting to + * unlock an unlocked mutex shall return with an error. + */ +#define PTHREAD_MUTEX_RECURSIVE 1 + +/* + * This type of mutex provides error checking. A thread attempting + * to relock this mutex without first unlocking it shall return with an + * error. A thread attempting to unlock a mutex which another thread has + * locked shall return with an error. A thread attempting to unlock an + * unlocked mutex shall return with an error. + */ +#define PTHREAD_MUTEX_ERRORCHECK 2 + +/* + * Attempting to recursively lock a mutex of this type results + * in undefined behavior. Attempting to unlock a mutex of this type + * which was not locked by the calling thread results in undefined + * behavior. Attempting to unlock a mutex of this type which is not locked + * results in undefined behavior. An implementation may map this mutex to + * one of the other mutex types. + */ +#define PTHREAD_MUTEX_DEFAULT 3 + +#endif /* !defined(_UNIX98_THREAD_MUTEX_ATTRIBUTES) */ + +#if defined(__XMK__) +typedef unsigned int pthread_mutex_t; /* identify a mutex */ + +typedef struct { + int type; +} pthread_mutexattr_t; + +#else /* !defined(__XMK__) */ +typedef __uint32_t pthread_mutex_t; /* identify a mutex */ + +typedef struct { + int is_initialized; +#if defined(_POSIX_THREAD_PROCESS_SHARED) + int process_shared; /* allow mutex to be shared amongst processes */ +#endif +#if defined(_POSIX_THREAD_PRIO_PROTECT) + int prio_ceiling; + int protocol; +#endif +#if defined(_UNIX98_THREAD_MUTEX_ATTRIBUTES) + int type; +#endif + int recursive; +} pthread_mutexattr_t; +#endif /* !defined(__XMK__) */ + +/* Condition Variables */ + +typedef __uint32_t pthread_cond_t; /* identify a condition variable */ + +typedef struct { + int is_initialized; +#if defined(_POSIX_THREAD_PROCESS_SHARED) + int process_shared; /* allow this to be shared amongst processes */ +#endif +} pthread_condattr_t; /* a condition attribute object */ + +/* Keys */ + +typedef __uint32_t pthread_key_t; /* thread-specific data keys */ + +typedef struct { + int is_initialized; /* is this structure initialized? */ + int init_executed; /* has the initialization routine been run? */ +} pthread_once_t; /* dynamic package initialization */ +#else +#if defined (__CYGWIN__) +#include +#endif +#endif /* defined(_POSIX_THREADS) */ + +/* POSIX Barrier Types */ + +#if defined(_POSIX_BARRIERS) +typedef __uint32_t pthread_barrier_t; /* POSIX Barrier Object */ +typedef struct { + int is_initialized; /* is this structure initialized? */ +#if defined(_POSIX_THREAD_PROCESS_SHARED) + int process_shared; /* allow this to be shared amongst processes */ +#endif +} pthread_barrierattr_t; +#endif /* defined(_POSIX_BARRIERS) */ + +/* POSIX Spin Lock Types */ + +#if !defined (__CYGWIN__) +#if defined(_POSIX_SPIN_LOCKS) +typedef __uint32_t pthread_spinlock_t; /* POSIX Spin Lock Object */ +#endif /* defined(_POSIX_SPIN_LOCKS) */ + +/* POSIX Reader/Writer Lock Types */ + +#if defined(_POSIX_READER_WRITER_LOCKS) +typedef __uint32_t pthread_rwlock_t; /* POSIX RWLock Object */ +typedef struct { + int is_initialized; /* is this structure initialized? */ +#if defined(_POSIX_THREAD_PROCESS_SHARED) + int process_shared; /* allow this to be shared amongst processes */ +#endif +} pthread_rwlockattr_t; +#endif /* defined(_POSIX_READER_WRITER_LOCKS) */ +#endif /* __CYGWIN__ */ + +#endif /* !__need_inttypes */ + +#undef __need_inttypes + +#endif /* _SYS_TYPES_H */ diff --git a/components/newlib/include/sys/unistd.h b/components/newlib/include/sys/unistd.h new file mode 100644 index 0000000000..a741383d06 --- /dev/null +++ b/components/newlib/include/sys/unistd.h @@ -0,0 +1,516 @@ +#ifndef _SYS_UNISTD_H +#define _SYS_UNISTD_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include <_ansi.h> +#define __need_size_t +#define __need_ptrdiff_t +#include +#include +#include +#include + +extern char **environ; + +void _EXFUN(_exit, (int __status ) _ATTRIBUTE ((__noreturn__))); + +int _EXFUN(access,(const char *__path, int __amode )); +unsigned _EXFUN(alarm, (unsigned __secs )); +int _EXFUN(chdir, (const char *__path )); +int _EXFUN(chmod, (const char *__path, mode_t __mode )); +#if !defined(__INSIDE_CYGWIN__) +int _EXFUN(chown, (const char *__path, uid_t __owner, gid_t __group )); +#endif +#if defined(__CYGWIN__) || defined(__rtems__) +int _EXFUN(chroot, (const char *__path )); +#endif +int _EXFUN(close, (int __fildes )); +#if defined(__CYGWIN__) +size_t _EXFUN(confstr, (int __name, char *__buf, size_t __len)); +#endif +char * _EXFUN(ctermid, (char *__s )); +char * _EXFUN(cuserid, (char *__s )); +#if defined(__CYGWIN__) +int _EXFUN(daemon, (int nochdir, int noclose)); +#endif +int _EXFUN(dup, (int __fildes )); +int _EXFUN(dup2, (int __fildes, int __fildes2 )); +#if defined(__CYGWIN__) +int _EXFUN(dup3, (int __fildes, int __fildes2, int flags)); +int _EXFUN(eaccess, (const char *__path, int __mode)); +void _EXFUN(endusershell, (void)); +int _EXFUN(euidaccess, (const char *__path, int __mode)); +#endif +int _EXFUN(execl, (const char *__path, const char *, ... )); +int _EXFUN(execle, (const char *__path, const char *, ... )); +int _EXFUN(execlp, (const char *__file, const char *, ... )); +#if defined(__CYGWIN__) +int _EXFUN(execlpe, (const char *__file, const char *, ... )); +#endif +int _EXFUN(execv, (const char *__path, char * const __argv[] )); +int _EXFUN(execve, (const char *__path, char * const __argv[], char * const __envp[] )); +int _EXFUN(execvp, (const char *__file, char * const __argv[] )); +#if defined(__CYGWIN__) +int _EXFUN(execvpe, (const char *__file, char * const __argv[], char * const __envp[] )); +#endif +#if __POSIX_VISIBLE >= 200809 || __BSD_VISIBLE || defined(__CYGWIN__) +int _EXFUN(faccessat, (int __dirfd, const char *__path, int __mode, int __flags)); +#endif +#if defined(__CYGWIN__) || defined(__rtems__) || defined(__SPU__) +int _EXFUN(fchdir, (int __fildes)); +#endif +int _EXFUN(fchmod, (int __fildes, mode_t __mode )); +#if !defined(__INSIDE_CYGWIN__) +int _EXFUN(fchown, (int __fildes, uid_t __owner, gid_t __group )); +#endif +#if __POSIX_VISIBLE >= 200809 || __BSD_VISIBLE || defined(__CYGWIN__) +int _EXFUN(fchownat, (int __dirfd, const char *__path, uid_t __owner, gid_t __group, int __flags)); +#endif +#if defined(__CYGWIN__) +int _EXFUN(fexecve, (int __fd, char * const __argv[], char * const __envp[] )); +#endif +pid_t _EXFUN(fork, (void )); +long _EXFUN(fpathconf, (int __fd, int __name )); +int _EXFUN(fsync, (int __fd)); +int _EXFUN(fdatasync, (int __fd)); +#if defined(__CYGWIN__) +char * _EXFUN(get_current_dir_name, (void)); +#endif +char * _EXFUN(getcwd, (char *__buf, size_t __size )); +#if defined(__CYGWIN__) +int _EXFUN(getdomainname ,(char *__name, size_t __len)); +#endif +#if !defined(__INSIDE_CYGWIN__) +gid_t _EXFUN(getegid, (void )); +uid_t _EXFUN(geteuid, (void )); +gid_t _EXFUN(getgid, (void )); +#endif +int _EXFUN(getgroups, (int __gidsetsize, gid_t __grouplist[] )); +#if defined(__CYGWIN__) +long _EXFUN(gethostid, (void)); +#endif +char * _EXFUN(getlogin, (void )); +#if defined(_POSIX_THREAD_SAFE_FUNCTIONS) +int _EXFUN(getlogin_r, (char *name, size_t namesize) ); +#endif +char * _EXFUN(getpass, (const char *__prompt)); +int _EXFUN(getpagesize, (void)); +#if defined(__CYGWIN__) +int _EXFUN(getpeereid, (int, uid_t *, gid_t *)); +#endif +pid_t _EXFUN(getpgid, (pid_t)); +pid_t _EXFUN(getpgrp, (void )); +pid_t _EXFUN(getpid, (void )); +pid_t _EXFUN(getppid, (void )); +#if defined(__CYGWIN__) || defined(__rtems__) +pid_t _EXFUN(getsid, (pid_t)); +#endif +#if !defined(__INSIDE_CYGWIN__) +uid_t _EXFUN(getuid, (void )); +#endif +#ifdef __CYGWIN__ +char * _EXFUN(getusershell, (void)); +char * _EXFUN(getwd, (char *__buf )); +int _EXFUN(iruserok, (unsigned long raddr, int superuser, const char *ruser, const char *luser)); +#endif +int _EXFUN(isatty, (int __fildes )); +#if !defined(__INSIDE_CYGWIN__) +int _EXFUN(lchown, (const char *__path, uid_t __owner, gid_t __group )); +#endif +int _EXFUN(link, (const char *__path1, const char *__path2 )); +#if __POSIX_VISIBLE >= 200809 || __BSD_VISIBLE || defined(__CYGWIN__) +int _EXFUN(linkat, (int __dirfd1, const char *__path1, int __dirfd2, const char *__path2, int __flags )); +#endif +int _EXFUN(nice, (int __nice_value )); +#if !defined(__INSIDE_CYGWIN__) +off_t _EXFUN(lseek, (int __fildes, off_t __offset, int __whence )); +#endif +#if defined(__SPU__) || defined(__CYGWIN__) +#define F_ULOCK 0 +#define F_LOCK 1 +#define F_TLOCK 2 +#define F_TEST 3 +int _EXFUN(lockf, (int __fd, int __cmd, off_t __len)); +#endif +long _EXFUN(pathconf, (const char *__path, int __name )); +int _EXFUN(pause, (void )); +#ifdef __CYGWIN__ +int _EXFUN(pthread_atfork, (void (*)(void), void (*)(void), void (*)(void))); +#endif +int _EXFUN(pipe, (int __fildes[2] )); +#ifdef __CYGWIN__ +int _EXFUN(pipe2, (int __fildes[2], int flags)); +#endif +ssize_t _EXFUN(pread, (int __fd, void *__buf, size_t __nbytes, off_t __offset)); +ssize_t _EXFUN(pwrite, (int __fd, const void *__buf, size_t __nbytes, off_t __offset)); +_READ_WRITE_RETURN_TYPE _EXFUN(read, (int __fd, void *__buf, size_t __nbyte )); +#if defined(__CYGWIN__) +int _EXFUN(rresvport, (int *__alport)); +int _EXFUN(revoke, (char *__path)); +#endif +int _EXFUN(rmdir, (const char *__path )); +#if defined(__CYGWIN__) +int _EXFUN(ruserok, (const char *rhost, int superuser, const char *ruser, const char *luser)); +#endif +void * _EXFUN(sbrk, (ptrdiff_t __incr)); +#if !defined(__INSIDE_CYGWIN__) +#if defined(__CYGWIN__) || defined(__rtems__) +int _EXFUN(setegid, (gid_t __gid )); +int _EXFUN(seteuid, (uid_t __uid )); +#endif +int _EXFUN(setgid, (gid_t __gid )); +#endif +#if defined(__CYGWIN__) +int _EXFUN(setgroups, (int ngroups, const gid_t *grouplist )); +#endif +#if __BSD_VISIBLE || (defined(_XOPEN_SOURCE) && __XSI_VISIBLE < 500) +int _EXFUN(sethostname, (const char *, size_t)); +#endif +int _EXFUN(setpgid, (pid_t __pid, pid_t __pgid )); +int _EXFUN(setpgrp, (void )); +#if defined(__CYGWIN__) && !defined(__INSIDE_CYGWIN__) +int _EXFUN(setregid, (gid_t __rgid, gid_t __egid)); +int _EXFUN(setreuid, (uid_t __ruid, uid_t __euid)); +#endif +pid_t _EXFUN(setsid, (void )); +#if !defined(__INSIDE_CYGWIN__) +int _EXFUN(setuid, (uid_t __uid )); +#endif +#if defined(__CYGWIN__) +void _EXFUN(setusershell, (void)); +#endif +unsigned _EXFUN(sleep, (unsigned int __seconds )); +void _EXFUN(swab, (const void *__restrict, void *__restrict, ssize_t)); +long _EXFUN(sysconf, (int __name )); +pid_t _EXFUN(tcgetpgrp, (int __fildes )); +int _EXFUN(tcsetpgrp, (int __fildes, pid_t __pgrp_id )); +char * _EXFUN(ttyname, (int __fildes )); +#if defined(__CYGWIN__) || defined(__rtems__) +int _EXFUN(ttyname_r, (int, char *, size_t)); +#endif +int _EXFUN(unlink, (const char *__path )); +int _EXFUN(usleep, (useconds_t __useconds)); +int _EXFUN(vhangup, (void )); +_READ_WRITE_RETURN_TYPE _EXFUN(write, (int __fd, const void *__buf, size_t __nbyte )); + +#ifdef __CYGWIN__ +# define __UNISTD_GETOPT__ +# include +# undef __UNISTD_GETOPT__ +#else +extern char *optarg; /* getopt(3) external variables */ +extern int optind, opterr, optopt; +int getopt(int, char * const [], const char *); +extern int optreset; /* getopt(3) external variable */ +#endif + +#ifndef _POSIX_SOURCE +pid_t _EXFUN(vfork, (void )); +#endif /* _POSIX_SOURCE */ + +#ifdef _COMPILING_NEWLIB +/* Provide prototypes for most of the _ names that are + provided in newlib for some compilers. */ +int _EXFUN(_close, (int __fildes )); +pid_t _EXFUN(_fork, (void )); +pid_t _EXFUN(_getpid, (void )); +int _EXFUN(_isatty, (int __fildes )); +int _EXFUN(_link, (const char *__path1, const char *__path2 )); +_off_t _EXFUN(_lseek, (int __fildes, _off_t __offset, int __whence )); +#ifdef __LARGE64_FILES +_off64_t _EXFUN(_lseek64, (int __filedes, _off64_t __offset, int __whence )); +#endif +_READ_WRITE_RETURN_TYPE _EXFUN(_read, (int __fd, void *__buf, size_t __nbyte )); +void * _EXFUN(_sbrk, (ptrdiff_t __incr)); +int _EXFUN(_unlink, (const char *__path )); +_READ_WRITE_RETURN_TYPE _EXFUN(_write, (int __fd, const void *__buf, size_t __nbyte )); +int _EXFUN(_execve, (const char *__path, char * const __argv[], char * const __envp[] )); +#endif + +#if defined(__CYGWIN__) || defined(__rtems__) || defined(__aarch64__) || defined (__arm__) || defined(__sh__) || defined(__SPU__) +#if !defined(__INSIDE_CYGWIN__) +int _EXFUN(ftruncate, (int __fd, off_t __length)); +int _EXFUN(truncate, (const char *, off_t __length)); +#endif +#endif + +#if defined(__CYGWIN__) || defined(__rtems__) +int _EXFUN(getdtablesize, (void)); +int _EXFUN(setdtablesize, (int)); +useconds_t _EXFUN(ualarm, (useconds_t __useconds, useconds_t __interval)); +#if !(defined (_WINSOCK_H) || defined (_WINSOCKAPI_) || defined (__USE_W32_SOCKETS)) +/* winsock[2].h defines as __stdcall, and with int as 2nd arg */ + int _EXFUN(gethostname, (char *__name, size_t __len)); +#endif +char * _EXFUN(mktemp, (char *)); +#endif + +#if defined(__CYGWIN__) || defined(__SPU__) || defined(__rtems__) +void _EXFUN(sync, (void)); +#endif + +ssize_t _EXFUN(readlink, (const char *__restrict __path, + char *__restrict __buf, size_t __buflen)); +#if __POSIX_VISIBLE >= 200809 || __BSD_VISIBLE || defined(__CYGWIN__) +ssize_t _EXFUN(readlinkat, (int __dirfd1, const char *__restrict __path, + char *__restrict __buf, size_t __buflen)); +#endif +int _EXFUN(symlink, (const char *__name1, const char *__name2)); +#if __POSIX_VISIBLE >= 200809 || __BSD_VISIBLE || defined(__CYGWIN__) +int _EXFUN(symlinkat, (const char *, int, const char *)); +int _EXFUN(unlinkat, (int, const char *, int)); +#endif + +#define F_OK 0 +#define R_OK 4 +#define W_OK 2 +#define X_OK 1 + +# define SEEK_SET 0 +# define SEEK_CUR 1 +# define SEEK_END 2 + +#include + +#define STDIN_FILENO 0 /* standard input file descriptor */ +#define STDOUT_FILENO 1 /* standard output file descriptor */ +#define STDERR_FILENO 2 /* standard error file descriptor */ + +/* + * sysconf values per IEEE Std 1003.1, 2008 Edition + */ + +#define _SC_ARG_MAX 0 +#define _SC_CHILD_MAX 1 +#define _SC_CLK_TCK 2 +#define _SC_NGROUPS_MAX 3 +#define _SC_OPEN_MAX 4 +#define _SC_JOB_CONTROL 5 +#define _SC_SAVED_IDS 6 +#define _SC_VERSION 7 +#define _SC_PAGESIZE 8 +#define _SC_PAGE_SIZE _SC_PAGESIZE +/* These are non-POSIX values we accidentally introduced in 2000 without + guarding them. Keeping them unguarded for backward compatibility. */ +#define _SC_NPROCESSORS_CONF 9 +#define _SC_NPROCESSORS_ONLN 10 +#define _SC_PHYS_PAGES 11 +#define _SC_AVPHYS_PAGES 12 +/* End of non-POSIX values. */ +#define _SC_MQ_OPEN_MAX 13 +#define _SC_MQ_PRIO_MAX 14 +#define _SC_RTSIG_MAX 15 +#define _SC_SEM_NSEMS_MAX 16 +#define _SC_SEM_VALUE_MAX 17 +#define _SC_SIGQUEUE_MAX 18 +#define _SC_TIMER_MAX 19 +#define _SC_TZNAME_MAX 20 +#define _SC_ASYNCHRONOUS_IO 21 +#define _SC_FSYNC 22 +#define _SC_MAPPED_FILES 23 +#define _SC_MEMLOCK 24 +#define _SC_MEMLOCK_RANGE 25 +#define _SC_MEMORY_PROTECTION 26 +#define _SC_MESSAGE_PASSING 27 +#define _SC_PRIORITIZED_IO 28 +#define _SC_REALTIME_SIGNALS 29 +#define _SC_SEMAPHORES 30 +#define _SC_SHARED_MEMORY_OBJECTS 31 +#define _SC_SYNCHRONIZED_IO 32 +#define _SC_TIMERS 33 +#define _SC_AIO_LISTIO_MAX 34 +#define _SC_AIO_MAX 35 +#define _SC_AIO_PRIO_DELTA_MAX 36 +#define _SC_DELAYTIMER_MAX 37 +#define _SC_THREAD_KEYS_MAX 38 +#define _SC_THREAD_STACK_MIN 39 +#define _SC_THREAD_THREADS_MAX 40 +#define _SC_TTY_NAME_MAX 41 +#define _SC_THREADS 42 +#define _SC_THREAD_ATTR_STACKADDR 43 +#define _SC_THREAD_ATTR_STACKSIZE 44 +#define _SC_THREAD_PRIORITY_SCHEDULING 45 +#define _SC_THREAD_PRIO_INHERIT 46 +/* _SC_THREAD_PRIO_PROTECT was _SC_THREAD_PRIO_CEILING in early drafts */ +#define _SC_THREAD_PRIO_PROTECT 47 +#define _SC_THREAD_PRIO_CEILING _SC_THREAD_PRIO_PROTECT +#define _SC_THREAD_PROCESS_SHARED 48 +#define _SC_THREAD_SAFE_FUNCTIONS 49 +#define _SC_GETGR_R_SIZE_MAX 50 +#define _SC_GETPW_R_SIZE_MAX 51 +#define _SC_LOGIN_NAME_MAX 52 +#define _SC_THREAD_DESTRUCTOR_ITERATIONS 53 +#define _SC_ADVISORY_INFO 54 +#define _SC_ATEXIT_MAX 55 +#define _SC_BARRIERS 56 +#define _SC_BC_BASE_MAX 57 +#define _SC_BC_DIM_MAX 58 +#define _SC_BC_SCALE_MAX 59 +#define _SC_BC_STRING_MAX 60 +#define _SC_CLOCK_SELECTION 61 +#define _SC_COLL_WEIGHTS_MAX 62 +#define _SC_CPUTIME 63 +#define _SC_EXPR_NEST_MAX 64 +#define _SC_HOST_NAME_MAX 65 +#define _SC_IOV_MAX 66 +#define _SC_IPV6 67 +#define _SC_LINE_MAX 68 +#define _SC_MONOTONIC_CLOCK 69 +#define _SC_RAW_SOCKETS 70 +#define _SC_READER_WRITER_LOCKS 71 +#define _SC_REGEXP 72 +#define _SC_RE_DUP_MAX 73 +#define _SC_SHELL 74 +#define _SC_SPAWN 75 +#define _SC_SPIN_LOCKS 76 +#define _SC_SPORADIC_SERVER 77 +#define _SC_SS_REPL_MAX 78 +#define _SC_SYMLOOP_MAX 79 +#define _SC_THREAD_CPUTIME 80 +#define _SC_THREAD_SPORADIC_SERVER 81 +#define _SC_TIMEOUTS 82 +#define _SC_TRACE 83 +#define _SC_TRACE_EVENT_FILTER 84 +#define _SC_TRACE_EVENT_NAME_MAX 85 +#define _SC_TRACE_INHERIT 86 +#define _SC_TRACE_LOG 87 +#define _SC_TRACE_NAME_MAX 88 +#define _SC_TRACE_SYS_MAX 89 +#define _SC_TRACE_USER_EVENT_MAX 90 +#define _SC_TYPED_MEMORY_OBJECTS 91 +#define _SC_V7_ILP32_OFF32 92 +#define _SC_V6_ILP32_OFF32 _SC_V7_ILP32_OFF32 +#define _SC_XBS5_ILP32_OFF32 _SC_V7_ILP32_OFF32 +#define _SC_V7_ILP32_OFFBIG 93 +#define _SC_V6_ILP32_OFFBIG _SC_V7_ILP32_OFFBIG +#define _SC_XBS5_ILP32_OFFBIG _SC_V7_ILP32_OFFBIG +#define _SC_V7_LP64_OFF64 94 +#define _SC_V6_LP64_OFF64 _SC_V7_LP64_OFF64 +#define _SC_XBS5_LP64_OFF64 _SC_V7_LP64_OFF64 +#define _SC_V7_LPBIG_OFFBIG 95 +#define _SC_V6_LPBIG_OFFBIG _SC_V7_LPBIG_OFFBIG +#define _SC_XBS5_LPBIG_OFFBIG _SC_V7_LPBIG_OFFBIG +#define _SC_XOPEN_CRYPT 96 +#define _SC_XOPEN_ENH_I18N 97 +#define _SC_XOPEN_LEGACY 98 +#define _SC_XOPEN_REALTIME 99 +#define _SC_STREAM_MAX 100 +#define _SC_PRIORITY_SCHEDULING 101 +#define _SC_XOPEN_REALTIME_THREADS 102 +#define _SC_XOPEN_SHM 103 +#define _SC_XOPEN_STREAMS 104 +#define _SC_XOPEN_UNIX 105 +#define _SC_XOPEN_VERSION 106 +#define _SC_2_CHAR_TERM 107 +#define _SC_2_C_BIND 108 +#define _SC_2_C_DEV 109 +#define _SC_2_FORT_DEV 110 +#define _SC_2_FORT_RUN 111 +#define _SC_2_LOCALEDEF 112 +#define _SC_2_PBS 113 +#define _SC_2_PBS_ACCOUNTING 114 +#define _SC_2_PBS_CHECKPOINT 115 +#define _SC_2_PBS_LOCATE 116 +#define _SC_2_PBS_MESSAGE 117 +#define _SC_2_PBS_TRACK 118 +#define _SC_2_SW_DEV 119 +#define _SC_2_UPE 120 +#define _SC_2_VERSION 121 +#define _SC_THREAD_ROBUST_PRIO_INHERIT 122 +#define _SC_THREAD_ROBUST_PRIO_PROTECT 123 +#define _SC_XOPEN_UUCP 124 + +/* + * pathconf values per IEEE Std 1003.1, 2008 Edition + */ + +#define _PC_LINK_MAX 0 +#define _PC_MAX_CANON 1 +#define _PC_MAX_INPUT 2 +#define _PC_NAME_MAX 3 +#define _PC_PATH_MAX 4 +#define _PC_PIPE_BUF 5 +#define _PC_CHOWN_RESTRICTED 6 +#define _PC_NO_TRUNC 7 +#define _PC_VDISABLE 8 +#define _PC_ASYNC_IO 9 +#define _PC_PRIO_IO 10 +#define _PC_SYNC_IO 11 +#define _PC_FILESIZEBITS 12 +#define _PC_2_SYMLINKS 13 +#define _PC_SYMLINK_MAX 14 +#define _PC_ALLOC_SIZE_MIN 15 +#define _PC_REC_INCR_XFER_SIZE 16 +#define _PC_REC_MAX_XFER_SIZE 17 +#define _PC_REC_MIN_XFER_SIZE 18 +#define _PC_REC_XFER_ALIGN 19 +#define _PC_TIMESTAMP_RESOLUTION 20 +#ifdef __CYGWIN__ +/* Ask for POSIX permission bits support. */ +#define _PC_POSIX_PERMISSIONS 90 +/* Ask for full POSIX permission support including uid/gid settings. */ +#define _PC_POSIX_SECURITY 91 +#endif + +/* + * confstr values per IEEE Std 1003.1, 2004 Edition + */ + +#ifdef __CYGWIN__ /* Only defined on Cygwin for now. */ +#define _CS_PATH 0 +#define _CS_POSIX_V7_ILP32_OFF32_CFLAGS 1 +#define _CS_POSIX_V6_ILP32_OFF32_CFLAGS _CS_POSIX_V7_ILP32_OFF32_CFLAGS +#define _CS_XBS5_ILP32_OFF32_CFLAGS _CS_POSIX_V7_ILP32_OFF32_CFLAGS +#define _CS_POSIX_V7_ILP32_OFF32_LDFLAGS 2 +#define _CS_POSIX_V6_ILP32_OFF32_LDFLAGS _CS_POSIX_V7_ILP32_OFF32_LDFLAGS +#define _CS_XBS5_ILP32_OFF32_LDFLAGS _CS_POSIX_V7_ILP32_OFF32_LDFLAGS +#define _CS_POSIX_V7_ILP32_OFF32_LIBS 3 +#define _CS_POSIX_V6_ILP32_OFF32_LIBS _CS_POSIX_V7_ILP32_OFF32_LIBS +#define _CS_XBS5_ILP32_OFF32_LIBS _CS_POSIX_V7_ILP32_OFF32_LIBS +#define _CS_XBS5_ILP32_OFF32_LINTFLAGS 4 +#define _CS_POSIX_V7_ILP32_OFFBIG_CFLAGS 5 +#define _CS_POSIX_V6_ILP32_OFFBIG_CFLAGS _CS_POSIX_V7_ILP32_OFFBIG_CFLAGS +#define _CS_XBS5_ILP32_OFFBIG_CFLAGS _CS_POSIX_V7_ILP32_OFFBIG_CFLAGS +#define _CS_POSIX_V7_ILP32_OFFBIG_LDFLAGS 6 +#define _CS_POSIX_V6_ILP32_OFFBIG_LDFLAGS _CS_POSIX_V7_ILP32_OFFBIG_LDFLAGS +#define _CS_XBS5_ILP32_OFFBIG_LDFLAGS _CS_POSIX_V7_ILP32_OFFBIG_LDFLAGS +#define _CS_POSIX_V7_ILP32_OFFBIG_LIBS 7 +#define _CS_POSIX_V6_ILP32_OFFBIG_LIBS _CS_POSIX_V7_ILP32_OFFBIG_LIBS +#define _CS_XBS5_ILP32_OFFBIG_LIBS _CS_POSIX_V7_ILP32_OFFBIG_LIBS +#define _CS_XBS5_ILP32_OFFBIG_LINTFLAGS 8 +#define _CS_POSIX_V7_LP64_OFF64_CFLAGS 9 +#define _CS_POSIX_V6_LP64_OFF64_CFLAGS _CS_POSIX_V7_LP64_OFF64_CFLAGS +#define _CS_XBS5_LP64_OFF64_CFLAGS _CS_POSIX_V7_LP64_OFF64_CFLAGS +#define _CS_POSIX_V7_LP64_OFF64_LDFLAGS 10 +#define _CS_POSIX_V6_LP64_OFF64_LDFLAGS _CS_POSIX_V7_LP64_OFF64_LDFLAGS +#define _CS_XBS5_LP64_OFF64_LDFLAGS _CS_POSIX_V7_LP64_OFF64_LDFLAGS +#define _CS_POSIX_V7_LP64_OFF64_LIBS 11 +#define _CS_POSIX_V6_LP64_OFF64_LIBS _CS_POSIX_V7_LP64_OFF64_LIBS +#define _CS_XBS5_LP64_OFF64_LIBS _CS_POSIX_V7_LP64_OFF64_LIBS +#define _CS_XBS5_LP64_OFF64_LINTFLAGS 12 +#define _CS_POSIX_V7_LPBIG_OFFBIG_CFLAGS 13 +#define _CS_POSIX_V6_LPBIG_OFFBIG_CFLAGS _CS_POSIX_V7_LPBIG_OFFBIG_CFLAGS +#define _CS_XBS5_LPBIG_OFFBIG_CFLAGS _CS_POSIX_V7_LPBIG_OFFBIG_CFLAGS +#define _CS_POSIX_V7_LPBIG_OFFBIG_LDFLAGS 14 +#define _CS_POSIX_V6_LPBIG_OFFBIG_LDFLAGS _CS_POSIX_V7_LPBIG_OFFBIG_LDFLAGS +#define _CS_XBS5_LPBIG_OFFBIG_LDFLAGS _CS_POSIX_V7_LPBIG_OFFBIG_LDFLAGS +#define _CS_POSIX_V7_LPBIG_OFFBIG_LIBS 15 +#define _CS_POSIX_V6_LPBIG_OFFBIG_LIBS _CS_POSIX_V7_LPBIG_OFFBIG_LIBS +#define _CS_XBS5_LPBIG_OFFBIG_LIBS _CS_POSIX_V7_LPBIG_OFFBIG_LIBS +#define _CS_XBS5_LPBIG_OFFBIG_LINTFLAGS 16 +#define _CS_POSIX_V7_WIDTH_RESTRICTED_ENVS 17 +#define _CS_POSIX_V6_WIDTH_RESTRICTED_ENVS _CS_POSIX_V7_WIDTH_RESTRICTED_ENVS +#define _CS_XBS5_WIDTH_RESTRICTED_ENVS _CS_POSIX_V7_WIDTH_RESTRICTED_ENVS +#define _CS_POSIX_V7_THREADS_CFLAGS 18 +#define _CS_POSIX_V7_THREADS_LDFLAGS 19 +#define _CS_V7_ENV 20 +#define _CS_V6_ENV _CS_V7_ENV +#endif + +#ifdef __cplusplus +} +#endif +#endif /* _SYS_UNISTD_H */ diff --git a/components/newlib/include/sys/utime.h b/components/newlib/include/sys/utime.h new file mode 100644 index 0000000000..5e937f1038 --- /dev/null +++ b/components/newlib/include/sys/utime.h @@ -0,0 +1,22 @@ +#ifndef _SYS_UTIME_H +#define _SYS_UTIME_H + +/* This is a dummy file, not customized for any + particular system. If there is a utime.h in libc/sys/SYSDIR/sys, + it will override this one. */ + +#ifdef __cplusplus +extern "C" { +#endif + +struct utimbuf +{ + time_t actime; + time_t modtime; +}; + +#ifdef __cplusplus +}; +#endif + +#endif /* _SYS_UTIME_H */ diff --git a/components/newlib/include/sys/wait.h b/components/newlib/include/sys/wait.h new file mode 100644 index 0000000000..73fe372024 --- /dev/null +++ b/components/newlib/include/sys/wait.h @@ -0,0 +1,44 @@ +#ifndef _SYS_WAIT_H +#define _SYS_WAIT_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include + +#define WNOHANG 1 +#define WUNTRACED 2 + +/* A status looks like: + <2 bytes info> <2 bytes code> + + == 0, child has exited, info is the exit value + == 1..7e, child has exited, info is the signal number. + == 7f, child has stopped, info was the signal number. + == 80, there was a core dump. +*/ + +#define WIFEXITED(w) (((w) & 0xff) == 0) +#define WIFSIGNALED(w) (((w) & 0x7f) > 0 && (((w) & 0x7f) < 0x7f)) +#define WIFSTOPPED(w) (((w) & 0xff) == 0x7f) +#define WEXITSTATUS(w) (((w) >> 8) & 0xff) +#define WTERMSIG(w) ((w) & 0x7f) +#define WSTOPSIG WEXITSTATUS + +pid_t wait (int *); +pid_t waitpid (pid_t, int *, int); + +#ifdef _COMPILING_NEWLIB +pid_t _wait (int *); +#endif + +/* Provide prototypes for most of the _ names that are + provided in newlib for some compilers. */ +pid_t _wait (int *); + +#ifdef __cplusplus +}; +#endif + +#endif diff --git a/components/newlib/include/tar.h b/components/newlib/include/tar.h new file mode 100644 index 0000000000..07b06dd7fb --- /dev/null +++ b/components/newlib/include/tar.h @@ -0,0 +1,39 @@ +/* + * tar.h + */ + +#ifndef _TAR_H +#define _TAR_H + +/* General definitions */ +#define TMAGIC "ustar" /* ustar plus null byte. */ +#define TMAGLEN 6 /* Length of the above. */ +#define TVERSION "00" /* 00 without a null byte. */ +#define TVERSLEN 2 /* Length of the above. */ + +/* Typeflag field definitions */ +#define REGTYPE '0' /* Regular file. */ +#define AREGTYPE '\0' /* Regular file. */ +#define LNKTYPE '1' /* Link. */ +#define SYMTYPE '2' /* Symbolic link. */ +#define CHRTYPE '3' /* Character special. */ +#define BLKTYPE '4' /* Block special. */ +#define DIRTYPE '5' /* Directory. */ +#define FIFOTYPE '6' /* FIFO special. */ +#define CONTTYPE '7' /* Reserved. */ + +/* Mode field bit definitions (octal) */ +#define TSUID 04000 /* Set UID on execution. */ +#define TSGID 02000 /* Set GID on execution. */ +#define TSVTX 01000 /* On directories, restricted deletion flag. */ +#define TUREAD 00400 /* Read by owner. */ +#define TUWRITE 00200 /* Write by owner. */ +#define TUEXEC 00100 /* Execute/search by owner. */ +#define TGREAD 00040 /* Read by group. */ +#define TGWRITE 00020 /* Write by group. */ +#define TGEXEC 00010 /* Execute/search by group. */ +#define TOREAD 00004 /* Read by other. */ +#define TOWRITE 00002 /* Write by other. */ +#define TOEXEC 00001 /* Execute/search by other. */ + +#endif diff --git a/components/newlib/include/termios.h b/components/newlib/include/termios.h new file mode 100644 index 0000000000..ee1820ce04 --- /dev/null +++ b/components/newlib/include/termios.h @@ -0,0 +1,7 @@ +#ifdef __cplusplus +extern "C" { +#endif +#include +#ifdef __cplusplus +} +#endif diff --git a/components/newlib/include/tgmath.h b/components/newlib/include/tgmath.h new file mode 100644 index 0000000000..f9c8311cc3 --- /dev/null +++ b/components/newlib/include/tgmath.h @@ -0,0 +1,184 @@ +/* http://pubs.opengroup.org/onlinepubs/9699919799/basedefs/tgmath.h.html */ +/*- + * Copyright (c) 2004 Stefan Farfeleder. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $FreeBSD$ + */ + +#ifndef _TGMATH_H_ +#define _TGMATH_H_ + +#include +#include + +#ifdef log2 +#undef log2 +#endif + +/* + * This implementation of requires two implementation-dependent + * macros to be defined: + * __tg_impl_simple(x, y, z, fn, fnf, fnl, ...) + * Invokes fnl() if the corresponding real type of x, y or z is long + * double, fn() if it is double or any has an integer type, and fnf() + * otherwise. + * __tg_impl_full(x, y, z, fn, fnf, fnl, cfn, cfnf, cfnl, ...) + * Invokes [c]fnl() if the corresponding real type of x, y or z is long + * double, [c]fn() if it is double or any has an integer type, and + * [c]fnf() otherwise. The function with the 'c' prefix is called if + * any of x, y or z is a complex number. + * Both macros call the chosen function with all additional arguments passed + * to them, as given by __VA_ARGS__. + * + * Note that these macros cannot be implemented with C's ?: operator, + * because the return type of the whole expression would incorrectly be long + * double complex regardless of the argument types. + */ + +/* requires GCC >= 3.1 */ +#if !__GNUC_PREREQ (3, 1) +#error " not implemented for this compiler" +#endif + +#define __tg_type(__e, __t) \ + __builtin_types_compatible_p(__typeof__(__e), __t) +#define __tg_type3(__e1, __e2, __e3, __t) \ + (__tg_type(__e1, __t) || __tg_type(__e2, __t) || \ + __tg_type(__e3, __t)) +#define __tg_type_corr(__e1, __e2, __e3, __t) \ + (__tg_type3(__e1, __e2, __e3, __t) || \ + __tg_type3(__e1, __e2, __e3, __t _Complex)) +#define __tg_integer(__e1, __e2, __e3) \ + (((__typeof__(__e1))1.5 == 1) || ((__typeof__(__e2))1.5 == 1) || \ + ((__typeof__(__e3))1.5 == 1)) +#define __tg_is_complex(__e1, __e2, __e3) \ + (__tg_type3(__e1, __e2, __e3, float _Complex) || \ + __tg_type3(__e1, __e2, __e3, double _Complex) || \ + __tg_type3(__e1, __e2, __e3, long double _Complex) || \ + __tg_type3(__e1, __e2, __e3, __typeof__(_Complex_I))) + +#ifdef _LDBL_EQ_DBL +#define __tg_impl_simple(x, y, z, fn, fnf, fnl, ...) \ + __builtin_choose_expr(__tg_type_corr(x, y, z, long double), \ + fnl(__VA_ARGS__), __builtin_choose_expr( \ + __tg_type_corr(x, y, z, double) || __tg_integer(x, y, z),\ + fn(__VA_ARGS__), fnf(__VA_ARGS__))) +#else +#define __tg_impl_simple(__x, __y, __z, __fn, __fnf, __fnl, ...) \ + (__tg_type_corr(__x, __y, __z, double) || __tg_integer(__x, __y, __z)) \ + ? __fn(__VA_ARGS__) : __fnf(__VA_ARGS__) +#endif + +#define __tg_impl_full(__x, __y, __z, __fn, __fnf, __fnl, __cfn, __cfnf, __cfnl, ...) \ + __builtin_choose_expr(__tg_is_complex(__x, __y, __z), \ + __tg_impl_simple(__x, __y, __z, __cfn, __cfnf, __cfnl, __VA_ARGS__), \ + __tg_impl_simple(__x, __y, __z, __fn, __fnf, __fnl, __VA_ARGS__)) + +/* Macros to save lots of repetition below */ +#define __tg_simple(__x, __fn) \ + __tg_impl_simple(__x, __x, __x, __fn, __fn##f, __fn##l, __x) +#define __tg_simple2(__x, __y, __fn) \ + __tg_impl_simple(__x, __x, __y, __fn, __fn##f, __fn##l, __x, __y) +#define __tg_simplev(__x, __fn, ...) \ + __tg_impl_simple(__x, __x, __x, __fn, __fn##f, __fn##l, __VA_ARGS__) +#define __tg_full(__x, __fn) \ + __tg_impl_full(__x, __x, __x, __fn, __fn##f, __fn##l, c##__fn, c##__fn##f, c##__fn##l, __x) + +/* 7.22#4 -- These macros expand to real or complex functions, depending on + * the type of their arguments. */ +#define acos(__x) __tg_full(__x, acos) +#define asin(__x) __tg_full(__x, asin) +#define atan(__x) __tg_full(__x, atan) +#define acosh(__x) __tg_full(__x, acosh) +#define asinh(__x) __tg_full(__x, asinh) +#define atanh(__x) __tg_full(__x, atanh) +#define cos(__x) __tg_full(__x, cos) +#define sin(__x) __tg_full(__x, sin) +#define tan(__x) __tg_full(__x, tan) +#define cosh(__x) __tg_full(__x, cosh) +#define sinh(__x) __tg_full(__x, sinh) +#define tanh(__x) __tg_full(__x, tanh) +#define exp(__x) __tg_full(__x, exp) +#define log(__x) __tg_full(__x, log) +#define pow(__x, __y) __tg_impl_full(__x, __x, __y, pow, powf, powl, \ + cpow, cpowf, cpowl, __x, __y) +#define sqrt(__x) __tg_full(__x, sqrt) + +/* "The corresponding type-generic macro for fabs and cabs is fabs." */ +#define fabs(__x) __tg_impl_full(__x, __x, __x, fabs, fabsf, fabsl, \ + cabs, cabsf, cabsl, __x) + +/* 7.22#5 -- These macros are only defined for arguments with real type. */ +#define atan2(__x, __y) __tg_simple2(__x, __y, atan2) +#define cbrt(__x) __tg_simple(__x, cbrt) +#define ceil(__x) __tg_simple(__x, ceil) +#define copysign(__x, __y) __tg_simple2(__x, __y, copysign) +#define erf(__x) __tg_simple(__x, erf) +#define erfc(__x) __tg_simple(__x, erfc) +#define exp2(__x) __tg_simple(__x, exp2) +#define expm1(__x) __tg_simple(__x, expm1) +#define fdim(__x, __y) __tg_simple2(__x, __y, fdim) +#define floor(__x) __tg_simple(__x, floor) +#define fma(__x, __y, __z) __tg_impl_simple(__x, __y, __z, fma, fmaf, fmal, \ + __x, __y, __z) +#define fmax(__x, __y) __tg_simple2(__x, __y, fmax) +#define fmin(__x, __y) __tg_simple2(__x, __y, fmin) +#define fmod(__x, __y) __tg_simple2(__x, __y, fmod) +#define frexp(__x, __y) __tg_simplev(__x, frexp, __x, __y) +#define hypot(__x, __y) __tg_simple2(__x, __y, hypot) +#define ilogb(__x) __tg_simple(__x, ilogb) +#define ldexp(__x, __y) __tg_simplev(__x, ldexp, __x, __y) +#define lgamma(__x) __tg_simple(__x, lgamma) +#define llrint(__x) __tg_simple(__x, llrint) +#define llround(__x) __tg_simple(__x, llround) +#define log10(__x) __tg_simple(__x, log10) +#define log1p(__x) __tg_simple(__x, log1p) +#define log2(__x) __tg_simple(__x, log2) +#define logb(__x) __tg_simple(__x, logb) +#define lrint(__x) __tg_simple(__x, lrint) +#define lround(__x) __tg_simple(__x, lround) +#define nearbyint(__x) __tg_simple(__x, nearbyint) +#define nextafter(__x, __y) __tg_simple2(__x, __y, nextafter) +/* not yet implemented even for _LDBL_EQ_DBL platforms +#define nexttoward(__x, __y) __tg_simplev(__x, nexttoward, __x, __y) +*/ +#define remainder(__x, __y) __tg_simple2(__x, __y, remainder) +#define remquo(__x, __y, __z) __tg_impl_simple(__x, __x, __y, remquo, remquof, \ + remquol, __x, __y, __z) +#define rint(__x) __tg_simple(__x, rint) +#define round(__x) __tg_simple(__x, round) +#define scalbn(__x, __y) __tg_simplev(__x, scalbn, __x, __y) +#define scalbln(__x, __y) __tg_simplev(__x, scalbln, __x, __y) +#define tgamma(__x) __tg_simple(__x, tgamma) +#define trunc(__x) __tg_simple(__x, trunc) + +/* 7.22#6 -- These macros always expand to complex functions. */ +#define carg(__x) __tg_simple(__x, carg) +#define cimag(__x) __tg_simple(__x, cimag) +#define conj(__x) __tg_simple(__x, conj) +#define cproj(__x) __tg_simple(__x, cproj) +#define creal(__x) __tg_simple(__x, creal) + +#endif /* !_TGMATH_H_ */ diff --git a/components/newlib/include/time.h b/components/newlib/include/time.h new file mode 100644 index 0000000000..d7b6612db1 --- /dev/null +++ b/components/newlib/include/time.h @@ -0,0 +1,291 @@ +/* + * time.h + * + * Struct and function declarations for dealing with time. + */ + +#ifndef _TIME_H_ +#define _TIME_H_ + +#include "_ansi.h" +#include + +#define __need_size_t +#define __need_NULL +#include + +/* Get _CLOCKS_PER_SEC_ */ +#include + +#ifndef _CLOCKS_PER_SEC_ +#define _CLOCKS_PER_SEC_ 1000 +#endif + +#define CLOCKS_PER_SEC _CLOCKS_PER_SEC_ +#define CLK_TCK CLOCKS_PER_SEC + +#include + +_BEGIN_STD_C + +struct tm +{ + int tm_sec; + int tm_min; + int tm_hour; + int tm_mday; + int tm_mon; + int tm_year; + int tm_wday; + int tm_yday; + int tm_isdst; +#ifdef __TM_GMTOFF + long __TM_GMTOFF; +#endif +#ifdef __TM_ZONE + const char *__TM_ZONE; +#endif +}; + +clock_t _EXFUN(clock, (void)); +double _EXFUN(difftime, (time_t _time2, time_t _time1)); +time_t _EXFUN(mktime, (struct tm *_timeptr)); +time_t _EXFUN(time, (time_t *_timer)); +#ifndef _REENT_ONLY +char *_EXFUN(asctime, (const struct tm *_tblock)); +char *_EXFUN(ctime, (const time_t *_time)); +struct tm *_EXFUN(gmtime, (const time_t *_timer)); +struct tm *_EXFUN(localtime,(const time_t *_timer)); +#endif +size_t _EXFUN(strftime, (char *__restrict _s, + size_t _maxsize, const char *__restrict _fmt, + const struct tm *__restrict _t)); + +char *_EXFUN(asctime_r, (const struct tm *__restrict, + char *__restrict)); +char *_EXFUN(ctime_r, (const time_t *, char *)); +struct tm *_EXFUN(gmtime_r, (const time_t *__restrict, + struct tm *__restrict)); +struct tm *_EXFUN(localtime_r, (const time_t *__restrict, + struct tm *__restrict)); + +_END_STD_C + +#ifdef __cplusplus +extern "C" { +#endif + +#ifndef __STRICT_ANSI__ +char *_EXFUN(strptime, (const char *__restrict, + const char *__restrict, + struct tm *__restrict)); +_VOID _EXFUN(tzset, (_VOID)); +_VOID _EXFUN(_tzset_r, (struct _reent *)); + +typedef struct __tzrule_struct +{ + char ch; + int m; + int n; + int d; + int s; + time_t change; + long offset; /* Match type of _timezone. */ +} __tzrule_type; + +typedef struct __tzinfo_struct +{ + int __tznorth; + int __tzyear; + __tzrule_type __tzrule[2]; +} __tzinfo_type; + +__tzinfo_type *_EXFUN (__gettzinfo, (_VOID)); + +/* getdate functions */ + +#ifdef HAVE_GETDATE +#ifndef _REENT_ONLY +#define getdate_err (*__getdate_err()) +int *_EXFUN(__getdate_err,(_VOID)); + +struct tm * _EXFUN(getdate, (const char *)); +/* getdate_err is set to one of the following values to indicate the error. + 1 the DATEMSK environment variable is null or undefined, + 2 the template file cannot be opened for reading, + 3 failed to get file status information, + 4 the template file is not a regular file, + 5 an error is encountered while reading the template file, + 6 memory allication failed (not enough memory available), + 7 there is no line in the template that matches the input, + 8 invalid input specification */ +#endif /* !_REENT_ONLY */ + +/* getdate_r returns the error code as above */ +int _EXFUN(getdate_r, (const char *, struct tm *)); +#endif /* HAVE_GETDATE */ + +/* defines for the opengroup specifications Derived from Issue 1 of the SVID. */ +extern __IMPORT long _timezone; +extern __IMPORT int _daylight; +extern __IMPORT char *_tzname[2]; + +/* POSIX defines the external tzname being defined in time.h */ +#ifndef tzname +#define tzname _tzname +#endif +#endif /* !__STRICT_ANSI__ */ + +#ifdef __cplusplus +} +#endif + +#include + +#ifdef __CYGWIN__ +#include +#endif /*__CYGWIN__*/ + +#if defined(_POSIX_TIMERS) + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/* Clocks, P1003.1b-1993, p. 263 */ + +int _EXFUN(clock_settime, (clockid_t clock_id, const struct timespec *tp)); +int _EXFUN(clock_gettime, (clockid_t clock_id, struct timespec *tp)); +int _EXFUN(clock_getres, (clockid_t clock_id, struct timespec *res)); + +/* Create a Per-Process Timer, P1003.1b-1993, p. 264 */ + +int _EXFUN(timer_create, + (clockid_t clock_id, + struct sigevent *__restrict evp, + timer_t *__restrict timerid)); + +/* Delete a Per_process Timer, P1003.1b-1993, p. 266 */ + +int _EXFUN(timer_delete, (timer_t timerid)); + +/* Per-Process Timers, P1003.1b-1993, p. 267 */ + +int _EXFUN(timer_settime, + (timer_t timerid, int flags, + const struct itimerspec *__restrict value, + struct itimerspec *__restrict ovalue)); +int _EXFUN(timer_gettime, (timer_t timerid, struct itimerspec *value)); +int _EXFUN(timer_getoverrun, (timer_t timerid)); + +/* High Resolution Sleep, P1003.1b-1993, p. 269 */ + +int _EXFUN(nanosleep, (const struct timespec *rqtp, struct timespec *rmtp)); + +#ifdef __cplusplus +} +#endif +#endif /* _POSIX_TIMERS */ + +#if defined(_POSIX_CLOCK_SELECTION) + +#ifdef __cplusplus +extern "C" { +#endif + +int _EXFUN(clock_nanosleep, + (clockid_t clock_id, int flags, const struct timespec *rqtp, + struct timespec *rmtp)); + +#ifdef __cplusplus +} +#endif + +#endif /* _POSIX_CLOCK_SELECTION */ + +#ifdef __cplusplus +extern "C" { +#endif + +/* CPU-time Clock Attributes, P1003.4b/D8, p. 54 */ + +/* values for the clock enable attribute */ + +#define CLOCK_ENABLED 1 /* clock is enabled, i.e. counting execution time */ +#define CLOCK_DISABLED 0 /* clock is disabled */ + +/* values for the pthread cputime_clock_allowed attribute */ + +#define CLOCK_ALLOWED 1 /* If a thread is created with this value a */ + /* CPU-time clock attached to that thread */ + /* shall be accessible. */ +#define CLOCK_DISALLOWED 0 /* If a thread is created with this value, the */ + /* thread shall not have a CPU-time clock */ + /* accessible. */ + +/* Manifest Constants, P1003.1b-1993, p. 262 */ + +#define CLOCK_REALTIME (clockid_t)1 + +/* Flag indicating time is "absolute" with respect to the clock + associated with a time. */ + +#define TIMER_ABSTIME 4 + +/* Manifest Constants, P1003.4b/D8, p. 55 */ + +#if defined(_POSIX_CPUTIME) + +/* When used in a clock or timer function call, this is interpreted as + the identifier of the CPU_time clock associated with the PROCESS + making the function call. */ + +#define CLOCK_PROCESS_CPUTIME_ID (clockid_t)2 + +#endif + +#if defined(_POSIX_THREAD_CPUTIME) + +/* When used in a clock or timer function call, this is interpreted as + the identifier of the CPU_time clock associated with the THREAD + making the function call. */ + +#define CLOCK_THREAD_CPUTIME_ID (clockid_t)3 + +#endif + +#if defined(_POSIX_MONOTONIC_CLOCK) + +/* The identifier for the system-wide monotonic clock, which is defined + * as a clock whose value cannot be set via clock_settime() and which + * cannot have backward clock jumps. */ + +#define CLOCK_MONOTONIC (clockid_t)4 + +#endif + +#if defined(_POSIX_CPUTIME) + +/* Accessing a Process CPU-time CLock, P1003.4b/D8, p. 55 */ + +int _EXFUN(clock_getcpuclockid, (pid_t pid, clockid_t *clock_id)); + +#endif /* _POSIX_CPUTIME */ + +#if defined(_POSIX_CPUTIME) || defined(_POSIX_THREAD_CPUTIME) + +/* CPU-time Clock Attribute Access, P1003.4b/D8, p. 56 */ + +int _EXFUN(clock_setenable_attr, (clockid_t clock_id, int attr)); +int _EXFUN(clock_getenable_attr, (clockid_t clock_id, int *attr)); + +#endif /* _POSIX_CPUTIME or _POSIX_THREAD_CPUTIME */ + +#ifdef __cplusplus +} +#endif + +#endif /* _TIME_H_ */ + diff --git a/components/newlib/include/unctrl.h b/components/newlib/include/unctrl.h new file mode 100644 index 0000000000..0040752329 --- /dev/null +++ b/components/newlib/include/unctrl.h @@ -0,0 +1,46 @@ +/* From curses.h. */ +/* + * Copyright (c) 1981, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef _UNCTRL_H_ +#define _UNCTRL_H_ + +#include <_ansi.h> + +#define unctrl(c) __unctrl[(c) & 0xff] +#define unctrllen(ch) __unctrllen[(ch) & 0xff] + +extern __IMPORT _CONST char * _CONST __unctrl[256]; /* Control strings. */ +extern __IMPORT _CONST char __unctrllen[256]; /* Control strings length. */ + +#endif /* _UNCTRL_H_ */ diff --git a/components/newlib/include/unistd.h b/components/newlib/include/unistd.h new file mode 100644 index 0000000000..4f6fd29a4d --- /dev/null +++ b/components/newlib/include/unistd.h @@ -0,0 +1,13 @@ +#ifndef _UNISTD_H_ +#define _UNISTD_H_ + +# include + +#ifndef L_SET +/* Old BSD names for the same constants; just for compatibility. */ +#define L_SET SEEK_SET +#define L_INCR SEEK_CUR +#define L_XTND SEEK_END +#endif + +#endif /* _UNISTD_H_ */ diff --git a/components/newlib/include/utime.h b/components/newlib/include/utime.h new file mode 100644 index 0000000000..652891aab1 --- /dev/null +++ b/components/newlib/include/utime.h @@ -0,0 +1,12 @@ +#ifdef __cplusplus +extern "C" { +#endif + +#include <_ansi.h> + +/* The utime function is defined in libc/sys//sys if it exists. */ +#include + +#ifdef __cplusplus +} +#endif diff --git a/components/newlib/include/utmp.h b/components/newlib/include/utmp.h new file mode 100644 index 0000000000..88cf6f8528 --- /dev/null +++ b/components/newlib/include/utmp.h @@ -0,0 +1,8 @@ +#ifdef __cplusplus +extern "C" { +#endif +#include +#ifdef __cplusplus +} +#endif + diff --git a/components/newlib/include/wchar.h b/components/newlib/include/wchar.h new file mode 100644 index 0000000000..810a6c0e33 --- /dev/null +++ b/components/newlib/include/wchar.h @@ -0,0 +1,254 @@ +#ifndef _WCHAR_H_ +#define _WCHAR_H_ + +#include <_ansi.h> + +#include + +#define __need_size_t +#define __need_wchar_t +#define __need_wint_t +#define __need_NULL +#include + +#define __need___va_list +#include + +/* For _mbstate_t definition. */ +#include +#include +/* For __STDC_ISO_10646__ */ +#include + +#ifndef WEOF +# define WEOF ((wint_t)-1) +#endif + +/* This must match definition in */ +#ifndef WCHAR_MIN +#ifdef __WCHAR_MIN__ +#define WCHAR_MIN __WCHAR_MIN__ +#elif defined(__WCHAR_UNSIGNED__) || (L'\0' - 1 > 0) +#define WCHAR_MIN (0 + L'\0') +#else +#define WCHAR_MIN (-0x7fffffff - 1 + L'\0') +#endif +#endif + +/* This must match definition in */ +#ifndef WCHAR_MAX +#ifdef __WCHAR_MAX__ +#define WCHAR_MAX __WCHAR_MAX__ +#elif defined(__WCHAR_UNSIGNED__) || (L'\0' - 1 > 0) +#define WCHAR_MAX (0xffffffffu + L'\0') +#else +#define WCHAR_MAX (0x7fffffff + L'\0') +#endif +#endif + +_BEGIN_STD_C + +/* As in stdio.h, defines __FILE. */ +typedef __FILE FILE; + +/* As required by POSIX.1-2008, declare tm as incomplete type. + The actual definition is in time.h. */ +struct tm; + +#ifndef _MBSTATE_T +#define _MBSTATE_T +typedef _mbstate_t mbstate_t; +#endif /* _MBSTATE_T */ + +wint_t _EXFUN(btowc, (int)); +int _EXFUN(wctob, (wint_t)); +size_t _EXFUN(mbrlen, (const char *__restrict, size_t, mbstate_t *__restrict)); +size_t _EXFUN(mbrtowc, (wchar_t *__restrict, const char *__restrict, size_t, + mbstate_t *__restrict)); +size_t _EXFUN(_mbrtowc_r, (struct _reent *, wchar_t * , const char * , + size_t, mbstate_t *)); +int _EXFUN(mbsinit, (const mbstate_t *)); +size_t _EXFUN(mbsnrtowcs, (wchar_t *__restrict, const char **__restrict, + size_t, size_t, mbstate_t *__restrict)); +size_t _EXFUN(_mbsnrtowcs_r, (struct _reent *, wchar_t * , const char ** , + size_t, size_t, mbstate_t *)); +size_t _EXFUN(mbsrtowcs, (wchar_t *__restrict, const char **__restrict, size_t, + mbstate_t *__restrict)); +size_t _EXFUN(_mbsrtowcs_r, (struct _reent *, wchar_t * , const char ** , size_t, mbstate_t *)); +size_t _EXFUN(wcrtomb, (char *__restrict, wchar_t, mbstate_t *__restrict)); +size_t _EXFUN(_wcrtomb_r, (struct _reent *, char * , wchar_t, mbstate_t *)); +size_t _EXFUN(wcsnrtombs, (char *__restrict, const wchar_t **__restrict, + size_t, size_t, mbstate_t *__restrict)); +size_t _EXFUN(_wcsnrtombs_r, (struct _reent *, char * , const wchar_t ** , + size_t, size_t, mbstate_t *)); +size_t _EXFUN(wcsrtombs, (char *__restrict, const wchar_t **__restrict, + size_t, mbstate_t *__restrict)); +size_t _EXFUN(_wcsrtombs_r, (struct _reent *, char * , const wchar_t ** , + size_t, mbstate_t *)); +int _EXFUN(wcscasecmp, (const wchar_t *, const wchar_t *)); +wchar_t *_EXFUN(wcscat, (wchar_t *__restrict, const wchar_t *__restrict)); +wchar_t *_EXFUN(wcschr, (const wchar_t *, wchar_t)); +int _EXFUN(wcscmp, (const wchar_t *, const wchar_t *)); +int _EXFUN(wcscoll, (const wchar_t *, const wchar_t *)); +wchar_t *_EXFUN(wcscpy, (wchar_t *__restrict, const wchar_t *__restrict)); +wchar_t *_EXFUN(wcpcpy, (wchar_t *__restrict, + const wchar_t *__restrict)); +wchar_t *_EXFUN(wcsdup, (const wchar_t *)); +wchar_t *_EXFUN(_wcsdup_r, (struct _reent *, const wchar_t * )); +size_t _EXFUN(wcscspn, (const wchar_t *, const wchar_t *)); +size_t _EXFUN(wcsftime, (wchar_t *__restrict, size_t, + const wchar_t *__restrict, const struct tm *__restrict)); +size_t _EXFUN(wcslcat, (wchar_t *, const wchar_t *, size_t)); +size_t _EXFUN(wcslcpy, (wchar_t *, const wchar_t *, size_t)); +size_t _EXFUN(wcslen, (const wchar_t *)); +int _EXFUN(wcsncasecmp, (const wchar_t *, const wchar_t *, size_t)); +wchar_t *_EXFUN(wcsncat, (wchar_t *__restrict, + const wchar_t *__restrict, size_t)); +int _EXFUN(wcsncmp, (const wchar_t *, const wchar_t *, size_t)); +wchar_t *_EXFUN(wcsncpy, (wchar_t *__restrict, + const wchar_t *__restrict, size_t)); +wchar_t *_EXFUN(wcpncpy, (wchar_t *__restrict, + const wchar_t *__restrict, size_t)); +size_t _EXFUN(wcsnlen, (const wchar_t *, size_t)); +wchar_t *_EXFUN(wcspbrk, (const wchar_t *, const wchar_t *)); +wchar_t *_EXFUN(wcsrchr, (const wchar_t *, wchar_t)); +size_t _EXFUN(wcsspn, (const wchar_t *, const wchar_t *)); +wchar_t *_EXFUN(wcsstr, (const wchar_t *__restrict, + const wchar_t *__restrict)); +wchar_t *_EXFUN(wcstok, (wchar_t *__restrict, const wchar_t *__restrict, + wchar_t **__restrict)); +double _EXFUN(wcstod, (const wchar_t *__restrict, wchar_t **__restrict)); +double _EXFUN(_wcstod_r, (struct _reent *, const wchar_t *, wchar_t **)); +float _EXFUN(wcstof, (const wchar_t *__restrict, wchar_t **__restrict)); +float _EXFUN(_wcstof_r, (struct _reent *, const wchar_t *, wchar_t **)); +#ifdef _LDBL_EQ_DBL +long double _EXFUN(wcstold, (const wchar_t *, wchar_t **)); +#endif /* _LDBL_EQ_DBL */ +int _EXFUN(wcswidth, (const wchar_t *, size_t)); +size_t _EXFUN(wcsxfrm, (wchar_t *__restrict, const wchar_t *__restrict, + size_t)); +int _EXFUN(wcwidth, (const wchar_t)); +wchar_t *_EXFUN(wmemchr, (const wchar_t *, wchar_t, size_t)); +int _EXFUN(wmemcmp, (const wchar_t *, const wchar_t *, size_t)); +wchar_t *_EXFUN(wmemcpy, (wchar_t *__restrict, const wchar_t *__restrict, + size_t)); +wchar_t *_EXFUN(wmemmove, (wchar_t *, const wchar_t *, size_t)); +wchar_t *_EXFUN(wmemset, (wchar_t *, wchar_t, size_t)); + +long _EXFUN(wcstol, (const wchar_t *__restrict, wchar_t **__restrict, int)); +long long _EXFUN(wcstoll, (const wchar_t *__restrict, wchar_t **__restrict, + int)); +unsigned long _EXFUN(wcstoul, (const wchar_t *__restrict, wchar_t **__restrict, + int)); +unsigned long long _EXFUN(wcstoull, (const wchar_t *__restrict, + wchar_t **__restrict, int)); +long _EXFUN(_wcstol_r, (struct _reent *, const wchar_t *, wchar_t **, int)); +long long _EXFUN(_wcstoll_r, (struct _reent *, const wchar_t *, wchar_t **, int)); +unsigned long _EXFUN(_wcstoul_r, (struct _reent *, const wchar_t *, wchar_t **, int)); +unsigned long long _EXFUN(_wcstoull_r, (struct _reent *, const wchar_t *, wchar_t **, int)); +/* On platforms where long double equals double. */ +#ifdef _LDBL_EQ_DBL +long double _EXFUN(wcstold, (const wchar_t *, wchar_t **)); +#endif /* _LDBL_EQ_DBL */ + +wint_t _EXFUN(fgetwc, (__FILE *)); +wchar_t *_EXFUN(fgetws, (wchar_t *__restrict, int, __FILE *__restrict)); +wint_t _EXFUN(fputwc, (wchar_t, __FILE *)); +int _EXFUN(fputws, (const wchar_t *__restrict, __FILE *__restrict)); +int _EXFUN (fwide, (__FILE *, int)); +wint_t _EXFUN (getwc, (__FILE *)); +wint_t _EXFUN (getwchar, (void)); +wint_t _EXFUN(putwc, (wchar_t, __FILE *)); +wint_t _EXFUN(putwchar, (wchar_t)); +wint_t _EXFUN (ungetwc, (wint_t wc, __FILE *)); + +wint_t _EXFUN(_fgetwc_r, (struct _reent *, __FILE *)); +wint_t _EXFUN(_fgetwc_unlocked_r, (struct _reent *, __FILE *)); +wchar_t *_EXFUN(_fgetws_r, (struct _reent *, wchar_t *, int, __FILE *)); +wchar_t *_EXFUN(_fgetws_unlocked_r, (struct _reent *, wchar_t *, int, __FILE *)); +wint_t _EXFUN(_fputwc_r, (struct _reent *, wchar_t, __FILE *)); +wint_t _EXFUN(_fputwc_unlocked_r, (struct _reent *, wchar_t, __FILE *)); +int _EXFUN(_fputws_r, (struct _reent *, const wchar_t *, __FILE *)); +int _EXFUN(_fputws_unlocked_r, (struct _reent *, const wchar_t *, __FILE *)); +int _EXFUN (_fwide_r, (struct _reent *, __FILE *, int)); +wint_t _EXFUN (_getwc_r, (struct _reent *, __FILE *)); +wint_t _EXFUN (_getwc_unlocked_r, (struct _reent *, __FILE *)); +wint_t _EXFUN (_getwchar_r, (struct _reent *ptr)); +wint_t _EXFUN (_getwchar_unlocked_r, (struct _reent *ptr)); +wint_t _EXFUN(_putwc_r, (struct _reent *, wchar_t, __FILE *)); +wint_t _EXFUN(_putwc_unlocked_r, (struct _reent *, wchar_t, __FILE *)); +wint_t _EXFUN(_putwchar_r, (struct _reent *, wchar_t)); +wint_t _EXFUN(_putwchar_unlocked_r, (struct _reent *, wchar_t)); +wint_t _EXFUN (_ungetwc_r, (struct _reent *, wint_t wc, __FILE *)); + +#if __GNU_VISIBLE +wint_t _EXFUN(fgetwc_unlocked, (__FILE *)); +wchar_t *_EXFUN(fgetws_unlocked, (wchar_t *__restrict, int, __FILE *__restrict)); +wint_t _EXFUN(fputwc_unlocked, (wchar_t, __FILE *)); +int _EXFUN(fputws_unlocked, (const wchar_t *__restrict, __FILE *__restrict)); +wint_t _EXFUN(getwc_unlocked, (__FILE *)); +wint_t _EXFUN(getwchar_unlocked, (void)); +wint_t _EXFUN(putwc_unlocked, (wchar_t, __FILE *)); +wint_t _EXFUN(putwchar_unlocked, (wchar_t)); +#endif + +__FILE *_EXFUN (open_wmemstream, (wchar_t **, size_t *)); +__FILE *_EXFUN (_open_wmemstream_r, (struct _reent *, wchar_t **, size_t *)); + +#ifndef __VALIST +#ifdef __GNUC__ +#define __VALIST __gnuc_va_list +#else +#define __VALIST char* +#endif +#endif + +int _EXFUN(fwprintf, (__FILE *__restrict, const wchar_t *__restrict, ...)); +int _EXFUN(swprintf, (wchar_t *__restrict, size_t, + const wchar_t *__restrict, ...)); +int _EXFUN(vfwprintf, (__FILE *__restrict, const wchar_t *__restrict, + __VALIST)); +int _EXFUN(vswprintf, (wchar_t *__restrict, size_t, + const wchar_t *__restrict, __VALIST)); +int _EXFUN(vwprintf, (const wchar_t *__restrict, __VALIST)); +int _EXFUN(wprintf, (const wchar_t *__restrict, ...)); + +int _EXFUN(_fwprintf_r, (struct _reent *, __FILE *, const wchar_t *, ...)); +int _EXFUN(_swprintf_r, (struct _reent *, wchar_t *, size_t, const wchar_t *, ...)); +int _EXFUN(_vfwprintf_r, (struct _reent *, __FILE *, const wchar_t *, __VALIST)); +int _EXFUN(_vswprintf_r, (struct _reent *, wchar_t *, size_t, const wchar_t *, __VALIST)); +int _EXFUN(_vwprintf_r, (struct _reent *, const wchar_t *, __VALIST)); +int _EXFUN(_wprintf_r, (struct _reent *, const wchar_t *, ...)); + +int _EXFUN(fwscanf, (__FILE *__restrict, const wchar_t *__restrict, ...)); +int _EXFUN(swscanf, (const wchar_t *__restrict, + const wchar_t *__restrict, ...)); +int _EXFUN(vfwscanf, (__FILE *__restrict, const wchar_t *__restrict, + __VALIST)); +int _EXFUN(vswscanf, (const wchar_t *__restrict, const wchar_t *__restrict, + __VALIST)); +int _EXFUN(vwscanf, (const wchar_t *__restrict, __VALIST)); +int _EXFUN(wscanf, (const wchar_t *__restrict, ...)); + +int _EXFUN(_fwscanf_r, (struct _reent *, __FILE *, const wchar_t *, ...)); +int _EXFUN(_swscanf_r, (struct _reent *, const wchar_t *, const wchar_t *, ...)); +int _EXFUN(_vfwscanf_r, (struct _reent *, __FILE *, const wchar_t *, __VALIST)); +int _EXFUN(_vswscanf_r, (struct _reent *, const wchar_t *, const wchar_t *, __VALIST)); +int _EXFUN(_vwscanf_r, (struct _reent *, const wchar_t *, __VALIST)); +int _EXFUN(_wscanf_r, (struct _reent *, const wchar_t *, ...)); + +#define getwc(fp) fgetwc(fp) +#define putwc(wc,fp) fputwc((wc), (fp)) +#define getwchar() fgetwc(_REENT->_stdin) +#define putwchar(wc) fputwc((wc), _REENT->_stdout) + +#if __GNU_VISIBLE +#define getwc_unlocked(fp) fgetwc_unlocked(fp) +#define putwc_unlocked(wc,fp) fputwc_unlocked((wc), (fp)) +#define getwchar_unlocked() fgetwc_unlocked(_REENT->_stdin) +#define putwchar_unlocked(wc) fputwc_unlocked((wc), _REENT->_stdout) +#endif + +_END_STD_C + +#endif /* _WCHAR_H_ */ diff --git a/components/newlib/include/wctype.h b/components/newlib/include/wctype.h new file mode 100644 index 0000000000..c72c9decff --- /dev/null +++ b/components/newlib/include/wctype.h @@ -0,0 +1,47 @@ +#ifndef _WCTYPE_H_ +#define _WCTYPE_H_ + +#include <_ansi.h> +#include + +#define __need_wint_t +#include + +#ifndef WEOF +# define WEOF ((wint_t)-1) +#endif + +_BEGIN_STD_C + +#ifndef _WCTYPE_T +#define _WCTYPE_T +typedef int wctype_t; +#endif + +#ifndef _WCTRANS_T +#define _WCTRANS_T +typedef int wctrans_t; +#endif + +int _EXFUN(iswalpha, (wint_t)); +int _EXFUN(iswalnum, (wint_t)); +int _EXFUN(iswblank, (wint_t)); +int _EXFUN(iswcntrl, (wint_t)); +int _EXFUN(iswctype, (wint_t, wctype_t)); +int _EXFUN(iswdigit, (wint_t)); +int _EXFUN(iswgraph, (wint_t)); +int _EXFUN(iswlower, (wint_t)); +int _EXFUN(iswprint, (wint_t)); +int _EXFUN(iswpunct, (wint_t)); +int _EXFUN(iswspace, (wint_t)); +int _EXFUN(iswupper, (wint_t)); +int _EXFUN(iswxdigit, (wint_t)); +wint_t _EXFUN(towctrans, (wint_t, wctrans_t)); +wint_t _EXFUN(towupper, (wint_t)); +wint_t _EXFUN(towlower, (wint_t)); +wctrans_t _EXFUN(wctrans, (const char *)); +wctype_t _EXFUN(wctype, (const char *)); + +_END_STD_C + +#endif /* _WCTYPE_H_ */ diff --git a/components/newlib/include/wordexp.h b/components/newlib/include/wordexp.h new file mode 100644 index 0000000000..1f09a64c5e --- /dev/null +++ b/components/newlib/include/wordexp.h @@ -0,0 +1,53 @@ +/* Copyright (C) 2002, 2010 by Red Hat, Incorporated. All rights reserved. + * + * Permission to use, copy, modify, and distribute this software + * is freely granted, provided that this notice is preserved. + */ + +#ifndef _WORDEXP_H_ +#define _WORDEXP_H_ + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +struct _wordexp_t +{ + size_t we_wordc; /* Count of words matched by words. */ + char **we_wordv; /* Pointer to list of expanded words. */ + size_t we_offs; /* Slots to reserve at the beginning of we_wordv. */ +}; + +typedef struct _wordexp_t wordexp_t; + +#define WRDE_DOOFFS 0x0001 /* Use we_offs. */ +#define WRDE_APPEND 0x0002 /* Append to output from previous call. */ +#define WRDE_NOCMD 0x0004 /* Don't perform command substitution. */ +#define WRDE_REUSE 0x0008 /* pwordexp points to a wordexp_t struct returned from + a previous successful call to wordexp. */ +#define WRDE_SHOWERR 0x0010 /* Print error messages to stderr. */ +#define WRDE_UNDEF 0x0020 /* Report attempt to expand undefined shell variable. */ + +enum { + WRDE_SUCCESS, + WRDE_NOSPACE, + WRDE_BADCHAR, + WRDE_BADVAL, + WRDE_CMDSUB, + WRDE_SYNTAX, + WRDE_NOSYS +}; + +/* Note: This implementation of wordexp requires a version of bash + that supports the --wordexp and --protected arguments to be present + on the system. It does not support the WRDE_UNDEF flag. */ +int wordexp(const char *__restrict, wordexp_t *__restrict, int); +void wordfree(wordexp_t *); + +#ifdef __cplusplus +} +#endif + +#endif /* _WORDEXP_H_ */ diff --git a/components/newlib/include/xtensa/config/core-isa.h b/components/newlib/include/xtensa/config/core-isa.h new file mode 100644 index 0000000000..f3f4e45f00 --- /dev/null +++ b/components/newlib/include/xtensa/config/core-isa.h @@ -0,0 +1,655 @@ +/* + * xtensa/config/core-isa.h -- HAL definitions that are dependent on Xtensa + * processor CORE configuration + * + * See , which includes this file, for more details. + */ + +/* Xtensa processor core configuration information. + + Copyright (c) 1999-2016 Tensilica Inc. + + Permission is hereby granted, free of charge, to any person obtaining + a copy of this software and associated documentation files (the + "Software"), to deal in the Software without restriction, including + without limitation the rights to use, copy, modify, merge, publish, + distribute, sublicense, and/or sell copies of the Software, and to + permit persons to whom the Software is furnished to do so, subject to + the following conditions: + + The above copyright notice and this permission notice shall be included + in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY + CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ + +#ifndef _XTENSA_CORE_CONFIGURATION_H +#define _XTENSA_CORE_CONFIGURATION_H + + +/**************************************************************************** + Parameters Useful for Any Code, USER or PRIVILEGED + ****************************************************************************/ + +/* + * Note: Macros of the form XCHAL_HAVE_*** have a value of 1 if the option is + * configured, and a value of 0 otherwise. These macros are always defined. + */ + + +/*---------------------------------------------------------------------- + ISA + ----------------------------------------------------------------------*/ + +#define XCHAL_HAVE_BE 0 /* big-endian byte ordering */ +#define XCHAL_HAVE_WINDOWED 1 /* windowed registers option */ +#define XCHAL_NUM_AREGS 64 /* num of physical addr regs */ +#define XCHAL_NUM_AREGS_LOG2 6 /* log2(XCHAL_NUM_AREGS) */ +#define XCHAL_MAX_INSTRUCTION_SIZE 3 /* max instr bytes (3..8) */ +#define XCHAL_HAVE_DEBUG 1 /* debug option */ +#define XCHAL_HAVE_DENSITY 1 /* 16-bit instructions */ +#define XCHAL_HAVE_LOOPS 1 /* zero-overhead loops */ +#define XCHAL_LOOP_BUFFER_SIZE 256 /* zero-ov. loop instr buffer size */ +#define XCHAL_HAVE_NSA 1 /* NSA/NSAU instructions */ +#define XCHAL_HAVE_MINMAX 1 /* MIN/MAX instructions */ +#define XCHAL_HAVE_SEXT 1 /* SEXT instruction */ +#define XCHAL_HAVE_DEPBITS 0 /* DEPBITS instruction */ +#define XCHAL_HAVE_CLAMPS 1 /* CLAMPS instruction */ +#define XCHAL_HAVE_MUL16 1 /* MUL16S/MUL16U instructions */ +#define XCHAL_HAVE_MUL32 1 /* MULL instruction */ +#define XCHAL_HAVE_MUL32_HIGH 1 /* MULUH/MULSH instructions */ +#define XCHAL_HAVE_DIV32 1 /* QUOS/QUOU/REMS/REMU instructions */ +#define XCHAL_HAVE_L32R 1 /* L32R instruction */ +#define XCHAL_HAVE_ABSOLUTE_LITERALS 0 /* non-PC-rel (extended) L32R */ +#define XCHAL_HAVE_CONST16 0 /* CONST16 instruction */ +#define XCHAL_HAVE_ADDX 1 /* ADDX#/SUBX# instructions */ +#define XCHAL_HAVE_WIDE_BRANCHES 0 /* B*.W18 or B*.W15 instr's */ +#define XCHAL_HAVE_PREDICTED_BRANCHES 0 /* B[EQ/EQZ/NE/NEZ]T instr's */ +#define XCHAL_HAVE_CALL4AND12 1 /* (obsolete option) */ +#define XCHAL_HAVE_ABS 1 /* ABS instruction */ +/*#define XCHAL_HAVE_POPC 0*/ /* POPC instruction */ +/*#define XCHAL_HAVE_CRC 0*/ /* CRC instruction */ +#define XCHAL_HAVE_RELEASE_SYNC 1 /* L32AI/S32RI instructions */ +#define XCHAL_HAVE_S32C1I 1 /* S32C1I instruction */ +#define XCHAL_HAVE_SPECULATION 0 /* speculation */ +#define XCHAL_HAVE_FULL_RESET 1 /* all regs/state reset */ +#define XCHAL_NUM_CONTEXTS 1 /* */ +#define XCHAL_NUM_MISC_REGS 4 /* num of scratch regs (0..4) */ +#define XCHAL_HAVE_TAP_MASTER 0 /* JTAG TAP control instr's */ +#define XCHAL_HAVE_PRID 1 /* processor ID register */ +#define XCHAL_HAVE_EXTERN_REGS 1 /* WER/RER instructions */ +#define XCHAL_HAVE_MX 0 /* MX core (Tensilica internal) */ +#define XCHAL_HAVE_MP_INTERRUPTS 0 /* interrupt distributor port */ +#define XCHAL_HAVE_MP_RUNSTALL 0 /* core RunStall control port */ +#define XCHAL_HAVE_PSO 0 /* Power Shut-Off */ +#define XCHAL_HAVE_PSO_CDM 0 /* core/debug/mem pwr domains */ +#define XCHAL_HAVE_PSO_FULL_RETENTION 0 /* all regs preserved on PSO */ +#define XCHAL_HAVE_THREADPTR 1 /* THREADPTR register */ +#define XCHAL_HAVE_BOOLEANS 1 /* boolean registers */ +#define XCHAL_HAVE_CP 1 /* CPENABLE reg (coprocessor) */ +#define XCHAL_CP_MAXCFG 8 /* max allowed cp id plus one */ +#define XCHAL_HAVE_MAC16 1 /* MAC16 package */ + +#define XCHAL_HAVE_FUSION 0 /* Fusion*/ +#define XCHAL_HAVE_FUSION_FP 0 /* Fusion FP option */ +#define XCHAL_HAVE_FUSION_LOW_POWER 0 /* Fusion Low Power option */ +#define XCHAL_HAVE_FUSION_AES 0 /* Fusion BLE/Wifi AES-128 CCM option */ +#define XCHAL_HAVE_FUSION_CONVENC 0 /* Fusion Conv Encode option */ +#define XCHAL_HAVE_FUSION_LFSR_CRC 0 /* Fusion LFSR-CRC option */ +#define XCHAL_HAVE_FUSION_BITOPS 0 /* Fusion Bit Operations Support option */ +#define XCHAL_HAVE_FUSION_AVS 0 /* Fusion AVS option */ +#define XCHAL_HAVE_FUSION_16BIT_BASEBAND 0 /* Fusion 16-bit Baseband option */ +#define XCHAL_HAVE_FUSION_VITERBI 0 /* Fusion Viterbi option */ +#define XCHAL_HAVE_FUSION_SOFTDEMAP 0 /* Fusion Soft Bit Demap option */ +#define XCHAL_HAVE_HIFIPRO 0 /* HiFiPro Audio Engine pkg */ +#define XCHAL_HAVE_HIFI4 0 /* HiFi4 Audio Engine pkg */ +#define XCHAL_HAVE_HIFI4_VFPU 0 /* HiFi4 Audio Engine VFPU option */ +#define XCHAL_HAVE_HIFI3 0 /* HiFi3 Audio Engine pkg */ +#define XCHAL_HAVE_HIFI3_VFPU 0 /* HiFi3 Audio Engine VFPU option */ +#define XCHAL_HAVE_HIFI2 0 /* HiFi2 Audio Engine pkg */ +#define XCHAL_HAVE_HIFI2EP 0 /* HiFi2EP */ +#define XCHAL_HAVE_HIFI_MINI 0 + + +#define XCHAL_HAVE_VECTORFPU2005 0 /* vector or user floating-point pkg */ +#define XCHAL_HAVE_USER_DPFPU 0 /* user DP floating-point pkg */ +#define XCHAL_HAVE_USER_SPFPU 0 /* user DP floating-point pkg */ +#define XCHAL_HAVE_FP 1 /* single prec floating point */ +#define XCHAL_HAVE_FP_DIV 1 /* FP with DIV instructions */ +#define XCHAL_HAVE_FP_RECIP 1 /* FP with RECIP instructions */ +#define XCHAL_HAVE_FP_SQRT 1 /* FP with SQRT instructions */ +#define XCHAL_HAVE_FP_RSQRT 1 /* FP with RSQRT instructions */ +#define XCHAL_HAVE_DFP 0 /* double precision FP pkg */ +#define XCHAL_HAVE_DFP_DIV 0 /* DFP with DIV instructions */ +#define XCHAL_HAVE_DFP_RECIP 0 /* DFP with RECIP instructions*/ +#define XCHAL_HAVE_DFP_SQRT 0 /* DFP with SQRT instructions */ +#define XCHAL_HAVE_DFP_RSQRT 0 /* DFP with RSQRT instructions*/ +#define XCHAL_HAVE_DFP_ACCEL 1 /* double precision FP acceleration pkg */ +#define XCHAL_HAVE_DFP_accel XCHAL_HAVE_DFP_ACCEL /* for backward compatibility */ + +#define XCHAL_HAVE_DFPU_SINGLE_ONLY 1 /* DFPU Coprocessor, single precision only */ +#define XCHAL_HAVE_DFPU_SINGLE_DOUBLE 0 /* DFPU Coprocessor, single and double precision */ +#define XCHAL_HAVE_VECTRA1 0 /* Vectra I pkg */ +#define XCHAL_HAVE_VECTRALX 0 /* Vectra LX pkg */ +#define XCHAL_HAVE_PDX4 0 /* PDX4 */ +#define XCHAL_HAVE_CONNXD2 0 /* ConnX D2 pkg */ +#define XCHAL_HAVE_CONNXD2_DUALLSFLIX 0 /* ConnX D2 & Dual LoadStore Flix */ +#define XCHAL_HAVE_BBE16 0 /* ConnX BBE16 pkg */ +#define XCHAL_HAVE_BBE16_RSQRT 0 /* BBE16 & vector recip sqrt */ +#define XCHAL_HAVE_BBE16_VECDIV 0 /* BBE16 & vector divide */ +#define XCHAL_HAVE_BBE16_DESPREAD 0 /* BBE16 & despread */ +#define XCHAL_HAVE_BBENEP 0 /* ConnX BBENEP pkgs */ +#define XCHAL_HAVE_BSP3 0 /* ConnX BSP3 pkg */ +#define XCHAL_HAVE_BSP3_TRANSPOSE 0 /* BSP3 & transpose32x32 */ +#define XCHAL_HAVE_SSP16 0 /* ConnX SSP16 pkg */ +#define XCHAL_HAVE_SSP16_VITERBI 0 /* SSP16 & viterbi */ +#define XCHAL_HAVE_TURBO16 0 /* ConnX Turbo16 pkg */ +#define XCHAL_HAVE_BBP16 0 /* ConnX BBP16 pkg */ +#define XCHAL_HAVE_FLIX3 0 /* basic 3-way FLIX option */ +#define XCHAL_HAVE_GRIVPEP 0 /* GRIVPEP is General Release of IVPEP */ +#define XCHAL_HAVE_GRIVPEP_HISTOGRAM 0 /* Histogram option on GRIVPEP */ + + +/*---------------------------------------------------------------------- + MISC + ----------------------------------------------------------------------*/ + +#define XCHAL_NUM_LOADSTORE_UNITS 1 /* load/store units */ +#define XCHAL_NUM_WRITEBUFFER_ENTRIES 4 /* size of write buffer */ +#define XCHAL_INST_FETCH_WIDTH 4 /* instr-fetch width in bytes */ +#define XCHAL_DATA_WIDTH 4 /* data width in bytes */ +#define XCHAL_DATA_PIPE_DELAY 2 /* d-side pipeline delay + (1 = 5-stage, 2 = 7-stage) */ +#define XCHAL_CLOCK_GATING_GLOBAL 1 /* global clock gating */ +#define XCHAL_CLOCK_GATING_FUNCUNIT 1 /* funct. unit clock gating */ +/* In T1050, applies to selected core load and store instructions (see ISA): */ +#define XCHAL_UNALIGNED_LOAD_EXCEPTION 0 /* unaligned loads cause exc. */ +#define XCHAL_UNALIGNED_STORE_EXCEPTION 0 /* unaligned stores cause exc.*/ +#define XCHAL_UNALIGNED_LOAD_HW 1 /* unaligned loads work in hw */ +#define XCHAL_UNALIGNED_STORE_HW 1 /* unaligned stores work in hw*/ + +#define XCHAL_SW_VERSION 1100003 /* sw version of this header */ + +#define XCHAL_CORE_ID "esp32_v3_49_prod" /* alphanum core name + (CoreID) set in the Xtensa + Processor Generator */ + +#define XCHAL_BUILD_UNIQUE_ID 0x0005FE96 /* 22-bit sw build ID */ + +/* + * These definitions describe the hardware targeted by this software. + */ +#define XCHAL_HW_CONFIGID0 0xC2BCFFFE /* ConfigID hi 32 bits*/ +#define XCHAL_HW_CONFIGID1 0x1CC5FE96 /* ConfigID lo 32 bits*/ +#define XCHAL_HW_VERSION_NAME "LX6.0.3" /* full version name */ +#define XCHAL_HW_VERSION_MAJOR 2600 /* major ver# of targeted hw */ +#define XCHAL_HW_VERSION_MINOR 3 /* minor ver# of targeted hw */ +#define XCHAL_HW_VERSION 260003 /* major*100+minor */ +#define XCHAL_HW_REL_LX6 1 +#define XCHAL_HW_REL_LX6_0 1 +#define XCHAL_HW_REL_LX6_0_3 1 +#define XCHAL_HW_CONFIGID_RELIABLE 1 +/* If software targets a *range* of hardware versions, these are the bounds: */ +#define XCHAL_HW_MIN_VERSION_MAJOR 2600 /* major v of earliest tgt hw */ +#define XCHAL_HW_MIN_VERSION_MINOR 3 /* minor v of earliest tgt hw */ +#define XCHAL_HW_MIN_VERSION 260003 /* earliest targeted hw */ +#define XCHAL_HW_MAX_VERSION_MAJOR 2600 /* major v of latest tgt hw */ +#define XCHAL_HW_MAX_VERSION_MINOR 3 /* minor v of latest tgt hw */ +#define XCHAL_HW_MAX_VERSION 260003 /* latest targeted hw */ + + +/*---------------------------------------------------------------------- + CACHE + ----------------------------------------------------------------------*/ + +#define XCHAL_ICACHE_LINESIZE 4 /* I-cache line size in bytes */ +#define XCHAL_DCACHE_LINESIZE 4 /* D-cache line size in bytes */ +#define XCHAL_ICACHE_LINEWIDTH 2 /* log2(I line size in bytes) */ +#define XCHAL_DCACHE_LINEWIDTH 2 /* log2(D line size in bytes) */ + +#define XCHAL_ICACHE_SIZE 0 /* I-cache size in bytes or 0 */ +#define XCHAL_DCACHE_SIZE 0 /* D-cache size in bytes or 0 */ + +#define XCHAL_DCACHE_IS_WRITEBACK 0 /* writeback feature */ +#define XCHAL_DCACHE_IS_COHERENT 0 /* MP coherence feature */ + +#define XCHAL_HAVE_PREFETCH 0 /* PREFCTL register */ +#define XCHAL_HAVE_PREFETCH_L1 0 /* prefetch to L1 dcache */ +#define XCHAL_PREFETCH_CASTOUT_LINES 0 /* dcache pref. castout bufsz */ +#define XCHAL_PREFETCH_ENTRIES 0 /* cache prefetch entries */ +#define XCHAL_PREFETCH_BLOCK_ENTRIES 0 /* prefetch block streams */ +#define XCHAL_HAVE_CACHE_BLOCKOPS 0 /* block prefetch for caches */ +#define XCHAL_HAVE_ICACHE_TEST 0 /* Icache test instructions */ +#define XCHAL_HAVE_DCACHE_TEST 0 /* Dcache test instructions */ +#define XCHAL_HAVE_ICACHE_DYN_WAYS 0 /* Icache dynamic way support */ +#define XCHAL_HAVE_DCACHE_DYN_WAYS 0 /* Dcache dynamic way support */ + + + + +/**************************************************************************** + Parameters Useful for PRIVILEGED (Supervisory or Non-Virtualized) Code + ****************************************************************************/ + + +#ifndef XTENSA_HAL_NON_PRIVILEGED_ONLY + +/*---------------------------------------------------------------------- + CACHE + ----------------------------------------------------------------------*/ + +#define XCHAL_HAVE_PIF 1 /* any outbound PIF present */ +#define XCHAL_HAVE_AXI 0 /* AXI bus */ + +#define XCHAL_HAVE_PIF_WR_RESP 0 /* pif write response */ +#define XCHAL_HAVE_PIF_REQ_ATTR 0 /* pif attribute */ + +/* If present, cache size in bytes == (ways * 2^(linewidth + setwidth)). */ + +/* Number of cache sets in log2(lines per way): */ +#define XCHAL_ICACHE_SETWIDTH 0 +#define XCHAL_DCACHE_SETWIDTH 0 + +/* Cache set associativity (number of ways): */ +#define XCHAL_ICACHE_WAYS 1 +#define XCHAL_DCACHE_WAYS 1 + +/* Cache features: */ +#define XCHAL_ICACHE_LINE_LOCKABLE 0 +#define XCHAL_DCACHE_LINE_LOCKABLE 0 +#define XCHAL_ICACHE_ECC_PARITY 0 +#define XCHAL_DCACHE_ECC_PARITY 0 + +/* Cache access size in bytes (affects operation of SICW instruction): */ +#define XCHAL_ICACHE_ACCESS_SIZE 1 +#define XCHAL_DCACHE_ACCESS_SIZE 1 + +#define XCHAL_DCACHE_BANKS 0 /* number of banks */ + +/* Number of encoded cache attr bits (see for decoded bits): */ +#define XCHAL_CA_BITS 4 + + +/*---------------------------------------------------------------------- + INTERNAL I/D RAM/ROMs and XLMI + ----------------------------------------------------------------------*/ + +#define XCHAL_NUM_INSTROM 1 /* number of core instr. ROMs */ +#define XCHAL_NUM_INSTRAM 2 /* number of core instr. RAMs */ +#define XCHAL_NUM_DATAROM 1 /* number of core data ROMs */ +#define XCHAL_NUM_DATARAM 2 /* number of core data RAMs */ +#define XCHAL_NUM_URAM 0 /* number of core unified RAMs*/ +#define XCHAL_NUM_XLMI 1 /* number of core XLMI ports */ + +/* Instruction ROM 0: */ +#define XCHAL_INSTROM0_VADDR 0x40800000 /* virtual address */ +#define XCHAL_INSTROM0_PADDR 0x40800000 /* physical address */ +#define XCHAL_INSTROM0_SIZE 4194304 /* size in bytes */ +#define XCHAL_INSTROM0_ECC_PARITY 0 /* ECC/parity type, 0=none */ + +/* Instruction RAM 0: */ +#define XCHAL_INSTRAM0_VADDR 0x40000000 /* virtual address */ +#define XCHAL_INSTRAM0_PADDR 0x40000000 /* physical address */ +#define XCHAL_INSTRAM0_SIZE 4194304 /* size in bytes */ +#define XCHAL_INSTRAM0_ECC_PARITY 0 /* ECC/parity type, 0=none */ + +/* Instruction RAM 1: */ +#define XCHAL_INSTRAM1_VADDR 0x40400000 /* virtual address */ +#define XCHAL_INSTRAM1_PADDR 0x40400000 /* physical address */ +#define XCHAL_INSTRAM1_SIZE 4194304 /* size in bytes */ +#define XCHAL_INSTRAM1_ECC_PARITY 0 /* ECC/parity type, 0=none */ + +/* Data ROM 0: */ +#define XCHAL_DATAROM0_VADDR 0x3F400000 /* virtual address */ +#define XCHAL_DATAROM0_PADDR 0x3F400000 /* physical address */ +#define XCHAL_DATAROM0_SIZE 4194304 /* size in bytes */ +#define XCHAL_DATAROM0_ECC_PARITY 0 /* ECC/parity type, 0=none */ +#define XCHAL_DATAROM0_BANKS 1 /* number of banks */ + +/* Data RAM 0: */ +#define XCHAL_DATARAM0_VADDR 0x3FF80000 /* virtual address */ +#define XCHAL_DATARAM0_PADDR 0x3FF80000 /* physical address */ +#define XCHAL_DATARAM0_SIZE 524288 /* size in bytes */ +#define XCHAL_DATARAM0_ECC_PARITY 0 /* ECC/parity type, 0=none */ +#define XCHAL_DATARAM0_BANKS 1 /* number of banks */ + +/* Data RAM 1: */ +#define XCHAL_DATARAM1_VADDR 0x3F800000 /* virtual address */ +#define XCHAL_DATARAM1_PADDR 0x3F800000 /* physical address */ +#define XCHAL_DATARAM1_SIZE 4194304 /* size in bytes */ +#define XCHAL_DATARAM1_ECC_PARITY 0 /* ECC/parity type, 0=none */ +#define XCHAL_DATARAM1_BANKS 1 /* number of banks */ + +/* XLMI Port 0: */ +#define XCHAL_XLMI0_VADDR 0x3FF00000 /* virtual address */ +#define XCHAL_XLMI0_PADDR 0x3FF00000 /* physical address */ +#define XCHAL_XLMI0_SIZE 524288 /* size in bytes */ +#define XCHAL_XLMI0_ECC_PARITY 0 /* ECC/parity type, 0=none */ + +#define XCHAL_HAVE_IMEM_LOADSTORE 1 /* can load/store to IROM/IRAM*/ + + +/*---------------------------------------------------------------------- + INTERRUPTS and TIMERS + ----------------------------------------------------------------------*/ + +#define XCHAL_HAVE_INTERRUPTS 1 /* interrupt option */ +#define XCHAL_HAVE_HIGHPRI_INTERRUPTS 1 /* med/high-pri. interrupts */ +#define XCHAL_HAVE_NMI 1 /* non-maskable interrupt */ +#define XCHAL_HAVE_CCOUNT 1 /* CCOUNT reg. (timer option) */ +#define XCHAL_NUM_TIMERS 3 /* number of CCOMPAREn regs */ +#define XCHAL_NUM_INTERRUPTS 32 /* number of interrupts */ +#define XCHAL_NUM_INTERRUPTS_LOG2 5 /* ceil(log2(NUM_INTERRUPTS)) */ +#define XCHAL_NUM_EXTINTERRUPTS 26 /* num of external interrupts */ +#define XCHAL_NUM_INTLEVELS 6 /* number of interrupt levels + (not including level zero) */ +#define XCHAL_EXCM_LEVEL 3 /* level masked by PS.EXCM */ + /* (always 1 in XEA1; levels 2 .. EXCM_LEVEL are "medium priority") */ + +/* Masks of interrupts at each interrupt level: */ +#define XCHAL_INTLEVEL1_MASK 0x000637FF +#define XCHAL_INTLEVEL2_MASK 0x00380000 +#define XCHAL_INTLEVEL3_MASK 0x28C08800 +#define XCHAL_INTLEVEL4_MASK 0x53000000 +#define XCHAL_INTLEVEL5_MASK 0x84010000 +#define XCHAL_INTLEVEL6_MASK 0x00000000 +#define XCHAL_INTLEVEL7_MASK 0x00004000 + +/* Masks of interrupts at each range 1..n of interrupt levels: */ +#define XCHAL_INTLEVEL1_ANDBELOW_MASK 0x000637FF +#define XCHAL_INTLEVEL2_ANDBELOW_MASK 0x003E37FF +#define XCHAL_INTLEVEL3_ANDBELOW_MASK 0x28FEBFFF +#define XCHAL_INTLEVEL4_ANDBELOW_MASK 0x7BFEBFFF +#define XCHAL_INTLEVEL5_ANDBELOW_MASK 0xFFFFBFFF +#define XCHAL_INTLEVEL6_ANDBELOW_MASK 0xFFFFBFFF +#define XCHAL_INTLEVEL7_ANDBELOW_MASK 0xFFFFFFFF + +/* Level of each interrupt: */ +#define XCHAL_INT0_LEVEL 1 +#define XCHAL_INT1_LEVEL 1 +#define XCHAL_INT2_LEVEL 1 +#define XCHAL_INT3_LEVEL 1 +#define XCHAL_INT4_LEVEL 1 +#define XCHAL_INT5_LEVEL 1 +#define XCHAL_INT6_LEVEL 1 +#define XCHAL_INT7_LEVEL 1 +#define XCHAL_INT8_LEVEL 1 +#define XCHAL_INT9_LEVEL 1 +#define XCHAL_INT10_LEVEL 1 +#define XCHAL_INT11_LEVEL 3 +#define XCHAL_INT12_LEVEL 1 +#define XCHAL_INT13_LEVEL 1 +#define XCHAL_INT14_LEVEL 7 +#define XCHAL_INT15_LEVEL 3 +#define XCHAL_INT16_LEVEL 5 +#define XCHAL_INT17_LEVEL 1 +#define XCHAL_INT18_LEVEL 1 +#define XCHAL_INT19_LEVEL 2 +#define XCHAL_INT20_LEVEL 2 +#define XCHAL_INT21_LEVEL 2 +#define XCHAL_INT22_LEVEL 3 +#define XCHAL_INT23_LEVEL 3 +#define XCHAL_INT24_LEVEL 4 +#define XCHAL_INT25_LEVEL 4 +#define XCHAL_INT26_LEVEL 5 +#define XCHAL_INT27_LEVEL 3 +#define XCHAL_INT28_LEVEL 4 +#define XCHAL_INT29_LEVEL 3 +#define XCHAL_INT30_LEVEL 4 +#define XCHAL_INT31_LEVEL 5 +#define XCHAL_DEBUGLEVEL 6 /* debug interrupt level */ +#define XCHAL_HAVE_DEBUG_EXTERN_INT 1 /* OCD external db interrupt */ +#define XCHAL_NMILEVEL 7 /* NMI "level" (for use with + EXCSAVE/EPS/EPC_n, RFI n) */ + +/* Type of each interrupt: */ +#define XCHAL_INT0_TYPE XTHAL_INTTYPE_EXTERN_LEVEL +#define XCHAL_INT1_TYPE XTHAL_INTTYPE_EXTERN_LEVEL +#define XCHAL_INT2_TYPE XTHAL_INTTYPE_EXTERN_LEVEL +#define XCHAL_INT3_TYPE XTHAL_INTTYPE_EXTERN_LEVEL +#define XCHAL_INT4_TYPE XTHAL_INTTYPE_EXTERN_LEVEL +#define XCHAL_INT5_TYPE XTHAL_INTTYPE_EXTERN_LEVEL +#define XCHAL_INT6_TYPE XTHAL_INTTYPE_TIMER +#define XCHAL_INT7_TYPE XTHAL_INTTYPE_SOFTWARE +#define XCHAL_INT8_TYPE XTHAL_INTTYPE_EXTERN_LEVEL +#define XCHAL_INT9_TYPE XTHAL_INTTYPE_EXTERN_LEVEL +#define XCHAL_INT10_TYPE XTHAL_INTTYPE_EXTERN_EDGE +#define XCHAL_INT11_TYPE XTHAL_INTTYPE_PROFILING +#define XCHAL_INT12_TYPE XTHAL_INTTYPE_EXTERN_LEVEL +#define XCHAL_INT13_TYPE XTHAL_INTTYPE_EXTERN_LEVEL +#define XCHAL_INT14_TYPE XTHAL_INTTYPE_NMI +#define XCHAL_INT15_TYPE XTHAL_INTTYPE_TIMER +#define XCHAL_INT16_TYPE XTHAL_INTTYPE_TIMER +#define XCHAL_INT17_TYPE XTHAL_INTTYPE_EXTERN_LEVEL +#define XCHAL_INT18_TYPE XTHAL_INTTYPE_EXTERN_LEVEL +#define XCHAL_INT19_TYPE XTHAL_INTTYPE_EXTERN_LEVEL +#define XCHAL_INT20_TYPE XTHAL_INTTYPE_EXTERN_LEVEL +#define XCHAL_INT21_TYPE XTHAL_INTTYPE_EXTERN_LEVEL +#define XCHAL_INT22_TYPE XTHAL_INTTYPE_EXTERN_EDGE +#define XCHAL_INT23_TYPE XTHAL_INTTYPE_EXTERN_LEVEL +#define XCHAL_INT24_TYPE XTHAL_INTTYPE_EXTERN_LEVEL +#define XCHAL_INT25_TYPE XTHAL_INTTYPE_EXTERN_LEVEL +#define XCHAL_INT26_TYPE XTHAL_INTTYPE_EXTERN_LEVEL +#define XCHAL_INT27_TYPE XTHAL_INTTYPE_EXTERN_LEVEL +#define XCHAL_INT28_TYPE XTHAL_INTTYPE_EXTERN_EDGE +#define XCHAL_INT29_TYPE XTHAL_INTTYPE_SOFTWARE +#define XCHAL_INT30_TYPE XTHAL_INTTYPE_EXTERN_EDGE +#define XCHAL_INT31_TYPE XTHAL_INTTYPE_EXTERN_LEVEL + +/* Masks of interrupts for each type of interrupt: */ +#define XCHAL_INTTYPE_MASK_UNCONFIGURED 0x00000000 +#define XCHAL_INTTYPE_MASK_SOFTWARE 0x20000080 +#define XCHAL_INTTYPE_MASK_EXTERN_EDGE 0x50400400 +#define XCHAL_INTTYPE_MASK_EXTERN_LEVEL 0x8FBE333F +#define XCHAL_INTTYPE_MASK_TIMER 0x00018040 +#define XCHAL_INTTYPE_MASK_NMI 0x00004000 +#define XCHAL_INTTYPE_MASK_WRITE_ERROR 0x00000000 +#define XCHAL_INTTYPE_MASK_PROFILING 0x00000800 + +/* Interrupt numbers assigned to specific interrupt sources: */ +#define XCHAL_TIMER0_INTERRUPT 6 /* CCOMPARE0 */ +#define XCHAL_TIMER1_INTERRUPT 15 /* CCOMPARE1 */ +#define XCHAL_TIMER2_INTERRUPT 16 /* CCOMPARE2 */ +#define XCHAL_TIMER3_INTERRUPT XTHAL_TIMER_UNCONFIGURED +#define XCHAL_NMI_INTERRUPT 14 /* non-maskable interrupt */ +#define XCHAL_PROFILING_INTERRUPT 11 /* profiling interrupt */ + +/* Interrupt numbers for levels at which only one interrupt is configured: */ +#define XCHAL_INTLEVEL7_NUM 14 +/* (There are many interrupts each at level(s) 1, 2, 3, 4, 5.) */ + + +/* + * External interrupt mapping. + * These macros describe how Xtensa processor interrupt numbers + * (as numbered internally, eg. in INTERRUPT and INTENABLE registers) + * map to external BInterrupt pins, for those interrupts + * configured as external (level-triggered, edge-triggered, or NMI). + * See the Xtensa processor databook for more details. + */ + +/* Core interrupt numbers mapped to each EXTERNAL BInterrupt pin number: */ +#define XCHAL_EXTINT0_NUM 0 /* (intlevel 1) */ +#define XCHAL_EXTINT1_NUM 1 /* (intlevel 1) */ +#define XCHAL_EXTINT2_NUM 2 /* (intlevel 1) */ +#define XCHAL_EXTINT3_NUM 3 /* (intlevel 1) */ +#define XCHAL_EXTINT4_NUM 4 /* (intlevel 1) */ +#define XCHAL_EXTINT5_NUM 5 /* (intlevel 1) */ +#define XCHAL_EXTINT6_NUM 8 /* (intlevel 1) */ +#define XCHAL_EXTINT7_NUM 9 /* (intlevel 1) */ +#define XCHAL_EXTINT8_NUM 10 /* (intlevel 1) */ +#define XCHAL_EXTINT9_NUM 12 /* (intlevel 1) */ +#define XCHAL_EXTINT10_NUM 13 /* (intlevel 1) */ +#define XCHAL_EXTINT11_NUM 14 /* (intlevel 7) */ +#define XCHAL_EXTINT12_NUM 17 /* (intlevel 1) */ +#define XCHAL_EXTINT13_NUM 18 /* (intlevel 1) */ +#define XCHAL_EXTINT14_NUM 19 /* (intlevel 2) */ +#define XCHAL_EXTINT15_NUM 20 /* (intlevel 2) */ +#define XCHAL_EXTINT16_NUM 21 /* (intlevel 2) */ +#define XCHAL_EXTINT17_NUM 22 /* (intlevel 3) */ +#define XCHAL_EXTINT18_NUM 23 /* (intlevel 3) */ +#define XCHAL_EXTINT19_NUM 24 /* (intlevel 4) */ +#define XCHAL_EXTINT20_NUM 25 /* (intlevel 4) */ +#define XCHAL_EXTINT21_NUM 26 /* (intlevel 5) */ +#define XCHAL_EXTINT22_NUM 27 /* (intlevel 3) */ +#define XCHAL_EXTINT23_NUM 28 /* (intlevel 4) */ +#define XCHAL_EXTINT24_NUM 30 /* (intlevel 4) */ +#define XCHAL_EXTINT25_NUM 31 /* (intlevel 5) */ +/* EXTERNAL BInterrupt pin numbers mapped to each core interrupt number: */ +#define XCHAL_INT0_EXTNUM 0 /* (intlevel 1) */ +#define XCHAL_INT1_EXTNUM 1 /* (intlevel 1) */ +#define XCHAL_INT2_EXTNUM 2 /* (intlevel 1) */ +#define XCHAL_INT3_EXTNUM 3 /* (intlevel 1) */ +#define XCHAL_INT4_EXTNUM 4 /* (intlevel 1) */ +#define XCHAL_INT5_EXTNUM 5 /* (intlevel 1) */ +#define XCHAL_INT8_EXTNUM 6 /* (intlevel 1) */ +#define XCHAL_INT9_EXTNUM 7 /* (intlevel 1) */ +#define XCHAL_INT10_EXTNUM 8 /* (intlevel 1) */ +#define XCHAL_INT12_EXTNUM 9 /* (intlevel 1) */ +#define XCHAL_INT13_EXTNUM 10 /* (intlevel 1) */ +#define XCHAL_INT14_EXTNUM 11 /* (intlevel 7) */ +#define XCHAL_INT17_EXTNUM 12 /* (intlevel 1) */ +#define XCHAL_INT18_EXTNUM 13 /* (intlevel 1) */ +#define XCHAL_INT19_EXTNUM 14 /* (intlevel 2) */ +#define XCHAL_INT20_EXTNUM 15 /* (intlevel 2) */ +#define XCHAL_INT21_EXTNUM 16 /* (intlevel 2) */ +#define XCHAL_INT22_EXTNUM 17 /* (intlevel 3) */ +#define XCHAL_INT23_EXTNUM 18 /* (intlevel 3) */ +#define XCHAL_INT24_EXTNUM 19 /* (intlevel 4) */ +#define XCHAL_INT25_EXTNUM 20 /* (intlevel 4) */ +#define XCHAL_INT26_EXTNUM 21 /* (intlevel 5) */ +#define XCHAL_INT27_EXTNUM 22 /* (intlevel 3) */ +#define XCHAL_INT28_EXTNUM 23 /* (intlevel 4) */ +#define XCHAL_INT30_EXTNUM 24 /* (intlevel 4) */ +#define XCHAL_INT31_EXTNUM 25 /* (intlevel 5) */ + + +/*---------------------------------------------------------------------- + EXCEPTIONS and VECTORS + ----------------------------------------------------------------------*/ + +#define XCHAL_XEA_VERSION 2 /* Xtensa Exception Architecture + number: 1 == XEA1 (old) + 2 == XEA2 (new) + 0 == XEAX (extern) or TX */ +#define XCHAL_HAVE_XEA1 0 /* Exception Architecture 1 */ +#define XCHAL_HAVE_XEA2 1 /* Exception Architecture 2 */ +#define XCHAL_HAVE_XEAX 0 /* External Exception Arch. */ +#define XCHAL_HAVE_EXCEPTIONS 1 /* exception option */ +#define XCHAL_HAVE_HALT 0 /* halt architecture option */ +#define XCHAL_HAVE_BOOTLOADER 0 /* boot loader (for TX) */ +#define XCHAL_HAVE_MEM_ECC_PARITY 0 /* local memory ECC/parity */ +#define XCHAL_HAVE_VECTOR_SELECT 1 /* relocatable vectors */ +#define XCHAL_HAVE_VECBASE 1 /* relocatable vectors */ +#define XCHAL_VECBASE_RESET_VADDR 0x40000000 /* VECBASE reset value */ +#define XCHAL_VECBASE_RESET_PADDR 0x40000000 +#define XCHAL_RESET_VECBASE_OVERLAP 0 + +#define XCHAL_RESET_VECTOR0_VADDR 0x50000000 +#define XCHAL_RESET_VECTOR0_PADDR 0x50000000 +#define XCHAL_RESET_VECTOR1_VADDR 0x40000400 +#define XCHAL_RESET_VECTOR1_PADDR 0x40000400 +#define XCHAL_RESET_VECTOR_VADDR 0x40000400 +#define XCHAL_RESET_VECTOR_PADDR 0x40000400 +#define XCHAL_USER_VECOFS 0x00000340 +#define XCHAL_USER_VECTOR_VADDR 0x40000340 +#define XCHAL_USER_VECTOR_PADDR 0x40000340 +#define XCHAL_KERNEL_VECOFS 0x00000300 +#define XCHAL_KERNEL_VECTOR_VADDR 0x40000300 +#define XCHAL_KERNEL_VECTOR_PADDR 0x40000300 +#define XCHAL_DOUBLEEXC_VECOFS 0x000003C0 +#define XCHAL_DOUBLEEXC_VECTOR_VADDR 0x400003C0 +#define XCHAL_DOUBLEEXC_VECTOR_PADDR 0x400003C0 +#define XCHAL_WINDOW_OF4_VECOFS 0x00000000 +#define XCHAL_WINDOW_UF4_VECOFS 0x00000040 +#define XCHAL_WINDOW_OF8_VECOFS 0x00000080 +#define XCHAL_WINDOW_UF8_VECOFS 0x000000C0 +#define XCHAL_WINDOW_OF12_VECOFS 0x00000100 +#define XCHAL_WINDOW_UF12_VECOFS 0x00000140 +#define XCHAL_WINDOW_VECTORS_VADDR 0x40000000 +#define XCHAL_WINDOW_VECTORS_PADDR 0x40000000 +#define XCHAL_INTLEVEL2_VECOFS 0x00000180 +#define XCHAL_INTLEVEL2_VECTOR_VADDR 0x40000180 +#define XCHAL_INTLEVEL2_VECTOR_PADDR 0x40000180 +#define XCHAL_INTLEVEL3_VECOFS 0x000001C0 +#define XCHAL_INTLEVEL3_VECTOR_VADDR 0x400001C0 +#define XCHAL_INTLEVEL3_VECTOR_PADDR 0x400001C0 +#define XCHAL_INTLEVEL4_VECOFS 0x00000200 +#define XCHAL_INTLEVEL4_VECTOR_VADDR 0x40000200 +#define XCHAL_INTLEVEL4_VECTOR_PADDR 0x40000200 +#define XCHAL_INTLEVEL5_VECOFS 0x00000240 +#define XCHAL_INTLEVEL5_VECTOR_VADDR 0x40000240 +#define XCHAL_INTLEVEL5_VECTOR_PADDR 0x40000240 +#define XCHAL_INTLEVEL6_VECOFS 0x00000280 +#define XCHAL_INTLEVEL6_VECTOR_VADDR 0x40000280 +#define XCHAL_INTLEVEL6_VECTOR_PADDR 0x40000280 +#define XCHAL_DEBUG_VECOFS XCHAL_INTLEVEL6_VECOFS +#define XCHAL_DEBUG_VECTOR_VADDR XCHAL_INTLEVEL6_VECTOR_VADDR +#define XCHAL_DEBUG_VECTOR_PADDR XCHAL_INTLEVEL6_VECTOR_PADDR +#define XCHAL_NMI_VECOFS 0x000002C0 +#define XCHAL_NMI_VECTOR_VADDR 0x400002C0 +#define XCHAL_NMI_VECTOR_PADDR 0x400002C0 +#define XCHAL_INTLEVEL7_VECOFS XCHAL_NMI_VECOFS +#define XCHAL_INTLEVEL7_VECTOR_VADDR XCHAL_NMI_VECTOR_VADDR +#define XCHAL_INTLEVEL7_VECTOR_PADDR XCHAL_NMI_VECTOR_PADDR + + +/*---------------------------------------------------------------------- + DEBUG MODULE + ----------------------------------------------------------------------*/ + +/* Misc */ +#define XCHAL_HAVE_DEBUG_ERI 1 /* ERI to debug module */ +#define XCHAL_HAVE_DEBUG_APB 1 /* APB to debug module */ +#define XCHAL_HAVE_DEBUG_JTAG 1 /* JTAG to debug module */ + +/* On-Chip Debug (OCD) */ +#define XCHAL_HAVE_OCD 1 /* OnChipDebug option */ +#define XCHAL_NUM_IBREAK 2 /* number of IBREAKn regs */ +#define XCHAL_NUM_DBREAK 2 /* number of DBREAKn regs */ +#define XCHAL_HAVE_OCD_DIR_ARRAY 0 /* faster OCD option (to LX4) */ +#define XCHAL_HAVE_OCD_LS32DDR 1 /* L32DDR/S32DDR (faster OCD) */ + +/* TRAX (in core) */ +#define XCHAL_HAVE_TRAX 1 /* TRAX in debug module */ +#define XCHAL_TRAX_MEM_SIZE 16384 /* TRAX memory size in bytes */ +#define XCHAL_TRAX_MEM_SHAREABLE 1 /* start/end regs; ready sig. */ +#define XCHAL_TRAX_ATB_WIDTH 32 /* ATB width (bits), 0=no ATB */ +#define XCHAL_TRAX_TIME_WIDTH 0 /* timestamp bitwidth, 0=none */ + +/* Perf counters */ +#define XCHAL_NUM_PERF_COUNTERS 2 /* performance counters */ + + +/*---------------------------------------------------------------------- + MMU + ----------------------------------------------------------------------*/ + +/* See core-matmap.h header file for more details. */ + +#define XCHAL_HAVE_TLBS 1 /* inverse of HAVE_CACHEATTR */ +#define XCHAL_HAVE_SPANNING_WAY 1 /* one way maps I+D 4GB vaddr */ +#define XCHAL_SPANNING_WAY 0 /* TLB spanning way number */ +#define XCHAL_HAVE_IDENTITY_MAP 1 /* vaddr == paddr always */ +#define XCHAL_HAVE_CACHEATTR 0 /* CACHEATTR register present */ +#define XCHAL_HAVE_MIMIC_CACHEATTR 1 /* region protection */ +#define XCHAL_HAVE_XLT_CACHEATTR 0 /* region prot. w/translation */ +#define XCHAL_HAVE_PTP_MMU 0 /* full MMU (with page table + [autorefill] and protection) + usable for an MMU-based OS */ +/* If none of the above last 4 are set, it's a custom TLB configuration. */ + +#define XCHAL_MMU_ASID_BITS 0 /* number of bits in ASIDs */ +#define XCHAL_MMU_RINGS 1 /* number of rings (1..4) */ +#define XCHAL_MMU_RING_BITS 0 /* num of bits in RING field */ + +#endif /* !XTENSA_HAL_NON_PRIVILEGED_ONLY */ + + +#endif /* _XTENSA_CORE_CONFIGURATION_H */ + diff --git a/components/newlib/lib/extracted/romsyms b/components/newlib/lib/extracted/romsyms new file mode 100644 index 0000000000..61a10cdfb2 --- /dev/null +++ b/components/newlib/lib/extracted/romsyms @@ -0,0 +1,639 @@ +abort +abs +__adddf3 +__any_on +app_gpio_arg +app_gpio_handler +__ascii_wctomb +asctime +asctime_r +asiprintf +_asiprintf_r +asniprintf +_asniprintf_r +asnprintf +_asnprintf_r +asprintf +_asprintf_r +atoi +_atoi_r +atol +_atol_r +__b2d +_Balloc +_Bfree +_bss_end +_bss_start +btdummy_bss +btdummy_text +bzero +cache_flash_mmu_set +Cache_Flush +Cache_Read_Disable +Cache_Read_Enable +Cache_Read_Init +cache_sram_mmu_set +calloc +_calloc_r +check_pos +_cleanup +_cleanup_r +close +_close_r +__copybits +creat +ctime +ctime_r +__d2b +_data_end +_data_start +_daylight +_DebugExceptionVector +debug_timer +debug_timerfn +div +__divdf3 +__divsi3 +_DoubleExceptionVector +__dummy_lock +__dummy_lock_try +environ +__env_lock +__env_unlock +eprintf +eprintf_init_buf +eprintf_to_host +__eqdf2 +est_get_printf_buf_remain_len +est_reset_printf_buf_len +_etext +ets_aes_crypt +ets_aes_set_endian +ets_aes_setkey_dec +ets_aes_setkey_enc +ets_aes_start +ets_aes_stop +ets_bigint_disable +ets_bigint_enable +ets_bigint_mod_mult_getz +ets_bigint_mod_mult_prepare +ets_bigint_mod_power_getz +ets_bigint_mod_power_prepare +ets_bigint_montgomery_mult_getz +ets_bigint_montgomery_mult_prepare +ets_bigint_mult_getz +ets_bigint_mult_prepare +ets_bigint_wait_finish +ets_delay_us +ets_efuse_get_8M_clock +ets_efuse_get_spiconfig +ets_efuse_program_op +ets_efuse_read_op +ets_efuse_start +ets_efuse_stop +ets_external_printf +ets_get_cpu_frequency +ets_get_detected_xtal_freq +ets_get_xtal_scale +ets_install_external_printf +ets_install_putc1 +ets_install_putc2 +ets_install_uart_printf +ets_intr_count +ets_intr_lock +ets_intr_unlock +ets_isr_attach +ets_isr_mask +ets_isr_unmask +ets_post +ets_printf +ets_readySet_ +ets_run +ets_secure_boot_check +ets_secure_boot_check_finish +ets_secure_boot_check_start +ets_secure_boot_finish +ets_secure_boot_hash +ets_secure_boot_obtain +ets_secure_boot_rd_abstract +ets_secure_boot_rd_iv +ets_secure_boot_start +ets_set_appcpu_boot_addr +ets_set_idle_cb +ets_set_startup_callback +ets_set_user_start +ets_sha_finish +ets_sha_init +ets_sha_start +ets_sha_stop +ets_sha_update +ets_startup_callback +ets_task +ets_timer_arm +ets_timer_arm_us +ets_timer_disarm +ets_timer_done +ets_timer_handler_isr +ets_timer_init +ets_timer_setfn +ets_uart_printf +ets_unpack_flash_code +ets_update_cpu_frequency +ets_waiti0 +_exit_r +fclose +_fclose_r +fflush +_fflush_r +FilePacketSendDeflatedReqMsgProc +FilePacketSendReqMsgProc +_findenv_r +fiprintf +_fiprintf_r +fiscanf +_fiscanf_r +__fixdfsi +__fixunsdfsi +FlashDwnLdDeflatedStartMsgProc +FlashDwnLdParamCfgMsgProc +FlashDwnLdStartMsgProc +FlashDwnLdStopDeflatedReqMsgProc +FlashDwnLdStopReqMsgProc +__floatsidf +__floatunsidf +__fpclassifyd +__fp_lock_all +fprintf +_fprintf_r +__fp_unlock_all +fputwc +__fputwc +_fputwc_r +free +_free_r +fscanf +_fscanf_r +_fstat_r +_fwalk +_fwalk_reent +__gedf2 +_GeneralException +__get_current_time_locale +_getenv_r +__gethex +_getpid_r +__getreent +_gettimeofday_r +__gettzinfo +GetUartDevice +_global_impure_ptr +gmtime +gmtime_r +gpio_init +gpio_input_get +gpio_input_get_high +gpio_intr_ack +gpio_intr_ack_high +gpio_intr_handler_register +gpio_intr_pending +gpio_intr_pending_high +gpio_matrix_in +gpio_matrix_out +gpio_output_set +gpio_output_set_high +gpio_pad_unhold +gpio_pending_mask +gpio_pending_mask_high +gpio_pin_intr_state_set +gpio_pin_wakeup_disable +gpio_pin_wakeup_enable +gpio_register_get +gpio_register_set +__gtdf2 +gTxMsg +__hexdig_fun +__hexnan +__hi0bits +__i2b +intr_matrix_set +iprintf +_iprintf_r +isalnum +isalpha +isascii +_isatty_r +isblank +iscanf +_iscanf_r +iscntrl +isdigit +isgraph +islower +isprint +ispunct +isspace +isupper +itoa +__itoa +_KernelExceptionVector +_kill_r +labs +ldiv +__ledf2 +_Level2FromVector +_Level2Vector +_Level3FromVector +_Level3Vector +_Level4FromVector +_Level4Vector +_Level5FromVector +_Level5Vector +_LevelOneInterrupt +_link_r +lldesc_build_chain +lldesc_num2link +lldesc_set_owner +__lo0bits +__locale_charset +__locale_cjk_lang +localeconv +_localeconv_r +__locale_mb_cur_max +__locale_msgcharset +localtime +localtime_r +_lock_acquire +_lock_acquire_recursive +_lock_close +_lock_close_recursive +_lock_init +_lock_init_recursive +_lock_release +_lock_release_recursive +_lock_try_acquire +_lock_try_acquire_recursive +longjmp +_lseek_r +__lshift +__ltdf2 +main +malloc +_malloc_r +__mcmp +MD5Final +MD5Init +MD5Update +md5_vector +__mdiff +memccpy +memchr +memcmp +memcpy +MemDwnLdStartMsgProc +MemDwnLdStopReqMsgProc +memmove +MemPacketSendReqMsgProc +memrchr +memset +mktime +mmu_init +_mprec_log10 +__muldf3 +__multadd +__multiply +multofup +mz_adler32 +mz_crc32 +mz_free +nanf +__nedf2 +_NMIExceptionVector +open +_open_r +__pow5mult +printf +_printf_common +_printf_float +_printf_i +_printf_r +print_rom_meminfo +qsort +_raise_r +rand +rand_r +__ratio +RcvMsg +read +_read_r +realloc +_realloc_r +RecvBuff +recv_packet +_rename_r +_ResetHandler +_ResetVector +_rom_store +_rom_store_table +roundup2 +rtc_boot_control +rtc_get_reset_reason +rtc_get_wakeup_cause +rtc_select_apb_bridge +__s2b +sbrk +_sbrk_r +scanf +_scanf_chars +_scanf_float +_scanf_i +_scanf_r +__sccl +__sclose +SelectSpiFunction +SelectSpiQIO +SendMsg +send_packet +__seofread +setjmp +setlocale +_setlocale_r +sf_dump +__sflush_r +__sfmoreglue +__sfp +__sfp_lock_acquire +__sfp_lock_release +__sfputs_r +__sfvwrite_r +__sinit +__sinit_lock_acquire +__sinit_lock_release +sip_alloc_to_host_evt +sip_get_ptr +sip_get_state +sip_init_attach +sip_install_rx_ctrl_cb +sip_install_rx_data_cb +sip_post_init +sip_reclaim_from_host_cmd +sip_reclaim_tx_data_pkt +siprintf +_siprintf_r +sip_send +sip_to_host_chain_append +sip_to_host_evt_send_done +siscanf +_siscanf_r +slc_add_credits +slc_enable +slc_from_host_chain_fetch +slc_from_host_chain_recycle +slc_has_pkt_to_host +slc_init_attach +slc_init_credit +slc_reattach +slc_select_tohost_gpio +slc_select_tohost_gpio_mode +slc_send_to_host_chain +slc_set_host_io_max_window +slc_to_host_chain_recycle +__smakebuf_r +sniprintf +_sniprintf_r +snprintf +_snprintf_r +software_reset +software_reset_app_cpu +software_reset_pro_cpu +spi_cache_sram_init +SPIClkConfig +SPI_Common_Command +SPI_Encrypt_Write +SPIEraseArea +SPIEraseBlock +SPIEraseChip +SPIEraseSector +spi_flash_attach +SPILock +SPIMasterReadModeCnfig +SPIParamCfg +SPI_Prepare_Encrypt_Data +SPIRead +SPIReadModeCnfig +SPIUnlock +SPIWrite +SPI_Write_Encrypt_Disable +SPI_Write_Encrypt_Enable +sprintf +_sprintf_r +__sprint_r +srand +__sread +__srefill_r +sscanf +_sscanf_r +__sseek +__ssprint_r +__ssputs_r +__ssrefill_r +__ssvfiscanf_r +__ssvfscanf_r +__stack +__stack_app +_stack_sentry +_stack_sentry_app +_start +start_tb_console +_stat_r +_stext +strcasecmp +strcasestr +strcat +strchr +strcmp +strcoll +strcpy +strcspn +strdup +_strdup_r +strftime +strlcat +strlcpy +strlen +strlwr +strncasecmp +strncat +strncmp +strncpy +strndup +_strndup_r +strnlen +strrchr +strsep +strspn +strstr +strtod +_strtod_r +strtof +__strtok_r +strtok_r +strtol +_strtol_r +strtoul +_strtoul_r +strupr +__subdf3 +__submore +_sungetc_r +_svfiprintf_r +__svfiscanf_r +_svfprintf_r +__svfscanf +__svfscanf_r +__swbuf +__swbuf_r +__swrite +__swsetup_r +_SyscallException +syscall_table_ptr_app +syscall_table_ptr_pro +_system_r +tdefl_compress +tdefl_compress_buffer +tdefl_compress_mem_to_heap +tdefl_compress_mem_to_mem +tdefl_compress_mem_to_output +tdefl_get_adler32 +tdefl_get_prev_return_status +tdefl_init +tdefl_write_image_to_png_file_in_memory +tdefl_write_image_to_png_file_in_memory_ex +time +__time_load_locale +times +_times_r +_timezone +tinfl_decompress +tinfl_decompress_mem_to_callback +tinfl_decompress_mem_to_heap +tinfl_decompress_mem_to_mem +toascii +tolower +toupper +__truncdfsf2 +__tzcalc_limits +__tz_lock +tzset +_tzset_r +__tz_unlock +uartAttach +uart_baudrate_detect +uart_buff_switch +UartConnCheck +UartConnectProc +UartDev +uart_div_modify +UartDwnLdProc +UartGetCmdLn +Uart_Init +UartRegReadProc +UartRegWriteProc +uart_rx_intr_handler +uart_rx_one_char +uart_rx_one_char_block +uart_rx_readbuff +UartRxString +UartSetBaudProc +UartSpiAttachProc +UartSpiReadProc +uart_tx_flush +uart_tx_one_char +uart_tx_one_char2 +uart_tx_switch +uart_tx_wait_idle +__udivdi3 +__ulp +__umoddi3 +ungetc +_ungetc_r +_unlink_r +__unorddf2 +user_code_start +_UserExceptionVector +utoa +__utoa +vasiprintf +_vasiprintf_r +vasniprintf +_vasniprintf_r +vasnprintf +_vasnprintf_r +vasprintf +_vasprintf_r +VerifyFlashMd5Proc +vfiprintf +_vfiprintf_r +vfiscanf +_vfiscanf_r +vfprintf +_vfprintf_r +vfscanf +_vfscanf_r +viprintf +_viprintf_r +viscanf +_viscanf_r +vprintf +_vprintf_r +vscanf +_vscanf_r +vsiprintf +_vsiprintf_r +vsiscanf +_vsiscanf_r +vsniprintf +_vsniprintf_r +vsnprintf +_vsnprintf_r +vsprintf +_vsprintf_r +vsscanf +_vsscanf_r +wcrtomb +_wcrtomb_r +_wctomb_r +_WindowOverflow12 +_WindowOverflow4 +_WindowOverflow8 +_WindowUnderflow12 +_WindowUnderflow4 +_WindowUnderflow8 +write +_write_r +xthal_bcopy +xthal_copy123 +xthal_get_ccompare +xthal_get_ccount +xthal_get_interrupt +xthal_get_intread +xthal_memcpy +xthal_set_ccompare +xthal_set_intclear +_xtos_alloca_handler +_xtos_cause3_handler +_xtos_c_wrapper_handler +_xtos_ints_off +_xtos_ints_on +_xtos_l1int_handler +_xtos_p_none +_xtos_restore_intlevel +_xtos_return_from_exc +_xtos_set_exception_handler +_xtos_set_interrupt_handler +_xtos_set_interrupt_handler_arg +_xtos_set_intlevel +_xtos_set_min_intlevel +_xtos_set_vpri +_xtos_syscall_handler +_xtos_unhandled_exception +_xtos_unhandled_interrupt diff --git a/components/newlib/lib/fixlibc.sh b/components/newlib/lib/fixlibc.sh new file mode 100755 index 0000000000..5a9e3fd006 --- /dev/null +++ b/components/newlib/lib/fixlibc.sh @@ -0,0 +1,23 @@ +#!/bin/bash + +ROMELF=~/esp8266/esp32/rom_image/eagle.pro.rom.out + +rm -rf extracted +mkdir extracted +cd extracted +mkdir inrom +ar x ../libc.a +cp ../libc.a ../libc-minusrom.a + +nm $ROMELF | grep -e ' [TB] ' | cut -d ' ' -f 3- > romsyms + +for x in *.o; do + nm $x | grep -e ' [TB] ' | cut -d ' ' -f 3- | while read a; do + if [ -e "$x" ] && cat romsyms | grep -q '^'$a'$'; then + echo "$a found in rom" + mv $x inrom + ar -d ../libc-minusrom.a $x + fi + done +done + diff --git a/components/newlib/lib/libc-minusrom.a b/components/newlib/lib/libc-minusrom.a new file mode 100644 index 0000000000000000000000000000000000000000..6f593d0587f8f120614ce47a1be4908ae5bbb1ff GIT binary patch literal 3675626 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 z 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 lME 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%0DLbg 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

!55Qk8* z7(PM8LG{KTD7%P>fq{(;64xb63=BL_b~&irg|e%d7#Jj=Y|x$Ba!__X69a<^l-7(m&ebDhng?8!_F3=U8>sQ&SSvS%|fFa$u^3z!%f!l3NMObiS$Q1%KY z28JXkdo>dSLk5(+nTdfR56T9e2@SfZ7UW;hInY&5@uN%(3=L5BDJBMnHYoc769YpJ zlntt*CPCScnHU&mK-r)=Y95sRg^7UybgwPQ{J%^L46C5x49pA+8=!0!W(J0BP&PX= z1H&FDn~Rx&;SiK9!py*M0?HO=W?%rF9SSlNRCis0iYqfSFx-Q(HJKS0UO?G8%nS_g zplndx^##f{XJ%md2W2}lGca(lL*f)vckw~l0n7{xB2acPGXsMZlntu86rk*AW(Ec| zC>vCd=|I_u%nS^mb3{Sz1l4I4Q1NtT1_sbMq9E~1W(EcisCW)D149s$UChkD5CLU_ z>bf{68&togK-sO#3=CONb{8`PLjjaMk(q%3bfzfC{29y)3^h>k*~|2yEz`)D_iPNvl3=Eu5Ht1|@ekdDMe~Locf0!8ry#%lV_{%$hKjSWGB9{T*`T`J zAIj!rWnciEaSBq;$I8GE0~HrwWnf5xvO#ydXF%EFtPBi!P__aq149Xvt<1{6Pz7bH zu`)0;K-r-4yxX8`LskZc9w-}hxBDb0+nkkwVFr{9I@^05lx@w*z_0|$wr6EvSOsN+ z&iUR5WxKO7Fl>jiLHED!g|eer85j;j*$J!+3@4%NR8|It^H6pMD+9w-C_9Ulf#Eik zUBJq~@DR!_W@TV_4rQ0JGBCV_vO#T!&ro(XD+9w%C>zv{_zz`++7YZ=kTlTF%D})4 zWrNxjf>1W-9C2|d8`Qp#g|a8JGB7AZ*)v%g7&M`5P+LPE%AU{4zyLZo6%==%v&OBV z;-GeiBb2?0m4U$>$_AY~?h9paWo2LhouLZSyMvX1ArdMMI*&Xa$_BMTQladVtPBjG zGgLw9LFbVdLdCDLGBA`w*`Tw@YoY90tPBjzP&TM-(g|fhWMyFJhq52DGB8YqvO#T@ z*--XtRt5&pIjbPMKC&_}EQgAN&N5#MW&dSmVAu?0|7T@j*a>Abu`w`!&RGTNWo2Vv zI0_Z#U}Io74Q2DOF)&<&vPIY!7_LLvl57kNccE-)HU@^rP_`l)1H(%wTa%4};XRbC z&Bnm+70T9SV_^6VWrNy5jNFiTH)dmCV2848*ccdip=^85ncq;hBO3#QB$VyK#=syC zWqYzQFo4cw1^ESZZn`#99MoOp6y`$EMN*ccdsq3ldH z1_sc%tROYHYzzzuQ1N^=28J{!8`Pf4fwIfl7#ND6Y*5>(0?MvoV_>L*vg_Fx7(n+i zgUoDVV_@ilinp>cFie25L1(c~gR=YC7#QY2*`PMpVkjGQF8fL-8`S1n4`nZBV_?_{ zWrNyZyP@ojYzzzsq3q3U3=GGi>;r5J4CkQiV{8lzSD8K| zp=?l_>n)W1ij9HcGnDH4f2no86mWhGk4;upm8&cFaV0~Ta2sJ)gC z6^~+PU?_#Mpf*|uRJ@v zS&%tR91IM7Q1K2928Jn6Hs~DsSy1*A4hDt=Q1)~V28Lx&Ht0rsI7Md$_BOdPC?o0I2af%K-rr)7#OZW**iHH7(i#wg50@}gMr}@ zRQwPJ1H%g_`zQwk!#gM&)E@i-WrNPS{{>~A2TdICLE`-q2Ll5elnpxbo(Ial1#0&} z*$+4v7$l(VM;r_ca!~dQ4h9AlC>zv%)Pk}>nHq3^q_UGbaOs zJCx1J$-n?Qw-)3t4o(J!5U98SCj&zilnrWECP3MuoD2+UP_{HD0|V#`TaaEkP6mb| zs5q!ySpj7ma56B|LD|Nf3=Az$wgo2xLl=~7!^yxf0m`=HWMBZDZ3{Bffs=t@4piKU zlYwColGofrwE(QkB*|{J!0$dCXOQGVRv;S8^*`izw3>%?r87>Bf?NGKH7X!myC|i|_ zf#EQet;NN_a1zP}-3f3W$~NL+V7LiogW9?Gp=@(528L%)wiOox!y72uhl_#X6O`@G z#lY|b$`0dVVE6}R$8a$)un0inI+=@sfeXsc;$mPBfU=G^p1_da)j*Edo z9m)o^XN{ojZY~A}(0RF_Fag~aU=I~vz{SAe3T1=t3h;)qS8y>f1VP!Ldjn#j>>XST z3@K3d0WJoHEGYW~7Xw29lnrXDmOT~gYFI30cA^ZGcfFf zvSqm$7>+>MO56+#r=V;VZU%-6P_{ZZ1H&~a8+6YA=zLv}`Jj6S9zn&;xEUB;K-u=( z3=Hp}Y!_|@hA&XI7dHdLFDN?%Gzw~wS}_VxfvLoq3k|x1_n1WiR1oU`U0sH*hmBWJB5exEUCVpzIUe3=FkU_9<=# zh88IM0yhIg7nFUEn}J~hlnuJ0U>cPDjGKXBE|d+ruV68h{gs=6VI`FPhns<6J(LY< z!)}GLL3b4FhO)(Z7#I#h*)lu~49B5tIUWXvvrx7I4+FzxC>zway$NM&@-Q%f&fo=w zC#Y@v6e@1P!@%$w$_CwO@Da+k<6&U<4rROYFfjauvO#wmFbhHAI+%xnffLFG-EY7T zWykR_Fo;6gpmwe_l%2xEzyLa@7vu)eT?gt=@gg1u23;t-numeG7|L$oVPF8A*$YzN z%)`K74;7!p!@%GQWrOZI@P@MI^Dr<3LfMOW7#PB#>?J%544^Z6LFR1aVPHsxitplK zV912B5AZNB2QLEy50vc(YNJ8f!MqF%5>R$1F9QSUTwjp+X}k;! zs!;JlUIqqjC>wNtf+3V$!OOs44rN#KGBDUe*$uo549-w?8!rQcCzRdE%fJ9S*B4}d zKQ9AAC{%nBF9Sm~ls%1?fgusfp2^F=kPc0ovNQM?7&M^lY(54C&{@GC zKj!f<4@d44|`xL25v4*r`x)7JdeX*-*9sKLf)eC>wM?!wM+dou7eW9h42aZ($3R9l_7Q zunWqL=4W6y2xZ6dGccThvO#w;oP)AK_b^<|1H*GDdkH@S z!&@kO13v@9XDA!g9{dSqgYHlG4`qYegRG*Ect69>z`zYzu^)P%A@?LmDg8+4Zf=p18^UPb{125YD|vj78wBa|&8z`)=R zWrOZX@P)EL?Y>|r+d_bWAri`V5ny15hq8SH7#LEaY*3pn8_LcUU|=YOvO#USawxl4 zfPtYF$_Cwy&zvXTL@)u5MW?f4rOl^ zU|?7aWp5K;VAu?0?-gKR*a>AH5MW@~4`qYyNdTRD46^Hr00YBWsQ5Dh28Jt8Hs}t7 zTTnKrjrIV_2Hl7749eydWMFs$WrNycpP+0>K?VlU*~lRCLG7=9P;o^;1_l-}NW6pE zVq8$Rx*!9C0F(`Cmx0bn2I_uFepLUc7hBHpfi&}Y8(X_81$gxpt})F zpllC81_moA+e?sv!2!w!-I?G9Wd{f{F!(^(!Ga77K~Q#>AOk}Ll${{RzyLZ+8Dv+o zAOk}RR6J9VfguaZE*4~9D1fr-1Q{60pzKaT28J3ayGM|L0d(Fn$Q;o92^~=JNrDUv zeNgrcK?a5?Q1)y=1_sc1%OLe@1Q{3>K*d4rxMfiGCP4;>=I!HhAU8ZnJ@#xEhxK1n1SH|l-()J!0-&p?h|HUcmrim5N2Tb1Z7VaW?=XM zWrOZ3_y=Xr5oTauk$|LudBO|~Tu}BhVFm^PC>zv%5reYV2{SOrK-pV_85oqH?Crt~ z3>r}O9$^Ls(3#JmaNZ}(z+eIu2eoTJXFh|(4+}FeI6%cu3NtXcLD`^t4}73(&|L>X zQ1%mH1_sdi&mg^^_DdX8{HHJjLkg75D8j%1I{z7@MnHstp#UnbAi}^<24#cVAT?07 zp$G#*6O;{Vk90uU<{}IXp!1(W=GclbFie4pgW4vupll}*28IPtHmIGl49W(zQ`SJ) zks=HXo1pA;5e9}GPWOT5e5c%DEp=e1A`ir4Z06O2g(MuM~tED$07_2 zc2M>+5e5cVDEplV1A{k|4Z0^G5Xxo{Wnc)0vROnK7-FGpPwMS zgEEx8Sd@W56UqkN!=MjkuMuTnFom+$i!w0SL)jZe85lgF>>Z*E4E|8|K~V;VP$>Jf zC<8+@lnrX9BtqF2L>U;;q3p||3=FwY_H|JPhGHlibcaJFl>JDQfuR}72Hoe-3uS}u zbC?cgzY=9&SO{gm6=h&p4rPB7WnciEBMl0}@1hJ0o1x;2VhjvBp={8d5Bs5PRxt*K zqfj>J{)f|0wxAdT!$l|?)W*3EWh;m=Fx-W*^~D$%9z)rnw#-W?+gyx+;XRaXEylnA zI$s*(9#FgHH&h&SF9f4BB_9OF23{yT7<3;3lpQ9 zR2EG#26TKpzLfh1_sdi(jfJq_KpQqyjYBZ!4Ap>wS8QmY*5?B3(Bq+V_*n? zvO(>jFen?;4vK-YyTuq7lAvtR9TcE*r$Kg25MyA-gNjcUV_+zOvZskLFo4dT2B`tH zj~bxji^Lch+MsOE-4s1g_6jiuhDlKNIxz-@8Bq3SF$RWtQ1(eN28Jb2_FXXshE-7Z z12G1M4N&$|F$RWhQ1%Nk28KOQ_FFLqhC@&`s7-VN%KjwAz;F)A{wl`6a0SZ#F2=xc z3(Ec_#=!6Z%Kj_HzyLa@8ssm~ofU7O;-EIvCny_qf5i_dn@ya70d!_HNIj@+#UcYq z16<+^3|vq)k2nK^0F=!y&cGlBWebWkFvvjJp!OH&ENhTCp!SyrR9sn{fk6+-2DP(H zpllOy1_moA+ew^(!2!zl5ocgx2ODJ9 zWpM_EeNb^wyXgp&eOH`;;S`h&YAaoUvOkJ5FkFMOzlbw1+<~&ci!(4hg0laJGcde> zvcn`87~VnIpti{uC_6!dfdO<@HpmTmpbaFlka!2RN7$fj(0vp?p!Uwzz_lz-zdSr06JS6Bo4a2A^|FXK!SlG4az<&!N8CMWgnAZU?_sJ zL2Z@_C>zvfsfV)fNiZ<9LD{b)7#Mn>>^Bk&43nU2P&);5&Nj$iMo9*Sc~EgqNd|@` zP`02X0|V%sZIBuTNd|@uP;m`O28L}=wyq=t!yYIbbY}(V%x#c*D@g{16Hsv{Nd|^< zP_~aG1H%<4+fR~#;TDt)YL7gCvO#SS(3#sHb220u7~Vj|n_oshKLtz#s+{2i;{M17**WWMEK&vgb-N zFla#8ptgw~l)Xlhfx!gI-Yv<%U62paU!AYM^X$7@lf__DF%jADEo^P14A~H z4Qk62LfN3ZGRmQB0ci$?S}0psnt`Di$`+GmU;v%n4YC*1u9*N8mzQQ>mVNY|!3P7~2D64pc8_4=GF>w5JZn z2JIDvu|fOgU~JGHIT(8ak~yG#aWL@}NaCP?KI-4M^-gNbD0x>?=s@2S{wtJ|&o4Kaj*(koJuVAhBhT*cwP|6C}0+659uf9f8D7 zL1Gsmu|fNJVD16!)q%06AgKZE$$^Q3_JqRNJCM{IL1KgU)xgx;K@xv~#0Kr9fvExQ zpMkM?m=Wy;LKZ7KG1Bv|viTweI z4O%k|(+k?O24jQvslnKwy=gEuXgxHH4cdbSW4o{;!Y}}d9fQQqKw_65u^W)sJxFZO z-Z7Z@OOV7jAhGu#u}>heuOP7>AhF*dv40@3SvU~x2dxQ)*$Z0x3uA-U_`=wry;?9f zXe}>{4ce0hV}sW0!q}j_S1>kczZHyKgJdsg%`QwFv`!bsUVx-#4HA0?5*xIa3a0)7 zlK34YHfYT&OwAW0aRyF=-+7SO5=d+nBsOSGD$E?v+EW<}b&0umdv z)(vKU1(J9R5_ekrXI9M1IFHhqz1HJ4JLjDN&E&9`w0^J0}}fW5}Sh;5e_0q zYy~8?4ieh}iS2^K4nShZAh9!$*d<78(7G;|`+JbYXCSecAh96#127XCm^wNkk}PS>=q>U1SIwxB=!m<_7)`e0VFnPeG<%Vpmj(v z_7fyEACTC8kk}jo2)~FRu|aFjVdj9=9>Lh4^+qr@XuT1P9e|`a28o@4#4bT%Hz2Wl zkk~Vj*h`SuptVFWyY?W7pFm=R)(OGXJU|i$trLQY|3DIF5k&Z10EsPw#MVG!n;@|r zkk~#*>9z*`zw&dTaefjkl1sO*q}8oFuhxl#19~` z&mggHAhDkyu|exvVCMWm66X*`go6kYTLFo!gT%H#V!I%*1CZD;NbC$GHfa3{%nc1l z;yp<08A$9UNbC(rY|xq#m^mkq#IGQ+A0V;cAhCZSu~|eAeg~})ftd+fzY1f6)~v$V zpmiZIHfa3^j15}n0b_&Kpu*Uob*C^kXss!X4O(9cV}sUzz}Qoe+yh$A0TW+?B)$WQ zeFTYp0f`M-djZq?0!jP}5*xIx0;YyX6cG**NNmu02$&iJByk%gwg(bB1c{x1#Lhut zS0J%L>lzJbIBts#J!^8rcx4-%V04B>YXBsOTi zAEs9aN!$X7?SjM(Kw`%ru|ae5Fmpp~AobG7of~A;>P!yamWTAoqd9K>ALA4$uTKpco_vVp=gU zFo3qv5>f{`YY?Qz2&4&gzMu>PgDR8_qCj#W><9G+bVv+5_YFD|3#0~wVdBwHbs#Yi zc94gh+XrHUFvuSuIt%7(T0Q{XuBFn4rE>>k{*x|67dWS_h5m9BnLXD6Xb7@8W8@L#K2%}3}Qhr zOb&F`A;@f)y&9H`3_F4$_VPjf2(lME#{8b}GcX*H2eBX+Cbti&2j;$#entij3y6O~%L-xcI}h~}XdVq@g6nn$2JpUa5COc4O1s_fPn#Y7A8~~=qOPze$2qY06M=DChmWLfdO>>D~t~^3&j2kH4nrF;r0WN zd;nsDFiah2ehlPRm_OzmX9VY0P`F4!{Rj#dCeZv5NFx;YgC^oYlZH?}%)Gx)JuvfD zfDi10gbOIUgX{vCC&<76nu>wyW?<;Q!N9-`GX%-)AR$n z%mbwdP+mbwz6^KnGBAM7Hw5VcVURf>IwvzJK2bL(GcUVHFJE6l!O+Ca#L&dT%-m2x z!PLN5K|#Sl0R#*U49rYS6cmgMEzLlD1%(8zdRHGeM$o~NAcMeej049Bl*<4bmj`(Y zR5md%XfOyd@Pp;+p<%+nz`_VRQbd$&kL(WzKuw9SC`rvL zPSiEhGtx8AP0Gx}Caw=vlv-S1Xkek6nv(`qh3p2fjiq_Tndy0{DGDH~!6IM+ML0gC zG&i?09^~Zs;>zOW#GIUB2DpmkjKm@aFag#HGRNI7RKZ!nM9)IcR6#cvBn;N0pqs9s z>t77PX?gj&Nu`-NC7F2)#TofUB?@p8K}JAb1vVEV4H89!sh++brkC_VPAt+(MmP?n zsW`JLwWP8jm4U(C+1W}#Be^KQxVR)gKS$TkT>-(#OV>5jGXe#wsj+UliCLPVnL(N+ z#24Vg08~JOGEf9K0^&XM(()NXgI(htor3*+LPK2ReLO>4gB*Q=Z4I~_ojh#~xFE>{ zM6zgrPQfj%%q>YwV$drtDT2@$Fjh%wMG1pmN@7VOgI-c`F@s)FYEGhFN@`MRdVD6x zA}BjCDXA#63`IJzC^0WRwU_~_A}2F16~-XK6hkOrW^;0LW%Rko#Z>18Y)d0K15h4Xgzm)u6NE zKs-?S3}cIe@;TILpgMsO)SzNuU{FUA2eRD%mjrMDA-`mK(4bv3Sj0LLd^q-fiOs2Gl&7jFm*c6 zIt5nGg66dFff45-i8_nPtl+=;bCTj)0<#w!cTl|`3Uo#@Xw49a4Z<+4%vI3QJJ(Mm7(0HZ!PA z1~m>IZ_xHkPGV9qQSBLHLjwz9+cThfT;%qQ1cNApnInTizoEhkg9fbw1{MaB7BH$? zF-=;)&|rLEg7E=a&~yvK|NsC0Gcz#OFz_%kfLahRH-oAX(3!Oid`W}|plrs(1lsh?zzk_HF)^~)FfuSOF>-*8P-kLd^#Ji8 zO(Z53*6j=o3`~$V6%z|PsIkh#$N@S$odr}z721@_v7+4!08X%ri0j}mjSAK7#LW=X`R`gk(rT`nE^yfFffA7{$ykX zHI5K%KS)alr6GjE0o%YpYV!(V2Z~|18&eS1>w|4WZcTw(V_*VoB&cx(W}p~LmGFhM zRdjK*Um@;ez}`k2G|fF|-2sYwP#prQ_dxeUfYLiCMT7VZdbpc};1(Lbc41mkVs0u* zQxMX$gR~m4v=npllTnnzTaI9>Alj(Xe1w0E8K#UIVFvjd6m8@L>0-fC_vV z8`K74gnAw1BhVSAAhSWPg|WeHRA}=U+(rc@J_ZH`P#+j(4#-SKXp`@z9$DX z4hCy)gZvEh3n-<)*x;~*`WFVuMmB z=zb6o8`LHS$-&|a92ZbCk>e3GP6ty1Qcny9r6*9^2^+#v??2eeHA;;TXVAoqjxf!3&lXcz|B1!9BR(V+5(kUDU>0BL|?ka?gq1m%LR z5CJnm?RRANf!0HU+Pxt6fs#B(4&*+N7|abIjWrAm40AyYD2B;_`b;1_F#m$qMRG7Q zFo4VhWeJcR$UKmHV0u7CNHQ`o1cMk*43h(=OQ;x#%3%bJRDoC!3{#f`4NI84pmm6# zHaf^&P!@vO3mSET=>eHAg%SIBE~uXd(gQOOv`!I}PC({?+z*li(cRE^1DOTFTNoJ_ zPJtLu46~~Z&3&LXjWG9thSp%_f%6Xo0|Q77WJDbk0|V&(6c8JPLFR$*BB;GEbvK!@ z_b))>$e?fs=>=iX+G$W94a5dvkXaylFVs8`8-#sW5N-hRVd_A4R)O3K3m4E@OOP8t z;R3pY2_y#!7f@LTOQRtDH7pDaptc~04Z<+kVdQIp_w3Mwx^ zH3zbJp!1*k!8#xW$Q%$0*1t%}EF-FaVPa}&L~Q?J0;t2o4Cyn2QlSh3sN@FO%D`aO z$Z(f+Ez@3Rha(D_j*Scq4>%Y)9CMl9a?Rzw%c{#|%e|IkFWXs`nSn2%vbC(eT(R6U z0$(^zb7Q(D%_RNKXaS?T9U~93gVzCFzFEde3mDxkn35JS6jUGRWl0D>;LCx(zXG01 z0RLB|m$tT#)0z zT_IQ(3RFFSyola~0x1Mt1;)k@GMOcGG7E?eSI2_rYJr-hpsdRQ?UGIA0P#SVi}653 zBEb4VBA_8EuxR9D7KkWF1XRFsFihrvh=6#B44`2INEZ(x3K9WzV!^tDC$mI>%>;>n z+yoPas0Fzkgh34{S2h{FHOfEd z0J`TAq#ncuWlB(n1F>P*4J1dfubPutl3J9Q1MOlC_MU4_W(m}#IA=i^Kurcv(19^# zKNeIef~CL&W;?6`LFRzm4q}5s0E9>T;S3B-p!OUz z3C>1hFGFI3*O@@-WCqZFWLO^?)MtkE?LqxySYI8~XMu@>?#_gX-$XJKw3Y)V4vr(J z`Ji}$nGcRHs5mITVB(;*8;lJ~8!$Gg2?Jw;(g}R62pyMu5aY`p!YcL47JvT!6$u;}xJaHy}2sxdobo z0kJ`IEYG0oLG=LWo?nnSXk8d+P7K5b%~yc-l7rZw@MZ?x56Z;A;Kabd0Gj6liG$`h zL3fdY*r5C<22}%UjDqeW1&M%g)RBnRI0AY|BAR2w`p9Uub187VQWF9C^LFz!}f!qT!4Nfa3SW@>Kw|5v>|;AS(bm?PuwkD&J`J@OWG4uN z_BkWx50IT8anSe-$gMDc7=X?XXJB9e`2#dw4Uz+e3&?LUJs^Fcd$2%dG>8qtFuBWU z;bOzfzyMMQG7mJq12YfQe1PQ*kbcnppASI{D2AB_qLGV+HS7!wpf$drd<`-KWF9EI zL1_`$yf+*S44|=esB!RgrEh3#30gr18UG=?w$9Ydkm$8_pnDTQ%`8yf2aOfUGsu9~ z^@7S9kUL>+0nxCy0EwF=GBh$UOk`l#$iOgDW2QwXV&pU{EG$ec?4bP1$^x2=U}EF|U1-e80$R??1`=WSXJlXyU{X5?Doa6^ zCNrrwf~@B-09md9VzY378Ujq3AT|dFXn{177KqKmzzJGu!e|R~GRW_Yb9@*X7`WDh zyk!eg1u~5LG?)us3lhvd0n7o(F^2Gf#__K)GBEHm#xol6GR85Q@G{0i7B%uR#(-{V zXJBCCWsGKJ289?eV-!;n120n{11o54Bd9$M${>tsiJ2< z?z$F$RK9{;AdA)085tN@nL%+W2+9PES~I}{Aa}BXw1ET}7%f0dh$VucF=|FjkS`&w z5Cm2Bj8>p)s39(8D*?4AK-D#~0!SGr69a=V$b-UQ7DyJt1xX5n34Tz9a&=0l9waiEUaabg>lo9-kD8rnU@|9F^nNCzC5`kKQ{?!^sF+qIJKgnhyku29Ok61ctKtnl9vxQ zaDW#7f{Hs(o&(XKmIjCo!m!aeP|gJvav&Nc&Y{7;0ILZ>;;=jmtIa`bSQsIz31DoP z97r5gV#CBiGzf$3BDB(k(CA%0XmK)V<+7okA#~uZ2rLHWK$edThBYZfjO?Mr1jhPi zPy+-MZV*h&xE^Q<4-^Zab|NDK8+e}xb6lS1;&`;f}mCySPD#FuJ;CwAb_R71ZbQP%zzTi zC@W?`_DL}$L*+oJ95hY{YI8t^7(jmRWk95QkURr&F@q>Ppv4BH+(8JVlqm>dh-z>_ zh_#A9DlrlDK|Hpa17GC;_68#;B0+6hP<;wzgJKaT4r&X-*dYI+j5k8ngWAlnu`*Eq z5~dzBb^|&C6=V@8WrFr;gV>;P2@o5k9n?1gu|al%hDSkcke#5I1hGMOg4Xwd*dVh( z<2WET$WBn}6vPIlSCAZt4YCu&=0;3KGr-&ovJb`v*#~2T?1QmE?i1#Llu{tOL2Qtj zAPgJZ0oex|p8>f8HVy{rQ^DAvwhc%xs6+%|m|jp{7p51~7XqmV$%FPn!Pubi0o|1Z zatqjPpnzdu0I%+XjX8tD2gU|@6=o*JdMRj@0l5dJ9u%H1Hh6LwYCd?aIg|}vF9l_T z*Goa!;Pp~aHfU@IW)65=3RE04J^>T21*I#fI4G~c#6jI07#lne096AX8-%h!v*9o` z;PF_fIA{zI=3h|X8x(G!umX?ALe;zl*$XW`K;wQeb3hwHU~C>xe*sigF)%PFgV>-2 zKA`*zVuKP30|SE@659=l?F(W&4~Pay!`L7zVQf$^ z!Pwxm2dWhCtT_Ys^Pv6(jah;EyCCyHOTa;FP+kXhc|dGX{swhML2OW32BiTI8#Jyo z8Puy{VgQ$;p!5I|2lW?0T>%gq6o#O*0b+yFENE2)hz%+OKu%^>GrQ2hoIN6wp|F;18`Xp9h6rh&Vopnzn6jBUci!DppH#X)25 zu<{V(24XO%%mUT9pzsH&2bB#Vw}IFo3^keoG`0g`!^Whxa5FG~>;~m~kbaOH$gk*Q zwxE4EuofAzdFW%dpnDiW?gyC%ibt4vAoqaG2Z@37gW?NB!!Sq=#6};p1??9Gl}{i! z5C)kCqCsP^AU&YC1o1)YKzl+#Y!C*?fiP%{9YjNu8v|&*08}o6)POL|JkYQOhz$#u z89b2nS|ERb%6gC-C|tm07Dyu$gT{7YdO$)Tbs!qF{~N@H$(`U~U;wT01eu4tehxHv z19Bfo4+w+G6fu}%L1hp~kb!{#wC4%gJkb5ypz~Kj=7HP=k^|A;Jy1|RAWDgufq@;# z0vHp0|BEII_Ax!sFbBwNm_KIlBfMV6rUg(rY@Qt`&jW+w6Wr8?AXVOpQDA#Id<&(updF&P%wXh?py=?dg05C*v&M88Kf4|M-7Ed7DTi(%%0!W@<-LHeRN7#Ki% zxIt_XhM5PVk%EgMf|G#(RIh;M%V6#U-r2Z?2ZSmM(v4ZN?|BIX%AntPn4a+w&Fkl(K_V;rQaSVzC@7V_J+lFCK zJ%!8$@p0k*;KgkWIQMsf+LW;UU7+?ZC|p5l1H6n8lqitKyg}<;k<|;cK-$cpG4G3@ zvztMOV1pJhgA6$fB0!6G7}-GkIGGqZ9)X6inOJ9mDRxj}6EWuf0VK%58Veer=3oa6 zq%yIv9tQDP*qxXd7{FuRcNrKM;A7rrm_Qs*GXpZ_t;WQ_V8f&aYNK(08X2%LZ&0RU zf{uA_1Q`e&^Y#X@A!FVgpbX2T4Qjp!aDWbfVA27xMZoEcNf*SH;MfoHiynwA!;uZr z3z~*tP~cb$5;p*et8joaE0ZCJt-%3mtS}jY*g71bh7Xf5h;6_D>QpkBfY>G+OF`zC zg4h-eoXL4*42&VLz9uM~8Rx77jk|+J>li~osz5=?oyou$3aZuls~9-`S21w@*VABR z5EGuy1Io$^nL)$uF^pEcjM0n+kfC)32EJxc>o69i3l_JGa~?7=Fz}ayqAeC=HmD=R z4?gWX7Sz`B1+6`{g3E%oLvR44sve^1A{;&R4fNqS8ekQsGBQ>)Oq2T%x^aC*=a~7g~AkF@u@Q2Jr1QCo2o)m&?--K+A#X4DZ z8N5dpv{ROalb3;!nU#}+fst7PJRbzwHw#)L%?efnS~bnWDb2tLS{Dsk5zP!*7|p~9 zl7;B10?#h7LG^Nib@31+Sva}Dvr!;(@Xki%rKTsAWR|7IgQgr9^5TnA3*wV18Kf*Q|>5Q%!WHPd?nR$?@ ztoY)}+@$;*hJyIy;`oB1)a29@&{RDN52QA&C^0!cB{My@&9q=R!%4`v2 ziY&PjW_EmhT4n{z6ELsFgX&j0PJJN<2x24`5}cqZC?Y1cVCgd%BWe(nXyBPBl+cKe z&xK^A_~Z=GAuK77X)DZN15L6)t%wi7HE#w=EhQQGrNxPPDaD|Kgk&1X8_4klo>hZS zpMjR^gXiK9A%QX`o`;n5K(?f$CTHd*=EN7|gUkgx7sLR2kdmo3&}laLISgpCsW6X2 zf@+{n;Q zf@M7ku9}ZP@dr+0ps^XyS~5^W6C?l~Q-F9{&d2j|{RJRG@*_pm8;I1_lNY8H;4^#7ig_Nhz+t6bp9iV4RQ-;8z_hkawBML7sLj+0mKH~Q4C^(#Aa{Y- z+)%fH){KMpX@JrRZ2ty`4O%k}QV(hcgV@|q_eX);3Cdgy3=E+4`XId^^FiatFg9om z7{=~GQa=re4cc!CQ?nLH9Ap+OY(ZfJV}rs4#s-BKj13AG7#kE`FgD1aFgC~!Fg7TR zU~Ev>!PuZMg|WdE6=;G9x@H$94xU4Rii6hO!^A;u76zSP2%U2Ru|aMDVc0w<*gep2 z1Gxt_Uj-VffU!Yt0OgU~{e@HfRU~q!+Z79E4$d!E--Q zdqMFC(hJJ}ptavHHfYX<5fqTHyZ~}IY`zxC235|WyWK&41xi1(S+|7rY2`cMh;-Dck7#lR60%L>cYoY4Fb01JPsGNtX0hN(3Hh8`k zss=QC0uu)fo50wh;Sv}dG_(a{gXe3ZdO_<=Vd9{%b{HG9jv2-V&(T8F{{)pMP&O-Q z&;rU9L}JS#u{Dv{rbui@Bz6Rd4UId{x_nqT7lOn=6)6J)LqCWORkI4jhT02W6ABgI z!N|Y>(hEu_hmq8P=Uk!YTtX7R17btPAA;CWGhc()P;v0U4AguH&{z&A5iu|@D1z9a zjLQHT!bF^H?Ftfys*gls=OVEik=Rp_*ej9Pdy&}SaayREk3iy3cfJ9!q2eDvBUjKd zFVF}QEbb&hqhZjzYz$&U_1c5jP;pNX8!8?OVnfB_L2RgaHi!-NZvlu66|VuYq2i4o zHdMS9#D5>q@9ND9ymcL2Ydq8@a9lg#}C;kw54zU`WH+cD z1L+6Jfx-ZN{Q<}iptdte4+w+QfoSyg2cSDjKzr&y=7G{ANFB&Lkb6MpgTz4kKxc7) zXcz{`f!Lt78K|uTQwKUr98{l!f$RavfiOr8gwfX@fX*xg z=>@3)VVHTKein!g3m4E`BA|VyAb)_|1Cj%o4+;m6xgfnD3>pOml>;C)2!qstX!P|5 zpnE<*ryzpN1GP&*>Okg!$_HfgK)Xo9L6RUtKz-Maz0qZDKw$Q+Os5DjX3 zBAfS`m4N|t#t_sP&?idIx>| z!5IMthSwkmK{3pI`i3UPhTxS45Q5P912aQ26NpN}=fK;5A|A{715kKCoq@8l8I-?4 z;vjikYYgl#))<^Q<-yX^vH~<)_JD(7rLyb?Gu-q4exbguL7vXwYd9D{?G?~C5hz`P z>R>R9AjAKr=Rs z94|oQiA=1Z+JT9QJrjI-J@^cKCKh&3GnQk3;9~L6tOgzZwH4=+Ie4Gth)2 z$eAF&G0p+i_*|gshS3Z%56Qs51-=p63^bn&ayb{MGY63cHP0aP*%lyE7=w5~ov+V~ z3=E*XbD)iD#-RCZV`AsC`9OVJBT!w>53a?dLH8Jd+yx4A*qpHd$ors0p@N_}V@3uc zc~GNU1+*NLl^GPFY@i!fgnom%3~Hdoph&a9LX99%Lr~EQnGF^S1Zg$`xgIhbECfD= z&G<25=NoALR@fe-Odh06#1j;4;E7()VhK@DD2akuAcYVvNS!E{&;fY{d7@VgJWH(r z)&(NyFwu*3Ga9J344UeN-g~@ zVonyM08|(;GK7FAm;(HBvak#e(hRD-m>58P5z^;m8FD~_ltr1z(3w*h4?J;-b+Xiq zky#u%y9t`DtOw71LUz`n%#1QYW=28hL)C-lQz55HF@xtv@y>A)o%)}&f<~G zLChG!=k`F3B>CVg&;)R5iUL?K*nThpHxpzxmg!s+dB~I{iV)a1B-esBB+_wi)fwGx zOkaT_4?Oz_pN~YH#f*>7gT@wYmK1I#$}Hso?a%{NQ=nW6qM@}lhzpsNV_;wa^@Tts zH;e|2mxIa#kRs3|A&3pClR#=xqsAljWEagaO+k4^xBLID+{ z#03@h=z*F8pm+db(3~D99ziz3_@E{eDBeKoK=N)NN!VC4N=p^Ar;URF)ZYZD1;zVt znBxP@VM4tO-b(^nt_R|S(l=<14m8IH;)5`#kAd9Z0r5dQ%0X&Dc>$yzxhBJ&;o+jt z;sLZ}8BGi{mj^0eiZYX-t4zRW6M~ByEaeK4ZbY$;rPRe!!JzB}N3$B_bp}RIM-Viz z4{GCs5)Za{Jm?-MP`JRxlR)z=FgAFc2s8k}0O@zb#6e??D06q9fgUu8ps@v*UeI_KNG~W| z!se+!Y*51wHa7(dBiLRx(6j=K4NAu_HYhw{W`g?eATvS!0J#TtmL14FF!kWMCQyWc z_P&AA36u?}!E;SeaqwId zlntJ1g0jJLO;9#yY!;>$bXFM5kDwMT%#YWR+z%S(hK-Sf&Ig0(1>K(q69?b92Q?qm zuZD?(=b%7^C2VgXG>?GBr(x+IbY~{a4N;)(8PuE<5F4r&bYd{bZJ>B;1&Kq|fV$eS zG&UPad^v~>$}|iN3>!ggsQSGiHYgD?Ffbefv7zGUKy0Y^We^)Gejmh!ioXQ0q2l1P zX`pOlP}dO32Bi;>J3%x^8;lJacYv`$`4`3p?W%^cL1Q^EHYjbw*r2oxV^eFM1e_N@ zy(T>K9-!spuy_I03!w3PkiS54DIhjzoEUWH5Qq)R>!35UKx~k)piVT14e~2!?j6Ji zl`G)2B218d-=HP`AaRiYRzl}VK>h#qP&TN{0WG=$sR6}1Xy^jO29<4~F+~s?RJI+5 zst3)JfX=4^iG#{HkXu1rNDvLeFg7^vL(>&Gk_wQ(0)c} zIt00a7z`?>LG2(=9D&q>$}>^KA(`o%fJAd_W_v)iffp8AoqaG1Brq3gGQ`CGz^2}Kx|O_fzky` z9ca85RNjN+Kp12mhz7+cNDrt^0r5fVKtr4$HVA{{Kp1^K0W_wMtPW-#`h0>2AEdqo z`2*x0kUCJffXi8s1yBr{=YxeMNC>13M5E6qSnxsioq@~)MJ-4j$UOA<1khZb3pAa9 z%mMiUM5E6q?BQczNMVB9*8wsIW*+){LI^Vh1LznlkQpEhGY@?}p@)Tm0W=Q^QUk&; zb)Z2nkl8RlDhMLt7nDyyav=NB=M#PryPr`I5ze4G6=ohN55wF5a*q@%0|O|mL2M9) z$${b>qzC4{H-Zcdpg0DFGiX>DBnNUIDDQ*xfbu9v|0`AohIF)W2FZi!GY}0^7sx@} zd_oTgaq|gBI1v3hkUKzjfoSyojBA95n@>2y0ZCUNGe8(-9{PO34k3s-P`H5V3|P2; z!W@>@K>7nXiJMOd;9_97zzCU70F{Rz^FVDh^!WtP{$|iQd?2$y80J3cJqbmLc_}6q zdinZ<<`XO}jELUPxCYeNLYhyIV~}RxGiG2oyZZls6CnnM+-Lv)zq$ASKg=y4cfqik zBSVuC-=7sSU67rKh71fV9~nh~b}sTn7)3D}GB7knu^L4&fp#|TFp6SsiefVaAA&cL zfx#$>rPFI>)Q(4MnIO759!-*9RFYttFws#!Nl;4@Jm&zBQe|KOouUUyo4C%t1C=$f zIRjW32oeK@Gfeyu=vFnb<5?K%L2EDWGBYr&2gL>h0|Th>2arIcCrnCl+;(2rFn?8B+=)$UZg}7BA58j_jbjzgc`hOQqRC zd#qS|L81&CpxJ?I3=9mMAcC2Jg@t_<69WSm2aEeZ1_lQ1`5^arf-Gm?UJhdWEeH3j zn6*G0f6(Sc=2DPJmpv_!hHV1b;Xeb}d=HU(lDF?F!_~I)VSPen*0U`|iEE=`t z>p(3^u+teBc-JyAFsQJaaxpP5aD!UbtmYuo8Mr|=7qVJ_*eu+j7Bs6Rh|R$r%*w#P zY6W8RaIXi=)L4Vq0^D67whf3a!W|8Afh~wF!7T)Gr5%VZ!z~ZeYY$>8FbIH}-yDpr z9$p}uLAO@0dV-kX=_>|SFA%#yP!VL356I07jDn!e^Q`_L4htg#2j~XnC?;qe$TRTn zU}9kCVGW)RG7cPKAs{9LH)shFYbeN47Va!iFon%!VqoCl-UMQYZ((9!=wRSy0hz?H zmWhD@gu!7W&%n>JnTdfxh@S-%IJ`2<3=ABs#rHwxgN`C*EdenZxIx7>Ybn@#27VS$ z$`GE!%)s!0wTMxhg@Hlj1SkN?7(ogcL_m&at!4yW8^j`V1LOh-heM&+ z>k$wEwToEm87o;C7(_%4fP%RZEF&TE0HmiG%#jfREstVtVO+(^z@Q)+pIgAd+Qzt+ zoq<6`qyc1F2jf0=1_lk0K9HU+upS+ePasY&m}4Mf4C3^G?J*JI0ogNw@d#+&yNDJj z-X=1hVrO8m5wQiyOad!&5Ge)4&s4_S>ON$0BrOd27Z>OpgowT%nS?} ztec}*85sED3m90pfJ2=xzKDT!D=17^_~OeMShs>lF|h6gT`DTT4a#z?yFltCxCKFe*$av$8E()OFsuhb5v0I97ZenS+gKSGRJfZ# zYL0GYWnj?YUJnY%6E|5I7<9NTL4k7eGb;mw0bhJ+5(DcQkohKj@udX}tY<;4wBd^{ zEn;9j2eQk78+0@U>qXGvv@YC|AibA3*%%ny`Qmeu7+9}@^m=ehgY3NlQXjw#TGGUN z6VyNo;f@En;Q=Qj149J2EyxXzK;=vfcPdEyF-Uz1gBXYcB@%Ivf5br^5eIWY;tc#O z^`NWT7&*=}GcfS8fPxdO0hC;jG=RBK4I5Y)7$iWt_*r^b85qPs>xMvHM^X+F5{D|^ z4N?PQgMtL1hJl~uJ}U#H$OL&9oVS=Dd`UKF_GMsTRR(!WmeG)ffk8Nxg@J*GRgp1@ zje$V~oR^isYz7f=kcU;k36@2K38Y08oRBye_*p=yi=PE#rZA{`A;D_P2)a&7WF|rZ9pmVi5uLEm>2+93Bw|kfCW{j)+J$NKZOgzl?}8h?4=fTSX)U}(SBX$OU7ElOC zg31kWe1Zx@c2Md`V*`<(T0|0*^I<9AAz1PPm;~Jk!NS3!1FGd%ST2F;T@IGTObiTC zpe3nn7eF;GsICV!5E$pwa4;}P7cnpjf|4#s7*yCYfF_r-IT#pZ9L(f;`giShg zAz#(RjZh1^n~4XqahezPbXY#r3!L~tia@psfR(X=c1D9n5(JUVVr5_u5@k@AWMB{m zE8@1|wq^w>5`ijW^%MqKC<-+i$`uo31ns^CDHMlHb4x(ZtCa*vfP|$`r@i5q?1JQ^ zQLovR;bsI$gJfipwrqfU%q0Ev{4e=*ri+XDaHBm8Hsr*IjIb}i8-KqcjH0F7RM)7 zBr?Pom!xFoF~le3WJBDUlb@U&U&4@*Uz(JY$`GGiRsyy-KP?TsJ|s5@?36a$Gl;N>jwiN(n!nYpPDPEjhznGEqD2QZX_w(FNL zfM!CoLHP%NdVmVlE#LwtErCMfxUVz4qbv4|l)H?ueyoB%;t1>#Ux z*n<@1=I6l@At<&}GE*}1GD{fZ^V8DeOBm8}@)JuK;?s&!Q*$zlOBmvP{GGkygIt|M zgMvN7T;oF!;RRW-g5*<30G8y&SEeLZg3JcTbG)0Uk1IobZW1`1gEB>YF^Ui*m&E6# zR+PX>0FZK|G?1B>%n+ZMmx727$V4(je0*|FYGPh#0YiLlVnumMF(|rI^GX=vi&Ilm zK+^f8AYOb~A}Hm8L_z5wB_EbA(+cv7K~737D$2_TpKuLMCh@tMc?`H$LqSR#eQ11u zZo$ee%_(7kcmZ@MLP>shd`==L_|oz~u}}<&m3U~BC8mJf7V49qm(Bp1hE7Q=NsR}m zihhb)vo9jU9bwIPOFj){E)Nw)PBhMaz zaXOMM(Tmu^8 z2k8Z25Fa$&1xsKc^{}}Om^`e|1eHV3A}PKI-W-XC7j{rN$f+HWk_fye1k_CcnFSgo zfbCZV&x=AG26BT4Xo8o4fdMpE0Ahn$<{0&4n$=F>pppmslq%?)bYGcYiK=3PPJAbUV;Zjd1i4B#`yLE<1c zg3cS~hPo5fYZXC?KG3~?Aa{b?0b+x+gD`BZ3dkL>IbM+6u=#dSry9lvg*`|wsJ{!s zFukBSfawMK7o;8(N3gXgAU4R4jG&9MU~9`jfdkv;3}u7*FtGJ3py7R(nV>WPG7}Up zAosxbr|E*$Xh8LX!V{*~5lI{rRxokU{cA8bxE}`93p&>fCJtUv4;2T6Axs>!v>nC< z&H2OFpgBbt8$1sQ)eBlD1``L(N5I&iIeZu!d>pP(Ac}Q&V-e#!yHY9QI z`Vpu&c>M^JeG5qq=)NJCy`TYQ82cZR8gMTasu#SU8OjFTaRgHjx^f7{1`RU9*wLUK zE>t~e4iqL{j3i!<#O_97??z%DM`B+_Vn0J-e@0@1x?eE6z-$-nBRt5%`U7%Sc7+V`j z+#HGRjKuawVmBeNrPvT=sv)tBk=PDMY+odHIug4CiQS0A?n7eFMq=+oVjn|dUq)g- zKw`f|VuQ+8nBV!>5$=~pVrw9=O_A76NNj&3b_^0b6Nz1h#BN4nPe5XSKw^JKV*f*8 zgRbg=xtW&(ab|%a2jtuYP?@g+5(ibR3=9mKAU3FF$-uy%3snOeSF;C+L)Ex|*r3Xj zfq@|m#DNs&^j}`xX)#HpR1`T8e=;&7v8`QP|?G*&EL1XW3Q1zfY zU_fV?gTz5obD%kO5F1oKgXY{pY|z@!IH-Ei{5@!`5J(&pFIiA=P}?UD$_5S8gZ#w^ zZKol#L4JX?E0Ehfp!O3?92B-NHfTZw#s--~38$${9QHWeri38@3cEldwcAILnI8$f)Jy&xL2&JDzd$)!j@ z*71Pc2WlFEvyFqJrKyo1S z(C<+F#L2*L6UhP?6Ld5%j198lG&ci7D2M^YFgZ}zgUp86`$QhH?hxb;kbNLI5Di)n z3ey8J0_kr5~F!MmyO2YJj^n>nN1+|+%Y!HUYLDr`*Fu>fmK>@OE4rCsvivcqa zbQT6k4=DeD^q=NqV2FjTcLwo6av%&k0|P|E)MjLGA;Y1;UF(ApI{88-!tUpf)?Qc`1qz zbs+OV{TGlNDBjT5rM(tmU;yo<2bl%JF!Mk(v^WI`GdvJwU?^aOtc!$&GbsK*X&aU& zK?(!JF~bie4qca4oSK?lq?fO+Kxkc>p``)Q>(btUJcqO{O@M(Hyyg-l4BGJp%A1U! zLzh4ose>E?Termmj!|YNc2FtA%*X~R7?~M4W`M>Qm{>u}mYF$NLAT{FbFhQ92Q#y< zg6{TUW?|ZQN z3UM9CIUo#*BPIq=2ODF@Dg$C<7c`Iyo-;rhy9SGZq(EcXunmw{b}~YQKnh7cViarx zm_V@@&H;}&(_s)3GB^U7y#Ni~LWYHLj|PKP>*qky9QusQKn!ByIbgH|G{~+8o}|!A zDn=do%gjs5XV8OO@0XaARFqnVGBB738!UvVAa0xxl;)5zCh9}`R*-0p&kgARXyiG$96 zg0aD63{(whUm{FA9#kJd#X;vJ!o)%A&S7k@`;qDM2_bc$b0|UPfy@SBka?grDT zc<`2~s09WyxD*7X2nYt3vCwD)^+zG1gvo&_S3uvs@xSU4Hk05oRvkXCIfiOr72!obEBj?9_2IBG~s2>6v3jmn~!XUF?G;)3f6=0yn zr=YwBss?c7N6=;SAT=N}Kp18oa()CgoC&s@EsQLPJs&CrIKu63lLtDY1S_W4u7}Vru z0xze;Xa(bL=0Rt+p%ZIGkYigI;!{dLrv$YtVRNb=XMyfJ1JT4{O6n1ipJDdE*y!z3P(1)s z1EOK^jov;5sRNxW0#XCQFm<5%24ps@o%n*8fdO>N8K|uU5(i;W`w6{$3fjvF(hD*R zgkk2Pw@+t5=j1_ZKp3VDy?tr}ZJ&bd1=T|^d(qpcn-~}vKzc!DfiTQG^!6#}&P33? z!XPyu3{nTe=LChfY_ip zX^@{_;p~CrU(o0YNDibAy}cX2#J~UwLy#FD46_$RBiFB>GoBwn`+6|*Kw$~0YhisE zkp45w3=C2r1{8zL0WtLrO-w8y6(*P*tzSVEt$to=IcNnn^2#x!5(pG{Xr&NHm!3Y9 z#G+k)w0?Ds_wfvI4RZ7ewl&~#bn>({Kx*(2I)94Z<3pqMD>T6}jMlH9auSr~LG)<- z%D^yMzcPSVcM?;-!uzi|`N_nLCmE7(9)S<2@j#&e3QDt#po3Fj0|rc>Rs|z3ZThdE z6%S0{xk%wU|@JKK>bz|q<$Qsek*964B}eEy@Kfd);|mk450HC zkkx_m0eZg`w6>R+ek&)Ac@^}2t0NO+-379}AU1lx)d9)Buzn`CeycB${ni&u3=G8d zTS13%V4LScu2)CLh4FMekw?xz2@0k98XXq~rD4!IFi_A$l%(brC&qh%mK%fyyT&^@ z1^fGihK%-GK?MSM-2rlo7ql(`RKr0f!SbL{Q)E7DGtf0P z)=f7tOEWYxNYhjRpEJS$D#1tVS5OWG)t8`L3SomtX3)GQhyld|vW^gHH;5XoUqPV& z!K3vnBpgQPT_NEB%DGgoUoFhQH7kS|op%Mzono0d9j#wS>sLq?1e2hA2xfqWwTHqw zeVAjx{o~PfO|ak?tzRJ_F5-F$1Fs=#p@d5N93(qX}q7JYz8STSJi#Plc_0=3`)houkUZz`zPS z&6Evt(kMIf*`A)lpc6zLB&It_f{ycMVCDcFcIqh%x*L=e>9kSUe4{t|urL6t2Ac+Q5|{xu2_ynmN1fwK zF%N4+jvYwoGhl9I1-SynN$_o;1HCMsfq?mGLQoq7#KkN zD`9#;w;#aR;JrRjbHHbnLD}H5%AjoUc^FVO_^dK08+=w7lntKShq6I?Lt*BF?ka<^ zLFY`s*r5GUFgAE~7S#Ro7!c>~fbO+|?b!u|1uT3(;R|Dftc0;a`yXL!a2SFJJZH~< zjt79ng*qbx1L#Z_kUgNQ-$86p%C&`xgHowGlnu(DeoC>s>#AhTfR zgX0nEN8~hseC`WKJuw(IwhZ+i_oT7~Hag%5}g+K&NZ!`9*JutU!40I3DFJwb9H zcY)IesDT91#K6FSymkX51X2s4L3uGhXzv9~4@ezoza6N32V#RT$X*Z) zT2~5U!`$b>4mrO9^@L@gZ4mx4T0|I1+l?*KY|!g47$e|MYC zIqwAI4^a95$${)GM=~2^#wA7u22fmr*dPpZ6Da?H^uWx!zyUdr1!Nw`9FQD{2HnE| z(*x2EI^Qk^NdU%dgSN9_=6&H{U;v$61Tqg)TEfhm4s{=>tqn2{bT%C5?i&yrghA$k zFz6~H5Dinefd%`%XHcUX6z(9sApDvI`##IPPDJv8v0S4^PJ z6btyyD`pnf=Zp*tOrV1qp?6;GWM*JsN?`;gGx(iXpfU)0=T$4{-VW?{UNN(I7U0$dv28$X5pM7`Ft#AJ1h*eZ z+z!N+;l2a9d&M5aR$veS9T5q?^J+Ip272e!CXf#3omXE$;;=ifZh}09^Uf>KwlvtC zSKttX-g(svGAItQ}3 z5iBDiauTGh8O)Ipc?aTPz4PibNDu7Jt5y)F3#>;+1bjzSFPLK>k^+)}-Ffu^6wRu*qv9PyL?%vLhrl+#Q^-yD^QIIzw=55Wb|CADf~Y&MKz2EB%Yf8F@4Vs#1p$^juRzxT zvfcox58wvhS_HlG3Upl~EA-B*Ss=a8JFh@B2l;~NcV0Px^uX@Cx(~|C+2EV4EJRpA#R=@rD^S0P@;k3UvChEHf_~=}6X>K)HXG0_ zUQ#Pr7#P^o!3r55+hiH%fDSGN-E?IFN`Ih=Um7&}2}**XN>c_t`WYh23u-EufYdXF zGVrs!1vT@K4nqSCV}cKaAYwois$}$HDe$;2==^u|i=|LUeq~u9H*s-$3WJW=07Vn{ zR3D6iU{LcO+|^_V0#TsG9O?)$NGqs6$H)*2qCo0F3WDc@SRgHo48b4@rZadxNCyam zMlK*NXHXj%Bmzl75EcUi=;Tx;2GGrv!*pyJ=XmCDx%~+|(NRJ7|9gBV#=Hk{if9M@DFO(;%*8fn1;ixxfd0 zH4*gY8I;>^Kv$y_XXF=^D1Zi=LF3DyD`>!%!a!~TiqA&e-vhdr2YgQwXs8-?b5MCQ z=+30vB>0_4&?}grcLAZ@wF19!Dn1!{9ZpGZd@ksUm3YY2GP&qiFoCZ!DlSO@-+=_t z4!`*bdbJD2y+F`QkK&>C{XlNiLA~7ubfpdGW*yKKO^_RGkS-bmA4(Vxy5@6v|~wpev~u;vtvzfE)$6qXwY~dK@o7L6AFZ zz}FaoE@gsVLIt@-3uFrDzAeN}TJT8(P~s$c+6CnbF7Q27;DnWgGGhUDFqnW_2J$l< zH)(?JnnJNWJ|1#Q7>Wl#c?S8iGDzx2)d#y540hWX?$?HMOfv@$alvf-3bTsXAuMP#dPuDYn4F72jc!L#C>L<7=+zR1--c~xwNP#HLoNd zT#TfG+ylN+3+=u-q$}+}MHuM5FE`LlUxQ$p4AhtawG}`#sC@uyYJkK*Q)ZwR28<1A zX~5JB&*?MRSRu%l!*T8mG#>-<8z?3bb7!#X0g@j;W3!++Gf;{EjgN!api}_T2bwbj zwJAa4t{^t3PYJ@qef|v8X@$*)f#x@0Y|y*}j1AhK3S)!!v_b8`pltA6KTtOKt{*5HeAf?@4ZiCK$_C%{17(92>A=hf ztuleJL4!LmHu$a|sCw{SKTtOKt{*5HeAf?@4ZiCK$_DKRhM5Dt>jx?hzUv3d2F-=Q z)PRPRVQlbSKTtK`yCk4&@LfMpHu$a|C>wm&50nkQ>j%mP-}M7!g9a{P=7aD0fr^9g z`hl{+cl|)w;JbdHZ17z_P&W9kA1E7q*AJ8pI%*kaKKQO5s5tnpA1E7q*AJ8p8pwsI z2jBGr6$j1dz{J6K{XoURcl|)w;JbdHZ17z_P&W9kA1E7q*AJ8pzUv3dJ`B3M2g(ND z^#f&t@A`qV!FT;Y+2Ff=pltA6KTtOKt{*5HeAf?@4ZiCK$_C%{17(Bn`hl{+cl|)w z;JbdHZ17z_P&W9kA1E7q*AJ8pzUv3d2H*7qWrOeffwIAO{Xp5Efo52Eg75l)ii7X^ zfwIAO{Xp5^yMCZ-@LfMpHu$a|C>wm&50nkQ>j%mP-}M7!gYWu*vcY%#K-u8CexPjd zT|ZDZ_^ux)8+_LflnuV?2g(ND^#f&t@A`qV!FT;Y+2Ff=pls0k1eo8!cl|)c!FT;Y z+2Ff=pltA6KTtOKt{*5HeAf?@4ZiCK$_C%{17(Bn`hl{+cl|)w;JbdH?029$eW2{0 zNNn)^KA`3W=qzaHeLA3eMhbL44yY-@z`&r6#5M=9q2_?pfo6q3G^kF3u|d)>HfWv@ z#s;m!fU!Z-bucz)jvvMb&4a_(pg}bl8#E9HW4j`)f$&6PgJ#uWYQmAk`Z@^~QR3D~RDjNp1UUp`2+|xo`Z@_8ka=u`*GU}a zU|=YRc@oJy^mP(eTnr4LHVo8Soa-c}NJGwt2c;8G8UpzjlrGTMNvz`{Zk9b17rvh>m+W7Ko&`&yAQTb z0yGRj%=us@Mz90t39nPP0VN=$brLcRpi-Fuv{rpD(^=-bEIeF|3=9uA7<9Qn%Ot>i zb#bj#2d%M#t&^C^$iM)Kf6)2ZptQgUS|A5n+y?R-NFj)Z-7y0y%$cr%W~^9P*r$W0 zgycX=8{8Q|E2dbO*o#1hF|xISDGtzlGz$|eXl*(RWZgOo2RmpgnuUcGJe><_e>0_k zXT{i9n7u&D*4Zb5)=>CVgK9NL5YrbV%D@3y?!JwIfq@f5Ff*{QurFa`VBq3lb_ZQj z#H|fd>IqtO!NBbSV*9m&*9I|zuDD|M2Q9>5VPSs^5@Y00V`O09VFAq{^MWRynL*VO ziw(#ezGRTg9YN(B$lDGK=Nq|%^h6sX| z=YT>$h%uI_gh7ZghN+lAh%uU}h(U-k3bfjThlPoefk8M6WQh~VfN6{j3?g6xWVQ%M zNCadU0}l%*sF9B$htE7AP9A55&Mw~jAQ&PZa2ht33nO$Ck8L&m^CEQpsGa+APAK%oqZ+JQR!5S)fUB{)(G4V1mXrwubOFo3cM>_L?>h!4V`z9J|Cfc6oBHa&pKFAyIzmjjXqVMeHvKt2-zwYeA= zz$aO8L&ZUAK;yTd)Ce*U#0K>{L3p6Ya>4hugB;GlzyRul!^SZ{_k+UNzM$L#RRdlx z4rNCpiG%vuF!jjex1hTzVB+Au3{)>@0U1mjw9W^{o{ePYP9!#{Ee=xyIwujv2CW`~ zvELx6|BS?D236rud-;&qplb_ZeQFs{D+^Q7jLjc(WYVCp8pqvO=UOg$Zxx*knC_F%BfbLcR z+H2VFy6F4E`5FqnF;Q&$xG7mJ40WuFH2GR#gs~{SNL2@8AC~bqHl#n{~ z`*U%PLxA!J$PKV@k`pfq@f?dFc1&$}uxAVB4<&%AX*!VfNN=L-rAX z`~k8LBnP6=@6WYo#y$=K+Sdfq12b<8H)I?FWFDxm2$BPthkk!K%a@@No@LMX8ssPw0FbOG`7N@4HO^O_d{!YsjM9Yy!3( zOqeAyG%_%BaC9=>QGpC}yye=R= zZ7_0xvOEhDs}VB;0}BW1VvryQJ81U`GiaeQGdF1HgP8}kfrSS&LdpCEq+4JrNF597 zH&EN|I!LQJNQCt_$RgOd3yT-13TCeZY48Ev1jqgtG(O=A5`~PrJOYiofC%uo%P}U< zxC@IrXd;#SAjnYYxXVcp+ix?-N(N@o)r~CvFF_V}fQ$3v%K?6_{th()t3=G`AKx>KhK}-g|_-qDN1CX~^xYvM$!E6rhCeWx8n9ai-3^EMN zhVDP<1&yaL@UxgOGB9u`F)}cKN@q@x(-|0e4={rFpNKIrFmQu*X0n=tOlRPJ4Km#V z#Ae|>30l8w31V|_2Y{9@TY=a-+&4f=>a9U+0q$)ewhf3a!VTK|!)gm+OK{tO%&`Np zWw>QPdhJ1M1qK07F#y_s5(cul6y$zS5EI<2WMK6Iu^R+=L4NT8xtW1c5WH&NAH-o{ zWZ+O>WMD`GRSh7I$TRRh1YMuW8oU@}95}>6KuiYiUXTMqL6)*`*Mh7GTgk-0z`^YT zVuv4KVqoZC;Aa7u#Ici!fdPcUVI$AL&$1shox#rn3LIWHX3!xG#jio;gRT^3EdenZ zxIsl4Ybn@#27VUMh@9{iX2|{%a~1{$k^3O~%NRil7(_%tmR2+7urV;Oh_HZy48q|M z0gdpnLO47k9UwimU_AmNpmqXlJ!2~?1A~ajOOT#Mu#AKV=;kKYW-v!aWD-bE3*$Cc z1_lMu_}l^p);7kS>0po{>jH8WT@r?WCJ@WmG}uxB9 za-|Jld}$E_>p75J4&0#8R@RHGYzz!8++rZTmqghZ7~J{dbCMWXuY&Y?aD$rYtT#aF z1GsHKZnz0Lt|WvTwB3&N0VwfAaHoUZ@Ca1S#Bfgn1=wSd`V_&rHUNDB`GKMP2?uo!gz$x4tp zpeY8{WN>KPGJN^EQ<(e?GI}zn8PDt3oh9GQe@d z&cM$C3IRz_xdDz(P=N^A3(Hc(21-MqT0|0*^I<9AEm-mnnB-w+U|^ob#K6F21M-nn z6e|M*n+s?tA5`0enh1<@`ZyREqzg)l7#O)hNfsm_T~MCPz{m}f0mY$AF#{tvC`~ek zfVQJ>gY+|o%7CU9xTk=o?!#n3l_sMQDBXc}yU2mYBm6iS800{^+(8U^Q1^?em_dOt zo(Xi*06%yRfu9AmYCsC4nhiYX0CEwi(ZV=KfD_~@kTY~a&PZfnU;sHo7wn8+kTZ0_ z&IkcJLl^9fP&rWNCX$nZK`{nY({nH|C@{t`l`<%RCp{FvlO77-Ne>1{Mz!E%U;qcI zILH!lkm2GWV<9Y%p$tmrnHU(@6`eudLJv+*h=ZJ_tOVN0!vV_KDoa4=kc}A}c-Xe% z4CJH;0|T!xBQqa2H|R_w(4++)FMPhkf}4SXA9ga509Y9-Oqn1re7}nYD+7a&D1*8r z1A{PF5y&i7kXa&7MXa8}AhSfFMnkz`qKxX2p28r7;*gmV3CQe>BuD}zEQLC&0-8l~ z03E{wk|VGk2XW^u=$IzC&L&0%$gGV#WCCY0Xx2snX$D6TA`Y6^Q9@|8m$Z>&U{Ka$ zu$N@!1Nj}~VvvvuT!1cNA;0>lm;P=5xT z5f}{SgJ_TnMusSmJ`e_RLCZ=Q8G=9*=(GS-3$X0~0;vLN2H`|d+nE8fV`ErOB;lOQ z7(P3Iz%w9_yQ#?C0R&#Pu9pGnB10#(1Q?llIN2B&nd>=O7#NvBM`kfHGjWPAfJg~2 z$qW_;$+B{?GB7f8f>knsr^BQ<1!2=+C=2UB^DgjFY7hssmLImtA8CC&WCx7_Lp<6N zdh~5P;JG0%fin9OpOcgZG99$J0USW_&^;)qn*c!D3P4*>zy^Q`jHx5YUKPmB3Xt-Q z{L&)O!u>P`wCx(OO&HM49B|X(p<6AW`;DO6CqTQMGV>VX;rkSz`x=T;OUe>+z&nRP zd!FE1ney}EQ!6q{;uDL~iy?bkFm@n8=EPtgg>B*i?G6HM9?C=7e^XqNl3G;65D(jm zfwoNqvQGoPuL`t3hk=+$NbrD4GU_}VcQ0pwlq&ZuPQMhV1jisZ7AoYXu9aCo7{ zA$Us_WRFuGcsm)EX+E&mV0*k!HY`Eh&j5A+18mYU9u&-=kVs4~HbRF1bWa{)Utw`(I%KmPsgv(?+y|BiiO!PTc*s^dNEno4=BCDjWguJU zpotBZtHJw{K>mj8MTE|O#}^IMG&X3W5Y&(W(V&4^5F3PH)7YR%8qnY^hz5y+COSZD z&;nA>SSe^y12m)vVuM;UU^N<$2@6oW9;6r6U;*hRxZQ}*6nH+UJkcvIDKgYEWPr?* zLr&cr3`hA9F(Zz+rwtTT)SnXv2QtWLFlL6&K!dpqm~-NwmBbJ^5XsB{npp&~AQiM!BoCU0 z0m*@q7f2q|t_I10Fi0NOIssjZ2+e(nRs^W(hZLIdvI?398IYsM|AO>_vL5K(dXO5B{UA0s)D4lKgENt$N*FZo30f=&TEh++oB_#$ z=7XScwCxhmHU~JG_6^sp9O$sv;6mB3hL6HJ-4{S~zyuJWr7;Jq3lnt6cg_#4I zvxTw2>kFW2!0QX3Z1B7%lnq{A0A+*bFJXGYbDmIf&^#ne9DFt$RD1>~JfZBlNNmtS zIxzKnkiRsB8h|dib2f*ogo5K!ws6lhl-0Kv6Ye721so1UNNY8Mwl! z1(XfmCjn)H_liN;;Jso{whd@61(fZH#0KvbgNlRqib2`+NNT`)#h~KTk;K7!#h~Kg zy<$-IeIzxXkl6o`*r0hXSeSs0b%L?gK>M_y<`^Tf9gx_d(N~!IC?s*vU^7g-5lOrc zi9H*My#k576^VTaiG3c4eFusC5{dl{iOmd}GlaTd0EsP&#MVM$+aa;Rd&Qu7%aO#v zd&QvQ;Jso{Hh8ZXlnvf124#cyib2`ny<$-IbtE&vd&QvQp!H9%a0BlZgNlRqib2`V ztPBh=HQ>EsQ1NIa@jfIrc&`{#jS(9{uRRjm2Z7KatqHpuJg8H%lS0)sfgHNNh(WwjUBZ8i}2O#4bf*HzBe6k=S#P*uRk2 zte^p8sN48KY)~5!R97JF8`A)ZgBAoZFff4kib2_NAaSVP3=kVCo(p0_%_&1-*CVlK zgV<2LOF?X?`jt?7L3P$XkT}%Lryw>|%{wHvB_|>c_#?5Skl3KQ3RY)<>V6m-*BUNR zy#`YQ8dHa{LG>(*4XS5hY|xlHj13x^gt0+;pkVAEP?$p94;oE}iKilogZACP#6k5P zj18`@p^H>NZ3|dk3~HLd)PQDZVd4s)30tULpm}uAIx>(Mu>EbI_Kp!$4JZmg)0`kR zpmvQNR2hl1oIH=77nxO`XgW?OczX-$zwS5wxYCtmqpzvpe zw!x6uAiH61MsD+fx-&3wP&mWb$ot_y_QAx#Z3(Dfj3?JAaYm`7~7bFKVuMpHu18Ia}(4`Qd(>g7MR%}IXxZ*h9(dLieYk~btoXSVfJPyFfbfofY=L4z92b}y`Z&fFg+k6Ht=9y zBi9d_1w#rm4MoTrIZ(KOdUi1L(8K=%4+BFgG(CgNhuH;Q+Jj`Ck0JvDX!03k9;odO zGY@pt2S^Vn?|}51@-r}`A}!|z$${{GX!ya@%@V=BM(zY?#}&vRD84F!eU02LsCiIj z47{S)*T`K(3zrv)ko!|W{s48EVE%ZHW}c`hWN#wOe2^bNY|z>lkRDjPeNlv{1DOXZ zS3q*0cmstIEDwS7HHtDYfOdI-*dPou4@4scKSPNa0|Tf%4(f}6CQCu)fy!Y}(nU7! zi8uoTXrC#_ED#2n1EOJTeKP$h=6Mh<#M4Ua@m(F`UYrU@F& zvLAFgWIurXk8AxJsH}snQfG?$CW@5Jo z?W<#C3j$Ldp!j8GV*L$T;l%+?cg!5@pzT=9EUcjZ6w5)7ObR2YK4oQL@&e@(wm8r( zEFaKem~5cEcuc+^Q3iHL1_lO@Rt^xs%)rdT4(cUwaxl4rdTd;085kItAdAenUV+$t zpo)`)fg7|JkjWpkL6Dh+9ki&GnUMpOj=4b{F%}z;W**RDgaO*gE^pF0A|3~Jc4*@K+(uh1?qv4zL_qxIJKx)KQp~3 zKRYA8Bs;%MKUF`upa6PXU_5mC(MS(;2W?Vj9yW2Pm_B%W6?8uuWV2gXeokp_YO%g+ za6m|YeonD|a#4P9aY=rDj;^1(eo|>>PD-&p)QZ&N0z(4}-PD{kkU{$C$;nt`z!%@@ zL+zl>ZZRC2=^zCMcsCt<2OSdw1AKy#nE^5-qn80%OanW0P>PumG?B=FxXFi&nGt-l zAT#1*LGVNom;gWnFaYRh}fxWGlJWw+bpeziVZ2*-8plT3AgTz5iIS?C^@j){Tpuzzr zPH-k+uy3C$D9Q)b93cOoU|1av62zPzK$ZoKwBxLx_;^1kGNEUe!IB^>4}x6{ z8smnU4jR`1`3%Gdu|ax47&a~sYIDK*V4yY=tdEM^uLkwCKBK|_N{AJkrist2Dl0%e01`@zfv^;uzTP(KyM2KCQjY|wZ;j1B6G zz}Vpa3)D=|F$gemaQ^}-4nF?^$_AZS4^xADE*YpD0uu+dm0;{UNbU#i-GGUM`bjW0 zXuUox9DX5<9f0?{fpRD)K#{~j@dOKhkh5THQ2ztQ2958-*vMfE>W9O`!SfBE(g1XG zAjqAd2!zgIz}y2$12FZVb)GQse(3!`Ag96hwSjU1XcabSya1F7mP6Hm($s1w8bF~~end_cL7I-h}o0sYLJ2^^659+3M$;SF;iNI%RCATvM( zpFENPj0x(?fb_unRW~>o7(jRJfXoBM8AuM~U-0+~$RH>N#W$#d4duf7;pk`PfX0qM zV;1P@KyyGKvtjm{a6z`nfb0cjb&wp$UhqCsm}UkBh6zmA`{C$!3r*pI^us~sfy{xK z2cADdGH(MD0|RIgJWL1{F6d|G?BGI#GpIy{nFs1$fb@XUB*+ZV1uHW^0w4}34?!`w z%s|?!_Jb9BKOFsTA<$WApm92=aqw^kEwV?lh9R2`GERlA4*kp=P-Orb&jN)DXu1;S z4^Wv5OQRq&K;z<|eQqE&2*d0G(a`J(5@sj>B@!ae%qakk`GR#o2#`4-mcF5>0kk6w zzC4}K-ZDc&Gw7i?gwM=T0S&$(^_yX5=78)qYh>tUpUZY8*@LC#rzfK?BM*Bn^I!I3 zA`B;3-g2yE+RJvAwKH(0DMY6Q9GMuqm$#RUDfrr_W1H9|3=9BD)>C;!}vV+g%!PtNHmkquH4U|rC z_1{7Bp^*N&1H3N=+J7nq8fO7T9G?Qi8l?Sa;PV2znHd;BlRF>}PXZC3jve%BBT(TA z-+u@H|{0_Xm-Wyt%_K$q08 zK!ygmuYoLp?LPxe|3UYkHG+(T?LRXCZG?dBKLcH?!V5aE6Sn`19VCmn{|t0r6J#$M z2X{4ShXHuc84tHVNI95I%>J{TNc+z~GuN>FXFovOAuK>66fE4J5|tIY|12D|83MZh zY&&TEJ9PiqG!PrQ|11RL0_grTX^=V4{b!(?##mwd&#o~rFu?bpWq{m|W&fEJ$RybQ zGtgKFE6)9Apq)%T(EVrN5QFYN1K(={-G5dFvIe^UY#)dn4${>@)c!M7r2S{0Q6$*@ zGf-0jZT}f)|KSJLB1X{00FgJK0D$d3Qv_KG*=5Ee@&v)*5a~j2ctk+czO1nQXX>EM zTlL^wDk35$K*0>#fA$8X2e$vL5M&S5{b!(wV^-MyGf*pt6}JBjH2uyB+ka*WG7Yx> z40Kp4D{TLn9w^RX`_DjA?X0l4{ZP0 z0+4@T`_I7J!4`mh3g3Tb#|*yz2()2}@cuI)kQbo)&pbg+!?OPjR3*dqpUHx3hweWE z4G+ThpREL$a~QJ!tRJKXy8rARD2$=|&%nEaNZ5Y{YKFu1pUHv(6wCfI4UoOi{b!)1 z8m!R$XE`7@K=+@4_Cc~j_n#Gk#7WzK2D%JuFz!DCZzhB8KZ|2wU;y2J1m1rJ&dad< zXUZTC!}gzXgJJ{g{xi^0G5G$o6Ch=<{b!7zQ~}$6rVrx4_MiEKl;PZe23m9j-+u;b zJ+i{~pREVQ8EpSq5GZ0{`_I7pG12y)DI@Pc1MjYd?LPx8`(TCbKLc$$gzrCd0T~M0 zf0hq&Gi?8v4TuBVe+Is83AXEfbf2FC1%91IM-pt-QT z++qgCY>*kCCZKdqY95sP9wZAIInRF1!NB0f$iN^2-quzOG6_`X%YrtMGM0dLc`;3N zkjYJ~U|=i-83YQK_1kEuHpo3D2oMeD2rw) zV^Cm>Vgi*Tu+3~BgP~j6Qdk%m*xW&e!P-HLb3oc5ep?H2(MLuG21T&n)`I-T7_12P z*;z%Xvw?CKBSR2~0_{PA%(H-4pmiXO3_&0&50uCl zJ~IZ*2eBX%-a#M=lzAaKKzSC1K{N4;48b4@q#mRo7)fU^vQEUlIFN48*bpN_2#5j= z4S{rq%m=X`oxh0=^Fa)dt&9wy{ys<#7=s7Y7(zi*D7Zfx3i1NTB1Q&~09X--0L_*% zGK7IBkWtJGod3aQf_f>843QuTG=Rs(P{~lvAT!^Sfq?xFACqhyvNh%urSbwicw3kpXm~ z4_Ft-wIJn;44{EQun^23CI*A~ASs9r(D~G0X;5heaxc>6LQpvbTHC?M5Coz?JuZ;j z@Sjo%QUx}Ufq~%ysAI$c8rmAYUW}&mgfudo0kl6V54?M>n6mwau=zdaj|_~=4B-8N z{NTNU;0wc;>p_!y&>e=5eTMm95m7M70VXTJBxG+PBc~X6{~;#>BQtnnkhvBt3p#!i zv{MnXFOdl>3);cR1e#Q2W(H3rGJ#b>_AA2FvobJ(rW~2m!ETZRtL6fej9|AiatdSH z%Lu(03^Z2;-W@hLHZh{?*aYvQM47?`ZxtL?dlgG^3*td7M({SmVYXF~n5k)KG6rqs8JLZY z>7?C%pA;u`Pc8R8n`=o4&fz~$)VX=?zQr~wTwLfbE(c`n$v zK1c|*$N<#10?iqKXi(D-w6Flwq5`P_=>f4pqgWtuP;(F_4q}7mT0r8U1}97$#0E_} zfW$%TtYP9HHfRkeNF3BOgNcLKAoUbHj4{_dfVv=HDKLS#M-mk4U@0)c%mA7(1~b6~GXrQS7|a9{n0q2Yy#%ln zm>}ldV3>`d^a0xA2wKws)(oBh28|8F(hEo)lwOhLQCohXwM)>F6x1MqZg`9@LQ;jX z`;h^4|08Ikoq>S?bp9h~T?Qx(gE}xUHmDy0VuQL%pp#5sY*0D}u|auF3$*7Dl(88Y z7(i^;8OETwW{?_C{sMI)L2OW-0$~svl#f96f!Lt@0UF{0orMgVD+IA&`yxSesUjeY zpaB6|CjwFfiY*Wu&m&YEyyp?h2Jd-!FwK|Z1A2(C>u2C2{RMC=MgFn-t!1$g9g80YCw};Fg9rF3dRQS zd4#G5?|Fo>!FwK|Z1A2(C>y-z5y}Sdd4#gTdmf=|@SaB~8@%Tc$_DRwgtEbV9-(aT zo<}Gfyyp?h2Jd-Ep=|J;M<^S-=Ml;V?|Fo>!FwK|Y|ykg%)j70k5F;&o<}Gf zyyp?h2Jd-!FwK|Z1A2(C>y-z5y}Sdd4#gTdmf=| z@SaB~8@%Tc$_DRwgtEbV9-(aTo<}Gfyyp?h2Jd--kI8#GJ|W0Sg; z5Y$$J=>@etU~JH!EQ}4>0|H}%M$2JrP&)_42DNiwY*2j)V}l0KVQf%+3S)!Tj=|WV zb_^XC1@Dwo@%J0Hdd-K79ygN}}du|a2a!q}j>Mi?8kwhzVzO*+EZhmqWN8i{=#i4B^SgsFdo zBo3NZgo%Ge690q5W?*7qfT;nuOF;y*F9B=Eg4)I~HGH7<12oS{Lig2z@}oSI4VsNm zg|b0yd~GNj)SotlvO)P3cBdt%9}HUM0a|+t%DbTRWI=3Da~;&40kJ{7B!8%0&^qi; zC>zx00Nn`;QUhxLgU&nzu|aKcQ2PhO2DQ6$q3S^s-JrG*NF0=>E1}|`JPm3Wfy6;` zN3BqC(Ee#q8wn&1>Vr&#ii3_81+|wz;-J3BT&Or`e=+E+Wso?iZvr~j8pH;z)!qzM zlf?iz(HbNU>brmsvgvQfY;zc;}qO4fU?2s&7o{i*#%P%avzKhUT+Rn1DZ^NiG#`|7#rN? zhpGYZ2Zgdh`&nUXKz<-q$AVTTVC|rK0mK09w*;|a>vqpbA@1@3js1Y+ zKw*ZyKN=J+urU^pIUsc)8ni?c#DS%oC7dV6b2(d^gAeE(V7CNEX1D;65Y7XfQdShk*f< zrokK}dqMRgvb`S43=9d(5PL!H2g!kG&^Ah#*&s7E@?l?Z4eFnQ^uYYFLJhLs8Wb*| zu@sOT$UOABK`!z!FkFGAQ;_*EyFmM`L3&{3ol#?8Xn@|C0vb;M$$`v6zZ+z!AOk}V zXyH4^FsOe)W}@E>A}Ef1y*2vXAU@*Q_dTD6nhmvvp+y|~zGqO~4{|HaA3hq8{R5zI z0hO^JIgmdEobQvcoUxUm5nFk7QP|`&%i7pgO>Mp{^*Ypta~dSPp=LDdL+t#uN}{aDso^MOo) zt+fViLC3w;8gxkqY^^mo#Gq@fK|?gG(6!c}`(#<6YppkdtR!KrwL8*UYw)^R+;@F| zMttCFtsj7*3AWZ6be;h8Mh_N|8z2`z7G86R)FC)LBAp;Tu(j5peS+}2J`REwo5I#w zKLF{0t+k#E(t~xa^9=wFVu1 z17B-h0E!>jT5C`Yz}H%XMx^0ut-pYlSHsp?gX#zPT^|cU{(-Hv2A#IUini7oRPz#j z*9YhhV^-)|Yj2R#u&lKPH6vkbt-*JlK-XG>wiUwGT7$YstcM|MtwGzUV0V370)-@W zt+fd#P)Jy7y%iJ&(7QfFKzgyPwFY%FVRwC4gCYvL)*94(fZg?x0dfO$tu?4C!Aja% z>*s^?t`9$ux1ejSK|90XYpua~8Mf9MGzJa7>q8l&1?yUCP_+bKYrO}g47S$#D~JPI zYi$ThBCxgA;Jpes*II)P|A4Qx4hJP#*jnqwpm>6ENrbcX!8y$+FEOI?!5H1M_7)*wS+Ypv5jZicP31`YAD!q!@cfE)r_YYl4b!q-|m zgJfW9txZAc5O&uGsBOq6YZ4q6Qjz2-v!+d5}O9G7;0x+07W zK_Cj04KSCznuGf^K_Cj$I>uB0=@UX5&`51)P|h*|uZsl@sg16SrP0z=$oV-mG90`v zma5BQ1rV!Ng~0b{u!C>bfUIK`!?yNxbk%82VtO${Jb~LZ$Xs_(641MoDfw#fwgfS>_1|1kfr^oY!Z-g9>y@2l#%4;dqe-d^t1Za4B+DpN_mG zrws1S&Q=O^UuOy$vja5;Ks0Rp5yXeBGX=FgK+Omc4HDlQ$AAPkZRt=>cwobd7yRFxoBphFgULX;7? z#uGGO1-ttKG*=5+YYDOw#D=Ze1Pz6Q#6b;Y5F54z6SSQUBn~nI#D=K{=?AS-0;vbN z9mEFBH-j*2O(pVtCdl8gxoA+&5XJ_D2}m!fD+$6dy`Z^Z*c>BhZVsd#WCkdY!PuY_ zGrAs=fnjt#CMY#BFpRFpgoMNBdQ3<-jIPIoh6Csx321dWx*ih}Cg6J~K#exg+0dXt zQE2#p?v8-fJ8PlqA3^obA&?qSCCI?Q@D{{|>iveqmPcCi=!?V#*$Aq$Ks2bngt0+Z z!q}j?7{*4fA3;N-FmX`*2xEilM;IGi4}u6h>%VxB)_;N4r^D88fDX<9u|ae3pfg!O zY|!YiCUhMW$nW}4HmF@-3}u5xYC-;?_L?S;nZ#gh>xn?^c9>pJID^=rbq63eY<}#8iqk~AU67XB3$Y~a}F>)AbmANt|y8SCvH6vs0{(Sb{k|i2*d0`Ur+QvoPl8l z8)RJ%XblID=L zss&c)0ga4oZlI$T896{#f-p0&MuT|ps}?|Wsmv^_pkjfUg}n$Q$HER;Y|hNcu@Q6x z6w5TwjUJt#?YZD98*)H3703}F$1u)$%fP_Ec@#7$V+mq{B)Ezh7%f3-O+o8Mpv1gJO%0|OiE)&h3OtpyyYlTIl2 z)pN2kKyHxt6b2pZ!-X`VCCIzbpzl|x!Bkc0#h11SN~AnXplb^)|rXqe7|;kp?C zbaynC^HhpUQgSkr^fDMg;mQELgx!XbnFD+T3FO!k$U!DdoZJkI%xs_oN;pAl^%%jo z4S)&IB?wp#_^(QhFJT~NC>`cHQZE<)TMs7SW6&VS!0z3K3xWrxAw+&@UJ2y71dz&t z^5kL&53Uv@Ous7~kZ(Z%U6+s#au6giK@LH273j8)cJgp+_uLqUO zAPn2{4%!<7V}r~Aje&yF2dM1`VuQv}K^Qh3O3YX)s0&E#@lfzN^q_VP0|SFGs5*zT zL1%`;_924y+rZf1wh2@Xsr%DG`{`ij)FIggZsSAE>_HL-?^S_{gZ9wD`t8Vj=s*hy zVP=BwDg$Ra$QpOp{>qymGoj+3g+(y+FObB+aRkcLpf(xOo;#5BuzomlA0E_KhKVa9 zsRy-vVB(;?A22p33}I|gI|#-G)!r~RXrB^{4Qe*Q*d<8jgZ3T4#6fq_!Pua76^so! zQy#_!H6CDWP(u*L2B#$ufoDuX0kmHp8YWuM`xZdq1lqq38b<)to1p!DAT}uN+d$QT zj&*T@vO!}Fpmr!o4XBI+>4(K5D38I|$mt)~-YAe>VlcL`15iGO=>_FO5F35$z=Q+R zX9S&X4=Ue4>OgJ;=Mm7lc#tLr1_sbQAW$Zl0;vTtK;t){WCjWs5FeL1&>mKp9*{av zo&q)ZL2M8P*$bl4?`nu3@~#HZ*a2v9F~|%MhS>$`B!J8YjeUT`7jO`FR|DwG1<+X$ zAUz-qGY|c)2GAJPCXfOshN%OM9U$BLhZAzA9w?kaX$2$)3TJTn0M!ekKzr~&aS39B zFw8vAfvzAuFn_!u@~#HZISJk{LqK^SWGDjz1NvPJ0^E?kKFEE@V+Wvo1=0@ce}S}u z&J_Ti=MG|nFh~xB(eG+lO5|M)4_LAH_0jKYkRbA|h7@kdoem&>fa)Vqn1R9>y>A}E z#=rpDcLeeS2!s3pqoLU!#AT2HZCE4Xt_B$n1_n^R2WvtKXMICcGh;}%9841Gn_F6% znSd245WcIS2h{LF>YF3q)c|sbSt0|ExIyV;9@b-g43M2XixQ!XMh1o(j59dia_wba z%XF6IFWUo7hHG66JWQHwpvxB+dQPo!kq+%K);2CW{y&WUk1i|zyAlIHbqJ^s;4@$l zN80BD+WX3QmYIP8v|j<_D3C%B%@hl|SOM0rHw5j6>0xGIK=kXALCc`w{rY*Jy*rE? zksykR6|~!(nS*sHs0+`*z6!L|aXt$J12Z?Mnqg7_34`xcU;=gEA$KY;v#^5p0x~gy zHu8Y?`LKW%lryC;f|52H3v{0ks61nV?DGL_WMRR+&xe_Xy_kW4fs2F1or{ryfg7|l zjl~mWIRiIn^pgd;&xgs2g@FNbrvejbgc`QbhY2)|!wTN#!_2}C+PuUY&BDL{+vfv1 zG=vp-pAX1n7Vc!wif;oDn}eGRv=ki7=HXrk3Mnv~n0-FGm>C#g`+PvR9kZH)Ol05& zoj${A0b;XoTZ7iMTY}ge+@Rg{tX3d45BD*U3#>tG0dDY)4;v6$gnKq&Z9IVBl8#=h#KtT-M=aU8s`ckm@ z4E!wM#*8Z~0|R`Yj|<2PWsD#N3?ks$2_Rd0SVY)BG7t`j2xz4QbO#WR$PJL2Yr%R1 zL_p`A!1wup4tQa01j|T>2!O0^26JRYOhFv1`+Q76ros04%mg{T3#>;+1ay=EYcH5% zAW{aBf!(RV2yz>2pATp^G%IYM&u)+m>`sM55C^u;2NVPFeLm+w+X-edrZF)v_=tcm zMu6X`@CBp?cBg_i$WquopQ#`{X#0FXJ5zD(^8tk^3txOW1M4;rlY<*n^}_b~yaQQ- zWuMOnP-yG|sh8jeZMI{D?(?Ywx#S?I!Kc6-3Q_~z=L6c_3ft$i10)XJ=L0$piIu2* zJ|MdsxIx#A!|qg&1Gx>$KA-a-^KXFE2XKRq*nr)sZ~~+rdZz;DwiVc&3ZT|2>tm4m z6b3O6)ym4i0NE-4@`yN?3leAGXX$2TU|?qCn1a~n1Cjup29Klx%ms-v@U!e;Wnhp1 z>EdUZ!OFlO2I`AEMKvEJBo0-69Ha)s{*R)DfuH3yD+2=uC}W7SF)(m~t|4ZE@Ks@a z1_l;ekQbr*d_Y&!!uR=r^D=Co52&rpssc{1ETFz411r{jKE2@5)0S}y8v}z#J19_L z`+UxUtby(G0bQfZ>Hr=&<`J<6DTD9x0W}nlz?{d#AiSBGfdRhHXCFu@Y@ZM4C^FV4 zsFPShnGm+mCmUoJ+CCp8RtAOu)&$0t>PuG_WAgLoCw?J1GQ$YrN92FZ#98_&e7c(%jfl?$W?MUY_FoN!RVgOAa%7V5HF|r*1%}j^M6{VIi zF!F-T22DlDmoPB$ff7Drh{6j{_l+Oqydw+@42s|uASVNZB50hLpOb+>2~^oDgLeoi zgLeffgLeff!*>ON2I(P}C4jRR=oleLZUMOwax($QUI+{190ry3EDQ`Bia$9R7$p92 zfCA(g2LpquE6D%OAeX3u`X(G4AQw_)_#gSwWOl?w$e;_0pqD0d!Y)nbLcTPa8==;M zn}LA`G>yQ(z$?ti%!jyznU5EK4**CJKS+_MFav`CSQ)Dow>3BD?0!Kcvsf7zghUzC zB^elm!HT%8xUE@1ibSA_SUrV7X3=`54j;&Ika-SSq-hTc1_n9Q%MIj_xDpHu3aGOn ziim3qKsOjL3NkVumqDGU+*?>jz~c zNbd;LuYxE9>4LBr7#ct=aR$)!Ov7}#1@j(k=mbnjVo|y-^v-LV?hB%+;owb2;341m zBFYZqhfg%IGBD)iCnx6UWkBv>gw8o}gXWe%TaTDIxxm|yl);DXgG3m?2js(Mp+E=h zLyqf*kdQelFdKZFej#|~N*Fv(1zHcp7!Tf^5uXOyx?{u;pPQ7EnipSOl30?8e9(1% zS{mpi{rK|a42F2vA@A{Ji8-aIpe4&7q#sTG+e2JlO~A*ZaTBvvxSr-NJzIyV=xbQ)${k%v!VnMH7nGJ)%z%0PJ;;Ti0EHM)4stqp4i8L# zLNz`uFR=);(JHYx8R7Aq{N!wg_}tQ*5{SmkV$iN&xF*=4{h2wbpxriUp!54dkpMc# zzaYOD6idlD`NgRW(6~%Nt8RBybilD&{%CMjU2%46Oo=gUpSLK;`C7>A2O)5gl^zp?hnJJlhnI-Uze3)S# zAD^6)nwVEwzz|=Qn3n=|8z_x{l79(9d{Js*3PZe8W;!T_K*<5*Zt!d}IA2tzCKiG6 zTv17Wc6?4EC`S~hrlvql17$~05~~EId{7CI4RU0Bs84=gIzxPXZW74D4DrROso5Zl zK!pk=ZO{1=0r+2Q|zfoUl7V1m@IoR88$=F=y-=VIJIF5}44Tsht%m}!LCFHN_X#v73gUw>NFLOe1hGLF z#0NJlKnp&=g%u*>gNhl5Fax{+fmH9n#XzMfs8Injj}bJX0UC1$%{73!xu8XBAU1fA zgnYYI1pbCzG zfx#b%4O)B*D~qy`#H&GUs5z}5HdJpHhz)92GB7YqMq-1{u7`@h2Z=-VvLfx95b1gbA#Y>+k>8+rW|Xb(0_9CWTGj15{l1Y?8N)WF!FA$1tr4rx7=D-s)2cf-_x zM%`g-jfzAVmt-pfp0RzQ@DRd7Qs1*yE{RXYw0<~ux zq2i!+kUNwOS~KViWrNyy!B94+eFR#d0MZKzZ_t^cAU0^t4(RYw5F6BP%7&^3?SCqT zvO#0Lpi|O7YCv&P4;2Ru5`)}F?LBFvp0f>d12Gu1b_vu^fJOuOOl(m145k;9&OvO@ ztQLq33L6k#LISc54YXbkq#q;)(g*6Qf%q`_p|sRP9!Ob<*QC=Y_zAPlk>M1$5vg4iJU zgZNt{5POI~ON>BrAoro4iM<1KdpKxQ8b}kUeGjG4_ptquU|@Jc#2&WGoD2-0NiwK0 zkTF>X1_p3@6(-2Qz_6Q}f#Et5ALd8U8cmQ}Vg7g^581l}3TKe}L2@7(yuKAl|0E*! zuo);K(gCQy1v3x*OzcfO3=E)q!C_Xw+=sr0Eku!l0d&qg$bF#x2+TZCnFG=T%GV$> z%=j4?N}_i z;mn}~*;fVf2WXucNDdUvpp{23Js^FmqL6eCVuLVD4t)=sh!R8{$UIO#7G@r(TM0|^ zApLViiQB{0AO=YXpnMH717sd3yg^A9*}MzTy`>Gm|niV0-<$s z#ugS9#IBPo09B|+>*Sz&*yaS!DG>`|Xkun)0+T#UJi-milVv~XGRuAdErJ7uFRp!T zpgI?JuJwIrKOD4=4RoFeBPi1{L45{N2=XZEJ~q%9vn*wx6>vEAv8@3OK{0ZGmW(qq zv4WORFvIt;#e?KnSV7mYFtf1#1oPNufha}}&{}dfq?85nIqOppX;F$1FwsEh;6G=lcAfe&zI3}G0!ZEGBe>0IP(YoJBbAQyu&0V6{Y zhysmofF?PE=7U(ERnLqJK_CiL89^jKEYJuZBSR2~0)+!a0%Q~ngYp3*LokQ}83a-g z3^o#^oDnez3zCF1^FXN_q8p?H!eU?u2X8t9%^MHXSy1SlXHI5PvOaXq6Et%O8pg() zHH6Ouf{Ov@^q)N=vk-XV4l^rIP8l?s~OVxZsb&;SkUgK`mU03TF?fN~m$29?I3ybH>GAT^*`6T}APL6A5o zi^If0Y?wGKXM)rd9JC*jJJX;w4aoBhnB(%uvJ4E&ke#1kwIG6-0TfOk76fCC+k;xC z5IGQuc`q$!q!}aw!OY-Wks)jl$;<$1#erB5jCn6DsI>r*1Cf~b)Cz;gvO#j7n1t?2 zgJu?JHV0LGpnF@HAZOQsnsK1i&|Q0=eUczH2*c#i_oU6?WMBaGA3^ql(izNNaQOhz2*m|V*zdDK-;-8CEPg?I>p=I{f&2lQZUxDK;ulo&!O|$m3@sw}q*f*FEX7gZuKbSc}H>bgNrQK!y3t9mVy?zSZ zvLM_aH-O(i1uAPmC$DnONgM6bCD4aETdm{}dDGG9Bo?Gz*X{WM7&BXuliy z{wZb_Ru)iy5p=0D3uIrKI%ppp+P<`9Acy!Y2c1s?I^GQTzO={4_fNeASp(gd2DO(m)&B;QP{6fZPw=mj=o!tk8XF@gP_DfUf0X zU=##j-h^{s8ZR>g18iR!IK-g)(sqJ&Xh8R+fv#AE-9H67;**qpX+=o)Pk~M&VukKY z0~IN(sQc1DS5CqArE!D20Na-ax|<%l`;0{de3=exUmEzXH3)}CWDCg6uzhKYpxs*a z;9F`$L_|R{uzhJdpgaNFm$nZigLPlpIgku&UmAFCAZ%Y6_`)aHzBFr49KiOaMSzTk z?MnmSssr1X2D$?Eb0SAP#I_+Fg)6uzhLZ z%T>_!rFAniFc7^jO$6ix=>1cmovEx?_N77Yp8^fdNpQ!4Y=`bkdk1pXLC|(C1@4z1 za}I+lBo%JZoprE%X@5Z>3Eh_lI(m(ieQBVkI&5E>1t=q6*_Q@7`hXR>FAaQY5cK}3 zEg*M7_oadF8H3(GwF@Lp+P*X)7SLXqbl4^`(6%4QP8*QVA^U4UVMF(QX_cU$h3-q+ z!ot7+-Du%?jI>_8yd0VEfW?K@khvm!=0Y5p7>u2J-z=K_L5+!8w~jWI0GR z?EWcGdlP>DR6NK~*uJz~AU&{sX_G)4*uJz`Acw&ArGXlv@cXC0+t*nnC$D$j4k^oD2-C;Kr*&G$$w{gPg2V0@?~Uy3>tb zJKZE07-SK<(U`F8bVEAt546(_v9%4f%Z*Wx(NLIyK?!Mdn=-;Udr6RiDmXT`f!0Pa zG6aDra1)#1Gb5$bFOXhMFo*)>1f&TUP@VzJ$}lp7fGC)SAxM)mpuRFl85n~)S&R&! zAPS~76iF?7hZ`vUf(#_aT#%DMi#iw?f9t%ACD1+*;&wDSr)dj=*zGhfIvXYr8jTHx(ODW$o& zm5{A5&|O-^X{h_n7~*03kD&XQARCt8Cc}0bL3i9yda)OYo4^!w)4 z?-qn@148T-N-itONzKD@W@bEin;~T1ALKqT(1a*xe*)N#3MkW;;9Xy^{f{WS{2Ibyln!y4GX$O5|nHpTdu%6*g%uMpnS&=AD>v9oS6yVQiWhp z!OS4Ze{Jyx%N78GPVrJaj87bW>RxbVDR$TPMW%pfJn@ zZT$l8uq1MV8eI6rgD!o7?{iDb0|h-OHD?wl!yE&Oz{DJ+eX!sSv#>31DBDWYz#BNh zJ^?uiygd}Uvo*)eBoVR+wm35#vgMS1)8EjYvLH7>cAi4~gxH@7*aeB?hz5y+CQCqUkb2Mr5@_NECJti5#6fK!u($@K z=LFINYVv>@Ltt?b0mWdusBvLfQ9ihg(F5NwmXexOnjW84l$e{!fGm=kmzK|<2a!!o zN-9b%Ly^wOPe$P<7A5ATrxv4#`DPqt|&d<#SZGzN;G;H)Bc7UBxQKFZV zSpwBwQKDB+ln+`M3H3URLJ4|?kN;ufAR2QX9y9|8l7V2#_sfBr<`A<$B;k2@(6~29 zB?L3WN6}$?WZ!_+5r9@+LF7OrGkEq2#DZXE@Dbn;Hi%?qkOYt4gV>;C1llhLni&AG zLCFZj2lX^T@*oVF>jcfuf!LtrCkVPb4Km#iDTB~TdYBYq2OX%C1Jy?GeRd$D7#Km5 z{h+hnk=6@d zn;%A=cLn(sHs=f)Pld5T^Nt|BpwUVYhUrC~n+46Eg4Bb;4CEdd8`NWho%;$J1ct2@ z2hIJ!*r3>gu|b1UusL4jeFPx)z~=eE=YN6>gPoBJWrOC$VCI0Z z9yI3&69*lf1Y?7;3ycjK0fDhWbEYshc&{APoEe~bJt!MA@B&k_0!bWnus=-vIFk5N zB=#pHHh8!OY9=>mJ_yPN9g+q!2Q*F&V}s6sg|SVM)H@=vL8s`!)TAJZgU%C$iO)k4 zUxmcphQvOE#6E|_2Je-Fy7L*5_$MSbXhH#I7wFJ37#nl~A&daeti625@pGRWfL1Mo|Vt+$o zgQojnW`d6RgRx~nXYE7X3_5ESCT@o$4n8ysss_AQ4$AIFQZpNg4LWQRX3l0L@%>2b z(@5;=NNjdiMEHZ&OTo<1MiMtiVml+T{gK$9GYw&S`;f%dK=*h--EV}%wnt+7Ah9En z*u_Zf1|)Vb5_=XBdpQytd}kQc-b+a0_mS9dkk~(w*u3nBFp)xHt0S>Zkl2n$Y(FG+ zG!i=liCv1sZbD-BBeCZov40`4!F%PP{^AD>M1$IAp!HACd%r;Sl^RGKv@oB6fdRZf z4$21akAt$o`{ST&@cuZcnTa61P<9>?y9LCCs-Fg8L)C!JTZYv&OQ3E5)nD5|YM|=x zgV<2@Z$NCQo4+El-9Y>1plX6ZY*2;9z`&3MVnfA2egoBsAR5$WfU$?lS~Jk>0?f^z zIuXVOogW8dgX%{Zy9*Sr(69o{)4;?*^&^Z8I`0q02Gx}?HfVnVjJ*xXoLxw4&|C#f z%~>SzD@bh6`XQJa&@KfS`x%lN&;$ld9JE^j#s)3?fw4hrAYg28dj_-+3eP@1(7kT3 zbfpX3D+h{q*j;X*pc|*lP>z@LlY*0Hc9Lff@*FclA zAoZa3A!yzY#0GVfGNEcf={XuK-_wk*OfSl(IG7l7wF!Mm}0htdH1L+6( z5k$i#K`a2v@27_$jY9SaWw1E_rr(gVUUb)fyfAhTii z&QV}s03Bir@(1$TJ!URDPHVr3wxpKg<LjofM1E`+~3ujRLfs!t=c{LIY44}LPG7E%3=74DEzQEMn+|*oR z_63@l8A6sS5^;Y15>UB}v{n&ze!iI_!&)XQr8}Z->-4mJX&kK-rLmiM0vDgX|4t;b6ZC$~P>mnjk?I z_GO@z7%VI-?4Tu8EQ}nWlkwT+fwF}mX!9Y+K9IePa|9R}7}$$JeMmzP6C}Yt6U+q- zMu0E}sI|cemSqg#0A*=LLy$OQD5nufp`|z@0|RIk1D7v|YX#ymhH!)GHqfd$9>y4^ zQU)HzXr>Yd9>yppkoCMQATRLovdA(rFz|y)LIKdyUS=`SK#(BF9S{O!4FlGra}k%~ zF(Y51#{w1SV_;wf9bn7Az=r3JJa(kRV#OI4IFPs!3=Euz8FBCpdPrOe1_tiVCPwHq zIuFt`Ixomp(6PCEpm7v_$US`msBQqA6D!Ed08#}CZqWD^10zEasIUMfC`N`T5Cw`J z)Olu*Vo>g6WC#XPAO%QM<)AzTG6K^i&`w`QhA2K})7oYLIXVtv=(fROzB zoMQdtqWt3GlKlJ}T|amIq|(fslwy6zz^iU*ae<+Mg>Gt2nto1Zl74z}G8P#VJqtZk z_-;h1OcP+=<_IZ@l0hXX@)U4!3CLrRNni%p&3dMc%$(r)+gk8EEf?sNQf6jOJ_bhc z*`?KBK08>2G$#ja#uhwV2_``EN_nZNDLJX}IjMQzb4KG!7^vbo%&*QT96C`WA2*-g&{-^L^6ZRcMuDLG51k|;sPQEB1zvz32I$|bV4vQ zsCV#6dMLOg-p! zBp4fXYXyv*jies5{|Y7!x+4$92KU*Z=C>oM2OSsz8xsKCyaF3;l zM8SKhpz1+Q8kibTTM@xP(vEV1|9nfV}n|(FgEC{B^VpDMi9o1L~;*kj0GkR ziWe9g6fZC~sBaBpgW>|l2K5r3`3cm&0F66=@(Ab> zA`lxCHeS%Zp`bhjx@R0D4l3P2-3bsIls7@)4;!CHW`oRvxeb&bVQf%dhOt563}cfz zP6e`y7!2wrfy!f0xPjDz#(zNhAH)V>7#n>&s)7?z6N174q#vXX2I9la1C2+4 z#6V_&Fi0JUMjwxA;e_0i2Qm*-1Ax?l%mcXxWFANiq%RFbAYqUkhzlwcK(#3$b+GX$ zkRA}uU|?VXm4hHQ2!ree(V#vvhz;w%-{2(fTq)35FLp3Tf$}HFFa`z&(6|+{c?w(% z44~d8$iJYn93%(wFL+)Tss}`Y<|tu@$$;bVs7$ygr4+fbH z^T!%)$bE?*dqMVrC ze?e>z2KfO*qmM^f@Iusq!UcIe3eJ6M+&le4HpAH0;B~ZU~|n*+6vw3nK?Jh{wbV>aMfE$B95gPb@5~paB>b z7Ix6?X;#oUkvt;<0~-q{ld&*zfV%eVpu?>gO+dpnAX`DUGtPMrI&2zTtHUKY!3_r! zkPKrm2dI`|Gy&Dcpfx32pnDq_tw6p26^mTOMac||)*vou^p=5*1vEj#P2m6!Y{Z2f zb(BSrQHae!V!D$g=t3e6q@f*g1_n+ft^@-E7t*yr;tUMjprIR(pBX?yaf}Q>APVGv z%;6YNfzHSPnkHocwNcm^Di{<>7?kFNIH0yH8$$_01%u3d5F2CyTmjg4=;^<9?|`}*;2e!H4g(*1F=u3E z1&^#Sak4|lTk61f&FFzdIYDb27{P-qU;@+lMpU<3_*Kz&(Ulx#rqm`iSI zE=W5=N^yw+WM~BJSClagI0rnU0w%zUKmh_~z!iW*2n?g-q~;mm8ax4o?m&*0fRZ(A zYy^}^K(!2r28n}c5C-*;K`mogHUNnc9QPPKGYYh=1r&@>On9sVG}{hU3@-gZEe>Qp zs8U1bgKB(aKBy&t%m)>$$b4Z2P}K|)0mUTb%qU1+fDBfEa|PJdpfLrIZcw2LVuNEG z)Zb%8TGPqO0A39XQZqWfz`y`H(-}6_0Gg+Tu|bnJuzuidP#A);7y|Ys<2pae7s+3sz7kA5s9^(RXCbM2Bvp1k~kXsXaZvua2W5lW{vbUtb3i#9#wKPQ0i>50jBQ*1l;>f3L1_cT28n^#uzt@2c1V8# zG>!!7bAaSPZUi;@KzxuNLHa=Bb08XqL2@8ADBXaPC?R#AHS91wAbp^-tFiUt(a)Ir z!4B!igWLyNegJbHcTu?B8cX5EqQIL6{S{S|GeTJO@Wo7~9K4`x?J0-KIh?sR7h9va6-+&y0)bAEx z;AO}|>NA7NWkv}`NW}y4G_0@80!sM|%uMW{(K=>EHc&=nX5;|vEnsG1bq6&?I9Nfa z?J;w(H-dO9te`PdW)^mSMg|6E7IyH05k?Nsf`8=hs(?5H0~2)30S5yEGn5HRPoOdp zQVoI}4RQOkRu++bux$z!Z0~ddkB;YVD&WUc%uUh4B*p$ zLE<0`s#ihnYM367eo(s>)aC-QK^P_nYA3-u|XIn=M63QVfH>?fsAK^ z%3e@u53?5>FCdLj{Dc9rCK1Yow_iZ>cp$T3^*(6G3p7uLtPUg(8W081Fm<6!*vIcd zqnsdj!1RO8z68xR!T2CEKy37S`UDdL1LzE1kQ@lZ)PZQ^+!(^lzyJzoP#p~lUyy&X z)zcy@kUIfEW`Qus91snwr%O_E3y7(wjSP(qOuz%=gwKM!0h&-ns;5EgE6<)ebA|~u zyMvs87n?m~Sj$wDC;(Z7*~<)S!%25c;$R4?{BJPhK>AKrndD<~3=9bw2Wr`3x(_li zw6QWAn6+raWXB0N7ks!YcwyCnMW+lFxihTgEZ@vgbo~D$c82YecM7H*SeAKsF1yaJ z>6;BVaWX8QZNS5|$dh3&^I9f>g9?)p1tB(0QWOlE#koW9`D->AXG6 zuCg&QaL;7>@IR*6lIfT%Xzpw+(_ZE|SDF+BE-h>bIH3U1zmnzJFV+=IGLqA!WY|O) z7|t?6#CvY7VB!&4bn4#%r{=XRZu|_=(+@4E+O!~Xx|sGNPKM*NI5&ARNY8Bh{hxth zBLl+@?p3=taWhJ@@=|No0T8IC>r&%ndw#=yWMrOPGz0d&qL4=>0SXBpq} z{^d=5^IwCp=Enk!W{{jC0}l^Kjz{(_&tIOUum1BeEdX73!2mv=6RwZtFYnVA$odi) zczA2hgLHyS{qRNL=`$p0kex7D9^SVsAHE7aeS#tnv-d6!$X?aQsP;kvgNJu76Ug+x zys8h8G{esX<>A@O1aY_O{r@~13z{bDa)A7l2t6|tr2j4RS;oJ-s(1feFxGs6_{9Kg10n6(BQsct3m*Sb76R4eV@EkUJp$Sb7b~9iY62Yi>sy zGywxDkogM0<4B;y4m$4_RHj4bd=O`rdN4A8=Nlm63UKwHy`xb^`QNupb=Dba}t;s7_f==`8bK^fTR}(ji8+Bh#lqeNI=J;M+bDsWuY> z1NU9f*_GxX(;2wqK&DuL*eu+j72d3tAT|g09ySIBRx1#jhx;?=tU+rKTYx(h#I^yk zMY!LC^xA^h65N%bvjy!yY#Ht>kY0NbTY*6Ul!rhEw`PNE-UV{MCx{7YJ+gX%*bRcS zK_>Zt+|0lzm<>|o58|*eGH`(QaD(n#1A9cCf%gyO;MN@=*n0%9_7KLt4;6l5t2 zH)vlrYuG*}1_lmp(4BFt;a8bJBcl8)Ad@)GF)=WJFw{tXmMfrrVf-whz~OBMosP#^ z47!1V8?-#0wFJau03R{HS_(Fwfu9AGGK6_p85lqZxB9R!Fo<}7yimpnQotYrTBOff z&DaP!b3h~-bP6Se!y)n%sWii90QSVkW3%g9utu{Ah%6me9F$iU?EZpinoc3uh|(GY(!pxWF~=?Ifw{?WTrCy zVP{})5dp;j>r6&auzQGrG9>FPMo_r=h=5Wy>s&@RHU@?pBI+P}=7GcDi3n)L2J3uA z4h{x}7b5pSMlS#x{f2>`g^ihkffuy>IfHdGXcrG(d;tUN7I3KZ#TPNKZUu!Y3txOW z1M4;rlY<*n&a!R?Wp^I#C!lcO0b=v<#V4gPu%mND@ekDmWo=Fz~a0QWrl9 z$V_3-x-ZbdttUYSfEJjt+A)II3?krjr|rQUHjxdW=yYHNRRlaDptU}%&WwrRZL1t0 zv70dGF);|oLJw}0W@lg!0S!;GMlym+WD(FfI%^cvN$Wrn8x5A>5K#uXFNP7Mg@=Kk z1*BYf2`d9b0BZu{K9D(WAp4WS>77C3GDvj_BPe27M9zZ}X)2h*BeDQwXd0L!BJv-k zCmpO`M&uZXlL59{MPv;q!DND!X^4P&6|7lcj)BN*kW4n1V<7_S`>^JKISwMAwIZy! zV2%d^2Pm>ZMFu#I*ctd)Kp`LrDmTFK$-vKYg&lNSXgeE-1l1yvpqvj&0Zbeq;g4V? zitG#wOfoDC3~W`P%9ZH~8v_H|Y*45&Ed(9sx&xH3nZ!T}c1{4D*}fYjx(hV%#B?0A zjAb{dZ^;Dez_Q&0b<>zYYm(URflS~9ZBMpgm$K(%VBiMD7rTr;s5i_FIu(~)R+58( zfr)!ED+2?&TmT0H0}Ho33j+hYd^88B*k8-Uz`(9x#lgV9#of)uz`(BP%E7?E!#xAU zRsxyB$L+?;vU?&cPL{XJC-!Vqj2&98#+Q zTGjWDpMk*+EEdB&aYDT!_!L{10#Kq=7GPk=1S^PT=4xP6WQ<{(7{FG_popSW3ADlu zWR@Z$*c?#80|k>Z=rntd1`rd}z5unk8RvWg%{qWXjEfNzWMNDU465KD;{xYB#$dIy z6b42z#9LIb3(Wo z7*xO(ih?aHhg&ELwNNRFk%0lz3PVN47?3^DOvSKJV^9ubVPN2B1bGQmy+OQm1#W{Z z*oGN!8)Tt2sDpO7Fv^1c#25nhpc0q^@?aU7?Mx*Mij25?_!_ictPW&9th>TECmggO z6YN6`u>CvX_G>`xR|Tgl4X~9^`*pz_ko{8;_Oq5SaQ=}Z5XiNl7F#{Y39z0Ks93YlpDUgFe7au^QgS8auAiRMBIt-tq85HfX zJ{jX2Z(dlmJAhpTI%^q{&K#gFQo4ljI4GWxQWl7d678V+lmpzZ1a%cay)4E#8+jQR zG{7m>3v8kcGXn$IC%!PBXoA|2?g9)9N}w}^pk4x*jbs%x5rYN-m8C$*w+Q49SYMHG z4rqTU#Fh}SEw;=I44R;;|G?&g>N`wx5h)jJ>}6I4297dNgn`OTh~w+|V2+Ol8w2^6wg$3XpC-6#AE3=*I=qP8hB z0|Vzokbgm?Fr;~){hf({fpa!UP*#9}0W2sEQY{YRGVrs2Dhq7~Rt5&n=^#ZQ+mRH3 zgdj}`9W7A1mW>%ySR>EWftG`UXX}u+3nR_f!FCRFFfgz}m9T<#=(343a&v<&Bn2%a zW#?sJ<^yp+G8~MIp28qePDKV!VSR1}1}zl= z4)L72q^B?_xZta2rI8L37iVCQL0Ua4&VYOnIRk?n>QY*H)J@Y0uuan-_bMW7n^uBJ zFfb_NS;ngZbqK4cFlbA*D%2q$t^@;v8q{tmR~<>Q1OtNxl45ZN22I3?=voLz+Dn2q zXKSN6!3Mm9SO_4Q9mE3lRT&wAKoqF;g}Hbb zypx6@7({{Qqd^LS=Yv?_rBw{UAPRJ921EkHS`3;?Vh9FNpd&0G5+D}n<_t!LU=XDW z8gpd$%osc$!~)sQ$Pf&oV2%ieuLB0TA2c1p$PfaeK#m3(88RQl0%>7n2mw(rogpYX zSA!iB3Zh^NLQxce#_AXu!ax+rS0JOq!2Z()>kI=?Fr8sobcVxpGBHdH0GR;ZV#g2; zqComU!XPhzFsRK4nsH}j2nJCgos0|-AWa}!7#Si!6nLtSAq+%;R;w^Fgo7y1L=7WD zB|$43&)YK@3oMBQ3@T*#U|hMusp% zq=X@&0kq8z#83cgd3=GG0HS_lC;&AYBtZxMF$94qY0wxc=x73XN&r>=W)KA+${MQz z6R?6{5Cv0!NZ_EFJQA!R2t>tUm;h1$I`D~+As9r#6d+6h)ySY0BqKu*h-$(x0i*yl zP{qg)45DBP5GH`CQc$;*ks$~~fkv`XgBr9E7BajIn!Qi-94Mg@J*IK?CFs zQdZ-qWaiU+F+Ob!v4 z21aInkde%FAX(@=1`u;uz$P+tih-~AW@TVxW(1#)0Wp^YESm-F%n0@m>} zjxgAdAm72%NPtB^;RZ7Yp#~-b3R{TD$Rd!iLNW)k4<I1MIk>K6ov5wE|CDm5IBlc6H^%CA@?%G zXEPK-Jz@xF8G*0hpxV_E@E9qEMF~oDgYTKhPfG(i4SW)OaY=k>W(q?*!aAL)_ z`mr=EEwchNI)MA~2~diNFM@d%b_qphUJ1xDP#Oa*JA;KH_%4cgP`DPQg3g5pu?jL% z;)@tk^79Ko$MclLLsBF5TPmnhZxK4S2UOq3L$V#nW4YO|v>u zwH*|%(AzRf;xqH|k#>lI^A_@@8O5N?oec@bc$CXBKv5Ep`~D1wpFvJZ2Dz9aJ~s&| zm(b=ujpCB{M2Kae_y>hI(gho^d}9L6E%CXat2R<|Q;X75^O7qW;=#9W#Dh{Y$YXh_ z6(yisSc*zu_i7ZE#DfZ1hIp*^Yam~z0V~kJSw01HQA%o25d$pjVGM?NVlLW9$p^2q zWB_Fu$b}n_n{r59Kn#jNP*a2fa*GDciN%nxz;~ZUaY=l7W(ou3$f@Fz_#$w<0X^Oy zlwVUB;z5^efWik7_VC*_;^V>1AJ8o~@$n3qdHL}r19dnPXqhCa*ak$< z5`9o>A4G%XL6c9Q9xJE=3+lCkFlgHchz2dygsA~_WkHM3LE@keEXYidUJx5}^D;;r zv>X*Qi34JTh6`Y7Kx~+qpzRGXHmJ)BQv+hd#6jI)m^g?HTE+-+GpJJw69=(D?gQBc znsJ1=^8y28852kx)Q^U#2eCoRaY5ot;Pc}k#}t5${{=1C1&K?73<1p;fXo0*F!Mod&=OgYIiSG-u($@KGYy*e0J$I3lZJ_d`p_WvfW$!^ zXqY&t>kLy5>Nms0K|N;Bax0K}PKzD<{G8c#s zS}zaFR3LsV0|NsrGlBS^yFp-?2*d}iF@R+r5Fa%23(GVhK4=dr%n2a(g7!_qG7m@| zv49Yq5T60kp3qAM*Q%g~69a1Xf@uALdn=&I zAJzzfR=pr0M57C(F$Aj*Axa?q5pXLBVrx9S`es0CZ$iz2Rp`YGFjL?RkPz6ZkU|x9 z1{-LxB50@`6kedPg57}ws&E)Vr7rZWHJCVPD2fquU@rsYY#kUIG(-(!gDN5z8?^Qx z#s*E_!`L9ZKzph|d(uF9L2S^#s6NsiJ4PTj69WTi0JI;<1`RfY&gB8A2UR?v18YHS z&;Tjud>s%QQ~`i09}!;2dQs5+0GK#vaR-PEG6yt13u1o+4a$R7G4evf26XTVNE}qz z$biI|7#Kif*r2m&LE<32pn?%(J}CS^Y;I^K0Tt*VHK6bV6{a9IC_F%Z0I@+8FzEa+ z5F1o6gYLrtu|Wkg$PXYkr~(Epa09VHm2MTt@4O7)bM-)M@S;El1_sbRVUQY-e?e&; z#0FL5ApIaVC=5Vn#DLhKN*AOh^g-gF z+LD2R0dyw-NDV0NKx~+rAS5-Q1(F~&pfnC*!_<@^sc8qXc^Mc$X&=OfsR7-A19K0^ zpP>7lK!dxWd;wyE;s}Ic`>{cB0NW!C%7d^y+n}--#s;|+q!;8K5Qgam*$vYRYIK6s zgUVyrJy9SwXpam?FKEsIgkgHYdy1i90!qUmy`ZuiRA$52pfnBA8^gfB0Kzc6p!4ux z_QKA?1C{fj@*JcW#0H)11=3r>z`y{)FukC?%P_s5^YKCIL3ILX>m`g0O7kGSpuI34 z4ATo*@deWhI-3im9#nsT$_*GBbgm&tFR1JXVVGV}o`LCw-Gc$DYd~ueL3%-K(EeJG zUeLmA5QgamEii)V1?`OosRz|dpgaX*gYqFrFKCZE2*dP(@)S%j=&Ur5dQhDOItL5J zegWFI&&I$2I-d!IVR}D+=ANK&1Uf?zq#jhif!1Te*q~kl$X-z11Yww74$%AyR4)%B z0|Q7ss4fJpCxx*=+hsv|L1iHb!}NmkJj~6Y)5AgPLG>o+fN>ZbbUqhIuL&aq0|>+P zg7$sG^x8n}1=X>RNNiAJ9kw?QRL;WAAO!7)g0VqG7>o@ndtqjRiUyDyKzR$4M_^}3 zfcBHY)Pve7FgB=D1Y?8KJjg-@1_sa`f0#IEat_7@wNYSfP}+vEL1`Pt2B&AJIp8To zC>xwsp=|KEn@~2WtcU4c4vJH#IQZTHC>wmY0F-?ZNew8?!1RJ9Az^HGQ2avG3nQ_? zaR(I#wNqj0!SMnWcSTYU+V22U6NV(7i^Q%(Vz(l(HzTq4Be72-v9BYsA0x3rWjoAX zP-h6nW(Q4nLEQ<8XP7vsJcqG$kko+gdx43A7U00xpnF|lY)~f&#;!rq+kwQMg2Y~c z#9o8MzJtVmfyDlT#0G8sfY}9Fe+^?Rg4R7k{iTP*wnk!mAhAIkBVc-yki_$m*fmJ( zX-MqFNbC(r?7c|rQ%LOVNbDy_?2kz7e@JX@7Q|gx5=d-SB(@O}8?=xX=9ge3@dhMz z4-$I`5_AW4J0;bT@g%;50ZEU5<3NnU4X=1 zjKsDEEr5l_uR9Vu1c{x9#Lh!vcObE+BC$c|KEm9#9!VUunFb~fI`a|6evYK(3lf_V z>8>z7B(@R~TOWySgT(ekVuvBIlabg3NbFi9b{7(RIud&c5_=;O8+>;eGz_Ic_kcm! zsz_|m*^n^*S|f?OA+ZCI*fB`#bR>2$61yIW-HpVaj>KM!#9oiY-i^dQj>Nu<#74gB z>@|}3cO*75Xi^sHUw$OEG!k1KiEWI;4nSf@f!NS`KaLYp?}O^fVvsm=FFNRaTv!-3 zA&Iwx*ibi21hJv&r-9f|@dY3@RD3Cj4HaJxVnfBZfY?y+eIPbe{4j_O6$hPJ3)?6E z93&1^^9IC*s$u0~V1TLN0)8#7bHwTZR2Giaj3nk zL2Rh{;~+Lv{bvvxD*hM5hKhsQ9iaLN)MggvMz~W3#D=QZ0i9^k71hJv&=OVFpg4j^KuRv_5nlB(WRQw0jOi+89 zj~5Yc!XP$Oy&{MWRqq30L&d{DY^Zn?FT`!2c6cgC9IB=O#D==F8N`OF??Ga30JY)(Ez*b0N#P&MLw5O;#w?MfhVsF}JT zHq=a8Bz6FZ4b>Zo#BKnwp?bSOY^a((sQI9_{Y;QJRLv3)8*2Va5F0AK1;mDm9|y6a z=3GEx{{pe0>RI?17+`I04t|JVKz#vWkT_J09Ec4yQxA!43}Qpo_=DI`yCRU-%^)^Z zO)rQIRWlK47pU(r2P6(vvmC^R+O-D6hN|C+#J&Y$L)E`RV*f{Cs|XIgZd^gHgewtGzI|^2lwBh?gaHmVB(;q%P_Vps1FELsB2}cqK-T4L+2aPYm*r4;NVQg?89BL-$>@Ao$=-vPr8?==R#s=*pg0Vq;Z5SKY z*9L_NXj~2^4mt-5#$Ji!HqbaLOdPb82*yS}pAK}c98CNil3q}M8723jNON%9<(cH zZD%lXP#FqiJ0qz99X0?H2kiobv7?aGBqFg>k=US3Trl;ZRiZF9Xo3#LZbMQJ+L8qm z2koYYu|X4eFg9raF^mn`LIq>*MKb3I5*u``3``AZzY~lN+BgkkKSfgi5{V7kjRaEz z+Q159gLYZN*j&trcmeG#f{802iK`>AwUOAMT|zMRj!5F5zA#MO2T2^X{Rbuv>KDV< znMi7Kk=UT^K`=GVNa9^cY|tIxFg2ikJ}~wYBsHs%*z1wlpnX6v^+%D!&mgfcAhAKa zd0^_FA&I|5VuSkKFg2jvJ}@>r3nHBPkk~>Uz)^HOw5)nFla&2hiCD&^pBp$_CAx`as#B33||2I%vNaX#OMuDh^uY02)gNiG$c# zP;t;aQ2~?<8vh23v4hlr=1o9jH6S*q{siS05F4}u05om`VuR+C`k;D2b4s8w9FRC@ z{$(Ci9CUuyN+=sN&bvC-g7OZ?%v1)*ArBxn=)5S< zc32P_RL6qy6o?Hvqv!!tZ#M%2!!sxwG{^M@$_CBjfbP8qsRzyH{D6vs#t8pG*`PWW zbe0N84QMV5l)pf1&=|G=Gvqv0(EN`Wlnolg2IV`DnxmkF6Hsx`n6w6z4LYwCH0}ga z1DXRefr^9nI9Ng1pu0UCpls0m4`@R(NIhum8I%V>Y|t2F5L69lo-G2(2GzHqya`gn z$H>5t0u=|%7iB@&pmE9qC>u0?R0d^(#w;5K|;krb?+J|8`RI*1Z9Kn)Z77OgX-ITP&TL!bp*-= z9T@`}D+8Gcs$)TU8N>$FtJk1v7Bez1+<~$|TS7s39Ha)+$9Vx2Kg`I$0NVQu5(m|d zU!dZk{>v{Y8#MRDzygV1&^}ByC>vA<@<7?3xi3(D2bm+z#J~U=e*>{W{R=s$8qioN zs2l)^gSJ3wLB&D!n*o#!n)@ts4`{9#rUukTg|R`q zr(kU4`It7RKE!PEt`X2c=h-ICz5#R2;OM2PO`xYhY|p{Q_fy>J%6|1<6cMJpvO4)g3T4sJ?))L3IR- z4Ibx*+6!ts5`#hW&!BZgpn4Oe9yIR?!XP#XgZhjh8nh+`#0Jg3g7|ZEA$Kf;&Z7Y7 z2g!lDsNnM`86f9dg4BW52Y}joAT|ht)PZQw*(4w~%sd4>1_mBx1_qFMp!ydi2Qm-j z7LfTMF_1oP7z4xsrAa6a>W6~rXP7iDb>KN;s2&gnvJ+I!g4iGovKK_7-$|uo$iN^0 zbswmC0a6EYA9$_}qydUS4s2Qm*- zN5k}h^sNwKU;ve2AT|iY;uVx zXi&cyW;VzOUunp?84w$UVRE1~Odvfl^Dej(cPCY@Gy_8{NF&HFB=>>(;viv|d0*Ta z7<5=5?gIrQNDkya(3%;L8$fFWKt`OBXJ7!$6@b_v43Yz3@Y(!GcULV@gRJWUsR3b- z8W2Xmlj^=2ad%RQt3%e_fXo76kXaxa{Z1+cAIKS=p!fyN{lfeKE^9#=pjcj=fdMop z2jzmMzrjrOJE?ShAnHKofzG9enFpF` z3|wIb0q{ASp#Cjr?I38;I5LgQhRK1%K;y|E8YTv#v5CzBt#t%>jDdv_v|f)9l;A*} zUyvB$EPPPco0*9n)U#q{WCI;u$IQq9y3>J~33>=VIQcVku!9ylF|)9O`h?6Z>D@h9Y_|C>p-`du!5I{fk|!#HgFr28+5upE4Wx>2c0{Ed>RM%Bo63d`Jhvv zpiDl{;h)e`HCSP%YOo<6&%h+Xz`(A?06HTBd_pQDHGtwBlycH3}pskH~DKN>*0NTz3W`YT320jK*Jpkf>#@_@%gCHm=1+*j| zE$u-2OrW(bAbp@VFC(ZjfZYiIWrNz1Fmcda9c(=TsQ!eBgZp4m^`Nmsm^k=O0H`>) z-h;A1#VSkEOZ(a5Snav(mf+8U6O8PawE#V5!v5Qdf2p!LZxH-N-Jeg}0o7G0QCnzX$2G{AUROHgUfr6MkqF7WMBw@vOyHgJaGJg1faMH zbXqc$4WeM`Ky$7jvtjmvPU!;K1F{#C@+v+7F z14AZA07)H)3p(5qM8nj9##ynotw6Oda@(qx8GBz0v@RNC9@H8J(EJ3*-7r2(4ix?% zKf(N)!v^V#f&2?fk{~&dJ`f*VsY4C8$jrb1ngfP%K}|9+6J#zd4S)nnSRnU0gZfP{ z^RV@uKr{gYq6IoMGaRK*ySbeZay98h2rAVPRkZ z9SjT-gViyxwj!vogx@g?n&o9-Vh5dA%EHJ78Z%&FHt)Xrn!UOliQ?M{FgQg%^{O^J~SGAxciJ-@*GqZw@&=pez39+y>Q*x{ zFmQv824&R;F`>t(gG^@O2F)w78i3dw+~uHya=~mKZf%fZU^es^^+wRf6$XA54bU;_ zpdCmPK|K1F>be zri`o}ULc#ZK<@VhF=5B3gV+s%uR*$fKyGGW6a;M|VD$%aK*y+qhOt4>1C9fE2Hvfp zt4mmeK@kB7u@DfGfja?YL@3Bo7VaXDHDPl>hjMa*mKLyvgU)5{VBlu~nZyA)Vi$y= zM)I?422F?Yvw#AJR}ysKBx^A!HF1NsHL;d}m<-_ES*)dC^I^xRw=+YIQ3u6@2x!SO zYZ)U*0fPw0(X7>spyHfG1T=UJ<#33!ft&`B;Sq@jxw#gsM?eHL_sCk$SP4Ex9W=qt z+6b1B5CN@TU~L9-WJEx>6|lB2u0lRWeJ%JH^-_>&9pICfHAJR??CApQ(GmFt;`D+! z1|p!nRIGhqdrU+?8;DpZFdhLPqpk&tw~36Wz{jYAmbkM{0xNS6@dBl_sf@STLC2_r zVt{ofBPiHCL_j+rSZ6VU!qrFQE$CF}xs0mdW7I+Wy;$dg!{CX?M9_id^BJGBgN{)L zt)ypN05%$Qj5=sR0Iv}<149Pu=4e(12FNk$;82GgqYesF=rQUbCI>g@`UTiA>Y%0I ztSHB*?_vU-iwvp?S$BcdOK^jZ{$kw=iY6KEryw^T1VxYn_fk-}90r|ot-{>^a^X?X zMF$$(py_zl6F0%fs9S;p<>Y5p#4+k1^I^xRgIozaMjd3A12wH3E?i_dlpzP zfsQwZ9itA?>%lDzviAl^eE_#Jhz&hPJssqR2b_!y3=!O*sZ!QQpmHXLI~OGW7^FUh zK@3EJ5{Wp-KjI*dh=aKxaRz>tdeD6ij2xg@MSd1gaDp{}k_(asFc+!;bjY{_NEbg# z59o+=&{zk^>qyE$LgG;6yFqF|Y*3IO)G+X~+y@flvouRL8r}&fJ;ARFq=UHG_T020#2|jkkian!3ha;j5;WF@w0%; z6b4O^fR0gL0XjwT^NIsNVxwnG812xzo|H5bhB zVBi2nHmJw|#}Vilbx;UMf=+w~$0q|n%VzKy>1p6&)Iqg~Bq-;@Qouv7e7W#qed{Co-aZU{f1A}xC1EU})>4JnoYY7+} z85kI{IT#pZ3*YA=Kj zJ_=R}w2+SNBFJV~vxIRDNP{A1XVpy(1_njY(nZi=@C-_zh7MaQC=-E<5C@H6GAOSC z9j`6|T2~Ja4{;ESfu9AGR#d<@Qm`?DT!}o^1UkwTeY^>J!Yemu90_*vD<8uMKKa#N zlE|}Pxfwy>3EEUH3q5X?8*&({95-XAI7nO`ah9tB(h;wUhyz!Zu$`}pa_%eS$W;|R z2B^DGk6eXJ9|nOaP~t^BP7%~M0m(2j;7|Y>41i2%27wYS2!qCCA$=84F9#&TzyNCs zgLt5H4cY<@(+Uy;VbGb8Obpzh*=LfDX3WV<8axQxP6lW~Egm#D2|b1peEt`fa~KozQcNuLG9aB_&~fJs49r5H z!ws1s2PJ}zM`Q&ZkI2Yr13vT+a;P8Z_(E3jfrGGv`8XLs2O=^sG9n+$mz$WAlb;Ma znyD%kJX{JoI11u$hIpitrC?|5k$JoxiHGWeM~cA&XjB(@te5gL^hi57FD1V;DJPX7 z7ZxPRWhF_aX$>(=zSHF5F%OOd>&Z1tSDAV>!zUA_E~Y=eIyB3LtVIlJI;MXjB`d5`vk*C;C9xAd;B@H1Z8%K`=9T z{u;stk)W0Wh=yTi22g7g#skgYfmX>Q^Fb?`kol63fjekI0-a@rtOL}B1kWC!Ss9grH(88{#|s09vE4`PE7I%v%!hz;rvg64uiY>+iPPfj6wtf_%>3P;c~PjnH<8$&bHHF~J|T&N z_A0={xj^fap?X1ga>B$x(-tr`Xb&Ka4Z0K&#`Zzd3)~lzJZXvOsA+bSw17Pa^A&G-~qfmcIfO@7-wh9s(w1yF;*A__} zbgL*#95mnwV;3W-sYhaWBe6l3@WIp{M-sn`#0Kq!fvNe7Bo69k!NfsV>B88c8>V1v z(8LXl4cfN?V}tgK!PuYyJQy1^fDdDXhTmaq(7qBFyC3O16VNOXOnfDh_%CT_o{WNbK)OY|!niF!h2+XO)2VYrw>j&r69%Qj?9u2HhnKQ{RsyJ{yS*y7&~P zW;2rbekAs3B=&D4HapUJCZO3Om^s==;-HHSVdBn6;-CvcVd70l;-H&LVd82?XOb8r zu^o`uzDVqJBz6fB8*~pY%*;L{@!3f1ok(oZEmSb|myyIDAhF*fu|ef4Og-{>DWEGk zVd5G{=a!fvv7M0E{z&W?Bz7hey9|lljKrRR#QuQ9{*J`{hs0(^I!lBX#0Iq*LG=O$ zV$UGxYD(C-Tbf8}bfIcMttNYrIH>YvU|?_ou|bt50|P@Chz%77pQ!>hKL;cZW!Hk( z&@!hT#DYB=$-W8>)9768jbs8&p?;%mLA$IvB>rwKpGB$HCNq z=0;#_P@M~7gX&xu8#Iy)V}s5zg|WePE{MRhM-t>Fn0jQlfr1Ps4)Pw14KAOd;iCka z=!CL$p=?lGfcCeytWzC7J}&og&T+sTE7Hh!`7peh(q>FfZ9_a z{UA9|Sc2DWLDx%x^nunMz&c7GK1dyi2DKwWY?yg7#2FYs`@BHrfx;Oi2Qm-T<^q`y z5(DW2?fC-HFbt9du|aJlP@E7_2Z}409*{nec`!GC_#k^hH2U5d9|_1_A&~n(>wG}! zK<)##wLlu67&ImS4CD|fA7&S5O&UlK%&rR(3=DtRAm?j>dNv?Aka_5PXFhQT$u$1Ff8Z`5ojY2Ob6nP&*vN24R>S`Z}i!1<3iGAoqdV^Dy&3=R?Bufb@gT z#{spEKx`0($wAhYFfhRUJ3|5CUr?6;W*+EVNst~;Sp(9)nU8@X7PNp3!~wNYp%`>N z2C_N<5$t<$K%TzZ0_tgk z}6lTn1I1DOZvkAUPr=Ao}AyDY-M0NQJeZXU>7 zXz>V^Iw8uyP{7E*0P4@c!Wk5QptKFklOTl_;+WwF5(iB_Bk48 z06IJ90cb3TfdRa83S=J0Y*121HV<^>6llLYL>B`*{9yHKNn%Mck@c$qvHK^$m#ri1 zpTJhXg7X~6QJ}*uKr|ER!ed5u+SIS0ksBs(pNxb(ps>m(7j)YgZ2KqSNpP5IQma!~ z@dnmU#~Jj|$~CVzQ4g|R6TE+u%=u+d4h1D-2xbP=T@WUiWCk@j!7K>D3|i_8VS-7l zX9|F2AOtf5C}%_1Ad;NA6*_DSwi!~lg3}skIv3h#1oIidbs&gffRt^pdJPTe03R-;+sz*U}AHI6km&ke*bcX{m_38;`?Bj{hdbOk|GZ$2?j-Kg~npBz| zKUBw&z|lB5j>G`jw~Z}-gLV-ix0?synJz{qkcKOmBs7j>WMOIoY3LF@(`5;0YzV2H zD-T}f!~iGZTT(3XF2-3uBC0+m@XNl@7ZW8tD9ciIWmJAiIrcH0pBsRCP>TK9i6AIk$(Sk)pVQ z%K=Yj*$-JoYdj_~G1zdl&y+mKz;Ka)VJ*vER*0^iEFOu3i~~u@3>M5*<><0!xGEiO zSlSpFq=O?Jotzmg9LtSAyS?~tmdN1b#Gu`zv-4UpgMmSU&dp>0|4(va7=<6=l3<`@BATD3Qweli_ z#ltZ}Z3pwphn*9Pm?dhus%N%mi!N9x(7kJ?noQ?*O{O*$hUJ- z)3sfTWrmm=6T@^Z7M;#XX-qTNGSsqWPCEHx1?LXQMae>&l7$y33vE&shS-oMWeVX! z0tg~_&5J?jT9UJ~Ph}zlL%AhWA_D`DnF2f8 ze}$jSNe6WfDGOav7S3c$I;fE;m~>Dj(~yTP)3GR#>5($yS|(KnhFq>i>+dgEF5pwS zW8w5!B9qqtovzI~Ntto`%7mul{~8KP+!z@qEl4f5ROQ~i=x{*6afO`=RT&so9_%={ zV&bY9Go7Dlv8-Tb&x)0vIn%jKlws0>wCU3|W(Y5n7TD>0#u6lDEj@GA>^2?-hBJ{T zn0chwa~QQ(u5>=e!BDgyeZ|D(+B`FucRI6Yib&4}ojA)QIej(jqy~ z$EIYl&V!Q}b$TpyZccJ`UdyzX`OrZHhbsyJPoa^U#>HIoN%q4G=H)L%*D~#8Im>p# z*{zu&gIPR{>DUB@W4#QE7NnM2F&#@|fCMpe#Du+KImo~O(#9kEfR#awYjeiLj)mzO ztVzlY>}k7BT)goRBng(9!NXQ`Sjr950SAelWru2MkWTBE$lcMd_JZxve};~Q&m_{3 z%}nEBV!QsoW8s+-9TUSk7@CwB*k3TUUH^|{b{ZFx+qwTd>`jNI*jO3Pa`4DDB?>%X zWoS|qNaJE^JN{p~e8$4HOcN#~>}8p*e(x;Xjfuy=ZMr69u^AH^W;#EUWar^%m>JB* z%W#(y>^QcWA0MzX%=nnb^|WpKe~{3j!%~+PFg7I$OiJX3m<^I;V%zXvx?_>D*o0jN zwrgBl)iz_|iiOj)q-HR)zZ9*QIAdW|T0`1_3FQY0(wv`(DIH^FV1PLs$&FXr=Kbek zFGve+;{*rhS&qAG4_Fz}xL&%=_`jCPVT%I9cCZ+e+vNY!$|7TzT+k4b4>pz2qu|}hUa7je&t#3bfFc zg@YBeHjRaY9dryaGpMV`0y)|Nbi^bJ4`@d>^Lus%237&^{5lJ3D98ZN+%u~>NQ8AJ z8v_IUXa`m=(Cv2YplilheU>pWFtE=A?b`JPi9(Kc0G-Cj2_nEpI~1}pFmQ3Ox`Vb~ zbAt{SV}%~=U<%s4>jxS#WMN>Q4%&+A54uN@`3gup7<7~h4-0cLXuGQzWFIVh6&nKs zFX#XR2{v8OhJS9*IrnV(ASU=|2R87r4J_R1Yzzz#HV1btD~!#<4LYV4A`U*SUILySrzy>|q;WFrUbLi0ypi30lphr7w zWM*JsgC6a06Xa~@(GHtIE`T2G0J^Y(4SKZ08IYOKqaAjF)WeQ;0QJ^67}-2Pr#f?| zvokQTd4iY>-0ML8@&d6N1aE@GeL!wzU=(EGU|?YL2XR10JAkfS2i;%*_J}+K?{^jk zh90)yMIeuWLo5WuWZ=FHasc#b2hgeDY+)~7~c_e&469WV2Xa|r<96Oj87(f_m zBtOeO&}t@r7Es{u%CIvqaIh7>0+|mwk(I3k#AM)p1aczk(GH-?!alGSF@g@R76BzZ zHrUY)GN2HsX3Pd9VG+=#b~XryL&Oo}IS7YGan} z1LE|7?J*GnomIp(f$==}XonXdqbD+61t0AIS{cSR39QUPWH%@fr!qbRAMF5&0k)Zp zpkVh9c?Ys*79%KJeMBrlVKkS~0DQE=Q&7s92M&WLpvgxDw)u>oz(+fPDhjp*V531t zJA440aiYM)z>vYVISqQW1KSpGsDqAnVA~2>EC)W?fo&Uz$-$iiT4l8zbS@GPcRR=d zNJl%c?K}!T+5yycVuK#-Fd5{ry`X54;Rda|W;+NlvND*>ATkLQK(M17KqWCb0`06HUwEs_yjB8z}lxwFBJb^u)y!WIpd;Sd4c zA;}g4)&e@(0i;~`Ix7Q109yj%3XnODAp4WS>77AjJ}4`tFoGhMMFcc;#+C}^@QC<< zl%;_=A|m>r5J(5>mk|N224;gD?EpG}hb}(SBhb+fpb(G*l^fvrWZ-839rM7?0;=rzSwOXjBq-;@ zQotMVp$?$K9{5?f*%=s^JDC_5*fl^)etALFJP!wh2?qlMw+$#gFn|&$12^bC8V)d< zg_{E`4oZC-49p@d3=Hf^KR{JJ2g?f(#liyGyuiZ2@`#0jK}sB?m~#T?enjaM2F^*K z1;Nsp44jieA`Bd$nVV(~1_rQK7#Vm$YrQPEBsXv}FmQwJF6NR3T>CW*hbu|L2fVrv5mQTK<+mLu}!#TL2fVtu}vBHSwL~X8^OrHkidN) zn~Q;g8?^M3`w&Q&fxC}^fr0xlh|R(+$jZRLeFVhj;0B#K#C;UR=HXt+!oa|N48#`T zD@rY4;64swi*PG3Gca(U09hl!4O(i>eGSj6z!1Rg4Knir$ovRM5(X&;$GbX&4^jr^GeP*X zxuEHSjX@?Jw4UA>6hENGD5yotIAFO~=nS$PwAxDc2xvQk zGsw6Wtzw!R|T53b^)b4rim=_$r%icE+CCe6FKCv zzzQK!Jn|rqGeWfqD1cX4x`9-J?iW*h3{nc_GEH<*1TCRvbO+hM7^IX`zyM{3D;1Tc zLODzm9h6IQ3m6zZLO2*0R6rY@W(Y7as4~Vgl`*I?MllsJs4^9DFimt&Wh!K0n&_g+ zRLHNhRA^yy)rKE0bP$5s-9TDz_?9(D1vWdSPx2e%oF$2D}pWzVcZCE3iHGr^$Omg zP}mIO9%N!*P)q`CV*s}~m?v(j*GMj4VB7{Wn3RQ8SH*gs9{)i25eC*hDExd>zh>>W0@y;uski-U=`485nMZ z6+)5{D>G8BF3QPz{3Pi*JlJ67$6!zWjwe= z10g_#vpARlDPiDe0cCj;Jy7*(^IU*|0ffOC8TeV6IT#pBKr8-v6+xDPq7iI0gUJFm z1_r(}pi%)8`r;rv7)*KD85p>)f(1dPoH(d#gIEQ2G{_GO$V)jv#~KNUGcYhg&mspM zOFnu`lrRH>q$s1hBxonMlsF?ZA2+uZw>3A2E6vNm%mLzn4$+c9J<)}I&(^bfk7F;WnfT2oI9n8 zbncWIHkVC@xJ(_%ZgB<%4TNzZyEVBW?q(HaWMI&OaTpl1VJBVbKpn^GDGYMDF2n&0 z40?z|vhwe)40kW|&?}Ij30#m{UD8t+ay*tPx*({o zV_;wa)f0>iK_Cj$z(7473#10LU4o4vWHL+WWEKz`v|J3v2eCn0G+=ztH3LPUPC8UQ zXiN=swFyifWF8EIhBX)&!ax*A3nN1qNHys4Iz|T2U?WT&14K3)M1fR*To^td!~#`G zj11u*3g-0i`7muDb3x+^j0~WAZ^5DG%#=9@7xFo2HZWMl{iQJ|wB!Qx|2uzIiwprZ^J85qn!!@dkb zAj$%C)-A(l#-RBiRzIk@#1I6crho=0z!D%9sKdy}06+f>A`POT z(x65UTzVO3l$ya{K8Rig+9u8r1)@M*AV!7=5GBIQz`(>{FdsxiO@OVtWB?t>`V(wH z80Z`b&~e3#3}N|93=H6H;|yV-kOAE+%E%BF%*?<5-Vn|Zc7U0Ip#jt;We5XNJz!=8 zXk-F(I5Hzc#19q*1|e`Dg@Gv0;iJq9WsLJdXG8jeM!P{AupdB&CNeTGR5F4bSu6pf zJHQSK2T}b{VGs?vxRQ|}97KVRVP#~908yZ8xELA2LG4(Glfw~C4hK0IbiW}ZLpaFE zp!OysL%1#r14AF!$>AU;gT{gx8NxwM28{`<7KkFH{7@DK zhIFuO1ZXM)6yA&spo7`Lj+x5BzyLCzks%D^k9}Z;VFy_l7%oAWU{wqdF35{WPE2BD zU;z0K$s?fB46=|GGED-~4N5a08iYZUCZIr_#>&8eEDrJy$P1vOP=i<)7(kBR#=^j` zn}vblJk&8D+d*c4FgEpd2rC&t=77QiWDc@8D5ZhCi_2V)IL!0N_JI;0C{|%!2Dt%* zi#R~Z?h7d2khHZVGk-XpNtm0MoROKAO5@Gq+5-~m{H7&6;rv!c=A~OR6^q52z1_rn&D+2@g2synB zP#3PaBqgyZ9df3kO;TxQPKj=29%%fRp)4&kH8nM@0CH?%PJVJ?PO4r8Xe}zLYrrxP zMUVyB5Jkl$MVWaZgV`7uauZ83AfgNmpe`N*1M?9EMrH<1W(G!Pc1|`1MrI~3n-R=r z=Hvj2ure?*GjobDFf!M2GBGeRbAw5UEJTD2Dk2Y8!weE(U}9ke9qGspI?|CJY;rLt z5BOk5kU31qYB)e@7&(Q&vLJhzIa$DLA;{5?%wW|Z(^w$_Y|QnX>t%Aipt##UXxUfwG~-FxP=pgIvnY#3>E75o9VP1nNO@%#0wCfr*6)WIGGQ zc4h{UN7$HI!65}!!CVh^1LTNGh>e_JyO^QkybO%Y9ANeAV80cD%w^^PldND8;x@30 zAnpgb3uG%lD0Emr{)M@N2ks7tM_3`z$iT$H!ps1&mVt?dnVA7(EQrO%%)u!Lj!k~B zA4S0=D73&a#as(@BP6syB+O5sn1ZmGIY9?;GI0uk(*sDH7+qmtleIt&VGaY6+F%kA zDoh}!GJ{E&U%5ek1;;isBn>cuW0;v!4eWkih{r*p!Uj92r>s|3o}SBL>wHh%#id9Nh4rgFqKRQm8>8Wn2}Nigbh;342gG$Tn5-aX|T^B zaS9O!n+sLR400bxC&(v|I0VHP*iWWeI`XTNChXy;`6@mQSh$BSljy3P5A=@#V=S`MF8)pdARQ3~4!u>BS6? z15S|+Fohoq3fg#!IG+}(8gj~JN@{XJ2}3+`-NjH)l$s2>%q>18H90dkF(auxCzk zeqI>^nxScV#SHPu`T5zIsSJ7X#i<4HNtN-%1&PV24Dn8x>0pcFOLF7OK}S!<7o`@L z=9Dmi52MV;FD+syK-E%`np+T`$q*l(oL`y;_E$-KN@7VO{18?8?842=hd2>@aw+7T z*Lcvmu4xSMu)|IvK8eppx*-oWzEDn|jW2fd^l@c~FHb3E$jmE=&jX!HnipS?U!2DP z3RQ5LfE?%qYC1z%Voqr)Lvemu2`Hf;AAp=% z0ZIt*>3OBeAjLVE#U-H7%}j?{13K#=z65N0L40y?JSdfn4 zBsU&%*lZ@q=FGelP@ETlE(T z>B!@p)I4aahMceqN|NByP(f~i91sgS7`Y_BJQ=DE)DTS0jxS*Vr^!6%$-(iN`AMM2 z$%{{|$SjFZEJ`nqFDNNuh)>SRFHQxe5!l(kWr^|NH~{6M%shtp^u*lUM38NH>4~{W zsRooos#1&c8RC-?i&Gg=D+)j{#SouXl$r`L0CIG0e5g-;UOG5m!vhQbtZT@Lxbew3 zsfl@|1)%Hb?uFz8*g?kzFb3QnaFoX9rBpDafNg`Qk1x&3%+F&0$B+WZx1e$|F((z2?m@@+ zf>LX7Nj5lTCYKf!#TQrRCgtZqtOTh?PHH)+dFdq?pppiju)$%<5D(ItnpXlfoB>>H zKq4&(Y&3e|1oC-hYGM(@(V&oyFG);i0B0*uB!D6nRIJB?+w%-5#p!wA59A zQ0b!7#GK+PhJyU!OhmEx>uaadNukd|ALoB?)1HaH$ZC$mEW38mmEfJ9s#IH8tHV{9I7ViH|P^83&1;6E-oo5$^(0CpJO9jcl6`l#J0SmzEJsgN`Y_bDi`p%z<+)2YF+0ZGu{ zvKbT*c_5F$j}Ol*j!&*gWQZ?LO-+H+6Nu8X0Gvo68pa@(FSeXdoIa&cMI`V#CyfMws=XW-5b+BOwPtfku}>vj8A7K|{`m+FS@aas{NOgNcCww9x{@2937D)PvZd=|YhBHqhECs9m7(W|$ff8?>qtq~;=$ znj4_eHfS8(L^A&ocqAJV*H1t;L2N7Vu{8_~pvxv<<}U`1#Y5r#0)10cQo!Lt$&anRT@=m0)Ynt92L zh+ohkGt7Jt8(@bM zg2q`vYC!CT;DKa_`Jk~^P#y-E4;pWV=>@T2c7euUVd5Y*D2_ntK?Bk-aS$7puVLe~ zApIaVOg$$n0|V%g4v-t{!9(y6H-N@*L7Q1YW`gDtU}l2YFgJt7d12xpHt66pkU5|$ zqd@vVc7cYzL1`Pr2Q7;MWjByGXt*CH4w}<}nFC^jzLu3<^l8RExP^3XOqCn1yhbqBx;ye~1 z;x?v23?}LjdQcF9f)j)>&))%MY>*5DlYRz0IM5-QL048XfHF9o%fQS4+Es$g2PGn8 zKB(|V=7SOYzQIDGwDH@9$6lgagh0-RZYlzDF$Q}pyCEJp$t<2;)51T zf%u>*40HxPsE7ygK^POoeXc0i8_`69*NSFgECHGZ-6` zDv;0E2Q480`43ce!Or0aofpIiDytbFRWBpxAR`9IIhKqd%Ry(|fELj~qZAa*Fmccx zU`9~+!vMKs8D=Kv`~#R>AUBABmg_*9HK4gzkg;7LJ|ASyQZJMZO6B0@4^(_Lk~nCw z0Z1=s0rpvtI1>YS{lFtA8`Q*k3u5y@_UD6U@ImT9lklKDIUqJ@*1Qh1Plt(tVG1Jy zLkpA*T4W8njT5A1F(U)RNsu@n1A`6&0|V%`Tafz=7#JAtL&ZVy0NP*y5(oL^Gf13? zfk75jJu@*dfW$#@A_!%J;z}9BW@2CfRmq^W!XUfsnHU&AbG{%p=&nxC)srALs0s&N zSqNf-CV@fcrGwa@YW^409FVvxGXn!iJPfqn9m)n3@kt;y)cv5#NI~uaxxWx94oV}S zxnq!C(6zgJK;ldc44^6>w5A=T9;D_!R9u{efkB-GVV5nG4a#evDN&F)pytIqs5q#~ z1Wl2`#6eTHAodIBlqrY}QvVgI9%Qd3Xy*;o%{ovv$jzX6YmoXWrM28b|@Pp4%$ry(z}6`fngU^927pFDi9ecNiPAJ_W=ErCHED+#oinDG%D|1~La!j)2(Q(Bc(zz7tFhXtNqf z4Ja>y*s!}NKx-gDYCui@Q=s(B1ZnQyg0eyB{1uc9YMO&qiGb9Dn)RS{CLlJbDenhL zlYEe~tUzpTkY^bf7(mN1K=y)~*&sGIG{5JA)PweEF)}cK?#Bd~18T~HFo+FmnuG3{ z1hGL)b`S=!LE@kbd_iV{%486m8n0O}rqE+z(<1In`p zpyHtBJ7}*FNF3A+I0Y34brsG**`T}(k^`v$bq_$-)PmTc?!h~#8c=ipE0hgV4?0Q+ zqz2UV7l-CeP=!EuV(5cS6;Gx($b*Y*2F_w5AoL<~lP2186HJhz&CTCR7cm3jtcR3=#*iA0vrB zgR(*Pg4Vr))cj&*U;y340Ahp8;fIz#qM#)`P&Px0;QkaLSbY*=|^3KC~xU;uSXBB5+hxf=szgTfZHG#g}QF)IT@0aP4h7wE!c zkT|G|0$R-rVuQ+O(29EydmSqS!)he;+o5bwmjl#B5eDtvgtqNKY*0A~!mx86LB$8` zE*nsB1KKeO(g)f(0%L>fV31x=Jr2S!y`XvprWaJtfz*TAmZ0Gb7#mcUf%JmPD-ee1 z1(ioIy`cOCQV(i(g3eiou|dNhu=6HCbqVZ@eNd|##s(EbFg9qI17;>D>w?UI`2}{z z1gJd>QxEEX!`R@nW1-D`u-l+)@Vz`xHfU`YOno${Ee90`Ee(ZxI1q~xX*-A)keI&LC z659cZ9gf6KMq-2NJD6Q_k;GRbv9}_z4h`4veVRMx}9LG=QR4cbf&V{3wji=h4mwSi&cSxDk#NNn&*OsM)< zNaCQ~IxxMPkiHPa4>4cagWQxkzCUWCN1M`D9_l|jt`9RLB-y9`Oq5hV6SB=$Wd z_G={e48WJ0{-5F-D1CqEe5<3cs4LU3VroIG8yb+1rhs2(Z#QurI zW&v$RgSt%si7kV~)<9yLBC(y2*r1*5F!ux?iH9PwTaefjkl1sO*r03HVdiW>5z{5<3HlU4q1JKw|eG zv1cH$mmsmXBe4%7vCkv1ZzHjvBe6dtvAMYr{uM`JD|i8zJQ8~j5_=hl z4I0N~U|?9qg}A?ID@YuguJ(i2piV6V1H%yz8!CPd#DycR_5Z_#+S-D*gt< zhKhd#v7zGsk=Rn)2>+TPu^m8cs9skP8>%-LiQNifL;bP|#D=Qb17btP4{$^L2x^aA z0f|G+e2m0?0b)b-{spn2YPfh97+~j=@`Kn=HF8L74GQc;93&1^?+9W; z&2$5?q2d7`HdH(j#D)UK5_<;{`w)l? zRev1BhN{00VnfB>g4j^;KS*pgUPPF1gV<0tLLfFY9K=CvsJJ|c4Vq^GT~rHVL&eQN zY^eGWBz6QZBn&}&WfMW-Q1v+=Hq>o}AU0HQKN5Q~R4-`r!W@t|RPS;S8>)8=hz-@d z1H^{9?I4H^ReuJ=hN`~^Vnfy30n3}Qpo#DLgPHR&KWR80Tc`v`~)HRmjd4K?Qm zhz&L8E{F{^=Qk3YAG90~Dz1XW)_Dm2P>X*w%>~~0PW<8U<1rtwXfTVwrcq$SbG@k%dQ;Q_t zg2e7XV)rAlLFZq<^n%VhfU!YGWWm^Lk<@QQVuSizFg5#;#6kTpm^f%$5yl3cdjMmD z_OHR%ptA>H?9WK%fKGRUiT^_q2OUlT69=8417k}wBEkoB8VO8X4M|)JiEW6)2Hmv^ zQ*VPL4(i{*#6f%0VQgO{HK0x5Fmcd0CyWg`Dgnj@Z9Idq%aHU|A+bT@pD;D8NaB4+ zY|tIAFg2iYQ5YN4uY|Edr!v6U8<6zwL}KqnVjn?bpFm=R?lFLw0~$Mpu|WrSz}OFv z)Pwq=F!8TQ;-CZEVB(-7%VBITCPaLJ##dqDpyRnOpto!q}h#FkozUW~4YmVhbU$C6U;&NNg1(wgwVgABk;@#0HHU!|b&~5(mva!Nfh0 z#6e@qF!2y1anL=yF!6XKaZukMCZ2^PUW~*pM`D9c_<*VJK@y*W#0HHs!_ij13yIhOt584>0y4Br`!{ z)G+b4Na7!n*gufipmq{WJu?d;4X`7z`H$ zYBnOVw<57YC!4_3pFk1^ZRLcCUq%wYg~Yyx#0DLN0#pAHNgTA<4JOXQiijidm@sIK z7IaJ-)?NaQX~Wcm+7K`{a@z(pFAft2jVHs{pfPY58+i;IG(Qa!2hBah*x>PSXnPDa z9u5-+jfcb7u<>w^TR>|AVB(h9R-VD9%cpx(0#k0@Bx+2AU0?<5NPZa#0E9v zL34N@HYjdEt;YZ{6T6!?N%G8IA|Ulbha8u95jysnwtT! zLG4-4edr)I=#D^8nG9ls+O|77<8a)(8&^@auuWov_8cVDh`^j2i+3|5(mxUgUVG98#KQUy0Z|( zwqRsnh=QsIokWoUW!o__Fr-1*p!F@FG8UvBG^SAm758RjU;v#+2oeXig+bfSL2S?= zNuW7O5Ic#HfuRek9&`lY1SmU=k%3_vl%2uIz%U2O2DP0*bD1E$pt+Q_Q1K#028JzA zHmL0kx@#V!2DJS5Bvc%<_6AhOg2X}X<-1UE&^nywP&Q~?0cfrhqz1Gm2Q&{2VsBw& zVE6}BbC{8V0aV6<#BYGk^kaqOHPBiD0Vo@^W=9Ol2CXlUfwDn!HA+x6XuW|3l>Lg4 zfdO>z5Xj6oj0_AWQ1N$+3=CFKHfTKqXigNQ1~i}J1{LRKVqoxrvO#UAPCI$x3S{IPGA`=5c6I2}3 z2Je8fLF*#=plod>1_sa?7?66Z%3uS{2 z%{UBY*Dx_KoPx5Om>3v9hXjJm1g)L81{DXbskj4WgVr@Yg0g2aF))CRxdo}8&&0s+ z4k`{>Tk!?T2DQQeL)oBp7Hn*gI0d!AL1!s~^n%u12tma`YcnLEY*2e#4$3~k#K52l zWrNmVfDSGN=>;8?Yz7qvwbN~&Y|vT^Cny_qnz09zeV2)WAqdI_tylCqY29X!NkDO3uS}m+@?d>ptk>f zC>yl)12k^}asy~h$Xcj4KQjZv7APB3&w$R&1gQb9OM!}m`UJE6AP&R0-$R{Wpw7%>wlnt84V_}EHT|4N^PbeES zrzZ+!gT@Typ={9F572xK$PJsB85ne+;-DqtMo>1W-E9kHgWA_FP&TN2?FD6n)`5gV z*`W4vJd_QZ-%EqCLF+woplr}l%|%c)Xw69llnq+r(F|pSj_l}#vO()WrbF4FH6HVz zY|uK8B~Uh~d|eM^gAO&>24#azOWp%zgW9%-plnb%dIHJ@t^K$RWrL3VxC>>2)`~ob zvO#M<-a*-*^&wxNY)~2b3(EclIt85r68@ldBA^3$L17D;KLnk^3u1%TjYvS%faVhA zpls0k5EUpJbi9ZblnpBLKxevv^n%uMfKFHgu|aD*+@NYe>p*;i-4ptT=`P&R0N2&m1(2wgjh%m%fSVC^eV8yLn0wRK@^P@5LU2DM#b zY*5=3#s;-fVeACZIs|Cj7}OSpiG$V~!`PrUCyWhhTf*3&HVupoYRACXTae5IwH0CF zpgY@PY)~5o#s;s8fV$xWlHNZ^Y!1*`0;n3$I2%kas67E=gU+~zu|e$y7~2I&FX;Gu zn0O45IH-)fg2V=malzE=K@tazWx>R+Ac=#3fdl6VRd8+>XhR1K)kgP94c=U{Bm z`al?a0g~P|NNmti_b@d_ki;(_u|eZPFg2ii$Y5;n;XP0{fY$!O#6f)u7#q}&fU!Y+ z2N)aFUx2YeeFPXARF1>gpuPZ%4Ql_x*g2qe5m0+UZGMh~q0W}kJd^JoQ)b@t4LG5iA z8&rYFmdql z$56k3*89Q4-yo?6mFX~XP+J$q29<}zV9;0qXm1K=`~jpM)V~My$3bim28}a-XwWiX z5F51a4aD!UVqgH3S)lc3ApIaYP`RrIDvQ7e0fJO9Fo62ou&qHL5s*3%4cg`fV#Cby zv1R}tOb#*+)c*y^fy@KB2V_1-45ZH!=1>p^Y8QwJTJr`P2O*>md`dI}0|V$zcaT1i zd7!>Dhz-IZyFeIpkR6ByiGgqo8w29#G3a(okhmX|4f98XGa_6-?t%FOH1~sS9;hv5 z3tI38G6cyVpn3+R2WFmw3j;$8F9QQ8TtK^eKysjPDMZo(GUB5+0|ThN3SxsW%r0=9 z1QLMaLsAS3!qE9QkPu8AXdNHOY?!@s0vQ-~a6s$@O~rxaK=y*hNnm^?=$7 zAS0|b85p9`%mdj6x(gFT!_-YP#D1UjZO}C~AcLUzq9J4rK9mdhFKA2wWFAbM(+IK! z5XOhefyN;~ZiR(&M=IoQR#3Qr+CCsTP&k9;#ZWEns{2HA=o zn>8|MGHNK-vLr2x;dbKTbKl1KXx-vhkCYb1YASm$D=lwOP*KoiRyr)BDVWQ|!*rHO z(^1pVmq}C6XC_-O149RU69>ce8BA`z4DFU)HnZEU4Q!;hTQIR1GU(jiK7+~4h@st@ zOJ~>e8BA^Z496N7bY5?t!NeBMV8gwA2GcPG2DVxTpQzrRH#LS&hko-&FIvC=(R-%q)1ki~RyT`j@klEvD3q{) z(w~}AS{rDbTP-Q24Rj#BT2W$~2Ez*G>93gD)EG9cg*eAk@t6<;!wTk4OBp`=64V(}K{~BNnY*J?xx-nyqtm%VoV%k_e3=AS2fK7fC%YS{ifd9%Siv|m z@nqo3!oBPdI2dLmo(OzVc*bgla#+@#o|YBNP3!(QbP04abD#O9qsYd}z@4U~9KV8b z6C1->_6JN18qVBGn$8-6=|)d^gk(Q3a5sIch}&iqobc#CFWZ9$C2gR&2JVhc91Nd8 z+BySY7M^8)z|XM4`9&f3s*b>w&aYN1SWxoK>z2}?zX}Q^3TX%2*pVzLIIaM<#X~UN z$D;N3JDnG-7VwE^pT&~P z)W*u7q#VCU5$1=aWB<67HnA~iI)gn2@fouWhk}McSP`F+8$$>4q-6{ZGXIAa^S*&gga;5co{ql_po$0u3$XNwCM!nr3GA&s}eID9Znr+TA1I^+|X{unzS%4 zA-Q2A14F_x==Fdr7L<@Qh&&*bo)GE-HigN=znrb9hb1;m@K!Qvsx z#>C*R!K~xrsp`QRp&I4lbmWf*OD0RDh?@WdL=n4(C}=q~1G2icY+#jp**#bw7M-br z&~8i&YuWa)LpUp0JdCAXJdI^P@G!}KNL9@N4a0+X^5VK54m7q4x$n(^L5v5ocM^2p z+fLA0UeHZz-=HNiNFk_5gWdNAnjC`P_Xg@wu`scNIzB9nY@o4l7Df)x5DE(uD`>|b z3kU0YP$j{^4jRvA4g{UO0J-E1G%mx;1DX|J1`X}A2!Jk5Vqswgt;uIT1iFk)9VEiK z6m;A{3L|Jrf{lg63$*lv9W>s@;sd(Nh#hn^Ba1Iclz{^@eFVCqixWhEFL`?jI`y4{ z#T~S`gnJFhQ0OIZpiyNOKhXXH76xX}c0?9`kmH#_EB0A}K{tT$urPy$Ygxs>*O#%d z>w)gJ0&Pf>VATcfY2yYBD6{H=nBYs^SfQ7^f#w_`Yz}VFSTlsp!wuRx4`G8Zd1EyM z4QPun@UwvKCgK2%@`HB7ft}94!26JqfkB1U6tsYX8{|1w=p}EU)!VGlOWr`WFDvwt zH_$3-R_G;fRiKONpqIRXRt&I0FL?tU*~|*P&jK=u z1GIVqgu!7W&%nPwq!-U{nec>|5gv%)TU%LD0YVO#~;B?Z3ZjkS$&Ejt5)iU??6kF|plbU~Ab$RUtDuuI-R z!|trGOWqPdGJRlsOhiBf53CaykAN?E<6~oBV4cW#3Vg{M=q41_Nnm9TA}c}hGnEl^ zv6G7kClSdR^Tii2u!1jK0blaQ3ccjb2xJfR zk~h$BJ}c5CZ>&2(80_Egq_$6uLn11`im8M$s1@$i}faGqB4XVG&IBd0CfI)1h+FNo*#kA znHX-6E>`4A-av^&9ONHykVnM9T+sSK27VUMNgFJT92Z$YcU*vi6MP#6D7heM0CS-l zK>Lp+K)U!@dO(-FfyNF&UPn?65(3|a!NAY58>9xL6%-^0H4OYL_gNVrMJC9@;JgLB z;5OKoV4Lfa4QXAcF64OJf72Ay6$M z3Cj7f6z~u%c>zo^fG&9h&B(K9fG%p|4P|3s;9+Ob1YPpB9^BakB~S)#(0Nnr3?McO zH|Tyob_P%q;$UC~&GfS+y#?Lw#=#N^nlfc!0j-2$;a~wR#1gpA0y+tSWAa6iiJ%)s zIi`YiGH`>Y)H$Ys*eu*Zppt$%s4>mK4cbn~F#{yd!wnj4;g|_x3vhdaQs*pCP7&b_ z0I_F-#3jIYjd9EY880LF10+80HwObl4Wpng8v_H!0#Qx|h6YARm_6cPV2}c(<5)(> z9Wx-6;2;ABjX0>dXW(Z6DFbIZkY0#1R0g!%UOF2zwyFxU9MlK`HHH}HlyNgK$bcsQ z7*#>J8YCer3>s%s1IaK3%Yp8?QU{p=8X1xUU2vsd!_B||TDu^h%)qD#G7i)(k}qIj z)B<@DG~zCwmQ%pMsNKZPzyPXt0{aSK3W*(M+^ zXl7OcbmRdem%|LA^(DhadpnG>2%|Yo3w2MyRENIx& z0>lMHr6Oo1jq!>N69a=%T7EVI<0W$@1_ou&92{u;;3O9Vg9^xhYK)-i8&LjG1X^?Ey0b!)0y;hHYTU7)Aqi#%Sh=E^IK}8lEf+44=3e z7&HPwR}X>)E;MtP7#JRa)kiaxGr&}8%>gwcix_@^WkB~U!DKYAFflL)a)X?SEUd)@ zI)JK(K^s#>2Ok|m%~Z>A!Kcnm$-We`26>KXW1K>M)xSwOjupT(L3lzTzD zv_Lya7&zyFLKC#H1(GDeRREX^N;?evETFj6*#x>A@E%A66i|?g1*B4!LFW*t5jGJN zMW7%;GlW40G&R5tzTb$Qhk-#Hq>e!kG~dac&IodfILMgM%ZxazxUE?|g)O)l7{ow# z7I}hi*%4=D09{Zdp$4W9ml-KCcnX8|yi23rqJwgCkqpvRMdAz$$QKz&FfhoW-X0{6 zdV3K1MMlv3gSZ7585oqfpm!dDILe6If>fYJfG!jgXJAl8y*x+_a!C;6@*s7jD~>b} z7YS)X)PN4*(Sk51J4t|e+Hf8NgAS^fA-4(Xf(8}!;4;w5hd{+8xUOMfU}Oja4K08g z@k|U89YC}ksFw!5R0hNXtxN*RfN0Qc3g}vxp!pycs3Zo-KurTvpy^#kh7b@1S`N#| z5Dub1szLff;QEj*_Wq*P*0DEVWJ0! z22av5gn%fJy&z$jHqcpKAmuP^pk5y%LkMVD6X>RCkT8f|4)$~is7Vg;I3q&{=yFxi z!91FM1w0!hOiURb4ZYa8>9l+5>V~|`42>cn;{Hw zB}@zqpwniM?yEv~4)~A)h8Pe9nu}**Fq{vfmB0ZMqsqj<0NPr?$PlB&#J~VCHU?xY z=&%|_2GEjPup7{goeXMkFa&|7=s{aiK*oaT9S~siBTNeacDP{y= znldpkK58{IoF&9Xzf>Ei6L1{iHHG|ebfyJQeKzz_z zD2Ny{STESY3=9mg+|I@jHklOK4DicnSQr>^Uq%BxBN<{mwi{J13a=z%GH@d%+IA^MeUYLUgf$@AY7Wnhd$A z0(4^yL@(qv3CO)L9N>E-IG{H}fbO$_+@S(72U$H6rzHGF7FMwB9AFzEBfeo!>q2p@8ja(fEIeRW_p zkSkf3Kt6#c9OTPeAZ*BGAxz*z#|kE4;(TB?gUp9qI#de|HAr$`17AwQ2#s)%yV=0O z&kQCZmnDHOet}*B0}f62RX=E#hCnWbLA}@qa{UnKq8P|MBg|~fjNmK*j%)_#B}Isf zM<5rv5Mc(?I7oPaZVX}u$19ix4pT4-5{i)I3%M|b3G6dSq6Eu=7JM@@#-|kL$7dww zrR1bC#DkA)&jFp_4?Y_mM1T%Ohh2~XI@Z4^H68hiiahX5BW19Q5fV#4cPJPzZ33fO_3ZJm~0u&{Y>; zlfVS%XUfrLH2Od;vp9FJXWkET3Ffl2i(^BP|Vd`3LA;h}2^6{R&`zAzf&Jd`}DXSp0bK zT`VAPFn|t^2VY(RKUf}i7Yph&6p*`Lpx3g*XM^v1K=olf=ynU#(2g%p&PW2qKjd~8 z$jSaC@$f4QKsN~Fq(bkEK-F4gVgb9E0d_$F=<*RP=kUivY9sK0{S4sK^An+0BcNQY z0=e-5av2Ncwg(2-od=+xWhjQ6D+>yc#Pnh#kgJPI@>AlA7>Yn1i!U$AECF5H0lM=9 zd>I7j$_Ivcl(T8+cION@@xYP->P;@-Lz%R!DH%UOTgt*uQ zdXWa?ZVu3m3Mt^5V>0v7@sR72z@CMKEht-p z(j55W5Kut|xpoD7;SHp$gI!ONmIu0e1C%W@i<6-@Nu*X3fbNYcDq)BR-GKq(CZ=SS zf^M^bUfdFod~HT@a!yHN5(D^F96ddK1k%q-EzikJ($C3EO4ctfNkQCT0dgCn@fQ!i zM+6iLkc*Wdw`d^l6)Db4humtD2EJR0#0zy0_lv~mfy$$Tw7mGzy!6x(==DI58)G0> zt-x zETG+^43GtMpk)T21!JJ|;z1ZR3jk6JS~mykW`hpb0EvSZF@p4h#6fJ(f-sOcXwf1} z9K;44h6oa$2@-_fp8#Tm#6TFf=nrHLXhR@q(=13FwvZ4c4q}5A{eZ;ZLGLF3iGvo> z!^~#|ITC6b^{QV(K-7DR%?b&=GA*f95l4xoUk2eCn61yT>{w8O+f zY|ugfL>PJ+w_4YtA318D9X=Jy!TLEX?h4M4*(FgJt7IY4d%>Fot6hS~*U z!^~L?8aRN8gNChOe%ue5tAL7w21;P*A2h55a~p^aIyN6VKXc)3WM_NE(2V%p*p9i!_6RHL@ zFbmTQV#CZwzuyC<*MtSK=on-#Xag)vFNh6GZ=eA}m^g?Hat0_IV8cBi_b})cSLTAM z7tmD`5IO_YSWir1fL!g6lUb5ll$ZnMm84dbFzA7AjnYdhE@sdx$_H^kn(1;+1=TO5 zfK~yZU;^Qxe=h~7AOZOVf|TiNP$=o%*+7Fa1b_#WM+^+5dp1B1}$&^ z$$^p$=-vp>*gc33!XSCjz5@^&gh6~K5Ce)qe9!_mC>L}L7DE(_13l*fc8>&Fqb0ti zs5CD*C9N2Amjsd=v{?@7Ou`%NpcD&ksK=u;#=$L9ux+sW9zaM@;-K+x(3w6UaZvFN+OrE{gC;*fd$&Mr(0RG$(DTYc z;z3Y0Xdl*WC>vB1gNkMmP}_uofdOzMCKHGcVuPB08PN0qN>iZwS3u$*HK4VdAU5dC zv@)m~P?Mt?$_Ax7(DE&i8c?&X4Jr=Wdjy(t2Z@84B7IPC&>ohFP&TLu1lpeoQUf|m zZ9Y^Sq#ncviG!Mspmn7nHt1ZnRZumcW)g@G5(hOqLH9I(*r4>j6{-f*{Da+10y+Z( zbVdb84X7yv${QdyC{KXSTm!K|O+L^W6(BZ9FKDp~hz)9{g3e+Cu|ap5+=rSEazE%? z3XnJ`KY`YBfY_io`V3X`lYxQZ8Xb~WY4H5^r6~qQLYn`CxfY?4zHmHdU;)B$H*zr(tP?N6^ z$_6!ALH-A+0p(-RIxY|!)cgba2gC+7ahsv)LF`^6_G%~_R1R#0vO#VGg%L?0bw147ZW=euuI_&DUR0HpooSncX1upk^UR4#WmEYyF`4 z8q|ygox2SZ2dOWEii5g8AU;SOq!)As8Hf#PE-rzp0W~Q>XB&XTL1hByYy%J*)GP#@ z3kG6?nvq=4ybo$Rg7)--#6itDQK&em`3Ks&4-yA85n*>ZfSP}>`xrn?qdus5P?HZd zmj+S~YVv`mT0v}3*|H9#h8MD?9K?p*@c_EM4WtHC_JGdR29-acx&_4MhSo2)pn5^| z42TV0$;-gN06K34q!-j&{0343y8niSfdN!zfy6=0MGywDLCr-aXxRnYhY!LaaZppx z86?gNDYrmuZfN}lT1*5|18Np}L)C!lG!PqhzeogB98}GL*xb-M4ph^D&i4n^nV@(d9~4Y5Hr})TL2Z8q z1_tn1|4?&4?GKn|!K#JrcVc ziM<<%eH@7mnyZJI{|reSbRG#z95ihTV}sf%Ft!wEq8;jHbtE>Z{DG+fEs%k+L1#|E z*r2ojU~KTJ8K^l;Naldfje@BG??qw1ycjM4+h45g`@^_ z?+Z+v1+;hwYK|Zh8`L$0sR6IIgsO>0Qj?9uZboAFBe6mEyTHs@jwBAc>jfqbIu{AX zK8>X2Hxip2v?3Jh26-g5HWJ$$iS3NU_D5oa&Iy9qB?US+A8Mu=65AMw?SRDgMPjET zu}hHHjY#Z1B=&41_D&@BF(me7BsS=*8JIiYB8fAC&eMmwnGcCAjl|YKVw)ndosii6 zNbDFSb|w`5_>)pdpi>Q2ohTcbjCf@FKQq*Xl#XnfkBHC zai*auNF1uh9>fN1@&(-&2x3FUqd;t^IQZ;-D7zF%ya|at5sAG3iMEEu~m@R8qhQSLF=8s_XI%AaR8}-n&S;(L&XC?Y^a%)NbD{U z8#E>gI(HAmhN{_)#6Ez;K83`7h{XPl#1;abtq(Ov2Z`;5#7;nB_k-9_H}6DZgU|7Y ziho8D=K!5k4;2Tu$DnqB+GMcy6{txBV}ph$VQf$n5XJ@#W5U>=h1D=N=nM)N8#E*f zV}s63gt0+W7ce&Hd_))n4o5oM5p*vgOdPal8pZ~-sbK6}B=zM;Y*2p|rUtaH z0LBLOTVd>}Na{g-Zyj`s^?@pglS;HmI)-W1mD)k9;OL=ss7N8qisTF!n z7Z4^6+KmKbBcJ^ZTBi;Z2b~cJV<#h-la9pBM`9zN{SDd~4bxkPq^1>#-HF5ool6B% zk9;OLXqyyF9CUvejJ+O7FKB-|OdR>_?|n#Wjv=u@XVJpcgYK$?v9BVjxrf9Coka^% z1KPI(V4p?Hm>u#+mQ5v&Xa|ypM)e1I!_iR4jw-N&HF*;OJL(I zpm7+O8c;a^69@H$L1zwv+6$mN06=We%qJ-CgV>-Z5NP}j#0D7)>LY{Lpym^3JPyPL zZ8ib*mqBdM*biufGl&hE&IRpA1+hV6KcMaHAU0^698@NN*q}`aE14kYDuT|!S`TG| z=8d*O*`TwhKz(qKdeEM8Q2792n=vpjfcoPgHt1|^Q2792gT{D3eRB{SbXFm#d;qaQ zV~L>c&mcBvoE}s@fY_ih@YhhgKw~GMvqeGTp#3Y~q2i$N-M>&aXiNoEK7iCnf|eXW z&prm-%>g<$6eJF+pF!h_Ahs$a0|RLK8N>#S&nrUJgT`GzeSeTRXs$*VDh?VO2HhC| z5_e%_U;vdBAhtgv0|V&(KM)(Vx4{*v9#kiLL)oA)<3K1IG;SOYWrN0vW1(!&*f6Nv z0GR{2gCi3vK7o;e0aR{)#6fi|Xlwz*2F(jqL)C!BkQd=jb#R1cqrvO$|zKxG9;4X7Rl9l`-(gT{&;Le+pa&49*HLE@l!s&`Ov z(6~CNtN@9F#?N8rR)faC89-C-ObiU5u_ZPr8#D$E8e;{i2i4V}JwG5eX#8ISss>b7 zgT_EW;-I@GL3aay*nvz84Ej(tpmA@|d=f|;H0Nal6$j-xCn&obbeA}k4a#${^Q=MR z-k>p9kY3RCPS9Kwhz*)A10B==VuR+tK=&zv*q||U(A~NqHfW3-bhjdi4a!fT^Y}n) z&}L9jnFC@!U}9hZoy`YggT~B35~EHfY{Z0(yorXud!W$_Di@K|A$9YCuO!fbNV0u_rP!Fc?79fHqHo?vDhC zgYp4rV?2lrnmYj9B?)4K&TsdCst3&@fbNw9iG%KL4uOh;<_kb~OoGHg^9u=3anKIo zG$DYR^WHU}Y|uQ09+VB5uP}kKL30^aP&Q}|7c>?J zG7~h9;{p{2wfo`VJt~ zpf)yWeipHF22XeCv%o0R{#6TF-Rsk*j1hGLFo0hz}M2^Y|+a*!NI8)yv>visNs z85lt8r=Z3#z~n&dj9_e#T&yqy!%~nTAP$nfp!sT$FwEXPwhRoQGjc%w04roj4%#Kx#nPQ5CY>7{mr)nA}y+aexevqX0nSZ+swU(1OARw89eR zkLOUgg4BR8=-|E+AW0AhNe;BW2_y^)mmfY13?OwN^FVDDkQ^vnKw$*S8z3VDwHO#c z>!d(z5Qe!AL_?b`AYld;Z3YHV-w;$LfR=lJ%melFL1O^O=1tLIV2B6nfDj;aKrDSj zGYdoTnX(YV(8SEd(8R*b+)zQm)BtoktpQlV(7?dV#6&^C$k^P%1S~?t8ML6u1f(-) z6&XN_%NZCz(G7|-kUK$P3UUX?{UEo4)|-IlH9+N$J_7>-X#T>Qfq?z&WQOopFhy^Hur!!t zK?!Ul1B1dM=z*bsyud1XVjwESyyQ{&v*b|th71e~l$&KgFn~m%wujA<0}UH8fW@G8 zo{3UqU;tSLQU?_iTlEi#7k26|8>nQ3*sG+aA^U*=##TpSt0A#1Wk0}_Xo3ufakSuS z7A#tzq$PonTd-(>#wxh3L*Ln$V3r)Z50c}8%V}95nAULfl(cM+*tSS)JA`s=gnh?e z{f9UTG%x|R>ey4Ln1&QwzlIh}yM`4)w}q4vGlSS7Hi!{UTv`x@5|@tqq)?{?|J^4^ zKty!8b|@JvhDM>-DwZ~02AwN9TNPZJkMT3CV1=awP1ZS=oSYb>7a44Zs?}gc*rudq zA^QOuO<)R4=sZ~qjjuok2JKxdSYbAX{rc7R;=k+%hSbtz?;r+-&|qE1U}sNH5Z@~R zL^}I1cn15&g9rxKP-lj$#CWd&hV1-!?;wV%jCf~128ae{h5-LyPtfvO@OpL7p^u>Z zazX1cLHB)u?z|0SWMBY|m*K*od$@4ndPW8YQZQ&f-B$a+Z7 z8M{Y8>uErPQ=kD*P+<#F2%?!7*+6roOpF|$;VdR5R!~cYiHRL_IS4ZgD`-D86ASxe z&@L+uR?rPEOdRZ>$zSk(I_7JjJ~u04DgW zY%@S+>Vw!uZ2cg28i3fwY#%^uLlE19O&p}g2*fsJU}pi*OpF}rtPBh+>p@3Psemd% zj(iZGMGZ7~$C&_X4se3n@Qj?G+g_MBuQ4$&FmuiVDdz;;eZ$JRo0)-ujT1EX#m+e$ zv>}TVbc!A)CupXKixaf&jGGfQJH*4em6?Homs6dMfq{=xA9P|Pr#Tw~g8-*J8v}zN zr#om=hSQ&ofkBuv9CS=3ryC0cgD5BH7)&wFAQlD&aZb>vrvzs*D+7ZhXC^BHgA^y| zZV_qDDi#I?8BWkxrYtAuyh=Gv(Ad5_ClBbjKu#A11_nh=&<+zNPSALaGAHPu8x>B_ zT256?&?ul9C+IFlb8D<R#)(A`n2 z1|aqvwv(X4UkyR*1#F=C2v#G|$lDS&XV7`3#vt)EY^k7QK21R8Z(sx6&&X;D5`Vx3 zIx>{i48(rIn_85}z-kU+zhDE6VY6C**l*ZC^B1g^Aod5g8=!+ktw8KAY@ju*tkxj* z4+cIE1#%`o=*Asx2p{AOFrN*=2VLk0<})&|{$^re;9*m%WMN=n1Lbcvb&v^={LQ8T zVngybnIJ2{BgV+M# z%+9U@VvB$?JG(B3EdkE#?0O)!3^=p1gF{*YoY~pIA*}+=?Cju>)&OUAb|a8_NM>gT zhqM7Wv$LCk#7)4NogEy~77VPQ>%jy#)XG^I7}!8l2OLljfJ#gbs0Sv3&H{yc0CY4a z2gCym0-!tDSS%Sqz|hCZzyLb$Rgy89l^N8e2PrRRV2}oFXIa6?z#z#O%~Zk)-GObu&cGmB zkYCKe*vtsZOh-W_1*mf*3zjI(V_<9pOFRKdfO>??>bV&~v14A8HZ49FcI9xzo9Wd`+uV3MFdxDgiv!(Omt z45KMnJE(^QQc=vnAOYH?15$AxMFpt;1XBU(CxcXg*6&L)!ps2mu3#!aJ90oy0NsoS zwgA-a0!bDzFi3!U3Lr_)*_&WVP@(`yf@}vJ$_|nQ-FXL=1a;J4lAwv&KrRM`QVwu9 zu`f z(DA}x2B=g4GuALNFn}4LGvL6CBQO!roF`ZWw5SNo0PU2k0lDWRBLf4N@rRLtp%)|q zI>{f*0IeJXGeFaoUKf{r&;1Z_$HB`tYSslgy8!p6YB)uqkM zzyM07@*svhNC|@iXg3vC6e!JtMH%EkC!BMFTRouM0&em^4LJ*%)RqF}U67SXGKvd9 zr&hXy7J#y|fQnx^P{!kw0mT$3$%6HR2?j;b>8woVKR6i}*jYe3)#N}^g-m83Q$cB0 z9;64NR1P!�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%0A7(z~BjGgU%@phO$BD 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Ë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 z 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 z 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 Y7#IqOI7jx1I0FNy-ve?J2*cb501oYcr2qf` literal 0 HcmV?d00001 diff --git a/components/newlib/lib/libc.a b/components/newlib/lib/libc.a new file mode 100644 index 0000000000000000000000000000000000000000..263a4d8858e9b21e8e7075b6fcafbf8780c0826b GIT binary patch literal 3699654 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≠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%0DOEc#QD_f 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

Mm|U{s8tUN3y>O+u^=`# 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%0A!zfaY<2TUOI#g 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

CJWaa~%Y{SgV$;-gVz{JAH#>@Z`U}NUynF9;?X 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

^w&B{sh>0jCVjXu$9-~3$jsGUay5YkBLDTw5tPt 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�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

93fkEX9D4;sP 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

Ir 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

OGhnKzxwBAR06t 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�H(P1ylbBNgTB92`2s)N&FWQ8+48( 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%0Ahp2UqEb7zXim{1i3?TDBc^0G&WFE*pAoD?D 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%0A{gU%$_0#yS#CHORm&BVX}8j%5w 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�JeVg4SAq*r4?- zpc5NFY|t13Xsrc^?Zm*q09tDSVuRNBse|VEnIQMU=t9|`^)H}vV?k;_;}D>`u2I3R)Bn(hFKY1L^~U*qsav45d&t zp!rGAJ#-*(&^nq%s5od`0dyxFNF21rrWYy>T1y7%_kqMgV+^469w7Es1_p-tP&J_W z%%xB^=#ZV&P&R1n0n`TssRv!206HQJ#0JfI?uDuWt=j>u0|AMH)~bQlfq>Yc@omuk zcOW+Cyq2p_^{*Hh7;Zz^pc7dhLfN2ki04o?=;RsDJRL|c==7VmgeN_+}v}P$Dss^-1 zFBQseWn^H;hO$BHi$Hhwfz*SJQz?gvgVyVT`mG@Gbz_o0o}!;VIM{5dSrl4a$F@`AU$O3KIhZ zsNV`=t1&S!{DrCkt%+i0fy60jtrTddB}fhE%oBd7IB4A>s1FMg2d#YqExre_L3s`| zzX@W4j@j0Rst2uaG=;Jgm>}zCKx#m1rW~Q-pm7&>D7%D-fx#Eb2CcsehO$9pFp*F; zXdFHs$_A~M1odq}W=>#YV917wgYsV?lnq)VSq^1`#$#%sY|tqt%~1AcCI$x3dK-{A zp!HXv%>W=aXnoX7s2b3kE6`>DkT_^eekoKOH0}agUkDNht(n>g6<1( zg|b11NFIi=K?lE_gt9?vsX%A>g3JM}r@9Ii2d$L?9V-kHk7j0IcnTE<9jx*i$_A~; z1RbjiQUglYzoFuw^;V#JUqRxa^;Dp~Fo@mE%)lVX3W;mbIxNsVj3Ds|%nS^mwTvJ( zXlw?w))B-8t>Faqg+Xl4IxKUjUeMT#EtCyfm*os)gN|tdtuX?r2d($?hl+#7X+Zs7 zkT~eBOHiK|#0IVB0`+-8Y|wfx&;|n#8?;`l8mbp`T6!at4O%bS4P}GYg-(RBLF>Gx zL)oBXz86B-pcAe^{alclp!HvCq2i$RrJJE_&|21=P&R1pV?UHF&%(fP6v|d%VPH57 zWrNOXxd>&0){)(SvO#OW?m^k0v6d%LHt0mlS5S643j@OkC>xaSzCqcbwO)UqY|uI` zP`?=DX3(5J2OA{5mV-8rK-r*lCjw=I##*GHY|vUT(6QAZy`VKuu>2CWTqfwDoTp?E>r|5+Fq0-$Wr+OaSw8?-ho2FjLUWnf5x zvO#NTGoWluRt5&pTtCPSpfzQnJ~fC9T1!?1Rb$P{z|a6?gVvh0L)oA-)eB{V*3?ag zvO(i0Gofrynwkq`gVxu9+BBfKD-aFBFg9qa2G;%o&8NWFpf%?(HfY`i#s;-xU~JI* z2#gJCi@?~Rwg`+3TDu8jBd_}ct^Y$IOVIIZ(3}NKd<&8|Xl?=~eg;V# zGzS3_2ekuWY|z1NF!moL^`LvFVB#X6^+iy7LH8lR#C4FwL3J}s+yzM-R3F2{L30N% zb_SA~5+rs561xY94XTe}dO`QW!Pua>8OGj&r2YgF8#FHfQvye=T6+mLkAhAJpAxymqlDGpB8&vYQL;;wSF!l)~HCK?>pj%&HYTh7;gT}^T;w+%`T2Ma< zAhAK^HB5~Lk~pZ$BnE@_zJPX`rWcitQZ*furn}#%mejdLFz!} zf!qT!4sVyGSv1*$(mYq&vd5C+)`qCtIL5F6&- z1SbXtPP!DhBA?Pe^y<-ie3oLji>gXmc#gJkT6J zvUyS}3=E(#b9D1S7hHh!z}yGgwDf`l;y%#68ju{wedu?~?$KgkxCY&93o;XA7YL)@ zEj!78xVvR98xVK5EVm(Ke;LS55C+)^qS5b`eUU-j-Lk@l3=Ae{{s5VWez)wG42U{V zID@wPz`_Nzz8se3LHgXyh`U=>19ZMF6Xb4L(AGqdd7$tHrA1`(G%OhyKw~T*vq2c< zU+5i{X`pS7pvz?m-C=2HWMpZk00M;Xuw0=H-qZ@d=NfdktPBHawLHjn!r06ad;ucp z`n%zpoMbgm`2GDw$lyBz!fKWRZa#37lCJZxu~G6nB4zh(Igy|+)7ZGq}!@EvVtDDHE( zq5yRsDE;HQyA2dFkUQ5D;CHlv))rwC2ko)KCJt%~V-p9J9iE^I%RmW&&j4;dXzUBr z_J-LDTH^;wKMV{kjG+Drc+J}*Xk`UjbOVYuCJvS$&{?-EETAqkGYc!|_!uS@@O5fT zOzhx;AQ;&|H;geca)3sBn3!1WK_?GzupR~-4#2?{}?z6Eldz}Q`=T-+g=fP(lhzS}MW%dP$ zGH`%)P}~IF=LRCc_ql=YW8&gqb_cEb;RZE2n4$N%fjXPaexTt*76ukjkDA#Zw8w#E zA?PUWV9-)29u^i*%Yju)1>|NHcF?d5?w>^{ zxN&gL2Hn^LX7g|_23-sUW<&3DYXR+}W8h~2jo)#A1^_{eb2vdxXJFvH3AxV=G`7SI z8n}er=LXsk1-s7;bh`uWJ~z1u_mCVj&BYvokPQh{%F2l$ywR7JQ#uCP>dDurdb`(DDw} zsf_o)_ql;$fORG#DA+wjKmoxzixCvAJ|cV|qvtYefbVnr3<|J$;4pY10=iF+bw1-O zb_RwQA|S=A3&2K$?sEh6b9gr~GcaVZZjOWB=LQaS9QV0_PF-N#4r*)haL)xL!W|$s z>^?Wpc)I|1KgfFMeQvfOzw8A?lMFX#R}t$$P^wbk2JPZuJq+6Wpu!Eh(vkJ(4pz`5 z44@Gr))RNY_qpkS0_7xVY{!5vzBGw}^$f^-*nMswSEAnM2D(3y^&)8e$Ay~*r1ugJ z(tU0qy&l|-pm2iT=avX!-vq6h4B?&#a_0jcMh1om?p>hRd;}_IVz{S+#F6iF10@o1 zkblHM9uWs~LHUz`pQQKAg!PvL8xKiXL-cR04Xv-9tP(vCJ0{!bYU8#9AaGn@|G;4 z322=UXtOpCt0H48Xj36LFDrxD3?j}T55w+r1Fc76RRt#`(0y*8)Wy#NGE*2dnghDe zZ8gXM&=M_HJ4O(jK?F4Z%xVwju!&TIl86H%=-L$?$n9{>jG&Eg0t_4=vE4A|F);|s zGcquM?sNMKG7+?ZkTsGKTq28rW)E0l_qjQOA~qTVNDJsbH;{7Se9+h$ zYXT!^4S@(~(3>?GoZcBk&Vf{?FoGhMMFceE#F`4`@Q8r+p|hreIU*vU!DZHTuznel z4v+_6_qlt$K9z#IdSd{9!#26HS#Ksz504HN>BpmGBopA7sg+rU@0WwL>;!UEMIlAxRqO94;7l9$0GGpLUS+Wg11 z1C$6sH9M&3z&IzKgMmRhg@Lgbba5U?SmqRH2%{I2au`EoGC|`yy&y%5p)#NWO-2YO zOct~&vX_g2L5?w=(LfG#=@Nq+V=PlCgB)WF6KESIKMTkVdC+VF+fIIvs3j2*gqdCsfuDbm=)e$kI5lO|eWRVEaH95J`dd60+?A z*#v7bG0w5$gm`Z)$a~(P!$!c~TMM=c>bM;l>R2DRU3JMiaK!So0*<bSIEc#_ssw64 zfp&_>Zen0ycnyg}rg8?5+$8JZK#*+jfvvSPPPI4k+e99$f_T zC}@#2#G{Kq)-whxgHFz4Tm;g>7^0F`oWj7k9OO>W-LJA27#J8p;RH%8h}ct|3Od$l z4@e6r*u_E0!3kL$6kHGjB*~x(x;CC|H;4`L0&azBpt)dHHfB)qt3HdFfq|V3qzRmL zkaU5?KsgO;+vw#^q+af1FA2Mu$rF6vkAnpC1|Xz+oCz;5`0YL5TYf+n2*Gbk0$ujRXT@y|GC`byK@ob%5r`|nz@UVaY|v;Ex>2CQ1=Lw$WC#LLpp6|6B?zNHr2=T;0%jD5 z4Z2zzq7LCIkUG$fnT!k}APS^}5q#PS*k>SF&=4XcLnw%X$b$BrfMr2hA9R=rBSR2~ z0(B1|#v_~oT2BFzV`KQrr1M>MK8Ouc$H4&h`FDgvK*0m)XF~d)AR9m`K{NzW{@BmNhYSpXkHiO^o2!?>z=U)RJ~IOY{GfcKBk>`^Ihje2 zWAMS}zM>t2Kar7<8FKD4Blv`B4)A%@$RZ*bBA99*BH%;5nHfPRyfZ^ix`rH34?8?v ziGh(h0(|B+%zV)C=ino~LCY*q546_P(?=kE>a>O<0NbVGdc*yC`@!1TZlbDG--5PXQH|3{VLrzpijZIL@ z5V*q8>G=})xk#OL2d~Oo@QPZH3037L{!>V&ZM@oazH246=G=>2^T^iJ* z1T`Z-G;HDn#D|?O4QjE0njatFC<{C^K)J%hkgPLbBaZs}iCJt(o z!NftWC{W)8WX@EOAoSE)5F51E1$00ssA&a~0@({{SAhoQLF!>mAkc*9h&$<(0X|m= z3K|xMkN-h53=?zKD@-kj9*SqX!lr>i$qIB9D$;Z`_+(j7X9MIn5C+Zpfsz?4*@D!A zrr%)66~qUvrvj-3VUT)|94y&_4GI+ka`AqQwdZuf{RB;`H%`~U8fYMfeu~;NkNXI2bUBe1)zc?jUgU-t}D0@LB6H| zEC3?Xpq9hVE(P@+U}u+tvJ9gbL;+~t4JHoCTCg)#L16_uOBFOn&Ino@!2p>Dhp7jR z*@*B!&b9?j27%b1b^M_I66g#zP&Nj|3rHMf8;A`%Lk^U+LE<2Hf!MHf<3MXGL_ib1 z3=9mQgULZ^K<)*xxuI?b-EasJ2e}=@hUo?QSp+oH#=yW(2RhG<2Xc-Zhz&bK5p>oU z%x$0{K9D&ezk=BC^A4eULH-5}X2Q-m1g(1qsRtEJAU4ci(7JaKP(lQG612A-d;uOL zT!caA&VkGWtyh4~frG;tREB|u*g)!`Y|y!Aussl<;uxeCG-L$AptZ6f<3Z^ZwiX7o zZUm$rl1fb@dWIjE?Hu|XrOAibdU3c@hG$m<6| z!^|M{p!@+Ei-WO2`2nOCG@uE>FukBjO_-ZOdmKROL25zs128sdeF{h~Xf_jsVR}Km zYnWcpItq|_P(A{!y@0Vn%Viir3szv~5Q7eTeUOsIG{l6ue{ z5SSX!%nytW3I`Y)G(-YpgU*eBu|dO{Fg9pR6UGKjhr-xjk?djuja@_C0NQf_Qv*8J z0mfEGQUhLt2~`hTGXzuPkE8~4CNWGLbWQ_|4LXMy#s*C#!`N$)^zKArgU(ZhsR8YA zfU!Y)9AIqF*~Kt6=uTT08x+qlHXmrP9_nV$ULTk^Xnzlk4cgNKV}sXJLe?sK z3{wM|PJyvO=OV+{eMsu}A+f;&&rmb3A&I|4Vt+$ogU&yOnJEBTGYHiS+P?x52c3%y zV}s5>g|R`45MXT3*$FUq9FjTU^^Z_9Tam;kA+hHpvDYB6LF?yXW*$Ql2kixciGyaa zVQkR3r!Y3?>{A#UH02CqgO(q_*ovTaf>5`C_G-YylaR#okl3KJ0bpt-A&JjJVuQ{A zfT;nkONX%!A*lhK0RR*Kha?U~bXaElBK%NNmvFZkT$|zHJyAv{xI(zJ{d! zF%tU&5}O5d_8ZjAf=FyRB(^pZ+X9L0io^~=V#gz~bCB4TNbEKw_GBdXM;fb|5y?9MC>sSojnmiI+h4%Yy3Mc91yK{2mY+ zYW_?l_A(^)W)K@{{sj;ls{R&;4Hdr!H6K(*gZAvg&R+cnQUg`b3_8CJ$_DM(g}GA} zBn~yl9>j*K@dUA<;=a&*rJ#Bov^N)Kekw=}RDBT=8?*-(WSy{10k}fM`%#7RCnk z5nyakn;6ChwJTt3P`eJs2F-lH*q~*LFgB=N0b_$^Jz#9mJp(XyJW?AH)Fy|CgW3`> zHmD5@V}sfiFg9p56vm!~WX>`qHfRADObw`A0b_&Oz%VvwZ5fOWY7fKMptc8$4O%+} zV?ReS|1}aDG(8Ga^AAZJ`3x#fq_dYmv!pQfpuL|kHfX&SjBSXd9^6(05qS0=gYOrH zriUBQ{luX71+BUQ?FRxa6$D)r1!9BRm9L;`K;^&(C>wOS&NnC#DDQ*Vpl&jV4eEn|_$@M!J1RhHnnC(O za-iS>^>aadn0cVS7Hmihqz|MHM5FH^cp}5V0NNJ?G7ppvLFz!}f%<|V^FU%CeV}vK zKr{@4P#pnX*!_kp@(Aax-3fyP5% zZUE^6ou4KKEoVV|m>j4t3ep1$zZ`i6h8pNvdCX^YHB< z$P!>+0G$T_avKQ4+z0COf!qLd-yTf{1_egKdk9VnF))BG&H|YQ!XWcN7<~_cjs$Ug z2y!Ke+e5Hag19{dceIGxL$FqYfdRC~5ab6C2KfO*qwgVjp#@O~3TMz5ASld0@dg?T zfaML4zFbM-_7DU}F))DADkxur%mA4Os@p+n5!pNi83qPWngp2*!Z7zi_YmZjWftY< z>E-Lg_YfE>D3}@>E5JxY0|PTN69olBa|0954gv)Q!g~lnXS0F!&4KbhXb*t^11|$; zoD$?l&^mR{7$?{r$siYj7MO!t4UFobvIlft0s{jx3rH_B3#e3JVdMZ+?hK5AjH-OX z+{}E^d;;PO3`~fXBleP@#VE}D4BXtF!VC;7Dh%A*cHGRMG7F)Y55FLc4AUeQEC~AbYf9r zUV3UVOhry+UMh@TTvEiKmz6?~8wX1o2pXJ5ppOc z235|0IoE-j0GSzJH7rC2;kgdz03bv;12bezKa>Zup9d}ivPlq>0io$fFBz6(K`WRT z7+`m6fXW}(S;B&#_7bS@U|?VXwH;yN;4w*Pe*|1s;2Z>IL}E+ z28pkR-s=KlgD^}E)W-su4YL=t?FD2H$X?_&45*(4(*x2E+Oq@F3u1#XOb)d448#Vt zbwT2w9Rwh?AT|ht%Tz8!RH|1 zbsTsV6yZ9~!pz)=*gEb4Xn>xX0o>jO)p1hbC52$?;e?qZ!$JlI$nG=HCNp$C$WOTT zmVx3Jw#N%piGd6S`5jrjfrEho6egfL^#o{aR+Eu|VLB)j85kHqnH8jo39{RZnT1`0 znSp_siMMm3+QwwW_6GVD`-%aC4~``UqHLPc7wKffjG=Qpl%-f50L4; zAW_I(0MPl+oFIakftiIJ)Jg&E_5y8X;Rbc>m_0$3F>r$#0nC1&!yZ@|SZqL-#rlI* zC9+Hd85az?6pV+31#}Jws~Bke88Ztz=)fIb(5?gtR^0;7ZZFUYLah2ACUmzK$Yd7o zP|#9;0}z{o8+337E11p04LW29!iMhl0-e+>!obf0>eX{_Gcqu=F)}cKozB3(3p#p8 zh1C>v3K92m&|V62kckZ3;Qdz?AT|p(Xa^LlC5X+z4NB6iRvDbPN}(J&3KqAOO141+?1>bgmaSsN>A)31TvE zgARga^#ZXQ1VOv)SbaclW?&TL1$o#X!~yO00*zOI&LIMOM4o{c#P4AZ?g8!g0*6=# zh{?cx5Tq*ca$1?|iz0Wlf4L1)0SmV(V^;Aa7qG{T@GPd=~~F@la45CPqH$6Ce+ zQotYr-tSh;7z*C)1=`rb3gK{wfUW_Aa(F~Qd;eK$!FmKlKnJ3*)-&dT<~&8df^2RC z%SecTj>Bbb26JRYBtaWZS{UcEGBCh*do2R*_EHChKnLSy@NTbVAOpI(hI| z90L*1LcPVex`UE+2Z#;Z?X{kXfkA*9bbbQsE|7W&ZZ?op_JX2Gh8uL=7wbWg9~8JjJ4RR! zgH9q+;a&+c^XMw@ZZFWClB_4rfp>d>&H!gU`GS>!0k+!c-CiKO9JoQ} zSFm1u$I8Iq!W{w%woCt585rF8;&YN1Sg(TgdT?(B#ncUu`T%ZFeaCteGzt~M4LaA3 z^#N$)E`nPbCI(^9NhF}%UhhFp0v*r9 z8p#MQks-UMqM%NC2{I%aEW;rJ8l7Z~VFYOb?e+pG7iME+U!15i5wd`&gu z90|~-tAdgu21b2Q8f6TU0ZD>(*T^zPLHf?1u@}%b99~#+fpLx>T$cq@7idVhjDvvz zNtYZbqcCcLYI%r3@}QmFOp2hHC2ZKwHDkA3_PF#00stLVMb;?gn@j#49w7dBp^lnAVnZs1;EN!VfG3lnFTsdOq4-g zl7T@OtO(>dR**A9po&;Mg+XSCLXC!U#Y7p^B_Zw=XJr7{A)yAQBta4&{Zh!gQ9!|k zb)Ss{1A`1=V~s4*#u_=qmnh1!Nm+K%F;GOhX#gkftK2O$cing4m!- zmYEo~gO)XrJQAWmx=ka$Sid;8AT_rXHu3}6eGm^BS>YZ7C8W`0sJ zVr6=6Qch|fbT>nMj+sefJZJ%5e12M5JZKeqd2$8=XkmS7Q4vFYd|6^nX(~f}d@)E( zaYlYo31quNVhZw_ebBColFEWq29PPmsUTxg^UC5uu8hx5%1TWxVTeawQeU2ox~U>Q zEhjO(m?0jzQXahdq$D#p72>kQlGKXK5(5Ur^6rw{c<^H7_;j%Aa+5&Dl_$gYXvD|E zY-fls0`2oCE=d9J6M&e+0C8ARYEEimacX=~YI12&ab{U612IE+AV29PGsNeC0t9od ze0&}xu;bl4eOwvhQ;Ul7@)_dOQ%h13OHx5x=sN$*JX((GfdV@|tu!y0AwI1rH8m%* zxP&1dJd_rnmRF2rcSU?|5_G={Xd!qxXdyUwj|-Rp?{7)VODqCKQDSj2B4$8=0b4u| z(wJGCQe47-&=g;s#t@&D2TB^C1Xz$?3`%0jIr+t@p!ArZoDJremE@%6K?0^YH5tOl z$S*BofN#nG4^xsld>S8Lo}7`y07`hNDGFdCz)k}baHGM#%groKM%V@xiZ6yFE|4GN z6O#)|GmDVZN_>7^JSbVlLxKf$!w)2*pjwe!2H9SboS&banaU8Kln4%l%$!sPu+!qx z6LWJDK{1z?o|wxJp9dQMj4w|qW{8LG<%uuJWr!~Yr#qCD{NC7^K3O)5gl+403G znJJlh;GHF)>`^4hhWPSiu_QG;zo?QS9u&v%&@DN|B`KMC2u0um2edCN6*Mf2z6C5bH?=4|H7~gm zWHxB~SbQ-!cMsgKIdqW#sQw1E@}NULAT9%Je*~y84664*G)MxpPXVMB#0QDP+5n(| zQjk0dvw#f3Gb9flfzQb-Ni9mufeyIi8>LSxO3Y1#sv~XO9&8ar3vq+@kja6H61|+v z5~z(8C3*!#`Jnkzkk^ng$d@oa=D0rcNF``o9bCu4lrwaDi-4G+0 z89)tq2pdE)gB$uF76dbcSM5XCAd(qAx(VWe+y@$6g|I;+GXv;EF%S!anHi8rMnURD z89+mqAX!jS0Im5)UM~PjBB1eR5Dk+DtpNe42VsynQqu)d)57a{q`DWJ*Rd3xU?s5f z2&@RRE(Tc!nv(zpGIaY5=>B<-Fh~fte*hGEjNpDO$Zre`pmp#dH6UMu*r4PM>f?jh zAblVA2hxM&1Rr`$w5*e44XSaUPl6IV#C(-faWM*Y*4s@ z^n!*!K^UeNG_DR?M*^C20I3IsD{QSihz)WlY~35keX#XypxB17!SgiGeh!odpyIcY*r0Vo(U{TYc3+QJP}4>~#v#+C$)`$NrFMPh^2TEWzS)=t6LF-U4Mkl3JeYCxk#FgEDE02uoXlKP)WY&N7d z*}_O{(C9HtZwQij0us9diQR(4o`A##jh({G0UZYiV{buHa{!6`0g3$wi7kS(&Kq>j zILsW->02;1=xlKq+XYE|ITD*6Y3;Q%5*u`A6ihGZ%vc!P2}up;%yXDH=;$LDy9`MU z=w2|G_yi>Jbx3T`X-Y6PCy>OiBC#JKvA-d)LFXyK^a_C1XG7DBED{@Z4;M@g=9Aiy8=l~D-!!L5*u_E6|4+@i?l|Z6|}Az)MjH~U;wWd2UTPY z3=EPWaj2W+L2RfRW$5~BP(1>^-yACL0a63i3%Xkh=C)`g@dOYXYGyeS8(bejCwoEW z!rTd}6Jd4D5m0#rwd)*ojVY)O0-ZMwni~eStU!0@fY=~2VCz;vbu~yGY&`)o8(jB6 z%|xzqiC()2^)JXwVlcM#lpwdl^umk-4I+csptcf7u0@oA0aUMp-N*o$mj$^Uw5AEv z-UNjoNFAttg*ClFe2^I+8ht(G7E#E(J|Ocz;RaF%G7r>V0GS681L*_Jnu2H;2FZcg zph;6u+Xto&v^Nf921pKsVQi3lV0u8}AayW5f%q_W=<6x}h%zvM*0+M(2TB$obs+bF z2LF-G1Kt1A0&)n*Fi`ysrP0?@Hi$7WfbuxVJkU}Sn0X-oA)BYc$-n^Gn*}un-Wo<< zPkE9H`}#*ve*k1Q%#Q-HkoAusdqM68$$@CldSzsLUve=pJVp|LF+pJf(gQQkM3#X8 zw0;<59;p2ck^`9sTH6fL14<(xx1Zr*U;rHn24aISNDhQSYgs`wOr44l_VtgTIWD4M}aJ4{UgX9p!^B*2WVm**}SDf42aW* zkm47#t^}k9W?qdfL>qlz2*0MraD;ZZU*Ior-=W_9!5?jWy zm*p(`S~iG~2V+&6%}wd$lROyqvPvIWwG1K*K42NDM3)Pucr6nfGXwO{W{5h_am}E3 z!L=?0v>z6-F2#W1I1{9t1Fb&+o#n^~YLtU6y9Na|NFj)30`072Vg;pV*uldfVdiU~ z)c`Ck?7g6b$HWfmJFqaafwpO~Fmiz9m{>sz&sjKFK@;ID9PFTNAS^7bpy?+T7WR#x zc{dgo7Ix511U44X0uvTS4$!txHWtu9jqD&1HWtvmARL^aT*}T1npy?f4RRXe96crm z1};!B&d3j9f+V<;Ks6XY`2LDuE>M?{ksoxK8K^J?UFOLE;WCEufF?H?MY|Xn7(g8z z9$rw&5(D`WwC|M%q@Gb6#61O?hXt?qk^pf*>lJuG$rW_HHs}g2KJYnix?OfKqst%R)K(=RK~!-4+>|H9KWKrK*7bv z0@_6+0IFu$`9VGs1O>hzD98mtLCqip>M64*f>eP#2NeWu*=0=ybtFOV76i#M2!ZzV zu!w^ML3Rp)7=obn3sC8Mpt)1<%qrNKX!Zz$4`z-6>%x9uAasrryrvj7kqKIHg_zT1 z1x+S0FtC9r(0m^|WWJ9B6kD9gGjV9A>Tw|*qbJV5z>UO}U|`@un&lH`VBm$#1%l@H z_>g7;`C$?a3vsLLlB4pWgUnFNCymq4nbgK2mw(b^&kZyNIFB1b%ua)2v{Sim3M^gJ_Ue zMuspD1=0W#2CIV{NDp4n1`-3co$9HH-{FAPQY6D1Sn#B2c9RaUv*OAS?z3(69g#1E`oHVQqP0QF;}bGeVFV zM}3spMSUt9Ne3F{tBOxdNznsOQG%zkAZN+J&yNEi8dsE=mkt+)93aQUzyR_PL^L(8 ztO~+nV1Uk53NtdZaWXT2W-0l=B#6z($;ALVU=Bj^FfcOLb22e7GBZO}B19NDS>Upe zs=L35PxB@B=W&Ai0i)cBm#JO&U0>`^cg zUzD1gUzW;HTmqU&VMxx;OHKr90jq`2=YZ#Hic(9;5_2GvU2qxD%m|jrpVXqF{G#|0 zh#jD*Qxpy0sTeSUA`EgcXy%LoG=>2doHWM{a6vazP~n#43;gD7Zm!#ejPb6Qo2R z6d53OddUzIL3+X7A$4*Mc~&hqF()S!}NX>{lB?=TcpnwBma^_z^ z`e2ywz6t1H22=y-^DXG}Daft|%{hR2M^MATH5I7wkIV=4c98kv@EIRaA^^?5AgciN zVL)T{FdZO1s2W4&gU0cZ`Jl0UWIm{`j?9M_JCKba;4&Q|hFaV~voW-60cAK)NdYN- zK<2^bTtJB!)EEJYff6u`4NB;+xfqbU8KE8ng$Rrd>i@yccmh?VjG)bMpjBm{#s{dy z4Q*0`_8EgR3@G+Mb2K2kKy29D4X6;O=7#zOG`;~62l)xahKYm5DL~>N|AE-BGoe6x zgF)gTzk=A@Q2&C~%Y(#0?gFu4>OuYloi_yX3&?H|8)O#%n-EC1I7k*H(+eg`Asl3XmKcv4LT1C#!dvqH7GI}7#Kjk448O6 zk~nw|3RF!kk~s4G5$L7_m|oCX05CS_=ww*<>_FP94;qtzsR8vJVDoFB-2^c4`$%?y z&m;mR9tH-6cSz#Dk=UU9|1fj7K)pw(n?ZY_VdBVhPs$)QP%}aIK*Q`cLJ~Izu|YKn z0|P@i5*yUDhWV==Nqi;}8+<+yR4-_J6{h|lk{ZzXD@@!PX^sZ8uO8+e&>i0}Hu8KB zXuUg39QphpaJq%s3rf4NbO;I#7#p;Y2gU}C+rZe!^Oc~=6($ZU_h4*Lmm0g_(lCq-I%5mQ26bUzYzd^ZDnNIf!^FYm42XcvmBZ2%sJw!y0nfKW(*`Kb zgVG-;y@2jJ2eH8&LFjw|s9d*#vO#8m?llLg0rmRapyHr(;R9uZI*y>btw3r(hq#l%BCPBqPX$0gqn#^TD!w_UXF&I?0fLbfi=mGCl1LZH6UQj*-u|b1i zAU15Q_6rXK1E{V7?NtZq2g!lzO7yu5(3yOoHVnuN5C*9O(dcs-3A_vppxrPa^FVP8 zQU@{*6n7x=L1G|%phfl|8iqk~AT}uPgNjT->d@yhK<0tc3djr)2H6XuLG?L^4fAgd zA7ritEa78d0Bwx}nFkt=hM5N{Z(w>r z=7G*5gHK?9>J*S50|Nv4T*hS<1_sc%c2H@!7WBCc(D{_0dwW6lg4_?Y7qrI&+1~%4 z4Nfq_kn9DObs#;kaN!Y#%#DD|L!Qe3opFe4o;(|3+abtUm>l}q5C+1CdrLuW8<1Tf zcY@b`FhJ(dK>9%!;(+E7L2M8PnFqq)bsvJjT$L1y@K5qCC(0XG8!=;9(!z6O~AG7l8qptOi=-Uc2922h>>nGM3Qu+TR( zgIpI0nHo_bG&f>mZb`i3t`K_EJU$1{M}} zFYr7@GejGxRly3L%U}bEu!DyCnYlrRfvg8PgK>@!BLf2msLEj!01c>vBsd*GxmWEJ zvm*~nqYasJAdQiWGca%>aU~cSxR8d-B^VgE5hLR~NCW1)sOCe)!ucTM#X9h-w zAW)tFoudpI#}1kgVu4x*j0`~_3e-4&NPt-2C}99CjsqJ2A|SO|2#5k{1*r`I8v;_# z$PfaeK-wS@ARQnK>c>H<7Dy@tiGfssXb?^YZNX;v4vJ^ux9Nbo@C?)#3MOwr58J>r zWZWS&ucW9FGOP?AOJ)LZi2;oiGczzGm8Qj~W#*+6mlUC0LLv+rB8ChXg9eA0z(d54 zjW0~#;a?`u;4lLd3up*ff`O5Ni3K#t$;r*Y$i~bH8cGJs6@XMRi-K<$sRWUnpoKV$ z-~m=J0U8(ujljm25H+L<^AUJ_6*RC6HUwon7d+Gq76ub2av*Jp{RiLySug=s33dv6 z>kY{RwP2knwjqz*g0|Sef*Ks`pxuR_;0Jkvym*K1eM&7ZFf_2xP0dL|*#HGjlxWVW zN(B#egF+!59FhY&(hJLiAR1Z)fbt-GZ9Ql`Ehw{sXpjV`aSCFCCYeB^yP&)e8a4#6 zL1h3;4Tue@ghAqJ0H|pJN-m&e02&(xjgx@* zAPj25p_ZRW83rXEgH$sxz{YDqNeeWt2}*vTGYmm&&!kZKScHns{HLj|b; zsRy-5VQf&p4#Wl}Z_wE}AT~%1X#F^d4NAtKz7>cKQUf|U0K^7m4Uiq6u}n~w0@(#( zgZlR%JkaBsx}aJWG*HFBzyRuN!p672ttzNE$S*K)aMp#2gZqe3HfZZKObuuq9gGb+ zhXBR~jT^w&l}Pp?k86U?K82|PuLlE_H4F?4ptW?cF%{4l5=;%KzXKa<1Ra$I6F-e) z{#6hgT&6HEfX0nrYF>cEq3-_%Vngi`2DKBR;^4T0ii6@0<_3^7j7`bd9%vy8%pA}d z4vY-dnTI|`wUdc~0dyW1NDT6b=MdS~BV^p9s z_F-ez$l(GW&R}3*faQ-CUPS)DH%8^lPUILB2Ll7>>|Rj5#y3U<10Tu%^Gq z{`?0Sg=_o?RJOpzpFnq&fYKUh{0Ve>JEJQj0|RK%6y#};LJ*C0{0VdsISUgz=(Hjh zMmEsg3=1O%=*krqCf4(yAsqPl6X+~L78X|Ua3%{oXoiD@g&j1p!pZ^~ZDL{MI0zn$ zngCij2@+ukl^V=Epn)Ec^&n?3&Jh5OKY^!t5#vvw6vhZ0f8qo$bOp;XhH#mJ+7a;4 zCtDB?W%LPT8rIP#&_odnc=Smhv;Y-6`UGZyOdOV@PoQQ3BSR2~0);ead?*Msod^ng z22fi8(gcH~5|AKB6^I65Z}9jK_~x8pFg}!?T0*nYA;|JV(AW_RbnJ);JW9mKTnri$ z;skAa!afcJ?rnjFMZlvnC_@+o$9BMa(^E^xT;oZ~kP3L<2uy(8IdG###4JUG#577+ zf=1oI!$AXjz5*Kl_f-s`GArbY^(;<&j7V)@s0U_)PwE_0gc;$k}U{>*dTFG-wMPA zC3BG5Kw~(d>;Wv3@3oJ}BNm_JhVfKxGMt4Zw!Qt41?rAZ1iytTB33exCf{o4@x5-Ge8*TK2Q$^**wtwV4xX$kbm)wdw}lNAZFZSG7|#>Xx%NyP7sFK zi$3o0g$uI21!ONMd_isk(dgqITbPI&_fX*`ZrlTOiY{nVCCF_c409hSyg+V%g|i1Y z0|Thv2XY^%JO{~v+=o8yq0GX-&BCwd{MD&qDV%vvI*r%D1^4%LUQhlcnUv zAbrb?f#EI_SS?hiE_^Ta3dS9RFcW;adZfgZe#m~nyXFTpehV9Od5yGxc`2x_1T6*y zP4s{~3Q`E7nLwuwq3&M>)miZU%b>-xEKKa6eeo=eY*#^xdKfttg2r8#SV4pMEF7%% zAVCgxP_@Xy!a4`UV_^raq+tc^Uk0rJhVNen9Xo`yf0+Z+bYtZMt-%4g1>`2iIiO>H zI6-F&F!F<#APKIAAm{UIgBEiKbAsn_z#ErAgFB#7j)9RMv|0%?QO5 z;H!AVK!YowRYTmM)xwP8AZ|4S0|PhcJ^@Av5EoPoa6bm+cS#TzG_J%Ao`RAB8T1ph z%NdkI3_%*JRJP~xMDay8G(2O8U04M}N z)*L7~DR5Cb}En;Rqp@)kq}6c1n)g8*nenhm@`8RTR^P-F^% zq7W(#S~AND-n0&KF`6_)jSy(r8haGT^^lFs!l1f{O$KD8AecZ{hjoz_^2#jI_BiV? z+Dk$XbOs%IjB=PU^5QIU1_tEa&Y;CvNNcsk85nqAYqdbThk9F)|1;8VWNo z;M(a7+s}+`uQOzI7s^g&kaAFN0bNT0O3DnNi(VPPnTi2MdxoL< zz!a!{WMl{hQBY~n>=;-I)La6IgSHWaXplT3;(!cfX;3cwgo4(Ofl?+TLnzo3 z@IErgJ?$WaK=->q=4E0*)5_p&G7O-}X0T#pGeHFfs3pwE5CzI3po`}j;iJf)8-c)m zNsyTc$AK&d8w47;fVAd8l_ppS95@gb0|V%oGA0J_#4xEtjAWe?jcxfDH5Ri$mQaAt z^n?sD60x&66~2cVw0sG&o4L3o1-{!EzOz|`k(mLs$c&j4Jh)g5CP6!pK|7uygN~rZ zYjt38$l^6d@J?mOUT4T|W{3zQR1HWyWN8~4rvP||G-zitOg+di zU=zT*qQQ&al0ZA7VGH5}KnvoOKyKv(RU3>TFB*Zj?}7&4;!8lApp!F-81ln`!#5kHXd|*DR|p=Jm@YkkSC15?g#I6 zL>Y(#51)bw6ydVO9I#eUFoDM@vFy(V55FRIXM=2kE^Gs(AFx%#jE;gs7kR5T$&3Fo z)AL|wAA=o{lbScMYwJLrc~FT0qCp)85F3PH1RWClnLs3?W00Tq@oy&yJ7KS(`j@eOFg5yS?aI|H%@#0HhpF!iHjuOn{k z6}ILMlng*)ujp&;Kw~wayQvAU3IyjqxIj|D7xTFYF5Q8NkMK8P%0gHhSlmM4OVBtK_x#3{rVe9`u)j6nj z1rh{h71$naQ2!ph&jGe~542{Lfq?-$h6~+84el*~`h^S(;5kT?{n{W&1_p3*2{bMY zYQlj03SxsA;-Gd5hz)AAfQ$yQLD>{!K5Psc#D=Xq1ht4j;vn~e*s%TDpjHh?FDUDS z8rC2+Ab)_^=zF(8Ssb)K6r={^KM)(XM;mN652RfMV#DkOwSYkCL2d!DVfKQWP#}9j zMF?o`A4mjZ4CIu9glKzm4G`@2EwR6y!MX$QpS25Dpf-IT?^05TI){D2zh zAT}tCfZ_%;h7R&Oh!0|e+ylY`J)RC4bA^pBgT@tMY|#2V7#qAG05q7)z`y|7dkYf> zEn$GMLHl1|Y-;WM2Jh8@+PfCis0Wql3=9mQCl)xAm7(hpw!SsUm&%*SA``A$R%%ILUlnvTH3sVE?@Wb?i)@8uNLHEJK#I-?s zp>~1BzG32^jvY)rX#4;s?un${55$K07qk`-wmuKEvIEARfTRX=Z!}CCd7t=YBsJhO zhoNS&gW82qHu8DG?jUife-n||xb}%3Mp6SBkA(RJoaUkCgVH@LzCcF9*vNAdpwSGN zIH=l&u|Z?nFg9o{FN_Tu?trmDJ$D!zl=oq5P`ZV&K|>%gHfW6_j15YwFg9r18pZ~V zk-*rXwQn$XJJMVWXh#=Jd=ip4XpJvS95lEBV}s6hgt3v+@Kz+fp!5t=1G;+}#s-bb zz}TSmTQD|g1PjInoo@hRgXWE3>{m$UgNAcp;(w9EK|@_IanN!j7#lR_KxnQAv@RBw z_F(fpp!f%+dC+_hs22;H?*YvffyVMd;-I-AC+HjxC|!6!*`U5TDE))ffXYkIeQ+Q) zsGb2`R|#T+%FYC+dQj6a4ax>}bV1jkfz*KNnIfn-sGg~SvO#q`X!jjR4XEB}fr^95 zzb+^nl#W383#0}#HZ=_@4qA^38s!6tgX)t-P;pRwvI5Emm5b}3Y*1Hz3zQA2Yj#1| zpn4Ou4;Ew&s9pn|84hBD>e*{hHJ~~KcBU?-)G4O&|WV}s@wU~G^( ziNT=y6V${9r7@6t(7Y6=>i}YdFsR%B(V%8Mhz*<1c*9Hl9(GW>4`c=igUkTYpfUx- zhM5<^$H3qMz1JR;RzY&0_65j2Aoqd9K>9%S1&D@WkQ|7OK2L^A9jN^T(*x26TAxqM zJlPz6;^xUf>+Rk{%UqE8FuTy_$)4~tFsxyM%%gxtkYWA>rB9e1kpBP73=E)s@gOz` z!{pG{2eX5&LWD_z>Q|6r1_lODI}v0yESx6@F)*BfhBGL9L2@7(eVz=o=NyzapvJ)G zZ$ND=kRF(M5hBFRli9N|Fo3Q?LpKk7o~%ZMfdMvu2r73#c7fanD#JnE1GPy(X2@|c zFuVc@fH+Y9g1G4OWE@jYB=vvgF~nN>@c%kVp#Ik1)`YD>VG0}#m_%!`y50(L`rE15Ky1A-1jG835B z0=2mz^I8fFdqFcypuk{YVFd370v&)1I-nOM22u#3VQYy&eLEJ|UUtx_0W3`Hpk<^i zjBKEM&BDkr12UNfI#mg=m)#R2$ifOb)&_KlFKD6zG?@kJ3bV0*GAj!s$1>15Vir)V zhaDsWnb+dr1dZM>f!cMDj=~(!(p4@{dyA1D!~{8x8&v!<@&|$%romj`GLav2V>oDb zg9l_FqX?+M1=<|L3mVa46b04Yp#B9Pr~v>vGznDD@qBfE4`aw7G<&qd3J{IS+pkb%QTt985lrQG>o7r8qnwhKhoTd0AlV&5Otym zGA$zn*>sOqTexKxM}A!B5qypA~_4;t2ooMwtC2O1zFY6CyS8u04MlA=ml?Zt!J{ezc$*#QNL5Wkj1EeyB$h^F?O6 z#sKw8L25vm0K|rklY^Q}AaRh{AU14l9AqD8%o$`RDC2?Hpz#wB9_aCBP#nR=3_*T_ zu|Z>cFgB>g24jP3bkJZC0|Nsk`}0BLdoVLW=iI^ApiNmYHn`shDtQT3WNPmFTL)C!BHuAl7;Pe1B2b3mYV|^fPFg7T!!PuadIgAZzi^JHU z1}%&Y>Knt@ptJ{LgZ8z<*r0JV7#lQp24jQT_AoZ6I|E}Q@8>T>8mk127ZDnh1g%+z zg^w6?JPqV;&{#caoDI~^RDz0w@*ikRB1jyR=k%cBpss}plnn|4(6~KF4X9-aJG&Az zeh6E$4obhUHS3_Gzd-g;d%O;0CNUT^egdj5Kw$+^4=N`>c^||EVNkq-XiymnV#E6S zK1gesLHa>*pz;KL4LYdb2CIxg=77|JXi(=4#D`q)}6GXn!?+zVYD`q&x^ zF9QR}jUa!3?1R}0>YT&e3Nqs_k$dlt@Dew+Cd)tR3W55C*v&gwe;=nAnLMTXSY7ZfvcZow%{J96ko{8e~v7gUStT?YOY}#F*i_M#R%F;4_ZGBax6$8h{ihR2AWM`VPXdz9?rtZCJQo$ zkppx!E(;SYXhs_`<_6vy!@>$W28e})eL8H+4b(h>kGX-`CTy5vZlHbuD=26gKyG22 z13FHS3tWEjgP4p#T%bu6M*d7tb0C;I8r0Gd290!qoXrF3b~B2As&&wG8Dy0>c*G5~ zx`G$fLTNrFmB z(C8)T#$CuAQVjf{Qt=Kb=^>BBfv)XiV3G#85M+TMXe>?;x#hiQuN9~Z8tAR=m%t1M@2$(<_egb)l z0kXi2)OD_KbHEF4!35ZR)WZ)zVF_8mOw8h2P%MBVB(F3lCq6B|G%p3TAP?jtkV7Hy z1-*d@ZavsOq&2rAar_QcAAqtahz6D0AT|iY#_vD{0H|jPqCw)IraOoYnmYoG-+^if zP*ViN29*k+ItRoCEr$T<1F>Pn07&nMTd|80s3UNU4^)|h5)LR4fX4VpU9XFNe-h}f z2#|Ro3~nPK@;7)spsWg(*&z#Y(MJ0ar3wY(ejs~c_acG%n4obyP~r#q6*OK4avO*Z z8xI6!E|?n7(o&EbP&*#PhK&b;`nDi7pbQ1tZwFEX$}k`{Y&;Njjvz=J)E@+~VdH_I zemh7nC}V=!i6Ay81A^Abfz*TC3u438!Ghce8Z!jB0VD@vgWU*fNrD!1F)%QI+y)zO z0oCoWF&xmi35*RIi=g(sMW6;UZ0rj(Rsdsz8!4axEe1$G3?@F<#t%VV37FeJcfr8e z;Qk~iLSgGvq3k!HFo*gJyiOG=4!*YtRDv=vFo=R0`cO8gn*xg$&^Q&04O&MBV}rKF z!t4e0SYYh=AakI0?L%UNu9k(V0jCY9U7+*B;KRg0<7hB8XtOGe z4a&nXHmDZ@VhEQpav#PJQ8Wl5Y%sji6f6Og3~03fX*Sn!UUAQVd{~? z6SULP)W`HnA9f(FBs|20902NfOe0A z*dPp(Lm#W$!3?=F8>9w=Vd~JwD!&jpR;j~6+<6&W_=p>;^kHFOsDe2PRE~li$-uyX zz7FsPA7U&ORCd9_1%0gY7%KzA0yOhLTu^+1XwaMp$ci)~$10Z-IaYa}$g#>9{E#s& zP%zygSd5oCY%fmpt=W?uknplF5$u) z>jk+lCo?HNQ8%@qC^N4lO)p=c&{(B~3Gri<4?v9=q_IjV29S?IwnDI(BLie8afQ`h zrnAg8equz-ky$B1!_ErRMm*x2GC(5>TOBUu>FvoJ6)<}n~Hq5>%d$uY68gARdU zVqynf>Br2%3hIh7F|vU!I%Hzx2xn$sU}9n|15q5T`$6lUIM_jzA`56mJrg(RLVFfh zkSq^qIXa6PGXn#&0O)2)CKguE1%@oDEDQ|H>L3x;QqaK}DU6`;HZ~S!uic;x_4!N; z49q^DCEo1s7#SFteLzG*B#X+YwEM{b2kYLpX zB@%8wkgPt4$-oz%&A@5^GMR<@7c&Et&A|AbOvrqkSP`*HVZfC>OEFV z5SxSBl9hph)e6Ms;oil>z`$w^VheCD1hH*EY!U7SAicIAwgh(r$dz^=whT8bNUuGJ zt-v4vI@61Tk=4VViGhI|bnzprCy2=aZg#PHf!Ga#i6E1FKyGGW6a?+6VD$%aSQr^N zKzlX(nV=q#XW#|x$LV1W?g1GG4zUmrlY#p-$N`}sOIf(vL8HrIlb9G7IJiOk4p_ri zGJ$rl@w0$T;#kDQzyQMFu#sorXIa6-z#zoW0ty`7F3_5A)?(0BA8ycGHfsrp$-oV& zH&{!-<}>iKfKrAq6AJ^w2i77+1r`Pd5nYfM${0Zk7(_q^;<8pVhO#j*u!wvGxdy`F z5SfkO@Q7Rkxw#gsM?eHr=&;r^=CLv`h=^1kn{54r|T zG(NY0fwhfs5jz8eipU3$Ob6p;b_NCw5zurvYZq9LjtD;}(t5!h1CaobX?k?o41Dng46Iwgq0Sdy#K5{06s9bE@#PGx+dxbX@X;=;+d(Y_9`30i zr|kf-`S{|K(im8Gu4iIk5a0&2fmwHf)Jt&dfh^n$iY6IuPqL4_C7? zFsN|P0;xH=ij{#ugIgYC=81Ex3=BHl@}NLD`GS>!!GJHmG>L)r49I*FzWCAt2G+A6 zSK9E!mliRwo&(wCzzsV8nDyd2Rt5$a?*AZjF8yO=U~uP)&q-ony$aIn!429I$9e;# zK7bpvwt@9#F#`ib2zL$04G;b?Ffc@LZw1BXBTzXL!`%cDe+*Ke!XO5sK#4>g0!5Tox1xW*#3)Qfcm4QJ5q>G=Wk(Gf#3^bt% z@;Z`okdQc3`38_05E~RE2sI4+ELT_=AVns~!{EHd1mW|sL9;Id1M6&%w`3XBSQr?D zSFtcK@USW}`m-@Gh=B95GMLREVgmB83OK>Ch@^tFsDcv`2LnF~D0T6(fXoyIEti&H zwPl{Ej7&t(Y z4JtCgam3ER&jJboNl>`~j!#g5$PP+9(QF_RREtQ0ay~2tTmwrU1(RPvCEQfdnM5X_ z7?GOD%)r17TAISZ0IJ&==M-=-Fi3;XS`-2$I>sPr2WAEaMqw}~Sb74eMF1{D7(=A9 zK{BFXnNS%}dmW@%7BoOs!@_HfB)nP%vj^U|?ea2iyz}1_p630kS}mfuH3OI|GA~6AJ?ayF0$=Fg^wb zxcBlSwIa*Fb1UsFoS`C;W7AVanQmR5~kT8OU0>u7)(iGQMztsUUE)pN~(TwWigrN zV>wv}Vp>5_ewIGQS=+j0CYJg+nMwNT$;p_q`X+i7dZzkNS5ePJ3=FVdOEPHXPfmVv zHe|*x9(3qTF?>ZnWKNKUfuSfhHLnCNoSCne!NAJE0Eq|)8-7ZWDB==5F$U1-K@5zH z@hQdm@fnGEDLJVO@u0J97~+c(^HNMK7~)gG$5G@ZS2DyWmZVl>mKZR^mnRpME z7ndZKq=LA`V16-F06hB!CQ#cSi%sWoS&ba2~t~}o>Q6%F&SiNd~QKeYBEE7T25kmF++T2aeQ(`B13#}NlIoO zLwr(BHrQwJpqPpW8B0mup{Er@`^#> zpPmP@C_gzHWK?lUN@`INL%dUFI@lrUiMhFn@gPs8C+0H57o{eqfXL#~oRau#uqRQy z77x1A4>cm<%ab#bz>d!^1v$2~s3U?|VbD*<^B6lNg*CZ-n~ zF~rBGrGBvS?AwD;=IGF(y+Muie_HTS{ejY4!l9>lF z@;%D6g^*;)5TBox268ayyp^2H;u40mOvu;*Ls}*%x~}UP@vmC~1NdPCPUZFvQ10!XY;aoZCS5#}}grLGmhO zZaY3V2`O1+<|Q-4XXd3a#3w_eI43_j5#-eP0cXqj_~Mkzl+3)$5{CF3Gm}I}>MG7mk54PjOJ*Q-1wnisB+N^4<1>p> zK+Xk+6C&Lv=j4M5klZBXvZ%nc7@GV*4ja&IGoaozsLBS>u+cdXA2#g{s?x#L`~Yr= zq01H+P;CkFI2f}G`uTC>xME;nW&n+Hf}IW~m>EDlG%yoPFf%|8W&-m->O~>rKn#%X z0%$%QG>!|E2A?+tnma+}gXT1l`A7|oc%(81UI@dBI7kKuYh{Ew6Vzmc?Qa3~9YF0& zkOI*Bh6s3o3gkux25zW&kn2I>AblVsbC57L=ng{|8+30Wj14+l3dU|kax>`gT9`O!(I|`!o`-WkF4muYGrXF-21&j?EZ-lWy3rAsWP^T2e1`P?r*r0R$VQkRZE-`FiquRvnAAhE%tB~UZxAc?O) zVsAlWA3$P%Kw|$vVvDdcFu>fPfW+28Vp|}wU69!2NNj#KggMekYz-u~DH7WWi5-K) z&O~CDA+ej0*b|W0>yX&Hk=Q4Y*jJI*kC52kkl4(iE7YN3D}cn7MPh3qvCWa#E=cS^ zBz7DUI~$2zfy8b_Vn0S=ze8ew1+l@+9|ne>>9-51o&f=F!8`7N+G)kYGx z0I{LwI3lsrk=TVGHq^{oB=&qHHfT8sq5Wy+KxG%yt{c#G8=xxj9+VBLV;@1;p!y0V zhrH$n#s;?tq2_>wfME3+NIfwa)P4Z9Qb2A7sRylf0GSD5gD|LW2GO87S`Ztyc0fWD zGUpDq6Lek(=$Lp01_sc$DzbSX^`O=%$P5q$nE|3f?Gz9jBoE@-h(gwBfy@K>9V7>G z2gp4j^FU%Cb)a)6K{O15jz0l)iU;v%x2Q>!X{zYGV@th0$ zS_$;E7cnx3cmstm%-&8Uw}R|q=Vo94)vq8n2*bh|bmkXG4=mmqWFU8+fcybk!w8ZC znL8C~9&8Q7J01oGXVBs(kYP|ckeT2+u#xtE846*}^@G%b_TPfS9jcw7NC^ABF3`+0 zNIgv5Dk1FqxAh*K&u|Wp1Rs!S?Q1cWd2l5B#?gwP^HVHw(4`x104z%|dqz7i+ z9;9#vwLL*{AoD;?WmsAUnQ={sf#D*E0mU%$Kr}R4gJo6-GcbVmoPx>%P+J*f9*72| z9c1%fh%hjK+N)qq&~OH^p=%`|qkcrJm9Vrlfu6BM_{^jV(84vOwGuK6AXkEHC5+7+ z8P+oGWrnPpSR~Bg3uPW!e*q$<%e6>^(Uu#+$>D*}ce&4U?PXS21igO*q=pHmrUt6! zEZ1FbgweWOw%njSU+{Gsdzn-j7$Bmcc)_(+1GF3iwpIhSCJmIQKx~*e11F>p1G?Y! z2B_`uoSA`PD>U{%83q&#u>D~y?4V=+n3>q+K#M9E*+6q#%#0i^pfwRpte~rmnK@Wz zfp+C^u!9!Xv49RXV&Vp^$6zr+tlH^xTQdB*cy&1ko}M~9H6C!@HHHrpt(5k8V+U_ z_FteoJU|m^c2HAT9q&|S#8pMXK;fM#h0lJ2x z7ZjV&H5{oR@y8(bDGXvD3cP3oK4p29k)d4({&m%Goqzt}>1GE?gw1NS=oPmi!7_@!{zJ|jK6zs4y9H7;9 ztWi)W*@6-UYz>D7$V9X?9H3q}d<{nu$T6@r91B6JVQV-*ca6i>aOi^!g{|Q@0@4Fp z!!Z%W$pG7}A_6+_7rurAG&%-f!vR`04`0Ip>Knk<6xNqIzCkvw0zKwG=agRy1V*sgwuoxJe zm_TPdo&k-a5Pw}2be5OO+jd9TvK43tlB{JbkiG1z3=B|1GC-plxrrqiXe(HR5i3}@ z7#NxBK=)WNgLkMiGlF-k*MmhMcWBjfLQbaSMN?S^7H8%JnZO3#5f8h6i<`VvF*zxz z6$PNhFyOT?u$3L<$)JTFxk<2vAK)bwU;=eX25fB%XkiHQBs0wxyre<`nOZAeQu0fa zKnn|!M;E?Oyzqt4nip{Lfdx2dWdwcKzog~lgH}pG6Ht5+Lp*#zOgvFbU?4}J;#l|M z243|;&($u3m!mt(ReTuOfWNu!`Ik=1VCfz$fMUFK4^FwBnL`9pfxz4GY3F?5C+ME?u`MlK^Vjb z?O6vkaY4xoq#kqzCP)s1LGldHq7_`=fJ<9YTOlQlAs)11E+x&FAs(s%RQSfjiycS{ z1S*BRk`iPvXsjP(A#^SdwuT3kq+$2KfyTLE;vjdx#6j9%>wG}-A22nbRya%zc%Bd% z^q{@zu)E?wb26YaBS207v0-OVfRuv7LG5=C8@5IWG>-@p2e}Kx=7vTGDC>g6L2d-G zVd_EiM<8*KdqHfNdQevuBo1;rhz(n71Ugq9Bo6Wihz&CbG?We!2l)xahM5DJZv%;g z{0Cyg%mM8<0*QnC3Sz_VegmBwD}t27Kx>vjegwG>#0I$sgh@G97vx`%UeI_w2*dP( z{0p1U1&wup=CwiT3UsCkj18K%rS_Q`p!p-%{4!_&0>%cfeS)t00?(sD+2FNLP<9X~ z9YWdQwNFqscwwNFqs zcwwNFqscy-?3CaeqeS)&VYoDNO@Y*LR8@%=j$_B4}g0jJD zpP+2;+9xO*y!Hvo2CsdBvcYSgpltBkCny`d_6f=cuYH2D!E2wOY|xqtSeSsy-?3CaeqeS)%|g4Q@e*>8~8pOM%I%R!0Vu(W@;db>w?%&z3xctXe4$%61xq=hMF@0#D?mf0<{-ZXMxv8LDj4T zse!s-9f%E8za5Ev0>p-@zlX&Bfy4&2IY9Lwhz8ZcFg8dVj7`Zo=Ad>3%pB140*sC8 z>>+Sn3?lHHC3F)sW(oB#X!9NDj2@8tUqaV&YJ~^gQf~VyW>G@Q2XLHR1K&- z1!@<7#6iQapu0RlY|#A&pfVrC2Dd3d`}Ua_7(i>IK;=J39CWR=JX9Ry4^UkI5(l-F zw4vglx*9Zr2@(e#&0r1{2gM_3&J-jLY7;p^#X%DZAU{z1j3JPj#9&a{4b%&O20a6) ztpxHvOfM*HfY_k+CWsANqq9UDaW*+fKS&PL{shfka_`^o{ z9zhi@1_sc%Ay8xB{Y~^WY(hK?450OR=;}b}4&+vtKV~Q}Fn|st0r>;uevll92JOQ~ z_D2y9_BC;!IR}s)n0XqCkTqQ(^N`oDfp(80n>UGvfx!)$cR_B1$)TSgi= zbgl^YHF2Q(lR<8Ug^P+3WKA5%AE0g;NDkx=kl&EaTPgxsy9qKIgkf^%=LZ=mLDYfF z1D&P=GY@@D+*=Xi&JVgE%D@1+)ee-eL1uu=1BEvz>B905$UOn#3=E*O3u1#X%zdym zaYcFgdinYa3WUxNGPf`$`X0d^kSCGW#KF!Fg0DZ*uYs^5MSLiuG z;UK%PpA*E)!Vcof;?Ol_yFucxHD+@_ zr}eVl>jhQ3JD4gd6fzFYHtuX_K7<7#p=spKl=o&Ln zf0h-x#w-qGB?)WHKxZ{_K+g%f0}2r68nf>p=azzko&~nX>>BbpL7)>xSYd0-_Jb6| z)|fp3t#*QNI7C3_3B%WzNr05W)|kBkabV{JfqI9mur+22K{Bv4X2(DrtZU4gLE#2l zWA+y0bl4g*(D(s-joBHH3~Y@V_#`CQ8nbyIhr-sFf$oQ9g{?6IA8Z3#V+M)=_!=|N zWdQJVf~J6shMf}x8USF0tuX`L8o~-&V+Lx1p|3Fmoh^myoFH(ZBd;+7)uFI8W{*I2 zVp(H06BO^zHD=nCc@U3fzBg^uQ8hj%7m~rW}s70S<%**ftJs~*O(m!nFCv6 z25P6V!q%997c;`n2@(b=gRLKMBV#=HC=SSBE=Hi!S&$CRK%6H5J?;a1SPAH) z7tqNR@vtK?;)_9NMigh{7nLZ0mog-#AfLlhoC&>76?A9__y`!#i7l{0QP5WfL0keq z>;&!f3HZ4?@MAeja^rJBhfc&pPQ$=BT?TwgOL0jG_;?qHcKD$#(8De;R%$@cbAg>V z0uD;lQ#sd(hoW`2<#j1 zaX_Hi)%3j76b0y!Ch)@#NIpjdlvI)!Krsz74eUlR0k;M0U+^h5s6z3OBZpAWB|=*d z21#$I`d~}0U`H204m$!Lo&xa@+KEAVsTCy*@!(@spobd8m*j#n0n)lN*x5X}NkvFm z1L@Qi=mAKWKEu752Arbw!6bNQ8-4^0Xw?k#%owC~KahisV5c6zj;R5~9^@P#l;dR} zD{w#tfzBraD+1>aSk%J~nJG?9%?6!y13iWal#f7X2PMJIZ_0$9n1izLj><)FPG(Xv zBp?`2PTm5aC<978hy!~NXEK3O4D8?>=&@7DXs7x>kJUjto(t&&FHot(5Dz+HCodm# z)DU>F)qtK{1FJ1TG;G`jRA0iD=77dHK=mq!28n~3ISd211cyGS*bKEbH^?yuT4Mtm zZ3D#?1QTs3kUrR&6wtUH=qwqK7>Es9-vQ!- z)=+@b8OS^k8?+7sgkkF`Kx;xk^Clp*p!OVWJ_oe%0>%dQ5mDAtK$n<-+zUH105lc~ zV}sTT!OX;UmJE131=JkydI~5Tyq*He29N1O+2HjQP&Rly1(Xe5PXT3v=4fDU0I#Qj zii6ivK-u8+6i_yJJq45vUQYpKgU6(yZ1A`y+< z0?G!jr+~7->nWgY&~OUOOz?UNs5p2%1(Xe5PXT3v*Hb{*pt&`eUeJ6Rj18JYgR#Nu zDWK}X>nWgY@Ola;8@!$Z$_B5efU?2sDWGiddI~5Tyq*He2Ct`pvcc;qplr}U1nWgY@Ola; z8@!$Z$_B5efU?2sDWGiddI~5Tyq*He2Ct`pvcc;qpltAZ3Md=Ao&w4Sucv^r!RslY zZ18#tC>y+<0?G!jr+~7->nWgY@Ola;8@!$Z$_B5efU?2sDWGiddI~5Tyq*He2Ct`p zvcc;qplsx`WZr_-O@JC93=9k(kM}K>kFZCkNeW1Tzan z!&)JrNg_}?5u_I+j!PZ5P6a7|V$do0*wzK0&y!COhRjof+=p+T95gR20dfe`e3<({ zbB!QB!NTu`Fav`M8^q6`xCY6A{0o`|gXsYo(ZRt09zg=JK^P{7K2QFE6Z^b2$UPvl zVfOx!gv@J$`~k8LBnP6=&w3HyVqgGmrU%&x!Z3S5YaT#)VCE@E5qH+hJka^vSmw3S z&w5!cfPG#Y{j8Ta0@&xZ(a(BO5yU>P4Vqv?_D6seB0Yna@`B_*;Q|^+hxr{84myGm z|AN>c43j$y%>%G-i9re%P}>k@9;nR-OQRtDF@nUM^=$fZ`QtUR#KPAH1FeG&Bx! zC+G|m(3uj9pi9s|1qsMuh4OX?(o1F-&~Xh=3IUH{;2EnZ0S(0IfyYht zl8TEN^omk*67^D2lSf=N51V}9iGc!Ok8Hf$S%vu4Pz+K7!k{`9?hVL)Ape4r8qB|-`~r(xkUj%u1_sax zWgs>P!^{KG$fd>^W(Ee(+EkE!n0X+xL0JjeyfrKg44`{ZL1uw4$Q%$2YsX}kfSWM{ z*XLOnn;H?@j+p=&07PoXz}Dx1>;+-)xpX|xW9J$f7*=p}tm=_?z`?MV333D-^t?-4 z=f;8Z4s7in=s*`xSc2L{po@zb>zEiAwnIY-q!45w6AL?NwFMIsJLozx#2tU2^Wm5n zIov=i^q5$qKosPBI40;Fe=?veTp)M+nSf*=YxjgeYv;h{!!fb2f)1@>`419--0|lL zTJwi?$DcE3!5-v%xI>_Z81}V$Of2l63j*P5_g;bwh2HV^5yXbA-Kzm{AZz#1K*qt= z?)ih(Q-Ig*F|n|}2AvOAj&#Q#cp(S!+C9+8HZ0s%KubEnclmK}gKu#Hvw67NL56|Z z#H`($hjcz%H)u%_^o~E!kP$2Njz7rxa3EVbxK%-i6+!R#TLxNk0lni7d{hwR@m=hu!gK3eo{vyT<}rcY|~79_W@d*xEgC zh(Xuxf$v0v-th;zFBrCV4}7i@32XQA@SYC`3LN;_y*tR~!?A24w`I*6xAahI&5SYmnQptlbj^ zr3mO9f1snaV0Zk1#>`ovYxnv=u?bzf7Y1@aX?Ohb4bnUQN?DwR@oZW?5lt_ojg240gvKXaJiPwsuboWHH*>Jv-z({y>MIvBK8wf!B+|*6!7U zN@CdBJt0s^gRR|L4stVW?Or&D1H0qT732`u+C9*&eE9irCLkI5-|;6^16sQWnxA6; z)#r?J^gzeJm4i-x16Lr7K{B8QkQE05gDeO$Ml%}7GJ=nNlLKi801JZo4Du-;ul{2K z9U!M53BE88Bn`e^5PY;DgCc0d35O6^gaO~lYomAb;l7)X8+JDz(z$DV&~w)$7#Kiz z^DzoC8iFq-ltsFbPY!X=nmlwYiPcls9(>&%;$}Yhk!p&_N2=kxk`I&yK#c(q{t0T& zF`NeN6C6F;jILMmRb-Zsu_h66tQ_PBGssdrJ@CP1rFogfB`J_Q`{0Wetr?lwz=xMH zfe$8Q*BjXA_==xa5 z@=lc1k?@tV$ZH6}>y=^aBGXe#;Fs^kr|0A+CFaCu<`$F|rGnS*Cg-Q5GJqnNVf557 zqE8(I4V8f^Y!D3_vI6nJ(*g_(;7brdgFK*NWzg^__!ucX(*@ws`<%>@)S|>3=wtxC z8HBW=#N1S;;mWD)?v#y6(`wg{q(#EFHR%o3=LxMmqp0%8Q*&j*TFP^5z}XlxTS zwhm&0T6Cawj-WLcAU+6#;PNDv!#&J}3(Q-leUSV3+FsR5Y*VsnEg$3X^--qQyT zh0(Q@;9y`FU0VqWhtai_kZ>4XTL}q=(Y2M3a6n#L`4VXj)PZR9HJU7kRi}{b`TS^E(4?o6doY{6j26-5F*xSzT#kD*ns3<7!$NI4aNqUH;c&o z_+CgO;tk|}kefg>`Wnq$Tnr4LnJSRkAPln$eT^oM3?kk@i|t_Mq2I^1ori$|bQ=rE zED#2n2g2xUG@l6)w?iM)?5gvk5&(uIgyqnUtoPa$Z{4=h|jYZG8;859oF ziM)?5gUI{%R){b#U|W*{S=$ir3L0}H=IkM3V?(0XHaq~OcPwig%p4iuSLT7z7_PMo zAUW9D1=!kI(AoviHFJ!h6K!Ax2uL9)(3n`*L1~SNiCq;m*U!QVTE@r3$Yuc=%4XyM z?JHtpVs!!WAnQAsIM^pMFfcH&u!2rOVPawT1Ie+lgLW)2F>-)58L@y$I401!DBv@a z80UZ%eX`boval9tnvpSx4P-q?lpQjY!oaZ#w9rh56C_Q_ya@6TJ>)JH=xr&iNSCij zFfgzohW^=+W&}8p^@E1^IawJ%m)n5X=0d6kP-+7O6zV!0Zjh%L-h;eEr;+}=)bgCn zBz^Gy)Xco(oYIt3GRN+)n517^SGO# zNQ#Ss|<3ldgV4<6ulctaCc8D7pzyn}lyHV@~i+~9fVel{{16&Ba zYL?*GDcBEs$qZoCU^78Jqw*SC#41|QR^XD#g4BUsCJRgWAR1J?Kr#UX18j^8l!d`r zWOQ5%7Brx>ub@Tt$b3*M7nu)g@gVa-E9#K>pc7D$`JiA%=7UOWWIm|njLb)lDv*0X zwIs4UXw?BSA8DWnR0K1K!q@78YzB>kfzDxt=>XdX%MM_g0g|Jj3K*f*fqV@bj{*sU z*h68jFKB-eY%e16zF+WKRcK!Z+~$R{L2FK7>T&J$1)YfrQS`E1a>5-7evYhpor z+hA=gQu<9G{ls9<*eWQcg4_vG59*tM3K|d_gkfw@O9I4(we|0?LF!>p-v*=~BnL{T z=zS&7`ecwe$Se>BsRPmIeWe#{kiA_X^FaOusRQW)xd&uENDQP86z?D!hCy;5HhNzP zmpYI*Ob;=*2eI?LRe9+!Eko!O-2S^>redv9q90mpk(B2)886XU^ z3%#%8!4BD<1Tqg)^1#eP-_NGT$iUD9G6;%c=7G~HR18F|U?groTLuSleWeqO3=I4* z%Rp%xWC;W0>|2mqVd80HW3{cP)5AmN8@9{PT^ zJxJk#udj5Og}D7}pmp@b>}NZ|#(;7=3(UXJzEXT@MS-CK5qFoH7#R|MPU{CyRf*JB zl4SrL+zJaJ6>t!nIWl|;;%#JLXi(a)f@y~k=;}`PBwp@CstgPV!9n20#GtUyQI&xK zbm=%`eK_Q5ai~EbKv@#B5+7_H14AT)cIb!D9fuu2=?+(a%o?;#A5@6&DKH3vj$s9x z%EAa*SIh`HcmX`K$iTn=QV5bm^vASN`eU}B4hLlW91|03EQkm1kAW%#CKlHH;BFav zI!KO%9ke))iID?TC@^ubfYK8a3(GQ)5)PI?kV`;^_AzpTt`r5?3$mYa4#-8U6%34= zpoOs@VKz_!%*X@El8~)>>>wFXE8rai0|Q4M1EVy^1Ws)R28KQc1_mz1D3&4yLsbR_ zPS7fSs1Q?8Jp%(bNFm4|9?(D$3j;66G7^@+A$Qe0g(00i=mIcMXAkM(O*ZJ_E^bd@ z&^AGKZbp!5(9{}-2?H}!Ap-*^qEE<$)Fpy}L1hRTi;y~tu5(zRN)Cxi7gAxid zUxER2o;*whlpH~Q0}vmSltBGYqyi374yhPfm|HT$gBDeRZ(M_BH;^7!p9fSvg9?0* z7^sgS0%{~e&-?(bnE(~jph6iW4l0u685kHqY*6Tdk~c^Vs1FFLxKZuR84uc)C-UH-EVRi=a?RFp|U}si=+T^hQ7|3m~{vK$^ z7RCno1-9Q5WCv_tDJWaQ*q{)Hu|e*HnF-o&4>Jd3ChX1+aJqsf1CX0xdcpl(s5q#< z0uu-Kd!gdselL^_T0;+01Mc@i#lihvC>z}Gg|fkY2`C#pI1FWj_LaiS=>qiupyHrr z4on<;zXPbeVPIgG3tHm>WrN16VSV7ONO})~*r32;U|;~iG9&^8}Xn1JH+4oD5u z9Pr34lnqKlAT=NwlvZGDP`-q*LAeIT28B6{jU48nIYpQ_D9mAOkh5TWmqBR*<~C5; zfT{6AavNwbGN^wJau4V%F%TP+PC?Bo5F2D(76StVhz&9Ww4WTr2IVu*epL_~-r2aPp=*r0p?GM5pWUy#}0^ac$R069?Vl2V;ZN z3CO`9i-^Ra@&Q!pz_fw->Y#9gX$Qp-hz)AGg4mFTIs=0N2c)kL5(nuA$$|WYK6U^~ z>!7j+WCjR>)PZR9u>%hdNWTOkg!+ygQnBnHw4+WQNlVHhL_Vxx~8;8F+b zfPnNsgOULhSD^F*G6RG`Wfq7A-2((t2V#RTX!|L$I*|K7;-GtkKx|mJoZ*1XJA(WH zG7BUJ@&_nwA)9xBfq_93NdU$K<$I7Gn0X?c3=AcV3=AOiK(!A@4rCrEO~Ukm+yOdQ z9yA98VuLVD4%Bmju|eV!nHa$LAc5E*43nz>^{tThKzDFK?w|qL3o0^T_V$AE4oD*u zpJu{7X3>FW-U}{BpBrQzD1XDuTZm@fYbFK;(ET+~Y@S=N(XcL3s=$_kaca{4S`h1C14d)PS%eEB3wS zpgUeb=7Q9Ka3m}CGk8Gf34+`T^G5|YWXuBO4^V9mk^}hzv|k+AyhK)re?ex0FiZ|~ zCLu@<%)Az)Z~>JoAUTkEpfG~vA&~yFtPBh^T1gN=b9fDv-O4yd&P zG7nTffX2I!&Ew!;U_j0vAag+a_07yoA$!pwB%!-yEG&$OK7&UFv{@c$%t8jd)EHzd z1e-ZBY-E6MREJzN1G#r*kp`&Y0TKa)4X*J9(C9vF{ufmCgG>d{ApgU}dy(#=0qx&s ztYu!k3^e=zxsT==69WVEKANK--QYd#%q*OFx@1p@-RtCL~ zW)El}1pA(LW)^nPDU9$v?NdQp*P-{(%muMwd)h%)1~5bRw1ak`GsE_@{|4=T1n+5Q zW?=^vNW6ted)m)|WRdr@gQ`sy?go%B^gfy>(5^)=n}@pqwEGXtCT36j42(VPAk!JR z_k&D_-bVu(yQb>E+w}4y%y^jWz4_Hy}qv=52)4myGKkPml&;$p3Pdn&TQ7DH)BopKu z*q-(nkRI55G@#)`R@i+syFkGVyN?F6#g7$sA59ua57s^HWgr>Yo_6qEL9qL1K({f$ z@1p^okOkk<{vG5T*q-*cpm>ArY1aU`0Jf)n5l9BMryUdn*!Q%9Z?}Q%X+HuAJlK6S zc_7nZ_tAi_r9j)$Zj5J7J1C{HK=!nQm>k^SK}K%}weonlvp`P6xu+eZUV{4%$d}MP z?bkti4}#7FQ{e6Zi9_$Bi3Pb3dLPYFP)I`ew1YSL6Sb!uWS0Z?I*|Dn-?1_4+i6XG@#qSSfP8` z>sc5W;CtG^c^S5+oe2~Wu={AffjETswD*Go%#Lv`sG%-$0>pvsY5xY|I52`%`|yak zfH?3y?I1DaJ?$Sry>`|x#`kOt3?il=i(z}(!RH@DF@hqEMMMx(I>Pp}gD-eO+tdDv znSlX*9}W0a64;)0e~|rH_p~#E42A7!p8-lbus!X}AP($48t~mvSogH+fsz#s_q2oj z&cM%djh%skpXDf+{L03_z!Jg4z`$n02fE-SaXDQ=gU=RZt)CHFTu^9MS9)TLFNT>gS2I}#g04N4O0g!=# z70O`+E!bicXXNGvZ2<=j`mpmNDdT_*=X1h_^SOkP)N&)#T7cTM{0!Wn5r1JuWbBIs)4n&&ddr&xRzz3BT$mr8qx6BQY-}CzT-{G%dmq54$D= z>0%7XK4k-jc(l7S&@bu%PZfa)l!=-6oTM~}*||wYNY|*~*f9?_08BvUYSIyx&y4Ps zhfZ>VLM9$^pAP8mCGbr~u=`FBm!c$>mE@%6K_Vw>f6%P*nlFZ!HcyQE$OJB6Bo#Mf_45gJP z=48XJ6N0CS_#y^KfP+%XfS#WV>UV=GZx9U|GXwEqQ^%kt0BAf8M1#aRG$3*#+nE6zMuh`4u+2pgTe;$EMMdiO3?i4K(8l;#UjYHAon20IEW7#VTH(nNM`V? zCWr;W%qXkEKh zDR3YR(+ip(fawLzMSh9-+b}kG9vL*r2|W-4W+uol zATvQ;0na0YCV4=6K0#pxRS&)^3Cae~BSYDsxPzGwo=1j?gXfWcMv}7-zAFjJ2H%wg zWrOcZg0jK;`Jrsks3y!D@LfqzaqwM9P&W9kBq$qvR}z#BI+7cv7kpO|R2+O)5|jwlN5|j}vj?@EHQ!FMG=+2Fg9plr}to-lL3 zcO^l^g+b>NLfPQElAvtxetsw$d{+{b4ZbT0$_C$+1Z9KoN`kUMr?$fE0^gMc6$jsy z1Z9KoN`kV%cO^mDpfOpPUhrK>P;t;vlQ41cT}e=J@LfqzHu$b2C>wlN5|qskT9pW8 zgYQa$vcY#HLD}HDlAvtxT}ewlN5|jHOL1~tYQ7#RK{?d=x=?av2Q zT%dXl#D=QT0I{KZjX-RuxETin1E?+l)hUih;@%)ORDC!S8&qe2)PrbH{Rd-%l)~7c zxpo*ETu*@r&?qpd+=ki^$MVAE0BJW97rGf`WBFSkb6O9fG|iMh(=%E@ z0pxy=d7v-^sRNk@au3LSkQhiGXx$NrhGCE#h>gC!1(!N-n*gK%ib3i?ZiI5-w^e}F z!GPQVlT#6ctiJ)d4>XJnk^{L9eQ(SX1_p+S&@>G)6Xrhjy)i4q7#J!*L*@(&;5~3K z^U(Lkm~t{O?1dQuN|PW%85kJA>)D`e5cP?R0eqw^hz-IpEui&SAhTiqP>_Y}g9rHo zvcQP=btZrR_<6MH%NMR1r{{Y9i1fX?(Ah*K&aY7cdZUy8IP}>$H2lB@aH1l2v zLDoZo%m!hQ+dwpEy$nbX%)BeI5OpB)K;;KW4rCsv4Gqg1AbkeH3=9uJ3@C<~2cn@x z30MZSh7`0o0hF&nW`N8Cg*W=Tl@d_~2GDvyuqGt8L-yK0dNQC}7YMCeF*GtaF##`e zA$)gKhAwE`2Lre)0NoP`E*D^RVFt|@n#>kSLom-&3 zB`Cr0DZqQrptY!=?jmf>&NME_+F{UH4!Nuh42+=ZwI!ew!oa`)+KK}Tc*I>@??Fpu znAkxJYnU0?K#N?N89BT_3u2g9<3JP#>mE>qa6sO!q)77 zZunvW&3Z!D?DRtJp#b$e*;tspK>Od=+d+$bAooy!=J%O>L81&Cpu7&svz#D;nSq&w z{Tvem1ANWSTaY!-H9KEHY}lF|&@vn7nw6L)MwtfdXg_h|R|rpOnVHIu~@eg8(;Zy(jBDka`Jj(EUNI3%Xc9s{w@{KvxHW zxFX!3z=Ev~aswG#&A1;lcP_#ViW~@sLu4gFhDT%zD0E<}gFwR?to4jHSQ!{ZL^we* zu+>5TKt{t>2kisNv@mkAF)%2I#^)9=u(mORZX{I^0k5y%|B*(CVPMAib9| z*ccex`Qmeu7+9}@^m=fEMr&B1tAjvS;=oo1O#uZAbal{VkQ<<@gJyxmkyi(S5{Wp- zKj2#c#KByU^$h$h_gF#eDmjF}H(r2(6TDCYlw6QBfVof&pl-1QNEbiLYgPsZF;FuR zT=Dl+Z_EyV$s8p>ccg9vCih!wUvC<3HK6`YVb82DL0sf(WlWTr4^XAS7a3wF@% zm**g5c8nl4gNP?6%h-cCY$Bk5Vuh^^ngddXvN}kdoq+-DJSGNV14af0(2W<7AQS6B z!46v;1nL#C!d3^p07Wcpb&xd3#27}979IwE7SK{_;cV!Q7odBCMM6Q2Nd~8P29f0; z)v(n;pe8RX?8b{*AVXoRgFuU?S<@Lo`ej6>gA9PJ4g%k016v(54V2ol7(auW!y<3#N1nRZ0=741!M8Ma-=`y1{E1#PqQ=dvw%WC5>#%0%F()K3&@y|FSU5zC`7>h>g9>Or zehwD{gA!oQQ-L1JAUw3nJmQH6_vK^#Od@Uz4+FfgbK zure?(se-}|BCKH!s*9I_oCxwhShG0DVGNp1pest)7(oF55e6;7WYE$AH8!*v)ippS z$%A|gF-Z$_D+-4WqxK?@6WN$Sv5ap6H`?{B(Dho}pp{dji?^^Y-h$m?0$RLih=D;HSpcLFRN^o&Ff0dmZi7G+XrB-x zLllStRoIXfW*`=%^Bx4EK!q1X0;(TOfm)o548b4@q=1nj7%a@dzyP|t6O^498A4$~ zprQ<99U}v7TVZNJ`5n||Vq^#cQJ_v3s_h^vK}}g$&kdvzqzXiXFsRMQ#Bd5UdP&k5 za-$31Qd5gc@{9G0a|=>)OJQfiK^D2iLzjaX=^5!6z@$(P&4W%CQ?}|2a`po56>!HG z7@3*Dhb@3f1|}9pHf9D+CI&_ZCKe`U22LI@i;0n0JN^gs@ffaqjmU}UZb`xSE31o%h^W@fM*tRU|(`-9A7HUhbYnH|iAs06PL zSw6%SgZjJ7r~zBsJ_w3;S6J~6qlG_xp`As%VDV03JZF@{_YcMirN&q!tx1#5-lCgB_Bdn46mz4_dC5o|wxJUzD1d0wO_+^y0I@YnB+| z^Yg%`#KnV51xG1-NgUV+^tFUIR}Ml}zs08|W~VYh*A5~Ud_b1ep_mLA3}uLiEZZ}H z_=U_>h4Jy}sU?t=a&DjnhDG3{SzeS03O>*}FKnv}L02h(oePVZ_~JA;AG~l9q?7!m zg&^~DN{chVOI(UlQ{#)!jz)>cx!N#3z8IV&;=#U&hb|}t#V{n4L1_Y-I6$j%2Y8Jk zamzJ9w{hf_=9Dl%T}$|?9YkSLl$w*8Se(ibkMs5&8m>=-tLt9<)XenGc$)N9KbzKqK?dG9Z#O$URqJl2G#zjeAhd z2(M{DZ6f5t2~zVSRmI@a3es8tRi&^-B)AZUwla~6Td+8m!a2S;4Xri?IRm}53f7HL zgk#o35ce=3H9Ww+WduzQgXRoD#R({1gNAEBY*4uYz1yA4bWnY5j0WF z067PR5ww7X0W>qhz`zJ9uNWZf3t()}8W9*9wAPdnnpi-^8_XQ=S{KlSH3I{9ZkQ3& z>1BYNH^B%h-=Ow_*2IDw50VC*rvzF<0xCX1;-Df6WIjwBWIjk7R78P>20`MWemZE1 z6vPG-i#g4o>9Z~%E5qy}WCGRRF#3=AN9Kxf~8#6j)> ztyclDK}9xbtqI5+P#OiXxuIbQ8iWI>0Tth%v=34Pas!CX4YGuRfguKDJ`W^}L2Pbl zID_&ANH3_k2c3loVuOl%(E1IKIiRosvALmf0XmNaqy|*<_kzr1VqgGO383TmLFz$% z0kL7~L1&tR)Pt%A&>#j#4JZylY?vC597r4#-XJzNG)_TR1AxRqVFF^q`~q4-0TKtr zGlZXh-{$ngve450nyAaT%%Zy+`|G!1~((}LDFfYJa6gVrsB;vE#e zAT}rrK^V4%85Cr&^;96Eg+X-}17tl7j1BSwNH56EAPmzBaw|+P$bBI7pehiy{u#su zrJvFD&kPKs>z_fX5p>=OV(sx@UjNJi+LH}xbArkPB(@F`+X9L0io^~=V#gz~bCB4e z=|0$c-8Lj~(Cj8md;ya9S|m2;fCHEs&<1-L8+4QijQtKtJ?QKem^cS$5D4loQ6#n! z5?ddMZG*%H%^kwb2}2T3Mq-1GW`U`xMG~Kg#NLO*K83^v9i9Ty`wmI`7ZMw^W(lT7 z2(&&2>K8dAwiXgQ3W=SD#I8ePcOkK-A+Z-Bu|Z1!VD>&l60byBJKc)Jo`l4nkHlVs z#6E_^zKq0vfW&@_#QufEmH@3QhWcF^@~8B~fCfyAMHuK}?^4HyOn z2GCIlu=D+#D=OliNwAI zVnfY&jl}+r#AfC~l+PkaY;7dA4H7#HiJgnYE=6LuA+h_A*r2!swHZJ(sEq<+gPaIs zBd<{hH4S0npym{e4QhMA*xg>wd-JQFi^V=rv5r;whI~#xbE`1Un zyrrRRPzu^^nkKKi@E%uY*0LeK-r)@YEe)& zsLh`MWrLO{fR;sp>;kP#6jyDK&vf5 zY|#0Ep!H86HfUugXte=|4QlT{fa(P;gLnpIgWC0Pplne8>l2g>>VJV2GlKMj=3W0m z#X@+A1J6XvqU89aDQh1*k6uOJksX0b_&D6osZS(0Pk6anN~@FgEBu z6&M>7zA!fE%tja+bbcm`4LWxW#y$Y*YeUTkg%L~~6c#Y{6C^dD6O3Tupl~1tgVHi+ ztO}F|Kk^zw+95YfOr;Ypa5hDC~lxM`W}!E3JeS~91#D4 z*4=~b0{It|-(h|NX|>{EUX_y|6{t$l17!8OG!Z10|xB*BH%sdw@;`V@)@G~&*!XgJLT+sJ` zWN1O|Qw6yXRJMcc0=W;gAP(dPP@fy*o<<=ChVMk|0jZDxuj>bC0b`IEAdJ2TWTymV zED5X#$$g-uOkg!hJRq@frjXif|cQ`ByoE{Zb&gOe1M*v3o-*_9w@v) zX%X4H6Ecvo7IgQ)_JHJ-|u9ERAB0OBz-v4c`GGb0;l@Qay|19X-vGZX6!@J0ky(8_LR4t7vQ!_2}8I!}<9 zg&lNO0y7Ic=)?eKMh+uTEFc{ghWnr}@IDGi_Jp_&{KCpSSd z5X=m^BLW`93}Dk??RrpI3A=v)R6fDjpt2Ok2IVnWe^(t;W<#w9w?Uw6&^hxk^`LeQ zjO~o1-V2Ehs;6OUK<#iCJ03|5sO=3C&qWdkg$`_N7~(_1B&b~liWQJvkZMqS2Smd# zNDjmXpML=kLl6%#2LfS1NSHcMI3Tx!aG3`>>jb6;WCBPXXqhmG4Z<)vP@e{r3Sjk` z1PcQLs9g%0^8ks1Fet7-{Ti4akbY1<4%9aSu|XIn2kK+O*dTFGyB0JC4`PEbOb*l^ z0+|i7_Xg;|PzDADkiE!zaKZ5c(g?+%_Auz&5GWT^u7jD`pm+i;h6nRNSIIIkxWX)h z%7M6`J`;$BwKLox`vRf57{KO%g?KH-U&lMoNoA|o59!O6_X0owM+%)|;h3WS-1bu}nQbFhOBpJ4%| zMkdJKNMXd@NYHsB%&@(Ypd-&&UVyePs)OdcSwUN|(9bi^0a*vx8womp0QcTV(0%~; z-bm09AJ`$|Dpj|H9phMnS zG51F91#NKw?}6mt?gZ^g0ke6yL4)AL?~Oc;be=h=DaZ=l8_5WA5_E6mMbP#a=-x>1 z9yRFRNYIc2D|Bz=-$ZlAidDNk-i{TLia}MgZ4$h_C|v49pHfNjjRE=AIsiI zWspg*y^*>gML73Hz6X^Btie4@3=EJEgYJz4o$ta5-5c2gG6A|b@(hSg!rsVm(0&Zo zV$e_wH>e*2+Zze0Ls9oe3WJV|`M_EP-t8;$0TckR9gC(QOChJ0vxs~`a5zLj=gPA} zWOzhog7m<4EP^J!;pdru2L&^1$0Fz$0Qh<4i$Qv@o@Wj|Q5|-kIq2$7R@jb39*}9U z9gE=Ya(#?>tPBh$B5EKR*m>rl;{jM<=b3~0&#bWX%wK}y2X>x0Cf3MKu*K5V-YlV z#|quCs134kFKAP?3^!<81-4@mbUqU+^gQ$FAT`kQ%pZZm7-oIJQz`zi~T?ujnbjM-^$PLgPi{Pzu$U7E6kq0@$8PuZ_ z2XjI73j;q(2`hNV;&*1ywlYv~f_E&=XN4X54AubVLNzR9Wnhp1>EdT;gzZ>7hpHUZ zGlcC|+W=An(hAzOhj0S}Kg$(X=#IsItne*>;O*t0ldi$L;}{sg``cmXncoC8PgoTh z{Xshx!KEMUJaa=(K)`k^f{wap#d@AOs2vE}u?RZDT;vQWz+mT@bAeI?>^yS|5C^tn zu@R&UWyd1&dFJxa9gE=e%)xgzz;-Nx&J=;~Sd0TjENsUjXr~A(+Ii+W&>f4DKsz7B zK=#AVGw%V}58JT_8pwg~SOi5DD{RN&eUKj5dFHMl4s6FFcwZuH$08_ZSYbOBLHCZb z!geg$fzlyt$D%KY1K+U-itI(OZJMARi=YsY+{_M5A`JX2E5L`9M73I)e-ZjX}!%0ZlwR zgHmNQ0|SFBXgi|^NEc&}+-Fdm0bI#4hRA_CDPRuM!~l6v(@ubsfuV{6bZv4B)5HJ; z#%QJz1_j7=MtRU`Owe&KePDU;enfdtcgBm8fnhO3jJfCr1A`*y?jz8gngU}KSO9wT zxfE!;kj)b88&FdRG*!Yl2V^7I`JEu=gNhj?u=6`X&Swl(25Bk+?MVbly#?Rs9K%%1 z0CF0rub={IP_Zus=><*oL2?jCt2l_uzz=RGs(?oP*_VKV0OVM(A_i5^MITIx(VPqn z;vfRLrBD@gOAM1L$V!N?8mL*#%Ek;T??yKOT5(%L4|5k2Wdv>O1MRC5X9eFGD*?GW zRuUuu5|%>V4oBehc2@W)_Mjbq$QuA97#QTB8}dNA{v;R}KEwIn_668Xkek6nv+Ju zv*#flVDOE_pw+N?8K46w<3WRu#d;Z_@vh>Ml$6voy$sOmQ1GB5To~WM^Pp{a?9i=f zf((qzeBkY8%%E*?4A3ojY@khZ+?@Oju=|no!RiIUBqMl>S_PO5-fG7T5rJ%b;{k1$ zLotU5w2u$6DUTVprHvQs@%EsV!HJ+PRiHsu$f@0+y%C6wYx!w8V0rjfCGxherGZ11 zVc<`_hip{ATssXPD2^Y_JJ?E#ic<4R;t|_<2JSR`q~+s~onF|ttl=K>FD^*|ore!j zSbE8b6ZFAL+addn$lt(*Iu#KQ-mMl7NyPC*(2KS~a}(gR&nrP&hK9txwcPv^&`J9x zx$(K6y$7W2NgId_XrNL!9?Omf(l(Ys$}m!AsVF!re{gIh1GR5J%?S_<8|ek{v27#+ zHAFz&2GHm_sA&S~$AFqjATbaIbss>T5D**GYXGSMu|aJekeQ&<^g(P;V+$k)YV?4` zK?I&DFz}35PG(7JQDP1QWc~}^tk@8_TpcB}89sszivooM7-PT;d7vIDNDhQS@(hro9kfq3z8JDq zJiZuKAr%*cuNsLj2JekxKvV;ung-H30&S9Fz}2*Xh+`IF5If1+M+Nc-x%;S~fe#8p z(4H7j7=Z3x2C+e<0BFw;hz%+MK!=im*r2XEXm%FF289=h4cmJJid)c-KB%++b!0nfiP@N7UT}t`Z$ms zu(hI~xm6e&yndDyvS$mFW?_0k{(|WR&6R@GgVG;tuMda~n!_F4>odC72e!r^)YXKs z2lHN^(Yp>nB_;#I=v@bpa2UPo01^(gxa&Xxv~LDf5i>9_sDjwgrXJ|jMA%v;&^d~* zaszp9P&7zAs433Cz)+3E?nh!TL1OO#v7zQ42eF}gPebV zcBH*2-AHV3djLeh+I3KOg4!f7y`T%eVeN`*&^sbP;d2Md1}!~-?Oy@udjS;(wasAr zS3qmNKojerJrJPd(?RtPhz)9wfzCAtu|aJ^(A+tQ4H^Uo(I5;88wu#X3Q(I-4$20t ziBo~HeHa)Rw4iKIThai^2DK%vp={7vIVUI^)TV>&cL9YTY`+UAy}|aofZB1O%Y#8~ z0EH{a&x2{-2FN|cU~Ky*KhI{tAc=J*Z~^s$Kyo1Wq3@sAz|X({I^Q2;76^mP17XmfE)Wgs?|{T*MTy%#5hqIA{)uU# z#O5mahFO7uQnv^6BTv^y(a3hQBvVazP zf>wMp;97$T+Q$f4gQ>s}inP{}8?@hChJ}G40+gB=7#KhbL4nD{$hIAHqyi%cA85rS z6RQ%KVh1e+V`gCm4d*klu!E{nCJxq>Ae9{Kpv|l-EUeDpnL>C91N;HS)D;^X25GLnON9Cl{@b|#61)|??J0@kk?v*%w^#LA7^d=Vsr3-F8gBz zvw3(xhYUd2Sni?VL68Y#5^SxdHb@a{ttBUDybyHv0N5k) z47@iGYb_xm23c##Qw#D)D9BP4o+gk9khPXPpwn_$QPx^=f)1kwVW^S(ETENuLi{YC z>V+3{&mRY5ttHP%P=G-0q2K|HGqIL}&1c|e0i_FGP?HDOJrrPteDUQBtg}E&4jvVd zn`VP{Z}afn0eN>0h>da&1rKQNHS0W(dI=uTI(+y&6iblrp*RonX&EC(8H0#1$XLkL z6D%U2ePFB*4u{Azgba@ec;#L#SdV}RXqXRv4+Usd4{IY>MnYs0$YIT3j*LhX$R4cs zP)q{J!0w?~2C}CMtVc)W2Z+-P<`{^0gE+8zD2hRe0(K9D4~PT1hXT~9WQE;B0UD-b zh228|ifj0)PSC;g@Kv3l8#Y;C_fXsfMHB2E3ebLN_&pS$hAb=EJrw?U?x6sMDfAu+ z5EB|}+d(k}jkO&hHZ<0Dg6?_{fW+D^ka}pWLGGd80iE&8dJvR;6?nFSf&y|61rKN^ zH}oC~o`ax}gxo{H6AcO!qVAyp+2z0k+9k>gxrc(s8l)HV9ts{Ski9oR>H~O!LF}8L z_EHE>0Vo?k0BwSZ-~p{JW_<)I&tiDWK;n-<>QflRKot1m3DB|a;vkPe?x6sQL+_zr zV&u36UeyV{hXN!4zIXzm0n7!7Gw`#Z-$MbaP7(J|fXxR9i9?lx@1X#(5%*Al)Ijf{ z02j@mdnmxUmbX6z#9tvUcI;jm5v9ML0p#Ai$X!lTnZlwueO#t5`Ap*J$i4}GaMK;L(6h=_Q zvWS3cHr7-yhexCWWM~?gBO>x0l;>ghP|z1mm0+91IN7poN-#AQq@$A=3?Nas+~uF^0&3`b40` z;RiVw800_|5MvN1rGiczlLvKG#5oxl6hM;;%AmE9j8ROWCD2Nsg{mf;3=G#Gmra0I zV=92|+W-xfC?b|;f^K(E2JIwaUCam?X#ro(pbWmaX$e?BISCZ*OTlcFI#85DZbVQ8 zxrucd$PVzO3Jj{Cjl@ifuAo(wAcBFP1=Olh1Fb7(QWXaa;af$?$H2g>!obaK$IZ;a zz`(-Kz|GCT0J}f|e47Fr^lAlG(A5g;;*8wfR@~Oyp!J3vyzoVY3=Eu%jGo{Hf?SFW zp2GUv3=G`DNNRZyYAv`K7VWE5g^keKcSzJ)*<_1**- z)OC`whW2{=#Ei^|Iw-~$vOs}>=C2YVT`DsAYjRRk}s1T9lcOU+MXh$nrmB7tf} zA7n0g#ZRbDeqK65e0pk0N@7WBJm}D6Dpxt+N&>uKl_8$^GxbSZZ-hhVi9v(D zAUO~Q$uq#qHKc>&L94xyGcwkb=0O^fmm|X4N#Ir3n0qF0Eo=n2gn@zD=fQ)*5wzY9 zWICuz0$K+MIzt1LQ$gaO+y@#lg^7c5Do7j@AD})thz;tFgV@~Ab%3B84pI*?8?=@H z#s;rxj;{c1*rkq37SU-u|f8L#_K?Akb6M=A`lx?I)H`*U~JHQImiv5 zd3g{Uwl)%U!zM@#s04`wtzBedU;wc}opF$QklR3P*m_8i|3T{&LH-5BH;4@~6NEtn zn;?0R9@shoPzeZIKY+Y;5j1B^?e&MC^%bzSDBw~P6u=A&450O#FmceBGmH&7w*|%q zrE3@)6b>*p_}oOOIpA|ypltBjD^NCQ+z6%~bUrfsjG%3KP`x}zY)K@x91>d#iS3BQ1|3HLGcyuN95np`6Q7JEJ|Bs_ z8i@_s%MVk37)ks*68kn1`#BODv?c_m7c^A_V-M!_hoJL2VeSOo1rK9`CWm0`(X+-u zr2qrN=vm{Ca2P#n91;%HI%_-$X^meRbbTPm2GD^7uyu*`AT`i(vIoQlHMbcU7$!i~ zgX-a#AaSS~(7^;Sy(>WCQ1u&;*oTnV*OA!oL2Rfw3`lDTd63u=NNg1(Ht3)PSh?YY zBo6Wqtlk9GwJuk0d23r>Sa)U4O0W&>J9bpN$8qA zko{MnY*1K%4u}Fx27^wWgstlX)$^cJc0l4F`~N`IgW4ycwHF|9&_t{Nbgdnzts)L( zgX&}@C>zvn(S))=YawB0RD;?urciOvS!}TNd!V&^ptH_E=7ZWVzECxwdOHxx2DM>8 zei$z6^g!(>kbgiJlpa7ds67Z`!`5e&NH8#f&U^-~8v^whL2{rrC;B=)P*{T6`yeww z7^DtFgZc&_Hq5*epz~v)>$5;<03-)84}F~;=(sSDei#PX4Pt}(7O?g&h>uGh`Z~Qm z3=9mQwj4+g2!ree(V)Hwhz)b!1xW@5&-6sOF)++Q+D-^E4}{Uz=~aplw@z=D2yyH5K8X;wPOnCZxOIBJL?G+$ zKw$#HAU}X;^mTe2N)UCRaKX1uuTGS>b$SV63=9*9Sf}?voPnVUAtfjVKJseOVP!F0Fbd*06WX;`MkVe>=JJ1P-tS3RM z;2>-6vazhWO9g3wths}naENQo-E!nLcc3HXn4xR#c7rT{t+{gpaUg5%ASWDxhF@6K zK`R&tA9$S|2M^?YLy%{Ac=mz}1B(;0<__t6Lmtqz zgs?StuR)eV*W7`+vamIGplf|tp=<6gf|dtB*W7`RfrGBOI|On8bj_U}$Q9?w;kkNQr6rpLtb-tALLWmnmg!8 ziu>6Z7~m%1(LGn4jgOHHFw}xBVo-Q8_12& zHFu!V7gp$+y9ppi9Tj0?V9?+>3<^o;nmaR4ppdZU4m1h{TXQD{(u-xy9pofMP}~IY zKu%HwwS7W(K!?1tLf70yg4_UIb5{X!8)<9qo(gi9DL2)7myyiZ>+F2cS#@_oNMl2Cnu)@~d?FFS9 z*qXaUP{hL4+z2B52W`h6w1+I#$@4JLpM@AQ`%@x$8!(xw{BjbN3Ov zIuO)?0JS6-=WKv2x>E+RK;ocflnkIXZL**Whfxi*#*Q&q4%Ep2?NXEnb&X#`&N>9I zuw&q70j-@=1YKFgx|k6(k^o*ir+5Gq_DjG5ingHeTMA|?HGsq+Yv+_f_OLF4teYEM z6Gy9)1tE*z7#Kij3i5$g?s*C`fzA}{Y+{5ifrFnX$iRSdnjreBHzmvy0hN&t69lb{ z10^B`P@9?&vcwHEZ-cbN4b*HCD3ESic^yrz(?bO3D7Dci=oOh@=J>tK*!=R#OLS5r&eT^#3vSkju%YM&(F>TDJo9SDNThK2{LV1pSD+4 zl9QST@hf~~7TDAA#h@eaz}LVt#OHwzmxCc|& zZpxE07|JvAO5#f(#}F~ZgU>uOLY~eC*~u`vL=BV*lXFrN^GXXC;&T%#%2SFN;=yNm zGQ=0Brlv5&$0z5P=9MtS$Co975-UhFn;|}}Aip@i1iZQ;zBCWCBm$&1wWugBp8>Mo z4z#`wv|x>lwQBM4SQeqh=Oz`E$UX-V!v| z2@(f2(+9))FOd5{YqCJ@0fi}u4Jr^ocyxUh1HIGW1qlaN&=nYVjl|{v&2d59DT>4f z4GqG~2aU49*r0JW7~2y`eHapZbbS^i4UDeOf`kLL)@LPy)#aaGfX{&g zw;UN58j#eqK-GZOm~?`~q3L`Yhz&JoJ`#I7hz(V90*QSEiTwbH{RW8*atCbP6R3`a zu|dYc*vRXuKuf1!_k4otQ*7&}KxgZ~#6f3qfYv2}?70eE4+ZkqeJC5WehPH@3P=s8 zO#xa13u1%TPyL0e0ktXEq3f7H>!$>vY|#2C*!gFm^;59(&p_=E*jg&kI3mdIfmrth zvX>YPYCnP6(x9*fsRykm0<}*-Y!C*;3y4Nv-}FR`fdSN}1g*CK=?AF;4ZowWZvw3e z0<}3oW`HnA9f(F>-=rYUzyP|>9%LRUjzH=_=7HP;G9M%c(g$iYfM^&7$${AD>zizi)KL)3xH!?(W4 zScJIsO`!9yL6eK1d=0v57UVuqc!Sa+EU$sw(;~*e06qo<#6e1bu=PzvMfpXzklXVnA8vM5S}c+*qi04jDga{2#O?Dh3qFNT(q%F|vW~24!O8 zumdlKVgoI|DyG6}XODg>km=Q(7cy)LjdQQ#1Ru89Km zX;`6aqCk6rSfS^Tf!Z>poI{p|xbv0g6DU>TUK0g6wvfgA=~6SWDX2kV-sLm(O0nkZ1GofUQt8F+~a zY)w=N$OW)9QRSdS0b3IVzTOhHCJKBa4{S{oD@Yk^O%y1u;cKEmrw78H!=$fdHppb;FiHZk#orE<};B(HP=aAWh^kP{Pl?-wN^c*tq zf<)*!WD7tk1-d4x9pnb+ny6(UanjaAv9W+|mjwkU_~0_|!DFCw3OTq8%msxd-OnKd zFA0LKiTaAXCJJ0?z}7^8jyPn6t%(BN8BfGHWZ<(KVds#EfU*p1O_URe16va{0Tiw{ z*F?D?pF;*(>jPgC^#l}Wur*O#pooR7i2|L@iGB{58T5A9KcL%XLDzi3*F?<**$-P2 zwHs8F!PZ38fDDDLiTVw4Gi*(iKZpZc6Ezj&5ZF0n;6+uiHBsP2r`h1s#^|~xYA0e% z6ljSg+bwX)f;J?O&LInjpF`FUYH~z@lwm!GEE<$jLEQyvokMmHl!1`XA$tcBfSyAJ zUT6$GhYWmR8DuRL<~d}lpu<%$&mlX(!oVgcYEo%B zsOX1Y@R|bVCl)2?0C$U1Vp?jH77N(I5oZ~HMz8? zII|3X76oY113K@<2s+pcw1*YcyAXyr7&JG=2%5Nooz)=*5eLnUGJ+;x7#J8pbH0wYwAFoM__Ewx-U}J)Pe3D1+5eS*#NtD6trIC0d&0_XieQK zC>zu?`T}Kx?EeR4gVxk>K-bZM*3^N_17Xm*B+y(ghz(j(2fIfUw5CoQsvdMEnIV)7 zYQvaA*`RZ@Y@uw>nPjkgL_uv*&}0|LOwgHR!B92ub|9#s2l5Q4?FVIpDA*c8kRM=d zkh@`QkXvDF&^kC68?@dH#s;1L1!IHHE`_dt0^Mf{6R!Z-3l)btgCGTJUxNBFptu7m z2Cb0;ZBhoYK^VHqgaNd+2gHW0ziXiKnPgW6`I%&QsC*`w$^e~7=0fE&$$CgQlMHm% zE+|cbFeuG|X!JFE8;CrU>^>g@!vZ4K?9~%_CfNZZ&m{XnyPVpzQCn^{1X;DOiS5xzUr(%8}n zqLlENWC5T;iHJ3OC~NgdJd;d~%rnVef%aK|*584q`9Wa!3w%v6S4j-3?v9ye+e7p;4wqaBm=qb7QoIVO9ycv>+cpI*56ryRyV-b z-+?NAUeM)Bu=RJ~gSjx*-|Yu2qX4hD4`>!>i3W829r)NP==wX*m6@#2^>@cWE`YAT1Kq9&y9ZPOq!+gS zjuUzP9q3L}RxIo9!0Sd}>+kG9p2WHS4s^pSZ2cWL#Gvc%K>Lee>+iq|N1*HP?t)As z;U3UPr1f{;+a__Zzf)ymU{D}-{hc|;9nkf6yFmd*%KAIdCARSOcb`B}23vmzTE+vt z`jbV38MM{|w*GD<$U+E*M+CeU2kZK~&mcXpGs#wh90pr|w-jU#*7bK=K{BxQcRNA$ zz}DY!gG__1zl#IOz}DXdff5C5{hc<516zNW2+{*ve+ORV23vmzifj1#J0Fm;S&X1I zq>l*bL?`(AI~I^Vu=RJFK+0h2??OQwwDosIq?}0xjy34|J8-O#u>MXQ+pzI1=eN%B{aqT!J<#=c&7gpR zuD=7HR|j2x2fApHm9+JDKL_cVWZ-K!q3iE1Ag{jzmm0A3cSfLqfUUm+A7e)NOtN#J zW&$m{R&K(2tDNp=ntPq6iOsi263t-limnTU2K znI`i3J7JLhuzNuJK&oNu??6Xv!tVhM2N?=me|HU}2e$qWynqn4{;nS65ZL;=b)eJ+ zTYm>Wt!x0+-_1d+zhecRN%jfXnPe(B&LmR@t+ylQOtOQZ7(qUh416#r^h`4FMc2?X z$tHpnLe|lZo=Ij6y_l1N^>M7~lAgkN@97*;XOe;12uuv1YoJH(*wly280)4M7Z@5? z=%(hR(eg|(&@?6Z3@t_m2G9Zuy$sNGD)A+i1*ye)84Sz}48#5K)qv zSDYB{30e*n8tfYH=oIYl6B^OeTWn*`Vv2_93xPA+aAJvEL!Fe<88ikk&~FA+hC<*jh;JC?qy$ zuPH2E>X5`i8;W7#phF&D>_tdw)*-P+*J?rHbR9clo!V|BHnrAjjkNR04uP%-fUfre z-CG1&mjnvw>(I4PptV#Fp={7vD$q?;AT^+MNME7iptV&0p={8aBu?m>CeT_c(DW`y zJ!pNB6jU6vmP!H22Cb!nt*Zj91qazZ9M32FK;`qvbO!nPWLKzsKAFq_olo|K%IA}* zkZ?X3=x8EPegI)u9}a!3lLwLKlilEDU?>3(<$_FOU;vp1!l3ivKr|?Sf@FM%JfEzW z$n(jL5_vuu=sYn{KaJ2@r?W(!Pxge!^T{lUJfBQPl!1Ym^T~R|7#I>k0SU#Rumv%p z=aZ%7lon?Ybv~Jy0d%nw;k8aRpu+~y*E)gD{1aec`2YR?e~|seVlzjECSkUQ2xapO zCN?VuM+OE5SA_-_Ta7HlAWSYppFu_H@!Qo3! z$RTCXHXa6s9nEK1)-qjM!1#cJ;Vf4gmqG{AoE?i!yyB5u;MwfpP!iU{&~)N)gJ-jt z2zMkC50mT%Ct)`A6h04OhcgE}F88=NDGPvDn|Cy?W#Zv|zyfkq8W*nzQ%{S`&FLa6 zGMUq-fR@%YvPKRCG zrPu?T>U;z1vfuUznN79)Ln6;q$EGM&C2!Yy@U^a_|5*rif63q6=Oh!t~pn#vDET;Kq zlCmWGOYZ3}I2Ij_fVg-q(_Us(28JeONnI}X7ko{^Y{;^*A3*lrQBq`J*vP=JNC{-* z0}ci@P~{ELzn4jsfkBrG{~en4j0_C0J2XMVaiBEgz{tQ*4%(LnGK)_Eev!ZqM#w$9 zF!i?F450ZVkV?idP`mXc69WTimKkISXfZa3W@2R92wC3->aH*`v4T$dVq#(kH3kst z+d#{>nK)P%gH&>`gAV&+VPORw9tS;NP7SfXjSsZG47R=vd_f=R{A1|(a>-cMw}Eaw zgRXCT3|f$e^L)Aa$m`ocM}5K8w}BQqz|WVP1hOBpzO5Z(9OQhtRM1ia*!nim^@O}L z7#SE~>)R|qvY6}JKnwFA=g4vJG=f$ffY-F~@Q8pGDS+9;tZxIIHm1UA3Tln<%mOV{ zfUa)?EsubmF9$w%4!XYW707hx`nFG?DSYVqwtf&By1q>kqz1aatpK!`0(!n&4@ex8 z2^ka^1VC$2IT)em%YjcE!?L~&bO$RdY<(N(a2-~h>)U=aF)+Z^w}C?py1wl+$N|vv z<-jLtLD#n(0R)Sx9ePDNPf^K(Zg|2S{ZL4H01?@y+Vc=&0o!ZaKL(2L#IgmS` z>)ZH10fc3JTL~y)=7H>x;4ufW7l1N~41+LeNgI59n=B}uz}B~cFDQkqVq*~j?Pq{4 zcHlJHTF-ccm4QJ-gc&3QTi^BsWHfAj+Xave*7a=XEOFM zF)(A;sEWaIEn>1H~Y8ecO6a>_hL|>;O6HDCEvfeo%lz*S9SLd7XsyZQvzK(DiL? zAiY@Dx0!(Kg|2S{uXTg2Z_5I?0lK~oyp9pNzO4WxPTKl5l|g#GTsJ6@Lf5w`vobL7 zuqra{WMg0u0hb!E^=+VSJn-}7z)Rw=u5Sa)3`nrrGO~kCaRaUBgWtJn1d2h}`nCiR z2e!U#9moMV*SCRIKMJshfiKV$0k6Y^t#1P@hGB)RZ@UPJSbXc-LXg+D*@5hbt#8{2 zvLCj-tp}7CVdu*o1{n%l-(~~iz}C0rf((GIZv!uggspF@1sMQa-v++E6}G<379^7c zK5WiG#0SL51#>(YIPZbNor8ga>nsBU13Lphi#R(2gQP460|Vq@N`4k04$$d@N7+DR z8zTdQq!maKl$jX#SscKU`d~7ioq>TBv@Da&qylstHRx_+#&obk1_lOD3x#n`8YcsT zH0YW-#&l2?1hp(=(h3+D(?Jr9!LkJmjM<>mBth*K**pfu9FX>@3=9miB@B$YAkJn6 z1_n9M>6eUo#taM$po_reK_`WuVqjqKF)}cOb1*OnfK^5_6~p|h3`*Yb!J-hQ z3{s$d32duCVG3(JGR~>yVqnk&xl)l4SfdgDUNO42cy*P-)z|W$<&AnjF2mmAt!K zxe2b5WMyFHKwQ}hy1^C36=z_OgWk`|?J3M8&cGlKSyag=%)p?~*~G{w$OvL8b~Q0F zFiA{wl3-v^f(TD`k^splLwJV53=Ap|CIf>i{5n_6HJoZD5XZ1WtW$^D4&`bL^c#53%?``R9-@4qd>BjU}K`d8bQT0 zw76zsDCUu6U|;~ue?nZP6?CpTCpJJ?)421eLj$;=FlY|PA@EDVgy%$(wIy&PZ>7EX}e zj9@bv!6F<`5p)y4vM@7QL1waobumHJgUqi5yM!4k!i?qyMz9Z=KpsMIKO;y4W-=RC z6B9E7CkMz57EX|V*f@C@7?~mVae(cp2kBvk_`d=y!T}P2nF6tznVA73#lXbE%*G4} zB_^;R898|w7?~k1frJ|q*e_u7KxQzPgG^&q1l!IJW<$aV>^G1KP|PsF-O2-If#L|^ zeh3Ryj1^fO$W5SBzzhl(n3-%KUo(RJ%Luj|96FHjf~f(=C=(|?10yp#)NLShz^-Rz z;uHa=0B#0Qj4?2x+-zNvTM!Sq371ZHS`XNgaLD;$nCFg-E*1CmaUGgRml8ZS7glyd zZW+$cV~B^`%ndrRH6=3zbe}sze12LQ=<;p&8uB!-E-XvQLD!>$=BMI|7?Mki^3&27 z;z63?i%4E%4zVI0bmKbc;8=$E+$8YT?I3qR*6zcF7~+c(^HSpTQY%V8VmYaK&`YJ` zGxL%e;xqG77~+#li;7b7N8AD_#88nM93BH#hK~xX{C9|4B!jf83y{?)cCaW#GGvC zedzG(Z8QpbSVH)F}Y9mO*S#*8-*�DJ*0y49gfq_Aufq?;}26Q=uB9sjpiUZBr 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

  • CAbC(sKx_a@nRS4+7|Mcz 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%0AZN>(EHRf9K`jh z^NGCQhJ}fN0hBjEc7ia>UeMYNkXvElT)~Mrdk2(OKysjP2JM@K=>h2n?K1<#C5R2e zFgZ{e1kwXDZv&C%^ZsXIU;w3ikXaxMGY`E_eFf=UTTnL%WEaSN;Ia&JGTab#p!5Q2 z#(?BN{y^_jKV&7YPrU+MP%ton@-e6!1(}DfPrZVjfdOP6$Za4Db054Zk;n0;#QmM$d&gAxUo1Mo|3IJlL(n!+^x>vDk3g8_vHuJsR~W*=-{ z3}{>v)gXJJ_uPQ?DvsWB177qD-Btn$9Lz2^sJvlh2nJCw z1*rGjfY#VBGJuAo7$Etif^j~G0V;^t8HzwVQV^Huf=Xe~s2Hq^4Pt{761evUWHTte zfUwc9T6qA@*%ZwrH^hulfE=rrjBED^Xs~18H=KZS2W)c*sG0$_ zRzWnVIsrAaK)DiB4S{kKDAR%DL2M8P=>@47rakrHe||2gItN7}C^BJvb!ei6AThVJ`-^+Q1WLtuR* zP&E!?gPT5};vITd1FU}wvIE8jt!IU?L2iPXi9A;gGIR6}98jzv&TIw64J@2N@eX5y zGB=D33O5*=n7%r$IeuJyb$Z;&YS?1N}#ic zkow!8wj?ZVfX?Uu^^HLx0zM0e3A8qcfdPCL4if{oK?6Ex1EdC&-a%WIL2OXE1I=H8 z*r4{fI&{t(l=eaAV}Qg#X99ti-GbPld;zipW-qAS3u6=0_eS1l0Wyae46+kcSVMyY zd=@PzKg0Bb;vK{Wxf#TU^;*Aors8!$ErtK>A@Aq!z?R?}y`3hu#kd zoiBuK&jb40wgr)A(Sr5_5OYrs=w4mW3>>JR1}b7;{zaeLu3%(f0L{aK{0PD@|Dw-r zD>E@LfEHMT)POKd9eO|f0w)6lXx%-?UQmM=W-ln6!}Ngk?*p=H?C@)6ABb`ek2*w*sI2y_&z(~*B|Yzz!$iVOw@B@M-b1;z>tU^148 z{m~imN7o!m9LuJ2S+ZJ+TB=$?&VFSB@q&(WsHZSng3gysVF4S(p2B1VI!_iDsbmN5 z?uVR33NaItgq{6~IPVjp9zr7Zte7G8B9oAFOkr+=m;fSSW`f)RQ4cvW6s8g+jv)f+ zxq%M$g4BtK6F@N&EnJ&*!i2qso>xS#XIPnEl?bS+CwllD1Jd~P#OWP z6$G(C=>n9lKx|N&0?C2cATf{}j15{B1Y(2I0tkcHptJzOAT}s1fG~&+N(&$iVuR8G zsC@()j0E`u)Rq9P;{=%x+A9iTgX%TV*-s!gs2v0H1c(iCPZemdJtJiAAE;df5(l;K zL3KWe4N8-sEmt5mC>?`#c!AiUFaV8wg4iH`faak|1yg@||h^@`QzyO|;Vq^dx76V#O3layl^Ugut397$9cY=V#LF%AT}tjKts+THmE%dTB-$NgW?2qP9BI2>cfE7 z$}%!AfZ`LpR+f>00kr=abgmOf4Jh6mKz#*91_n?(gI0He#6fLH&~0!aHfXLg2&x7Y z|Ddy+K;oc%=Abp0AT}sHfXWHjydfyPjh?j!IY$hZM?m?67z}HtfWi}`9+dV#c?ZM> zVNkvT(dhl899GEMPtdpqC?A5p!fjQHr zA+hJlLr$NE97hjf7nc+<=q2ap=7OS554iyiNo+_YEPsN82=5z&q+F0%5GK5i4^}II zRD;GQ!TAls0c9=*Q0W2ZGGOi_1eG+%@;nR-@VJJYuY%HsfEouXqZpxV@VGjZ4a#G% z^=?5)`0JS|pY!HUY zf!eV!Hb@*)r-87=0htZ6_XZ23zW}lqlf30$07Oj~gQ>fItR<(l^Is3SL-sV9_aqMeYo1ImKKzeqwq!ac%Mi%Gu$E~r^PDS9iUOAwHUykdfaqVza_txE3MLuJ=~6OmA`A>? z86o05w^lIm2rWAGZ-GrB|tEvo2bYc_#*K18Im+eFHDw)_btnZuL4h>pvc4Qy~_i#SM@Qfy^z4*;oZvwGW{>F>O&;W zW{wO{d7iyY5O=HI|Ifp*plLFAF_u{(OrCcy(_7}VjDLAm@BX)7toa1-8IpX>`MpdZ zJ_~>>d3p;;3CR5rJ3uNxX7KQS_#&|M28tSFcR>8H^cs>oKzR?>nlR8g^pG`S1>h4` zK*=6-a51P%hlm@%#XQ*7`UXY@2GE=xL_NYB(0NYS#1AksfKP*l zs7IK8hmnB+)W(H~Bh2}OB92fm!-QSE4fNbLbaN7Lh_|4aqrea#0J*mo)P9#{V_;we zbsCGIlkT9)3qXO#1R7mrx&|tHnOWG~LDQd1?4a8TSXfv=jZtPsHqg8%Gb6_fW(Edk zCRWgF4>JcVXn`v;2RmqbDpp&p!EkSG! z?zLbeqd|J@L2LyE z0Z<;|U}W{kW@2FA-UV{MCx{6-GlJC%#BLC@2ASjoax(*?An3LgR(}wOg^_^+v}duJ z3F;Af2HrW$3=BQ2!8<_4fkP|=#AM)Z1vwxTWGM^xA&@m;`B zGBBucgYHpfJ$j9mfkA`&Bq$_L{9$H2f4!Yu-d^#`D%%_F$|L2h^iDraK2l|bT;LF!WT1%k%)u*BM$P2 zIG76(XW(Z6-QB><$nlaj5b;AT=O1C`b@$82DL0M{0tLOpu4cd5Z~Bgj%sdvo8Y!t0~A^vW!723=G1b zSs563SQQzo*%%l^zf&bsnJEl9BSwPN zmhmLWfXyIfc3?Jxh!7}M*n>H2A^{+d10$#+;1P)cDRX8_1TW*^0Eyj%Igg1!7&J>P zz#7IV&Cb9e0@_x<8p#MQkwrjjZCInAPMQyj*l4f}hsa@2?8Jbz@G$VRfRqcnfNs2C zO<>#yGDi($e=<0|Gl&#}>`!3?MJ$U5=&~Z#R4|7}WFpAWG%!a*&vITj+Iz7J~-nByP7tHZs-~dH7 zsK@}v5jz7v3n&C6LFEQGK0yT{J1F(Evw=uZEg}iZ`LGng!~qii2v(xV&cML5hnaza ztqN4RG96`OU|^dK3RR|sObiTcJ3tAWX&Xqv&IzC!20>R9vF!p~O2u@Xk%572H>hvP z1nR)D-2_$1OrUc?*zSQ$-~~;=*sx34b22b+gW`)_MjzB0=H_5wU|^S(gR**D^6Muq#+`Ffed&*RU}#uq(Q9Ffj0NcY@eTAanS* z-9YM4K6X2F5;6Mh8jAfX=01>;vU?&}@|q=*UvWK9EAtjTC!tXQy#6FfdP?P%l@InZm$07Zg(#pv6O=9{fvw1_oI!(5V|yOhpU~3ZPlQ zfBXy#c3`m>kTyleXr^KYMMj7MP@+{9U|`4uD~M(0YG71kjA5G?z*fqjh@w;pw2BF2 zmLenA98kgo1(R|GGXn!h1BeM~Ux3=&jB`GLRw;o)j0;>PhcPiQsDgux3!L{DgVoYf z7#R7$`G{#^fD-7K8BjDRGR89+C^E)@h*%I2!!$7f#T^XF%^(YFL7@U`{4>r80bS7z zwonvoVL9AFQK*GVpffTttuRz%i~-q$6etYJ-#|7rg1iK(-XLDO0=GdHY{Lw=4YE)h z)Is+MFv^1c#25nhpc0q^@?aV0{yk1m%s@QIRKlRhh|7nsL6?Hof$WEMR~YAngATg| z`%nXHKWM=iBuF)&_N#)^l?K>KsQtQN4#RV+h1SP+llFKrF#hAO~$l1PE&>)IoRyB@YxS&7f$9 z^~o6Lc=IwasDJ~-0qmmRa2Gj1U8HmgVGk&tkx~|jixTai76%8oT?y(cfO>a~b2joa zFlc~Nt{2!u8D<6suuptpKG6iVBi#iU7?eKYvBXj9kB|r zB?N4XEi(gyCMy#I1K3ALY-}7e z1A_`Ul}3YIUk~$4JebQgF+dY^*B{tYBPIq0WJ|$?21C!}z=<;zY|lZMwV7Zp$XZvJUqN>PLak*jh9(P;r!j2~1f7Ol0EDQ`B6`%-( zb

    *+=M%%8tf1i76t~*UYOyt(83nsK@ck%RCF_FZD(U(;L?4<&%hu7Y9nf!GBYr6 zP6YWER0>0y2il-(|2SuZ1Z4#n7{G$!Al2d^E(1RcsIt(0z{0@5IUS@36thT*KthnF zgbwJgG*&idaQ((8$f(LE%+1Uv%?CO(7d%TR#=s1{{fL2q88J`C0%dZ5deaakte~5W z*u)vRxj~mFfezbc=Y_~{gJd`u89jwTqMV8hp2GUv3=CYtNNTweYAv`K7Wnkt2neHhJQp68Z1TtFytc(>T1F}I7$t+d|1|d-fbx8&WVXz{Q<5)q8 zM4*aTA!dm}jfQf?L>bj3A?_82+|eWfIb2v0BmvSdrN;;f8IU?qa5=!v7?x&*yOK$q zfk6i8L>qAi23ZrNK#@Z|-bNlF$0WhPpa8pE3S^%m()ChGFbM_*Wju!+t3VyX>M0Cz zh$_?}Ag%-hgBsLsC|4axu>=Ey29jcN1_sT}CPoH9Mnho+1}%gm?Il5%SZSj=!3KQL zvW^~uy(Bn*SU~{z&JZN$hal?=fuE2J@;PLZJrqR2j1EOn02-@f zWC#OMAYXxu4g>oSw4{oWAq+&pbcSKk84lCQ#4s@cWCG|eHAaST5Czf)5(YU0gh6da z&}a(uOly!%MurHGCXg+R3=tp-Jk`e#2BJVKn;03wK@@1BhLIr>bPgP70RSUIBq$(2 zEf;2na>n@}2IwqsMutcb1=@na%uvZVAH)EKH_`z~AUi;D!^jYZh?FoyG=P?3fgB6I z#~E^mLKJAw2jmJy2GD{mu&fRv0|RK)6(d6shyri>1??n-2N9^X2wGaj$PfggK&xgz zfr~gU3e?!E0JZ-afIEHo#l*lM4H_dwaU`hvH)8_rUJC+I)>svo zfE5ITD3}670teOPkzfTuASw>S1dxJou!3L^1yg`90aPP{T9AwkK_IFL!vv55&_ER< zLokSfDL|M2s!BoKRz`*(5Cs~^Mhyqh;zY>A9%u>=oB|j?svs-|1_2h(Y2)`nL5aRl z1otwD;*ylie5xFfMdc+XC5c7px|w;&Ii)G7`o)#S4CI-gms*~anWUeSnUt(g6VpKJ z4!~2R82giR@{_Y6yOZNVD^H5`GC-#(gV&`%m`I|4A7ZDFtw}< z49OtH5K;JfV^bIznIY@^%Q!*n=V5F%21aIXPEdYeVqs)sW&oY6&c+Ph{R}0Up}V44 z85o%%E9&dO`vo8?@EJKpp*Q-~g3M)LVqpTA!py+P#>@&jpq-f?WF&JPNR}C*2Vy!4 z_y#~`PBE~#Ak!JadkG+FIKZ-LU{VyUmltd+2k5vo<~lG5aSb!42m>QC8z(o|9MD1V z%$)oTjLeX|4UpXkwP3vvlNrJOf!s$}1va0V6Qm35erAYzhzmWywkUwr$bsDe(FNOM z0J4Q0tQVq-5$qCnuzE~2FcBdJMrIDMYmr6R!6LZL5eEAa|FfcGO#-|kL$7dwwrR1bC#K)&+ro@*p#Dg|sGvwuD=4Ho&)^CBg zw8s}E=B1ceFy!W^q{f#p5GXM8bF-mozPKblCAEwpKCvXVBD2JRp&+p&gCV{=xu_&R zHwknbVM!{8TMXtGLj}MqufPP#`nBSc_#{xKDQ1YzNlF8|GCnt{s3gBU8LBb9JQ>;C z_>$cC;?!gYQ0`%f&&|#+2DvJ}2GAvX;e$7eE zgLySA58{rrykZ7;#HHsk#HXj0fV>H^H$NE^g&-SKi;5WHoifuwE{so4%*{=V2YEX^ zF_$486hj~f6s0DnFvJ(77MJFf#Ah=ULp@>$XBjcX$Cu=y21Gn)umL5S;^WJcGm^mm z%r7lrh)*spDoV{OiBC=}Nlni$s$_^yE-L}`x#2NV42u#}bBatX81mE7Ku$|ZEJ*}8 zqck&xAwDlNKdG3Z6r5PGEh#KbOUtYPTLAK6Vop3bSQCqrOEPm)AskSOh%bV9mI3T! zhVsn35|Cw}2m!4YgN0&ZdNIi7>8T|};3bWq5H83}i7#SE$VhEO|kKAo<6P&pafcySOO{z z;^T`^gc!iZMSNarMF|7M&mgCO!ylv#DHUhtB{Rfl=A|H#Nlt!pBDge4&Ph$oD=lD% z&rPf-PbmgPR%#xocuGx8VTg}U&MyV=;>!|2*)P60H8qHnwwgbo|>0j$q=7gnp46M9}h`h5HG}o7G36N z$LAy#mw-G1Dg+tg)AB%dZZRa1;Ff2`;YUbIeQ#iO7p7mylI=N_g8#Dbd4`RdAgSzryaSa9rP}dhUO98SE)bE9fgL=Fm z_khGf-CdYCsG|#059;N@#6kUA&>|?1dQj&UCJyS>!o)#+T9`PfHw!Z#)Rl#agF3OG z5onM(pdKtt9MpG(iA#edLGv6M3=E(yD@+{J9fhd}^)o?X15yg=WWvNjy+@chsOtz5 z2Xz`@=D_-bpztTSnR3`&bBwaC6mz{g^2%AzdUH@>0|g=kGc&Nk?+FGaGbYf|3WyY# z9E$fIgNh=smHZ9sg`S+6iBfYv92&L@RsACNp~+8&l| zKzz_XO;~mT@j(;buxtY2gVx}{vImF{ZK&uagR5&$iwxAr09EnOY6j8l12@4ztqNG{ z0$THegb=MclvWn3UW6!tbVR_-FG%w!z6eoigY1E{CZJ})q>2$O3Yc*qA+S>+cNoF$ zqXsQ51PzUY!V45ujG(#(dL9h;e16#ZLr`(h&=L4-*yAoD@t2V!$WGYP0j2dM!C7pOP|u|eSh@&kws zs)9jxDTCOcsu^^r4~Pval0kj|u|ZWZXh9l?4XSoQdy_$Sfx-;L1~1}cU|;~9@dHu= z@-HaOgV>;|9Hbw_2899W&T0@FRPF8pg&{9wPa%lS4XRh6dyPSAKvm>PkQyci22gc; z3B=}woH+|(!|VmEW&o)NsR4x@hz)WBXn84!4XUz1dxSx3P#9W+!WL8yF)%QMBe9E- z*prahprtw>y`VIC9!VTDAPEWwP#OfWxuI$AJ(8OLAT}=~ZGzY^HK0WxFf-+u7#Kk2 zfYKd^4O62J5{J6e9>fOCUo$W;fY>lKK_GFc8qk79kU5|<4r0U9lp(1B?ZE)40i}Hq z8>VJDk{Xadg+Xg9q2(or4N5;C4BLAo0h)(_+6(eO?3^c1Sqx)?(iuoE$UPto(+jd2 zc9s&T*$Gk)DvvFpXFh@0pgk=hy`VV)5Qgam?FonJ1*Kt-UQpQ$Dzjm1P?`qmjbUJ5 z0AZM3(7tY%UeI1{ka|!#4=T@LY|uT&Aibdd#2^gQ3pyhhrnd&_PEefyySoa+2BmqB zUeMkZ5QgamtI8&vJ2D<1C<*v_5zTZYzz#bvLA$DdO>*xrWbUH2uMAst^utb zgt0;A*n;c@EwlzO-1*!`{>pwwyL2S?+SRlQivJiw}dO>*}rWbS{7Dzp)-UMx2g|R_*6@&DG z_WFY`Os@rKasis2ZJ_po>R3l4HmJD{+e-&3XJPlTgZ3}M*q|Z|#s-zWF!z9p29O&- zc?*<~X&c4{ zr)Q`+;3+>S8=O|5Z16QCP&TNnhv@~~Q3GRxt}%wO!DlT))n5da2~ajD&A`-vCJkY1 zc2GD&)qv07g|fkM2W5lWsWA26c!7$8_M*YWLHiS6>@XxVbCKAUNbFW5_GTpZekAs3 zB=&VA_G2VAsBDMX3+fKR*zBMwG^jg4@eC6OmFFKD)+O_)1Xk;ILV z*!D>5U?etZe*sKy50W@&O9@PT1Csb2BsS;E*!oCp8ziPT#3Bz6E2I|{^x*1vI_h_gPs5$>YY^Zu39z_1q z0I{KZBS37Znj{b#DxSszaT}}z_n%M|qL)FhkV($d8p?Y6|*ibcJKy0Y^52%@- zwl^OyBHV;QY^Zug5F4uA2gHVohk@8o@hD!1+dysaRFF7SO#z4vb!Rh(4OQQR#NGsA zL)GsAv7u@XK+OcT&rgHIp=z#y*ibWXgV<2@PmtK0e2B0W2C<=P#Q7lZ1hw0hK;lp{ zbwO;XnYKvm01z9hHxh~60AfS+c7fPXHGNR?LGAgOAaSUgB_KA`{FNX!RD27F4HZ8Q zVnfZjfW-a0>U71s2VvC8)~K=65ANWhN|%gv7vTFAhDZ4 zY^a)E5F4syBGfKW-(e0&9I9qHhz+%C4Tud@zZHpn3&e)1e}%;UkHl6HK*W~^5*yU7 z0Oe~C4O&D6V}ni;fw4j7B*569z6p$t+&2M@LBPbp{dcH4LH!Y!IB2Ocj14-k4aW9_ z_Ax%zoA_h-S_psiOhHfY}uj1B5* z!`QICHpo4oaXFYc=$u;^8~Ofd&^Rkh9JKWZ#zwve>J*Y+Kxf~<)PVZSFgB>~17kl% zQV-hw3=@a-g+Xrni=+nB7lx?;^@U+<&}JhT8+7k8j13wigRx=#T#%W@(0(h3ZH~kS zZO(zI2kk3`u|d0+U~JI&bue~3lHOz_HfT37OiezLIB0JSOdPZy6UGMZfr7F7kko_r zvcSY=B8h{_ZkYHIB=OZq?Da_OZAfg;c4(O1gGk~>k=SRD*cXu4pne}r?`i9g)OAePNh5=zJO&8?;>q#s>9^VeCvKy}3wi z&~_e}8qg*=7`qEe4QLM`OdPZ?2gU~Na)+^3BdG@+@BkAB?c0H|k0Pl#gT%go#0KrY zfvJCnB>onO4eEEp)PQ#9z}W1dUCGe$oDYdDgv17Is)4E3KoZwSVjCl|!DDftd4A{^ zHLR`&jZwqQc>@}^f!g~WbUr7P{TIpx&73lW&L{wFi)LV803Emt+MflQKLO=a5F512 z0hBjkY(=Pg&^(bklnomH)`hY`^CrenHmLptjq`x?f>!K<#_d6D(3}!z%m>5<%_(_9 z)r00=KzpV@;-K@kKWS&2fS9FGw6TkFydg4w}zd4`qYK2)9Dn zpgI<`5gDW&G#3Usl?22FjbR^$ssYXaoQ1MMW7wCW?4t|}3^$={(3mvnE<2E3&^fZ8 zJPu-m=67C0)qwUSe1x*!F)%QIHcx@nfaZVxLd8L2&&4S4P}Goi$G&vAibb*N>DifVuR+7bfIcMW0uBHHmDx9gt9^NaiC4aAoZaB znk!UXpOJyV8_EXN!+}sXs4o@{WqX6pqJ^?Sb#F414eDos$_kK~ptJiy<7pr^sJ<vD2J%_SEc?eYIfXoNwmCsOdP+s{7WrOCv{zKWIJi*EWNdurZIcN+J zq!%>z1v(iA#GVf=7Z{=QyrB9R#s)RVVPy;QoENB_3=>D5&jO#H2Q?2oZVzRH@1}sV zL3tIX7u4>Bv61JPT0mpzQ1zfTEldq4zrom`dSY*0Fe zsp&xypMk^%wFzNrHXw=bL1LdkVuN<*z|=oL5=X8hejtg1jy{5^7XXcuL;VFxuP|{9 zByrI08<@BQlDH2NI|7NFg2XOBVuQ!|p>~1C`Jrs^I6ssP9_NR$L1~p33|Kax(p1UvE}%9MNDgEkXbu~u2c$n&nt?$CBnjdmxewGA2MNQ> zTjI{Zpu+-jA1D|>av<|SYi2;^fyz{n5smT;45vYjJrDGc3)6G*)UdFo5RbL2M9)xer7m z7Y#953=E({%0T%VbY}p_JWzOp(ju~XJvs~wpgX8RW`Qus91smZBQrBMm8dhU%`Ht# zz?a_;J|ok?5p>oZ1NfdR(A_uk3^EMzt*--NaSE~@8H3~m)EO8Q{1_M-0wFG(tl|l3 znj$L$ooTp&$!7EN&1yEMA%`2TWb_cSVB9HaWzr#NDKyQ4p_7S?iJ|F)4YzS8lcmrK zA&_bfB-KiA)k@Pc7&?VOU0tYpAxotdN;1XEH*3gr!%a7Wt2Y9vSAwdS;5P15vNT%Z z#It$%W>p@9Yl7hFgFvovI>yLwx`W%e)5$VuMv%;j2?ip6E*mm1Oo%r$@Z2PG!@*TC zz~z90%K`_N1rJ;V-DfH~Ezj|qX<)f&g1@1GxuS#d0R!U&2F42x7z-NAJRoyqLd#?e zqh-Q^7a16M_+-v+WMGiF?6f?W&5VI(x6Bzw1_qhCkCtbDWME(e4Ft|`;+{FvDUH)} zMbJ(s?pZT~CIpDcocJ@

    xxOc*BNP#ej|j4IK*_Iu<;L5R|zQK2zb>353m_ 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

    a2DVKXFHhf5Tn2W z3^{=lWGZ?jfyAH+QCtK$kr3)4gzfwcpa@|=J6|w4BQ-fY9&{cW_@udb@S%Pn0(9aR z=m;{L+#5%zNmVP`$z zIIl3iI1TLDc-Tpcs0SD(=H$euYiShnO9I+5)TU;i8Yz0o_|8X6%Plcrpxz;g6r78Ql(WF+ zsusbjCh|{9WN>$Owo=eYF3K-1F3Hc&(e-mzKydQXbq)25jPwk2O^tQaP0Z2^%?#3X zQ!jt@8}fl?-Ls08t>y7;u_@W6Kre1<>=&T zYXDkS%)r0^+Gz&r*@0--YD*9wd`=w$0|RJ+6Vw|7(V!JRphY>L5e<+U(8vdf4O(#u z5(f=!z{Ejp&_P}xanR{epw*rrHfSCYrUt}@=>-jfz{EjpP%jju9<-Ypv~m{222C}B zR*Qn{1r3jYRyl*jLAU6E+zt{4?N|n#;sX-*1PMYBBGY7;5t-b@P0}V>S z#6fIWx(x@9UqRvvG(x2eb!QED{1YM$8mWSX4`|8`mQFw?_`vcMXaEtEcR+T5X7E5X z$UUIpQWzUF1`2kA1_J|VAPbZRKysj|Gtfo^kow0+_JVe7!o)$#^5PeQ4u@gVzG zKZVUYSX5Ce)qd{7MrNV1EDzdSjm!t_^*~k+x`haq zV?p{s(`KNY3YzZ#@nskp7?AlWXNiKEe2@dF!7cJ)$T`zsHh7Q`G!_sa&j3AH6xsoS zcUnN|!0k@VelO|)qmbS)X6qDcE~rBSIyN8N&C3KG&0dz43F#C-j{JvrzrZ~yr1oEa zX$eRP2k5v2%v_KrxH2dMe&>1oyanSOkM^N=3Hs}l)nD{TKIOtAVaV7=^khm%n1A{u04H5^<&B4S$i`7Bw zXeI`R45%8AU7&rVAn|S{1_sdTSr8i}4!R&1#0IsTK$CGGHpu+*P`#j5&SNMW)Y1j* zuLh|BwN5~H0)yDn%nS^m^GslD(0LaiHb^gMW(~v!&6$Cw(_m~+YXuaxp!5qmrvfAn zGJiTV#E&5NfLazHH5Q;5KdAT*W(EdO%K{`0O5<;k#6c|!kT@v4gIWq8HfRqJXf6z7 zKIndNP)h+M4odq8pev!77#Kj}pq2ti9Fz}0wGBu;sOJMZLj=YKWe<=VQ2qe1xj~W) z3=E*NJwa+fttgOw5F6B!DTSsnP;UoxHU~%?)H{NmISlF@f#zyK;;R@K7(jakKx|MC z1T=pOVuN}?plt&nHmK(VDyKni0A)!Kn;XPnU|;~9ivdytni&R_#UM7Q=OYeHKcMp~ zK<8P2#6hiL(8_)gTa^)X4<;ncK|KTzA0!UyO@X!zfY_jxH|T6A5F6w+bEuiNj0_A` zP&TL+0XpXsqz05foT1{No(yQ&4@ex;^YMp@gL+?}JH$capfjQ(pyHt31&9w4Ph@0Z zh=YoQdN`nc8z6B|F9>vAD2NR*A9U#~hz;sZfmXnR*r2=!I_Cn!2IWoAITs){sOJVc z=K{nAzcc7(vAU3Gi2U@=XVuSMTTBsX9E$PotHmH}y0?HS>3=E*+4#b9? zMGQLO9;DZTiGjfsq=t!s0hHH3)8rs=P%j8HT@GS{dQBhn9Aqj{L>ftPdssXXrfY`hY;C-MVHq0E* zxp4_CsI2-7 zWrNBz5C-W5)l(og%q~t)83k>wg3hG@sR7l8AT~^m7Lpp!DnF22pz;s2+#JRR?b!tB z1=XJ*Hq34QAiYcs44`r`8p;Nhg`jh0Kzc!CVIP7o5VY+9)XN5y-5@roJOp9T zSy&)>P>}>XqX3jQU}rjkdUr53D1CtRg3R-UrfX|VJs=0}z26VY8ObuvD9*hm@T*BDkbEKhqL3I;M9CUUPj1Aho17n+lRyje{ zgX$5OIHI}9ccI$sXPmIsa2K;34J#CAqvgSI`u)W;%;gUW4~IOxnb7#nnM28=xs zNj+$pF-&|lk~k%VtXO6!;#q8NbCwEb}JHl5)ykp z5_=62dnXe67!vz368ixX`z;dt7ZN)HbPhArU&%=9d?a=?61yFVJq3xq42iuNiMU-4H||8^=qK# zJcH`KO(1co`FlZZ(2za@1H&04_C*jIss?mMG$T~aFOWEt%>g?17|IqyVoQVAP`zd# zHdGDx%x5SYeC9J$O%zBCl%0me&IPfd?gyXw3{_K!Bwhz%L&aM`Y^eG!5F08EKJytW zJ`G8HE{F{kUxdU)KIi!YlK4v`_J1Tc^4ZS%pmUp{W_lp8y_0L(TW(ft=k9D!*ev;?S_I0kNTK8lY-GZRbvqI5bSAf!I(r^O4vakk~ts z*cU)-sNP#3HdOCDsQI9F-6xPZ)D7Q3Y^ZucUIqqO8%zp`Z3tpR)!2a8P%|BPA^rlj z{k%cqP&J_-Hq`uNBz6;s4b|HQ)eCBa_k+ZtdS`;zP`&d&Y^eJ6NbEBpHdOsxB=$=r z_E#h}D<2|WWRTd_NbG1Nb`BDI0up-*68i=c`w0>oly6~eS5Uhj#sdl(zk z?uD_D+r6N1LYO$X{SOTXBWT+mWDjUe52glme-(@kY7fKM-bm^}?O~WWs67m0M95d1xfupBsOSV9;Rj`k~s4D;h_DJFg2i= zZ5SJLrYejLI!6`828~6+*r4_{j1AgZ31frKae}dt&j|;uMu&+bpA*iCbnY}i5*xII z9Ht&LUIb&yA*lh45y8YkZFLwMG)4+zgT{|wY-=RF_DF2dI1x+@==@U{8~OZj&=?U+ z95faLV<#b*13L2*CJx#}4P%40>ciL-Na{g*P+{WTNaCQr156zGEOF3%G%)dnNa|N0 zvDYB6L1Vr!^`I^GFgEDkC>R^m?|`vE<5n>C6(nNzq^$SyzizE&@lN2_u0lK>irluB2O$(@B1DalEU|;~9PYP3md`>v%oHLj?pdG|8 zHK4IG7#noj2aFB6_X@@aomC2BgT@VE>?25SIDy2zfW!ukwZYVb&YFg?LA#(~Y|yzf zFg9o`9mf8JWDe+jQkXa^(z)579nCOtAy7XE8V;cCuP|{HB=w*%dYHIAk~nB*Door7 zNgVlXa9<>G&^A+;`eY<=P#+K`4mx)l#s-bi!PubwAdKCOq_-c54eA@h)PT;KhOt41 z_Q2R{k<^37VL(fRpmUqB`W-X|1yc{2!+?o{`rV*&U%~YYXf+2D=>A0p1{)|F6pT(# zHfYWWG=~CG51I!69iReYgUkjUGy-CS<^>X<>Otc-pu3+y;`*RFQ=sCYdJJ^FJxClh zc2xltw`O2q0Nn`%5(mv$fzmUG4I0M+9UK5+gT_cfn|wiR&^Q+8>|GEWv{MK)77t>B z<`F=1Hy}1>yazNU3}S=knL*>gAa)i50|RIb6vPJAf%~9t0G%ZcO3xs1&|DbkK0y#0 zG#>#ZMVURdzjzb12zK?-{0d&4SNE|fZ0Xowj#J&ug--N0G)rX)o z3=#*;(YZjyL37q#P&N}I0|RL60;C4CX%2RFI%s|bG!_jK2W^f^f~p72YkOp5>%z&~%^M0Uo z4pIY}2U!9Y2bKM+plr~X6X>)FkQ&gu26%3tiGcw$-?0a(1~dATX9znx9W2K*d30c-~MpXkI1=%3cgQ4-U!(&7s6Y*`RqA(AX5n98ljd z8!En=nSr4U$_DiZ8=!2^Jpf%$HYoj0fwDpAcOH}tO1~?hY*6~$1Z9KLFKGMcp>bpa?o7LU8p!{ybyFO3rH`h4+uJG1;hqz zp8Nt;14_UDplo{<1_lo3IpLr=7a=G+h=qYc2FeD_t*AlSphL+Fplr}Qi#e2?&BDL{ zI_U~z7buN8Ld8J`F@WkV*u9g;Y*2R*R>vXFxq$jvFmdGh6wrJ*OdLF?0PTN)=Ez~< z$nzkeIs+ySsvBTz(D}qLHmFYoV}s`lpk}TB%?m);pt~htYC!8NU~KRix==MYkko_k zqlAisHrB$_|3Oj%y2}A34mvpk#s=NZ0AqvhV1ThfcNoFgE}*e}sQIA#6=33^dlX>o z3?wz6egsUs0ZANmZ!AoF29h{v9vLPMnm>lIL3a$n*r0obU~EvEAI1ii`!F_WEeMPa zD&Jvj&|EW&4Z2GJ#s;?tvr@T9*P72ij?n!~ML1iM04LXw&#s-yrFgB>{gRw#79gGbs<6vx1y$oZ6>S7ohRR6-*;JFW| ze?fPYz{EjEy203>yGUSc(ETGYHt5a~7#lSI3uA-s7J;!rt7u_t&>bQ$Ht60E7#mc# z!q}kt6vhVCp)fY+P7oLybPouO4Z8aS#(o2uD}nk2RPGUjLF;lrtAas&1dw{r95SeV z3}S;YX#5I9gO)CU*r2&&5Pypi0|ThM0EvV2gXBQvEBg8NptU=oFaYTRVURiy4eAqs z*f8@R7&9<{?x_Ts2U<-Fk^`9sau3LSkQhiGsJ;f#Fbt9du|adepuPwpb?E2YgUkcj z1u_GKLFR!l=oA1D4H5%k8CC`c&{!CV4Z<)zpmnPtHq0L()(i}wau?(ekb6LKAb+HS z%3_d4Cyy6j}{L%2`OAd4` z8Ut7iYUi0KMFs|tWnkS8A7IKg zL59OPT5vTB7A;WHl0e8UShPT66bnVJM}+KhE0qN z450atQ;ZA@ptbLybIiXnGBAMdSObkyfz}>^<|O)<7#L>K310=BL&(6ufa_d*(EXs0 z^XwHEW^+OI8i3BT2i=jzxEwU#39Ugu3PI&A6C)dF9UK!Q2WXik6BFw+76t|;CU#JV ziJ65Jv;m%pg&lNl9TNvDsMpKH!QKUG7=UI+nXiHR=&YblxCN8sRM2Tx32Y1uOwu4G z16vSii=qsO&B6xi>@mrL*c@yLplzyhAT|#hsM27P2eAd%K$p}pDS+4_Y)?VXPz13h z*g!{eGbw@CGHjql(@e@BwgMaIA~+@$5L<-}G~vgj3W_=nwtA3WH4s~q4K&Ejqz+I^gKfY|zMpbOlXbU|zb zwof2)^gwJwHqc@wCVddwh^-&wF9Q(UnC%0IZ3tqUuyKIY8-duS4D8@DdzlzHz^&i~ zpab|-Koube=!QKO7B$dO^_-xQdj`%}P~U;Rn-%n2G3%n3SKT7VNY z#v{mS0UE{ObYNp(5atBkJ}1Hn8b=c41dSkxaXPawFo<({vM?}6aDooOmE;873Mj=1 z8W)o01dRyEa2B#KFvxO(PHdLr1kKsXbAnFGRNw^77btRqW(SlwLE|^doS@aLDx9Fc zjw@1*LPI*9a#d@BBf#DCU zmIMm}125?O307?olYtF%&m*f2h;6_I8q;Id)nH*@NMQ2;9Yd`LV%M;N#tB&ULAR&Q zV5-oXilEh z8pQs=zz3p0&g2J;LU2R)AZLL2Y!JQ&3j+g~&&a?EI(MCiO%1fhnhlh{+0;QMK=L=6 z28a#G-)x#7HU|SMXa?GbT@5r?3(oB9Pz|8W&JNW8%IxeA4dBeqt_9M}1J3O1+90+7 zIJ2|sfY>77%+9V0VoQKCJG&l;Ed$Q%?BI}A0B3e~a7e3wGdnvtq&2{qo!tne9+KJF z!69t`&g|?aAaN6LW@iV7v;_mJ9V-Ka0EZgrMoTu(a0Lg{1E3O<1L}b$Rt5$Rs0Rud z85lSq9$*jvjdieCGJ?t_ka|!_%Q(l6lYv1H6zGiGK<8P5B!s}HNbdxx16_wAlw8cf z2<9<>2HlGp7p2+B;LD+6Reog-Ox1_s%J;yeb%Hn0R}vOxyaBV=Z0U=Y6u8p7%WJ5P$0fk6ti z)dcJU&{!VG1y3O^U@B$+SzpA+AOV^k0r}u3SSE_8n1MkGG#di)0fQ81e*X|B1A{c^ zj)%)&SAvx=NP$Ki--3Jzng#+f7$iUgGygal7(Cd)zF{?LIkc)w# z6s8kqEGXRSd>8ybQL=%xYYy7E#M{()DY0+!kki|ybH1tNk$QL6(PI( zSx!*J1S)>zKpBry1{71EBn#FLCKwd6K#dIZA7G`RBdg^&KrI_PwM~wkwDlabsGw6(FZcky5F?@`Sp28sG`4t&Fg+Xgp1>gq>gU=R5Iqp~x^?YL? z6S!GS;tUMJh~tczBp4V(khtOu45H98ow-39BE=8~FN;H!fzE*zXJC+k9O?`??O77( zv}Y;AiOkY4H4F?g+>D{(Aot5c-2yd64(tWoNPs9%kCK_8h;u%O0ota? z$PfggK(!r21BeBlXJZHgQJ^j*L;}PD^=TLxflE{LC(k!1foFQLx=>31-iJ3ks$~~f%>ly2@nf(>o+4q5QqYGWFZnD z7HDdhks$~~fqJ(P2@ng^?q*~N0#TqYFGK>w0xh&)WC#LLpnfn!0>lFC;AUh90#TqA z5JUo+fWX57pyb2GzziBWoDX7yx(JL6K_CjWvWJhwKxvPS0n~zEfTu&4(V*l98i9cEVQCO4)gh%bq?Cn}mKYg=V5x_ZAqbXU7#V_K zDTI+B2($_Z6yuDD*hY$9q!?vn2!h2SQmi4x6H?3|#RXF6Gcp8$f*!OM3+5{j8x-o$ z5C;uMfQ}_+VqjPdn&D&!0#TqvCE(x#F+i)a7#V^<)GAQt5)|AZ#z`gy2AHWJHYoBK z5hp+!GcYiKf|HRU1k|O6*cl9(QUz&dWC#IKAbpGs!5|8v9TchHxCd=d1&s1& zK{UilxYs}pQSeqbhA0pPx;dVip}G!!G&ZPh2pQ%FHQ2!xF@Qn`!eU?m-T4Nx2^N4b zagb}UiNjn5a|%p7sMF8H0N#km_?wTHfsqlks2Viez=$~TPETJC<;=UB{N%)(R0jQw z{M=Oi%(BEheb8ZwMJ4&g`o*~gskx;v)p@DqIhjfE72uQHbdB_k^bBB9;KTDW^OAE) zQ&Ji93ySiy^r6a9iwg`5EOb+I(savAEcJ6Tll0S*lQCuWP4q1EO!Z-AFy!UL=OpH( zXXd5lLk^XOI8!f!feCzObV_O(Ga9YUO#E?^o z8KI}`axgG5*MXHn#F;>+?lLg3FoI6kWrCcp3pukGbVe`a9A3yt(u|zk;In%{=NB`B zkG*9CAG6E^KIIoeLTrSbeas9#_m_HrQ zHyd&&FGM}ar4aQH(-=W#{W3Fy59@`vmj!gzG&A@NVP=?nkxf8mgH9-hm`1$q%;1xs znV~)cxe9!yH8VRnj3I1DNJH2#w}Ik;5p>`)GZWMV9&qS_LYhM5I%H^jxDc!8Yr4RJj`*v}v8KmpFo1UkZ*`2_=*f`kSW`21$bDauM9H*kWA zW5&Gv)QW;4hUC(sqSUxx zCQ9>)Gt=`@QxrgBzTgvr;3sOrvJB|7B2Y0=oRgZz04g9DlH);l8s#L%gYsN_2t#5{ zNqkCXdS*#6lF1+gp=N^)G-3d|+W!6(uIa z3{1?8FUW-$3o=~ThDIROB^iiAWkGI*SWui=5T8^TUtExwoC;DEpOTuKnVXmsUyu({ zR9sR73Rg%X2muEH+)~UKN=Yn91^XS6U`jIbON$fpQi|h?QwzX>=^PRn;2Q7j@8TNl z8WQj4=<5n{IKBx{2x@czQiOprR7qt)Duat-WV|7mGy;>xVA2Fknu19)Flo*Z z07+YDIRaX1z;Z+~DCST-8szBW8R6{V7{n0i8tfVo5X4ZPl32;$=o1p};_2=g63mcS zP*TK@n-ZU2l#*J6T-h;HrWS(>h|H4ITn0!&2jw$x#sOy-BQR+UCQT4&4V=AP;vo?M zQf&@aVF4yBK`Av4RIDK9DzMskN8bQn21p73CB?j)c(B!|o(AV}XrTJ}gS`ZD8zc*c zc=(3~y9R*EFtC~66porKAw`xMLt<`0E;yAy^F?NQ9yC8?Bo@Ikk^zii$WQ=E)QGGD z%ABz94`C=zP0a=cEXcd2V2_$H#K*&Y0C6t32#j^`WHiRT3)_xQfX#RNhYXtsLTb0d2&V( zG$Wvt07a>ZIXU^s3@Q2Xpp%M0MTw&mBwa#iP?-+mgUWOe4Jy+?v?&8b-V92cGx+&~ zdI|U!Zy+msK;xsJfk;p<0yH=cT6+RwgC-eIr+L2Q`4pg|0n zIEW1s--zU2(0B$+d@qtXXgC8VeiBI>G@1bu2Mu7r%m=Yy;-J;XAa{ZM1scoXgvJwS zb{?i4#D^)2zG>Z>Y4`PE>`hm;^H_)K*3mOuEiGxN#VCq3^m^kQ4Dv&;q zdqBN%C#ZXpK!Q+nKx~kDQ2GIN+hFE^*dTF`QqWWfDBXk9^nfO$p?X1GKbYS^-Flc_ z5F3_O=OL*Fb;V)gpng6~J%|kx2X!%F;vhCCZG+qZ>e0f)L2Qs12*bLmAU}fSK^T;u zVI5fz8zct8;CxMkvulg;!M7mj6{Y4R>e28Z+oHt0^weSoWP5Tl^HLe0c7iGmz2yAd z+|;}h20cjoLl4wJh3cp%(aXs!L2wF+@{!lDf=o%1_lrx#D-zg&%Q-kGz(t-2eJ)j8fc#)s9Z(nLk|Rn3SpjY3!2M^N`lQp4h@ib z5(r7KJj^!`VP*#CA)OE|12cmRgEEv2N~xf;T|qMyP$BSHv!MNr$b8t^O^_IV1hGLF#0RZp0I@+B#7_n>pcupl?Q4W`!S;jJ4kPnHdsUG6 zlVBX^e$n-4{Ih6$(7t+@5Xe5{)}vlBxL=}TWNc{2kX&4u3t|}{t3YaZgWBmCMW9v+ zxMc|KgTR_5;65HmNkJt@Npd2jw*%^#Lb{}=?Iq*}BB~5pOA1vo7uJ}AwzJS=q2o2M zrZz+oxJ3sE0oXojaM}kIanOk#V}Pu) zhKYmsEJ4i&t$u=ugU^P8ii2jdVdCI*^iXlo05?n=yvGSD4oZhGyFiolurqBz=@E9O zEocP|BQy(u&eemROA8u#gq>*%8svnXX$wl5jG#j;7#J8p1E#R^c0ucIU}x!qW(Z+s zf?85AHmIzEvB77tfvN@u1_n@ih3N&Y27s{}KrJlLyg35{19;s#Xo8Y~fdMpd&j@9M z&u)XV!F#cwZ1B2vC>ykA0j3_bOcurl?cas5LFbUd*r54y7#p;g7sdvk0S7e`ye=Ke z2F<3!)PVN#!r0)wUQjil8C%$SzM#2v7#q9?3|hc|Ta-}t6_DSdZ1CPNC>u2E&In2@ zpfh1XYCwyh85kHqtLMO%B{MKEya0(q)w}_*q2Uagl!wLR7mzqK9)Ez?P6EZ zXnYfv20*O@5kUs<$>JcRL9G-}D*=@DK;ob@4qER4VuR8+s7wN}LD2_lHG|k7eW1P6 zAT}tCuV!Fi0I@-79CW50hz&~Ppzr~)LHP;PvIen1=^Zp11F{#?k_NS`LE<3$L3|J! z)PexDra^2_K41r(RVoNM*HRS3hOVOo&9H&Y0nMm^X7E95(CrqWNqi6+G<6S}#|N=N z;_=XPLP7ooo!tNu2Mvsa_#nGL*%{O_0nGf)-< znF9(}kh?)_ka?im2c#a9UqNix8M~mC8%PbPm!b^~H&8wXv0-Q6f~HSEYCvHFvJYeq zD1U?4u(Me~OG`j%Kyd;(M+T$@ls0&?3`0jeh29V z?m_B7YC&w+nWvzA_8>JNf0aSq3@SfBY;I`U1Lbj$UXa-!HaDo-#lXNY8LA#+4~WeT zO~astFCa5P=>l}t3`j4iyaBOcegx%TkQz{&Y=W8tax;hxQv=GgAT^-4Is{b%DxW}X zn3`))aZp(WV#C}3%7Y-ipjIsC3}TQQKxG(+4O0WkYalhC^axtL2vP$o+dyoX8c@p? zqz06JL8}@;YCvHCVsnEs4g&)NXgLf_4QLh%qy|(Lg4o>9JPYa(g2X}PB8UwW2lWU+ z;-E4T#D;$o4;-DTONE}p-g4i%|P>&EK4k}YYY?wHx zM+g!Jm9HQ+OdQlB1c`&nS`Zs14(btt#6j@}V#CBiJwlK;s0;?NVd9`3AxIol9)s90 zaZryCBn~Q@L2Q^fs7DAA2gNyv4HF0T2tneYG8@E(iGzBCAaPLn4PwK@K|Ml{IH)WK zv0>-Wf_j7?aZtGhV#CBiJwlK;sEh}(VQ0>QdW0ZxP<6)7;-L5k ziG%6^5E~{A>Jfs(LFp01<^~n843P8JLFz#H4m9xxQUf|C0>tKq))$~zN{~3H-T<*- z;-LMpFukCeOAs5>!}J7|U4oFh1;mEg6$TXt)iWSAENz39#DVmJdVqN#HP8!@LHlVz z_JZ;Uhz%<%K<9&i)Pvj%I?n*422@9Z*s!t!)LR9KgX${~8x}91^FBc0pt=jhhLvNW znNpBAs2&5cVdWTTN*81os87#rNi19f2;7#KkH zA50un|H0UxYz$+Aq6fwX)qgNHsQ!boLG>Su4XX2CY*0N1V}t587#mc!!`PrY1I7l` z4KOyS4uG*iWj%}yD&JvjP}vP*gUV(;g`A!NfuN3dRQI9~c{yXJBklK7p}8c>~4<)kiQk z^7#Uw`Uoa202)z)+KYVd0BGbArbY%y4QRzCOdNd1F;p*TZy`(^w3rjd2A!b>V}s66 zgRw#DJYj4bB=bRM?!&}EOF&_44wk(Hk1wOZo%9DY6ii~0h!4N9sU59 z4^Z`>@didH8?@yF#s-}a2xEiVZ!k9KoFo`K64bVb>IJR6hKYmE#fFN5?rDIDHzKJA zwGm1XBar=K*7bmM+5BpgSC3 zY|y!TFg9qf1B~qmig&2Le396ZNbFQ3b|DfQwBQP64(JRd7#n765I2fQFSA5*u`O9!!lok~sL>5U6?wB=HC&b_x<3 zbjA|Q9PsUXP`#ktV=(b4Na{fg$zbB3-DWU0=*%P-`v{Wy3rOr2NbE02Y*0ZC(+fKH z2*w8OFoUr}LHpjIZUdin4rPPR9D=E-LQ>O)#GZu22A!n^Qx7^n3&sYWnFV8m_KLyS z=aBT?LSjEdVt+zn|3hMPfi~zs-6@8|RzhNf&a{HrWsM~6j>HZ|VuQ}Bf~g0cQ3YdH zAgO5vv7z;5J1gW|U{KvR2_z16&m0gNROvA=Fsw#mgU+Rbotu0NNgQ+*70fQs`BSj* z$vYr5P%~eE*r3KZ0|Ucb5F0A~9mIy(^#{a;iZg-sBSGECj>P5$?K@;*U;u4W5&?-r z)ysp}P;*p3Y^Yw)ZbewV3_5=b#`Z!|6Afa625%S`7}7y(sNM|zib>fd@08*2Up5F08!2gHVoZvwHQ;`=~ssQ48S8!8SyJ02?j4N05{ zbPhXITo}ZLs+R|`q2dN0HdNdO#DK5_=^Q`!Evw3KIJr68k?ATM~4JJJc>? zBz6!II|qqfi^T3jVuQ*fSo;}NWWd;YKyFL2Yjso7QJ@ zgZk7kyFh(v7&{;7?CfGBb}bSc)K-V72lba>Y*2q0#-4_xeijlNwD}9B2GpL1u|ac# zFgEB8HW(XpUMY+XI-?ZE2K94cY*0TJ#s-~N3S(bKvKQ3;hlzv6sbOqT9~Q<2^k!5cM$#LL#0IUVfvExQNrbUMcfrBfpnc>pb`_Fd(9r}ianSBX7#nmf z0E|5uN&PG&HmLssQ$y;R-3O7(If}#v^<`jYg7!ti*q}39VQf%e2F3=R;R<8FL^20- zpBzm5JCZo)ZXuXBs4oL!^B|oQ4cb`=69?T531dqmsR5mX3=`Kx5(k~z3KIwI)`hV_ zW1cWJsLujp2ZGw$(0T;aXMu@>&P0Z>6OqhMMPh^cEHE{oGm&9z(0Q&fHu4$Ypgs#s z9JC7s#-4~|=2Rp$=xkTm{4cKazCrUT$mfQG&RmA60iCM| zV@D&Y2c1m|6Hh}DM?O!y5J|igi4E#o!SsU8VurEXk<=icGY&e785ZxLyG3E@XCtXc zK64y&o(D_~@|oisk<^3wXfQRPbD3dm(EU{~_DLl5puQVS{0frzT_pBHBsREz2Tg}> zk;FeDu|a)3n3*grh`tHvObeJeKa#i@5*u{hEliCflDH}o8+3LgOpO7OIQYZ_XgdmY zehEyC7m^y#InFR~P=6D~2A$~)V}tHqg|SnR^ny-3fr;lMiGvPafQdIDiFYEgdy&{v zkl3KJDPej+2Q$FftC7@fLSlpZurM{CvlU=$(3u}F_C+N1pu4_c;-DiJVC)x2YCa&b zL1#U~)ci&g2c1Cz6K6;2Z*n8CK_@rB)PT-+hOt$V)PU{`gNcL3W-r*vRck(3}oT95kl`V}s^&U~JHw4vY;R ztAwU8(A|EZ9kU=eW-~G{fY_kb#h`IZ5F50rvm7c8S{ncw!vu+g#)+Gu;vjoKoq|8?LlnNTo7oE6~qSZZv@S&g4m$>AJF};AU5dCebBk@AU0^8e<##@ z(EJbRtap$&XwDzhP5`k%Yd}sz)qv)FE<)L$Lp`oT*`P6I(3v+N^`NyOpu?a*Y|z>e zP&)y{2CWTw4^G@D`(0<@jC>u1FUJYe~ z;<*vZ2F<0nL)oDDbI@HNAag*wh9^VCL2(P3TLp=OHjIPr(*?0X@eEo60b+ypi?4>N z2hE>@+6f?W(01|dP;t=wIp}P7kT__kF=#Fo#0JfugVsZU*r3hgp!>5yY|#AqRj6K2 zdl1w%0EvU<&mTg?L38GydqF_rpz&-_+W^D{&5eJCssU{${|RM-=Ena+*&ubGV{1S( zXgr%6dN%-QGr1s?4I0lDhq6KYib3rGkb2O3xH426GzYE;WrH@wg4zQhHK4g}OQ<+# zOd53l1V|jTh6mIJ0I@;y*xpbzpgHA0C>u1V9S&uK#-~B|M}pLY+IpaSL_loN*)y3? zHJ~}|d?*{VwHE$C2GrJ@3Ka*fKLXYD zAaPJ!&4-GE;tEuzFd{9lg|R_p9ju%Lm31&Ss7!;gL1h|@4Jx}}Y~*=oP?-V~2bCi* zHmJOSv61J6k>`Jr=XsImbCKt5k>_WT=V3wpP?-71^Qy@6r=UJ2ObzmUDDu1~^86<9 zJSOsdCGxx^sBZ`}6M3EybPx?p9MtcFu}9BU2clyPbJanEVGNKvx?yAN zpwsMNYmy;05+*@y8qf-QP&*2w8q|IP)uSLb2t%!50G&?^VuRMBfW$XwF))D6rw1+D z1L+6Jfyx#1^Ta{<2ehspqz8mS>OeH8Edyf1%-f^Oz;J_&fdOP5sQm+y1DOYM56FCw z7)T#8NCL!wVvrn&iGH3qsLudu-+|;n7^V&VJaLdZP@4&)282Q8fiURQ2oMczrZIrd zkq7Of0;vIEn0e^uiBBN4rCsvJqptU(tlW-fdO>45r_@K zFgegYhaf#L^ECV!7(jOnfXoA}4FSo4%mc3pLOSm}U7CR*50?3$ZU>opAIb*R!ytRE zDq=tH9JEddbTT4H4G4=VVL$I2G|mb#7o-M+{gfcP3PEfThRK2Mm;$*K=8p-%3=AN5 zgZu$nuMCm{@j>ltm>!V+FeL^C&|MB7HVDJyK=)LE^uWxU6AV!YG7r?Z0?C2Q1H~aM zkAw8PsWC8s)*^w}APh4PM8onVNIXKFfdO>lDX1I+^_4*8fuc_fLtc}0nNDJB+r`TB&;JGV46vH%}EMm}Lkb&>4 zVqh?HWLV3z7kZeok}#u@Fq49!qkyrXl@jO>W{^DOY~{U7stgReTp&SEIN>_G7c|!a zS{uN?rvP5V53&*zCg3yRK>@+1z_1E*9vVo3frarnX#N@0i3BZD0EvMnLO?VVwtK|8EC*g+E&ETCQx6L^^^ix24Z zI3CcsIV`3ig#w_`g_(sF)DdF=ony(Y4iaGnHI!LW7(weJ*;tspK>a{=(0RJdKA^0~ z4(cl~`+`InI6%kBon~NQ-~L;u zAH-zfi_d0YH2|5+!VS8p9m3||25l~Yuz9#amvBMY0(|im46KHrQGO8yeiqQI1P3=G z14A1l)aeWiyr88)Dy*iU-VZlus)f}YWI6-44aiap5SxV?v~-Hq62#`Ey4{N0%ElVu_d@cT?tk@5L<@(FUU-L5L9IVBlB{kfj`xRJAKuiX1P(ENS1)I;n&jLyr z!k}d$A6SbRLFcWCfX4G!%OJaDL@XH@7+9+rL)jP@SVTa##X&h7BA}&SP!5mC36Ps> z!FmKlKm{FZJ!2j#1A~YN_;kWXu#AKVXb6I}8O)Ip0o_f<+QK-Wm4QJ)G(NY0fwhfs z5jz8eipV37X&sE4*%=r#L_k9-tX*I|IwGKX4Ax#S$3P?kgnsq+o9d-tW7b2jk4%P)=qu(&_vw#W% zUQib@gLQKND+2>xd;tUN7I3KZ#TPNKZUqNAUwkoyRRgIf#ah3%jg3J*7Ee3Eqs zh|R|rpOnVHx^q1f1A_oJXzecRE|7W&ZqU7|tb0MxB*V=G(t8k;suZ|E_rk6X#eN7<9PBK^fsBX!VEzUwmm21M3-(`6hhvr3DPEXF;yC z;fpUVVqiT7vde)RG#ANw@f|Azg9|t4#Awz_pj*w{`Qmeu7+9}@^m=fE)|ay00I3h) z1|2QVdJ{Ao8^R5`x03Y%Xht%EdpRgJAA!o57;eyf4eMi&`V@ghz$x7gc=5ZmMfs+g+UnuwOQ@JYz7fmPz>6GIcy@uAdUkgXeSeo2Iy|0a&xa91D>|(7D|?V2*}(SBX$OU7ElOCg31kWd@}H}tYBwg;Aa6XOX6n%)gqFhoDWL@*T9lT!Q@vq z1_ovh7SQF=%q%RRyTF(^SU^L0Qr4j3RIh+)Tu=oMYAG|hp`QE74^jlORRFAv6?V$3Ad*?2OBF>K)Fl}hgu#lq zt+=gOL1(RsKozlig3pi@g&Gaziit9Uj$8#P6o(wRDgilqRuUuu5|%1 zJ3$IST`NY0U=RgU5DY)$5R{fc{T)VzAP@y=k)oOa>M%eW|Da|*$UFuHkSYj^fdRDm znTY{Zl`s;2dSP)%N={}HnWq;*&T!C8g`ZIfJ431@u_#>^dKRI6ab+=?=0i?Q1RZ*q z3_IBnVj2}rNTl9*jSR5VPGgqP0cHT9KHw% zeZ36OJ+RPD82H>p_?d~qjLeX84Z$ZMGS@@T>jRyr2Vq0b0AvFnq6bk4K2Z?V3t(i7 zPbtoi&q&Nm$w_612c6%=5D&41AwD%XwJ05QfF8{C4DpF2sTG+e1`N25E`vB%AK~Bl z^5mkD{M@AY;*!LYREGHS4~|yiQr?`(i3wT;)_xfQ$S>KX--LeHrSJ> zUW*5vgobkTTzq_aaz+x^G?&K4DrcjC7?ssz(I7*P2CxGd%0UN&l`zDEf)3>0#Pnh# z2Jrb5;0(YJUtW|6N;9Bnt4vKSVu;VpEKUZW+X%`ykSKx$I7kubA`xgJC9^!iSzdw9 zUxlP@hWPxnwD=N+w4D6J5{7utF&;UY#U%{!KK{<$@jY zB0)~B1f8xHA72a(op?7-A6EuYS^;GiP~68CqX=GXrQ~5XJ+YodjK!1r=guKpL0^jr1`fk2HhS zgGO1Qiox>WktDbPGkD|}&ShX`fNqF@3NeFsWkNY%{h&BQ<|DfvWFM&Ah%66U<%7%z zjkF{4#Tj5O0;LYn*-oG_Vweh0GZoa=0ku0pHiP6rJr-nnSmQu1nIRsLA>!lVB?nXx zxm*Y7X9O7t8g&GX<3pVZ3Oy0f;1vS{I3&5DYCuQ7fW$$KS`eEXsvdOq2Y7!w$Ux8< zYgVMate~+e(D@Z0^P$m(JeLn@D#O+rf&2(#gV(-;MpGCV7(nB$u(gAr1~+Wp8Z_qy zQV$9j(AifoHYhbPf;_T+J!p+Mj6EMoFKBcdCcYg>{4f&xJQ5pp1rAL8 zb0l%ldTy9F=pc0%n-{cx8tNWNBsOS$HcSn8PbpLlc#kNQ4c-?DWrO#ELfPQ`pHMb< z&nJ|<0m*#unr5i@2_$jQIwY9A;JenLYQ7?=VFK+fgo^Vcv1O3hpfy7uzCe(3mrfeIH3ZXleo`{u42B_WMEIrhvo-4e!C!TOf(MAhAI=t-;jrgZ9fo&5=f8gKjN^sWC+ocS2&vAh9!% z*kwrUW+e6mB=$Na_HHEh2_*JaB=#dD_BSLp=pGW7I|V>{=b(N8U3~@<*Fq9EM`F7m zu>+CVaY*cJBz6T7yA_H36p8%?iTxRg{R4@OyswXq1F=?H612As-0Wgt0No-6bH4_X zxGsndYNjzTFnEF3Q2&O2*idoMJz}7`15_U+gT$d~azSjU`9&Z$RDCrPy9dOEs$Yb} z2Gv6#GeI<{-i5J2N?~l!It3UTRA<51pwUkl8&rqF*q}NT#s&?4!q}iQxnOKxP(2QH zCun^xOdMRdf(Sh8n8D>URPRmbx>%6=??c(3)*NUb4rnbPX!sVi?h?cXwR1pcpMlt* z78Gb74u}nE3xQ_DKx|N54Z2kk#0G^k=pl0+|OA1L+5?l?Kr;43Yz}(bp>B zQU`ALfHXicXzBpw29OZQUJwmh(*$C}tD1F=CECI>ou2&4yQo{t=4 z%@D{uP)`IT2Qm+Q_6bNM6i?)atiy+LL1UU=Cg?mOkRF(M1#*aR2IVo39LPLyyAf%P z&thH%1~+IM9b^#5eIN`9e-I5SH$dVqg|M&j*$M40fYgAnmN51;KBuAS8>9w=lZ3Ia z@i_*~12BJlk%P47LE!>wzr*|iURw(?2#T|Wv9F~9?F9wtftd$d#0Q!M2AKystrsK* z3Kvj60hTvFMs5;jU;xe0g4iGo3JVwwE#^R6hAAQp450P4pnMH717sd3yg_LZ*}NyB zkh37cnvlW*vc?BG8cM_(A7cvx17g?sRDk+1Sl0NMIWp{JI?K$%%OeF@#{*fy1MU&y zTEhbldyt3t6c|9~-+=rHx_^5a$S|tUdAX!Lk0#ukT!mhnfxFf z46H0569x1@$FTE)g~0@V=OS zunQkK@yx1mq0XvtBXK1d7L+f)dAoB z1ev`756^=M(0DTBh7r_(c<5+2WTFW%9t~0sR|p==C2z8esNr%_Z}tFt2u#482y!pM zNhd^rLRpYuYOqNl1LEV0QqwbwOHzx#(>?`7`Ot|Y6l>z+Q%mCW^FR|r44`QY_(T#& z95nL-31*0asU^?=ModZ!=vXkMM1+ijK?@jAif4e01%t8ysOA9CAPI2eW^~LK6ckWA zlE!>NsQ@&l3o1sT-iM4hL-UVbGOUndz?OHwT43Y2pnf4}j20vaV#CI6L4086J zAbSpi&T$4`gUY~g6v_s*bUX#4}DABI78gV^YOVqEIb z`^2F0Zb5SzATvN1WG{$D?-MI9AAJ_)`)F=)S{F3eG&Gzv0|fq?63uW z1NB2d_JaJ2-X~tl$iRSn{|3xx^gc1@+z?QM8)_ZA&k4#`AhTidwu6&_0o2$B*$c7{ zBnP6=`^2Dq!JxE(ZXSA{_ys3%ed5hb3=F4Wh9QLudY_nw3*kOc9}VU{^geMdGXn!? z2|dh6P`H3FIFBLqodsEm>k|jD64xj00S*yw#?52SFx*C#&2N?f0K2^#|g=qz1Oz6O;wAoqd78wZCEElw1_lmL;#6Q@_<#RDXnG7JOciYA$dD$=7GVrpD$9_j${gVw<#MfsK_=OfspgBD z0z-$fhO_z(4JBr&8Nv)o%FBfKA~=TvcnW|*nmzQw9TScAh$X_=&?k`MzAt5Przh#M5dprPzw=xE8*#=*d#!~~LYmH^8* zF+><^C`U56F)>&uFOy_yXmspk)@1?h!c`#HU@@CUZ5}v=LvF`(lpm}S5lL#WVaOe zRA+z0rzFNU{Sn8aV-XPjHJ_Bi*m;;VrztWpRJLg@Q)FP!+y)|!DKao9g|R8ANiGxR zFl1mbP*QMXWB@Y+l+q-X)Fj!FjL~HS1s!N_REO{+W~m(<9m)(dl}~USI>We3lIg=4 zL0G``Xmtp$`TjUkCy%0rnUOK%j_#Cp(Z6LhDTnIkl6 zk;Fh{7p`$9(D)Mi-Z9WVe9+bzh`0fKPZ=ohg68QV;)uOwpuD{b)YbwOK1h4eKy$L7 zWe(`-?|{yCz@q*G=q>>);voH?Wf346w8t$1G@1i0F<2N4K=Wsyjb?G+K`sUc36LW| zSLuOTX-tBk@|l^D4Rl00Gb0D+BqC-e)~}$AX-w=pm>3vX;9K5;L9I9rR?tNs%pB~X zn<1G%g(veh&~{)}(D@Y1?u@Ps3=C{6OrV`jEZm^8_nD3}Gcd65fR+?6tp{zY5CFAe znORsvLE~2ILE8t^K_X1TYzz#n<{&Ms+d$T*FoMiwXJPdM*~kGp3z*esKLY~;2WU$p zt1n2DfzzCUfdRCAlM6(Ex4wb4VQ_P>x+^glgs1;+6*A(3>p(;VebTOd;=YyBEhCR7i1XdxE?lr5EH!djm-dL zE(=d33j+g$&A|gY0S?0E;rRkG46Fvc@r}(8w5JNR@y!dg-wm|)8?^Ze>~IDKUeHz& z6*g1QG1EMtabGrYP%!Y^1etCDu?e*2lg$#u=HOYx#=yX41!D8?OlD?aV6z6X1$eYU zY#R_;gy$#71-2lz1kZnvxE+Ws!;=QmYY$>8FbK$lDjY^Oj~pfj1|Cpx$mR)Rf(K(6 z*t|gO20>AfNj@MqGcXE*j@)7M2XR;!893`1Acq)$JtEJ*JBOKpp@%JaC&)N(h=qWd z3_PGs;%uQHOIdh82cxis?Pp?O;NWp&VqjnkzXsj-209Lb6LfwG2t$qJX8|9g!p{N< z9A41q7YAE0BQpa74``DVTM3BCzyn&;!&VA5pMjqRlrDrDSr`~TuoW@-vM?}+oCO7B z86!vmg9vEImaUqx3B2(w9pnNCheHH3p9huU0dMwUs|D*35b*>h?Rv)9pv6TZpl!}< zjbIrG5zq!4wq`I#Mg(-|6j8f%WK! zfDW@^>jiTRL_oJLvGsxNF%g*!QZ|9{89M`mg-9VN-X=1Frk!m>K!?t;O#&-(5K#lk zOlADb4%+wziUGEnjG$om0PnA1o5ctUS0543VexEp8QsAf-#{Bq+2(=6;E6~YD0$2W zUGL8DLIiXs0owww(V&fQpd;sal~@=UGT1iPLN~s#Z2^ZmXyY5(R#2F-fHuCdZ38hm zctCrL*tXk&mO}A>wwST)0I?w(-`IA7iZ=ls&>=@`yFltCc$R^Dxfc{oGCZIT2HQbU zs#4$qML65x6`+l8JfOqt*p7mZP1fL935v@Tzd=j2csf8{KPd`o@_{$Lv7G^#583#} zb{6DH$i_Feb0E7Mct8g@uw4W#e{kVR0O`G?&Bnk0+4#nG6{OdL2h>1fy8%)kzyn$+ z#CCH!0|P?{56CpO2Ot+l@MwYD@Ca1O#PEO)+hKbQQlG*g2BJWTL>%NFagayE!Ca6y z13$|`Rt5%UMvf~ipsh=w-~?*`B^M+OU@la{CD6t0fb)ZdcD;XFVKwd{u4iXZF zD!&U-17d@M1fhn3pM?>$fee%}KpqC?Ehb0-YR$&L0Om6=unK^@CCeBL+W5xI#=yYC zrpQFC z8-dyEz-$JQuOMse!5lUbTTtoZ0IoZDM2tZ)&WxaaVFC=Cp!(z%%y~= zsR(GDA6qgwy)%f|f$UFV1Vt>12&kvRmI~(Zi1dR}OB$FXA|eCgq=WU#hy;Q>kO8(^ zMPvsf0|Q$oSeb?hXgG!~3(PSPSq_rP26HS#Ko?oE<$yU3B9)-BB^S)`VBiErHmJw| z#|dcT8z=-MLFEQGJ{kB~u7Y>9fs#Hy3#b;61m%2K3Si~{C9O|jB}(iJ3``4{7#P@h zfRZp1Xel83Y0%+8OkS)E3>+fhIU^P`4h9A(b|%KKAkfygWCq4?kQ=1S85ko#TRs_h zL1lmpqyK&m1_qvIpyfpYpoGo91G<`xF%Tro!XpP-S`~DZgMopAuOPpeff2HwoG&#$ zje#))w6|P!7v`sA0x9$AgoBK^C;ffpHoryMZL+wu6>VO#`_PG-x0Tb_!SUW|L25fEaQfbSEVr$Y*o;L0uJ4Uyz^WGzSBNBIsgdMlEpqhPC_{=S<{c zU{C^EtOc%LKd0G%qW#u&}$1C>w* z9dj{}mw`bQw61a{FQ{Gw>tZgu!N8ynY8Y(*$%0O91L@b~0?RTLF)*lucKCv|f~Jr` zTHPU%5Urpy+Q3>tn}2ukGB9L;WuuwO;f|Wd$iQ%(mw}-kEE5IRrvWBH5Q>3=5VVw1860_HjG)+K4Ax9$V3Y!f3S+PeIB=!GxfFD% zhbpMc@R65+;U~mukbgA9m>3v94uu8{gA8bbmN5Yo+ptDBfO!H`r~ z3r&R@pq7>&I9bIqasCH6sRV3AG2BUdk60KOxQ>7tN1*Bu)I(vMvkY!e8`z#8xIJx* zAUT*lZ7_RYF)=Ve?O`;;W(_~f8XizV1u9^4_OUQ9a7KXr2J7W8&f(%^V1VSQ31Ghz zGczzid@})JORzeq+u_d#IxdKrfdLe;Ae%s50Zp7UFzA80c3g)+UIBHEK%FGUIiQRM zF?I&n>7ZjUAjZys8OzJezyLN@gqeW>6vU{;>Q^%}FmNvc84Jo$kW$$o6|_&B1)Ow2 zc?v8l4oUG2E1<-7W{3>1s25}I(s5Izu6<)9?$kSkkIOwtgh_p!us7hpG24xnk%L$;{in&3n29Wn2BX%USLX|*v z9)ngGFfgzqZ$RdN?(qei!3o=d%%#ZSDXh=Uz`%{X0htG(7PJ9*Fz-B8V_;yAhVEAe zdrd}X&R1jB!fk6doDu^r2z@Q3Sn87H_z@Ub-G(#P+;aLNwhJis7Nw)+8gBH{( zZckw*2?hpjZpKh?kU=`|g(8^F(}n5*IY5GeK@YAJyyOGLC;F&zHsI~s25>>J*$_cP zJqCM8aPY9IOM0P?mUnJ(4jw!48b4@ zG+hYtSnzxh3v|dXBSSEV0-do7m0)CG0G)Wj$Pf&oU`8SW6V$8&HAfg3Knpy<&H&vi z2oZwcJr8P=NPsp!Fa&`p(0yPa^ARoswKW953ZlSfFff1z>_fmpK_Cir=M_W`h;;-a z0ir+y=MV{GouHmABSSEV0-bFGQV={J!~*GNWC#XPFr5hBfZ8yigJ~HVLO>Kq5lCmq zd=Lwy94WLx=Qe?iC*2m%aloJ>UKkm|5az;z4>V8(8na>KtqfS$cX?{{WF1j5)45g3RG>Qng9|3-{Qp(1foFW znWzdtBSGNdWY9V3&_D;Nf-)IE$LxTd4e}f)hG62nYzz!c44{K+Njo7SGoRWUj!_Os z$W2Vn$jnP+&>yg44REgXLUAVz4syuI&rQ|OEKAJO2W_-2D#EDQ{gC3Mh(7@+4fure^f^s$0ZaL5E7+rS24=j&yFHi(vk*4IIp z;7!J8i~PWfi!$@lAxhv2{$?>UGP58Z=D>(@fCCEyBQxY+2S!d1TY!@lEW!?6CddtD z^Ml!342;aooE!{{%=Mg1U^a-X1DnhO)>Q{K0cIL#i6KNK?63%snJk>!YHnZOn^aq@y4DgbsCNF~Hs5F?ntdf7QS!MZ?>W(12c zg7rdzg9#caAiYdrDxgKqjD?4+<2Bnap69K)eUBmlYg9Ff&1c zQVSMg1lz&_CM%FcAmVHwaRw$9MmA;!kR%&3BPS>tn4xY4`5op4kb5AySfR4442&?n zJYXghGXu!`3`{IcAd@)3f?%`R7#P`@nLv`v^XtKZ0C6xQCl5HLAx1HQoWTax#l!|p z1rRGC!2~%nFg71JCPCo@F&bh5B$gPV zp$k$2Nf@`D~S<)Wn>e{N#Ah*&d`E zvjRGx1QhO|qc})7Uj-C*sh~4E;K!_F=9Q!tT*Q{w}Cw09RX}!~?1VL4g6OHbH>_KBpxa6#NCCM2vY( z3*M#LnfdytVGTMu0QF#(;>0rW(Imxb1q_%G13tzF`KTA`#MJOVWn#0D*11gQb- zFoT&1VrxOwgJxo2;Q$&SfvEwpVc`H8_5dx01epUGD*>y~U|;}^e}ERvg4_hUd=Ru% z4x|Qj;UJ6+8We%42aQ937Jh=%g9a_Y;tUK7AhtEsJ)n6FQ2c?+0iD4MQv+gyMyEjH zpbN)A14tnMgD&p_jUa)_;ONCFZ547BlD-A&y|8{%J`J z@O9Uq;9?=;yd+Rmfb@d08WRIE18ATIl$1bg<3N1SXgMe;f@VuVe9+o7(3l`-tsRID z(hI}P;8TKNJka?^pbUb{2NgERd{6;{%m*cGWIkwxFft$JT8J1ke3c)J56zztE(0?I zC__Lw;PaY5CkP<(K`Wb)`H~D?2rhW<4X7xC34vS#A8Ul}y8zu+fh-T&KZ48$-FJ)3 zp9kYW^>0JtgU;%K34!dp3FAQ3gGNeWLLhn289uPA2HHCWx?c>I#Xx+}?p0XU0`aAh zf(WD^bf*|Bi-F`ZM`aKdEuw1!YLkLaWGiC8-ChTs=?FgL4%VSSv`655Fi=}I9$b?m zRsLX&kahvIy#P7X57ZC>Yk+D;)&drXszw$^^k=}{C;>H`lM5=bwPG=wU0@NAK5!QV z`NS-+45En!TK@@Jn-41Mpv59=j}It?!`Ps_#RyG;pkkO2n*2c17>uC$fB`gV%D}(~ znh$`TcLk~gp!*A8>cM+dpz1-@9ZWswj0Z-jdeFWAMo`(!z`y|Bg95Ug0kWrrQ5KSd zK(mdEau7Bsox{|FW(Q#65g>no>U#zTh8PeVYe_+F1F=C{!a;ZMf!H8%(1H&b`w-}SFeU~DP?ZQ;A^{Qy-J=D%lLN#C z-GwF0$iM(%gU+7I{{*Ynogj( zDG(dfL;~F#17d@kLZG{_L2OV{2z0{*$ep0*2C=!J=?ygL0#XACThN{mkQz`_g4o>9 zbOOpxO#O8+PchGreAbUai9>nGb zB^U+<2GB$lNH3__2s!~B#0E7Lw}H%IVqgF@6)!{Cptb_&E=7!PJ13bc%r5pO7MpL6{RXTgd>fr$KCR-U5|T z&}IiH$s(7%uzi#uYhY|pItJ+lrCShYgz5#QMVMYtnggi^xgU1EAczf0Lm<7N@)d+( zdO`6G(+i4MkX}$53bZE=#s-BoNG~XCK^UeN6fQ8mApe8ZgW6-Da{*y&&>lOGUeF38 z5Qgam?FEGC1(mTN^`N!^Xgv#z-2pn!iIaf=w6-3EVR}Iq*ueCH_Q-+MgW3_Gvu0py zP`LxLcL@Un0|>+Pg2Do(7qkZ!q#o4f*a)(ViGcyc-T`8BGBAM3D-ee11(nw@y`Y7e zAibdW$VrfT&_pC?p(rR$p-o3ndCdqas2La-KwUQ&8`RQ+u|Y)=%uG<01DOd*GN5>8 z1ocrF7#Kk9T9|s!6#+0dXkRCc4JwOaY;c@H?FG%d!o)$B2Eo{%_=2%P@daap;|Qv^ z3FH?jyBCQKD(hkD!Fvy(YC!F9m^i4+hq1xo22}&TqYKIg-@^rEgUWH3deE|b7#q~p zg|R`mR>0VxV@qIcQ2QRnb_1;xgqrD%#12PdgVt8U)K?*igO+W>#J3=cA3$QCL1N!P zVuSJwOz#II@jpmx(6U3A8c-PnV}tHkg|R{R=fc=lpows(U)+$`K}hU)BsS>ECzxJP zT@PbVMN$JQ`(Wa0k;LyJv0oywK?@UM>N!Bu>QMKHBC(Z_*r2;#Vd_EmWWd;GBC$bN55d%c?h1#o zLHC2h*bkA^zeQrpf|eaa?FHT64O8!kB<_pEjznUoBC!jR*q}QUVdmI?mZL(=_dsHU z?tOx(NkS6OM`Cv(v8N%i7bCGZAhGu%v2P=>Um&qTx3R$NWdfa*2z47j5?dLGZGgnK zMPhp)vBQzrDM;)>Bz7GVyBmo;1Bty9iMNR4?%2bzwas1S(3j%;-Jckfq~&ahz$)-PEG~}*cl5FNNiaU8>&Vf z#D?lML1J5i*ibdjAU0HuKZp$#j{>ow?g5=|2deu(^>YbG9ICzriQNfeL-kHaVy_3W zq3ZV{u@8aRQ1h=LvEL)He;~1WxfmE=b+H%{TMLP8jKl`*JBO(cL=w+NVmBbMCxO^d z_s<2fp>A8q1v%FfREKN_i9`Le2gHV|e+Xhj#h-!LP`$s9*xcNRG$smSL)A!fL(B)Y z&GbOxP;-nyY^eFRAU0Io2Z^16#LfhZwm4xqMT z3P>DkPC1ATRo@C?L)C8vv7zGoKy0Y^A*eZ^w&D$tIMkfGAU0I}YY-c%{tFVDn-}3` zQ4kxdMv@oeHc)#~A0!Sn(*(qZn&|{$L)CjDv6Db-sG4#l_9P_sEF|_uB=$}u_5~#N zLnQVmB(@MA!u^Iw>;NP-sQn7c%ODywmH}gfn#C|SsA&shgW9?2lqjs@dfIGz|^dR_7^~EHX*S=XHmk`>_rj>jfcR*K|9J| z>|01`K)ZWj;-C#ZF!mcHHK5DbVB(-_3t?=~Hf9(bH1+{wgT`ZFY|!3e7+Z-El2$?P z2aUc9=NmFh&@A5|SFwxCu;r0h0I_{Z_ppEk|@f0NSJR~;gtR0w|N+fYm-vlNO+7kt1gU-@{ zv1cKv2Tkq4#6kC#!q}jlqcApT4;73J+6)e3gQoUi>{Cc)f^M;diGx-b!`Szc)I3IF zgZe%&HK2_`FgECF4;UL%Uc=a+%~~+FI5Q$HKpPuj;-J0~j1Agr1!IGbSb(uX{U#XO z0m&TDo++3(s1F5W$0DgoL}G*XJHga|&dZ0f>yXqmA+bRlnP6&WAc=!6Erp3MMiK{2 zvBK_}098M*wh(A+3#J}aM!?v}bpdEx8zv5_>R{|vP~Q_;W=;T|V*zDPgR((m)pMY1 zko}+wZb4^-fyS*t=>)_Exdn6+D~Jtp3+Ogu5F0dfybG!qG?aP($_5P;g3=5~4d_UU zGf;8RdDWm>U_s)b@fA>-0kJ{z0{5V5Ky?dfA2CQgl!1W(v~3N<2Guj5_5p|u8YBM( zRUgm5!0-pk291}4)~JKjq=DvQm?38)gT`a{plr}lt)NY0AT^+~tfiphpfj!%plr~1 zyBd@Ys+V-2Y|yz?Mo>0rEX@MS2AvgW2W5lC>0O}gxuA36p=?my6$oX6=03uqY*70g zl-@w@0d2tt_1{5k&^TEpR1IjnCm+fNjq`&x>VnjOZi)u&d;_sTd#21IH;bChq7lgGBAKPD}vO3=B%=z;)@s= z7z&|mQ2kjBWrOCjYN2dUT?*O{2+|9h%bElg2hC;8g|b0)Dd@fnkQ&g=L(nNNAU3F8 z-3CvBit3%nKIT2kb8??E^7|I51m9d1fL3?HFp={9Hh%1y08VmG>vOyP4gN_ma z*$bLm35SY<#t37fY|tD^GL#M4C!7gogAVw}hqCLK7#K>SY|#7(=;mmUne9vr44}J{ zL2S@`N;^~yXne63$_9-uPKL5U^NjPLY*4)oI*0?L7j&}7W~ex5{$(eWy^o23VLy}& zn)f*dWrH@^fc8>@^n&_;pc5@XY|uF)H=t@j+mi1=*`WU26DS*0x4(k2L1ps?C>vBZ ze}l3?b31>aY*5|K#0JTapt_v{$_CBt@Icw1@)%UFF@gs5K@8B?IFt>l%V6~&@|+H6 z>Ifzd>dU~`pgBJn8$50gt?$6|+E6y~JWCG9E~q%DZvxZXf+UVSKQaeN98`A0)Ps*P zfSLm;uVLb6kko_bTVdi)ki(i!q}kl6vlQz zQV%LCVd9|nKa35!_!-6qm3=Tas4RoAdyveTfy4%tM=&*@atFo+l{+vtXbT{W4JvD3 zZ14dNP`|uEG80s$z|??Ffr7C?^PVs^sJwu&HIUjipf)*7+yP142Z;^J!!R|V_BM=N zfTRYLZ(-scNa9nF*r4+}U}`}55XJ_b&jn+H@)(SL0ZA`3c@v~SZ79%k9Z;JLq!=_0 z30lqxVuLWK?FXVk?Jf`-G#?4#r|5w$jAj6@NIH2?lr9op0ptdPY8kaio94b@~ zhytm*0AfHf$X*Z=wCohbhWYo3F#`iA4S}ZPLCaS`av=AC=jlKipcr%~R19=X4I~6| zJBS9&%YyX4%sXJpz`(){@h@mP7$gTW4>XwuBMHhslB3kuWw${G2EQ z!&aE*k-`Nuj|(yzX73RP28I``5PL!Pf#g6msLhFNUb7@*{Rqfx5QfQt+N>ZwF!R>9 zLDp}8!Ug1QkQ~T7(0B?=4@m!FNyu5aAT|iYJNbAK<0tw zd|`S(`gcn*FbKjD8IpgOL)S^c%wuq8U|7Kh@h@n-5X?N#TrtQzP?-)g?~FVH!x}X6 zK=Oy7X2aA~s9`^Q6;%F$(gnyY5Z2kQxyFsD}MM6407FkXvE?Sm6sf zdleKep#Bg@4iqk+b~mzlKh+o*K=mldY!HUYJwpqZExr(SAoDJnX$2BoCa=Zks^JHQLO{X(+u!4NU%)t)oBr&tF zg2v~VS=d2qW|>*oLA_gMMh?)R8uAGm0^$q|Oo&r5kj~BkuL*;ME5vmm2Y@grj+hug zr?z8kQf5HxX93+%0KWSG<$42J?6`nzOF_OYp*SPIs6+w9Vu%pPQB=AQ0&Y5Z;||!T zAk#s+B|w{U8E|hx0=pNy38_dg8R?P;xETYtkpj7_OA;CMl8RARdS~XP zDDlAPkcOtyhGxLE@l#7}S3Qu|XIn2O9eWnGLh|2I$Zx1_to$%brnf$B6U7oOrl<9i^pVeJCYTnwl$gscuEUj_{qm^xP`?Cl5892LkNF#T;z*xL`F zv*o)k#E5h@x-0{9VK3MP*a@>lhMq+oNoO)($63$W+{DZv zmch75iP>PW0_6PXg$xWkj3CS%Olz5VWbQ&w@b1ZiiyQH*f~b)FfOJN*Dg%S;2P*|g zn+w+&(V)IQXsm&O4{;VWNDLIN5OD>Dbm;m~P&)&36fGmD)93;UedwZgkoOSnjgz1= zh?&?ytI3!d*+2{Pm>D@hW5mo%tX81okvUjFJt}4nc2LKI1$5dy6E|q?l?61o!Ndbv zD#-F3bYinW9jKMU!ul1|@B`h7%d8F(VFeA&v!pPB@*x`wvlr+zX!b6U1|QJy1N$|Q z1AIZE3>=`bbI`fToFD>x$TDbzor{Cn9W*1!4H|Z3_5@kZzJ474(knT7p7=x8#~?4AUxF6i7?ZYIz<&H5lF_?Tr@1CYrq z+@KB`gw4SX8a#lodAOH=l!MiPk6C6lECa20X5eR$1s!b6&B(w2S{4X)Is*gmCPoGZ z6;@M_rQDMlKqpRvOlRN*4fC>EfY>bDCqUwsAT|fL9V-I^s}+dN!wtGNnbjJ^7T^XA zd$HPp*dpAZ(`Z?3L2L<99f&Q%%>~kH4`M4Y2wVrv4=}QNfadJD(?J)?d4iab zJJ?yhKxQvigHKEQ|~spk^s(+z{*$c?Mq4oJ9|7FlZPL5@I1B zCIk0W&>7pIAWK=eLF3M>VW3sh9NeILty#lYLXTMnnZyB_dI4dmk^C&+`4@f`P~h#|L_j0HP!5MkGbjWgGCU#^KyI!D>k$wEWqHWAU!RN^H~`fAjd4TwlOXOAG5p)B-6pTnVo?_Lj-i?H)|JIkB$iF zZdcY`FvmayG z;A56SF~B;L5ftnmBD$b7Gm8-vu0A55>j+urGD?AuSq3G4)_LGCcp?ItrDC1Wc!!;V z;e|*h$mj)Nqd~_kgElVmrZY1zWUy`yfF85Vx&<8SpktOp75J4&0!)Mhd;Y;vw-wo`o{`8W|{RWNUsMsXkP~F4UqZ(ZqR%T z>rK#EkRjaDL2h{PkAZ<9f*Ujs#rg~0oT>2@4*$g6}1p%xo-~`JeVgk~l3QkC%W0pawi=PE#rZ8wcLxR7gXVK2ZM#`qrO zq$W_XM>2v-WRVr1j2i`Y5@>RRH5x3#Ap)xDSYyCiK*ubDlncwTFfatLCNNF{9oNhO zN}|c&^v)pC46;9k5frg3BA|d}O$Bp!M6^MvB@N6G5!ngSlMdD|BVrEXWPt5f5s3sj zBonMmLj=^iV$A|`3`9WFcC6W8j)e$lFDYvdnByPVF?lgEijd5jADf}4&^}WtE4y? z7^Z=h#xhL|kY|ixG=!R@04gv*x)g&zd-piORxnyIFeriM%h+ziS}}}sKu!R;IS%aR zAO%nZ1GMH-5j0TwmK~%Ka^$Kq$Z@R8K!!qsQRN>fTn>VSMK~E4#6bp#gIEmwERR4X zHfXw*y%^+uJCHmme86E0AwXgb{45~tDxiA+*bac0AgdwrV3Smrg3>4(Ge|G;01M~@ zN!)`hEYMR)!6$Q~9#M*XHYq#eyiw3tH>0O8=(tEu*x969$Y+ysBh-SOADj<#yRfMTw zU{HeF%B?PmVyiN;j1AZ!D#${hgE>KVsA4&-6O`87!Tl`IiVaX+0#8doxt>4A_l`t(uHtJM z%*!lcfZhvB_OV{@!@T0Dcz9PzX>Kmai6y!58Tq9}AjhUL#OLRM@57BxEJ`nCh=-mW z6dzxlo>Pi^R97xh=W~Hhi2{uaz&FpAFpzmxS9}`$kgoVNQ2GEJMpayrl3G;65buSM;?kUw_-qEyNl~c&iwD)e@R4J%5%J~88A%NB z#U&~Er69+a78RxDmBc3}mZYZV7gd6tpOc!$03IDi)mmg?!2msa3zC>YzRt_cPby}B z40od_Cs3H^LyQ2Oh6VCZVop5hgsu3*;^dOd+*AmsC>7*0hIo*h8DNK8fx-rUELS|@ zoG3R>A6Lw?x#Cfe+Da=ZElCCkR6PD8wLl7sAqOLXPt*dB{xHP*_&a;Y2e~?j1_gVD zxyFYe<{!Yr^6^N40SWDr-1y3rL{KU$2Kz4_;>_Hn;*!LYR8Snp7o!M4a#?&HX!tum zHz_AI4|YOcW?nKwd}dw>Lwqtc(sJ^X6LV4-;&Gm$Rh$YwSPb9MS=bNB%EfUaRy@|D zu#nHa0!2s)$ZMd4ON;3jaB+z5=&E=soKpo!oDA`KkVq@Zjn6DjDJ}t@vz3^GNTJ}v zH3so9RiHHvph_P^!^THJeAqEnpr$sc76H+qZRw!x-=JnSXdD^D1~ryJ;~yY4sAUY& z%b@{j;)BNeKzc#@a>3#t0?&*N_^6(o%#zfi#2g05!969QRE{#qlMkBl(JL+~GSoAK zDuT@7q!lIRrlN=tm<7toPexG=pA`bT17av~Q$rB9R+Q-FWR^gUtSHedD9Q(|FaUWP zflG%p8J0~(8fu|XGB!PubvUNAOjjXjJF+V2Hp zgU+9TvD=W$pNPZ;pLqbacLS0*=sYZ#-rGpx&ym=mH83zWptb8THfXdS#+C%FF@%~A zTB8mV*Fq9^L}G*XQNh%JhP7a9(E4o{8#Is&V}sUg!`Ptp*f2I|j3356jAZ_KB=&72 zHfXIiOg(6=HH-~98wSP(-G>NcOM=!FLj46=7Y!2!UA+cl2Oy~do%;e4&p;9fo$mq@ zZ$J_U4WPlqK@%)6HfYT-j18KEfw5m8=>_fefr*3mWWd<`pmPGCZk9n}Ya+4Dkl4;h z>;NQo77`n@7YAm33zGOmB=$TcHfT=+O#Kcd@uNuWOGs?cEFDb!8zgbi{sWje8|eH1 zsK11f*y>1Z@OcJMH3>-K6-aE*Iz^b76OhE`AhAJf`C)3dAc-G9VuRM*!_@pi5*GoT zNdR?&0uoyXiEV+zc0pp7BeD5G=LbN|0bSk*vr7X>+!TrJgv5?PVrL?;%aGX3NbCtn z>~%=&-AL>cNbIXf>_qk&y1X@SK>Qhi14O0U?R|e`%(D_@S{S6@V9x+1pB7oX8FQIHu zP<(;1L3QkJC>zwI0htZb3#wz;q5I50?ITb*3=#*`=O8;lY|t7OP?-#3gW4yc{VX6h zD11PBSU_x0y94A7MrivAnGFgKkbNLAJ!G91F_N9p5synT2l_v1KOVm(g#upGaJMQ$$>Cv zZz6~WiGeU^9v- zU$dck8YBd>3$$Maqz7i#3`qtC4t53xka?h97Dx_cULl%!>0As9KVgO-$${L0B+QTi zI)4FVAr!;pKx>~sX2a}Vpa5Ab4zd@Nd_i&`dqHc(VR}GD6!TzTqYm093DN^IZ-)Y8 zjXKCYQ11^U2Qm-5uLfig6i?=1U;yp)fO6q$pBAHq^Bn~S2GCL$ka?hd3^NbBHwSu- zCdiE4d<+a8piB?qK*I&(e$Z{^AR3gXK~l^j*w=)C7NkInACNKz7ZL1h!a(Nn?U{m^`T(?0JnQ#hA}WOw1_Y;fc7uJgkW}o_JV@+z{0sj z5uy%c9;jRa$$`Qd6h_GD{DTMs186T2x_KaTp+zZJ>VYT&1LzDyP~QjCZ33AG>ZgH{ zF0y$A;tULKU>y(wWDbZ0U9(n{nOBkqT2xMG&6=TsfiYxJIpH;H7eJkKq%~_Y;MJob zTT!vuLI%&o$imFV%85OjDw58WD=dO8PTQgM=%B!*g9bePYnje6zZAU5_)`(G5>1y& z_Ji3%2FpN@&ZI<+%83whTdtn2imWs45Z(@DsDA&mOlvXpgTfuxx;0Qg7c^_nz!v~s zZw_)XNDLH@F!5@nb!$&S?K;q=qZm*OFfcHHHn4#-A=a(E11%e4V)p$NX2v8-DIFA0LKTeAjP2wk@Z zIv0Qyx^C?_$i2{YYoNW#tk899A3-4rUAJZm3KSC7t%25Q!q%;U7Xo5gw+3FT23@z7 z3UUK<-5Ti3Mpo#$HPCqouyt#o^HNwzTek-4-t)5zzIAK4prD1WTRV-sZVjB5Ve8gF zo895-)<7%HSqZOO10Bo&U$-U#O0ckXYfc~zY~31ottifQYoHTG;p^5w!%VEOb!%rq z@dR7977R)huyt#o6J5~Pt(hUOTLUdBVuh_+n+*y8*t#{)W&~E)x;4;_epcAJwTmD( z!`7|&gE+8tYoJ3MSYhkd`ap#SY~5Ne$ceCZYoK*3@O5jTReH2rw+7lu&!+K~oq>Tj ziIstYhn+!=gMon?beae|1889-1NcB|2%Cl5hLwSVodHz+a4@id)(>-l*SxWSMtRwi zKr6bW?t&IOF99#q12qpoZ3@OY8{tdfq(C7Gl8{NuEn#4k0<8#R43?EEN-bev1TSu5 zjFL+%U|^KjZLQL6&a< zxesJ7s4c@d2c%URY?&d*GSEOZ)H)N8La247Fze(%D+L(MK+a?gRt62}7lD?>fmRiP zOp*s%8pTx1z@P{kdxklp2*ib!Et_*~A$bWKb8k$%48ma?ty%p$p#RVawG(Mk^pKX~VUS%~Ke~MrFjxHKwx&@aiEn=pfy{mDGHEPPo>~hG7xJ)6Yfdi+weddX|?VSvJ?P9Ls+2d z9lD+_9=Y<(giAvh$jj-Vav(cEm=PK*pr$#fqX7~F&Dp`$$$>%{rUv9Dm>SR;IMBK@ zP=*1`Wx?2>Fc1N0f@U^usQI7{DM%b-4~Pw0KL?sG0f~d`1hHXj*FbZMATvRk4YVE$ z#s|+{5D7* zsGAOBgW?Wk4rpx~2*dP(=FVVxK?4FH^`JO|t#1RdLG!?j&;kQ& zfU&{r+n{Q|>)W7g@cK3=I|j7=49W(tZ-cTy1CKCs!0X$f;^6gdP&Rmd8y-K4ax?uZ-cVI>)W7g@cK3=8@#>^$_B4*gR;Tv+n{Xl`Zg#VyuJ;}2Cr{}vcc=y zpltB^HYgjsz75I-uWy60!Ryy-K4ax?uZ-cVI>)W7g@cK3=8@#>^$_B4* zgR;Tv+n{Xl`Zg#VyuJ;}2Cr{}vcc=ypltB^HYgjsz75I-uWy60!Ryy-K z4ax?uZ-cVI>)W7g@cK3=8@#>^$_B4*gR*~t*0({~Y@jt^P__^fTONt6g~T>RVmpA? zpcW`-?J{&N8mOL%1c`$xPzDBub`Tq?W;POg6NnA9cMpgSRdWDp4yc~G3KEB!!wec; zfvVv_Vk;oA%|UFanI1^&Vk9=meV{rKM1$&n7#pMw#s;+?U~J?%7c?{u69?6~FgB>p zg|WePD~Q0eHtrT^%`wz3ptGJq>(W5(c?Dhf23o`M70L#=3v}liNDXMs4`}uk#0Ir< zK<7Jy*q}B7A9QUTXssHkZ2}SpwGlwql!MryHV)`sHV_-sE&v^+0Aho}SqG}unt_1< zRJMb}L2Vz<-3lN!Xu#hNss_aNgt9?xB2f7cQUf|~3UppGhz)8Zf$9PfJBERQAqlD; zwB`&{FMz~BXQ_hjSpcy??IX}V3m`VAZU==0Y&|P78{Afbh8uDl3FK#3`vephFgExc zGN^jcdO(;ssGSC5gUlxegVx`HTIkTIWdMaCsBH<;3rb5MHfW6xhz)8(gZMEL3=AN5 zfZ_|JA0!9z2Pi&3e3*G4_rW@EAblWpAR2v5-V6x_2GIH}ka?hV0#XMu59A(@c_1;6 zKG4}=AR2~2av(OSO%KXagw%oCY9I|z3^EVqCy)@xUJwmhy9Z*!|kyH=>shyt4Hcm!Q?>a!h!U_%sV2uj#t-BMnEPB5K@)wDZ~^r( zKyo1Sz-?WmwRTbb3=9QW*4lyF!AR;(;aF=2y2A$)k07^zFlZkTsLTMdK^W$~)1Wp# zNC1kRMX|57JBGH_E=38l)(#Xdpgsr8AKOkfpp9c%-+rZL1NdIb428M?q1{A~01JOvq&(I^rzyLar8W`OJhg*PZIBAdq} z!NA}PH48+6%mLBRwRWHp@x&axe0@S|?JNzAOo%-nP6o7*3u&z#?0h&-{s!5N4VyVK zteNb@%pm5%1X(WUVFh1#w~>M2F4tLRhb7RJc(NZD7$Ax)tYF8qxYpMBgW??&V0;P;mpCB(U(nfap`f`B&_di+P{=YcFn|<-9L~hZ zc9wyGfr*g=v_OZ6i51kEXJTS^0WGCtVFgVyFtM)sPWJ239_7lXEVqG zzj+|9Gq8eJ{rQ9Li)95}IKdp81#%$hP7KJ|Z%i!gpbDCI4I={sbPXNP6VU1kc>of(2eB0x1d!Lz@pORP4_QM8D!&+DXTO1#II?10L&pg^YX@|)7}z87 z47{K_ZJ=xDARz`>L&pQ^x3PwTEM?&Vt(S$K{l){j!wU86H%`#H4G@MJiF)>%0pjd8 z9?;kTbPXL3$i1wkVDlOHSwQJR7}O1fpZx|p2#~dm5u|`Y1Z52!=*AA{f;tWn&{6(S z4v$C?C~9lLdeF{(1D%J)+6b1B5CL8D!P*Sw$cWT{^k7{>*8`G)t)T;50nFM3)}tdL z0gAw0FvkFLb`)$49jFBeUqkmA6mPIKbjct+ur+kvAQ{*iI#3M2*U*8Q$waK71KnK2 z3R^=L4l){T4ISu;U0i3sfx;Ae_8W-F!2=p=VciZI!Q|lqog&7%1H?u-`;7;5kR$6Z zka`IobC89QHFP|XHFTg6mY92XF0zkwvc>uf+vdLSCWT#z^eKMVTV zZ|w{W42ZMez~+O5#G%T;XTO2ih_l~7YM^JofeTE~*>B*y#RMrpL8pR&`3wwf=AfX3 zuA#F=UPA{i{gk0+zuAI3tO8E3EFxkcEri$5fi6;luc5mK(gRyV2RhD`)d6&}7Xyz- z6i5cPhK>`|LI$0D26i43gD}b(I?z=W@HKRxLrGbqpiYtmm5#7Abl`Iu(awHjKwd-l z3S=d04P7dTlfnp!SQZgb?C(2088Zt{%LkfYr|N=g_QWI>C9!1_Tg zLXiGSu-Yi5A_fKpPzw#DAFK=1OakcwEl^XO2})j&MP^E%v2^x6P=*4jg`{#N(Bp(6(&%wYT4kkd3R)!wihVPg)J_ZKZS@xi&59AOu*a2(c)7IFaN3XGh)^V{TpSH$< zI6;kpfs+w>+8P(^v^8$z)7E$pYC$W+hQu*z=m(x5FHDm_U6>}$z#xlQM27c>HAX>3 zLtzF6Ma%_cC`YZqPES(?4JUw-9|Ndw!^jW}qCm+Nv~nzXK3IkUa#;qXa{z6uBDGgR zYCwZFObnoFG)Y-GmYJTHn8QHcLMqJVSh`osVDG-&^dthHmA`H&T2 zSkF(>Wn^aLWM*JQS<}VH30e=v#Hq@_$SKc2^l@m3C8-seC1f9ihG(G-I0@+&z(aw` zC#FHyQ8C2RZS5A+E8qjiM%QhDLxAw%XOQ!#K&#)#J^~GNN*sa1&qh~amE>o~=Ols- z{37kZv-q@3(Av)Olw!ysbLHT(-@r!;QsY=MD%T+311cdU3dFhi4mm3>DS|1@O#-c} zge|KqFok+H7v$LiU2_E*!UxsTAR0D22jaulT!EU$pxPZqgW87%43OK8Kx?f)?E#Q_ zkT?USYpaI%QD&eHDJU$!81w!c&_Ewp3QRCFAPqo+*Gj==J;2fo%nZmQ%%HVT;2?%b zg4IJ8nLtID!6S`O4p<&EGlt9u&EO&PL7fU@KKj}!NHAZ1< zP{_g7M1jVqU}uei>_j<(4C+8o!xyFo)Z>Dw0kJ`6b%D$W^`t;-kUgN71Q2oj@T45(l{j#D<*_2D-BbBo1;Hhz*)o0NDjH7bFgf0T3Hz4yacS z5(l{##D(fD+OhP*GfUzpz%AHdhl8)s5p47 z6qF5KD+Oh@gXYkoZ17qsC>y+13d#nrm4dRtYo(xU&=?=gF7R3@s5p476qF5KD+OhP z*GfUz;I&dvHh8TRlnq`h1!aTRNy+13d#nrm4dRtYo(xU@LDM-8@yHu$_B5Mg0jJDrJ!u^S}7y+13d#nrm4dRtYo(xU@LDM-8@yHu$_B5M zg0jJDrJ!u^S}7y+1 z3d#nrm4dRtYo(xU@LDM-8@yHu$_B5Mg0jJDrJ!u^S}7(5yXb70iO#7Wm_SM2ZGqpW>74M4ONqd#I8bOgV#+#)lUJ5L)`;D z7YxeYiX;xM@1SOa>S@?|Bv4%pV}n{nFgCbegEqTBbuer_45;3PsR7+p4-*H?nSs{l zfb4k;U7G}I3xFnILE<2%et?RD?1Y`?1**eAdZ>Ng7RXFuFs!i;@-Ij|Xq^m548#Uu zP*{Oz(EL7#4QlIv_%dRUbp#-BQ0ovR2MTsj=K#cqnFm@+1Zwkv^nfr(9f(F>w^Jhq zxn~Y!9w^*E>Okg!+ygQXBnHw4I#UTm!!Sq=#0Ir_Ky52R>OkvpKzd+jX@SfG*#j~I zgh6s3jDD6DXgvt1T>?@A!XWp7Xz-Le(pg$I;tUL+S#pp+K<)vl1DOw+!UvfP(gVVv z^&8hf3P2oCy8udq+9@DCuyAe>hulL9G7r?s2g!lVLqAJv9VY|BAtVc6O!Tv~3b+{< zKx_7(*1`KJ=x1r^$U*K?2H6YhJ;3Y*t+Rod4KiaQH*sfa#mGU{_khd;KxTt5 z%ze=HJ*6d}&920(?=dkpBX)gH4XB_(THk~7EGG{SZ6^~q0sZOwt(2s^RcFayaPQSOA9n*4ZYX# zJ4hUMKGq%3aw*vPSd&1r&yck}pf&+~Z4Va_CP`mvbKl2 z8sq@z`B<|+CP2@}0-Z04y0!=Zy^f$;YT&%e{`) zpyUf(+cO_|Z4bEggRSjx2YDEFucH)53*ogrD?!R&_d31+abRnE#6ZyiJ0B|!Bm-O9 zgK@7TGa~~7{Cun`kSk#4V}TY&vck^C0-q!YTiXLV9t!<@EH31=Jzqdp!q)a=f;h1A zvA_$^VCQ2=fKnRle5|D)H^bKUD1$h#^RZe$2?lmP7HGF4{9eamkPPg6EYQLf`1x3% z%^0*h9}9FXE*oTR4=7=W-!hHX_Zc9V2lC@ zgDg~B58D103$ltaSP69TEa=Q@SHkAjPwj(Qs7x{=(;He2GE6Y z8Hq)D6s;?QpFDMu0sCSi9HV0NVhOTJ%M~U z1BEM*sJy(0X3L83te67j4Si_HfDW)o%E^YDxdmE26JG+0`OyVPpv8%h3l|A5Kmvu` z=+dLS(gKF~+{6m-Iv?oCOyIi~q3rn48yDk2IWNA5!QC%Z!C3)(qM(9qF6cPA;bW1YlYN7=PB_(<|jaG*qR{FS{sm=pspckcNmNf+A;z%2jngg8)iOepEyVyP$mV9ErZm8TKAw9Jctd-%rG`6{6Ts_yIMdPrWe#7 zh3N&&4}#Q#;tO_$6Nn9(e;hr-iGgAC3@1>kg477G^MSzYl0X@Sfq?y*k3CaeqOMyn^s@VX=@8@w(F$_B4Xg0jKulAvtxx+EwYyey*k3CaeqOMyn^s@VX=@ z8@w(F$_B4Xg0jKulAvtxx+EwYG*%1?XYjfts5oe11ttz&mjo3DuSy*k3CaeqOMyn^s@VX=@8@w(F$_7mf!R!UEOM;4n*Cj#O;B`q*Hh5hUlnq{& z1Z9KQB|+KXbxBY*cwG{d4PKW7WrNoxLD}GSNl-R;T@sWHUY7)AgV!ZN+2D0aP&Rm7 z5|j;Imjq>l*Cj#O;B`q*Hh5hUlnq{&1Z9KQB|+KXbxBY*cwG{d4PKW7WrNoxLD}GS zNl-R;T@sWHUY7)AgV!ZN+2D0aP&Rm75|j;Imjq>l*Cj#O;B`q*Hh5hUlnq{&1Z9KQ zB|+KXbxBY*cwG{d4PKW7WrOY|gw+v$k=7-F&u{`&whRmmN}%;Ypw=X4{uhZ2zLyYc zPB@ZyH1zBxQ2mkz5{H^o3}QpoH-OksGdq#kbCKAfU6Zghc@!iL)%zNW4Jx%j^%{r< z)uS*rNGXgBT1Nq6BiEatkzbfNsNRIJLG>n#4Xz(S1fFx4z#H|TegWNA2wKMkau4Wo zArKqX9=Qiy(*#;#0XwS+)INc&djgGI!`3~4!tEPWJ*eFQiXV_UpmqmnRuIHCWME)` zoz(|T@izHP(ah1ApM{?2KfWj)&%ik=7HP?>%4&615yW~(brE2fYu2y zK+d}X#S2Is$UIQ{2xJ~e45SaVeg{OuFh~x>MqfXLOC9>TM<8{uH8~)2K=y)Y&^jv+ z8zu+3dl9r23FKc;+Z7}Sav%D+N1*dRzC-gB$Q+pa(9b=xkzimrK*YI6r#TrI{=y6a z4>5yGWnciE9)KjwaDtn-bC3SWLDs#2`~h-5%pagRL1go|c(AXF0-dG;(gO>Z7_M2XZI+xkrwC3=E*VjzDIC zFvvU*2CZ`g(V+YS5-$_RzAg&=+@tL{)j|3DT>!LvZ0PQY;`2)0W z4&*+N+d%lcFeE-eY!HUYp`UvsgLGaMs4oOF4^&pc@&-tMxCn9Q9$A3STVjOVaS1X5 zWF9EI(bq-I5My8f^-DlzgD}i}`i7Qf(1lLme&z8!dd7*rfo-+{sebcWGc z&>2RcBOjC?A`GAoHYhL<>zodN)&()KgHGdPW@Ot8S?6>Ev~G!sRRXkph=UcBf|;Rb z7^x%HIUPf+bJ_}04_oK-1GLTwybKAl&M5@TIw$b5D#$&6ptTRU*EvlyiG{!oF0H?z%kc3O#%r+*ExX~ zMS$5n+)W_Ez-(gHIjuyTVZ;r(dK9+K=_1H<3y>dJxItMIw$8~MH0cgq=LA0T0lLl! z)TLpCu5)S!xd6J(349qAbe$73NH1)i6XzqD=Tmf6>#1B%0bDb0D z@FCbbCvb>C*Etn~jDW6lN&}eyUFQT|SVY1-fS~InVe6cZg4V3yUgrc_fd)Ur2-M$! z-vcNPasXsC6N|_d1cw810trNhMO@bh#${9zcDN3~ZefsI>(@!-x+QZ?JVvmLM0v);Vnj#WZZ46DS7Y>zqI- z2foe;bSEn-Y@HKmfh+tTz%Gz!uyszlAP(9(Cs$I|IdOoz0A1%)19BRcbxxpl*06O> zpng6pbe+=+P@F>7If1X$gx&*K333#4ozr$uNJ7pq;+6#k3JL3+K`F|Cv%WrpzEB#7bHU0Ie`{_!R`SBFAO7XofGKx(7|{QpfMmhvoWelLaISL#?Z$(zb8-V& z3|r>}USbMc=VSy*6tHzppwS%kbxwbn85jas6BsA4Gcbre16c`M=adNIz}7i|uknMe zb5a2r3R~y28sui!Iww&O2e!^B0F+>0>zqI*!ot@%*@I+Y>zqLS2lzTC&?ZURt#bkm zc|q4XO=n?XU|RuR5Cp2%K@9}PIYyv^jKJ%h96$?%KoX#JP7a{5gE3eZw5tHra|W$u z0xdI=s%2ncVDkVQ0&7h$&Hm0f!E2#FJAPzAb3dS42tkXYiWnFe6!wE$ z;SM&S540=^q(vOWg04tX%ml^k=!zt|-joMhk;K4&z8;AIat0A%JrdF~A}j|Jfzl5H zXvl++AqYf)5*g|$AyBFT_xTxuKoqEziK+lJ(E#Z~K^vkB4Dhxn$oSWwW+ek?5&Gyd zBD&se2iYDHUrMEgM2FyugcvzNx64764KahxDPjgM5+Y@J5RKLXfo2Io6NjaFpj9EM zDP-RqN4GPF;z#d@qtzX8;9JTVKntuux0XSUlcDZiZ$vKj0%yVEjQpY!1<(n?;Ny-e zK_}D1#}|W7S&Db_^l=4UBUW6JSdt35MKHb?MTjB3C^0W3J}jHmU}y#IY?E0*Ql`2Z34$piwGNBLLJq0E>f&k+viVzV8?0 zdFr1}1R4benGC^$@h&(}?*rsIP%9F&#s}230P#T>G>!|JlY*rdkUVU>9wraYec<{V zc@+>WH$s>HAaW;qmd02W1Y7R|YM8>#8v@OffY#T5>;$o4>ux~f*C26_S`Zs{)(>cL zy$HxdAPo!*44}0$AT=QWfY>1afG}(w4f0$WsA&x9euK1v!UD!7WepC4Xg98bNk+ufM7-{{B z9f%ETrZF%uI6>Flfa;V`kT|Hx$H2f41!6LHK?0G=Ldn-wt(CNnk@pcLDQ$Vplf76ZIlO4HpuVK zplnc`{|d?m4T6I7Q+r(u$V_4|w)HR2=mBd7g)@i&I^P7uhP9(Eh%zvM+8?0#eNgKi zBnMij02;pr@j-0|kUr2_9au{p#0RMZ(dg@6UWg*r(}2Pdqz+^r`uZ2py;vaqFbuK_ z#71BLf=eCx`WMihZ7@H9%mLX8qS4pCsE9Ez5VQVe2?GPeLZkqMxetB)%L*|D2GE*5 zQ22pb+aP;E{sp-krU&E>S55|oO-KSTCi?o9?_9*Kf3c8-thWH!3$hPpFZ%iyOC09{ zp|5|LAxqr)mq=~~hW9YXBdy~>U;na4mVp7Zjtk^IP`elAKG5m`kapO*77tzq21n4M zHBcZy%>&7!uYc*paV`-0`j=Be*v|z5O|FB?g<8YFMC|$(=(#{3f8bmH!iD2pAdK}d z&~t%6=7Gu&Sh#??3!wZ0b6=1!aqC}9L>L%AQ&OOO4Kf2{9w@v)X%X4H7EuNU(D|G& z^I>6uI2TASUtd8%fzbLFLql^D$O0I`>tAX>g#(WDFEDqY(`M*r1T``+v`=C25IV*J zIti$K3af__=u#oDFr$Z2lZqt!3%({1w&^c879ELz-1pU?!rjrSa!rGIM#^*znGO~s z4+aaCP0S2xvpJ=eHCdFH8Q3@()-tg%GBAJ+AUewe(WcAg#>}9>V&uf2!6I#B$)d!> zV5B0+{+Q25gl+m`gz=#J#>^0FbNzUVQOI46HLjp#`}kYZi#f!Q%~b$86BfCmxRF|b|*>Ggoz zW_AOlK7a>&Q5E!Nv+1Bvg5GS_3~~eXW;5`yD#$mRff9*0$Ul&a%D`NZaSZ${_gKL< zL^823Fz~a0f)jid8YdeA1Cj16VFYR6Vc=&eU}RtrHiDjh^ao^)49NauaC&DDnGRA7yV(rXq=esW z)&MdTcC#7y1i5rZkbW5v@Wq0#o6SH+d&6%wTLmhcU^knAmYA}_ZZ-p7r3t&)tP-RQ zezO@UvOz@#I8Hz}n}I?=5>#%0*t2vAdmagG2d0|VsrqgYUy1xbL`_r!t{An4Fl z>9hg{##oRlkb0T9tPBi{NgzqaAX!j526TWC=;CuZP}$6w3^L;g=n@K0BXlAs=+a;C zRb~u|t_%zei#Qn=K&KrkFh((#++bi(tYKha*vZMj@Q(weGKQ&yfk7VB<+=&c30B0w z&jLE4NogtQj<%y9t6>c$#yJ@v*C#VD=75Aj%RQAr&dmWimoZpnBLf4&D^3Om`5g=l z44|Du3XGsT*c2F}LAR?hsDiJkT+CR)$-p21VynIa!|7#uU=AQv&H9bsW$U{VD+ z38GB{yug%=85C;x&SVdw4hzb1~SP(V!9L9P0Fkc%p6wS*4&=LOcD$XDu~mXRG}8JdJ5Z1 z+DI}ms39Nv1Uacm9WI2l?n*|?|%nYEr@StL>Sj5IQT+#F;Aa_Qw5<%45k(r7#djUrskxfoHGc@Q2B`Eg2{;`spw@}$zV_#%d))Z)?{SV9FYyByRP0)o0+ zpau?z2F;;@<|09j9#G>3G=&9X!^FY+{Xu7+GcYiK))axx1puiB_0m9ds~|S0Jqgnb zVuPkIpcWfw z+#4hZYlwl|$uQzp|1p4CnV?_+l_MZ=P+X>i&NO3UVCZLHU;u?RNDZh53F?@F z*dTFGClJI2*#lZn31frGD3CcIw}aTQ^Uy$U2B`tL5xlmN2~u`xL+t{&4KxY`QUfZ- zKx-diY|#8a$V^ZefY{v7Z~)DPg4BS@E6_3IAU3E>1C2q0*r0L`bSEK5FUWonn;RN# zlc4s3%C{LvY|sT3AoZXi1+lq73kC0^d0}kO`E@WhXnQ1#4T={S8+?Z(C?PN~Fo5rngt9?* zGr`n=?~sIwgW?D#4jS)(vB7spLe+rpkc6^9H@3jkfbWomii2iNVdCIBB%$KqJ0ziO z&;%e%4QRLk#s=RZ2~`8SZUZI`+H(wJgYS@pssZ0231x%tkc6_qcSu6n;5#ItY|ub6 z%pB03SQs08ha^-D_zp=Z8@$d5$_C#d31x%tkc6_qcSu6n;5#It?4hzwlmm3IKGe-3 zNNmtq0HYdlwS>3KIJv5*u{K1k9bF z8A})&v~e272JJzHu|daoz}WhrGd-Yww?SfiBC*4e*vUxj0wi`V5*xHJ9A^GLB=J*7 zY|xZCOwBta@n1-6Hqe{_)NMjYY&j&h77{xOiJgYTu0vvXA+e_+u@@n+*CDYVBC#vk z7#Lt~Zbf2GLSoNHVy{7BA46haMq)oeV!uUV|3YF*fbM35hJz{++X#tmkHq#tVkaQ6 zbCK9pNbGhb_7o)cLL~M&B=&A3_6a2RRV4N!B=&nGHu9Nl5lCw~k=K2uL)VFds|V}t5q7#maZ_61 zpmmEdHJ~;)j14+N3&sYmF@&)}?SB{>G~WtigQosqY*70O#s^+af2CdbD zsR7mdF!nw92q(3~ZV4O*cAV=I9ss-a=4 zhQtQ9%|Ha6a{@t^Yr)e0N$9#{Q2Ie$(~Nvh;0vf4P&@n+lnrX){(-VV?QPInJJ5P) zP#+$&+6%-6r6bV#84w$^P8f8L7l;jNhifu1Fo4*gG-U#1gWBYFP&VkEPERNs)W!xK z2L)0O>KA~{UjebFGB7ZJ&RhYpL2c}GsCrNv6?Fd>NF3CTE`*AMW_dyW1h1C^F+lwq zP$z-`a()&pOhCSc}m_|_90%C*K zkAm2+HPjW-i1o#wwW1(7P>_P+8^nhuMexiXYzzlv4oDq{2KC!PY?ygBq!}1W7zv+? zC;&1XWB?SyxS)PNs7MCY1t2M0>d@DPgVe#?0MZ9?6Nm=&1wm|>oR2JV>%u{6ZNGDZ zOn_jR`#=lDkj=Xw%fQgX4)HHYIYg&*f*U?{`l z4^Wv6as$kL6Vw?P{y@*i1og>5av=AiuM4*oWMBZbOkg! z%3zQjC|p2gGc3)6^aV%|xh`Cifnfs?=OR9lVqgHp5y)&1hPe;1E*LXWaPGkhtcI+(7UVA|!iMAk{AZxt$ zfR0e~1&Kly5`wN{1us%#W?*7r2Q3hXuki-07iEU7@dhoGWQMKr=0mLU23=wdUE>Yv z1GB=`ct2%iVBiHE*C@fN3tFwmvjwy!4|9!o8b}ztmYahIyrLJ(=HUT#a#_J_V%B)i zKw9J74O)i>UE{qJWIA+>H)u5pY>hXlo5~7Z;|)2F5!5&q;K>Iq9D}a$js~qLgs$=a z1`>y^@jeU^hpq8G2?|~4y|X-^0UuT@YrKzxTmf6-{SV|koNK&6rvbv&c!NU>y2jfb zWCV1LcPMCeE#y2#p1B}432VGTD|VpgG4g=gD6G&m-k^NIin7LAI1l;W*_j~wVJoje z8!cENr!KOHfJUUC91f98kaHk1JR+d`iCJMQuR#SN{N7pca=AwE3PuT$(;z*tmDfHX zd$69z7z2`loyS-S($fVtKt}|0=`bs70i_kR^B5)ZoW}@Cc_=Hdzk}?7uDlKaIStFoYsh(w zAgvNSp!PlVJVqYyb-2)#*Bv0=L(XI50o|#<3OSFFryCTKknO4k}T@F0! zKyHKFJIk{dq!;r%Mjl>}z0j4{pgs>Pbmg@dC}5x~uN6UVfUdj--2=gjyz)Aam4N|# zB_?F$HJA&so`IjG1hVoPG&~1Aj}at+xOWyb-VeEV79@`4-dWHxYs9^?VC5ho@aj(3 zy|W;#h(R`h(ipB21uw zfUUeH@;t^;kjb#~7{U7!VCOO30m;BtUV|^lMp=2i7Un!A24T>y4)}SDrXW|q&SUHY z#TjhnwKQnSY&0XN*ya$yb{->WQwIDzM$nKbE9^W*Q;=g|E3ZK(55iYoKLMo{*vji{ z5C?W1<4cep*vf10sf(G6UqSQPBGB^~K^y}SJ&+S&E3ZNQ7FO8GYtSGED}3cOD2XhB zEjI_Pyat7Ul_5E$o}!_Q;%L_UuZTyHW4%YYU#dxF$3hRA|kJsH&P;b#F2$Vt^h zPF4ij3~N|0&H*U^E!_r}_MoN}*oaWD5y7&c2@=r#va+Dr5fDQTwDl9DM;^Q=nt?$9 zbaw`H^)g5SBqxFF5C@sTpcny)c*4gujxJWFWU(^p8e&<*8e%!vGGqn@d8F0JBpufX zicCg^AP@yggQ)9cK`9Be(4CPX2t+}8l%E-cz>9#vV;T%WAPO|30nrI!fm%(B3_&0Y z)NF-FfD$=W8M=BK3a~EfdRA}K`#R|#}^Me?5vBPh zWyQcNWWkGN#lcHsSz%_t)FKwviXznNVp}wed-W@P#RGxyHw*r0M-EcW*t!I3CPH8Gb{NOn0k(jLk z;1WH)z_geFX)PJZJGmh54CvBT&=4=E(g)G7p+yiMb~q$xIVz|&0ns3NP+J!?y#yLE z2TeJFuAu^{2Z@8&pp|YQaZoD;EUv-80BXO0n!O-%K;2xhI0FL%hz*)91*r!$YGC3Z zwlH*wDtMU?Xh?7}mZgFs0u)#vJQCNWa)CU~z`y`XWS}*npt&)q z5I8}D)=7gB9cWw^BoA79h%66YGYZX=r6tKI)dqaACrX8azPgiv0oys0pu`9}lM*!k z22%r?%LJ`iv|wOh0QDF_Y|#7`Xs!vw2DQ<1L2D417#Khec~A!sBo11~2wFn`VuLal zXelCy4a$I^3^t)Ya~F9{%VP$kH~ zz)%QcgIci+3=CCB>}Di3=*At`T1n*lYeAt6G806D>PQ$HWIc=xs_S8FO>eDR42mNp!GK}wjI*CH_+NHm^kR<7Z{t=^@8BK6-3}!-v+vz5LUl~CILa~z(D@J z2wkrRnnj1*i3@5Hfadu?YCwBT9z)fD!UJ?48%P`!9zUSspoTx_&@_-ZsEq)cY6r1F z?I?ceIx|ok0CY1VNZg%)fk6c-4%$DW4`qYeIL1&msC@-;-*8!%2J#Cr7_`0&)Q5mZ zC-^R2P@4^=7nD9hY*4!z#D=YbaS&%<0Hrz5)GtUsNDkD_1+{5Ge3*Hlcz|`#K<0qd zfoSwKX9du;Hz4ysX#=DVWFDw}2Qm*N2GR$*BN0TyFh~x>2BmpW)+D43+;=M!US)_g33=E*XTOd0@7-lc1y$*6K%pWE43=E((iy(i1+z*li(dcW=n25ZK z*F=H1HD^jZ3=9^~@)Fs7pcOG7H^AH%p}@cZTDt&pA1EDyFfq@f5fLC;ZRy1>QFuQ+dU|`?|9h}GP39_7l8&u4}@7Vnd@&x3LUC{YC z%&M|qYjco^4BVh&PgyNMY!+_N z*`=(OAT|g0C(zOqD-fH98@#^28pIahmIJxK2E-QO24B!>3t~%fgO4P&1F>be9YN;X zgV+iT0-(!xVdr*oD}ZDmYr44SflTtUXJTMz5R3we!`5_x7kI(eba8MpGBAM7Y6N>k zo`F|^k%0larVA2ckTqS9D~Cftma=ez*6u^k?c{z7TIhhXri%l#EDVI9M)I?)0JTZ@ zSwMlq3%bW1x~7X8bcQE%O&2%loH*7}u=x!9ETEJj{ECHv0d$%sXrY2g7|5P7Mvwvq zk;@>zK~`?Dh)95BARG=6&=Pv+0xupB(7rO(TCg4g5zzD@d`;ILP+DjN%SecTZ@6s+ zb7VwrfsDqwrVG4c5VocZeC2Q#SdWf~2FL}yV2*(ZXj312O&9oVN!XgMOQ1N%x~2|@7@mlLm-4{w*adAZWkp-lCCJLa zkioh+0NZJrpfH85=>jo1xWUWCpm*$Mfb7I_$L>^6IPC(dm*57Ugb2N3HwvU4ddDtk z4bCpoR%zO&3@>NJt#2d;{pjO%NNgrVFG7x~2qc^7+C#5K>}UV1zPG3I!zO_j!Ohw`oY$8d4N=@fDf}XuOy;3hJa)AiH2|x^93R8^idX4b%XEo~C&mdYUHqj$I9qYS@}CK2Uta z?$`z2QVzRg7rZJIcE>KL+sO)B(-jM{Ap>l;iU@eQ8tjf;1CVdB7(vyMfd~^w8SIW- z&{3uEJ9a^L)l+`QE-2Qqtm%>ht$r+biWnHBK&cZ{$;*J| ztw7?kpmqBO91IMwOL65vr7=|F z1|}5-Zf-knX0)YMVhrG;0l7gZBeFs{tRN1XI3qVV=p;hWF%ay$NXj@E89jwTqMV8h zp2GUv3=CYtNNTweYAv`K7-Fok5L+FEtNO}gA8IV6=+!%BjmbUIi$5z@|dSBB9>Qy%?F*`2#R0^(8M7l1L$;q za4I0Y>Ib?ZVB1(vsA?GSH$C#F~Qqv^4Ogo#n|H-~;PG>m1_a z%M!s$4fPgR_CO^R)c`= zLe0(0qjrt}uaqk;NdaXxP%uF*_lyS}qL!0cTmm~xF)go{AwEAZKD8pVBtEeyy%=&7 zV{Q`oB38)RcHm_s;6+?u0(>l8S{_I-LwsU!G9pYtX^|m57k<`QW^qb!3FOQ_u%`Ip zG=})JJn;HFhWNCC{9;g|NzTbHP6eHMn4g>t;zQ0?1TFXg9mEI@pN#y{A_n+*fRJMt zL7@m)<3#curSav-8A%MFw3C{m05%QmF)#tQ1?*z*vM5xc_+rR{8stC&x?ZMM#HN zmS^UbfPySHsR-#t-1y>@%#_T$%o6w+l309(xEvR8u`VQMgX{puKFH*v)Wj5qc&E&C zNN^-pfE@&i9LQOT#U({0`PuO~iJ&A^oC>;d8e|@5fg4y6Xvq%bASlrJbD=)@dFc%C z#i^;;umS**#K6ZVCgo&9PUu8j>5FkQ^_!(%a1^#x1h=wL_^18KwJjc@*_~?3>rWL(I5$s zx)HbB2UID7JP*brdA$!P6@b?BfZFchz<|z0frbu|`JnYZkZKi{{}Dwi=qyV}We?E- zTcZOSa|X40L872xL(tk67#p_61vEDW5(lXTvAKmoDj*oNW(6b;8ovgyL0v`=hOJ*g zKHC7~Uf4Vw@;o1?k4>-jE1)eluz5<*z#)uH%=uoRGeuzPGeKkTpuk{&%tgS&LFcx? z*lkE^CL*!HlQkSjB+GyrE$W z+BXOjFF_J-Kw@t|VuN;z!PK8X62Fbaeu2dPio|9@Izx*ei7kV~)H@uyqw8AaSUA zRS+ARuMLsdApNlV1ym=&*dV1aHfU`Hj18`LKm@cth1-R+j^q$%Py}l48R(h}kUf{6 zY*3wf4a$bq&*ZMF0GUe+#li>2C7?D3$P5q$sRPmI>loIEAl5~I!U3cXWFGoD2GDu{kbW2j*$rZ&uVcWa4qQ)z zG(a)v%p=fR7$_ICB@E0&U&nAqgnt%)!6_x+V|oC{P^@Wq_t%VP=DbQn(lxK z0Hz0|zmjv)dm2<2@hLEfBHde>1!|u~Gcqt_fMS(_fdQltBUjG1^EMgJCw*G;c zg%z|Rl|>P>ssXb8p`4k4fh7ez8-{KD!$Ocs?CT$xS=dq5KY*4sF?)h6M_c~@n!#s= ztbecq83$YcAP<@d1FwHzW?`QXTK{l^8L|EWJTZ;D{sCk%3-<%i6qf;r&B1*FWB{1W z!wtSE6wD@O{X+`U`UlVvd#vUl6B)R{GmRD?HVbzUXwuLU#OB}z9fQbf1!D7XgJ%}4 zL2Lo;7a-TzfY>732SM{~wjj0yH!sL#b|AJ4_b-sRJ&3KqAOKpX0$=}d6C?v&|F9cm z5_J881juIC`UmiRdpOrWfX-5ct$zTA7Yu73cXS;mUAuA``a$;S0zbwDk|5DRmx^f1siUzWxCuhP?hE7J2=HE+`qm&a{E9e*pQM zMFf0m7i|5*M37x*>mMEU$+nvIAA}GT`M9N}#kW$H2fKTfo4m2I4RV%W;ARS->1n_d$*iq)#1WAm|iWd0yyo z&oSWpK%<$8859`7_lL@Z4l_Q^!N5=kmEo`j$rLj%$b+^!KIC9vm?RHNaNswA)=>chyqcdBe)qEVnCER0|NsyLrpzsr5wl@ z22htBlztf*KpShpLZDH7$N&knWev@UU`f!TB+v?C2GHqxj3ixS37YSw@(BwiiACwU z(Bo_Liz|!CoT^7YuK~rhf};E^%wuzO%S#mZ%TQtANqlihQA%k+d=UeY3vl9#KsQJgXQmH=H6=x5i8-Ki zLU1oEDN0SvgI+M223nv3TGc?@5))F_l@ym0C1(^d#8b4qq&O9}x(fS36VU1k$l8$9 z!qUVXh9R}o1bN*CbcqotItJw;6Dn6CDC@E4v}OhErrW`=gatIv3##HlG;Dwo#D^_m z0UiDUY8HTKkUVI79n??-H8wye-+)>XAbAiQ)Fc7v1*sW%%UnkMIv3D*E-3mz$pEy@ z1$q@8NQeQHyg){JqL-s0*O7k4hIr1!*w0bAJF<7 zXj(#ElOqaRZv(2B7#J9k*Wu_RiJO4fP`%)@W}xap`_W-*Y+^xbK^>r3lj&8EW_BKli^`(&|C{6h=8_pU||KS$6;zNfa(iq_}qf7I|8}? z0hA4z`hEswg9fkPK-r*mPq4exK%;=L^JPG7lYdY(pymV%Xg@X+0|TfX!Ubh(f!qUS zgW5Tub_(bu08o1dWH-6%oj~VS!2AeWa|C09*6hI8AoGdApf)0?n*j|zqR)1DAqH8? z0a_yj(hq7wf!bG~flv@1W**3|p!O-uEg*FuHYlxt*swK165@!nQ$TS6k^`BCz9y;* zq!|f=>;iE?;S0(xAiW?yE_ERH!1RFB^?>df05PB#WG{#bO0ys~%zbmjiCYr|I+sKe zv}+V(2+|rR^fggW#2FY45V0oeEGGj4DD6UxgZFtrbCAgXn9I$;0GgylSBJhPYKa`; zj1W-xg8T@gK~spx=1CEGwo8gUaciQiKx>$w`48kqm|f^=qB`Um7(n;yfzlPIO%8J( z`kJUJ`urv?SpGoA|E|NZ}<<@+FI7}%_l!CpbJz%G;EC)XwH@C8fa3Ag@qk-;u#AQ zJLp6e7Dl$$AiEejKx>Uym{{vU3#~X1m2U{Onu zLIKbmH46)C5J-tO3j+g-I!J`|5NPHqg%M;Q8w-mU=&C(-P=AEQXEx~M8g$mTVU2axGbq1%9A|I9M2%SAgvI2f33O zw6=^TxEORdC<}8nXm(yqk&yvpR4fw%1MeM1@N%tc&?z#0AX$A7lYuWjn}HR)6pMu$ z6p#=$2lr9XyggW)hnoX59}i|jmurE-LWF^z1#~zG2k2%t&^iK6kkc6$ctNMlsj!-Y zDu3=Ppw%wWTn#93i5P>t09&pFx>=63nlXWmfq_Lt4-{k&4u=Tnc3h|oj|li~B-nB- z(8(FB^^BFQ3=AS7dZ6HhE!Q#w830?Z^$aA_!nlf+fk8nuKDU5@wT*EtI|GA?2sC+}^!G${!&-d_28IyslOQ)d0IlYT;0CW|d;}_IVz|$P#F3Y4 zff9*0$UovBkBEc0AnO_US?XCC7+4rNtXM$HwLrlMUakd7E=U@{T&M=n`YQ>LE`F9C z&~hzMQ4R7sl5&ucI8^y=kQxvh6eI{W4E!wjSs5TjCdk9!yu}3JOR_OAfcXpztP4TO zSC-L`g@Hj>9JDZ)Rgp0YblMC!FDrxD3?fw^55tygRf4prf)f%413wEWb@8)+%oGOA zLP)UMGOhp_zz>QvJ20C;!~?{!2Xoj&%0L_kM$q6YkH`^_Y0iv^pxzGy2S{uO%y~=< z!l1RppyO(OflLGy8my6w;1XHnCn(OMz)PlBM5civHX1C$A>sfsF@_POg@=Kk1*BX! z3%XouE;|E*2xz2+H5r`V8AL#*l(D8Tf+Chh1XRtirh+*{Ej7&t(Y z4JtCgaRR!63={&ApmGBopA7sgpzFx^S<=8)kbx4YBq-;@Qouv-gFi7#vVrF3A zVV4O7sjUZ9y|N%C12?F_&n^c_Vl3RCx{O^Oqz@GJKiC-KoT;=42-^@gbvz_Av+t?3JC%k$`~Y<%)l57GBcWifkD1BGoOJm z1ayoJ)5HMz%=|J2#!!%POcNdCLARrY1%U=5f)zl{n!(Ay@SKBzL6I?vshEL50W^-k zmXm?uH&m>Mfk6RuF6}-}1_l96usY`A8w?Bzl?)6FS2-CN48VdhOcMhX8A0pBKn4{t zFepuBU|{$KmWu*wVBi4x6=X9wk{B8ISwMTMltJs-*p7p|0c&zG&H*_J)$~6RTA8Pivm#~ zMNAA6K_e_+V?p@`v_74YAqYf)Iwhz!V_N|SQU%t{z`!sS)Q?~|1sb^{X$4$nK7;;% zEh)o!O%bgZ(NXnQxnjuTH~8&wOz`{Vm>C%0_sb#ODaXRV0KS3=vfeGNth^|*Bvmhi zfe|E*SQH0e2zMU5?v0s&k(rf~lYx<$3B3BP9=tY=5zIy=k=Mr6VaS5@!Y-U+Vqj!r zX5{1rub*QA-#Nz!y0nfBBF>Kx5rl{cfmMni#K9_MIr$kFnc1Q40lAZrlN)|G6w)%D z(#-t$%>1(CJn&&mRjJ_9oWN^(67y0(r@$Z`q!M2YIg|!+c9H=@JldHn=m$7~PpttH zC@1Matz?LY9S4JV*;-~k=-4PwgvO&She17C26S2t=)57YeP9A~;tl9r8Q2*?@sL$x zkaK%L%E6}+#e)wuLOl!!dc+UNp+%|1nJJ(JYLG*Nzzfh4lM72Ti&Eo@Qj<%IiZjbn zk&Z}$9`yr0cnf}f5A5g~_yIX!V@klMPl3;!f*ps2ab^|j!9cJ>o4|)YfxL!v>QZq@ z3i!}2*ik=drx8JxXu;3y0-ef)<=iNgc!I8j134aiWESk;9mEZJ@x{=b0$OJQUC;;) zdQ@|YK+*_AKu04Xoi+qIq6~I!5-1!&VE{Sh3~}seRyJoxmZg3^*=hIr5!L*Qf&I@by!3qH;WlFUJI4?m6xdQ2K<-3a6mE{p@i zK$d|H6oZEV?6|Ek3>&)Y^m{H-@yt4!ZU$9xB8T zk61?-pPPhqcogF7C0Klc4^B&Eh)0|ll?y!v3cR!ue4G;~i6`fmf=U6{sc(=&o?wT3 zK~6q{dIogTT4o;Xq_Diy3Q*yJe2^6Uj4)8x!p?63pBfhrJwhrywFG{I8jV)!W#%)) zgAz!5QEE*&US|i|y9$~q1Brt=Fd(%cHmEHIGKWKhfdSOa0*wrVGIJ_A%XF)67iwG2f%CqEg5pIDTb zm!4XTB9@bxmkKiiwChMOIX^cyHLrw057MI2gV+IfMn#EUPG$*Idqs&}K~X+vo(mKr z$QUKW89t)S8!&?|$3;@i3_8mig%6v-ga|T&`r!~Jm}F)EhcTE9BA6Lqx6FZfpxqy! z)-i+)BAFRLv&tYA1T!;$W|kpr5XsB{YJ-DV5X=ldnH0hXk)S(wK{O0A!)FE{BFy09 zOCf9!$;^Pf8W7|j3Al?vsRy)P5H#NdQVYT$HYf#x*dPqzgVxr8*dPqzgL<(bHVA|G z@RmM!q=$h4blWs6HG<3sjR1kvf-p!uXni5L9RjL0;)@tyH505^1TJeZ+XkQp2BbX+ zswKgSFbgD*k?6PX!PfABVgl3&gSi8?9uYLR!U&qYXMmjV!3Yg9P``u`8W`aDaZvAu zfq?;Z4zdU|8bQO;AU0^;EE#mi9WUgp1W>90iG%C}vAIDD1)w<^H2)9E>7aF(Fg9qQ z0HhuiJ|H%1%_1nQL25vy0cg!1j15{p0a6cgJBSTi%NPN21E`hGz`y{S3jwJCogoHd zb3^?Fx*QW^4yYsnP1L~H{UE)(3=ANDgV^Aacm@Ur&}s@>&Pb zS^$tA1GY{AG&Ke?2jmrydtht7KOpG@U~ET_zd)8SK-L4m#Ql-P!S}sD)qoE2hN($GQUg8*4XOsTjS;2>G)xC$gVrX% z*x+-}pz7x!nFBrt4Jr=00RpD}CX$+GNNmt02{1LF0ujdM0`;!2HjNvW2=MKGD6*Kg2Z-2V*4SnqmkI9NNms<_AoR1k;La9u~#Co zw;{0)Be5?avF{?WUm>x-Be7XPYa*fU7er!%F6)4~#|TLrbT$A?9CWz{j13yNhq3#S z)Xzp@FGpf;Mq=+rVxLB0|3+f7gGRNX?vzJjYa_AEk=V{iY=0zn6B1jBje!B?W;Gf*nLRs*+}f2NbF-s?8`{(2T1IoEVOgVaFlsca6!nQILoanOPp1_p*+B=#f_8*0vS5F4uI3WyCg=LHh` z4-#7tG!+6>V~E6#1hJuJCWF{eHR+rX_kileDv&tTu6hs~s-^>pJrl%+nzIgxy&s8v z4T=35iOs`>2wPBn39C0jZ6FvMwCDiF2DNZuY*5__V}s^5U~Eub4`YMsdKepY7yyh7 zTH^>~c81G=vm#!f?OV<4{|1UgW>^n zXA4Li)XTJiii6_B3CaewQGKCoP@5|R$_BNA;-PF%yEF~Tj$&Y7$bqs!J=St48+0#q z9h40^)3pW42DLvy7dL_207|zLpyHr5CTQgXNE|e;1`0byXnPx(4GKG0ID^`_FgCcC z4Ndc)v;-3er5_j@G-(TCgU-W)u@gXTB&c4HA7J7jdx^oIHZrKc2}&m*^`LMAxd+4s zVNf0c(V#d2v0>{V4lD>>Yli(UMbP?hkXvE?I3o>N4-E1L$UPuAkUv28aUz@N0$SdM)b)nR zf#MUS2WDP?3m zk3eh?hRK22?;x{b_8w7YVEDkmzyR_GC@F*FK=y*xy~6Z>^mFimmp6i#U<{K3^~XSZ zVCHR6fvmR$nFlIgL2@ATKr?JGJs<-#_!t;wV(|y4?*`HXGw+59<{f_^^FZsELFR$- z5y-rQ0t^gmu&lS;4-G$7_1_p*_Vvv3{ zj1QB$3Q9{z_i}2eLDt)X!Ufdb1^E%=5AYe#FwG1M4DZAk7%GtXF!LUvnP;K~Q3o;) zRK~!}1C`IPya6&MO&k)xAT|iY%mdL#!OsvO!N9P95z_w!b)7-xf%^QQ>KfU+ACe3V zpz;S~76^mP0nz$K1_s99^|KIy(0W@-Q!~hNTLr@FZGV6YFQoOhG7O+v1!OC33}4gQ z%Vl8j<%9-kJuGA~Eab99Ge-smg)b11Iav_8NsBFP2LptSO!ji^&{)d^5drB2#T%}3 z3PF2M;A>!^&I36gRK~-^zaib705YxNPXPCi@V_7-Ci(^6E zde(iQ1+D_19SF=UtUp0394~{GtEz)USU`vCF~QCFv=EnpnT5TViGcyMI2P1%=iUo46uLO}D2VL`Dg;;o;#Jz-)0&d9*P+YBl_S#@hbi(|oy8}&g1 zISjfu_Bm)}7j$v#A&@w9aV+TCR@mZL@J(CL#j&-Zr7qCLvCBX%fG&;&A1Mc2919xB zWrZz{y~qGr9P15QZ5j`9zbA+ZTO12wHwbcqO!5J_nSoJI0Hnwt!~rdi6=h^#0F48H zJtEJ*yP65SICcieIB%`2!z`lp(x<8FH4P4hsW= z$Zb$S!WPFuuWw8QjmwE#1-YP_5yasT0WFZO8T0nYWi(^4c>{;s>tH6t6LCbYn zVT)ry*KV`I7RUC1^t3RpMqV7d4!k&a9!RExaX)x*Y&XbK*y7mtAP#JCEck-KKCnF| zBA^3pSSK(Z1uu>TUspMi@icgGEa(tU)=6Mx4k8CY@iUbXbQGbB2q*?vXEK6<-9rR4 zOvgHl5frXIA|FBFHJ1_8rM@9@2E>^M_VyEzc2KgJ&-enoI2OEGcmddG(BfFoC=4%X zcqD^$a}0cOEI8D0ERF>&A7$MRYCZCBgT@(HcYxTi#j&7~9|7)MkoC~Tv7ocjSoeaW zNroGIdgDP*s#4&d1qzqL?cl|+Wgr(G-3DG9dlnRuCvJfk$4Y@#DW3d-v^W-IK5TI; z$d#yzW4D3qz4!~fIQADP*e-D)Esh20_28BV*$Z79YXM^41hra1xIydXSs#E#0wcJS zL2h^iDraK2K{wH&oMi|~B;p|dh=V*L4(5V75Dfe*4Xg|d%#0k5z-JkPf)l(r7L;6& zG=RBK4I4pc8G>~2v-E-%zJdliL0(5v4ibVbjobrL1JVi#5`-ECewGKI#j&7_0rD_7 zZ!tlNP|$D-n9sn#;tBGWEF)-SNq7Sb0|V$R!)VZuH8?LTGlJL*BA|hBR@mZL4UiU9 za6$sDkOZYJeio3K!k~H_v^aJp$bju2Wp<1pHiO6q5XT%S9FUAN zBj{*C0R|3Gbpsle0XvV0K^WAE1}%>L4KmRklq4bAyNiPZCPNBfe7e`W!7vk$3g^jW&vvs znByP<>a?@wf;k=x9H7Vs6&YYpgBHhvLO>E!Zh+&HfuCgyc>ODAsEeNkREtQ0ay~2t zJOWEz1e2gqDXD3o<*HjiwI`@*2Q?5F=Qx4xas;nd%>|`Xkc3QmG6Q2S==4a&U|CSJ z3p6w%2P*b9b1*Q-gBOd+Lk=lqkebB8z`(W$WG1X}!8iw`UK(Ub1;`LkM_Lv%dI1ua z1$D2$3{blo%m8hAyu`u4APbr)0*T0hx^R!dR)J4KWKaO#)5^vSa-iaU1_lPUl^_d2 zn!o`8zP?l(RBkgUfl@r{GLUYt6oWD&GXn$L9FTe>WrS9LA{KnY4k!fQG6`G#2|lfG z^vX%lR3ZA6lSu18B^Ve$*G@7(ubo6J=9EWTpX*y{4xyWW^@RL4^<@v^Amd zg9<^jbBqi@APSVmQI}GJQYmN{hLIr%M1f{vQ5Ar+LHZ-mb}&*?7?e9ebrd;QS&pu? zOiiWmCd+crq98KXTSD|@fSSATWtH#2iy1-773(=U;A}=t9tK8c4o)@(MrH=Yl1A8) zNe;+DNC~idA#95r;~`hTftE~xmZDLANh5qIBmLGWrWKTylqZ9h6hK!i#zW7W124b> zuPz%=YY}O*{1AH0DdbQ<25_1Mt&RmPUmg&iB1nGae%1dc3*LA&}8ydD*NhwgwbI|Q``K$SX(h7BNs z_^@S%p!Nf(F#w`L;-F=OAhn?FFd%VI+Z8m33R-FiYD$3BfC#lj0tZL2YK(nn2JPJ?IQU zkUbza?2JN?UXVDbRSjZuLxUKUl|bU4xhoJGrXJK|1Pw2MvKVNN52OaFpLdezXuwzVqjnZ`4OfUG%p0x3+g0;)PvFo zZ2caH4Vp6r_2fZr0fhx@4IXH&1;z%=f5X_I*$J4Lpm}bPnIOF&_b@`|0+G*81lbGI z>javw0xeQtU|;~vVZ+1&kiU#8Yw)1<>L9T#kk~FrY|vFaFul!4;?kgXaZq#Ak=Q0kY)2%v9}+tQiCv1sZbD-B zBeCZov3DV{k0Y_KAh91JvEL!FnLumgpl;?zV#^@0HIdk6NNi^$b^sDP7KxpO#4bl- zw;-`6BC+2ivBB&2K#cbW=;*2RG;P|*5$5F4sS2Z;?n8xiU+UnKEB=sG=6 z{gMh2hnkZGVnfX-Mq<|>v0IVYeMoHNGZt5X#G&?XL1JG%V2EK;4h2~s#{@fP~8e+gX>Tb!N34M`x#b0g6eUY8t|HGsNc^*&n^VH z>oSxLYS)0SdjqY%0=erxR2;NE?J1NE8ZUnhWrM=@Ba{tl2mXPwLG2yTX-FV*KtC5!EFGjJCWNSp!HNRe}ViCV}sh7FgEh~E|8hTV30pR zEoEr%fzLn$iNW-O;tRwEtpx$GLG3LN|A`m_18AKQC`>^5L2@9sgZvEQ!^{KC4#K)o zAblWpAR2w`mWwz8!wm+=J({4n0I36+2X4QB`vV|d3=E(({}2|01la{*f!c?lWDe2` z;^R^W+P4GK15*d{6NnG87es?*r$B6&oQwoyO%}+%ptU?8IgtB6OCgZW1Fd)Z1#$?; z5K#LDN~52FxIlt|;Rz9EAim;cV7P%~0gMT5cR|etQHQu07(nei5F3PH>OgzLKyHQk zqeUJOZy@)B?tAg48*NOo`LvQ82g$m&{;dk{+L1J8HitnA!{H(ZUteG z+d(w?8Hh`WJOj~_$TJXiL>U+gh`1Maju-<2XbKbLCJ=_XPv6ME$Pls|3rrGRlVxUX z23APKnk*Mk1u#t4WPJd&&p=bhPN39+G!cbZlLa~piUqXV39%+C7_ue{w4jKYkwXQv z+=_`6wC;zQgY_h+bcC+S@&>JMf~?6B0x9AFugUs_ye3NqwCDk}ON9lpCJWSHM_-c# zS~3D%lLcCXjeAWNXmJ^QO%~`HS=fPvpmV5LU~96XKnt`WYqCIVp;%yRvcMM>!q#Nz zgU)H&jkG2Ud@>>CnygKr8GZ2DD-P}@AisdwJlvqe#UX38h*^^bTA~hHlLfjL7k0nw zN08~zHCgXL6a3IMSy7+`0?_+qK^N$;Lf2%07B{g%*JSMkts8)@$pUp{SfOjO)IfS+ zYqCHmbAb*l1TDVe1}z(7#j+*~bSOJ3Y)zIi$dfqNWP$o&J*>f?6+ztK5QDDC0v$BS z3SE;0>a(&!*JOeEovb9R$?`#3lLcPCgL_TZF61>?PeB0*TayL85E8QTibVv}3W6@f z;t<&k@*G5lM+CgS3hSCI&|zQjHCdvdMIW#=Su;TPU|o|1Uc3ielLhLM!|#^`9m2^9 zTay(Gasg~jmLte$*qSWR(W0!dHCaU<8Q7Yv%b=Kst;qt#0QNOmptb0%ur*oWwUDqi zS^Ghz!PaDfwi2+St;tG-99RfiM8p?gz`(i%wAzUQ$C@l1kQbn9veto|Mqo{r8_0I( znk*iWUg(;vOCUCMO%`a89xHTB)^$)AL)T)}d92ViS)enJU~95+L2iJq$(jvvKk|Wv;6+%Vr6f4lWPz?i;Aa5^=ipkC6%6tg zbWIlMmR9(hEO1_it;zBMc^I}P3w+Bn;Wb$YK_nhU~958KuH9)CJQv4!isZE z7H9+wz9tK_-IEozCJWRig|Ep91tkjDnk>*_U{Su)6Lve-cO!`5Uqf?Nh$leGzy zSYT_i+(CxI)?}Ro>4B}u0$=bATa#4+N<6SNS)djEtgtm%$sm~lSd-NSx|DS*Xn7K- z!33H-Kwguj3QDIS3GkXMRnT%OBGzPquGC;V05TKQIRkh45NomwK!$+YOcbukS`12N z&^1|iL5sjvfh;6$P1ZTkLbTl=^`mRDJcTW|85l%)Avd|QLbzh0jOvn}!k`6K;;amw z!VC-&YG6tdBmokZLR}<HBzC05U+9&*bMZ#N#|V4r7(p=<=+=a#kEhh9GsFRyr1SD6uc{2OR_1Ssghn1$-+zYYGiTcCM6kmo_&FVI>n&>S6z z55l0eKA?Fj5F3O+e9+lepmYc7T7lGq_U?n^Ko}$sI%5OG24N5%z8(uw?_=bDP=$y% zQWQ(>#?XPbunSQ$fUIPIt=9sL8iP6uAVJVH6HFX5hXZ4S+y`TW=0Hc+cR}WbN7r{T zFpRG60_7YAhSBw1kZ>4X-vtSW(e+)Ba2Q?R1qp}I^<9u~7%J<#j)2z9Lf1`!&JlsF zH38j-24aKO1%b}b1hGNuyI^$@&cd3~3G0_4msP~HIL6<9i$iL|y2R8oM}cfrGDO~S`+>;yT?It0?+PJueb*5&28L`Pn4uNXN%%cz){SVcjrt~gjhsh*jG9dxiCE9go{=s8)SWh~5)HCY#s*JObY z?*T2Jfv(8{U22BDCJS^T3Up1@F|cEBos$JRG77#XYYAxS74)2}H6S)@O_n)`16h-m z1u_n{CW{L+(GFXa1vLvuQ<3t2VX?K-wkE3^v=RV%PS!cl5&`I%tX&{+=$b4E&;kMInk>*UQm{2ylR(qh&^1|I zAQwQ_WXXfffv(AV0uqO<$pWpQgRjX72dx^wvL*|BtPN~U76(WX&NW$kk77xYuM&M_!Y42xLEOO&0j5FUZO(77@^j zc=(#EVvutnGCU&LAU#;uWP#TH!PjJg588sQ$pW3R&5CtRRx8Lf*qSWR0c`L!S>SbP zur*nrqvcp(YqCJA+u`SAy$8h`Y)zICD57C&vX+2kU~95KF#una1=>OYKPL;kh7GnR z>j)?{!PaEW0htC{lcfgYpsmRQt?48BoGj24->`GC>OoG!vL*|(rw(?BENGo2?3}EJ zAZJ0>WPy$VVuh~B0-doATa&c~6q3+2S^q%hldvXh9mss>nyh;uy;#;{fzE(qg|5j0 zA6o`plLa~}5Vj@@bSE||bWIlM6fzRe$vQbm&&e_X1ub+<))eG(vcP#6wk8X-IS+nL z7C%S};Wb&{W8z?IvcRkAU~95KTgu?)WPulj;arpT3$)9HH4J>{m54nkox;{+%>ZRw z*g09C!A@4#nk?{=RkSr(KbaXA0$3Bk=UjpGI*qSWRJ~;R}S)L$=z}95tfl?c6O&0jbHQ1UgP+tOmP8R5*589oR1v)s7Z4+pD z5~yAWH3k^x_`}c1QbAdhr2<+`#TYCDx}H@9bOaS+h%9JGeJ%$BgB)WFQwf6{V>DYa z1K0omQgX0Evp{?Q*cO5;02vNyX)w+KX#gLZ1z(^AHq!uXX0R;ign>O^GeLK?$}vW< z6@krUV2}qb^oE>>1yTS$_6liPmBI_qVyn>uut3+5LRVMOd9f8E^Z+cRQ?KMvS8qYi zvr<481f@O(1_p5YUvOD zqh~5X!eR7GB}h1|0PVpCEdpR*U;u3!hn;f-x@rN&9z9bD5>~_YOeKBL`9z>L76SuA z0Ei7u4^bdCR6GuPjuNO&DFTUu+hGh0%^)^Z%{&krs&_9E8x(r5x(rko!q_0CFgC5v zJlYQ$0fM^oBy{}>$X%c_=|JmLKx<+^6E`3>sICT`PX}Uy{QD599(3Ox?EE8G`-0l% z7J=ME3Dmo*|zyLa524o&63_>Vi!G2agM|p@J$<0?2KA4S&Fc_l zU;yP+uqLFiKw8TZU#gd{PjD@ZrI87-YguaKK#q$iWR-#KOc1S}(!O!3w&Kl$nDa zbl4m6oo_!uS|Dp#9wM)00iSaMI$aaGmIX9dg}#=h5~Klg=i3j^;uBw7YgyJH-}$x< zv}6UkmIZVbH~f4d(7oT-?tBvgO;EztvM7Si7XmFgfURW#U%!UAmSrYr@)Nvfg@YUU z&bJvL!@%OitYrZ$JB6)f0Udb@J74Gq$aLsh7Vs@y(6ua}qs(A;zJV83K+hKfFG_%} zWtj_d0dy@3XbA}Hd?7B-q%3SL%WY!rd;=c`0$a-hUI>D7Eeq&e2iW;S;1GkZWvK#r z1iF?5`OY`c8H%KwFJz3gmIZW%8lJT*3z65doB`PnTgw7E^cT8(g+&C^+kC&nS{CrxKG5@p_JP6}x|T%+ z6euLDWdR@F1zpR+0@90REeozY-$2Kl!Pc^bfZPCG%K|!kjl{Jqpi3?XHiMR$fEqfW z&KmMs7OdwBf!Cd=g4dl8v6iJ7boS4FkOd&aL6Z?kYgr6It7AYTwO}(1!DixJ%W@E8 z8u%n3tZP|7C+M+_9vn2fmIc~gMQXBwlJ^Tn1_maEEufK%(X}k}UdsaB+s??qP+XFd zlA5NM!NA1806OnQFN1-Zfg!%6vLLlsF9S600=}&T!UP{5q=$Mnn+EIG?&K4DkcF{w1Ekx)#V3D&n*T$kGGS zmbZ+a<3rlI7TT?7K`m285Ak7Oh$u5jIMdn%gHQ(-VRq$qE}Fq4?3G47CbN-CCEnL zxjmryF;G}QdLGOSpgXQWd=LhW`GUsOA##v4FQB;(kQ@kutZCt2KTxc570Um=pAGD?(iaZUCbGfc>}O6CV;j<|I(wM4FqNg#4v%mz^g2GEogD9%6_7H^1kG2kO!6bP=1F(&>FF9XoRek^Ca zm?bi-W#sYZk-5vPl*j-%(S>^zj|30X0*%QE3JJ0wAYqQ{Y!^^j3pvBZfT0TM43}x3 zbuY@GH6GA;1du|IXPFq;Rx&U!Ffnp~CJvdHSecm_7?_yY1wiXpSXe=0xJ)eU+d$I{ z9IUfJDmmCg85kH?K=WQq*FbkFva+zqf-lwr9TLlO7o?E~bO$oa8PGZw0nk|`Of0PL zK$<|aqAcnl5jN0tCQ}L{$N+X07OxYaF_CPL1|QIZ5Dw6dL@d4_Q3g)X#g?GOR$L&0 znSqIgeK`{Y12+eYJLnu=o=M<^FCfbqcxHjvejp#QFtDhCIR5uR7K7Gcumpov+OdF+ zGGrA~1o?=C9h6^rDL5HI8fNp(eH3yl_ zz_SNrx&?^M!gCNbIcf=FbMUZ(=3uQrY#yEspy^+05LD}=)%5(&~%3)Ukb0-CvHt!J!cWnd5yIS2~!MzD;82>AA=W-v!aBpIZq zg>e-t1A~HSd~N{)Ya8QQb_NC&kz$Zc2jf0=1_lk029OK7zO1_lce@QEW68Beh@FxZHMfm|>Ntjs~A2Ncs&8E>;QFt~_-Vt{of zBPiHCL_h(-I*Sn$u0A5qK;bo)QI(B>;f4rk%_HkPa2PxhSqL(1KI3zC28I_Rpg3n; z053uYcyd5)*#%NB!2`PXm31#Dnq+wHfy57jQk4QvKgjoo z+gKSGRCpjqxNK!*V9?-M1PaL$H$fN2^SlL_fATXc1A_ryd}$H`>lu*wCVcUw1q`fb zL9Vpni!Uu=U_A%2%YkPr$oz{xSs55yc#eVeUgBh9U~uP)&q-ony$aIn!2`a2>;_1E z0FN%n4L3o{7eaU{K%w*ibZL4759kg-)<+DC3=AVjv2XNW?+@5eIoh z9LxoYGw`$2vx19M(2d&sETG^7YXBt|Bn@CLRKo^V1_lX`E`F9CRt5$!Q0V~jI+Ajb zkT_KNZjc%f8x$l6H4OYL_gNVr1t!SD;Jn2I;Y+f?%ON&7P|(UU8nQ4j2-iTDy+pAw zFo=NjvN9ux%^(80o0nAuoM2f*{(^k33QkBI4E!vh)Wy#NGE-QRfq_AS)s}Gu$bcS@ z$#!5igUC@3#~#dK6Zs6{I52`1ck_sVmL#$|GlFi16=2{5iS2+nkBLF}JM;*bUmz1f z2amBvGJ;EFk*T0~ih??c2~;{pgJn2GE`!_`!wAyC!@$o1QZ5Wy!~;6QWiC4dg9zvr zbJk>VdS?&;t?yz@VFX1ii%1J7v7~}IJR)B}sU;1}5fNzuancz<`ej5w^SG=TV7paB z+&~V=1S``J0aYukSzwNVh$%=W8_cl~F$Ec&1Lio0fYz(C=7KpM44k0I1{E3LIAUku zX90zPB&gf~$0w*jWM^RDXGvoNk)T>c5|r~{Dc~Vk@&cG-U}s=pX#*X4Vgia0DbT7& zHhZv3K~+4cs%MSPpuSrW_^_2&ree@BE{uk9jM0oH zpaWbc27p}fmYsn?9<=R;?NlrS149`H1A{o20P)1Z1jsA~eiqPu*$NDdf{dzs!raV! z(tMz+ngqld7?@NTxVi1PnfVwPn4wHi6Ge=H8MM5E8+7RtD?bA_Hv6MFvk{eQpK@Zeb*~JP5U*8>e`M8JYPIChbg285o4Yia@Sn1-VKDs)+LAR#-u|V1WY6L1Ma- zB*<)OR>(zJ+@8Wr;tUK}?zSTOxE0u9X9m#Hb4G?B5CuvdObnnn1|ocs)ooU9BC zjEwOq#rg3WiFqkGsSJ=~Q$XuKK!p|;(5_96g3x5)elS?vlQz4w9)Z)^d5{7ut+7<@b%}t=iQ=p?{64Q%~ z7~DL4Tp2Kymw+ZM8PLy80j)jC#k-~?KCLJdK{0EhO|B@ zvp5Bm0CMt^6LSzLF*zq6v>+`v33+W>foU-VWU11CU;6~BhCwuJXbMzS!&ZzyDsV(4 z4c_vpS6rD}l9lb?*jPb^BzOHV~LG$%7J6=pctI%yia~QU;B_B*$zX~B znkPWgurp0SXP3j)Yk=6Wb4);LKxdSI5+BGM5F6B20AW(jD*^3EruLa5pfgZlYYLFp zS(t(LHbNK5fR4?Csqsb<4?IWVpq?m9jSrG|1QHu`95qZ0 z=qz0rdmfUSRY+{mKrl?rAtZ6oof0r{&^;0`Ht4KH7#nn71dI(D@`ACsk=8y)AhA`D z*ak>!TO>BlgW?+D^)sfgHNNmvH2TYA0l6W){8?+Y>rltu=9JH$rCO!vAd?gYawD}XJ<}i}@ z1td1;tX`O!S4iUDk=QJtIRj|A5=3IlA+e2+*zrj0Y$P^lzYNT-ekAePNNmvNE0~(i zNaFjE*r$=$zmeGNpiT?ao$^R*&<-Y;ndV61&PZ&3Bz6-LTZ#=4k7`J4VWy7$h;wF#0S(? z0;vN{rhqoff%woMVz7X=A<)eOof`ns1KP(2lG`AHSQ`NfACMf#JoGa@qCkp~Fvu;b%zYVqlO5F`yVG2U_!t?2ia( z#F`OM_=4m>H2N7IySRuu};i=kzABtTwIc$pQG#Nu7Kd=rRy5%85!vr=$abqrkj|h z8JZcS>84~Bl~igfnCMyPnS$2|z^Wcncf5dN1Uy!OXG{X$00d+x0OxQ6e0Tw(g2a&p z9NSF5=@;a15XQV88dh3^WEmKkLHj--Ofbm|>KuSs5Q3QjHFYvGz-n8VJgA0(ut6l| z*{h)46d)N0W@Z4jLLh7q$qbGj5DS8t8F=9;KsF14+y_kxpfOprv;lSvBh*QtGKvvY zs4y@vfXW#d8&oF3*q{ktMrff5I^G8+t_8|((18b#aj@|LkgGuVKY?gsF{qpag)+z- zkRDLG0z|_wNDjmXt=9mt!9@rIoLk0%SI<{&>I)IqM2kCWFL57!;P^@dub@1_lPuZ66@LFd>+| z0ciHl0!^yJ6d}oh#xOu;!|XKy&E7-XwxCo5k^|WrkE91=3}_4jq!+{nVVJ$(F%AYq zo%WZ3f#E1f0ThGOfiQUd14$jI?++?pp~}GF0#a9xb`}?C(FZ6Dk=23N6Vcpf4O-~~ zl7M26Ss-Q)v<`v!*8$1Dpri)#FDR|T(f~*w=sGY^7=qX!3^NZzLuw3=CEP!kt=)@*a+Zmz@QLjSQ2o@IS7nOh)2@qa>lsFiSJQ$=q zlsp+4v<^tmd?xf#_5=95t-Z_&NeT~G8LpjTG+3}vmZ7=&-mbHYh0ml;d3BguFtwF4MQ_Md^lpwZExqp2&2 zySY>T<+`D`mu)ToS-z)l|L1a@*}8&l z2GdHWnQUyJ1hAHAFB{0MsW1M|5UgNynAub*I4fzUW2PYwhZ`ru8?G~3X9(_KU%|PP zb0vEl6T=EYh~HA5{_ha<>gW{Yk?<-nH?x9xZZ8wmZ(7Gb{C^{LW^0Gx3bq{_JK0up zv@tR4FkB0^Yw5%PGYoko9A+MvY3Pu4pnMyXn=u2}05+%r*QEZi=`t|vU|YeylYJ#y z8xzA?c8EKl-u>@Y?vQqXN8;GS|7W(&VDDg?$=1mZ@e4HEm)`yl3UfY(vI8B8AdL?= z7@kR8oWbZdb0%X3qxrU+W8eRGIL;9Cvam9;WK=kLV1oGpgEP)OJ!_c`Y(H?9b?Np0 z9fmU)6EY4ooIK!g=0L)k<4xpxXb$V>VNYs+&2{0GC6EMbe2Vxfgyd1j0IzY z@&O04L&r-0i?x1XyYfHm#ZPeBXnXvhfzX;((7BV4HLVKZ79S`Ng2X_rJalnTe=Z2L ziWC%gd;tu5Kucpl8W>m@gF*d#P$3CAj0q$LI@StAGqJFP)-^IQvVjgjV`AjU1hpTT zSgk;7M48w@tCXOvQzi~pNsu51`%`Ga#K3e7bb%TZ3#$uAf`y$OwEl;MiG>~1b!B4# zb<~&`IY4c9cFASf zsD$qW)f)_KEXzSfET|3w1ve<}80Uc2bqVbQ@j(~1EmF89SRZy)u3Qipka6+kiJDA13)GnW?*0tg=r829j*0*fq_Bn69WSSXi1sa zAJE_iBLjmdsDuYKV8lR?l?|#B7#KuBmkEK6UKbN)WMHUcWMB}JVPs&~0Ai>yGBAKn ze+8=%2AOFHx{MK0kqA07GBAMr1WJ#Lb3B0|w7ydaqzSZ$S_oteXq6+_U{Lc?0<;F3 zsg&U(69a=JV>D9U|tH82O4fxD9C~G>{vkh za-qBqFfR|v+Xv#MFfi@}xdgP7MWG1Fkzr+EPy|Ik<1SFIGU|;~92d7ZNz<3KJRR)&20F?rrsRfdH1d{3mOM!041{rt)YT!$d)EuxBXaWQz z^%yGk2_&^1B&7n%X`s9X^06diEI9H(*RX-oML9U4%NQ6WKr>7%6L-|JfsT*^NtJ=6 z${83`bQl>JK-m$rP*svK7OYB=F^0XI!BC}$K}nJ^nze|b9K?uXDq>ItrBOx$1{E8q zwh64D!~)mGS_V-Y%>=dq%$0#_0-YBIvTH4pCb(n*)Wi!&k`SlDmDDgYFn~P!4Wb0a zvtav}iWnGF)<9Lsv4Ne2q6!=&EEBiXvoT13j@$!#*AlESnyCmLD4>&-Ko)^c@Inh! zmWg}n*+BUX6t1kG+6EM^H7G`uF)*lrCa^$8ECS1*MhwKQpwRbVg81kJ7FA%kGJ&j# zgjw?#tPC2sOdta~p$6!%BY9Q`0GTNYVKOj?nLt&EgH$mvNOU$aG72(Ic9H-o zlSH~qPYN!>z#t7_gOtcXm<$ZE$oJ}j>;b!kfk6)8KhRQAc_gj`1A_v>b0Aqo#K;?n ztAxarU|>+@f`*PDs3wG1Y$yzJg(}FQhQbq_Bp4XfU=q-J9#ru%G6aDrP>qRtZy!hv zNQRLi7(~Go1kVRaz%WRLks$;`fhuf}2_f@AERb?Wh7g!KP%{7|%*X($DZ!#3A&@={ z?O<631_p!zumeEaLFOYIfKUMT0!%>=+=U?HL83?w0SSS|DH$1pKon%(R}ss65CftV zv=#yE1dviO1_lOhhR=+_pBaN>iWrpUg9Jcoc|n3j3`!tzWrTKah9U-#&}YVACAc#{ z7D3F802|Bz8T1D&lHdZVE@4orV33&);)4chc@SdCjBrCh27rfj7$QIvNHH@*1tVA& zB(PBo*F|=C1%uLjkN`*%*x?mWhafU&_Ifjk`h7)p5Q=2APX?;K{f{DYDN^t!(>4Xt399v1`I(U3e+`0 z@;FEqRFg0=1cO>JdSHdYSxgKJ1rX+bCI$x3Nw|y*aA$+`fI1Y6451(jWFj-eL~!E^ zY$>QFodDXm$1rh2J%|Ci5tA8IKY$qEBLx{EK-3k`jy{k$SQ`Ta1BOnBd%{8P0V!r= z2!|}M1d%4Ff%@sk%0kpfjA>WJjm`Oh^1g-7#JAVGcYiKOk-q- z02v4hPez6a7DfgJkQ*2o!a#aJj%5Y~3``fOkEIPZJ`O~Itl$QP30nz+94MQD1R!?C zfzI`)0^1o3qClQSF$%O<5~Lg{m};3A7&^dOVnEbPP>%s@I%*9*A0)8^q7FoXDr^Oi zEAds(^FgXWwJsw=Fo*)Vhmipu@SxBJ9f;1z5VeqzfnhP&k5Qn85opevks%7Sy&rVl z1tUWgsI3E<`DSE@0v+Nk4R%Qs$iNd2CM>j8FfcHH3}#|5m=9W31WHCs42JVTG-zih zBSQpecKsu$%gkUnA4Ic&O^5)snLrT$QVoiP9EdQ;d{CNTWPlespdKG+sFINZw15k2 za|R;=Lm}7$a3PS_K>lK6fKM@l`~~t9k`TyKARi$KnJ_UhfL9tJYy=gd78e*ASm>tar0JHKSn7l3 zg3^l5Hmrt5LYvC@}k%davC!ONRW-08RTqcn0}C+Ist8ba>z^YlGl8nq%P!>2Gm_h#K zQUNmwD^_z~Ta6Gr=Y>fm{a> zX9Kx~nTZoQ=0TwhiR~n?EGsxX!6Ka8p#3q>-7t9OZ^3z5AC`&0G(&NDVnJGI9_WPB z`~t`^sVK*M7H8xal_;PH!8zdbQ)#jiAM8?wl8n;4YzDY>pk4pqBV54*ig0pn0rd1z z22e17&bS5pEIv7}1mY>M9*_wj4};~wuFp+PF=l}H5hMv$1v0RNfz%0Z(7qDbxv~R3 zyA2sYgwz7ynQrKW9H_1Uwdp}4hM-mY%HZ}3WI+n3bqyMA1c`&1s36^-`%OV?&|)i) z-c;xqGe`}n0SZ>bz`y`vgY<&bfJQ+zKJw;jn|P|F9@jRC0# z)t+GW&`Cegf@+ZXTWDVh#Qp^uI0TJZGcYiKno6LG6(kO7z`)E&VubXaK;rq}DjniS zP*n_C=Oz+8{P3cu|Zl>L|(n80_*g4m!jeGnh45lUdL-v9?NR2H-zgwT2o zP(p$$XJBRkB?4qVD1jsMk$nd;A9VH#vOFl$AoE2SKO9q$K z;93Y&9;;*)7bU6~LRxzapzDo9m>}J(LktWIAodmL+zE&cxH_wHjyhpt zU;yn20PPn5iGv1SL3ina*r03BE1Ti1f+}DP(LFRz&Mgge- z4T`2i#X%=k?1!>JL-L>tfIwi z2n7ucf!Ls87Bp}GVuOlP&K-7#KivP#`uadvZX-4ODD`4xs>vgNjqo-VG2NlsP2sMrLZZ~$V1^nyCVAU3E7T?9=7AaM{MBn~Q0 zH-f~WSp~!giG$1pr9TiGR0V+C4Pt|eXpnwk=zK9K-GJDjDg}f=YwJPspel(GTAYB2 zao8Gi(A*`A4XQ>#dO_=aKp3VMG=m1y3tG*xk$^HfWs-NH1ve7=&SZ!P8Vw zdqE>jAibdc4O*uRV}q&**jg;m8X!h!F#{@1U~Ev;24jP&MVNa)>(@c%fcyyZ3v3-b z$S*MUpus#C8$3x3H6Ogj3Cae$8OjC?+riX>nhh{Ec#joS4S4+#lnu&*Fg4YnCJR)& z1BngFlQ1=#k;HEyu|X5@Ff~=6(EzA9pnL)IFKB)a=3nrT2dMC1U|;~1UyM-pR*+sO z8~IGcql^p;AiW@CL8k)2)PrV-VQkQ0KQQ)NBy+%fprG;i4apqPtz0nm9H3?j)Lua( zHmJ;mxnBx2LIgTuhk=0sbgUOlFQ_bqsnLh30hN28auue=5y?zY9)yYegT$e33r5ll z%AYVb8AxhCLo=Xo0Hxb%kT}%MElBLeAU4!Y(4k!*^`P_%n%;()3CfQ!_GyrMs5zj# z3KPEx5{H`e35m@C+OGr^S43i)BeA_eY*1u@?y?23q3S_*T7ldH%159BonUr>CaPiV zZjgGYdq7v;!Niv%iEl+>A4Xz>PMm?MzmFsix_}8L4!UX%#%2fYX@c6t17btnECymj z#ic=PsJI3a8@vw-s>U2i+!n-!`qv4G?FKsfhlzm!G`k%R5{K%I1+k&(6QOEA)7+p_ z#$fKOKvGi!RRhXTy&!R@Ig>$bs5#T2YCsd;;Jc-vYStmC*#uPsDw7X`#Gz_Vg4j@V z&O+6Irous|WWn6?1W66(vOie*R|W0og6fSyVoyY3uR~&AL}GtOV#|Z}SV7IPLSiQ& zv1^goi;>tTk=Rd=*t($oP*5``A+bT_FDOldXwV=dj16k)!`PtKB8&|xt6^-=IwTky zRPVsppn3sWBC%n03djwhCHpYFpf#m1HfR+Nj14NcVQf(Q3C0Gk zB7(6&GY~NL1SGpaYj%cd2ZFJGBk2X*xCRqvgO<;raNtK`gVqPZ)F>f|gH{Q_#6hzWFg9pb0>%clCl+I2ATX-MLrMWRe6Ovv~I};`jny`Yg zry!}Bjl`ah#0K3g2~)ocNgPz)!Nm6>iGx;m!Nfs*85kS1*bByfjHLb*68jwz8?+`2 zrXI8=62=DIRSRSDGeg=fpzsGR+JcEIA&G-7PKAlQ?m+59CT4GOdM2q z!`M5K)PNSG!NkuYiC;%z-$r6TLSjEdVuO~l!OZ!IBo5jV0uu-Avxc#`p>-T6jzAYh z!o)#~;9zVeBsHLGjA7!sNaCPnaxigFy$@r1BB}93Vuv8HBaqmjJ>4+9$w=Z^NbEc$ zb}16O5{V63s0T9#bdDvA4QeOA*syj2$nW!z^e#eTuS8;l7SO@;f|mZl*oTnRfZ7i* zaaj8SWIm|<026B_uZJY)hE=cag+Ft1n^VACSaG^iW+ZX&m;iKm5;Ud(Ya4^cG+^pMV^c73(EcCL zWH=~~FhlpYgSPF0&e8>mgSsA|_78{+>Q{nR!-LqMJ|O5GVGtX%couZNEr{*Rz`y`n zF9BkM+MA$t(;zlz91he*0jpm8=38+5)4=puR$8?;^oG#&?HgO=)o#@s+`Jw^tG zzfdzl3t>Qetw7?Sb-AFkTS06)Mg|6c&_Z-31_npa(swA^gOPy&w0r}k#*2}G0W@9* zVuQvZb)afM8ovXn0fj55od#lq!qpS12GmvsjUj-u0}2^t3ksRxbI^h3o#%auUm zfgo{E{D4-*fY_ih&ec#gI~f@mK;wZRaZo!Kw8jd=290qZgQ@}bPtQWxpfOL-vKEg^H^&F)%1Y*_uoY450QHNDXLQ2XuxEhz%MewS%ewwWC3+X+h$k_yLV+ zfY_k%bI^G*Ahs_P149~AJ!mW^7s>{WnS+k22B`s!e^x@pLE}20wiZY{kBNZ+biy`> z4O-U(YIlLypmEvhQ1zhmbwKSdkT@uQK!?18*q}IB4^;zdFN4}zAaT$b?QW>}3MK}I zgHSeTjP^K`y`71H;VhI5iYw3s;vl`Cd4QWxanQICXj}y(4jRXO3>62BA%V&-M$mj3 z17u%6tb9WrzXg?FFmX^H8O8>cWiU4KxGQL>A50vy%L2v*9dZq0SAfPLq5TU`nFSLE z^?6}z(9O{>Hh4S}svb1|0uu+_+YV!&K{6AxPYEUt>f6HDACT05${?6Hs0@O!LFEgK ztpFO6gxU)#Q()p2NaEmeRH&K&ByrGY6qtI@iYpkq1W64j|HH(4ki=&ou|bEz!_K#2hBCWrh-9ym^x7U2eCnO4j}Ofph+{(CM4*TKS&NVj{qL`N7_3LD$hXbVHji= zhz(k-3uQ#2P#3k_V7DX!|S34RH4I6e2`fnb3tddz}O)EK}iONHPE~U;=|-XH)nv{3iC&dIYb>OTtMwzkQ^vn zK=WZp!N8C!!@vNV&jpzU!Z7ndG?Fz8HnNa2SU`0MXj&0u9;i)?zE?a)4iX6jCo6m)-{%W5^@v&~czCk=fzhf%JV$ZWat6!`AYFjN8lf0Akp+sNZb{ z3=Avyz&rK%+L#&k@!{r^RySDM4S13Z#$cm9Lpg>5I>N=Ur0LE`16-){%%Jg-uniV34>%YfYRmf1Ahz^#+lBvOo{&A}mW*r<{>y#-Xu_)4>WGdz=yiW9CR-f zx;SVq1JoyhhzBtIfUX%}U|?YcpT!B<#t3RSf-*g5&=o{8F|vh#mc}uHPjz5oVg>aG znV8r?2a~`ym$R^gE-qr?U+{gmQyl^py3Ka(R$r-~$KsrFJJ8+j1BnFy~5CW+IO+W~N^niP{ zAX7lo>p~!Ng+XmW&~^)^Qik753=9&CF-&C)65!qD5|G{Ik}06JVkw3cXi88V)ZSt$ zWdQ9iM`$f(0BJ2^V2}bOLeMk;LaqcXSIod54eC0fi-S&WkO7SuFs=ZlWKa%doFkja zz_L>9aYeFZ4FG=ny%gOdzc+hXumbJ(VI z(Cj^8Q~C$69Bfm%BxvJx0c=w`Xe=DDDIIjesX_s4Q#xpzS)l;7Dg7HrA8b>)2L?V0%{V0nyjEH zchDYk@TPRonW79LWsHyouArHAkQ8`R`a)2%RAd=+=Q(JC9V7+bl)eQl^$scp8W#si zfj6Ze2TOsLj)3g?3Gzq@10#4-`Yo_j9O!Z{(26&Zw@Mfo!JE?Gf}~XLGB7ZJ@}U*z zVk7XTbWnVPVmO)!k_O5d7{otC*gRyD}gB*CLx&&i17nEPbpae~5Dxfh$kO`nMY6(Vk6QaR;sKG@xBLl;8 z?6!cmV5<}{GBAM55o8191$1*@c>}Z~8`R?kdEOkX614Ff;dzM9K-;ZBXDESG#bZ$g z%4bn5pncU0;-J1R*t<<&g@`~Z0tXUkr#Wc24`kF5unH6l!JE|?#C5^@$G6n89Rw>u zHiSVXfC&;=55aQC+M~ceFNMmpvx9t&EDwv!G6n{5(AW>yomyaJ2rIyz0Ub`E0xEVu z?kokXfEpxR%mCWvR>n}wAOqX0F2NWr1`@!Kkb%YOEvTEWAR8rH4%#!w2H&a<+Wd~# zsxHA8tx(Q@R|(koG6n|Kw@eHSpb{1{!GMldfI5PKTKm&MyU{rio76cWo74yG{&dK$ zZs^8z3DACTCJFF9R;W(Zx~ssY@_0fcB|FZ-@fz zM5oq1b%4**ZB<@WIjr1@w1c9hrP~FWC4x+$g!VEzm3Uu=+ z(zahvV=fJ>Fc?IE6hro=gIJ(p9!7>>5CuLxl_3a3K}>*e@&+~RK#Gwz^df{n3*14C zUhwU<5LKWtY`74}PDTbatHH9MHWX+!4eT~#|G;EHEimwT_zXcH3e?MCMC{WC$%1Cr z7#V^=_lSZf9T*vcXD~4^%mR&jG6a7ET~-HL5{cNZ4$=b|u?huIAQQox(UENgt^Q|Z z2m?`2dBk@1$&3sPi$INDhHwxCvJ<@P8e}VIBofSl8HPnMBSRQSDflpd#O`R&g@YjD z7#ZR~Q$?VuI!1;#&@Ba^Su#e3xNs&029RBh3~?asJHY;n11-mam;_qv47L@?B#?n1 zS(FX#M;I6wzJbF#95g8inh<4V2m(={juj(A6o>*fKNuO}L9=n7SvW?9c#z$FU`ydU zy7z!C9R!C&7--rSCn!$jjKA#Vg0Zq(EfVZnds&!EF243UO2g!n_*%%pO zK-3*31_n9&mGyj(nm1rqM}q2WP^v;Y009)t;JYgrqCiWzw}br>1!_%!X6P6hqW*wJ z=D^ycK+Pj72ouzu0xdmbWQYQV2q-F%wuOTREkOo@cD92iFhG-upuOrK8j?C9LGux! zObiSlVGs>TDUm_YlmZe4MFeQs7-;W0GXn!CF@TuRP(8)KzyMmrh-58j9Xsf1VWj=< zpeaz0zmPP7R+oc3g(PId#J~XZ5t0yS-VZe2hh#ixD+8pH2_A0%y91QNzzhZkhC|?; z?Vy3;f!Wy(*`WkEk{NkFIuU!&6+oNEnZdhvnd_nZyg@s>VY{@MA^U=v89C*^Eby*l zKFAJXJ_bf+j6LbhRiK^F%qaWQg~3|E`_nnWyNy9MFoU*sL$)*{@6_f2t7XK#&shj2 z3D&{P0NUov#thq^4!W%m;%?AQeT?uO=qzwMVf)hs89=g-9np|I(vTg_AU155ImnH$ z5CMrp_G>e7qVALiZS;ohsz>Zn2knrC>8IuFvm zbJrdCWKh!+WCv&z3B-ogHlW2@AhjShpmr@-jRpe)s3{2Av}4Yh*Y2+|8` zB7r72LFzApn@W(OE>K+w5(8n-8`S=R znF*?3!ERt+U;wc}Dq zK8Ou62jn(Ta}OpCV#EBHiDV9_5dbm+gnOU|aD&*O)(K26hz;6U0ul!;TnA0+g4m$; z7HBdR#Quq7CaB2-8UO^j0n~JYnFC_O+yH9sz{EjpkXn#Auoed>zDD<}gF*<5vF%p} zML$Rq)Pn@=PY2C!gV>{vQwmwZ1_saw=~O5iGz|mlih$IBM(h7V z#X;E<)Ds1XgSu>>Ep8w-Xg&y3T!7f1VhL3Af!H8%&>RYg4JtN4Q!yYmsAvTZCV<$W zA`~=f2x5b}CLj!AgNi#)aS39Bibv4?SP&bOCP3i=VuOlG&;UG$4N?o5djPTjF)%QI z_C$f$pzI0iM1t6$qEZ?fR-hu(2+9VfJ2xaY@*Z{2UM7%UkQ$JF5F1pqc0$#I+ye@C zkT|H=1a+xEY*29u+NT6!gVcb+8pH+_iJ-l;FgB=21+hWJCaB*9VuOlPHfWfG^n&z& z#O0VEYhFQYP;q1kRRb~uv_=vv&H(AogV>1#0HrIidPUDR8)e-x1{KR7b3uE>LDeiM-GJDjasY&3`^G`@jIcFlplTPk<{MPC!PuZZ-XOi8 zJ%b<&(+euQFXleK}08Jan%bD4l}WTtd}=)-S`1~*Xi0;(Rgz8oeV0ul$c z9T*rGKUVQO-b)D%M907}CRAaSUfpu7xIk8Qs?s7?i~O@^rfY4 zK96MP4J7tm5F6^wKS*o|&;Te@9C^QbFp_ukn3=GBWuWPD(7rO5IY&V1p>}~zXa|`Cnm4}*5{H^| zAH;^L0Ugy2QUfZtLHoyG=KMlZ^AEb03^bF@5887MHAfW0hMHrI#EwH^FF<00*0I9e z{{l%|2x-r`1rj>}iQSCEUW&v9t!0Io`3Omz18KjyHWC|rCn(g-SCPa)WfmwLKs2bX zg0VquSQs1BWrMMi>n2dw111itn_z5E-2`KUSMfmY1?@3{iI47S2ZcBT!|0xNNH~BN zR>9H+Xs8~>9^KOp2_MiN9axxvCMRHQTJLEGEjWYO1?o4!*r0wBj19U!4#ozpOM|gN z3)*08TzlFPuLF+Y8ID=Ns!Ng^e#8r^kptEdXYV?uBjgi<^NNnW& z?XF1T$oty^ki?Pqw}aXhFuT%`)PUL*Fmcd%H!wD6bsvn~j-(#cu7HWd+7%%G&O}l( z7m2+Di49tv2h+PANgQXhP6XLZhMX-4qBNA zGY8Zrfw4jNHp1AfNPDe8ix*+y5=i2pJJ(_2%1Gj%^^GubTO@H@d){ujr z3KBa5iCuui2HkTHGqV~=ydH@STAvD2GYLr?v^W(e4r+hG*r1iEF!l~4^`K>`F!9q! z;-EFDF!6gx;-CeoF!7H_;^6TI@K`eg1E^mLYwLo>Phjei_iBPJF$3*21?3~q`9vT# zXm31dK_iF_>bC3!-9^R(+5ZEYx&VoT`kN=A;-I~6puI*QaZp2JMHx4OIgg z^8+0s4-yCUJwbarL2S?%AZU3xhz(j51ly|*8UqAPb%4Y{{XtIXo^a4~J?PvbkT~eR zP0;265PKQ}0|RLPCx|@*X@5Rw-xh3tK4=^fwm%=_KhWY6kb2NKp%2u2P(Ldi$_9-w zg7%Ap)PTldGoj*-7#J8p<9;A<(0C(g9Rr9B8nXqB1A^F~@kY?q3m`UV+!A!ID2NRj zcLXh70kJ_#VnAacAU4P!ps`#K8?+-~Dby~|*yL&`8?^rcG&TZK16s%eTKoZGgH{vo zg{lFa%LKZN03;4tX9GI76vPIN$DD_%@n&RTxC&*1?&t%xAwgRb3=E+2{y=Qd7%6Bx8N>#K0TXmjIH>OlTCfWe2ZaG_e?Dl88Z?dx5(k}202)65 zu|Z(~+n)~#19hl5a~T;JKKB9de}lw9=rb33Q`XmzXk1M z1+hVX1&ynK*r0KB&>2Y}HfVevwkIDnKJ*@H4rrOyS121aeh(T)1*r#(--5>EL2OVT zTokmaf{B3vH1-R+EDt0O8rxTgii0lnFoLo{bBHfTKG9?G7~#K7PRWrN0PLFXcY z%mJ-^3xtZ#VPaqihq6KEmx9hk0;vI=T>v_Z5X1(ZmzW1t0~%K@g|b0m209lBqy{t= z)dm#@g;Ot-4LZkQGL#J(V+NgF2vQH)yk3DSq8e|J-oC`#Q z#6(F-g z7-ScSM&Dz<=g*#$Nm5`Nsn|NyA1eZ36Sj&Z05+Iut=eif#CrM!(Ohl%xjq- zY+Ww!-Rls}UM5ur29OBkTpC>akwJ5{kp0Do{m39O(DX1&{2&Jd=ompzDZ-cvo>O3A zV3-Pu0R{#JJ&2nam{?dri`$r4*g?%dW+rw}%ZZth4Rr7fGb0D6?ZeE(3K}|N=3oUa ztY_w62W=8y0bPE~#0?sMXZZnI%*+GIvMl#NcfkpOF3DqNVFewC#d4CFfq_{aB*F@s zEN4k!1dY?Pu`qk>W?*1o2OTEF>;pRfh8?uujoB9@$^hP!e42rQffGb9GcdETgSLio zaWK1o2HhjL8Dyv@$Z`g5&{09mexQyR3j+)2>`7*SP;Y}J4Rm*1Fz6aw9u^kR7!#|Q z7)XeP9dvLOZ#g3ag9NK?0ca!f8)gOuR(%kYfiFIrfz<$HG7I+%kT96d!428~2odMu zwqap_suAFeuV7#`1hv>j82DL0CvkCrHg1EC5Cc1%fq@rv^??ejDd+@m?unqK_vRqe z8MyC)Ot%2BS-3&Rmatla*c{xT`*&HbKx`gv&=E$g)*!Y3H>ionY6D`6a65urU<+bP zaBG0fu>-MXxIciz?Llk>1_4k%l7o@e!=8zOfg5z=G^;0w$pD&HVPN$Fu^R+I19YrD zAU88G3W6@VWAz7dSQr^NK>b8ee*o+ec?Mok`>}^L7}Tug28UP(h{?bWIv0vH6l5t2 zcQojB^Ds~=pMx88MjC54$k`nX{45}oI6zHV5QZAb&jLE%Nr;~X6ga$~b~6WSG3Z!t zZqV)!))Ektfg4orv6h0(XW(Z6?R^zqz|6q#fwhQHfrWuV1ayuzYZ)U*0fPu=BQ z%6NgDfx$%t6a%a?89~ABAp-I*>nui4xcZ2I#sgUAGD@*AFx(IU?GIp`2M&WLBAb~Q z7+B{s-eG58cp>5q;w%6g{f2>`1++(!7u5a8VBH+R%D})EU%3EB zL9GJ=zWCB42G%nm^G*2TOA8oS&w^ZO!xvv##K3wEWS0XsXiS3j;yYFb1{dy1kVh~5 zV`X4)=ZnutVqm=r((AzuI-8L721tDXH|Sg|)|Vjv2XNW?+@5eIoh9LxoYGw`#Nure?(Gjf2Y$@y78!3ov?N-jtm zz+9+?rJ&8kAYJ?{jjRj|VxR-DL0(5v4iXZFD&GK717d@M1fhn3pXCZG1Ek0Vc^I6x zm>_&UHfRybz`$w=O1`p;YM>EbZx+z~#fpsnYzzz{;JmC1W;2L@7Co`5fD2xtWY zt137laWL?+fKnGf3&>1iP(35TYRfnmWB_Q=fz=MoW)K0b3}CefbJ#>gKuN@b5p>ZM zk4Oy20nUt|eMkZf93Zi^Fy}Eb2!lp^1X#lu--Ap99i7D*$p|iyML=i#u|`3i1R6|c zjRwnbh=5KwW{m-B;bGus0Vx;eU}0bgU`=2IotiH431nq5IK4B7q=PsqjG%~R5dqzW z#hMD{@Q4VqGBB{FfjJ@~fgm@hgZ0aZD1tZ{V7paBTtSI86Rb=_qy$uGWPv#bBA^XW ztl40Wg$QUZ6l)Hc;~)Y$;F2{L%<*9007W*a$Nz3Cj7f6mShJc@#{3Wn*BFdJ5Vn2To?7>KxPnV4UN`!N4F5UfbabN~d6n z;>>ggMsR(}7%U4aPg^(`7_>PU7~~j1SGF_AgVuq~1oLBn-nO`fy@R) zI^!IWRt2zu4j>6oD@zf?*ulZTAP>5r_YphDT+m(V3=B%30S@+wAbF7S5ML_ku`n>O zPX-BsG=T-dUIY^i%DtdW$HokHJ)z`z5# zE}VgZSD2BR4`Co5FZ{}HkRpDNB9N^DU}dZ@dj*lqVr5_u5@k@AWMB{mD*`!=6|@gp z1gePDQy65HDAZ^uR}8TMTpY3iTtW?eS-B)g0;FFGdHb{{>K)_Ki0jHho1|rsc2r9+ zFv!9-JA;goL)x(|50hYEP(acm&cLA9*~G{o$OzgWt%Pc?jU>nvWjzLaN$~yYtf0%) zZ9q$SL5UGm+cGi)fhbU-0&QqTT#yYC0ksbq8G=9*DE(n7fUMY3WF>P?&2n*>` zfp3J($xqJK%K+Uf77x1Lu^4h6EPP)c3j;$@YHD5yR2UrgdKnC?2w~8y3GDXR)8JiB zkiAQy42;Yr;Jr(beN5n6NI5}W8^-vQ;{5oG#JrT8REBua&65oAMTvPSCKe3wskx~| z>8W|il??HTC8-seB?b&&$1=p1Cl{6E=O)D$mn4>?g1E(Celb)4dFJ|`&+ zVnc3HQAvJzGE{kdc`~wT@g=$O#i^j{JoC~Oz@~sYTF4hu#+N3QrZL1PB^IYL#DkP) zF~sNR#eSM;?kUw_-wH6Q2i8NP*Q|?p=f-3d2&V)*zx(LAjg{Y5t#3v_~q^9Q=Rf3(L zlbQ$dJ!*^;nOHF3*;;fnX+^22 zIhn;J4Dmkx&ff7suFj!B!Jc8R@gayn1z)QgkK{{mM1ieONvs4J4|aLHo2QQ}I4yv3 z0mzp4ViX}rPKwV08+pNr8JwfyGmBF| zeg_9SB9$iReNz2eH;lEfqiJy2=@(-|;UQEE=2-q5XJPe}x^ zAeb3^p)G_BBALM}B|t0)W(MDs3Somt&~ADV4a3X~u;Xi7+VXp?*?kGBN7|5)&!;ow59~c2Cb8Uu|e}fFg9pC42%t00|R4& z*1f>kptUYAHfVhdj15}T0%L>LvB21$k=z4n?8C%C>o#C)&^-n)wkl|E3)C-0NNmvQ zaxgWZ^%gKT=wMD58+5k-j1AtK12ty@k~yGz0AOlB=l#Rjw~^GmKw^W|d%)B%f%dRK z%>>QU!o+2e#6fp0z{Ej^R>IhzIaU}u07-oo61yCU-GaoPh{T?U#0IUkfSI`iN&F}h z8?;6jrUtYw7sdvS=fT)Nk<^3M-@?R&L7gV3f7OxLpmne?H3>-K;5!|m>RXV+Cm^xs zAhAK~S7GLCK@vZJ#0E`Pz|{Of5(lj#g^7diMuM?*K>JppZm>XNgVu|})RZHMgYNi& ziG$Wj!q^(1y(&<1Op(~2^^h<%F-YQ>NNmu3JTNujeKAmTCLpO1Y?8T4`YMYp2FB5bBMtT zpgIiNo&l)`wGlw}g4iGo3TF@vS}Ox$!`3tih(Xp!fJXj6?S7CPNFS&@58^|EkpZM0 zBnC1AghA>+H0a(65E~>9;+u#uFo33_LFR$N5F`gO59A(@c_1;6I?zGQAR2~2av(P7 z{s>SKBcu-8<^XAcV$hlsm>WPsAbUYHXiW`>4U_8-V_*OsR19(-sFe+p1Gx`00RnRa zNFS&@aTMeb5CwY(E3=A*&qzF3$&&Nqz7i6g&ZOsfZD?#Igoka zHX8#211PseT0GS6> z#^53hIhF;+hslA~M}yo7^GA;yWX%UCTtIDSkQ~S#;5&U_ni&`ve1sVoK(nqeA((lW zp=knU-V8a2I*@sw^*1o{Ky7qbng^LNMVNsBbd)rR4Z<+ zHOLH*d7$tH^%#-OyCKTJ09uCz)`S$Nu(da!QCZO98$$P6SehF^uD2j!?Trnn;6_?| zBgY`kz-P?BaCY_o|0Y5V47tz#|9^AuKWLo+%vlU(jtm`-{_I$^KmxM##*u+x$NnHH>W`Y^NU!h^308cnaxteSb?!B;I! zExk*@42Oalm4caMKS1Ig*IJ)0P`rWym`{OWGt!!#g`hSQXd^Ia^Et>@AcY_rwx$Qv z>0-JDIxd8Tg&kBPurRTMHrKN-vVqb(3nK?;c`^$Vs}C~+0}BT$==^#X4)z$(H~{GK zIA-wj9%ePrVjCXNLKE);u!7DFWJ+NK*~iAh;sr|H z?4b5Mi_dIO&H;5JSbRaE3>=_kfY(697>HnIU}0egEs*BoU~vac!E=LloUwqXD;c;! zw|24kf%aCgFffCbJG1zM77{RnmRYa_gJ$n}SeS!A)3josWAa&8*g|a93C0Rt-UGUoofW#g2Xu%#Y;^&5{(4p)keeA81wj<6KZs;uWZ(c@_Z7v&zyS7$JOeN2%A6k7;OQXaz#$d_Vlr@p zXZNAYdqCS1Si|Omj&fvBCvKa?gKCH0o_mrU)}@Sy1)us-UHer!rBM6$3z5l&;{!R#v|b6J)j$8 zStl}{Vh1hn0i7MnIti@IK?HQCE$dXq+u-Frpcr7C$p{K|4-wG%2-aDQpm6mO0bRk# zI+sxuyu9Z+Xyw5?a2Pxh0d1~eozM6jyu8O6l!g|7jRr060j&<;1+C7?VBH)IU)}=_ zbsWokK-+;>w}Va(=HUiyePrDMV#AjA>;f=<*)W78KUKplFie23<EQ7uR&pa0#z>t^sfD(x~$UovBkBEc0puESx&r%N>a%1EWWC1PB00k#_-32JQAZY+| zp&CHzbtFK#_*r^DOLstv96?@3QVtS=EPCK)0c}MD8wm;$gc=5ZmiwUPJ)n#M@-R4W zF+qw@NznQkNIAp`Ufm+gXb4)~Qv+Sz69rmJ1J29Jj373H2xy-We0h%>C?r(D2??~k z2b8+_SwLnAgPQoDBnH})2X(G6XyXHDdCxD9lR!IfSR)z1C9=p`P+Ea4?_mR#j?rKl4iV7c3u_D` zNDF9r4@kK%XyqeldCy#S1_lvOM6o7=(>sI6RFM5CjG%~R5dj?+$eIe~@Q8peWM)kR zb3{ZyS7NZHGlKNXh(v*W16$q`2XaUzSeb@M4JeakfjI^upwTwgY%s?{1k`0>%>i>9 zL_lMZthr#02LlHvvOz@#*wdipJ)jVf1eF`$_+;Q`0WJ06XGsGu?*Y{!lAxRqO92nT z3wuBde)w4!K$iw_uz;?2VPRnr16R;2pprrAJ7`D;e84iOzGs}%4_fb2#K1To6dIuF zU*;oN1xTDRSQd2JGvi`V)d*@L$^HU0$d*jyU|{fKU|;~P>jkxU806!N7#NpS^M*5L-Nn_)pL=^0(cqb>kL+oUx$)MXq7(k}6 zfw(cCopE4QpzUM$Ed+ItARTki&_7rcXuJf{Ujg+@z(QcNAuP!F3}~7KrWGb023o$( z09yV|%95dyl$^{Y2K@nBgfn2vjxzFdQ}r{;67%#yix7%R@{9G0a|=>)OJVDtAPbh_ zp$;_CGtx7FNg*#{VqkzQ(7`;l8?=@JvN#C7eh6vJ5DNoCF*xucYlh%Qd@p2VWCkC5 z3_B*71#+acEqDPD=xFSE@S(`8V6qxavT%ZqScWVng2;kRV6H)ut>y$B*$vT!EMAYK zw+g%{38ELQk`puzjj|{yH!&wCKN+-+rYaS@=mWII0TKdOmnaSN;-tjnVOxWkhDxGCBHNYv?^m*uU4Y+A|z0jK`cKau+j*;7!4N6pk*(}tBz>0W(AyI zVXK(Za`F>P7~(;t$IxBEgnjW+1$cQ=e0)kiEN9bYHB%byRZQ{4@HJ#qSkM#?S?mT% zGi0wl!m~~foJ{l~L8q5Iu!o<6xu95?Tx&LBoWg00LuXaLW$N1QX1lWxrq+gc$hsNuZfKh+9A;=6WSi>k%Xa!ORR| z5C)V4txtk7!4xxtBm;DL3%D%`T7QIW0;ofUXa^w`9MI+hs7(uMtAh*!sTBcjE(Xo5 zf^Jphg{%PrrBIMKC@9j^Ijk}Xnqhh9RfNp7}S&o zxf3J~vJ=DxkIaEAW?*0dtuX?%szGLf*dTL27`A2zWEN~55u_hB_X+BA!q}ksJ(M*= zAV)Gl*9<|~ps<0>WrBvUVP;~i83IkygX{ov8y;4_-3_RRh|R3KIv7x5L<=9j-9; zO(b)kA+bRNelRtl3lA!i(LsD}Hi4B@zfT_QQB>oJE4L&;rYE~kNZ$n}q zMq*z;VuLmy!}PvF5(f`3LEX;+nqz{pK_j0q_2Bb-q2fkJYT}XD*+^{A8F?_h{Yc`o zk=V<36}(D`LB zb3o-QjLipHuLE_nG!k0_iEWC+c0ywNBe7$U*qKOd@Oi#a^P7>xCm^vuAhEwAvHu~l znL+DypyqIb*q~+=0|NsubUhHL3Q_=xgDN-%1_o6S8>-$2iERU7L)AEf*ibdzAU0Gy z0K|rx9|AQWG_{%p5{Ifu2eCmFAOizKC5R0buLrTAdY6INQ1e0VgVk}MIugbPRZ%cD zC2Nd8bvMi$YfxPbbpvPs7bfn9Bo12t3KIv_YcMuwU=GFxtp$OxK||dzHfXH|j13y{ zg|R_r!ok?!dK^T6NBS8UV0AR8JpfaKD@;H^2~z_KJ{TKZk3ju(7P{sMWX26B8x%*N zGkHPlpFnGAo?j5X2GAK}AT^*c1D!DjVuRMbfF`*>>|_Q82GINoh@Hy7zyLdE4Ya-pcFr0ojE$jY zg4zp~P&R1D6LjDLNH6Ga4p*o+Xmk{`DIX*bYEuM4#hVxy7+~kGf!5i8!UA>%Ix-s+ zhOqEQZi6AO_X4RW27}s>ptd_SY8gQ7N01myFDPw;*r4?vAU15B$qzBe`UOzC52PO? z2XYr^4Ht+HGY_;@3)Wi#nFCS>qCss|5F2J5i#P)VD2zbnf#Mw`2Qm-j9*}t;F_6A{ zAOZ=4$kaaa6_kq$PNFB(1 z;Pxa)0~CX%ytacJ0_DT(LSNT)M4W-)1{(td$UM+m8kl+L>$>)HGB6x~83Jl6Ld^x` zWh7ySdTs^=(Ap=cG|E{?AhTiNJV%a!0d#gG$X<~9L2@7(l-`idQ{f?QU007hWPKmV zJbdfATzD85Kxq}-edz1DHpoNPZh_1L^*dnhTZ80xkQp&N3=E)Yau6GYVQz=48DRjg zCj^N%>6m7i1nt4G8CnU|%N&>LY;M3X3<;!A78X0{H`ZUDs=$`XCRx$qX~j@k~PFy1q5FijnOw=$t7=4p0}5nTZuNC&|pg3ThNE zbFhQ%Sz$6@VPIh92F*@0ftGzRgV(Qt&emdptY2ehVO0ao`+*KZg|1)g23=yC!U(b! zzJ3ifeGOf|2HIYNWBnR43p;3_0KR?=bjmM_C&+RJZcuFmTffHi05p#eUcbf!s_9|t z*ONYC4iR0n1f7Y;0CW|vH-DJAj@YgL2M50qo9QmRvYY z240~7UB3ouKf%|pfi}h9UcUx9*9EqI4IE<7^=qJRC~GLlQWoyrpd}vA^=qK2l$7;r zpld{6>(@Ztci8$h8PJlIQn2|9{4AhGs4%E!3SYkl8jfKt122+c5P1R$CCHLB77(LPbUE{{u3+5PzfbKznuU`XI67cnFpwTfYVxT!F7&s{(}q+WIvmRt5%K>({`64mq9*#N^OkSN3#49x8#L(;TfYWA9|^jC4ZKbbx_)gQ$V}+^H3yJh==wEK zx@9G5{Tj$F2X0Uk1-5<-bR0Lf^=q*p^KXFE2XGgG?1iph19eSc>(?%Uf*iVj4b-$| zeGF2c!XO5szzfzu%XpC1uYts&>(`hWIeeMn>(@XM;00?44PY)voPnQ(*!62r<>2*e zAU1jH*OWlsg05c!om|Jmst8`QCIZgOu=Q)8GrU<J2Kf3lZjd>!^=qIeGb?QUS^-D~wtlS^l#*fV*Fe25 z`1&;iP@rXi?N$*1-3h`9TfYWcsm%&ozjhUrlwj-Em_X$fZ2cN&zbobI*Fdq(z|Vrd zeoYE=8wMNbXj2AI+kkOSCTOWzB50`56I9EB>Ux>;Ag(tk1%mcCf!d4=@t}jKKr7FD z;liN)f4*MZiptW-ju!VORYvMq2aw>Y*54Zx2H!(5JZQ}~%n2Yd5C%=hFfoAc zxE@_Lmsgyqi*unHC_LKqPD#9TQ?19V;gf zTs1iO>fzM9@FE0ZVp!kW0og#*Ok`{DzLp)^J8stzXkbcObB7|Ph zQD~s$Kn(Hl^POM|s-UMFrGbn9#XsaMHIN~oL)XBEX@QSZgCFe$JxL0FG8d_bIe}08 zN@4(|qtp}yuxVh2f(f`SU@wCY_Cghkhn(DocCH)h0dkN;jj9i}2oiPz9OSS#@PaR} z6VMJ`gRDQx10U4|KGh1k@-n_87nI$QPK1ITUxs?*8`5$y=wWhLyazwr3wq2JD2AYC za^)t0&(Z@$2;>Mj*!gg;o$Tol^x)ARxnFhj^rAaEt(V%5j=*xPM4krYaWS~>o+(75C4d@A7pqUy_6%V38qq`tB z2*cLCL7FuT;8s0I9CSh#sCf*U{Q@;fK(|?ex-&`)4Dcois8P-^x;_rvtOJD^1P{IQ zyTH9}h~vRS>B#8=blwjaiEj~GXd0c2F*zz^FecxpwtE$ zR|csEub*>0X2?c;sK!efr^6~%Aoad zF!dldsHqK_BLuNQ?ly$3!voEifHsDK#6fNb%^8B&AfrG7hafh{JWyjA#0JgJg623u zY>;`Nd3O*SG~Nu_Obud#dZwT`F%TOx_X!%@0keS- z(KU#mP-b8lU4sY-2hcD%ENzUgL4%c&4=o&#|5F09P0b)bNy+CZJIP$u~ z1duq?4Ot*IwC+GY+pGe*HW5^3H6y9%1+k%KP6Dx^b}a$1q2en+Y^eBd5F08Ex(^Cg zmt6#jL)~y2#D==z0}>k)lCb&?RACDQ8`Sm#-SGob13LE#G`9<4gW8@Tcaytj5fsiK_kqj+g(r*+ z3QrgtBu5Me#U-eh0!=#LwLhRRhv@~SZ4etYC=OzS+Rh-pj09p`6i7cv4wOyM*EMz^ z^>RV_KXO+LNHHOh_H5 z9{|$>G6HmF7tBu}KFD4W4eFzS*f6;{l92Q2K<>l0u5ke)1H&JXLqLXr+P+X4eO;r1 z6a#|}JEY$QN~<8dK>kHv*EolZf#C^~gJDe2gaeEXvZ8^9fdO>46o?JNFgZ}43S>6S zA3ll<44{KmK>h&P2a*HP=<6C^6S=POjv{gE8o7BP=j4Ih2Es7+f%%=NZZnb)awo z_2WQtpl}BD^|B^ur8UqiIEMo=Z%Sx1GK1)iHQ|-d>Io5I2kjsuwDS&lgq;H z#mKQfL6^i9R>BrK~{jQVw?jy3x^f7%$rdX!~{vOWiv2JgL>Ye z9z9zz1EUOx1KRq)z|I01UBEhR51pRpL)<_GTGxnra0}4NP}8Hj0_PV3f!2(V&Qy{1jxCJ44}3J zNGEtfJEV;X%6ecS@L@v`76Sw5{yTUX+;;JoCxODaZg4mjus#eSZaI`19-XyEC^Q&lEpHC1)7 zEDs$lhYB&H)OH~CV(>lwpadWUx(or5QS_3*lN0fvwVdFS4nTK%fQ$k4*FbDg!3ZkS zL2QsOK}9Tx4Qi)=&iMwhL2V3B=?Y?l#>zqZLF3;by&yRd8zc_Gu(5D(LWKr9$b4A; z5>(5<*q~5G84CwF3br2~$_9^xL)oA<6s+$BY6HQ{0h!4NjS|qU+Z2pnZ2RHn^_?Yv?1e~U zB%u3|VdDFc#KCb2BJhlnEC%@t>X)?)3=E+DI>>*Up=?lF7IfA%NF0VFU$l%_zM1#T@ z#D=+#hXb-75#&Bl7=YwJ?gRD5kMOWcO!$$1GyU{ z2Qm-TFox*?=?9(1nG0e-F-#8BABV9)QlN1u&I2jl~*Up3N z1*J8R9LQeK+$c;BNdHzQ?E4Wxduc&>VCHFXLHg|=^FTEMNDgEks6UQu-c=?BhFc(m zp%^9yTDT0-12fNui-94Bfq?;J9w@JaZzoB)l#fYg96=&S6fMS>&=*}aM9+-JYxFF+X zAoD<{;eg~o=7DNiSegeJv6+>D0d#0Jhz-Ip^FTBxUxCCx7<88ksGA5nw;p5$$UIOz zhu+WLzz#V(2BZgsLFRyHeIo-?OYnX`2tlx)ZEQsJIr9!sM}WrcK>G(J7(_vP{R|9B znwS{OC0L}D*#7<}uul%unt=6>Zy@!LK`VP1K}U#R0r>({s6%PkdG0LiplXGg3DQkw zWOD-*K8zfo@knMSR!|?98PYLk=3obHAZKP_1(ngvEbJkS3=AwR%q;BsjNm)UK}m-d zR6aAhfpQ_p9+0aT=YZzv*}xY~xq+A<3HD?LMmJC$2C|%^xG0%{(F@e=W(?v;VPNzI zrC`Qj22K{xkS`Y}3#e1a4HCrHaRwdwis(bLfV#g746Jzi&upmuXLi)9h&hnD(-I5} zoFMZ+XUTGbrslaJmn4I{0=|Ncks%0FN`m~0+O-C$0Ld^i1cNA;f?#-87*y#&5-KQ3 zf|N6$Twe!T(80t2y78N&{%lcZUOMP7%<|mS+~f>sM-<-qJOS=mf>!8iLHnSfb-Ik8 z6}QabgDXKt7%(z|J7Zu1)W3rCv{3qH*g4?dT~Q*`YLvx|RO(IQ>*|4gt`E0eFBx*% zC)^jb=_-RPg&a+Z5+ub%$?;|RnJLg4VZou8S(Q5QeNRw2gY`2(#UUsKf@qL9sJI8Q zL1LiAcAzv16DPRXt^~A7R1dtkS1+j;^;o#HqQu-(=t*yo!{H$3z(LrFNl8ViWhm01 zvrUoDl}n`jtT`OV%Yo}tkS9SHbNw8w768eD`ew*A5QvY+x*!#p=g%S6ydd?U0w1Ij zf|=nxJs2NU(?QrElJI?)py&drgkaR$D?#=NgExtQWI>TB1oAC%4uP{7z&CG#)>eTE zE08NeY?$ewJ|W1bpn4O;2G#Q*Jkb3^aGM#_xMN^o0L=x%`f0T2AA;MVP`k=OZ8Rtw zblwfjUeNwGSbqa_HVLdxH5ExcsQibm2LR8}fN~uufQ5LORG-4wxcY>kcx40;c=~dnd1RRTLG!qveiz7Tpm|&n89~U~Eu(7RCnIO$^31CksmNFukC(3u1%% zb|5yat+|E`a&`!)oe9e6AUTj5K@~lS5ArWapF4;^!XP;i7Zlc@=p&>KoHjukpcvHu z!`2rAt^WkM0p`9VY>>Vf$bF!`Ge{2PK9GKx8$d>a(k8aHFsShW(gQP(haI%HkpXejdg7m=5+rR;t+XI;gO1~gEka?grvLHR6GzrqblZk;L79;@TfbujHgRVLP z3B%NZZtDRzTG7;j`fQ+ZhYB-*&RM|L7XwXBfy{%c1D$aPYG1?nFgZ{k9OPD*KUg>! z7(nVk{s5(akQ~S#pnM2RqaZUt=iY%D?I1P?!^{KG&>{#V%rFI%=olFoK=Y@dvIk@y zs15+t56I?CVS}gvYl4Oehz*^iOifGyPf-#+d&R=i2-3?UeD(_H>;ur5iLkzt00S=r zXbcbJMg|5J##117fF|id3yDCELG*h-JZ2_#&}bDiBU>e;-y;a>%P_GX0P#3jK{sVE zbFhQ%w_s*rl?TbOuxmglQ173ak;4!aT1dNa1;iN`n4sMd)E)_VgclO75Z8em0K%X? zE)%%XkI}?uU_fb4f?KgDBD84ELKeCsPqN@{Z-dq9gSO>>`WRTc2oNDq%a=-Rf4KL- z-3)MufJ}$a=^%vRasxNbgJ-%1UrU)lyBOXMhP0fCJ8l`2(oiud<-$Y=w|OBc7p5Nb z%w^OxP5PP3pc(;YI;hPGYVjcRc^DXA$qaf=D6Aa=D%%)Ag%NC?0m=r?GeFs(JO*oT zf$lwrsRxa7z}TQMRTvvoe!|$G`V+-5jEoEnE+7G@S`ZV2!D~;D#%Mw3FJi0jL3@fo?tp4%Xk)^@#tFTC-p9ni z06GU6rVnH%hz+8Vb0g@cMNl|{>SmBXLH@;7Kl89KFhG+c$QXF|=^GiCLkBCt)h?m2 zO-mEv@6b#DHOi6J5Xpc?y1~|i2{T8Avn*?w3^pr3jyChbqz*ZEou!F8}XX0R00x98O=K-C@ z1v%rF*p76t~$ zotG?4ObiULGs9TwK}W=Z&kSQ?VFyjA^MXzhgPj?+4s>P=@|j^ElUcaI2N)TE*c{w9 zK?Z=?JltDA%E4@6&I~(%bY|Eb&?Lcf9ZqPYtto9(b0)v1j=nhHPotK~k zC}3xXodB5xJu@r|WHao}%O4<*;k@$_bTl07%rJ0>LC*|Z12QfYWGM?b=n7)kotL0v zWJx(Q3{=&?&J61VxdeLWr77qPo>H*+4E*3_X2PIb@8M^Lxq||-40Ho61B1w4kYgYx zgRzK!3OM+gVW4COF(&tVc&g66CgCFvmaybh{+{%&=Ufu&4 z06Q}b6a(-x!$3U%_??&FGuGxp@4QR}82~#oOc~@H*qxW4SyEQCGsCR$oEZiVbjX=u zASMSls8hkZ9kfu8hkFXhYbOMBgk2Ifz(TIgO0F=of!tcOA>l!7-$O;EA-4T z&=el*&P&iCNUYE^!>U2vAnMF8kX;Vkprh(xXNG~U@WXay80Z8=)*B%80oiWsFi??+eCH*I54xWcT!b<(u!2q*Wrdy@23q?GKQj!Rmtkjy zS%T7=3OK>CfcCdCU_Ub~m4$%;er6cx9D7#SnPH#KKEiJ3)ttDS;L!fEv`YmqA>0uv~~7sCjjYgMlFqbe|<-3{we%JYzId zF@ro~6jKocg9514^9n47B+4KKnssOE0hs}E1E@X1I0s~mBG_U>kOXKTO$ltZA;@aR zU}f-iB%BNk3ZQoPTXqHpdBzy9RnZ`;7*r;LJjc!m(hRZ^d@Cp<6M+n1Pz4QXu(2_M zdL9Tl1~oHK#Nata3_6B^wj3GxY_ZW(#MC7{g;ADdgD%rVK1U2`N*V1kO$i1Dxy~j= z@Lidpg97A{4iHm-NiZ-dBAFo0z@UUQWi7$LpxoKS2t8>`1wPTu3UZYV_-;>CWI>3K z8jb_TKr?-e3_&0Ylr}MEu|ew>85u%A6ih(~XchyMaTq`%km2nh5Cs~|L^T21G&e{U zST_R$1L$0RCI-;G=NMyPxCfsgS2m8`mr2omnW^AAB-7wa)l*W_AWPLjhai!DW2P$T zY%b8s0!B`L@G5o|@LB^d21aIf(3xG3^##m~oV*N-oS=(W7(r)iq$HN4#)FUK%FItH zMqE0Wn?&$1FYpK?sQd&Sjs-Si$e-#3y2UWQh`iIi2;~;gSS{$%P*8+}540K{hkt<& zbz+Fef9e;p2YwYn@&qUfK&M9GJ^Kr)HZ8u0fz$zR3J?E+A37FKrE|bQL+A|g1P%j( zp2>y(9I!l4ex$}>VDaE3?|Gm_C9p%`Kqq&B27(#l>2nNNQcgA`U;)JZK7q zAs%*S7Yz^gf+fO%z1#M-?N6;h-n)`u?gV#Dk#Xwld8k7ybdlSkA-@OTCgYVvivOxovFgJkj-h_&S@7{#6L8I_6 zHQ>89q2i#ic9=M5jSh?rzIzj@27LD>lnt69fvExCy$KZu4QRr|!FO*$#ld%PLfPQE zH=%6sxmQp&_}nWf8#LDgGY5S4CR7}J_a>ALzIzkO2H(92WrGHmVS2%LZ$ibvcW*-3 z;JY`WZ1CNiP&WAPO(+|D_a>ALzIzkO2H(92WgiBOL_yi$yEmb1@ZFnGHu&yMC>wnD zCX@}ndlSkA-@OTCgU`K!vO$B+Fu#DtEMaWWr6({p`0h=pdeFKgnD}f^mkufpnmmAs zgYVviih~BeVd9`QNHF$qB)#CfH=*jmcW*-3;JY`WZ1CNiP&Q~}4Q3Ab?oFsT`0h<8 z8+`XBlnuUn6UqkPy$NN5@7{#6!RKB<+3BFWF`;bm-J4K0`0h<88+`XBlnuUn6UqkP zy$NN5@7{#6!FO*$+2Ff3p=|Kon@~2We1-W7eD@|)9DMgClnuUn6UqkPy$NN5@7{#6 z{Xu6`LD}HDH=%6s-J4K0`0h<88+`XBlnp-j3d#nbdj(~K&borF(fosS?iD-eyeFs{ zK@b~MkufkZD1+Egaa|A_Dh|GH6Dn>G5{K41peq|-=9huQp=ugHY^a(R=$Tfax@jgz z9BSq~5F4s~HHZyWzXgeX8pMXGd5y$o;$&ceg*m9I1=V*T8dOii*dT2%HfY`*#s&=) z!`Q^E#{~`d!qkJd-oV(tp!yx^X3#nlm^ir31rd1G?;Zh_`B1%}G90u97v%mc&@-Dr ztw&IK4iX2oO&&nSLF)xUWjjb5)K+-|6$gbasGJ9hgW4nCpyIGL7P)&dk=q#H^)^s9 zgJvLM@eXn~F&N}tP@e-DG~oT3ur?$}KPc`%G-z@I#D=XEc_9XAH-g$mN4XgoKxc%3*dPp(1I>_u%!b+fKn`*q6UbhWeIPjy4O;36(*x44LF9Q%1<-pY zLFR$h4Z+LCzIj(Z_Nd#XY42r>(VF9;)+uYmX{IL7hXre0@S|pA0PwA=g4G5MG-MT8RQ`Q-bn7XkVug13$QD3|{;L zwx5L&w7-H8v|t^~2OT`L4dgl|Q2E0O_5gID5%SJQ@ET*p6*cyfOcE%E2H{+34BElK z1U@c@^jQ{I4;nI2z(9+I$I$s4QpZt=9r6a9vY%3#n_C&544(5C*wHdjgo8)M2GJT} z$Y#5W5WFQ#`W(MCX3SomtW(HmcmjLN zpfU!=29<{}HuCynIZzIUIu~@_3hcZ}ka4i_6_8n=%PK)Mu^3dwfkGK%4oDBATmi8l z7$gT`f!d%THY~(J>Og)5$$>D84Qk6Fw>6O4Hz0K&Ge9(G+zG}8@j>c9<1rvM2*cz+ z<3}K~VRgqHW=L5NDvv?pAPfpi@c0c#BNT)7Yk>4Zx!^Jq#0ITcgqaQEgU+W%9tVWU zfyRJ9X2a|SUDFD(2V^fO6@lbHe9-Dmm>!UMn-~}vKzc!J5QfR2umAnaz`y`Ha~`Ay zghA>+7=8WkK}PIn9D>G{K<)tP1z{!}>wm#xO&|qOY{dkrd!bx-xPZo|Kz@Sx*MpnGH(P$mW4o zY=Y7~$P5sMnWt}L0KGdIyquVb{XRwp5S4`MR3DJ%kk%7pt5ZSyy1*4H$Wb87G-&Ho z$ZZm!tuvs&qhXy&u#QBygw*Oc9#W@54H&Id^GX=>DoRrGiWBu9`*?~{a}xD%RjQ!6 z0+dFfcv#e{(4>H;w#9UC#V=iuUA2H65y4cP=z2hAdFtGG80*^S`%5Xg7!6l!W9(GuzC>0 z2i1$n^`JYE_39HM>(wL7knt3#cj5Iutgo7yR{}cfmvFrb>db;GR>Jja252G>sa{3j zrvq~fF|?T@!w%*i>$Oa(3=D{!JV^U^mQP}8GhwipwCA&jF%Pr3h_=Th4-+ew9V~3j z3=AIJYndQ>fA+G3asT%=PJ4XcV$xcs9mWt*i%C0}d$M6_b_5}@Cn2#PA+bLp*qf9D zkU7?3-3$tgpnH!tDOn-pjFg0WE^ks+LRPTj5<=c0spqrBqP0v9m>D)HnL&Mve_s-) z?F!p}1eym1g(XM~v=0p?ejRCF66l_KM$qnouh7;RXfFgv6B7&j0?=+FCiY8A3=Gf# z0wzYba*!Y+hXROVVg(J=F>$a?1RZ0{!QKqo=2OJNz`(=}+KRvenrvj^0j&^b0gY2L z3)F!IA6QsH7X+|80_{{%2Z^xm0qti>VFamRV`26J&2_Sa8tcqHpiL6&1t16bfEKcFuQ{;apwjdDah;zvYde%G|b8D2bxf2VPH`LZISZ71Um8J zBgo?53`#~(7`i8-02|W!X`0+!XXF54qwT{z|g_K&jK=uV-XVr0|!*Z||Ujdo#4~mfz5R-x10JONj6l^{NKMN>j2=lWtFn~5ADX=gwh-88S zuZ$6-fI;L3$Zyq*p==BcEFvF48-5@h4iV5$87qXtBeDpjtQM?CKtvT}K|Nz0D+7aw z$VHINjbIrGky{{T&0vm<$bS&0g>gPB1A~HSd~N{)Ya8Ptb_NC&k#8V99gLgV85lG~ z567Zgo0 z+;2fHIS2|71#VrCn!}(I0ads`E5BKfu3}|i(BN(YiJv&f%D|w*{R*V_5$Pn%=AiEy?V_;y2;I0F)AA!o57;ez`2y!(Rt5$M zkS>0fMpgy}G0=nq$m>YTK|&k&NIHSp;;>3u_eAN#{W_(O?-4k#LY*F^nKBJPiCSAmzeu zSQr>Un~^55Gcbtwf>bAi(>sF*XfB2|g%K37EF$0?l&N42k4PIRC8vQoA|jxnG1hcO zkbW5vbC3-gV7paBK#L_O|L8Kj&VRFG7 z4+aiUWP^$fa2&BS@UwtIKoV4Lfa4QXAhI(s@Uuj-fk;p-A_>a*uoQ3&EO``6eg(~x z{Q^zTg2w0=K$Sn^92?L^B+!CcMnzB>Wek!5?dWAx1jQ|5uq>#>`G}o?L6w7nK@PIL zNFFp(yPXrn2W>BciZUn&gF=ph8DuP|O~E(^q(&NSv@XPGMNokXip4`53=B${42kLC|*Eq4Q0>_H6xe{+TDmp;M!Yq{st*$~APyu=E947;V zEa+TQkj#CA%Vk0HlpwLsNMfM#ltE(bU>|`uP|1QC7a%cdBr#BP0VJl6B({=)fdM4u zj3fq{y99}aBZ-0f86dH2Br(uhEs$6}k{D>mA4qI6LQM4osAW{lunZw24>}PB6e+M! zPy=nDWn*Im`5T-nz$FcXx*jOOu`z=JA9(@?v}XuBi8H#%N}QDebgHHV1A_`;+m$NB*vU>3AWdq>Cfk6WtBz&Al^p{E z186Fa5qu3QD3>vS8pNRSTtEQo;HKAd^5v923K4P#MGc zn~#@)kr9+ML48O@++%={MXppHek@5WO4rTIOU@}xN!2f|EGBcxFfX+{Co@SuCo?Ho zAH}qSqWmm<$UvKJYH@*~frV~rPMU6+i6uy}etL2;rmVh+o`s$%%pB^u2y`|Ls9T;4 z3TWuYDJBMnc+g3o#gI)@#U&|_tyL^A#TlTO{JZ5qkXOJ#_UFHR~=Lpp&qJ~1T)baOiB zy7%~O2GHgXP&6^b=clC=r}%EHPk+k5A4o%`0JmY_I}fI-j0Xn#uqsKpR<#O7hE-;bs4-owgO9mIqSI5T96_jPO1v;ZwW^D>)}MF|V{B9uiii zU|)k=fp-@c$ls7cjO5vi)S{xidOO#$?}FH%ZUaml)Lj7eq(S1KZURg%sCxif_5l(H^#MR` z1hHW)Fp%3u+;%mTNXEFQ33;Xjw2lX9u_Jh|7-+Nx6!j2Hc-;>uIY88cNX&IUpb-O* z3BLGAR!Ou;5F5t1>(@Xbue+zR1u5~8cTq&L2FuJY|xq`7#q~L0quDM^=3e^ z4`PGd1qwIVem0QXKzrUmegd&!d*?s{J0Nk;TqB6h4RSc>u51Pd29PJ zLxR?0gV>-#0dy`nhz%N{0F7dR%mHOk5F2Jb$W0(MpaR7oY9^@A0rk2->Ot-Vv0>^# z>zYC8LFR+bb_A&bxfjHSsR6BL0;vHNMxb*NL25wG2C-pkK=(<3)PM>p&^!xB4JaN! zY?vC*Iu?)`P~inSM;xRE6h9y~ObzIcCy*LYp*9WVe&~8<5F4fjG*$~z11ju5_cVdb z0fiZe4O6oQq?d_-0aOTr);Tz##RYGy-D7)Pn}$Kx#k*>wS=39>{(}5F4iEIY^v|fdLf1pn*V;dJr3Q zl_xCyfYJ?UA0sH8fZ_wh28B5Y!`9q^!WXu$02Gd}Jr$qgABcwUF50Yh|G7LDMcU^^r(wKof5;@ySTypy@T3_-Z6^@F_G< zGY=z)pGRVY&OC?deU2pl8Ho*AVhU3OnnZ-LB|+y+Ld{o2VjCf`1CZFD^C4k+Gmykf zkk}1K>=#IE&{Q+bE+(XXhWtou86-C7@JpC_(1}towlk8N03>!6 z61yCU-GaoPh{T?U#9ocW-hsph9ZLqY_Y#sg=o~Vb_!}hgpGa&r&|o(-E?Oa)fN{xlsV zwgnQ~1&Ljb#O6oZ$0&`&)<9yLBC(y2*fB`#OeA(061y3R4Z3p+=H_)s;=7U9Cy>}z zk=T!r*x!)Y%%IUBXnYAEv1O6iT1aejB(@6@I}nK-hs4fCVpkxsTann0k=QRmY)~(N zfq?;ZHXE!AXGPjiClel7J+h0u=|fPr&;jq3WxU z#G66tp=S1i*q{av0|Ub(5F08!2gHVoF9fln=4?V@A4X!IL1I5ZVt+wmbAa|tLd}su zVjCc_U69xjNbDRWHt4=SSe-ZpNqjjHdk2UO^~-rAHmL4|g+Hhr0Aqt%^e{GP&k>9b zYL~;jIPw>J43kvO#O;?m*d~ z_5x_t4QP)gDBeLwHiFooHt##A8c3v9 zZCV~E8#Ji^TCf6A1De8es^j z1k&2f&A`9~jcX7eCWpRXx0e@k*9=Gv2*cEY$^($uFngbd zs4_5s4&?^957d7I$$`uR_i>Q+;cgIMV6X!XVt@>ThBL@aaQ_EM-8)h2dx6mR>*|XU zw_i713^J|*wH7qZ2xfv79)jEo^GAX@WG@iNAE3S_NDkx=aNY&$fDrj&3=GKm1LOyg z45)7o(gQOuM;)RLWFDyQ1j&KS1NCWPX&$66Tb#K4x;_#N3;~P`44`}sG6Q5DD7-;w z5!t*slGwuqwgx&aGbabM2pY7++04?|#KKrX!PMAT0Y(}c7?_!vC@2^j8=F8j7ZF|q zy$3X4L}(4P0t3VU`~N{*R*<)GVlzjEO+suuGa7aatYzY1YM;#xS-lLpyTHtmp=Xgt z(wP+4B4$Sh2KUJ<7D8;SpuM^7li4hkKy@jE!)Rd?B+TZ>z|hdD91tQ95b)&=tAmF^ zkg}vxFi69n9WnT!9zJbgXx$#gZc|6_ZNITQzMytm=shLl!DpXj2O%_ z*5X)W~(UynGnpjD4A(dGFy-^8;^^FtAbN7+c8dt9hcW=I~{g$mu81K zHAq>2hsE=9q_Ddvr^aVZX3+f%3=AI5XQm)s;t(Xv7U1y3p+RKL3Lc53V75jEhK&pi zi!>M@VGtC|#xpg*MSy2&_!KTAZ6};PChusz5xkb^P%^^<7KW9=JWS7|#GHiL)Mv5i zFdbuH&=mGzQg8t|uI3Z|wbr2V9oU*`&=?RXqCjFEpi65(35`#Ip@9o>eirBs2z^i= z=?Du0Lm((cGB7ZJ4p9PWVq#?_}a&&j&4KW?=;_7G?rpTg&;-DYaDb{OW*^W%9|vf4C9^L`lz|g8It3bG;{p-j)z-5?i*PxZ z-9haUo@>ku49t+LA9(J8*naasu3})#1abU9*8#Kkfmd6D7HPAB_7Jkd)>?xqb6(Ks zhy*Kmtu+rnXki)hT5HgPUKXB%pe1^@K z&cMKXjFEu>y4IQpGz`fKx%hzxyz~%q@dFQN7>N~f@dM8`&{93f#Sc73LF=omL9P+t z0UZOy3c2`!2fU&fa`6L?JIIxgiywGWL3&{qKfD5sl|$EB^MEcMXN9b_29<9NtkAXA zpvCE|u(j5p8^GXetvNx9=RqrZ!5)!k;5`SruLZK!8WLiVwbnd~Kn{Rh{J;acVuTg4 z)|v;j)SeY(tu-fToizwUjYM5*9SFLp00A3$F6BJsI^}(}1Ob#9iP}I!^EmGy-c?*iVIUqK4eem4%ObiSHJfJZ^ z)_EZH5IU6duOhM?B-6nt z%K=)|4PKNDyJF%e$Wqu96QHBhSo^^Cn25{+C5j1*pyP=wL<&HhiHw>YpjF+V*kzpr zR^|X%aXyvNiUYK&8x+^@Ro$Qt5i4v}H>hf6oy*w5#=vkx1k`Wj)eVX%-V$a8h78utyRfb51_eDN*0zC|&{%_9F#(A+lq)8XVhwV| z1SHn>f}%-==LaYT4}#LK0uSi)H`c>XSs55qcv?V?Ix51(z@WkN3>1i8 zfpQXb#kB!}Rox)BIq-n4?Pk3g!N$Pg!V?eDdntnrZB;jqH7GuAfYb-@fUXi}y$Nbt zhVT@E-0%PtiV-|DAU8Y$m1i+Lpv^5PS4@Bsi8#nV;vkQRgSjB%82DN4K~{DD2467& z3Qq8y6rkjSqyfx@Y5)z3Nq}_mv%Cha*aoct26-JxIY>wxsvNYa8f+veNDyim_*v{g ztD`|hGswf>T+9S1sw>zS7{Gi62DT)Sw`3VXf{47TitGYosAC>|fI6#ZN z^}%F3I|Bo2J?It&6Htsu)q~m+QsAV*04gIH7#QbF04?%PD_~%h0<{QG3tR-&IP#uG>G*SViWkv2zgMm17rqh)wIGV(C~i_sK^I(bWa3t5QHptyvAfx(`Ofgu*6nyHupDy0bO zaYS)3FcgAiz^l3yK_@8`axpM;gT+8=*P*JFz-^@xm}Um$C7@DZF(YW$PXe^#MR^NI zUYyVdIoKFMeuW5wiYNvRJw^rw_8kxruo)yQ3g>6w=4N1k-MPUHS~SfDy^Vtv#9eM31k`N)3W#XQ~5J7dg z<5*$pG~hyDt)Nnafq?;7!h_ejGc$wNxYvP6M(7%M(296& zun03q1hyWX3A`+xiJ1Ykh#n-!%)rS87h?sp7*WL7k;T}UnLuWOG=f&Q3oJvuEMt249N;az7LFq7;w_%;g|)E>1qM8WxDAtYy{CTGWI=4F;Z)|Z18 z-Gf%E7Nvp`3h3~4&_xfRW$>xFsYU6j;3ci`#UKr^mFnfm;Dz|m)ztCm3-iHC)4>Gl z66>6#G>B!WtFhzDlR?Y+VWzYI02i&yy+=8N1&=UNd#Pni@_{`$?=j?Iv>2cALI+rzJ>hcY>-jKB`M%r za$vV-q$lR)CW3Yd?O;IlAUFb1!#KV?IU@<|6YvfO=#B-j$I%oP zgO(@9rzK{m!Zt2oTNV%50$~7J)SR9N+lhg))1W97w0i@xY9GGd928g}k0z!U8!><^ zf^X9R#aCr&Vi7}pZf0>Z(w2|-;xw>p5V3&ZgZ%>1nVX-7*p?AroRXOWNtgL)X`lcF ztyqyCQDxfq7ih%e^ z&<+gfMwa+AxH-^0AGt~Jh4As<0EVxPXF$C_1u2DOf;NL>=A|I6CjpnYpe5wc4HyjZ zxrr6vYhH>{L1!Ap7pJDCAnj}^O9bs`0f}Za#HSVH7lXnAvY7(n5pd9fk~ZX0o;>g+ zF2yB9CHdL$IfR!YXn}+=1MVFUV2%2a;tO=nQCenBDnmRtxIq2}Z<&E^VM)))PfE;*&&(|-ElLIF zp7NA5HgP=wqXb%C14Vqp8sR8wVL90bT zYG6~$peb7r8z$}y-ID+kcV%E;04=WosRvDCf~KcHY|sEb*n9>C1`r!Gy#^8oHK$?X zAU5b~5|B7(IRa>E62t~g)4|k$*q~L_AaPJ988kfsVuKEs0J#_B22e{J)W8RcgF4Ni z>nuR*Fz7rTNDYV$x@H6m>K0}b! zRWpnOl?Sa;feC@+r^7f; z^^ZYacF@{+(A@%{!Ve@4awBN2A0`ee{6ONME;i`=RS+8#7wMoi_`IMKlNcCkL2M?- zx!a&=NswMp0R);S1+hVe7cb~^C0+*b5f=hbHpqFwAT|>NLlh%qAOoZxV|l+QqHZji?rAnPVTYC!5iL$Dw=sL%)RZ{UT*Gl2&s3S-XXiXD{%?(W(pnMCm3shnFLDhpQ6;K=qgJ$iZ z`3}SeC1VhVo!tluZdkenSqYkO1nC3qU4XGc{sid-rBe`w=>@qJrWfQUkb00Apz;RB z2Cd^_1SL*b-T@^@1_lOD83wy=0#pIR*q~^DnF;b9$Q+n^U~7;;?t!TXE%ku0L6eR! zHh7aE)GpB3z%X&pdPo=>R2jqApfyb}Hu&6Ns9x|HhEO&rEy2`));+@5lR@i;plX&Q zu|a!oU}`{X6k%-8xxgZENE*^Wr+ z!Fws7;^4g$P&Rlk1(XfmO95qrRtv!F1@EPRii7u3K-u8E6i_yJF9nnh-b(>xgZENE z+2FktP&R0NE6jZGUJ9rLSn}wv2&2vl}K#R z2}m%%Ohyu4fW%&l#NLI(zJkPlh{S$}#0E{D!p!FY?L~n43pAAn69+AifU)(F)PUBL zz{EX~#KVx-$w=%1Bz7$ldm<8h9}@c%68jMn`yCSd7ZRHdG$#jjzYr2z4vDRW#EwE@ zry;THkl0;F>}g2sMM&&*NbHA5>`FEU23YvCBC#hSvF9VP*C4UMcSu3~0=`2E$_C#d z1!aTpkb<&*A?cL>?N@+`t0J+Dkl6M}Y#$_c0unnHiCu-nZbxEIL1HgNVy{DD??z&u zKw@7-VuKD^f`!$4BynHR{sX9AB9PcgAU3Ec#lXOj2HhJ0stZ8-Bw*+D*CVN!4q`*i zLEaCs6si|gH|+wc;RKn&z;FVIeHO%q+I11C9@J*J1rmpv`2@s<>U{}fL)HI6V*i8c z1x&cTBDR}i$n0jgIF#D?lsM`G(Dv61&!#36|nA+dXq*mFQ^s5{ppv3DY|k0P-z zBC($#vA-j+)wmF8+X0Ckjl?cOVuL~zR$qhKsW3LE2L)q;I>RtFsOb!2gPKqYGXjt z@I&Zc7Et_y>V43@3eeKbw@`6V{Day6AaT&a44@TUAT}s1fDRu8u|a(W(4k2nHYhEC z?wtg&L3tLo-vyK(L5pcX;-L1a7IfbRs80dg*8*DpUaFss^+e6SPkhBo5lA{TnI{ z-V?&izyK0|!N9=44rPP-HK6-6LE@l$P=%r5pgxWylnpBPwD%Omwqs;q@Pw)dwQWJ?(}Kj^7#SEq=b(bv zpgs`j@J|pM)CWq0st;sjU`U6uL4BfJC>wOoYB7`z>g$2_u!8i0`cR;B47=+EnGGsl zVR-?$-vsJI!o)%46^uR9_W*(R6~O!gidPt01S#(;AhC6j*cM1^(3&8aUQl=vgF)i~ zpfOTVSp-rK>R*ELGl&hsp!x+wgSyfnHfZbv#7{xGPY$FXBnOH&(2^<;A7&nCzZGmy z6{HWO4n(8xEBYeGzyK;+KxGoBOarL{nFn$Y$UKl3NFQilAc%%xkQ|5&T9XIr{t{A$ zzOM*m9?VZ5b3pcjX!LzW8j8g2D-vL0U}%92go65+Aj23K7|{0>tx;rPctga#qA5HK z4EoUWA7m8Fzo0S^#s-NW=3`*sM-qTBL1ik)PcT2u&}3jZ!3f#U1PWh}9Ee8WS9FP= zxP3(l+QjWE`ozz`09u_2aw`bK+=sres70HB;SLkTeV{rK=05a&MR~#u3(DEga z94OvE<2$f457Pf%3Nk(hVuLWuJP?hPj2IqBGcbVeF$LvoP@4c`9w@v)O=o2D4#+Yv zECLw>#UOJ)OxV7n-2AdsV)hkTSQ;9EuT~)99>4<7Mq?cNip(65u1Jtx#UsJPv_PX- zK_Nl*1B00(bi>SE&`k=UokNf~`2YX^e`W^88U`Ll@J)Xp_k%FV@7VUdfWre62z&|* zQ#c@F)Sx{t8$tbJ(1qC=pwMDqU;q_%AcL47`&yV;*g=cKnVHx@yM>t<*+3g_nHf1i zQz6Vutf1iyW)9Zbpi`VU*h4|9$UtZ5GjW6N3SfB$-thvOB47dC3l6zofSH9A)EHpd z3EG1KxnCd*bT2^)__S&G{Q{r?8|eK4pfMw6U(m@jki)S-=@)zuGcyA-3wtjU0|Wei zfyE$0JwcW;aD$GDfZs0wI+ubOa=!rRsC#DE{Q}_i(cnEV%q;An%Wioq7#SF#dtSJ~ z=jtQxc>$Ts!rcd2x@-Vqb3hJC2eWy&!KYt?*;w|xVB9YN8ZLwGdEo{Pp|hHUOl06b z3o_jT#Ae|JHRD+=L2M3g(2)qG~5qSdQ^ny7C zBB~$`?0y08VrJO=0-r$f2D@JXbY~4K?0y08gKrfEIVM!tNIU zWgPhZ0_~tA1iN1VR2`$=F95pEK7(~L=s<-;nzSK;qE*1(+E*PJnl!fPxdO0eqnVLIao!)j;h10#N1P`vpL3 z^6nSV2L&zkeu3$r>z!B?!FLLXfb+64n9U#}3i7ZDIKi@r@PV{oygASc4^7XZz@vcm2c05#fKDZXC- z6zdH9EEx9-$boi2tOh#|RGEWX1&nh*J5?YXNZdi`4kRHn4K%mm4oZBC!LpzMmO{|> z6Y%~H*tz!dpf(xX1CUjq5fxBNf^iN=nF3gI2uL%iq*Mf{=;mNxkOf_M3L3DLV~hsx zHBkbM&alsg$wLmu2Wewa2924p5E3P>i1GcbU5Lof(3g0@yDq3W^$pLef}<-B`PY6Df+j0`~_3X~!-_Z5Ju zE=GnR5Cv+7Vk&?%_n}Qyq}D3PbkHy%6T?2x-~sWc-hylfJB4nOE1dvJ$|qJ{q8<)x4{{|vAL@K1tIk_W9ZXWYD1+-?kDiyNs6>T{=d{yx#^WJH zLVOXm%Xn}Z2&p~dL6MDP;Wr&tdBc`>5AN06pn+^qEe)b!18yKb>_m7_g8)>!gJ_UA zYy~%{xd{>nwFkiBAVROWGPfi#i9rvvl>kgS!9JZzsJm?2qQwe2**Hl8;p#D5;{taVI zB{WjN>nNe>!RsiYZ16ftC>zw>g{{E^&6~s6;5C&{HQ+UsP&Q}|9i|4fwgSd30nJ@N z)r_7`4N8R!450CGSona~R6@fCyrvS$2Cc1tsR4DAU~KT3N~jv}no1}eyrvS$2Cu1v zvcYRAp={6)JL9l+S5=Tk${!07qZkZ>41pBfSl$mdhP1Fe??wV@ao7(THxFu>Mfv4hqgg4$!C zx&Xw6<~vCc8>-#_#Dr{!gT_^1 zc9FU!2xJa17~5JHX!L-!gTfia0JWrxet9U%nC6EhB=^{ei<0Ry8=P>g8U0w zGYZoKatCOwF6iJ$5F3PHa-dlR7#k$6$j!h2y0Zqv24R>S`dSzlS>n#vP39(UEzA;G z;?}}|&IL5=C-0gRC%dYhh&MAnPzd{s6U?Vg3NEkwi96RhWSRwC@br zA0RgRS{MyEh&qsY_}0SY3KO>$CO`zTwg!~1LF;Ki?gNE4`dXL;q6`e6G7{t_5Qe!O zwiX67hDFp`7-KUFV%Ne1fC@|8YhfS<#O`G>III9+f>ynN@(!*wFQBp$w&o=UX>H45 z(ApMn76yiopc01xQlNo6iCEhLI;x+UiCqeG9xEdoD04G2a$E-Sm{^~KC=OQ84nJlN zcF+Y-ET9#O(6ucG5o=pOZCUu*mXDw{Fg>7UD3G-+Az0S7_<>CJ0c~|OgEi&_V7j3@n@=4rFahA;>t`+7|HqEo^PeH%0~q-X^5A zE$czEo|tP}K#N~l!E0DJxU)gCmtZyzcNJ*D6U-)NZOcl;d9K``CCae1Eud{ltkAVB zM?eQqLf5u{Ct9IvTc&_!nxSi3szGe%+Ln5d3!rOTK7z!dYg=xD#9?b&K=}&3wj~ba zek^NS4uQN5Tie0`QiOAD%Ur~HuH4`dgRX6H0vQ2a+mZ${0lKzj9f(cB+7{5dX%5JF zuH5@T0Rmmy0!r^_Yg<5v_I_Y3Vg$|IicA674_n&;+FT1=!NMYP1>^$ALKhB^Dg=i| z1hhUHzP1Ha(7@NWECmH8Y;6musly6e+u{zg2kY9FaF7gaZA%x(9@yFzP&^wguFWW`(Y8 zc?gPA=-QTt!)9VuZOQ~0o`j)yR|K#?E!2LK^;C&T@I@J z8RwXTj#kajNnv2L2d^suop_p;S`Oth2FrrlJs?GLpw6B%2LppVV+>OKwx&@@TDXN;Y&#vIRzO&$1gIV zE*y!6td_uX03pO3pxL6)wIgY1#i=FGm;s+J2fo|B7yrs19W;HXe|h6Y!$=?Z%Bd| z!vMNJ93&31AH)WAJ3tt;cLk&b2A$^sV~^e?4hh52yTl>kFr4lZe~YwM<0H~q z4K~m^325Bd@Cf*E=8r zdiEo%o&wchF!i8`GnhDN%>?ND6OcU@q3a$%Gj3O*Y>+;X9Jy;CKzfP6?#1`@)ds?LqoL z_jZHso(Hi(80J3owGJL2^N3jMaEF6|VFSz%B)ibpI`nWcFo4=YAUi=ArUiYi!vtwW zID^~|^9TC5A8WaYTkCK@nz*$NXSo;{ZowRd(x9;9KjE zFGS>82Vn*V2O{nho*=@&payan6vNzyyw;&eFJGVFeZm%&M4$Tsn&bqXl>y58pp%;g z7{t97Ix5PUS>uP&~-`3H;mz)u>hYV0;yI&u?4ao zfvI&N`4Ka|^h9F`26C}cdG0uT33p#5bl5#<6K^XIFf7CP$I@=$l4u+W-Ks6zZ z2Qm*dV~EU$ZgzkQF*AT#Pf!jhYl6=9N2DnRP@4g^))Z7X!Ok27ja9(dpmk#~HYkt5 z&bkKe8G(s|+aOS0@dvxHmGd`;^R^W3I|Y=mykL` zkRLz>K{3cY&{>O6E_mG_hz(j73`zyCdPstWf#CoH0|RL61|$x`ptu6>TLEc+;$@(- z)S+w;1#&xx2AvTKV}tl-kd~N%_%J!peixA0Fne!+79v3H1*JNW9LQd9ynr-9G3YEs z(4HG87w!-68RO9N{y}n}^(mkuC_row2H6Y3;Pc0k)VVWZZ$E&}CD@9gO(ODv3>_p9IT)gDKiJVAE?0rY8F7(E?z{eT?DNrL0!8z2eg_H zvUbrI%i2XyB7&aF1-i5y_qkl46HVc37ePy$n4xPIL8oWI&*cK0{RusnD+}Zw*xJQ6 zpfxD4wTtgTYZpP6v%}8i+7FV&T)S8Z5(ckP%%6|fuPXMoZQ zZ0+JVP{hL4F75*lhdq z*rtKoIH1M>A_hhW&=POPAn@((4j^I1U>Q*3YZ3TfnA5SHW=rCi~*bN4K_PS0aP-9E;Nt> z?N$SgK!YxL2eqITLECZJCV`hif((W%hXm;ouVY|f5C>^wP?`kt)D4gU;vgvo2qgf(%4C)XN6vkzSw_1!?C)+o;g{$Ux0h5C-j&99=q@nWRtmrIX;E5_OhN9zt3= z3A&4#19b8h6 z7U=TgBJc&bpqp`tUQL-+oSK>qN*JR@Yz>w>nFsb@El5!Tzdjjr(IoCU2JpdP`Va#^ zXAXfABIp9|fg9)t9r6IGm7z4a;R)r#R#$@Bp`Z#KM1!PYXK;ZAsX*eO0aUO!h`=*( z06uk#hG%fWXBWU0kut>qIq0jRL~r<=xrH2|p!o|>hXE8%5X{T~+Pwy0gGgrZd>)7e z!ORSz46qpvQ1pY=Rl>$8K`KB=0C_AL#0Sl#g4%!}Hb_0_E+vp!5C(}cAksgC1u9%& zr7XOVhDaf=$pqhi(N1jP@?Opy8DITp|WI|Bm)c+DqNJ$TJ0lnv_Y!psD(C4q{A z<||<0;Pbhl;^6bSpltB@Tu?Und@d*(d_EVH4L+X>$_CwE1v7IZXubw24qgiZWp6+d z2W{ttsR!LP1!F%)QUkh=3?>e`gAB$7-+2l(6MW|>lnuV~6v_s#`Gm5;Yd)cD@S0C3 z8@%Qd$_B6bgtEbFKA~*znolSjyyg?i2Cw;qvcYRUp=|K^Tu?Und@d*(H0}sb3w&H zXBxo7!RK>9#X$oCFmdqtTu^cF`CL#o_gsx_b-82Hmy*V^0L#VG3104~Y#L?1QP~BbHX3!c-s9pgiwk#4`3yE!x z#CAbq2O_cKkl5Ks>b zwV8uydw}BSEXAH9!wEhytCg$!ukU7L)Y->kB z_QLdn+7lo)sBHvd!{+k0h(gv3g53q0W`#DdL1W6G78xk~K>9%HL2UsL8-zh-fN1o! zqc=n$=Ocm41I>+t)PdXqYA=Ay1Brq3fzGu8(J%~>1F_N9j^a`WuJ1t_pcteMT0m*^PLq8|0k&}S|R9`}kfv<%?UppFu<6JBBwWAKubFD!3g6xCY+lk~>kX<$0 z3=Gd;fr}&ux+Vmq2j-6yS;(4Nka@86Bp`D^hu?s-gW7%|^OATO81#_V)qvzccmdRG zn7Ro#&b0zvzXb|+kXayn5y!b!pc92a=7Q9KFei?4tw8t3BKu>FEM%=G$RD8gGe{2P zj}uV$fy@G7K^*5=9fsxsSh(y!3Kvkj6=oi&9Dt=|ka>~93=9`R3@C=V9YjNmJ+O=p z^js@YyBAa*fy@KZptOT*UX3XBH7wAzBf+keK zE@5C`WQc>OLy*u8P=SQBmPCdDy^egMop8iIEKy?@Wvw z#>@;1OiZkxQ-he8*d0NuP$2inF|n|NuBBw+U z2-3>~S_H)^09u100J;m8iG>w>Koh9##jFkzVQYb`N&%g!#?Hd*wU>c`fujy&lMm*&cMJ6TI&P7D~<}dUqG{Q)*!Y352#tsY6D`6@LT{n*cQZ=;0Xjx zo7#ccGCZJT_gL*gYy}2^SD?^kWc2_|@bct==2IbSQb1(_{H{1HkV&vLDWDsASz+gC zae^-Y^9S9~2Z{lC2HwAjH7Sq~gRDv6Sp;%GD9BP4o-&X%kToehpzB;%QP!kzE@EO} z0AX;X$}{k@fNnn%;%5O}2h9t*#}|5@7SB~s{6Wss;sLcaSWCg?Gw`#3(giQ*Tqp(B z=`PF+4B&MXGp>LN8ou}<2G*Hih2Zj zEFz$Lt63o&4iWH)S`ZG82>2qcTCg4g5l|PNwVv??D+7aw2rDSu8o@FWBAY=DYX);< zM3#eOS{OOm7#I{p<8uobSlbwRI2agIM7D!uIv7DsN)3@&AQyCj_2`IzT6C=U?T!PIcE}BnS;nHkPD_Vf=-Hc5dp!Nx2`P+IU20Tr99a~WIM7#MDdJOxG5Ja8C15!nSwtn(S&I2agSh=4C&TL3m1 zbaEFcrg%Y@?PaiT-o*-ywJnHP+X@O(7I3U>12LhowjC5x&{*36VnbtXCsM5K0;z|_ z+FnpJ$?*IDIqM)O{VMQ)jL)r49I*FzWCAt2G+A6SK9E!mliRwo&(wCzyrF8o%Lb_8v}z24|oaL zr3^L(26w*roFoR;t027|JbIwWxdBoiz~c^L-vqUHLU=&u00f*Q^W-VxZHcKwd{u4iXZFDwkqofVcq^BnUMO{492C43MH3yHm1)N}6L_il7vZ^wIG7|>_ zKMN>z@w0%;6b7}%K__>yvokP=TmYGD#|UCGh=A@8Vzmcz*hK6>sn>xK)Q08}X$2{R zt$yJIiHWmAoyWu=EXc^f06MuV5@aIyqC(i}m-V1{ih?>RACyyIt6#)HCdM#=wD2(S zvw-fM6gFmo+)DQcWR5Jz{$y}^XAqeHQk}vGidYsAP`$*O3g+;LB!Uc019L<~9)R?u zGlKNXi1>gw8DP6rL_k-Qvu1*oX^8ZLQgarVV<6%Wa$+`^V$H zjTvw)3TyH(&XMF~U;tZa4zdu`notB~n_Nx?202iNBpiHh81zoNlc1!xm{FCJfk6Uv zrl1mN=`HILuz->`D2kSX*~%b4vMvKT1QKd0N(>AP?5jY+Ad|s@;vfqdRA++BWMc+- z3E#pQKE!Q!pyN&NwBS;!# zn5+o{_y#?0Phlo;1_qobjWI%R+T+H!X%G1(Jg8x;p2GH$ptHx6k=NfqR?(;+3wa7d z1XVFlG6SW220L(zzQ1==@4_#icqDwx%v(P$=yJ);My(R(!zsIN=WTA-Z#-U?Ve=#F$FxX1#MzT=BaQu0en81P&b7+(xpJ`|sp zn4OC6f8y^ z@eqfC)TU&nK$7tYKOzniY7Fstpc~)fL07`%XUFFZs-xoKlQB*v9N1M(u#<3u=agk{d{U0#pt}f#exLRR(yq zAx33_s9Ydb2$BMDUWXK%km?3flOVU7AhPI7v=|scc?;Y#L7bZh3IkBr3gjkm{~R>w z!@vOcKO^V_X3$xBpl$>-a6m?Y&d>v?2lZD(m>_3^fU+k@9F*li(<(4=Q1%3ggX{sN zD3CbF3{Yx;u|e4yqy}U^h|LXk11JVTYCvX#=9@umka^l5H$m+M&9j2^g2EHT=7zc% z6jvbipkg2#q@ITXJZA!8b3^?Cnz|4HSpxD51O3;Mfzk$SEg6Un%2CulKM)jNusM40 zx-w7zGcYiK2Bl%*;B{qCaqwC)C>y+%49W(tC4;g-=@_OLytf@H4&J{GWjBM;43yo0 z#GZ`AUXH}xgv7pp#J-Ef2HhV4v-ca4IB1FwCJtUp2DKNwmJG@UuO)-B!E4E&Y)4T4 z7Rm;%C4;iTYssK&@LDn`8@!eb$_B3`gR;SE$)IfTS~4gbyp{~g2CpT9vO#m>FgJtO zl0n76YssK&@LDn`8@!eb$_B3`gR;SE$)IfTS~4gb)O&}S4_-?K6$h^+gR;SE$)IfT zS~4gbH0cD>3tmeG6$h^+gR;SE$)Icw(Ap{}8+1_zOfP7kCyZ@@q{bDA4cglbQxlIQ zo`b{&ZAONv0c}i&u_q&`0bNuB6JLuYz6*(c1&RF-iTw_V4H{mDnZp4Za)kOz6p5{b z#MVb*+aR$$k=S8K>|`W1Xp<<+u39AViAd~yNbFNc>_~%=& z-AL>cNbIXfY|utfSiHPP688nI^@92Zyp{~gP6mmC+O!M|4C&Cj9zoSw4M-eR`7$st zbRn_(L2Rgc(7H0vOd_a$o&yqxnz;SSAU4z-Z6vli65APx9fHKpLt=yc4Dt(z2DL?CY>?3~Ht1Xv z7#q}vfw7U-V}sf-FmX^F3S)!X6)-kvq!-3^1+^cbe)mLTgW7;FH8Duy$w=&UBz7SZ z8#H$a(+fJ=55@+qs(`UUlO8bkG$g%qk=P57*x)t>h=8^6pl${=gJ9;I1l5U9@ypON zAwl7J56T9m6WBePpk4v&?o3d-?hjNA=u{TadKlQcK>;QP1`r$69RuCo24aK4RS_x< zn(I_p!*a-_fCPtLG3!w8V3*?G_dXpRRc$W1UdXjKc04YC`?2Dg!*VF+5Q2NMU~$OB`8)}+DMpv&c8 zY>+#N!PwS7LYuZ=?V$7zVxX^q2IVPG@jyr& zsJ{i%1JbvJfq?<$1`r=)FNnri11Uw^U7?`;2~|klR+wF&{vOC|m|YvB7#Kk7ib4Jb zDF?}c{0mBBFg+l5JuXfaR`G3uQz) z0QJXU?gQ@`K|0rJ5Ystk24R@{pld2K^HNePK&vVVt*JCNH8Uahe6Ai) zhQP9>(#(+ou_O|7K`3ZF9|Hpet~)|OVFO#!2wHFi3N!GUMo^rBI;o&dNgz*w6oP2P zIa{El%*@2D0$K>j$Oc-l$jrzA%5%(2tj-`o(DiH#49pztpaP1Sg%#94WoBUqb^n-I z*g-WE3k#^6W@h97bz@mrKpBh`B*F$NN|~fUM{R)Y1li3v=MpG67BetvfX-zD33DVf zFlvCtBpHK2TkaV^3b+_SYZ|zqYZ|!UfQHc2K<4m(bn$>xGvHf7fOc6KZ0?>Fa)TEe z>O3`Qz8roM1v}DBUE&N397tRV1_n;V`4e17w{>x&8VH&m=Yh=RgFMIpYC$nF1c4|} z7!aOV2B`w;WME)83R;26uox7PjKBGK85kjJbU}>{d~-)dnR)39AR>!YWAm z2hX$?mw-$!*2@5Oxgi_~8$N%k#Rxe=ftit$3pSexJ`EI1fKCa8pC=096oCzA0864s zfJMLriZCIM>q89GOGcdE3O?&u163fPebJza0;n3$eq>N$1hu0;Y*7CUgkgJ=B|ya|w0{8_ABXkbK>LVcY*0I% z+T+Q@j3I;D>Ck8cRn@R@3}VKUL49GEde8}AFm^S_zfdzlhdjc>!TWWf;Q(s4!u$?e zbPqe9cMnJ}R1K(Y2Ga`)YM6RZSi{&LYhY|p6$fL3!xKc{={tkluu!{pF+lpfAbUXP z)`I$>pxgnvNE^fko%jusBezcq(n}1+)=vca7p51+1~qO#Y*;_XfgRBf2IYB>94NV> z_Y*;P$s*?gkUEgr=>0^{xEd(kg4)5LZ~&Q>|(g4Mvek^FL0m=pK!2mPS`-v&+h<-6BZ^GP%zE=*kXC5>c0X77bwxA63e&QN- zM1Kv`EQXnf-cO8WWMBaGk)X!F`&XbgE6nd8IVL9J?pZj)0hyBng)=C8VfKQWvB>5r zGZEKM`~%vBz`(!&G7r?ahM5P-Z^-63Gchon1UVFnVRE2TZ9#fq=}LhU;XY9L29g80 z6BGs@J)p4`kP$r03=Cl)0T2fo&LA#0k0JFFlURuBCoX2ezQ+u`pLm;vxPD>)CnA5~ z>nA>Df%q5d4S4*5$|8{8Vc`;k6fXGsiJr?`5Kfz zL3V+{8L(gn8bFm3-g^hy^A1|w3d;M~ z?pXkL4?vrlKn?+6ME@=t)OTWH2kqWrW@M`Z@fbNkbA8NAte_;x%)x30?&h(B0+^YF z6|`xGnS~t`6wEB_84wMYAYUTg4h`y5W4{?1JZ}sMS5OFo90S3iv16R~EYPMco|2Q9 zgy;f*+RdOQxB`LpHL7$*eo=`6NGqvrd9YPr0>waleHV~>^^23@LH(5C)RJP14h+~h zkYnKOe~?m0#|bVsa9sjCP5Tninl(M}I#j)+;$oC$I6ZD#Ahdo5l)fS96htzEdbS`2 z6c5OK3#bWU^v(qa1_ns^2aObH9S7op+VP+mgq72{)Pa`5fjXgt)RBAVg318hxd6I{ z2h=72wKtI4VxToUpl|_&5eSoV=YkKCMi3K(!E08K+7h56^g%m)KxTt5NDT;sM(IHA z0EvNcACY%190Tp21!;g{kXaxmh=$ZDARYrl2$6R#h_En#N8cd25M=;lOt(0xC>wMm z65)OFMurv^;7VPAa9zCz)P+YH(-mUi2e)BBVFIZUSr|dvg&9GMY(Sj@kmC^bH7F@F zGqHnWl9`cB2vjvQa%=?E!c457YcQDMjjf+xeqHt)@RDd`NT!W(61r`AlD8g_Kxb_7TU`3#s znbc-Nd`f9`o`pk?oAoK_WI#VFxOQ!J)yx0J@X}$|Q;c^#MV# z4KfF$0atqhR9J)5A-5+$VGq&+!Z0>^y8|=^1d@kgkQpF0db%f-jyaSKqG0Bs-}MB#at~DUgVca9OdV)^ z5@a^a-X*M%K0U}@P<;=Q1KEq-?%-mCj1_^*0%4eWp!rr18#aa!#K^z^T1yI21HvFV z5JqoztS0iVr#Cp-9iZt@khvf`Kp1rC2*}+aHVDJydO&3u(z=NaNd5&SHJE=v;{~uZ z0Mc*3%)kJuoH~G|<#E5$F9Fm_jahB;1a90-D-IYRBL@@5gK*gJqy+Vq{@bB1h#!$SFRyTs>VC zS!diKydA=i4hmd4Xu#utmT4{XOTn9rKNTS|ps8)Mg$y9wnT?ebdp1=hohesXqyUlK zAq3Uezn1ANhCWby;hGNzrBBFwcmQ}j0u)vtF;ISjiB}_?{qr2OCUiLy14A4rMj03w zK-1SCO^9|G=!iFFCU!&6Q9O)n;6@iChd$_79VS-LQI5$I{ zQOSZ&{sC>ZX911T!SAC2U3SR=I%$y^avxPTOgEU6%lKWK)Xr32JngxyC4T7Sz5 zKKloBwI=B7pP7sd4A8TGxMe`+E+C)%12UO~`vm9+2k^a99NbNyGZ(;Y9&XSgT*%#2 zSkC_8fSvur2^vRaVBiHEuLnK*hkGsPum4QID?#t0k_DYx0K1RsHPYEX-1#8)L(cvI&1b;R{sApm zW`&*o16oZ4Kl=xKS1D+{9M~iB47@)?3_wf6u z7K8L)y^m@iNT!2vGdlx=hR8yYJ+S+zSV5823%-EGKm>HjEo&dx9upCHkPPfTDh*J) z!S161t<{I$M|BtEIoN$vpcsIk$OBq#3crsEwC90!E+gpBmK!3^K>nG>7|O=L@I+)G z$R5~zR4yP6+I>_7q})dZ8drtgN3{dwG%WW~f!Zmo(EF%VKo&ypqxuPQ)9ci3PonssiMON1$>hhPwjfHq!2+0&No*jQ3H+fxHF1kLoPw z3QJZ+M(}-9;JmC1W;2LrfjkVmkIELLh46h;*Fnl)_fd&~QiVO^Ts8&A5|cT1G|qZ5#$iqeN>>c zlHm7IfyO4__fffnjLrcY?H~f0ETr9iR5w7!@MyecXJFt>0kz!N8RR$^7`Q=^6hQ|7f%u90{Zj7Xljy5d`HY$XFr+_)s8F%0^u& z2@-*H1cN{nsELlM0JO3P(z}AT;*lEiAmc%`7!$)8(9%ib$1A~ioshYb66adMlEk8P zUFh0M{o=}EGR?=bQWIiYK~a8|K8EeOWhR#TIhl07v8x!|KLwBV=Hw@5L)MDMgRYGS zts!M*U??t0Nl8u9%K)u40S{{GWq@Y8i%U`xi_#&&HsB?ax|w;Pb{$AVX1-nqWS2dt z5y`;7tjfsD4mz`kxdwc)4h!gj9_AX*W+%w$J4k2wurafN)}=DnfKTON;pAXoWUk?4 zVPIs2=wb%z6$Xp2fz7M~sX;S=7px0(eh&^4K&S69GRCJA=f`Ix=B4DMGC)u5ft}P7 zUzQkOl$y>EpPHLml%ATGTnRev1iVANEHOSOv$zCy42l6mJe5!H0oh$#k_|GqBtJJP zzPKc@B$WYt{6%qUGWwW&W_liM5o&ztkhob4oah+h)AEWzp`M<{5T6E0eDNg=phIZD z#{xKIrh|sdQ z7~*piE6P)fK`A3O50r{hQ&Sj15z#HSVH7lYDUYEe;M zJ_C4~2%NuiK}R6vmgbZU?xTDL$-zBkiScPd>Xd-gfSTnnHK67WSPh84Go=Q; zG>nF~lZ~#SAAqxWK=T2hcn2j8&>DKsI%^OgghBHKpacVAgD{8>N>m^=2!r^bLuEm1 zn10ZF7Kjb%I)cmt%@ZN>8NkIKsI&()-H?yQiH992h$td6!HOB;!4#+hfC$8cx{ILs zC+IqTP@5cfb`EF_4(zTo(D)@x9OPD*IA{d~=&Tx$yFqN&U1y*pYd~k!fcyyZH;fHx z{e#ql>;bX4g+V$YXSaaFL3VwM_Hq33{d)1)g;Ct1eY|vyJObz&6HK;iFUNtBie6Jdm4Zc?m$_C%7 z24#chZD8hr?^T0}gYQ*?vcdPNLD}GY)u3$fy=qW4=xz^~IiT4-7#n=A8dMGVUNtBi ze6Jdm4Zc?m$_C%724#cqRfDp@_o_kJp!4Km=7aB5gNlRiRfDp@_o_kJ;Ct1eY|t8W zm|pO`YEW_Ty=qW4_+B+A8+@-ClnuUD4ax@H6aX^^e6Jc*9CW}wOdNc#8dMy7uNssM zzE=&(2H&d&WrOckgR;T*szKS{d)1(9@V#nKHt5bJm|fs|)u7_wd)1(9@V#nK_En_w zZ@~AeLB+xMszKS{d)1(9@V#nKHuzpOC>wmQ8k7ybR}IProqqsx5BOd+s5tmuH7FZ= zuNssMzE=&(2H&d&WrOckgR;T*szKSmkj}he1DziO6$c$)53^SuNn8twZHmOU2eCmd zPX-1CXXu$Upi%*Rb`GclWnf?c-?s)ezYR$}@)a%d)jV-#uuUPe+)g}1>~NWP&R0t$a^Ro)UNpoWrNxazmeFm^I$;j9ng7Z zpgnM)v0ac`Kx|O^2XwX>hz&Y_2Q*^}VuRccI_C_;2Dx1udcF&&?E_l901^jHESN*Z zLG1@yDBGEVfx!dH2DOhs^V=Zxpz~uwq2i$SQZ$qeI-@5M$_AaAo(^S$c8%mh*`T&k zA(RcO=RsjX?jAmne_-hW>tUT1 zP#*wf80hQ~wDnYHBpDbu*dcr6K*~Y(g8YlV=dYfNfk6XBIZvqbk1L)i% zkQxw%sROO`1ep!<;}r!42GE&9pm+n>2a*HP=zIPy@esG?&qR^9vtd5*Fff3wQvtaR zgkkPO-}4uNbaoA>PXTiuxZR7i{yu}BfuRUG=Ljx zVJeg$>jOdIjBn3hv?wG#Kz;yWkRL!aXiFN%@344lQG%!gnTK!B-)>Rj&W4#I#=y`( z#Mv-15)2HWd25iHKp5se*!sKV9Psixg6r>0jm?POM_>V6R0zuZpgn&Q45AEXjtouA z3^6aKORz~V=3#DQWYAvR#LUPeJZS;LtW8GV4AL{xetzYVF|avs<_5Qx?1x@%Hf9E$ z8^;(K7z_@S=-iFD*JX6bnPD#1CQb(FmDi;?pGzx+b^ism8H_j?+m$bGI=ooy_8;w; z(j8rk4tX({YkY0{@}B{;PEVIp_5&!7;97GBI%f^CwoZZJJ2anz&Y%HpOJoFX?gkY) zpuhtu1ks4Kb)agHnTcHrv?Ps@O&3gYfX+K*W@7aO@!)$NKm!@fEUcjYoXjljpcO;R zEbQP?8FmH@=mI`g&~`Ok!YEf(}wJu!HBy z!RkQQiGU8JQ3JII4uMvQ7aKbiWHH7xcOp(B(}a2SIK|X9xlvLI7G=44Etiu|T^(85x2= z6zHTphy;iQTARek5Coz?Aq9~Dn*}966%ZpsFo*)JS7l}>W}FXVfW~+j8KOWGsNMvN zgBYNYVPuE`QJ^svMutcb1-fsLks%61foerYhDZ z6sV~Kbq;8?GE5bS4RQ=4LokQ}Sp|~fR;GZZH$=jef_Wnpu%V0T03Q&m8-q0I1mN$SCO zl(2(mOl!exhzJ`FlI%#!2`#KvUs%n+C$JP8MmF|cz%ej|0W5oC`L zivK~=p0KIiQt-}W#1tPyImn{;cu-;)*qIej27=9^fC?H=Vg=D4aZuk8#0DKU1L_!o zG9jqJ0b+v+0+<>Q8`NF`iGvCRm^g?H6SsyoSV3ljN(#_n>LB%?o%EoJA0!Uy_<(9H zkT|Fq1C@awb~%z>Q27BW0zl%R!WCv0hz$}4xgS8NLGw%w=F^ z03`?r8$^ZPeF4FpsE5?pMlt* z$_G@T!Pua>48#T{4NxB$#0J%wpkx7JgOWCA88(OwO4^_*2gC*?Pf&#lVuO+-=*%Dx z8T`hDpeh`MVRI3n z@dsF+8{`hqSOiEP@;C~p-X02b5upAbY-|j)Wdp_rjaR_f$mb}5;uj`P%$Z8-Kt%y4 z0vQ+>K=(Dn&R05xBz_%<4ceOxQv*6L2WHoMkQz`~0SaiOvx!0R1Pgy$<6EFK2U7#u z2Ml9_#*1KV@Vpb$d?O_DLFogg1~fkiV}n}NFgB>E3}b`N4~DTp^E@y%s4ov=XCs*p zx*{7U4qDF#V}n|yFg9rK8;lKFQ4C}EA(?}GrZeb36POz0Go692h$uNqssJ zI~$1&&ifz&&-f_#tQu%~18w*LjW2?dHYof-Y)}mVIG&u zP?-waF%M#cyP43jSWx*1S}P6`2jvNVs5q$X6@{`v<7CoMHmGa|#RW(`s0;_4rvqYx z%4ty77Q_aX)u5wRL2OXj47yhX#0HhapzsH=L1i=OkW~;HRGx!6vLH4ne}MK#g4m$? z0(2f0hz;trfx;11K7;z|Fg9|z4a)m4aZ<-q!DS{i?nphS8?*%tW-llY!q}j5sbOr; zI3$dH2C3Ww{57cA@$${Jl8e>K_4^$3;$`+6rAPkcOrB9F^n0Yt27#Lz085lt3fm%}_Igojv zwGS{oApM{Xkf1Uc#0FuQ9JuZT2|#fi69YpPOcE4_P;pQ_05Th9uL%zW!vZFVy`WYa zNDgE#tO*U(#&Clf`xq=}^h44{&aq2d4k|Mg~$ z42=v73mF&!A_NR(2~03mz(1Y|YWKp%GeH}eK>h@cXM)OqMo?t|s=PoR0x1O17~`3s z9dyi$Y@kY%nUMpueubHdwUUv6fdy1HF-w6;3dC_Ppmskq3oEFp!py>M4;uDlVFzUz zW=0Osb}VKN77nl=3n)c1bFhFaVO9<%enwErV9O~kXJ8U!1l2MOY`Gwg5SYWlz|O(M z!+0Mwj#&&Edg5aQ-K4-V3&a*?1htqLIGaHn5wJmApu4MB*uaWFz5@A6%35tAj^3(DxoZpZaz?o0HqRsP%+Es2XY1|5rWbK z;xHP}3EX%Nq(RvL1l`92zE_(K^&)N9P2gZT*iGQzokE;YBfuOk)a@rA%fZKgGca(Y z?q=aZ46rgV@FF;%(N;dlJ=+Wn{78FiKv@FhVNfx_$N=hqfx>_R)ItGaHU>!Gfdv^D z7(hKJNX~+!Es!`UxIr`sgVF#KgA8Z@o7j=UT>a$yT+rfcDvw{GY*@)nOwP#6OQqhX z6$Xal_~iV8O3+voWI!?vbQE4LwzQo5#1d?S zeqg1bK{hJKSx#mW%`R&3UzFI5;}>gYSBRCKqTn;b`TB2*v9T)av+)+eo_dC2Qp6#zS0|%0))WlDIu3r@G=0jS&ad- zHW;K6I=cfGE6~rDmXhcFj#@u(4-7H2^XXWREdMeL}2EC`r)v#IZzyf)PQJEyu#R^W(|xD zY6!sCp!C29BJhlfXd=161UilYG9TnNP~RTp9+2BWY*0%ABuDNVDv(}cFu1|S068NJ zq#m>m0UBf=E_`Gjw1x>(dP2PjUJnII-(W@1z6gj78g~GN7pz}0gM$IwItPu@fPx<+ z2WmKhrmI2bf&2{82TE%o8iqk~Ahs!}MGHRn48&t#z@-i}HUrZGQVCLrt)C5AI|XtB z%zYa;ApLBR`#^pJ$${JlI=39zJkZ!o2$BGd2|7m|qz7i+4-N)~9!AL2F(@2Cav<}- z`3K}MC?byCI$vjHw456VVE2!-+|1A+1tVeIZqqp4^TD& z$${(z=RJ@{C_abdd~?tkI7ko7ye(Xiem2NFP>BqZ1DOX}!vu2!$jEn03=E(=1Y(0Q zOs*fACSc})#ved^X^?rKo&wCg1)#i+w1&x$g@IuK%n+y?hzsgJgJ_T$AbT#dV(({z z##cb&8z40xEQF(<4eA4f%mb+bVJ|l9=bIly^9Khv1NgQLkUv1_ALb8mIR!EZii6l7 z@d4$+;}^7d0i*{OE+X6zbs+OVeRq%?D4apH94v2u%xGd`U;vHvfY=}mb32FzhV3^E5qL)SW`rly!!fL1%f`|ZZC9y_G> z4(qoY8W@_Ifx7KPoSFIuG)IcmZQxtT&BDOI;s;v$#lpb63}nAQ z=u&IuWuRe`V9;qqJS@zepkrsmK!fZoEbO55&AgyXq$OB&s~H&>xMM)F`XD9)Uwk$L z&k?ph*-C&}<9nXe_YP85np$ zw|c6unsPBQFmN9Ron!+&uFMx?3iP?l#AE>Prb8T821*&ipq((Fp@O~$nc2V0tFiExH3@P&RWk{2|liDC&)C|ab=(t#PH+Fo`CeUFs@={U{DZ^&n;kJ zZDU-^&cL7|@&zQ*!MG26T-kn*J+R}-Kv#gU!j3CT0m<}%?J*GnEud$ez<7k6fx$vV z5)^L}8Beh@FxZIXfg*hpSeb*!IgoRvGTvrqU~mxu#Q^I}Mo_SOh=5uFtg{$F;p!tI z4l;T!qbeH%!wr!?pwu)E90pHBc7aTr&-k33f#HQn5{R<^Z1fujewL@8bNerRke0^Fc!R95J5WlkUq_kyBHh8r{t%6br#suZ}-f!uqzjg^5xg?lAP&C#u_3=A6F z${;gO+yoz220p{>dR$o)=xi`>>8H#HVl#+<_HwYojw`DJX;B3y zBn}3C7EtQqX91Zh3>uD>V6|mj0WyFW6lr!~HiHQ0GImybFo#V9w9|~$fe~~93y;Vl zkZI10iQrxh2S{uO%y~=z5G$T@}v?JFcu1}(SBX$OU7ElOCg31kWd@}H}fQ~%mXGvpYVBlu~)gqFh zoDWL@57|M&7r-O~I|Bm?2McH}mxYDJ161#Eu$*LKV30CrVPIgp(E;i)FfcHH8V!td zKs@Op21Y?p(gn2}WHdpI13{2DXnI>Vf|-GVQ4|!Nkdxo#Kn+IF!VUTOA_hjV>p^ytTeu|ijedkTZ5FF*%`@gW@$ z2Aj>0N1f$R;ARXJ2brdbI1Wq+>69>K#7SZ*@L3h`5oM4=y|A1I21>3Bpu5Nz8G=9* zC`DtgGtUKg@Pa`UOhGVc5)7;xl$b$Uahd>H`3c%>z{mhv5C_%+O0YA)h6aHsP}>>R zR&0|oAXQ-9;6jdp0W`z|GaDujy2gu%VJm0=huBG)Wc}h2(EJ92{(zm+g>g2ReqL%h z=x8vMi5?o9OqP+Ko2s8#mYAoXR+O4rRFYq;Uz}Tznp+BU0K^^fPzM_68R;3oq;fKo zlJ%jdrZF%SLwcg%_3Q8h#F!WuK&L!GriQ>14WJ{&SQsD&^+1jig9JX>>0!c*%;2@? zpf%=f%nYCf>1@o5oVE<0Q^i2%gH?joqQh^sWdpBNM<R1GJ;mMW1bS0o0tPyoeMcE40PTS=nx^;nPG^d!f;Jk!IGCgJcQyCOF)NL zQU4IJ^5nsNb{HfCV6$KG$z>(rv&-_+(uz|{Kt~D{7nS6fCl|v`Kg&%j%1OhW66p^Nq`}Ka2_)jkN0e`c&w+2RX{uhJ6jCI zGqC`jx|3Q&yHm#E@tg$~U!0Pe0zR`aKF7=?F&>=5iZj#W(@OJ_NuF_z&jag^FUgJ1 zEKUI(fS8k?oS0LRnVSkRIXNf4I2Dw2K^Yg8QwvOs86b%*C9!f~CzV0N51_UIh(;c+ zgiR`gnlqpQJP-|12Ric$)HneR`+>w^Z4PLIAEbnV1!T}5Kl7_7F)uw8^|5% z$ZnM4k|G8@(ApHxd3kz}9IXf0q5?j#tfE9OC$j{)fd%IUJ)m#^hX`m$l8n2wVKdC2 z`5Z>@?Kd#fK=ZxGvjZSLXk;8&9z4_r7a)Bv2`Gx;+8HqCn~{A7vLDpcL{<-)1wiJ5 zW*L$Bk_<2%pu`0_*9)|D38n(nrvt5Fg(WtSJZPOWvOJ{O^L`*UXbu9T9>fMEc+gxThz;r{ zg611RY>+it8#G)1V}r&3U~JGLKNuTyd^?N{ z8o`9I!Rr7(lYwM)3QWyS zB)y{4tzl9|J42k^-iTw|W%?;Z73U#Lh5*u{K1k6kW zByrG?HB20Io(qf(I>QCVE=E#ckHiKYjt^6_8%g{)68ka|8#HAFQ~w!B9JFu-Ce8~Q zvx2%`3W=?b#5O@aaj>KjG4b4H-2qLlNkl02@?06)0HWIrTiQSLHo{hv_j>HCy3d7vFA4&W) z68kq2o1K+`0j6FaiLH&q2HiOVQ{#*z?vKQ7LSjpS&eekYT@8tCjKp?8V*4Vo(~;OE zNbE)=b{`UZHWGU$68jhu`!W*y0TTNy5*xI45#~oe(79Sr_e&$OHIUe*NNgu0wm%X( z28o@C#4bZ(HzTnpAhACnvA-j+{~@uNLFZ>d-N_4LgIbcHd&Q8>@KOPZLz^_9iyvTq zG)5A)0I{LwxPaK83Yvj|!4t%Wn&}HQ6Eq4J4HAc%nE+x#n@B|9I9p$hz&JoJBST6=KvD>B8UxD{|t!@s@YNDXNGR|+Z)TK}W~WrNyxYEU+4J)sVi z4VwNlg0ew-M=hXiP`a{%vO(=T&_pK4e9-&^$e)bRb}2F&6h5%91+_I{Y)~5!#s;Ma z7#p-75XJ_#mp}mzGLT3NYLkL`0HF8P4O=7HiJBnL7N;=)F^?M*T%zZ~BAZL()+y_dF zAUTlxz->{G1}FyYb^Qc#2$T=A3zR28dSK>(&NS0uhx8#pMGZ&}WFBbi4NMQn2rVuK zhDS&OFeYeD5XJ_nFgYr5|4@m!F zBF`Z6fu2DIG7prTVdjB$_#m5im(4;ufyx<>9LRlZ zK<#aiMkv0`!@%GUi&P{z$Qm972AFvZ6d4#mYZ*Z1fqKF)^FaI6KyCo#C6JLy{0s~} zpiUcz12qpM4_a*lqG9UtaGYrdTGj+g7f|gC>qW5dr@IF=8>a5L2=;Y;p#BBOtuTMg zfu3mw@&~8~4w3_f3uu2a$bB&L-it6Wfc8+r_%Jz89|fcbX5I=Vh&qsYp#B<24rCsv zPY26GATyjr85lqZSAp0d3^NZzBLzQ$g%|@v0V4wgxW5M;Ct+X!#UChbBb&EE9DBIv z8yT8n-JgeJou7pv^h!}8*7=B|+4YYKPiIodvNP7Y))3lC^@Agck0&B4*St-bi>xk8G}3tTPMc}TKEWBg$4GAJOeLi zrD6|jFldz)B*Y-=s#|c^^2f|PzQP;_VmS%83 z*2(dJ*EK@c$?<@ibF8Ic^BMSAKQG~{6KIx zL_i}D&_#1RA_*WpwO~C0BA|L7zE180D99VZG7=)7jV`RsV2+Fk=-6yltn1{eK&HXg z$*luf+6C65BLZq#vG#&F1|pzy3s_<69=lLIeigRPUB36g=WlLN&7 ze4QMq6#`!;2Ui zx*fFkmWL+~ctFR>vmOMcDg~aspg@AGlj8v; zC|1ZiIUdlk11n^m9M5Nv`9!Ug1KH)k1G>zY6|zo_=Q2ny<~lhZCy>22Kdr)jX0+li`JY691#~}473}PS(yf6;5K1Uqn5y(0@kT`Um z91|l4=#E!@$T~TY1bAT_LIao!634Pm4s?DCVx1h=e2|bhR5^H^9EgorCkIjkT_*=F zFhT3&zx%O5dl>y ztXS8{fx3wBb#jwICd1arfiCifuao-)l5t=JHH3LYKx?^JVb^+cg2X_p#K6vDVh~nk zWMF`=lgkGMJ8YfYVNjfbSFba$h=3PB!q&;%0x3gVC-;t-fdRfw4s>Dye4QNVtVY%p zMo`4Eh%5vxb4vwtctn1IQcD_`BO(GCQDTLylVb*TQ&!kkK1tE@Ox+ zXpBFNgMmSgF_x)>L5?wo+sL4p!9Y`kkwHvYjxn04m_d#)3cPNOpXDt(1A{!M4q;mh z(k>1%9gz>jLG29&d}n|1F)%Pg*Q*pXb-ANMU2jrz|5)2G7NK4lw z7#L&`OVQ+zmZHg{uRp`F!5-Ec1hok7gN{9501w8Kw00{qe{|^u}Oiiy)i* zNnO2#arNUl@My67r={-U~3o1TSEn2W&1(EdpI6nTC38Awzs}etvc) z=#t0cbkH?*VC|r8Pke4cQED>ihQ!45Vutw4;`ro>MDT5fpquKFaVS`A_ zb2dODmmnDkCVcLOCy*62g(Mo!GW^DYjB`!@ERN_8@vVw$_9;q!R!LB z!GVf{oBdEWc>WX02Cu<^vcYR`plt9O94H&S1_#Opufc(`!E11!Z15T!C>y*62g(Mo z!GW^DYjB`!@ERN_8@vVw$_B5&fwIACaG-4P8XPDayaor#2Cu<^vO&YrFu#M>;6TN} zYjB`!@ERN_8@vVw$_B5&fwIACaG-4P8XPDayaor#2Cu<^vcYR`plt9O94H&S1_#Op zufc(`!E11!Y|vmB%+266I8gD!pfxp6Hh2vVlnq{k17(BP;6T~nH8@Z&z}Vn5I8ZgKP5tIuxjS@cnwwGCv(j98^og z)_#KOBbYg$`Utiz12hN-69<(`pn-Le`Jhd-AU3Ea04k$EY)~x^TcZK3Rv2LC7lHJ^ z*r3`SW+tdz1!E(xYXGSy24h>Z0IFYMdSPtPv>%8KoAay?ft-y2wjVr$1>vKwSpc1p z4^o3}9%$|Y*}N7J$oL;fEhtPtav*<#W(z>=N{|@H4A9v>AR2~2av(NnSQgZ_B%}^~ z%>u|gP~8nO1B5~Lf@t(L3v)yuX9 z%wvQ285Gwr^U&8U{O4d`m;m!6l6j!nK_p>@elF~1?4qw((2<6$H39hp9%)GW1^ENCTpZ*_Q22l* zbwTcg83{Ve#sJ1aiVx7*29O?@c{8LTYcD|Nf!dNFIgojvrYtOtf{aNKVqgHBeGX!S zFw8Cx4J~p&!VDI|3=E*Ne?Vq4@85~4zhU>A`A@3dj>$}fDC}0{R0}#(#zK; zc+Z)IfhFYVA0pNSOaK)Q1l9y7EK<0%paHfj020=?&eZ|U)`O;S82A(zNz*##0py%@P(0qffsZM z9&BB}bxl71$OK^)k+0MKQ( z@O1%?LGcM&7XY4`g{=#i0g{2O3joCc_H_a8KnV!8E&z1?8Y^sFz%r13VCw=vCr7cO ztqZUrWnBR1iVoPifMSr-u&fIJZFymZt_uKl4`J&9K+C{j>jI{Of&#iOAP3|^=(>P) zppb;F3-|;wpM-S*pzb+rUBD%fUM%YZKns;vq3Z%bU2NF8fJl%Vpz8u$KyHAp3y24a zleR7Z)N31z>jJbu-h!?R=s-R{2b`B->jJ_@O1$$pkRls3z!Q^E3kC|p#CB&Y+V583?){ybpfA|*9Cxj z%J6jopd(`7>jFUguUKL00)B#03v69LABY267r+DJz}5wTj*Mf4tqZ6H%6}p&FB5W6X#$8b@H9MQ~dFe z8AH%f2%|IlN#NxO`K2Wc@yVq{MX7lu@yUrLspq{gQf718Pln#_C#e21hA=(Im1S)~m0$tbXj z7(~McmOxc8Y_cEJQUg`lAQ~hN9tR!%ll>?`LB^RTprC?bX3#m3Fb;Sv0BD2{Aut%` z`k~Vz;D$M9t{*g}33DN6OcFG!pH!L#pXdki5wrZDMYa&tpgm-;d43Rkbe^AqVRW7! zk~T)?`61yjI?oRYhtYX{NH~nn^FzXc)Or5@pgDg~+XPgnBF*!wgXZ(0;*lUWv~nY6 zZvOyi>;bA5G}Qx|!w0$UBJ`{T(7YV%`~}e5Yp$0jUG|6Mb$Uv*{#OnL2GCU% z5YrHAM$zZ?%ZQxY{~|@)-2OB!28IVP$0N;QqtES25IMJB#>2oMM#S8H50P{GXNjEK zXC-oOKZMA+eO@8RoIQGcfF|!iX#zI4pFrf?zAce+`vOGH?Hhj)k0L{0TvM?|(fiKfx5dsY} z^MF?ifX)BA6MNA(sSmaWK1o23@8DI^uvCdYKNW=wtQ+9iqp=z@o~+ zz`*Pe+Ahoz4)Q@TXd5jL3rj6%Qb!E5f1jC!9kghY*NlaML4s8mbch7^QqVM&K8T5O znT{Pu6Zp~`4({u4HV^k|kaDm%bTL2~^fDb;Mg|5B&`#qvMyS&n7%oU1!6Y{f=E^$keeA81>b`_<`3e4 zF4F;BEdsh)2^@2EJZ*ov!NUg5hG9-Lu7bF zmV(?2zf1>YK|Nz0_%a>vl{v7>bnb$bH8XoDRE82Xv?{{4yQTB4O4(ustRs;Bz4+Fz#drU8V!N51Vx&<9_gEI=rB$ngmwn zAOh;-u})NBPiHCM8I?3vlv0)>LX$cvUDyZXc_Dc5i5`Z^T1*7L_{7W zGoSGe_%a>Pky5M+z(#{E(*bR==Cx#HV8~$I900#e2OR2r*e}xooh8M(9dt?v4|g}n z402`dYMiFNd3ik;LCJCYwuYv{bNO3rUTOJ z!953LKJ+pj&^Q9?O;C`8aD&bbVSNBPRwIHNbnX}HBTzXL!wqWVvLaum14<;~ApeMi zJR%O}f|3UVKT8QKsO01TEmYxW0R<=cG96HILDB%`LNzR9Wnhp1>EdT;1YMK^Iur@y zbtL5=A=p(apu2a#MuLI_p@xB<@+cALzCkP!Y<&z^V<33Ry-q z76t}k&^jT|Ap!oN<6XgdS(y>UW)J~wPJmyg1F9fcRlx}fbeRq)b@8)+%oI)rm!7ta zb3q2gf&$eJ%w`Y)onFRj59Y9mfNol1bzlS?B*7yh1yTlE48Q>rTMKg@6NB&uX2>A{ z??EPZgOo-xf=gr((0OXCu*-BVfn=h=G8`h{qb6b)L0UkU>420Azh{9Q5-1$a;`WDwx9~auAd<)4&`N5ztCK)^tXYei;!=`y1{E3LI079K015#~ zP`Lq)PX>OL72un4qQRHxfNBv*P|k;?fNNmMqhRtY8v}zB=voD~&EVw30BQIz&hY}R z0st+LVpIktHc%YOfa+HWmoZpoBd9H)4AR6HA`9wh^?=R?0JR)ufNseF9~2xhV(B=>rUcjE2Gt404Fo2=Yj)5ft?N5&Ca{9c2CYU=L|>o)TJ@lWE(l7F43N7w85x2=Tj0P=S%%MyLGY_@KxquTL5v{? zM1h*Bgs-syse&5L@DkJ@CHJ}-vMz6dob|4oig9}bt*@FHu*-EISJ>#IUsqEC>R^Ev zK7cmT>t%qBS%P0t!_2?{KL!Emx*CXZPG%C?bv0^?@T+Kq7#Nv3IoaV$As9LN7#KmN zA0uNtc*;9IEhjO(*a&p+0Mg|qh#5)fcJlc0>l_Qc(nT+5X&9lm)685=a=S{Fd(Ke^e8?>tC^NyOE_FG|LNKnF1!jF$TNFCb2jfag7Ej2{OdzmgYdi6>`}ILQ{Nk z8tCF1P}~+Xz<1?CFW*Q5=?0wyQ3^^N;P5F;ZJS6vStsbq^3$d=UeD0Znp7 zVi7}8D&$-QcfU{tX9W{I3q4Z>-CU5Xk`r@siWPLz6?FZJAvi5BUpJ{VGp7V}Mg=JG zCNY50UTTU0*r<3|K*kqA7KVUKQGi5^~i~aY+$k-390x2!?o&L7+u8U`3$R7Y|Duu+wn;9cBsH%%G2SyT zEuSGY*frkKDcIj9G{iOD$1}t=$k8X*)_}{=$nL(TZnu@?9uGrRDfRYMCHROy1(A_W~F_1|h^`Q18 zvOH)V2BZZ8FHO=@OQ2;XLO@)v9jBh-tav2alP7bFNunlN$Dm@Xs8a?l(b z=w20&0F=!Q)eAbWU4#d6Cpw7D4Gk91Ff<WFCkOQ?Cv+2V@k8%?&jlWH;#i2asDp z*$l)6jTM71DQ7`|=7&IfK|{454ATqR;|H621I<%`_Va?m7Iv2lhz%M)0qt`Jxdr4t z*c={cJq(NuaxRPw%H}XLG0u^IMm8wUVCunVM}Q8yXJB9epB({ZgXg)RZ16b}P&Q~@ z45k-+js#R3e2xT^4Zh0-$_8z0fvE?dBLNj}1I-CR*%Oi2OOe>%yIi1ZK!dt4bHL|F zK*gUUsRxZ#!qkAaM!?vhu`C!{5;UI*)hma@)^@S4P#G0QUe-;g^8~~65oQvK7hpj zfW-cT#1;YF!2)%g0uoyXiEV+zc0pp7BeD5G_o6_}kw#)`AhAu6*iK077$kNk61xnE z-HgPZfW%&h#NLg>K7qu(io|||#QuiFW(KX>fVy7*i7ku7))rW%EP&J^nDImK*^-c;%9I7S{#D>~c3}Qpo*C4TbL2Rgc@SQDC_Fg1$ zkRL$igJ@8l3S)zm!q}kt8pZ~Vh{D*QflL@1RENUYpgI)B2G^A!0@fUcx)W4i!__f)^Fd-DeV}zG zAR2~2av(Nn5*n1m2&n_P2c`$44|Em=%ugUb$X*bQezwLAG01%&Aphc9e*-$v|1!uS zAVWZL2Bp#0-`I#VFq{F+Ab{rBq31k+{EL3JMmHw|!%-v$!HHVDJ)Lcb5BM-FmN1;{*5It1ATav!)|hjdoQd|n0yM=a}kz->Mxbq|EF zpVhIGfdOR|yP`1mvpP;A#UaSuk;2%|>HsZ>0J#+wE)V1&=SP720V)STav*Wsd7ySYEX{-TuM}orcnD%ZG0Z#= z4J|&vGCd*;3<-=344`}sG6Q5DD7-<_QOM@K5oKVo2J3(jAag)0eIrA26UYJ`FllIF zW@2V(Y+`}q{tiPk6LZL69SL0Zu0C#zpo7{#27$vj4s>uhl*hnu1!N)8dLCKuDt@>$ z=qND+hXyROMuxS_n-mL=bcD!tIF|2XYSUoI3JGFm$f^i(XOK<{WBm_PyODumEi*)AkCYoD z1BA)LB>RCOk%1wWYX_Sf1A}zvhSmig9AOdv8yOh1kIvwjvvMudgEN8<#VgtVWWkK9 z`6T;+;lUX}9?6*;dwJF}orJogm+OS1Sl8bjY=_SLK)9@vErU(EH6ddG4@W0kBx5Wy z*sdg2hNfeO#WWbg#QrBTFw9`=U^56kP_?z8bHQ3B?cGg@&@kw5tYurtA*S^sf-Qs5 z=4L?Hf(TYnA1#(6iJ3vVHOZCXOqV07qM;3473(PQG>!S?t6TBg0su-NkDLeiki0$vXm62%Y_Wedr_ zxYmEo0G)FJ$|!se450P_C>espQbA=oSlobt1v-Ynz`(-j4r=e#urM(2fg~9i82&L3wT&{=*=DU2Zd*jQM+ zK*bk3=-3JtpV^?25p-o5i!Vr&fdh2R{xwiF1tORkSXkJ|9mTPc(vM?~P zK$n6Ag4lkLJDHeIf$aCc3mRNm0`gBVXr%`a3-b@q%s=>C7#0?G&=NJ?t&HHMVAYHa z4BWdwvdHJcfLd-W+&Um(@RBbMZqQkatY9_|H)vc0!WQ6*uV7#`1T9t-Vc=)cU}Rw6 z0IfFz-50|NaykP8FK9nD^u8GGEuiH{(4}DDV>O^l!5)Lep-aK`fL0tqmxBETt!{xX z1q0p5!wOvrCIM0dT?)1dG|3KK3RVjehb;vIT@wpC7ls?;BIvm=pr$MQT$pvi8fSn7&0lI?(bYBeEBk~NqY|IP{(EDN_AqF`YhMO5=1av9bOppnXb78n2g4ihM z!f=4@iUDD$k*N2@fR+_N?~CCE#US)t81RS}D|{&!C}jwnut1iAf$rfDNe9^vTM7og z5Cn4i3yTOpDEJ^84w1DW=Ri0-BL6^v23raSYCpp7i_riDA#5p_ILH9lQZNpXJy_3$ zQ3A=p&V>Q5Pk}83(*zmN3tmfRAQA;~0qk5D(A`Y%b749_mcq`30S#fW!p?=U1IOgT$pzt7r@Si0gaTPp9^yp&$%$*d;qyG2E^px z2Hz;O9kjxShZ}T51?vtF8@3c|7kDWcXt^{ibSYQ}$actmG2Ec~mh~VgRVi?Tx-qPf zb78peg496Hh2f3_g(T!$81CsHuM>4H49IN`+}A)DOeO}-4(d>gPjWl%JA@|V6#A4u$~J8 z8d8Vf7h?^IG}yT?paC8DeKFuGe;gR?7#J9MM4o|6b7o8g_jEZxVxaqCz|Lc05C+{u z1V0xBd^Z;CTo_O{7rqp14Jc8-&V?xenTU2S%yZ~cu(_b6V4x8t)?`Ldq%nwm1gTD8 z1Vt>1$TCo3Nd0zb37P0VE4s(%cLTKfz+r$m*3rBk4Av zx=j((CyeH1U;wRiQ(}x};;;poSwiW z;0F~eVPH@MrP4Lr3=DZ-u^6U_4j==I89)XWF)%2CuEYg7vI#5?Hb*&%fq?;Jjw0y( zR*>X;grp*q;7=RL-Qr?k zkhssqz`)M}a*z6E(CEA(h^e6nTBXR&2r3CdL4s5^gNED~G(m&?9K4{w1WPe!NU$(4 zu(5zOfRYPXR2-~U3v}`zJGfv6`3TGq2MugOr9rzI*rh?i3G%r(D3Bm!v$gVq^#g83H~m zpCK4Tfz+}wd}a(*W`r*%1t|yhQyCdTKvW*+W>SU{hB5{vWybj+9>^#*h{$}9c{!l! zjv)j@6@vP$3?+>7K@5=Lj40RLGJp(ZWC#UOAe|s*hJww23_ym0D3CUY1jr>I3>sAf zbzT@5B0v+;;E8C42#_Hl=WsBTF;u`E2O1$}gNT3)2H#Y`5CNhZ zv7qav85zPsZU$jc-yCEy6NABg5Difo3Q`HOnUNtBqzZ&#Dj6A~K?)ZzFfed2lrk8p zR5K_kv&;waK^wg|U}Ez@W`KIh2oVqubk{2=vW}$l)If_L^#^RF?traLCTk@%o^{3XWL~8PUs+sSQk0pO4q0WK znpXx|!w2OQ73JmYWiYTXFo0H%LIfEYK%3?m7?>>>nOQkO7q2mK@-r|pvw+qfGc$2= zfL9}PF)%VSaSDP-CI&`kW=>uPMg}GpkSJ)?G9!o&S1kb6!^XhK%)!YDR>#D~%)rS7 zW->A}fCSl?89@{?6DKFwR9-L%GMf=>CmUF{9_%8}8fefeX+8#!8(G1oL)5c?+1xO_ z3`{Iwn;@2gY+_$pp2b8Z5^S z4rPdKkjw8tO+QBD%kQ9TuR#m88H!7al5-2di?_k6J`?j&Kub80RzX4*PaA-iWTGsT zL|@SjUTO*^P}jhwW#*-%=9R@4F~IM=D~M0cE6XebE&W7YLyNZT6SR;Nw3--fDwqH* zMg=YTL@ezEFFS^;s|6`1_ISK_&@{>XCr05Pjuqml2pf&br zYtm5{>%!JzgV%C{`~)nM_^Jrrq0si`@cphM{}_8Gt<1hNJkyfdS?q$m%Z5fR%fz`g-5qlWCf zfbB~_TBHqKn+)3i09p7CT7nH<%Z;?f1F^6g7U8f}(7E9B3QF~e72&zi)!s#r1N6YF zyK~^%Kww)iV8uu(XiaxoL4GkPJzdr2D*(R zH>o7QJQ;QmD0pQ%IH5z5IY@ghC?%9sf&4w7OVL3CVW5^Ch=$INfw&B?rRd-(G6u-q z5g>WcG7C`W1~gct#K6D+x+ewHdIX7sn)RUhY>+spX$@MJ3u1#Nzd(k9)PUHaC9NQF z@Lgo!jtK(;s0|Jh2bl$GJj2w3*dVna3~G6U#_T}sGvKyAWL*HL8LiF0zyK2e!N9-( zT2c&RgL(rnb3km+xEM$rG%p9*i3?(TgW9!FH-P#HpsS-n;-JBCm|hSYP(o*@JB!v3@( z(4G}!k<7fbd0F*vKVFAJ{RM-~)N^20aKxgp4R%?MoKzAh~ zhdzi8O1%&{5XlVQAOd1RFf;rnL>M2mMghVGk<1LB6(JxN1T!;07r;Zf44C@{U^Czl z1KztAe!* z5FfPO3&aLt5Z@KVfMO6I)Vqgr89;n^7aBa{!N8CLlZ5g?XA!`JK+bkfBxdjZ6k{qSc3AQo5hymLCfwc(Y(RWWUFu?W}fcoE{(I}9gK&gun zBmkN^0+n^pbyuLXt6*wCVFue*0ZI*w&?pCun=*nHEP*CDKzcy}43M>DjG)a143PC> zjG!?q1_lPuWB?;n4X8YWiG#{`M$lp<1_tmNMMlt20Rv>s79*%IVu0N71XB+h;bD{m zxt@Umyyg#7c`!iMP{G7OX#}PoRCh3fDia0<@Yn{-{V^anLz6RTeIm>+p!5TCKWMcD z%p8!jM3@*DKm%%^2?-DzG?f4vUIrh4z`(!&N;@!dP+bEO2L&%^%myS58k|`H+Ec;@ zsZ-cNr`s?wFo5ENIhsgDITf@R1c&>*`RwXTS06-$XXWAv;;^!Xt)hD zApkN56o;U5;XvY`a{VqyJriVb1{CigHK4c!v0?jKKzxvTP;i0j2ap<2oP*fh(0B*c z4Ipt)RD#&t&@`Y0^%p3dKx}T10%$yf)Pu|f-N(iaO&g$i1la`&CufjeCI$vj-R=%z z^Fh)Mh|LX6KOp~r%mJk%5F2JbC>}xPfZ77_Aibc;WJU%C(0CtA9JD?Kq!*O#Kx~+q zplNB4I4BK**xb-`2nt7#UQjy%gh6UR>s3K)Zjc8V7#Kk77C~x2ZHM(xdqHgk(A{1j z^&r23*xb-Gybr1d)OI)oV)H@LHHZy!&n>7pC~QD%ZfH7x0upCpU;wpEK$p{i%m<}? z5StsC{y|4Yf!qU1N1%IqKx|NZL=P12e31MBV#CY?EkgmR0ht*FQp3c+0BVDPE*%1i zgW4(J)0dbS7(i(cw1x*{FDP$;*f2NugY@!2+Grp)Hz=YR7#L=Q#F-cvKy46E`vjyH zG`0w0!_v|Qs2Y$MXdetn4JbZAY*?BEO?`pf15$Gcq@EA5&K1OlrM;UVaV7@vpd;v> zRggKLd<wM{3rr2@ju;plysrzY26Vg_OdPz%7b*@K#DF>IJ2Hm^k=;V5m6g2p*U?_uZp4DIL1`7n2Hy`1)eF8K7|P}b4a-5< zpzGye>cRH|L&d@O14G&1`+=cs@cqD0Ht41sm|oCLXfSp?lKI_8Y|xrQm>Tf?z)*9* z_X9)O&yduE&kcr(gBJC|^n&jPhKhsl2Zpl2_X9)O;QN80Z1DZSP&W8}U?>}WKQNRH zI{FJ{KKOoMs5tn3U?>}WKQNRHz8@IM2Hy`1WrJ4kz{~;P4-6FtEmVSugYI{OvA=`% zbwSmDF2sY0gYO51ii6J$hO)u;14G%M<(e?{phMwk~Fq93x9~jC8-wzCBgN|*3nGd?}3C0HB4-8cUz8@IM2Hy`1WrObrhO)u;14G&1 z`+=cs(9u;eGr{)*L&d@O14G#kpgmPkHu!#EC>wk~Fq93x9~jC8-wzCBgYO51vcdNQ zL)qZ_fuU^h{lHK*_& zVyh#ut&!ONNbGzhb~6&Y2Z_A^iMpK+*unf7M9rCL}hfUkOtWT15zBgZdsY zHmE-WV}tH1hOxIJnFDH5!NiXviG%hbz{Ei(yu#R^g#s`(Xu$xC4O&SLV}sgYFgECh zS{VB;lKG%5K`?R98K^KeKO@5LpcVZvaVaEm&_YO)OR9@gYM6UiBCZi2lbC&;-Iqu zVC-c`YC!Etm^f$!D2%-yNzE}N_9-Mb=p1;MdeDLl7#p-c6vhVaRfVxXAn66&=?fDF zE%AV{L5Io0*r27QFg9rKD~t^~Zve)YWkSTSE)pBGHw2~zbWARc4O*@bV+SIs4@F|9 zAhAK`6TsAi7FNR8)ktcZkl1ZV>8Hn zZ-muNpgto^4Y)lIEoc5f_XmUWI};NF11Ri3i%3Bmb3km+SPLj@L2OW08r1g%u|Z`O z=qyzb8&p<-P6Gw8L1QPN!-+v`&{!#`{SRV;#!}3n=7aibHc&Qb{L=}_28~^T)?0$q zgT^-epyHr$Ezl*dAaPLLoeUKRl{Z;XHs~hn0w^0ard0-IgYLqvfwDnk9-#0CnFAVU z=zxlY#?bnpY|xkqDEvWcE-)}K%z}zvVPIfb0A+(#CxP}bfz*J`^#Cm)1+hV^kvBor zfW}pJK-tWU3=D^%Y|!$lvrsmuUkEzg7Ni$6<_0>Y7sLjQnLL21k!NIJ0QF@+;-LQG z8>qNCBLl-HC>ykL7_@5$qy}_bDd@a#5F6BY1Z@KYu|Z{w1T!RlL1l~_lnok7QGv26 z85tNrH_3w3gO(c`K*d4r0nqstAaPJR0lHNf#0HIlxIxu`Zo>9~vO!}kK~Og6UI@_T ztRVHEvA{T}IA|;|12GA0J5F2#P2xy-fhz%MqY=Eii6=nCLFEJ}O*4Wfz(5R8pB>5uk7Gd7Kl1nqs4j-(7v!-K8<1Y8dhoae zlnom9gQ*9P*+RuZbt_C9w5kur294vv*q}`wFgAG10jd|2c46Y6ontUID80hi;CVo( zdhmKcC>t~`2UGI_$<3hiykX*?O+zp?X#F&dtpJ)6gqj1Y<6z?8g@I6U7bGkhFC#t&=@C3e1~r^5k~02u~KgHRfjKR|k5=DBDxFi3Dh_JxDG5Fj~_ zHc)+lY~BYx1_sb!`cPv)`^msea9#qlAVioT1H%!dFoc-_8uJ604YN1Kh=Bog?>fjI zpl$|84rDK=UV-TWnJ6U!nL7fpK^P_ns*6B+VCH=>gUk(p%mcOeL2@AT!1)-Y5sIxu z7#OC)A`vNEK=l?#56nCXa|Q-b7=p|Ljj@8{K<0tV0;KZ>&V$Z%fc6DJR)E|G!uz3S zgUT21=0h;AhSR;Xxtyh2JuDYAag|^HVDJyuA-$E1}n&1 z5Xc{(sT!C+K=ma|4@kd^90LQWUI4K{7$yg*V?lag;lg7DQ3o;)RAz(ZK;Z%kBcxzu zcp}fh04n=HW`QuwJP?hPJQ%JhFff4HEZ{M7sM|qf?C9qbd{JUxSO_u*ib3Xpm^qnA z@rk;{sU=yt1;pGlVr*_=06xHghbo_(Ip@>UhBOXP30vW+0WS~4*_5&ymVP!QbM@rT)F)%POfO@@* zcvooa>FenuuQbk0OwP#6OVx)ggahB;42r>ENWlVK2Yej7yce{n6}8Jk z#}z}Cyb>l+b%D%*EWgDhVasC)n+bCjL?yyZ7VsikR9T1`>?Fi($o6uB7UVMXLd}7g z4ABc=BS&9rGogApFXtw2&Tzl%xFm+wC>L_Siwlo$W+ge zfw6&6kU@Y=kWq+{nM0aGl>>CZ0oV@=44^U*>NBVa1K4M94wL~~F9#~8KXq*c) z4-Z?L* z#KoYOR9wuU2g%ubki}X^2esy8=B1*n*Mg|Pxtt62VAqNgy@H~A&`24`QP?r&dL`tV z3AA1cRBIvhGBbc$QpkKzO9+_{Yi&ZrFz>rXY5;(?-ZFr8BtX=H!dZxc5o`m94Vni9 z@j>f@vT_T+i^f4TD7-=a08o5+f#&rYA?sd1bD|(|P`rT7Faohb@dcVQ2aTVBY)J;K zJA_tp31wrF7 zjF2@&pgCiZIB5L|=;kR98x&W{P&J^q1I-_U#6e@f`cQGuK6KDrGDsZM?gx!ag4m$V zTcEQ;L2S@^HFv0b(DpRYIieu(Xa)v`V5m4~o*i_iC`cUCjt8v)0S7&U0@0mKIN4>m*9fX1tLLfIV*3=E+0N|2f^ z2FRIbAU0?{0BB4C#O`BYU;vF*g4m#Z0KT`95wczvG!6k02i=eK7-}XcZGvv10EvV8 z^6#PIpmh2b$_C{f(3k{B4d@amP~R5B2AxU34jRW{WMBaG89-;Hg2Y!r$E!i?HJ~eB zpla5E)+IyPp!Er$GgLupKwAX0q2i!*KAu1M4=UkcYXL!J0V7BNHg*XuTR>x%urdcE4O=4!YOlk@ zL287d>Oo}_OdM<`R2Q5>#9&w( z7vz4BdQiCmtLH#`Sj_+`yFhGEc>ogcVS}812=*(qp91m|X!kP6IiT_uqz*KG2%=#a zBnM)H*86~J8A9qnWg4iA2I&D|ka?go48#Uun0cV_T^JiA4jL-~jj4jzAPkcOm2JrW z*u%!a0J@|J+WD|kn{o;)c!umOprKe-5$tnn7yFm13+m9l zFQ^VfHV$-VbDoZps_-beo#FNvI}H3dcU@Y4YD2@qz8mS=74B@BST9gNJkY+5;||s z!pH)8JRjln_WpnpH_~}~u=_L392t1H*D~?Q+~tOxtwzMXn4oq5Xq=mYPXW9p0OU{5 z`DdUz3K>BKk0L|_zC@gfkqy))U}EF|osPuB#0om$nTd%Vv~Y=;g%z}aj){eRALv3M z4pz{p3=;=CsN!P*E%;=*1}Y0!Sy)s-+r+s+6R#|HK-W(4fa*7v)1dRy1iBd*7?@aC zL9>o5paZ&C)IlO_L7<*$3M0q>b`};d(7+3a4@iR#=sr9SP^H7-3le4E1Z7rGp}++q zm>HN@z(=KVbFjFB@&ONM-4Kf>$Z`grC7?sk{6I6SEDS9AAdWw1N|XgOPskDsszq6N zKu7d|&p%^gVF%5j@qz|nC0KPq>m_+W2Sl?XpMM52mxZStbYPAFh|R&1$;iOK3TE^0 zG=dBRv$33i#tE7&1)W?2b~pnAFQ`U_o`1#znjvO22bsvg16s+%Y5`)i@PKL&R!b0@ zg9miNGpiMd&BL=Ev|`p8#1`P$1#*oIh%Lg?26BNdh%Ldx0}{6bv1NE3fW+-VYy}1Z zP{6^?KjQ(7OGD2;17%V8`DdR%x?$&^@q#=FJO7Lmv;-4$91_?g@(jG7DIDneXOIws zoPWlX0Wu;KWGM>|XgY-za{d|58jxuy=bv$c&OQTSsFA4WpNTOuFhI{g;{jE@(DToD zK-C#*DcF1leil%=5C*Lv16_p)I<`gR2+002Mvwvq5zzWtR>&!5EF$2OlOP-pkqVG= zARHc%WRRX(upR*s&^R^x{Idg~Aa4ZANQi(|0kSrOIWi)-AU#;mKLcO#2s{6*17uGZ zSdWef=)4!!UNFZ%L>D9jJO7LgWX}Y~BjBqrUxVTecK#Wti2^_W3{)1g!p=Vf#Q^;L zGf=GwKmQE0+?aJPqbeH%!wnHoyMh&V{uyZSn-zBc8K_l+e*T#ip7YN@VaftI{|v=8hJhwo4G0#8akpbCz1EfBH z2h<&4y$NbGhwy-=R9PQ@Ivo)_P9Qft0+li`JnyVGsjRpu=h)2i1T)0y+N- zBo00QjERxsG&ATF9Ps&PAPLZcHAou3T#z`H^Uo$RFfbs_KLeW&5)y|h2cLfiVk6E! z1F3*;dkV4= zcK%ryh?BwyidYsAP#=di70lrg0X4c=)4&`Nk!c_|!_Gew0dX?GcB_bh_I$8rf|Y5A z)PfFB%K~!@L_jmmtl40Wg$QU_5^D~a;~)ZBlh2w9=6Eo0*0VA&tYv3l0DGE*^UpxB z&cM%te*PH?sJFpp0*YlRS!M0BJt4#0aSB_9I=GxS6y z&|TcfCoQq^GjMY=Ft9 zb2Bh-3nQuJL8!IhW?{WSsz587s^}K_o+185o2_8Pp{i z7=*!!K(1m1*)IZB#Of&wGD{R{G?XhQ$_P3$2&7P)l>uajgc_KV1WAB|rQjzAfsZBv zordIqd?zK+*-0{p(~o44&PS4in*cwb2o#y%J%Wr3L7+h)P=uqN^#U3~gfxet%|8YP zcnc7u8&tV5F@QF7FyfsyK$$ZDUA~piFnX>_Nq(_@ac)6sZYeByATulRkRexHBRwNM z1DF)}K!MD>cJh*vpU>7eOzG&cA(7mprn0psR5edK_vWm0%v-}Bc0qp<{2Eg&)z6b zErGg(fi}l*;6HpL9)9m>8RRZj$VG~%Y!(e`4v{Ay|t_i;QJLoE(CRrKuW;#1)xL; zJyQU-ej3yfgt0+m*`WPfAoZZogWY!q>T&24a&jT;Qg^sKZ5tiLfN4G3@|m|{jpGS@cvjR8?-hVrUuk`fU&{* zW1(um>*=9v@cvjR8#E9EQx6(uhOxo>W1(t5>*HbKpt(618#LDjV}p9UFg9pt8^#9j zkA<28-X9BPgZIZm+2H-LP&RmfER+peQw}o+ygwEy4r+$O#KHSxq2l2Eu~0U6e=L*@ z-X9BPgZIZm+2H-LP&RmfER+r29}8uJ_s2rnpwUg3y`XV!7#qAl7ODokKNiY94BGDs zWrIeQVe0Q9iG%mYLe+rx$3ofQ{jpFscz-OE4c;FMWrO#}LfPQ`u~0U6e=L*@-X9BP zgZIZm+2H-LP&RmfER+r29}8uJ_s2rn;Qg^sHh6z5lnve=3uS}%$3ofQ{jpFscz-OE z4c;FMWrO#}LfPQ`u~0U6e=L*@-X9BPgZIZm+2H-LP&RmfER+r29}8uJ_s2rn;Qg^s zHh6z5lnve=3uS}%$3ofQ{jpFscz-OE4c;FMWrO#}LfN456&AnX{jpGS@cvjR8@xXj z$_DR`g|fl>W1(z+(7skE8@xXj$_DR`g|fl>W1(#D{#Ym*ygwGoeurevPb4-A(!Nj* z=w4G$IWGee2RCRK7!*NlXr1B?VnfXYse{!8pf(bW4U&ejLF;2+Y;e5;B4BgnP%}aG z7fj6&(7Ji3IOzUX&>jhpJ)k`nAU0@z5p-4shz+W*Kyt7%8j#uGdJSq0a-9g82ZhyT zAoavxZ1dnC|HAab*r2IG5F0j6+93j2PYjxk1GO?hav*ns*5!cs(4b%d%~^x$TXge4 z^Bo{PF!QE}Fff4p0x}O24j?&@d7v2vka-|6kQt!0H6R*>L2@8AXebvHrG(Uh&P9Rg z0qFys{{vcM1Y(0Q$X*Z)TE7os!`!z<1ad|S$bF!Bd5|2)eW3lE$mW68$fScD0x|?t z*FtH~+8>Y}n0a47<`HoZ;C&7T2GF`3s4<{{V=xmmqlj#85*GslsLcYFM6wsOLJrwp z8)?WqJ;)y*_k-j>H2OV&&0MJS?=ZVSQxzaRFn{DoL)P1a%mcL*L2@ATKx=SddO&Vk z%*DU}x)T$`24R>SXq`Vu56rv?NbUp8lY`_y=7H9gf%F)FG&3+TH1aSo$bko-AOavc z5C*Nm0nspZ^98Z5w+F4m0mUOkHv_{1LG0`8LF;Ki=E2lS2w`7u54ti7k>fzBNm%ELT}N_Wzyy9>8i*&;|^KNP{_bgK8+L1u*s}N3mO8#o7b{J^w@I!S+$lO#(s0E=93!( z0}qpv7#okWfr$bSi>I2?F?UZkPd6Ts24iKKnclT=V( zxx+O5u>jnQvL8U#>VbA0K+-L)`|m*KLc!K~xN$-HYoK)=pgTDk6B!v8`amg(fq?;} z5ENNVjBKEFXiSV8pk^l%6Kg&*0|OHidp2mf27H}|3}{gX2P}oOw$1}|6FZ9v=ps7EI*)ZABhl7*fOc20K-PJHZUw`= z&f^sm0|R`W2Or2#=sFKE5Ze#B&SN%WoyS@5O?RMDnWYjmUk6*~;lRYezzZt)VCy`5 zK(d(YJU)Xa2Epq&ICzeOCWygo9v<*5b6_?x>pVdFC1C43K&uX6>pW~hmO|HgJOxb} zLf3g51kGeZ*LjG5TmW6?0owV>3SH+R3sM7J=TQk#16}6pVa+iLiAZ;1GkZ^SAEno570Ut*g6kT6AE>m2QO&7kOJ#;e`W>-zW4$L)*1If9^;EIVql%=2wDLMUYjrr z#N^-srFz!cp!EnmJVKy=n*(A)*Cxyb-_6DYS~kWy52Rj#2Rt>qU@8k}k-so#+8DH= z1jH2qUwjB#Q3Ad)t(x%^8v_H22&jw73gK{wTmuCogu^3p9uzvT6(yik!&vJXAA<%` zL{vdCuoWdQK&b(?q69ow-ohxt#=xK;8lPLhz}m(r&cVQ-BJvWXr-M<0gMmRq1k}G~ zg{>&D0EISeMM*cv1$|(9Ohi_K{5*jXbZfYU2&kXKI+4+YgMq=kHe|ETW$Xv9D0vS`xAVYZ@I(ZB5#xNuKn@0m7b5K- zqZfdUe#5}e0*Wc#WsnsmM_Hklsk0FyV_YEnr|h3v#6mUwmm11M4}EGaYz9hnulpOlD(XaN#Kg>Ah6U#=zjt z7oU^Fzf#Hl zLvPeO0=iKTTxuvYg4hfq;3YJ$6(ykiQCU^N35kP&p9Pe<_*p<^3WFBif>x9Wf$pti z0_74rMi84p#0|u;2Xoj&N5L%#G9uu`gRm7P;3aaf6(yi%J1cBO321#kd_@Up@DjeF z1e8h;D@s6-4JtCgaRgdX0tx|1P`Lq)PX>M#&?!{>EEfVa}TECqOTfRdIKn9Kql zuXql0m7WPGMx;RX2V@Nhs4W4?r;KwZfwn1w7L+7|SRip}(8MxhGAP-Cj>MF)03Cvs z3`&on?wAZ{zcOPoXwe9$H7{F~TEf7X36cd3Xv%@E6lKf;CH_)I1_t@Oq%;P`xuBzP z6hP~LL3>VkI2jn^KplC;9GEgi(75qI#MN&M%AkhxB~Atg6;KcL9w!5X7DSf0>;?ma z3aA_Qm6L(N1uPiNR0g}fP6f0vLV$~bAp$G|UI3#4+K`~m#lVmQ6)R<6PyuypKw=G0 zv2q3mMNk9Y27HTK6xbRDewJ_!1_o8o03z#R#wDB#3=&V77#LJR_t3E}0Slj0`~_3S4q9 zfCg)zatxrG)fpHWf1_lPuULHn<5D*121hgV51bl@SXww-ZLkNfh83U03u|Os< zGK7FAkV_#F$VP&;F)=cPf++AT4?`%30u5p?GjKG_2QffJ79&F_$VSk?BVch51LSZ< zhER|-Ajcxz6$a|(gK7-WtzsY=WC}9_=YP0yAPJDMATt>mfK%1zIXr2fl8K3B0=qHC#}WK`vwjT?@v{3N{&XRT(EI$jl0`UJkH& z$o_gJkV|0x7#e?3+iv#tSxSAD^6&nw%YQKo{y{$0sHimSz^E#uud~mlhRgmZgICXe)ph!;!SGkBB8{ z(3}>ZTvh^V%7QL@0^Q0p$d>??mE@%6K|%#>tza=|NnU(fVsVX>fx`ftionhT-N6(Oy^Sj^EvK|N1AK87#2?hXmka-bKuGuz zSQd!17%(?KB^4S_pdidG%_(7k-V=s=vDV;O5eU1c3~?_V=yH|#qSTz!#A4)pK1kLM zA}31l)qO>vmD1R*^%@i_3PF=Lphg>rhRtGu_^=g)pdK@5K7fW>L25t~ zrXV&<9K6a3dLtIdJkZK4ka|$x8l)D)2A!G!nz;h8L9I=gIUqJ@6aXX+>Rg*bZ{-3t zLt$z_Y|yMPNDb)Z2#|Y0=7L(dAUA@8EN7igsvXx0oQ4%*5EI!z12 z1~rIb=7ZRvc@U5|sF4g42eD!1gBs&7Hmt!5as$OTXr<;PLNCP{BC9Mxp$`fn5FUwZ zEJ3Lr|(|#0FsyA2eqVVuLV<4_fvK zYr!BFTA*qHnGdO1k*Zp7sg|6RnwVEw5MKl{h5@NMkB2oZ!9_J@lPn%lWkTy*SmP6{ z0kdoextS4^mBC$p1_s!=R8YD>ng-SDj;iB7(okG zpleZKcS3>J(|{I3!0xw#Mkc7Vf!$*Tici=*R-n=lwjLI=egkx#FKEpSs5AtLgGv#Q zdYCwpK#TkeVyJrW~ zZ3pQExdjw7Fg9qlFi1TpC_rr3eLA2nJ4g-4jiCD#L2Qt_KvP{HHpu1By=&8>R*{90O7VszE^OZ9!~M2@f(C#0JF!=sa@}8&qp3LGK#^ z)d-+?0*QmvgJ!Wo=7ZuK#D?7`1xj_GBf&uF0Th2AHYi>|cyxU<1Hk$9M++mZDV9fKgC@>kes@L^4?tprh7)0GKxbUT*yTuST9DWik=XN)*sGD)JCN8% zk=US3?J)D-Ac_A(VzYs!s-O)3VI;N!5?dFEZH2^kM`DK{u@jNlc}Q%~VF@tzbRdb( zL1LdoVqZmKzeQsIL}IhDGBCi*6hvZ!R*k^KHIc+kk=Ut7Y|zv;OnoPk_*5kJLL~ND zB=$}u_8TO23+P@UXxL6bV$VfluR>yPM`B+@V&6kzzeZyJKw`5ZtvgmmVjCc_ZIRes zNbGPVb~X~b0*T#<#GZu2o{z*{gT&s6#6E_^zKq0vfW&@_#QufEjzC%y4ZiCK8lJfz zaZvY#fq|hAX>B$5ejiZdgn@x!3P=rRk+CL&aBs*ii9JAU0I|AQJl+hz(V9 z0mO!?xea1N-S7a3{RHYBP`lg7ecmq!eVt&PNXMPf%Hv2&5w zjY#a7AU4$ARY>e@NbEyM?8`{(`$+6>NNhpSojXu7HIUf0NNi9oAPn^vsI35FgS5fe z$m`ZYJ!P0UsJ9AZgVtxm*r59XVQh2IJ}s#Epf(;%9CSt^jO~V`2Gp*DiG$Wa!`PtZ z1TZ#eW*)`{om&WFgJz6jY|unLj19Vz7shTzvI}(P7fc**gU+Ocv2op-16m3SQv*7a62=Ctv4F8b_glc&prf#0>=q<xKo z#6jm!!r0T0)XYL+gZ3SuoLLA>tDtr=OfP7yCTyR?4bXXzP&J@snxMTGpuQ349vl#x zlYxQZ6;ur<4}q3=fy6;&3+TQZ5F3=AKyxV|HmDB;vIoQloo@=d;|9bA^(oXr=PWWY zFo0IJg3p6wf~@@pEvEyi0i9P0J_C{ovKAe*f)XSSI=e3bsuz@>Kzq?Z;-J0~Xl)CK z4eB4|K-GYzw2Po@P#>xS$_6b$0j;kCsRy0$*#Z>@9hTGuWmhpUFo5p90jUA?p{7B_ zL4Bqlr8;bnq7FSRIfW&^ebkpyKBk7#QwB*`T{%K#KrDYCvn{K?`<4Y|#0zAE0VL zYwf>5*`Pid=qMqO8c-h%blMz<4eHZzK<_94_0?eavw+Tu1+9n$sR7;B0orc|VuSi| z3Q+Z+yr>3cgYu#dlnq)gU<74@`g|5pHfTW&s9g#&2h;}y9YzFVgYqcseil&Q7Ir@i zsBahp)eGtyg35Ms_XC0Y=dd&nK2sB#=0RgeFmdqNk5F;&xs6aZ=sZN28c;b5V}sHM zj15X3Fg7S1z}TR40AqvV9>xYQvVfXDQ1_>R!jl*b8b1JyQG&`Akb2ObBv5#Q*dPq5 zXF)V*s0YM`?b)c2V_*P<3urh9q#q;)8izsOBL%ASKx20xGe8)m4n%|MU=SN-9*;Z& zg9Z}=1IRp383mF9nFn$Y$b66(NFQiVEr^C;kQ|7OzDEj|I?$>xm>!V61&p9u4?rvk z2H6W@q3@A0Q6z4U6zF~lFX-NCkU22BKCGv7#KjSv_WhThRK0e@f1D=hLuPHFea#61ep!9HwF~&%#d&f*$0vX(V%fr zm>!UMyaL4Sk&4kFZjY3%00ToJED}LujUY=v?P%y&CCq&dIt&b;WB5Sf0vZc~xetAh zRG%;d!)YS+NJUB#w?}H0B&1$~It#uR4b&Dw4wp-k#O;x?(1+|b0r>;p9;sWBkUN0T z?FE(lAiu-H#YG>Y4rCr^m=+`liZ{@hCQ`66$Vn5oM+$WC{sl(Joj4#fK<0tM8~ z|NsAkuGeXR?0srb5@=*#XfPHqP*Q;0>w#-e52$Sf+tULYa|HPlw5JDD2Qq>V9S1e0 zL7oFC1kp?^ETHqk5y!NGcK$Ijv4ajkXJTXn)mu!A9H8vS#Ka0Zi;@MjvYJ^6G(gP6 z0Zx%j9PFT>T_zS*&zETKndgs&<-U~4i#in0#17#P@*Po?94ubTufk_1`c06Mabfq|11 zx>6IeaFfdfh0D#&2vW0$qi8k@-*l;0R~0}P-_Ex_=qq=5d#k>-AENPIC!hb zODX|_LK&C%*iQM&`np+^)H6tw7h)X zq|(fslFU48OO-&8k(#1_a5>cI^8BI{23(80VD8W_Mv2if@R?hX^-!PyC{BwnWdJR* zE2%6IOu0afo6IkYC$A3N(l@)LrM&811JRuf&7b_wh<)+_)IDW2GD#a z$ShD50Aj;J1T=>UVuRXLAU4Q65FSkPnV>Nl*t`U2-35#d?ju2?0@ry@pu1dP>Op-x z7#sP#C(t+yOdQmxfU!a6EWp^HaZMN-d7cwAt_c$dosbV>uLreEpl$=*F#;0@9cm9_ zgWArpzW8;dF;36{*^J;U&Am z?#6|w2c-j$8W0VNdl(y}6vhUnU>Fu|Z)DV}p)UhOt4plF&FJsI3h1J7^3QG?oMM7pN}}VuQlL0XlXF@)PK84v;u3 z$B{dh1G0k{3~CR9$|{gwK;loCm3bid5K;$8q?B45`Zy5+k8QKVCHFXGBAMd z!3CKIayLj0WFBb#0;UJ#4$vL#pg9B(8-!tUpm7Em8zdgW#J~WWg8;EX7$yfQA3$cq z?7hJSxr+#7FDRdY;wdUsmkn5uouyHxk-MnORVer5}f@d#scGYg1X!e_QLfX4H%j7R+cUtbRykC@27pwJ<}Bh<36#;~J9yhZo3Gd+9B5J!-*0$e5T|lR&3+fQ~9;k_0WZLX1g31|wK^fW{qI*g==EGqFI%6&N`{ zS9&pVuz+Ulm^fI%K>O@LB|38kBghPp8$fPhoWoYZz$gJ5Wnc#lEXaWd7L-9M$ld9R zb0~lfbtr%xbtnLAC1`Mlks$~~fgA|#!ZV?E;X$dA6W%$W58{H9GBSY1XuyVm*4aVQ zA|xh2f*>Uz8ibv}eRFWjfY@z%u&xoA{pNw}o2P+xJEcN;=0x_!Wf+-Z+r5|>7@6y# zJ#!EnygiIy&m7ceRY2)i)3DbJwhT<5*hsi1PfR};9(vFYG?n}25aZJr;^Sds7GRG+ zEko*aXI7;St?o7`1A-Q5z%m}F5rS{K!0_vOgNDCA#SIu^?iBz95LgOK49C7VsJ#aA z94HCE`reQPub0dKVSu_i;2~E~UmK(r)b<6jK_xe+767d^2DNWMa-e=UNF3CT0I@;h zAUxU!XJ7!guR#rN1_lOV`rx3O)nNT=P(uUOHw2v)2J2UXS{AUrFu0ux&cmRXU|@i$ z0mTQ54YD4_2DPnWY*1?g#s;myhp|E96)-laKLlfg(g30UEND#v%*|@hek;gjI#4#K zIR;vv0P4en%mcNlKx|O^(+;Wz)N}w%*MP)9=?J8s+o-vDzD$Q)uYC4F8{o`Tr{ ziUSZEz0bRW9np6Jl{O%CAU~t`c|m8Mfb_#KtPPId=f$NCz0V6;n?X#U_X;~?4j$D0 z2gMQ0edv8&&>A|>x(jsoq4#+~XXS!gxghgENfl-udY{*Wk%0j;Cx~tydY>0`)sH7k z5vVN>Wuy0b6F3+@Q0LHc1Je}M8U%pd4|-dI*hA0KKwydFmH^SW?B)Pc+cMW@g9;W#h9D3Hav!#yF-Q(+avNJW7^D>x${-B7a-E3*bn*2_n4(TANX|(t zF3wD=B&jRR#mLMG?f!z!PN@fN%qX&R?m|jpD zAI8Sj_XhR12=%c+^EWWJf##1v{bZ2+p#3-?HmF$#T0aS5gW9+@(0(<@EuiKaNF0bTUQ_timtYhwE9F&xD8)j{d`6wGm;bPHvp_tlqhK-NEl`d*-94)ZU1UpWZSIUC|f`Nsx1a!nKs1OHjG6RW$6oP0b78cOjGbR>xP%?*g>6zF;i<+1i*_J^1 z@?N06Iuk2s=NbzrOEO7<*50##c5E?8f%@c39IT+NZ%iEQpq#G7;^+8XyYLRJ7`-Ub0j0E z)Z(}Ts#5LY%kV*-V4PFH$iM(viZ2Bl3E%?lpkW0YvC)`%zDD=0=_0=YcHs z2kGNQUF^@t%@``qz`&0XWnd71T|h605S8I#U=V`b6%UF;2GD+RMus2|1qw_ahObPj zUsORQrjOiwkO-*akKoSS*gc6{{$;c24qCl|?I?6a0v@ioK4Jv&>hA=V&fhf=# z4i1P}KXvAVcp%dm8KOWGC?zm5M1m+#YUXFCWDxxS|9^9Z6vrPo6-5*?LA5O-Lj;Hd znajpd!cfE@H6PTd0c}`ETE_s&Y9J-d3_+7wKn##0p>CLu*opx2KOc(!Av!>g6M(oH z9x@1>*hYvzc7XlQ02$;31rF%&Bapvf;wM4*j{%gbNf*-Op z&jQyTh_s^AiUQnYOYlt*%)s}R6z{0Rgk=x{Ws zpRujA01wB&M}a`YK9E5f6d~wv4blJ@iZs{^Fo7amQl4*Q%7A_QM`}Sy5d%0b(h!>z zz(#-xkUP>r8yLVNQV>1F1njl||>>Cgt)M|kn z$H2@0nps2UgL?kRd`a*+R+tEAdZ`D zoCv7R#lXM-5(2S7Wh_Vyhz&}Bpvn@&289A>9WaOuvJ+HwgV-S7foguxI2fqP1Gxpp z22C`9*r3D>8dm|S2bm3G)BJ95kb@Z*z&m7M;~pTl!PubwB5bS%bOJ4?{|X9I&=?AA zod>AN0aFhiSAd!c-YWuSgQ|O&8t`5bs5ofuA0`gks{mtzTD>qfXigo*2Hy=1)eCBp z!^A3=9kmzmUvf0rg{`;^6s7C>uNu24#bm=)%kd-75|<6O`mYYfWHo0F8se z*3E#%!C>m$pl82;nsWXiyP)m_T^I;c59->$?s5m;Lk?8~n!<#c4~kciy&xKtzF}-o zPKU8UX&A-^r2!Zl)M0?JL1`Ywc10RX1m!!JIB5R@j17uw7#p;33&zex(p!kc25s<$ zsR3=0hOxVl)PVK~!Nfs(gkWq?8i27ueJL0l6z?!LXlXT!eH6*ei%4wH87nX~pneyO z4Z2$%#{P(;9+Wm<;-Ib=j15{X3}b_~j>FiX{X#G{F=MKrID@H2jyq8Df{BBo9L5HX zm%`Ey=#F~OcqzyXP_Gfh29jT}30a6Rn z50V495&i5GP+kJ%Esz-?3{nT8L17GH!_14|W?%r7lOXdz@e7gznFn$Y$b66(NFQi4 z1VqCyNDjmXt)&CSKOuFXu!rdZ=>wSusv|&b5C+)`qCs&7V#C~bhZ{163UVK)^#PIt zxeqi7f@~gW-l7Ld0LBEZ?*i$8nWw_TzyP{b6=WW$^#YOunFlIwV0u9A0G%rZy1Wy_ z24R>S=o>fVuLWq91yK+Al>01_KKL zEoB9LR@o2WwmE2l7&8N74FeA&$_{JL?rYdtETDE5DBM76yFg>MV8671d;_Xnp)?Z* ziy|Wf18g9eg*^r|X3NA5nnYw`WCQKrV`Aj^2Nncf=E%STUhW0n_r#J35{51F0v!*? z#K8_asgQ|<6?C8=6AL?N?IIHkJLrfwCPoe(&>$5H%MXw?4i-?mid70^IV*e%6v+LM zbzX=qP@v&l@D?aYK}hD%DkWQ>K&gZcG~yRLnFYiKxf0uIFHj0aI=2Lrcp-@p5)Ggr z2WbV-APkzcWn$n1H9Lp>rl)ww<^tS_B?SjfG(_JU}VHS00tTZ$j{R+ zM%YB^kPga#7Si|^c$f%9k`_Z#5cfj{r!Z~AHk=0@F9RzD4Q4?Cm;pMR1r`PqAUVjO z8j2T?k0U`0GJVsI|@*U)Ha2sRf zoht$=eL>y_#Xn??7NRJCW)75fS)e`zXw4O@a0acR0$A}AZ&riQY?V?hpr^*M|0sLG46+C>zw50LdYb|G?OwbO`e!uD&oxFEJR@uLb36ko!UE zLH$i=FoC#u&)@*%1F#}!*n!xf{x~R&!`j)PGXX$u1huh2UI)p6+z%d$gr2_x(&rB% zkTA$iATIhECtT`4{Z*JAkUmhq8x&U{HVA|41<{~>GKdXx-x4DCBZ1D~0G&evG6RHR zc7gi#$mYFaXJ7zbcMtL}C>%j@ApfGTaRQA6g2qlkW`QuwJWziX#s-Ol#!NtG$$;1( z43k4&<77kR8mFI(*!#8UYn)n$+>a#5#J~VLTL$Dd5Qe!AwD<$$cUU;D;Dq#RLE!=# zg96Ec!Udd;a%3u1#XOb&fN5@??msBaB24>W56GY`EVT0`U-rwAg~IDzhNK+eA~ z_vsrM8ybQ-pioS(A8Kw6-M&P4jZ+KGerN-<9|}5yLqlLz6OSZpqY)^L;OdKl#{ocv zCZ7TWXg&ZGcA&l}s58k38Yl)0Sb_o{q!2{oI)g(G)NN#B11)YqoWYR{T5tn8N*@0i z9JwI9=x1<1*CmC679@er<6u4xsw+TF067KH|KtP>%Y%f#M{o@6Mk7!tGcp8$D3Akj zbv@CJ-~f$tFfs&zD3C68hKh!UhCl4^l`q)3ryzwOPlNEtI+G)_I5RITjiml57y1Gb z(9#gdVh-?C%LF$WfqPphy|TgBu_WB(PK$?!UObcu>xYus2ZwYzQNm>S^;AK*4Aj~J z(V(0LYKe@bo+<-;JRIcvk$esZCE`PfLw6IY8@M zKzSC{*F|Q7nkTSu1NA9kY*3#Q#s;Y;22;}S1?4H29gsFBWDXF-hV^&0utVniK<#=^ zNeq$$xgWjX3px)JW)_HswZqZ-y|~n&_j^HSJ`mIIJws%_7qnOCG{|94409iPzgL9F zy*;3_D~Rd$ZewI%h=SS)qG0x-_j@Ba85lr)b5J;g@&hcKLG!dQJs|x8M4rQOfyjQZ z0g>l$d?E524$%FMp!FIcw}LRp?I4Wa?*-j+2+FS@H6RR91Hz!OF68-FJtF(PX+-vW zJ&4@flSgE~7qsVzn11g(BKy5HMD}~-^TjE$ias^Fe4;eIdZMhuWr z!u{SFI`wEG`Koma%fAONa4hyAoHwAG2b z+Y4IJpH_f2F)KuA#~0FFgv@oK^z{Z~{}(zPN|&B2(S2>bWau3eLuY;#RNR5uS|A!! z{Ef6;FRU&D`F$kzc|oN)$nT)|N9ptGB{M(^gwgp~P$QXvfnl`23rZ;r45apV!S_ah z3K<3l2GBZi*c`4dblw&;9bpV*gZj^wP&Q~)mpzmXN~fT)Z;;;M(%%K$?G5UagZg2h z;DPnS21|eU2$lQ0JOk9<4WM#=_XG+3UC@~>kX(ZpUj=mvKyeKl_jp5Of472}fuR_w z!U8ct7`?yyn#g%x9U}X?DMa>n9f<7j<`CK6_2Gid2ZQnlzIom`MD}+{Id>ArJg*7# z@&r&PmM(WKFfcTr-?gAg>Rk)S^Sq$$DAhW z`?HuBIY3uhFfp-$=Xo!II<;v1UC`C)Of0P6V<%bIq4T_;vwfHtIbMO(bHElFgXeic zyLOmQ!uq=)r$FX;g;DyuVguUW1@-$GN3UAQ&rQ|OEKAJOPb*4IEh@<`)-TR2NX;#U z-JS^9?jH}?>#J*|XQXEUlgi0VO4f&7tjGY`q?%crmzYP|w5|xg-Yo}gkA6;mUb+I9 z0QJC7Iv2RT?@p_@e+I20x5I6)VyoqKap#jiM?wCLQygR6G2U>>#N+X~#9`v=%Y0L}^#LV%I-n9VAZICerP%{U@V_+bq&x@RYLE{P_ zGxUv&&CJ2QT?j$M94~ZAnD88L1@1Xss`hz7GpvlD!zf^Dn_(WswYC|&7nYF?bgl(r zZ8P|OLC_Wi{A-&*hm>I4F9=##&BVbX4qDp`x`2@R2xgyG8l}$*-dj6hbG)Ed4$b?# zBW+4IFENkADP5$!wxCta$OqF6r~3t=JxeOj<$^oMP@{?N{OctnT`>sn;3E3GkdX_9 z0X})wuvk_DUz~~X(<3$M|j5Fjw!2}9A2p*1i3xe8IAm4$i zJe2+}czzes*#*tNf%>-~b)bF@hz)9wfog%#zAgg;X#FH?pKTFn3 zAeVrSB4zSHyJtWY)P)AEqh=I=^_SUFD+(AGML<1j(20!fAn$^dfv!E^V2on^%B0G` zuEoH>06H_`8>r#T7|m470G9$C#RyUl>h8k?IYHMgg3cjj-~#pgnKHnKVSx5Z0 zxQ!$O1261m0Z^bTSp0r{qIss`XK3rOBJ##bT0vab+=hjyop>e#||{t$G;@ObiUEMMZh} zXzR8m7$N7;Gcd6*u`x4%4y$KlX5AKtm5RvoTNPH{fr=&K>OpQcJ;w7 zN+UDAp-U1{iwg`5EOb+I(va3A1k+U^sZ5>IZaziXBkkK{4i>IH+=jN`mKwL3iXJ^Fh5OWIpnaGSFUO&?;7B zd1xmQD#Q#vITFeNn-8i;k@=vRWn@0+=m=y!a*TuQLvGoC_@I^=vU=F+S%?@jgE)!{ zK(@hjfYJr%TzSxPF^Fmg29P{tSQ;V%;)BjRhVUTrpd~)w919*zOD!x;GhzVq(->eG z305$`G9LKMBv9Q2G6$3n89|4+FhI_YVT3veWEV^gNC>6|w1$=u>Mc;{fyOUD=73@b z#0IrfL2Pbl(102Upm7aQ9srGtfYgBO1hKiH_JZ;fObuub6Ql;D55(pMSLAst4_}g{cRfn+{`x&P|80L2GScY*3pGHXl9@blfVa z0AyfbSczml_~Ix~VqjokI0O=hvO#MoVR}J}AYp9KsWmV*=pQ4eCxEBsOTC z7v>&t{6gITN~5s-I!54NA+PGyXy9LFpW1 zE;Yt?KHF__#l%N?L+gn=$;0hP3%cmkCJpso>!4+>+D{h+hcK;Q9)1_sbNTabC6um#D1%malR$UKl3NFC^maS#o|AUO~lbQT*ZNfJ^= z?wRGFJ;tDBJji{ZnhfSX&=Opj8$j*=ommb#XCK4{VVE5HndNi1AZLez%mdYgF!R7? z9fCAMG3Z?L15h@If|&=-?;rsvzQe@80NTF~<-*S_0i6K{G8-1oCOnXPLP7R|!WSe5 zqS4PRmuAL(wi{?X7o-Pf-V`3lc?BTzK=}Y92Qm+Qz9P&q3=9m`%naZQzhFWzf1saP zzJrH>A%}s10c0Mi{(zYWK9>>cY_}Q~28L#sA)xXIios_#BB}e2yRVuWXHl1jc$z03Su4#Pj1VbYOgF=Tu zC$k%k*Mt|6t7#LQ9F0EX!SU{J+I1s4( zf}K&m5j6S&4hR;;Y*5|R$-uw>YxaT^g5;Q3SU`D`iG>|>EeLGe024c?aARU*n+@vJ zGjf2ANMvGS^#Pd(x(Wq)XC>%ldH9``pzU5v9PFSI=$KeoK|?=GEbQQ8xLMf2d*m58 zK(!_l2g`lX$Px66a`>H+-qD?vv+usDE+Ye0?%d4h4yOz54JlHeg7 z1_lN$&;SpkBuE_8ROHSyU|^I7m3*KW;?9EcKy4Q8Oa?{;(A}7eL5)<9YEW(g?PuTx z6-A7ypo{|AA;G`{T80Pec7cKtB544U`~Y$YAE=xL=>*@1X$mqB2Z1P%0_bItKXu^e@PWz)P=A1tAp%5!nh!h-MGTxzRXG2s za@5Pr2Z?|xcSeQ?5Ct*`RRJh^K^PBc;Fu`&lKFCxlOj8w#7*O?t(iJFFm>7x~Kr~v|fqFfV z(i2opf?UtQ016)n3sMs?F-U^S1mcJ4pl7I)H^hc>@TMfOC|wu2sYE|FF*zeMFO|#z zA}qsr;2}J4k)I4|V#KGUrX`lSp5UAV%bvQwtOV}o4kT|FY z1C>i4_0Hgu6SDdURO*1t2Z_Uq36Oex$0iQbK}3`w##mLuoGO3=9zFumaWD52(qu2%w?4@!feb0=VK z0Nu9)Qx94I4jX$4hTc;NN=q@IHWAbfX&^QzQ86$ufL43M)PrWjLFR+v2XtOL%uG=K z9;T)pY9=TxgYJZbxdEIeq3#6b0gyRhF{E)!P=6UF4l34RY*29yV}p7!FgB<$31fpA zkuWx>h=;L3eH|DZbRIv94cZF^V`m__p$dszhr|YryTH_gx|1+AsQUzCgYIF2u|eqs z#s;lLfU!YcDj543lKG(C6igg+_ZW-~N)IqL2Q+L!;Rfnu!Nftwzrom`@k$sQbT=7{ z4eE>$8cPM8AU3Ff0a_>kVuO+mXdMxV4Jx-ly+{xn zRBnORWPsS9G#LdQR|S=epfL@QIH*hmr8f{8RJMWA8;A``lSNSVpt7w3%7&#qkQz`L zgWYQhDnCJPrS|wNXe<#HCZPR3FgB>y4r7DH!C-8V8;HRme}if*P`rTDgVHsqDFR}H zFes0JXi!*z*r0j>#Mgk{K?xdP0_g|If%Kt|=YrIO>MoET5C*9O(V#E}u|e`6z6taW zN|1S=_yx&<%mcXxWIjj?q;3L;K*At75Em3TprV41I#9g9^nmn%%!5wvg1F%MGY|um zk3nvLxo-#b4oZ;wK;wWQIgtB6qZ-KOf$lckiX;GIqL1f-CJTL-Amf&xGz>EjT!(-h z0L8gX3=E*PHc&3869s01#*AQQg9MV985lriDu@ljFgeh;2gq!gKYaKY7#bKM_JZ6G zk^|A8as{Rbq<<5UcTk>z-a!cp7kuNnmsl7WKxHz>Y!HUog+8A9fuDf^G=2>-50r0V z?n58XjbvkBSPnA;+LQ)yH$d5-d<(LN0mq$@=;OJLIPQ!@AJ47Cac3lGWC`R}SU7JG zAZ|RjkppsuEZD73w}aTAx*OTNJpvGQpl|`zParu^yn)7IVQC(u?~h88XIP2Vg*gbF>`>&ZkajQL6f1(EUcip8)g=E(8(^$kkd$+896{l zl(MjZ2A)|#YuuSRSk8i$BS23<6$L)j*?z4ieLyBpDdk zQP;w8m@qISjSYev!2qfk7#V^<6v&mJ5x^k$7#p@>E|4m)P6h@BP~(G%0hGlV=`_rR zYX}OIO2H#gpk+#saVG}o2$K{uCun?$lNB@~1Rk;g6QD$aGA>e@S6ZB!0y)D2MS_L{ zNMM(M2^1T_qcaTPO($@1@E{DB0ILT%pWLCBjQpY!1-QW=laNPaz{W$3h7SlKMt_JI z%7VnkfDY?`$~#ap1<|lF4a|o&20+Oe)J*`Og4Fk~+=->c7JJ(BM7?)Er{g7l9VB!}Rtc zxdF6R9VQN5Qv@{=+|~nSKIobvSlAUROG5}aZ92}FbXQ!qA&4^js$YC&AM`#}9TkQ+eqAc+gm^$sBSf&2!N z1Gx{>pF%b-gMonobiW-)4+z8LK>cx$9+-I&>Ss6Pc`gTz-bGBAL4Zh+Vz43h)xbp)9Wvp0YPaRwtOU4rC5_JY>O!1RFh zpCs}ekp>RPIvS8aK&2zhJaA(RWDpd;WMp6fjr%~k@ctvH2@BE#bKepq^FVn8BnNUI z`Z*%AnIL0v$mW6E587}7qGA0mb|Uvyd9Yw#M+53lfy{&1)4&3mDuMA~a-b6-KyHQk z;{*pHJ%dVhkQ~S#p#Bt056FxT7D#-6*dPp(1EnF59+-Jokm3zAfen%anFp$IU}+wt ze+LT#186-Xhz-Ip^FTBxUxCCxcnT{6g95bw4Kf2{9=3kh7SIenNCOmu%mFd=jZ6%T zAq!)`B%yUQCgui2ucOfbb>K1jT?`HXL6htZAO8RUf4~0!e^BZW0Nt5rut=eoX)ZI5 z(wWz@ctUy*@< zM^dXpX#qonX0w8pfb0iIoZ;GA1zHmT>(ha{aG)>)-L(i>Pss>c83S6C0ty_ELJ-Zw z!2()$30q9V!Vd1JFtLLMNSGMez&nu`IY31Q6B8?FG=v3Id@@Uc7A_&SS%HT9nOIms zDVvFf9ke@%iG>|h{xUIgfQIy$SXe-#HB1~Vd7#Zy98CO-dqE|2PH{N{lOQ8#WQc(+ z7sL?)b66PIIhc4DL5puVz?-)C!0Tu@7J`=e2s46Kz%g)kfjA;ygSbG^!Ey#PO9S#0 z$a9QyxIw)_(CQVC5D&<7M)38Gpt6()WHW>dy0(=UR$hWv!7%cHECv|@s@Vh?Rr!Ru znfavoK;1zBaRvq^L}CROZekT?!NFIH5*>If%Ve;Qdh`%b|TyZdQnS+@8Wr;tUKth`uO@%gfCOQp>== zX96)AstgngprJGdHin?dEWwjmKzS47N%U(ZK`l&B-N(oPYRQ1LA%r5pd}wV4G6C5% zkS;cch{-IGlUYEu3B+^=AEpnSzQ7zv+5|B{>OeFIuL8v?1L$HCdUb>cZoNl*T0wG7 zVsUY1S|#L|7UTsU*cO05yX4@~loec7GIN2JY=D+^)PcI@%q*NN42;ZmphX`HOe~;% zUQEzUT=k%Z9T;MuMIg)|)yzzwOorZ%D(7rzD zD>$lBLCbugS9!oa3vw;4@dU_%8N^@$cr6OVe&od{1&Ku^#RGeI3}{3Wl(RuJtZoMJ zVaq~5Z9-652GO8>J)pTmQ0V~@1F>PH1E>v(Z<)vFxB@6tA$T~9D}dU1Am4!EA2P0h znxRok8_3u@Y@7j2P(0UC} z8U&?T5F2EkJZOyx6J%SuArjjXi4Ah^U>)B8wR>P=2$YO(Ag|*9&B?>e1oh)!Y*2p? z#s-bj!`R?H9H>*rz`#JvSO=~(8V^7%GpIRlkl3L4KiIr3XpIJJ9D@^SeS`!O8?>JY zwk86+X9`s4fc7{*=j}o5LQ{}>s9oSS8lc1jifE*@0HAaRvkR1-U~Eu&g0Vs24`YK` zsxUUF0SaS-`u;FBDBZ)@pmj7bb{vwupjI_Z9JFT*#s-Byj1BSwp)nlrDs-sdLH-4e z+km`i4V}XWwKyE1Y>;`N)$t%TpoSsn*Z~k5ly9P;YC!GrR45yihw`Cp(41T;lnu&H z)lfDle>Fncp#5Z^`A?9Ups|%+s5mIUPKL7085kHqYvw^}K>2SzR2-C#mqOW~#l|b4 zY*1bX`G?#wC{SM=maaf{z}O%&iNV;$ra<8W(+f&JAU3FT1*#)KVGQDf+zm9&rhaeh;L2@8A`q&gMb)fVK z(*x26+A{`9*B~|sgX{&-=wnkBT#!9BpfMPb-$3d>?n57&0?iYGx{n|;Kp18hC>%g~ zVE%33VqjRp2=Ol{JA&ju=An;GaWOG4faW$qW`QuwJoK@tD@+UwZ6F0u3{wXx(?Dj! z>{a1mU;y0(4Dtu4NC3%!>;;!=P`w~33dbHVP!}Ae2WH+G=pHYSdHBYrs+buV*1;SF zD(^s+FfcHnk4=FNUU>pd2cXdhkX<16p^r^zuwq{m0P4YmtO2EWkQL|I7#N7T$5a3` zRtVAn#UL|4O!ToS4|d|lrmjHuc!9zNREEO*fj%}B0KG2=WETj->_s1&dcccFfB43x zX0Q`CHdVqw+}P9=zOO(AhP6x&85nq&G+7Le3hZUR%dE?FT+ePn zkHVe~MFxiBN}>lD7%nm}D6KyQ+3apf#D>J!d(GH z1_p(_3bx#Y_JGBJ)*XNfCq4y+?U3C?AQ8q&P@Ov)G(-dqF_1!#vza(pKzpze<5i$p z5+){gP^HMk$ObC!nHV`hTiuzMSpR^`0wsUQ`ME5h9otN>p)1fSLrfg(pc03Pg*62< z?7+efYF99^u!D*lCPog>PHQF>7SIF%69)_EY8h4zW`0J{;l6C30VHNYM$q;t$j}wD z5SRlRx?<*G1l>Ht0V?U3p+i@oVK8Q4M$o}~44j}O$SeXj2vmbIuoS|^sX+c@oCDg* z1{%JKh6(e4P8MQ}28lC<@McsnFeZWq%|I^W&4lqlg&JQDjK>ekH=w!zv_4M&G+xJ; z1acK<8#)6&sK5tFwlXp>2o{1$lnjt0gAiy18put8@t`Qk0}C<;gHII_0oBZm5ui0& z9H6*hU=1HE?NzeL60v&A0|Uu!6CuGz>7L+1{y4bF6dxj;D-#M zfyV9xPzTWj5nKiaA&4>t24UDT5)p(nXv>%=WK{_`tU#qZY^)5#21NjDT;!z@ zoCy}ZF%Far8Hz!^1v?Ei76@iQeNFlpV|rd{iUN4(bU>FAftFE&iU<%5t=vIe2H0>Q zsQ3ZZOduMh1~dc+D^|eO4xXh&!*Zt=N+6By^MdaT10@Q`J}-Dqj*rhR%}Gf!W`Gn+ zkU9#s&kNMd1dZ{5QX42Cf!LtZ6_m(8Y>=25Xe^HhGRF$4Izi%~<}_$e0f-H1Q-P{s z5F6Bg2Vv0oAgGQ6wew+Y(0NrLHYgE;`rsh-p!yQT9%_5Os5Mpy8moeh1JZiW7iiB8 z%r5YLE>LHkfq~&QsObY`gIf16HH@IfE~wN29XkOX`vavD%cVV;CEG zua-N~SR`od1*QhnErPK@-4YnP1W7$;ECePFS_BSbgBEhb*r4$Z7#q}afw4gcy299? zrPDArX#Eb1y${JQ(79SLaZs;}(0HgXC_JHI4mxuPG|mVL&p7CKBB(3@bs0h8AoD=S z!-CkLXa()L1F=C-1G+~D#0HJU)IjxuR#?LJK!M@`Hogh!6i$Jv0kz3zLD``ASpa2& z%BN*eHfRia4U`QkS2jV}p!Bl?$_9;-?t`*HP5&cMHYh$%LD`_P?E;hyTF7w?$_8~g z?m*d~^!5PC29f13+w;d7$+hpnXuFacoc;0Lg&{7(ng;xep`;(g#|938G;b zBnM)H;sBIJ2&qHgdj&EN+c+y|@CM`tnEOr;x%UcmR?=>mqd;XM$Z-q|450B?Wb*`g z7#IYI*n2gZiGe{Li+SjKuQo9=FkFM$1)^YDKxG87y$XDY@ikERg5*Fn`ra$h+BD>J z05cCX9t+X~3l|3>_g<}FVPJR)GXyDIKx+k&%}e1&xDQmWg5*H%1Fy#g%^!h0$H2hQ z%f`R}8ZUuz!D|XZ#)IM$M8n2eorv6f)lB5xtKCHIy=ozH@6}-r1_n@>f$R?u8#EpZ z@;fY?CkQ~)f$|5wy;uK<+56(kEA+l>TqIM_igHYOHU&?F-h3p=Q7#>B!7-cZKK z0U8x$;$Q(E0mi}70$P>`Ki><~N`am41sY#wjsOqsGO$}QGBCi-_W}hgOCfk&BFOO| zPcY5_)w`S(42-JaVNnJK2F^SNMpaNv4LXUQE1Q8)8#G=ATKvcb8n*@WKpU&MKx4W( zpk@=O3BV1i=RnO5&?#m-;0B`}D2g6~$_#E$W&=rPGBPkgB+WsRnjkUmWYFPY3=9mQ zRwEB+N|4bGBxwhd1dTf~fTl_z60RVLV2}jgLW+g3j4$S^1B0!l8_p>ZpOGOF!1bqivE)Ibk^n?IQa!~;1EEDd6S!WkhA3u~B0urin+ES)ejAk7(od;|&- zVa#MQnFS;P@-DI@G@&479YEt0ph5vwVuP#$xe7#sFvteb)Evk#@N^bPkb!{#w10w$ zK^j!L(`gGU&H+?9oYV$6P8_mq7w=F$_OseFVas-rN7o?>ZXqH};1Pb<$UJD-EriVs zx~%~^ZVw*eXNIVUkl;~z=ptXx8F1yCptIh%p=N>3gJT5ihm7(wa`J=EePacaAoYyk zli-*+MHm>N=E77$Wce5vA?LxBl;`IfnKD2^A&nt9zn~JdQk6CrCO}Sh!rk_Q#(pfVYRK~n>u(F>4zkT{49YB_<#L93=f`at5KLKd_l z4I~a;C;&RemH~2FGiWphBo3++VCI0>pdCjbanPCpn7yF75~h9{=wMi=IiL~|)Z+o! z2O5C_wVXkEVWlR>4fs|r4~A)rqQt!P)M5rbuv=16lSjocC?r9l48lY2-V4xZ z9mwSn%na_$L)ah^^Nc!BPYfgj!JsqiAS?*U%pl1CZjnQ{;PF{x9iV15s09L&2Bjp> zT!%V{1H~YD&>45|QYk(@F(n0b${lzb1jK+yAs5dKpi`e27#Kmx7I#}$ zVPaqawQ@i?6(kM{QP7wp$Q)4H4YY&-#I9vvU;y=GKx#nk5l~YHBo4}5)PVd7T2BFDgZ6`iFo+E* zWk5Ym5F6w!P@5LS2Du$H1`aY46el1y?0ycAA3)-u_yMtDc7fuLChN{YgIWv>44`<2 zjrW31VuZ0lLm;sE3t6P`cF=lW*!%@3>|pA_b4gG$!Tai=Z18v|lnqJ`F!i8y&oDN4 z-8obZcrFRb2Bi&{8qg{$7#ox}U~EvB!q}kjgs~@qx)e}zKm!XfaqxOcs5oeT0VWRK zOAi$XuT6)tLE~UBHQ@OsP*s5E{6Hp9D;bno7(jh)1_sz%5@^H%#s;s+hN=OLfx*HV z)FlVaWq@ir&_!l2dqHcmVS170FF@pp^`QJ$ z4ss{dkD&G0F!iAI*^HoNVhjun;PD)&8qk~tObuwx0%qn;By-LovF{A@+^!EN|P`)Xcz;=2IX5A8-Y~(ffps{Y4IB3rUj16i*z}TR&3C0GEEWy~IbO>XE)>OmTpmYdhgGN<{3((+uJa5*BWp1ApnViDHmIiuV}r*2VQekv zJSHfP^pMz~eFZQzmPq2D6=E=P7bI~|8it9((lE$O&~O<{9F&G(Y|vr%Fg9qv0gMfr zgM+a_^Qtg5C_Tg2pk zG%^Si4@VL&Kw_65u|ee#p?Ou1J78ua=Veea2NMSsB`~%Is2qUiebBk7pt)3#8K841 zKx|Ok#11+y39=uQen8?N^Fa54g4m#P0yOpuVuR{=&~*P1S$^dt$@-JNE}qpgLcM)*q}NMH1Y~!gUVY_*$85TmRwGQ z>IJn2=0Mq?_5*0{9;61;E&`pA0b+-Ojs%0M0ks#lK-r)&c^8xoYCnL+#6jvoZK7jP zaZtT?2FeE2dzYYWP#fb0lnolc0hPTVz4I6t7@k1IL2aTJP&TM71PW_LXxk5&4T>XJ z*$!%Z!Pua%gRwznDU1!8JA$!6{)e$a^R6&9$e%Dac%%**?-igr8p;Ow2c`x*ga;J| zm6QF`H>h5YWsrvGN3dEQV(j6fzkws4Z@(b z4WiNKqi^s*&e8z2KSBCI>Of(MeikUm|DZNM$P5q$sRPmI^U)mqkbN*9^FVn4qz+^r z$UPwQL1G|%N+1r10mU#bDD8ss3L$mi_8C+!h*DvM^dmrQ5C+)`qS5E0*9buNU4YyN zo-l#VPJkvsU~T~E1I=@YLgNy|hsmMOM}HAuV3@)LS=R+Re-UIa$iLwBAV?z=Co(fI zfZAA4F1)7(s-t0MgXEG~7#OBvu@`+lxJnHU0_pSPVPF8A2@PU{Fw8sD=b;k%*~K%PUI z-xgrtWdPkX2@(dKDFdq0!0rH5L?Fj7foe;}Xi!8>i;(_Sh1j+iKA?d^%2Jj`ji8+wLdInr0y)flaU7%|N zQc81kE8~kZb4zm)OHxzfq2`e~*h>B7;V`!j;K>enmSLBqR+KR4r6iUlGUz20qYf%& z=B4E`=s^Y;6O)pPQp-@r91~&VkPsEb4MBp^2Py`qOQ;a$I3uzw=*&Y%dV?xwUUuhRK22 z>@YS+95fSvt&Rqb8Gy`&*(<^Vsf$4Nf>I1f4rFgUD9k|yK{05&33hiWNC;*ZXfHB| z4XaasFfcHH4on8A0b!6F2!qGKkk+6bWyD_hg4W!E+yT-H!k|7RavK(87DybFo?vkX z;)D8&Js<`Y!_T9A*Xv&}<3RICvWexo#^$z6TLU z-DYHHX+&(@b^w&dk?J-f27a);pfCZs6I8$b1jP#|af1e~L5{;X|5_8Y9Egz(bio2M zBgb9P+9f7d(6tJP^RK~&VzaP<##WeF*n>bCSlB_QLNhaRfEpnzpv|O=BB1&oQfFdR zme9k-&D84GJsdwg+;32vP?#554UHQU@C62dM#Jm^x7V0c19; z4RC>lfdMq$1gZx?;vfvF8`0YyyBQc5KzlbpW`QuwJoL85Ck6)ajSnC-APiH7-u76* z3Tb;={NFnhsq2hs?|T#O71pg4ze!F3{tjo$VE?QH^`^#hUvVUWEbjNbNG&qQ3? z;{y}+em`hkD#%=r9U!d14Dknu4Z<)vP6E|r7jYStUNXG-( zHpU_bQYZi_8JJmELAN`z`~ZolgG5-@ffkRaFoN=`dYC!kUaDoVC24)uar%VhCTpY~qpBWe!xF3NG^#obY!2Jru_5%$ZvoNrf zf;j%5U4ty3h2_k_pc8L-SXe-3F0+b(PS0g#VgJU+z`)zY$iN`MstelW#VyUkz`&{x zVlwc>XEU%GfJ|oLKFiDiWpi+YCZ!&K7SOCO2R9>R z(KguW3=F)WqfAs-P5(18FmQv8e`hrZna;q?12V+|#Ae|J9bUp}31V|_E3h&!uv&rG zJlwyS7#LWsL2Lo;t01-wh%LfB38dE+#FpTW1-a4=#FpWH0}{6fu@x8uKy%p~jI18^ zObiU%pbc-Vo**Wq&SLcfu^R;SKstOtZf0N<1l@AR>JQ?uFfwp}<_P_n7#P4Fk!Rp# zW@cdMVGZs983zur5D=4rdmYFDp&(0HxIy=cv4%}zVqoCl2Ay-n8orW=fuVzep9N$R z$08;M1`viC$ zUu9-s_`q7k2pZZF0c}WNEd#GgXAl8xHDIk~3}s_rU=ab$%0W3CBA{s=D2GR6CCJUS zU_AmNpvex_dd56f1_lukZjekPSVlqwv~7;H8O)Ip*$k3tVVn;-&RR4+w}64Qjd2k> z1A~glVUSD*<7RdS1`QF=)=t(gupS+eccA?Uy|S#B{gFz_}o zGcaVZZVq5&VBm`{U|`(>4t2ixA_ms2;6Ue#FK1xg24Zq>gZ9_5ZU@c$@Nl<-oVEkR z=HrV`N@HN%392OoxIybUSa*TcOK_)yEZhrTh1?^qcaT)3Zs+;-_7D+7Z&Uwlpy1M5|gUJq{26-TT$Kz|6=2ItHGf1r(fM4WQ(Lqyfx@YFNt3z#swA#m~~n%D^B7nuGv(9Z5Mz zNF1ts14s>s4GI#38U}urE36EVA`|3caNc5q@cG!F*_VNVH4o%1Sw=M$1_t3dpdk!a zMMi%%1_lvuURDOP8AL#rud%9t6D*5}FG!0jI3aN`@UwtY7e5QgOkvO%w*;##<6Mvd zcR&LEBhBk0f~9+8P4WzOJp!37vNKw@iQ&SPQ_2A%RKz#7K* z9%SMIP_Rcbf=gr((0n~>6x2!5pwclKEW;t93^FkWtc8bxp9Q2`*qnudA%Hc3aS}TN zgNP!?{$y}^XAl96Pq3yif+Chh1hjyIH5JU^5#a?Hng-^Gh%5r>NeAnf5eWcsGQf7L zh=3-aSu?@PG(#%0{Le1$1`~4Z5R;8?@q(9eN--SQ!T+qo*)Plv9zxQ&^vy zfq@HpusT>RH$p9FV=fQq7$yb=USURNKJe-5U`2e;)7QBnr?2ya6oF2k5&$b>wc@r0 zD-%RAiSu9zsJx+KKC;*bqK5|AB0k{}6? zH>6Ov0)Ya|0d&6@NKU%5iIG8&(NLIyK}L_kUJ`tmJS)gR(2gOjr!9e^2-Fw@;j5r6 zZw#A3>m`WYeUYpW89AZym<-D1i{i>+GLLh@a)OdR*tCM8{49NptslB&CYJg+nMwNT z$;p_q`X+i7dZzlBdC57YDXG+R5v1b|YSV+ybjrz3&W2o>2EGcuST6%Kmrz`il9HOH zmjP;UfI}Q23_9RPFM|Qx`-L9x#0@&I9dwvGc&`WKp0)Ut;{5oG#JrT8REBuah!I14 zQDR<-i3LMEcs?pUF_$4eH8-^=JvA@6k|92^B();5#DF2bJh`YOKQ}49xFoS86~rwD z^NXPZ;NdMWfihARpOcgZu_ZUDs3gBU8LB+KJQ>-v_>$cC;#BCV>R?kK16t|uLx$o@ zlS`7Fw#e+_eLJi&c^5l#pu*vzQB@FS&rA0-lc_s15 zi6yD&`9+ls@yTT+IjMP&KtR=6WMV;P!o|oe`pB6JoFp0I!P9l|d71f1#n{fF2YWj) zCmtNOiN(n!nYpPD4kQ2=;z3?xD9_9*0RQa~Y@m|kqe5FekOS^~AEyeJct8bJx7 zGBvS?AwD;=IGF(yli(BZ!AS|arv;p9a`W?GX&RJxQZiFA^D;{q;`7te;!B`=en98{ zq~>H6moUWp_&a;Y2e~?j1_gVDxyFZ}4eZ7vc@G?=V0WY>R)Wk1doAA0)5jH@YCzcr z%)AstwC3a|CxWtVd~!}|VqR$hLws&xMR`gw zDAj;Q*yD>+Q&Sk?&yLSY1O-4^9w;1(A>kSi4fMnmkS(D;`FZIKptwj$EJ=+AC2e8`?jfaH zd|D>RCt$~e0<9bzXy6PRpJQf{2uTaYnd$LqrFqE=q>h=#=RrchBsV^@I0fVpaM&SI zS#nN3s36HrLN1dEOpC$UER}KK8a)EBK^Q!;4sA|>#!z5&HmEr@ zkb8pQ6YVtJ@PiT(gZ}I?WY>b`=|Q7?pg4qJW(H921;PfA%nayvBZ@-CNT9I|+OGqe ze+Q`rVbFLXcwQfxp}-|7xb_BRNk~owsY5xh47yYRG{#8tbHhN35MX;fplp!)Ve9jywdn1O)-G+zl@qYEBe2Xzq`7#Ki<3o!Mdxp){GJiZMz6TFrX$_9;7!_)T=CpaUylY~;Nap!4ow z;-LO4jJ+Dk9MHMRF!94k;^&drw~^SOwdFANpOM5t(@-#R&~Pt|Ey={d0As5nv5k<} z0Z8l^Bz6W88#F=;Gp7Mbd;=1D4-)$X68kn1`vnsFD-xTD8R1TTB(@9^TN8<>unKS*p5&=t{8cY+3{Vdm%{ ziCZACU69!2NNj#KM4U<^u{Ds`rbuijBz6oEI}?drhQw}0VoyL~uR~(*Mq-~pVqZmK zKSE-ELt-*l&>7pOM%< zkl4%|3=FXK@a!CjJtjg(;z}SkG=4#IudumkP#p);3))8st0O>@L@;sKxpSbp4zw2r zvGL2PJM!T{Sp2vP@QgU0k>=782*!Puaoco-X`o*0a64L_*$2Ga{;gQnL& zY}nl58)3*CB-noFdSj5gz;o-+HFO{|K;wC^)*grtG6O`Tui^h844K0PnFk67kUEfg zpt)>Niv%PF(g#`r3!-5dBnM)nui?j~4qWeoG(a(E1Rk_E6UqgRPJo%{Yxo63AZz$R z?n9nCMqk4ZTBo50Zq|a0fzKU-)(wFC1Pi|ika=tnKZD{LBnR>@`WpUu91IMgeK-)) z7~tliui7gX0n ztDnW>UVL~vwKx_R$dSK=;NJG?t!UfcR1j&KS1GT1MX&Ge3EkW>g5+EiR!^{KG z&}JrBe2oy~tUXZs6I8x{%mdM&w1aHk8DZ?{K;Os&cBmV8c_5*CV2uq8EWiqhSR=0k zbp$A{f_B6RgLm8|wR@hiQS<7=qi#pml(tg)<1aka&;m(jMh;LLlbMMXw3UpRgB7#_gPDUJwCR(Xg%z}?l9`1awC$D!w8n&44759y znS~v65iBcc=NM>Khz)Yk5i=tP=T8Rj126clgC&XML;ui9BB-UVqiul1EV-7Z!$2muz>cxfyxR70Y+)i>@Y`8 z3In4on3c)ECr@oC_2hAc;gn+}o!tAT0) zpHu`L5C+M?M`{Ojv<*~Lg6`!3)dR?EQ1b&k;zrV1)_m~TH)PEzWZwxbcBw$jAE-60 zNDUCsI(3v51!$}b6mp=DgkWO!tUy#kNYI*A2n#|oGw^{YkU>0990@Y8fSLv1+7VtdmO8}PbVC>y*k7Rm;#k%XxSwQpf;&=NNo8@#p>svdk#CX@}nZ3)Wm z0JSfn>|P``Xb%X?98miT#s=+Cgt0+ucVKML+AA0vd{zk5OwiT@MoX+5-g-NDdTMpzR|tJs>lmF)}cK&IbXpK^P_nPCFn0 zD2``>^pT)kc>f1M8nj9mee@H6hZ9*$%B^2K(i!RHii{@e+7N7^Aymk zF0c*=0Wu53Lf`Am!3pWdf&2?fsxbe8_~1qzND~7C!wyyk2GBhLP%b?DK<2{I07wor zP6S&12O8annFq=;;08EI0Tk!3Gl2KMLb-7B^o>kFTWcX*1_cELg8d6im~z5CK3UIFLe+CMFJ+tDrmy zKcg8GVoXfzpn-5EMmA8>oQaVGG`!Bl#0nbiW&s^z1U;h}l=I>D??Fss2c6Ev#KH>N z2+qX94mxj$iG>|hH83%9fL3!dv9N#+x?oewHmAthiChyv+iVJK#h2kjjLYXc>9ka>&@ zpotT(5U4bRq-;n$f&@VtK{N=1PJd!z-~*NM#I6y7wMEJ74B%`rqbw52O-#O0DOF9CykLKL!HZUdb(0cC>ZLG2FEePJLr z$QBSAR-V)3j7Lx#12*puWrO=nP&T;F1dSeyd4Fg>1LP;z91VC(6RHm4`YMRc!a6}ovjBG2e&z) z;^6UjC>y*s0LoquYWqO_yBXjuUKoudU~gZfy6=H@`>_`&ARRH0{o zfzlqR;Rc$I12r@Zq2i#l3EKYv5(hOtK<7__*r43w3{?Y4vz|~kC>{Aj*`O8;Xv7wz z9@G*9t$6^kL34K?`(Wo%BC|nuz}yDX4`YM$z}O)5#9)w}pj-?J6OejP{|zbH;3W=d zehyh3Xbb=pPar)Y42o9}4RQmB4eN)Aa6tNNp!@<#J|H=e`@w5sz-0(X7Xt%mEC9lS zkRZE2EYP?E$UUI&2JvyJ1EmL;9+*08?gPyWg4_UepAH9P9uMR`P#A#ZK<)#NUw{mP zV$jGsXq*Ach4*tnmtuqTz{~^Pfez~Lg3JTC8zcuZ5452V*?pkx6`=f!ZXRfU4q4rO zMg|6K>Ogx>L1x43y}-%90NVHmvKN$PL2@8_L1%0so9D-beLe_u?;J=E%)A6HNPiM! z9;j9T$$`uR^*fQx%VT0-0Bwgu_Xp^XI*=Zic`aNF44|?IWF9DAfaE~tfy*1Db2-j1 zL(bSjHV=GBAMppCC2}!^{KGpnL@q1K~TMv(^|H7^I+e7sxzNISVSIkj?wU z&cFaFhd_Ej7-SBJhVIFQ)V#=ha*eQ`on>rkO7z)THlTz#0R48*PBcbP9~m^b1@a`U zU|`~40Zl4FPvl}^VTbnH^+4N37}-EQbws}%JiP~6o<_Le{tk2uJ_~y>$QT^`_HfW_ zTQX>q?tV}e2Xhsq-!6pGZx==Bw}W}0nr)=_+d=cZObnn&Q;g|ALOrD++Hc3*Z3kVS zkye1#aTgxx9d|;>0M=pFgYMV?b+VzoZn|{s!Gke_ZWa;LY5^5TAR1OHfcT@Gc2FpQ zFiNP5z&<;u8V7{~s2WA?v+E@@K$0}*ia*eO6rhF-0|R)6z-WIR(vFAqxkvl!pcDi- zR|nQF2eoQoY*PE{GNAE$XhT>H+P4PT09xAw>Q95(zOb{>L2Y5!S?Qo83Og$u)GvXZ zl@98!!_G3-e2b#pX!XWcN7`?yl zNo0S$i^%@^AtL+hpv`BX_yol-zW(|tBKzw+ME2Kz5!qkAL1cd&v=;$1CIAX!5C(-Y zh}JhUv49@%37%^wJkJhW_Dgu4-2hb4lhI$-XT?9i4%%aYZGN2tREC2t5P~hB04W4{ zl8J)_bXE>VKOIzvGcmG(rsSCzId+12-At^xpq0d+?lrWZ4l0?^=hs08Trsh*f)0yC z%&&unB$*gFKu4M|v9N#!xtTav5<&fRP(jap3f4~txeC%x&qwK}7oqgi!938_#e<@s z4stV*^Xnkba)Rb%KGYX6$jk?E!3QHFX4FA-DJV}7m}Cdp35q=s1`TnKph@<;#5~d_ z**`Fl(pd-3yF(7b0MDF*2~h79K6?$~faa}14q+Gq6YWHG)j^)oONMOvhkKcx9d^WA z{Lq+R2jxIen;1lcav`XJGdjNx3JEY~2F*8vSrB44&#!}$0KBgb%}DS9Vzj>w-&Z+0 zzYfU@p!rl-UmSF6FpLdamjGjfS~oCuD$?9MXdac6`E^?N*Fn3rKz(#jQwHR_!Q4j& z4#xhp8kPHZ0?G#^aNoI0_6bkM$7Y;)!4bL!U_85lt4WPscb!Z1IgpJNB1UjPMz33 zdNvaS185xx$Za4Db04-oI_Ts?P~R3bb_I$LP`ey`PW=dxbLyb;24Gz;n7tso(dX1# ziR`2AC9;qHg$uG)ALI{weRR+qJ#79T<~|UOKBo@q^MllZ%)>XQ{*}l+`V}Jk=wArV zsplo;5jCf7O!S<(2A%up;JI|rN_N;>I;_CLHJ1*$n3su>4RjAL6C(%cC>bUuR`6VU zFlc&Q64a|^0hP??eRSv=c&u~jpj|$QHSn>ZK00X5o_Qb0G*FTNxeC%pKY-FlKZepr z2lGI+*k~Uex)o{!O{jzNBKUktZ0q2$PN*MYq(vvaG&2ur)i+8HexMe?6WbftOGa!+ z1}~Kd6O?w%GmG;Q^Ptn>D8WI>V)@Yy`p{Sa4{Be43TzO@yt4*0cma}u;NjRm2UXu7 z-+?MDXxpdII^&mEAE*&&60Ahn$fFL`Ddf%Ld z$oX?nUmE0J7>1RDwC_stIwIe$)U-#mcG`EyX;9JJ;GJ>Jm! z<|SMV48-)!LFXP4Gk@+#_`fNlO9w%$D_CAFe}h`zar8S&>}EdXttK$<_7VE~Otz(NQ+ZRW_ZmT50D ztffaPF6{9Omf-SY8fPv8!Gy(t`n_ve8K1dk{ z=z4C@Q6P^%O)170rV<7QcF^`EkR&^3JODKQ%)kX25oBToU#JCA4Ze+wfeW+`h=~t; zX9-9dSd<%N2Lq2AX!SlnXcHJO3s?l{MsLt=c;r*F_)zZiX2G^~ewvdc=*A0HRtE4T z7u=r0OyZb(=@Iu~aC9~?GJ>wg0O{iFYGPzyl9=cu!N9-;HywIW21o%nHS93kN`KQ1HX#!5W|hD54n|LO>Kq2@At##t`_f zd~93rL8_p789*E6m>AxGk{a<_@IhPE$y~^fT9KfP z1zWEVx*ZeLj|S18jme-x6Qe+dEd%6+X;?-iv^W5KB>u45fsYbm7;E`KJsnV3LNGJr zS{eukymu8e(+TG?5We#s*4u~ZVFsc>!1jT9QpkK{*Ms)o z6WVVN>U|;W7Y9w1zy(121YstCQU&O&e&iMlNFJ2RU>ZPt(0O6Vdt^=JZ3{nGfJBST4AJlgTsR6kGqz;WFgU&ht*#*L|GsZyX!uEZG^uy-lK`k;E8+|gR0p;X z0TkRYHpogC8x-#_GiiOk0r*}6Xx0F&`-iy!d{!4!9CT_cOdNEcDvVtNN*ho$pu2`) z;$2AMpuQPQ9DLRRs5oR`V3>=vW?==AdeAAauyYJR`+s3<@Sb6)-t!>!Q1)XaHn~}XD4ap|f#g6m=p<;E9*};}y%@;p044`IQvsw0X5Jni$XN*> z^FTYuL2@ATz-0}{ASm`^W?%sADTi|5XGnm~Q~>FLnfHK)fgy(hvWFj(uRwAj^T6k^ zAf1)a#lpZ)4|5bKuR<{>K0(5ud;zkHlMVY>37`e@pm+qS0bwsT#L;#jKFACZ4Z1cO z#s=}5*bwJJg7`2wQ27XQE6g80ypVMrpl|`zEg(6NKS1dNrU#_Iiw%;lKx`0($$`#P z0O^657r_fr2Qm+In>R=fWFDvvgQaWD!nY)@SmLiS}3~PA}wg|Y1Fx31w&|zS3Lx6{;jgP^`_V`*pr~)1?gDnDV zJPfzr)%<7RbNKLJqQW_WGjE`>Yk3T|2(+;WPz}w@$ObyqotcpXbe0h_ z6Dw$1fdv$QOp>56Ar{cZCtAto3k4r(^?W*RUsM*4#qubGBW7GD-j475m#FOz{W3gkG@$({V5ECR|NpkpXN z!NR~84{{&_Kj0R5Og&a!k8kkVg`QDU^vKNF(#O$|(0*JHn85jg1;tUKzu#r1qghm-I1_lx6LHeN3 zaRQ%N95k6FcrptpCPDWKz{c-D_lAM)2!ruKfj$dKJxD(cgUVn=h7b@1G6pif2V#Mi zPcbrtfGCi85D5?qbj<@JLkNfh84QsCu|QTZGK7FAP{M~u!0Z7vmqFzgBSQ>`0yRrm z80s1;=7U(Ea)FT{21JE|@0bBefLP$&)C@5oY91(mFcdRzK2_oTsmk@ASq44~3DO5z zzs$%G1EN40xj-k2@`Ef;n-4nj7koq-LmY?#ou=U z3xvhMa1=D&%^(5FzQhk`Qgp$<0G=rduKvK|oY+=UrKRL#Cgtj7fLc4CQ8u)}&+G7w zPmG)#42;axoJ<>(Fs~177rO1j4#eeEJy`kZcOGd zGS1iog&pkX3CPGSe6SX=)(S2J9+b?;FDg+$5h_S5Dk+9v1so4waE77?JkSXyP=rB| z%a94WvKPLhiip)=AYHIiRlsI~Tn2V9V)PU)4rV|?lH?mwk(Y!G=-msT$_kYGK{TkH z31WjVY!nvMCkB-mFd9_lfr>Ox{{l233o1%M>OtZlHfVebq#jgA!NfsqP_qyu4k}?` z;vhC?+zKQPI%gbYKgb+VVG9}?0*S*)Cy+S4EnvfQl$X#stH`Z=&^RinH3JG=2*x~D z6}i_0QV;4eK-7XrW|UD?kUS_=fMg(eAjWw?tx|~XkntYqFetc*4I1ZVD2|6_+W7e5 z(xj9$V+If(GCm9H95FC3fEtvbF-nj*%Aj#sCI$vjEe=Y@AaPJ#2x>!u*dR5aGyXy2 zn;p^T-`UkN=cA7)o0Lm|*Gg3j~ zpu7NT27uV0^bhJ=gUke_dk`Bo_6l+zXe<@vW>6y�KRp5FY4pRnSIs*!Uo5{0znh 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 ?7%-~b(zoeDbZ6XZI12HxvT3=BQ2!HYn~ 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

    0;JwFvmjVBgp6+FvmdzbS^7vE|}xNzyXSEP>}(S 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�b+qp;ALb80#Tr`1Be8Obrzxn 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

    x~rGn5V5f$$B= z2D!lmTCah|?m&CQKxqur*8#C%aSB@I2eKD5UI$u72x5cA=oUcrg4m$?5+n|a3(#st z5F1o~UIVESU|<0CnLun_GLS0HnVKVsk_LT%fiNNIj_U1!BYUENH_8$ekcJOa$qL zx(BqK52PN{KLfF0_O1h|5nx~d_0>RZSULfXA%e^SjTwS4NH3_q0es>8 zpmqX`4XRdQY)~-@V}pVc#zsDW64d8`iG%t)FgAEB0yKCDowJ0AgWAwAHmHvWV}sgf zFgB=90%L>v7%(=dj{#$Y+U_tms2v7lgWBRSHh8=O>IP7o7$y#C@50!i_A87HYLCL$ zptc%}4Qi{w*r4_tj16j^!Pua735*RM(}3Cws{3K$pt>B!2Gz|lHmI(Ju|ahwj18&_ zVQf&{24jQjEf^bASHakzx(CJv)iE$OsBVCu1E0aF9IU=YSOK{5w)0Uk^ow1*$Yc0f`CYG=a4L7PcoZ16eZP`f~FQJ6;N@1BsHKtkT5l%F=rSXTn<3hXCtWx^@(6=Kx51>b{mqKX-I5v zzJrSy&Ub~W0dF;f+A9DW_kyxP zSIxrIXdsD$`WG;92PAPHBz6Q68??RwroIMA9Mr#niBCZizlg-X17bt-&I2X}23Q(< z4HAdC^Baf_n)GI1U;vHF!ORo|tvP_Ikq5D%=79F1gUkV?e{+yHRId$)4OQ45k+}rUzq# zZy$u}y#dk-b;Dy28!G++#DyKR|4#IH;cj%fFy8Kp2|?bchKP0|Tg>Qvj`R zfQFkb65A1~2DBC>6eJEcKNX2x24X|)0$mskbAKC19BSqSB=!`jnV|I{b3x)zy`XVL znBKi0aj4#NAU3GbVqjo+0AfSMKZ4j$@$VouRGb5}9}LRo0Ua2^#J~VrA0i48huWn8 zVnh9+3SvXW4M1$DxG9JYH3!spf`wZ!l6W}Oe9*d)1duq?oNN#qYEA)&4Hd5jv7zFi zJ{K$vbR&sR0I{L!XM@;K^`QP3Og-pQQ&?CX0I7khKMi6-)n5Ryq3(Zz#D0s!25SMyh`9XXCpyq?dX<>74%1Gkspo3AE7#KkPDp3Cu=4NY<8mPVC-L+6Q zDBNN0j{vEGnh)xe!o;(X#OEWiS0b^&2jDO`buv7zRlM`GVV zVuSj$FneDkiGM+2bAZ;4K+TasVuKF8f$4QY5|2P)CnB-4kl4jYY*3#T7H$tg;!wYU z*P}q$e~`q@K*--^&XacN-FW zKN1@>rwLOJ8jpstLF3mjHt4V(7#p-t9L5IS2o7VvMKbdn68jet8#HzeQ_sqX2wOfR zwh$5<)Fy^;2NtpneLBZHS}>bm$dK98^!k*r5IhjO~u3-W!Px>UY4@fZC!k zc07`rWF&SL5<3rx4H`3t=>;8(2V*xOsR6C!g^7d4(qZgrNNN@#u|bFVz|?@w+k&w- zBB|Mh#NLO*K8nOXiNwBy#J+~a2HpJuGyfry_$wqfXnY=~<|~po=xjZhIOrl~7@G~L zjS9MN1ST$qBrc1@RzzZh+SoAlI!NNiNNjT?wjC1N35g9p;tpDVf{xdNnHi6yCK-vH zg~ZN7VuR+>VR|c(#6jm7!o)!bQoz{VNNW0#*q|f!U}`{Ttijlzqc36XwMgo>AhCBK zvG*gf4i^NVuVuR*X zVCLr{iG%ttF!4$x@kS&zs9yt9(}N^F0f`MdJQ1b_)W?CbS0Slchs55B#0ITrfT=%# zBz^>meHw{<9*GS)q!Fg~5t2A)?gl3Q4oMueMg%7Q8%Z2=CJIcPAKEto)zRWeY-uDm z`0z()dH}7Rfax_uQUjXnfr-QVP#`m1k<|Dgu>+9U;YjRgBsOTC2xev)l6Wo>yAX*D znnQxAuR#(A-6;kWZ$}dELt;-tV$VckgZgVQy-ShAS0b@DAhEX~u|ezXVR}J#lfl@a zOA%n~Q%LGBBC)R`vF{+ULH$9PUeH_^jQtu(%_k%_=*&u(8qk~>j19Vv5yl4fA7N}* z{}B{-p!*wP;^NT05=dMQiLHdh2CadCsn5D#LJM_RY>ecBz7wj8#G4l2b1@PVSxybL;0 z6{a4vcLK%+%}c`iXrR6@Ok5J$uLPw5(2=V!aUCRa(3z?*aeE|jPb4}n+Spkta~;+;t1y+~}(0bejRGmyl=XSG7ZXEl=e zCL}g!o)xASbe1cOeG*9xXwDTTeg{eXF%lcJ<`1R@)Tf5AKO?CD^{-*#|B%Glp#5b~ zT!8x8Fg4%9c$NNOsO*fmIO(EWfg^`K*fU~JG4IxzNRB=xh9*q~EUVQOIgdQkX)=AB{U zyOGp`)^x$dPa=t*MPgq^V&6t$gO5;!h7V{x7|a~d;kPh0XpREL2CWT)u|+@!-9q(( z&Ps)e%Oi<{#spyEpt)}t8+2wWjO~u3-Vcclnj?p)Nkb9`jT^wk3z5V@^X@Ql&^gI4 zHt6&q7#p8>}(`9=r~}QdeGcDjNOW)1~ktO69=t%gRvJNsR5q=40R{yI8~UM zy+~>fBC$^+vCkv1Zz8epBC($%v0o#xzap_g>lb16g6863Y!=XI#89{KBC!RL*x(b3 zp=v<$_b|OyNNVhm*r7=5NF;VX61y0Q-G#*NLt;-uV$VWiZ$x5mMPh?aQii$h1d=%D zz+{;CZ6tBf$;mMBcSz!(qm5zWpz%l;n}ZwCf8jx5gQ`qM(3(@|9uC;J9B950rWaJE zz}U#+TA=Anm^f&j5ysvPnxBG(Ip~y1Q2!ZZ2JG%m&{k2<+3X;3(As&>J;)$7Xq_Zz zZVSW)t&;@Zi40?}6@02C+f&L7=sCAU0^N zB51uGhz%Ma0`=KJ?E4H144`#)AU0^M2(&jC#0ITb1ohKFY|xrU(3y=OHfY}4o{510 z#0Jf8yF%HZHI1P4cp!0QMh1pJs5t0+R#2ZEBo12B2wL|JVuR+WL49@*+nkYsArq<| zwB|7%$_9-Cf%@zqHK4QPtD)kcb6p#uY|#93JCqF?`{{+ULF*wWL)oD9{4=3!(D==K zC>wNs=29qo4kH7@YA74D-hU&M4O#;Ux&s>I2GC6k2chDiHIkt9fgo|ver?bx^dL6q zAkNEBHK1`CP(K|c4%#aKT0;n8gVsjAgsK7ERsrgpgTz5&GobZ_AU0@EH)!q;#0H<} z$qWf|&4cems+W!nTHwUpnd&5CoGxnbCCEdCI$vje;mZ# z#>Bud8L9@fR&yql4GLFK-yEa{bm-+$s5od31ZbZ&NF20I6SRI3#0G`&cBmTA9*DhA zHfTL3XkHSe2DF|Nw5}4w2JL|W^~XVM&=|>8sCv**rMIDM&|dO~P&OzmLHiLv>Oo=o z7Ag)J^8oeDLE_+ZO<5pu3JM$0wE!S-(B25px=Iimv^PQ$ss=QNC=X?W{GkeEgXUDV zp={8aP|#XTkY3Q+=y=elP&J_Y5J3HFkT|F>4w{Dru|emCg63gC z>{l!d3{0$$cm(yiIiYM&pBr>EC`b)xpNJGx9JEGN5y}S5wdz3GpgB@wD7%@Jfx!~W z2K7Nf{bi6jQ&|}pT%qEiIZ|&Z8?sm9R zY|t5_pguB4{Z3W}hEk|FXuT_F4i_X2Iv^C(M+UJ$Yhc@>A2kmPCxd|i=nui7TmqBdMI$4n2AU0@U%VDT`(7IWWeIRkr zeC&CsIB5U=RVW*@Xa6>o4cey=s5oeyEvSzS5(mw-euj#J_N@GbvO#Az z{)e)cvN14#`pY2opgtnVtspjNUyC3cB;G-5Yh|EpP#+O=7d%MKJ~jph1E}~dHU7w186=Pq!-lp5`~I`PFIzNvO(tts6pAFzLzeP4eD2c`p6)?pgxl&R2(!{ zZVzRHjze{YvRgSA7`&nE4h{we(AsH`UeG$_aHu$_j};4LPvT%;NQSaOYnVY{2T~6@ zsTI_B2C+f=fJ&iiR&g*eR72UDI2afjp={6^XHfWp)bHhBVCaR4gZgTqzB5Q1wDuVk z?jZI_4h9C${5XgWS_{1tsvdNa$!aJYbdCY29}Q9inxo$i6$c%fx);g@-B)rL$_A}> z2KA{y>OuREK=bAxwiYJ?!&Rsn9Zm)YP@ftkZpg{N0E%xA+k}&W;W<uLZRZI z!|cT zO)T=-S5O}VrX~idPnUtj2JO9qscAqG??GaNZW4g00re|j>OY);+@5B1r27 zk=H=#Aci?}8xCVLfY#$d z-NS>#2H$f56<0wL2enaQdckWNp=vyk)PVMb!_*`oi6gIFtUwY6?O%hbpMWF|YG=d5 z!D|$uc5OjYa{!5b28j)tTY>2XwGUzJ4@heMAhAL1W|$h#o^cpk0cmZX4iX#GR)(o@ zK@tx@VuRYjFf|!S;w4Dz1|&A}zkk}89*q}Bs%={ln z;w+%`e$cQ5%|XD_Ag@2vKvDy0@50Vwfi@usQsBK<3=E*;2389iw*=M2U=HZaNGJoe zg%&hk3ffx*5;C!6U;x!UpzU&?vyeb?pmqxAY%UNVG!_d|2U<4d45ZHov;YyrfMSpwhzYuU4K#*JNFC@*6ObOz z`9dIlAoD<1#DUl#43Yz3(EU{)8XEizTeuk*Kx302H6RRfABgrt^GAX&0|Thc2KfWz z9*{baKfvuRkOnB`;f0+20p&7))PdNb8$Cd5Sh!>aLiUS;%mbbJ1d;=p2i{i#(g4Li zybKJWGsmD@(3TG{6Ld2oNDs`sH-QWc6`YW82AKnr1JQM$_9j>dgy0ruV331(9!UmV~&bQu^xNjD=7Hi6mUlr$q*yXAfcDja*dPou4@4s+ zONJ6F1_lMt?Xe6D;8V*$=7G9RplKjv^QPE9&T;~o1;QY6Ky*%KQhcH==zy){#1g%H zeM1v76EjO=6ANPn1yf^V1sG{)U|?ouqM%@EVql>F1_@mCu0C#zpar%dgTP@O2Tu<$7ZRzSn&c2SZro zzhgiDLvMK3(vtn4Cc?JKgMr&cxlyalp}ffux*nOPAe!3VN{fm-)!!mn=xU(yJ=c+vrO7bXYvMoVtU zU6`CmTnPpSF6gb3P+4xoO_EIF3=BMoYbbe9tpHv7$OpMl5)^3Qq`=4!1WFO0QWbPd zW6*pM3v}KdBSR2~0tGol0;~l}fXA5D*1&H?kfOAL0hk z@CeuqAY(vEq2U8+Dljqxft&-X?U8OB0u^A8!U&SBK)OL@foKqJ1mzNj=b)@c{AEGK zC7>H@7zWjKLEw9PazG_yGN^n)e%#eE>Ah#?)?n(f&!BFayHW_lO z4eVYC(2XMCTN6O@tc;AH)7=%o1n5xw;*9*F5(W6t`Cy^Us?_)r2HaN-Kw?B6R!Jm7 zt}Z|^18hE+KoN#>z{lu=39urNwX`@GAL3GykGD_BNzDTtUK;;0;91t5M4pI*)%s}!WHmDT{s{BE0 zSb+dChk?>lbwS7ILQb(wD*|220XbL~A_6(W7Q#+UN-9b%V?dS$UB7|MPo&2&xuDVl z6j)$P&N;bYjZgyfTwG9GK_$U;3Q|V|%m>9YvOK5}gUkoT5i%c?CXo4{_($f0dIrdR zP)&i%2etH(`Qi*P7lBd%=p0*Q6Tr43N);#zmJuQ5FhZRK@+s)t7LX4>eQ^*Qlqx}Y z8-UoL_A^Kh#0I5e&^ZVoHYg>6&d~<3L7@TCBLZT8?n3~ziJ<0#QZh&lC>4Xwg$J=g zVjx$5){=vA7s$OJHptf?3|fZ{l1HAC09A>wwNs!rAdC$f4}gtLfUF0t=K|>kxf{j? zg&vFzazAXm1LGVAP?m$8;{Xj{a7zQq2A#PNGshNG`9j6Lk=UTi1Yv4G7qY_G;C?z( zJ!n56OdLE%0u=|J;{auY&vAgV!RI(Y+307iz`|iC$PM74fPvvE68jMn`#lmHJQo60 z59(^b+`|p(e?i4T{UlgeNrA+nZUBWZ%wACZ!Pp>a7#q|Vhp|Cn4r3#SIcS~)q8#Jc{V}s7)fU!Y+3m6-;Mi0imhh#n|eqrLE zd(dHQii65FkiS6Upt1|J z#t_5?^*KQMOF?WI;Y*3k505#K%fq|h6$_8~tKxd$U z)PT;90?iSE*q~kk$j^)*kAN7U{0n7+C|KS^E+;{G3MLNfhr-w(H^JDT-ZP91>YTvX z;4%st=HPM($_C{Tm>Oc{ZlO*kNP)r_R1-pz0s|;)LFEZdBa98Imq2V#_<`gSxFD@B z(6|vuKS&M~9_VAlpz$hD{Rq+n!XR}Z8q@*)ra4|4|{0K4+l&(N>AoD=(0htdH z1L*_p>ju#<43Yz}L2(Z%G6|^zpBVZmjU|KJ0CV3HE(QiroPpd2 zO6wpwko&-A2EjBlFff3|9<^bP0;LtG9O#Z0kRF(MI@}BlpgC!fd7%6Pk^`9sDkG7! zGl13~gUTbQG4M7QXx}@sI?$TgBqRYC6LdZq$ZVLs3wRh9K=a2SdqMVrz|4EV2N|mcnFq?>AUTkEpt2a*JVh1;2GE^LAhSUjCI>px45SBU z9t%GM0|z4m_*MZ>n*<~WGH)p~EJ67Rq#v}74zy<+#0FuIc_0i5e-I5*2U=f*ZEO`( z_JiUPq!)xiXIOyJDu@ljATvPpX{fy*HVA|6NdcuZ5F3PH>OgD1L2iZlgGT_7KR|6C zkQ~S#;58B;jZoah&cFa#X94BH;}=x#fb_u3lMsNY1BElFj0DMn%mbC9urv=c!-#`{ z0klpW#0FuQ`#?0bC;6TXg}Q@q#qAD#0MiVCKlM#)R9Ymw8TzbO-kgX{AY=4BU$*c`@`@ za=Wno`hQ1-hsDW>!Ht2Tmsz@lTSJM7AuQ;>LB|1Z4O!5f7bvW7jiZ9vk+5-8&{#Ss zEI{L^p!CcLYVd##fdB;nNFj)3Vq^p5aVAC%@USQoD|l3ui5+w(9AX^R5i~*sA4dgc zL?#wiP`iYQg&kCVv4H9&_&6%)z+w0}D(HlL-h^G=>SX9^?$hIgl|_ZP3st zNDwlHstsxBWMiO0Hm;yfq?-uhH3~>2FiM%F;pXvGSInuv>qB|U?6E= z6yz(=(lrJ~h9FR~1T_IbLzO}EK`hYWBa93|APN*75DBmrC;`gdj0~Xll3+ua8A=#I z2cj^5G=o%!AQ=;aYz*p%CrAcqSP+yqK#pMq-%`#1N~w$t5g-bbigR(PAWIk- zB0vI{Xf8JQOsFz{mg|aRsShWB@e=z&-%=wjenck{&^VAfJM05C*mWn1;~+ zWI-k7z2T5CFSG$jJDNC?~m~5^;4YcvuchfE9yA<7haZ2(|;& zLD+^-hsb~-C}Y3|2SH6+PzD0gAaPK&4Pt{v7(m$$lsRGIAT~%XNF0<8VQN6b4WNPq zBo51bAae)~_LZbolrZRl?#W`%ODaaauxc<2?_s_83aNev1q|kx9;g)ol7V1m&_X^4 z6HGG0ThCxF12Y5Y=0pe^L=qn30|h%sB?L2rZ%T!*K_uqgSD+RPNCtv2@4kW#fI*}g zKzCt*#z#P0P-F^$T3g_eIdJ}jvKSaZ<0GIkGEg}Wy7v#n1|{>Xx}Sn90!zlVdGPvQVBHH1`-FwIq3Xm5F6ANQi6^Lf$}kE{Gg^NXx}qPKS&PbC(xV(hz|-+kUr2^d>|TzL2@8AC~QDkl8`!3 zxWV**^nu2Ov5m)o?xg{_0p`9h9FXxCko!RK36cZ34>U%DY#wNB8EEVhWHt!H9&@l0oCoAT|iY<&^%-F|cKx+j-dSK=m@Ic06K<0tW0m*@A z&>cL;=D9I5Fn~I!AhSUjCI>2qL3&{3f!1Px#v4KAf%?NBIgojv``|!&VB;*H^P9p! z0wBXcoS z8{}4)KW^|aFo4v7`~jM$1IdB>0qU&5(kRG`!)y!;pfU`^24R?aAR1a_fP@)9>xMzi z2hdmysICB+2P&ID?E+-;dO&AsfOS9!kU1b0V*DgEPcL6zfzaACV?$#jV#iNFc>~lm z1Lbwl+B8uHAqIy3AX_1XnIePHp+8Ow{s)5Zc`9UJV1L9W{)iWJc1;sAi?s2Y4)J6` zZQ~B+bPm1p4t8r}1?2;>9~gKz$~yQvguRX3Ik>_(c+xop%Q^l-C8eQiv>`MoXkkSU zDOcQsrZ<=vz>|4+SJmk0>*?pEmgi(9>E~o7CF|!VCTC>krRqa&dHaXh5_Bv07;{u85&T0GcbV8P(@k&fXHtMtVl3dWH;)4UB>e0&IeeLX6BD(j2NBpe8cd6WB&VK>h+tLJ3fU z12I7~ERTWsu+AW;eglOKhz7}n>L!r6pfVR!zk}*EP+0(CgXWY#dO0*8We`XoXx<7m zlm;q0Kzv{5-O->0WS~0)Ky?sEFQ~o%>t$d759NT$G>|xG?KjL`&>6QdahN|q?!nio z%*iZCElSLRuKK{}T|&}5@=eE(wIYzak-;}KLj(vcBtcy`Ley=^Am1V|Gicoyg3Ca- zPY5b85gM4`t12L3n0-c2C_>~wBxWBG*3tpVg6>lW)mjiXh-79EfRqUgkh~!TaxbXo zmzoD2CIsz60jUF}BM=)@u7k>V5E~Rnptc-nuOeu!0Mxq#u|eqwG{z5NgVGUbZ3Ku7 zN+aO)8H|v01Zq2i#6j_|3%b7!Dh^6lAaRg-&|C$G4N6m>xhfDFl&0LF>Op$FplpzO z(AmkLwF4kGgW49L`D73qbYBgK4XTUs7#J8pY*5I6+E*YpDAYlB_kq|Tzk=pPLXYL4F6FoeW}w)_sHSoB^>xVF2n!fY_ig0L{yQ z*r4zMot+F~gW7qZG7H28g$<}50b+x~2DCOG#0Iq+Klt1_n^Pfcp-N3=E)t8@TVl2+8Z!N?mI9tFo4#d=z;nU zjF3A#L3g}>%m=ND0QVyp!F4crj}B}c02Ci6{T*nM2laPgaSe(~&>S5ou0ib%m^es{ zFjPHA4z?}_nGH4{ssh`>K^T;uK{ROo z8Dum}9jKiMD~mz$Fm<3X0kJ{yAaT$hLy)^*^#Di?WIlL}5@?nNq=IxQ45(iO(gQOOwC4__A7mb=<^aio_@Eg%WcPvgDudPxL5+up z3#eQK>4BLC+P4Q%2Qm+oPeF1Z^FVD4SQ-GC0opqZTBihJgD}i45DjW?fW$x;w09SD zh8QTHgUkV$2Qn8F=E&v+uwwTwqTf+oL`=WK#K4m1eg|m39df@zjscV#89;NljSLKP znO1PHu`+b+I>gPm>4d_810vjK4s-Vg%vb=!py=Bib`fCcF-mfW=1y9Vk2fo4p803%)|;> zV#LhBDhk@G!odz&Si#J~3K|<@W?=^{nPO&PX9n$bVgc0~EG(eibj*w#pvwbTSU|~# z6(qt2x^#=F6I9%RYzDc2an4N!1_t(G21ZqoFk=u$X>u_GqXwwU4pIY(G6s(L_zDI_ zZIIER#mWqza|0O|m~}zpVyvJ+Jbc?#I2ah1RT#Lr?YNow7#LXi8MwJUg&7!F)fhk& z8|wBElpQMUs9RDvP`9LTax;dCLpG}LS#eu)dkWi2f_9&PA{RR483da01p5+P#ew_- zmH~~OGcrVgC{XrgVyFaf`2#h9nHj1RK*0)D3u-q&(lsO&L4qLTKr{%0(lV%Q2IYHD z8y#dF$WV|R2!rlNU}6C8FvQzYMCm0$rV|;+>)If9H#75+b4pWEA^ptqBG|+wXmbZ- z=R`7S?L34D?|!N=GP8g?ceP*=(ygmQ>KN8>3NtW*<|^5k89>5p%&eSj44@7t10!R6 zJlM?mf|8>6c*JBOD1D>!@343n+^GY*64c{zRxr`C&@)xg%>_;UB`4M1mQVLP%jIt6ihIKxAlRUU;?zx0nC6B%;24{P!71g2^!Hv z=7UBgk@=F4Dg`P8YAZ-U*`SmI+P47Sl>jauPzxDoHUX=K?NtDUo(L%UfmRZM`k_n= z44_m9x)%sE*9nzk01e)NN_LQaAU3GI0>ZF94#*9#`4LcE0Gr1F^&4SqP)xx3FQ8C` zt-%GgonUNGzZAv>&BMaX1mzBxIUqA(YwN-7bdX^T3=H782PhlVSA>}Z>J!4);GsyU z8c=@^CJyS?!Pwxw4^$0!9stS)^}AteKy!02Hh7;sRLyKq8yJ+m85kHql_Si}pgVOpB0v{n)%4r;7`_S=Klpzr{X z8!&-J&p|dYFff7?Lzr+j$jvbKAg5J!1(;C?jJUr?h6QXqGM`T!vRfE0uJ zv!M6|u|XKd2DP+7Y*@bobk+#SeW1Jr(hrgY@v*JX29*OKvp^W64n%{}0f-GV57y5D znFlHZKyo1SK<)vV4-y0E1C2p}Xcz{`f!Lt_EGQlbsRQRdkOn9Q&3l8!iJ)Bg3KP(H z4#*8K_ksFtps@*%`;hyyps^U38$f1&+WfCT3@C=lp|8&_;9y_??N0!i2P*MFc7gm0 z@*hkO$OzE>0g#y>HVDJyK-~x!8zc_8vk5e&1Y(0QOb)ax6l6BcAE5KiLA?c#y&(HQ zav&Pi6@cjh=?9(r1xgzrHVDJyK;w8IJuve`xFGX^AoD<-Adno$JoNS1InZ+!KxTn3 z%skNA0gxV;c^1%h@F4R*`4l7vG7o&WEl492_b@Rqe1x(=6wEx(-D)5`F!Mn3pD_P| zYC@14$UIQ~2I&FiACUf9W(Ee(*=`^<2!rH67<4uVh=!>Hof!-2Oo7yZFh~xBLFd$g z(gjEighA)MVjE8ZuO9&^fZ`w={b*3v4&+vtKYl>>Lx92sR0D(LK>h%&X#m*|HI5;Q z6*6xP&(?2pY!)nFYcib3nAdk(mYba18J?B%%3AQw!qH(g00Qg1VNV zvIJD(B8?lIWm05d;Ne)oSv(t$HY(j7gP?lX?_FyTK(12l#P8&}8y_4Gj=W?%tdDb3i+ zz`y{iNI+sBg&-O>t^irU4Vo@uVPQ`M>11Lz22qS`ZeWT7w4IHGi4`<6&ceY8I&7VV zgB>(B&%(lb5VZV=g&lOm9SaLPsGwqDk4Es$N`LV zKzq74iVYbU^+6-5AaTxOBPfqCm?MvYQ6IGY0#wCw1%dVqnt*hGMmM>@LnWplE@(iJ zJB5MK3}iN_<^!cx2JU1-21ZNJCMr2b1_thABL+q*5N|Uh0|PIpyaA10bA!h$EJGO? z7(mD7Gw^{b3(x=;M8XOr@e7i0SXn?EHjum7Ko)_TAPg+Jpxsz(V8=5GGOF?kb2IZv z^MM8^1jHE_n4m)%pwSI624?681Oo#LRGg22ffY8?!3G)XV8=7mL3qtM)CSP$8=%8D zI3PnFATAGNAcPl0F$yy<@NqMOT*<(|k2tggIy3@`22cgZ$PfggKt5(<0L|8bB)}My z-541{Kon^82^&KRLj{A(d=MKHEgTTOGUI#@4;1e(6=2;A4B*w2AhV%XfDB?}hyhU` zGdLJ(7%CW)lo`P$LiB@0K+Q_95uiCr0Z@CBAs9q~mNv366oWL)2eBcBfcYqffJIOY z0adkIVvI5wp zU^aqP1@g@lMq??C|5ApU8jK8L!eGCF?6QLBHk1MDf$E3yz$QT1*vtUCh=GB@hJk?r zWERpPB%tmDsQ6}LC}IH7AcwL-tO7AXs@Wl2Lr}>KHVKs1K$5JGummw7>c9bqPzTZg zDUv~jIan(LD3~BDMD&81sG!UUDyBgO;gbjDJeYhWXuk==cTfbAJ|tF9l%EA%J%Ka| zqg!TT30h#GpPrnIDXR}2NYaN5hLJb&gKJnVFFCO|H95BcHnxU-DoHV9R{(fW48nvD zv>CxpD1n?!0y{edwB7KDkp|t^VdHN#pz$|m4o+6=!*8UHqk%@6;!7Ax zlZ%Z&oo$%k@Q!GqjAOw$;K4RMJ$(eiGExQ_@PpZ*m&^dx10N+LFPexSpo3dPU^uQc zx!8~aq6Rd02lpX}0}8LfKQhM;T>}E5LDe0oYz7sqpuP^M4+$y~ z2V;ZA17K{>x(yf`)YOKt!SmgqfMH-@0F5=k#6fH9VQkQZ9gGb=9|Wo%)YpcIgXf!} z;-INP*q9G!Z47Mu3Uq%sZ0zndsG0^B1`G_Ku_>52;4wX@IQX1MsF|Rl9zX>esN;gPwx3#KjL74Ppz&Ccdq8%A#$aJ=P&~repdJm34H|cau|eamFg7Ue zU~Ev_!PubA6^sp<#D%dz8+u`EP!|ct28~<5*r0Jp7#kF)Fg9o$62=CtWrDFm@e5;v z)-S=>pk5b@4H|ERu|fTL7#p-s3C0Gk-i5J2Gtw|N@_8csNN0S2x^OTxptVUbwkDDq zT_koo5<44-4eI>C^lnEI2X+2n;-`?rLHBCG#F6hmN51p?DUy0nUlFDrbY~ij4O-O- zWAh^2gAE!BMOhyOO_QK<38o&DZeVOs`2}NxvIL9`O4cwoxO~H64yexyQv({;g|R_n zk}x)?0{~-##-U(r(0B%n4O&+Q%WHg~^4D8GlP?-%oGX>;c(ArbbxHKr6 zgT^F5Y>?Ywds09h1@KxjCI$vj{so=t2~q><-+(rngV>-l9(GO&sEh}lcMK8-mH(iy zqW1VUxa@`c5oA6w7!=l^b`&UnLFz%_2Z}oo8-!tO^s(*&Zpc{+pbi#DKS&)Ye6Wpm zgX&X|Ss)Bj2ckh?24cg;-fFlZeM69Wpm+hvfy@KB2V_1-45SY{fB|AaF-Q)?1l32N zcq60^eXJW~9w=Rb%m87Ky&xJ?SA*Cv_w7I$8w8DMg5*H%1J`RH4NwdklLei11LeZo zTI{$`nEO}+85lro9YN-S@+?RWWFGoh_YpP* zhH{u8&~OHE(Z{;2Ik4}gK_Ba`;ef0^2DuG{L1uwy^s#Qx{Y0R23z7q2m^$>a?gfH~ z{015%f%yY{ta}d!WL+%CED(m7hd$Q5Mi8P76fXG2x&=6i8|wz$x9Y$M*~beDXHfis z(l#tlg52Z64Jj`{Y!HUI557h&4|FOj;d7%+42(>`gW^P-ZSn)uSi(HpWG?u;Xz)6? zivMd_+87zmNGm|L~7xgX$mHSoR%gI}Nl(4wMEN zL8DusMh(cbAcY_rHkJ*V9Adf#9m@vo3}azp2Q7MLVPpfXnqy()03AZY0y*o11#+wj z3kN$mPqVOsn!GH~V@+7tK?|xOXPK}ta)3@~Lq5v{)BM+Pb)!MBnO)A1vwv-U7*9U zpulBhhy+ofgv`NE2^v{dW}FY=ftDb!K}6<**r2Kjp#o$Q41@GDG6aJtkVX#3pdyMf z;BiGHW59f6M)(jd$S9D0Murd&1rB0{D3B-!gG_}K&Y*k?5@BEfDS@ycyC8?pxgy{! zOx(f7#~EM?^cX?oexQYTkkgDo%kkJ47}=O12aA9fGUp z!Q)_H0yd&W2!a4?M;R#VgYprG28n}c5awlotcU_-J(xI%4QkbcMgl=6c!7Ebt-kqojlu(+g%K`%K!H#aq}gh3B7GK{?StfE8@>+vG6`V|x^ znCtS8WkG9skZWoXA5mI?^kc5u1GR)fG7!uR-pvJJgGgqSRd68lKrJtj3e0kJ`;3WO;dn*+5^7#J8pzJ;xs1K9^- zgW6}Xek^E=64t*3Rcf#?Ch*uC)ErP>2&NZ2HU||4_Ya|L(3lQP4Y&^j6$g*aLD}H3 zIVc-EHV0*c#&=+PLE}3xHfRqUj7`khy`VikurV*t*bR(*9@PE@MG7duk;c40;STdV z$SE*3XdD;D2CdA5u|aVOV}ts5FgB=R17m~MqrljpzB`N!Y6ZdApzwjQLE!^qgYKb+ zv60UNDMoTLXfXmz4f5H#poSGp9JJ2`#s=->gRwzdD`0F;|D4eH3up`rmQFz9R-my4 zP!O^rjdy^?szBnP;05ogV}fjdkcFxNrE5^z6Ql-|20>$0AU3Ga0UPfCA={ad<$cP!XL&4r&Ulf4c*fV69=#Rgo=agA_ij{ z;{e$U(+f&hAU66KhXT@h7od_7qz>dK(0)n~A68m|@(D;k41?rAY*0D_g)<>_;5D%z z4Nwd+50qY^T=@Ds^z%3}klY8V>0s^yhaF5a0|NtStsH2tCQJzCKG66SNDru=0+QPR zU4IA4L!go!BnR>@c+Vk70ThGQ>wwZVlnWo@0F4L3%m&H5W@KOhonHfDgD^}EG{ylk z8)okvPRRMAAbUY&G)N9)FKFKxObXBfylP?rrP2Qm-+JPs}v1_scoBam4j3^EUd z(a+;ZB=S5C&^j|v`2;cxgh6J3X!P?qZm~kn*#OCbFiah2j05CWm_K^BA?iT>04*H? z$$|UeSXlL(;)jmW`i)yeMo)&+yWxb zGc~pZ-53Sx^%FkNbPuS4!0hw)GVw5}i>MuAWk?g@cH&@AVrEcK0iCnK?IQN*pLB<` z@g%U|bfJ4~-~WTo-(X;1z_m9Hbk-QG-w&Ew0{I`*?+2BejG$#muzo*CA;{xc`~9H4 zIj(*`=%gb=zaKP)%z~}o5AX4V`tOi6Y@oGp%*vqUUm%M?4uJOf?LZ@*ATe-{AIt-_ zcR)RUJ5YfIDun6Y%?G)M0g{@6Kor=$h)aw>(jc!eG6aJth%D&zdyoVegPL-T3?U#2 zlmeL~DDA7~D$-6N9p=4tFP_TMuS|dhodggJfGBD0jfR>Y%I$ z%0(a=Bo1l_f!Lsm2GsQiWm8ZY4Pt{DUZ6?=qz07xKm{mB9F#d>dO>WEc_49EZUm_x zp51nMn+oLp;oNTrMJ1x&4$hLr&@>GmJplE?K?OFbZvkS1k`1Va0I@+y0+ggcY*4ZR zmGK}pNDZvt4w46jA*inoD$YT2AU3Ga4#K1Tb_NE}oF1&-4w`#|u|X3IuznZvni|kr z3|LP=8Jk+Q$Z^chK4*kT@tkD?-IVX&H0}DM%a?ez3keXj}+%IzC7o)ISHE zO#)(r@)2m33B(5F9Z(#>;uq8pfU#-OR|kbB%zTi (awc2Ic%(+kSaAU3G_0I@;o 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�A~-72#9wC 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

    LBC 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%0A1^zz_gsUt?!r0IgL3 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�FJZAR43)L?hP4m4eohF|qT4C`LBW3Bk;a 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 zpon600?B}e132

  • }RQYn;=eYCvc6 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

    l$kps;hF){>!C{Q9mT>%GbVnSMdpq4Kvp)fFj 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

    gXjN2QHRVIhOZa^MWzs_H400f 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

    hCw0k34_Aa9SjOfJ|OT}9|ncHFBlZwYA`7L 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

    !^GBWUZD00Rf8;77g>d^^YN#t`^@;O!t8 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°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�Jgr!PFc@62FARzK_Iy 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%0AY|i5DiL~AU4cA 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�CWkLJb2y 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≻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�H<` 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≀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 ?Yc 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 YDBxjI0-h^|^40%Ye7&My05FekMlbV=U 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

    7$bB`I~VaMyn7lRLghMN`-Jwz9}6$W}R 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 QObJ|Nqa-z*xh;!w5S18)P&XgVvsd)|4{v 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

    SIIV*Op!lXR0|T~mLO|n-AhTii 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

    -)U1E(~&{Lutw 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

      ViSW~D$ERmg$5 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 V;t<)q4mJjcM_?Tg0%Q(|1pxf~6bJwS literal 0 HcmV?d00001 diff --git a/components/newlib/lib/libm.a b/components/newlib/lib/libm.a new file mode 100644 index 0000000000000000000000000000000000000000..f3fe6dab3ee9690d048156511abc069802bc84e7 GIT binary patch literal 2227074 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

      AJ{=B9do5t|J!p3ySiy^g(kr#fiG9#RY~27P_f9 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

      |`b;)24e$l8-t%U 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 | Full +---> | Active | | Empty | <- states + | #11 | | #12 | | #14 | | | <- sequence numbers + +---+----+ +----+---+ +----+---+ +---+----+ + | | | | + | | | | + | | | | + +---v------+ +-----v----+ +------v---+ +------v---+ + | Sector 3 | | Sector 0 | | Sector 2 | | Sector 1 | <- physical sectors + +----------+ +----------+ +----------+ +----------+ + +Structure of a page +~~~~~~~~~~~~~~~~~~~ + +For now we assume that flash sector size is 4096 bytes and that ESP32 flash encryption hardware operates on 32-byte blocks. It is possible to introduce some settings configurable at compile-time (e.g. via menuconfig) to accommodate flash chips with different sector sizes (although it is not clear if other components in the system, e.g. SPI flash driver and SPI flash cache can support these other sizes). + +Page consists of three parts: header, entry state bitmap, and entries themselves. To be compatible with ESP32 flash encryption, entry size is 32 bytes. For integer types, entry holds one key-value pair. For strings and blobs, an entry holds part of key-value pair (more on that in the entry structure description). + +The following diagram illustrates page structure. Numbers in parentheses indicate size of each part in bytes. :: + + +-----------+--------------+-------------+-----------+ + | State (4) | Seq. no. (4) | Unused (20) | CRC32 (4) | Header (32) + +-----------+--------------+-------------+-----------+ + | Entry state bitmap (32) | + +----------------------------------------------------+ + | Entry 0 (32) | + +----------------------------------------------------+ + | Entry 1 (32) | + +----------------------------------------------------+ + / / + / / + +----------------------------------------------------+ + | Entry 125 (32) | + +----------------------------------------------------+ + +Page header and entry state bitmap are always written to flash unencrypted. Entries are encrypted if flash encryption feature of the ESP32 is used. + +Page state values are defined in such a way that changing state is possible by writing 0 into some of the bits. Therefore it not necessary to erase the page to change page state, unless that is a change to *erased* state. + +CRC32 value in header is calculated over the part which doesn't include state value (bytes 4 to 28). Unused part is currently filled with ``0xff`` bytes. Future versions of the library may store format version there. + +The following sections describe structure of entry state bitmap and entry itself. + +Entry and entry state bitmap +~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Each entry can be in one of the following three states. Each state is represented with two bits in the entry state bitmap. Final four bits in the bitmap (256 - 2 * 126) are unused. + +Empty (2'b11) + Nothing is written into the specific entry yet. It is in an uninitialized state (all bytes ``0xff``). + +Written (2'b10) + A key-value pair (or part of key-value pair which spans multiple entries) has been written into the entry. + +Erased (2'b00) + A key-value pair in this entry has been discarded. Contents of this entry will not be parsed anymore. + + +Structure of entry +~~~~~~~~~~~~~~~~~~ + +For values of primitive types (currently integers from 1 to 8 bytes long), entry holds one key-value pair. For string and blob types, entry holds part of the whole key-value pair. In case when a key-value pair spans multiple entries, all entries are stored in the same page. + +:: + + +--------+----------+----------+---------+-----------+---------------+----------+ + | NS (1) | Type (1) | Span (1) | Rsv (1) | CRC32 (4) | Key (16) | Data (8) | + +--------+----------+----------+---------+-----------+---------------+----------+ + + +--------------------------------+ + +-> Fixed length: | Data (8) | + | +--------------------------------+ + Data format ---+ + | +----------+---------+-----------+ + +-> Variable length: | Size (2) | Rsv (2) | CRC32 (4) | + +----------+---------+-----------+ + + +Individual fields in entry structure have the following meanings: + +NS + Namespace index for this entry. See section on namespaces implementation for explanation of this value. + +Type + One byte indicating data type of value. See ``ItemType`` enumeration in ``nvs_types.h`` for possible values. + +Span + Number of entries used by this key-value pair. For integer types, this is equal to 1. For strings and blobs this depends on value length. + +Rsv + Unused field, should be ``0xff``. + +CRC32 + Checksum calculated over all the bytes in this entry, except for the CRC32 field itself. + +Key + Zero-terminated ASCII string containing key name. Maximum string length is 15 bytes, excluding zero terminator. + +Data + For integer types, this field contains the value itself. If the value itself is shorter than 8 bytes it is padded to the right, with unused bytes filled with ``0xff``. For string and blob values, these 8 bytes hold additional data about the value, described next: + +Size + (Only for strings and blobs.) Size, in bytes, of actual data. For strings, this includes zero terminator. + +CRC32 + (Only for strings and blobs.) Checksum calculated over all bytes of data. + +Variable length values (strings and blobs) are written into subsequent entries, 32 bytes per entry. `Span` field of the first entry indicates how many entries are used. + + +Namespaces +~~~~~~~~~~ + +As mentioned above, each key-value pair belongs to one of the namespaces. Namespaces identifiers (strings) are stored as keys of key-value pairs in namespace with index 0. Values corresponding to these keys are indexes of these namespaces. + +:: + + +-------------------------------------------+ + | NS=0 Type=uint8_t Key="wifi" Value=1 | Entry describing namespace "wifi" + +-------------------------------------------+ + | NS=1 Type=uint32_t Key="channel" Value=6 | Key "channel" in namespace "wifi" + +-------------------------------------------+ + | NS=0 Type=uint8_t Key="pwm" Value=2 | Entry describing namespace "pwm" + +-------------------------------------------+ + | NS=0 Type=uint16_t Key="channel" Value=20 | Key "channel" in namespace "pwm" + +-------------------------------------------+ + + diff --git a/components/nvs_flash/include/nvs.h b/components/nvs_flash/include/nvs.h new file mode 100644 index 0000000000..084fa70545 --- /dev/null +++ b/components/nvs_flash/include/nvs.h @@ -0,0 +1,212 @@ +// Copyright 2015-2016 Espressif Systems (Shanghai) PTE LTD +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at + +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +#ifndef ESP_NVS_H +#define ESP_NVS_H + +#include +#include +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * Opaque pointer type representing non-volatile storage handle + */ +typedef uint32_t nvs_handle; + +#define ESP_ERR_NVS_BASE 0x1100 +#define ESP_ERR_NVS_NOT_INITIALIZED (ESP_ERR_NVS_BASE + 0x01) +#define ESP_ERR_NVS_NOT_FOUND (ESP_ERR_NVS_BASE + 0x02) +#define ESP_ERR_NVS_TYPE_MISMATCH (ESP_ERR_NVS_BASE + 0x03) +#define ESP_ERR_NVS_READ_ONLY (ESP_ERR_NVS_BASE + 0x04) +#define ESP_ERR_NVS_NOT_ENOUGH_SPACE (ESP_ERR_NVS_BASE + 0x05) +#define ESP_ERR_NVS_INVALID_NAME (ESP_ERR_NVS_BASE + 0x06) +#define ESP_ERR_NVS_INVALID_HANDLE (ESP_ERR_NVS_BASE + 0x07) +#define ESP_ERR_NVS_KEY_TOO_LONG (ESP_ERR_NVS_BASE + 0x09) +#define ESP_ERR_NVS_PAGE_FULL (ESP_ERR_NVS_BASE + 0x0a) +#define ESP_ERR_NVS_INVALID_STATE (ESP_ERR_NVS_BASE + 0x0b) +#define ESP_ERR_NVS_INVALID_LENGTH (ESP_ERR_NVS_BASE + 0x0c) + +typedef enum { + NVS_READONLY, + NVS_READWRITE +} nvs_open_mode; + +/** + * @brief Open non-volatile storage with a given namespace + * + * Multiple SDK and application modules can store their key-value pairs in the + * NVS module. In order to reduce possible conflicts on key names, each module + * can use its own namespace. + * + * @param[in] name Namespace name. Maximal length is determined by the + * underlying implementation, but is guaranteed to be + * at least 16 characters. Shouldn't be empty. + * @param[in] open_mode NVS_READWRITE or NVS_READONLY. If NVS_READONLY, will + * open a handle for reading only. All write requests will + * be rejected for this handle. + * @param[out] out_handle If successful (return code is zero), handle will be + * returned in this argument. + * + * @return - ESP_OK if storage handle was opened successfully + * - ESP_ERR_NVS_NOT_INITIALIZED if the storage driver is not initialized + * - ESP_ERR_NVS_NOT_FOUND id namespace doesn't exist yet and + * mode is NVS_READONLY + * - ESP_ERR_NVS_INVALID_NAME if namespace name doesn't satisfy constraints + * - other error codes from the underlying storage driver + */ +esp_err_t nvs_open(const char* name, nvs_open_mode open_mode, nvs_handle *out_handle); + +/** + * @brief nvs_set_X - set value for given key + * + * This family of functions set value for the key, given its name. Note that + * actual storage will not be updated until nvs_commit function is called. + * + * @param[in] handle Handle obtained from nvs_open function. If the handle was + * opened with read_only set to true, nvs_set_X functions will + * fail with ESP_ERR_NVS_READONLY. + * @param[in] key Key name. Maximal length is determined by the underlying + * implementation, but is guaranteed to be at least + * 16 characters. Shouldn't be empty. + * @param[in] value The value to set. + * @param[in] length For nvs_set_blob: length of binary value to set, in bytes. + * + * @return - ESP_OK if value was set successfully + * - ESP_ERR_NVS_INVALID_HANDLE if handle has been closed or is NULL + * - ESP_ERR_NVS_READ_ONLY if storage handle was opened as read only + * - ESP_ERR_NVS_INVALID_NAME if key name doesn't satisfy constraints + * - ESP_ERR_NVS_NOT_ENOUGH_SPACE if there is not enough space in the + * underlying storage to save the value + */ +esp_err_t nvs_set_i8 (nvs_handle handle, const char* key, int8_t value); +esp_err_t nvs_set_u8 (nvs_handle handle, const char* key, uint8_t value); +esp_err_t nvs_set_i16 (nvs_handle handle, const char* key, int16_t value); +esp_err_t nvs_set_u16 (nvs_handle handle, const char* key, uint16_t value); +esp_err_t nvs_set_i32 (nvs_handle handle, const char* key, int32_t value); +esp_err_t nvs_set_u32 (nvs_handle handle, const char* key, uint32_t value); +esp_err_t nvs_set_i64 (nvs_handle handle, const char* key, int64_t value); +esp_err_t nvs_set_u64 (nvs_handle handle, const char* key, uint64_t value); +esp_err_t nvs_set_str (nvs_handle handle, const char* key, const char* value); +esp_err_t nvs_set_blob(nvs_handle handle, const char* key, const void* value, size_t length); + +/** + * @brief nvs_get_X - get value for given key + * + * These functions retrieve value for the key, given its name. If key does not + * exist, or the requested variable type doesn't match the type which was used + * when setting a value, an error is returned. + * + * In case of any error, out_value is not modified. + * + * All functions expect out_value to be a pointer to an already allocated variable + * of the given type. + * Additionally, nvs_get_str and nvs_get_blob support WinAPI-style length queries. + * To get the size necessary to store the value, call nvs_get_str or nvs_get_blob + * with zero out_value and non-zero pointer to length. Variable pointed to + * by length argument will be set to the required length. For nvs_get_str, + * this length includes the zero terminator. When calling nvs_get_str and + * nvs_get_blob with non-zero out_value, length has to be non-zero and has to + * point to the length available in out_value. + * It is suggested that nvs_get/set_str is used for zero-terminated C strings, and + * nvs_get/set_blob used for arbitrary data structures. + * + * Example of using nvs_get_i32: + * int32_t max_buffer_size = 4096; // default value + * esp_err_t err = nvs_get_i32(my_handle, "max_buffer_size", &max_buffer_size); + * assert(err == ESP_OK || err == ESP_ERR_NVS_NOT_FOUND); + * // if ESP_ERR_NVS_NOT_FOUND was returned, max_buffer_size will still + * // have its default value. + * + * Example (without error checking) of using nvs_get_str to get a string into dynamic array: + * size_t required_size; + * nvs_get_str(my_handle, "server_name", NULL, &required_size); + * char* server_name = malloc(required_size); + * nvs_get_str(my_handle, "server_name", server_name, &required_size); + * + * Example (without error checking) of using nvs_get_blob to get a binary data + * into a static array: + * uint8_t mac_addr[6]; + * size_t size = sizeof(mac_addr); + * nvs_get_blob(my_handle, "dst_mac_addr", mac_addr, &size); + * + * @param[in] handle Handle obtained from nvs_open function. + * @param[in] key Key name. Maximal length is determined by the underlying + * implementation, but is guaranteed to be at least + * 16 characters. Shouldn't be empty. + * @param out_value Pointer to the output value. + * May be NULL for nvs_get_str and nvs_get_blob, in this + * case required length will be returned in length argument. + * @param[inout] length For nvs_get_str and nvs_get_blob, non-zero pointer + * to the variable holding the length of out_value. + * In case out_value a zero, will be set to the length + * required to hold the value. In case out_value is not + * zero, will be set to the actual length of the value + * written. For nvs_get_str this includes zero terminator. + * + * @return - ESP_OK if the value was retrieved successfully + * - ESP_ERR_NVS_NOT_FOUND if the requested key doesn't exist + * - ESP_ERR_NVS_INVALID_HANDLE if handle has been closed or is NULL + * - ESP_ERR_NVS_INVALID_NAME if key name doesn't satisfy constraints + * - ESP_ERR_NVS_INVALID_LENGTH if length is not sufficient to store data + */ +esp_err_t nvs_get_i8 (nvs_handle handle, const char* key, int8_t* out_value); +esp_err_t nvs_get_u8 (nvs_handle handle, const char* key, uint8_t* out_value); +esp_err_t nvs_get_i16 (nvs_handle handle, const char* key, int16_t* out_value); +esp_err_t nvs_get_u16 (nvs_handle handle, const char* key, uint16_t* out_value); +esp_err_t nvs_get_i32 (nvs_handle handle, const char* key, int32_t* out_value); +esp_err_t nvs_get_u32 (nvs_handle handle, const char* key, uint32_t* out_value); +esp_err_t nvs_get_i64 (nvs_handle handle, const char* key, int64_t* out_value); +esp_err_t nvs_get_u64 (nvs_handle handle, const char* key, uint64_t* out_value); +esp_err_t nvs_get_str (nvs_handle handle, const char* key, char* out_value, size_t* length); +esp_err_t nvs_get_blob(nvs_handle handle, const char* key, void* out_value, size_t* length); + +/** + * @brief Write any pending changes to non-volatile storage + * + * After setting any values, nvs_commit() must be called to ensure changes are written + * to non-volatile storage. Individual implementations may write to storage at other times, + * but this is not guaranteed. + * + * @param[in] handle Storage handle obtained with nvs_open. If handle has to be + * opened as not read only for this call to succeed. + * + * @return - ESP_OK if the changes have been written successfully + * - ESP_ERR_NVS_INVALID_HANDLE if handle has been closed or is NULL + * - other error codes from the underlying storage driver + */ +esp_err_t nvs_commit(nvs_handle handle); + +/** + * @brief Close the storage handle and free any allocated resources + * + * This function should be called for each handle opened with nvs_open once + * the handle is not in use any more. Closing the handle may not automatically + * write the changes to nonvolatile storage. This has to be done explicitly using + * nvs_commit function. + * Once this function is called on a handle, the handle should no longer be used. + * + * @param[in] handle Storage handle to close + */ +void nvs_close(nvs_handle handle); + + +#ifdef __cplusplus +} // extern "C" +#endif + +#endif //ESP_NVS_H diff --git a/components/nvs_flash/include/nvs_flash.h b/components/nvs_flash/include/nvs_flash.h new file mode 100644 index 0000000000..5d9dc7359b --- /dev/null +++ b/components/nvs_flash/include/nvs_flash.h @@ -0,0 +1,29 @@ +// Copyright 2015-2016 Espressif Systems (Shanghai) PTE LTD +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at + +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +#ifndef nvs_flash_h +#define nvs_flash_h + +#ifdef __cplusplus +extern "C" { +#endif + +esp_err_t nvs_flash_init(uint32_t baseSector, uint32_t sectorCount); + + +#ifdef __cplusplus +} +#endif + + +#endif /* nvs_flash_h */ diff --git a/components/nvs_flash/src/compressed_enum_table.hpp b/components/nvs_flash/src/compressed_enum_table.hpp new file mode 100644 index 0000000000..8ee95d9f99 --- /dev/null +++ b/components/nvs_flash/src/compressed_enum_table.hpp @@ -0,0 +1,79 @@ +// Copyright 2015-2016 Espressif Systems (Shanghai) PTE LTD +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at + +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#ifndef compressed_enum_table_h +#define compressed_enum_table_h + +#include +#include +#include + +template +class CompressedEnumTable +{ +public: + uint32_t* data() + { + return mData; + } + + const uint32_t* data() const + { + return mData; + } + + Tenum get(size_t index) + { + assert(index >= 0 && index < Nitems); + size_t wordIndex = index / ITEMS_PER_WORD; + size_t offset = (index % ITEMS_PER_WORD) * Nbits; + + return static_cast((mData[wordIndex] >> offset) & VALUE_MASK); + } + + void set(size_t index, Tenum val) + { + assert(index >= 0 && index < Nitems); + size_t wordIndex = index / ITEMS_PER_WORD; + size_t offset = (index % ITEMS_PER_WORD) * Nbits; + + uint32_t v = static_cast(val) << offset; + mData[wordIndex] = (mData[wordIndex] & ~(VALUE_MASK << offset)) | v; + } + + static constexpr size_t getWordIndex(size_t index) + { + return index / ITEMS_PER_WORD; + } + + static constexpr size_t byteSize() + { + return WORD_COUNT * 4; + } + + static constexpr size_t count() + { + return Nitems; + } + + +protected: + static_assert(32 % Nbits == 0, "Nbits must divide 32"); + static const size_t ITEMS_PER_WORD = 32 / Nbits; + static const size_t WORD_COUNT = ( Nbits * Nitems + 31 ) / 32; + static const uint32_t VALUE_MASK = (1 << Nbits) - 1; + uint32_t mData[WORD_COUNT]; +}; + +#endif /* compressed_enum_table_h */ diff --git a/components/nvs_flash/src/intrusive_list.h b/components/nvs_flash/src/intrusive_list.h new file mode 100644 index 0000000000..fc92442cd7 --- /dev/null +++ b/components/nvs_flash/src/intrusive_list.h @@ -0,0 +1,248 @@ +// Copyright 2015-2016 Espressif Systems (Shanghai) PTE LTD +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at + +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +#ifndef intrusive_list_h +#define intrusive_list_h + +#include + +template +class intrusive_list; + +template +class intrusive_list_node +{ +protected: + friend class intrusive_list; + T* mPrev = nullptr; + T* mNext = nullptr; +}; + +template +class intrusive_list +{ + typedef intrusive_list_node TNode; + static_assert(std::is_base_of::value, ""); + +public: + + class iterator : public std::iterator + { + public: + + iterator() : mPos(nullptr) {} + + iterator(T* pos) : mPos(pos) {} + + iterator operator++(int) + { + auto result = *this; + mPos = mPos->mNext; + return result; + } + + iterator operator--(int) + { + auto result = *this; + mPos = mPos->mPrev; + return result; + } + + iterator& operator++() + { + mPos = mPos->mNext; + return *this; + } + + iterator& operator--() + { + mPos = mPos->mPrev; + return *this; + } + + + bool operator==(const iterator& other) const + { + return mPos == other.mPos; + } + + bool operator!=(const iterator& other) const + { + return !(*this == other); + } + + T& operator*() + { + return *mPos; + } + + const T& operator*() const + { + return *mPos; + } + + T* operator->() + { + return mPos; + } + + const T* operator->() const + { + return mPos; + } + + operator T*() + { + return mPos; + } + + operator const T*() const + { + return mPos; + } + + + protected: + T* mPos; + }; + + void push_back(T* node) + { + if (mLast) { + mLast->mNext = node; + } + node->mPrev = mLast; + node->mNext = nullptr; + mLast = node; + if (mFirst == nullptr) { + mFirst = node; + } + ++mSize; + } + + void push_front(T* node) + { + node->mPrev = nullptr; + node->mNext = mFirst; + if (mFirst) { + mFirst->mPrev = node; + } + mFirst = node; + if (mLast == nullptr) { + mLast = node; + } + ++mSize; + } + + T& back() + { + return *mLast; + } + + const T& back() const + { + return *mLast; + } + + T& front() + { + return *mFirst; + } + + const T& front() const + { + return *mFirst; + } + + void pop_front() + { + erase(mFirst); + } + + void pop_back() + { + erase(mLast); + } + + void insert(iterator next, T* node) + { + if (static_cast(next) == nullptr) { + push_back(node); + } else { + auto prev = next->mPrev; + if (!prev) { + push_front(node); + } else { + prev->mNext = node; + next->mPrev = node; + node->mNext = next; + node->mPrev = &(*prev); + ++mSize; + } + } + } + + void erase(iterator it) + { + auto prev = it->mPrev; + auto next = it->mNext; + + if (prev) { + prev->mNext = next; + } else { + mFirst = next; + } + if (next) { + next->mPrev = prev; + } else { + mLast = prev; + } + --mSize; + } + + iterator begin() + { + return iterator(mFirst); + } + + iterator end() + { + return iterator(nullptr); + } + + size_t size() const + { + return mSize; + } + + bool empty() const + { + return mSize == 0; + } + + + void clear() + { + while (mFirst) { + erase(mFirst); + } + } + +protected: + T* mFirst = nullptr; + T* mLast = nullptr; + size_t mSize = 0; +}; + + +#endif /* intrusive_list_h */ diff --git a/components/nvs_flash/src/nvs.hpp b/components/nvs_flash/src/nvs.hpp new file mode 100644 index 0000000000..d2f9d3d014 --- /dev/null +++ b/components/nvs_flash/src/nvs.hpp @@ -0,0 +1,25 @@ +// Copyright 2015-2016 Espressif Systems (Shanghai) PTE LTD +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at + +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +#ifndef nvs_hpp +#define nvs_hpp + + +#include +#include "nvs.h" +#include "nvs_types.hpp" +#include "nvs_page.hpp" +#include "nvs_pagemanager.hpp" +#include "nvs_storage.hpp" + +#endif /* nvs_hpp */ diff --git a/components/nvs_flash/src/nvs_api.cpp b/components/nvs_flash/src/nvs_api.cpp new file mode 100644 index 0000000000..655ed24f87 --- /dev/null +++ b/components/nvs_flash/src/nvs_api.cpp @@ -0,0 +1,278 @@ +// Copyright 2015-2016 Espressif Systems (Shanghai) PTE LTD +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at + +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +#include "nvs.hpp" +#include "nvs_flash.h" +#include "nvs_storage.hpp" +#include "intrusive_list.h" +#include "nvs_platform.hpp" + +class HandleEntry : public intrusive_list_node +{ +public: + HandleEntry(){} + + HandleEntry(nvs_handle handle, bool readOnly, uint8_t nsIndex) : + mHandle(handle), + mReadOnly(readOnly), + mNsIndex(nsIndex) + { + } + + nvs_handle mHandle; + uint8_t mReadOnly; + uint8_t mNsIndex; +}; + +#ifdef ESP_PLATFORM +SemaphoreHandle_t nvs::Lock::mSemaphore = NULL; +#endif + +using namespace std; +using namespace nvs; + +static intrusive_list s_nvs_handles; +static uint32_t s_nvs_next_handle = 1; +static nvs::Storage s_nvs_storage; + +extern "C" esp_err_t nvs_flash_init(uint32_t baseSector, uint32_t sectorCount) +{ + Lock::init(); + Lock lock; + NVS_DEBUGV("%s %d %d\r\n", __func__, baseSector, sectorCount); + return s_nvs_storage.init(baseSector, sectorCount); +} + +static esp_err_t nvs_find_ns_handle(nvs_handle handle, HandleEntry& entry) +{ + auto it = find_if(begin(s_nvs_handles), end(s_nvs_handles), [=](HandleEntry& e) -> bool { + return e.mHandle == handle; + }); + if (it == end(s_nvs_handles)) { + return ESP_ERR_NVS_INVALID_HANDLE; + } + entry = *it; + return ESP_OK; +} + +extern "C" esp_err_t nvs_open(const char* name, nvs_open_mode open_mode, nvs_handle *out_handle) +{ + Lock lock; + NVS_DEBUGV("%s %s %d\r\n", __func__, name, open_mode); + uint8_t nsIndex; + esp_err_t err = s_nvs_storage.createOrOpenNamespace(name, open_mode == NVS_READWRITE, nsIndex); + if (err != ESP_OK) { + return err; + } + + uint32_t handle = s_nvs_next_handle; + ++s_nvs_next_handle; + *out_handle = handle; + + s_nvs_handles.push_back(new HandleEntry(handle, open_mode==NVS_READONLY, nsIndex)); + return ESP_OK; +} + +extern "C" void nvs_close(nvs_handle handle) +{ + Lock lock; + NVS_DEBUGV("%s %d\r\n", __func__, handle); + auto it = find_if(begin(s_nvs_handles), end(s_nvs_handles), [=](HandleEntry& e) -> bool { + return e.mHandle == handle; + }); + if (it == end(s_nvs_handles)) { + return; + } + s_nvs_handles.erase(it); +} + +template +static esp_err_t nvs_set(nvs_handle handle, const char* key, T value) +{ + Lock lock; + NVS_DEBUGV("%s %s %d %d\r\n", __func__, key, sizeof(T), (uint32_t) value); + HandleEntry entry; + auto err = nvs_find_ns_handle(handle, entry); + if (err != ESP_OK) { + return err; + } + if (entry.mReadOnly) { + return ESP_ERR_NVS_READ_ONLY; + } + return s_nvs_storage.writeItem(entry.mNsIndex, key, value); +} + +extern "C" esp_err_t nvs_set_i8 (nvs_handle handle, const char* key, int8_t value) +{ + return nvs_set(handle, key, value); +} + +extern "C" esp_err_t nvs_set_u8 (nvs_handle handle, const char* key, uint8_t value) +{ + return nvs_set(handle, key, value); +} + +extern "C" esp_err_t nvs_set_i16 (nvs_handle handle, const char* key, int16_t value) +{ + return nvs_set(handle, key, value); +} + +extern "C" esp_err_t nvs_set_u16 (nvs_handle handle, const char* key, uint16_t value) +{ + return nvs_set(handle, key, value); +} + +extern "C" esp_err_t nvs_set_i32 (nvs_handle handle, const char* key, int32_t value) +{ + return nvs_set(handle, key, value); +} + +extern "C" esp_err_t nvs_set_u32 (nvs_handle handle, const char* key, uint32_t value) +{ + return nvs_set(handle, key, value); +} + +extern "C" esp_err_t nvs_set_i64 (nvs_handle handle, const char* key, int64_t value) +{ + return nvs_set(handle, key, value); +} + +extern "C" esp_err_t nvs_set_u64 (nvs_handle handle, const char* key, uint64_t value) +{ + return nvs_set(handle, key, value); +} + +extern "C" esp_err_t nvs_commit(nvs_handle handle) +{ + Lock lock; + // no-op for now, to be used when intermediate cache is added + HandleEntry entry; + return nvs_find_ns_handle(handle, entry); +} + +extern "C" esp_err_t nvs_set_str(nvs_handle handle, const char* key, const char* value) +{ + Lock lock; + NVS_DEBUGV("%s %s %s\r\n", __func__, key, value); + HandleEntry entry; + auto err = nvs_find_ns_handle(handle, entry); + if (err != ESP_OK) { + return err; + } + return s_nvs_storage.writeItem(entry.mNsIndex, nvs::ItemType::SZ, key, value, strlen(value) + 1); +} + +extern "C" esp_err_t nvs_set_blob(nvs_handle handle, const char* key, const void* value, size_t length) +{ + Lock lock; + NVS_DEBUGV("%s %s %d\r\n", __func__, key, length); + HandleEntry entry; + auto err = nvs_find_ns_handle(handle, entry); + if (err != ESP_OK) { + return err; + } + return s_nvs_storage.writeItem(entry.mNsIndex, nvs::ItemType::BLOB, key, value, length); +} + + +template +static esp_err_t nvs_get(nvs_handle handle, const char* key, T* out_value) +{ + Lock lock; + NVS_DEBUGV("%s %s %d\r\n", __func__, key, sizeof(T)); + HandleEntry entry; + auto err = nvs_find_ns_handle(handle, entry); + if (err != ESP_OK) { + return err; + } + return s_nvs_storage.readItem(entry.mNsIndex, key, *out_value); +} + +extern "C" esp_err_t nvs_get_i8 (nvs_handle handle, const char* key, int8_t* out_value) +{ + return nvs_get(handle, key, out_value); +} + +extern "C" esp_err_t nvs_get_u8 (nvs_handle handle, const char* key, uint8_t* out_value) +{ + return nvs_get(handle, key, out_value); +} + +extern "C" esp_err_t nvs_get_i16 (nvs_handle handle, const char* key, int16_t* out_value) +{ + return nvs_get(handle, key, out_value); +} + +extern "C" esp_err_t nvs_get_u16 (nvs_handle handle, const char* key, uint16_t* out_value) +{ + return nvs_get(handle, key, out_value); +} + +extern "C" esp_err_t nvs_get_i32 (nvs_handle handle, const char* key, int32_t* out_value) +{ + return nvs_get(handle, key, out_value); +} + +extern "C" esp_err_t nvs_get_u32 (nvs_handle handle, const char* key, uint32_t* out_value) +{ + return nvs_get(handle, key, out_value); +} + +extern "C" esp_err_t nvs_get_i64 (nvs_handle handle, const char* key, int64_t* out_value) +{ + return nvs_get(handle, key, out_value); +} + +extern "C" esp_err_t nvs_get_u64 (nvs_handle handle, const char* key, uint64_t* out_value) +{ + return nvs_get(handle, key, out_value); +} + +static esp_err_t nvs_get_str_or_blob(nvs_handle handle, nvs::ItemType type, const char* key, void* out_value, size_t* length) +{ + Lock lock; + NVS_DEBUGV("%s %s\r\n", __func__, key); + HandleEntry entry; + auto err = nvs_find_ns_handle(handle, entry); + if (err != ESP_OK) { + return err; + } + + size_t dataSize; + err = s_nvs_storage.getItemDataSize(entry.mNsIndex, type, key, dataSize); + if (err != ESP_OK) { + return err; + } + + if (length != nullptr && out_value == nullptr) { + *length = dataSize; + return ESP_OK; + } + + if (length == nullptr || *length < dataSize) { + return ESP_ERR_NVS_INVALID_LENGTH; + } + + return s_nvs_storage.readItem(entry.mNsIndex, type, key, out_value, dataSize); +} + +extern "C" esp_err_t nvs_get_str(nvs_handle handle, const char* key, char* out_value, size_t* length) +{ + return nvs_get_str_or_blob(handle, nvs::ItemType::SZ, key, out_value, length); +} + +extern "C" esp_err_t nvs_get_blob(nvs_handle handle, const char* key, void* out_value, size_t* length) +{ + return nvs_get_str_or_blob(handle, nvs::ItemType::BLOB, key, out_value, length); +} + diff --git a/components/nvs_flash/src/nvs_page.cpp b/components/nvs_flash/src/nvs_page.cpp new file mode 100644 index 0000000000..de325a170c --- /dev/null +++ b/components/nvs_flash/src/nvs_page.cpp @@ -0,0 +1,689 @@ +// Copyright 2015-2016 Espressif Systems (Shanghai) PTE LTD +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at + +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +#include "nvs_page.hpp" +#if defined(ESP_PLATFORM) +#include +#else +#include "crc.h" +#endif + + +namespace nvs +{ + +uint32_t Page::Header::calculateCrc32() +{ + return crc32_le(0xffffffff, + reinterpret_cast(this) + offsetof(Header, mSeqNumber), + offsetof(Header, mCrc32) - offsetof(Header, mSeqNumber)); +} + +esp_err_t Page::load(uint32_t sectorNumber) +{ + mBaseAddress = sectorNumber * SEC_SIZE; + mUsedEntryCount = 0; + mErasedEntryCount = 0; + + Header header; + auto rc = spi_flash_read(mBaseAddress, reinterpret_cast(&header), sizeof(header)); + if (rc != ESP_OK) { + mState = PageState::INVALID; + return rc; + } + if (header.mState == PageState::UNINITIALIZED) { + mState = header.mState; + // check if the whole page is really empty + // reading the whole page takes ~40 times less than erasing it + uint32_t line[8]; + for (uint32_t i = 0; i < SPI_FLASH_SEC_SIZE; i += sizeof(line)) { + rc = spi_flash_read(mBaseAddress + i, line, sizeof(line)); + if (rc != ESP_OK) { + mState = PageState::INVALID; + return rc; + } + if (std::any_of(line, line + 4, [](uint32_t val) -> bool { return val != 0xffffffff; })) { + // page isn't as empty after all, mark it as corrupted + mState = PageState::CORRUPT; + break; + } + } + } + else if (header.mCrc32 != header.calculateCrc32()) { + header.mState = PageState::CORRUPT; + } + else { + mState = header.mState; + mSeqNumber = header.mSeqNumber; + } + + switch (mState) { + case PageState::UNINITIALIZED: + break; + + case PageState::FULL: + case PageState::ACTIVE: + case PageState::FREEING: + mLoadEntryTable(); + break; + + default: + mState = PageState::CORRUPT; + break; + } + + return ESP_OK; +} + +esp_err_t Page::writeEntry(const Item& item) +{ + auto rc = spi_flash_write(getEntryAddress(mNextFreeEntry), reinterpret_cast(&item), sizeof(item)); + if (rc != ESP_OK) { + mState = PageState::INVALID; + return rc; + } + + auto err = alterEntryState(mNextFreeEntry, EntryState::WRITTEN); + if (err != ESP_OK) { + return err; + } + + if (mNextFreeEntry == 0) { + mFirstUsedEntry = 0; + } + + ++mUsedEntryCount; + + if (++mNextFreeEntry == ENTRY_COUNT) { + alterPageState(PageState::FULL); + } + + return ESP_OK; +} + +esp_err_t Page::writeItem(uint8_t nsIndex, ItemType datatype, const char* key, const void* data, size_t dataSize) +{ + Item item; + + esp_err_t err; + if (mState == PageState::UNINITIALIZED) { + err = initialize(); + if (err != ESP_OK) { + return err; + } + } + + if (mState == PageState::FULL) { + return ESP_ERR_NVS_PAGE_FULL; + } + + const size_t keySize = strlen(key); + if (keySize > Item::MAX_KEY_LENGTH) { + return ESP_ERR_NVS_KEY_TOO_LONG; + } + + size_t totalSize = ENTRY_SIZE; + size_t entriesCount = 1; + if (datatype == ItemType::SZ || datatype == ItemType::BLOB) { + size_t roundedSize = (dataSize + ENTRY_SIZE - 1) & ~(ENTRY_SIZE - 1); + totalSize += roundedSize; + entriesCount += roundedSize / ENTRY_SIZE; + } + + // primitive types should fit into one entry + assert(totalSize == ENTRY_SIZE || datatype == ItemType::BLOB || datatype == ItemType::SZ); + + if (mNextFreeEntry + entriesCount > ENTRY_COUNT) { + // page will not fit this amount of data + return ESP_ERR_NVS_PAGE_FULL; + } + + // write first item + + item.nsIndex = nsIndex; + item.datatype = datatype; + item.span = (totalSize + ENTRY_SIZE - 1) / ENTRY_SIZE; + item.reserved = 0xff; + + std::fill_n(reinterpret_cast(item.key), sizeof(item.key) / 4, 0xffffffff); + std::fill_n(reinterpret_cast(item.data), sizeof(item.data) / 4, 0xffffffff); + + strlcpy(item.key, key, Item::MAX_KEY_LENGTH + 1); + + + if (datatype != ItemType::SZ && datatype != ItemType::BLOB) { + memcpy(item.data, data, dataSize); + item.crc32 = item.calculateCrc32(); + err = writeEntry(item); + if (err != ESP_OK) { + return err; + } + } else { + const uint8_t* src = reinterpret_cast(data); + item.varLength.dataCrc32 = Item::calculateCrc32(src, dataSize); + item.varLength.dataSize = dataSize; + item.varLength.reserved2 = 0xffff; + item.crc32 = item.calculateCrc32(); + err = writeEntry(item); + if (err != ESP_OK) { + return err; + } + + size_t left = dataSize; + while (left != 0) { + size_t willWrite = Page::ENTRY_SIZE; + willWrite = (left < willWrite)?left:willWrite; + memcpy(item.rawData, src, willWrite); + src += willWrite; + left -= willWrite; + err = writeEntry(item); + if (err != ESP_OK) { + return err; + } + } + } + return ESP_OK; +} + +esp_err_t Page::readItem(uint8_t nsIndex, ItemType datatype, const char* key, void* data, size_t dataSize) +{ + size_t index = 0; + Item item; + esp_err_t rc = findItem(nsIndex, datatype, key, index, item); + if (rc != ESP_OK) { + return rc; + } + + if (datatype != ItemType::SZ && datatype != ItemType::BLOB) { + if (dataSize != getAlignmentForType(datatype)) { + return ESP_ERR_NVS_TYPE_MISMATCH; + } + + memcpy(data, item.data, dataSize); + return ESP_OK; + } + + if (dataSize < static_cast(item.varLength.dataSize)) { + return ESP_ERR_NVS_INVALID_LENGTH; + } + + uint8_t* dst = reinterpret_cast(data); + size_t left = item.varLength.dataSize; + for (size_t i = index + 1; i < index + item.span; ++i) { + Item ditem; + rc = readEntry(i, ditem); + if (rc != ESP_OK) { + return rc; + } + size_t willCopy = ENTRY_SIZE; + willCopy = (left < willCopy)?left:willCopy; + memcpy(dst, ditem.rawData, willCopy); + left -= willCopy; + dst += willCopy; + } + if (Item::calculateCrc32(reinterpret_cast(data), item.varLength.dataSize) != item.varLength.dataCrc32) { + rc = eraseEntryAndSpan(index); + if (rc != ESP_OK) { + return rc; + } + return ESP_ERR_NVS_NOT_FOUND; + } + return ESP_OK; +} + +esp_err_t Page::eraseItem(uint8_t nsIndex, ItemType datatype, const char* key) +{ + size_t index = 0; + Item item; + esp_err_t rc = findItem(nsIndex, datatype, key, index, item); + if (rc != ESP_OK) { + return rc; + } + if (CachedFindInfo(nsIndex, datatype, key) == mFindInfo) { + invalidateCache(); + } + return eraseEntryAndSpan(index); +} + +esp_err_t Page::findItem(uint8_t nsIndex, ItemType datatype, const char* key) +{ + size_t index = 0; + Item item; + return findItem(nsIndex, datatype, key, index, item); +} + +esp_err_t Page::eraseEntry(size_t index) +{ + auto state = mEntryTable.get(index); + assert(state == EntryState::WRITTEN || state == EntryState::EMPTY); + + auto rc = alterEntryState(index, EntryState::ERASED); + if (rc != ESP_OK) { + return rc; + } + + return ESP_OK; +} + +esp_err_t Page::eraseEntryAndSpan(size_t index) +{ + auto state = mEntryTable.get(index); + assert(state == EntryState::WRITTEN || state == EntryState::EMPTY); + + size_t span = 1; + if (state == EntryState::WRITTEN) { + Item item; + auto rc = readEntry(index, item); + if (rc != ESP_OK) { + return rc; + } + if (item.calculateCrc32() != item.crc32) { + rc = alterEntryState(index, EntryState::ERASED); + if (rc != ESP_OK) { + return rc; + } + } else { + span = item.span; + for (ptrdiff_t i = index + span - 1; i >= static_cast(index); --i) { + rc = alterEntryState(i, EntryState::ERASED); + if (rc != ESP_OK) { + return rc; + } + } + } + } + else { + auto rc = alterEntryState(index, EntryState::ERASED); + if (rc != ESP_OK) { + return rc; + } + } + + if (index == mFirstUsedEntry) { + updateFirstUsedEntry(index, span); + } + + mErasedEntryCount += span; + mUsedEntryCount -= span; + + return ESP_OK; +} + +void Page::updateFirstUsedEntry(size_t index, size_t span) +{ + assert(index == mFirstUsedEntry); + mFirstUsedEntry = INVALID_ENTRY; + for (size_t i = index + span; i < mNextFreeEntry; ++i) { + if (mEntryTable.get(i) == EntryState::WRITTEN) { + mFirstUsedEntry = i; + break; + } + } +} + +esp_err_t Page::moveItem(Page& other) +{ + if (mFirstUsedEntry == INVALID_ENTRY) { + return ESP_ERR_NVS_NOT_FOUND; + } + + if (mFindInfo.itemIndex() == mFirstUsedEntry) { + invalidateCache(); + } + + if (other.mState == PageState::UNINITIALIZED) { + auto err = other.initialize(); + if (err != ESP_OK) { + return err; + } + } + + Item entry; + auto err = readEntry(mFirstUsedEntry, entry); + if (err != ESP_OK) { + return err; + } + err = other.writeEntry(entry); + if (err != ESP_OK) { + return err; + } + err = eraseEntry(mFirstUsedEntry); + if (err != ESP_OK) { + return err; + } + + size_t span = entry.span; + size_t end = mFirstUsedEntry + span; + + assert(mFirstUsedEntry != INVALID_ENTRY || span == 1); + + for (size_t i = mFirstUsedEntry + 1; i < end; ++i) { + readEntry(i, entry); + err = other.writeEntry(entry); + if (err != ESP_OK) { + return err; + } + err = eraseEntry(i); + if (err != ESP_OK) { + return err; + } + } + updateFirstUsedEntry(mFirstUsedEntry, span); + mErasedEntryCount += span; + mUsedEntryCount -= span; + + return ESP_OK; +} + +esp_err_t Page::mLoadEntryTable() +{ + // for states where we actually care about data in the page, read entry state table + if (mState == PageState::ACTIVE || + mState == PageState::FULL || + mState == PageState::FREEING) { + auto rc = spi_flash_read(mBaseAddress + ENTRY_TABLE_OFFSET, mEntryTable.data(), + static_cast(mEntryTable.byteSize())); + if (rc != ESP_OK) { + mState = PageState::INVALID; + return rc; + } + } + + mErasedEntryCount = 0; + mUsedEntryCount = 0; + for (size_t i = 0; i < ENTRY_COUNT; ++i) { + auto s = mEntryTable.get(i); + if (s == EntryState::WRITTEN) { + if (mFirstUsedEntry == INVALID_ENTRY) { + mFirstUsedEntry = i; + } + ++mUsedEntryCount; + } else if (s == EntryState::ERASED) { + ++mErasedEntryCount; + } + } + + // for PageState::ACTIVE, we may have more data written to this page + // as such, we need to figure out where the first unused entry is + if (mState == PageState::ACTIVE) { + for (size_t i = 0; i < ENTRY_COUNT; ++i) { + if (mEntryTable.get(i) == EntryState::EMPTY) { + mNextFreeEntry = i; + break; + } + } + + // however, if power failed after some data was written into the entry. + // but before the entry state table was altered, the entry locacted via + // entry state table may actually be half-written. + // this is easy to check by reading EntryHeader (i.e. first word) + uint32_t entryAddress = mBaseAddress + ENTRY_DATA_OFFSET + + static_cast(mNextFreeEntry) * ENTRY_SIZE; + uint32_t header; + auto rc = spi_flash_read(entryAddress, &header, sizeof(header)); + if (rc != ESP_OK) { + mState = PageState::INVALID; + return rc; + } + if (header != 0xffffffff) { + auto err = alterEntryState(mNextFreeEntry, EntryState::ERASED); + if (err != ESP_OK) { + mState = PageState::INVALID; + return err; + } + ++mNextFreeEntry; + } + + // check that all variable-length items are written or erased fully + for (size_t i = 0; i < mNextFreeEntry; ++i) { + if (mEntryTable.get(i) == EntryState::ERASED) { + continue; + } + + Item item; + auto err = readEntry(i, item); + if (err != ESP_OK) { + mState = PageState::INVALID; + return err; + } + + if (item.crc32 != item.calculateCrc32()) { + err = eraseEntryAndSpan(i); + if (err != ESP_OK) { + mState = PageState::INVALID; + return err; + } + continue; + } + + if (item.datatype != ItemType::BLOB && item.datatype != ItemType::SZ) { + continue; + } + + size_t span = item.span; + bool needErase = false; + for (size_t j = i; j < i + span; ++j) { + if (mEntryTable.get(j) != EntryState::WRITTEN) { + needErase = true; + break; + } + } + if (needErase) { + eraseEntryAndSpan(i); + } + i += span - 1; + } + + } + + return ESP_OK; +} + + +esp_err_t Page::initialize() +{ + assert(mState == PageState::UNINITIALIZED); + mState = PageState::ACTIVE; + Header header; + header.mState = mState; + header.mSeqNumber = mSeqNumber; + header.mCrc32 = header.calculateCrc32(); + + auto rc = spi_flash_write(mBaseAddress, reinterpret_cast(&header), sizeof(header)); + if (rc != ESP_OK) { + mState = PageState::INVALID; + return rc; + } + + mNextFreeEntry = 0; + std::fill_n(mEntryTable.data(), mEntryTable.byteSize() / sizeof(uint32_t), 0xffffffff); + invalidateCache(); + return ESP_OK; +} + +esp_err_t Page::alterEntryState(size_t index, EntryState state) +{ + assert(index < ENTRY_COUNT); + mEntryTable.set(index, state); + size_t wordToWrite = mEntryTable.getWordIndex(index); + uint32_t word = mEntryTable.data()[wordToWrite]; + auto rc = spi_flash_write(mBaseAddress + ENTRY_TABLE_OFFSET + static_cast(wordToWrite) * 4, &word, 4); + if (rc != ESP_OK) { + mState = PageState::INVALID; + return rc; + } + return ESP_OK; +} + +esp_err_t Page::alterPageState(PageState state) +{ + auto rc = spi_flash_write(mBaseAddress, reinterpret_cast(&state), sizeof(state)); + if (rc != ESP_OK) { + mState = PageState::INVALID; + return rc; + } + mState = (PageState) state; + return ESP_OK; +} + +esp_err_t Page::readEntry(size_t index, Item& dst) +{ + auto rc = spi_flash_read(getEntryAddress(index), reinterpret_cast(&dst), sizeof(dst)); + if (rc != ESP_OK) { + return rc; + } + return ESP_OK; +} + +esp_err_t Page::findItem(uint8_t nsIndex, ItemType datatype, const char* key, size_t &itemIndex, Item& item) +{ + if (mState == PageState::CORRUPT || mState == PageState::INVALID || mState == PageState::UNINITIALIZED) { + return ESP_ERR_NVS_NOT_FOUND; + } + + CachedFindInfo findInfo(nsIndex, datatype, key); + if (mFindInfo == findInfo) { + itemIndex = mFindInfo.itemIndex(); + } + + size_t start = mFirstUsedEntry; + if (itemIndex > mFirstUsedEntry && itemIndex < ENTRY_COUNT) { + start = itemIndex; + } + + size_t next; + for (size_t i = start; i < mNextFreeEntry; i = next) { + next = i + 1; + if (mEntryTable.get(i) != EntryState::WRITTEN) { + continue; + } + + auto rc = readEntry(i, item); + if (rc != ESP_OK) { + mState = PageState::INVALID; + return rc; + } + + auto crc32 = item.calculateCrc32(); + if (item.crc32 != crc32) { + eraseEntryAndSpan(i); + continue; + } + + if (item.datatype == ItemType::BLOB || item.datatype == ItemType::SZ) { + next = i + item.span; + } + + if (nsIndex != NS_ANY && item.nsIndex != nsIndex) { + continue; + } + + if (key != nullptr && strncmp(key, item.key, Item::MAX_KEY_LENGTH) != 0) { + continue; + } + + if (datatype != ItemType::ANY && item.datatype != datatype) { + return ESP_ERR_NVS_TYPE_MISMATCH; + } + + itemIndex = i; + findInfo.setItemIndex(static_cast(itemIndex)); + mFindInfo = findInfo; + + return ESP_OK; + } + + return ESP_ERR_NVS_NOT_FOUND; +} + +esp_err_t Page::getSeqNumber(uint32_t& seqNumber) const +{ + if (mState != PageState::UNINITIALIZED && mState != PageState::INVALID && mState != PageState::CORRUPT) { + seqNumber = mSeqNumber; + return ESP_OK; + } + return ESP_ERR_NVS_NOT_INITIALIZED; +} + + +esp_err_t Page::setSeqNumber(uint32_t seqNumber) +{ + if (mState != PageState::UNINITIALIZED) { + return ESP_ERR_NVS_INVALID_STATE; + } + mSeqNumber = seqNumber; + return ESP_OK; +} + +esp_err_t Page::erase() +{ + auto sector = mBaseAddress / SPI_FLASH_SEC_SIZE; + auto rc = spi_flash_erase_sector(sector); + if (rc != ESP_OK) { + mState = PageState::INVALID; + return rc; + } + return load(sector); +} + +esp_err_t Page::markFreeing() +{ + if (mState != PageState::FULL && mState != PageState::ACTIVE) { + return ESP_ERR_NVS_INVALID_STATE; + } + return alterPageState(PageState::FREEING); +} + +esp_err_t Page::markFull() +{ + if (mState != PageState::ACTIVE) { + return ESP_ERR_NVS_INVALID_STATE; + } + return alterPageState(PageState::FULL); +} + + +void Page::invalidateCache() +{ + mFindInfo = CachedFindInfo(); +} + +void Page::debugDump() +{ + printf("state=%x addr=%x seq=%d\nfirstUsed=%d nextFree=%d used=%d erased=%d\n", mState, mBaseAddress, mSeqNumber, static_cast(mFirstUsedEntry), static_cast(mNextFreeEntry), mUsedEntryCount, mErasedEntryCount); + size_t skip = 0; + for (size_t i = 0; i < ENTRY_COUNT; ++i) { + printf("%3d: ", static_cast(i)); + EntryState state = mEntryTable.get(i); + if (state == EntryState::EMPTY) { + printf("E\n"); + } + else if (state == EntryState::ERASED) { + printf("X\n"); + } + else if (state == EntryState::WRITTEN) { + Item item; + readEntry(i, item); + if (skip == 0) { + printf("W ns=%2u type=%2u span=%3u key=\"%s\"\n", item.nsIndex, static_cast(item.datatype), item.span, item.key); + skip = item.span - 1; + } + else { + printf("D\n"); + skip--; + } + } + } +} + +} // namespace nvs diff --git a/components/nvs_flash/src/nvs_page.hpp b/components/nvs_flash/src/nvs_page.hpp new file mode 100644 index 0000000000..f0c69c4246 --- /dev/null +++ b/components/nvs_flash/src/nvs_page.hpp @@ -0,0 +1,246 @@ +// Copyright 2015-2016 Espressif Systems (Shanghai) PTE LTD +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at + +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +#ifndef nvs_page_hpp +#define nvs_page_hpp + +#include "nvs.h" +#include "nvs_types.hpp" +#include +#include +#include +#include +#include "esp_spi_flash.h" +#include "compressed_enum_table.hpp" +#include "intrusive_list.h" + +namespace nvs +{ + +class CachedFindInfo +{ +public: + CachedFindInfo() { } + CachedFindInfo(uint8_t nsIndex, ItemType type, const char* key) : + mKeyPtr(key), + mNsIndex(nsIndex), + mType(type) + { + } + + bool operator==(const CachedFindInfo& other) const + { + return mKeyPtr == other.mKeyPtr && mType == other.mType && mNsIndex == other.mNsIndex; + } + + void setItemIndex(uint32_t index) + { + mItemIndex = index; + } + uint32_t itemIndex() const + { + return mItemIndex; + } + +protected: + uint32_t mItemIndex = 0; + const char* mKeyPtr = nullptr; + uint8_t mNsIndex = 0; + ItemType mType; + +}; + +class Page : public intrusive_list_node +{ +public: + static const uint32_t PSB_INIT = 0x1; + static const uint32_t PSB_FULL = 0x2; + static const uint32_t PSB_FREEING = 0x4; + static const uint32_t PSB_CORRUPT = 0x8; + + static const uint32_t ESB_WRITTEN = 0x1; + static const uint32_t ESB_ERASED = 0x2; + + static const uint32_t SEC_SIZE = SPI_FLASH_SEC_SIZE; + + static const size_t ENTRY_SIZE = 32; + static const size_t ENTRY_COUNT = 126; + static const uint32_t INVALID_ENTRY = 0xffffffff; + + static const uint8_t NS_INDEX = 0; + static const uint8_t NS_ANY = 255; + + enum class PageState : uint32_t { + // All bits set, default state after flash erase. Page has not been initialized yet. + UNINITIALIZED = 0xffffffff, + + // Page is initialized, and will accept writes. + ACTIVE = UNINITIALIZED & ~PSB_INIT, + + // Page is marked as full and will not accept new writes. + FULL = ACTIVE & ~PSB_FULL, + + // Data is being moved from this page to a new one. + FREEING = FULL & ~PSB_FREEING, + + // Page was found to be in a corrupt and unrecoverable state. + // Instead of being erased immediately, it will be kept for diagnostics and data recovery. + // It will be erased once we run out out free pages. + CORRUPT = FREEING & ~PSB_CORRUPT, + + // Page object wasn't loaded from flash memory + INVALID = 0 + }; + + PageState state() const + { + return mState; + } + + esp_err_t load(uint32_t sectorNumber); + + esp_err_t getSeqNumber(uint32_t& seqNumber) const; + + esp_err_t setSeqNumber(uint32_t seqNumber); + + esp_err_t writeItem(uint8_t nsIndex, ItemType datatype, const char* key, const void* data, size_t dataSize); + + esp_err_t readItem(uint8_t nsIndex, ItemType datatype, const char* key, void* data, size_t dataSize); + + esp_err_t eraseItem(uint8_t nsIndex, ItemType datatype, const char* key); + + esp_err_t findItem(uint8_t nsIndex, ItemType datatype, const char* key); + + esp_err_t findItem(uint8_t nsIndex, ItemType datatype, const char* key, size_t &itemIndex, Item& item); + + template + esp_err_t writeItem(uint8_t nsIndex, const char* key, const T& value) + { + return writeItem(nsIndex, itemTypeOf(value), key, &value, sizeof(value)); + } + + template + esp_err_t readItem(uint8_t nsIndex, const char* key, T& value) + { + return readItem(nsIndex, itemTypeOf(value), key, &value, sizeof(value)); + } + + template + esp_err_t eraseItem(uint8_t nsIndex, const char* key) + { + return eraseItem(nsIndex, itemTypeOf(), key); + } + + size_t getUsedEntryCount() const + { + return mUsedEntryCount; + } + + size_t getErasedEntryCount() const + { + return mErasedEntryCount; + } + + + esp_err_t markFull(); + + esp_err_t markFreeing(); + + esp_err_t moveItem(Page& other); + + esp_err_t erase(); + + void invalidateCache(); + + void debugDump(); + +protected: + + class Header { + public: + Header() { + std::fill_n(mReserved, sizeof(mReserved)/sizeof(mReserved[0]), UINT32_MAX); + } + + PageState mState; // page state + uint32_t mSeqNumber; // sequence number of this page + uint32_t mReserved[5]; // unused, must be 0xffffffff + uint32_t mCrc32; // crc of everything except mState + + uint32_t calculateCrc32(); + }; + + enum class EntryState { + EMPTY = 0x3, // 0b11, default state after flash erase + WRITTEN = EMPTY & ~ESB_WRITTEN, // entry was written + ERASED = WRITTEN & ~ESB_ERASED, // entry was written and then erased + INVALID = 0x4 // entry is in inconsistent state (write started but ESB_WRITTEN has not been set yet) + }; + + esp_err_t mLoadEntryTable(); + + esp_err_t initialize(); + + esp_err_t alterEntryState(size_t index, EntryState state); + + esp_err_t alterPageState(PageState state); + + esp_err_t readEntry(size_t index, Item& dst); + + esp_err_t writeEntry(const Item& item); + + esp_err_t eraseEntry(size_t index); + + esp_err_t eraseEntryAndSpan(size_t index); + + void updateFirstUsedEntry(size_t index, size_t span); + + static constexpr size_t getAlignmentForType(ItemType type) + { + return static_cast(type) & 0x0f; + } + + uint32_t getEntryAddress(size_t entry) + { + assert(entry < ENTRY_COUNT); + return mBaseAddress + ENTRY_DATA_OFFSET + static_cast(entry) * ENTRY_SIZE; + } + + +protected: + uint32_t mBaseAddress = 0; + PageState mState = PageState::INVALID; + uint32_t mSeqNumber = UINT32_MAX; + typedef CompressedEnumTable TEntryTable; + TEntryTable mEntryTable; + size_t mNextFreeEntry = INVALID_ENTRY; + size_t mFirstUsedEntry = INVALID_ENTRY; + uint16_t mUsedEntryCount = 0; + uint16_t mErasedEntryCount = 0; + + CachedFindInfo mFindInfo; + + static const uint32_t HEADER_OFFSET = 0; + static const uint32_t ENTRY_TABLE_OFFSET = HEADER_OFFSET + 32; + static const uint32_t ENTRY_DATA_OFFSET = ENTRY_TABLE_OFFSET + 32; + + static_assert(sizeof(Header) == 32, "header size must be 32 bytes"); + static_assert(ENTRY_TABLE_OFFSET % 32 == 0, "entry table offset should be aligned"); + static_assert(ENTRY_DATA_OFFSET % 32 == 0, "entry data offset should be aligned"); + +}; // class Page + +} // namespace nvs + + +#endif /* nvs_page_hpp */ diff --git a/components/nvs_flash/src/nvs_pagemanager.cpp b/components/nvs_flash/src/nvs_pagemanager.cpp new file mode 100644 index 0000000000..8fd62430d5 --- /dev/null +++ b/components/nvs_flash/src/nvs_pagemanager.cpp @@ -0,0 +1,137 @@ +// Copyright 2015-2016 Espressif Systems (Shanghai) PTE LTD +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at + +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +#include "nvs_pagemanager.hpp" + +namespace nvs +{ +esp_err_t PageManager::load(uint32_t baseSector, uint32_t sectorCount) +{ + mBaseSector = baseSector; + mPageCount = sectorCount; + mPageList.clear(); + mFreePageList.clear(); + mPages.reset(new Page[sectorCount]); + + for (uint32_t i = 0; i < sectorCount; ++i) { + auto err = mPages[i].load(baseSector + i); + if (err != ESP_OK) { + return err; + } + uint32_t seqNumber; + if (mPages[i].getSeqNumber(seqNumber) != ESP_OK) { + mFreePageList.push_back(&mPages[i]); + } else { + auto pos = std::find_if(std::begin(mPageList), std::end(mPageList), [=](const Page& page) -> bool { + uint32_t otherSeqNumber; + return page.getSeqNumber(otherSeqNumber) == ESP_OK && otherSeqNumber > seqNumber; + }); + if (pos == mPageList.end()) { + mPageList.push_back(&mPages[i]); + } else { + mPageList.insert(pos, &mPages[i]); + } + } + } + + if (mPageList.empty()) { + mSeqNumber = 0; + return activatePage(); + } + else { + uint32_t lastSeqNo; + assert(mPageList.back().getSeqNumber(lastSeqNo) == ESP_OK); + mSeqNumber = lastSeqNo + 1; + } + + return ESP_OK; +} + +esp_err_t PageManager::requestNewPage() +{ + if (mFreePageList.empty()) { + return ESP_ERR_NVS_INVALID_STATE; + } + + // do we have at least two free pages? in that case no erasing is required + if (mFreePageList.size() >= 2) { + return activatePage(); + } + + // find the page with the higest number of erased items + TPageListIterator maxErasedItemsPageIt; + size_t maxErasedItems = 0; + for (auto it = begin(); it != end(); ++it) { + auto erased = it->getErasedEntryCount(); + if (erased > maxErasedItems) { + maxErasedItemsPageIt = it; + maxErasedItems = erased; + } + } + + if (maxErasedItems == 0) { + return ESP_ERR_NVS_NOT_ENOUGH_SPACE; + } + + esp_err_t err = activatePage(); + if (err != ESP_OK) { + return err; + } + + Page* newPage = &mPageList.back(); + + Page* erasedPage = maxErasedItemsPageIt; + err = erasedPage->markFreeing(); + if (err != ESP_OK) { + return err; + } + while (true) { + err = erasedPage->moveItem(*newPage); + if (err == ESP_ERR_NVS_NOT_FOUND) { + break; + } else if (err != ESP_OK) { + return err; + } + } + + err = erasedPage->erase(); + if (err != ESP_OK) { + return err; + } + + mPageList.erase(maxErasedItemsPageIt); + mFreePageList.push_back(erasedPage); + + return ESP_OK; +} + +esp_err_t PageManager::activatePage() +{ + if (mFreePageList.empty()) { + return ESP_ERR_NVS_NOT_ENOUGH_SPACE; + } + Page* p = &mFreePageList.front(); + if (p->state() == Page::PageState::CORRUPT) { + auto err = p->erase(); + if (err != ESP_OK) { + return err; + } + } + mFreePageList.pop_front(); + mPageList.push_back(p); + p->setSeqNumber(mSeqNumber); + ++mSeqNumber; + return ESP_OK; +} + +} // namespace nvs diff --git a/components/nvs_flash/src/nvs_pagemanager.hpp b/components/nvs_flash/src/nvs_pagemanager.hpp new file mode 100644 index 0000000000..3484e70a18 --- /dev/null +++ b/components/nvs_flash/src/nvs_pagemanager.hpp @@ -0,0 +1,70 @@ +// Copyright 2015-2016 Espressif Systems (Shanghai) PTE LTD +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at + +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +#ifndef nvs_pagemanager_hpp +#define nvs_pagemanager_hpp + +#include +#include +#include "nvs_types.hpp" +#include "nvs_page.hpp" +#include "nvs_pagemanager.hpp" +#include "intrusive_list.h" + +namespace nvs +{ +class PageManager +{ + using TPageList = intrusive_list; + using TPageListIterator = TPageList::iterator; +public: + + PageManager() {} + + esp_err_t load(uint32_t baseSector, uint32_t sectorCount); + + TPageListIterator begin() + { + return mPageList.begin(); + } + + TPageListIterator end() + { + return mPageList.end(); + } + + Page& back() + { + return mPageList.back(); + } + + esp_err_t requestNewPage(); + +protected: + friend class Iterator; + + esp_err_t activatePage(); + + TPageList mPageList; + TPageList mFreePageList; + std::unique_ptr mPages; + uint32_t mBaseSector; + uint32_t mPageCount; + uint32_t mSeqNumber; +}; // class PageManager + + +} // namespace nvs + + +#endif /* nvs_pagemanager_hpp */ diff --git a/components/nvs_flash/src/nvs_platform.hpp b/components/nvs_flash/src/nvs_platform.hpp new file mode 100644 index 0000000000..d0bcae90cf --- /dev/null +++ b/components/nvs_flash/src/nvs_platform.hpp @@ -0,0 +1,84 @@ +// Copyright 2015-2016 Espressif Systems (Shanghai) PTE LTD +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at + +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +#ifndef nvs_platform_h +#define nvs_platform_h + + +#ifdef ESP_PLATFORM +#define NVS_DEBUGV(...) ets_printf(__VA_ARGS__) + +#include "rom/ets_sys.h" +#include "freertos/FreeRTOS.h" +#include "freertos/semphr.h" + +namespace nvs +{ + +class Lock +{ +public: + Lock() + { + assert(mSemaphore); + xSemaphoreTake(mSemaphore, portMAX_DELAY); + } + + ~Lock() + { + assert(mSemaphore); + xSemaphoreGive(mSemaphore); + } + + static esp_err_t init() + { + assert(mSemaphore == nullptr); + mSemaphore = xSemaphoreCreateMutex(); + if (!mSemaphore) { + return ESP_ERR_NO_MEM; + } + return ESP_OK; + } + + static void uninit() + { + vSemaphoreDelete(mSemaphore); + mSemaphore = nullptr; + } + + static SemaphoreHandle_t mSemaphore; +}; +} // namespace nvs + +#else // ESP_PLATFORM +#define NVS_DEBUGV(...) printf(__VA_ARGS__) +namespace nvs +{ +class Lock +{ +public: + Lock() { } + ~Lock() { } + static void init() {} + static void uninit() {} +}; +} // namespace nvs +#endif // ESP_PLATFORM + +#ifndef CONFIG_NVS_DEBUG +#undef NVS_DEBUGV +#define NVS_DEBUGV(...) +#endif + + +#endif /* nvs_platform_h */ diff --git a/components/nvs_flash/src/nvs_storage.cpp b/components/nvs_flash/src/nvs_storage.cpp new file mode 100644 index 0000000000..510c52407a --- /dev/null +++ b/components/nvs_flash/src/nvs_storage.cpp @@ -0,0 +1,195 @@ +// Copyright 2015-2016 Espressif Systems (Shanghai) PTE LTD +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at + +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +#include "nvs_storage.hpp" + +namespace nvs +{ + +Storage::~Storage() +{ + clearNamespaces(); +} + +void Storage::clearNamespaces() +{ + for (auto it = std::begin(mNamespaces); it != std::end(mNamespaces); ) { + auto tmp = it; + ++it; + mNamespaces.erase(tmp); + delete static_cast(tmp); + } +} + +esp_err_t Storage::init(uint32_t baseSector, uint32_t sectorCount) +{ + auto err = mPageManager.load(baseSector, sectorCount); + if (err != ESP_OK) { + mState = StorageState::INVALID; + return err; + } + + clearNamespaces(); + std::fill_n(mNamespaceUsage.data(), mNamespaceUsage.byteSize() / 4, 0); + for (auto it = mPageManager.begin(); it != mPageManager.end(); ++it) { + Page& p = *it; + size_t itemIndex = 0; + Item item; + while(p.findItem(Page::NS_INDEX, ItemType::U8, nullptr, itemIndex, item) == ESP_OK) { + NamespaceEntry* entry = new NamespaceEntry; + item.getKey(entry->mName, sizeof(entry->mName) - 1); + item.getValue(entry->mIndex); + mNamespaces.push_back(entry); + mNamespaceUsage.set(entry->mIndex, true); + } + } + mNamespaceUsage.set(0, true); + mNamespaceUsage.set(255, true); + mState = StorageState::ACTIVE; + return ESP_OK; +} + +esp_err_t Storage::writeItem(uint8_t nsIndex, ItemType datatype, const char* key, const void* data, size_t dataSize) +{ + if (mState != StorageState::ACTIVE) { + return ESP_ERR_NVS_NOT_INITIALIZED; + } + + Page* findPage = nullptr; + Item item; + auto err = findItem(nsIndex, datatype, key, findPage, item); + if (err != ESP_OK && err != ESP_ERR_NVS_NOT_FOUND) { + return err; + } + + Page& page = getCurrentPage(); + err = page.writeItem(nsIndex, datatype, key, data, dataSize); + if (err == ESP_ERR_NVS_PAGE_FULL) { + page.markFull(); + err = mPageManager.requestNewPage(); + if (err != ESP_OK) { + return err; + } + + err = getCurrentPage().writeItem(nsIndex, datatype, key, data, dataSize); + if (err != ESP_OK) { + return err; + } + } + + if (findPage) { + if (findPage->state() == Page::PageState::UNINITIALIZED) { + auto err = findItem(nsIndex, datatype, key, findPage, item); + assert(err == ESP_OK); + } + err = findPage->eraseItem(nsIndex, datatype, key); + if (err != ESP_OK) { + return err; + } + } + + return ESP_OK; +} + +esp_err_t Storage::createOrOpenNamespace(const char* nsName, bool canCreate, uint8_t& nsIndex) +{ + if (mState != StorageState::ACTIVE) { + return ESP_ERR_NVS_NOT_INITIALIZED; + } + auto it = std::find_if(mNamespaces.begin(), mNamespaces.end(), [=] (const NamespaceEntry& e) -> bool { + return strncmp(nsName, e.mName, sizeof(e.mName) - 1) == 0; + }); + if (it == std::end(mNamespaces)) { + if (!canCreate) { + return ESP_ERR_NVS_NOT_FOUND; + } + + uint8_t ns; + for (ns = 1; ns < 255; ++ns) { + if (mNamespaceUsage.get(ns) == false) { + break; + } + } + + if (ns == 255) { + return ESP_ERR_NVS_NOT_ENOUGH_SPACE; + } + + auto err = writeItem(Page::NS_INDEX, ItemType::U8, nsName, &ns, sizeof(ns)); + if (err != ESP_OK) { + return err; + } + mNamespaceUsage.set(ns, true); + nsIndex = ns; + + NamespaceEntry* entry = new NamespaceEntry; + entry->mIndex = ns; + strlcpy(entry->mName, nsName, sizeof(entry->mName)); + mNamespaces.push_back(entry); + + } else { + nsIndex = it->mIndex; + } + return ESP_OK; +} + +esp_err_t Storage::readItem(uint8_t nsIndex, ItemType datatype, const char* key, void* data, size_t dataSize) +{ + if (mState != StorageState::ACTIVE) { + return ESP_ERR_NVS_NOT_INITIALIZED; + } + + Item item; + Page* findPage = nullptr; + auto err = findItem(nsIndex, datatype, key, findPage, item); + if (err != ESP_OK) { + return err; + } + + return findPage->readItem(nsIndex, datatype, key, data, dataSize); +} + +esp_err_t Storage::eraseItem(uint8_t nsIndex, ItemType datatype, const char* key) +{ + if (mState != StorageState::ACTIVE) { + return ESP_ERR_NVS_NOT_INITIALIZED; + } + + Item item; + Page* findPage = nullptr; + auto err = findItem(nsIndex, datatype, key, findPage, item); + if (err != ESP_OK) { + return err; + } + + return findPage->eraseItem(nsIndex, datatype, key); +} + +esp_err_t Storage::getItemDataSize(uint8_t nsIndex, ItemType datatype, const char* key, size_t& dataSize) +{ + if (mState != StorageState::ACTIVE) { + return ESP_ERR_NVS_NOT_INITIALIZED; + } + + Item item; + Page* findPage = nullptr; + auto err = findItem(nsIndex, datatype, key, findPage, item); + if (err != ESP_OK) { + return err; + } + + dataSize = item.varLength.dataSize; + return ESP_OK; +} + +} \ No newline at end of file diff --git a/components/nvs_flash/src/nvs_storage.hpp b/components/nvs_flash/src/nvs_storage.hpp new file mode 100644 index 0000000000..d61b219b26 --- /dev/null +++ b/components/nvs_flash/src/nvs_storage.hpp @@ -0,0 +1,114 @@ +// Copyright 2015-2016 Espressif Systems (Shanghai) PTE LTD +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at + +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +#ifndef nvs_storage_hpp +#define nvs_storage_hpp + +#include +#include +#include +#include "nvs.hpp" +#include "nvs_types.hpp" +#include "nvs_page.hpp" +#include "nvs_pagemanager.hpp" + +//extern void dumpBytes(const uint8_t* data, size_t count); + +namespace nvs +{ + +class Storage +{ + enum class StorageState : uint32_t { + INVALID, + ACTIVE, + }; + + struct NamespaceEntry : public intrusive_list_node { + public: + char mName[Item::MAX_KEY_LENGTH + 1]; + uint8_t mIndex; + }; + + typedef intrusive_list TNamespaces; + +public: + ~Storage(); + + esp_err_t init(uint32_t baseSector, uint32_t sectorCount); + + esp_err_t createOrOpenNamespace(const char* nsName, bool canCreate, uint8_t& nsIndex); + + esp_err_t writeItem(uint8_t nsIndex, ItemType datatype, const char* key, const void* data, size_t dataSize); + + esp_err_t readItem(uint8_t nsIndex, ItemType datatype, const char* key, void* data, size_t dataSize); + + esp_err_t getItemDataSize(uint8_t nsIndex, ItemType datatype, const char* key, size_t& dataSize); + + esp_err_t eraseItem(uint8_t nsIndex, ItemType datatype, const char* key); + + template + esp_err_t writeItem(uint8_t nsIndex, const char* key, const T& value) + { + return writeItem(nsIndex, itemTypeOf(value), key, &value, sizeof(value)); + } + + template + esp_err_t readItem(uint8_t nsIndex, const char* key, T& value) + { + return readItem(nsIndex, itemTypeOf(value), key, &value, sizeof(value)); + } + + template + esp_err_t eraseItem(uint8_t nsIndex, const char* key) + { + return eraseItem(nsIndex, itemTypeOf(), key); + } + + +protected: + + Page& getCurrentPage() + { + return mPageManager.back(); + } + + void clearNamespaces(); + + esp_err_t findItem(uint8_t nsIndex, ItemType datatype, const char* key, Page* &page, Item& item) + { + size_t itemIndex = 0; + for (auto it = std::begin(mPageManager); it != std::end(mPageManager); ++it) { + auto err = it->findItem(nsIndex, datatype, key, itemIndex, item); + if (err == ESP_OK) { + page = it; + return ESP_OK; + } + } + return ESP_ERR_NVS_NOT_FOUND; + } + + +protected: + size_t mPageCount; + PageManager mPageManager; + TNamespaces mNamespaces; + CompressedEnumTable mNamespaceUsage; + StorageState mState = StorageState::INVALID; +}; + +} // namespace nvs + + + +#endif /* nvs_storage_hpp */ diff --git a/components/nvs_flash/src/nvs_types.cpp b/components/nvs_flash/src/nvs_types.cpp new file mode 100644 index 0000000000..9884b276b8 --- /dev/null +++ b/components/nvs_flash/src/nvs_types.cpp @@ -0,0 +1,42 @@ +// Copyright 2015-2016 Espressif Systems (Shanghai) PTE LTD +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at + +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +#include "nvs_types.hpp" + +#if defined(ESP_PLATFORM) +#include +#else +#include "crc.h" +#endif + +namespace nvs +{ +uint32_t Item::calculateCrc32() +{ + uint32_t result = 0xffffffff; + const uint8_t* p = reinterpret_cast(this); + result = crc32_le(result, p + offsetof(Item, nsIndex), + offsetof(Item, crc32) - offsetof(Item, nsIndex)); + result = crc32_le(result, p + offsetof(Item, key), sizeof(key)); + result = crc32_le(result, p + offsetof(Item, data), sizeof(data)); + return result; +} + +uint32_t Item::calculateCrc32(const uint8_t* data, size_t size) +{ + uint32_t result = 0xffffffff; + result = crc32_le(result, data, size); + return result; +} + +} // namespace nvs diff --git a/components/nvs_flash/src/nvs_types.hpp b/components/nvs_flash/src/nvs_types.hpp new file mode 100644 index 0000000000..cc1f86940f --- /dev/null +++ b/components/nvs_flash/src/nvs_types.hpp @@ -0,0 +1,100 @@ +// Copyright 2015-2016 Espressif Systems (Shanghai) PTE LTD +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at + +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +#ifndef nvs_types_h +#define nvs_types_h + +#include +#include +#include +#include +#include +#include "nvs.h" +#include "compressed_enum_table.hpp" + + +namespace nvs +{ + +enum class ItemType : uint8_t { + U8 = 0x01, + I8 = 0x11, + U16 = 0x02, + I16 = 0x12, + U32 = 0x04, + I32 = 0x14, + U64 = 0x08, + I64 = 0x18, + SZ = 0x21, + BLOB = 0x41, + ANY = 0xff +}; + +template::value, void*>::type = nullptr> +constexpr ItemType itemTypeOf() +{ + return static_cast(((std::is_signed::value)?0x10:0x00) | sizeof(T)); +} + +template +constexpr ItemType itemTypeOf(const T&) +{ + return itemTypeOf(); +} + +class Item +{ +public: + union { + struct { + uint8_t nsIndex; + ItemType datatype; + uint8_t span; + uint8_t reserved; + uint32_t crc32; + char key[16]; + union { + struct { + uint16_t dataSize; + uint16_t reserved2; + uint32_t dataCrc32; + } varLength; + uint8_t data[8]; + }; + }; + uint8_t rawData[32]; + }; + + static const size_t MAX_KEY_LENGTH = sizeof(key) - 1; + + uint32_t calculateCrc32(); + static uint32_t calculateCrc32(const uint8_t* data, size_t size); + + void getKey(char* dst, size_t dstSize) + { + strncpy(dst, key, (dstSize + void getValue(T& dst) + { + assert(itemTypeOf(dst) == datatype); + dst = *reinterpret_cast(data); + } +}; + +} // namespace nvs + + + +#endif /* nvs_types_h */ diff --git a/components/nvs_flash/test/Makefile b/components/nvs_flash/test/Makefile new file mode 100644 index 0000000000..ded1235d70 --- /dev/null +++ b/components/nvs_flash/test/Makefile @@ -0,0 +1,40 @@ +TEST_PROGRAM=test_nvs +all: test + +SOURCE_FILES = \ + $(addprefix ../src/, \ + nvs_types.cpp \ + nvs_api.cpp \ + nvs_page.cpp \ + nvs_pagemanager.cpp \ + nvs_storage.cpp \ + ) \ + spi_flash_emulation.cpp \ + test_compressed_enum_table.cpp \ + test_spi_flash_emulation.cpp \ + test_intrusive_list.cpp \ + test_nvs.cpp \ + crc.cpp \ + main.cpp + +CPPFLAGS += -I../include -I../src -I./ -I../../esp32/include -I ../../spi_flash/include +CXXFLAGS += -std=c++11 -Wall -Werror +LDFLAGS += -lstdc++ + +OBJ_FILES = $(SOURCE_FILES:.cpp=.o) + +$(OBJ_FILES): %.o: %.cpp + +$(TEST_PROGRAM): $(OBJ_FILES) + gcc $(LDFLAGS) -o $(TEST_PROGRAM) $(OBJ_FILES) + +$(OUTPUT_DIR): + mkdir -p $(OUTPUT_DIR) + +test: $(TEST_PROGRAM) + ./$(TEST_PROGRAM) + +clean: + rm -f $(OBJ_FILES) $(TEST_PROGRAM) + +.PHONY: clean all test diff --git a/components/nvs_flash/test/catch.hpp b/components/nvs_flash/test/catch.hpp new file mode 100644 index 0000000000..879fc5b1d1 --- /dev/null +++ b/components/nvs_flash/test/catch.hpp @@ -0,0 +1,10509 @@ +/* + * Catch v1.5.6 + * Generated: 2016-06-09 19:20:41.460328 + * ---------------------------------------------------------- + * This file has been merged from multiple headers. Please don't edit it directly + * Copyright (c) 2012 Two Blue Cubes Ltd. All rights reserved. + * + * Distributed under the Boost Software License, Version 1.0. (See accompanying + * file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + */ +#ifndef TWOBLUECUBES_SINGLE_INCLUDE_CATCH_HPP_INCLUDED +#define TWOBLUECUBES_SINGLE_INCLUDE_CATCH_HPP_INCLUDED + +#define TWOBLUECUBES_CATCH_HPP_INCLUDED + +#ifdef __clang__ +# pragma clang system_header +#elif defined __GNUC__ +# pragma GCC system_header +#endif + +// #included from: internal/catch_suppress_warnings.h + +#ifdef __clang__ +# ifdef __ICC // icpc defines the __clang__ macro +# pragma warning(push) +# pragma warning(disable: 161 1682) +# else // __ICC +# pragma clang diagnostic ignored "-Wglobal-constructors" +# pragma clang diagnostic ignored "-Wvariadic-macros" +# pragma clang diagnostic ignored "-Wc99-extensions" +# pragma clang diagnostic ignored "-Wunused-variable" +# pragma clang diagnostic push +# pragma clang diagnostic ignored "-Wpadded" +# pragma clang diagnostic ignored "-Wc++98-compat" +# pragma clang diagnostic ignored "-Wc++98-compat-pedantic" +# pragma clang diagnostic ignored "-Wswitch-enum" +# pragma clang diagnostic ignored "-Wcovered-switch-default" +# endif +#elif defined __GNUC__ +# pragma GCC diagnostic ignored "-Wvariadic-macros" +# pragma GCC diagnostic ignored "-Wunused-variable" +# pragma GCC diagnostic push +# pragma GCC diagnostic ignored "-Wpadded" +#endif +#if defined(CATCH_CONFIG_MAIN) || defined(CATCH_CONFIG_RUNNER) +# define CATCH_IMPL +#endif + +#ifdef CATCH_IMPL +# ifndef CLARA_CONFIG_MAIN +# define CLARA_CONFIG_MAIN_NOT_DEFINED +# define CLARA_CONFIG_MAIN +# endif +#endif + +// #included from: internal/catch_notimplemented_exception.h +#define TWOBLUECUBES_CATCH_NOTIMPLEMENTED_EXCEPTION_H_INCLUDED + +// #included from: catch_common.h +#define TWOBLUECUBES_CATCH_COMMON_H_INCLUDED + +#define INTERNAL_CATCH_UNIQUE_NAME_LINE2( name, line ) name##line +#define INTERNAL_CATCH_UNIQUE_NAME_LINE( name, line ) INTERNAL_CATCH_UNIQUE_NAME_LINE2( name, line ) +#ifdef CATCH_CONFIG_COUNTER +# define INTERNAL_CATCH_UNIQUE_NAME( name ) INTERNAL_CATCH_UNIQUE_NAME_LINE( name, __COUNTER__ ) +#else +# define INTERNAL_CATCH_UNIQUE_NAME( name ) INTERNAL_CATCH_UNIQUE_NAME_LINE( name, __LINE__ ) +#endif + +#define INTERNAL_CATCH_STRINGIFY2( expr ) #expr +#define INTERNAL_CATCH_STRINGIFY( expr ) INTERNAL_CATCH_STRINGIFY2( expr ) + +#include +#include +#include + +// #included from: catch_compiler_capabilities.h +#define TWOBLUECUBES_CATCH_COMPILER_CAPABILITIES_HPP_INCLUDED + +// Detect a number of compiler features - mostly C++11/14 conformance - by compiler +// The following features are defined: +// +// CATCH_CONFIG_CPP11_NULLPTR : is nullptr supported? +// CATCH_CONFIG_CPP11_NOEXCEPT : is noexcept supported? +// CATCH_CONFIG_CPP11_GENERATED_METHODS : The delete and default keywords for compiler generated methods +// CATCH_CONFIG_CPP11_IS_ENUM : std::is_enum is supported? +// CATCH_CONFIG_CPP11_TUPLE : std::tuple is supported +// CATCH_CONFIG_CPP11_LONG_LONG : is long long supported? +// CATCH_CONFIG_CPP11_OVERRIDE : is override supported? +// CATCH_CONFIG_CPP11_UNIQUE_PTR : is unique_ptr supported (otherwise use auto_ptr) + +// CATCH_CONFIG_CPP11_OR_GREATER : Is C++11 supported? + +// CATCH_CONFIG_VARIADIC_MACROS : are variadic macros supported? +// CATCH_CONFIG_COUNTER : is the __COUNTER__ macro supported? +// **************** +// Note to maintainers: if new toggles are added please document them +// in configuration.md, too +// **************** + +// In general each macro has a _NO_ form +// (e.g. CATCH_CONFIG_CPP11_NO_NULLPTR) which disables the feature. +// Many features, at point of detection, define an _INTERNAL_ macro, so they +// can be combined, en-mass, with the _NO_ forms later. + +// All the C++11 features can be disabled with CATCH_CONFIG_NO_CPP11 + +#ifdef __cplusplus + +# if __cplusplus >= 201103L +# define CATCH_CPP11_OR_GREATER +# endif + +# if __cplusplus >= 201402L +# define CATCH_CPP14_OR_GREATER +# endif + +#endif + +#ifdef __clang__ + +# if __has_feature(cxx_nullptr) +# define CATCH_INTERNAL_CONFIG_CPP11_NULLPTR +# endif + +# if __has_feature(cxx_noexcept) +# define CATCH_INTERNAL_CONFIG_CPP11_NOEXCEPT +# endif + +# if defined(CATCH_CPP11_OR_GREATER) +# define CATCH_INTERNAL_SUPPRESS_PARENTHESES_WARNINGS _Pragma( "clang diagnostic ignored \"-Wparentheses\"" ) +# endif + +#endif // __clang__ + +//////////////////////////////////////////////////////////////////////////////// +// Borland +#ifdef __BORLANDC__ + +#endif // __BORLANDC__ + +//////////////////////////////////////////////////////////////////////////////// +// EDG +#ifdef __EDG_VERSION__ + +#endif // __EDG_VERSION__ + +//////////////////////////////////////////////////////////////////////////////// +// Digital Mars +#ifdef __DMC__ + +#endif // __DMC__ + +//////////////////////////////////////////////////////////////////////////////// +// GCC +#ifdef __GNUC__ + +# if __GNUC__ == 4 && __GNUC_MINOR__ >= 6 && defined(__GXX_EXPERIMENTAL_CXX0X__) +# define CATCH_INTERNAL_CONFIG_CPP11_NULLPTR +# endif + +# if !defined(CATCH_INTERNAL_SUPPRESS_PARENTHESES_WARNINGS) && defined(CATCH_CPP11_OR_GREATER) +# define CATCH_INTERNAL_SUPPRESS_PARENTHESES_WARNINGS _Pragma( "GCC diagnostic ignored \"-Wparentheses\"" ) +# endif + +// - otherwise more recent versions define __cplusplus >= 201103L +// and will get picked up below + +#endif // __GNUC__ + +//////////////////////////////////////////////////////////////////////////////// +// Visual C++ +#ifdef _MSC_VER + +#if (_MSC_VER >= 1600) +# define CATCH_INTERNAL_CONFIG_CPP11_NULLPTR +# define CATCH_INTERNAL_CONFIG_CPP11_UNIQUE_PTR +#endif + +#if (_MSC_VER >= 1900 ) // (VC++ 13 (VS2015)) +#define CATCH_INTERNAL_CONFIG_CPP11_NOEXCEPT +#define CATCH_INTERNAL_CONFIG_CPP11_GENERATED_METHODS +#endif + +#endif // _MSC_VER + +//////////////////////////////////////////////////////////////////////////////// + +// Use variadic macros if the compiler supports them +#if ( defined _MSC_VER && _MSC_VER > 1400 && !defined __EDGE__) || \ + ( defined __WAVE__ && __WAVE_HAS_VARIADICS ) || \ + ( defined __GNUC__ && __GNUC__ >= 3 ) || \ + ( !defined __cplusplus && __STDC_VERSION__ >= 199901L || __cplusplus >= 201103L ) + +#define CATCH_INTERNAL_CONFIG_VARIADIC_MACROS + +#endif + +// Use __COUNTER__ if the compiler supports it +#if ( defined _MSC_VER && _MSC_VER >= 1300 ) || \ + ( defined __GNUC__ && __GNUC__ >= 4 && __GNUC_MINOR__ >= 3 ) || \ + ( defined __clang__ && __clang_major__ >= 3 ) + +#define CATCH_INTERNAL_CONFIG_COUNTER + +#endif + +//////////////////////////////////////////////////////////////////////////////// +// C++ language feature support + +// catch all support for C++11 +#if defined(CATCH_CPP11_OR_GREATER) + +# if !defined(CATCH_INTERNAL_CONFIG_CPP11_NULLPTR) +# define CATCH_INTERNAL_CONFIG_CPP11_NULLPTR +# endif + +# ifndef CATCH_INTERNAL_CONFIG_CPP11_NOEXCEPT +# define CATCH_INTERNAL_CONFIG_CPP11_NOEXCEPT +# endif + +# ifndef CATCH_INTERNAL_CONFIG_CPP11_GENERATED_METHODS +# define CATCH_INTERNAL_CONFIG_CPP11_GENERATED_METHODS +# endif + +# ifndef CATCH_INTERNAL_CONFIG_CPP11_IS_ENUM +# define CATCH_INTERNAL_CONFIG_CPP11_IS_ENUM +# endif + +# ifndef CATCH_INTERNAL_CONFIG_CPP11_TUPLE +# define CATCH_INTERNAL_CONFIG_CPP11_TUPLE +# endif + +# ifndef CATCH_INTERNAL_CONFIG_VARIADIC_MACROS +# define CATCH_INTERNAL_CONFIG_VARIADIC_MACROS +# endif + +# if !defined(CATCH_INTERNAL_CONFIG_CPP11_LONG_LONG) +# define CATCH_INTERNAL_CONFIG_CPP11_LONG_LONG +# endif + +# if !defined(CATCH_INTERNAL_CONFIG_CPP11_OVERRIDE) +# define CATCH_INTERNAL_CONFIG_CPP11_OVERRIDE +# endif +# if !defined(CATCH_INTERNAL_CONFIG_CPP11_UNIQUE_PTR) +# define CATCH_INTERNAL_CONFIG_CPP11_UNIQUE_PTR +# endif + +#endif // __cplusplus >= 201103L + +// Now set the actual defines based on the above + anything the user has configured +#if defined(CATCH_INTERNAL_CONFIG_CPP11_NULLPTR) && !defined(CATCH_CONFIG_CPP11_NO_NULLPTR) && !defined(CATCH_CONFIG_CPP11_NULLPTR) && !defined(CATCH_CONFIG_NO_CPP11) +# define CATCH_CONFIG_CPP11_NULLPTR +#endif +#if defined(CATCH_INTERNAL_CONFIG_CPP11_NOEXCEPT) && !defined(CATCH_CONFIG_CPP11_NO_NOEXCEPT) && !defined(CATCH_CONFIG_CPP11_NOEXCEPT) && !defined(CATCH_CONFIG_NO_CPP11) +# define CATCH_CONFIG_CPP11_NOEXCEPT +#endif +#if defined(CATCH_INTERNAL_CONFIG_CPP11_GENERATED_METHODS) && !defined(CATCH_CONFIG_CPP11_NO_GENERATED_METHODS) && !defined(CATCH_CONFIG_CPP11_GENERATED_METHODS) && !defined(CATCH_CONFIG_NO_CPP11) +# define CATCH_CONFIG_CPP11_GENERATED_METHODS +#endif +#if defined(CATCH_INTERNAL_CONFIG_CPP11_IS_ENUM) && !defined(CATCH_CONFIG_CPP11_NO_IS_ENUM) && !defined(CATCH_CONFIG_CPP11_IS_ENUM) && !defined(CATCH_CONFIG_NO_CPP11) +# define CATCH_CONFIG_CPP11_IS_ENUM +#endif +#if defined(CATCH_INTERNAL_CONFIG_CPP11_TUPLE) && !defined(CATCH_CONFIG_CPP11_NO_TUPLE) && !defined(CATCH_CONFIG_CPP11_TUPLE) && !defined(CATCH_CONFIG_NO_CPP11) +# define CATCH_CONFIG_CPP11_TUPLE +#endif +#if defined(CATCH_INTERNAL_CONFIG_VARIADIC_MACROS) && !defined(CATCH_CONFIG_NO_VARIADIC_MACROS) && !defined(CATCH_CONFIG_VARIADIC_MACROS) +# define CATCH_CONFIG_VARIADIC_MACROS +#endif +#if defined(CATCH_INTERNAL_CONFIG_CPP11_LONG_LONG) && !defined(CATCH_CONFIG_NO_LONG_LONG) && !defined(CATCH_CONFIG_CPP11_LONG_LONG) && !defined(CATCH_CONFIG_NO_CPP11) +# define CATCH_CONFIG_CPP11_LONG_LONG +#endif +#if defined(CATCH_INTERNAL_CONFIG_CPP11_OVERRIDE) && !defined(CATCH_CONFIG_NO_OVERRIDE) && !defined(CATCH_CONFIG_CPP11_OVERRIDE) && !defined(CATCH_CONFIG_NO_CPP11) +# define CATCH_CONFIG_CPP11_OVERRIDE +#endif +#if defined(CATCH_INTERNAL_CONFIG_CPP11_UNIQUE_PTR) && !defined(CATCH_CONFIG_NO_UNIQUE_PTR) && !defined(CATCH_CONFIG_CPP11_UNIQUE_PTR) && !defined(CATCH_CONFIG_NO_CPP11) +# define CATCH_CONFIG_CPP11_UNIQUE_PTR +#endif +#if defined(CATCH_INTERNAL_CONFIG_COUNTER) && !defined(CATCH_CONFIG_NO_COUNTER) && !defined(CATCH_CONFIG_COUNTER) +# define CATCH_CONFIG_COUNTER +#endif + +#if !defined(CATCH_INTERNAL_SUPPRESS_PARENTHESES_WARNINGS) +# define CATCH_INTERNAL_SUPPRESS_PARENTHESES_WARNINGS +#endif + +// noexcept support: +#if defined(CATCH_CONFIG_CPP11_NOEXCEPT) && !defined(CATCH_NOEXCEPT) +# define CATCH_NOEXCEPT noexcept +# define CATCH_NOEXCEPT_IS(x) noexcept(x) +#else +# define CATCH_NOEXCEPT throw() +# define CATCH_NOEXCEPT_IS(x) +#endif + +// nullptr support +#ifdef CATCH_CONFIG_CPP11_NULLPTR +# define CATCH_NULL nullptr +#else +# define CATCH_NULL NULL +#endif + +// override support +#ifdef CATCH_CONFIG_CPP11_OVERRIDE +# define CATCH_OVERRIDE override +#else +# define CATCH_OVERRIDE +#endif + +// unique_ptr support +#ifdef CATCH_CONFIG_CPP11_UNIQUE_PTR +# define CATCH_AUTO_PTR( T ) std::unique_ptr +#else +# define CATCH_AUTO_PTR( T ) std::auto_ptr +#endif + +namespace Catch { + + struct IConfig; + + struct CaseSensitive { enum Choice { + Yes, + No + }; }; + + class NonCopyable { +#ifdef CATCH_CONFIG_CPP11_GENERATED_METHODS + NonCopyable( NonCopyable const& ) = delete; + NonCopyable( NonCopyable && ) = delete; + NonCopyable& operator = ( NonCopyable const& ) = delete; + NonCopyable& operator = ( NonCopyable && ) = delete; +#else + NonCopyable( NonCopyable const& info ); + NonCopyable& operator = ( NonCopyable const& ); +#endif + + protected: + NonCopyable() {} + virtual ~NonCopyable(); + }; + + class SafeBool { + public: + typedef void (SafeBool::*type)() const; + + static type makeSafe( bool value ) { + return value ? &SafeBool::trueValue : 0; + } + private: + void trueValue() const {} + }; + + template + inline void deleteAll( ContainerT& container ) { + typename ContainerT::const_iterator it = container.begin(); + typename ContainerT::const_iterator itEnd = container.end(); + for(; it != itEnd; ++it ) + delete *it; + } + template + inline void deleteAllValues( AssociativeContainerT& container ) { + typename AssociativeContainerT::const_iterator it = container.begin(); + typename AssociativeContainerT::const_iterator itEnd = container.end(); + for(; it != itEnd; ++it ) + delete it->second; + } + + bool startsWith( std::string const& s, std::string const& prefix ); + bool endsWith( std::string const& s, std::string const& suffix ); + bool contains( std::string const& s, std::string const& infix ); + void toLowerInPlace( std::string& s ); + std::string toLower( std::string const& s ); + std::string trim( std::string const& str ); + bool replaceInPlace( std::string& str, std::string const& replaceThis, std::string const& withThis ); + + struct pluralise { + pluralise( std::size_t count, std::string const& label ); + + friend std::ostream& operator << ( std::ostream& os, pluralise const& pluraliser ); + + std::size_t m_count; + std::string m_label; + }; + + struct SourceLineInfo { + + SourceLineInfo(); + SourceLineInfo( char const* _file, std::size_t _line ); + SourceLineInfo( SourceLineInfo const& other ); +# ifdef CATCH_CONFIG_CPP11_GENERATED_METHODS + SourceLineInfo( SourceLineInfo && ) = default; + SourceLineInfo& operator = ( SourceLineInfo const& ) = default; + SourceLineInfo& operator = ( SourceLineInfo && ) = default; +# endif + bool empty() const; + bool operator == ( SourceLineInfo const& other ) const; + bool operator < ( SourceLineInfo const& other ) const; + + std::string file; + std::size_t line; + }; + + std::ostream& operator << ( std::ostream& os, SourceLineInfo const& info ); + + // This is just here to avoid compiler warnings with macro constants and boolean literals + inline bool isTrue( bool value ){ return value; } + inline bool alwaysTrue() { return true; } + inline bool alwaysFalse() { return false; } + + void throwLogicError( std::string const& message, SourceLineInfo const& locationInfo ); + + void seedRng( IConfig const& config ); + unsigned int rngSeed(); + + // Use this in variadic streaming macros to allow + // >> +StreamEndStop + // as well as + // >> stuff +StreamEndStop + struct StreamEndStop { + std::string operator+() { + return std::string(); + } + }; + template + T const& operator + ( T const& value, StreamEndStop ) { + return value; + } +} + +#define CATCH_INTERNAL_LINEINFO ::Catch::SourceLineInfo( __FILE__, static_cast( __LINE__ ) ) +#define CATCH_INTERNAL_ERROR( msg ) ::Catch::throwLogicError( msg, CATCH_INTERNAL_LINEINFO ); + +#include + +namespace Catch { + + class NotImplementedException : public std::exception + { + public: + NotImplementedException( SourceLineInfo const& lineInfo ); + NotImplementedException( NotImplementedException const& ) {} + + virtual ~NotImplementedException() CATCH_NOEXCEPT {} + + virtual const char* what() const CATCH_NOEXCEPT; + + private: + std::string m_what; + SourceLineInfo m_lineInfo; + }; + +} // end namespace Catch + +/////////////////////////////////////////////////////////////////////////////// +#define CATCH_NOT_IMPLEMENTED throw Catch::NotImplementedException( CATCH_INTERNAL_LINEINFO ) + +// #included from: internal/catch_context.h +#define TWOBLUECUBES_CATCH_CONTEXT_H_INCLUDED + +// #included from: catch_interfaces_generators.h +#define TWOBLUECUBES_CATCH_INTERFACES_GENERATORS_H_INCLUDED + +#include + +namespace Catch { + + struct IGeneratorInfo { + virtual ~IGeneratorInfo(); + virtual bool moveNext() = 0; + virtual std::size_t getCurrentIndex() const = 0; + }; + + struct IGeneratorsForTest { + virtual ~IGeneratorsForTest(); + + virtual IGeneratorInfo& getGeneratorInfo( std::string const& fileInfo, std::size_t size ) = 0; + virtual bool moveNext() = 0; + }; + + IGeneratorsForTest* createGeneratorsForTest(); + +} // end namespace Catch + +// #included from: catch_ptr.hpp +#define TWOBLUECUBES_CATCH_PTR_HPP_INCLUDED + +#ifdef __clang__ +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wpadded" +#endif + +namespace Catch { + + // An intrusive reference counting smart pointer. + // T must implement addRef() and release() methods + // typically implementing the IShared interface + template + class Ptr { + public: + Ptr() : m_p( CATCH_NULL ){} + Ptr( T* p ) : m_p( p ){ + if( m_p ) + m_p->addRef(); + } + Ptr( Ptr const& other ) : m_p( other.m_p ){ + if( m_p ) + m_p->addRef(); + } + ~Ptr(){ + if( m_p ) + m_p->release(); + } + void reset() { + if( m_p ) + m_p->release(); + m_p = CATCH_NULL; + } + Ptr& operator = ( T* p ){ + Ptr temp( p ); + swap( temp ); + return *this; + } + Ptr& operator = ( Ptr const& other ){ + Ptr temp( other ); + swap( temp ); + return *this; + } + void swap( Ptr& other ) { std::swap( m_p, other.m_p ); } + T* get() const{ return m_p; } + T& operator*() const { return *m_p; } + T* operator->() const { return m_p; } + bool operator !() const { return m_p == CATCH_NULL; } + operator SafeBool::type() const { return SafeBool::makeSafe( m_p != CATCH_NULL ); } + + private: + T* m_p; + }; + + struct IShared : NonCopyable { + virtual ~IShared(); + virtual void addRef() const = 0; + virtual void release() const = 0; + }; + + template + struct SharedImpl : T { + + SharedImpl() : m_rc( 0 ){} + + virtual void addRef() const { + ++m_rc; + } + virtual void release() const { + if( --m_rc == 0 ) + delete this; + } + + mutable unsigned int m_rc; + }; + +} // end namespace Catch + +#ifdef __clang__ +#pragma clang diagnostic pop +#endif + +#include +#include +#include + +namespace Catch { + + class TestCase; + class Stream; + struct IResultCapture; + struct IRunner; + struct IGeneratorsForTest; + struct IConfig; + + struct IContext + { + virtual ~IContext(); + + virtual IResultCapture* getResultCapture() = 0; + virtual IRunner* getRunner() = 0; + virtual size_t getGeneratorIndex( std::string const& fileInfo, size_t totalSize ) = 0; + virtual bool advanceGeneratorsForCurrentTest() = 0; + virtual Ptr getConfig() const = 0; + }; + + struct IMutableContext : IContext + { + virtual ~IMutableContext(); + virtual void setResultCapture( IResultCapture* resultCapture ) = 0; + virtual void setRunner( IRunner* runner ) = 0; + virtual void setConfig( Ptr const& config ) = 0; + }; + + IContext& getCurrentContext(); + IMutableContext& getCurrentMutableContext(); + void cleanUpContext(); + Stream createStream( std::string const& streamName ); + +} + +// #included from: internal/catch_test_registry.hpp +#define TWOBLUECUBES_CATCH_TEST_REGISTRY_HPP_INCLUDED + +// #included from: catch_interfaces_testcase.h +#define TWOBLUECUBES_CATCH_INTERFACES_TESTCASE_H_INCLUDED + +#include + +namespace Catch { + + class TestSpec; + + struct ITestCase : IShared { + virtual void invoke () const = 0; + protected: + virtual ~ITestCase(); + }; + + class TestCase; + struct IConfig; + + struct ITestCaseRegistry { + virtual ~ITestCaseRegistry(); + virtual std::vector const& getAllTests() const = 0; + virtual std::vector const& getAllTestsSorted( IConfig const& config ) const = 0; + }; + + bool matchTest( TestCase const& testCase, TestSpec const& testSpec, IConfig const& config ); + std::vector filterTests( std::vector const& testCases, TestSpec const& testSpec, IConfig const& config ); + std::vector const& getAllTestCasesSorted( IConfig const& config ); + +} + +namespace Catch { + +template +class MethodTestCase : public SharedImpl { + +public: + MethodTestCase( void (C::*method)() ) : m_method( method ) {} + + virtual void invoke() const { + C obj; + (obj.*m_method)(); + } + +private: + virtual ~MethodTestCase() {} + + void (C::*m_method)(); +}; + +typedef void(*TestFunction)(); + +struct NameAndDesc { + NameAndDesc( const char* _name = "", const char* _description= "" ) + : name( _name ), description( _description ) + {} + + const char* name; + const char* description; +}; + +void registerTestCase + ( ITestCase* testCase, + char const* className, + NameAndDesc const& nameAndDesc, + SourceLineInfo const& lineInfo ); + +struct AutoReg { + + AutoReg + ( TestFunction function, + SourceLineInfo const& lineInfo, + NameAndDesc const& nameAndDesc ); + + template + AutoReg + ( void (C::*method)(), + char const* className, + NameAndDesc const& nameAndDesc, + SourceLineInfo const& lineInfo ) { + + registerTestCase + ( new MethodTestCase( method ), + className, + nameAndDesc, + lineInfo ); + } + + ~AutoReg(); + +private: + AutoReg( AutoReg const& ); + void operator= ( AutoReg const& ); +}; + +void registerTestCaseFunction + ( TestFunction function, + SourceLineInfo const& lineInfo, + NameAndDesc const& nameAndDesc ); + +} // end namespace Catch + +#ifdef CATCH_CONFIG_VARIADIC_MACROS + /////////////////////////////////////////////////////////////////////////////// + #define INTERNAL_CATCH_TESTCASE2( TestName, ... ) \ + static void TestName(); \ + namespace{ Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME( autoRegistrar )( &TestName, CATCH_INTERNAL_LINEINFO, Catch::NameAndDesc( __VA_ARGS__ ) ); }\ + static void TestName() + #define INTERNAL_CATCH_TESTCASE( ... ) \ + INTERNAL_CATCH_TESTCASE2( INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ ), __VA_ARGS__ ) + + /////////////////////////////////////////////////////////////////////////////// + #define INTERNAL_CATCH_METHOD_AS_TEST_CASE( QualifiedMethod, ... ) \ + namespace{ Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME( autoRegistrar )( &QualifiedMethod, "&" #QualifiedMethod, Catch::NameAndDesc( __VA_ARGS__ ), CATCH_INTERNAL_LINEINFO ); } + + /////////////////////////////////////////////////////////////////////////////// + #define INTERNAL_CATCH_TEST_CASE_METHOD2( TestName, ClassName, ... )\ + namespace{ \ + struct TestName : ClassName{ \ + void test(); \ + }; \ + Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME( autoRegistrar ) ( &TestName::test, #ClassName, Catch::NameAndDesc( __VA_ARGS__ ), CATCH_INTERNAL_LINEINFO ); \ + } \ + void TestName::test() + #define INTERNAL_CATCH_TEST_CASE_METHOD( ClassName, ... ) \ + INTERNAL_CATCH_TEST_CASE_METHOD2( INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ ), ClassName, __VA_ARGS__ ) + + /////////////////////////////////////////////////////////////////////////////// + #define INTERNAL_CATCH_REGISTER_TESTCASE( Function, ... ) \ + Catch::AutoReg( Function, CATCH_INTERNAL_LINEINFO, Catch::NameAndDesc( __VA_ARGS__ ) ); + +#else + /////////////////////////////////////////////////////////////////////////////// + #define INTERNAL_CATCH_TESTCASE2( TestName, Name, Desc ) \ + static void TestName(); \ + namespace{ Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME( autoRegistrar )( &TestName, CATCH_INTERNAL_LINEINFO, Catch::NameAndDesc( Name, Desc ) ); }\ + static void TestName() + #define INTERNAL_CATCH_TESTCASE( Name, Desc ) \ + INTERNAL_CATCH_TESTCASE2( INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ ), Name, Desc ) + + /////////////////////////////////////////////////////////////////////////////// + #define INTERNAL_CATCH_METHOD_AS_TEST_CASE( QualifiedMethod, Name, Desc ) \ + namespace{ Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME( autoRegistrar )( &QualifiedMethod, "&" #QualifiedMethod, Catch::NameAndDesc( Name, Desc ), CATCH_INTERNAL_LINEINFO ); } + + /////////////////////////////////////////////////////////////////////////////// + #define INTERNAL_CATCH_TEST_CASE_METHOD2( TestCaseName, ClassName, TestName, Desc )\ + namespace{ \ + struct TestCaseName : ClassName{ \ + void test(); \ + }; \ + Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME( autoRegistrar ) ( &TestCaseName::test, #ClassName, Catch::NameAndDesc( TestName, Desc ), CATCH_INTERNAL_LINEINFO ); \ + } \ + void TestCaseName::test() + #define INTERNAL_CATCH_TEST_CASE_METHOD( ClassName, TestName, Desc )\ + INTERNAL_CATCH_TEST_CASE_METHOD2( INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ ), ClassName, TestName, Desc ) + + /////////////////////////////////////////////////////////////////////////////// + #define INTERNAL_CATCH_REGISTER_TESTCASE( Function, Name, Desc ) \ + Catch::AutoReg( Function, CATCH_INTERNAL_LINEINFO, Catch::NameAndDesc( Name, Desc ) ); +#endif + +// #included from: internal/catch_capture.hpp +#define TWOBLUECUBES_CATCH_CAPTURE_HPP_INCLUDED + +// #included from: catch_result_builder.h +#define TWOBLUECUBES_CATCH_RESULT_BUILDER_H_INCLUDED + +// #included from: catch_result_type.h +#define TWOBLUECUBES_CATCH_RESULT_TYPE_H_INCLUDED + +namespace Catch { + + // ResultWas::OfType enum + struct ResultWas { enum OfType { + Unknown = -1, + Ok = 0, + Info = 1, + Warning = 2, + + FailureBit = 0x10, + + ExpressionFailed = FailureBit | 1, + ExplicitFailure = FailureBit | 2, + + Exception = 0x100 | FailureBit, + + ThrewException = Exception | 1, + DidntThrowException = Exception | 2, + + FatalErrorCondition = 0x200 | FailureBit + + }; }; + + inline bool isOk( ResultWas::OfType resultType ) { + return ( resultType & ResultWas::FailureBit ) == 0; + } + inline bool isJustInfo( int flags ) { + return flags == ResultWas::Info; + } + + // ResultDisposition::Flags enum + struct ResultDisposition { enum Flags { + Normal = 0x01, + + ContinueOnFailure = 0x02, // Failures fail test, but execution continues + FalseTest = 0x04, // Prefix expression with ! + SuppressFail = 0x08 // Failures are reported but do not fail the test + }; }; + + inline ResultDisposition::Flags operator | ( ResultDisposition::Flags lhs, ResultDisposition::Flags rhs ) { + return static_cast( static_cast( lhs ) | static_cast( rhs ) ); + } + + inline bool shouldContinueOnFailure( int flags ) { return ( flags & ResultDisposition::ContinueOnFailure ) != 0; } + inline bool isFalseTest( int flags ) { return ( flags & ResultDisposition::FalseTest ) != 0; } + inline bool shouldSuppressFailure( int flags ) { return ( flags & ResultDisposition::SuppressFail ) != 0; } + +} // end namespace Catch + +// #included from: catch_assertionresult.h +#define TWOBLUECUBES_CATCH_ASSERTIONRESULT_H_INCLUDED + +#include + +namespace Catch { + + struct AssertionInfo + { + AssertionInfo() {} + AssertionInfo( std::string const& _macroName, + SourceLineInfo const& _lineInfo, + std::string const& _capturedExpression, + ResultDisposition::Flags _resultDisposition ); + + std::string macroName; + SourceLineInfo lineInfo; + std::string capturedExpression; + ResultDisposition::Flags resultDisposition; + }; + + struct AssertionResultData + { + AssertionResultData() : resultType( ResultWas::Unknown ) {} + + std::string reconstructedExpression; + std::string message; + ResultWas::OfType resultType; + }; + + class AssertionResult { + public: + AssertionResult(); + AssertionResult( AssertionInfo const& info, AssertionResultData const& data ); + ~AssertionResult(); +# ifdef CATCH_CONFIG_CPP11_GENERATED_METHODS + AssertionResult( AssertionResult const& ) = default; + AssertionResult( AssertionResult && ) = default; + AssertionResult& operator = ( AssertionResult const& ) = default; + AssertionResult& operator = ( AssertionResult && ) = default; +# endif + + bool isOk() const; + bool succeeded() const; + ResultWas::OfType getResultType() const; + bool hasExpression() const; + bool hasMessage() const; + std::string getExpression() const; + std::string getExpressionInMacro() const; + bool hasExpandedExpression() const; + std::string getExpandedExpression() const; + std::string getMessage() const; + SourceLineInfo getSourceInfo() const; + std::string getTestMacroName() const; + + protected: + AssertionInfo m_info; + AssertionResultData m_resultData; + }; + +} // end namespace Catch + +// #included from: catch_matchers.hpp +#define TWOBLUECUBES_CATCH_MATCHERS_HPP_INCLUDED + +namespace Catch { +namespace Matchers { + namespace Impl { + + namespace Generic { + template class AllOf; + template class AnyOf; + template class Not; + } + + template + struct Matcher : SharedImpl + { + typedef ExpressionT ExpressionType; + + virtual ~Matcher() {} + virtual Ptr clone() const = 0; + virtual bool match( ExpressionT const& expr ) const = 0; + virtual std::string toString() const = 0; + + Generic::AllOf operator && ( Matcher const& other ) const; + Generic::AnyOf operator || ( Matcher const& other ) const; + Generic::Not operator ! () const; + }; + + template + struct MatcherImpl : Matcher { + + virtual Ptr > clone() const { + return Ptr >( new DerivedT( static_cast( *this ) ) ); + } + }; + + namespace Generic { + template + class Not : public MatcherImpl, ExpressionT> { + public: + explicit Not( Matcher const& matcher ) : m_matcher(matcher.clone()) {} + Not( Not const& other ) : m_matcher( other.m_matcher ) {} + + virtual bool match( ExpressionT const& expr ) const CATCH_OVERRIDE { + return !m_matcher->match( expr ); + } + + virtual std::string toString() const CATCH_OVERRIDE { + return "not " + m_matcher->toString(); + } + private: + Ptr< Matcher > m_matcher; + }; + + template + class AllOf : public MatcherImpl, ExpressionT> { + public: + + AllOf() {} + AllOf( AllOf const& other ) : m_matchers( other.m_matchers ) {} + + AllOf& add( Matcher const& matcher ) { + m_matchers.push_back( matcher.clone() ); + return *this; + } + virtual bool match( ExpressionT const& expr ) const + { + for( std::size_t i = 0; i < m_matchers.size(); ++i ) + if( !m_matchers[i]->match( expr ) ) + return false; + return true; + } + virtual std::string toString() const { + std::ostringstream oss; + oss << "( "; + for( std::size_t i = 0; i < m_matchers.size(); ++i ) { + if( i != 0 ) + oss << " and "; + oss << m_matchers[i]->toString(); + } + oss << " )"; + return oss.str(); + } + + AllOf operator && ( Matcher const& other ) const { + AllOf allOfExpr( *this ); + allOfExpr.add( other ); + return allOfExpr; + } + + private: + std::vector > > m_matchers; + }; + + template + class AnyOf : public MatcherImpl, ExpressionT> { + public: + + AnyOf() {} + AnyOf( AnyOf const& other ) : m_matchers( other.m_matchers ) {} + + AnyOf& add( Matcher const& matcher ) { + m_matchers.push_back( matcher.clone() ); + return *this; + } + virtual bool match( ExpressionT const& expr ) const + { + for( std::size_t i = 0; i < m_matchers.size(); ++i ) + if( m_matchers[i]->match( expr ) ) + return true; + return false; + } + virtual std::string toString() const { + std::ostringstream oss; + oss << "( "; + for( std::size_t i = 0; i < m_matchers.size(); ++i ) { + if( i != 0 ) + oss << " or "; + oss << m_matchers[i]->toString(); + } + oss << " )"; + return oss.str(); + } + + AnyOf operator || ( Matcher const& other ) const { + AnyOf anyOfExpr( *this ); + anyOfExpr.add( other ); + return anyOfExpr; + } + + private: + std::vector > > m_matchers; + }; + + } // namespace Generic + + template + Generic::AllOf Matcher::operator && ( Matcher const& other ) const { + Generic::AllOf allOfExpr; + allOfExpr.add( *this ); + allOfExpr.add( other ); + return allOfExpr; + } + + template + Generic::AnyOf Matcher::operator || ( Matcher const& other ) const { + Generic::AnyOf anyOfExpr; + anyOfExpr.add( *this ); + anyOfExpr.add( other ); + return anyOfExpr; + } + + template + Generic::Not Matcher::operator ! () const { + return Generic::Not( *this ); + } + + namespace StdString { + + inline std::string makeString( std::string const& str ) { return str; } + inline std::string makeString( const char* str ) { return str ? std::string( str ) : std::string(); } + + struct CasedString + { + CasedString( std::string const& str, CaseSensitive::Choice caseSensitivity ) + : m_caseSensitivity( caseSensitivity ), + m_str( adjustString( str ) ) + {} + std::string adjustString( std::string const& str ) const { + return m_caseSensitivity == CaseSensitive::No + ? toLower( str ) + : str; + + } + std::string toStringSuffix() const + { + return m_caseSensitivity == CaseSensitive::No + ? " (case insensitive)" + : ""; + } + CaseSensitive::Choice m_caseSensitivity; + std::string m_str; + }; + + struct Equals : MatcherImpl { + Equals( std::string const& str, CaseSensitive::Choice caseSensitivity = CaseSensitive::Yes ) + : m_data( str, caseSensitivity ) + {} + Equals( Equals const& other ) : m_data( other.m_data ){} + + virtual ~Equals(); + + virtual bool match( std::string const& expr ) const { + return m_data.m_str == m_data.adjustString( expr );; + } + virtual std::string toString() const { + return "equals: \"" + m_data.m_str + "\"" + m_data.toStringSuffix(); + } + + CasedString m_data; + }; + + struct Contains : MatcherImpl { + Contains( std::string const& substr, CaseSensitive::Choice caseSensitivity = CaseSensitive::Yes ) + : m_data( substr, caseSensitivity ){} + Contains( Contains const& other ) : m_data( other.m_data ){} + + virtual ~Contains(); + + virtual bool match( std::string const& expr ) const { + return m_data.adjustString( expr ).find( m_data.m_str ) != std::string::npos; + } + virtual std::string toString() const { + return "contains: \"" + m_data.m_str + "\"" + m_data.toStringSuffix(); + } + + CasedString m_data; + }; + + struct StartsWith : MatcherImpl { + StartsWith( std::string const& substr, CaseSensitive::Choice caseSensitivity = CaseSensitive::Yes ) + : m_data( substr, caseSensitivity ){} + + StartsWith( StartsWith const& other ) : m_data( other.m_data ){} + + virtual ~StartsWith(); + + virtual bool match( std::string const& expr ) const { + return startsWith( m_data.adjustString( expr ), m_data.m_str ); + } + virtual std::string toString() const { + return "starts with: \"" + m_data.m_str + "\"" + m_data.toStringSuffix(); + } + + CasedString m_data; + }; + + struct EndsWith : MatcherImpl { + EndsWith( std::string const& substr, CaseSensitive::Choice caseSensitivity = CaseSensitive::Yes ) + : m_data( substr, caseSensitivity ){} + EndsWith( EndsWith const& other ) : m_data( other.m_data ){} + + virtual ~EndsWith(); + + virtual bool match( std::string const& expr ) const { + return endsWith( m_data.adjustString( expr ), m_data.m_str ); + } + virtual std::string toString() const { + return "ends with: \"" + m_data.m_str + "\"" + m_data.toStringSuffix(); + } + + CasedString m_data; + }; + } // namespace StdString + } // namespace Impl + + // The following functions create the actual matcher objects. + // This allows the types to be inferred + template + inline Impl::Generic::Not Not( Impl::Matcher const& m ) { + return Impl::Generic::Not( m ); + } + + template + inline Impl::Generic::AllOf AllOf( Impl::Matcher const& m1, + Impl::Matcher const& m2 ) { + return Impl::Generic::AllOf().add( m1 ).add( m2 ); + } + template + inline Impl::Generic::AllOf AllOf( Impl::Matcher const& m1, + Impl::Matcher const& m2, + Impl::Matcher const& m3 ) { + return Impl::Generic::AllOf().add( m1 ).add( m2 ).add( m3 ); + } + template + inline Impl::Generic::AnyOf AnyOf( Impl::Matcher const& m1, + Impl::Matcher const& m2 ) { + return Impl::Generic::AnyOf().add( m1 ).add( m2 ); + } + template + inline Impl::Generic::AnyOf AnyOf( Impl::Matcher const& m1, + Impl::Matcher const& m2, + Impl::Matcher const& m3 ) { + return Impl::Generic::AnyOf().add( m1 ).add( m2 ).add( m3 ); + } + + inline Impl::StdString::Equals Equals( std::string const& str, CaseSensitive::Choice caseSensitivity = CaseSensitive::Yes ) { + return Impl::StdString::Equals( str, caseSensitivity ); + } + inline Impl::StdString::Equals Equals( const char* str, CaseSensitive::Choice caseSensitivity = CaseSensitive::Yes ) { + return Impl::StdString::Equals( Impl::StdString::makeString( str ), caseSensitivity ); + } + inline Impl::StdString::Contains Contains( std::string const& substr, CaseSensitive::Choice caseSensitivity = CaseSensitive::Yes ) { + return Impl::StdString::Contains( substr, caseSensitivity ); + } + inline Impl::StdString::Contains Contains( const char* substr, CaseSensitive::Choice caseSensitivity = CaseSensitive::Yes ) { + return Impl::StdString::Contains( Impl::StdString::makeString( substr ), caseSensitivity ); + } + inline Impl::StdString::StartsWith StartsWith( std::string const& substr ) { + return Impl::StdString::StartsWith( substr ); + } + inline Impl::StdString::StartsWith StartsWith( const char* substr ) { + return Impl::StdString::StartsWith( Impl::StdString::makeString( substr ) ); + } + inline Impl::StdString::EndsWith EndsWith( std::string const& substr ) { + return Impl::StdString::EndsWith( substr ); + } + inline Impl::StdString::EndsWith EndsWith( const char* substr ) { + return Impl::StdString::EndsWith( Impl::StdString::makeString( substr ) ); + } + +} // namespace Matchers + +using namespace Matchers; + +} // namespace Catch + +namespace Catch { + + struct TestFailureException{}; + + template class ExpressionLhs; + + struct STATIC_ASSERT_Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison; + + struct CopyableStream { + CopyableStream() {} + CopyableStream( CopyableStream const& other ) { + oss << other.oss.str(); + } + CopyableStream& operator=( CopyableStream const& other ) { + oss.str(""); + oss << other.oss.str(); + return *this; + } + std::ostringstream oss; + }; + + class ResultBuilder { + public: + ResultBuilder( char const* macroName, + SourceLineInfo const& lineInfo, + char const* capturedExpression, + ResultDisposition::Flags resultDisposition, + char const* secondArg = "" ); + + template + ExpressionLhs operator <= ( T const& operand ); + ExpressionLhs operator <= ( bool value ); + + template + ResultBuilder& operator << ( T const& value ) { + m_stream.oss << value; + return *this; + } + + template STATIC_ASSERT_Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison& operator && ( RhsT const& ); + template STATIC_ASSERT_Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison& operator || ( RhsT const& ); + + ResultBuilder& setResultType( ResultWas::OfType result ); + ResultBuilder& setResultType( bool result ); + ResultBuilder& setLhs( std::string const& lhs ); + ResultBuilder& setRhs( std::string const& rhs ); + ResultBuilder& setOp( std::string const& op ); + + void endExpression(); + + std::string reconstructExpression() const; + AssertionResult build() const; + + void useActiveException( ResultDisposition::Flags resultDisposition = ResultDisposition::Normal ); + void captureResult( ResultWas::OfType resultType ); + void captureExpression(); + void captureExpectedException( std::string const& expectedMessage ); + void captureExpectedException( Matchers::Impl::Matcher const& matcher ); + void handleResult( AssertionResult const& result ); + void react(); + bool shouldDebugBreak() const; + bool allowThrows() const; + + private: + AssertionInfo m_assertionInfo; + AssertionResultData m_data; + struct ExprComponents { + ExprComponents() : testFalse( false ) {} + bool testFalse; + std::string lhs, rhs, op; + } m_exprComponents; + CopyableStream m_stream; + + bool m_shouldDebugBreak; + bool m_shouldThrow; + }; + +} // namespace Catch + +// Include after due to circular dependency: +// #included from: catch_expression_lhs.hpp +#define TWOBLUECUBES_CATCH_EXPRESSION_LHS_HPP_INCLUDED + +// #included from: catch_evaluate.hpp +#define TWOBLUECUBES_CATCH_EVALUATE_HPP_INCLUDED + +#ifdef _MSC_VER +#pragma warning(push) +#pragma warning(disable:4389) // '==' : signed/unsigned mismatch +#endif + +#include + +namespace Catch { +namespace Internal { + + enum Operator { + IsEqualTo, + IsNotEqualTo, + IsLessThan, + IsGreaterThan, + IsLessThanOrEqualTo, + IsGreaterThanOrEqualTo + }; + + template struct OperatorTraits { static const char* getName(){ return "*error*"; } }; + template<> struct OperatorTraits { static const char* getName(){ return "=="; } }; + template<> struct OperatorTraits { static const char* getName(){ return "!="; } }; + template<> struct OperatorTraits { static const char* getName(){ return "<"; } }; + template<> struct OperatorTraits { static const char* getName(){ return ">"; } }; + template<> struct OperatorTraits { static const char* getName(){ return "<="; } }; + template<> struct OperatorTraits{ static const char* getName(){ return ">="; } }; + + template + inline T& opCast(T const& t) { return const_cast(t); } + +// nullptr_t support based on pull request #154 from Konstantin Baumann +#ifdef CATCH_CONFIG_CPP11_NULLPTR + inline std::nullptr_t opCast(std::nullptr_t) { return nullptr; } +#endif // CATCH_CONFIG_CPP11_NULLPTR + + // So the compare overloads can be operator agnostic we convey the operator as a template + // enum, which is used to specialise an Evaluator for doing the comparison. + template + class Evaluator{}; + + template + struct Evaluator { + static bool evaluate( T1 const& lhs, T2 const& rhs) { + return bool( opCast( lhs ) == opCast( rhs ) ); + } + }; + template + struct Evaluator { + static bool evaluate( T1 const& lhs, T2 const& rhs ) { + return bool( opCast( lhs ) != opCast( rhs ) ); + } + }; + template + struct Evaluator { + static bool evaluate( T1 const& lhs, T2 const& rhs ) { + return bool( opCast( lhs ) < opCast( rhs ) ); + } + }; + template + struct Evaluator { + static bool evaluate( T1 const& lhs, T2 const& rhs ) { + return bool( opCast( lhs ) > opCast( rhs ) ); + } + }; + template + struct Evaluator { + static bool evaluate( T1 const& lhs, T2 const& rhs ) { + return bool( opCast( lhs ) >= opCast( rhs ) ); + } + }; + template + struct Evaluator { + static bool evaluate( T1 const& lhs, T2 const& rhs ) { + return bool( opCast( lhs ) <= opCast( rhs ) ); + } + }; + + template + bool applyEvaluator( T1 const& lhs, T2 const& rhs ) { + return Evaluator::evaluate( lhs, rhs ); + } + + // This level of indirection allows us to specialise for integer types + // to avoid signed/ unsigned warnings + + // "base" overload + template + bool compare( T1 const& lhs, T2 const& rhs ) { + return Evaluator::evaluate( lhs, rhs ); + } + + // unsigned X to int + template bool compare( unsigned int lhs, int rhs ) { + return applyEvaluator( lhs, static_cast( rhs ) ); + } + template bool compare( unsigned long lhs, int rhs ) { + return applyEvaluator( lhs, static_cast( rhs ) ); + } + template bool compare( unsigned char lhs, int rhs ) { + return applyEvaluator( lhs, static_cast( rhs ) ); + } + + // unsigned X to long + template bool compare( unsigned int lhs, long rhs ) { + return applyEvaluator( lhs, static_cast( rhs ) ); + } + template bool compare( unsigned long lhs, long rhs ) { + return applyEvaluator( lhs, static_cast( rhs ) ); + } + template bool compare( unsigned char lhs, long rhs ) { + return applyEvaluator( lhs, static_cast( rhs ) ); + } + + // int to unsigned X + template bool compare( int lhs, unsigned int rhs ) { + return applyEvaluator( static_cast( lhs ), rhs ); + } + template bool compare( int lhs, unsigned long rhs ) { + return applyEvaluator( static_cast( lhs ), rhs ); + } + template bool compare( int lhs, unsigned char rhs ) { + return applyEvaluator( static_cast( lhs ), rhs ); + } + + // long to unsigned X + template bool compare( long lhs, unsigned int rhs ) { + return applyEvaluator( static_cast( lhs ), rhs ); + } + template bool compare( long lhs, unsigned long rhs ) { + return applyEvaluator( static_cast( lhs ), rhs ); + } + template bool compare( long lhs, unsigned char rhs ) { + return applyEvaluator( static_cast( lhs ), rhs ); + } + + // pointer to long (when comparing against NULL) + template bool compare( long lhs, T* rhs ) { + return Evaluator::evaluate( reinterpret_cast( lhs ), rhs ); + } + template bool compare( T* lhs, long rhs ) { + return Evaluator::evaluate( lhs, reinterpret_cast( rhs ) ); + } + + // pointer to int (when comparing against NULL) + template bool compare( int lhs, T* rhs ) { + return Evaluator::evaluate( reinterpret_cast( lhs ), rhs ); + } + template bool compare( T* lhs, int rhs ) { + return Evaluator::evaluate( lhs, reinterpret_cast( rhs ) ); + } + +#ifdef CATCH_CONFIG_CPP11_LONG_LONG + // long long to unsigned X + template bool compare( long long lhs, unsigned int rhs ) { + return applyEvaluator( static_cast( lhs ), rhs ); + } + template bool compare( long long lhs, unsigned long rhs ) { + return applyEvaluator( static_cast( lhs ), rhs ); + } + template bool compare( long long lhs, unsigned long long rhs ) { + return applyEvaluator( static_cast( lhs ), rhs ); + } + template bool compare( long long lhs, unsigned char rhs ) { + return applyEvaluator( static_cast( lhs ), rhs ); + } + + // unsigned long long to X + template bool compare( unsigned long long lhs, int rhs ) { + return applyEvaluator( static_cast( lhs ), rhs ); + } + template bool compare( unsigned long long lhs, long rhs ) { + return applyEvaluator( static_cast( lhs ), rhs ); + } + template bool compare( unsigned long long lhs, long long rhs ) { + return applyEvaluator( static_cast( lhs ), rhs ); + } + template bool compare( unsigned long long lhs, char rhs ) { + return applyEvaluator( static_cast( lhs ), rhs ); + } + + // pointer to long long (when comparing against NULL) + template bool compare( long long lhs, T* rhs ) { + return Evaluator::evaluate( reinterpret_cast( lhs ), rhs ); + } + template bool compare( T* lhs, long long rhs ) { + return Evaluator::evaluate( lhs, reinterpret_cast( rhs ) ); + } +#endif // CATCH_CONFIG_CPP11_LONG_LONG + +#ifdef CATCH_CONFIG_CPP11_NULLPTR + // pointer to nullptr_t (when comparing against nullptr) + template bool compare( std::nullptr_t, T* rhs ) { + return Evaluator::evaluate( nullptr, rhs ); + } + template bool compare( T* lhs, std::nullptr_t ) { + return Evaluator::evaluate( lhs, nullptr ); + } +#endif // CATCH_CONFIG_CPP11_NULLPTR + +} // end of namespace Internal +} // end of namespace Catch + +#ifdef _MSC_VER +#pragma warning(pop) +#endif + +// #included from: catch_tostring.h +#define TWOBLUECUBES_CATCH_TOSTRING_H_INCLUDED + +#include +#include +#include +#include +#include + +#ifdef __OBJC__ +// #included from: catch_objc_arc.hpp +#define TWOBLUECUBES_CATCH_OBJC_ARC_HPP_INCLUDED + +#import + +#ifdef __has_feature +#define CATCH_ARC_ENABLED __has_feature(objc_arc) +#else +#define CATCH_ARC_ENABLED 0 +#endif + +void arcSafeRelease( NSObject* obj ); +id performOptionalSelector( id obj, SEL sel ); + +#if !CATCH_ARC_ENABLED +inline void arcSafeRelease( NSObject* obj ) { + [obj release]; +} +inline id performOptionalSelector( id obj, SEL sel ) { + if( [obj respondsToSelector: sel] ) + return [obj performSelector: sel]; + return nil; +} +#define CATCH_UNSAFE_UNRETAINED +#define CATCH_ARC_STRONG +#else +inline void arcSafeRelease( NSObject* ){} +inline id performOptionalSelector( id obj, SEL sel ) { +#ifdef __clang__ +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Warc-performSelector-leaks" +#endif + if( [obj respondsToSelector: sel] ) + return [obj performSelector: sel]; +#ifdef __clang__ +#pragma clang diagnostic pop +#endif + return nil; +} +#define CATCH_UNSAFE_UNRETAINED __unsafe_unretained +#define CATCH_ARC_STRONG __strong +#endif + +#endif + +#ifdef CATCH_CONFIG_CPP11_TUPLE +#include +#endif + +#ifdef CATCH_CONFIG_CPP11_IS_ENUM +#include +#endif + +namespace Catch { + +// Why we're here. +template +std::string toString( T const& value ); + +// Built in overloads + +std::string toString( std::string const& value ); +std::string toString( std::wstring const& value ); +std::string toString( const char* const value ); +std::string toString( char* const value ); +std::string toString( const wchar_t* const value ); +std::string toString( wchar_t* const value ); +std::string toString( int value ); +std::string toString( unsigned long value ); +std::string toString( unsigned int value ); +std::string toString( const double value ); +std::string toString( const float value ); +std::string toString( bool value ); +std::string toString( char value ); +std::string toString( signed char value ); +std::string toString( unsigned char value ); + +#ifdef CATCH_CONFIG_CPP11_LONG_LONG +std::string toString( long long value ); +std::string toString( unsigned long long value ); +#endif + +#ifdef CATCH_CONFIG_CPP11_NULLPTR +std::string toString( std::nullptr_t ); +#endif + +#ifdef __OBJC__ + std::string toString( NSString const * const& nsstring ); + std::string toString( NSString * CATCH_ARC_STRONG const& nsstring ); + std::string toString( NSObject* const& nsObject ); +#endif + +namespace Detail { + + extern const std::string unprintableString; + + struct BorgType { + template BorgType( T const& ); + }; + + struct TrueType { char sizer[1]; }; + struct FalseType { char sizer[2]; }; + + TrueType& testStreamable( std::ostream& ); + FalseType testStreamable( FalseType ); + + FalseType operator<<( std::ostream const&, BorgType const& ); + + template + struct IsStreamInsertable { + static std::ostream &s; + static T const&t; + enum { value = sizeof( testStreamable(s << t) ) == sizeof( TrueType ) }; + }; + +#if defined(CATCH_CONFIG_CPP11_IS_ENUM) + template::value + > + struct EnumStringMaker + { + static std::string convert( T const& ) { return unprintableString; } + }; + + template + struct EnumStringMaker + { + static std::string convert( T const& v ) + { + return ::Catch::toString( + static_cast::type>(v) + ); + } + }; +#endif + template + struct StringMakerBase { +#if defined(CATCH_CONFIG_CPP11_IS_ENUM) + template + static std::string convert( T const& v ) + { + return EnumStringMaker::convert( v ); + } +#else + template + static std::string convert( T const& ) { return unprintableString; } +#endif + }; + + template<> + struct StringMakerBase { + template + static std::string convert( T const& _value ) { + std::ostringstream oss; + oss << _value; + return oss.str(); + } + }; + + std::string rawMemoryToString( const void *object, std::size_t size ); + + template + inline std::string rawMemoryToString( const T& object ) { + return rawMemoryToString( &object, sizeof(object) ); + } + +} // end namespace Detail + +template +struct StringMaker : + Detail::StringMakerBase::value> {}; + +template +struct StringMaker { + template + static std::string convert( U* p ) { + if( !p ) + return "NULL"; + else + return Detail::rawMemoryToString( p ); + } +}; + +template +struct StringMaker { + static std::string convert( R C::* p ) { + if( !p ) + return "NULL"; + else + return Detail::rawMemoryToString( p ); + } +}; + +namespace Detail { + template + std::string rangeToString( InputIterator first, InputIterator last ); +} + +//template +//struct StringMaker > { +// static std::string convert( std::vector const& v ) { +// return Detail::rangeToString( v.begin(), v.end() ); +// } +//}; + +template +std::string toString( std::vector const& v ) { + return Detail::rangeToString( v.begin(), v.end() ); +} + +#ifdef CATCH_CONFIG_CPP11_TUPLE + +// toString for tuples +namespace TupleDetail { + template< + typename Tuple, + std::size_t N = 0, + bool = (N < std::tuple_size::value) + > + struct ElementPrinter { + static void print( const Tuple& tuple, std::ostream& os ) + { + os << ( N ? ", " : " " ) + << Catch::toString(std::get(tuple)); + ElementPrinter::print(tuple,os); + } + }; + + template< + typename Tuple, + std::size_t N + > + struct ElementPrinter { + static void print( const Tuple&, std::ostream& ) {} + }; + +} + +template +struct StringMaker> { + + static std::string convert( const std::tuple& tuple ) + { + std::ostringstream os; + os << '{'; + TupleDetail::ElementPrinter>::print( tuple, os ); + os << " }"; + return os.str(); + } +}; +#endif // CATCH_CONFIG_CPP11_TUPLE + +namespace Detail { + template + std::string makeString( T const& value ) { + return StringMaker::convert( value ); + } +} // end namespace Detail + +/// \brief converts any type to a string +/// +/// The default template forwards on to ostringstream - except when an +/// ostringstream overload does not exist - in which case it attempts to detect +/// that and writes {?}. +/// Overload (not specialise) this template for custom typs that you don't want +/// to provide an ostream overload for. +template +std::string toString( T const& value ) { + return StringMaker::convert( value ); +} + + namespace Detail { + template + std::string rangeToString( InputIterator first, InputIterator last ) { + std::ostringstream oss; + oss << "{ "; + if( first != last ) { + oss << Catch::toString( *first ); + for( ++first ; first != last ; ++first ) + oss << ", " << Catch::toString( *first ); + } + oss << " }"; + return oss.str(); + } +} + +} // end namespace Catch + +namespace Catch { + +// Wraps the LHS of an expression and captures the operator and RHS (if any) - +// wrapping them all in a ResultBuilder object +template +class ExpressionLhs { + ExpressionLhs& operator = ( ExpressionLhs const& ); +# ifdef CATCH_CONFIG_CPP11_GENERATED_METHODS + ExpressionLhs& operator = ( ExpressionLhs && ) = delete; +# endif + +public: + ExpressionLhs( ResultBuilder& rb, T lhs ) : m_rb( rb ), m_lhs( lhs ) {} +# ifdef CATCH_CONFIG_CPP11_GENERATED_METHODS + ExpressionLhs( ExpressionLhs const& ) = default; + ExpressionLhs( ExpressionLhs && ) = default; +# endif + + template + ResultBuilder& operator == ( RhsT const& rhs ) { + return captureExpression( rhs ); + } + + template + ResultBuilder& operator != ( RhsT const& rhs ) { + return captureExpression( rhs ); + } + + template + ResultBuilder& operator < ( RhsT const& rhs ) { + return captureExpression( rhs ); + } + + template + ResultBuilder& operator > ( RhsT const& rhs ) { + return captureExpression( rhs ); + } + + template + ResultBuilder& operator <= ( RhsT const& rhs ) { + return captureExpression( rhs ); + } + + template + ResultBuilder& operator >= ( RhsT const& rhs ) { + return captureExpression( rhs ); + } + + ResultBuilder& operator == ( bool rhs ) { + return captureExpression( rhs ); + } + + ResultBuilder& operator != ( bool rhs ) { + return captureExpression( rhs ); + } + + void endExpression() { + bool value = m_lhs ? true : false; + m_rb + .setLhs( Catch::toString( value ) ) + .setResultType( value ) + .endExpression(); + } + + // Only simple binary expressions are allowed on the LHS. + // If more complex compositions are required then place the sub expression in parentheses + template STATIC_ASSERT_Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison& operator + ( RhsT const& ); + template STATIC_ASSERT_Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison& operator - ( RhsT const& ); + template STATIC_ASSERT_Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison& operator / ( RhsT const& ); + template STATIC_ASSERT_Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison& operator * ( RhsT const& ); + template STATIC_ASSERT_Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison& operator && ( RhsT const& ); + template STATIC_ASSERT_Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison& operator || ( RhsT const& ); + +private: + template + ResultBuilder& captureExpression( RhsT const& rhs ) { + return m_rb + .setResultType( Internal::compare( m_lhs, rhs ) ) + .setLhs( Catch::toString( m_lhs ) ) + .setRhs( Catch::toString( rhs ) ) + .setOp( Internal::OperatorTraits::getName() ); + } + +private: + ResultBuilder& m_rb; + T m_lhs; +}; + +} // end namespace Catch + + +namespace Catch { + + template + inline ExpressionLhs ResultBuilder::operator <= ( T const& operand ) { + return ExpressionLhs( *this, operand ); + } + + inline ExpressionLhs ResultBuilder::operator <= ( bool value ) { + return ExpressionLhs( *this, value ); + } + +} // namespace Catch + +// #included from: catch_message.h +#define TWOBLUECUBES_CATCH_MESSAGE_H_INCLUDED + +#include + +namespace Catch { + + struct MessageInfo { + MessageInfo( std::string const& _macroName, + SourceLineInfo const& _lineInfo, + ResultWas::OfType _type ); + + std::string macroName; + SourceLineInfo lineInfo; + ResultWas::OfType type; + std::string message; + unsigned int sequence; + + bool operator == ( MessageInfo const& other ) const { + return sequence == other.sequence; + } + bool operator < ( MessageInfo const& other ) const { + return sequence < other.sequence; + } + private: + static unsigned int globalCount; + }; + + struct MessageBuilder { + MessageBuilder( std::string const& macroName, + SourceLineInfo const& lineInfo, + ResultWas::OfType type ) + : m_info( macroName, lineInfo, type ) + {} + + template + MessageBuilder& operator << ( T const& value ) { + m_stream << value; + return *this; + } + + MessageInfo m_info; + std::ostringstream m_stream; + }; + + class ScopedMessage { + public: + ScopedMessage( MessageBuilder const& builder ); + ScopedMessage( ScopedMessage const& other ); + ~ScopedMessage(); + + MessageInfo m_info; + }; + +} // end namespace Catch + +// #included from: catch_interfaces_capture.h +#define TWOBLUECUBES_CATCH_INTERFACES_CAPTURE_H_INCLUDED + +#include + +namespace Catch { + + class TestCase; + class AssertionResult; + struct AssertionInfo; + struct SectionInfo; + struct SectionEndInfo; + struct MessageInfo; + class ScopedMessageBuilder; + struct Counts; + + struct IResultCapture { + + virtual ~IResultCapture(); + + virtual void assertionEnded( AssertionResult const& result ) = 0; + virtual bool sectionStarted( SectionInfo const& sectionInfo, + Counts& assertions ) = 0; + virtual void sectionEnded( SectionEndInfo const& endInfo ) = 0; + virtual void sectionEndedEarly( SectionEndInfo const& endInfo ) = 0; + virtual void pushScopedMessage( MessageInfo const& message ) = 0; + virtual void popScopedMessage( MessageInfo const& message ) = 0; + + virtual std::string getCurrentTestName() const = 0; + virtual const AssertionResult* getLastResult() const = 0; + + virtual void handleFatalErrorCondition( std::string const& message ) = 0; + }; + + IResultCapture& getResultCapture(); +} + +// #included from: catch_debugger.h +#define TWOBLUECUBES_CATCH_DEBUGGER_H_INCLUDED + +// #included from: catch_platform.h +#define TWOBLUECUBES_CATCH_PLATFORM_H_INCLUDED + +#if defined(__MAC_OS_X_VERSION_MIN_REQUIRED) +#define CATCH_PLATFORM_MAC +#elif defined(__IPHONE_OS_VERSION_MIN_REQUIRED) +#define CATCH_PLATFORM_IPHONE +#elif defined(WIN32) || defined(__WIN32__) || defined(_WIN32) || defined(_MSC_VER) +#define CATCH_PLATFORM_WINDOWS +#endif + +#include + +namespace Catch{ + + bool isDebuggerActive(); + void writeToDebugConsole( std::string const& text ); +} + +#ifdef CATCH_PLATFORM_MAC + + // The following code snippet based on: + // http://cocoawithlove.com/2008/03/break-into-debugger.html + #ifdef DEBUG + #if defined(__ppc64__) || defined(__ppc__) + #define CATCH_BREAK_INTO_DEBUGGER() \ + if( Catch::isDebuggerActive() ) { \ + __asm__("li r0, 20\nsc\nnop\nli r0, 37\nli r4, 2\nsc\nnop\n" \ + : : : "memory","r0","r3","r4" ); \ + } + #else + #define CATCH_BREAK_INTO_DEBUGGER() if( Catch::isDebuggerActive() ) {__asm__("int $3\n" : : );} + #endif + #endif + +#elif defined(_MSC_VER) + #define CATCH_BREAK_INTO_DEBUGGER() if( Catch::isDebuggerActive() ) { __debugbreak(); } +#elif defined(__MINGW32__) + extern "C" __declspec(dllimport) void __stdcall DebugBreak(); + #define CATCH_BREAK_INTO_DEBUGGER() if( Catch::isDebuggerActive() ) { DebugBreak(); } +#endif + +#ifndef CATCH_BREAK_INTO_DEBUGGER +#define CATCH_BREAK_INTO_DEBUGGER() Catch::alwaysTrue(); +#endif + +// #included from: catch_interfaces_runner.h +#define TWOBLUECUBES_CATCH_INTERFACES_RUNNER_H_INCLUDED + +namespace Catch { + class TestCase; + + struct IRunner { + virtual ~IRunner(); + virtual bool aborting() const = 0; + }; +} + +/////////////////////////////////////////////////////////////////////////////// +// In the event of a failure works out if the debugger needs to be invoked +// and/or an exception thrown and takes appropriate action. +// This needs to be done as a macro so the debugger will stop in the user +// source code rather than in Catch library code +#define INTERNAL_CATCH_REACT( resultBuilder ) \ + if( resultBuilder.shouldDebugBreak() ) CATCH_BREAK_INTO_DEBUGGER(); \ + resultBuilder.react(); + +/////////////////////////////////////////////////////////////////////////////// +#define INTERNAL_CATCH_TEST( expr, resultDisposition, macroName ) \ + do { \ + Catch::ResultBuilder __catchResult( macroName, CATCH_INTERNAL_LINEINFO, #expr, resultDisposition ); \ + try { \ + CATCH_INTERNAL_SUPPRESS_PARENTHESES_WARNINGS \ + ( __catchResult <= expr ).endExpression(); \ + } \ + catch( ... ) { \ + __catchResult.useActiveException( Catch::ResultDisposition::Normal ); \ + } \ + INTERNAL_CATCH_REACT( __catchResult ) \ + } while( Catch::isTrue( false && !!(expr) ) ) // expr here is never evaluated at runtime but it forces the compiler to give it a look + +/////////////////////////////////////////////////////////////////////////////// +#define INTERNAL_CATCH_IF( expr, resultDisposition, macroName ) \ + INTERNAL_CATCH_TEST( expr, resultDisposition, macroName ); \ + if( Catch::getResultCapture().getLastResult()->succeeded() ) + +/////////////////////////////////////////////////////////////////////////////// +#define INTERNAL_CATCH_ELSE( expr, resultDisposition, macroName ) \ + INTERNAL_CATCH_TEST( expr, resultDisposition, macroName ); \ + if( !Catch::getResultCapture().getLastResult()->succeeded() ) + +/////////////////////////////////////////////////////////////////////////////// +#define INTERNAL_CATCH_NO_THROW( expr, resultDisposition, macroName ) \ + do { \ + Catch::ResultBuilder __catchResult( macroName, CATCH_INTERNAL_LINEINFO, #expr, resultDisposition ); \ + try { \ + expr; \ + __catchResult.captureResult( Catch::ResultWas::Ok ); \ + } \ + catch( ... ) { \ + __catchResult.useActiveException( resultDisposition ); \ + } \ + INTERNAL_CATCH_REACT( __catchResult ) \ + } while( Catch::alwaysFalse() ) + +/////////////////////////////////////////////////////////////////////////////// +#define INTERNAL_CATCH_THROWS( expr, resultDisposition, matcher, macroName ) \ + do { \ + Catch::ResultBuilder __catchResult( macroName, CATCH_INTERNAL_LINEINFO, #expr, resultDisposition, #matcher ); \ + if( __catchResult.allowThrows() ) \ + try { \ + expr; \ + __catchResult.captureResult( Catch::ResultWas::DidntThrowException ); \ + } \ + catch( ... ) { \ + __catchResult.captureExpectedException( matcher ); \ + } \ + else \ + __catchResult.captureResult( Catch::ResultWas::Ok ); \ + INTERNAL_CATCH_REACT( __catchResult ) \ + } while( Catch::alwaysFalse() ) + +/////////////////////////////////////////////////////////////////////////////// +#define INTERNAL_CATCH_THROWS_AS( expr, exceptionType, resultDisposition, macroName ) \ + do { \ + Catch::ResultBuilder __catchResult( macroName, CATCH_INTERNAL_LINEINFO, #expr, resultDisposition ); \ + if( __catchResult.allowThrows() ) \ + try { \ + expr; \ + __catchResult.captureResult( Catch::ResultWas::DidntThrowException ); \ + } \ + catch( exceptionType ) { \ + __catchResult.captureResult( Catch::ResultWas::Ok ); \ + } \ + catch( ... ) { \ + __catchResult.useActiveException( resultDisposition ); \ + } \ + else \ + __catchResult.captureResult( Catch::ResultWas::Ok ); \ + INTERNAL_CATCH_REACT( __catchResult ) \ + } while( Catch::alwaysFalse() ) + +/////////////////////////////////////////////////////////////////////////////// +#ifdef CATCH_CONFIG_VARIADIC_MACROS + #define INTERNAL_CATCH_MSG( messageType, resultDisposition, macroName, ... ) \ + do { \ + Catch::ResultBuilder __catchResult( macroName, CATCH_INTERNAL_LINEINFO, "", resultDisposition ); \ + __catchResult << __VA_ARGS__ + ::Catch::StreamEndStop(); \ + __catchResult.captureResult( messageType ); \ + INTERNAL_CATCH_REACT( __catchResult ) \ + } while( Catch::alwaysFalse() ) +#else + #define INTERNAL_CATCH_MSG( messageType, resultDisposition, macroName, log ) \ + do { \ + Catch::ResultBuilder __catchResult( macroName, CATCH_INTERNAL_LINEINFO, "", resultDisposition ); \ + __catchResult << log + ::Catch::StreamEndStop(); \ + __catchResult.captureResult( messageType ); \ + INTERNAL_CATCH_REACT( __catchResult ) \ + } while( Catch::alwaysFalse() ) +#endif + +/////////////////////////////////////////////////////////////////////////////// +#define INTERNAL_CATCH_INFO( log, macroName ) \ + Catch::ScopedMessage INTERNAL_CATCH_UNIQUE_NAME( scopedMessage ) = Catch::MessageBuilder( macroName, CATCH_INTERNAL_LINEINFO, Catch::ResultWas::Info ) << log; + +/////////////////////////////////////////////////////////////////////////////// +#define INTERNAL_CHECK_THAT( arg, matcher, resultDisposition, macroName ) \ + do { \ + Catch::ResultBuilder __catchResult( macroName, CATCH_INTERNAL_LINEINFO, #arg ", " #matcher, resultDisposition ); \ + try { \ + std::string matcherAsString = (matcher).toString(); \ + __catchResult \ + .setLhs( Catch::toString( arg ) ) \ + .setRhs( matcherAsString == Catch::Detail::unprintableString ? #matcher : matcherAsString ) \ + .setOp( "matches" ) \ + .setResultType( (matcher).match( arg ) ); \ + __catchResult.captureExpression(); \ + } catch( ... ) { \ + __catchResult.useActiveException( resultDisposition | Catch::ResultDisposition::ContinueOnFailure ); \ + } \ + INTERNAL_CATCH_REACT( __catchResult ) \ + } while( Catch::alwaysFalse() ) + +// #included from: internal/catch_section.h +#define TWOBLUECUBES_CATCH_SECTION_H_INCLUDED + +// #included from: catch_section_info.h +#define TWOBLUECUBES_CATCH_SECTION_INFO_H_INCLUDED + +// #included from: catch_totals.hpp +#define TWOBLUECUBES_CATCH_TOTALS_HPP_INCLUDED + +#include + +namespace Catch { + + struct Counts { + Counts() : passed( 0 ), failed( 0 ), failedButOk( 0 ) {} + + Counts operator - ( Counts const& other ) const { + Counts diff; + diff.passed = passed - other.passed; + diff.failed = failed - other.failed; + diff.failedButOk = failedButOk - other.failedButOk; + return diff; + } + Counts& operator += ( Counts const& other ) { + passed += other.passed; + failed += other.failed; + failedButOk += other.failedButOk; + return *this; + } + + std::size_t total() const { + return passed + failed + failedButOk; + } + bool allPassed() const { + return failed == 0 && failedButOk == 0; + } + bool allOk() const { + return failed == 0; + } + + std::size_t passed; + std::size_t failed; + std::size_t failedButOk; + }; + + struct Totals { + + Totals operator - ( Totals const& other ) const { + Totals diff; + diff.assertions = assertions - other.assertions; + diff.testCases = testCases - other.testCases; + return diff; + } + + Totals delta( Totals const& prevTotals ) const { + Totals diff = *this - prevTotals; + if( diff.assertions.failed > 0 ) + ++diff.testCases.failed; + else if( diff.assertions.failedButOk > 0 ) + ++diff.testCases.failedButOk; + else + ++diff.testCases.passed; + return diff; + } + + Totals& operator += ( Totals const& other ) { + assertions += other.assertions; + testCases += other.testCases; + return *this; + } + + Counts assertions; + Counts testCases; + }; +} + +namespace Catch { + + struct SectionInfo { + SectionInfo + ( SourceLineInfo const& _lineInfo, + std::string const& _name, + std::string const& _description = std::string() ); + + std::string name; + std::string description; + SourceLineInfo lineInfo; + }; + + struct SectionEndInfo { + SectionEndInfo( SectionInfo const& _sectionInfo, Counts const& _prevAssertions, double _durationInSeconds ) + : sectionInfo( _sectionInfo ), prevAssertions( _prevAssertions ), durationInSeconds( _durationInSeconds ) + {} + + SectionInfo sectionInfo; + Counts prevAssertions; + double durationInSeconds; + }; + +} // end namespace Catch + +// #included from: catch_timer.h +#define TWOBLUECUBES_CATCH_TIMER_H_INCLUDED + +#ifdef CATCH_PLATFORM_WINDOWS +typedef unsigned long long uint64_t; +#else +#include +#endif + +namespace Catch { + + class Timer { + public: + Timer() : m_ticks( 0 ) {} + void start(); + unsigned int getElapsedMicroseconds() const; + unsigned int getElapsedMilliseconds() const; + double getElapsedSeconds() const; + + private: + uint64_t m_ticks; + }; + +} // namespace Catch + +#include + +namespace Catch { + + class Section : NonCopyable { + public: + Section( SectionInfo const& info ); + ~Section(); + + // This indicates whether the section should be executed or not + operator bool() const; + + private: + SectionInfo m_info; + + std::string m_name; + Counts m_assertions; + bool m_sectionIncluded; + Timer m_timer; + }; + +} // end namespace Catch + +#ifdef CATCH_CONFIG_VARIADIC_MACROS + #define INTERNAL_CATCH_SECTION( ... ) \ + if( Catch::Section const& INTERNAL_CATCH_UNIQUE_NAME( catch_internal_Section ) = Catch::SectionInfo( CATCH_INTERNAL_LINEINFO, __VA_ARGS__ ) ) +#else + #define INTERNAL_CATCH_SECTION( name, desc ) \ + if( Catch::Section const& INTERNAL_CATCH_UNIQUE_NAME( catch_internal_Section ) = Catch::SectionInfo( CATCH_INTERNAL_LINEINFO, name, desc ) ) +#endif + +// #included from: internal/catch_generators.hpp +#define TWOBLUECUBES_CATCH_GENERATORS_HPP_INCLUDED + +#include +#include +#include +#include + +namespace Catch { + +template +struct IGenerator { + virtual ~IGenerator() {} + virtual T getValue( std::size_t index ) const = 0; + virtual std::size_t size () const = 0; +}; + +template +class BetweenGenerator : public IGenerator { +public: + BetweenGenerator( T from, T to ) : m_from( from ), m_to( to ){} + + virtual T getValue( std::size_t index ) const { + return m_from+static_cast( index ); + } + + virtual std::size_t size() const { + return static_cast( 1+m_to-m_from ); + } + +private: + + T m_from; + T m_to; +}; + +template +class ValuesGenerator : public IGenerator { +public: + ValuesGenerator(){} + + void add( T value ) { + m_values.push_back( value ); + } + + virtual T getValue( std::size_t index ) const { + return m_values[index]; + } + + virtual std::size_t size() const { + return m_values.size(); + } + +private: + std::vector m_values; +}; + +template +class CompositeGenerator { +public: + CompositeGenerator() : m_totalSize( 0 ) {} + + // *** Move semantics, similar to auto_ptr *** + CompositeGenerator( CompositeGenerator& other ) + : m_fileInfo( other.m_fileInfo ), + m_totalSize( 0 ) + { + move( other ); + } + + CompositeGenerator& setFileInfo( const char* fileInfo ) { + m_fileInfo = fileInfo; + return *this; + } + + ~CompositeGenerator() { + deleteAll( m_composed ); + } + + operator T () const { + size_t overallIndex = getCurrentContext().getGeneratorIndex( m_fileInfo, m_totalSize ); + + typename std::vector*>::const_iterator it = m_composed.begin(); + typename std::vector*>::const_iterator itEnd = m_composed.end(); + for( size_t index = 0; it != itEnd; ++it ) + { + const IGenerator* generator = *it; + if( overallIndex >= index && overallIndex < index + generator->size() ) + { + return generator->getValue( overallIndex-index ); + } + index += generator->size(); + } + CATCH_INTERNAL_ERROR( "Indexed past end of generated range" ); + return T(); // Suppress spurious "not all control paths return a value" warning in Visual Studio - if you know how to fix this please do so + } + + void add( const IGenerator* generator ) { + m_totalSize += generator->size(); + m_composed.push_back( generator ); + } + + CompositeGenerator& then( CompositeGenerator& other ) { + move( other ); + return *this; + } + + CompositeGenerator& then( T value ) { + ValuesGenerator* valuesGen = new ValuesGenerator(); + valuesGen->add( value ); + add( valuesGen ); + return *this; + } + +private: + + void move( CompositeGenerator& other ) { + std::copy( other.m_composed.begin(), other.m_composed.end(), std::back_inserter( m_composed ) ); + m_totalSize += other.m_totalSize; + other.m_composed.clear(); + } + + std::vector*> m_composed; + std::string m_fileInfo; + size_t m_totalSize; +}; + +namespace Generators +{ + template + CompositeGenerator between( T from, T to ) { + CompositeGenerator generators; + generators.add( new BetweenGenerator( from, to ) ); + return generators; + } + + template + CompositeGenerator values( T val1, T val2 ) { + CompositeGenerator generators; + ValuesGenerator* valuesGen = new ValuesGenerator(); + valuesGen->add( val1 ); + valuesGen->add( val2 ); + generators.add( valuesGen ); + return generators; + } + + template + CompositeGenerator values( T val1, T val2, T val3 ){ + CompositeGenerator generators; + ValuesGenerator* valuesGen = new ValuesGenerator(); + valuesGen->add( val1 ); + valuesGen->add( val2 ); + valuesGen->add( val3 ); + generators.add( valuesGen ); + return generators; + } + + template + CompositeGenerator values( T val1, T val2, T val3, T val4 ) { + CompositeGenerator generators; + ValuesGenerator* valuesGen = new ValuesGenerator(); + valuesGen->add( val1 ); + valuesGen->add( val2 ); + valuesGen->add( val3 ); + valuesGen->add( val4 ); + generators.add( valuesGen ); + return generators; + } + +} // end namespace Generators + +using namespace Generators; + +} // end namespace Catch + +#define INTERNAL_CATCH_LINESTR2( line ) #line +#define INTERNAL_CATCH_LINESTR( line ) INTERNAL_CATCH_LINESTR2( line ) + +#define INTERNAL_CATCH_GENERATE( expr ) expr.setFileInfo( __FILE__ "(" INTERNAL_CATCH_LINESTR( __LINE__ ) ")" ) + +// #included from: internal/catch_interfaces_exception.h +#define TWOBLUECUBES_CATCH_INTERFACES_EXCEPTION_H_INCLUDED + +#include +#include + +// #included from: catch_interfaces_registry_hub.h +#define TWOBLUECUBES_CATCH_INTERFACES_REGISTRY_HUB_H_INCLUDED + +#include + +namespace Catch { + + class TestCase; + struct ITestCaseRegistry; + struct IExceptionTranslatorRegistry; + struct IExceptionTranslator; + struct IReporterRegistry; + struct IReporterFactory; + + struct IRegistryHub { + virtual ~IRegistryHub(); + + virtual IReporterRegistry const& getReporterRegistry() const = 0; + virtual ITestCaseRegistry const& getTestCaseRegistry() const = 0; + virtual IExceptionTranslatorRegistry& getExceptionTranslatorRegistry() = 0; + }; + + struct IMutableRegistryHub { + virtual ~IMutableRegistryHub(); + virtual void registerReporter( std::string const& name, Ptr const& factory ) = 0; + virtual void registerListener( Ptr const& factory ) = 0; + virtual void registerTest( TestCase const& testInfo ) = 0; + virtual void registerTranslator( const IExceptionTranslator* translator ) = 0; + }; + + IRegistryHub& getRegistryHub(); + IMutableRegistryHub& getMutableRegistryHub(); + void cleanUp(); + std::string translateActiveException(); + +} + +namespace Catch { + + typedef std::string(*exceptionTranslateFunction)(); + + struct IExceptionTranslator; + typedef std::vector ExceptionTranslators; + + struct IExceptionTranslator { + virtual ~IExceptionTranslator(); + virtual std::string translate( ExceptionTranslators::const_iterator it, ExceptionTranslators::const_iterator itEnd ) const = 0; + }; + + struct IExceptionTranslatorRegistry { + virtual ~IExceptionTranslatorRegistry(); + + virtual std::string translateActiveException() const = 0; + }; + + class ExceptionTranslatorRegistrar { + template + class ExceptionTranslator : public IExceptionTranslator { + public: + + ExceptionTranslator( std::string(*translateFunction)( T& ) ) + : m_translateFunction( translateFunction ) + {} + + virtual std::string translate( ExceptionTranslators::const_iterator it, ExceptionTranslators::const_iterator itEnd ) const CATCH_OVERRIDE { + try { + if( it == itEnd ) + throw; + else + return (*it)->translate( it+1, itEnd ); + } + catch( T& ex ) { + return m_translateFunction( ex ); + } + } + + protected: + std::string(*m_translateFunction)( T& ); + }; + + public: + template + ExceptionTranslatorRegistrar( std::string(*translateFunction)( T& ) ) { + getMutableRegistryHub().registerTranslator + ( new ExceptionTranslator( translateFunction ) ); + } + }; +} + +/////////////////////////////////////////////////////////////////////////////// +#define INTERNAL_CATCH_TRANSLATE_EXCEPTION2( translatorName, signature ) \ + static std::string translatorName( signature ); \ + namespace{ Catch::ExceptionTranslatorRegistrar INTERNAL_CATCH_UNIQUE_NAME( catch_internal_ExceptionRegistrar )( &translatorName ); }\ + static std::string translatorName( signature ) + +#define INTERNAL_CATCH_TRANSLATE_EXCEPTION( signature ) INTERNAL_CATCH_TRANSLATE_EXCEPTION2( INTERNAL_CATCH_UNIQUE_NAME( catch_internal_ExceptionTranslator ), signature ) + +// #included from: internal/catch_approx.hpp +#define TWOBLUECUBES_CATCH_APPROX_HPP_INCLUDED + +#include +#include + +namespace Catch { +namespace Detail { + + class Approx { + public: + explicit Approx ( double value ) + : m_epsilon( std::numeric_limits::epsilon()*100 ), + m_scale( 1.0 ), + m_value( value ) + {} + + Approx( Approx const& other ) + : m_epsilon( other.m_epsilon ), + m_scale( other.m_scale ), + m_value( other.m_value ) + {} + + static Approx custom() { + return Approx( 0 ); + } + + Approx operator()( double value ) { + Approx approx( value ); + approx.epsilon( m_epsilon ); + approx.scale( m_scale ); + return approx; + } + + friend bool operator == ( double lhs, Approx const& rhs ) { + // Thanks to Richard Harris for his help refining this formula + return fabs( lhs - rhs.m_value ) < rhs.m_epsilon * (rhs.m_scale + (std::max)( fabs(lhs), fabs(rhs.m_value) ) ); + } + + friend bool operator == ( Approx const& lhs, double rhs ) { + return operator==( rhs, lhs ); + } + + friend bool operator != ( double lhs, Approx const& rhs ) { + return !operator==( lhs, rhs ); + } + + friend bool operator != ( Approx const& lhs, double rhs ) { + return !operator==( rhs, lhs ); + } + + Approx& epsilon( double newEpsilon ) { + m_epsilon = newEpsilon; + return *this; + } + + Approx& scale( double newScale ) { + m_scale = newScale; + return *this; + } + + std::string toString() const { + std::ostringstream oss; + oss << "Approx( " << Catch::toString( m_value ) << " )"; + return oss.str(); + } + + private: + double m_epsilon; + double m_scale; + double m_value; + }; +} + +template<> +inline std::string toString( Detail::Approx const& value ) { + return value.toString(); +} + +} // end namespace Catch + +// #included from: internal/catch_interfaces_tag_alias_registry.h +#define TWOBLUECUBES_CATCH_INTERFACES_TAG_ALIAS_REGISTRY_H_INCLUDED + +// #included from: catch_tag_alias.h +#define TWOBLUECUBES_CATCH_TAG_ALIAS_H_INCLUDED + +#include + +namespace Catch { + + struct TagAlias { + TagAlias( std::string _tag, SourceLineInfo _lineInfo ) : tag( _tag ), lineInfo( _lineInfo ) {} + + std::string tag; + SourceLineInfo lineInfo; + }; + + struct RegistrarForTagAliases { + RegistrarForTagAliases( char const* alias, char const* tag, SourceLineInfo const& lineInfo ); + }; + +} // end namespace Catch + +#define CATCH_REGISTER_TAG_ALIAS( alias, spec ) namespace{ Catch::RegistrarForTagAliases INTERNAL_CATCH_UNIQUE_NAME( AutoRegisterTagAlias )( alias, spec, CATCH_INTERNAL_LINEINFO ); } +// #included from: catch_option.hpp +#define TWOBLUECUBES_CATCH_OPTION_HPP_INCLUDED + +namespace Catch { + + // An optional type + template + class Option { + public: + Option() : nullableValue( CATCH_NULL ) {} + Option( T const& _value ) + : nullableValue( new( storage ) T( _value ) ) + {} + Option( Option const& _other ) + : nullableValue( _other ? new( storage ) T( *_other ) : CATCH_NULL ) + {} + + ~Option() { + reset(); + } + + Option& operator= ( Option const& _other ) { + if( &_other != this ) { + reset(); + if( _other ) + nullableValue = new( storage ) T( *_other ); + } + return *this; + } + Option& operator = ( T const& _value ) { + reset(); + nullableValue = new( storage ) T( _value ); + return *this; + } + + void reset() { + if( nullableValue ) + nullableValue->~T(); + nullableValue = CATCH_NULL; + } + + T& operator*() { return *nullableValue; } + T const& operator*() const { return *nullableValue; } + T* operator->() { return nullableValue; } + const T* operator->() const { return nullableValue; } + + T valueOr( T const& defaultValue ) const { + return nullableValue ? *nullableValue : defaultValue; + } + + bool some() const { return nullableValue != CATCH_NULL; } + bool none() const { return nullableValue == CATCH_NULL; } + + bool operator !() const { return nullableValue == CATCH_NULL; } + operator SafeBool::type() const { + return SafeBool::makeSafe( some() ); + } + + private: + T* nullableValue; + char storage[sizeof(T)]; + }; + +} // end namespace Catch + +namespace Catch { + + struct ITagAliasRegistry { + virtual ~ITagAliasRegistry(); + virtual Option find( std::string const& alias ) const = 0; + virtual std::string expandAliases( std::string const& unexpandedTestSpec ) const = 0; + + static ITagAliasRegistry const& get(); + }; + +} // end namespace Catch + +// These files are included here so the single_include script doesn't put them +// in the conditionally compiled sections +// #included from: internal/catch_test_case_info.h +#define TWOBLUECUBES_CATCH_TEST_CASE_INFO_H_INCLUDED + +#include +#include + +#ifdef __clang__ +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wpadded" +#endif + +namespace Catch { + + struct ITestCase; + + struct TestCaseInfo { + enum SpecialProperties{ + None = 0, + IsHidden = 1 << 1, + ShouldFail = 1 << 2, + MayFail = 1 << 3, + Throws = 1 << 4 + }; + + TestCaseInfo( std::string const& _name, + std::string const& _className, + std::string const& _description, + std::set const& _tags, + SourceLineInfo const& _lineInfo ); + + TestCaseInfo( TestCaseInfo const& other ); + + friend void setTags( TestCaseInfo& testCaseInfo, std::set const& tags ); + + bool isHidden() const; + bool throws() const; + bool okToFail() const; + bool expectedToFail() const; + + std::string name; + std::string className; + std::string description; + std::set tags; + std::set lcaseTags; + std::string tagsAsString; + SourceLineInfo lineInfo; + SpecialProperties properties; + }; + + class TestCase : public TestCaseInfo { + public: + + TestCase( ITestCase* testCase, TestCaseInfo const& info ); + TestCase( TestCase const& other ); + + TestCase withName( std::string const& _newName ) const; + + void invoke() const; + + TestCaseInfo const& getTestCaseInfo() const; + + void swap( TestCase& other ); + bool operator == ( TestCase const& other ) const; + bool operator < ( TestCase const& other ) const; + TestCase& operator = ( TestCase const& other ); + + private: + Ptr test; + }; + + TestCase makeTestCase( ITestCase* testCase, + std::string const& className, + std::string const& name, + std::string const& description, + SourceLineInfo const& lineInfo ); +} + +#ifdef __clang__ +#pragma clang diagnostic pop +#endif + + +#ifdef __OBJC__ +// #included from: internal/catch_objc.hpp +#define TWOBLUECUBES_CATCH_OBJC_HPP_INCLUDED + +#import + +#include + +// NB. Any general catch headers included here must be included +// in catch.hpp first to make sure they are included by the single +// header for non obj-usage + +/////////////////////////////////////////////////////////////////////////////// +// This protocol is really only here for (self) documenting purposes, since +// all its methods are optional. +@protocol OcFixture + +@optional + +-(void) setUp; +-(void) tearDown; + +@end + +namespace Catch { + + class OcMethod : public SharedImpl { + + public: + OcMethod( Class cls, SEL sel ) : m_cls( cls ), m_sel( sel ) {} + + virtual void invoke() const { + id obj = [[m_cls alloc] init]; + + performOptionalSelector( obj, @selector(setUp) ); + performOptionalSelector( obj, m_sel ); + performOptionalSelector( obj, @selector(tearDown) ); + + arcSafeRelease( obj ); + } + private: + virtual ~OcMethod() {} + + Class m_cls; + SEL m_sel; + }; + + namespace Detail{ + + inline std::string getAnnotation( Class cls, + std::string const& annotationName, + std::string const& testCaseName ) { + NSString* selStr = [[NSString alloc] initWithFormat:@"Catch_%s_%s", annotationName.c_str(), testCaseName.c_str()]; + SEL sel = NSSelectorFromString( selStr ); + arcSafeRelease( selStr ); + id value = performOptionalSelector( cls, sel ); + if( value ) + return [(NSString*)value UTF8String]; + return ""; + } + } + + inline size_t registerTestMethods() { + size_t noTestMethods = 0; + int noClasses = objc_getClassList( CATCH_NULL, 0 ); + + Class* classes = (CATCH_UNSAFE_UNRETAINED Class *)malloc( sizeof(Class) * noClasses); + objc_getClassList( classes, noClasses ); + + for( int c = 0; c < noClasses; c++ ) { + Class cls = classes[c]; + { + u_int count; + Method* methods = class_copyMethodList( cls, &count ); + for( u_int m = 0; m < count ; m++ ) { + SEL selector = method_getName(methods[m]); + std::string methodName = sel_getName(selector); + if( startsWith( methodName, "Catch_TestCase_" ) ) { + std::string testCaseName = methodName.substr( 15 ); + std::string name = Detail::getAnnotation( cls, "Name", testCaseName ); + std::string desc = Detail::getAnnotation( cls, "Description", testCaseName ); + const char* className = class_getName( cls ); + + getMutableRegistryHub().registerTest( makeTestCase( new OcMethod( cls, selector ), className, name.c_str(), desc.c_str(), SourceLineInfo() ) ); + noTestMethods++; + } + } + free(methods); + } + } + return noTestMethods; + } + + namespace Matchers { + namespace Impl { + namespace NSStringMatchers { + + template + struct StringHolder : MatcherImpl{ + StringHolder( NSString* substr ) : m_substr( [substr copy] ){} + StringHolder( StringHolder const& other ) : m_substr( [other.m_substr copy] ){} + StringHolder() { + arcSafeRelease( m_substr ); + } + + NSString* m_substr; + }; + + struct Equals : StringHolder { + Equals( NSString* substr ) : StringHolder( substr ){} + + virtual bool match( ExpressionType const& str ) const { + return (str != nil || m_substr == nil ) && + [str isEqualToString:m_substr]; + } + + virtual std::string toString() const { + return "equals string: " + Catch::toString( m_substr ); + } + }; + + struct Contains : StringHolder { + Contains( NSString* substr ) : StringHolder( substr ){} + + virtual bool match( ExpressionType const& str ) const { + return (str != nil || m_substr == nil ) && + [str rangeOfString:m_substr].location != NSNotFound; + } + + virtual std::string toString() const { + return "contains string: " + Catch::toString( m_substr ); + } + }; + + struct StartsWith : StringHolder { + StartsWith( NSString* substr ) : StringHolder( substr ){} + + virtual bool match( ExpressionType const& str ) const { + return (str != nil || m_substr == nil ) && + [str rangeOfString:m_substr].location == 0; + } + + virtual std::string toString() const { + return "starts with: " + Catch::toString( m_substr ); + } + }; + struct EndsWith : StringHolder { + EndsWith( NSString* substr ) : StringHolder( substr ){} + + virtual bool match( ExpressionType const& str ) const { + return (str != nil || m_substr == nil ) && + [str rangeOfString:m_substr].location == [str length] - [m_substr length]; + } + + virtual std::string toString() const { + return "ends with: " + Catch::toString( m_substr ); + } + }; + + } // namespace NSStringMatchers + } // namespace Impl + + inline Impl::NSStringMatchers::Equals + Equals( NSString* substr ){ return Impl::NSStringMatchers::Equals( substr ); } + + inline Impl::NSStringMatchers::Contains + Contains( NSString* substr ){ return Impl::NSStringMatchers::Contains( substr ); } + + inline Impl::NSStringMatchers::StartsWith + StartsWith( NSString* substr ){ return Impl::NSStringMatchers::StartsWith( substr ); } + + inline Impl::NSStringMatchers::EndsWith + EndsWith( NSString* substr ){ return Impl::NSStringMatchers::EndsWith( substr ); } + + } // namespace Matchers + + using namespace Matchers; + +} // namespace Catch + +/////////////////////////////////////////////////////////////////////////////// +#define OC_TEST_CASE( name, desc )\ ++(NSString*) INTERNAL_CATCH_UNIQUE_NAME( Catch_Name_test ) \ +{\ +return @ name; \ +}\ ++(NSString*) INTERNAL_CATCH_UNIQUE_NAME( Catch_Description_test ) \ +{ \ +return @ desc; \ +} \ +-(void) INTERNAL_CATCH_UNIQUE_NAME( Catch_TestCase_test ) + +#endif + +#ifdef CATCH_IMPL +// #included from: internal/catch_impl.hpp +#define TWOBLUECUBES_CATCH_IMPL_HPP_INCLUDED + +// Collect all the implementation files together here +// These are the equivalent of what would usually be cpp files + +#ifdef __clang__ +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wweak-vtables" +#endif + +// #included from: ../catch_session.hpp +#define TWOBLUECUBES_CATCH_RUNNER_HPP_INCLUDED + +// #included from: internal/catch_commandline.hpp +#define TWOBLUECUBES_CATCH_COMMANDLINE_HPP_INCLUDED + +// #included from: catch_config.hpp +#define TWOBLUECUBES_CATCH_CONFIG_HPP_INCLUDED + +// #included from: catch_test_spec_parser.hpp +#define TWOBLUECUBES_CATCH_TEST_SPEC_PARSER_HPP_INCLUDED + +#ifdef __clang__ +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wpadded" +#endif + +// #included from: catch_test_spec.hpp +#define TWOBLUECUBES_CATCH_TEST_SPEC_HPP_INCLUDED + +#ifdef __clang__ +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wpadded" +#endif + +// #included from: catch_wildcard_pattern.hpp +#define TWOBLUECUBES_CATCH_WILDCARD_PATTERN_HPP_INCLUDED + +namespace Catch +{ + class WildcardPattern { + enum WildcardPosition { + NoWildcard = 0, + WildcardAtStart = 1, + WildcardAtEnd = 2, + WildcardAtBothEnds = WildcardAtStart | WildcardAtEnd + }; + + public: + + WildcardPattern( std::string const& pattern, CaseSensitive::Choice caseSensitivity ) + : m_caseSensitivity( caseSensitivity ), + m_wildcard( NoWildcard ), + m_pattern( adjustCase( pattern ) ) + { + if( startsWith( m_pattern, "*" ) ) { + m_pattern = m_pattern.substr( 1 ); + m_wildcard = WildcardAtStart; + } + if( endsWith( m_pattern, "*" ) ) { + m_pattern = m_pattern.substr( 0, m_pattern.size()-1 ); + m_wildcard = static_cast( m_wildcard | WildcardAtEnd ); + } + } + virtual ~WildcardPattern(); + virtual bool matches( std::string const& str ) const { + switch( m_wildcard ) { + case NoWildcard: + return m_pattern == adjustCase( str ); + case WildcardAtStart: + return endsWith( adjustCase( str ), m_pattern ); + case WildcardAtEnd: + return startsWith( adjustCase( str ), m_pattern ); + case WildcardAtBothEnds: + return contains( adjustCase( str ), m_pattern ); + } + +#ifdef __clang__ +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wunreachable-code" +#endif + throw std::logic_error( "Unknown enum" ); +#ifdef __clang__ +#pragma clang diagnostic pop +#endif + } + private: + std::string adjustCase( std::string const& str ) const { + return m_caseSensitivity == CaseSensitive::No ? toLower( str ) : str; + } + CaseSensitive::Choice m_caseSensitivity; + WildcardPosition m_wildcard; + std::string m_pattern; + }; +} + +#include +#include + +namespace Catch { + + class TestSpec { + struct Pattern : SharedImpl<> { + virtual ~Pattern(); + virtual bool matches( TestCaseInfo const& testCase ) const = 0; + }; + class NamePattern : public Pattern { + public: + NamePattern( std::string const& name ) + : m_wildcardPattern( toLower( name ), CaseSensitive::No ) + {} + virtual ~NamePattern(); + virtual bool matches( TestCaseInfo const& testCase ) const { + return m_wildcardPattern.matches( toLower( testCase.name ) ); + } + private: + WildcardPattern m_wildcardPattern; + }; + + class TagPattern : public Pattern { + public: + TagPattern( std::string const& tag ) : m_tag( toLower( tag ) ) {} + virtual ~TagPattern(); + virtual bool matches( TestCaseInfo const& testCase ) const { + return testCase.lcaseTags.find( m_tag ) != testCase.lcaseTags.end(); + } + private: + std::string m_tag; + }; + + class ExcludedPattern : public Pattern { + public: + ExcludedPattern( Ptr const& underlyingPattern ) : m_underlyingPattern( underlyingPattern ) {} + virtual ~ExcludedPattern(); + virtual bool matches( TestCaseInfo const& testCase ) const { return !m_underlyingPattern->matches( testCase ); } + private: + Ptr m_underlyingPattern; + }; + + struct Filter { + std::vector > m_patterns; + + bool matches( TestCaseInfo const& testCase ) const { + // All patterns in a filter must match for the filter to be a match + for( std::vector >::const_iterator it = m_patterns.begin(), itEnd = m_patterns.end(); it != itEnd; ++it ) + if( !(*it)->matches( testCase ) ) + return false; + return true; + } + }; + + public: + bool hasFilters() const { + return !m_filters.empty(); + } + bool matches( TestCaseInfo const& testCase ) const { + // A TestSpec matches if any filter matches + for( std::vector::const_iterator it = m_filters.begin(), itEnd = m_filters.end(); it != itEnd; ++it ) + if( it->matches( testCase ) ) + return true; + return false; + } + + private: + std::vector m_filters; + + friend class TestSpecParser; + }; +} + +#ifdef __clang__ +#pragma clang diagnostic pop +#endif + +namespace Catch { + + class TestSpecParser { + enum Mode{ None, Name, QuotedName, Tag }; + Mode m_mode; + bool m_exclusion; + std::size_t m_start, m_pos; + std::string m_arg; + TestSpec::Filter m_currentFilter; + TestSpec m_testSpec; + ITagAliasRegistry const* m_tagAliases; + + public: + TestSpecParser( ITagAliasRegistry const& tagAliases ) : m_tagAliases( &tagAliases ) {} + + TestSpecParser& parse( std::string const& arg ) { + m_mode = None; + m_exclusion = false; + m_start = std::string::npos; + m_arg = m_tagAliases->expandAliases( arg ); + for( m_pos = 0; m_pos < m_arg.size(); ++m_pos ) + visitChar( m_arg[m_pos] ); + if( m_mode == Name ) + addPattern(); + return *this; + } + TestSpec testSpec() { + addFilter(); + return m_testSpec; + } + private: + void visitChar( char c ) { + if( m_mode == None ) { + switch( c ) { + case ' ': return; + case '~': m_exclusion = true; return; + case '[': return startNewMode( Tag, ++m_pos ); + case '"': return startNewMode( QuotedName, ++m_pos ); + default: startNewMode( Name, m_pos ); break; + } + } + if( m_mode == Name ) { + if( c == ',' ) { + addPattern(); + addFilter(); + } + else if( c == '[' ) { + if( subString() == "exclude:" ) + m_exclusion = true; + else + addPattern(); + startNewMode( Tag, ++m_pos ); + } + } + else if( m_mode == QuotedName && c == '"' ) + addPattern(); + else if( m_mode == Tag && c == ']' ) + addPattern(); + } + void startNewMode( Mode mode, std::size_t start ) { + m_mode = mode; + m_start = start; + } + std::string subString() const { return m_arg.substr( m_start, m_pos - m_start ); } + template + void addPattern() { + std::string token = subString(); + if( startsWith( token, "exclude:" ) ) { + m_exclusion = true; + token = token.substr( 8 ); + } + if( !token.empty() ) { + Ptr pattern = new T( token ); + if( m_exclusion ) + pattern = new TestSpec::ExcludedPattern( pattern ); + m_currentFilter.m_patterns.push_back( pattern ); + } + m_exclusion = false; + m_mode = None; + } + void addFilter() { + if( !m_currentFilter.m_patterns.empty() ) { + m_testSpec.m_filters.push_back( m_currentFilter ); + m_currentFilter = TestSpec::Filter(); + } + } + }; + inline TestSpec parseTestSpec( std::string const& arg ) { + return TestSpecParser( ITagAliasRegistry::get() ).parse( arg ).testSpec(); + } + +} // namespace Catch + +#ifdef __clang__ +#pragma clang diagnostic pop +#endif + +// #included from: catch_interfaces_config.h +#define TWOBLUECUBES_CATCH_INTERFACES_CONFIG_H_INCLUDED + +#include +#include +#include + +namespace Catch { + + struct Verbosity { enum Level { + NoOutput = 0, + Quiet, + Normal + }; }; + + struct WarnAbout { enum What { + Nothing = 0x00, + NoAssertions = 0x01 + }; }; + + struct ShowDurations { enum OrNot { + DefaultForReporter, + Always, + Never + }; }; + struct RunTests { enum InWhatOrder { + InDeclarationOrder, + InLexicographicalOrder, + InRandomOrder + }; }; + struct UseColour { enum YesOrNo { + Auto, + Yes, + No + }; }; + + class TestSpec; + + struct IConfig : IShared { + + virtual ~IConfig(); + + virtual bool allowThrows() const = 0; + virtual std::ostream& stream() const = 0; + virtual std::string name() const = 0; + virtual bool includeSuccessfulResults() const = 0; + virtual bool shouldDebugBreak() const = 0; + virtual bool warnAboutMissingAssertions() const = 0; + virtual int abortAfter() const = 0; + virtual bool showInvisibles() const = 0; + virtual ShowDurations::OrNot showDurations() const = 0; + virtual TestSpec const& testSpec() const = 0; + virtual RunTests::InWhatOrder runOrder() const = 0; + virtual unsigned int rngSeed() const = 0; + virtual UseColour::YesOrNo useColour() const = 0; + }; +} + +// #included from: catch_stream.h +#define TWOBLUECUBES_CATCH_STREAM_H_INCLUDED + +// #included from: catch_streambuf.h +#define TWOBLUECUBES_CATCH_STREAMBUF_H_INCLUDED + +#include + +namespace Catch { + + class StreamBufBase : public std::streambuf { + public: + virtual ~StreamBufBase() CATCH_NOEXCEPT; + }; +} + +#include +#include +#include + +namespace Catch { + + std::ostream& cout(); + std::ostream& cerr(); + + struct IStream { + virtual ~IStream() CATCH_NOEXCEPT; + virtual std::ostream& stream() const = 0; + }; + + class FileStream : public IStream { + mutable std::ofstream m_ofs; + public: + FileStream( std::string const& filename ); + virtual ~FileStream() CATCH_NOEXCEPT; + public: // IStream + virtual std::ostream& stream() const CATCH_OVERRIDE; + }; + + class CoutStream : public IStream { + mutable std::ostream m_os; + public: + CoutStream(); + virtual ~CoutStream() CATCH_NOEXCEPT; + + public: // IStream + virtual std::ostream& stream() const CATCH_OVERRIDE; + }; + + class DebugOutStream : public IStream { + CATCH_AUTO_PTR( StreamBufBase ) m_streamBuf; + mutable std::ostream m_os; + public: + DebugOutStream(); + virtual ~DebugOutStream() CATCH_NOEXCEPT; + + public: // IStream + virtual std::ostream& stream() const CATCH_OVERRIDE; + }; +} + +#include +#include +#include +#include +#include + +#ifndef CATCH_CONFIG_CONSOLE_WIDTH +#define CATCH_CONFIG_CONSOLE_WIDTH 80 +#endif + +namespace Catch { + + struct ConfigData { + + ConfigData() + : listTests( false ), + listTags( false ), + listReporters( false ), + listTestNamesOnly( false ), + showSuccessfulTests( false ), + shouldDebugBreak( false ), + noThrow( false ), + showHelp( false ), + showInvisibles( false ), + filenamesAsTags( false ), + abortAfter( -1 ), + rngSeed( 0 ), + verbosity( Verbosity::Normal ), + warnings( WarnAbout::Nothing ), + showDurations( ShowDurations::DefaultForReporter ), + runOrder( RunTests::InDeclarationOrder ), + useColour( UseColour::Auto ) + {} + + bool listTests; + bool listTags; + bool listReporters; + bool listTestNamesOnly; + + bool showSuccessfulTests; + bool shouldDebugBreak; + bool noThrow; + bool showHelp; + bool showInvisibles; + bool filenamesAsTags; + + int abortAfter; + unsigned int rngSeed; + + Verbosity::Level verbosity; + WarnAbout::What warnings; + ShowDurations::OrNot showDurations; + RunTests::InWhatOrder runOrder; + UseColour::YesOrNo useColour; + + std::string outputFilename; + std::string name; + std::string processName; + + std::vector reporterNames; + std::vector testsOrTags; + }; + + class Config : public SharedImpl { + private: + Config( Config const& other ); + Config& operator = ( Config const& other ); + virtual void dummy(); + public: + + Config() + {} + + Config( ConfigData const& data ) + : m_data( data ), + m_stream( openStream() ) + { + if( !data.testsOrTags.empty() ) { + TestSpecParser parser( ITagAliasRegistry::get() ); + for( std::size_t i = 0; i < data.testsOrTags.size(); ++i ) + parser.parse( data.testsOrTags[i] ); + m_testSpec = parser.testSpec(); + } + } + + virtual ~Config() { + } + + std::string const& getFilename() const { + return m_data.outputFilename ; + } + + bool listTests() const { return m_data.listTests; } + bool listTestNamesOnly() const { return m_data.listTestNamesOnly; } + bool listTags() const { return m_data.listTags; } + bool listReporters() const { return m_data.listReporters; } + + std::string getProcessName() const { return m_data.processName; } + + bool shouldDebugBreak() const { return m_data.shouldDebugBreak; } + + std::vector getReporterNames() const { return m_data.reporterNames; } + + int abortAfter() const { return m_data.abortAfter; } + + TestSpec const& testSpec() const { return m_testSpec; } + + bool showHelp() const { return m_data.showHelp; } + bool showInvisibles() const { return m_data.showInvisibles; } + + // IConfig interface + virtual bool allowThrows() const { return !m_data.noThrow; } + virtual std::ostream& stream() const { return m_stream->stream(); } + virtual std::string name() const { return m_data.name.empty() ? m_data.processName : m_data.name; } + virtual bool includeSuccessfulResults() const { return m_data.showSuccessfulTests; } + virtual bool warnAboutMissingAssertions() const { return m_data.warnings & WarnAbout::NoAssertions; } + virtual ShowDurations::OrNot showDurations() const { return m_data.showDurations; } + virtual RunTests::InWhatOrder runOrder() const { return m_data.runOrder; } + virtual unsigned int rngSeed() const { return m_data.rngSeed; } + virtual UseColour::YesOrNo useColour() const { return m_data.useColour; } + + private: + + IStream const* openStream() { + if( m_data.outputFilename.empty() ) + return new CoutStream(); + else if( m_data.outputFilename[0] == '%' ) { + if( m_data.outputFilename == "%debug" ) + return new DebugOutStream(); + else + throw std::domain_error( "Unrecognised stream: " + m_data.outputFilename ); + } + else + return new FileStream( m_data.outputFilename ); + } + ConfigData m_data; + + CATCH_AUTO_PTR( IStream const ) m_stream; + TestSpec m_testSpec; + }; + +} // end namespace Catch + +// #included from: catch_clara.h +#define TWOBLUECUBES_CATCH_CLARA_H_INCLUDED + +// Use Catch's value for console width (store Clara's off to the side, if present) +#ifdef CLARA_CONFIG_CONSOLE_WIDTH +#define CATCH_TEMP_CLARA_CONFIG_CONSOLE_WIDTH CLARA_CONFIG_CONSOLE_WIDTH +#undef CLARA_CONFIG_CONSOLE_WIDTH +#endif +#define CLARA_CONFIG_CONSOLE_WIDTH CATCH_CONFIG_CONSOLE_WIDTH + +// Declare Clara inside the Catch namespace +#define STITCH_CLARA_OPEN_NAMESPACE namespace Catch { +// #included from: ../external/clara.h + +// Version 0.0.2.4 + +// Only use header guard if we are not using an outer namespace +#if !defined(TWOBLUECUBES_CLARA_H_INCLUDED) || defined(STITCH_CLARA_OPEN_NAMESPACE) + +#ifndef STITCH_CLARA_OPEN_NAMESPACE +#define TWOBLUECUBES_CLARA_H_INCLUDED +#define STITCH_CLARA_OPEN_NAMESPACE +#define STITCH_CLARA_CLOSE_NAMESPACE +#else +#define STITCH_CLARA_CLOSE_NAMESPACE } +#endif + +#define STITCH_TBC_TEXT_FORMAT_OPEN_NAMESPACE STITCH_CLARA_OPEN_NAMESPACE + +// ----------- #included from tbc_text_format.h ----------- + +// Only use header guard if we are not using an outer namespace +#if !defined(TBC_TEXT_FORMAT_H_INCLUDED) || defined(STITCH_TBC_TEXT_FORMAT_OUTER_NAMESPACE) +#ifndef STITCH_TBC_TEXT_FORMAT_OUTER_NAMESPACE +#define TBC_TEXT_FORMAT_H_INCLUDED +#endif + +#include +#include +#include +#include + +// Use optional outer namespace +#ifdef STITCH_TBC_TEXT_FORMAT_OUTER_NAMESPACE +namespace STITCH_TBC_TEXT_FORMAT_OUTER_NAMESPACE { +#endif + +namespace Tbc { + +#ifdef TBC_TEXT_FORMAT_CONSOLE_WIDTH + const unsigned int consoleWidth = TBC_TEXT_FORMAT_CONSOLE_WIDTH; +#else + const unsigned int consoleWidth = 80; +#endif + + struct TextAttributes { + TextAttributes() + : initialIndent( std::string::npos ), + indent( 0 ), + width( consoleWidth-1 ), + tabChar( '\t' ) + {} + + TextAttributes& setInitialIndent( std::size_t _value ) { initialIndent = _value; return *this; } + TextAttributes& setIndent( std::size_t _value ) { indent = _value; return *this; } + TextAttributes& setWidth( std::size_t _value ) { width = _value; return *this; } + TextAttributes& setTabChar( char _value ) { tabChar = _value; return *this; } + + std::size_t initialIndent; // indent of first line, or npos + std::size_t indent; // indent of subsequent lines, or all if initialIndent is npos + std::size_t width; // maximum width of text, including indent. Longer text will wrap + char tabChar; // If this char is seen the indent is changed to current pos + }; + + class Text { + public: + Text( std::string const& _str, TextAttributes const& _attr = TextAttributes() ) + : attr( _attr ) + { + std::string wrappableChars = " [({.,/|\\-"; + std::size_t indent = _attr.initialIndent != std::string::npos + ? _attr.initialIndent + : _attr.indent; + std::string remainder = _str; + + while( !remainder.empty() ) { + if( lines.size() >= 1000 ) { + lines.push_back( "... message truncated due to excessive size" ); + return; + } + std::size_t tabPos = std::string::npos; + std::size_t width = (std::min)( remainder.size(), _attr.width - indent ); + std::size_t pos = remainder.find_first_of( '\n' ); + if( pos <= width ) { + width = pos; + } + pos = remainder.find_last_of( _attr.tabChar, width ); + if( pos != std::string::npos ) { + tabPos = pos; + if( remainder[width] == '\n' ) + width--; + remainder = remainder.substr( 0, tabPos ) + remainder.substr( tabPos+1 ); + } + + if( width == remainder.size() ) { + spliceLine( indent, remainder, width ); + } + else if( remainder[width] == '\n' ) { + spliceLine( indent, remainder, width ); + if( width <= 1 || remainder.size() != 1 ) + remainder = remainder.substr( 1 ); + indent = _attr.indent; + } + else { + pos = remainder.find_last_of( wrappableChars, width ); + if( pos != std::string::npos && pos > 0 ) { + spliceLine( indent, remainder, pos ); + if( remainder[0] == ' ' ) + remainder = remainder.substr( 1 ); + } + else { + spliceLine( indent, remainder, width-1 ); + lines.back() += "-"; + } + if( lines.size() == 1 ) + indent = _attr.indent; + if( tabPos != std::string::npos ) + indent += tabPos; + } + } + } + + void spliceLine( std::size_t _indent, std::string& _remainder, std::size_t _pos ) { + lines.push_back( std::string( _indent, ' ' ) + _remainder.substr( 0, _pos ) ); + _remainder = _remainder.substr( _pos ); + } + + typedef std::vector::const_iterator const_iterator; + + const_iterator begin() const { return lines.begin(); } + const_iterator end() const { return lines.end(); } + std::string const& last() const { return lines.back(); } + std::size_t size() const { return lines.size(); } + std::string const& operator[]( std::size_t _index ) const { return lines[_index]; } + std::string toString() const { + std::ostringstream oss; + oss << *this; + return oss.str(); + } + + inline friend std::ostream& operator << ( std::ostream& _stream, Text const& _text ) { + for( Text::const_iterator it = _text.begin(), itEnd = _text.end(); + it != itEnd; ++it ) { + if( it != _text.begin() ) + _stream << "\n"; + _stream << *it; + } + return _stream; + } + + private: + std::string str; + TextAttributes attr; + std::vector lines; + }; + +} // end namespace Tbc + +#ifdef STITCH_TBC_TEXT_FORMAT_OUTER_NAMESPACE +} // end outer namespace +#endif + +#endif // TBC_TEXT_FORMAT_H_INCLUDED + +// ----------- end of #include from tbc_text_format.h ----------- +// ........... back in clara.h + +#undef STITCH_TBC_TEXT_FORMAT_OPEN_NAMESPACE + +// ----------- #included from clara_compilers.h ----------- + +#ifndef TWOBLUECUBES_CLARA_COMPILERS_H_INCLUDED +#define TWOBLUECUBES_CLARA_COMPILERS_H_INCLUDED + +// Detect a number of compiler features - mostly C++11/14 conformance - by compiler +// The following features are defined: +// +// CLARA_CONFIG_CPP11_NULLPTR : is nullptr supported? +// CLARA_CONFIG_CPP11_NOEXCEPT : is noexcept supported? +// CLARA_CONFIG_CPP11_GENERATED_METHODS : The delete and default keywords for compiler generated methods +// CLARA_CONFIG_CPP11_OVERRIDE : is override supported? +// CLARA_CONFIG_CPP11_UNIQUE_PTR : is unique_ptr supported (otherwise use auto_ptr) + +// CLARA_CONFIG_CPP11_OR_GREATER : Is C++11 supported? + +// CLARA_CONFIG_VARIADIC_MACROS : are variadic macros supported? + +// In general each macro has a _NO_ form +// (e.g. CLARA_CONFIG_CPP11_NO_NULLPTR) which disables the feature. +// Many features, at point of detection, define an _INTERNAL_ macro, so they +// can be combined, en-mass, with the _NO_ forms later. + +// All the C++11 features can be disabled with CLARA_CONFIG_NO_CPP11 + +#ifdef __clang__ + +#if __has_feature(cxx_nullptr) +#define CLARA_INTERNAL_CONFIG_CPP11_NULLPTR +#endif + +#if __has_feature(cxx_noexcept) +#define CLARA_INTERNAL_CONFIG_CPP11_NOEXCEPT +#endif + +#endif // __clang__ + +//////////////////////////////////////////////////////////////////////////////// +// GCC +#ifdef __GNUC__ + +#if __GNUC__ == 4 && __GNUC_MINOR__ >= 6 && defined(__GXX_EXPERIMENTAL_CXX0X__) +#define CLARA_INTERNAL_CONFIG_CPP11_NULLPTR +#endif + +// - otherwise more recent versions define __cplusplus >= 201103L +// and will get picked up below + +#endif // __GNUC__ + +//////////////////////////////////////////////////////////////////////////////// +// Visual C++ +#ifdef _MSC_VER + +#if (_MSC_VER >= 1600) +#define CLARA_INTERNAL_CONFIG_CPP11_NULLPTR +#define CLARA_INTERNAL_CONFIG_CPP11_UNIQUE_PTR +#endif + +#if (_MSC_VER >= 1900 ) // (VC++ 13 (VS2015)) +#define CLARA_INTERNAL_CONFIG_CPP11_NOEXCEPT +#define CLARA_INTERNAL_CONFIG_CPP11_GENERATED_METHODS +#endif + +#endif // _MSC_VER + +//////////////////////////////////////////////////////////////////////////////// +// C++ language feature support + +// catch all support for C++11 +#if defined(__cplusplus) && __cplusplus >= 201103L + +#define CLARA_CPP11_OR_GREATER + +#if !defined(CLARA_INTERNAL_CONFIG_CPP11_NULLPTR) +#define CLARA_INTERNAL_CONFIG_CPP11_NULLPTR +#endif + +#ifndef CLARA_INTERNAL_CONFIG_CPP11_NOEXCEPT +#define CLARA_INTERNAL_CONFIG_CPP11_NOEXCEPT +#endif + +#ifndef CLARA_INTERNAL_CONFIG_CPP11_GENERATED_METHODS +#define CLARA_INTERNAL_CONFIG_CPP11_GENERATED_METHODS +#endif + +#if !defined(CLARA_INTERNAL_CONFIG_CPP11_OVERRIDE) +#define CLARA_INTERNAL_CONFIG_CPP11_OVERRIDE +#endif +#if !defined(CLARA_INTERNAL_CONFIG_CPP11_UNIQUE_PTR) +#define CLARA_INTERNAL_CONFIG_CPP11_UNIQUE_PTR +#endif + +#endif // __cplusplus >= 201103L + +// Now set the actual defines based on the above + anything the user has configured +#if defined(CLARA_INTERNAL_CONFIG_CPP11_NULLPTR) && !defined(CLARA_CONFIG_CPP11_NO_NULLPTR) && !defined(CLARA_CONFIG_CPP11_NULLPTR) && !defined(CLARA_CONFIG_NO_CPP11) +#define CLARA_CONFIG_CPP11_NULLPTR +#endif +#if defined(CLARA_INTERNAL_CONFIG_CPP11_NOEXCEPT) && !defined(CLARA_CONFIG_CPP11_NO_NOEXCEPT) && !defined(CLARA_CONFIG_CPP11_NOEXCEPT) && !defined(CLARA_CONFIG_NO_CPP11) +#define CLARA_CONFIG_CPP11_NOEXCEPT +#endif +#if defined(CLARA_INTERNAL_CONFIG_CPP11_GENERATED_METHODS) && !defined(CLARA_CONFIG_CPP11_NO_GENERATED_METHODS) && !defined(CLARA_CONFIG_CPP11_GENERATED_METHODS) && !defined(CLARA_CONFIG_NO_CPP11) +#define CLARA_CONFIG_CPP11_GENERATED_METHODS +#endif +#if defined(CLARA_INTERNAL_CONFIG_CPP11_OVERRIDE) && !defined(CLARA_CONFIG_NO_OVERRIDE) && !defined(CLARA_CONFIG_CPP11_OVERRIDE) && !defined(CLARA_CONFIG_NO_CPP11) +#define CLARA_CONFIG_CPP11_OVERRIDE +#endif +#if defined(CLARA_INTERNAL_CONFIG_CPP11_UNIQUE_PTR) && !defined(CLARA_CONFIG_NO_UNIQUE_PTR) && !defined(CLARA_CONFIG_CPP11_UNIQUE_PTR) && !defined(CLARA_CONFIG_NO_CPP11) +#define CLARA_CONFIG_CPP11_UNIQUE_PTR +#endif + +// noexcept support: +#if defined(CLARA_CONFIG_CPP11_NOEXCEPT) && !defined(CLARA_NOEXCEPT) +#define CLARA_NOEXCEPT noexcept +# define CLARA_NOEXCEPT_IS(x) noexcept(x) +#else +#define CLARA_NOEXCEPT throw() +# define CLARA_NOEXCEPT_IS(x) +#endif + +// nullptr support +#ifdef CLARA_CONFIG_CPP11_NULLPTR +#define CLARA_NULL nullptr +#else +#define CLARA_NULL NULL +#endif + +// override support +#ifdef CLARA_CONFIG_CPP11_OVERRIDE +#define CLARA_OVERRIDE override +#else +#define CLARA_OVERRIDE +#endif + +// unique_ptr support +#ifdef CLARA_CONFIG_CPP11_UNIQUE_PTR +# define CLARA_AUTO_PTR( T ) std::unique_ptr +#else +# define CLARA_AUTO_PTR( T ) std::auto_ptr +#endif + +#endif // TWOBLUECUBES_CLARA_COMPILERS_H_INCLUDED + +// ----------- end of #include from clara_compilers.h ----------- +// ........... back in clara.h + +#include +#include +#include + +#if defined(WIN32) || defined(__WIN32__) || defined(_WIN32) || defined(_MSC_VER) +#define CLARA_PLATFORM_WINDOWS +#endif + +// Use optional outer namespace +#ifdef STITCH_CLARA_OPEN_NAMESPACE +STITCH_CLARA_OPEN_NAMESPACE +#endif + +namespace Clara { + + struct UnpositionalTag {}; + + extern UnpositionalTag _; + +#ifdef CLARA_CONFIG_MAIN + UnpositionalTag _; +#endif + + namespace Detail { + +#ifdef CLARA_CONSOLE_WIDTH + const unsigned int consoleWidth = CLARA_CONFIG_CONSOLE_WIDTH; +#else + const unsigned int consoleWidth = 80; +#endif + + using namespace Tbc; + + inline bool startsWith( std::string const& str, std::string const& prefix ) { + return str.size() >= prefix.size() && str.substr( 0, prefix.size() ) == prefix; + } + + template struct RemoveConstRef{ typedef T type; }; + template struct RemoveConstRef{ typedef T type; }; + template struct RemoveConstRef{ typedef T type; }; + template struct RemoveConstRef{ typedef T type; }; + + template struct IsBool { static const bool value = false; }; + template<> struct IsBool { static const bool value = true; }; + + template + void convertInto( std::string const& _source, T& _dest ) { + std::stringstream ss; + ss << _source; + ss >> _dest; + if( ss.fail() ) + throw std::runtime_error( "Unable to convert " + _source + " to destination type" ); + } + inline void convertInto( std::string const& _source, std::string& _dest ) { + _dest = _source; + } + inline void convertInto( std::string const& _source, bool& _dest ) { + std::string sourceLC = _source; + std::transform( sourceLC.begin(), sourceLC.end(), sourceLC.begin(), ::tolower ); + if( sourceLC == "y" || sourceLC == "1" || sourceLC == "true" || sourceLC == "yes" || sourceLC == "on" ) + _dest = true; + else if( sourceLC == "n" || sourceLC == "0" || sourceLC == "false" || sourceLC == "no" || sourceLC == "off" ) + _dest = false; + else + throw std::runtime_error( "Expected a boolean value but did not recognise:\n '" + _source + "'" ); + } + + template + struct IArgFunction { + virtual ~IArgFunction() {} +#ifdef CLARA_CONFIG_CPP11_GENERATED_METHODS + IArgFunction() = default; + IArgFunction( IArgFunction const& ) = default; +#endif + virtual void set( ConfigT& config, std::string const& value ) const = 0; + virtual bool takesArg() const = 0; + virtual IArgFunction* clone() const = 0; + }; + + template + class BoundArgFunction { + public: + BoundArgFunction() : functionObj( CLARA_NULL ) {} + BoundArgFunction( IArgFunction* _functionObj ) : functionObj( _functionObj ) {} + BoundArgFunction( BoundArgFunction const& other ) : functionObj( other.functionObj ? other.functionObj->clone() : CLARA_NULL ) {} + BoundArgFunction& operator = ( BoundArgFunction const& other ) { + IArgFunction* newFunctionObj = other.functionObj ? other.functionObj->clone() : CLARA_NULL; + delete functionObj; + functionObj = newFunctionObj; + return *this; + } + ~BoundArgFunction() { delete functionObj; } + + void set( ConfigT& config, std::string const& value ) const { + functionObj->set( config, value ); + } + bool takesArg() const { return functionObj->takesArg(); } + + bool isSet() const { + return functionObj != CLARA_NULL; + } + private: + IArgFunction* functionObj; + }; + + template + struct NullBinder : IArgFunction{ + virtual void set( C&, std::string const& ) const {} + virtual bool takesArg() const { return true; } + virtual IArgFunction* clone() const { return new NullBinder( *this ); } + }; + + template + struct BoundDataMember : IArgFunction{ + BoundDataMember( M C::* _member ) : member( _member ) {} + virtual void set( C& p, std::string const& stringValue ) const { + convertInto( stringValue, p.*member ); + } + virtual bool takesArg() const { return !IsBool::value; } + virtual IArgFunction* clone() const { return new BoundDataMember( *this ); } + M C::* member; + }; + template + struct BoundUnaryMethod : IArgFunction{ + BoundUnaryMethod( void (C::*_member)( M ) ) : member( _member ) {} + virtual void set( C& p, std::string const& stringValue ) const { + typename RemoveConstRef::type value; + convertInto( stringValue, value ); + (p.*member)( value ); + } + virtual bool takesArg() const { return !IsBool::value; } + virtual IArgFunction* clone() const { return new BoundUnaryMethod( *this ); } + void (C::*member)( M ); + }; + template + struct BoundNullaryMethod : IArgFunction{ + BoundNullaryMethod( void (C::*_member)() ) : member( _member ) {} + virtual void set( C& p, std::string const& stringValue ) const { + bool value; + convertInto( stringValue, value ); + if( value ) + (p.*member)(); + } + virtual bool takesArg() const { return false; } + virtual IArgFunction* clone() const { return new BoundNullaryMethod( *this ); } + void (C::*member)(); + }; + + template + struct BoundUnaryFunction : IArgFunction{ + BoundUnaryFunction( void (*_function)( C& ) ) : function( _function ) {} + virtual void set( C& obj, std::string const& stringValue ) const { + bool value; + convertInto( stringValue, value ); + if( value ) + function( obj ); + } + virtual bool takesArg() const { return false; } + virtual IArgFunction* clone() const { return new BoundUnaryFunction( *this ); } + void (*function)( C& ); + }; + + template + struct BoundBinaryFunction : IArgFunction{ + BoundBinaryFunction( void (*_function)( C&, T ) ) : function( _function ) {} + virtual void set( C& obj, std::string const& stringValue ) const { + typename RemoveConstRef::type value; + convertInto( stringValue, value ); + function( obj, value ); + } + virtual bool takesArg() const { return !IsBool::value; } + virtual IArgFunction* clone() const { return new BoundBinaryFunction( *this ); } + void (*function)( C&, T ); + }; + + } // namespace Detail + + inline std::vector argsToVector( int argc, char const* const* const argv ) { + std::vector args( static_cast( argc ) ); + for( std::size_t i = 0; i < static_cast( argc ); ++i ) + args[i] = argv[i]; + + return args; + } + + class Parser { + enum Mode { None, MaybeShortOpt, SlashOpt, ShortOpt, LongOpt, Positional }; + Mode mode; + std::size_t from; + bool inQuotes; + public: + + struct Token { + enum Type { Positional, ShortOpt, LongOpt }; + Token( Type _type, std::string const& _data ) : type( _type ), data( _data ) {} + Type type; + std::string data; + }; + + Parser() : mode( None ), from( 0 ), inQuotes( false ){} + + void parseIntoTokens( std::vector const& args, std::vector& tokens ) { + const std::string doubleDash = "--"; + for( std::size_t i = 1; i < args.size() && args[i] != doubleDash; ++i ) + parseIntoTokens( args[i], tokens); + } + + void parseIntoTokens( std::string const& arg, std::vector& tokens ) { + for( std::size_t i = 0; i <= arg.size(); ++i ) { + char c = arg[i]; + if( c == '"' ) + inQuotes = !inQuotes; + mode = handleMode( i, c, arg, tokens ); + } + } + Mode handleMode( std::size_t i, char c, std::string const& arg, std::vector& tokens ) { + switch( mode ) { + case None: return handleNone( i, c ); + case MaybeShortOpt: return handleMaybeShortOpt( i, c ); + case ShortOpt: + case LongOpt: + case SlashOpt: return handleOpt( i, c, arg, tokens ); + case Positional: return handlePositional( i, c, arg, tokens ); + default: throw std::logic_error( "Unknown mode" ); + } + } + + Mode handleNone( std::size_t i, char c ) { + if( inQuotes ) { + from = i; + return Positional; + } + switch( c ) { + case '-': return MaybeShortOpt; +#ifdef CLARA_PLATFORM_WINDOWS + case '/': from = i+1; return SlashOpt; +#endif + default: from = i; return Positional; + } + } + Mode handleMaybeShortOpt( std::size_t i, char c ) { + switch( c ) { + case '-': from = i+1; return LongOpt; + default: from = i; return ShortOpt; + } + } + Mode handleOpt( std::size_t i, char c, std::string const& arg, std::vector& tokens ) { + if( std::string( ":=\0", 3 ).find( c ) == std::string::npos ) + return mode; + + std::string optName = arg.substr( from, i-from ); + if( mode == ShortOpt ) + for( std::size_t j = 0; j < optName.size(); ++j ) + tokens.push_back( Token( Token::ShortOpt, optName.substr( j, 1 ) ) ); + else if( mode == SlashOpt && optName.size() == 1 ) + tokens.push_back( Token( Token::ShortOpt, optName ) ); + else + tokens.push_back( Token( Token::LongOpt, optName ) ); + return None; + } + Mode handlePositional( std::size_t i, char c, std::string const& arg, std::vector& tokens ) { + if( inQuotes || std::string( "\0", 1 ).find( c ) == std::string::npos ) + return mode; + + std::string data = arg.substr( from, i-from ); + tokens.push_back( Token( Token::Positional, data ) ); + return None; + } + }; + + template + struct CommonArgProperties { + CommonArgProperties() {} + CommonArgProperties( Detail::BoundArgFunction const& _boundField ) : boundField( _boundField ) {} + + Detail::BoundArgFunction boundField; + std::string description; + std::string detail; + std::string placeholder; // Only value if boundField takes an arg + + bool takesArg() const { + return !placeholder.empty(); + } + void validate() const { + if( !boundField.isSet() ) + throw std::logic_error( "option not bound" ); + } + }; + struct OptionArgProperties { + std::vector shortNames; + std::string longName; + + bool hasShortName( std::string const& shortName ) const { + return std::find( shortNames.begin(), shortNames.end(), shortName ) != shortNames.end(); + } + bool hasLongName( std::string const& _longName ) const { + return _longName == longName; + } + }; + struct PositionalArgProperties { + PositionalArgProperties() : position( -1 ) {} + int position; // -1 means non-positional (floating) + + bool isFixedPositional() const { + return position != -1; + } + }; + + template + class CommandLine { + + struct Arg : CommonArgProperties, OptionArgProperties, PositionalArgProperties { + Arg() {} + Arg( Detail::BoundArgFunction const& _boundField ) : CommonArgProperties( _boundField ) {} + + using CommonArgProperties::placeholder; // !TBD + + std::string dbgName() const { + if( !longName.empty() ) + return "--" + longName; + if( !shortNames.empty() ) + return "-" + shortNames[0]; + return "positional args"; + } + std::string commands() const { + std::ostringstream oss; + bool first = true; + std::vector::const_iterator it = shortNames.begin(), itEnd = shortNames.end(); + for(; it != itEnd; ++it ) { + if( first ) + first = false; + else + oss << ", "; + oss << "-" << *it; + } + if( !longName.empty() ) { + if( !first ) + oss << ", "; + oss << "--" << longName; + } + if( !placeholder.empty() ) + oss << " <" << placeholder << ">"; + return oss.str(); + } + }; + + typedef CLARA_AUTO_PTR( Arg ) ArgAutoPtr; + + friend void addOptName( Arg& arg, std::string const& optName ) + { + if( optName.empty() ) + return; + if( Detail::startsWith( optName, "--" ) ) { + if( !arg.longName.empty() ) + throw std::logic_error( "Only one long opt may be specified. '" + + arg.longName + + "' already specified, now attempting to add '" + + optName + "'" ); + arg.longName = optName.substr( 2 ); + } + else if( Detail::startsWith( optName, "-" ) ) + arg.shortNames.push_back( optName.substr( 1 ) ); + else + throw std::logic_error( "option must begin with - or --. Option was: '" + optName + "'" ); + } + friend void setPositionalArg( Arg& arg, int position ) + { + arg.position = position; + } + + class ArgBuilder { + public: + ArgBuilder( Arg* arg ) : m_arg( arg ) {} + + // Bind a non-boolean data member (requires placeholder string) + template + void bind( M C::* field, std::string const& placeholder ) { + m_arg->boundField = new Detail::BoundDataMember( field ); + m_arg->placeholder = placeholder; + } + // Bind a boolean data member (no placeholder required) + template + void bind( bool C::* field ) { + m_arg->boundField = new Detail::BoundDataMember( field ); + } + + // Bind a method taking a single, non-boolean argument (requires a placeholder string) + template + void bind( void (C::* unaryMethod)( M ), std::string const& placeholder ) { + m_arg->boundField = new Detail::BoundUnaryMethod( unaryMethod ); + m_arg->placeholder = placeholder; + } + + // Bind a method taking a single, boolean argument (no placeholder string required) + template + void bind( void (C::* unaryMethod)( bool ) ) { + m_arg->boundField = new Detail::BoundUnaryMethod( unaryMethod ); + } + + // Bind a method that takes no arguments (will be called if opt is present) + template + void bind( void (C::* nullaryMethod)() ) { + m_arg->boundField = new Detail::BoundNullaryMethod( nullaryMethod ); + } + + // Bind a free function taking a single argument - the object to operate on (no placeholder string required) + template + void bind( void (* unaryFunction)( C& ) ) { + m_arg->boundField = new Detail::BoundUnaryFunction( unaryFunction ); + } + + // Bind a free function taking a single argument - the object to operate on (requires a placeholder string) + template + void bind( void (* binaryFunction)( C&, T ), std::string const& placeholder ) { + m_arg->boundField = new Detail::BoundBinaryFunction( binaryFunction ); + m_arg->placeholder = placeholder; + } + + ArgBuilder& describe( std::string const& description ) { + m_arg->description = description; + return *this; + } + ArgBuilder& detail( std::string const& detail ) { + m_arg->detail = detail; + return *this; + } + + protected: + Arg* m_arg; + }; + + class OptBuilder : public ArgBuilder { + public: + OptBuilder( Arg* arg ) : ArgBuilder( arg ) {} + OptBuilder( OptBuilder& other ) : ArgBuilder( other ) {} + + OptBuilder& operator[]( std::string const& optName ) { + addOptName( *ArgBuilder::m_arg, optName ); + return *this; + } + }; + + public: + + CommandLine() + : m_boundProcessName( new Detail::NullBinder() ), + m_highestSpecifiedArgPosition( 0 ), + m_throwOnUnrecognisedTokens( false ) + {} + CommandLine( CommandLine const& other ) + : m_boundProcessName( other.m_boundProcessName ), + m_options ( other.m_options ), + m_positionalArgs( other.m_positionalArgs ), + m_highestSpecifiedArgPosition( other.m_highestSpecifiedArgPosition ), + m_throwOnUnrecognisedTokens( other.m_throwOnUnrecognisedTokens ) + { + if( other.m_floatingArg.get() ) + m_floatingArg.reset( new Arg( *other.m_floatingArg ) ); + } + + CommandLine& setThrowOnUnrecognisedTokens( bool shouldThrow = true ) { + m_throwOnUnrecognisedTokens = shouldThrow; + return *this; + } + + OptBuilder operator[]( std::string const& optName ) { + m_options.push_back( Arg() ); + addOptName( m_options.back(), optName ); + OptBuilder builder( &m_options.back() ); + return builder; + } + + ArgBuilder operator[]( int position ) { + m_positionalArgs.insert( std::make_pair( position, Arg() ) ); + if( position > m_highestSpecifiedArgPosition ) + m_highestSpecifiedArgPosition = position; + setPositionalArg( m_positionalArgs[position], position ); + ArgBuilder builder( &m_positionalArgs[position] ); + return builder; + } + + // Invoke this with the _ instance + ArgBuilder operator[]( UnpositionalTag ) { + if( m_floatingArg.get() ) + throw std::logic_error( "Only one unpositional argument can be added" ); + m_floatingArg.reset( new Arg() ); + ArgBuilder builder( m_floatingArg.get() ); + return builder; + } + + template + void bindProcessName( M C::* field ) { + m_boundProcessName = new Detail::BoundDataMember( field ); + } + template + void bindProcessName( void (C::*_unaryMethod)( M ) ) { + m_boundProcessName = new Detail::BoundUnaryMethod( _unaryMethod ); + } + + void optUsage( std::ostream& os, std::size_t indent = 0, std::size_t width = Detail::consoleWidth ) const { + typename std::vector::const_iterator itBegin = m_options.begin(), itEnd = m_options.end(), it; + std::size_t maxWidth = 0; + for( it = itBegin; it != itEnd; ++it ) + maxWidth = (std::max)( maxWidth, it->commands().size() ); + + for( it = itBegin; it != itEnd; ++it ) { + Detail::Text usage( it->commands(), Detail::TextAttributes() + .setWidth( maxWidth+indent ) + .setIndent( indent ) ); + Detail::Text desc( it->description, Detail::TextAttributes() + .setWidth( width - maxWidth - 3 ) ); + + for( std::size_t i = 0; i < (std::max)( usage.size(), desc.size() ); ++i ) { + std::string usageCol = i < usage.size() ? usage[i] : ""; + os << usageCol; + + if( i < desc.size() && !desc[i].empty() ) + os << std::string( indent + 2 + maxWidth - usageCol.size(), ' ' ) + << desc[i]; + os << "\n"; + } + } + } + std::string optUsage() const { + std::ostringstream oss; + optUsage( oss ); + return oss.str(); + } + + void argSynopsis( std::ostream& os ) const { + for( int i = 1; i <= m_highestSpecifiedArgPosition; ++i ) { + if( i > 1 ) + os << " "; + typename std::map::const_iterator it = m_positionalArgs.find( i ); + if( it != m_positionalArgs.end() ) + os << "<" << it->second.placeholder << ">"; + else if( m_floatingArg.get() ) + os << "<" << m_floatingArg->placeholder << ">"; + else + throw std::logic_error( "non consecutive positional arguments with no floating args" ); + } + // !TBD No indication of mandatory args + if( m_floatingArg.get() ) { + if( m_highestSpecifiedArgPosition > 1 ) + os << " "; + os << "[<" << m_floatingArg->placeholder << "> ...]"; + } + } + std::string argSynopsis() const { + std::ostringstream oss; + argSynopsis( oss ); + return oss.str(); + } + + void usage( std::ostream& os, std::string const& procName ) const { + validate(); + os << "usage:\n " << procName << " "; + argSynopsis( os ); + if( !m_options.empty() ) { + os << " [options]\n\nwhere options are: \n"; + optUsage( os, 2 ); + } + os << "\n"; + } + std::string usage( std::string const& procName ) const { + std::ostringstream oss; + usage( oss, procName ); + return oss.str(); + } + + ConfigT parse( std::vector const& args ) const { + ConfigT config; + parseInto( args, config ); + return config; + } + + std::vector parseInto( std::vector const& args, ConfigT& config ) const { + std::string processName = args[0]; + std::size_t lastSlash = processName.find_last_of( "/\\" ); + if( lastSlash != std::string::npos ) + processName = processName.substr( lastSlash+1 ); + m_boundProcessName.set( config, processName ); + std::vector tokens; + Parser parser; + parser.parseIntoTokens( args, tokens ); + return populate( tokens, config ); + } + + std::vector populate( std::vector const& tokens, ConfigT& config ) const { + validate(); + std::vector unusedTokens = populateOptions( tokens, config ); + unusedTokens = populateFixedArgs( unusedTokens, config ); + unusedTokens = populateFloatingArgs( unusedTokens, config ); + return unusedTokens; + } + + std::vector populateOptions( std::vector const& tokens, ConfigT& config ) const { + std::vector unusedTokens; + std::vector errors; + for( std::size_t i = 0; i < tokens.size(); ++i ) { + Parser::Token const& token = tokens[i]; + typename std::vector::const_iterator it = m_options.begin(), itEnd = m_options.end(); + for(; it != itEnd; ++it ) { + Arg const& arg = *it; + + try { + if( ( token.type == Parser::Token::ShortOpt && arg.hasShortName( token.data ) ) || + ( token.type == Parser::Token::LongOpt && arg.hasLongName( token.data ) ) ) { + if( arg.takesArg() ) { + if( i == tokens.size()-1 || tokens[i+1].type != Parser::Token::Positional ) + errors.push_back( "Expected argument to option: " + token.data ); + else + arg.boundField.set( config, tokens[++i].data ); + } + else { + arg.boundField.set( config, "true" ); + } + break; + } + } + catch( std::exception& ex ) { + errors.push_back( std::string( ex.what() ) + "\n- while parsing: (" + arg.commands() + ")" ); + } + } + if( it == itEnd ) { + if( token.type == Parser::Token::Positional || !m_throwOnUnrecognisedTokens ) + unusedTokens.push_back( token ); + else if( errors.empty() && m_throwOnUnrecognisedTokens ) + errors.push_back( "unrecognised option: " + token.data ); + } + } + if( !errors.empty() ) { + std::ostringstream oss; + for( std::vector::const_iterator it = errors.begin(), itEnd = errors.end(); + it != itEnd; + ++it ) { + if( it != errors.begin() ) + oss << "\n"; + oss << *it; + } + throw std::runtime_error( oss.str() ); + } + return unusedTokens; + } + std::vector populateFixedArgs( std::vector const& tokens, ConfigT& config ) const { + std::vector unusedTokens; + int position = 1; + for( std::size_t i = 0; i < tokens.size(); ++i ) { + Parser::Token const& token = tokens[i]; + typename std::map::const_iterator it = m_positionalArgs.find( position ); + if( it != m_positionalArgs.end() ) + it->second.boundField.set( config, token.data ); + else + unusedTokens.push_back( token ); + if( token.type == Parser::Token::Positional ) + position++; + } + return unusedTokens; + } + std::vector populateFloatingArgs( std::vector const& tokens, ConfigT& config ) const { + if( !m_floatingArg.get() ) + return tokens; + std::vector unusedTokens; + for( std::size_t i = 0; i < tokens.size(); ++i ) { + Parser::Token const& token = tokens[i]; + if( token.type == Parser::Token::Positional ) + m_floatingArg->boundField.set( config, token.data ); + else + unusedTokens.push_back( token ); + } + return unusedTokens; + } + + void validate() const + { + if( m_options.empty() && m_positionalArgs.empty() && !m_floatingArg.get() ) + throw std::logic_error( "No options or arguments specified" ); + + for( typename std::vector::const_iterator it = m_options.begin(), + itEnd = m_options.end(); + it != itEnd; ++it ) + it->validate(); + } + + private: + Detail::BoundArgFunction m_boundProcessName; + std::vector m_options; + std::map m_positionalArgs; + ArgAutoPtr m_floatingArg; + int m_highestSpecifiedArgPosition; + bool m_throwOnUnrecognisedTokens; + }; + +} // end namespace Clara + +STITCH_CLARA_CLOSE_NAMESPACE +#undef STITCH_CLARA_OPEN_NAMESPACE +#undef STITCH_CLARA_CLOSE_NAMESPACE + +#endif // TWOBLUECUBES_CLARA_H_INCLUDED +#undef STITCH_CLARA_OPEN_NAMESPACE + +// Restore Clara's value for console width, if present +#ifdef CATCH_TEMP_CLARA_CONFIG_CONSOLE_WIDTH +#define CLARA_CONFIG_CONSOLE_WIDTH CATCH_TEMP_CLARA_CONFIG_CONSOLE_WIDTH +#undef CATCH_TEMP_CLARA_CONFIG_CONSOLE_WIDTH +#endif + +#include + +namespace Catch { + + inline void abortAfterFirst( ConfigData& config ) { config.abortAfter = 1; } + inline void abortAfterX( ConfigData& config, int x ) { + if( x < 1 ) + throw std::runtime_error( "Value after -x or --abortAfter must be greater than zero" ); + config.abortAfter = x; + } + inline void addTestOrTags( ConfigData& config, std::string const& _testSpec ) { config.testsOrTags.push_back( _testSpec ); } + inline void addReporterName( ConfigData& config, std::string const& _reporterName ) { config.reporterNames.push_back( _reporterName ); } + + inline void addWarning( ConfigData& config, std::string const& _warning ) { + if( _warning == "NoAssertions" ) + config.warnings = static_cast( config.warnings | WarnAbout::NoAssertions ); + else + throw std::runtime_error( "Unrecognised warning: '" + _warning + "'" ); + } + inline void setOrder( ConfigData& config, std::string const& order ) { + if( startsWith( "declared", order ) ) + config.runOrder = RunTests::InDeclarationOrder; + else if( startsWith( "lexical", order ) ) + config.runOrder = RunTests::InLexicographicalOrder; + else if( startsWith( "random", order ) ) + config.runOrder = RunTests::InRandomOrder; + else + throw std::runtime_error( "Unrecognised ordering: '" + order + "'" ); + } + inline void setRngSeed( ConfigData& config, std::string const& seed ) { + if( seed == "time" ) { + config.rngSeed = static_cast( std::time(0) ); + } + else { + std::stringstream ss; + ss << seed; + ss >> config.rngSeed; + if( ss.fail() ) + throw std::runtime_error( "Argment to --rng-seed should be the word 'time' or a number" ); + } + } + inline void setVerbosity( ConfigData& config, int level ) { + // !TBD: accept strings? + config.verbosity = static_cast( level ); + } + inline void setShowDurations( ConfigData& config, bool _showDurations ) { + config.showDurations = _showDurations + ? ShowDurations::Always + : ShowDurations::Never; + } + inline void setUseColour( ConfigData& config, std::string const& value ) { + std::string mode = toLower( value ); + + if( mode == "yes" ) + config.useColour = UseColour::Yes; + else if( mode == "no" ) + config.useColour = UseColour::No; + else if( mode == "auto" ) + config.useColour = UseColour::Auto; + else + throw std::runtime_error( "colour mode must be one of: auto, yes or no" ); + } + inline void forceColour( ConfigData& config ) { + config.useColour = UseColour::Yes; + } + inline void loadTestNamesFromFile( ConfigData& config, std::string const& _filename ) { + std::ifstream f( _filename.c_str() ); + if( !f.is_open() ) + throw std::domain_error( "Unable to load input file: " + _filename ); + + std::string line; + while( std::getline( f, line ) ) { + line = trim(line); + if( !line.empty() && !startsWith( line, "#" ) ) + addTestOrTags( config, "\"" + line + "\"," ); + } + } + + inline Clara::CommandLine makeCommandLineParser() { + + using namespace Clara; + CommandLine cli; + + cli.bindProcessName( &ConfigData::processName ); + + cli["-?"]["-h"]["--help"] + .describe( "display usage information" ) + .bind( &ConfigData::showHelp ); + + cli["-l"]["--list-tests"] + .describe( "list all/matching test cases" ) + .bind( &ConfigData::listTests ); + + cli["-t"]["--list-tags"] + .describe( "list all/matching tags" ) + .bind( &ConfigData::listTags ); + + cli["-s"]["--success"] + .describe( "include successful tests in output" ) + .bind( &ConfigData::showSuccessfulTests ); + + cli["-b"]["--break"] + .describe( "break into debugger on failure" ) + .bind( &ConfigData::shouldDebugBreak ); + + cli["-e"]["--nothrow"] + .describe( "skip exception tests" ) + .bind( &ConfigData::noThrow ); + + cli["-i"]["--invisibles"] + .describe( "show invisibles (tabs, newlines)" ) + .bind( &ConfigData::showInvisibles ); + + cli["-o"]["--out"] + .describe( "output filename" ) + .bind( &ConfigData::outputFilename, "filename" ); + + cli["-r"]["--reporter"] +// .placeholder( "name[:filename]" ) + .describe( "reporter to use (defaults to console)" ) + .bind( &addReporterName, "name" ); + + cli["-n"]["--name"] + .describe( "suite name" ) + .bind( &ConfigData::name, "name" ); + + cli["-a"]["--abort"] + .describe( "abort at first failure" ) + .bind( &abortAfterFirst ); + + cli["-x"]["--abortx"] + .describe( "abort after x failures" ) + .bind( &abortAfterX, "no. failures" ); + + cli["-w"]["--warn"] + .describe( "enable warnings" ) + .bind( &addWarning, "warning name" ); + +// - needs updating if reinstated +// cli.into( &setVerbosity ) +// .describe( "level of verbosity (0=no output)" ) +// .shortOpt( "v") +// .longOpt( "verbosity" ) +// .placeholder( "level" ); + + cli[_] + .describe( "which test or tests to use" ) + .bind( &addTestOrTags, "test name, pattern or tags" ); + + cli["-d"]["--durations"] + .describe( "show test durations" ) + .bind( &setShowDurations, "yes|no" ); + + cli["-f"]["--input-file"] + .describe( "load test names to run from a file" ) + .bind( &loadTestNamesFromFile, "filename" ); + + cli["-#"]["--filenames-as-tags"] + .describe( "adds a tag for the filename" ) + .bind( &ConfigData::filenamesAsTags ); + + // Less common commands which don't have a short form + cli["--list-test-names-only"] + .describe( "list all/matching test cases names only" ) + .bind( &ConfigData::listTestNamesOnly ); + + cli["--list-reporters"] + .describe( "list all reporters" ) + .bind( &ConfigData::listReporters ); + + cli["--order"] + .describe( "test case order (defaults to decl)" ) + .bind( &setOrder, "decl|lex|rand" ); + + cli["--rng-seed"] + .describe( "set a specific seed for random numbers" ) + .bind( &setRngSeed, "'time'|number" ); + + cli["--force-colour"] + .describe( "force colourised output (deprecated)" ) + .bind( &forceColour ); + + cli["--use-colour"] + .describe( "should output be colourised" ) + .bind( &setUseColour, "yes|no" ); + + return cli; + } + +} // end namespace Catch + +// #included from: internal/catch_list.hpp +#define TWOBLUECUBES_CATCH_LIST_HPP_INCLUDED + +// #included from: catch_text.h +#define TWOBLUECUBES_CATCH_TEXT_H_INCLUDED + +#define TBC_TEXT_FORMAT_CONSOLE_WIDTH CATCH_CONFIG_CONSOLE_WIDTH + +#define CLICHE_TBC_TEXT_FORMAT_OUTER_NAMESPACE Catch +// #included from: ../external/tbc_text_format.h +// Only use header guard if we are not using an outer namespace +#ifndef CLICHE_TBC_TEXT_FORMAT_OUTER_NAMESPACE +# ifdef TWOBLUECUBES_TEXT_FORMAT_H_INCLUDED +# ifndef TWOBLUECUBES_TEXT_FORMAT_H_ALREADY_INCLUDED +# define TWOBLUECUBES_TEXT_FORMAT_H_ALREADY_INCLUDED +# endif +# else +# define TWOBLUECUBES_TEXT_FORMAT_H_INCLUDED +# endif +#endif +#ifndef TWOBLUECUBES_TEXT_FORMAT_H_ALREADY_INCLUDED +#include +#include +#include + +// Use optional outer namespace +#ifdef CLICHE_TBC_TEXT_FORMAT_OUTER_NAMESPACE +namespace CLICHE_TBC_TEXT_FORMAT_OUTER_NAMESPACE { +#endif + +namespace Tbc { + +#ifdef TBC_TEXT_FORMAT_CONSOLE_WIDTH + const unsigned int consoleWidth = TBC_TEXT_FORMAT_CONSOLE_WIDTH; +#else + const unsigned int consoleWidth = 80; +#endif + + struct TextAttributes { + TextAttributes() + : initialIndent( std::string::npos ), + indent( 0 ), + width( consoleWidth-1 ), + tabChar( '\t' ) + {} + + TextAttributes& setInitialIndent( std::size_t _value ) { initialIndent = _value; return *this; } + TextAttributes& setIndent( std::size_t _value ) { indent = _value; return *this; } + TextAttributes& setWidth( std::size_t _value ) { width = _value; return *this; } + TextAttributes& setTabChar( char _value ) { tabChar = _value; return *this; } + + std::size_t initialIndent; // indent of first line, or npos + std::size_t indent; // indent of subsequent lines, or all if initialIndent is npos + std::size_t width; // maximum width of text, including indent. Longer text will wrap + char tabChar; // If this char is seen the indent is changed to current pos + }; + + class Text { + public: + Text( std::string const& _str, TextAttributes const& _attr = TextAttributes() ) + : attr( _attr ) + { + std::string wrappableChars = " [({.,/|\\-"; + std::size_t indent = _attr.initialIndent != std::string::npos + ? _attr.initialIndent + : _attr.indent; + std::string remainder = _str; + + while( !remainder.empty() ) { + if( lines.size() >= 1000 ) { + lines.push_back( "... message truncated due to excessive size" ); + return; + } + std::size_t tabPos = std::string::npos; + std::size_t width = (std::min)( remainder.size(), _attr.width - indent ); + std::size_t pos = remainder.find_first_of( '\n' ); + if( pos <= width ) { + width = pos; + } + pos = remainder.find_last_of( _attr.tabChar, width ); + if( pos != std::string::npos ) { + tabPos = pos; + if( remainder[width] == '\n' ) + width--; + remainder = remainder.substr( 0, tabPos ) + remainder.substr( tabPos+1 ); + } + + if( width == remainder.size() ) { + spliceLine( indent, remainder, width ); + } + else if( remainder[width] == '\n' ) { + spliceLine( indent, remainder, width ); + if( width <= 1 || remainder.size() != 1 ) + remainder = remainder.substr( 1 ); + indent = _attr.indent; + } + else { + pos = remainder.find_last_of( wrappableChars, width ); + if( pos != std::string::npos && pos > 0 ) { + spliceLine( indent, remainder, pos ); + if( remainder[0] == ' ' ) + remainder = remainder.substr( 1 ); + } + else { + spliceLine( indent, remainder, width-1 ); + lines.back() += "-"; + } + if( lines.size() == 1 ) + indent = _attr.indent; + if( tabPos != std::string::npos ) + indent += tabPos; + } + } + } + + void spliceLine( std::size_t _indent, std::string& _remainder, std::size_t _pos ) { + lines.push_back( std::string( _indent, ' ' ) + _remainder.substr( 0, _pos ) ); + _remainder = _remainder.substr( _pos ); + } + + typedef std::vector::const_iterator const_iterator; + + const_iterator begin() const { return lines.begin(); } + const_iterator end() const { return lines.end(); } + std::string const& last() const { return lines.back(); } + std::size_t size() const { return lines.size(); } + std::string const& operator[]( std::size_t _index ) const { return lines[_index]; } + std::string toString() const { + std::ostringstream oss; + oss << *this; + return oss.str(); + } + + inline friend std::ostream& operator << ( std::ostream& _stream, Text const& _text ) { + for( Text::const_iterator it = _text.begin(), itEnd = _text.end(); + it != itEnd; ++it ) { + if( it != _text.begin() ) + _stream << "\n"; + _stream << *it; + } + return _stream; + } + + private: + std::string str; + TextAttributes attr; + std::vector lines; + }; + +} // end namespace Tbc + +#ifdef CLICHE_TBC_TEXT_FORMAT_OUTER_NAMESPACE +} // end outer namespace +#endif + +#endif // TWOBLUECUBES_TEXT_FORMAT_H_ALREADY_INCLUDED +#undef CLICHE_TBC_TEXT_FORMAT_OUTER_NAMESPACE + +namespace Catch { + using Tbc::Text; + using Tbc::TextAttributes; +} + +// #included from: catch_console_colour.hpp +#define TWOBLUECUBES_CATCH_CONSOLE_COLOUR_HPP_INCLUDED + +namespace Catch { + + struct Colour { + enum Code { + None = 0, + + White, + Red, + Green, + Blue, + Cyan, + Yellow, + Grey, + + Bright = 0x10, + + BrightRed = Bright | Red, + BrightGreen = Bright | Green, + LightGrey = Bright | Grey, + BrightWhite = Bright | White, + + // By intention + FileName = LightGrey, + Warning = Yellow, + ResultError = BrightRed, + ResultSuccess = BrightGreen, + ResultExpectedFailure = Warning, + + Error = BrightRed, + Success = Green, + + OriginalExpression = Cyan, + ReconstructedExpression = Yellow, + + SecondaryText = LightGrey, + Headers = White + }; + + // Use constructed object for RAII guard + Colour( Code _colourCode ); + Colour( Colour const& other ); + ~Colour(); + + // Use static method for one-shot changes + static void use( Code _colourCode ); + + private: + bool m_moved; + }; + + inline std::ostream& operator << ( std::ostream& os, Colour const& ) { return os; } + +} // end namespace Catch + +// #included from: catch_interfaces_reporter.h +#define TWOBLUECUBES_CATCH_INTERFACES_REPORTER_H_INCLUDED + +#include +#include +#include +#include + +namespace Catch +{ + struct ReporterConfig { + explicit ReporterConfig( Ptr const& _fullConfig ) + : m_stream( &_fullConfig->stream() ), m_fullConfig( _fullConfig ) {} + + ReporterConfig( Ptr const& _fullConfig, std::ostream& _stream ) + : m_stream( &_stream ), m_fullConfig( _fullConfig ) {} + + std::ostream& stream() const { return *m_stream; } + Ptr fullConfig() const { return m_fullConfig; } + + private: + std::ostream* m_stream; + Ptr m_fullConfig; + }; + + struct ReporterPreferences { + ReporterPreferences() + : shouldRedirectStdOut( false ) + {} + + bool shouldRedirectStdOut; + }; + + template + struct LazyStat : Option { + LazyStat() : used( false ) {} + LazyStat& operator=( T const& _value ) { + Option::operator=( _value ); + used = false; + return *this; + } + void reset() { + Option::reset(); + used = false; + } + bool used; + }; + + struct TestRunInfo { + TestRunInfo( std::string const& _name ) : name( _name ) {} + std::string name; + }; + struct GroupInfo { + GroupInfo( std::string const& _name, + std::size_t _groupIndex, + std::size_t _groupsCount ) + : name( _name ), + groupIndex( _groupIndex ), + groupsCounts( _groupsCount ) + {} + + std::string name; + std::size_t groupIndex; + std::size_t groupsCounts; + }; + + struct AssertionStats { + AssertionStats( AssertionResult const& _assertionResult, + std::vector const& _infoMessages, + Totals const& _totals ) + : assertionResult( _assertionResult ), + infoMessages( _infoMessages ), + totals( _totals ) + { + if( assertionResult.hasMessage() ) { + // Copy message into messages list. + // !TBD This should have been done earlier, somewhere + MessageBuilder builder( assertionResult.getTestMacroName(), assertionResult.getSourceInfo(), assertionResult.getResultType() ); + builder << assertionResult.getMessage(); + builder.m_info.message = builder.m_stream.str(); + + infoMessages.push_back( builder.m_info ); + } + } + virtual ~AssertionStats(); + +# ifdef CATCH_CONFIG_CPP11_GENERATED_METHODS + AssertionStats( AssertionStats const& ) = default; + AssertionStats( AssertionStats && ) = default; + AssertionStats& operator = ( AssertionStats const& ) = default; + AssertionStats& operator = ( AssertionStats && ) = default; +# endif + + AssertionResult assertionResult; + std::vector infoMessages; + Totals totals; + }; + + struct SectionStats { + SectionStats( SectionInfo const& _sectionInfo, + Counts const& _assertions, + double _durationInSeconds, + bool _missingAssertions ) + : sectionInfo( _sectionInfo ), + assertions( _assertions ), + durationInSeconds( _durationInSeconds ), + missingAssertions( _missingAssertions ) + {} + virtual ~SectionStats(); +# ifdef CATCH_CONFIG_CPP11_GENERATED_METHODS + SectionStats( SectionStats const& ) = default; + SectionStats( SectionStats && ) = default; + SectionStats& operator = ( SectionStats const& ) = default; + SectionStats& operator = ( SectionStats && ) = default; +# endif + + SectionInfo sectionInfo; + Counts assertions; + double durationInSeconds; + bool missingAssertions; + }; + + struct TestCaseStats { + TestCaseStats( TestCaseInfo const& _testInfo, + Totals const& _totals, + std::string const& _stdOut, + std::string const& _stdErr, + bool _aborting ) + : testInfo( _testInfo ), + totals( _totals ), + stdOut( _stdOut ), + stdErr( _stdErr ), + aborting( _aborting ) + {} + virtual ~TestCaseStats(); + +# ifdef CATCH_CONFIG_CPP11_GENERATED_METHODS + TestCaseStats( TestCaseStats const& ) = default; + TestCaseStats( TestCaseStats && ) = default; + TestCaseStats& operator = ( TestCaseStats const& ) = default; + TestCaseStats& operator = ( TestCaseStats && ) = default; +# endif + + TestCaseInfo testInfo; + Totals totals; + std::string stdOut; + std::string stdErr; + bool aborting; + }; + + struct TestGroupStats { + TestGroupStats( GroupInfo const& _groupInfo, + Totals const& _totals, + bool _aborting ) + : groupInfo( _groupInfo ), + totals( _totals ), + aborting( _aborting ) + {} + TestGroupStats( GroupInfo const& _groupInfo ) + : groupInfo( _groupInfo ), + aborting( false ) + {} + virtual ~TestGroupStats(); + +# ifdef CATCH_CONFIG_CPP11_GENERATED_METHODS + TestGroupStats( TestGroupStats const& ) = default; + TestGroupStats( TestGroupStats && ) = default; + TestGroupStats& operator = ( TestGroupStats const& ) = default; + TestGroupStats& operator = ( TestGroupStats && ) = default; +# endif + + GroupInfo groupInfo; + Totals totals; + bool aborting; + }; + + struct TestRunStats { + TestRunStats( TestRunInfo const& _runInfo, + Totals const& _totals, + bool _aborting ) + : runInfo( _runInfo ), + totals( _totals ), + aborting( _aborting ) + {} + virtual ~TestRunStats(); + +# ifndef CATCH_CONFIG_CPP11_GENERATED_METHODS + TestRunStats( TestRunStats const& _other ) + : runInfo( _other.runInfo ), + totals( _other.totals ), + aborting( _other.aborting ) + {} +# else + TestRunStats( TestRunStats const& ) = default; + TestRunStats( TestRunStats && ) = default; + TestRunStats& operator = ( TestRunStats const& ) = default; + TestRunStats& operator = ( TestRunStats && ) = default; +# endif + + TestRunInfo runInfo; + Totals totals; + bool aborting; + }; + + class MultipleReporters; + + struct IStreamingReporter : IShared { + virtual ~IStreamingReporter(); + + // Implementing class must also provide the following static method: + // static std::string getDescription(); + + virtual ReporterPreferences getPreferences() const = 0; + + virtual void noMatchingTestCases( std::string const& spec ) = 0; + + virtual void testRunStarting( TestRunInfo const& testRunInfo ) = 0; + virtual void testGroupStarting( GroupInfo const& groupInfo ) = 0; + + virtual void testCaseStarting( TestCaseInfo const& testInfo ) = 0; + virtual void sectionStarting( SectionInfo const& sectionInfo ) = 0; + + virtual void assertionStarting( AssertionInfo const& assertionInfo ) = 0; + + // The return value indicates if the messages buffer should be cleared: + virtual bool assertionEnded( AssertionStats const& assertionStats ) = 0; + + virtual void sectionEnded( SectionStats const& sectionStats ) = 0; + virtual void testCaseEnded( TestCaseStats const& testCaseStats ) = 0; + virtual void testGroupEnded( TestGroupStats const& testGroupStats ) = 0; + virtual void testRunEnded( TestRunStats const& testRunStats ) = 0; + + virtual void skipTest( TestCaseInfo const& testInfo ) = 0; + + virtual MultipleReporters* tryAsMulti() { return CATCH_NULL; } + }; + + struct IReporterFactory : IShared { + virtual ~IReporterFactory(); + virtual IStreamingReporter* create( ReporterConfig const& config ) const = 0; + virtual std::string getDescription() const = 0; + }; + + struct IReporterRegistry { + typedef std::map > FactoryMap; + typedef std::vector > Listeners; + + virtual ~IReporterRegistry(); + virtual IStreamingReporter* create( std::string const& name, Ptr const& config ) const = 0; + virtual FactoryMap const& getFactories() const = 0; + virtual Listeners const& getListeners() const = 0; + }; + + Ptr addReporter( Ptr const& existingReporter, Ptr const& additionalReporter ); + +} + +#include +#include + +namespace Catch { + + inline std::size_t listTests( Config const& config ) { + + TestSpec testSpec = config.testSpec(); + if( config.testSpec().hasFilters() ) + Catch::cout() << "Matching test cases:\n"; + else { + Catch::cout() << "All available test cases:\n"; + testSpec = TestSpecParser( ITagAliasRegistry::get() ).parse( "*" ).testSpec(); + } + + std::size_t matchedTests = 0; + TextAttributes nameAttr, tagsAttr; + nameAttr.setInitialIndent( 2 ).setIndent( 4 ); + tagsAttr.setIndent( 6 ); + + std::vector matchedTestCases = filterTests( getAllTestCasesSorted( config ), testSpec, config ); + for( std::vector::const_iterator it = matchedTestCases.begin(), itEnd = matchedTestCases.end(); + it != itEnd; + ++it ) { + matchedTests++; + TestCaseInfo const& testCaseInfo = it->getTestCaseInfo(); + Colour::Code colour = testCaseInfo.isHidden() + ? Colour::SecondaryText + : Colour::None; + Colour colourGuard( colour ); + + Catch::cout() << Text( testCaseInfo.name, nameAttr ) << std::endl; + if( !testCaseInfo.tags.empty() ) + Catch::cout() << Text( testCaseInfo.tagsAsString, tagsAttr ) << std::endl; + } + + if( !config.testSpec().hasFilters() ) + Catch::cout() << pluralise( matchedTests, "test case" ) << "\n" << std::endl; + else + Catch::cout() << pluralise( matchedTests, "matching test case" ) << "\n" << std::endl; + return matchedTests; + } + + inline std::size_t listTestsNamesOnly( Config const& config ) { + TestSpec testSpec = config.testSpec(); + if( !config.testSpec().hasFilters() ) + testSpec = TestSpecParser( ITagAliasRegistry::get() ).parse( "*" ).testSpec(); + std::size_t matchedTests = 0; + std::vector matchedTestCases = filterTests( getAllTestCasesSorted( config ), testSpec, config ); + for( std::vector::const_iterator it = matchedTestCases.begin(), itEnd = matchedTestCases.end(); + it != itEnd; + ++it ) { + matchedTests++; + TestCaseInfo const& testCaseInfo = it->getTestCaseInfo(); + Catch::cout() << testCaseInfo.name << std::endl; + } + return matchedTests; + } + + struct TagInfo { + TagInfo() : count ( 0 ) {} + void add( std::string const& spelling ) { + ++count; + spellings.insert( spelling ); + } + std::string all() const { + std::string out; + for( std::set::const_iterator it = spellings.begin(), itEnd = spellings.end(); + it != itEnd; + ++it ) + out += "[" + *it + "]"; + return out; + } + std::set spellings; + std::size_t count; + }; + + inline std::size_t listTags( Config const& config ) { + TestSpec testSpec = config.testSpec(); + if( config.testSpec().hasFilters() ) + Catch::cout() << "Tags for matching test cases:\n"; + else { + Catch::cout() << "All available tags:\n"; + testSpec = TestSpecParser( ITagAliasRegistry::get() ).parse( "*" ).testSpec(); + } + + std::map tagCounts; + + std::vector matchedTestCases = filterTests( getAllTestCasesSorted( config ), testSpec, config ); + for( std::vector::const_iterator it = matchedTestCases.begin(), itEnd = matchedTestCases.end(); + it != itEnd; + ++it ) { + for( std::set::const_iterator tagIt = it->getTestCaseInfo().tags.begin(), + tagItEnd = it->getTestCaseInfo().tags.end(); + tagIt != tagItEnd; + ++tagIt ) { + std::string tagName = *tagIt; + std::string lcaseTagName = toLower( tagName ); + std::map::iterator countIt = tagCounts.find( lcaseTagName ); + if( countIt == tagCounts.end() ) + countIt = tagCounts.insert( std::make_pair( lcaseTagName, TagInfo() ) ).first; + countIt->second.add( tagName ); + } + } + + for( std::map::const_iterator countIt = tagCounts.begin(), + countItEnd = tagCounts.end(); + countIt != countItEnd; + ++countIt ) { + std::ostringstream oss; + oss << " " << std::setw(2) << countIt->second.count << " "; + Text wrapper( countIt->second.all(), TextAttributes() + .setInitialIndent( 0 ) + .setIndent( oss.str().size() ) + .setWidth( CATCH_CONFIG_CONSOLE_WIDTH-10 ) ); + Catch::cout() << oss.str() << wrapper << "\n"; + } + Catch::cout() << pluralise( tagCounts.size(), "tag" ) << "\n" << std::endl; + return tagCounts.size(); + } + + inline std::size_t listReporters( Config const& /*config*/ ) { + Catch::cout() << "Available reporters:\n"; + IReporterRegistry::FactoryMap const& factories = getRegistryHub().getReporterRegistry().getFactories(); + IReporterRegistry::FactoryMap::const_iterator itBegin = factories.begin(), itEnd = factories.end(), it; + std::size_t maxNameLen = 0; + for(it = itBegin; it != itEnd; ++it ) + maxNameLen = (std::max)( maxNameLen, it->first.size() ); + + for(it = itBegin; it != itEnd; ++it ) { + Text wrapper( it->second->getDescription(), TextAttributes() + .setInitialIndent( 0 ) + .setIndent( 7+maxNameLen ) + .setWidth( CATCH_CONFIG_CONSOLE_WIDTH - maxNameLen-8 ) ); + Catch::cout() << " " + << it->first + << ":" + << std::string( maxNameLen - it->first.size() + 2, ' ' ) + << wrapper << "\n"; + } + Catch::cout() << std::endl; + return factories.size(); + } + + inline Option list( Config const& config ) { + Option listedCount; + if( config.listTests() ) + listedCount = listedCount.valueOr(0) + listTests( config ); + if( config.listTestNamesOnly() ) + listedCount = listedCount.valueOr(0) + listTestsNamesOnly( config ); + if( config.listTags() ) + listedCount = listedCount.valueOr(0) + listTags( config ); + if( config.listReporters() ) + listedCount = listedCount.valueOr(0) + listReporters( config ); + return listedCount; + } + +} // end namespace Catch + +// #included from: internal/catch_run_context.hpp +#define TWOBLUECUBES_CATCH_RUNNER_IMPL_HPP_INCLUDED + +// #included from: catch_test_case_tracker.hpp +#define TWOBLUECUBES_CATCH_TEST_CASE_TRACKER_HPP_INCLUDED + +#include +#include +#include +#include + +namespace Catch { +namespace TestCaseTracking { + + struct ITracker : SharedImpl<> { + virtual ~ITracker(); + + // static queries + virtual std::string name() const = 0; + + // dynamic queries + virtual bool isComplete() const = 0; // Successfully completed or failed + virtual bool isSuccessfullyCompleted() const = 0; + virtual bool isOpen() const = 0; // Started but not complete + virtual bool hasChildren() const = 0; + + virtual ITracker& parent() = 0; + + // actions + virtual void close() = 0; // Successfully complete + virtual void fail() = 0; + virtual void markAsNeedingAnotherRun() = 0; + + virtual void addChild( Ptr const& child ) = 0; + virtual ITracker* findChild( std::string const& name ) = 0; + virtual void openChild() = 0; + + // Debug/ checking + virtual bool isSectionTracker() const = 0; + virtual bool isIndexTracker() const = 0; + }; + + class TrackerContext { + + enum RunState { + NotStarted, + Executing, + CompletedCycle + }; + + Ptr m_rootTracker; + ITracker* m_currentTracker; + RunState m_runState; + + public: + + static TrackerContext& instance() { + static TrackerContext s_instance; + return s_instance; + } + + TrackerContext() + : m_currentTracker( CATCH_NULL ), + m_runState( NotStarted ) + {} + + ITracker& startRun(); + + void endRun() { + m_rootTracker.reset(); + m_currentTracker = CATCH_NULL; + m_runState = NotStarted; + } + + void startCycle() { + m_currentTracker = m_rootTracker.get(); + m_runState = Executing; + } + void completeCycle() { + m_runState = CompletedCycle; + } + + bool completedCycle() const { + return m_runState == CompletedCycle; + } + ITracker& currentTracker() { + return *m_currentTracker; + } + void setCurrentTracker( ITracker* tracker ) { + m_currentTracker = tracker; + } + }; + + class TrackerBase : public ITracker { + protected: + enum CycleState { + NotStarted, + Executing, + ExecutingChildren, + NeedsAnotherRun, + CompletedSuccessfully, + Failed + }; + class TrackerHasName { + std::string m_name; + public: + TrackerHasName( std::string const& name ) : m_name( name ) {} + bool operator ()( Ptr const& tracker ) { + return tracker->name() == m_name; + } + }; + typedef std::vector > Children; + std::string m_name; + TrackerContext& m_ctx; + ITracker* m_parent; + Children m_children; + CycleState m_runState; + public: + TrackerBase( std::string const& name, TrackerContext& ctx, ITracker* parent ) + : m_name( name ), + m_ctx( ctx ), + m_parent( parent ), + m_runState( NotStarted ) + {} + virtual ~TrackerBase(); + + virtual std::string name() const CATCH_OVERRIDE { + return m_name; + } + virtual bool isComplete() const CATCH_OVERRIDE { + return m_runState == CompletedSuccessfully || m_runState == Failed; + } + virtual bool isSuccessfullyCompleted() const CATCH_OVERRIDE { + return m_runState == CompletedSuccessfully; + } + virtual bool isOpen() const CATCH_OVERRIDE { + return m_runState != NotStarted && !isComplete(); + } + virtual bool hasChildren() const CATCH_OVERRIDE { + return !m_children.empty(); + } + + virtual void addChild( Ptr const& child ) CATCH_OVERRIDE { + m_children.push_back( child ); + } + + virtual ITracker* findChild( std::string const& name ) CATCH_OVERRIDE { + Children::const_iterator it = std::find_if( m_children.begin(), m_children.end(), TrackerHasName( name ) ); + return( it != m_children.end() ) + ? it->get() + : CATCH_NULL; + } + virtual ITracker& parent() CATCH_OVERRIDE { + assert( m_parent ); // Should always be non-null except for root + return *m_parent; + } + + virtual void openChild() CATCH_OVERRIDE { + if( m_runState != ExecutingChildren ) { + m_runState = ExecutingChildren; + if( m_parent ) + m_parent->openChild(); + } + } + + virtual bool isSectionTracker() const CATCH_OVERRIDE { return false; } + virtual bool isIndexTracker() const CATCH_OVERRIDE { return false; } + + void open() { + m_runState = Executing; + moveToThis(); + if( m_parent ) + m_parent->openChild(); + } + + virtual void close() CATCH_OVERRIDE { + + // Close any still open children (e.g. generators) + while( &m_ctx.currentTracker() != this ) + m_ctx.currentTracker().close(); + + switch( m_runState ) { + case NotStarted: + case CompletedSuccessfully: + case Failed: + throw std::logic_error( "Illogical state" ); + + case NeedsAnotherRun: + break;; + + case Executing: + m_runState = CompletedSuccessfully; + break; + case ExecutingChildren: + if( m_children.empty() || m_children.back()->isComplete() ) + m_runState = CompletedSuccessfully; + break; + + default: + throw std::logic_error( "Unexpected state" ); + } + moveToParent(); + m_ctx.completeCycle(); + } + virtual void fail() CATCH_OVERRIDE { + m_runState = Failed; + if( m_parent ) + m_parent->markAsNeedingAnotherRun(); + moveToParent(); + m_ctx.completeCycle(); + } + virtual void markAsNeedingAnotherRun() CATCH_OVERRIDE { + m_runState = NeedsAnotherRun; + } + private: + void moveToParent() { + assert( m_parent ); + m_ctx.setCurrentTracker( m_parent ); + } + void moveToThis() { + m_ctx.setCurrentTracker( this ); + } + }; + + class SectionTracker : public TrackerBase { + public: + SectionTracker( std::string const& name, TrackerContext& ctx, ITracker* parent ) + : TrackerBase( name, ctx, parent ) + {} + virtual ~SectionTracker(); + + virtual bool isSectionTracker() const CATCH_OVERRIDE { return true; } + + static SectionTracker& acquire( TrackerContext& ctx, std::string const& name ) { + SectionTracker* section = CATCH_NULL; + + ITracker& currentTracker = ctx.currentTracker(); + if( ITracker* childTracker = currentTracker.findChild( name ) ) { + assert( childTracker ); + assert( childTracker->isSectionTracker() ); + section = static_cast( childTracker ); + } + else { + section = new SectionTracker( name, ctx, ¤tTracker ); + currentTracker.addChild( section ); + } + if( !ctx.completedCycle() && !section->isComplete() ) { + + section->open(); + } + return *section; + } + }; + + class IndexTracker : public TrackerBase { + int m_size; + int m_index; + public: + IndexTracker( std::string const& name, TrackerContext& ctx, ITracker* parent, int size ) + : TrackerBase( name, ctx, parent ), + m_size( size ), + m_index( -1 ) + {} + virtual ~IndexTracker(); + + virtual bool isIndexTracker() const CATCH_OVERRIDE { return true; } + + static IndexTracker& acquire( TrackerContext& ctx, std::string const& name, int size ) { + IndexTracker* tracker = CATCH_NULL; + + ITracker& currentTracker = ctx.currentTracker(); + if( ITracker* childTracker = currentTracker.findChild( name ) ) { + assert( childTracker ); + assert( childTracker->isIndexTracker() ); + tracker = static_cast( childTracker ); + } + else { + tracker = new IndexTracker( name, ctx, ¤tTracker, size ); + currentTracker.addChild( tracker ); + } + + if( !ctx.completedCycle() && !tracker->isComplete() ) { + if( tracker->m_runState != ExecutingChildren && tracker->m_runState != NeedsAnotherRun ) + tracker->moveNext(); + tracker->open(); + } + + return *tracker; + } + + int index() const { return m_index; } + + void moveNext() { + m_index++; + m_children.clear(); + } + + virtual void close() CATCH_OVERRIDE { + TrackerBase::close(); + if( m_runState == CompletedSuccessfully && m_index < m_size-1 ) + m_runState = Executing; + } + }; + + inline ITracker& TrackerContext::startRun() { + m_rootTracker = new SectionTracker( "{root}", *this, CATCH_NULL ); + m_currentTracker = CATCH_NULL; + m_runState = Executing; + return *m_rootTracker; + } + +} // namespace TestCaseTracking + +using TestCaseTracking::ITracker; +using TestCaseTracking::TrackerContext; +using TestCaseTracking::SectionTracker; +using TestCaseTracking::IndexTracker; + +} // namespace Catch + +// #included from: catch_fatal_condition.hpp +#define TWOBLUECUBES_CATCH_FATAL_CONDITION_H_INCLUDED + +namespace Catch { + + // Report the error condition then exit the process + inline void fatal( std::string const& message, int exitCode ) { + IContext& context = Catch::getCurrentContext(); + IResultCapture* resultCapture = context.getResultCapture(); + resultCapture->handleFatalErrorCondition( message ); + + if( Catch::alwaysTrue() ) // avoids "no return" warnings + exit( exitCode ); + } + +} // namespace Catch + +#if defined ( CATCH_PLATFORM_WINDOWS ) ///////////////////////////////////////// + +namespace Catch { + + struct FatalConditionHandler { + void reset() {} + }; + +} // namespace Catch + +#else // Not Windows - assumed to be POSIX compatible ////////////////////////// + +#include + +namespace Catch { + + struct SignalDefs { int id; const char* name; }; + extern SignalDefs signalDefs[]; + SignalDefs signalDefs[] = { + { SIGINT, "SIGINT - Terminal interrupt signal" }, + { SIGILL, "SIGILL - Illegal instruction signal" }, + { SIGFPE, "SIGFPE - Floating point error signal" }, + { SIGSEGV, "SIGSEGV - Segmentation violation signal" }, + { SIGTERM, "SIGTERM - Termination request signal" }, + { SIGABRT, "SIGABRT - Abort (abnormal termination) signal" } + }; + + struct FatalConditionHandler { + + static void handleSignal( int sig ) { + for( std::size_t i = 0; i < sizeof(signalDefs)/sizeof(SignalDefs); ++i ) + if( sig == signalDefs[i].id ) + fatal( signalDefs[i].name, -sig ); + fatal( "", -sig ); + } + + FatalConditionHandler() : m_isSet( true ) { + for( std::size_t i = 0; i < sizeof(signalDefs)/sizeof(SignalDefs); ++i ) + signal( signalDefs[i].id, handleSignal ); + } + ~FatalConditionHandler() { + reset(); + } + void reset() { + if( m_isSet ) { + for( std::size_t i = 0; i < sizeof(signalDefs)/sizeof(SignalDefs); ++i ) + signal( signalDefs[i].id, SIG_DFL ); + m_isSet = false; + } + } + + bool m_isSet; + }; + +} // namespace Catch + +#endif // not Windows + +#include +#include + +namespace Catch { + + class StreamRedirect { + + public: + StreamRedirect( std::ostream& stream, std::string& targetString ) + : m_stream( stream ), + m_prevBuf( stream.rdbuf() ), + m_targetString( targetString ) + { + stream.rdbuf( m_oss.rdbuf() ); + } + + ~StreamRedirect() { + m_targetString += m_oss.str(); + m_stream.rdbuf( m_prevBuf ); + } + + private: + std::ostream& m_stream; + std::streambuf* m_prevBuf; + std::ostringstream m_oss; + std::string& m_targetString; + }; + + /////////////////////////////////////////////////////////////////////////// + + class RunContext : public IResultCapture, public IRunner { + + RunContext( RunContext const& ); + void operator =( RunContext const& ); + + public: + + explicit RunContext( Ptr const& _config, Ptr const& reporter ) + : m_runInfo( _config->name() ), + m_context( getCurrentMutableContext() ), + m_activeTestCase( CATCH_NULL ), + m_config( _config ), + m_reporter( reporter ) + { + m_context.setRunner( this ); + m_context.setConfig( m_config ); + m_context.setResultCapture( this ); + m_reporter->testRunStarting( m_runInfo ); + } + + virtual ~RunContext() { + m_reporter->testRunEnded( TestRunStats( m_runInfo, m_totals, aborting() ) ); + } + + void testGroupStarting( std::string const& testSpec, std::size_t groupIndex, std::size_t groupsCount ) { + m_reporter->testGroupStarting( GroupInfo( testSpec, groupIndex, groupsCount ) ); + } + void testGroupEnded( std::string const& testSpec, Totals const& totals, std::size_t groupIndex, std::size_t groupsCount ) { + m_reporter->testGroupEnded( TestGroupStats( GroupInfo( testSpec, groupIndex, groupsCount ), totals, aborting() ) ); + } + + Totals runTest( TestCase const& testCase ) { + Totals prevTotals = m_totals; + + std::string redirectedCout; + std::string redirectedCerr; + + TestCaseInfo testInfo = testCase.getTestCaseInfo(); + + m_reporter->testCaseStarting( testInfo ); + + m_activeTestCase = &testCase; + + do { + m_trackerContext.startRun(); + do { + m_trackerContext.startCycle(); + m_testCaseTracker = &SectionTracker::acquire( m_trackerContext, testInfo.name ); + runCurrentTest( redirectedCout, redirectedCerr ); + } + while( !m_testCaseTracker->isSuccessfullyCompleted() && !aborting() ); + } + // !TBD: deprecated - this will be replaced by indexed trackers + while( getCurrentContext().advanceGeneratorsForCurrentTest() && !aborting() ); + + Totals deltaTotals = m_totals.delta( prevTotals ); + if( testInfo.expectedToFail() && deltaTotals.testCases.passed > 0 ) { + deltaTotals.assertions.failed++; + deltaTotals.testCases.passed--; + deltaTotals.testCases.failed++; + } + m_totals.testCases += deltaTotals.testCases; + m_reporter->testCaseEnded( TestCaseStats( testInfo, + deltaTotals, + redirectedCout, + redirectedCerr, + aborting() ) ); + + m_activeTestCase = CATCH_NULL; + m_testCaseTracker = CATCH_NULL; + + return deltaTotals; + } + + Ptr config() const { + return m_config; + } + + private: // IResultCapture + + virtual void assertionEnded( AssertionResult const& result ) { + if( result.getResultType() == ResultWas::Ok ) { + m_totals.assertions.passed++; + } + else if( !result.isOk() ) { + m_totals.assertions.failed++; + } + + if( m_reporter->assertionEnded( AssertionStats( result, m_messages, m_totals ) ) ) + m_messages.clear(); + + // Reset working state + m_lastAssertionInfo = AssertionInfo( "", m_lastAssertionInfo.lineInfo, "{Unknown expression after the reported line}" , m_lastAssertionInfo.resultDisposition ); + m_lastResult = result; + } + + virtual bool sectionStarted ( + SectionInfo const& sectionInfo, + Counts& assertions + ) + { + std::ostringstream oss; + oss << sectionInfo.name << "@" << sectionInfo.lineInfo; + + ITracker& sectionTracker = SectionTracker::acquire( m_trackerContext, oss.str() ); + if( !sectionTracker.isOpen() ) + return false; + m_activeSections.push_back( §ionTracker ); + + m_lastAssertionInfo.lineInfo = sectionInfo.lineInfo; + + m_reporter->sectionStarting( sectionInfo ); + + assertions = m_totals.assertions; + + return true; + } + bool testForMissingAssertions( Counts& assertions ) { + if( assertions.total() != 0 ) + return false; + if( !m_config->warnAboutMissingAssertions() ) + return false; + if( m_trackerContext.currentTracker().hasChildren() ) + return false; + m_totals.assertions.failed++; + assertions.failed++; + return true; + } + + virtual void sectionEnded( SectionEndInfo const& endInfo ) { + Counts assertions = m_totals.assertions - endInfo.prevAssertions; + bool missingAssertions = testForMissingAssertions( assertions ); + + if( !m_activeSections.empty() ) { + m_activeSections.back()->close(); + m_activeSections.pop_back(); + } + + m_reporter->sectionEnded( SectionStats( endInfo.sectionInfo, assertions, endInfo.durationInSeconds, missingAssertions ) ); + m_messages.clear(); + } + + virtual void sectionEndedEarly( SectionEndInfo const& endInfo ) { + if( m_unfinishedSections.empty() ) + m_activeSections.back()->fail(); + else + m_activeSections.back()->close(); + m_activeSections.pop_back(); + + m_unfinishedSections.push_back( endInfo ); + } + + virtual void pushScopedMessage( MessageInfo const& message ) { + m_messages.push_back( message ); + } + + virtual void popScopedMessage( MessageInfo const& message ) { + m_messages.erase( std::remove( m_messages.begin(), m_messages.end(), message ), m_messages.end() ); + } + + virtual std::string getCurrentTestName() const { + return m_activeTestCase + ? m_activeTestCase->getTestCaseInfo().name + : ""; + } + + virtual const AssertionResult* getLastResult() const { + return &m_lastResult; + } + + virtual void handleFatalErrorCondition( std::string const& message ) { + ResultBuilder resultBuilder = makeUnexpectedResultBuilder(); + resultBuilder.setResultType( ResultWas::FatalErrorCondition ); + resultBuilder << message; + resultBuilder.captureExpression(); + + handleUnfinishedSections(); + + // Recreate section for test case (as we will lose the one that was in scope) + TestCaseInfo const& testCaseInfo = m_activeTestCase->getTestCaseInfo(); + SectionInfo testCaseSection( testCaseInfo.lineInfo, testCaseInfo.name, testCaseInfo.description ); + + Counts assertions; + assertions.failed = 1; + SectionStats testCaseSectionStats( testCaseSection, assertions, 0, false ); + m_reporter->sectionEnded( testCaseSectionStats ); + + TestCaseInfo testInfo = m_activeTestCase->getTestCaseInfo(); + + Totals deltaTotals; + deltaTotals.testCases.failed = 1; + m_reporter->testCaseEnded( TestCaseStats( testInfo, + deltaTotals, + "", + "", + false ) ); + m_totals.testCases.failed++; + testGroupEnded( "", m_totals, 1, 1 ); + m_reporter->testRunEnded( TestRunStats( m_runInfo, m_totals, false ) ); + } + + public: + // !TBD We need to do this another way! + bool aborting() const { + return m_totals.assertions.failed == static_cast( m_config->abortAfter() ); + } + + private: + + void runCurrentTest( std::string& redirectedCout, std::string& redirectedCerr ) { + TestCaseInfo const& testCaseInfo = m_activeTestCase->getTestCaseInfo(); + SectionInfo testCaseSection( testCaseInfo.lineInfo, testCaseInfo.name, testCaseInfo.description ); + m_reporter->sectionStarting( testCaseSection ); + Counts prevAssertions = m_totals.assertions; + double duration = 0; + try { + m_lastAssertionInfo = AssertionInfo( "TEST_CASE", testCaseInfo.lineInfo, "", ResultDisposition::Normal ); + + seedRng( *m_config ); + + Timer timer; + timer.start(); + if( m_reporter->getPreferences().shouldRedirectStdOut ) { + StreamRedirect coutRedir( Catch::cout(), redirectedCout ); + StreamRedirect cerrRedir( Catch::cerr(), redirectedCerr ); + invokeActiveTestCase(); + } + else { + invokeActiveTestCase(); + } + duration = timer.getElapsedSeconds(); + } + catch( TestFailureException& ) { + // This just means the test was aborted due to failure + } + catch(...) { + makeUnexpectedResultBuilder().useActiveException(); + } + m_testCaseTracker->close(); + handleUnfinishedSections(); + m_messages.clear(); + + Counts assertions = m_totals.assertions - prevAssertions; + bool missingAssertions = testForMissingAssertions( assertions ); + + if( testCaseInfo.okToFail() ) { + std::swap( assertions.failedButOk, assertions.failed ); + m_totals.assertions.failed -= assertions.failedButOk; + m_totals.assertions.failedButOk += assertions.failedButOk; + } + + SectionStats testCaseSectionStats( testCaseSection, assertions, duration, missingAssertions ); + m_reporter->sectionEnded( testCaseSectionStats ); + } + + void invokeActiveTestCase() { + FatalConditionHandler fatalConditionHandler; // Handle signals + m_activeTestCase->invoke(); + fatalConditionHandler.reset(); + } + + private: + + ResultBuilder makeUnexpectedResultBuilder() const { + return ResultBuilder( m_lastAssertionInfo.macroName.c_str(), + m_lastAssertionInfo.lineInfo, + m_lastAssertionInfo.capturedExpression.c_str(), + m_lastAssertionInfo.resultDisposition ); + } + + void handleUnfinishedSections() { + // If sections ended prematurely due to an exception we stored their + // infos here so we can tear them down outside the unwind process. + for( std::vector::const_reverse_iterator it = m_unfinishedSections.rbegin(), + itEnd = m_unfinishedSections.rend(); + it != itEnd; + ++it ) + sectionEnded( *it ); + m_unfinishedSections.clear(); + } + + TestRunInfo m_runInfo; + IMutableContext& m_context; + TestCase const* m_activeTestCase; + ITracker* m_testCaseTracker; + ITracker* m_currentSectionTracker; + AssertionResult m_lastResult; + + Ptr m_config; + Totals m_totals; + Ptr m_reporter; + std::vector m_messages; + AssertionInfo m_lastAssertionInfo; + std::vector m_unfinishedSections; + std::vector m_activeSections; + TrackerContext m_trackerContext; + }; + + IResultCapture& getResultCapture() { + if( IResultCapture* capture = getCurrentContext().getResultCapture() ) + return *capture; + else + throw std::logic_error( "No result capture instance" ); + } + +} // end namespace Catch + +// #included from: internal/catch_version.h +#define TWOBLUECUBES_CATCH_VERSION_H_INCLUDED + +namespace Catch { + + // Versioning information + struct Version { + Version( unsigned int _majorVersion, + unsigned int _minorVersion, + unsigned int _patchNumber, + std::string const& _branchName, + unsigned int _buildNumber ); + + unsigned int const majorVersion; + unsigned int const minorVersion; + unsigned int const patchNumber; + + // buildNumber is only used if branchName is not null + std::string const branchName; + unsigned int const buildNumber; + + friend std::ostream& operator << ( std::ostream& os, Version const& version ); + + private: + void operator=( Version const& ); + }; + + extern Version libraryVersion; +} + +#include +#include +#include + +namespace Catch { + + Ptr createReporter( std::string const& reporterName, Ptr const& config ) { + Ptr reporter = getRegistryHub().getReporterRegistry().create( reporterName, config.get() ); + if( !reporter ) { + std::ostringstream oss; + oss << "No reporter registered with name: '" << reporterName << "'"; + throw std::domain_error( oss.str() ); + } + return reporter; + } + + Ptr makeReporter( Ptr const& config ) { + std::vector reporters = config->getReporterNames(); + if( reporters.empty() ) + reporters.push_back( "console" ); + + Ptr reporter; + for( std::vector::const_iterator it = reporters.begin(), itEnd = reporters.end(); + it != itEnd; + ++it ) + reporter = addReporter( reporter, createReporter( *it, config ) ); + return reporter; + } + Ptr addListeners( Ptr const& config, Ptr reporters ) { + IReporterRegistry::Listeners listeners = getRegistryHub().getReporterRegistry().getListeners(); + for( IReporterRegistry::Listeners::const_iterator it = listeners.begin(), itEnd = listeners.end(); + it != itEnd; + ++it ) + reporters = addReporter(reporters, (*it)->create( ReporterConfig( config ) ) ); + return reporters; + } + + Totals runTests( Ptr const& config ) { + + Ptr iconfig = config.get(); + + Ptr reporter = makeReporter( config ); + reporter = addListeners( iconfig, reporter ); + + RunContext context( iconfig, reporter ); + + Totals totals; + + context.testGroupStarting( config->name(), 1, 1 ); + + TestSpec testSpec = config->testSpec(); + if( !testSpec.hasFilters() ) + testSpec = TestSpecParser( ITagAliasRegistry::get() ).parse( "~[.]" ).testSpec(); // All not hidden tests + + std::vector const& allTestCases = getAllTestCasesSorted( *iconfig ); + for( std::vector::const_iterator it = allTestCases.begin(), itEnd = allTestCases.end(); + it != itEnd; + ++it ) { + if( !context.aborting() && matchTest( *it, testSpec, *iconfig ) ) + totals += context.runTest( *it ); + else + reporter->skipTest( *it ); + } + + context.testGroupEnded( iconfig->name(), totals, 1, 1 ); + return totals; + } + + void applyFilenamesAsTags( IConfig const& config ) { + std::vector const& tests = getAllTestCasesSorted( config ); + for(std::size_t i = 0; i < tests.size(); ++i ) { + TestCase& test = const_cast( tests[i] ); + std::set tags = test.tags; + + std::string filename = test.lineInfo.file; + std::string::size_type lastSlash = filename.find_last_of( "\\/" ); + if( lastSlash != std::string::npos ) + filename = filename.substr( lastSlash+1 ); + + std::string::size_type lastDot = filename.find_last_of( "." ); + if( lastDot != std::string::npos ) + filename = filename.substr( 0, lastDot ); + + tags.insert( "#" + filename ); + setTags( test, tags ); + } + } + + class Session : NonCopyable { + static bool alreadyInstantiated; + + public: + + struct OnUnusedOptions { enum DoWhat { Ignore, Fail }; }; + + Session() + : m_cli( makeCommandLineParser() ) { + if( alreadyInstantiated ) { + std::string msg = "Only one instance of Catch::Session can ever be used"; + Catch::cerr() << msg << std::endl; + throw std::logic_error( msg ); + } + alreadyInstantiated = true; + } + ~Session() { + Catch::cleanUp(); + } + + void showHelp( std::string const& processName ) { + Catch::cout() << "\nCatch v" << libraryVersion << "\n"; + + m_cli.usage( Catch::cout(), processName ); + Catch::cout() << "For more detail usage please see the project docs\n" << std::endl; + } + + int applyCommandLine( int argc, char const* const* const argv, OnUnusedOptions::DoWhat unusedOptionBehaviour = OnUnusedOptions::Fail ) { + try { + m_cli.setThrowOnUnrecognisedTokens( unusedOptionBehaviour == OnUnusedOptions::Fail ); + m_unusedTokens = m_cli.parseInto( Clara::argsToVector( argc, argv ), m_configData ); + if( m_configData.showHelp ) + showHelp( m_configData.processName ); + m_config.reset(); + } + catch( std::exception& ex ) { + { + Colour colourGuard( Colour::Red ); + Catch::cerr() + << "\nError(s) in input:\n" + << Text( ex.what(), TextAttributes().setIndent(2) ) + << "\n\n"; + } + m_cli.usage( Catch::cout(), m_configData.processName ); + return (std::numeric_limits::max)(); + } + return 0; + } + + void useConfigData( ConfigData const& _configData ) { + m_configData = _configData; + m_config.reset(); + } + + int run( int argc, char const* const* const argv ) { + + int returnCode = applyCommandLine( argc, argv ); + if( returnCode == 0 ) + returnCode = run(); + return returnCode; + } + + int run() { + if( m_configData.showHelp ) + return 0; + + try + { + config(); // Force config to be constructed + + seedRng( *m_config ); + + if( m_configData.filenamesAsTags ) + applyFilenamesAsTags( *m_config ); + + // Handle list request + if( Option listed = list( config() ) ) + return static_cast( *listed ); + + return static_cast( runTests( m_config ).assertions.failed ); + } + catch( std::exception& ex ) { + Catch::cerr() << ex.what() << std::endl; + return (std::numeric_limits::max)(); + } + } + + Clara::CommandLine const& cli() const { + return m_cli; + } + std::vector const& unusedTokens() const { + return m_unusedTokens; + } + ConfigData& configData() { + return m_configData; + } + Config& config() { + if( !m_config ) + m_config = new Config( m_configData ); + return *m_config; + } + private: + Clara::CommandLine m_cli; + std::vector m_unusedTokens; + ConfigData m_configData; + Ptr m_config; + }; + + bool Session::alreadyInstantiated = false; + +} // end namespace Catch + +// #included from: catch_registry_hub.hpp +#define TWOBLUECUBES_CATCH_REGISTRY_HUB_HPP_INCLUDED + +// #included from: catch_test_case_registry_impl.hpp +#define TWOBLUECUBES_CATCH_TEST_CASE_REGISTRY_IMPL_HPP_INCLUDED + +#include +#include +#include +#include +#include + +#ifdef CATCH_CPP14_OR_GREATER +#include +#endif + +namespace Catch { + + struct RandomNumberGenerator { + typedef int result_type; + + result_type operator()( result_type n ) const { return std::rand() % n; } + +#ifdef CATCH_CPP14_OR_GREATER + static constexpr result_type min() { return 0; } + static constexpr result_type max() { return 1000000; } + result_type operator()() const { return std::rand() % max(); } +#endif + template + static void shuffle( V& vector ) { + RandomNumberGenerator rng; +#ifdef CATCH_CPP14_OR_GREATER + std::shuffle( vector.begin(), vector.end(), rng ); +#else + std::random_shuffle( vector.begin(), vector.end(), rng ); +#endif + } + }; + + inline std::vector sortTests( IConfig const& config, std::vector const& unsortedTestCases ) { + + std::vector sorted = unsortedTestCases; + + switch( config.runOrder() ) { + case RunTests::InLexicographicalOrder: + std::sort( sorted.begin(), sorted.end() ); + break; + case RunTests::InRandomOrder: + { + seedRng( config ); + RandomNumberGenerator::shuffle( sorted ); + } + break; + case RunTests::InDeclarationOrder: + // already in declaration order + break; + } + return sorted; + } + bool matchTest( TestCase const& testCase, TestSpec const& testSpec, IConfig const& config ) { + return testSpec.matches( testCase ) && ( config.allowThrows() || !testCase.throws() ); + } + + void enforceNoDuplicateTestCases( std::vector const& functions ) { + std::set seenFunctions; + for( std::vector::const_iterator it = functions.begin(), itEnd = functions.end(); + it != itEnd; + ++it ) { + std::pair::const_iterator, bool> prev = seenFunctions.insert( *it ); + if( !prev.second ) { + std::ostringstream ss; + + ss << Colour( Colour::Red ) + << "error: TEST_CASE( \"" << it->name << "\" ) already defined.\n" + << "\tFirst seen at " << prev.first->getTestCaseInfo().lineInfo << "\n" + << "\tRedefined at " << it->getTestCaseInfo().lineInfo << std::endl; + + throw std::runtime_error(ss.str()); + } + } + } + + std::vector filterTests( std::vector const& testCases, TestSpec const& testSpec, IConfig const& config ) { + std::vector filtered; + filtered.reserve( testCases.size() ); + for( std::vector::const_iterator it = testCases.begin(), itEnd = testCases.end(); + it != itEnd; + ++it ) + if( matchTest( *it, testSpec, config ) ) + filtered.push_back( *it ); + return filtered; + } + std::vector const& getAllTestCasesSorted( IConfig const& config ) { + return getRegistryHub().getTestCaseRegistry().getAllTestsSorted( config ); + } + + class TestRegistry : public ITestCaseRegistry { + public: + TestRegistry() + : m_currentSortOrder( RunTests::InDeclarationOrder ), + m_unnamedCount( 0 ) + {} + virtual ~TestRegistry(); + + virtual void registerTest( TestCase const& testCase ) { + std::string name = testCase.getTestCaseInfo().name; + if( name == "" ) { + std::ostringstream oss; + oss << "Anonymous test case " << ++m_unnamedCount; + return registerTest( testCase.withName( oss.str() ) ); + } + m_functions.push_back( testCase ); + } + + virtual std::vector const& getAllTests() const { + return m_functions; + } + virtual std::vector const& getAllTestsSorted( IConfig const& config ) const { + if( m_sortedFunctions.empty() ) + enforceNoDuplicateTestCases( m_functions ); + + if( m_currentSortOrder != config.runOrder() || m_sortedFunctions.empty() ) { + m_sortedFunctions = sortTests( config, m_functions ); + m_currentSortOrder = config.runOrder(); + } + return m_sortedFunctions; + } + + private: + std::vector m_functions; + mutable RunTests::InWhatOrder m_currentSortOrder; + mutable std::vector m_sortedFunctions; + size_t m_unnamedCount; + std::ios_base::Init m_ostreamInit; // Forces cout/ cerr to be initialised + }; + + /////////////////////////////////////////////////////////////////////////// + + class FreeFunctionTestCase : public SharedImpl { + public: + + FreeFunctionTestCase( TestFunction fun ) : m_fun( fun ) {} + + virtual void invoke() const { + m_fun(); + } + + private: + virtual ~FreeFunctionTestCase(); + + TestFunction m_fun; + }; + + inline std::string extractClassName( std::string const& classOrQualifiedMethodName ) { + std::string className = classOrQualifiedMethodName; + if( startsWith( className, "&" ) ) + { + std::size_t lastColons = className.rfind( "::" ); + std::size_t penultimateColons = className.rfind( "::", lastColons-1 ); + if( penultimateColons == std::string::npos ) + penultimateColons = 1; + className = className.substr( penultimateColons, lastColons-penultimateColons ); + } + return className; + } + + void registerTestCase + ( ITestCase* testCase, + char const* classOrQualifiedMethodName, + NameAndDesc const& nameAndDesc, + SourceLineInfo const& lineInfo ) { + + getMutableRegistryHub().registerTest + ( makeTestCase + ( testCase, + extractClassName( classOrQualifiedMethodName ), + nameAndDesc.name, + nameAndDesc.description, + lineInfo ) ); + } + void registerTestCaseFunction + ( TestFunction function, + SourceLineInfo const& lineInfo, + NameAndDesc const& nameAndDesc ) { + registerTestCase( new FreeFunctionTestCase( function ), "", nameAndDesc, lineInfo ); + } + + /////////////////////////////////////////////////////////////////////////// + + AutoReg::AutoReg + ( TestFunction function, + SourceLineInfo const& lineInfo, + NameAndDesc const& nameAndDesc ) { + registerTestCaseFunction( function, lineInfo, nameAndDesc ); + } + + AutoReg::~AutoReg() {} + +} // end namespace Catch + +// #included from: catch_reporter_registry.hpp +#define TWOBLUECUBES_CATCH_REPORTER_REGISTRY_HPP_INCLUDED + +#include + +namespace Catch { + + class ReporterRegistry : public IReporterRegistry { + + public: + + virtual ~ReporterRegistry() CATCH_OVERRIDE {} + + virtual IStreamingReporter* create( std::string const& name, Ptr const& config ) const CATCH_OVERRIDE { + FactoryMap::const_iterator it = m_factories.find( name ); + if( it == m_factories.end() ) + return CATCH_NULL; + return it->second->create( ReporterConfig( config ) ); + } + + void registerReporter( std::string const& name, Ptr const& factory ) { + m_factories.insert( std::make_pair( name, factory ) ); + } + void registerListener( Ptr const& factory ) { + m_listeners.push_back( factory ); + } + + virtual FactoryMap const& getFactories() const CATCH_OVERRIDE { + return m_factories; + } + virtual Listeners const& getListeners() const CATCH_OVERRIDE { + return m_listeners; + } + + private: + FactoryMap m_factories; + Listeners m_listeners; + }; +} + +// #included from: catch_exception_translator_registry.hpp +#define TWOBLUECUBES_CATCH_EXCEPTION_TRANSLATOR_REGISTRY_HPP_INCLUDED + +#ifdef __OBJC__ +#import "Foundation/Foundation.h" +#endif + +namespace Catch { + + class ExceptionTranslatorRegistry : public IExceptionTranslatorRegistry { + public: + ~ExceptionTranslatorRegistry() { + deleteAll( m_translators ); + } + + virtual void registerTranslator( const IExceptionTranslator* translator ) { + m_translators.push_back( translator ); + } + + virtual std::string translateActiveException() const { + try { +#ifdef __OBJC__ + // In Objective-C try objective-c exceptions first + @try { + return tryTranslators(); + } + @catch (NSException *exception) { + return Catch::toString( [exception description] ); + } +#else + return tryTranslators(); +#endif + } + catch( TestFailureException& ) { + throw; + } + catch( std::exception& ex ) { + return ex.what(); + } + catch( std::string& msg ) { + return msg; + } + catch( const char* msg ) { + return msg; + } + catch(...) { + return "Unknown exception"; + } + } + + std::string tryTranslators() const { + if( m_translators.empty() ) + throw; + else + return m_translators[0]->translate( m_translators.begin()+1, m_translators.end() ); + } + + private: + std::vector m_translators; + }; +} + +namespace Catch { + + namespace { + + class RegistryHub : public IRegistryHub, public IMutableRegistryHub { + + RegistryHub( RegistryHub const& ); + void operator=( RegistryHub const& ); + + public: // IRegistryHub + RegistryHub() { + } + virtual IReporterRegistry const& getReporterRegistry() const CATCH_OVERRIDE { + return m_reporterRegistry; + } + virtual ITestCaseRegistry const& getTestCaseRegistry() const CATCH_OVERRIDE { + return m_testCaseRegistry; + } + virtual IExceptionTranslatorRegistry& getExceptionTranslatorRegistry() CATCH_OVERRIDE { + return m_exceptionTranslatorRegistry; + } + + public: // IMutableRegistryHub + virtual void registerReporter( std::string const& name, Ptr const& factory ) CATCH_OVERRIDE { + m_reporterRegistry.registerReporter( name, factory ); + } + virtual void registerListener( Ptr const& factory ) CATCH_OVERRIDE { + m_reporterRegistry.registerListener( factory ); + } + virtual void registerTest( TestCase const& testInfo ) CATCH_OVERRIDE { + m_testCaseRegistry.registerTest( testInfo ); + } + virtual void registerTranslator( const IExceptionTranslator* translator ) CATCH_OVERRIDE { + m_exceptionTranslatorRegistry.registerTranslator( translator ); + } + + private: + TestRegistry m_testCaseRegistry; + ReporterRegistry m_reporterRegistry; + ExceptionTranslatorRegistry m_exceptionTranslatorRegistry; + }; + + // Single, global, instance + inline RegistryHub*& getTheRegistryHub() { + static RegistryHub* theRegistryHub = CATCH_NULL; + if( !theRegistryHub ) + theRegistryHub = new RegistryHub(); + return theRegistryHub; + } + } + + IRegistryHub& getRegistryHub() { + return *getTheRegistryHub(); + } + IMutableRegistryHub& getMutableRegistryHub() { + return *getTheRegistryHub(); + } + void cleanUp() { + delete getTheRegistryHub(); + getTheRegistryHub() = CATCH_NULL; + cleanUpContext(); + } + std::string translateActiveException() { + return getRegistryHub().getExceptionTranslatorRegistry().translateActiveException(); + } + +} // end namespace Catch + +// #included from: catch_notimplemented_exception.hpp +#define TWOBLUECUBES_CATCH_NOTIMPLEMENTED_EXCEPTION_HPP_INCLUDED + +#include + +namespace Catch { + + NotImplementedException::NotImplementedException( SourceLineInfo const& lineInfo ) + : m_lineInfo( lineInfo ) { + std::ostringstream oss; + oss << lineInfo << ": function "; + oss << "not implemented"; + m_what = oss.str(); + } + + const char* NotImplementedException::what() const CATCH_NOEXCEPT { + return m_what.c_str(); + } + +} // end namespace Catch + +// #included from: catch_context_impl.hpp +#define TWOBLUECUBES_CATCH_CONTEXT_IMPL_HPP_INCLUDED + +// #included from: catch_stream.hpp +#define TWOBLUECUBES_CATCH_STREAM_HPP_INCLUDED + +#include +#include +#include + +namespace Catch { + + template + class StreamBufImpl : public StreamBufBase { + char data[bufferSize]; + WriterF m_writer; + + public: + StreamBufImpl() { + setp( data, data + sizeof(data) ); + } + + ~StreamBufImpl() CATCH_NOEXCEPT { + sync(); + } + + private: + int overflow( int c ) { + sync(); + + if( c != EOF ) { + if( pbase() == epptr() ) + m_writer( std::string( 1, static_cast( c ) ) ); + else + sputc( static_cast( c ) ); + } + return 0; + } + + int sync() { + if( pbase() != pptr() ) { + m_writer( std::string( pbase(), static_cast( pptr() - pbase() ) ) ); + setp( pbase(), epptr() ); + } + return 0; + } + }; + + /////////////////////////////////////////////////////////////////////////// + + FileStream::FileStream( std::string const& filename ) { + m_ofs.open( filename.c_str() ); + if( m_ofs.fail() ) { + std::ostringstream oss; + oss << "Unable to open file: '" << filename << "'"; + throw std::domain_error( oss.str() ); + } + } + + std::ostream& FileStream::stream() const { + return m_ofs; + } + + struct OutputDebugWriter { + + void operator()( std::string const&str ) { + writeToDebugConsole( str ); + } + }; + + DebugOutStream::DebugOutStream() + : m_streamBuf( new StreamBufImpl() ), + m_os( m_streamBuf.get() ) + {} + + std::ostream& DebugOutStream::stream() const { + return m_os; + } + + // Store the streambuf from cout up-front because + // cout may get redirected when running tests + CoutStream::CoutStream() + : m_os( Catch::cout().rdbuf() ) + {} + + std::ostream& CoutStream::stream() const { + return m_os; + } + +#ifndef CATCH_CONFIG_NOSTDOUT // If you #define this you must implement these functions + std::ostream& cout() { + return std::cout; + } + std::ostream& cerr() { + return std::cerr; + } +#endif +} + +namespace Catch { + + class Context : public IMutableContext { + + Context() : m_config( CATCH_NULL ), m_runner( CATCH_NULL ), m_resultCapture( CATCH_NULL ) {} + Context( Context const& ); + void operator=( Context const& ); + + public: // IContext + virtual IResultCapture* getResultCapture() { + return m_resultCapture; + } + virtual IRunner* getRunner() { + return m_runner; + } + virtual size_t getGeneratorIndex( std::string const& fileInfo, size_t totalSize ) { + return getGeneratorsForCurrentTest() + .getGeneratorInfo( fileInfo, totalSize ) + .getCurrentIndex(); + } + virtual bool advanceGeneratorsForCurrentTest() { + IGeneratorsForTest* generators = findGeneratorsForCurrentTest(); + return generators && generators->moveNext(); + } + + virtual Ptr getConfig() const { + return m_config; + } + + public: // IMutableContext + virtual void setResultCapture( IResultCapture* resultCapture ) { + m_resultCapture = resultCapture; + } + virtual void setRunner( IRunner* runner ) { + m_runner = runner; + } + virtual void setConfig( Ptr const& config ) { + m_config = config; + } + + friend IMutableContext& getCurrentMutableContext(); + + private: + IGeneratorsForTest* findGeneratorsForCurrentTest() { + std::string testName = getResultCapture()->getCurrentTestName(); + + std::map::const_iterator it = + m_generatorsByTestName.find( testName ); + return it != m_generatorsByTestName.end() + ? it->second + : CATCH_NULL; + } + + IGeneratorsForTest& getGeneratorsForCurrentTest() { + IGeneratorsForTest* generators = findGeneratorsForCurrentTest(); + if( !generators ) { + std::string testName = getResultCapture()->getCurrentTestName(); + generators = createGeneratorsForTest(); + m_generatorsByTestName.insert( std::make_pair( testName, generators ) ); + } + return *generators; + } + + private: + Ptr m_config; + IRunner* m_runner; + IResultCapture* m_resultCapture; + std::map m_generatorsByTestName; + }; + + namespace { + Context* currentContext = CATCH_NULL; + } + IMutableContext& getCurrentMutableContext() { + if( !currentContext ) + currentContext = new Context(); + return *currentContext; + } + IContext& getCurrentContext() { + return getCurrentMutableContext(); + } + + void cleanUpContext() { + delete currentContext; + currentContext = CATCH_NULL; + } +} + +// #included from: catch_console_colour_impl.hpp +#define TWOBLUECUBES_CATCH_CONSOLE_COLOUR_IMPL_HPP_INCLUDED + +namespace Catch { + namespace { + + struct IColourImpl { + virtual ~IColourImpl() {} + virtual void use( Colour::Code _colourCode ) = 0; + }; + + struct NoColourImpl : IColourImpl { + void use( Colour::Code ) {} + + static IColourImpl* instance() { + static NoColourImpl s_instance; + return &s_instance; + } + }; + + } // anon namespace +} // namespace Catch + +#if !defined( CATCH_CONFIG_COLOUR_NONE ) && !defined( CATCH_CONFIG_COLOUR_WINDOWS ) && !defined( CATCH_CONFIG_COLOUR_ANSI ) +# ifdef CATCH_PLATFORM_WINDOWS +# define CATCH_CONFIG_COLOUR_WINDOWS +# else +# define CATCH_CONFIG_COLOUR_ANSI +# endif +#endif + +#if defined ( CATCH_CONFIG_COLOUR_WINDOWS ) ///////////////////////////////////////// + +#ifndef NOMINMAX +#define NOMINMAX +#endif + +#ifdef __AFXDLL +#include +#else +#include +#endif + +namespace Catch { +namespace { + + class Win32ColourImpl : public IColourImpl { + public: + Win32ColourImpl() : stdoutHandle( GetStdHandle(STD_OUTPUT_HANDLE) ) + { + CONSOLE_SCREEN_BUFFER_INFO csbiInfo; + GetConsoleScreenBufferInfo( stdoutHandle, &csbiInfo ); + originalForegroundAttributes = csbiInfo.wAttributes & ~( BACKGROUND_GREEN | BACKGROUND_RED | BACKGROUND_BLUE | BACKGROUND_INTENSITY ); + originalBackgroundAttributes = csbiInfo.wAttributes & ~( FOREGROUND_GREEN | FOREGROUND_RED | FOREGROUND_BLUE | FOREGROUND_INTENSITY ); + } + + virtual void use( Colour::Code _colourCode ) { + switch( _colourCode ) { + case Colour::None: return setTextAttribute( originalForegroundAttributes ); + case Colour::White: return setTextAttribute( FOREGROUND_GREEN | FOREGROUND_RED | FOREGROUND_BLUE ); + case Colour::Red: return setTextAttribute( FOREGROUND_RED ); + case Colour::Green: return setTextAttribute( FOREGROUND_GREEN ); + case Colour::Blue: return setTextAttribute( FOREGROUND_BLUE ); + case Colour::Cyan: return setTextAttribute( FOREGROUND_BLUE | FOREGROUND_GREEN ); + case Colour::Yellow: return setTextAttribute( FOREGROUND_RED | FOREGROUND_GREEN ); + case Colour::Grey: return setTextAttribute( 0 ); + + case Colour::LightGrey: return setTextAttribute( FOREGROUND_INTENSITY ); + case Colour::BrightRed: return setTextAttribute( FOREGROUND_INTENSITY | FOREGROUND_RED ); + case Colour::BrightGreen: return setTextAttribute( FOREGROUND_INTENSITY | FOREGROUND_GREEN ); + case Colour::BrightWhite: return setTextAttribute( FOREGROUND_INTENSITY | FOREGROUND_GREEN | FOREGROUND_RED | FOREGROUND_BLUE ); + + case Colour::Bright: throw std::logic_error( "not a colour" ); + } + } + + private: + void setTextAttribute( WORD _textAttribute ) { + SetConsoleTextAttribute( stdoutHandle, _textAttribute | originalBackgroundAttributes ); + } + HANDLE stdoutHandle; + WORD originalForegroundAttributes; + WORD originalBackgroundAttributes; + }; + + IColourImpl* platformColourInstance() { + static Win32ColourImpl s_instance; + + Ptr config = getCurrentContext().getConfig(); + UseColour::YesOrNo colourMode = config + ? config->useColour() + : UseColour::Auto; + if( colourMode == UseColour::Auto ) + colourMode = !isDebuggerActive() + ? UseColour::Yes + : UseColour::No; + return colourMode == UseColour::Yes + ? &s_instance + : NoColourImpl::instance(); + } + +} // end anon namespace +} // end namespace Catch + +#elif defined( CATCH_CONFIG_COLOUR_ANSI ) ////////////////////////////////////// + +#include + +namespace Catch { +namespace { + + // use POSIX/ ANSI console terminal codes + // Thanks to Adam Strzelecki for original contribution + // (http://github.com/nanoant) + // https://github.com/philsquared/Catch/pull/131 + class PosixColourImpl : public IColourImpl { + public: + virtual void use( Colour::Code _colourCode ) { + switch( _colourCode ) { + case Colour::None: + case Colour::White: return setColour( "[0m" ); + case Colour::Red: return setColour( "[0;31m" ); + case Colour::Green: return setColour( "[0;32m" ); + case Colour::Blue: return setColour( "[0:34m" ); + case Colour::Cyan: return setColour( "[0;36m" ); + case Colour::Yellow: return setColour( "[0;33m" ); + case Colour::Grey: return setColour( "[1;30m" ); + + case Colour::LightGrey: return setColour( "[0;37m" ); + case Colour::BrightRed: return setColour( "[1;31m" ); + case Colour::BrightGreen: return setColour( "[1;32m" ); + case Colour::BrightWhite: return setColour( "[1;37m" ); + + case Colour::Bright: throw std::logic_error( "not a colour" ); + } + } + static IColourImpl* instance() { + static PosixColourImpl s_instance; + return &s_instance; + } + + private: + void setColour( const char* _escapeCode ) { + Catch::cout() << '\033' << _escapeCode; + } + }; + + IColourImpl* platformColourInstance() { + Ptr config = getCurrentContext().getConfig(); + UseColour::YesOrNo colourMode = config + ? config->useColour() + : UseColour::Auto; + if( colourMode == UseColour::Auto ) + colourMode = (!isDebuggerActive() && isatty(STDOUT_FILENO) ) + ? UseColour::Yes + : UseColour::No; + return colourMode == UseColour::Yes + ? PosixColourImpl::instance() + : NoColourImpl::instance(); + } + +} // end anon namespace +} // end namespace Catch + +#else // not Windows or ANSI /////////////////////////////////////////////// + +namespace Catch { + + static IColourImpl* platformColourInstance() { return NoColourImpl::instance(); } + +} // end namespace Catch + +#endif // Windows/ ANSI/ None + +namespace Catch { + + Colour::Colour( Code _colourCode ) : m_moved( false ) { use( _colourCode ); } + Colour::Colour( Colour const& _other ) : m_moved( false ) { const_cast( _other ).m_moved = true; } + Colour::~Colour(){ if( !m_moved ) use( None ); } + + void Colour::use( Code _colourCode ) { + static IColourImpl* impl = platformColourInstance(); + impl->use( _colourCode ); + } + +} // end namespace Catch + +// #included from: catch_generators_impl.hpp +#define TWOBLUECUBES_CATCH_GENERATORS_IMPL_HPP_INCLUDED + +#include +#include +#include + +namespace Catch { + + struct GeneratorInfo : IGeneratorInfo { + + GeneratorInfo( std::size_t size ) + : m_size( size ), + m_currentIndex( 0 ) + {} + + bool moveNext() { + if( ++m_currentIndex == m_size ) { + m_currentIndex = 0; + return false; + } + return true; + } + + std::size_t getCurrentIndex() const { + return m_currentIndex; + } + + std::size_t m_size; + std::size_t m_currentIndex; + }; + + /////////////////////////////////////////////////////////////////////////// + + class GeneratorsForTest : public IGeneratorsForTest { + + public: + ~GeneratorsForTest() { + deleteAll( m_generatorsInOrder ); + } + + IGeneratorInfo& getGeneratorInfo( std::string const& fileInfo, std::size_t size ) { + std::map::const_iterator it = m_generatorsByName.find( fileInfo ); + if( it == m_generatorsByName.end() ) { + IGeneratorInfo* info = new GeneratorInfo( size ); + m_generatorsByName.insert( std::make_pair( fileInfo, info ) ); + m_generatorsInOrder.push_back( info ); + return *info; + } + return *it->second; + } + + bool moveNext() { + std::vector::const_iterator it = m_generatorsInOrder.begin(); + std::vector::const_iterator itEnd = m_generatorsInOrder.end(); + for(; it != itEnd; ++it ) { + if( (*it)->moveNext() ) + return true; + } + return false; + } + + private: + std::map m_generatorsByName; + std::vector m_generatorsInOrder; + }; + + IGeneratorsForTest* createGeneratorsForTest() + { + return new GeneratorsForTest(); + } + +} // end namespace Catch + +// #included from: catch_assertionresult.hpp +#define TWOBLUECUBES_CATCH_ASSERTIONRESULT_HPP_INCLUDED + +namespace Catch { + + AssertionInfo::AssertionInfo( std::string const& _macroName, + SourceLineInfo const& _lineInfo, + std::string const& _capturedExpression, + ResultDisposition::Flags _resultDisposition ) + : macroName( _macroName ), + lineInfo( _lineInfo ), + capturedExpression( _capturedExpression ), + resultDisposition( _resultDisposition ) + {} + + AssertionResult::AssertionResult() {} + + AssertionResult::AssertionResult( AssertionInfo const& info, AssertionResultData const& data ) + : m_info( info ), + m_resultData( data ) + {} + + AssertionResult::~AssertionResult() {} + + // Result was a success + bool AssertionResult::succeeded() const { + return Catch::isOk( m_resultData.resultType ); + } + + // Result was a success, or failure is suppressed + bool AssertionResult::isOk() const { + return Catch::isOk( m_resultData.resultType ) || shouldSuppressFailure( m_info.resultDisposition ); + } + + ResultWas::OfType AssertionResult::getResultType() const { + return m_resultData.resultType; + } + + bool AssertionResult::hasExpression() const { + return !m_info.capturedExpression.empty(); + } + + bool AssertionResult::hasMessage() const { + return !m_resultData.message.empty(); + } + + std::string AssertionResult::getExpression() const { + if( isFalseTest( m_info.resultDisposition ) ) + return "!" + m_info.capturedExpression; + else + return m_info.capturedExpression; + } + std::string AssertionResult::getExpressionInMacro() const { + if( m_info.macroName.empty() ) + return m_info.capturedExpression; + else + return m_info.macroName + "( " + m_info.capturedExpression + " )"; + } + + bool AssertionResult::hasExpandedExpression() const { + return hasExpression() && getExpandedExpression() != getExpression(); + } + + std::string AssertionResult::getExpandedExpression() const { + return m_resultData.reconstructedExpression; + } + + std::string AssertionResult::getMessage() const { + return m_resultData.message; + } + SourceLineInfo AssertionResult::getSourceInfo() const { + return m_info.lineInfo; + } + + std::string AssertionResult::getTestMacroName() const { + return m_info.macroName; + } + +} // end namespace Catch + +// #included from: catch_test_case_info.hpp +#define TWOBLUECUBES_CATCH_TEST_CASE_INFO_HPP_INCLUDED + +namespace Catch { + + inline TestCaseInfo::SpecialProperties parseSpecialTag( std::string const& tag ) { + if( startsWith( tag, "." ) || + tag == "hide" || + tag == "!hide" ) + return TestCaseInfo::IsHidden; + else if( tag == "!throws" ) + return TestCaseInfo::Throws; + else if( tag == "!shouldfail" ) + return TestCaseInfo::ShouldFail; + else if( tag == "!mayfail" ) + return TestCaseInfo::MayFail; + else + return TestCaseInfo::None; + } + inline bool isReservedTag( std::string const& tag ) { + return parseSpecialTag( tag ) == TestCaseInfo::None && tag.size() > 0 && !isalnum( tag[0] ); + } + inline void enforceNotReservedTag( std::string const& tag, SourceLineInfo const& _lineInfo ) { + if( isReservedTag( tag ) ) { + { + Colour colourGuard( Colour::Red ); + Catch::cerr() + << "Tag name [" << tag << "] not allowed.\n" + << "Tag names starting with non alpha-numeric characters are reserved\n"; + } + { + Colour colourGuard( Colour::FileName ); + Catch::cerr() << _lineInfo << std::endl; + } + exit(1); + } + } + + TestCase makeTestCase( ITestCase* _testCase, + std::string const& _className, + std::string const& _name, + std::string const& _descOrTags, + SourceLineInfo const& _lineInfo ) + { + bool isHidden( startsWith( _name, "./" ) ); // Legacy support + + // Parse out tags + std::set tags; + std::string desc, tag; + bool inTag = false; + for( std::size_t i = 0; i < _descOrTags.size(); ++i ) { + char c = _descOrTags[i]; + if( !inTag ) { + if( c == '[' ) + inTag = true; + else + desc += c; + } + else { + if( c == ']' ) { + TestCaseInfo::SpecialProperties prop = parseSpecialTag( tag ); + if( prop == TestCaseInfo::IsHidden ) + isHidden = true; + else if( prop == TestCaseInfo::None ) + enforceNotReservedTag( tag, _lineInfo ); + + tags.insert( tag ); + tag.clear(); + inTag = false; + } + else + tag += c; + } + } + if( isHidden ) { + tags.insert( "hide" ); + tags.insert( "." ); + } + + TestCaseInfo info( _name, _className, desc, tags, _lineInfo ); + return TestCase( _testCase, info ); + } + + void setTags( TestCaseInfo& testCaseInfo, std::set const& tags ) + { + testCaseInfo.tags = tags; + testCaseInfo.lcaseTags.clear(); + + std::ostringstream oss; + for( std::set::const_iterator it = tags.begin(), itEnd = tags.end(); it != itEnd; ++it ) { + oss << "[" << *it << "]"; + std::string lcaseTag = toLower( *it ); + testCaseInfo.properties = static_cast( testCaseInfo.properties | parseSpecialTag( lcaseTag ) ); + testCaseInfo.lcaseTags.insert( lcaseTag ); + } + testCaseInfo.tagsAsString = oss.str(); + } + + TestCaseInfo::TestCaseInfo( std::string const& _name, + std::string const& _className, + std::string const& _description, + std::set const& _tags, + SourceLineInfo const& _lineInfo ) + : name( _name ), + className( _className ), + description( _description ), + lineInfo( _lineInfo ), + properties( None ) + { + setTags( *this, _tags ); + } + + TestCaseInfo::TestCaseInfo( TestCaseInfo const& other ) + : name( other.name ), + className( other.className ), + description( other.description ), + tags( other.tags ), + lcaseTags( other.lcaseTags ), + tagsAsString( other.tagsAsString ), + lineInfo( other.lineInfo ), + properties( other.properties ) + {} + + bool TestCaseInfo::isHidden() const { + return ( properties & IsHidden ) != 0; + } + bool TestCaseInfo::throws() const { + return ( properties & Throws ) != 0; + } + bool TestCaseInfo::okToFail() const { + return ( properties & (ShouldFail | MayFail ) ) != 0; + } + bool TestCaseInfo::expectedToFail() const { + return ( properties & (ShouldFail ) ) != 0; + } + + TestCase::TestCase( ITestCase* testCase, TestCaseInfo const& info ) : TestCaseInfo( info ), test( testCase ) {} + + TestCase::TestCase( TestCase const& other ) + : TestCaseInfo( other ), + test( other.test ) + {} + + TestCase TestCase::withName( std::string const& _newName ) const { + TestCase other( *this ); + other.name = _newName; + return other; + } + + void TestCase::swap( TestCase& other ) { + test.swap( other.test ); + name.swap( other.name ); + className.swap( other.className ); + description.swap( other.description ); + tags.swap( other.tags ); + lcaseTags.swap( other.lcaseTags ); + tagsAsString.swap( other.tagsAsString ); + std::swap( TestCaseInfo::properties, static_cast( other ).properties ); + std::swap( lineInfo, other.lineInfo ); + } + + void TestCase::invoke() const { + test->invoke(); + } + + bool TestCase::operator == ( TestCase const& other ) const { + return test.get() == other.test.get() && + name == other.name && + className == other.className; + } + + bool TestCase::operator < ( TestCase const& other ) const { + return name < other.name; + } + TestCase& TestCase::operator = ( TestCase const& other ) { + TestCase temp( other ); + swap( temp ); + return *this; + } + + TestCaseInfo const& TestCase::getTestCaseInfo() const + { + return *this; + } + +} // end namespace Catch + +// #included from: catch_version.hpp +#define TWOBLUECUBES_CATCH_VERSION_HPP_INCLUDED + +namespace Catch { + + Version::Version + ( unsigned int _majorVersion, + unsigned int _minorVersion, + unsigned int _patchNumber, + std::string const& _branchName, + unsigned int _buildNumber ) + : majorVersion( _majorVersion ), + minorVersion( _minorVersion ), + patchNumber( _patchNumber ), + branchName( _branchName ), + buildNumber( _buildNumber ) + {} + + std::ostream& operator << ( std::ostream& os, Version const& version ) { + os << version.majorVersion << "." + << version.minorVersion << "." + << version.patchNumber; + + if( !version.branchName.empty() ) { + os << "-" << version.branchName + << "." << version.buildNumber; + } + return os; + } + + Version libraryVersion( 1, 5, 6, "", 0 ); + +} + +// #included from: catch_message.hpp +#define TWOBLUECUBES_CATCH_MESSAGE_HPP_INCLUDED + +namespace Catch { + + MessageInfo::MessageInfo( std::string const& _macroName, + SourceLineInfo const& _lineInfo, + ResultWas::OfType _type ) + : macroName( _macroName ), + lineInfo( _lineInfo ), + type( _type ), + sequence( ++globalCount ) + {} + + // This may need protecting if threading support is added + unsigned int MessageInfo::globalCount = 0; + + //////////////////////////////////////////////////////////////////////////// + + ScopedMessage::ScopedMessage( MessageBuilder const& builder ) + : m_info( builder.m_info ) + { + m_info.message = builder.m_stream.str(); + getResultCapture().pushScopedMessage( m_info ); + } + ScopedMessage::ScopedMessage( ScopedMessage const& other ) + : m_info( other.m_info ) + {} + + ScopedMessage::~ScopedMessage() { + getResultCapture().popScopedMessage( m_info ); + } + +} // end namespace Catch + +// #included from: catch_legacy_reporter_adapter.hpp +#define TWOBLUECUBES_CATCH_LEGACY_REPORTER_ADAPTER_HPP_INCLUDED + +// #included from: catch_legacy_reporter_adapter.h +#define TWOBLUECUBES_CATCH_LEGACY_REPORTER_ADAPTER_H_INCLUDED + +namespace Catch +{ + // Deprecated + struct IReporter : IShared { + virtual ~IReporter(); + + virtual bool shouldRedirectStdout() const = 0; + + virtual void StartTesting() = 0; + virtual void EndTesting( Totals const& totals ) = 0; + virtual void StartGroup( std::string const& groupName ) = 0; + virtual void EndGroup( std::string const& groupName, Totals const& totals ) = 0; + virtual void StartTestCase( TestCaseInfo const& testInfo ) = 0; + virtual void EndTestCase( TestCaseInfo const& testInfo, Totals const& totals, std::string const& stdOut, std::string const& stdErr ) = 0; + virtual void StartSection( std::string const& sectionName, std::string const& description ) = 0; + virtual void EndSection( std::string const& sectionName, Counts const& assertions ) = 0; + virtual void NoAssertionsInSection( std::string const& sectionName ) = 0; + virtual void NoAssertionsInTestCase( std::string const& testName ) = 0; + virtual void Aborted() = 0; + virtual void Result( AssertionResult const& result ) = 0; + }; + + class LegacyReporterAdapter : public SharedImpl + { + public: + LegacyReporterAdapter( Ptr const& legacyReporter ); + virtual ~LegacyReporterAdapter(); + + virtual ReporterPreferences getPreferences() const; + virtual void noMatchingTestCases( std::string const& ); + virtual void testRunStarting( TestRunInfo const& ); + virtual void testGroupStarting( GroupInfo const& groupInfo ); + virtual void testCaseStarting( TestCaseInfo const& testInfo ); + virtual void sectionStarting( SectionInfo const& sectionInfo ); + virtual void assertionStarting( AssertionInfo const& ); + virtual bool assertionEnded( AssertionStats const& assertionStats ); + virtual void sectionEnded( SectionStats const& sectionStats ); + virtual void testCaseEnded( TestCaseStats const& testCaseStats ); + virtual void testGroupEnded( TestGroupStats const& testGroupStats ); + virtual void testRunEnded( TestRunStats const& testRunStats ); + virtual void skipTest( TestCaseInfo const& ); + + private: + Ptr m_legacyReporter; + }; +} + +namespace Catch +{ + LegacyReporterAdapter::LegacyReporterAdapter( Ptr const& legacyReporter ) + : m_legacyReporter( legacyReporter ) + {} + LegacyReporterAdapter::~LegacyReporterAdapter() {} + + ReporterPreferences LegacyReporterAdapter::getPreferences() const { + ReporterPreferences prefs; + prefs.shouldRedirectStdOut = m_legacyReporter->shouldRedirectStdout(); + return prefs; + } + + void LegacyReporterAdapter::noMatchingTestCases( std::string const& ) {} + void LegacyReporterAdapter::testRunStarting( TestRunInfo const& ) { + m_legacyReporter->StartTesting(); + } + void LegacyReporterAdapter::testGroupStarting( GroupInfo const& groupInfo ) { + m_legacyReporter->StartGroup( groupInfo.name ); + } + void LegacyReporterAdapter::testCaseStarting( TestCaseInfo const& testInfo ) { + m_legacyReporter->StartTestCase( testInfo ); + } + void LegacyReporterAdapter::sectionStarting( SectionInfo const& sectionInfo ) { + m_legacyReporter->StartSection( sectionInfo.name, sectionInfo.description ); + } + void LegacyReporterAdapter::assertionStarting( AssertionInfo const& ) { + // Not on legacy interface + } + + bool LegacyReporterAdapter::assertionEnded( AssertionStats const& assertionStats ) { + if( assertionStats.assertionResult.getResultType() != ResultWas::Ok ) { + for( std::vector::const_iterator it = assertionStats.infoMessages.begin(), itEnd = assertionStats.infoMessages.end(); + it != itEnd; + ++it ) { + if( it->type == ResultWas::Info ) { + ResultBuilder rb( it->macroName.c_str(), it->lineInfo, "", ResultDisposition::Normal ); + rb << it->message; + rb.setResultType( ResultWas::Info ); + AssertionResult result = rb.build(); + m_legacyReporter->Result( result ); + } + } + } + m_legacyReporter->Result( assertionStats.assertionResult ); + return true; + } + void LegacyReporterAdapter::sectionEnded( SectionStats const& sectionStats ) { + if( sectionStats.missingAssertions ) + m_legacyReporter->NoAssertionsInSection( sectionStats.sectionInfo.name ); + m_legacyReporter->EndSection( sectionStats.sectionInfo.name, sectionStats.assertions ); + } + void LegacyReporterAdapter::testCaseEnded( TestCaseStats const& testCaseStats ) { + m_legacyReporter->EndTestCase + ( testCaseStats.testInfo, + testCaseStats.totals, + testCaseStats.stdOut, + testCaseStats.stdErr ); + } + void LegacyReporterAdapter::testGroupEnded( TestGroupStats const& testGroupStats ) { + if( testGroupStats.aborting ) + m_legacyReporter->Aborted(); + m_legacyReporter->EndGroup( testGroupStats.groupInfo.name, testGroupStats.totals ); + } + void LegacyReporterAdapter::testRunEnded( TestRunStats const& testRunStats ) { + m_legacyReporter->EndTesting( testRunStats.totals ); + } + void LegacyReporterAdapter::skipTest( TestCaseInfo const& ) { + } +} + +// #included from: catch_timer.hpp + +#ifdef __clang__ +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wc++11-long-long" +#endif + +#ifdef CATCH_PLATFORM_WINDOWS +#include +#else +#include +#endif + +namespace Catch { + + namespace { +#ifdef CATCH_PLATFORM_WINDOWS + uint64_t getCurrentTicks() { + static uint64_t hz=0, hzo=0; + if (!hz) { + QueryPerformanceFrequency( reinterpret_cast( &hz ) ); + QueryPerformanceCounter( reinterpret_cast( &hzo ) ); + } + uint64_t t; + QueryPerformanceCounter( reinterpret_cast( &t ) ); + return ((t-hzo)*1000000)/hz; + } +#else + uint64_t getCurrentTicks() { + timeval t; + gettimeofday(&t,CATCH_NULL); + return static_cast( t.tv_sec ) * 1000000ull + static_cast( t.tv_usec ); + } +#endif + } + + void Timer::start() { + m_ticks = getCurrentTicks(); + } + unsigned int Timer::getElapsedMicroseconds() const { + return static_cast(getCurrentTicks() - m_ticks); + } + unsigned int Timer::getElapsedMilliseconds() const { + return static_cast(getElapsedMicroseconds()/1000); + } + double Timer::getElapsedSeconds() const { + return getElapsedMicroseconds()/1000000.0; + } + +} // namespace Catch + +#ifdef __clang__ +#pragma clang diagnostic pop +#endif +// #included from: catch_common.hpp +#define TWOBLUECUBES_CATCH_COMMON_HPP_INCLUDED + +namespace Catch { + + bool startsWith( std::string const& s, std::string const& prefix ) { + return s.size() >= prefix.size() && s.substr( 0, prefix.size() ) == prefix; + } + bool endsWith( std::string const& s, std::string const& suffix ) { + return s.size() >= suffix.size() && s.substr( s.size()-suffix.size(), suffix.size() ) == suffix; + } + bool contains( std::string const& s, std::string const& infix ) { + return s.find( infix ) != std::string::npos; + } + void toLowerInPlace( std::string& s ) { + std::transform( s.begin(), s.end(), s.begin(), ::tolower ); + } + std::string toLower( std::string const& s ) { + std::string lc = s; + toLowerInPlace( lc ); + return lc; + } + std::string trim( std::string const& str ) { + static char const* whitespaceChars = "\n\r\t "; + std::string::size_type start = str.find_first_not_of( whitespaceChars ); + std::string::size_type end = str.find_last_not_of( whitespaceChars ); + + return start != std::string::npos ? str.substr( start, 1+end-start ) : ""; + } + + bool replaceInPlace( std::string& str, std::string const& replaceThis, std::string const& withThis ) { + bool replaced = false; + std::size_t i = str.find( replaceThis ); + while( i != std::string::npos ) { + replaced = true; + str = str.substr( 0, i ) + withThis + str.substr( i+replaceThis.size() ); + if( i < str.size()-withThis.size() ) + i = str.find( replaceThis, i+withThis.size() ); + else + i = std::string::npos; + } + return replaced; + } + + pluralise::pluralise( std::size_t count, std::string const& label ) + : m_count( count ), + m_label( label ) + {} + + std::ostream& operator << ( std::ostream& os, pluralise const& pluraliser ) { + os << pluraliser.m_count << " " << pluraliser.m_label; + if( pluraliser.m_count != 1 ) + os << "s"; + return os; + } + + SourceLineInfo::SourceLineInfo() : line( 0 ){} + SourceLineInfo::SourceLineInfo( char const* _file, std::size_t _line ) + : file( _file ), + line( _line ) + {} + SourceLineInfo::SourceLineInfo( SourceLineInfo const& other ) + : file( other.file ), + line( other.line ) + {} + bool SourceLineInfo::empty() const { + return file.empty(); + } + bool SourceLineInfo::operator == ( SourceLineInfo const& other ) const { + return line == other.line && file == other.file; + } + bool SourceLineInfo::operator < ( SourceLineInfo const& other ) const { + return line < other.line || ( line == other.line && file < other.file ); + } + + void seedRng( IConfig const& config ) { + if( config.rngSeed() != 0 ) + std::srand( config.rngSeed() ); + } + unsigned int rngSeed() { + return getCurrentContext().getConfig()->rngSeed(); + } + + std::ostream& operator << ( std::ostream& os, SourceLineInfo const& info ) { +#ifndef __GNUG__ + os << info.file << "(" << info.line << ")"; +#else + os << info.file << ":" << info.line; +#endif + return os; + } + + void throwLogicError( std::string const& message, SourceLineInfo const& locationInfo ) { + std::ostringstream oss; + oss << locationInfo << ": Internal Catch error: '" << message << "'"; + if( alwaysTrue() ) + throw std::logic_error( oss.str() ); + } +} + +// #included from: catch_section.hpp +#define TWOBLUECUBES_CATCH_SECTION_HPP_INCLUDED + +namespace Catch { + + SectionInfo::SectionInfo + ( SourceLineInfo const& _lineInfo, + std::string const& _name, + std::string const& _description ) + : name( _name ), + description( _description ), + lineInfo( _lineInfo ) + {} + + Section::Section( SectionInfo const& info ) + : m_info( info ), + m_sectionIncluded( getResultCapture().sectionStarted( m_info, m_assertions ) ) + { + m_timer.start(); + } + + Section::~Section() { + if( m_sectionIncluded ) { + SectionEndInfo endInfo( m_info, m_assertions, m_timer.getElapsedSeconds() ); + if( std::uncaught_exception() ) + getResultCapture().sectionEndedEarly( endInfo ); + else + getResultCapture().sectionEnded( endInfo ); + } + } + + // This indicates whether the section should be executed or not + Section::operator bool() const { + return m_sectionIncluded; + } + +} // end namespace Catch + +// #included from: catch_debugger.hpp +#define TWOBLUECUBES_CATCH_DEBUGGER_HPP_INCLUDED + +#include + +#ifdef CATCH_PLATFORM_MAC + + #include + #include + #include + #include + #include + + namespace Catch{ + + // The following function is taken directly from the following technical note: + // http://developer.apple.com/library/mac/#qa/qa2004/qa1361.html + + // Returns true if the current process is being debugged (either + // running under the debugger or has a debugger attached post facto). + bool isDebuggerActive(){ + + int mib[4]; + struct kinfo_proc info; + size_t size; + + // Initialize the flags so that, if sysctl fails for some bizarre + // reason, we get a predictable result. + + info.kp_proc.p_flag = 0; + + // Initialize mib, which tells sysctl the info we want, in this case + // we're looking for information about a specific process ID. + + mib[0] = CTL_KERN; + mib[1] = KERN_PROC; + mib[2] = KERN_PROC_PID; + mib[3] = getpid(); + + // Call sysctl. + + size = sizeof(info); + if( sysctl(mib, sizeof(mib) / sizeof(*mib), &info, &size, CATCH_NULL, 0) != 0 ) { + Catch::cerr() << "\n** Call to sysctl failed - unable to determine if debugger is active **\n" << std::endl; + return false; + } + + // We're being debugged if the P_TRACED flag is set. + + return ( (info.kp_proc.p_flag & P_TRACED) != 0 ); + } + } // namespace Catch + +#elif defined(_MSC_VER) + extern "C" __declspec(dllimport) int __stdcall IsDebuggerPresent(); + namespace Catch { + bool isDebuggerActive() { + return IsDebuggerPresent() != 0; + } + } +#elif defined(__MINGW32__) + extern "C" __declspec(dllimport) int __stdcall IsDebuggerPresent(); + namespace Catch { + bool isDebuggerActive() { + return IsDebuggerPresent() != 0; + } + } +#else + namespace Catch { + inline bool isDebuggerActive() { return false; } + } +#endif // Platform + +#ifdef CATCH_PLATFORM_WINDOWS + extern "C" __declspec(dllimport) void __stdcall OutputDebugStringA( const char* ); + namespace Catch { + void writeToDebugConsole( std::string const& text ) { + ::OutputDebugStringA( text.c_str() ); + } + } +#else + namespace Catch { + void writeToDebugConsole( std::string const& text ) { + // !TBD: Need a version for Mac/ XCode and other IDEs + Catch::cout() << text; + } + } +#endif // Platform + +// #included from: catch_tostring.hpp +#define TWOBLUECUBES_CATCH_TOSTRING_HPP_INCLUDED + +namespace Catch { + +namespace Detail { + + const std::string unprintableString = "{?}"; + + namespace { + const int hexThreshold = 255; + + struct Endianness { + enum Arch { Big, Little }; + + static Arch which() { + union _{ + int asInt; + char asChar[sizeof (int)]; + } u; + + u.asInt = 1; + return ( u.asChar[sizeof(int)-1] == 1 ) ? Big : Little; + } + }; + } + + std::string rawMemoryToString( const void *object, std::size_t size ) + { + // Reverse order for little endian architectures + int i = 0, end = static_cast( size ), inc = 1; + if( Endianness::which() == Endianness::Little ) { + i = end-1; + end = inc = -1; + } + + unsigned char const *bytes = static_cast(object); + std::ostringstream os; + os << "0x" << std::setfill('0') << std::hex; + for( ; i != end; i += inc ) + os << std::setw(2) << static_cast(bytes[i]); + return os.str(); + } +} + +std::string toString( std::string const& value ) { + std::string s = value; + if( getCurrentContext().getConfig()->showInvisibles() ) { + for(size_t i = 0; i < s.size(); ++i ) { + std::string subs; + switch( s[i] ) { + case '\n': subs = "\\n"; break; + case '\t': subs = "\\t"; break; + default: break; + } + if( !subs.empty() ) { + s = s.substr( 0, i ) + subs + s.substr( i+1 ); + ++i; + } + } + } + return "\"" + s + "\""; +} +std::string toString( std::wstring const& value ) { + + std::string s; + s.reserve( value.size() ); + for(size_t i = 0; i < value.size(); ++i ) + s += value[i] <= 0xff ? static_cast( value[i] ) : '?'; + return Catch::toString( s ); +} + +std::string toString( const char* const value ) { + return value ? Catch::toString( std::string( value ) ) : std::string( "{null string}" ); +} + +std::string toString( char* const value ) { + return Catch::toString( static_cast( value ) ); +} + +std::string toString( const wchar_t* const value ) +{ + return value ? Catch::toString( std::wstring(value) ) : std::string( "{null string}" ); +} + +std::string toString( wchar_t* const value ) +{ + return Catch::toString( static_cast( value ) ); +} + +std::string toString( int value ) { + std::ostringstream oss; + oss << value; + if( value > Detail::hexThreshold ) + oss << " (0x" << std::hex << value << ")"; + return oss.str(); +} + +std::string toString( unsigned long value ) { + std::ostringstream oss; + oss << value; + if( value > Detail::hexThreshold ) + oss << " (0x" << std::hex << value << ")"; + return oss.str(); +} + +std::string toString( unsigned int value ) { + return Catch::toString( static_cast( value ) ); +} + +template +std::string fpToString( T value, int precision ) { + std::ostringstream oss; + oss << std::setprecision( precision ) + << std::fixed + << value; + std::string d = oss.str(); + std::size_t i = d.find_last_not_of( '0' ); + if( i != std::string::npos && i != d.size()-1 ) { + if( d[i] == '.' ) + i++; + d = d.substr( 0, i+1 ); + } + return d; +} + +std::string toString( const double value ) { + return fpToString( value, 10 ); +} +std::string toString( const float value ) { + return fpToString( value, 5 ) + "f"; +} + +std::string toString( bool value ) { + return value ? "true" : "false"; +} + +std::string toString( char value ) { + return value < ' ' + ? toString( static_cast( value ) ) + : Detail::makeString( value ); +} + +std::string toString( signed char value ) { + return toString( static_cast( value ) ); +} + +std::string toString( unsigned char value ) { + return toString( static_cast( value ) ); +} + +#ifdef CATCH_CONFIG_CPP11_LONG_LONG +std::string toString( long long value ) { + std::ostringstream oss; + oss << value; + if( value > Detail::hexThreshold ) + oss << " (0x" << std::hex << value << ")"; + return oss.str(); +} +std::string toString( unsigned long long value ) { + std::ostringstream oss; + oss << value; + if( value > Detail::hexThreshold ) + oss << " (0x" << std::hex << value << ")"; + return oss.str(); +} +#endif + +#ifdef CATCH_CONFIG_CPP11_NULLPTR +std::string toString( std::nullptr_t ) { + return "nullptr"; +} +#endif + +#ifdef __OBJC__ + std::string toString( NSString const * const& nsstring ) { + if( !nsstring ) + return "nil"; + return "@" + toString([nsstring UTF8String]); + } + std::string toString( NSString * CATCH_ARC_STRONG const& nsstring ) { + if( !nsstring ) + return "nil"; + return "@" + toString([nsstring UTF8String]); + } + std::string toString( NSObject* const& nsObject ) { + return toString( [nsObject description] ); + } +#endif + +} // end namespace Catch + +// #included from: catch_result_builder.hpp +#define TWOBLUECUBES_CATCH_RESULT_BUILDER_HPP_INCLUDED + +namespace Catch { + + std::string capturedExpressionWithSecondArgument( std::string const& capturedExpression, std::string const& secondArg ) { + return secondArg.empty() || secondArg == "\"\"" + ? capturedExpression + : capturedExpression + ", " + secondArg; + } + ResultBuilder::ResultBuilder( char const* macroName, + SourceLineInfo const& lineInfo, + char const* capturedExpression, + ResultDisposition::Flags resultDisposition, + char const* secondArg ) + : m_assertionInfo( macroName, lineInfo, capturedExpressionWithSecondArgument( capturedExpression, secondArg ), resultDisposition ), + m_shouldDebugBreak( false ), + m_shouldThrow( false ) + {} + + ResultBuilder& ResultBuilder::setResultType( ResultWas::OfType result ) { + m_data.resultType = result; + return *this; + } + ResultBuilder& ResultBuilder::setResultType( bool result ) { + m_data.resultType = result ? ResultWas::Ok : ResultWas::ExpressionFailed; + return *this; + } + ResultBuilder& ResultBuilder::setLhs( std::string const& lhs ) { + m_exprComponents.lhs = lhs; + return *this; + } + ResultBuilder& ResultBuilder::setRhs( std::string const& rhs ) { + m_exprComponents.rhs = rhs; + return *this; + } + ResultBuilder& ResultBuilder::setOp( std::string const& op ) { + m_exprComponents.op = op; + return *this; + } + + void ResultBuilder::endExpression() { + m_exprComponents.testFalse = isFalseTest( m_assertionInfo.resultDisposition ); + captureExpression(); + } + + void ResultBuilder::useActiveException( ResultDisposition::Flags resultDisposition ) { + m_assertionInfo.resultDisposition = resultDisposition; + m_stream.oss << Catch::translateActiveException(); + captureResult( ResultWas::ThrewException ); + } + + void ResultBuilder::captureResult( ResultWas::OfType resultType ) { + setResultType( resultType ); + captureExpression(); + } + void ResultBuilder::captureExpectedException( std::string const& expectedMessage ) { + if( expectedMessage.empty() ) + captureExpectedException( Matchers::Impl::Generic::AllOf() ); + else + captureExpectedException( Matchers::Equals( expectedMessage ) ); + } + + void ResultBuilder::captureExpectedException( Matchers::Impl::Matcher const& matcher ) { + + assert( m_exprComponents.testFalse == false ); + AssertionResultData data = m_data; + data.resultType = ResultWas::Ok; + data.reconstructedExpression = m_assertionInfo.capturedExpression; + + std::string actualMessage = Catch::translateActiveException(); + if( !matcher.match( actualMessage ) ) { + data.resultType = ResultWas::ExpressionFailed; + data.reconstructedExpression = actualMessage; + } + AssertionResult result( m_assertionInfo, data ); + handleResult( result ); + } + + void ResultBuilder::captureExpression() { + AssertionResult result = build(); + handleResult( result ); + } + void ResultBuilder::handleResult( AssertionResult const& result ) + { + getResultCapture().assertionEnded( result ); + + if( !result.isOk() ) { + if( getCurrentContext().getConfig()->shouldDebugBreak() ) + m_shouldDebugBreak = true; + if( getCurrentContext().getRunner()->aborting() || (m_assertionInfo.resultDisposition & ResultDisposition::Normal) ) + m_shouldThrow = true; + } + } + void ResultBuilder::react() { + if( m_shouldThrow ) + throw Catch::TestFailureException(); + } + + bool ResultBuilder::shouldDebugBreak() const { return m_shouldDebugBreak; } + bool ResultBuilder::allowThrows() const { return getCurrentContext().getConfig()->allowThrows(); } + + AssertionResult ResultBuilder::build() const + { + assert( m_data.resultType != ResultWas::Unknown ); + + AssertionResultData data = m_data; + + // Flip bool results if testFalse is set + if( m_exprComponents.testFalse ) { + if( data.resultType == ResultWas::Ok ) + data.resultType = ResultWas::ExpressionFailed; + else if( data.resultType == ResultWas::ExpressionFailed ) + data.resultType = ResultWas::Ok; + } + + data.message = m_stream.oss.str(); + data.reconstructedExpression = reconstructExpression(); + if( m_exprComponents.testFalse ) { + if( m_exprComponents.op == "" ) + data.reconstructedExpression = "!" + data.reconstructedExpression; + else + data.reconstructedExpression = "!(" + data.reconstructedExpression + ")"; + } + return AssertionResult( m_assertionInfo, data ); + } + std::string ResultBuilder::reconstructExpression() const { + if( m_exprComponents.op == "" ) + return m_exprComponents.lhs.empty() ? m_assertionInfo.capturedExpression : m_exprComponents.op + m_exprComponents.lhs; + else if( m_exprComponents.op == "matches" ) + return m_exprComponents.lhs + " " + m_exprComponents.rhs; + else if( m_exprComponents.op != "!" ) { + if( m_exprComponents.lhs.size() + m_exprComponents.rhs.size() < 40 && + m_exprComponents.lhs.find("\n") == std::string::npos && + m_exprComponents.rhs.find("\n") == std::string::npos ) + return m_exprComponents.lhs + " " + m_exprComponents.op + " " + m_exprComponents.rhs; + else + return m_exprComponents.lhs + "\n" + m_exprComponents.op + "\n" + m_exprComponents.rhs; + } + else + return "{can't expand - use " + m_assertionInfo.macroName + "_FALSE( " + m_assertionInfo.capturedExpression.substr(1) + " ) instead of " + m_assertionInfo.macroName + "( " + m_assertionInfo.capturedExpression + " ) for better diagnostics}"; + } + +} // end namespace Catch + +// #included from: catch_tag_alias_registry.hpp +#define TWOBLUECUBES_CATCH_TAG_ALIAS_REGISTRY_HPP_INCLUDED + +// #included from: catch_tag_alias_registry.h +#define TWOBLUECUBES_CATCH_TAG_ALIAS_REGISTRY_H_INCLUDED + +#include + +namespace Catch { + + class TagAliasRegistry : public ITagAliasRegistry { + public: + virtual ~TagAliasRegistry(); + virtual Option find( std::string const& alias ) const; + virtual std::string expandAliases( std::string const& unexpandedTestSpec ) const; + void add( char const* alias, char const* tag, SourceLineInfo const& lineInfo ); + static TagAliasRegistry& get(); + + private: + std::map m_registry; + }; + +} // end namespace Catch + +#include +#include + +namespace Catch { + + TagAliasRegistry::~TagAliasRegistry() {} + + Option TagAliasRegistry::find( std::string const& alias ) const { + std::map::const_iterator it = m_registry.find( alias ); + if( it != m_registry.end() ) + return it->second; + else + return Option(); + } + + std::string TagAliasRegistry::expandAliases( std::string const& unexpandedTestSpec ) const { + std::string expandedTestSpec = unexpandedTestSpec; + for( std::map::const_iterator it = m_registry.begin(), itEnd = m_registry.end(); + it != itEnd; + ++it ) { + std::size_t pos = expandedTestSpec.find( it->first ); + if( pos != std::string::npos ) { + expandedTestSpec = expandedTestSpec.substr( 0, pos ) + + it->second.tag + + expandedTestSpec.substr( pos + it->first.size() ); + } + } + return expandedTestSpec; + } + + void TagAliasRegistry::add( char const* alias, char const* tag, SourceLineInfo const& lineInfo ) { + + if( !startsWith( alias, "[@" ) || !endsWith( alias, "]" ) ) { + std::ostringstream oss; + oss << "error: tag alias, \"" << alias << "\" is not of the form [@alias name].\n" << lineInfo; + throw std::domain_error( oss.str().c_str() ); + } + if( !m_registry.insert( std::make_pair( alias, TagAlias( tag, lineInfo ) ) ).second ) { + std::ostringstream oss; + oss << "error: tag alias, \"" << alias << "\" already registered.\n" + << "\tFirst seen at " << find(alias)->lineInfo << "\n" + << "\tRedefined at " << lineInfo; + throw std::domain_error( oss.str().c_str() ); + } + } + + TagAliasRegistry& TagAliasRegistry::get() { + static TagAliasRegistry instance; + return instance; + + } + + ITagAliasRegistry::~ITagAliasRegistry() {} + ITagAliasRegistry const& ITagAliasRegistry::get() { return TagAliasRegistry::get(); } + + RegistrarForTagAliases::RegistrarForTagAliases( char const* alias, char const* tag, SourceLineInfo const& lineInfo ) { + try { + TagAliasRegistry::get().add( alias, tag, lineInfo ); + } + catch( std::exception& ex ) { + Colour colourGuard( Colour::Red ); + Catch::cerr() << ex.what() << std::endl; + exit(1); + } + } + +} // end namespace Catch + +// #included from: ../reporters/catch_reporter_multi.hpp +#define TWOBLUECUBES_CATCH_REPORTER_MULTI_HPP_INCLUDED + +namespace Catch { + +class MultipleReporters : public SharedImpl { + typedef std::vector > Reporters; + Reporters m_reporters; + +public: + void add( Ptr const& reporter ) { + m_reporters.push_back( reporter ); + } + +public: // IStreamingReporter + + virtual ReporterPreferences getPreferences() const CATCH_OVERRIDE { + return m_reporters[0]->getPreferences(); + } + + virtual void noMatchingTestCases( std::string const& spec ) CATCH_OVERRIDE { + for( Reporters::const_iterator it = m_reporters.begin(), itEnd = m_reporters.end(); + it != itEnd; + ++it ) + (*it)->noMatchingTestCases( spec ); + } + + virtual void testRunStarting( TestRunInfo const& testRunInfo ) CATCH_OVERRIDE { + for( Reporters::const_iterator it = m_reporters.begin(), itEnd = m_reporters.end(); + it != itEnd; + ++it ) + (*it)->testRunStarting( testRunInfo ); + } + + virtual void testGroupStarting( GroupInfo const& groupInfo ) CATCH_OVERRIDE { + for( Reporters::const_iterator it = m_reporters.begin(), itEnd = m_reporters.end(); + it != itEnd; + ++it ) + (*it)->testGroupStarting( groupInfo ); + } + + virtual void testCaseStarting( TestCaseInfo const& testInfo ) CATCH_OVERRIDE { + for( Reporters::const_iterator it = m_reporters.begin(), itEnd = m_reporters.end(); + it != itEnd; + ++it ) + (*it)->testCaseStarting( testInfo ); + } + + virtual void sectionStarting( SectionInfo const& sectionInfo ) CATCH_OVERRIDE { + for( Reporters::const_iterator it = m_reporters.begin(), itEnd = m_reporters.end(); + it != itEnd; + ++it ) + (*it)->sectionStarting( sectionInfo ); + } + + virtual void assertionStarting( AssertionInfo const& assertionInfo ) CATCH_OVERRIDE { + for( Reporters::const_iterator it = m_reporters.begin(), itEnd = m_reporters.end(); + it != itEnd; + ++it ) + (*it)->assertionStarting( assertionInfo ); + } + + // The return value indicates if the messages buffer should be cleared: + virtual bool assertionEnded( AssertionStats const& assertionStats ) CATCH_OVERRIDE { + bool clearBuffer = false; + for( Reporters::const_iterator it = m_reporters.begin(), itEnd = m_reporters.end(); + it != itEnd; + ++it ) + clearBuffer |= (*it)->assertionEnded( assertionStats ); + return clearBuffer; + } + + virtual void sectionEnded( SectionStats const& sectionStats ) CATCH_OVERRIDE { + for( Reporters::const_iterator it = m_reporters.begin(), itEnd = m_reporters.end(); + it != itEnd; + ++it ) + (*it)->sectionEnded( sectionStats ); + } + + virtual void testCaseEnded( TestCaseStats const& testCaseStats ) CATCH_OVERRIDE { + for( Reporters::const_iterator it = m_reporters.begin(), itEnd = m_reporters.end(); + it != itEnd; + ++it ) + (*it)->testCaseEnded( testCaseStats ); + } + + virtual void testGroupEnded( TestGroupStats const& testGroupStats ) CATCH_OVERRIDE { + for( Reporters::const_iterator it = m_reporters.begin(), itEnd = m_reporters.end(); + it != itEnd; + ++it ) + (*it)->testGroupEnded( testGroupStats ); + } + + virtual void testRunEnded( TestRunStats const& testRunStats ) CATCH_OVERRIDE { + for( Reporters::const_iterator it = m_reporters.begin(), itEnd = m_reporters.end(); + it != itEnd; + ++it ) + (*it)->testRunEnded( testRunStats ); + } + + virtual void skipTest( TestCaseInfo const& testInfo ) CATCH_OVERRIDE { + for( Reporters::const_iterator it = m_reporters.begin(), itEnd = m_reporters.end(); + it != itEnd; + ++it ) + (*it)->skipTest( testInfo ); + } + + virtual MultipleReporters* tryAsMulti() CATCH_OVERRIDE { + return this; + } + +}; + +Ptr addReporter( Ptr const& existingReporter, Ptr const& additionalReporter ) { + Ptr resultingReporter; + + if( existingReporter ) { + MultipleReporters* multi = existingReporter->tryAsMulti(); + if( !multi ) { + multi = new MultipleReporters; + resultingReporter = Ptr( multi ); + if( existingReporter ) + multi->add( existingReporter ); + } + else + resultingReporter = existingReporter; + multi->add( additionalReporter ); + } + else + resultingReporter = additionalReporter; + + return resultingReporter; +} + +} // end namespace Catch + +// #included from: ../reporters/catch_reporter_xml.hpp +#define TWOBLUECUBES_CATCH_REPORTER_XML_HPP_INCLUDED + +// #included from: catch_reporter_bases.hpp +#define TWOBLUECUBES_CATCH_REPORTER_BASES_HPP_INCLUDED + +#include + +namespace Catch { + + struct StreamingReporterBase : SharedImpl { + + StreamingReporterBase( ReporterConfig const& _config ) + : m_config( _config.fullConfig() ), + stream( _config.stream() ) + { + m_reporterPrefs.shouldRedirectStdOut = false; + } + + virtual ReporterPreferences getPreferences() const CATCH_OVERRIDE { + return m_reporterPrefs; + } + + virtual ~StreamingReporterBase() CATCH_OVERRIDE; + + virtual void noMatchingTestCases( std::string const& ) CATCH_OVERRIDE {} + + virtual void testRunStarting( TestRunInfo const& _testRunInfo ) CATCH_OVERRIDE { + currentTestRunInfo = _testRunInfo; + } + virtual void testGroupStarting( GroupInfo const& _groupInfo ) CATCH_OVERRIDE { + currentGroupInfo = _groupInfo; + } + + virtual void testCaseStarting( TestCaseInfo const& _testInfo ) CATCH_OVERRIDE { + currentTestCaseInfo = _testInfo; + } + virtual void sectionStarting( SectionInfo const& _sectionInfo ) CATCH_OVERRIDE { + m_sectionStack.push_back( _sectionInfo ); + } + + virtual void sectionEnded( SectionStats const& /* _sectionStats */ ) CATCH_OVERRIDE { + m_sectionStack.pop_back(); + } + virtual void testCaseEnded( TestCaseStats const& /* _testCaseStats */ ) CATCH_OVERRIDE { + currentTestCaseInfo.reset(); + } + virtual void testGroupEnded( TestGroupStats const& /* _testGroupStats */ ) CATCH_OVERRIDE { + currentGroupInfo.reset(); + } + virtual void testRunEnded( TestRunStats const& /* _testRunStats */ ) CATCH_OVERRIDE { + currentTestCaseInfo.reset(); + currentGroupInfo.reset(); + currentTestRunInfo.reset(); + } + + virtual void skipTest( TestCaseInfo const& ) CATCH_OVERRIDE { + // Don't do anything with this by default. + // It can optionally be overridden in the derived class. + } + + Ptr m_config; + std::ostream& stream; + + LazyStat currentTestRunInfo; + LazyStat currentGroupInfo; + LazyStat currentTestCaseInfo; + + std::vector m_sectionStack; + ReporterPreferences m_reporterPrefs; + }; + + struct CumulativeReporterBase : SharedImpl { + template + struct Node : SharedImpl<> { + explicit Node( T const& _value ) : value( _value ) {} + virtual ~Node() {} + + typedef std::vector > ChildNodes; + T value; + ChildNodes children; + }; + struct SectionNode : SharedImpl<> { + explicit SectionNode( SectionStats const& _stats ) : stats( _stats ) {} + virtual ~SectionNode(); + + bool operator == ( SectionNode const& other ) const { + return stats.sectionInfo.lineInfo == other.stats.sectionInfo.lineInfo; + } + bool operator == ( Ptr const& other ) const { + return operator==( *other ); + } + + SectionStats stats; + typedef std::vector > ChildSections; + typedef std::vector Assertions; + ChildSections childSections; + Assertions assertions; + std::string stdOut; + std::string stdErr; + }; + + struct BySectionInfo { + BySectionInfo( SectionInfo const& other ) : m_other( other ) {} + BySectionInfo( BySectionInfo const& other ) : m_other( other.m_other ) {} + bool operator() ( Ptr const& node ) const { + return node->stats.sectionInfo.lineInfo == m_other.lineInfo; + } + private: + void operator=( BySectionInfo const& ); + SectionInfo const& m_other; + }; + + typedef Node TestCaseNode; + typedef Node TestGroupNode; + typedef Node TestRunNode; + + CumulativeReporterBase( ReporterConfig const& _config ) + : m_config( _config.fullConfig() ), + stream( _config.stream() ) + { + m_reporterPrefs.shouldRedirectStdOut = false; + } + ~CumulativeReporterBase(); + + virtual ReporterPreferences getPreferences() const CATCH_OVERRIDE { + return m_reporterPrefs; + } + + virtual void testRunStarting( TestRunInfo const& ) CATCH_OVERRIDE {} + virtual void testGroupStarting( GroupInfo const& ) CATCH_OVERRIDE {} + + virtual void testCaseStarting( TestCaseInfo const& ) CATCH_OVERRIDE {} + + virtual void sectionStarting( SectionInfo const& sectionInfo ) CATCH_OVERRIDE { + SectionStats incompleteStats( sectionInfo, Counts(), 0, false ); + Ptr node; + if( m_sectionStack.empty() ) { + if( !m_rootSection ) + m_rootSection = new SectionNode( incompleteStats ); + node = m_rootSection; + } + else { + SectionNode& parentNode = *m_sectionStack.back(); + SectionNode::ChildSections::const_iterator it = + std::find_if( parentNode.childSections.begin(), + parentNode.childSections.end(), + BySectionInfo( sectionInfo ) ); + if( it == parentNode.childSections.end() ) { + node = new SectionNode( incompleteStats ); + parentNode.childSections.push_back( node ); + } + else + node = *it; + } + m_sectionStack.push_back( node ); + m_deepestSection = node; + } + + virtual void assertionStarting( AssertionInfo const& ) CATCH_OVERRIDE {} + + virtual bool assertionEnded( AssertionStats const& assertionStats ) CATCH_OVERRIDE { + assert( !m_sectionStack.empty() ); + SectionNode& sectionNode = *m_sectionStack.back(); + sectionNode.assertions.push_back( assertionStats ); + return true; + } + virtual void sectionEnded( SectionStats const& sectionStats ) CATCH_OVERRIDE { + assert( !m_sectionStack.empty() ); + SectionNode& node = *m_sectionStack.back(); + node.stats = sectionStats; + m_sectionStack.pop_back(); + } + virtual void testCaseEnded( TestCaseStats const& testCaseStats ) CATCH_OVERRIDE { + Ptr node = new TestCaseNode( testCaseStats ); + assert( m_sectionStack.size() == 0 ); + node->children.push_back( m_rootSection ); + m_testCases.push_back( node ); + m_rootSection.reset(); + + assert( m_deepestSection ); + m_deepestSection->stdOut = testCaseStats.stdOut; + m_deepestSection->stdErr = testCaseStats.stdErr; + } + virtual void testGroupEnded( TestGroupStats const& testGroupStats ) CATCH_OVERRIDE { + Ptr node = new TestGroupNode( testGroupStats ); + node->children.swap( m_testCases ); + m_testGroups.push_back( node ); + } + virtual void testRunEnded( TestRunStats const& testRunStats ) CATCH_OVERRIDE { + Ptr node = new TestRunNode( testRunStats ); + node->children.swap( m_testGroups ); + m_testRuns.push_back( node ); + testRunEndedCumulative(); + } + virtual void testRunEndedCumulative() = 0; + + virtual void skipTest( TestCaseInfo const& ) CATCH_OVERRIDE {} + + Ptr m_config; + std::ostream& stream; + std::vector m_assertions; + std::vector > > m_sections; + std::vector > m_testCases; + std::vector > m_testGroups; + + std::vector > m_testRuns; + + Ptr m_rootSection; + Ptr m_deepestSection; + std::vector > m_sectionStack; + ReporterPreferences m_reporterPrefs; + + }; + + template + char const* getLineOfChars() { + static char line[CATCH_CONFIG_CONSOLE_WIDTH] = {0}; + if( !*line ) { + memset( line, C, CATCH_CONFIG_CONSOLE_WIDTH-1 ); + line[CATCH_CONFIG_CONSOLE_WIDTH-1] = 0; + } + return line; + } + + struct TestEventListenerBase : StreamingReporterBase { + TestEventListenerBase( ReporterConfig const& _config ) + : StreamingReporterBase( _config ) + {} + + virtual void assertionStarting( AssertionInfo const& ) CATCH_OVERRIDE {} + virtual bool assertionEnded( AssertionStats const& ) CATCH_OVERRIDE { + return false; + } + }; + +} // end namespace Catch + +// #included from: ../internal/catch_reporter_registrars.hpp +#define TWOBLUECUBES_CATCH_REPORTER_REGISTRARS_HPP_INCLUDED + +namespace Catch { + + template + class LegacyReporterRegistrar { + + class ReporterFactory : public IReporterFactory { + virtual IStreamingReporter* create( ReporterConfig const& config ) const { + return new LegacyReporterAdapter( new T( config ) ); + } + + virtual std::string getDescription() const { + return T::getDescription(); + } + }; + + public: + + LegacyReporterRegistrar( std::string const& name ) { + getMutableRegistryHub().registerReporter( name, new ReporterFactory() ); + } + }; + + template + class ReporterRegistrar { + + class ReporterFactory : public SharedImpl { + + // *** Please Note ***: + // - If you end up here looking at a compiler error because it's trying to register + // your custom reporter class be aware that the native reporter interface has changed + // to IStreamingReporter. The "legacy" interface, IReporter, is still supported via + // an adapter. Just use REGISTER_LEGACY_REPORTER to take advantage of the adapter. + // However please consider updating to the new interface as the old one is now + // deprecated and will probably be removed quite soon! + // Please contact me via github if you have any questions at all about this. + // In fact, ideally, please contact me anyway to let me know you've hit this - as I have + // no idea who is actually using custom reporters at all (possibly no-one!). + // The new interface is designed to minimise exposure to interface changes in the future. + virtual IStreamingReporter* create( ReporterConfig const& config ) const { + return new T( config ); + } + + virtual std::string getDescription() const { + return T::getDescription(); + } + }; + + public: + + ReporterRegistrar( std::string const& name ) { + getMutableRegistryHub().registerReporter( name, new ReporterFactory() ); + } + }; + + template + class ListenerRegistrar { + + class ListenerFactory : public SharedImpl { + + virtual IStreamingReporter* create( ReporterConfig const& config ) const { + return new T( config ); + } + virtual std::string getDescription() const { + return ""; + } + }; + + public: + + ListenerRegistrar() { + getMutableRegistryHub().registerListener( new ListenerFactory() ); + } + }; +} + +#define INTERNAL_CATCH_REGISTER_LEGACY_REPORTER( name, reporterType ) \ + namespace{ Catch::LegacyReporterRegistrar catch_internal_RegistrarFor##reporterType( name ); } + +#define INTERNAL_CATCH_REGISTER_REPORTER( name, reporterType ) \ + namespace{ Catch::ReporterRegistrar catch_internal_RegistrarFor##reporterType( name ); } + +#define INTERNAL_CATCH_REGISTER_LISTENER( listenerType ) \ + namespace{ Catch::ListenerRegistrar catch_internal_RegistrarFor##listenerType; } + +// #included from: ../internal/catch_xmlwriter.hpp +#define TWOBLUECUBES_CATCH_XMLWRITER_HPP_INCLUDED + +#include +#include +#include +#include + +namespace Catch { + + class XmlEncode { + public: + enum ForWhat { ForTextNodes, ForAttributes }; + + XmlEncode( std::string const& str, ForWhat forWhat = ForTextNodes ) + : m_str( str ), + m_forWhat( forWhat ) + {} + + void encodeTo( std::ostream& os ) const { + + // Apostrophe escaping not necessary if we always use " to write attributes + // (see: http://www.w3.org/TR/xml/#syntax) + + for( std::size_t i = 0; i < m_str.size(); ++ i ) { + char c = m_str[i]; + switch( c ) { + case '<': os << "<"; break; + case '&': os << "&"; break; + + case '>': + // See: http://www.w3.org/TR/xml/#syntax + if( i > 2 && m_str[i-1] == ']' && m_str[i-2] == ']' ) + os << ">"; + else + os << c; + break; + + case '\"': + if( m_forWhat == ForAttributes ) + os << """; + else + os << c; + break; + + default: + // Escape control chars - based on contribution by @espenalb in PR #465 + if ( ( c < '\x09' ) || ( c > '\x0D' && c < '\x20') || c=='\x7F' ) + os << "&#x" << std::uppercase << std::hex << static_cast( c ); + else + os << c; + } + } + } + + friend std::ostream& operator << ( std::ostream& os, XmlEncode const& xmlEncode ) { + xmlEncode.encodeTo( os ); + return os; + } + + private: + std::string m_str; + ForWhat m_forWhat; + }; + + class XmlWriter { + public: + + class ScopedElement { + public: + ScopedElement( XmlWriter* writer ) + : m_writer( writer ) + {} + + ScopedElement( ScopedElement const& other ) + : m_writer( other.m_writer ){ + other.m_writer = CATCH_NULL; + } + + ~ScopedElement() { + if( m_writer ) + m_writer->endElement(); + } + + ScopedElement& writeText( std::string const& text, bool indent = true ) { + m_writer->writeText( text, indent ); + return *this; + } + + template + ScopedElement& writeAttribute( std::string const& name, T const& attribute ) { + m_writer->writeAttribute( name, attribute ); + return *this; + } + + private: + mutable XmlWriter* m_writer; + }; + + XmlWriter() + : m_tagIsOpen( false ), + m_needsNewline( false ), + m_os( &Catch::cout() ) + {} + + XmlWriter( std::ostream& os ) + : m_tagIsOpen( false ), + m_needsNewline( false ), + m_os( &os ) + {} + + ~XmlWriter() { + while( !m_tags.empty() ) + endElement(); + } + + XmlWriter& startElement( std::string const& name ) { + ensureTagClosed(); + newlineIfNecessary(); + stream() << m_indent << "<" << name; + m_tags.push_back( name ); + m_indent += " "; + m_tagIsOpen = true; + return *this; + } + + ScopedElement scopedElement( std::string const& name ) { + ScopedElement scoped( this ); + startElement( name ); + return scoped; + } + + XmlWriter& endElement() { + newlineIfNecessary(); + m_indent = m_indent.substr( 0, m_indent.size()-2 ); + if( m_tagIsOpen ) { + stream() << "/>\n"; + m_tagIsOpen = false; + } + else { + stream() << m_indent << "\n"; + } + m_tags.pop_back(); + return *this; + } + + XmlWriter& writeAttribute( std::string const& name, std::string const& attribute ) { + if( !name.empty() && !attribute.empty() ) + stream() << " " << name << "=\"" << XmlEncode( attribute, XmlEncode::ForAttributes ) << "\""; + return *this; + } + + XmlWriter& writeAttribute( std::string const& name, bool attribute ) { + stream() << " " << name << "=\"" << ( attribute ? "true" : "false" ) << "\""; + return *this; + } + + template + XmlWriter& writeAttribute( std::string const& name, T const& attribute ) { + std::ostringstream oss; + oss << attribute; + return writeAttribute( name, oss.str() ); + } + + XmlWriter& writeText( std::string const& text, bool indent = true ) { + if( !text.empty() ){ + bool tagWasOpen = m_tagIsOpen; + ensureTagClosed(); + if( tagWasOpen && indent ) + stream() << m_indent; + stream() << XmlEncode( text ); + m_needsNewline = true; + } + return *this; + } + + XmlWriter& writeComment( std::string const& text ) { + ensureTagClosed(); + stream() << m_indent << ""; + m_needsNewline = true; + return *this; + } + + XmlWriter& writeBlankLine() { + ensureTagClosed(); + stream() << "\n"; + return *this; + } + + void setStream( std::ostream& os ) { + m_os = &os; + } + + private: + XmlWriter( XmlWriter const& ); + void operator=( XmlWriter const& ); + + std::ostream& stream() { + return *m_os; + } + + void ensureTagClosed() { + if( m_tagIsOpen ) { + stream() << ">\n"; + m_tagIsOpen = false; + } + } + + void newlineIfNecessary() { + if( m_needsNewline ) { + stream() << "\n"; + m_needsNewline = false; + } + } + + bool m_tagIsOpen; + bool m_needsNewline; + std::vector m_tags; + std::string m_indent; + std::ostream* m_os; + }; + +} +// #included from: catch_reenable_warnings.h + +#define TWOBLUECUBES_CATCH_REENABLE_WARNINGS_H_INCLUDED + +#ifdef __clang__ +# ifdef __ICC // icpc defines the __clang__ macro +# pragma warning(pop) +# else +# pragma clang diagnostic pop +# endif +#elif defined __GNUC__ +# pragma GCC diagnostic pop +#endif + + +namespace Catch { + class XmlReporter : public StreamingReporterBase { + public: + XmlReporter( ReporterConfig const& _config ) + : StreamingReporterBase( _config ), + m_sectionDepth( 0 ) + { + m_reporterPrefs.shouldRedirectStdOut = true; + } + + virtual ~XmlReporter() CATCH_OVERRIDE; + + static std::string getDescription() { + return "Reports test results as an XML document"; + } + + public: // StreamingReporterBase + + virtual void noMatchingTestCases( std::string const& s ) CATCH_OVERRIDE { + StreamingReporterBase::noMatchingTestCases( s ); + } + + virtual void testRunStarting( TestRunInfo const& testInfo ) CATCH_OVERRIDE { + StreamingReporterBase::testRunStarting( testInfo ); + m_xml.setStream( stream ); + m_xml.startElement( "Catch" ); + if( !m_config->name().empty() ) + m_xml.writeAttribute( "name", m_config->name() ); + } + + virtual void testGroupStarting( GroupInfo const& groupInfo ) CATCH_OVERRIDE { + StreamingReporterBase::testGroupStarting( groupInfo ); + m_xml.startElement( "Group" ) + .writeAttribute( "name", groupInfo.name ); + } + + virtual void testCaseStarting( TestCaseInfo const& testInfo ) CATCH_OVERRIDE { + StreamingReporterBase::testCaseStarting(testInfo); + m_xml.startElement( "TestCase" ).writeAttribute( "name", trim( testInfo.name ) ); + + if ( m_config->showDurations() == ShowDurations::Always ) + m_testCaseTimer.start(); + } + + virtual void sectionStarting( SectionInfo const& sectionInfo ) CATCH_OVERRIDE { + StreamingReporterBase::sectionStarting( sectionInfo ); + if( m_sectionDepth++ > 0 ) { + m_xml.startElement( "Section" ) + .writeAttribute( "name", trim( sectionInfo.name ) ) + .writeAttribute( "description", sectionInfo.description ); + } + } + + virtual void assertionStarting( AssertionInfo const& ) CATCH_OVERRIDE { } + + virtual bool assertionEnded( AssertionStats const& assertionStats ) CATCH_OVERRIDE { + const AssertionResult& assertionResult = assertionStats.assertionResult; + + // Print any info messages in tags. + if( assertionStats.assertionResult.getResultType() != ResultWas::Ok ) { + for( std::vector::const_iterator it = assertionStats.infoMessages.begin(), itEnd = assertionStats.infoMessages.end(); + it != itEnd; + ++it ) { + if( it->type == ResultWas::Info ) { + m_xml.scopedElement( "Info" ) + .writeText( it->message ); + } else if ( it->type == ResultWas::Warning ) { + m_xml.scopedElement( "Warning" ) + .writeText( it->message ); + } + } + } + + // Drop out if result was successful but we're not printing them. + if( !m_config->includeSuccessfulResults() && isOk(assertionResult.getResultType()) ) + return true; + + // Print the expression if there is one. + if( assertionResult.hasExpression() ) { + m_xml.startElement( "Expression" ) + .writeAttribute( "success", assertionResult.succeeded() ) + .writeAttribute( "type", assertionResult.getTestMacroName() ) + .writeAttribute( "filename", assertionResult.getSourceInfo().file ) + .writeAttribute( "line", assertionResult.getSourceInfo().line ); + + m_xml.scopedElement( "Original" ) + .writeText( assertionResult.getExpression() ); + m_xml.scopedElement( "Expanded" ) + .writeText( assertionResult.getExpandedExpression() ); + } + + // And... Print a result applicable to each result type. + switch( assertionResult.getResultType() ) { + case ResultWas::ThrewException: + m_xml.scopedElement( "Exception" ) + .writeAttribute( "filename", assertionResult.getSourceInfo().file ) + .writeAttribute( "line", assertionResult.getSourceInfo().line ) + .writeText( assertionResult.getMessage() ); + break; + case ResultWas::FatalErrorCondition: + m_xml.scopedElement( "Fatal Error Condition" ) + .writeAttribute( "filename", assertionResult.getSourceInfo().file ) + .writeAttribute( "line", assertionResult.getSourceInfo().line ) + .writeText( assertionResult.getMessage() ); + break; + case ResultWas::Info: + m_xml.scopedElement( "Info" ) + .writeText( assertionResult.getMessage() ); + break; + case ResultWas::Warning: + // Warning will already have been written + break; + case ResultWas::ExplicitFailure: + m_xml.scopedElement( "Failure" ) + .writeText( assertionResult.getMessage() ); + break; + default: + break; + } + + if( assertionResult.hasExpression() ) + m_xml.endElement(); + + return true; + } + + virtual void sectionEnded( SectionStats const& sectionStats ) CATCH_OVERRIDE { + StreamingReporterBase::sectionEnded( sectionStats ); + if( --m_sectionDepth > 0 ) { + XmlWriter::ScopedElement e = m_xml.scopedElement( "OverallResults" ); + e.writeAttribute( "successes", sectionStats.assertions.passed ); + e.writeAttribute( "failures", sectionStats.assertions.failed ); + e.writeAttribute( "expectedFailures", sectionStats.assertions.failedButOk ); + + if ( m_config->showDurations() == ShowDurations::Always ) + e.writeAttribute( "durationInSeconds", sectionStats.durationInSeconds ); + + m_xml.endElement(); + } + } + + virtual void testCaseEnded( TestCaseStats const& testCaseStats ) CATCH_OVERRIDE { + StreamingReporterBase::testCaseEnded( testCaseStats ); + XmlWriter::ScopedElement e = m_xml.scopedElement( "OverallResult" ); + e.writeAttribute( "success", testCaseStats.totals.assertions.allOk() ); + + if ( m_config->showDurations() == ShowDurations::Always ) + e.writeAttribute( "durationInSeconds", m_testCaseTimer.getElapsedSeconds() ); + + m_xml.endElement(); + } + + virtual void testGroupEnded( TestGroupStats const& testGroupStats ) CATCH_OVERRIDE { + StreamingReporterBase::testGroupEnded( testGroupStats ); + // TODO: Check testGroupStats.aborting and act accordingly. + m_xml.scopedElement( "OverallResults" ) + .writeAttribute( "successes", testGroupStats.totals.assertions.passed ) + .writeAttribute( "failures", testGroupStats.totals.assertions.failed ) + .writeAttribute( "expectedFailures", testGroupStats.totals.assertions.failedButOk ); + m_xml.endElement(); + } + + virtual void testRunEnded( TestRunStats const& testRunStats ) CATCH_OVERRIDE { + StreamingReporterBase::testRunEnded( testRunStats ); + m_xml.scopedElement( "OverallResults" ) + .writeAttribute( "successes", testRunStats.totals.assertions.passed ) + .writeAttribute( "failures", testRunStats.totals.assertions.failed ) + .writeAttribute( "expectedFailures", testRunStats.totals.assertions.failedButOk ); + m_xml.endElement(); + } + + private: + Timer m_testCaseTimer; + XmlWriter m_xml; + int m_sectionDepth; + }; + + INTERNAL_CATCH_REGISTER_REPORTER( "xml", XmlReporter ) + +} // end namespace Catch + +// #included from: ../reporters/catch_reporter_junit.hpp +#define TWOBLUECUBES_CATCH_REPORTER_JUNIT_HPP_INCLUDED + +#include + +namespace Catch { + + class JunitReporter : public CumulativeReporterBase { + public: + JunitReporter( ReporterConfig const& _config ) + : CumulativeReporterBase( _config ), + xml( _config.stream() ) + { + m_reporterPrefs.shouldRedirectStdOut = true; + } + + virtual ~JunitReporter() CATCH_OVERRIDE; + + static std::string getDescription() { + return "Reports test results in an XML format that looks like Ant's junitreport target"; + } + + virtual void noMatchingTestCases( std::string const& /*spec*/ ) CATCH_OVERRIDE {} + + virtual void testRunStarting( TestRunInfo const& runInfo ) CATCH_OVERRIDE { + CumulativeReporterBase::testRunStarting( runInfo ); + xml.startElement( "testsuites" ); + } + + virtual void testGroupStarting( GroupInfo const& groupInfo ) CATCH_OVERRIDE { + suiteTimer.start(); + stdOutForSuite.str(""); + stdErrForSuite.str(""); + unexpectedExceptions = 0; + CumulativeReporterBase::testGroupStarting( groupInfo ); + } + + virtual bool assertionEnded( AssertionStats const& assertionStats ) CATCH_OVERRIDE { + if( assertionStats.assertionResult.getResultType() == ResultWas::ThrewException ) + unexpectedExceptions++; + return CumulativeReporterBase::assertionEnded( assertionStats ); + } + + virtual void testCaseEnded( TestCaseStats const& testCaseStats ) CATCH_OVERRIDE { + stdOutForSuite << testCaseStats.stdOut; + stdErrForSuite << testCaseStats.stdErr; + CumulativeReporterBase::testCaseEnded( testCaseStats ); + } + + virtual void testGroupEnded( TestGroupStats const& testGroupStats ) CATCH_OVERRIDE { + double suiteTime = suiteTimer.getElapsedSeconds(); + CumulativeReporterBase::testGroupEnded( testGroupStats ); + writeGroup( *m_testGroups.back(), suiteTime ); + } + + virtual void testRunEndedCumulative() CATCH_OVERRIDE { + xml.endElement(); + } + + void writeGroup( TestGroupNode const& groupNode, double suiteTime ) { + XmlWriter::ScopedElement e = xml.scopedElement( "testsuite" ); + TestGroupStats const& stats = groupNode.value; + xml.writeAttribute( "name", stats.groupInfo.name ); + xml.writeAttribute( "errors", unexpectedExceptions ); + xml.writeAttribute( "failures", stats.totals.assertions.failed-unexpectedExceptions ); + xml.writeAttribute( "tests", stats.totals.assertions.total() ); + xml.writeAttribute( "hostname", "tbd" ); // !TBD + if( m_config->showDurations() == ShowDurations::Never ) + xml.writeAttribute( "time", "" ); + else + xml.writeAttribute( "time", suiteTime ); + xml.writeAttribute( "timestamp", "tbd" ); // !TBD + + // Write test cases + for( TestGroupNode::ChildNodes::const_iterator + it = groupNode.children.begin(), itEnd = groupNode.children.end(); + it != itEnd; + ++it ) + writeTestCase( **it ); + + xml.scopedElement( "system-out" ).writeText( trim( stdOutForSuite.str() ), false ); + xml.scopedElement( "system-err" ).writeText( trim( stdErrForSuite.str() ), false ); + } + + void writeTestCase( TestCaseNode const& testCaseNode ) { + TestCaseStats const& stats = testCaseNode.value; + + // All test cases have exactly one section - which represents the + // test case itself. That section may have 0-n nested sections + assert( testCaseNode.children.size() == 1 ); + SectionNode const& rootSection = *testCaseNode.children.front(); + + std::string className = stats.testInfo.className; + + if( className.empty() ) { + if( rootSection.childSections.empty() ) + className = "global"; + } + writeSection( className, "", rootSection ); + } + + void writeSection( std::string const& className, + std::string const& rootName, + SectionNode const& sectionNode ) { + std::string name = trim( sectionNode.stats.sectionInfo.name ); + if( !rootName.empty() ) + name = rootName + "/" + name; + + if( !sectionNode.assertions.empty() || + !sectionNode.stdOut.empty() || + !sectionNode.stdErr.empty() ) { + XmlWriter::ScopedElement e = xml.scopedElement( "testcase" ); + if( className.empty() ) { + xml.writeAttribute( "classname", name ); + xml.writeAttribute( "name", "root" ); + } + else { + xml.writeAttribute( "classname", className ); + xml.writeAttribute( "name", name ); + } + xml.writeAttribute( "time", Catch::toString( sectionNode.stats.durationInSeconds ) ); + + writeAssertions( sectionNode ); + + if( !sectionNode.stdOut.empty() ) + xml.scopedElement( "system-out" ).writeText( trim( sectionNode.stdOut ), false ); + if( !sectionNode.stdErr.empty() ) + xml.scopedElement( "system-err" ).writeText( trim( sectionNode.stdErr ), false ); + } + for( SectionNode::ChildSections::const_iterator + it = sectionNode.childSections.begin(), + itEnd = sectionNode.childSections.end(); + it != itEnd; + ++it ) + if( className.empty() ) + writeSection( name, "", **it ); + else + writeSection( className, name, **it ); + } + + void writeAssertions( SectionNode const& sectionNode ) { + for( SectionNode::Assertions::const_iterator + it = sectionNode.assertions.begin(), itEnd = sectionNode.assertions.end(); + it != itEnd; + ++it ) + writeAssertion( *it ); + } + void writeAssertion( AssertionStats const& stats ) { + AssertionResult const& result = stats.assertionResult; + if( !result.isOk() ) { + std::string elementName; + switch( result.getResultType() ) { + case ResultWas::ThrewException: + case ResultWas::FatalErrorCondition: + elementName = "error"; + break; + case ResultWas::ExplicitFailure: + elementName = "failure"; + break; + case ResultWas::ExpressionFailed: + elementName = "failure"; + break; + case ResultWas::DidntThrowException: + elementName = "failure"; + break; + + // We should never see these here: + case ResultWas::Info: + case ResultWas::Warning: + case ResultWas::Ok: + case ResultWas::Unknown: + case ResultWas::FailureBit: + case ResultWas::Exception: + elementName = "internalError"; + break; + } + + XmlWriter::ScopedElement e = xml.scopedElement( elementName ); + + xml.writeAttribute( "message", result.getExpandedExpression() ); + xml.writeAttribute( "type", result.getTestMacroName() ); + + std::ostringstream oss; + if( !result.getMessage().empty() ) + oss << result.getMessage() << "\n"; + for( std::vector::const_iterator + it = stats.infoMessages.begin(), + itEnd = stats.infoMessages.end(); + it != itEnd; + ++it ) + if( it->type == ResultWas::Info ) + oss << it->message << "\n"; + + oss << "at " << result.getSourceInfo(); + xml.writeText( oss.str(), false ); + } + } + + XmlWriter xml; + Timer suiteTimer; + std::ostringstream stdOutForSuite; + std::ostringstream stdErrForSuite; + unsigned int unexpectedExceptions; + }; + + INTERNAL_CATCH_REGISTER_REPORTER( "junit", JunitReporter ) + +} // end namespace Catch + +// #included from: ../reporters/catch_reporter_console.hpp +#define TWOBLUECUBES_CATCH_REPORTER_CONSOLE_HPP_INCLUDED + +namespace Catch { + + struct ConsoleReporter : StreamingReporterBase { + ConsoleReporter( ReporterConfig const& _config ) + : StreamingReporterBase( _config ), + m_headerPrinted( false ) + {} + + virtual ~ConsoleReporter() CATCH_OVERRIDE; + static std::string getDescription() { + return "Reports test results as plain lines of text"; + } + + virtual void noMatchingTestCases( std::string const& spec ) CATCH_OVERRIDE { + stream << "No test cases matched '" << spec << "'" << std::endl; + } + + virtual void assertionStarting( AssertionInfo const& ) CATCH_OVERRIDE { + } + + virtual bool assertionEnded( AssertionStats const& _assertionStats ) CATCH_OVERRIDE { + AssertionResult const& result = _assertionStats.assertionResult; + + bool printInfoMessages = true; + + // Drop out if result was successful and we're not printing those + if( !m_config->includeSuccessfulResults() && result.isOk() ) { + if( result.getResultType() != ResultWas::Warning ) + return false; + printInfoMessages = false; + } + + lazyPrint(); + + AssertionPrinter printer( stream, _assertionStats, printInfoMessages ); + printer.print(); + stream << std::endl; + return true; + } + + virtual void sectionStarting( SectionInfo const& _sectionInfo ) CATCH_OVERRIDE { + m_headerPrinted = false; + StreamingReporterBase::sectionStarting( _sectionInfo ); + } + virtual void sectionEnded( SectionStats const& _sectionStats ) CATCH_OVERRIDE { + if( _sectionStats.missingAssertions ) { + lazyPrint(); + Colour colour( Colour::ResultError ); + if( m_sectionStack.size() > 1 ) + stream << "\nNo assertions in section"; + else + stream << "\nNo assertions in test case"; + stream << " '" << _sectionStats.sectionInfo.name << "'\n" << std::endl; + } + if( m_headerPrinted ) { + if( m_config->showDurations() == ShowDurations::Always ) + stream << "Completed in " << _sectionStats.durationInSeconds << "s" << std::endl; + m_headerPrinted = false; + } + else { + if( m_config->showDurations() == ShowDurations::Always ) + stream << _sectionStats.sectionInfo.name << " completed in " << _sectionStats.durationInSeconds << "s" << std::endl; + } + StreamingReporterBase::sectionEnded( _sectionStats ); + } + + virtual void testCaseEnded( TestCaseStats const& _testCaseStats ) CATCH_OVERRIDE { + StreamingReporterBase::testCaseEnded( _testCaseStats ); + m_headerPrinted = false; + } + virtual void testGroupEnded( TestGroupStats const& _testGroupStats ) CATCH_OVERRIDE { + if( currentGroupInfo.used ) { + printSummaryDivider(); + stream << "Summary for group '" << _testGroupStats.groupInfo.name << "':\n"; + printTotals( _testGroupStats.totals ); + stream << "\n" << std::endl; + } + StreamingReporterBase::testGroupEnded( _testGroupStats ); + } + virtual void testRunEnded( TestRunStats const& _testRunStats ) CATCH_OVERRIDE { + printTotalsDivider( _testRunStats.totals ); + printTotals( _testRunStats.totals ); + stream << std::endl; + StreamingReporterBase::testRunEnded( _testRunStats ); + } + + private: + + class AssertionPrinter { + void operator= ( AssertionPrinter const& ); + public: + AssertionPrinter( std::ostream& _stream, AssertionStats const& _stats, bool _printInfoMessages ) + : stream( _stream ), + stats( _stats ), + result( _stats.assertionResult ), + colour( Colour::None ), + message( result.getMessage() ), + messages( _stats.infoMessages ), + printInfoMessages( _printInfoMessages ) + { + switch( result.getResultType() ) { + case ResultWas::Ok: + colour = Colour::Success; + passOrFail = "PASSED"; + //if( result.hasMessage() ) + if( _stats.infoMessages.size() == 1 ) + messageLabel = "with message"; + if( _stats.infoMessages.size() > 1 ) + messageLabel = "with messages"; + break; + case ResultWas::ExpressionFailed: + if( result.isOk() ) { + colour = Colour::Success; + passOrFail = "FAILED - but was ok"; + } + else { + colour = Colour::Error; + passOrFail = "FAILED"; + } + if( _stats.infoMessages.size() == 1 ) + messageLabel = "with message"; + if( _stats.infoMessages.size() > 1 ) + messageLabel = "with messages"; + break; + case ResultWas::ThrewException: + colour = Colour::Error; + passOrFail = "FAILED"; + messageLabel = "due to unexpected exception with message"; + break; + case ResultWas::FatalErrorCondition: + colour = Colour::Error; + passOrFail = "FAILED"; + messageLabel = "due to a fatal error condition"; + break; + case ResultWas::DidntThrowException: + colour = Colour::Error; + passOrFail = "FAILED"; + messageLabel = "because no exception was thrown where one was expected"; + break; + case ResultWas::Info: + messageLabel = "info"; + break; + case ResultWas::Warning: + messageLabel = "warning"; + break; + case ResultWas::ExplicitFailure: + passOrFail = "FAILED"; + colour = Colour::Error; + if( _stats.infoMessages.size() == 1 ) + messageLabel = "explicitly with message"; + if( _stats.infoMessages.size() > 1 ) + messageLabel = "explicitly with messages"; + break; + // These cases are here to prevent compiler warnings + case ResultWas::Unknown: + case ResultWas::FailureBit: + case ResultWas::Exception: + passOrFail = "** internal error **"; + colour = Colour::Error; + break; + } + } + + void print() const { + printSourceInfo(); + if( stats.totals.assertions.total() > 0 ) { + if( result.isOk() ) + stream << "\n"; + printResultType(); + printOriginalExpression(); + printReconstructedExpression(); + } + else { + stream << "\n"; + } + printMessage(); + } + + private: + void printResultType() const { + if( !passOrFail.empty() ) { + Colour colourGuard( colour ); + stream << passOrFail << ":\n"; + } + } + void printOriginalExpression() const { + if( result.hasExpression() ) { + Colour colourGuard( Colour::OriginalExpression ); + stream << " "; + stream << result.getExpressionInMacro(); + stream << "\n"; + } + } + void printReconstructedExpression() const { + if( result.hasExpandedExpression() ) { + stream << "with expansion:\n"; + Colour colourGuard( Colour::ReconstructedExpression ); + stream << Text( result.getExpandedExpression(), TextAttributes().setIndent(2) ) << "\n"; + } + } + void printMessage() const { + if( !messageLabel.empty() ) + stream << messageLabel << ":" << "\n"; + for( std::vector::const_iterator it = messages.begin(), itEnd = messages.end(); + it != itEnd; + ++it ) { + // If this assertion is a warning ignore any INFO messages + if( printInfoMessages || it->type != ResultWas::Info ) + stream << Text( it->message, TextAttributes().setIndent(2) ) << "\n"; + } + } + void printSourceInfo() const { + Colour colourGuard( Colour::FileName ); + stream << result.getSourceInfo() << ": "; + } + + std::ostream& stream; + AssertionStats const& stats; + AssertionResult const& result; + Colour::Code colour; + std::string passOrFail; + std::string messageLabel; + std::string message; + std::vector messages; + bool printInfoMessages; + }; + + void lazyPrint() { + + if( !currentTestRunInfo.used ) + lazyPrintRunInfo(); + if( !currentGroupInfo.used ) + lazyPrintGroupInfo(); + + if( !m_headerPrinted ) { + printTestCaseAndSectionHeader(); + m_headerPrinted = true; + } + } + void lazyPrintRunInfo() { + stream << "\n" << getLineOfChars<'~'>() << "\n"; + Colour colour( Colour::SecondaryText ); + stream << currentTestRunInfo->name + << " is a Catch v" << libraryVersion << " host application.\n" + << "Run with -? for options\n\n"; + + if( m_config->rngSeed() != 0 ) + stream << "Randomness seeded to: " << m_config->rngSeed() << "\n\n"; + + currentTestRunInfo.used = true; + } + void lazyPrintGroupInfo() { + if( !currentGroupInfo->name.empty() && currentGroupInfo->groupsCounts > 1 ) { + printClosedHeader( "Group: " + currentGroupInfo->name ); + currentGroupInfo.used = true; + } + } + void printTestCaseAndSectionHeader() { + assert( !m_sectionStack.empty() ); + printOpenHeader( currentTestCaseInfo->name ); + + if( m_sectionStack.size() > 1 ) { + Colour colourGuard( Colour::Headers ); + + std::vector::const_iterator + it = m_sectionStack.begin()+1, // Skip first section (test case) + itEnd = m_sectionStack.end(); + for( ; it != itEnd; ++it ) + printHeaderString( it->name, 2 ); + } + + SourceLineInfo lineInfo = m_sectionStack.front().lineInfo; + + if( !lineInfo.empty() ){ + stream << getLineOfChars<'-'>() << "\n"; + Colour colourGuard( Colour::FileName ); + stream << lineInfo << "\n"; + } + stream << getLineOfChars<'.'>() << "\n" << std::endl; + } + + void printClosedHeader( std::string const& _name ) { + printOpenHeader( _name ); + stream << getLineOfChars<'.'>() << "\n"; + } + void printOpenHeader( std::string const& _name ) { + stream << getLineOfChars<'-'>() << "\n"; + { + Colour colourGuard( Colour::Headers ); + printHeaderString( _name ); + } + } + + // if string has a : in first line will set indent to follow it on + // subsequent lines + void printHeaderString( std::string const& _string, std::size_t indent = 0 ) { + std::size_t i = _string.find( ": " ); + if( i != std::string::npos ) + i+=2; + else + i = 0; + stream << Text( _string, TextAttributes() + .setIndent( indent+i) + .setInitialIndent( indent ) ) << "\n"; + } + + struct SummaryColumn { + + SummaryColumn( std::string const& _label, Colour::Code _colour ) + : label( _label ), + colour( _colour ) + {} + SummaryColumn addRow( std::size_t count ) { + std::ostringstream oss; + oss << count; + std::string row = oss.str(); + for( std::vector::iterator it = rows.begin(); it != rows.end(); ++it ) { + while( it->size() < row.size() ) + *it = " " + *it; + while( it->size() > row.size() ) + row = " " + row; + } + rows.push_back( row ); + return *this; + } + + std::string label; + Colour::Code colour; + std::vector rows; + + }; + + void printTotals( Totals const& totals ) { + if( totals.testCases.total() == 0 ) { + stream << Colour( Colour::Warning ) << "No tests ran\n"; + } + else if( totals.assertions.total() > 0 && totals.testCases.allPassed() ) { + stream << Colour( Colour::ResultSuccess ) << "All tests passed"; + stream << " (" + << pluralise( totals.assertions.passed, "assertion" ) << " in " + << pluralise( totals.testCases.passed, "test case" ) << ")" + << "\n"; + } + else { + + std::vector columns; + columns.push_back( SummaryColumn( "", Colour::None ) + .addRow( totals.testCases.total() ) + .addRow( totals.assertions.total() ) ); + columns.push_back( SummaryColumn( "passed", Colour::Success ) + .addRow( totals.testCases.passed ) + .addRow( totals.assertions.passed ) ); + columns.push_back( SummaryColumn( "failed", Colour::ResultError ) + .addRow( totals.testCases.failed ) + .addRow( totals.assertions.failed ) ); + columns.push_back( SummaryColumn( "failed as expected", Colour::ResultExpectedFailure ) + .addRow( totals.testCases.failedButOk ) + .addRow( totals.assertions.failedButOk ) ); + + printSummaryRow( "test cases", columns, 0 ); + printSummaryRow( "assertions", columns, 1 ); + } + } + void printSummaryRow( std::string const& label, std::vector const& cols, std::size_t row ) { + for( std::vector::const_iterator it = cols.begin(); it != cols.end(); ++it ) { + std::string value = it->rows[row]; + if( it->label.empty() ) { + stream << label << ": "; + if( value != "0" ) + stream << value; + else + stream << Colour( Colour::Warning ) << "- none -"; + } + else if( value != "0" ) { + stream << Colour( Colour::LightGrey ) << " | "; + stream << Colour( it->colour ) + << value << " " << it->label; + } + } + stream << "\n"; + } + + static std::size_t makeRatio( std::size_t number, std::size_t total ) { + std::size_t ratio = total > 0 ? CATCH_CONFIG_CONSOLE_WIDTH * number/ total : 0; + return ( ratio == 0 && number > 0 ) ? 1 : ratio; + } + static std::size_t& findMax( std::size_t& i, std::size_t& j, std::size_t& k ) { + if( i > j && i > k ) + return i; + else if( j > k ) + return j; + else + return k; + } + + void printTotalsDivider( Totals const& totals ) { + if( totals.testCases.total() > 0 ) { + std::size_t failedRatio = makeRatio( totals.testCases.failed, totals.testCases.total() ); + std::size_t failedButOkRatio = makeRatio( totals.testCases.failedButOk, totals.testCases.total() ); + std::size_t passedRatio = makeRatio( totals.testCases.passed, totals.testCases.total() ); + while( failedRatio + failedButOkRatio + passedRatio < CATCH_CONFIG_CONSOLE_WIDTH-1 ) + findMax( failedRatio, failedButOkRatio, passedRatio )++; + while( failedRatio + failedButOkRatio + passedRatio > CATCH_CONFIG_CONSOLE_WIDTH-1 ) + findMax( failedRatio, failedButOkRatio, passedRatio )--; + + stream << Colour( Colour::Error ) << std::string( failedRatio, '=' ); + stream << Colour( Colour::ResultExpectedFailure ) << std::string( failedButOkRatio, '=' ); + if( totals.testCases.allPassed() ) + stream << Colour( Colour::ResultSuccess ) << std::string( passedRatio, '=' ); + else + stream << Colour( Colour::Success ) << std::string( passedRatio, '=' ); + } + else { + stream << Colour( Colour::Warning ) << std::string( CATCH_CONFIG_CONSOLE_WIDTH-1, '=' ); + } + stream << "\n"; + } + void printSummaryDivider() { + stream << getLineOfChars<'-'>() << "\n"; + } + + private: + bool m_headerPrinted; + }; + + INTERNAL_CATCH_REGISTER_REPORTER( "console", ConsoleReporter ) + +} // end namespace Catch + +// #included from: ../reporters/catch_reporter_compact.hpp +#define TWOBLUECUBES_CATCH_REPORTER_COMPACT_HPP_INCLUDED + +namespace Catch { + + struct CompactReporter : StreamingReporterBase { + + CompactReporter( ReporterConfig const& _config ) + : StreamingReporterBase( _config ) + {} + + virtual ~CompactReporter(); + + static std::string getDescription() { + return "Reports test results on a single line, suitable for IDEs"; + } + + virtual ReporterPreferences getPreferences() const { + ReporterPreferences prefs; + prefs.shouldRedirectStdOut = false; + return prefs; + } + + virtual void noMatchingTestCases( std::string const& spec ) { + stream << "No test cases matched '" << spec << "'" << std::endl; + } + + virtual void assertionStarting( AssertionInfo const& ) { + } + + virtual bool assertionEnded( AssertionStats const& _assertionStats ) { + AssertionResult const& result = _assertionStats.assertionResult; + + bool printInfoMessages = true; + + // Drop out if result was successful and we're not printing those + if( !m_config->includeSuccessfulResults() && result.isOk() ) { + if( result.getResultType() != ResultWas::Warning ) + return false; + printInfoMessages = false; + } + + AssertionPrinter printer( stream, _assertionStats, printInfoMessages ); + printer.print(); + + stream << std::endl; + return true; + } + + virtual void testRunEnded( TestRunStats const& _testRunStats ) { + printTotals( _testRunStats.totals ); + stream << "\n" << std::endl; + StreamingReporterBase::testRunEnded( _testRunStats ); + } + + private: + class AssertionPrinter { + void operator= ( AssertionPrinter const& ); + public: + AssertionPrinter( std::ostream& _stream, AssertionStats const& _stats, bool _printInfoMessages ) + : stream( _stream ) + , stats( _stats ) + , result( _stats.assertionResult ) + , messages( _stats.infoMessages ) + , itMessage( _stats.infoMessages.begin() ) + , printInfoMessages( _printInfoMessages ) + {} + + void print() { + printSourceInfo(); + + itMessage = messages.begin(); + + switch( result.getResultType() ) { + case ResultWas::Ok: + printResultType( Colour::ResultSuccess, passedString() ); + printOriginalExpression(); + printReconstructedExpression(); + if ( ! result.hasExpression() ) + printRemainingMessages( Colour::None ); + else + printRemainingMessages(); + break; + case ResultWas::ExpressionFailed: + if( result.isOk() ) + printResultType( Colour::ResultSuccess, failedString() + std::string( " - but was ok" ) ); + else + printResultType( Colour::Error, failedString() ); + printOriginalExpression(); + printReconstructedExpression(); + printRemainingMessages(); + break; + case ResultWas::ThrewException: + printResultType( Colour::Error, failedString() ); + printIssue( "unexpected exception with message:" ); + printMessage(); + printExpressionWas(); + printRemainingMessages(); + break; + case ResultWas::FatalErrorCondition: + printResultType( Colour::Error, failedString() ); + printIssue( "fatal error condition with message:" ); + printMessage(); + printExpressionWas(); + printRemainingMessages(); + break; + case ResultWas::DidntThrowException: + printResultType( Colour::Error, failedString() ); + printIssue( "expected exception, got none" ); + printExpressionWas(); + printRemainingMessages(); + break; + case ResultWas::Info: + printResultType( Colour::None, "info" ); + printMessage(); + printRemainingMessages(); + break; + case ResultWas::Warning: + printResultType( Colour::None, "warning" ); + printMessage(); + printRemainingMessages(); + break; + case ResultWas::ExplicitFailure: + printResultType( Colour::Error, failedString() ); + printIssue( "explicitly" ); + printRemainingMessages( Colour::None ); + break; + // These cases are here to prevent compiler warnings + case ResultWas::Unknown: + case ResultWas::FailureBit: + case ResultWas::Exception: + printResultType( Colour::Error, "** internal error **" ); + break; + } + } + + private: + // Colour::LightGrey + + static Colour::Code dimColour() { return Colour::FileName; } + +#ifdef CATCH_PLATFORM_MAC + static const char* failedString() { return "FAILED"; } + static const char* passedString() { return "PASSED"; } +#else + static const char* failedString() { return "failed"; } + static const char* passedString() { return "passed"; } +#endif + + void printSourceInfo() const { + Colour colourGuard( Colour::FileName ); + stream << result.getSourceInfo() << ":"; + } + + void printResultType( Colour::Code colour, std::string passOrFail ) const { + if( !passOrFail.empty() ) { + { + Colour colourGuard( colour ); + stream << " " << passOrFail; + } + stream << ":"; + } + } + + void printIssue( std::string issue ) const { + stream << " " << issue; + } + + void printExpressionWas() { + if( result.hasExpression() ) { + stream << ";"; + { + Colour colour( dimColour() ); + stream << " expression was:"; + } + printOriginalExpression(); + } + } + + void printOriginalExpression() const { + if( result.hasExpression() ) { + stream << " " << result.getExpression(); + } + } + + void printReconstructedExpression() const { + if( result.hasExpandedExpression() ) { + { + Colour colour( dimColour() ); + stream << " for: "; + } + stream << result.getExpandedExpression(); + } + } + + void printMessage() { + if ( itMessage != messages.end() ) { + stream << " '" << itMessage->message << "'"; + ++itMessage; + } + } + + void printRemainingMessages( Colour::Code colour = dimColour() ) { + if ( itMessage == messages.end() ) + return; + + // using messages.end() directly yields compilation error: + std::vector::const_iterator itEnd = messages.end(); + const std::size_t N = static_cast( std::distance( itMessage, itEnd ) ); + + { + Colour colourGuard( colour ); + stream << " with " << pluralise( N, "message" ) << ":"; + } + + for(; itMessage != itEnd; ) { + // If this assertion is a warning ignore any INFO messages + if( printInfoMessages || itMessage->type != ResultWas::Info ) { + stream << " '" << itMessage->message << "'"; + if ( ++itMessage != itEnd ) { + Colour colourGuard( dimColour() ); + stream << " and"; + } + } + } + } + + private: + std::ostream& stream; + AssertionStats const& stats; + AssertionResult const& result; + std::vector messages; + std::vector::const_iterator itMessage; + bool printInfoMessages; + }; + + // Colour, message variants: + // - white: No tests ran. + // - red: Failed [both/all] N test cases, failed [both/all] M assertions. + // - white: Passed [both/all] N test cases (no assertions). + // - red: Failed N tests cases, failed M assertions. + // - green: Passed [both/all] N tests cases with M assertions. + + std::string bothOrAll( std::size_t count ) const { + return count == 1 ? "" : count == 2 ? "both " : "all " ; + } + + void printTotals( const Totals& totals ) const { + if( totals.testCases.total() == 0 ) { + stream << "No tests ran."; + } + else if( totals.testCases.failed == totals.testCases.total() ) { + Colour colour( Colour::ResultError ); + const std::string qualify_assertions_failed = + totals.assertions.failed == totals.assertions.total() ? + bothOrAll( totals.assertions.failed ) : ""; + stream << + "Failed " << bothOrAll( totals.testCases.failed ) + << pluralise( totals.testCases.failed, "test case" ) << ", " + "failed " << qualify_assertions_failed << + pluralise( totals.assertions.failed, "assertion" ) << "."; + } + else if( totals.assertions.total() == 0 ) { + stream << + "Passed " << bothOrAll( totals.testCases.total() ) + << pluralise( totals.testCases.total(), "test case" ) + << " (no assertions)."; + } + else if( totals.assertions.failed ) { + Colour colour( Colour::ResultError ); + stream << + "Failed " << pluralise( totals.testCases.failed, "test case" ) << ", " + "failed " << pluralise( totals.assertions.failed, "assertion" ) << "."; + } + else { + Colour colour( Colour::ResultSuccess ); + stream << + "Passed " << bothOrAll( totals.testCases.passed ) + << pluralise( totals.testCases.passed, "test case" ) << + " with " << pluralise( totals.assertions.passed, "assertion" ) << "."; + } + } + }; + + INTERNAL_CATCH_REGISTER_REPORTER( "compact", CompactReporter ) + +} // end namespace Catch + +namespace Catch { + // These are all here to avoid warnings about not having any out of line + // virtual methods + NonCopyable::~NonCopyable() {} + IShared::~IShared() {} + IStream::~IStream() CATCH_NOEXCEPT {} + FileStream::~FileStream() CATCH_NOEXCEPT {} + CoutStream::~CoutStream() CATCH_NOEXCEPT {} + DebugOutStream::~DebugOutStream() CATCH_NOEXCEPT {} + StreamBufBase::~StreamBufBase() CATCH_NOEXCEPT {} + IContext::~IContext() {} + IResultCapture::~IResultCapture() {} + ITestCase::~ITestCase() {} + ITestCaseRegistry::~ITestCaseRegistry() {} + IRegistryHub::~IRegistryHub() {} + IMutableRegistryHub::~IMutableRegistryHub() {} + IExceptionTranslator::~IExceptionTranslator() {} + IExceptionTranslatorRegistry::~IExceptionTranslatorRegistry() {} + IReporter::~IReporter() {} + IReporterFactory::~IReporterFactory() {} + IReporterRegistry::~IReporterRegistry() {} + IStreamingReporter::~IStreamingReporter() {} + AssertionStats::~AssertionStats() {} + SectionStats::~SectionStats() {} + TestCaseStats::~TestCaseStats() {} + TestGroupStats::~TestGroupStats() {} + TestRunStats::~TestRunStats() {} + CumulativeReporterBase::SectionNode::~SectionNode() {} + CumulativeReporterBase::~CumulativeReporterBase() {} + + StreamingReporterBase::~StreamingReporterBase() {} + ConsoleReporter::~ConsoleReporter() {} + CompactReporter::~CompactReporter() {} + IRunner::~IRunner() {} + IMutableContext::~IMutableContext() {} + IConfig::~IConfig() {} + XmlReporter::~XmlReporter() {} + JunitReporter::~JunitReporter() {} + TestRegistry::~TestRegistry() {} + FreeFunctionTestCase::~FreeFunctionTestCase() {} + IGeneratorInfo::~IGeneratorInfo() {} + IGeneratorsForTest::~IGeneratorsForTest() {} + WildcardPattern::~WildcardPattern() {} + TestSpec::Pattern::~Pattern() {} + TestSpec::NamePattern::~NamePattern() {} + TestSpec::TagPattern::~TagPattern() {} + TestSpec::ExcludedPattern::~ExcludedPattern() {} + + Matchers::Impl::StdString::Equals::~Equals() {} + Matchers::Impl::StdString::Contains::~Contains() {} + Matchers::Impl::StdString::StartsWith::~StartsWith() {} + Matchers::Impl::StdString::EndsWith::~EndsWith() {} + + void Config::dummy() {} + + namespace TestCaseTracking { + ITracker::~ITracker() {} + TrackerBase::~TrackerBase() {} + SectionTracker::~SectionTracker() {} + IndexTracker::~IndexTracker() {} + } +} + +#ifdef __clang__ +#pragma clang diagnostic pop +#endif + +#endif + +#ifdef CATCH_CONFIG_MAIN +// #included from: internal/catch_default_main.hpp +#define TWOBLUECUBES_CATCH_DEFAULT_MAIN_HPP_INCLUDED + +#ifndef __OBJC__ + +// Standard C/C++ main entry point +int main (int argc, char * argv[]) { + return Catch::Session().run( argc, argv ); +} + +#else // __OBJC__ + +// Objective-C entry point +int main (int argc, char * const argv[]) { +#if !CATCH_ARC_ENABLED + NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init]; +#endif + + Catch::registerTestMethods(); + int result = Catch::Session().run( argc, (char* const*)argv ); + +#if !CATCH_ARC_ENABLED + [pool drain]; +#endif + + return result; +} + +#endif // __OBJC__ + +#endif + +#ifdef CLARA_CONFIG_MAIN_NOT_DEFINED +# undef CLARA_CONFIG_MAIN +#endif + +////// + +// If this config identifier is defined then all CATCH macros are prefixed with CATCH_ +#ifdef CATCH_CONFIG_PREFIX_ALL + +#define CATCH_REQUIRE( expr ) INTERNAL_CATCH_TEST( expr, Catch::ResultDisposition::Normal, "CATCH_REQUIRE" ) +#define CATCH_REQUIRE_FALSE( expr ) INTERNAL_CATCH_TEST( expr, Catch::ResultDisposition::Normal | Catch::ResultDisposition::FalseTest, "CATCH_REQUIRE_FALSE" ) + +#define CATCH_REQUIRE_THROWS( expr ) INTERNAL_CATCH_THROWS( expr, Catch::ResultDisposition::Normal, "", "CATCH_REQUIRE_THROWS" ) +#define CATCH_REQUIRE_THROWS_AS( expr, exceptionType ) INTERNAL_CATCH_THROWS_AS( expr, exceptionType, Catch::ResultDisposition::Normal, "CATCH_REQUIRE_THROWS_AS" ) +#define CATCH_REQUIRE_THROWS_WITH( expr, matcher ) INTERNAL_CATCH_THROWS( expr, Catch::ResultDisposition::Normal, matcher, "CATCH_REQUIRE_THROWS_WITH" ) +#define CATCH_REQUIRE_NOTHROW( expr ) INTERNAL_CATCH_NO_THROW( expr, Catch::ResultDisposition::Normal, "CATCH_REQUIRE_NOTHROW" ) + +#define CATCH_CHECK( expr ) INTERNAL_CATCH_TEST( expr, Catch::ResultDisposition::ContinueOnFailure, "CATCH_CHECK" ) +#define CATCH_CHECK_FALSE( expr ) INTERNAL_CATCH_TEST( expr, Catch::ResultDisposition::ContinueOnFailure | Catch::ResultDisposition::FalseTest, "CATCH_CHECK_FALSE" ) +#define CATCH_CHECKED_IF( expr ) INTERNAL_CATCH_IF( expr, Catch::ResultDisposition::ContinueOnFailure, "CATCH_CHECKED_IF" ) +#define CATCH_CHECKED_ELSE( expr ) INTERNAL_CATCH_ELSE( expr, Catch::ResultDisposition::ContinueOnFailure, "CATCH_CHECKED_ELSE" ) +#define CATCH_CHECK_NOFAIL( expr ) INTERNAL_CATCH_TEST( expr, Catch::ResultDisposition::ContinueOnFailure | Catch::ResultDisposition::SuppressFail, "CATCH_CHECK_NOFAIL" ) + +#define CATCH_CHECK_THROWS( expr ) INTERNAL_CATCH_THROWS( expr, Catch::ResultDisposition::ContinueOnFailure, "CATCH_CHECK_THROWS" ) +#define CATCH_CHECK_THROWS_AS( expr, exceptionType ) INTERNAL_CATCH_THROWS_AS( expr, exceptionType, Catch::ResultDisposition::ContinueOnFailure, "CATCH_CHECK_THROWS_AS" ) +#define CATCH_CHECK_THROWS_WITH( expr, matcher ) INTERNAL_CATCH_THROWS( expr, Catch::ResultDisposition::ContinueOnFailure, matcher, "CATCH_CHECK_THROWS_WITH" ) +#define CATCH_CHECK_NOTHROW( expr ) INTERNAL_CATCH_NO_THROW( expr, Catch::ResultDisposition::ContinueOnFailure, "CATCH_CHECK_NOTHROW" ) + +#define CHECK_THAT( arg, matcher ) INTERNAL_CHECK_THAT( arg, matcher, Catch::ResultDisposition::ContinueOnFailure, "CATCH_CHECK_THAT" ) +#define CATCH_REQUIRE_THAT( arg, matcher ) INTERNAL_CHECK_THAT( arg, matcher, Catch::ResultDisposition::Normal, "CATCH_REQUIRE_THAT" ) + +#define CATCH_INFO( msg ) INTERNAL_CATCH_INFO( msg, "CATCH_INFO" ) +#define CATCH_WARN( msg ) INTERNAL_CATCH_MSG( Catch::ResultWas::Warning, Catch::ResultDisposition::ContinueOnFailure, "CATCH_WARN", msg ) +#define CATCH_SCOPED_INFO( msg ) INTERNAL_CATCH_INFO( msg, "CATCH_INFO" ) +#define CATCH_CAPTURE( msg ) INTERNAL_CATCH_INFO( #msg " := " << msg, "CATCH_CAPTURE" ) +#define CATCH_SCOPED_CAPTURE( msg ) INTERNAL_CATCH_INFO( #msg " := " << msg, "CATCH_CAPTURE" ) + +#ifdef CATCH_CONFIG_VARIADIC_MACROS + #define CATCH_TEST_CASE( ... ) INTERNAL_CATCH_TESTCASE( __VA_ARGS__ ) + #define CATCH_TEST_CASE_METHOD( className, ... ) INTERNAL_CATCH_TEST_CASE_METHOD( className, __VA_ARGS__ ) + #define CATCH_METHOD_AS_TEST_CASE( method, ... ) INTERNAL_CATCH_METHOD_AS_TEST_CASE( method, __VA_ARGS__ ) + #define CATCH_REGISTER_TEST_CASE( Function, ... ) INTERNAL_CATCH_REGISTER_TESTCASE( Function, __VA_ARGS__ ) + #define CATCH_SECTION( ... ) INTERNAL_CATCH_SECTION( __VA_ARGS__ ) + #define CATCH_FAIL( ... ) INTERNAL_CATCH_MSG( Catch::ResultWas::ExplicitFailure, Catch::ResultDisposition::Normal, "CATCH_FAIL", __VA_ARGS__ ) + #define CATCH_SUCCEED( ... ) INTERNAL_CATCH_MSG( Catch::ResultWas::Ok, Catch::ResultDisposition::ContinueOnFailure, "CATCH_SUCCEED", __VA_ARGS__ ) +#else + #define CATCH_TEST_CASE( name, description ) INTERNAL_CATCH_TESTCASE( name, description ) + #define CATCH_TEST_CASE_METHOD( className, name, description ) INTERNAL_CATCH_TEST_CASE_METHOD( className, name, description ) + #define CATCH_METHOD_AS_TEST_CASE( method, name, description ) INTERNAL_CATCH_METHOD_AS_TEST_CASE( method, name, description ) + #define CATCH_REGISTER_TEST_CASE( function, name, description ) INTERNAL_CATCH_REGISTER_TESTCASE( function, name, description ) + #define CATCH_SECTION( name, description ) INTERNAL_CATCH_SECTION( name, description ) + #define CATCH_FAIL( msg ) INTERNAL_CATCH_MSG( Catch::ResultWas::ExplicitFailure, Catch::ResultDisposition::Normal, "CATCH_FAIL", msg ) + #define CATCH_SUCCEED( msg ) INTERNAL_CATCH_MSG( Catch::ResultWas::Ok, Catch::ResultDisposition::ContinueOnFailure, "CATCH_SUCCEED", msg ) +#endif +#define CATCH_ANON_TEST_CASE() INTERNAL_CATCH_TESTCASE( "", "" ) + +#define CATCH_REGISTER_REPORTER( name, reporterType ) INTERNAL_CATCH_REGISTER_REPORTER( name, reporterType ) +#define CATCH_REGISTER_LEGACY_REPORTER( name, reporterType ) INTERNAL_CATCH_REGISTER_LEGACY_REPORTER( name, reporterType ) + +#define CATCH_GENERATE( expr) INTERNAL_CATCH_GENERATE( expr ) + +// "BDD-style" convenience wrappers +#ifdef CATCH_CONFIG_VARIADIC_MACROS +#define CATCH_SCENARIO( ... ) CATCH_TEST_CASE( "Scenario: " __VA_ARGS__ ) +#define CATCH_SCENARIO_METHOD( className, ... ) INTERNAL_CATCH_TEST_CASE_METHOD( className, "Scenario: " __VA_ARGS__ ) +#else +#define CATCH_SCENARIO( name, tags ) CATCH_TEST_CASE( "Scenario: " name, tags ) +#define CATCH_SCENARIO_METHOD( className, name, tags ) INTERNAL_CATCH_TEST_CASE_METHOD( className, "Scenario: " name, tags ) +#endif +#define CATCH_GIVEN( desc ) CATCH_SECTION( std::string( "Given: ") + desc, "" ) +#define CATCH_WHEN( desc ) CATCH_SECTION( std::string( " When: ") + desc, "" ) +#define CATCH_AND_WHEN( desc ) CATCH_SECTION( std::string( " And: ") + desc, "" ) +#define CATCH_THEN( desc ) CATCH_SECTION( std::string( " Then: ") + desc, "" ) +#define CATCH_AND_THEN( desc ) CATCH_SECTION( std::string( " And: ") + desc, "" ) + +// If CATCH_CONFIG_PREFIX_ALL is not defined then the CATCH_ prefix is not required +#else + +#define REQUIRE( expr ) INTERNAL_CATCH_TEST( expr, Catch::ResultDisposition::Normal, "REQUIRE" ) +#define REQUIRE_FALSE( expr ) INTERNAL_CATCH_TEST( expr, Catch::ResultDisposition::Normal | Catch::ResultDisposition::FalseTest, "REQUIRE_FALSE" ) + +#define REQUIRE_THROWS( expr ) INTERNAL_CATCH_THROWS( expr, Catch::ResultDisposition::Normal, "", "REQUIRE_THROWS" ) +#define REQUIRE_THROWS_AS( expr, exceptionType ) INTERNAL_CATCH_THROWS_AS( expr, exceptionType, Catch::ResultDisposition::Normal, "REQUIRE_THROWS_AS" ) +#define REQUIRE_THROWS_WITH( expr, matcher ) INTERNAL_CATCH_THROWS( expr, Catch::ResultDisposition::Normal, matcher, "REQUIRE_THROWS_WITH" ) +#define REQUIRE_NOTHROW( expr ) INTERNAL_CATCH_NO_THROW( expr, Catch::ResultDisposition::Normal, "REQUIRE_NOTHROW" ) + +#define CHECK( expr ) INTERNAL_CATCH_TEST( expr, Catch::ResultDisposition::ContinueOnFailure, "CHECK" ) +#define CHECK_FALSE( expr ) INTERNAL_CATCH_TEST( expr, Catch::ResultDisposition::ContinueOnFailure | Catch::ResultDisposition::FalseTest, "CHECK_FALSE" ) +#define CHECKED_IF( expr ) INTERNAL_CATCH_IF( expr, Catch::ResultDisposition::ContinueOnFailure, "CHECKED_IF" ) +#define CHECKED_ELSE( expr ) INTERNAL_CATCH_ELSE( expr, Catch::ResultDisposition::ContinueOnFailure, "CHECKED_ELSE" ) +#define CHECK_NOFAIL( expr ) INTERNAL_CATCH_TEST( expr, Catch::ResultDisposition::ContinueOnFailure | Catch::ResultDisposition::SuppressFail, "CHECK_NOFAIL" ) + +#define CHECK_THROWS( expr ) INTERNAL_CATCH_THROWS( expr, Catch::ResultDisposition::ContinueOnFailure, "", "CHECK_THROWS" ) +#define CHECK_THROWS_AS( expr, exceptionType ) INTERNAL_CATCH_THROWS_AS( expr, exceptionType, Catch::ResultDisposition::ContinueOnFailure, "CHECK_THROWS_AS" ) +#define CHECK_THROWS_WITH( expr, matcher ) INTERNAL_CATCH_THROWS( expr, Catch::ResultDisposition::ContinueOnFailure, matcher, "CHECK_THROWS_WITH" ) +#define CHECK_NOTHROW( expr ) INTERNAL_CATCH_NO_THROW( expr, Catch::ResultDisposition::ContinueOnFailure, "CHECK_NOTHROW" ) + +#define CHECK_THAT( arg, matcher ) INTERNAL_CHECK_THAT( arg, matcher, Catch::ResultDisposition::ContinueOnFailure, "CHECK_THAT" ) +#define REQUIRE_THAT( arg, matcher ) INTERNAL_CHECK_THAT( arg, matcher, Catch::ResultDisposition::Normal, "REQUIRE_THAT" ) + +#define INFO( msg ) INTERNAL_CATCH_INFO( msg, "INFO" ) +#define WARN( msg ) INTERNAL_CATCH_MSG( Catch::ResultWas::Warning, Catch::ResultDisposition::ContinueOnFailure, "WARN", msg ) +#define SCOPED_INFO( msg ) INTERNAL_CATCH_INFO( msg, "INFO" ) +#define CAPTURE( msg ) INTERNAL_CATCH_INFO( #msg " := " << msg, "CAPTURE" ) +#define SCOPED_CAPTURE( msg ) INTERNAL_CATCH_INFO( #msg " := " << msg, "CAPTURE" ) + +#ifdef CATCH_CONFIG_VARIADIC_MACROS + #define TEST_CASE( ... ) INTERNAL_CATCH_TESTCASE( __VA_ARGS__ ) + #define TEST_CASE_METHOD( className, ... ) INTERNAL_CATCH_TEST_CASE_METHOD( className, __VA_ARGS__ ) + #define METHOD_AS_TEST_CASE( method, ... ) INTERNAL_CATCH_METHOD_AS_TEST_CASE( method, __VA_ARGS__ ) + #define REGISTER_TEST_CASE( Function, ... ) INTERNAL_CATCH_REGISTER_TESTCASE( Function, __VA_ARGS__ ) + #define SECTION( ... ) INTERNAL_CATCH_SECTION( __VA_ARGS__ ) + #define FAIL( ... ) INTERNAL_CATCH_MSG( Catch::ResultWas::ExplicitFailure, Catch::ResultDisposition::Normal, "FAIL", __VA_ARGS__ ) + #define SUCCEED( ... ) INTERNAL_CATCH_MSG( Catch::ResultWas::Ok, Catch::ResultDisposition::ContinueOnFailure, "SUCCEED", __VA_ARGS__ ) +#else + #define TEST_CASE( name, description ) INTERNAL_CATCH_TESTCASE( name, description ) + #define TEST_CASE_METHOD( className, name, description ) INTERNAL_CATCH_TEST_CASE_METHOD( className, name, description ) + #define METHOD_AS_TEST_CASE( method, name, description ) INTERNAL_CATCH_METHOD_AS_TEST_CASE( method, name, description ) + #define REGISTER_TEST_CASE( method, name, description ) INTERNAL_CATCH_REGISTER_TESTCASE( method, name, description ) + #define SECTION( name, description ) INTERNAL_CATCH_SECTION( name, description ) + #define FAIL( msg ) INTERNAL_CATCH_MSG( Catch::ResultWas::ExplicitFailure, Catch::ResultDisposition::Normal, "FAIL", msg ) + #define SUCCEED( msg ) INTERNAL_CATCH_MSG( Catch::ResultWas::Ok, Catch::ResultDisposition::ContinueOnFailure, "SUCCEED", msg ) +#endif +#define ANON_TEST_CASE() INTERNAL_CATCH_TESTCASE( "", "" ) + +#define REGISTER_REPORTER( name, reporterType ) INTERNAL_CATCH_REGISTER_REPORTER( name, reporterType ) +#define REGISTER_LEGACY_REPORTER( name, reporterType ) INTERNAL_CATCH_REGISTER_LEGACY_REPORTER( name, reporterType ) + +#define GENERATE( expr) INTERNAL_CATCH_GENERATE( expr ) + +#endif + +#define CATCH_TRANSLATE_EXCEPTION( signature ) INTERNAL_CATCH_TRANSLATE_EXCEPTION( signature ) + +// "BDD-style" convenience wrappers +#ifdef CATCH_CONFIG_VARIADIC_MACROS +#define SCENARIO( ... ) TEST_CASE( "Scenario: " __VA_ARGS__ ) +#define SCENARIO_METHOD( className, ... ) INTERNAL_CATCH_TEST_CASE_METHOD( className, "Scenario: " __VA_ARGS__ ) +#else +#define SCENARIO( name, tags ) TEST_CASE( "Scenario: " name, tags ) +#define SCENARIO_METHOD( className, name, tags ) INTERNAL_CATCH_TEST_CASE_METHOD( className, "Scenario: " name, tags ) +#endif +#define GIVEN( desc ) SECTION( std::string(" Given: ") + desc, "" ) +#define WHEN( desc ) SECTION( std::string(" When: ") + desc, "" ) +#define AND_WHEN( desc ) SECTION( std::string("And when: ") + desc, "" ) +#define THEN( desc ) SECTION( std::string(" Then: ") + desc, "" ) +#define AND_THEN( desc ) SECTION( std::string(" And: ") + desc, "" ) + +using Catch::Detail::Approx; + +#endif // TWOBLUECUBES_SINGLE_INCLUDE_CATCH_HPP_INCLUDED + diff --git a/components/nvs_flash/test/crc.cpp b/components/nvs_flash/test/crc.cpp new file mode 100644 index 0000000000..288b58a323 --- /dev/null +++ b/components/nvs_flash/test/crc.cpp @@ -0,0 +1,38 @@ +// Copyright 2015-2016 Espressif Systems (Shanghai) PTE LTD +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at + +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +#include +#include + +extern "C" unsigned long crc32_le(unsigned long crc_in, unsigned char const* data, unsigned int length) +{ + uint32_t i; + bool bit; + uint8_t c; + uint32_t crc = (uint32_t) crc_in; + + while (length--) { + c = *data++; + for (i = 0x80; i > 0; i >>= 1) { + bit = crc & 0x80000000; + if (c & i) { + bit = !bit; + } + crc <<= 1; + if (bit) { + crc ^= 0x04c11db7; + } + } + } + return crc; +} diff --git a/components/nvs_flash/test/crc.h b/components/nvs_flash/test/crc.h new file mode 100644 index 0000000000..c752b30303 --- /dev/null +++ b/components/nvs_flash/test/crc.h @@ -0,0 +1,30 @@ +// Copyright 2015-2016 Espressif Systems (Shanghai) PTE LTD +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at + +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +#ifndef crc_h +#define crc_h + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +uint32_t crc32_le(uint32_t crc, const uint8_t* buf, size_t len); + +#ifdef __cplusplus +} +#endif + + +#endif /* crc_h */ diff --git a/components/nvs_flash/test/main.cpp b/components/nvs_flash/test/main.cpp new file mode 100644 index 0000000000..0c7c351f43 --- /dev/null +++ b/components/nvs_flash/test/main.cpp @@ -0,0 +1,2 @@ +#define CATCH_CONFIG_MAIN +#include "catch.hpp" diff --git a/components/nvs_flash/test/spi_flash_emulation.cpp b/components/nvs_flash/test/spi_flash_emulation.cpp new file mode 100644 index 0000000000..5185bd34cb --- /dev/null +++ b/components/nvs_flash/test/spi_flash_emulation.cpp @@ -0,0 +1,97 @@ +// Copyright 2015-2016 Espressif Systems (Shanghai) PTE LTD +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at + +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +#include "esp_spi_flash.h" +#include "spi_flash_emulation.h" + + +static SpiFlashEmulator* s_emulator = nullptr; + +void spi_flash_emulator_set(SpiFlashEmulator* e) +{ + s_emulator = e; +} + +esp_err_t spi_flash_erase_sector(uint16_t sec) +{ + if (!s_emulator) { + return ESP_ERR_FLASH_OP_TIMEOUT; + } + + if (!s_emulator->erase(sec)) { + return ESP_ERR_FLASH_OP_FAIL; + } + + return ESP_OK; +} + +esp_err_t spi_flash_write(uint32_t des_addr, const uint32_t *src_addr, uint32_t size) +{ + if (!s_emulator) { + return ESP_ERR_FLASH_OP_TIMEOUT; + } + + if (!s_emulator->write(des_addr, src_addr, size)) { + return ESP_ERR_FLASH_OP_FAIL; + } + + return ESP_OK; +} + +esp_err_t spi_flash_read(uint32_t src_addr, uint32_t *des_addr, uint32_t size) +{ + if (!s_emulator) { + return ESP_ERR_FLASH_OP_TIMEOUT; + } + + if (!s_emulator->read(des_addr, src_addr, size)) { + return ESP_ERR_FLASH_OP_FAIL; + } + + return ESP_OK; +} + +// timing data for ESP8266, 160MHz CPU frequency, 80MHz flash requency +// all values in microseconds +// values are for block sizes starting at 4 bytes and going up to 4096 bytes +static size_t readTimes[] = {7, 5, 6, 7, 11, 18, 32, 60, 118, 231, 459}; +static size_t writeTimes[] = {19, 23, 35, 57, 106, 205, 417, 814, 1622, 3200, 6367}; +static size_t blockEraseTime = 37142; + + +static size_t timeInterp(uint32_t bytes, size_t* lut) +{ + int lz = __builtin_clz(bytes / 4); + int log_size = 32 - lz; + size_t x2 = 1 << (log_size + 2); + size_t y2 = lut[log_size]; + size_t x1 = 1 << (log_size + 1); + size_t y1 = lut[log_size - 1]; + return (bytes - x1) * (y2 - y1) / (x2 - x1) + y1; +} + +size_t SpiFlashEmulator::getReadOpTime(uint32_t bytes) +{ + return timeInterp(bytes, readTimes); +} + +size_t SpiFlashEmulator::getWriteOpTime(uint32_t bytes) +{ + return timeInterp(bytes, writeTimes); +} + +size_t SpiFlashEmulator::getEraseOpTime() +{ + return blockEraseTime; +} + diff --git a/components/nvs_flash/test/spi_flash_emulation.h b/components/nvs_flash/test/spi_flash_emulation.h new file mode 100644 index 0000000000..a321c61b37 --- /dev/null +++ b/components/nvs_flash/test/spi_flash_emulation.h @@ -0,0 +1,198 @@ +// Copyright 2015-2016 Espressif Systems (Shanghai) PTE LTD +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at + +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +#ifndef spi_flash_emulation_h +#define spi_flash_emulation_h + +#include +#include +#include +#include +#include "esp_spi_flash.h" +#include "catch.hpp" + +using std::copy; +using std::begin; +using std::end; +using std::fill_n; + +class SpiFlashEmulator; + +void spi_flash_emulator_set(SpiFlashEmulator*); + +class SpiFlashEmulator +{ +public: + SpiFlashEmulator(size_t sectorCount) : mUpperSectorBound(sectorCount) + { + mData.resize(sectorCount * SPI_FLASH_SEC_SIZE / 4, 0xffffffff); + spi_flash_emulator_set(this); + } + + ~SpiFlashEmulator() + { + spi_flash_emulator_set(nullptr); + } + + bool read(uint32_t* dest, uint32_t srcAddr, size_t size) const + { + if (srcAddr % 4 != 0 || + size % 4 != 0 || + srcAddr + size > mData.size() * 4) { + return false; + } + + copy(begin(mData) + srcAddr / 4, begin(mData) + (srcAddr + size) / 4, dest); + + ++mReadOps; + mReadBytes += size; + mTotalTime += getReadOpTime(static_cast(size)); + return true; + } + + bool write(uint32_t dstAddr, const uint32_t* src, size_t size) + { + uint32_t sectorNumber = dstAddr/SPI_FLASH_SEC_SIZE; + if (sectorNumber < mLowerSectorBound || sectorNumber >= mUpperSectorBound) { + WARN("invalid flash operation detected: erase sector=" << sectorNumber); + return false; + } + + if (dstAddr % 4 != 0 || + size % 4 != 0 || + dstAddr + size > mData.size() * 4) { + return false; + } + + for (size_t i = 0; i < size / 4; ++i) { + uint32_t sv = src[i]; + size_t pos = dstAddr / 4 + i; + uint32_t& dv = mData[pos]; + + if (((~dv) & sv) != 0) { // are we trying to set some 0 bits to 1? + WARN("invalid flash operation detected: dst=" << dstAddr << " size=" << size << " i=" << i); + return false; + } + + dv = sv; + } + ++mWriteOps; + mWriteBytes += size; + mTotalTime += getWriteOpTime(static_cast(size)); + return true; + } + + bool erase(uint32_t sectorNumber) + { + size_t offset = sectorNumber * SPI_FLASH_SEC_SIZE / 4; + if (offset > mData.size()) { + return false; + } + + if (sectorNumber < mLowerSectorBound || sectorNumber >= mUpperSectorBound) { + WARN("invalid flash operation detected: erase sector=" << sectorNumber); + return false; + } + + std::fill_n(begin(mData) + offset, SPI_FLASH_SEC_SIZE / 4, 0xffffffff); + + ++mEraseOps; + mTotalTime += getEraseOpTime(); + return true; + } + + void randomize(uint32_t seed) + { + std::random_device rd; + std::mt19937 gen(rd()); + gen.seed(seed); + std::generate_n(mData.data(), mData.size(), gen); + } + + size_t size() const + { + return mData.size() * 4; + } + + const uint32_t* words() const + { + return mData.data(); + } + + const uint8_t* bytes() const + { + return reinterpret_cast(mData.data()); + } + + void clearStats() + { + mReadBytes = 0; + mWriteBytes = 0; + mEraseOps = 0; + mReadOps = 0; + mWriteOps = 0; + mTotalTime = 0; + } + + size_t getReadOps() const + { + return mReadOps; + } + size_t getWriteOps() const + { + return mWriteOps; + } + size_t getEraseOps() const + { + return mEraseOps; + } + size_t getReadBytes() const + { + return mReadBytes; + } + size_t getWriteBytes() const + { + return mWriteBytes; + } + size_t getTotalTime() const + { + return mTotalTime; + } + + void setBounds(uint32_t lowerSector, uint32_t upperSector) { + mLowerSectorBound = lowerSector; + mUpperSectorBound = upperSector; + } + +protected: + static size_t getReadOpTime(uint32_t bytes); + static size_t getWriteOpTime(uint32_t bytes); + static size_t getEraseOpTime(); + + + std::vector mData; + + mutable size_t mReadOps = 0; + mutable size_t mWriteOps = 0; + mutable size_t mReadBytes = 0; + mutable size_t mWriteBytes = 0; + mutable size_t mEraseOps = 0; + mutable size_t mTotalTime = 0; + size_t mLowerSectorBound = 0; + size_t mUpperSectorBound = 0; + +}; + + + +#endif /* spi_flash_emulation_h */ diff --git a/components/nvs_flash/test/test_compressed_enum_table.cpp b/components/nvs_flash/test/test_compressed_enum_table.cpp new file mode 100644 index 0000000000..225a11c271 --- /dev/null +++ b/components/nvs_flash/test/test_compressed_enum_table.cpp @@ -0,0 +1,56 @@ +// Copyright 2015-2016 Espressif Systems (Shanghai) PTE LTD +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at + +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +#include "catch.hpp" +#include "compressed_enum_table.hpp" +#include + + +TEST_CASE("test if CompressedEnumTable works as expected", "[enumtable]") +{ + + enum class TEnum1 : uint32_t { + ZERO = 0, + ONE = 1, + TWO = 2, + THREE = 3, + }; + CompressedEnumTable table; + memset(table.data(), 0xff, table.byteSize()); + for (size_t i = 0; i < table.count(); ++i) { + CHECK(table.get(i) == TEnum1::THREE); + } + + table.set(0, TEnum1::ONE); + table.set(1, TEnum1::TWO); + table.set(2, TEnum1::ZERO); + table.set(3, TEnum1::ONE); + table.set(4, TEnum1::TWO); + table.set(5, TEnum1::ZERO); + table.set(6, TEnum1::ONE); + table.set(7, TEnum1::TWO); + table.set(8, TEnum1::ZERO); + table.set(9, TEnum1::ZERO); + table.set(10, TEnum1::ONE); + table.set(11, TEnum1::TWO); +// table.set(12, ... + table.set(13, TEnum1::ZERO); + table.set(14, TEnum1::ONE); + table.set(15, TEnum1::TWO); + + // b10010011100100001001001001001001 + // h 9 3 9 0 9 2 4 9 + + CHECK(table.data()[0] == 0x93909249); + +} \ No newline at end of file diff --git a/components/nvs_flash/test/test_intrusive_list.cpp b/components/nvs_flash/test/test_intrusive_list.cpp new file mode 100644 index 0000000000..8fc7aa95de --- /dev/null +++ b/components/nvs_flash/test/test_intrusive_list.cpp @@ -0,0 +1,212 @@ +// Copyright 2015-2016 Espressif Systems (Shanghai) PTE LTD +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at + +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +#include "catch.hpp" +#include +#include +#include "intrusive_list.h" + +struct TestNode : public intrusive_list_node { + TestNode(const char* name_ = "", int num_ = 0) : num(num_) + { + strlcpy(name, name_, sizeof(name)); + } + char name[32]; + int num; +}; + +typedef intrusive_list TestList; + + +TEST_CASE("can add items to the list", "[list]") +{ + TestList list; + TestNode n1("one", 1); + TestNode n2("two", 2); + TestNode n3("three", 3); + + list.push_back(&n1); + REQUIRE(list.begin()->num == 1); + REQUIRE(list.front().num == 1); + REQUIRE(list.back().num == 1); + list.push_front(&n2); + REQUIRE(list.begin()->num == 2); + REQUIRE(list.front().num == 2); + REQUIRE(list.back().num == 1); + + list.insert(list.begin(), &n3); + REQUIRE(list.begin()->num == 3); + REQUIRE(list.front().num == 3); + REQUIRE(list.back().num == 1); + + + auto second = ++list.begin(); + REQUIRE(second->num == 2); + + second++; + REQUIRE(second->num == 1); +} + +TEST_CASE("can iterate over items", "[list]") +{ + TestList list; + + TestNode n1("one", 1); + TestNode n2("two", 2); + TestNode n3("three", 3); + + + list.push_back(&n1); + list.push_back(&n2); + list.push_back(&n3); + + int val = 1; + for (auto it = std::begin(list); it != std::end(list); ++it) { + REQUIRE(it->num == val); + ++val; + } +} + +TEST_CASE("iterator's prefix and postfix increments and decrements behave as expected", "[list]") +{ + TestList list; + + TestNode n1("one", 1); + TestNode n2("two", 2); + TestNode n3("three", 3); + + + list.push_back(&n1); + list.push_back(&n2); + list.push_back(&n3); + + auto it = std::begin(list); + REQUIRE((++it)->num == 2); + REQUIRE(it++->num == 2); + REQUIRE((--it)->num == 2); + REQUIRE(it--->num == 2); +} + +TEST_CASE("can pop_front from the list", "[list]") +{ + TestList list; + + TestNode n1("one", 1); + TestNode n2("two", 2); + TestNode n3("three", 3); + + list.push_back(&n1); + list.push_back(&n2); + list.push_back(&n3); + + list.pop_front(); + list.pop_front(); + list.pop_front(); + + REQUIRE(std::begin(list) == std::end(list)); +} + + +TEST_CASE("can erase first item in the list", "[list]") +{ + TestList list; + TestNode n1("one", 1); + TestNode n2("two", 2); + TestNode n3("three", 3); + + list.push_back(&n1); + list.push_back(&n2); + list.push_back(&n3); + + list.erase(std::begin(list)); + + REQUIRE(list.front().num == 2); + REQUIRE(list.back().num == 3); +} + + +TEST_CASE("can erase last item in the list", "[list]") +{ + TestList list; + TestNode n1("one", 1); + TestNode n2("two", 2); + TestNode n3("three", 3); + + list.push_back(&n1); + list.push_back(&n2); + list.push_back(&n3); + + list.erase(&list.back()); + + REQUIRE(list.front().num == 1); + REQUIRE(list.back().num == 2); +} + +TEST_CASE("can erase item in the middle of the list", "[list]") +{ + TestList list; + TestNode n1("one", 1); + TestNode n2("two", 2); + TestNode n3("three", 3); + + list.push_back(&n1); + list.push_back(&n2); + list.push_back(&n3); + + list.erase(++std::begin(list)); + + REQUIRE(list.front().num == 1); + REQUIRE(list.back().num == 3); +} + +TEST_CASE("can erase all items in the list", "[list]") +{ + TestList list; + TestNode n1("one", 1); + TestNode n2("two", 2); + TestNode n3("three", 3); + + list.push_back(&n1); + list.push_back(&n2); + list.push_back(&n3); + + list.erase(std::begin(list)); + list.erase(std::begin(list)); + list.erase(std::begin(list)); + REQUIRE(std::begin(list) == std::end(list)); +} + + +TEST_CASE("can erase all items in the list using clear method", "[list]") +{ + TestList list; + TestNode n1("one", 1); + TestNode n2("two", 2); + TestNode n3("three", 3); + TestNode n4("four", 4); + TestNode n5("five", 5); + TestNode n6("six", 6); + + + list.push_back(&n1); + list.push_back(&n2); + list.insert(++list.begin(), &n3); + list.insert(++list.begin(), &n4); + list.push_front(&n5); + list.insert(list.begin(), &n6); + + list.clear(); + + REQUIRE(std::begin(list) == std::end(list)); +} + diff --git a/components/nvs_flash/test/test_nvs.cpp b/components/nvs_flash/test/test_nvs.cpp new file mode 100644 index 0000000000..713513a03d --- /dev/null +++ b/components/nvs_flash/test/test_nvs.cpp @@ -0,0 +1,715 @@ +// Copyright 2015-2016 Espressif Systems (Shanghai) PTE LTD +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at + +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +#include "catch.hpp" +#include "nvs.hpp" +#include "nvs_flash.h" +#include "spi_flash_emulation.h" +#include +#include + +using namespace std; +using namespace nvs; + +stringstream s_perf; + +void dumpBytes(const uint8_t* data, size_t count) +{ + for (uint32_t i = 0; i < count; ++i) { + if (i % 32 == 0) { + printf("%08x ", i); + } + printf("%02x ", data[i]); + if ((i + 1) % 32 == 0) { + printf("\n"); + } + } +} + +TEST_CASE("crc32 behaves as expected", "[nvs]") +{ + Item item1; + item1.datatype = ItemType::I32; + item1.nsIndex = 1; + item1.crc32 = 0; + item1.reserved = 0xff; + fill_n(item1.key, sizeof(item1.key), 0xbb); + fill_n(item1.data, sizeof(item1.data), 0xaa); + + auto crc32_1 = item1.calculateCrc32(); + + Item item2 = item1; + item2.crc32 = crc32_1; + + CHECK(crc32_1 == item2.calculateCrc32()); + + item2 = item1; + item2.nsIndex = 2; + CHECK(crc32_1 != item2.calculateCrc32()); + + item2 = item1; + item2.datatype = ItemType::U32; + CHECK(crc32_1 != item2.calculateCrc32()); + + item2 = item1; + strlcpy(item2.key, "foo", Item::MAX_KEY_LENGTH); + CHECK(crc32_1 != item2.calculateCrc32()); +} + +TEST_CASE("starting with empty flash, page is in uninitialized state", "[nvs]") +{ + SpiFlashEmulator emu(1); + Page page; + CHECK(page.state() == Page::PageState::INVALID); + CHECK(page.load(0) == ESP_OK); + CHECK(page.state() == Page::PageState::UNINITIALIZED); +} + +TEST_CASE("can distinguish namespaces", "[nvs]") +{ + SpiFlashEmulator emu(1); + Page page; + CHECK(page.load(0) == ESP_OK); + int32_t val1 = 0x12345678; + CHECK(page.writeItem(1, ItemType::I32, "intval1", &val1, sizeof(val1)) == ESP_OK); + int32_t val2 = 0x23456789; + CHECK(page.writeItem(2, ItemType::I32, "intval1", &val2, sizeof(val2)) == ESP_OK); + + int32_t readVal; + CHECK(page.readItem(2, ItemType::I32, "intval1", &readVal, sizeof(readVal)) == ESP_OK); + CHECK(readVal == val2); + +} + +TEST_CASE("reading with different type causes type mismatch error", "[nvs]") +{ + SpiFlashEmulator emu(1); + Page page; + CHECK(page.load(0) == ESP_OK); + int32_t val = 0x12345678; + CHECK(page.writeItem(1, ItemType::I32, "intval1", &val, sizeof(val)) == ESP_OK); + CHECK(page.readItem(1, ItemType::U32, "intval1", &val, sizeof(val)) == ESP_ERR_NVS_TYPE_MISMATCH); +} + +TEST_CASE("when page is erased, it's state becomes UNITIALIZED", "[nvs]") +{ + SpiFlashEmulator emu(1); + Page page; + CHECK(page.load(0) == ESP_OK); + int32_t val = 0x12345678; + CHECK(page.writeItem(1, ItemType::I32, "intval1", &val, sizeof(val)) == ESP_OK); + CHECK(page.erase() == ESP_OK); + CHECK(page.state() == Page::PageState::UNINITIALIZED); +} + +TEST_CASE("when writing and erasing, used/erased counts are updated correctly", "[nvs]") +{ + SpiFlashEmulator emu(1); + Page page; + CHECK(page.load(0) == ESP_OK); + CHECK(page.getUsedEntryCount() == 0); + CHECK(page.getErasedEntryCount() == 0); + uint32_t foo1 = 0; + CHECK(page.writeItem(1, "foo1", foo1) == ESP_OK); + CHECK(page.getUsedEntryCount() == 1); + CHECK(page.writeItem(2, "foo1", foo1) == ESP_OK); + CHECK(page.getUsedEntryCount() == 2); + CHECK(page.eraseItem(2, "foo1") == ESP_OK); + CHECK(page.getUsedEntryCount() == 1); + CHECK(page.getErasedEntryCount() == 1); + for (size_t i = 0; i < Page::ENTRY_COUNT - 2; ++i) { + char name[16]; + snprintf(name, sizeof(name), "i%ld", i); + CHECK(page.writeItem(1, name, i) == ESP_OK); + } + CHECK(page.getUsedEntryCount() == Page::ENTRY_COUNT - 1); + CHECK(page.getErasedEntryCount() == 1); + for (size_t i = 0; i < Page::ENTRY_COUNT - 2; ++i) { + char name[16]; + snprintf(name, sizeof(name), "i%ld", i); + CHECK(page.eraseItem(1, itemTypeOf(), name) == ESP_OK); + } + CHECK(page.getUsedEntryCount() == 1); + CHECK(page.getErasedEntryCount() == Page::ENTRY_COUNT - 1); +} + +TEST_CASE("when page is full, adding an element fails", "[nvs]") +{ + SpiFlashEmulator emu(1); + Page page; + CHECK(page.load(0) == ESP_OK); + for (size_t i = 0; i < Page::ENTRY_COUNT; ++i) { + char name[16]; + snprintf(name, sizeof(name), "i%ld", i); + CHECK(page.writeItem(1, name, i) == ESP_OK); + } + CHECK(page.state() == Page::PageState::FULL); + CHECK(page.writeItem(1, "foo", 64UL) == ESP_ERR_NVS_PAGE_FULL); + CHECK(page.state() == Page::PageState::FULL); +} + +TEST_CASE("page maintains its seq number") +{ + SpiFlashEmulator emu(1); + { + Page page; + CHECK(page.load(0) == ESP_OK); + CHECK(page.setSeqNumber(123) == ESP_OK); + int32_t val = 42; + CHECK(page.writeItem(1, ItemType::I32, "dummy", &val, sizeof(val)) == ESP_OK); + } + { + Page page; + CHECK(page.load(0) == ESP_OK); + uint32_t seqno; + CHECK(page.getSeqNumber(seqno) == ESP_OK); + CHECK(seqno == 123); + } +} + +TEST_CASE("can write and read variable length data", "[nvs]") +{ + SpiFlashEmulator emu(1); + Page page; + CHECK(page.load(0) == ESP_OK); + const char str[] = "foobar1234foobar1234foobar1234foobar1234foobar1234foobar1234foobar1234foobar1234"; + size_t len = strlen(str); + CHECK(page.writeItem(1, "stuff1", 42) == ESP_OK); + CHECK(page.writeItem(1, "stuff2", 1) == ESP_OK); + CHECK(page.writeItem(1, ItemType::SZ, "foobaar", str, len + 1) == ESP_OK); + CHECK(page.writeItem(1, "stuff3", 2) == ESP_OK); + CHECK(page.writeItem(1, ItemType::BLOB, "baz", str, len) == ESP_OK); + CHECK(page.writeItem(1, "stuff4", 0x7abbccdd) == ESP_OK); + + char buf[sizeof(str) + 16]; + int32_t value; + CHECK(page.readItem(1, "stuff1", value) == ESP_OK); + CHECK(value == 42); + CHECK(page.readItem(1, "stuff2", value) == ESP_OK); + CHECK(value == 1); + CHECK(page.readItem(1, "stuff3", value) == ESP_OK); + CHECK(value == 2); + CHECK(page.readItem(1, "stuff4", value) == ESP_OK); + CHECK(value == 0x7abbccdd); + + fill_n(buf, sizeof(buf), 0xff); + CHECK(page.readItem(1, ItemType::SZ, "foobaar", buf, sizeof(buf)) == ESP_OK); + CHECK(memcmp(buf, str, strlen(str) + 1) == 0); + + fill_n(buf, sizeof(buf), 0xff); + CHECK(page.readItem(1, ItemType::BLOB, "baz", buf, sizeof(buf)) == ESP_OK); + CHECK(memcmp(buf, str, strlen(str)) == 0); +} + + +TEST_CASE("can init PageManager in empty flash", "[nvs]") +{ + SpiFlashEmulator emu(4); + PageManager pm; + CHECK(pm.load(0, 4) == ESP_OK); +} + +TEST_CASE("PageManager adds page in the correct order", "[nvs]") +{ + const size_t pageCount = 8; + SpiFlashEmulator emu(pageCount); + uint32_t pageNo[pageCount] = { -1U, 50, 11, -1U, 23, 22, 24, 49}; + + for (uint32_t i = 0; i < pageCount; ++i) { + Page p; + p.load(i); + if (pageNo[i] != -1U) { + p.setSeqNumber(pageNo[i]); + p.writeItem(1, "foo", 10U); + } + } + + PageManager pageManager; + CHECK(pageManager.load(0, pageCount) == ESP_OK); + + uint32_t lastSeqNo = 0; + for (auto it = std::begin(pageManager); it != std::end(pageManager); ++it) { + uint32_t seqNo; + CHECK(it->getSeqNumber(seqNo) == ESP_OK); + CHECK(seqNo > lastSeqNo); + } +} + +TEST_CASE("can init storage in empty flash", "[nvs]") +{ + SpiFlashEmulator emu(8); + Storage storage; + emu.setBounds(4, 8); + CHECK(storage.init(4, 4) == ESP_OK); + s_perf << "Time to init empty storage (4 sectors): " << emu.getTotalTime() << " us" << std::endl; +} + +TEST_CASE("storage doesn't add duplicates within one page", "[nvs]") +{ + SpiFlashEmulator emu(8); + Storage storage; + emu.setBounds(4, 8); + CHECK(storage.init(4, 4) == ESP_OK); + int bar = 0; + CHECK(storage.writeItem(1, "bar", bar) == ESP_OK); + CHECK(storage.writeItem(1, "bar", bar) == ESP_OK); + + Page page; + page.load(4); + CHECK(page.getUsedEntryCount() == 1); + CHECK(page.getErasedEntryCount() == 1); +} + +TEST_CASE("can write one item a thousand times", "[nvs]") +{ + SpiFlashEmulator emu(8); + Storage storage; + emu.setBounds(4, 8); + CHECK(storage.init(4, 4) == ESP_OK); + for (size_t i = 0; i < Page::ENTRY_COUNT * 4 * 2; ++i) { + REQUIRE(storage.writeItem(1, "i", static_cast(i)) == ESP_OK); + } + s_perf << "Time to write one item a thousand times: " << emu.getTotalTime() << " us (" << emu.getEraseOps() << " " << emu.getWriteOps() << " " << emu.getReadOps() << " " << emu.getWriteBytes() << " " << emu.getReadBytes() << ")" << std::endl; +} + +TEST_CASE("storage doesn't add duplicates within multiple pages", "[nvs]") +{ + SpiFlashEmulator emu(8); + Storage storage; + emu.setBounds(4, 8); + CHECK(storage.init(4, 4) == ESP_OK); + int bar = 0; + CHECK(storage.writeItem(1, "bar", bar) == ESP_OK); + for (size_t i = 0; i < Page::ENTRY_COUNT; ++i) { + CHECK(storage.writeItem(1, "foo", static_cast(bar)) == ESP_OK); + } + CHECK(storage.writeItem(1, "bar", bar) == ESP_OK); + + Page page; + page.load(4); + CHECK(page.findItem(1, itemTypeOf(), "bar") == ESP_ERR_NVS_NOT_FOUND); + page.load(5); + CHECK(page.findItem(1, itemTypeOf(), "bar") == ESP_OK); +} + +TEST_CASE("can write and read variable length data lots of times", "[nvs]") +{ + SpiFlashEmulator emu(8); + Storage storage; + emu.setBounds(4, 8); + CHECK(storage.init(4, 4) == ESP_OK); + const char str[] = "foobar1234foobar1234foobar1234foobar1234foobar1234foobar1234foobar1234foobar1234"; + char buf[sizeof(str) + 16]; + size_t len = strlen(str); + for (size_t i = 0; i < Page::ENTRY_COUNT * 4 * 2; ++i) { + CAPTURE(i); + CHECK(storage.writeItem(1, ItemType::SZ, "foobaar", str, len + 1) == ESP_OK); + CHECK(storage.writeItem(1, "foo", static_cast(i)) == ESP_OK); + + uint32_t value; + CHECK(storage.readItem(1, "foo", value) == ESP_OK); + CHECK(value == i); + + fill_n(buf, sizeof(buf), 0xff); + CHECK(storage.readItem(1, ItemType::SZ, "foobaar", buf, sizeof(buf)) == ESP_OK); + CHECK(memcmp(buf, str, strlen(str) + 1) == 0); + } + s_perf << "Time to write one string and one integer a thousand times: " << emu.getTotalTime() << " us (" << emu.getEraseOps() << " " << emu.getWriteOps() << " " << emu.getReadOps() << " " << emu.getWriteBytes() << " " << emu.getReadBytes() << ")" << std::endl; +} + + +TEST_CASE("can get length of variable length data", "[nvs]") +{ + SpiFlashEmulator emu(8); + emu.randomize(200); + Storage storage; + emu.setBounds(4, 8); + CHECK(storage.init(4, 4) == ESP_OK); + const char str[] = "foobar1234foobar1234foobar1234foobar1234foobar1234foobar1234foobar1234foobar1234"; + size_t len = strlen(str); + CHECK(storage.writeItem(1, ItemType::SZ, "foobaar", str, len + 1) == ESP_OK); + size_t dataSize; + CHECK(storage.getItemDataSize(1, ItemType::SZ, "foobaar", dataSize) == ESP_OK); + CHECK(dataSize == len + 1); + + CHECK(storage.writeItem(2, ItemType::BLOB, "foobaar", str, len) == ESP_OK); + CHECK(storage.getItemDataSize(2, ItemType::BLOB, "foobaar", dataSize) == ESP_OK); + CHECK(dataSize == len); +} + + +TEST_CASE("can create namespaces", "[nvs]") +{ + SpiFlashEmulator emu(8); + Storage storage; + emu.setBounds(4, 8); + CHECK(storage.init(4, 4) == ESP_OK); + uint8_t nsi; + CHECK(storage.createOrOpenNamespace("wifi", false, nsi) == ESP_ERR_NVS_NOT_FOUND); + + CHECK(storage.createOrOpenNamespace("wifi", true, nsi) == ESP_OK); + Page page; + page.load(4); + CHECK(page.findItem(Page::NS_INDEX, ItemType::U8, "wifi") == ESP_OK); +} + +TEST_CASE("storage may become full", "[nvs]") +{ + SpiFlashEmulator emu(8); + Storage storage; + emu.setBounds(4, 8); + CHECK(storage.init(4, 4) == ESP_OK); + for (size_t i = 0; i < Page::ENTRY_COUNT * 3; ++i) { + char name[Item::MAX_KEY_LENGTH + 1]; + snprintf(name, sizeof(name), "key%05d", static_cast(i)); + REQUIRE(storage.writeItem(1, name, static_cast(i)) == ESP_OK); + } + REQUIRE(storage.writeItem(1, "foo", 10) == ESP_ERR_NVS_NOT_ENOUGH_SPACE); +} + +TEST_CASE("can modify an item on a page which will be erased", "[nvs]") +{ + SpiFlashEmulator emu(2); + Storage storage; + CHECK(storage.init(0, 2) == ESP_OK); + for (size_t i = 0; i < Page::ENTRY_COUNT * 3 + 1; ++i) { + REQUIRE(storage.writeItem(1, "foo", 42U) == ESP_OK); + } +} + + +#define TEST_ESP_ERR(rc, res) CHECK((rc) == (res)) +#define TEST_ESP_OK(rc) CHECK((rc) == ESP_OK) + +TEST_CASE("nvs api tests", "[nvs]") +{ + SpiFlashEmulator emu(10); + emu.randomize(100); + + nvs_handle handle_1; + const uint32_t NVS_FLASH_SECTOR = 6; + const uint32_t NVS_FLASH_SECTOR_COUNT_MIN = 3; + emu.setBounds(NVS_FLASH_SECTOR, NVS_FLASH_SECTOR + NVS_FLASH_SECTOR_COUNT_MIN); + + + TEST_ESP_ERR(nvs_open("namespace1", NVS_READWRITE, &handle_1), ESP_ERR_NVS_NOT_INITIALIZED); + for (uint16_t i = NVS_FLASH_SECTOR; i (count)); + + const uint32_t NVS_FLASH_SECTOR = 6; + const uint32_t NVS_FLASH_SECTOR_COUNT_MIN = 3; + emu.setBounds(NVS_FLASH_SECTOR, NVS_FLASH_SECTOR + NVS_FLASH_SECTOR_COUNT_MIN); + + TEST_ESP_OK(nvs_flash_init(NVS_FLASH_SECTOR, NVS_FLASH_SECTOR_COUNT_MIN)); + + nvs_handle handle_1; + TEST_ESP_ERR(nvs_open("namespace1", NVS_READONLY, &handle_1), ESP_ERR_NVS_NOT_FOUND); + + TEST_ESP_OK(nvs_open("namespace1", NVS_READWRITE, &handle_1)); + TEST_ESP_OK(nvs_set_i32(handle_1, "foo", 0x12345678)); + for (size_t i = 0; i < 500; ++i) { + nvs_handle handle_2; + TEST_ESP_OK(nvs_open("namespace2", NVS_READWRITE, &handle_2)); + TEST_ESP_OK(nvs_set_i32(handle_1, "foo", 0x23456789 % (i + 1))); + TEST_ESP_OK(nvs_set_i32(handle_2, "foo", static_cast(i))); + const char* str = "value 0123456789abcdef0123456789abcdef %09d"; + char str_buf[128]; + snprintf(str_buf, sizeof(str_buf), str, i + count * 1024); + TEST_ESP_OK(nvs_set_str(handle_2, "key", str_buf)); + + int32_t v1; + TEST_ESP_OK(nvs_get_i32(handle_1, "foo", &v1)); + CHECK(0x23456789 % (i + 1) == v1); + + int32_t v2; + TEST_ESP_OK(nvs_get_i32(handle_2, "foo", &v2)); + CHECK(static_cast(i) == v2); + + char buf[128]; + size_t buf_len = sizeof(buf); + + TEST_ESP_OK(nvs_get_str(handle_2, "key", buf, &buf_len)); + + CHECK(0 == strcmp(buf, str_buf)); + nvs_close(handle_2); + } + nvs_close(handle_1); + } +} + +template +esp_err_t doRandomThings(nvs_handle handle, TGen gen, size_t count) { + + const char* keys[] = {"foo", "bar", "longkey_0123456", "another key", "param1", "param2", "param3", "param4", "param5"}; + const ItemType types[] = {ItemType::I32, ItemType::I32, ItemType::U64, ItemType::U64, ItemType::SZ, ItemType::SZ, ItemType::SZ, ItemType::SZ, ItemType::SZ}; + + int32_t v1 = 0, v2 = 0; + uint64_t v3 = 0, v4 = 0; + const size_t strBufLen = 1024; + char v5[strBufLen], v6[strBufLen], v7[strBufLen], v8[strBufLen], v9[strBufLen]; + + void* values[] = {&v1, &v2, &v3, &v4, &v5, &v6, &v7, &v8, &v9}; + + const size_t nKeys = sizeof(keys) / sizeof(keys[0]); + static_assert(nKeys == sizeof(types) / sizeof(types[0]), ""); + static_assert(nKeys == sizeof(values) / sizeof(values[0]), ""); + + bool written[nKeys]; + std::fill_n(written, nKeys, false); + + auto generateRandomString = [](char* dst, size_t size) { + size_t len = 0; + }; + + auto randomRead = [&](size_t index) -> esp_err_t { + switch (types[index]) { + case ItemType::I32: + { + int32_t val; + auto err = nvs_get_i32(handle, keys[index], &val); + if (err == ESP_ERR_FLASH_OP_FAIL) { + return err; + } + if (!written[index]) { + REQUIRE(err == ESP_ERR_NVS_NOT_FOUND); + } + else { + REQUIRE(val == *reinterpret_cast(values[index])); + } + break; + } + + case ItemType::U64: + { + uint64_t val; + auto err = nvs_get_u64(handle, keys[index], &val); + if (err == ESP_ERR_FLASH_OP_FAIL) { + return err; + } + if (!written[index]) { + REQUIRE(err == ESP_ERR_NVS_NOT_FOUND); + } + else { + REQUIRE(val == *reinterpret_cast(values[index])); + } + break; + } + + case ItemType::SZ: + { + char buf[strBufLen]; + size_t len = strBufLen; + auto err = nvs_get_str(handle, keys[index], buf, &len); + if (err == ESP_ERR_FLASH_OP_FAIL) { + return err; + } + if (!written[index]) { + REQUIRE(err == ESP_ERR_NVS_NOT_FOUND); + } + else { + REQUIRE(strncmp(buf, reinterpret_cast(values[index]), strBufLen)); + } + break; + } + + default: + assert(0); + } + return ESP_OK; + }; + + auto randomWrite = [&](size_t index) -> esp_err_t { + switch (types[index]) { + case ItemType::I32: + { + int32_t val = static_cast(gen()); + *reinterpret_cast(values[index]) = val; + + auto err = nvs_set_i32(handle, keys[index], val); + if (err == ESP_ERR_FLASH_OP_FAIL) { + return err; + } + REQUIRE(err == ESP_OK); + written[index] = true; + break; + } + + case ItemType::U64: + { + uint64_t val = static_cast(gen()); + *reinterpret_cast(values[index]) = val; + + auto err = nvs_set_u64(handle, keys[index], val); + if (err == ESP_ERR_FLASH_OP_FAIL) { + return err; + } + REQUIRE(err == ESP_OK); + written[index] = true; + break; + } + + case ItemType::SZ: + { + char buf[strBufLen]; + size_t len = strBufLen; + + size_t strLen = gen() % (strBufLen - 1); + std::generate_n(buf, strLen, [&]() -> char { + const char c = static_cast(gen() % 127); + return (c < 32) ? 32 : c; + }); + + auto err = nvs_set_str(handle, keys[index], buf); + if (err == ESP_ERR_FLASH_OP_FAIL) { + return err; + } + REQUIRE(err == ESP_OK); + written[index] = true; + break; + } + + default: + assert(0); + } + return ESP_OK; + }; + + + for (size_t i = 0; i < count; ++i) { + size_t index = gen() % nKeys; + switch (gen() % 3) { + case 0: // read, 1/3 + if (randomRead(index) == ESP_ERR_FLASH_OP_FAIL) { + return ESP_ERR_FLASH_OP_FAIL; + } + break; + + default: // write, 2/3 + if (randomWrite(index) == ESP_ERR_FLASH_OP_FAIL) { + return ESP_ERR_FLASH_OP_FAIL; + } + break; + } + } + return ESP_OK; +} + +TEST_CASE("monkey test", "[nvs][monkey]") +{ + std::random_device rd; + std::mt19937 gen(rd()); + uint32_t seed = 3; + gen.seed(seed); + + SpiFlashEmulator emu(10); + emu.randomize(seed); + + const uint32_t NVS_FLASH_SECTOR = 6; + const uint32_t NVS_FLASH_SECTOR_COUNT_MIN = 3; + emu.setBounds(NVS_FLASH_SECTOR, NVS_FLASH_SECTOR + NVS_FLASH_SECTOR_COUNT_MIN); + + TEST_ESP_OK(nvs_flash_init(NVS_FLASH_SECTOR, NVS_FLASH_SECTOR_COUNT_MIN)); + + nvs_handle handle; + TEST_ESP_OK(nvs_open("namespace1", NVS_READWRITE, &handle)); + + CHECK(doRandomThings(handle, gen, 10000) == ESP_OK); + +} + +TEST_CASE("dump all performance data", "[nvs]") +{ + std::cout << "====================" << std::endl << "Dumping benchmarks" << std::endl; + std::cout << s_perf.str() << std::endl; + std::cout << "====================" << std::endl; +} diff --git a/components/nvs_flash/test/test_spi_flash_emulation.cpp b/components/nvs_flash/test/test_spi_flash_emulation.cpp new file mode 100644 index 0000000000..ea233da61b --- /dev/null +++ b/components/nvs_flash/test/test_spi_flash_emulation.cpp @@ -0,0 +1,154 @@ +// Copyright 2015-2016 Espressif Systems (Shanghai) PTE LTD +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at + +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +#include "catch.hpp" +#include "esp_spi_flash.h" +#include "spi_flash_emulation.h" + +using namespace std; + +template +bool range_empty_n(Tit it_begin, size_t n) +{ + return all_of(it_begin, it_begin + n, bind(equal_to(), placeholders::_1, 0xffffffff)); +} + +TEST_CASE("flash starts with all bytes == 0xff", "[spi_flash_emu]") +{ + SpiFlashEmulator emu(4); + + uint8_t sector[SPI_FLASH_SEC_SIZE]; + + for (int i = 0; i < 4; ++i) { + CHECK(spi_flash_read(0, reinterpret_cast(sector), sizeof(sector)) == ESP_OK); + for (auto v: sector) { + CHECK(v == 0xff); + } + } +} + +TEST_CASE("invalid writes are checked", "[spi_flash_emu]") +{ + SpiFlashEmulator emu(1); + + uint32_t val = 0; + CHECK(spi_flash_write(0, &val, 4) == ESP_OK); + val = 1; + CHECK(spi_flash_write(0, &val, 4) == ESP_ERR_FLASH_OP_FAIL); +} + + +TEST_CASE("out of bounds writes fail", "[spi_flash_emu]") +{ + SpiFlashEmulator emu(4); + uint32_t vals[8]; + std::fill_n(vals, 8, 0); + CHECK(spi_flash_write(0, vals, sizeof(vals)) == ESP_OK); + + CHECK(spi_flash_write(4*4096 - sizeof(vals), vals, sizeof(vals)) == ESP_OK); + + CHECK(spi_flash_write(4*4096 - sizeof(vals) + 4, vals, sizeof(vals)) == ESP_ERR_FLASH_OP_FAIL); +} + + +TEST_CASE("after erase the sector is set to 0xff", "[spi_flash_emu]") +{ + SpiFlashEmulator emu(4); + uint32_t val1 = 0xab00cd12; + CHECK(spi_flash_write(0, &val1, sizeof(val1)) == ESP_OK); + uint32_t val2 = 0x5678efab; + CHECK(spi_flash_write(4096 - 4, &val2, sizeof(val2)) == ESP_OK); + + CHECK(emu.words()[0] == val1); + CHECK(range_empty_n(emu.words() + 1, 4096 / 4 - 2)); + CHECK(emu.words()[4096 / 4 - 1] == val2); + + CHECK(spi_flash_erase_sector(0) == ESP_OK); + + CHECK(emu.words()[0] == 0xffffffff); + CHECK(range_empty_n(emu.words() + 1, 4096 / 4 - 2)); + CHECK(emu.words()[4096 / 4 - 1] == 0xffffffff); +} + +TEST_CASE("read/write/erase operation times are calculated correctly", "[spi_flash_emu]") +{ + SpiFlashEmulator emu(1); + uint32_t data[128]; + spi_flash_read(0, data, 4); + CHECK(emu.getTotalTime() == 7); + CHECK(emu.getReadOps() == 1); + CHECK(emu.getReadBytes() == 4); + emu.clearStats(); + spi_flash_read(0, data, 8); + CHECK(emu.getTotalTime() == 5); + CHECK(emu.getReadOps() == 1); + CHECK(emu.getReadBytes() == 8); + emu.clearStats(); + spi_flash_read(0, data, 16); + CHECK(emu.getTotalTime() == 6); + CHECK(emu.getReadOps() == 1); + CHECK(emu.getReadBytes() == 16); + emu.clearStats(); + spi_flash_read(0, data, 128); + CHECK(emu.getTotalTime() == 18); + CHECK(emu.getReadOps() == 1); + CHECK(emu.getReadBytes() == 128); + emu.clearStats(); + spi_flash_read(0, data, 256); + CHECK(emu.getTotalTime() == 32); + emu.clearStats(); + spi_flash_read(0, data, (128+256)/2); + CHECK(emu.getTotalTime() == (18+32)/2); + emu.clearStats(); + + spi_flash_write(0, data, 4); + CHECK(emu.getTotalTime() == 19); + CHECK(emu.getWriteOps() == 1); + CHECK(emu.getWriteBytes() == 4); + emu.clearStats(); + CHECK(emu.getWriteOps() == 0); + CHECK(emu.getWriteBytes() == 0); + spi_flash_write(0, data, 8); + CHECK(emu.getTotalTime() == 23); + emu.clearStats(); + spi_flash_write(0, data, 16); + CHECK(emu.getTotalTime() == 35); + CHECK(emu.getWriteOps() == 1); + CHECK(emu.getWriteBytes() == 16); + emu.clearStats(); + spi_flash_write(0, data, 128); + CHECK(emu.getTotalTime() == 205); + emu.clearStats(); + spi_flash_write(0, data, 256); + CHECK(emu.getTotalTime() == 417); + emu.clearStats(); + spi_flash_write(0, data, (128+256)/2); + CHECK(emu.getTotalTime() == (205+417)/2); + emu.clearStats(); + + spi_flash_erase_sector(0); + CHECK(emu.getEraseOps() == 1); + CHECK(emu.getTotalTime() == 37142); +} + +TEST_CASE("data is randomized predicatbly", "[spi_flash_emu]") +{ + SpiFlashEmulator emu1(3); + emu1.randomize(0x12345678); + + SpiFlashEmulator emu2(3); + emu2.randomize(0x12345678); + + CHECK(std::equal(emu1.bytes(), emu1.bytes() + emu1.size(), emu2.bytes())); +} + diff --git a/components/partition_table/Kconfig.projbuild b/components/partition_table/Kconfig.projbuild new file mode 100644 index 0000000000..fa2685d7a1 --- /dev/null +++ b/components/partition_table/Kconfig.projbuild @@ -0,0 +1,50 @@ +menu "Partition Table" + +choice + prompt "Partition Table" + default PARTITION_TABLE_SINGLE_APP + help + The partition table to flash to the ESP32. The partition table + determines where apps, data and other resources are expected to + be found. + + The predefined partition table CSV descriptions can be found + in the components/partition_table directory. Otherwise it's + possible to create a new custom partition CSV for your application. + +config PARTITION_TABLE_SINGLE_APP + bool "Single factory app, no OTA" +config PARTITION_TABLE_TWO_OTA + bool "Factory app, two OTA definitions" +config PARTITION_TABLE_CUSTOM + bool "Custom partition table CSV" +endchoice + +config PARTITION_TABLE_CUSTOM_FILENAME + string "Custom partition CSV file" if PARTITION_TABLE_CUSTOM + default partitions.csv + help + Name of the custom partition CSV filename. This path is evaluated + relative to the project root directory. + +config PARTITION_TABLE_CUSTOM_APP_BIN_OFFSET + hex "App offset in flash" if PARTITION_TABLE_CUSTOM + default 0x10000 + help + If using a custom partition table, specify the offset in the flash + where 'make flash' should write the built app. + +config PARTITION_TABLE_FILENAME + string + default partitions_singleapp.csv if PARTITION_TABLE_SINGLE_APP + default partitions_two_ota.csv if PARTITION_TABLE_TWO_OTA + default PARTITION_TABLE_CUSTOM_FILENAME if PARTITION_TABLE_CUSTOM + +config APP_OFFSET + hex + default PARTITION_TABLE_CUSTOM_APP_BIN_OFFSET if PARTITION_TABLE_CUSTOM + default 0x10000 # this is the factory app offset used by the default tables + +endmenu + + diff --git a/components/partition_table/Makefile.projbuild b/components/partition_table/Makefile.projbuild new file mode 100644 index 0000000000..99ed60d280 --- /dev/null +++ b/components/partition_table/Makefile.projbuild @@ -0,0 +1,42 @@ +# +# Partition table +# +# The partition table is not a real component that gets linked into +# the project. Instead, it is a standalone project to generate +# the partition table binary as part of the build process. This +# binary is then added to the list of files for esptool.py to flash. +# +.PHONY: partition_table partition_table-flash partition_table-clean + +EXTRA_CLEAN_TARGETS+=partition_table-clean + +# NB: gen_esp32part.py lives in the sdk/bin/ dir not component dir +GEN_ESP32PART := $(PYTHON) $(SDK_PATH)/bin/gen_esp32part.py -q + +# Path to partition CSV file is relative to project path for custom +# partition CSV files, but relative to component dir otherwise.$ +PARTITION_TABLE_ROOT := $(call dequote,$(if $(CONFIG_PARTITION_TABLE_CUSTOM),$(PROJECT_PATH),$(COMPONENT_PATH))) +PARTITION_TABLE_CSV_PATH := $(call dequote,$(abspath $(PARTITION_TABLE_ROOT)/$(subst $(quote),,$(CONFIG_PARTITION_TABLE_FILENAME)))) + +PARTITION_TABLE_BIN := $(BUILD_DIR_BASE)/$(notdir $(PARTITION_TABLE_CSV_PATH:.csv=.bin)) + +$(PARTITION_TABLE_BIN): $(PARTITION_TABLE_CSV_PATH) + @echo "Building partitions from $(PARTITION_TABLE_CSV_PATH)..." + $(Q) $(GEN_ESP32PART) $< $@ + +PARTITION_TABLE_FLASH_CMD = $(ESPTOOLPY_SERIAL) write_flash 0x4000 $(PARTITION_TABLE_BIN) + +partition_table: $(PARTITION_TABLE_BIN) + @echo "Partition table binary generated. Contents:" + @echo $(SEPARATOR) + $(Q) $(GEN_ESP32PART) $< + @echo $(SEPARATOR) + @echo "Partition flashing command:" + @echo "$(PARTITION_TABLE_FLASH_CMD)" + +partition_table-flash: $(PARTITION_TABLE_BIN) + @echo "Flashing partition table..." + $(Q) $(PARTITION_TABLE_FLASH_CMD) + +partition_table-clean: + $(Q) rm -f $(PARTITION_TABLE_BIN) diff --git a/components/partition_table/partitions_singleapp.csv b/components/partition_table/partitions_singleapp.csv new file mode 100644 index 0000000000..940b8a76c4 --- /dev/null +++ b/components/partition_table/partitions_singleapp.csv @@ -0,0 +1,4 @@ +# Name, Type, SubType, Offset, Size +factory, app, factory, 0x10000, 1M +rfdata, data, rf, , 256K +wifidata, data, wifi, , 256K diff --git a/components/partition_table/partitions_two_ota.csv b/components/partition_table/partitions_two_ota.csv new file mode 100644 index 0000000000..8e064e14b2 --- /dev/null +++ b/components/partition_table/partitions_two_ota.csv @@ -0,0 +1,7 @@ +# Name, Type, SubType, Offset, Size +factory, 0, 0, 0x10000, 1M +ota_0, 0, ota_0, , 1M +ota_1, 0, ota_1, , 1M +rfdata, data, rf, , 256K +wifidata, data, wifi, , 256K +otadata, data, ota, , 256K diff --git a/components/partition_table/tests/gen_esp32part_tests.py b/components/partition_table/tests/gen_esp32part_tests.py new file mode 100755 index 0000000000..413f1aac91 --- /dev/null +++ b/components/partition_table/tests/gen_esp32part_tests.py @@ -0,0 +1,313 @@ +#!/usr/bin/env python +import unittest +import struct +import csv +import sys +import subprocess +import tempfile +import os +sys.path.append("..") +from gen_esp32part import * + +SIMPLE_CSV = """ +# Name,Type,SubType,Offset,Size +factory,0,2,65536,1048576 +""" + +LONGER_BINARY_TABLE = "" +# type 0x00, subtype 0x00, +# offset 64KB, size 1MB +LONGER_BINARY_TABLE += "\xAA\x50\x00\x00" + \ + "\x00\x00\x01\x00" + \ + "\x00\x00\x10\x00" + \ + "factory\0" + ("\0"*8) + \ + "\x00\x00\x00\x00" +# type 0x01, subtype 0x20, +# offset 0x110000, size 128KB +LONGER_BINARY_TABLE += "\xAA\x50\x01\x20" + \ + "\x00\x00\x11\x00" + \ + "\x00\x02\x00\x00" + \ + "data" + ("\0"*12) + \ + "\x00\x00\x00\x00" +# type 0x10, subtype 0x00, +# offset 0x150000, size 1MB +LONGER_BINARY_TABLE += "\xAA\x50\x10\x00" + \ + "\x00\x00\x15\x00" + \ + "\x00\x10\x00\x00" + \ + "second" + ("\0"*10) + \ + "\x00\x00\x00\x00" + + +class CSVParserTests(unittest.TestCase): + + def test_simple_partition(self): + table = PartitionTable.from_csv(SIMPLE_CSV) + self.assertEqual(len(table), 1) + self.assertEqual(table[0].name, "factory") + self.assertEqual(table[0].type, 0) + self.assertEqual(table[0].subtype, 2) + self.assertEqual(table[0].offset, 65536) + self.assertEqual(table[0].size, 1048576) + + + def test_require_type(self): + csv = """ +# Name,Type, SubType,Offset,Size +ihavenotype, +""" + with self.assertRaisesRegexp(InputError, "type"): + PartitionTable.from_csv(csv) + + + def test_type_subtype_names(self): + csv_magicnumbers = """ +# Name, Type, SubType, Offset, Size +myapp, 0, 0,, 0x100000 +myota_0, 0, 0x10,, 0x100000 +myota_1, 0, 0x11,, 0x100000 +myota_15, 0, 0x1f,, 0x100000 +mytest, 0, 0x20,, 0x100000 +myota_status, 1, 0,, 0x100000 + """ + csv_nomagicnumbers = """ +# Name, Type, SubType, Offset, Size +myapp, app, factory,, 0x100000 +myota_0, app, ota_0,, 0x100000 +myota_1, app, ota_1,, 0x100000 +myota_15, app, ota_15,, 0x100000 +mytest, app, test,, 0x100000 +myota_status, data, ota,, 0x100000 +""" + # make two equivalent partition tables, one using + # magic numbers and one using shortcuts. Ensure they match + magic = PartitionTable.from_csv(csv_magicnumbers) + magic.verify() + nomagic = PartitionTable.from_csv(csv_nomagicnumbers) + nomagic.verify() + + self.assertEqual(nomagic["myapp"].type, 0) + self.assertEqual(nomagic["myapp"].subtype, 0) + self.assertEqual(nomagic["myapp"], magic["myapp"]) + self.assertEqual(nomagic["myota_0"].type, 0) + self.assertEqual(nomagic["myota_0"].subtype, 0x10) + self.assertEqual(nomagic["myota_0"], magic["myota_0"]) + self.assertEqual(nomagic["myota_15"], magic["myota_15"]) + self.assertEqual(nomagic["mytest"], magic["mytest"]) + self.assertEqual(nomagic["myota_status"], magic["myota_status"]) + + #self.assertEqual(nomagic.to_binary(), magic.to_binary()) + + def test_unit_suffixes(self): + csv = """ +# Name, Type, Subtype, Offset, Size +one_megabyte, app, factory, 32k, 1M +""" + t = PartitionTable.from_csv(csv) + t.verify() + self.assertEqual(t[0].offset, 32*1024) + self.assertEqual(t[0].size, 1*1024*1024) + + def test_default_offsets(self): + csv = """ +# Name, Type, Subtype, Offset, Size +first, app, factory,, 1M +second, data, 0x15,, 1M +minidata, data, 0x40,, 32K +otherapp, app, factory,, 1M + """ + t = PartitionTable.from_csv(csv) + # 'first' + self.assertEqual(t[0].offset, 0x010000) # 64KB boundary as it's an app image + self.assertEqual(t[0].size, 0x100000) # Size specified in CSV + # 'second' + self.assertEqual(t[1].offset, 0x110000) # prev offset+size + self.assertEqual(t[1].size, 0x100000) # Size specified in CSV + # 'minidata' + self.assertEqual(t[2].offset, 0x210000) + # 'otherapp' + self.assertEqual(t[3].offset, 0x220000) # 64KB boundary as it's an app image + + def test_negative_size_to_offset(self): + csv = """ +# Name, Type, Subtype, Offset, Size +first, app, factory, 0x10000, -2M +second, data, 0x15, , 1M + """ + t = PartitionTable.from_csv(csv) + t.verify() + # 'first' + self.assertEqual(t[0].offset, 0x10000) # in CSV + self.assertEqual(t[0].size, 0x200000 - t[0].offset) # Up to 2M + # 'second' + self.assertEqual(t[1].offset, 0x200000) # prev offset+size + + def test_overlapping_offsets_fail(self): + csv = """ +first, app, factory, 0x100000, 2M +second, app, ota_0, 0x200000, 1M +""" + t = PartitionTable.from_csv(csv) + with self.assertRaisesRegexp(InputError, "overlap"): + t.verify() + +class BinaryOutputTests(unittest.TestCase): + def test_binary_entry(self): + csv = """ +first, 0x30, 0xEE, 0x100400, 0x300000 +""" + t = PartitionTable.from_csv(csv) + tb = t.to_binary() + self.assertEqual(len(tb), 32) + self.assertEqual('\xAA\x50', tb[0:2]) # magic + self.assertEqual('\x30\xee', tb[2:4]) # type, subtype + eo, es = struct.unpack(" +#include +#include + +#include +#include +#include +#include +#include + +static esp_err_t spi_flash_translate_rc(SpiFlashOpResult rc) +{ + switch (rc) { + case SPI_FLASH_RESULT_OK: + return ESP_OK; + case SPI_FLASH_RESULT_TIMEOUT: + return ESP_ERR_FLASH_OP_TIMEOUT; + case SPI_FLASH_RESULT_ERR: + default: + return ESP_ERR_FLASH_OP_FAIL; + } +} + +extern void Cache_Flush(int); + +static void IRAM_ATTR spi_flash_disable_interrupts_caches_and_app_cpu() +{ + vTaskSuspendAll(); + // SET_PERI_REG_MASK(APPCPU_CTRL_REG_C, DPORT_APPCPU_RUNSTALL); + Cache_Read_Disable(0); + Cache_Read_Disable(1); +} + +static void IRAM_ATTR spi_flash_enable_interrupts_caches_and_app_cpu() +{ + Cache_Read_Enable(0); + Cache_Read_Enable(1); + // CLEAR_PERI_REG_MASK(APPCPU_CTRL_REG_C, DPORT_APPCPU_RUNSTALL); + xTaskResumeAll(); +} + +esp_err_t IRAM_ATTR spi_flash_erase_sector(uint16_t sec) +{ + spi_flash_disable_interrupts_caches_and_app_cpu(); + SpiFlashOpResult rc; + if (xPortGetCoreID() == 1) { + rc = SPI_FLASH_RESULT_ERR; + } + else { + rc = SPIUnlock(); + if (rc == SPI_FLASH_RESULT_OK) { + rc = SPIEraseSector(sec); + } + } + Cache_Flush(0); + Cache_Flush(1); + spi_flash_enable_interrupts_caches_and_app_cpu(); + return spi_flash_translate_rc(rc); +} + +esp_err_t IRAM_ATTR spi_flash_write(uint32_t dest_addr, const uint32_t *src, uint32_t size) +{ + spi_flash_disable_interrupts_caches_and_app_cpu(); + SpiFlashOpResult rc; + if (xPortGetCoreID() == 1) { + rc = SPI_FLASH_RESULT_ERR; + } + else { + rc = SPIUnlock(); + if (rc == SPI_FLASH_RESULT_OK) { + rc = SPIWrite(dest_addr, src, (int32_t) size); + } + } + Cache_Flush(0); + Cache_Flush(1); + spi_flash_enable_interrupts_caches_and_app_cpu(); + return spi_flash_translate_rc(rc); +} + +esp_err_t IRAM_ATTR spi_flash_read(uint32_t src_addr, uint32_t *dest, uint32_t size) +{ + spi_flash_disable_interrupts_caches_and_app_cpu(); + SpiFlashOpResult rc; + if (xPortGetCoreID() == 1) { + rc = SPI_FLASH_RESULT_ERR; + } + else { + rc = SPIRead(src_addr, dest, (int32_t) size); + } + spi_flash_enable_interrupts_caches_and_app_cpu(); + return spi_flash_translate_rc(rc); +} diff --git a/components/spi_flash/include/esp_spi_flash.h b/components/spi_flash/include/esp_spi_flash.h new file mode 100644 index 0000000000..aa12b2aa42 --- /dev/null +++ b/components/spi_flash/include/esp_spi_flash.h @@ -0,0 +1,69 @@ +// Copyright 2015-2016 Espressif Systems (Shanghai) PTE LTD +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at + +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#ifndef ESP_SPI_FLASH_H +#define ESP_SPI_FLASH_H + +#include +#include "esp_err.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#define ESP_ERR_FLASH_BASE 0x10010 +#define ESP_ERR_FLASH_OP_FAIL (ESP_ERR_FLASH_BASE + 1) +#define ESP_ERR_FLASH_OP_TIMEOUT (ESP_ERR_FLASH_BASE + 2) + +#define SPI_FLASH_SEC_SIZE 4096 /**< SPI Flash sector size */ + +/** + * @brief Erase the Flash sector. + * + * @param uint16 sec : Sector number, the count starts at sector 0, 4KB per sector. + * + * @return esp_err_t + */ +esp_err_t spi_flash_erase_sector(uint16_t sec); + +/** + * @brief Write data to Flash. + * + * @param uint32 des_addr : destination address in Flash. + * @param uint32 *src_addr : source address of the data. + * @param uint32 size : length of data + * + * @return esp_err_t + */ +esp_err_t spi_flash_write(uint32_t des_addr, const uint32_t *src_addr, uint32_t size); + +/** + * @brief Read data from Flash. + * + * @param uint32 src_addr : source address of the data in Flash. + * @param uint32 *des_addr : destination address. + * @param uint32 size : length of data + * + * @return esp_err_t + */ +esp_err_t spi_flash_read(uint32_t src_addr, uint32_t *des_addr, uint32_t size); + + +#ifdef __cplusplus +} +#endif + + +#endif /* ESP_SPI_FLASH_H */ + diff --git a/components/tcpip_adapter/Makefile b/components/tcpip_adapter/Makefile new file mode 100755 index 0000000000..6fd5e726d2 --- /dev/null +++ b/components/tcpip_adapter/Makefile @@ -0,0 +1,12 @@ +# +# Component Makefile +# +# This Makefile should, at the very least, just include $(SDK_PATH)/make/component.mk. By default, +# this will take the sources in this directory, compile them and link them into +# lib(subdirectory_name).a in the build directory. This behaviour is entirely configurable, +# please read the SDK documents if you need to do this. +# + +EXTRA_CFLAGS := -DLWIP_ESP8266 + +include $(SDK_PATH)/make/component.mk diff --git a/components/tcpip_adapter/include/tcpip_adapter.h b/components/tcpip_adapter/include/tcpip_adapter.h new file mode 100644 index 0000000000..7996632f3d --- /dev/null +++ b/components/tcpip_adapter/include/tcpip_adapter.h @@ -0,0 +1,100 @@ +// Copyright 2015-2016 Espressif Systems (Shanghai) PTE LTD +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at + +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#ifndef _TCPIP_ADAPTER_H_ +#define _TCPIP_ADAPTER_H_ + +#include + +#include "esp_wifi.h" + +#define CONFIG_TCPIP_LWIP 1 + +#if CONFIG_TCPIP_LWIP +#include "lwip/ip_addr.h" + +struct ip_info { + ip4_addr_t ip; + ip4_addr_t netmask; + ip4_addr_t gw; +}; +#endif + +#define ESP_ERR_TCPIP_ADAPTER_BASE 0x5000 // base should be moved to esp_err.h + +#define ESP_ERR_TCPIP_ADAPTER_INVALID_PARAMS ESP_ERR_TCPIP_ADAPTER_BASE + 0x00 +#define ESP_ERR_TCPIP_ADAPTER_IF_NOT_READY ESP_ERR_TCPIP_ADAPTER_BASE + 0x01 +#define ESP_ERR_TCPIP_ADAPTER_DHCPC_START_FAILED ESP_ERR_TCPIP_ADAPTER_BASE + 0x02 +#define ESP_ERR_TCPIP_ADAPTER_DHCP_ALREADY_STARTED ESP_ERR_TCPIP_ADAPTER_BASE + 0x03 +#define ESP_ERR_TCPIP_ADAPTER_DHCP_ALREADY_STOPED ESP_ERR_TCPIP_ADAPTER_BASE + 0x04 + +/* will add ethernet interface */ +typedef enum { + TCPIP_ADAPTER_IF_STA = 0, /**< ESP32 station interface */ + TCPIP_ADAPTER_IF_AP, /**< ESP32 soft-AP interface */ + TCPIP_ADAPTER_IF_MAX +} tcpip_adapter_if_t; + +typedef enum { + TCPIP_ADAPTER_DHCP_INIT = 0, + TCPIP_ADAPTER_DHCP_STARTED, + TCPIP_ADAPTER_DHCP_STOPED, + TCPIP_ADAPTER_DHCP_STATUS_MAX +} tcpip_adapter_dhcp_status_t; + +void tcpip_adapter_init(void); + +esp_err_t tcpip_adapter_start(tcpip_adapter_if_t tcpip_if, uint8_t *mac, struct ip_info *info); + +esp_err_t tcpip_adapter_stop(tcpip_adapter_if_t tcpip_if); + +esp_err_t tcpip_adapter_up(tcpip_adapter_if_t tcpip_if); + +esp_err_t tcpip_adapter_down(tcpip_adapter_if_t tcpip_if); + +esp_err_t tcpip_adapter_get_ip_info(tcpip_adapter_if_t tcpip_if, struct ip_info *if_ip); + +esp_err_t tcpip_adapter_set_ip_info(tcpip_adapter_if_t tcpip_if, struct ip_info *if_ip); + +#if 0 +esp_err_t tcpip_adapter_get_mac(tcpip_adapter_if_t tcpip_if, uint8_t *mac); + +esp_err_t tcpip_adapter_set_mac(tcpip_adapter_if_t tcpip_if, uint8_t *mac); +#endif + +esp_err_t tcpip_adapter_dhcps_get_status(tcpip_adapter_if_t tcpip_if, tcpip_adapter_dhcp_status_t *status); + +esp_err_t tcpip_adapter_dhcps_start(tcpip_adapter_if_t tcpip_if); + +esp_err_t tcpip_adapter_dhcps_stop(tcpip_adapter_if_t tcpip_if); + +esp_err_t tcpip_adapter_dhcpc_get_status(tcpip_adapter_if_t tcpip_if, tcpip_adapter_dhcp_status_t *status); + +esp_err_t tcpip_adapter_dhcpc_start(tcpip_adapter_if_t tcpip_if); + +esp_err_t tcpip_adapter_dhcpc_stop(tcpip_adapter_if_t tcpip_if); + +esp_err_t tcpip_adapter_sta_input(void *buffer, uint16_t len, void* eb); +esp_err_t tcpip_adapter_ap_input(void *buffer, uint16_t len, void* eb); + +#if 0 +//esp_err_t tcpip_dep_input(wifi_interface_t wifi_if, void *buffer, uint16 len); + +esp_err_t tcpip_adapter_output(tcpip_adapter_if_t tcpip_if, void *buffer, uint16_t len); +#endif + +wifi_interface_t tcpip_adapter_get_wifi_if(void *dev); + +#endif /* _TCPIP_ADAPTER_H_ */ + diff --git a/components/tcpip_adapter/tcpip_adapter_lwip.c b/components/tcpip_adapter/tcpip_adapter_lwip.c new file mode 100644 index 0000000000..2bc708857a --- /dev/null +++ b/components/tcpip_adapter/tcpip_adapter_lwip.c @@ -0,0 +1,450 @@ +// Copyright 2015-2016 Espressif Systems (Shanghai) PTE LTD +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at + +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +#include +#include + +#include "tcpip_adapter.h" + +#if CONFIG_TCPIP_LWIP + +#include "lwip/inet.h" +#include "lwip/tcpip.h" +#include "lwip/dhcp.h" +#include "lwip/ip_addr.h" + +#include "netif/wlanif.h" + +#include "apps/dhcpserver.h" + +static struct netif *esp_netif[TCPIP_ADAPTER_IF_MAX]; +static struct ip_info esp_ip[TCPIP_ADAPTER_IF_MAX]; + +static tcpip_adapter_dhcp_status_t dhcps_status = TCPIP_ADAPTER_DHCP_INIT; +static tcpip_adapter_dhcp_status_t dhcpc_status = TCPIP_ADAPTER_DHCP_INIT; + + +static esp_err_t tcpip_adapter_addr_change_cb(struct netif *netif); + +#define TCPIP_ADAPTER_DEBUG ets_printf + +void tcpip_adapter_init(void) +{ + static bool tcpip_inited = false; + + if (tcpip_inited == false) { + tcpip_inited = true; + + tcpip_init(NULL, NULL); + + IP4_ADDR(&esp_ip[TCPIP_ADAPTER_IF_AP].ip, 192, 168 , 4, 1); + IP4_ADDR(&esp_ip[TCPIP_ADAPTER_IF_AP].gw, 192, 168 , 4, 1); + IP4_ADDR(&esp_ip[TCPIP_ADAPTER_IF_AP].netmask, 255, 255 , 255, 0); + } + + netif_reg_addr_change_cb(tcpip_adapter_addr_change_cb); +} + +esp_err_t tcpip_adapter_start(tcpip_adapter_if_t tcpip_if, uint8_t *mac, struct ip_info *info) +{ + if (tcpip_if >= TCPIP_ADAPTER_IF_MAX || mac == NULL || info == NULL) { + return ESP_ERR_TCPIP_ADAPTER_INVALID_PARAMS; + } + + if (esp_netif[tcpip_if] == NULL) { + esp_netif[tcpip_if] = malloc(sizeof(struct netif)); + if (esp_netif[tcpip_if] == NULL) { + return ESP_ERR_NO_MEM; + } + memcpy(esp_netif[tcpip_if]->hwaddr, mac, NETIF_MAX_HWADDR_LEN); + netif_add(esp_netif[tcpip_if], &info->ip, &info->netmask, &info->gw, NULL, wlanif_init, tcpip_input); + } + + if (tcpip_if == TCPIP_ADAPTER_IF_AP) { + netif_set_up(esp_netif[tcpip_if]); + + if (dhcps_status == TCPIP_ADAPTER_DHCP_INIT) { + dhcps_start(esp_netif[tcpip_if]); + printf("dhcp server start:(ip: %s, mask: %s, gw: %s)\n", inet_ntoa(info->ip), inet_ntoa(info->netmask), inet_ntoa(info->gw)); + dhcps_status = TCPIP_ADAPTER_DHCP_STARTED; + } + } + + /* if ap is on, choose ap as default if */ + if (esp_netif[TCPIP_ADAPTER_IF_AP]) { + netif_set_default(esp_netif[TCPIP_ADAPTER_IF_AP]); + } else if (esp_netif[TCPIP_ADAPTER_IF_STA]) { + netif_set_default(esp_netif[TCPIP_ADAPTER_IF_STA]); + } + + return ESP_OK; +} + +esp_err_t tcpip_adapter_stop(tcpip_adapter_if_t tcpip_if) +{ + if (tcpip_if >= TCPIP_ADAPTER_IF_MAX) { + return ESP_ERR_TCPIP_ADAPTER_INVALID_PARAMS; + } + + if (esp_netif[tcpip_if] == NULL) { + return ESP_ERR_TCPIP_ADAPTER_IF_NOT_READY; + } + + if (tcpip_if == TCPIP_ADAPTER_IF_AP) { + dhcps_stop(esp_netif[tcpip_if]); // TODO: dhcps checks status by its self + dhcps_status = TCPIP_ADAPTER_DHCP_INIT; + } else if (tcpip_if == TCPIP_ADAPTER_IF_STA) { + dhcp_stop(esp_netif[tcpip_if]); + dhcpc_status = TCPIP_ADAPTER_DHCP_INIT; + } + + netif_remove(esp_netif[tcpip_if]); + + free(esp_netif[tcpip_if]); + esp_netif[tcpip_if] = NULL; + + /* in ap + sta mode, if stop ap, choose sta as default if */ + if (esp_netif[TCPIP_ADAPTER_IF_STA] && tcpip_if == TCPIP_ADAPTER_IF_AP) { + netif_set_default(esp_netif[TCPIP_ADAPTER_IF_STA]); + } + + return ESP_OK; +} + +esp_err_t tcpip_adapter_up(tcpip_adapter_if_t tcpip_if) +{ + if (tcpip_if == TCPIP_ADAPTER_IF_STA) { + if (esp_netif[tcpip_if] == NULL){ + return ESP_ERR_TCPIP_ADAPTER_IF_NOT_READY; + } + + netif_set_up(esp_netif[tcpip_if]); + } + + return ESP_OK; +} + +esp_err_t tcpip_adapter_down(tcpip_adapter_if_t tcpip_if) +{ + if (tcpip_if == TCPIP_ADAPTER_IF_STA) { + if (esp_netif[tcpip_if] == NULL){ + return ESP_ERR_TCPIP_ADAPTER_IF_NOT_READY; + } + + if (esp_netif[tcpip_if]->dhcp != NULL) { + dhcp_release(esp_netif[tcpip_if]); + dhcp_stop(esp_netif[tcpip_if]); + dhcp_cleanup(esp_netif[tcpip_if]); + dhcpc_status = TCPIP_ADAPTER_DHCP_STOPED; + } else { + netif_set_down(esp_netif[tcpip_if]); + netif_set_addr(esp_netif[tcpip_if], IP4_ADDR_ANY, IP4_ADDR_ANY, IP4_ADDR_ANY); + } + } + + return ESP_OK; +} + +esp_err_t tcpip_adapter_get_ip_info(tcpip_adapter_if_t tcpip_if, struct ip_info *if_ip) +{ + struct netif *p_netif; + + if (tcpip_if >= TCPIP_ADAPTER_IF_MAX || if_ip == NULL) { + return ESP_ERR_TCPIP_ADAPTER_INVALID_PARAMS; + } + + p_netif = esp_netif[tcpip_if]; + + if (p_netif != NULL && netif_is_up(p_netif)) { + ip4_addr_set(&if_ip->ip, ip_2_ip4(&p_netif->ip_addr)); + ip4_addr_set(&if_ip->netmask, ip_2_ip4(&p_netif->netmask)); + ip4_addr_set(&if_ip->gw, ip_2_ip4(&p_netif->gw)); + + return ESP_OK; + } + + ip4_addr_copy(if_ip->ip, esp_ip[tcpip_if].ip); + ip4_addr_copy(if_ip->gw, esp_ip[tcpip_if].gw); + ip4_addr_copy(if_ip->netmask, esp_ip[tcpip_if].netmask); + + return ESP_OK; +} + +esp_err_t tcpip_adapter_addr_change_cb(struct netif *netif) +{ + tcpip_adapter_if_t tcpip_if; + + if (!netif) { + TCPIP_ADAPTER_DEBUG("null netif=%p\n", netif); + return ESP_ERR_TCPIP_ADAPTER_IF_NOT_READY; + } + + if (netif == esp_netif[TCPIP_ADAPTER_IF_STA]) { + tcpip_if = TCPIP_ADAPTER_IF_STA; + } else if (netif == esp_netif[TCPIP_ADAPTER_IF_AP]){ + tcpip_if = TCPIP_ADAPTER_IF_AP; + } else { + TCPIP_ADAPTER_DEBUG("invalid netif=%p\n", netif); + return ESP_ERR_TCPIP_ADAPTER_IF_NOT_READY; + } + + //check whether IP is changed + if ( !ip4_addr_cmp(ip_2_ip4(&netif->ip_addr), &esp_ip[tcpip_if].ip) || + !ip4_addr_cmp(ip_2_ip4(&netif->gw), &esp_ip[tcpip_if].gw) || + !ip4_addr_cmp(ip_2_ip4(&netif->netmask), &esp_ip[tcpip_if].netmask) ) { + + ip4_addr_set(&esp_ip[tcpip_if].ip, ip_2_ip4(&netif->ip_addr)); + ip4_addr_set(&esp_ip[tcpip_if].netmask, ip_2_ip4(&netif->netmask)); + ip4_addr_set(&esp_ip[tcpip_if].gw, ip_2_ip4(&netif->gw)); + + //notify event + printf("ip: %s, ", inet_ntoa(esp_ip[tcpip_if].ip)); + printf("mask: %s, ", inet_ntoa(esp_ip[tcpip_if].netmask)); + printf("gw: %s\n", inet_ntoa(esp_ip[tcpip_if].gw)); + + if (ip_2_ip4(&netif->ip_addr) != IP4_ADDR_ANY) { + } + } else { + TCPIP_ADAPTER_DEBUG("ip unchanged\n"); + } + + return ESP_OK; +} + +esp_err_t tcpip_adapter_set_ip_info(tcpip_adapter_if_t tcpip_if, struct ip_info *if_ip) +{ + struct netif *p_netif; + + if (tcpip_if >= TCPIP_ADAPTER_IF_MAX || if_ip == NULL) { + return ESP_ERR_TCPIP_ADAPTER_INVALID_PARAMS; + } + + ip4_addr_copy(esp_ip[tcpip_if].ip, if_ip->ip); + ip4_addr_copy(esp_ip[tcpip_if].gw, if_ip->gw); + ip4_addr_copy(esp_ip[tcpip_if].netmask, if_ip->netmask); + + p_netif = esp_netif[tcpip_if]; + + if (p_netif != NULL && netif_is_up(p_netif)) { + netif_set_addr(p_netif, &if_ip->ip, &if_ip->netmask, &if_ip->gw); + } + + return ESP_OK; +} + +#if 0 +esp_err_t tcpip_adapter_get_mac(tcpip_adapter_if_t tcpip_if, uint8_t mac[6]) +{ + struct netif *p_netif; + + if (tcpip_if >= TCPIP_ADAPTER_IF_MAX || mac == NULL) { + return ESP_ERR_TCPIP_ADAPTER_INVALID_PARAMS; + } + + p_netif = esp_netif[tcpip_if]; + + if (p_netif != NULL) { + memcpy(mac, p_netif->hwaddr, NETIF_MAX_HWADDR_LEN); + + return ESP_OK; + } + + return ESP_ERR_TCPIP_ADAPTER_IF_NOT_READY; +} + +esp_err_t tcpip_adapter_set_mac(tcpip_adapter_if_t tcpip_if, uint8_t mac[6]) +{ + struct netif *p_netif; + + if (tcpip_if >= TCPIP_ADAPTER_IF_MAX || mac == NULL) { + return ESP_ERR_TCPIP_ADAPTER_INVALID_PARAMS; + } + + p_netif = esp_netif[tcpip_if]; + + if (p_netif != NULL) { + memcpy(p_netif->hwaddr, mac, NETIF_MAX_HWADDR_LEN); + + return ESP_OK; + } + + return ESP_ERR_TCPIP_ADAPTER_IF_NOT_READY; +} +#endif + +esp_err_t tcpip_adapter_dhcps_get_status(tcpip_adapter_if_t tcpip_if, tcpip_adapter_dhcp_status_t *status) +{ + *status = dhcps_status; + + return ESP_OK; +} + +esp_err_t tcpip_adapter_dhcps_start(tcpip_adapter_if_t tcpip_if) +{ + /* only support ap now */ + if (tcpip_if != TCPIP_ADAPTER_IF_AP || tcpip_if >= TCPIP_ADAPTER_IF_MAX) { + TCPIP_ADAPTER_DEBUG("dhcp server invalid if=%d\n", tcpip_if); + return ESP_ERR_TCPIP_ADAPTER_INVALID_PARAMS; + } + + if (dhcps_status != TCPIP_ADAPTER_DHCP_STARTED) { + struct netif *p_netif = esp_netif[tcpip_if]; + + if (p_netif != NULL && netif_is_up(p_netif)) { + dhcps_start(p_netif); + dhcps_status = TCPIP_ADAPTER_DHCP_STARTED; + TCPIP_ADAPTER_DEBUG("dhcp server start successfully\n"); + return ESP_OK; + } else { + TCPIP_ADAPTER_DEBUG("dhcp server re init\n"); + dhcps_status = TCPIP_ADAPTER_DHCP_INIT; + return ESP_OK; + } + } + + TCPIP_ADAPTER_DEBUG("dhcp server already start\n"); + return ESP_ERR_TCPIP_ADAPTER_DHCP_ALREADY_STARTED; +} + +esp_err_t tcpip_adapter_dhcps_stop(tcpip_adapter_if_t tcpip_if) +{ + /* only support ap now */ + if (tcpip_if != TCPIP_ADAPTER_IF_AP || tcpip_if >= TCPIP_ADAPTER_IF_MAX) { + TCPIP_ADAPTER_DEBUG("dhcp server invalid if=%d\n", tcpip_if); + return ESP_ERR_TCPIP_ADAPTER_INVALID_PARAMS; + } + + if (dhcps_status == TCPIP_ADAPTER_DHCP_STARTED) { + struct netif *p_netif = esp_netif[tcpip_if]; + + if (p_netif != NULL) { + dhcps_stop(p_netif); + } else { + TCPIP_ADAPTER_DEBUG("dhcp server if not ready\n"); + return ESP_ERR_TCPIP_ADAPTER_IF_NOT_READY; + } + } else if (dhcps_status == TCPIP_ADAPTER_DHCP_STOPED) { + TCPIP_ADAPTER_DEBUG("dhcp server already stoped\n"); + return ESP_ERR_TCPIP_ADAPTER_DHCP_ALREADY_STOPED; + } + + TCPIP_ADAPTER_DEBUG("dhcp server stop successfully\n"); + dhcps_status = TCPIP_ADAPTER_DHCP_STOPED; + return ESP_OK; +} + +esp_err_t tcpip_adapter_dhcpc_get_status(tcpip_adapter_if_t tcpip_if, tcpip_adapter_dhcp_status_t *status) +{ + *status = dhcpc_status; + + return ESP_OK; +} + +esp_err_t tcpip_adapter_dhcpc_start(tcpip_adapter_if_t tcpip_if) +{ + /* only support sta now, need to support ethernet */ + if (tcpip_if != TCPIP_ADAPTER_IF_STA || tcpip_if >= TCPIP_ADAPTER_IF_MAX) { + TCPIP_ADAPTER_DEBUG("dhcp client invalid if=%d\n", tcpip_if); + return ESP_ERR_TCPIP_ADAPTER_INVALID_PARAMS; + } + + if (dhcpc_status != TCPIP_ADAPTER_DHCP_STARTED) { + struct netif *p_netif = esp_netif[tcpip_if]; + + if (p_netif != NULL) { + if (netif_is_up(p_netif)) { + TCPIP_ADAPTER_DEBUG("dhcp client init ip/mask/gw to all-0\n"); + ip_addr_set_zero(&p_netif->ip_addr);; + ip_addr_set_zero(&p_netif->netmask); + ip_addr_set_zero(&p_netif->gw); + } + + if (dhcp_start(p_netif) != ERR_OK) { + TCPIP_ADAPTER_DEBUG("dhcp client start failed\n"); + return ESP_ERR_TCPIP_ADAPTER_DHCPC_START_FAILED; + } + + TCPIP_ADAPTER_DEBUG("dhcp client start successfully\n"); + dhcpc_status = TCPIP_ADAPTER_DHCP_STARTED; + return ESP_OK; + } else { + TCPIP_ADAPTER_DEBUG("dhcp client re init\n"); + dhcpc_status = TCPIP_ADAPTER_DHCP_INIT; + return ESP_OK; + } + } + + TCPIP_ADAPTER_DEBUG("dhcp client already started\n"); + return ESP_ERR_TCPIP_ADAPTER_DHCP_ALREADY_STARTED; +} + +esp_err_t tcpip_dep_dhcpc_stop(tcpip_adapter_if_t tcpip_if) +{ + /* only support sta now, need to support ethernet */ + if (tcpip_if != TCPIP_ADAPTER_IF_STA || tcpip_if >= TCPIP_ADAPTER_IF_MAX) { + TCPIP_ADAPTER_DEBUG("dhcp client invalid if=%d\n", tcpip_if); + return ESP_ERR_TCPIP_ADAPTER_INVALID_PARAMS; + } + + if (dhcpc_status == TCPIP_ADAPTER_DHCP_STARTED) { + struct netif *p_netif = esp_netif[tcpip_if]; + + if (p_netif != NULL) { + dhcp_stop(p_netif); + } else { + TCPIP_ADAPTER_DEBUG("dhcp client if not ready\n"); + return ESP_ERR_TCPIP_ADAPTER_IF_NOT_READY; + } + } else if (dhcps_status == TCPIP_ADAPTER_DHCP_STOPED) { + TCPIP_ADAPTER_DEBUG("dhcp client already stoped\n"); + return ESP_ERR_TCPIP_ADAPTER_DHCP_ALREADY_STOPED; + } + + TCPIP_ADAPTER_DEBUG("dhcp client stop successfully\n"); + dhcpc_status = TCPIP_ADAPTER_DHCP_STOPED; + return ESP_OK; +} + +esp_err_t tcpip_adapter_sta_input(void *buffer, uint16_t len, void* eb) +{ + wlanif_input(esp_netif[TCPIP_ADAPTER_IF_STA], buffer, len, eb); + return ESP_OK; +} + +esp_err_t tcpip_adapter_ap_input(void *buffer, uint16_t len, void* eb) +{ + wlanif_input(esp_netif[TCPIP_ADAPTER_IF_AP], buffer, len, eb); + return ESP_OK; +} + +#if 0 +bool tcpip_dep_output(wifi_interface_t wifi_if, void *buffer, uint16_t len) +{ + + return true; +} +#endif + +wifi_interface_t tcpip_adapter_get_wifi_if(void *dev) +{ + struct netif *p_netif = (struct netif *)dev; + + if (p_netif == esp_netif[TCPIP_ADAPTER_IF_STA]) { + return WIFI_IF_STA; + } else if (p_netif == esp_netif[TCPIP_ADAPTER_IF_AP]) { + return WIFI_IF_AP; + } + + return WIFI_IF_MAX; +} +#endif diff --git a/docs/COPYRIGHT.rst b/docs/COPYRIGHT.rst new file mode 100644 index 0000000000..da5f5b204a --- /dev/null +++ b/docs/COPYRIGHT.rst @@ -0,0 +1,103 @@ +Software Copyrights +=================== + +All original source code in this repository is Copyright (C) 2015-2016 +Espressif Systems. This source code is licensed under the Apache +License 2.0 as described in the file LICENSE. + +Additional third party copyrighted code is included under the following licenses: + +* Newlib_ (components/newlib) is licensed under the BSD License and is Copyright of various parties, as described in the file components/newlib/COPYING.NEWLIB. + +* Xtensa header files (components/esp32/include/xtensa) are Copyright (C) 2013 Tensilica Inc and are licensed under the MIT License as reproduce in the individual header files. + +* `esptool.py`_ (bin/esptool.py) is Copyright (C) 2014-2016 Fredrik Ahlberg, Angus Gratton and is licensed under the GNU General Public License v2, as described in the file components/esptool_py/LICENSE. + +* Original parts of FreeRTOS_ (components/freertos) are Copyright (C) 2015 Real Time Engineers Ltd and is licensed under the GNU General Public License V2 with the FreeRTOS Linking Exception, as described in the file components/freertos/license.txt. + +* Original parts of LWIP_ (components/lwip) are Copyright (C) 2001, 2002 Swedish Institute of Computer Science and are licensed under the BSD License as described in the file components/lwip/COPYING. + +* KConfig (tools/kconfig) is Copyright (C) 2002 Roman Zippel and others, and is licensed under the GNU General Public License V2. + +* `wpa_supplicant`_ Copyright (c) 2003-2005 Jouni Malinen and licensed under the BSD license. + +* `FreeBSD net80211`_ Copyright (c) 2004-2008 Sam Leffler, Errno Consulting and licensed under the BSD license. + +Where source code headers specify Copyright & License information, this information takes precedence over the summaries made here. + +ROM Source Code Copyrights +========================== + +ESP32 mask ROM hardware includes binaries compiled from portions of the following third party software: + +* Newlib_, as licensed under the BSD License and Copyright of various parties, as described in the file components/newlib/COPYING.NEWLIB. + +* Xtensa libhal, Copyright (c) Tensilica Inc and licensed under the MIT license (see below). + +* TinyBasic_ Plus, Copyright Mike Field & Scott Lawrence and licensed under the MIT license (see below). + +* miniz_, by Rich Geldreich - placed into the public domain. + +* `wpa_supplicant`_ Copyright (c) 2003-2005 Jouni Malinen and licensed under the BSD license. + +* TJpgDec_ Copyright (C) 2011, ChaN, all right reserved. See below for license. + +Xtensa libhal MIT License +========================= + +Copyright (c) 2003, 2006, 2010 Tensilica Inc. + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be included +in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +TinyBasic Plus MIT License +========================== + +Copyright (c) 2012-2013 + +Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +TJpgDec License +=============== +TJpgDec - Tiny JPEG Decompressor R0.01 (C)ChaN, 2011 +The TJpgDec is a generic JPEG decompressor module for tiny embedded systems. +This is a free software that opened for education, research and commercial +developments under license policy of following terms. + +Copyright (C) 2011, ChaN, all right reserved. + +* The TJpgDec module is a free software and there is NO WARRANTY. +* No restriction on use. You can use, modify and redistribute it for +personal, non-profit or commercial products UNDER YOUR RESPONSIBILITY. +* Redistributions of source code must retain the above copyright notice. + + +.. _Newlib: https://sourceware.org/newlib/ +.. _FreeRTOS: http://freertos.org/ +.. _esptool.py: https://github.com/themadinventor/esptool +.. _LWIP: http://savannah.nongnu.org/projects/lwip/ +.. _TinyBasic: https://github.com/BleuLlama/TinyBasicPlus +.. _miniz: https://code.google.com/archive/p/miniz/ +.. _wpa_supplicant: http://w1.fi/wpa_supplicant/ +.. _FreeBSD net80211: https://github.com/freebsd/freebsd/tree/master/sys/net80211 +.. _TJpgDec: http://elm-chan.org/fsw/tjpgd/00index.html diff --git a/docs/eclipse-setup.rst b/docs/eclipse-setup.rst new file mode 100644 index 0000000000..cbb9425ee2 --- /dev/null +++ b/docs/eclipse-setup.rst @@ -0,0 +1,75 @@ +Installing Eclipse IDE +====================== + +The Eclipse IDE gives you a graphical integrated development environment for writing, compiling and debugging ESP-IDF projects. + +* Start by installing the SDK for your platform (see Windows, OS X, Linux). + +* Download the Eclipse Installer for your platform from eclipse.org_. + +* When running the Eclipse Installer, choose "Eclipse for C/C++ Development" (in other places you'll see this referred to as CDT.) + +Setting up Eclipse +================== + +Once your new Eclipse installation launches, follow these steps: + +Import New Project +------------------ + +* Eclipse makes use of the Makefile support in ESP-IDF. This means you need to start by creating an ESP-IDF project. You can use the skeleton project from github. + +* Once Eclipse is running, choose File -> Import... + +* In the dialog that pops up, choose "C/C++" -> "EXisting Code as Makefile Project" and click Next. + +* On the next page, enter "Existing Code Location" to be the directory of your SDK project. Don't specify the path to the SDK itself. + +* On the same page, under "Toolchain for Indexer Settings" choose "Cross GCC". Then click Finish. + + +Project Properties +------------------ + +* The new project will appear under Project Explorer. Right-click the project and choose Properties from the context menu. + +* Click on the "Environment" properties page under "C/C++ Build". Click "Add..." and enter name ``V`` and value ``1``. + +* Click "Add..." again, and enter name ``SDK_PATH``. The value should be the full path where the ESP32 SDK is installed. *Windows users: Use forward-slashes not backslashes for this path, ie C:/Users/MyUser/Development/SDK*. + +*Windows users only, follow these two additional steps:* + +* On the same Environment property page, edit the PATH environment variable and append ";C:\msys32\usr\bin;C:\msys32\mingw32\bin;C:\msys32\opt\xtensa-esp32-elf\bin" to the end of the default value. (If you installed msys32 to a different directory then you'll need to change these paths to match.) + +* Click on the "C/C++ Build" top-level properties page then uncheck "Use default build command" and enter this for the custom build command: ``bash ${SDK_PATH}/bin/eclipse_windows_make.sh``. + +*All users, continue with these steps:* + +Navigate to "C/C++ General" -> "Preprocessor Include Paths" property page: + +* Click the "Providers" tab + +* In the list of providers, click "CDT Cross GCC Built-in Compiler Settings". Under "Command to get compiler specs", replace the text ``${COMMAND}`` at the beginning of the line with ``xtensa-esp32-elf-gcc``. This means the full "Command to get compiler specs" should be ``xtensa-esp32-elf-gcc ${FLAGS} -E -P -v -dD "${INPUTS}"``. + +* In the list of providers, click "CDT GCC Build Output Parser" and type ``xtensa-esp32-elf-`` at the beginning of the Compiler command pattern. This means the full Compiler command pattern should be ``xtensa-esp32-elf-(g?cc)|([gc]\+\+)|(clang)`` + +* Click OK to close the Properties dialog, and choose Project -> Build to build your project. + +Flash from Eclipse +------------------ + +You can integrate the "make flash" target into your Eclipse project to flash using esptool.py from the Eclipse UI: + +* Right-click the "esp-idf-tests" project in Project Explorer (important to make sure you don't select a subdirectory of the project or Eclipse may find the wrong Makefile.) + +* Select Make Targets -> Create from the context menu. + +* Type "flash" as the target name. Leave the other options as their defaults. + +* Now you can use Project -> Make Target -> Build (Shift+F9) to build the custom flash target, which will compile and flash the project. + +Note that you will need to use "make menuconfig" to set the serial port and other config options for flashing. "make menuconfig" still requires a command line terminal (see the instructions for your platform.) + +Follow the same steps to add ``bootloader`` and ``partition_table`` targets, if necessary. + +.. _eclipse.org: http://www.eclipse.org/ diff --git a/docs/windows-setup.rst b/docs/windows-setup.rst new file mode 100644 index 0000000000..aa0fb0d541 --- /dev/null +++ b/docs/windows-setup.rst @@ -0,0 +1,87 @@ +Step 1: Toolchain for Windows: Quick Steps +================================== + +Windows doesn't have a built-in "make" environment, so as well as installing the toolchain you will need a GNU-compatible environment. We use the MSYS2_ environment to provide. + You don't need to use this environment all the time (you can use Eclipse_ or some other front-end), but it runs behind the scenes. + +The quick setup is to download the Windows all-in-one toolchain & MSYS zip file from dl.espressif.com: + +http://dl.espressif.com/dl/esp32_win32_msys2_environment_and_toolchain-20160816.zip + +Unzip the zip file to C:\ and it will create an "msys32" directory with a pre-prepared environment. + + +Alternative Step 1: Configure toolchain & environment from scratch +================================================================== + +As an alternative to getting a pre-prepared environment, you can set up the environment from scratch: + +* Navigate to the MSYS2_ installer page and download the ``msys2-i686-xxxxxxx.exe`` installer executable (we only support a 32-bit MSYS environment, it works on both 32-bit and 64-bit Windows.) + +* Run through the installer steps, and accept the "Run MSYS2 now" option at the end. A window will open with a MSYS2 terminal. + +* The SDK repository on github contains a script in the tools directory titled ``windows_install_prerequisites.sh``. If you haven't downloaded the SDK yet, that's OK - you can just `download that one file in Raw format from here `_. Save it somewhere on your computer. + +* Type the path to the shell script into the MSYS2 terminal window. You can type it as a normal Windows path, but use forward-slashes instead of back-slashes. ie: ``C:/Users/myuser/Downloads/windows_install_prerequisites.sh``. You can read the script beforehand to check what it does. + +* If you use the 201602 MSYS2 installer, the first time you run ``windows_install_prerequisites.sh`` it will update the MSYS2 core system. At the end of this update, you will be prompted to close the MSYS2 terminal and re-open. When you re-open after the update, re-run ``windows_install_prerequisites.sh``. The next version of MSYS2 (after 201602) will not need this interim step. + +* The ``windows_install_prerequisites.sh`` script will download and install packages for ESP32 SDK support, and the ESP32 toolchain. + +Note: You may encounter a bug where svchost.exe uses 100% CPU in Windows after setup is finished, resulting in the SDK building very slowly. Terminating svchost.exe or restarting Windows will solve this problem. + +Another Alternative Step 1: Just download a toolchain +===================================================== + +If you already have an MSYS2 install or want to do things differently, you can download just the toolchain here: + +http://dl.espressif.com/dl/xtensa-esp32-elf-win32-1.22.0-59.zip + +If you followed one of the above options for Step 1, you won't need this download. + +Important: Just having this toolchain is *not enough* to use ESP-IDF on Windows. You will need GNU make, bash, and sed at minimum. The above environments provide all this, plus a host compiler (required for menuconfig support). + +Step 2: Getting the SDK from github +=================================== + +Option 1: Direct Download +------------------------- + +This is the quick option to get up and running with the SDK, but you'll have to re-download in order to update the SDK. + +Navigate to the github repository and click Download. Unzip the SDK somewhere that you need to use it. + +Option 2: Using git +------------------- + +It takes longer to check out the SDK directly from git, but you'll have the option of using ``git pull`` to update the SDK sources. + +Open an MSYS2 terminal window by running ``C:\msys32\msys2_shell.cmd``. The environment in this window is a bash shell. + +Change to the directory you want to clone the SDK into by typing a command like this one: ``cd "C:/path/to/dir"`` (note the forward-slashes in the path). Then type ``git clone https://github.com/espressif/esp-idf.git`` + +If you'd rather use a Windows UI tool to manage your git repositories, this is also possible. A wide range are available. + +Step 3: Starting a project +========================== + +The SDK by itself does not build a binary to run on the ESP32. The binary "app" comes from a project in a different directory. Multiple projects can share the same ESP32 SDK. + +The easiest way to start a project is to download the Getting Started project from github_. + +The process is the same as for checking out the SDK from github. Change to the parent directory and run ``git clone https://github.com/espressif/esp-idf-template.git``. + +Step 4: Configuring the project +=============================== + +Open an MSYS2 terminal window by running ``C:\msys32\msys2_shell.cmd``. The environment in this window is a bash shell. + +Type a command like this to set the path to ESP-IDF directory: ``export SDK_PATH="C:/path/to/esp-idf"`` (note the forward-slashes not back-slashes for the path). If you don't want to run this command every time you open an MSYS2 window, create a new file in ``C:/msys32/etc/profile.d/`` and paste this line in - then it will be run each time you open an MYS2 terminal. + +Use ``cd`` to change to the project directory (not the SDK directory.) Type ``make menuconfig`` to configure your project, then ``make`` to build it, ``make clean`` to remove built files, and ``make flash`` to flash (use the menuconfig to set the serial port for flashing.) + +If you'd like to use the Eclipse IDE instead of running ``make``, check out the Eclipse setup guide in this directory. + + +.. _MSYS2: https://msys2.github.io/ +.. _github: https://github.com/espressif/esp-idf-template diff --git a/make/common.mk b/make/common.mk new file mode 100644 index 0000000000..24d8294b8d --- /dev/null +++ b/make/common.mk @@ -0,0 +1,56 @@ +# Functionality common to both top-level project makefile +# and component makefiles +# + +# Include project config file, if it exists. +# +# (Note that we only rebuild auto.conf automatically for some targets, +# see project_config.mk for details.) +-include $(PROJECT_PATH)/build/include/config/auto.conf + +ifeq ("$(LDFLAGS)","") +LDFLAGS = -nostdlib \ + -L$(SDK_PATH)/lib \ + -L$(SDK_PATH)/ld \ + $(addprefix -L$(BUILD_DIR_BASE)/,$(COMPONENTS) $(SRCDIRS)) \ + -u call_user_start_cpu0 \ + -Wl,--gc-sections \ + -Wl,-static \ + -Wl,--start-group \ + $(COMPONENT_LDFLAGS) \ + -lgcc \ + -Wl,--end-group +endif + +ifeq ("$(CFLAGS)","") +CFLAGS = -DESP_PLATFORM -Og -std=gnu99 -g3 \ + -Wpointer-arith -Werror -Wno-error=unused-function -Wno-error=unused-but-set-variable -Wno-error=unused-variable \ + -Wl,-EL -fno-inline-functions -nostdlib -mlongcalls -Wall -ffunction-sections -fdata-sections $(EXTRA_CFLAGS) +endif + +ifeq ("$(CXXFLAGS)","") +CXXFLAGS = -DESP_PLATFORM -Og -std=gnu++11 -g3 \ + -Wpointer-arith -Werror -Wno-error=unused-function -Wno-error=unused-but-set-variable -Wno-error=unused-variable \ + -Wl,-EL -nostdlib -mlongcalls -Wall -ffunction-sections -fdata-sections $(EXTRA_CFLAGS) -fno-exceptions +endif + +#Handling of V=1/VERBOSE=1 flag +V ?= $(VERBOSE) +ifeq ("$(V)","1") +Q := +vecho := @true +else +Q := @ +vecho := @echo +endif + +# General make utilities + +# convenience variable for printing an 80 asterisk wide separator line +SEPARATOR:="*******************************************************************************" + +# macro to remove quotes from an argument, ie $(call dequote (CONFIG_BLAH)) +define dequote +$(subst ",,$(1)) +endef +# " comment kept here to keep syntax highlighting happy diff --git a/make/component.mk b/make/component.mk new file mode 100644 index 0000000000..3ee16166da --- /dev/null +++ b/make/component.mk @@ -0,0 +1,111 @@ +# Main SDK Makefile +# This Makefile gets included in the Makefile of all the components to set the correct include paths etc. +# PWD is the build directory of the component and the top Makefile is the one in the +# component source dir. +# +# The way the Makefile differentiates between those two is by looking at the environment +# variable PROJECT_PATH. If this is set (to the basepath of the project), we're building a +# component and its Makefile has included this makefile. If not, we're building the entire project. +# + +# +# This Makefile requires the environment variable SDK_PATH to be set +# to the directory where the SDK (containing the make directory with +# this file) is located +# + +ifeq ("$(PROJECT_PATH)","") +$(error Make was invoked from $(CURDIR). However please do not run make from the sdk or a component directory; invoke make from the project directory. See SDK README for details.) +endif + +# Find the path to the component +COMPONENT_PATH := $(abspath $(dir $(firstword $(MAKEFILE_LIST)))) +export COMPONENT_PATH + +include $(SDK_PATH)/make/common.mk + +#Some of these options are overridable by the components Makefile. + +#Name of the component +COMPONENT_NAME ?= $(lastword $(subst /, ,$(realpath $(COMPONENT_PATH)))) + +#Absolute path of the .a file +COMPONENT_LIBRARY := lib$(COMPONENT_NAME).a + +#Source dirs a component has. Default to root directory of component. +COMPONENT_SRCDIRS ?= . + +#Object files which need to be linked into the library +#By default we take all .c/.S files in the component directory. +ifeq ("$(COMPONENT_OBJS)", "") +#Find all source files in all COMPONENT_SRCDIRS +COMPONENT_OBJS := $(foreach compsrcdir,$(COMPONENT_SRCDIRS),$(patsubst %.c,%.o,$(wildcard $(COMPONENT_PATH)/$(compsrcdir)/*.c))) +COMPONENT_OBJS += $(foreach compsrcdir,$(COMPONENT_SRCDIRS),$(patsubst %.cpp,%.o,$(wildcard $(COMPONENT_PATH)/$(compsrcdir)/*.cpp))) +COMPONENT_OBJS += $(foreach compsrcdir,$(COMPONENT_SRCDIRS),$(patsubst %.S,%.o,$(wildcard $(COMPONENT_PATH)/$(compsrcdir)/*.S))) +#Make relative by removing COMPONENT_PATH from all found object paths +COMPONENT_OBJS := $(patsubst $(COMPONENT_PATH)/%,%,$(COMPONENT_OBJS)) +endif + +#By default, include only the include/ dir. +COMPONENT_ADD_INCLUDEDIRS ?= include +COMPONENT_ADD_LDFLAGS ?= -l$(COMPONENT_NAME) + +#If we're called to compile something, we'll get passed the COMPONENT_INCLUDES +#variable with all the include dirs from all the components in random order. This +#means we can accidentally grab a header from another component before grabbing our own. +#To make sure that does not happen, re-order the includes so ours come first. +OWN_INCLUDES:=$(abspath $(addprefix $(COMPONENT_PATH)/,$(COMPONENT_ADD_INCLUDEDIRS) $(COMPONENT_PRIV_INCLUDEDIRS))) +COMPONENT_INCLUDES := $(OWN_INCLUDES) $(filter-out $(OWN_INCLUDES),$(COMPONENT_INCLUDES)) + +#This target is used to collect variable values from inside the main makefile +get_variable: + @echo "$(GET_VARIABLE)=$(call $(GET_VARIABLE)) " + +#Targets for build/clean. Use builtin recipe if component Makefile +#hasn't defined its own. +ifeq ("$(COMPONENT_OWNBUILDTARGET)", "") +build: $(COMPONENT_LIBRARY) + @mkdir -p $(COMPONENT_SRCDIRS) + +#Build the archive. We remove the archive first, otherwise ar will get confused if we update +#an archive when multiple filenames have the same name (src1/test.o and src2/test.o) +$(COMPONENT_LIBRARY): $(COMPONENT_OBJS) + $(vecho) AR $@ + $(Q) rm -f $@ + $(Q) $(AR) cru $@ $(COMPONENT_OBJS) +endif + +ifeq ("$(COMPONENT_OWNCLEANTARGET)", "") +clean: + $(vecho) RM $(COMPONENT_LIBRARY) $(COMPONENT_OBJS) $(COMPONENT_OBJS:.o=.d) $(COMPONENT_EXTRA_CLEAN) + $(Q) rm -f $(COMPONENT_LIBRARY) $(COMPONENT_OBJS) $(COMPONENT_OBJS:.o=.d) $(COMPONENT_EXTRA_CLEAN) +endif + +#Also generate dependency files +CFLAGS+=-MMD +CXXFLAGS+=-MMD +#Include all dependency files already generated +-include $(COMPONENT_OBJS:.o=.d) + +#This pattern is generated for each COMPONENT_SRCDIR to compile the files in it. +define GenerateCompileTargets +# $(1) - directory containing source files, relative to $(COMPONENT_PATH) +$(1)/%.o: $$(COMPONENT_PATH)/$(1)/%.c | $(1) + $$(vecho) CC $$@ + $$(Q) $$(CC) $$(CFLAGS) $$(addprefix -I ,$$(COMPONENT_INCLUDES)) $$(addprefix -I ,$$(COMPONENT_EXTRA_INCLUDES)) -I$(1) -c $$< -o $$@ + +$(1)/%.o: $$(COMPONENT_PATH)/$(1)/%.cpp | $(1) + $$(vecho) CC $$@ + $$(Q) $$(CXX) $$(CXXFLAGS) $$(addprefix -I,$$(COMPONENT_INCLUDES)) $$(addprefix -I,$$(COMPONENT_EXTRA_INCLUDES)) -I$(1) -c $$< -o $$@ + +$(1)/%.o: $$(COMPONENT_PATH)/$(1)/%.S | $(1) + $$(vecho) CC $$@ + $$(Q) $$(CC) $$(CFLAGS) $$(addprefix -I ,$$(COMPONENT_INCLUDES)) $$(addprefix -I ,$$(COMPONENT_EXTRA_INCLUDES)) -I$(1) -c $$< -o $$@ + +# CWD is build dir, create the build subdirectory if it doesn't exist +$(1): + @mkdir -p $(1) +endef + +#Generate all the compile target recipes +$(foreach srcdir,$(COMPONENT_SRCDIRS), $(eval $(call GenerateCompileTargets,$(srcdir)))) diff --git a/make/project.mk b/make/project.mk new file mode 100644 index 0000000000..873c311ecd --- /dev/null +++ b/make/project.mk @@ -0,0 +1,185 @@ +# +# Main Project Makefile +# This Makefile is included directly from the user project Makefile in order to call the Makefiles of all the +# components (in a separate make process) to build all the libraries, then links them together +# into the final file. If so, PWD is the project dir (we assume). +# + +# +# This Makefile requires the environment variable SDK_PATH to be set to the directory where this +# Makefile is located. +# + +.PHONY: build-components menuconfig all build clean +all: project + +# disable built-in make rules, makes debugging saner +MAKEFLAGS +=-rR + +# Figure out PROJECT_PATH if not set, check for unacceptable Makefile entry points +ifeq ("$(PROJECT_PATH)","") +#The path to the project: we assume the Makefile including this file resides +#in the root of that directory. +PROJECT_PATH := $(abspath $(dir $(firstword $(MAKEFILE_LIST)))) +export PROJECT_PATH + +#The directory where we put all objects/libraries/binaries. The project Makefile can +#configure this if needed. +BUILD_DIR_BASE ?= $(PROJECT_PATH)/build + +#Component directories. These directories are searched for components. +#The project Makefile can override these component dirs, or define extra component directories. +COMPONENT_DIRS ?= $(PROJECT_PATH)/components $(EXTRA_COMPONENT_DIRS) $(SDK_PATH)/components +export COMPONENT_DIRS + +#The project Makefile can define a list of components, but if it does not do this we just take +#all available components in the component dirs. +ifeq ("$(COMPONENTS)","") +#Find all component names. The component names are the same as the +#directories they're in, so /bla/components/mycomponent/ -> mycomponent. We later use +#the COMPONENT_DIRS bit to find back the component path. +COMPONENTS := $(foreach dir,$(COMPONENT_DIRS),$(wildcard $(dir)/*)) +COMPONENTS := $(sort $(foreach comp,$(COMPONENTS),$(lastword $(subst /, ,$(comp))))) +endif +export COMPONENTS + +#Sources default to only "main" +SRCDIRS ?= main + +#Here, we resolve and add all the components and source paths into absolute paths. +#If a component exists in multiple COMPONENT_DIRS, we take the first match. +#WARNING: These directories paths must be generated WITHOUT a trailing / so we +#can use $(notdir x) to get the component name. +COMPONENT_PATHS := $(foreach comp,$(COMPONENTS),$(firstword $(foreach dir,$(COMPONENT_DIRS),$(wildcard $(dir)/$(comp))))) +COMPONENT_PATHS += $(abspath $(SRCDIRS)) + +#A component is buildable if it has a Makefile; we assume that a 'make -C $(component dir) build' results in a +#lib$(componentname).a. +COMPONENT_PATHS_BUILDABLE := $(foreach cp,$(COMPONENT_PATHS),$(if $(wildcard $(cp)/Makefile),$(cp))) + +# Assemble global list of include dirs (COMPONENT_INCLUDES), and +# LDFLAGS args (COMPONENT_LDFLAGS) supplied by each component. +# +# Also add any inter-component dependencies for each component. + +# Extract a variable from a child make process +# +# $(1) - path to directory to invoke make in +# $(2) - name of variable to print via the getvariable target (passed in GET_VARIABLE) +# +# needs 'sed' processing of stdout because make sometimes echoes other stuff on stdout, +# even if asked not to. +# +# Debugging this? Replace $(shell with $(error and you'll see the full command as-run. +define GetVariable +$(shell "$(MAKE)" -s --no-print-directory -C $(1) get_variable COMPONENT_INCLUDES=dummy COMPONENT_LDFLAGS=dummy PROJECT_PATH=$(PROJECT_PATH) GET_VARIABLE=$(2) | sed -En "s/^$(2)=(.+)/\1/p" ) +endef + +ifeq ("$(COMPONENT_INCLUDES)","") +COMPONENT_INCLUDES := $(abspath $(foreach comp,$(COMPONENT_PATHS_BUILDABLE),$(addprefix $(comp)/, \ + $(call GetVariable,$(comp),COMPONENT_ADD_INCLUDEDIRS)))) +endif + +#Also add project include path, for sdk includes +COMPONENT_INCLUDES += $(PROJECT_PATH)/build/include/ +export COMPONENT_INCLUDES + +#COMPONENT_LDFLAGS has a list of all flags that are needed to link the components together. It's collected +#in the same way as COMPONENT_INCLUDES is. +ifeq ("$(COMPONENT_LDFLAGS)","") +COMPONENT_LDFLAGS := $(foreach comp,$(COMPONENT_PATHS_BUILDABLE), \ + $(call GetVariable,$(comp),COMPONENT_ADD_LDFLAGS)) +export COMPONENT_LDFLAGS +endif + +# Generate component dependency targets from dependencies lists +# each component gains a target of its own -build with dependencies +# of the names of any other components (-build) that need building first +# +# the actual targets (that invoke submakes) are generated below by +# GenerateComponentTarget macro. +define GenerateComponentDependencies +# $(1) = component path +.PHONY: $$(notdir $(1)) +$$(notdir $(1))-build: $(addsuffix -build,$(call GetVariable,$(1),COMPONENT_DEPENDS)) +endef +$(foreach comp,$(COMPONENT_PATHS_BUILDABLE), $(eval $(call GenerateComponentDependencies,$(comp)))) + +#Make sure submakes can also use this. +export PROJECT_PATH + +#Include functionality common to both project & component +-include $(SDK_PATH)/make/common.mk + +#Set host compiler and binutils +HOSTCC := $(CC) +HOSTLD := $(LD) +HOSTAR := $(AR) +HOSTOBJCOPY := $(OBJCOPY) + +#Set target compiler. Defaults to whatever the user has +#configured as prefix + yer olde gcc commands +CC := $(call dequote,$(CONFIG_TOOLPREFIX))gcc +CXX := $(call dequote,$(CONFIG_TOOLPREFIX))c++ +LD := $(call dequote,$(CONFIG_TOOLPREFIX))ld +AR := $(call dequote,$(CONFIG_TOOLPREFIX))ar +OBJCOPY := $(call dequote,$(CONFIG_TOOLPREFIX))objcopy +export CC CXX LD AR OBJCOPY + +PYTHON=$(call dequote,$(CONFIG_PYTHON)) + +PROJECT_ELF:=$(BUILD_DIR_BASE)/$(PROJECT_NAME).elf +PROJECT_BIN:=$(PROJECT_ELF:.elf=.bin) + +# Include any Makefile.projbuild file letting components add +# configuration at the project level +define includeProjBuildMakefile +COMPONENT_PATH := $(1) +-include $(1)/Makefile.projbuild +endef +$(foreach componentpath,$(COMPONENT_PATHS),$(eval $(call includeProjBuildMakefile,$(componentpath)))) + +# ELF depends on the -build target of every component +$(PROJECT_ELF): $(addsuffix -build,$(notdir $(COMPONENT_PATHS_BUILDABLE))) + $(vecho) LD $(notdir $@) + $(Q) $(CC) $(LDFLAGS) -o $@ -Wl,-Map=$(patsubst %.elf,%.map,$@) + +# Generation of $(PROJECT_BIN) from $(PROJECT_ELF) is added by the esptool +# component's Makefile.projbuild + +project: $(PROJECT_BIN) + @echo "App built. Default flash app command is:" + @echo $(PROJECT_FLASH_COMMAND) # PROJECT_FLASH_COMMAND is set in esptool_py's Makefile.projbuild + +$(BUILD_DIR_BASE): + mkdir -p $(BUILD_DIR_BASE) + +define GenerateComponentTarget +# $(1) - path to component dir +# $(2) - target to generate (build, clean) +# $(3) - optional dependencies to add +.PHONY: $(notdir $(1))-$(2) +$(notdir $(1))-$(2): $(3) | $(BUILD_DIR_BASE)/$(notdir $(1)) + @+$(MAKE) -C $(BUILD_DIR_BASE)/$(notdir $(1)) -f $(1)/Makefile COMPONENT_BUILD_DIR=$(BUILD_DIR_BASE)/$(notdir $(1)) $(2) +endef + +define GenerateComponentBuildDirTarget +# $(1) - path to component dir +$(BUILD_DIR_BASE)/$(notdir $(1)): + @mkdir -p $(BUILD_DIR_BASE)/$(notdir $(1)) +endef + +$(foreach component,$(COMPONENT_PATHS_BUILDABLE),$(eval $(call GenerateComponentBuildDirTarget,$(component)))) + +$(foreach component,$(COMPONENT_PATHS_BUILDABLE),$(eval $(call GenerateComponentTarget,$(component),build,$(PROJECT_PATH)/build/include/sdkconfig.h))) +$(foreach component,$(COMPONENT_PATHS_BUILDABLE),$(eval $(call GenerateComponentTarget,$(component),clean))) + +include $(SDK_PATH)/make/project_config.mk + +clean: $(addsuffix -clean,$(notdir $(COMPONENT_PATHS_BUILDABLE))) $(EXTRA_CLEAN_TARGETS) + $(vecho) RM $(PROJECT_ELF) + $(Q) rm -f $(PROJECT_ELF) + $(Q) rm -rf $(PROJECT_PATH)/build/include/config $(PROJECT_PATH)/build/include/sdkconfig.h + +endif + diff --git a/make/project_config.mk b/make/project_config.mk new file mode 100644 index 0000000000..2f4d1fa2d9 --- /dev/null +++ b/make/project_config.mk @@ -0,0 +1,63 @@ +# Makefile support for the menuconfig system + +#Find all Kconfig files for all components +COMPONENT_KCONFIGS := $(foreach component,$(COMPONENT_PATHS),$(wildcard $(component)/Kconfig)) +COMPONENT_KCONFIGS_PROJBUILD := $(foreach component,$(COMPONENT_PATHS),$(wildcard $(component)/Kconfig.projbuild)) + +#For doing make menuconfig etc +KCONFIG_TOOL_DIR=$(SDK_PATH)/tools/kconfig + +# clear MAKEFLAGS as the menuconfig makefile uses implicit compile rules +$(KCONFIG_TOOL_DIR)/mconf $(KCONFIG_TOOL_DIR)/conf: + MAKEFLAGS="" \ + CFLAGS="" \ + LDFLAGS="" \ + $(MAKE) -C $(KCONFIG_TOOL_DIR) + +menuconfig: $(KCONFIG_TOOL_DIR)/mconf $(SDK_PATH)/Kconfig $(BUILD_DIR_BASE) + $(vecho) MENUCONFIG + $(Q) KCONFIG_AUTOHEADER=$(PROJECT_PATH)/build/include/sdkconfig.h \ + KCONFIG_CONFIG=$(PROJECT_PATH)/sdkconfig \ + COMPONENT_KCONFIGS="$(COMPONENT_KCONFIGS)" \ + COMPONENT_KCONFIGS_PROJBUILD="$(COMPONENT_KCONFIGS_PROJBUILD)" \ + $(KCONFIG_TOOL_DIR)/mconf $(SDK_PATH)/Kconfig + +ifeq ("$(wildcard $(PROJECT_PATH)/sdkconfig)","") +#No sdkconfig found. Need to run menuconfig to make this if we need it. +$(PROJECT_PATH)/sdkconfig: menuconfig +endif + + +# Work out of whether we have to build the Kconfig makefile +# (auto.conf), or if we're in a situation where we don't need it +NON_CONFIG_TARGETS := clean %-clean get_variable +AUTO_CONF_REGEN_TARGET := $(PROJECT_PATH)/build/include/config/auto.conf + +# disable AUTO_CONF_REGEN_TARGET if all targets are non-config targets +# (and not building default target) +ifneq ("$(MAKECMDGOALS)","") +ifeq ($(filter $(NON_CONFIG_TARGETS), $(MAKECMDGOALS)),$(MAKECMDGOALS)) +AUTO_CONF_REGEN_TARGET := +# dummy target +$(PROJECT_PATH)/build/include/config/auto.conf: +endif +endif + +$(AUTO_CONF_REGEN_TARGET) $(PROJECT_PATH)/build/include/sdkconfig.h: $(PROJECT_PATH)/sdkconfig $(KCONFIG_TOOL_DIR)/conf $(COMPONENT_KCONFIGS) $(COMPONENT_KCONFIGS_PROJBUILD) + $(vecho) GENCONFIG + $(Q) mkdir -p $(PROJECT_PATH)/build/include/config + $(Q) cd build; KCONFIG_AUTOHEADER="$(PROJECT_PATH)/build/include/sdkconfig.h" \ + KCONFIG_CONFIG=$(PROJECT_PATH)/sdkconfig \ + COMPONENT_KCONFIGS="$(COMPONENT_KCONFIGS)" \ + COMPONENT_KCONFIGS_PROJBUILD="$(COMPONENT_KCONFIGS_PROJBUILD)" \ + $(KCONFIG_TOOL_DIR)/conf --silentoldconfig $(SDK_PATH)/Kconfig + $(Q) touch $(AUTO_CONF_REGEN_TARGET) $(PROJECT_PATH)/build/include/sdkconfig.h +# touch to ensure both output files are newer - as 'conf' can also update sdkconfig (a dependency). Without this, +# sometimes you can get an infinite make loop on Windows where sdkconfig always gets regenerated newer +# than the target(!) + +clean: config-clean +.PHONY: config-clean +EXTRA_CLEAN_TARGETS += config-clean +config-clean: + $(MAKE) -C $(KCONFIG_TOOL_DIR) clean diff --git a/tools/gen_esp32part.py b/tools/gen_esp32part.py new file mode 100755 index 0000000000..89da746710 --- /dev/null +++ b/tools/gen_esp32part.py @@ -0,0 +1,343 @@ +#!/usr/bin/env python +# +# ESP32 partition table generation tool +# +# Takes partition input from a CSV file of this format: +# +# Name,Type,SubType,Offset,Size +# +# Any row which starts with # is ignored as a comment. Whitespace at beginning/end of field is ignored. +# +# EXAMPLE CSV FILE CONTENTS +# ------------------------- +""" +# Name, Type, SubType, Offset, Size +factory, 0, 0, , 1M +ota_0, 0, 0x11, , 1M +ota_1, 0, 0x12, , 1M +ota_data, 1, 0, 5M, 128K +""" +# +# SAMPLE USAGE +# ------------ +# +# Convert CSV layout to binary: +# gen_esp32part.py table.csv table.bin +# +# Convert binary to CSV, print on stdout: +# gen_esp32part.py table.bin +# +# FIELD DETAILS +# ------------- +# +# Name: Human-readable name of partition. Values longer than 16 bytes will be truncated. +# +# Type: Numeric value for type field, or special keywords 'app' (for 0x00) or 'data' (for 0x01). +# +# SubType: Numeric value for subtype field, or special keywords depending on known types: +# app (0x00) : factory, ota_0 through ota_15, test. +# data (0x01) : ota, rf, wifi +# +# Default is zero if left blank. +# +# +# Offset: Start of partition. Examples: 0x800, 0x10000, 512, 2K, 1M +# - Offset can be left blank, and gen_esp32part will find the next valid offset (aligned to 64KB for app partitions.) +# +# Size: Size of partition. Examples: 0x800, 0x10000, 512, 2K, 1M +# +# SubType: 0 +# +# Offset: End of previous partition, aligned to 64kB if Type = 0 (app) & 4 bytes otherwise. +# +# +# +import struct +import argparse +import sys + +__version__ = '1.0' + +def debug(msg): + """ Print to stderr """ + sys.stderr.write(msg) + sys.stderr.write('\n') + +class PartitionTable(list): + def __init__(self): + super(PartitionTable, self).__init__(self) + + @classmethod + def from_csv(cls, csv_contents): + res = PartitionTable() + lines = csv_contents.split("\n") + for line_no in range(len(lines)): + line = lines[line_no].strip() + if line.startswith("#") or len(line) == 0: + continue + try: + res.append(PartitionDefinition.from_csv(line)) + except InputError as e: + raise InputError("Error at line %d: %s" % (line_no+1, e)) + except Exception: + debug("Unexpected error parsing line %d: %s" % (line_no+1, line)) + raise + + # fix up missing offsets & negative sizes + last_end = 0x5000 # first offset after partition table + for e in res: + if e.offset is None: + pad_to = 0x10000 if e.type == PartitionDefinition.APP_TYPE else 4 + if last_end % pad_to != 0: + last_end += pad_to - (last_end % pad_to) + e.offset = last_end + if e.size < 0: + e.size = -e.size - e.offset + last_end = e.offset + e.size + + return res + + def __getitem__(self, item): + """ Allow partition table access via name as well as by + numeric index. """ + if isinstance(item, str): + for x in self: + if x.name == item: + return x + raise ValueError("No partition entry named '%s'" % item) + else: + return super(PartitionTable, self).__getitem__(item) + + def verify(self): + # verify each partition individually + for p in self: + p.verify() + # check for overlaps + last = None + for p in sorted(self): + if p.offset < 0x5000: + raise InputError("Partition offset 0x%x is below 0x5000" % p.offset) + if last is not None and p.offset < last.offset + last.size: + raise InputError("Partition at 0x%x overlaps 0x%x-0x%x" % (p.offset, last.offset, last.offset+last.size-1)) + last = p + + @classmethod + def from_binary(cls, b): + if len(b) % 32 != 0: + raise InputError("Partition table length must be a multiple of 32 bytes. Got %d bytes." % len(b)) + result = cls() + for o in range(0,len(b),32): + result.append(PartitionDefinition.from_binary(b[o:o+32])) + return result + + def to_binary(self): + return "".join(e.to_binary() for e in self) + + def to_csv(self, simple_formatting=False): + rows = [ "# Espressif ESP32 Partition Table", + "# Name, Type, SubType, Offset, Size" ] + rows += [ x.to_csv(simple_formatting) for x in self ] + return "\n".join(rows) + +class PartitionDefinition(object): + APP_TYPE = 0x00 + DATA_TYPE = 0x01 + TYPES = { + "app" : APP_TYPE, + "data" : DATA_TYPE, + } + + SUBTYPES = { + APP_TYPE : { + "factory" : 0x00, + "test" : 0x20, + }, + DATA_TYPE : { + "ota" : 0x00, + "rf" : 0x01, + "wifi" : 0x02, + }, + } + + MAGIC_BYTES = "\xAA\x50" + + ALIGNMENT = { + APP_TYPE : 0x1000, + DATA_TYPE : 0x04, + } + + # add subtypes for the 16 OTA slot values ("ota_XXX, etc.") + for ota_slot in range(16): + SUBTYPES[TYPES["app"]]["ota_%d" % ota_slot] = 0x10 + ota_slot + + def __init__(self): + self.name = "" + self.type = None + self.subtype = None + self.offset = None + self.size = None + + @classmethod + def from_csv(cls, line): + """ Parse a line from the CSV """ + line_w_defaults = line + ",,," # lazy way to support default fields + fields = [ f.strip() for f in line_w_defaults.split(",") ] + + res = PartitionDefinition() + res.name = fields[0] + res.type = res.parse_type(fields[1]) + res.subtype = res.parse_subtype(fields[2]) + res.offset = res.parse_address(fields[3]) + res.size = res.parse_address(fields[4]) + if res.size is None: + raise InputError("Size field can't be empty") + return res + + def __eq__(self, other): + return self.name == other.name and self.type == other.type \ + and self.subtype == other.subtype and self.offset == other.offset \ + and self.size == other.size + + def __repr__(self): + def maybe_hex(x): + return "0x%x" % x if x is not None else "None" + return "PartitionDefinition('%s', 0x%x, 0x%x, %s, %s)" % (self.name, self.type, self.subtype or 0, + maybe_hex(self.offset), maybe_hex(self.size)) + + def __str__(self): + return "Part '%s' %d/%d @ 0x%x size 0x%x" % (self.name, self.type, self.subtype, self.offset or -1, self.size or -1) + + def __cmp__(self, other): + return self.offset - other.offset + + def parse_type(self, strval): + if strval == "": + raise InputError("Field 'type' can't be left empty.") + return parse_int(strval, self.TYPES) + + def parse_subtype(self, strval): + if strval == "": + return 0 # default + return parse_int(strval, self.SUBTYPES.get(self.type, {})) + + def parse_address(self, strval): + if strval == "": + return None # PartitionTable will fill in default + return parse_int(strval) + + def verify(self): + if self.type is None: + raise ValidationError("Type field is not set") + if self.subtype is None: + raise ValidationError("Subtype field is not set") + if self.offset is None: + raise ValidationError("Offset field is not set") + align = self.ALIGNMENT.get(self.type, 4) + if self.offset % align: + raise ValidationError("%s offset 0x%x is not aligned to 0x%x" % (self.name, self.offset, align)) + if self.size is None: + raise ValidationError("Size field is not set") + + STRUCT_FORMAT = "<2sBBLL16sL" + + @classmethod + def from_binary(cls, b): + if len(b) != 32: + raise InputError("Partition definition length must be exactly 32 bytes. Got %d bytes." % len(b)) + res = cls() + (magic, res.type, res.subtype, res.offset, + res.size, res.name, reserved) = struct.unpack(cls.STRUCT_FORMAT, b) + if "\x00" in res.name: # strip null byte padding from name string + res.name = res.name[:res.name.index("\x00")] + if magic != cls.MAGIC_BYTES: + raise InputError("Invalid magic bytes (%r) for partition definition" % magic) + if reserved != 0: + debug("WARNING: Partition definition had unexpected reserved value 0x%08x. Newer binary format?" % reserved) + return res + + def to_binary(self): + return struct.pack(self.STRUCT_FORMAT, + self.MAGIC_BYTES, + self.type, self.subtype, + self.offset, self.size, + self.name, + 0) # reserved + + def to_csv(self, simple_formatting=False): + def addr_format(a): + if not simple_formatting: + for (val, suffix) in [ (0x100000, "M"), (0x400, "K") ]: + if a % val == 0: + return "%d%s" % (a / val, suffix) + return "0x%x" % a + + def lookup_keyword(t, keywords): + for k,v in keywords.items(): + if simple_formatting == False and t == v: + return k + return "%d" % t + + return ",".join([ self.name, + lookup_keyword(self.type, self.TYPES), + lookup_keyword(self.subtype, self.SUBTYPES), + addr_format(self.offset), + addr_format(self.size) ]) + +class InputError(RuntimeError): + def __init__(self, e): + super(InputError, self).__init__(e) + +def parse_int(v, keywords={}): + """Generic parser for integer fields - int(x,0) with provision for + k/m/K/M suffixes and 'keyword' value lookup. + """ + try: + for letter, multiplier in [ ("k",1024), ("m",1024*1024) ]: + if v.lower().endswith(letter): + return parse_int(v[:-1], keywords) * multiplier + return int(v, 0) + except ValueError: + if len(keywords) == 0: + raise InputError("Invalid field value %s" % v) + try: + return keywords[v.lower()] + except KeyError: + raise InputError("Value '%s' is not valid. Known keywords: %s" % (v, ", ".join(keywords))) + +def main(): + parser = argparse.ArgumentParser(description='ESP32 partition table utility') + + parser.add_argument('--verify', '-v', help='Verify partition table fields', default=True, action='store_false') + + parser.add_argument('input', help='Path to CSV or binary file to parse. Will use stdin if omitted.', type=argparse.FileType('r'), default=sys.stdin) + parser.add_argument('output', help='Path to output converted binary or CSV file. Will use stdout if omitted, unless the --display argument is also passed (in which case only the summary is printed.)', + type=argparse.FileType('w'), nargs='?', + default=sys.stdout) + + args = parser.parse_args() + + input = args.input.read() + input_is_binary = input[0:2] == PartitionDefinition.MAGIC_BYTES + if input_is_binary: + debug("Parsing binary partition input...") + table = PartitionTable.from_binary(input) + else: + debug("Parsing CSV input...") + table = PartitionTable.from_csv(input) + + if args.verify: + debug("Verifying table...") + table.verify() + + if input_is_binary: + output = table.to_csv() + else: + output = table.to_binary() + args.output.write(output) + +if __name__ == '__main__': + try: + main() + except InputError as e: + print(e) + sys.exit(2) diff --git a/tools/kconfig/.gitignore b/tools/kconfig/.gitignore new file mode 100644 index 0000000000..be603c4fef --- /dev/null +++ b/tools/kconfig/.gitignore @@ -0,0 +1,22 @@ +# +# Generated files +# +config* +*.lex.c +*.tab.c +*.tab.h +zconf.hash.c +*.moc +gconf.glade.h +*.pot +*.mo + +# +# configuration programs +# +conf +mconf +nconf +qconf +gconf +kxgettext diff --git a/tools/kconfig/Kconfig b/tools/kconfig/Kconfig new file mode 100644 index 0000000000..8b13789179 --- /dev/null +++ b/tools/kconfig/Kconfig @@ -0,0 +1 @@ + diff --git a/tools/kconfig/Makefile b/tools/kconfig/Makefile new file mode 100644 index 0000000000..b265e9b381 --- /dev/null +++ b/tools/kconfig/Makefile @@ -0,0 +1,306 @@ +# =========================================================================== +# Kernel configuration targets +# These targets are used from top-level makefile + +PHONY += xconfig gconfig menuconfig config silentoldconfig \ + localmodconfig localyesconfig clean + +ifdef KBUILD_KCONFIG +Kconfig := $(KBUILD_KCONFIG) +else +Kconfig := Kconfig +endif + +ifeq ($(quiet),silent_) +silent := -s +endif + +# We need this, in case the user has it in its environment +unexport CONFIG_ + + +default: mconf conf + +xconfig: qconf + $< $(silent) $(Kconfig) + +gconfig: gconf + $< $(silent) $(Kconfig) + +menuconfig: mconf + $< $(silent) $(Kconfig) + +config: conf + $< $(silent) --oldaskconfig $(Kconfig) + +nconfig: nconf + $< $(silent) $(Kconfig) + +silentoldconfig: conf + $(Q)mkdir -p include/config include/generated + $< $(silent) --$@ $(Kconfig) + +localyesconfig localmodconfig: streamline_config.pl conf + $(Q)mkdir -p include/config include/generated + $(Q)perl $< --$@ . $(Kconfig) > .tmp.config + $(Q)if [ -f .config ]; then \ + cmp -s .tmp.config .config || \ + (mv -f .config .config.old.1; \ + mv -f .tmp.config .config; \ + conf $(silent) --silentoldconfig $(Kconfig); \ + mv -f .config.old.1 .config.old) \ + else \ + mv -f .tmp.config .config; \ + conf $(silent) --silentoldconfig $(Kconfig); \ + fi + $(Q)rm -f .tmp.config + + +# These targets map 1:1 to the commandline options of 'conf' +simple-targets := oldconfig allnoconfig allyesconfig allmodconfig \ + alldefconfig randconfig listnewconfig olddefconfig +PHONY += $(simple-targets) + +$(simple-targets): conf + $< $(silent) --$@ $(Kconfig) + +PHONY += oldnoconfig savedefconfig defconfig + +# oldnoconfig is an alias of olddefconfig, because people already are dependent +# on its behavior (sets new symbols to their default value but not 'n') with the +# counter-intuitive name. +oldnoconfig: olddefconfig + +savedefconfig: conf + $< $(silent) --$@=defconfig $(Kconfig) + +defconfig: conf +ifeq ($(KBUILD_DEFCONFIG),) + $< $(silent) --defconfig $(Kconfig) +else +ifneq ($(wildcard $(srctree)/arch/$(SRCARCH)/configs/$(KBUILD_DEFCONFIG)),) + @$(kecho) "*** Default configuration is based on '$(KBUILD_DEFCONFIG)'" + $(Q)$< $(silent) --defconfig=arch/$(SRCARCH)/configs/$(KBUILD_DEFCONFIG) $(Kconfig) +else + @$(kecho) "*** Default configuration is based on target '$(KBUILD_DEFCONFIG)'" + $(Q) $(MAKE) -f $(srctree)/Makefile $(KBUILD_DEFCONFIG) +endif +endif + +%_defconfig: conf + $(Q)$< $(silent) --defconfig=arch/$(SRCARCH)/configs/$@ $(Kconfig) + +configfiles=$(wildcard $(srctree)/kernel/configs/$@ $(srctree)/arch/$(SRCARCH)/configs/$@) + +%.config: conf + $(if $(call configfiles),, $(error No configuration exists for this target on this architecture)) + $(Q)$(CONFIG_SHELL) $(srctree)/scripts/kconfig/merge_config.sh -m .config $(configfiles) + +$(Q)yes "" | $(MAKE) -f $(srctree)/Makefile oldconfig + +PHONY += kvmconfig +kvmconfig: kvm_guest.config + @: + +PHONY += xenconfig +xenconfig: xen.config + @: + +PHONY += tinyconfig +tinyconfig: + $(Q)$(MAKE) -f $(srctree)/Makefile allnoconfig tiny.config + +# Help text used by make help +help: + @echo ' config - Update current config utilising a line-oriented program' + @echo ' nconfig - Update current config utilising a ncurses menu based' + @echo ' program' + @echo ' menuconfig - Update current config utilising a menu based program' + @echo ' xconfig - Update current config utilising a Qt based front-end' + @echo ' gconfig - Update current config utilising a GTK+ based front-end' + @echo ' oldconfig - Update current config utilising a provided .config as base' + @echo ' localmodconfig - Update current config disabling modules not loaded' + @echo ' localyesconfig - Update current config converting local mods to core' + @echo ' silentoldconfig - Same as oldconfig, but quietly, additionally update deps' + @echo ' defconfig - New config with default from ARCH supplied defconfig' + @echo ' savedefconfig - Save current config as ./defconfig (minimal config)' + @echo ' allnoconfig - New config where all options are answered with no' + @echo ' allyesconfig - New config where all options are accepted with yes' + @echo ' allmodconfig - New config selecting modules when possible' + @echo ' alldefconfig - New config with all symbols set to default' + @echo ' randconfig - New config with random answer to all options' + @echo ' listnewconfig - List new options' + @echo ' olddefconfig - Same as silentoldconfig but sets new symbols to their' + @echo ' default value' + @echo ' kvmconfig - Enable additional options for kvm guest kernel support' + @echo ' xenconfig - Enable additional options for xen dom0 and guest kernel support' + @echo ' tinyconfig - Configure the tiniest possible kernel' + +# lxdialog stuff +check-lxdialog := lxdialog/check-lxdialog.sh + +# Use recursively expanded variables so we do not call gcc unless +# we really need to do so. (Do not call gcc as part of make mrproper) +CFLAGS += $(shell $(CONFIG_SHELL) $(check-lxdialog) -ccflags) \ + -DLOCALE + +# =========================================================================== +# Shared Makefile for the various kconfig executables: +# conf: Used for defconfig, oldconfig and related targets +# nconf: Used for the nconfig target. +# Utilizes ncurses +# mconf: Used for the menuconfig target +# Utilizes the lxdialog package +# qconf: Used for the xconfig target +# Based on Qt which needs to be installed to compile it +# gconf: Used for the gconfig target +# Based on GTK+ which needs to be installed to compile it +# object files used by all kconfig flavours + +lxdialog := lxdialog/checklist.o lxdialog/util.o lxdialog/inputbox.o +lxdialog += lxdialog/textbox.o lxdialog/yesno.o lxdialog/menubox.o + +conf-objs := conf.o zconf.tab.o +mconf-objs := mconf.o zconf.tab.o $(lxdialog) +nconf-objs := nconf.o zconf.tab.o nconf.gui.o +kxgettext-objs := kxgettext.o zconf.tab.o +qconf-cxxobjs := qconf.o +qconf-objs := zconf.tab.o +gconf-objs := gconf.o zconf.tab.o + +hostprogs-y := conf nconf mconf kxgettext qconf gconf + +clean-files := qconf.moc .tmp_qtcheck .tmp_gtkcheck +clean-files += zconf.tab.c zconf.lex.c zconf.hash.c gconf.glade.h +clean-files += $(conf-objs) $(mconf-objs) conf mconf $(lxdialog) + +# Check that we have the required ncurses stuff installed for lxdialog (menuconfig) +PHONY += dochecklxdialog +$(addprefix ,$(lxdialog)): dochecklxdialog +dochecklxdialog: + $(Q)$(CONFIG_SHELL) $(check-lxdialog) -check $(CC) $(CFLAGS) $(LOADLIBES_mconf) + +always := dochecklxdialog + +# Add environment specific flags +EXTRACFLAGS += $(shell $(CONFIG_SHELL) $(srctree)/$(src)/check.sh $(CC) $(CFLAGS)) + +# generated files seem to need this to find local include files +CFLAGS_zconf.lex.o := -I$(src) +CFLAGS_zconf.tab.o := -I$(src) + +LEX_PREFIX_zconf := zconf +YACC_PREFIX_zconf := zconf + +LOADLIBES_qconf = $(KC_QT_LIBS) +CXXFLAGS_qconf.o = $(KC_QT_CFLAGS) + +LOADLIBES_gconf = `pkg-config --libs gtk+-2.0 gmodule-2.0 libglade-2.0` +CFLAGS_gconf.o = `pkg-config --cflags gtk+-2.0 gmodule-2.0 libglade-2.0` \ + -Wno-missing-prototypes + +LOADLIBES_mconf = $(shell $(CONFIG_SHELL) $(check-lxdialog) -ldflags $(CC)) + +LOADLIBES_conf = $(LOADLIBES_mconf) + +LOADLIBES_nconf = $(shell \ + pkg-config --libs menuw panelw ncursesw 2>/dev/null \ + || pkg-config --libs menu panel ncurses 2>/dev/null \ + || echo "-lmenu -lpanel -lncurses" ) + +ifeq ("$(OS)","Windows_NT") +# Windows toolchains don't seem to count libintl +# as a system library +LOADLIBES_mconf += -lintl +LOADLIBES_nconf += -lintl +endif + +qconf.o: .tmp_qtcheck + +ifeq ($(MAKECMDGOALS),xconfig) +.tmp_qtcheck: $(src)/Makefile +-include .tmp_qtcheck + +# Qt needs some extra effort... +.tmp_qtcheck: + @set -e; $(kecho) " CHECK qt"; \ + if pkg-config --exists Qt5Core; then \ + cflags="-std=c++11 -fPIC `pkg-config --cflags Qt5Core Qt5Gui Qt5Widgets`"; \ + libs=`pkg-config --libs Qt5Core Qt5Gui Qt5Widgets`; \ + moc=`pkg-config --variable=host_bins Qt5Core`/moc; \ + elif pkg-config --exists QtCore; then \ + cflags=`pkg-config --cflags QtCore QtGui`; \ + libs=`pkg-config --libs QtCore QtGui`; \ + moc=`pkg-config --variable=moc_location QtCore`; \ + else \ + echo >&2 "*"; \ + echo >&2 "* Could not find Qt via pkg-config."; \ + echo >&2 "* Please install either Qt 4.8 or 5.x. and make sure it's in PKG_CONFIG_PATH"; \ + echo >&2 "*"; \ + exit 1; \ + fi; \ + echo "KC_QT_CFLAGS=$$cflags" > $@; \ + echo "KC_QT_LIBS=$$libs" >> $@; \ + echo "KC_QT_MOC=$$moc" >> $@ +endif + +gconf.o: .tmp_gtkcheck + +ifeq ($(MAKECMDGOALS),gconfig) +-include .tmp_gtkcheck + +# GTK+ needs some extra effort, too... +.tmp_gtkcheck: + @if `pkg-config --exists gtk+-2.0 gmodule-2.0 libglade-2.0`; then \ + if `pkg-config --atleast-version=2.0.0 gtk+-2.0`; then \ + touch $@; \ + else \ + echo >&2 "*"; \ + echo >&2 "* GTK+ is present but version >= 2.0.0 is required."; \ + echo >&2 "*"; \ + false; \ + fi \ + else \ + echo >&2 "*"; \ + echo >&2 "* Unable to find the GTK+ installation. Please make sure that"; \ + echo >&2 "* the GTK+ 2.0 development package is correctly installed..."; \ + echo >&2 "* You need gtk+-2.0, glib-2.0 and libglade-2.0."; \ + echo >&2 "*"; \ + false; \ + fi +endif + +zconf.tab.o: zconf.lex.c zconf.hash.c + +qconf.o: qconf.moc + +quiet_cmd_moc = MOC $@ + cmd_moc = $(KC_QT_MOC) -i $< -o $@ + +%.moc: $(src)/%.h .tmp_qtcheck + $(call cmd,moc) + +# Extract gconf menu items for i18n support +gconf.glade.h: gconf.glade + $(Q)intltool-extract --type=gettext/glade --srcdir=$(srctree) \ + gconf.glade + + +mconf: $(mconf-objs) + $(CC) -o $@ $(mconf-objs) $(LOADLIBES_mconf) + +conf: $(conf-objs) + $(CC) -o $@ $(conf-objs) $(LOADLIBES_conf) + +zconf.tab.c: zconf.lex.c + +zconf.lex.c: zconf.l + flex -L -P zconf -o zconf.lex.c zconf.l + +zconf.hash.c: zconf.gperf + gperf -t --output-file zconf.hash.c -a -C -E -g -k '1,3,$$' -p -t zconf.gperf + +zconf.tab.c: zconf.y + bison -t -l -p zconf -o zconf.tab.c zconf.y + +clean: + rm -f $(clean-files) diff --git a/tools/kconfig/POTFILES.in b/tools/kconfig/POTFILES.in new file mode 100644 index 0000000000..9674573969 --- /dev/null +++ b/tools/kconfig/POTFILES.in @@ -0,0 +1,12 @@ +scripts/kconfig/lxdialog/checklist.c +scripts/kconfig/lxdialog/inputbox.c +scripts/kconfig/lxdialog/menubox.c +scripts/kconfig/lxdialog/textbox.c +scripts/kconfig/lxdialog/util.c +scripts/kconfig/lxdialog/yesno.c +scripts/kconfig/mconf.c +scripts/kconfig/conf.c +scripts/kconfig/confdata.c +scripts/kconfig/gconf.c +scripts/kconfig/gconf.glade.h +scripts/kconfig/qconf.cc diff --git a/tools/kconfig/check.sh b/tools/kconfig/check.sh new file mode 100755 index 0000000000..55b79ba1ba --- /dev/null +++ b/tools/kconfig/check.sh @@ -0,0 +1,13 @@ +#!/bin/sh +# Needed for systems without gettext +$* -x c -o /dev/null - > /dev/null 2>&1 << EOF +#include +int main() +{ + gettext(""); + return 0; +} +EOF +if [ ! "$?" -eq "0" ]; then + echo -DKBUILD_NO_NLS; +fi diff --git a/tools/kconfig/conf.c b/tools/kconfig/conf.c new file mode 100644 index 0000000000..866369f10f --- /dev/null +++ b/tools/kconfig/conf.c @@ -0,0 +1,723 @@ +/* + * Copyright (C) 2002 Roman Zippel + * Released under the terms of the GNU GPL v2.0. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "lkc.h" + +static void conf(struct menu *menu); +static void check_conf(struct menu *menu); +static void xfgets(char *str, int size, FILE *in); + +enum input_mode { + oldaskconfig, + silentoldconfig, + oldconfig, + allnoconfig, + allyesconfig, + allmodconfig, + alldefconfig, + randconfig, + defconfig, + savedefconfig, + listnewconfig, + olddefconfig, +} input_mode = oldaskconfig; + +static int indent = 1; +static int tty_stdio; +static int valid_stdin = 1; +static int sync_kconfig; +static int conf_cnt; +static char line[PATH_MAX]; +static struct menu *rootEntry; + +static void print_help(struct menu *menu) +{ + struct gstr help = str_new(); + + menu_get_ext_help(menu, &help); + + printf("\n%s\n", str_get(&help)); + str_free(&help); +} + +static void strip(char *str) +{ + char *p = str; + int l; + + while ((isspace(*p))) + p++; + l = strlen(p); + if (p != str) + memmove(str, p, l + 1); + if (!l) + return; + p = str + l - 1; + while ((isspace(*p))) + *p-- = 0; +} + +static void check_stdin(void) +{ + if (!valid_stdin) { + printf(_("aborted!\n\n")); + printf(_("Console input/output is redirected. ")); + printf(_("Run 'make oldconfig' to update configuration.\n\n")); + exit(1); + } +} + +static int conf_askvalue(struct symbol *sym, const char *def) +{ + enum symbol_type type = sym_get_type(sym); + + if (!sym_has_value(sym)) + printf(_("(NEW) ")); + + line[0] = '\n'; + line[1] = 0; + + if (!sym_is_changable(sym)) { + printf("%s\n", def); + line[0] = '\n'; + line[1] = 0; + return 0; + } + + switch (input_mode) { + case oldconfig: + case silentoldconfig: + if (sym_has_value(sym)) { + printf("%s\n", def); + return 0; + } + check_stdin(); + /* fall through */ + case oldaskconfig: + fflush(stdout); + xfgets(line, sizeof(line), stdin); + if (!tty_stdio) + printf("\n"); + return 1; + default: + break; + } + + switch (type) { + case S_INT: + case S_HEX: + case S_STRING: + printf("%s\n", def); + return 1; + default: + ; + } + printf("%s", line); + return 1; +} + +static int conf_string(struct menu *menu) +{ + struct symbol *sym = menu->sym; + const char *def; + + while (1) { + printf("%*s%s ", indent - 1, "", _(menu->prompt->text)); + printf("(%s) ", sym->name); + def = sym_get_string_value(sym); + if (sym_get_string_value(sym)) + printf("[%s] ", def); + if (!conf_askvalue(sym, def)) + return 0; + switch (line[0]) { + case '\n': + break; + case '?': + /* print help */ + if (line[1] == '\n') { + print_help(menu); + def = NULL; + break; + } + /* fall through */ + default: + line[strlen(line)-1] = 0; + def = line; + } + if (def && sym_set_string_value(sym, def)) + return 0; + } +} + +static int conf_sym(struct menu *menu) +{ + struct symbol *sym = menu->sym; + tristate oldval, newval; + + while (1) { + printf("%*s%s ", indent - 1, "", _(menu->prompt->text)); + if (sym->name) + printf("(%s) ", sym->name); + putchar('['); + oldval = sym_get_tristate_value(sym); + switch (oldval) { + case no: + putchar('N'); + break; + case mod: + putchar('M'); + break; + case yes: + putchar('Y'); + break; + } + if (oldval != no && sym_tristate_within_range(sym, no)) + printf("/n"); + if (oldval != mod && sym_tristate_within_range(sym, mod)) + printf("/m"); + if (oldval != yes && sym_tristate_within_range(sym, yes)) + printf("/y"); + if (menu_has_help(menu)) + printf("/?"); + printf("] "); + if (!conf_askvalue(sym, sym_get_string_value(sym))) + return 0; + strip(line); + + switch (line[0]) { + case 'n': + case 'N': + newval = no; + if (!line[1] || !strcmp(&line[1], "o")) + break; + continue; + case 'm': + case 'M': + newval = mod; + if (!line[1]) + break; + continue; + case 'y': + case 'Y': + newval = yes; + if (!line[1] || !strcmp(&line[1], "es")) + break; + continue; + case 0: + newval = oldval; + break; + case '?': + goto help; + default: + continue; + } + if (sym_set_tristate_value(sym, newval)) + return 0; +help: + print_help(menu); + } +} + +static int conf_choice(struct menu *menu) +{ + struct symbol *sym, *def_sym; + struct menu *child; + bool is_new; + + sym = menu->sym; + is_new = !sym_has_value(sym); + if (sym_is_changable(sym)) { + conf_sym(menu); + sym_calc_value(sym); + switch (sym_get_tristate_value(sym)) { + case no: + return 1; + case mod: + return 0; + case yes: + break; + } + } else { + switch (sym_get_tristate_value(sym)) { + case no: + return 1; + case mod: + printf("%*s%s\n", indent - 1, "", _(menu_get_prompt(menu))); + return 0; + case yes: + break; + } + } + + while (1) { + int cnt, def; + + printf("%*s%s\n", indent - 1, "", _(menu_get_prompt(menu))); + def_sym = sym_get_choice_value(sym); + cnt = def = 0; + line[0] = 0; + for (child = menu->list; child; child = child->next) { + if (!menu_is_visible(child)) + continue; + if (!child->sym) { + printf("%*c %s\n", indent, '*', _(menu_get_prompt(child))); + continue; + } + cnt++; + if (child->sym == def_sym) { + def = cnt; + printf("%*c", indent, '>'); + } else + printf("%*c", indent, ' '); + printf(" %d. %s", cnt, _(menu_get_prompt(child))); + if (child->sym->name) + printf(" (%s)", child->sym->name); + if (!sym_has_value(child->sym)) + printf(_(" (NEW)")); + printf("\n"); + } + printf(_("%*schoice"), indent - 1, ""); + if (cnt == 1) { + printf("[1]: 1\n"); + goto conf_childs; + } + printf("[1-%d", cnt); + if (menu_has_help(menu)) + printf("?"); + printf("]: "); + switch (input_mode) { + case oldconfig: + case silentoldconfig: + if (!is_new) { + cnt = def; + printf("%d\n", cnt); + break; + } + check_stdin(); + /* fall through */ + case oldaskconfig: + fflush(stdout); + xfgets(line, sizeof(line), stdin); + strip(line); + if (line[0] == '?') { + print_help(menu); + continue; + } + if (!line[0]) + cnt = def; + else if (isdigit(line[0])) + cnt = atoi(line); + else + continue; + break; + default: + break; + } + + conf_childs: + for (child = menu->list; child; child = child->next) { + if (!child->sym || !menu_is_visible(child)) + continue; + if (!--cnt) + break; + } + if (!child) + continue; + if (line[0] && line[strlen(line) - 1] == '?') { + print_help(child); + continue; + } + sym_set_choice_value(sym, child->sym); + for (child = child->list; child; child = child->next) { + indent += 2; + conf(child); + indent -= 2; + } + return 1; + } +} + +static void conf(struct menu *menu) +{ + struct symbol *sym; + struct property *prop; + struct menu *child; + + if (!menu_is_visible(menu)) + return; + + sym = menu->sym; + prop = menu->prompt; + if (prop) { + const char *prompt; + + switch (prop->type) { + case P_MENU: + if ((input_mode == silentoldconfig || + input_mode == listnewconfig || + input_mode == olddefconfig) && + rootEntry != menu) { + check_conf(menu); + return; + } + /* fall through */ + case P_COMMENT: + prompt = menu_get_prompt(menu); + if (prompt) + printf("%*c\n%*c %s\n%*c\n", + indent, '*', + indent, '*', _(prompt), + indent, '*'); + default: + ; + } + } + + if (!sym) + goto conf_childs; + + if (sym_is_choice(sym)) { + conf_choice(menu); + if (sym->curr.tri != mod) + return; + goto conf_childs; + } + + switch (sym->type) { + case S_INT: + case S_HEX: + case S_STRING: + conf_string(menu); + break; + default: + conf_sym(menu); + break; + } + +conf_childs: + if (sym) + indent += 2; + for (child = menu->list; child; child = child->next) + conf(child); + if (sym) + indent -= 2; +} + +static void check_conf(struct menu *menu) +{ + struct symbol *sym; + struct menu *child; + + if (!menu_is_visible(menu)) + return; + + sym = menu->sym; + if (sym && !sym_has_value(sym)) { + if (sym_is_changable(sym) || + (sym_is_choice(sym) && sym_get_tristate_value(sym) == yes)) { + if (input_mode == listnewconfig) { + if (sym->name && !sym_is_choice_value(sym)) { + printf("%s%s\n", CONFIG_, sym->name); + } + } else if (input_mode != olddefconfig) { + if (!conf_cnt++) + printf(_("*\n* Restart config...\n*\n")); + rootEntry = menu_get_parent_menu(menu); + conf(rootEntry); + } + } + } + + for (child = menu->list; child; child = child->next) + check_conf(child); +} + +static struct option long_opts[] = { + {"oldaskconfig", no_argument, NULL, oldaskconfig}, + {"oldconfig", no_argument, NULL, oldconfig}, + {"silentoldconfig", no_argument, NULL, silentoldconfig}, + {"defconfig", optional_argument, NULL, defconfig}, + {"savedefconfig", required_argument, NULL, savedefconfig}, + {"allnoconfig", no_argument, NULL, allnoconfig}, + {"allyesconfig", no_argument, NULL, allyesconfig}, + {"allmodconfig", no_argument, NULL, allmodconfig}, + {"alldefconfig", no_argument, NULL, alldefconfig}, + {"randconfig", no_argument, NULL, randconfig}, + {"listnewconfig", no_argument, NULL, listnewconfig}, + {"olddefconfig", no_argument, NULL, olddefconfig}, + /* + * oldnoconfig is an alias of olddefconfig, because people already + * are dependent on its behavior(sets new symbols to their default + * value but not 'n') with the counter-intuitive name. + */ + {"oldnoconfig", no_argument, NULL, olddefconfig}, + {NULL, 0, NULL, 0} +}; + +static void conf_usage(const char *progname) +{ + + printf("Usage: %s [-s] [option] \n", progname); + printf("[option] is _one_ of the following:\n"); + printf(" --listnewconfig List new options\n"); + printf(" --oldaskconfig Start a new configuration using a line-oriented program\n"); + printf(" --oldconfig Update a configuration using a provided .config as base\n"); + printf(" --silentoldconfig Same as oldconfig, but quietly, additionally update deps\n"); + printf(" --olddefconfig Same as silentoldconfig but sets new symbols to their default value\n"); + printf(" --oldnoconfig An alias of olddefconfig\n"); + printf(" --defconfig New config with default defined in \n"); + printf(" --savedefconfig Save the minimal current configuration to \n"); + printf(" --allnoconfig New config where all options are answered with no\n"); + printf(" --allyesconfig New config where all options are answered with yes\n"); + printf(" --allmodconfig New config where all options are answered with mod\n"); + printf(" --alldefconfig New config with all symbols set to default\n"); + printf(" --randconfig New config with random answer to all options\n"); +} + +int main(int ac, char **av) +{ + const char *progname = av[0]; + int opt; + const char *name, *defconfig_file = NULL /* gcc uninit */; + struct stat tmpstat; + + setlocale(LC_ALL, ""); + bindtextdomain(PACKAGE, LOCALEDIR); + textdomain(PACKAGE); + + tty_stdio = isatty(0) && isatty(1) && isatty(2); + + while ((opt = getopt_long(ac, av, "s", long_opts, NULL)) != -1) { + if (opt == 's') { + conf_set_message_callback(NULL); + continue; + } + input_mode = (enum input_mode)opt; + switch (opt) { + case silentoldconfig: + sync_kconfig = 1; + break; + case defconfig: + case savedefconfig: + defconfig_file = optarg; + break; + case randconfig: + { + struct timeval now; + unsigned int seed; + char *seed_env; + + /* + * Use microseconds derived seed, + * compensate for systems where it may be zero + */ + gettimeofday(&now, NULL); + seed = (unsigned int)((now.tv_sec + 1) * (now.tv_usec + 1)); + + seed_env = getenv("KCONFIG_SEED"); + if( seed_env && *seed_env ) { + char *endp; + int tmp = (int)strtol(seed_env, &endp, 0); + if (*endp == '\0') { + seed = tmp; + } + } + fprintf( stderr, "KCONFIG_SEED=0x%X\n", seed ); + srand(seed); + break; + } + case oldaskconfig: + case oldconfig: + case allnoconfig: + case allyesconfig: + case allmodconfig: + case alldefconfig: + case listnewconfig: + case olddefconfig: + break; + case '?': + conf_usage(progname); + exit(1); + break; + } + } + if (ac == optind) { + printf(_("%s: Kconfig file missing\n"), av[0]); + conf_usage(progname); + exit(1); + } + name = av[optind]; + conf_parse(name); + //zconfdump(stdout); + if (sync_kconfig) { + name = conf_get_configname(); + if (stat(name, &tmpstat)) { + fprintf(stderr, _("***\n" + "*** Configuration file \"%s\" not found!\n" + "***\n" + "*** Please run some configurator (e.g. \"make oldconfig\" or\n" + "*** \"make menuconfig\" or \"make xconfig\").\n" + "***\n"), name); + exit(1); + } + } + + switch (input_mode) { + case defconfig: + if (!defconfig_file) + defconfig_file = conf_get_default_confname(); + if (conf_read(defconfig_file)) { + printf(_("***\n" + "*** Can't find default configuration \"%s\"!\n" + "***\n"), defconfig_file); + exit(1); + } + break; + case savedefconfig: + case silentoldconfig: + case oldaskconfig: + case oldconfig: + case listnewconfig: + case olddefconfig: + conf_read(NULL); + break; + case allnoconfig: + case allyesconfig: + case allmodconfig: + case alldefconfig: + case randconfig: + name = getenv("KCONFIG_ALLCONFIG"); + if (!name) + break; + if ((strcmp(name, "") != 0) && (strcmp(name, "1") != 0)) { + if (conf_read_simple(name, S_DEF_USER)) { + fprintf(stderr, + _("*** Can't read seed configuration \"%s\"!\n"), + name); + exit(1); + } + break; + } + switch (input_mode) { + case allnoconfig: name = "allno.config"; break; + case allyesconfig: name = "allyes.config"; break; + case allmodconfig: name = "allmod.config"; break; + case alldefconfig: name = "alldef.config"; break; + case randconfig: name = "allrandom.config"; break; + default: break; + } + if (conf_read_simple(name, S_DEF_USER) && + conf_read_simple("all.config", S_DEF_USER)) { + fprintf(stderr, + _("*** KCONFIG_ALLCONFIG set, but no \"%s\" or \"all.config\" file found\n"), + name); + exit(1); + } + break; + default: + break; + } + + if (sync_kconfig) { + if (conf_get_changed()) { + name = getenv("KCONFIG_NOSILENTUPDATE"); + if (name && *name) { + fprintf(stderr, + _("\n*** The configuration requires explicit update.\n\n")); + return 1; + } + } + valid_stdin = tty_stdio; + } + + switch (input_mode) { + case allnoconfig: + conf_set_all_new_symbols(def_no); + break; + case allyesconfig: + conf_set_all_new_symbols(def_yes); + break; + case allmodconfig: + conf_set_all_new_symbols(def_mod); + break; + case alldefconfig: + conf_set_all_new_symbols(def_default); + break; + case randconfig: + /* Really nothing to do in this loop */ + while (conf_set_all_new_symbols(def_random)) ; + break; + case defconfig: + conf_set_all_new_symbols(def_default); + break; + case savedefconfig: + break; + case oldaskconfig: + rootEntry = &rootmenu; + conf(&rootmenu); + input_mode = silentoldconfig; + /* fall through */ + case oldconfig: + case listnewconfig: + case olddefconfig: + case silentoldconfig: + /* Update until a loop caused no more changes */ + do { + conf_cnt = 0; + check_conf(&rootmenu); + } while (conf_cnt && + (input_mode != listnewconfig && + input_mode != olddefconfig)); + break; + } + + if (sync_kconfig) { + /* silentoldconfig is used during the build so we shall update autoconf. + * All other commands are only used to generate a config. + */ + if (conf_get_changed() && conf_write(NULL)) { + fprintf(stderr, _("\n*** Error during writing of the configuration.\n\n")); + exit(1); + } + if (conf_write_autoconf()) { + fprintf(stderr, _("\n*** Error during update of the configuration.\n\n")); + return 1; + } + } else if (input_mode == savedefconfig) { + if (conf_write_defconfig(defconfig_file)) { + fprintf(stderr, _("n*** Error while saving defconfig to: %s\n\n"), + defconfig_file); + return 1; + } + } else if (input_mode != listnewconfig) { + if (conf_write(NULL)) { + fprintf(stderr, _("\n*** Error during writing of the configuration.\n\n")); + exit(1); + } + } + return 0; +} + +/* + * Helper function to facilitate fgets() by Jean Sacren. + */ +void xfgets(char *str, int size, FILE *in) +{ + if (fgets(str, size, in) == NULL) + fprintf(stderr, "\nError in reading or end of file.\n"); +} diff --git a/tools/kconfig/confdata.c b/tools/kconfig/confdata.c new file mode 100644 index 0000000000..dd243d2abd --- /dev/null +++ b/tools/kconfig/confdata.c @@ -0,0 +1,1247 @@ +/* + * Copyright (C) 2002 Roman Zippel + * Released under the terms of the GNU GPL v2.0. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "lkc.h" + +struct conf_printer { + void (*print_symbol)(FILE *, struct symbol *, const char *, void *); + void (*print_comment)(FILE *, const char *, void *); +}; + +static void conf_warning(const char *fmt, ...) + __attribute__ ((format (printf, 1, 2))); + +static void conf_message(const char *fmt, ...) + __attribute__ ((format (printf, 1, 2))); + +static const char *conf_filename; +static int conf_lineno, conf_warnings, conf_unsaved; + +const char conf_defname[] = "arch/$ARCH/defconfig"; + +static void conf_warning(const char *fmt, ...) +{ + va_list ap; + va_start(ap, fmt); + fprintf(stderr, "%s:%d:warning: ", conf_filename, conf_lineno); + vfprintf(stderr, fmt, ap); + fprintf(stderr, "\n"); + va_end(ap); + conf_warnings++; +} + +static void conf_default_message_callback(const char *fmt, va_list ap) +{ + printf("#\n# "); + vprintf(fmt, ap); + printf("\n#\n"); +} + +static void (*conf_message_callback) (const char *fmt, va_list ap) = + conf_default_message_callback; +void conf_set_message_callback(void (*fn) (const char *fmt, va_list ap)) +{ + conf_message_callback = fn; +} + +static void conf_message(const char *fmt, ...) +{ + va_list ap; + + va_start(ap, fmt); + if (conf_message_callback) + conf_message_callback(fmt, ap); + va_end(ap); +} + +const char *conf_get_configname(void) +{ + char *name = getenv("KCONFIG_CONFIG"); + + return name ? name : ".config"; +} + +const char *conf_get_autoconfig_name(void) +{ + char *name = getenv("KCONFIG_AUTOCONFIG"); + + return name ? name : "include/config/auto.conf"; +} + +static char *conf_expand_value(const char *in) +{ + struct symbol *sym; + const char *src; + static char res_value[SYMBOL_MAXLENGTH]; + char *dst, name[SYMBOL_MAXLENGTH]; + + res_value[0] = 0; + dst = name; + while ((src = strchr(in, '$'))) { + strncat(res_value, in, src - in); + src++; + dst = name; + while (isalnum(*src) || *src == '_') + *dst++ = *src++; + *dst = 0; + sym = sym_lookup(name, 0); + sym_calc_value(sym); + strcat(res_value, sym_get_string_value(sym)); + in = src; + } + strcat(res_value, in); + + return res_value; +} + +char *conf_get_default_confname(void) +{ + struct stat buf; + static char fullname[PATH_MAX+1]; + char *env, *name; + + name = conf_expand_value(conf_defname); + env = getenv(SRCTREE); + if (env) { + sprintf(fullname, "%s/%s", env, name); + if (!stat(fullname, &buf)) + return fullname; + } + return name; +} + +static int conf_set_sym_val(struct symbol *sym, int def, int def_flags, char *p) +{ + char *p2; + + switch (sym->type) { + case S_TRISTATE: + if (p[0] == 'm') { + sym->def[def].tri = mod; + sym->flags |= def_flags; + break; + } + /* fall through */ + case S_BOOLEAN: + if (p[0] == 'y') { + sym->def[def].tri = yes; + sym->flags |= def_flags; + break; + } + if (p[0] == 'n') { + sym->def[def].tri = no; + sym->flags |= def_flags; + break; + } + if (def != S_DEF_AUTO) + conf_warning("symbol value '%s' invalid for %s", + p, sym->name); + return 1; + case S_OTHER: + if (*p != '"') { + for (p2 = p; *p2 && !isspace(*p2); p2++) + ; + sym->type = S_STRING; + goto done; + } + /* fall through */ + case S_STRING: + if (*p++ != '"') + break; + for (p2 = p; (p2 = strpbrk(p2, "\"\\")); p2++) { + if (*p2 == '"') { + *p2 = 0; + break; + } + memmove(p2, p2 + 1, strlen(p2)); + } + if (!p2) { + if (def != S_DEF_AUTO) + conf_warning("invalid string found"); + return 1; + } + /* fall through */ + case S_INT: + case S_HEX: + done: + if (sym_string_valid(sym, p)) { + sym->def[def].val = strdup(p); + sym->flags |= def_flags; + } else { + if (def != S_DEF_AUTO) + conf_warning("symbol value '%s' invalid for %s", + p, sym->name); + return 1; + } + break; + default: + ; + } + return 0; +} + +#define LINE_GROWTH 16 +static int add_byte(int c, char **lineptr, size_t slen, size_t *n) +{ + char *nline; + size_t new_size = slen + 1; + if (new_size > *n) { + new_size += LINE_GROWTH - 1; + new_size *= 2; + nline = realloc(*lineptr, new_size); + if (!nline) + return -1; + + *lineptr = nline; + *n = new_size; + } + + (*lineptr)[slen] = c; + + return 0; +} + +static ssize_t compat_getline(char **lineptr, size_t *n, FILE *stream) +{ + char *line = *lineptr; + size_t slen = 0; + + for (;;) { + int c = getc(stream); + + switch (c) { + case '\n': + if (add_byte(c, &line, slen, n) < 0) + goto e_out; + slen++; + /* fall through */ + case EOF: + if (add_byte('\0', &line, slen, n) < 0) + goto e_out; + *lineptr = line; + if (slen == 0) + return -1; + return slen; + default: + if (add_byte(c, &line, slen, n) < 0) + goto e_out; + slen++; + } + } + +e_out: + line[slen-1] = '\0'; + *lineptr = line; + return -1; +} + +int conf_read_simple(const char *name, int def) +{ + FILE *in = NULL; + char *line = NULL; + size_t line_asize = 0; + char *p, *p2; + struct symbol *sym; + int i, def_flags; + + if (name) { + in = zconf_fopen(name); + } else { + struct property *prop; + + name = conf_get_configname(); + in = zconf_fopen(name); + if (in) + goto load; + sym_add_change_count(1); + if (!sym_defconfig_list) + return 1; + + for_all_defaults(sym_defconfig_list, prop) { + if (expr_calc_value(prop->visible.expr) == no || + prop->expr->type != E_SYMBOL) + continue; + name = conf_expand_value(prop->expr->left.sym->name); + in = zconf_fopen(name); + if (in) { + conf_message(_("using defaults found in %s"), + name); + goto load; + } + } + } + if (!in) + return 1; + +load: + conf_filename = name; + conf_lineno = 0; + conf_warnings = 0; + conf_unsaved = 0; + + def_flags = SYMBOL_DEF << def; + for_all_symbols(i, sym) { + sym->flags |= SYMBOL_CHANGED; + sym->flags &= ~(def_flags|SYMBOL_VALID); + if (sym_is_choice(sym)) + sym->flags |= def_flags; + switch (sym->type) { + case S_INT: + case S_HEX: + case S_STRING: + if (sym->def[def].val) + free(sym->def[def].val); + /* fall through */ + default: + sym->def[def].val = NULL; + sym->def[def].tri = no; + } + } + + while (compat_getline(&line, &line_asize, in) != -1) { + conf_lineno++; + sym = NULL; + if (line[0] == '#') { + if (memcmp(line + 2, CONFIG_, strlen(CONFIG_))) + continue; + p = strchr(line + 2 + strlen(CONFIG_), ' '); + if (!p) + continue; + *p++ = 0; + if (strncmp(p, "is not set", 10)) + continue; + if (def == S_DEF_USER) { + sym = sym_find(line + 2 + strlen(CONFIG_)); + if (!sym) { + sym_add_change_count(1); + goto setsym; + } + } else { + sym = sym_lookup(line + 2 + strlen(CONFIG_), 0); + if (sym->type == S_UNKNOWN) + sym->type = S_BOOLEAN; + } + if (sym->flags & def_flags) { + conf_warning("override: reassigning to symbol %s", sym->name); + } + switch (sym->type) { + case S_BOOLEAN: + case S_TRISTATE: + sym->def[def].tri = no; + sym->flags |= def_flags; + break; + default: + ; + } + } else if (memcmp(line, CONFIG_, strlen(CONFIG_)) == 0) { + p = strchr(line + strlen(CONFIG_), '='); + if (!p) + continue; + *p++ = 0; + p2 = strchr(p, '\n'); + if (p2) { + *p2-- = 0; + if (*p2 == '\r') + *p2 = 0; + } + if (def == S_DEF_USER) { + sym = sym_find(line + strlen(CONFIG_)); + if (!sym) { + sym_add_change_count(1); + goto setsym; + } + } else { + sym = sym_lookup(line + strlen(CONFIG_), 0); + if (sym->type == S_UNKNOWN) + sym->type = S_OTHER; + } + if (sym->flags & def_flags) { + conf_warning("override: reassigning to symbol %s", sym->name); + } + if (conf_set_sym_val(sym, def, def_flags, p)) + continue; + } else { + if (line[0] != '\r' && line[0] != '\n') + conf_warning("unexpected data"); + continue; + } +setsym: + if (sym && sym_is_choice_value(sym)) { + struct symbol *cs = prop_get_symbol(sym_get_choice_prop(sym)); + switch (sym->def[def].tri) { + case no: + break; + case mod: + if (cs->def[def].tri == yes) { + conf_warning("%s creates inconsistent choice state", sym->name); + cs->flags &= ~def_flags; + } + break; + case yes: + if (cs->def[def].tri != no) + conf_warning("override: %s changes choice state", sym->name); + cs->def[def].val = sym; + break; + } + cs->def[def].tri = EXPR_OR(cs->def[def].tri, sym->def[def].tri); + } + } + free(line); + fclose(in); + return 0; +} + +int conf_read(const char *name) +{ + struct symbol *sym; + int i; + + sym_set_change_count(0); + + if (conf_read_simple(name, S_DEF_USER)) { + sym_calc_value(modules_sym); + return 1; + } + + sym_calc_value(modules_sym); + + for_all_symbols(i, sym) { + sym_calc_value(sym); + if (sym_is_choice(sym) || (sym->flags & SYMBOL_AUTO)) + continue; + if (sym_has_value(sym) && (sym->flags & SYMBOL_WRITE)) { + /* check that calculated value agrees with saved value */ + switch (sym->type) { + case S_BOOLEAN: + case S_TRISTATE: + if (sym->def[S_DEF_USER].tri != sym_get_tristate_value(sym)) + break; + if (!sym_is_choice(sym)) + continue; + /* fall through */ + default: + if (!strcmp(sym->curr.val, sym->def[S_DEF_USER].val)) + continue; + break; + } + } else if (!sym_has_value(sym) && !(sym->flags & SYMBOL_WRITE)) + /* no previous value and not saved */ + continue; + conf_unsaved++; + /* maybe print value in verbose mode... */ + } + + for_all_symbols(i, sym) { + if (sym_has_value(sym) && !sym_is_choice_value(sym)) { + /* Reset values of generates values, so they'll appear + * as new, if they should become visible, but that + * doesn't quite work if the Kconfig and the saved + * configuration disagree. + */ + if (sym->visible == no && !conf_unsaved) + sym->flags &= ~SYMBOL_DEF_USER; + switch (sym->type) { + case S_STRING: + case S_INT: + case S_HEX: + /* Reset a string value if it's out of range */ + if (sym_string_within_range(sym, sym->def[S_DEF_USER].val)) + break; + sym->flags &= ~(SYMBOL_VALID|SYMBOL_DEF_USER); + conf_unsaved++; + break; + default: + break; + } + } + } + + sym_add_change_count(conf_warnings || conf_unsaved); + + return 0; +} + +/* + * Kconfig configuration printer + * + * This printer is used when generating the resulting configuration after + * kconfig invocation and `defconfig' files. Unset symbol might be omitted by + * passing a non-NULL argument to the printer. + * + */ +static void +kconfig_print_symbol(FILE *fp, struct symbol *sym, const char *value, void *arg) +{ + + switch (sym->type) { + case S_BOOLEAN: + case S_TRISTATE: + if (*value == 'n') { + bool skip_unset = (arg != NULL); + + if (!skip_unset) + fprintf(fp, "# %s%s is not set\n", + CONFIG_, sym->name); + return; + } + break; + default: + break; + } + + fprintf(fp, "%s%s=%s\n", CONFIG_, sym->name, value); +} + +static void +kconfig_print_comment(FILE *fp, const char *value, void *arg) +{ + const char *p = value; + size_t l; + + for (;;) { + l = strcspn(p, "\n"); + fprintf(fp, "#"); + if (l) { + fprintf(fp, " "); + xfwrite(p, l, 1, fp); + p += l; + } + fprintf(fp, "\n"); + if (*p++ == '\0') + break; + } +} + +static struct conf_printer kconfig_printer_cb = +{ + .print_symbol = kconfig_print_symbol, + .print_comment = kconfig_print_comment, +}; + +/* + * Header printer + * + * This printer is used when generating the `include/generated/autoconf.h' file. + */ +static void +header_print_symbol(FILE *fp, struct symbol *sym, const char *value, void *arg) +{ + + switch (sym->type) { + case S_BOOLEAN: + case S_TRISTATE: { + const char *suffix = ""; + + switch (*value) { + case 'n': + break; + case 'm': + suffix = "_MODULE"; + /* fall through */ + default: + fprintf(fp, "#define %s%s%s 1\n", + CONFIG_, sym->name, suffix); + } + break; + } + case S_HEX: { + const char *prefix = ""; + + if (value[0] != '0' || (value[1] != 'x' && value[1] != 'X')) + prefix = "0x"; + fprintf(fp, "#define %s%s %s%s\n", + CONFIG_, sym->name, prefix, value); + break; + } + case S_STRING: + case S_INT: + fprintf(fp, "#define %s%s %s\n", + CONFIG_, sym->name, value); + break; + default: + break; + } + +} + +static void +header_print_comment(FILE *fp, const char *value, void *arg) +{ + const char *p = value; + size_t l; + + fprintf(fp, "/*\n"); + for (;;) { + l = strcspn(p, "\n"); + fprintf(fp, " *"); + if (l) { + fprintf(fp, " "); + xfwrite(p, l, 1, fp); + p += l; + } + fprintf(fp, "\n"); + if (*p++ == '\0') + break; + } + fprintf(fp, " */\n"); +} + +static struct conf_printer header_printer_cb = +{ + .print_symbol = header_print_symbol, + .print_comment = header_print_comment, +}; + +/* + * Tristate printer + * + * This printer is used when generating the `include/config/tristate.conf' file. + */ +static void +tristate_print_symbol(FILE *fp, struct symbol *sym, const char *value, void *arg) +{ + + if (sym->type == S_TRISTATE && *value != 'n') + fprintf(fp, "%s%s=%c\n", CONFIG_, sym->name, (char)toupper(*value)); +} + +static struct conf_printer tristate_printer_cb = +{ + .print_symbol = tristate_print_symbol, + .print_comment = kconfig_print_comment, +}; + +static void conf_write_symbol(FILE *fp, struct symbol *sym, + struct conf_printer *printer, void *printer_arg) +{ + const char *str; + + switch (sym->type) { + case S_OTHER: + case S_UNKNOWN: + break; + case S_STRING: + str = sym_get_string_value(sym); + str = sym_escape_string_value(str); + printer->print_symbol(fp, sym, str, printer_arg); + free((void *)str); + break; + default: + str = sym_get_string_value(sym); + printer->print_symbol(fp, sym, str, printer_arg); + } +} + +static void +conf_write_heading(FILE *fp, struct conf_printer *printer, void *printer_arg) +{ + char buf[256]; + + snprintf(buf, sizeof(buf), + "\n" + "Automatically generated file; DO NOT EDIT.\n" + "%s\n", + rootmenu.prompt->text); + + printer->print_comment(fp, buf, printer_arg); +} + +/* + * Write out a minimal config. + * All values that has default values are skipped as this is redundant. + */ +int conf_write_defconfig(const char *filename) +{ + struct symbol *sym; + struct menu *menu; + FILE *out; + + out = fopen(filename, "w"); + if (!out) + return 1; + + sym_clear_all_valid(); + + /* Traverse all menus to find all relevant symbols */ + menu = rootmenu.list; + + while (menu != NULL) + { + sym = menu->sym; + if (sym == NULL) { + if (!menu_is_visible(menu)) + goto next_menu; + } else if (!sym_is_choice(sym)) { + sym_calc_value(sym); + if (!(sym->flags & SYMBOL_WRITE)) + goto next_menu; + sym->flags &= ~SYMBOL_WRITE; + /* If we cannot change the symbol - skip */ + if (!sym_is_changable(sym)) + goto next_menu; + /* If symbol equals to default value - skip */ + if (strcmp(sym_get_string_value(sym), sym_get_string_default(sym)) == 0) + goto next_menu; + + /* + * If symbol is a choice value and equals to the + * default for a choice - skip. + * But only if value is bool and equal to "y" and + * choice is not "optional". + * (If choice is "optional" then all values can be "n") + */ + if (sym_is_choice_value(sym)) { + struct symbol *cs; + struct symbol *ds; + + cs = prop_get_symbol(sym_get_choice_prop(sym)); + ds = sym_choice_default(cs); + if (!sym_is_optional(cs) && sym == ds) { + if ((sym->type == S_BOOLEAN) && + sym_get_tristate_value(sym) == yes) + goto next_menu; + } + } + conf_write_symbol(out, sym, &kconfig_printer_cb, NULL); + } +next_menu: + if (menu->list != NULL) { + menu = menu->list; + } + else if (menu->next != NULL) { + menu = menu->next; + } else { + while ((menu = menu->parent)) { + if (menu->next != NULL) { + menu = menu->next; + break; + } + } + } + } + fclose(out); + return 0; +} + +int conf_write(const char *name) +{ + FILE *out; + struct symbol *sym; + struct menu *menu; + const char *basename; + const char *str; + char dirname[PATH_MAX+1], tmpname[PATH_MAX+1], newname[PATH_MAX+1]; + char *env; + + dirname[0] = 0; + if (name && name[0]) { + struct stat st; + char *slash; + + if (!stat(name, &st) && S_ISDIR(st.st_mode)) { + strcpy(dirname, name); + strcat(dirname, "/"); + basename = conf_get_configname(); + } else if ((slash = strrchr(name, '/'))) { + int size = slash - name + 1; + memcpy(dirname, name, size); + dirname[size] = 0; + if (slash[1]) + basename = slash + 1; + else + basename = conf_get_configname(); + } else + basename = name; + } else + basename = conf_get_configname(); + + sprintf(newname, "%s%s", dirname, basename); + env = getenv("KCONFIG_OVERWRITECONFIG"); + if (!env || !*env) { + sprintf(tmpname, "%s.tmpconfig.%d", dirname, (int)getpid()); + out = fopen(tmpname, "w"); + } else { + *tmpname = 0; + out = fopen(newname, "w"); + } + if (!out) + return 1; + + conf_write_heading(out, &kconfig_printer_cb, NULL); + + if (!conf_get_changed()) + sym_clear_all_valid(); + + menu = rootmenu.list; + while (menu) { + sym = menu->sym; + if (!sym) { + if (!menu_is_visible(menu)) + goto next; + str = menu_get_prompt(menu); + fprintf(out, "\n" + "#\n" + "# %s\n" + "#\n", str); + } else if (!(sym->flags & SYMBOL_CHOICE)) { + sym_calc_value(sym); + if (!(sym->flags & SYMBOL_WRITE)) + goto next; + sym->flags &= ~SYMBOL_WRITE; + + conf_write_symbol(out, sym, &kconfig_printer_cb, NULL); + } + +next: + if (menu->list) { + menu = menu->list; + continue; + } + if (menu->next) + menu = menu->next; + else while ((menu = menu->parent)) { + if (menu->next) { + menu = menu->next; + break; + } + } + } + fclose(out); + + if (*tmpname) { + strcat(dirname, basename); + strcat(dirname, ".old"); + rename(newname, dirname); + if (rename(tmpname, newname)) + return 1; + } + + conf_message(_("configuration written to %s"), newname); + + sym_set_change_count(0); + + return 0; +} + +static int conf_split_config(void) +{ + const char *name; + char path[PATH_MAX+1]; + char *s, *d, c; + struct symbol *sym; + struct stat sb; + int res, i, fd; + + name = conf_get_autoconfig_name(); + conf_read_simple(name, S_DEF_AUTO); + sym_calc_value(modules_sym); + + if (chdir("include/config")) + return 1; + + res = 0; + for_all_symbols(i, sym) { + sym_calc_value(sym); + if ((sym->flags & SYMBOL_AUTO) || !sym->name) + continue; + if (sym->flags & SYMBOL_WRITE) { + if (sym->flags & SYMBOL_DEF_AUTO) { + /* + * symbol has old and new value, + * so compare them... + */ + switch (sym->type) { + case S_BOOLEAN: + case S_TRISTATE: + if (sym_get_tristate_value(sym) == + sym->def[S_DEF_AUTO].tri) + continue; + break; + case S_STRING: + case S_HEX: + case S_INT: + if (!strcmp(sym_get_string_value(sym), + sym->def[S_DEF_AUTO].val)) + continue; + break; + default: + break; + } + } else { + /* + * If there is no old value, only 'no' (unset) + * is allowed as new value. + */ + switch (sym->type) { + case S_BOOLEAN: + case S_TRISTATE: + if (sym_get_tristate_value(sym) == no) + continue; + break; + default: + break; + } + } + } else if (!(sym->flags & SYMBOL_DEF_AUTO)) + /* There is neither an old nor a new value. */ + continue; + /* else + * There is an old value, but no new value ('no' (unset) + * isn't saved in auto.conf, so the old value is always + * different from 'no'). + */ + + /* Replace all '_' and append ".h" */ + s = sym->name; + d = path; + while ((c = *s++)) { + c = tolower(c); + *d++ = (c == '_') ? '/' : c; + } + strcpy(d, ".h"); + + /* Assume directory path already exists. */ + fd = open(path, O_WRONLY | O_CREAT | O_TRUNC, 0644); + if (fd == -1) { + if (errno != ENOENT) { + res = 1; + break; + } + /* + * Create directory components, + * unless they exist already. + */ + d = path; + while ((d = strchr(d, '/'))) { + *d = 0; + if (stat(path, &sb) && mkdir(path, 0755)) { + res = 1; + goto out; + } + *d++ = '/'; + } + /* Try it again. */ + fd = open(path, O_WRONLY | O_CREAT | O_TRUNC, 0644); + if (fd == -1) { + res = 1; + break; + } + } + close(fd); + } +out: + if (chdir("../..")) + return 1; + + return res; +} + +int conf_write_autoconf(void) +{ + struct symbol *sym; + const char *name; + FILE *out, *tristate, *out_h; + int i; + + sym_clear_all_valid(); + + file_write_dep("include/config/auto.conf.cmd"); + + if (conf_split_config()) + return 1; + + out = fopen(".tmpconfig", "w"); + if (!out) + return 1; + + tristate = fopen(".tmpconfig_tristate", "w"); + if (!tristate) { + fclose(out); + return 1; + } + + out_h = fopen(".tmpconfig.h", "w"); + if (!out_h) { + fclose(out); + fclose(tristate); + return 1; + } + + conf_write_heading(out, &kconfig_printer_cb, NULL); + + conf_write_heading(tristate, &tristate_printer_cb, NULL); + + conf_write_heading(out_h, &header_printer_cb, NULL); + + for_all_symbols(i, sym) { + sym_calc_value(sym); + if (!(sym->flags & SYMBOL_WRITE) || !sym->name) + continue; + + /* write symbol to auto.conf, tristate and header files */ + conf_write_symbol(out, sym, &kconfig_printer_cb, (void *)1); + + conf_write_symbol(tristate, sym, &tristate_printer_cb, (void *)1); + + conf_write_symbol(out_h, sym, &header_printer_cb, NULL); + } + fclose(out); + fclose(tristate); + fclose(out_h); + + name = getenv("KCONFIG_AUTOHEADER"); + if (!name) + name = "include/generated/autoconf.h"; + if (rename(".tmpconfig.h", name)) + return 1; + name = getenv("KCONFIG_TRISTATE"); + if (!name) + name = "include/config/tristate.conf"; + if (rename(".tmpconfig_tristate", name)) + return 1; + name = conf_get_autoconfig_name(); + /* + * This must be the last step, kbuild has a dependency on auto.conf + * and this marks the successful completion of the previous steps. + */ + if (rename(".tmpconfig", name)) + return 1; + + return 0; +} + +static int sym_change_count; +static void (*conf_changed_callback)(void); + +void sym_set_change_count(int count) +{ + int _sym_change_count = sym_change_count; + sym_change_count = count; + if (conf_changed_callback && + (bool)_sym_change_count != (bool)count) + conf_changed_callback(); +} + +void sym_add_change_count(int count) +{ + sym_set_change_count(count + sym_change_count); +} + +bool conf_get_changed(void) +{ + return sym_change_count; +} + +void conf_set_changed_callback(void (*fn)(void)) +{ + conf_changed_callback = fn; +} + +static bool randomize_choice_values(struct symbol *csym) +{ + struct property *prop; + struct symbol *sym; + struct expr *e; + int cnt, def; + + /* + * If choice is mod then we may have more items selected + * and if no then no-one. + * In both cases stop. + */ + if (csym->curr.tri != yes) + return false; + + prop = sym_get_choice_prop(csym); + + /* count entries in choice block */ + cnt = 0; + expr_list_for_each_sym(prop->expr, e, sym) + cnt++; + + /* + * find a random value and set it to yes, + * set the rest to no so we have only one set + */ + def = (rand() % cnt); + + cnt = 0; + expr_list_for_each_sym(prop->expr, e, sym) { + if (def == cnt++) { + sym->def[S_DEF_USER].tri = yes; + csym->def[S_DEF_USER].val = sym; + } + else { + sym->def[S_DEF_USER].tri = no; + } + sym->flags |= SYMBOL_DEF_USER; + /* clear VALID to get value calculated */ + sym->flags &= ~SYMBOL_VALID; + } + csym->flags |= SYMBOL_DEF_USER; + /* clear VALID to get value calculated */ + csym->flags &= ~(SYMBOL_VALID); + + return true; +} + +void set_all_choice_values(struct symbol *csym) +{ + struct property *prop; + struct symbol *sym; + struct expr *e; + + prop = sym_get_choice_prop(csym); + + /* + * Set all non-assinged choice values to no + */ + expr_list_for_each_sym(prop->expr, e, sym) { + if (!sym_has_value(sym)) + sym->def[S_DEF_USER].tri = no; + } + csym->flags |= SYMBOL_DEF_USER; + /* clear VALID to get value calculated */ + csym->flags &= ~(SYMBOL_VALID | SYMBOL_NEED_SET_CHOICE_VALUES); +} + +bool conf_set_all_new_symbols(enum conf_def_mode mode) +{ + struct symbol *sym, *csym; + int i, cnt, pby, pty, ptm; /* pby: probability of boolean = y + * pty: probability of tristate = y + * ptm: probability of tristate = m + */ + + pby = 50; pty = ptm = 33; /* can't go as the default in switch-case + * below, otherwise gcc whines about + * -Wmaybe-uninitialized */ + if (mode == def_random) { + int n, p[3]; + char *env = getenv("KCONFIG_PROBABILITY"); + n = 0; + while( env && *env ) { + char *endp; + int tmp = strtol( env, &endp, 10 ); + if( tmp >= 0 && tmp <= 100 ) { + p[n++] = tmp; + } else { + errno = ERANGE; + perror( "KCONFIG_PROBABILITY" ); + exit( 1 ); + } + env = (*endp == ':') ? endp+1 : endp; + if( n >=3 ) { + break; + } + } + switch( n ) { + case 1: + pby = p[0]; ptm = pby/2; pty = pby-ptm; + break; + case 2: + pty = p[0]; ptm = p[1]; pby = pty + ptm; + break; + case 3: + pby = p[0]; pty = p[1]; ptm = p[2]; + break; + } + + if( pty+ptm > 100 ) { + errno = ERANGE; + perror( "KCONFIG_PROBABILITY" ); + exit( 1 ); + } + } + bool has_changed = false; + + for_all_symbols(i, sym) { + if (sym_has_value(sym) || (sym->flags & SYMBOL_VALID)) + continue; + switch (sym_get_type(sym)) { + case S_BOOLEAN: + case S_TRISTATE: + has_changed = true; + switch (mode) { + case def_yes: + sym->def[S_DEF_USER].tri = yes; + break; + case def_mod: + sym->def[S_DEF_USER].tri = mod; + break; + case def_no: + if (sym->flags & SYMBOL_ALLNOCONFIG_Y) + sym->def[S_DEF_USER].tri = yes; + else + sym->def[S_DEF_USER].tri = no; + break; + case def_random: + sym->def[S_DEF_USER].tri = no; + cnt = rand() % 100; + if (sym->type == S_TRISTATE) { + if (cnt < pty) + sym->def[S_DEF_USER].tri = yes; + else if (cnt < (pty+ptm)) + sym->def[S_DEF_USER].tri = mod; + } else if (cnt < pby) + sym->def[S_DEF_USER].tri = yes; + break; + default: + continue; + } + if (!(sym_is_choice(sym) && mode == def_random)) + sym->flags |= SYMBOL_DEF_USER; + break; + default: + break; + } + + } + + sym_clear_all_valid(); + + /* + * We have different type of choice blocks. + * If curr.tri equals to mod then we can select several + * choice symbols in one block. + * In this case we do nothing. + * If curr.tri equals yes then only one symbol can be + * selected in a choice block and we set it to yes, + * and the rest to no. + */ + if (mode != def_random) { + for_all_symbols(i, csym) { + if ((sym_is_choice(csym) && !sym_has_value(csym)) || + sym_is_choice_value(csym)) + csym->flags |= SYMBOL_NEED_SET_CHOICE_VALUES; + } + } + + for_all_symbols(i, csym) { + if (sym_has_value(csym) || !sym_is_choice(csym)) + continue; + + sym_calc_value(csym); + if (mode == def_random) + has_changed = randomize_choice_values(csym); + else { + set_all_choice_values(csym); + has_changed = true; + } + } + + return has_changed; +} diff --git a/tools/kconfig/expr.c b/tools/kconfig/expr.c new file mode 100644 index 0000000000..cbf4996dd9 --- /dev/null +++ b/tools/kconfig/expr.c @@ -0,0 +1,1206 @@ +/* + * Copyright (C) 2002 Roman Zippel + * Released under the terms of the GNU GPL v2.0. + */ + +#include +#include +#include + +#include "lkc.h" + +#define DEBUG_EXPR 0 + +static int expr_eq(struct expr *e1, struct expr *e2); +static struct expr *expr_eliminate_yn(struct expr *e); + +struct expr *expr_alloc_symbol(struct symbol *sym) +{ + struct expr *e = xcalloc(1, sizeof(*e)); + e->type = E_SYMBOL; + e->left.sym = sym; + return e; +} + +struct expr *expr_alloc_one(enum expr_type type, struct expr *ce) +{ + struct expr *e = xcalloc(1, sizeof(*e)); + e->type = type; + e->left.expr = ce; + return e; +} + +struct expr *expr_alloc_two(enum expr_type type, struct expr *e1, struct expr *e2) +{ + struct expr *e = xcalloc(1, sizeof(*e)); + e->type = type; + e->left.expr = e1; + e->right.expr = e2; + return e; +} + +struct expr *expr_alloc_comp(enum expr_type type, struct symbol *s1, struct symbol *s2) +{ + struct expr *e = xcalloc(1, sizeof(*e)); + e->type = type; + e->left.sym = s1; + e->right.sym = s2; + return e; +} + +struct expr *expr_alloc_and(struct expr *e1, struct expr *e2) +{ + if (!e1) + return e2; + return e2 ? expr_alloc_two(E_AND, e1, e2) : e1; +} + +struct expr *expr_alloc_or(struct expr *e1, struct expr *e2) +{ + if (!e1) + return e2; + return e2 ? expr_alloc_two(E_OR, e1, e2) : e1; +} + +struct expr *expr_copy(const struct expr *org) +{ + struct expr *e; + + if (!org) + return NULL; + + e = xmalloc(sizeof(*org)); + memcpy(e, org, sizeof(*org)); + switch (org->type) { + case E_SYMBOL: + e->left = org->left; + break; + case E_NOT: + e->left.expr = expr_copy(org->left.expr); + break; + case E_EQUAL: + case E_GEQ: + case E_GTH: + case E_LEQ: + case E_LTH: + case E_UNEQUAL: + e->left.sym = org->left.sym; + e->right.sym = org->right.sym; + break; + case E_AND: + case E_OR: + case E_LIST: + e->left.expr = expr_copy(org->left.expr); + e->right.expr = expr_copy(org->right.expr); + break; + default: + printf("can't copy type %d\n", e->type); + free(e); + e = NULL; + break; + } + + return e; +} + +void expr_free(struct expr *e) +{ + if (!e) + return; + + switch (e->type) { + case E_SYMBOL: + break; + case E_NOT: + expr_free(e->left.expr); + return; + case E_EQUAL: + case E_GEQ: + case E_GTH: + case E_LEQ: + case E_LTH: + case E_UNEQUAL: + break; + case E_OR: + case E_AND: + expr_free(e->left.expr); + expr_free(e->right.expr); + break; + default: + printf("how to free type %d?\n", e->type); + break; + } + free(e); +} + +static int trans_count; + +#define e1 (*ep1) +#define e2 (*ep2) + +static void __expr_eliminate_eq(enum expr_type type, struct expr **ep1, struct expr **ep2) +{ + if (e1->type == type) { + __expr_eliminate_eq(type, &e1->left.expr, &e2); + __expr_eliminate_eq(type, &e1->right.expr, &e2); + return; + } + if (e2->type == type) { + __expr_eliminate_eq(type, &e1, &e2->left.expr); + __expr_eliminate_eq(type, &e1, &e2->right.expr); + return; + } + if (e1->type == E_SYMBOL && e2->type == E_SYMBOL && + e1->left.sym == e2->left.sym && + (e1->left.sym == &symbol_yes || e1->left.sym == &symbol_no)) + return; + if (!expr_eq(e1, e2)) + return; + trans_count++; + expr_free(e1); expr_free(e2); + switch (type) { + case E_OR: + e1 = expr_alloc_symbol(&symbol_no); + e2 = expr_alloc_symbol(&symbol_no); + break; + case E_AND: + e1 = expr_alloc_symbol(&symbol_yes); + e2 = expr_alloc_symbol(&symbol_yes); + break; + default: + ; + } +} + +void expr_eliminate_eq(struct expr **ep1, struct expr **ep2) +{ + if (!e1 || !e2) + return; + switch (e1->type) { + case E_OR: + case E_AND: + __expr_eliminate_eq(e1->type, ep1, ep2); + default: + ; + } + if (e1->type != e2->type) switch (e2->type) { + case E_OR: + case E_AND: + __expr_eliminate_eq(e2->type, ep1, ep2); + default: + ; + } + e1 = expr_eliminate_yn(e1); + e2 = expr_eliminate_yn(e2); +} + +#undef e1 +#undef e2 + +static int expr_eq(struct expr *e1, struct expr *e2) +{ + int res, old_count; + + if (e1->type != e2->type) + return 0; + switch (e1->type) { + case E_EQUAL: + case E_GEQ: + case E_GTH: + case E_LEQ: + case E_LTH: + case E_UNEQUAL: + return e1->left.sym == e2->left.sym && e1->right.sym == e2->right.sym; + case E_SYMBOL: + return e1->left.sym == e2->left.sym; + case E_NOT: + return expr_eq(e1->left.expr, e2->left.expr); + case E_AND: + case E_OR: + e1 = expr_copy(e1); + e2 = expr_copy(e2); + old_count = trans_count; + expr_eliminate_eq(&e1, &e2); + res = (e1->type == E_SYMBOL && e2->type == E_SYMBOL && + e1->left.sym == e2->left.sym); + expr_free(e1); + expr_free(e2); + trans_count = old_count; + return res; + case E_LIST: + case E_RANGE: + case E_NONE: + /* panic */; + } + + if (DEBUG_EXPR) { + expr_fprint(e1, stdout); + printf(" = "); + expr_fprint(e2, stdout); + printf(" ?\n"); + } + + return 0; +} + +static struct expr *expr_eliminate_yn(struct expr *e) +{ + struct expr *tmp; + + if (e) switch (e->type) { + case E_AND: + e->left.expr = expr_eliminate_yn(e->left.expr); + e->right.expr = expr_eliminate_yn(e->right.expr); + if (e->left.expr->type == E_SYMBOL) { + if (e->left.expr->left.sym == &symbol_no) { + expr_free(e->left.expr); + expr_free(e->right.expr); + e->type = E_SYMBOL; + e->left.sym = &symbol_no; + e->right.expr = NULL; + return e; + } else if (e->left.expr->left.sym == &symbol_yes) { + free(e->left.expr); + tmp = e->right.expr; + *e = *(e->right.expr); + free(tmp); + return e; + } + } + if (e->right.expr->type == E_SYMBOL) { + if (e->right.expr->left.sym == &symbol_no) { + expr_free(e->left.expr); + expr_free(e->right.expr); + e->type = E_SYMBOL; + e->left.sym = &symbol_no; + e->right.expr = NULL; + return e; + } else if (e->right.expr->left.sym == &symbol_yes) { + free(e->right.expr); + tmp = e->left.expr; + *e = *(e->left.expr); + free(tmp); + return e; + } + } + break; + case E_OR: + e->left.expr = expr_eliminate_yn(e->left.expr); + e->right.expr = expr_eliminate_yn(e->right.expr); + if (e->left.expr->type == E_SYMBOL) { + if (e->left.expr->left.sym == &symbol_no) { + free(e->left.expr); + tmp = e->right.expr; + *e = *(e->right.expr); + free(tmp); + return e; + } else if (e->left.expr->left.sym == &symbol_yes) { + expr_free(e->left.expr); + expr_free(e->right.expr); + e->type = E_SYMBOL; + e->left.sym = &symbol_yes; + e->right.expr = NULL; + return e; + } + } + if (e->right.expr->type == E_SYMBOL) { + if (e->right.expr->left.sym == &symbol_no) { + free(e->right.expr); + tmp = e->left.expr; + *e = *(e->left.expr); + free(tmp); + return e; + } else if (e->right.expr->left.sym == &symbol_yes) { + expr_free(e->left.expr); + expr_free(e->right.expr); + e->type = E_SYMBOL; + e->left.sym = &symbol_yes; + e->right.expr = NULL; + return e; + } + } + break; + default: + ; + } + return e; +} + +/* + * bool FOO!=n => FOO + */ +struct expr *expr_trans_bool(struct expr *e) +{ + if (!e) + return NULL; + switch (e->type) { + case E_AND: + case E_OR: + case E_NOT: + e->left.expr = expr_trans_bool(e->left.expr); + e->right.expr = expr_trans_bool(e->right.expr); + break; + case E_UNEQUAL: + // FOO!=n -> FOO + if (e->left.sym->type == S_TRISTATE) { + if (e->right.sym == &symbol_no) { + e->type = E_SYMBOL; + e->right.sym = NULL; + } + } + break; + default: + ; + } + return e; +} + +/* + * e1 || e2 -> ? + */ +static struct expr *expr_join_or(struct expr *e1, struct expr *e2) +{ + struct expr *tmp; + struct symbol *sym1, *sym2; + + if (expr_eq(e1, e2)) + return expr_copy(e1); + if (e1->type != E_EQUAL && e1->type != E_UNEQUAL && e1->type != E_SYMBOL && e1->type != E_NOT) + return NULL; + if (e2->type != E_EQUAL && e2->type != E_UNEQUAL && e2->type != E_SYMBOL && e2->type != E_NOT) + return NULL; + if (e1->type == E_NOT) { + tmp = e1->left.expr; + if (tmp->type != E_EQUAL && tmp->type != E_UNEQUAL && tmp->type != E_SYMBOL) + return NULL; + sym1 = tmp->left.sym; + } else + sym1 = e1->left.sym; + if (e2->type == E_NOT) { + if (e2->left.expr->type != E_SYMBOL) + return NULL; + sym2 = e2->left.expr->left.sym; + } else + sym2 = e2->left.sym; + if (sym1 != sym2) + return NULL; + if (sym1->type != S_BOOLEAN && sym1->type != S_TRISTATE) + return NULL; + if (sym1->type == S_TRISTATE) { + if (e1->type == E_EQUAL && e2->type == E_EQUAL && + ((e1->right.sym == &symbol_yes && e2->right.sym == &symbol_mod) || + (e1->right.sym == &symbol_mod && e2->right.sym == &symbol_yes))) { + // (a='y') || (a='m') -> (a!='n') + return expr_alloc_comp(E_UNEQUAL, sym1, &symbol_no); + } + if (e1->type == E_EQUAL && e2->type == E_EQUAL && + ((e1->right.sym == &symbol_yes && e2->right.sym == &symbol_no) || + (e1->right.sym == &symbol_no && e2->right.sym == &symbol_yes))) { + // (a='y') || (a='n') -> (a!='m') + return expr_alloc_comp(E_UNEQUAL, sym1, &symbol_mod); + } + if (e1->type == E_EQUAL && e2->type == E_EQUAL && + ((e1->right.sym == &symbol_mod && e2->right.sym == &symbol_no) || + (e1->right.sym == &symbol_no && e2->right.sym == &symbol_mod))) { + // (a='m') || (a='n') -> (a!='y') + return expr_alloc_comp(E_UNEQUAL, sym1, &symbol_yes); + } + } + if (sym1->type == S_BOOLEAN && sym1 == sym2) { + if ((e1->type == E_NOT && e1->left.expr->type == E_SYMBOL && e2->type == E_SYMBOL) || + (e2->type == E_NOT && e2->left.expr->type == E_SYMBOL && e1->type == E_SYMBOL)) + return expr_alloc_symbol(&symbol_yes); + } + + if (DEBUG_EXPR) { + printf("optimize ("); + expr_fprint(e1, stdout); + printf(") || ("); + expr_fprint(e2, stdout); + printf(")?\n"); + } + return NULL; +} + +static struct expr *expr_join_and(struct expr *e1, struct expr *e2) +{ + struct expr *tmp; + struct symbol *sym1, *sym2; + + if (expr_eq(e1, e2)) + return expr_copy(e1); + if (e1->type != E_EQUAL && e1->type != E_UNEQUAL && e1->type != E_SYMBOL && e1->type != E_NOT) + return NULL; + if (e2->type != E_EQUAL && e2->type != E_UNEQUAL && e2->type != E_SYMBOL && e2->type != E_NOT) + return NULL; + if (e1->type == E_NOT) { + tmp = e1->left.expr; + if (tmp->type != E_EQUAL && tmp->type != E_UNEQUAL && tmp->type != E_SYMBOL) + return NULL; + sym1 = tmp->left.sym; + } else + sym1 = e1->left.sym; + if (e2->type == E_NOT) { + if (e2->left.expr->type != E_SYMBOL) + return NULL; + sym2 = e2->left.expr->left.sym; + } else + sym2 = e2->left.sym; + if (sym1 != sym2) + return NULL; + if (sym1->type != S_BOOLEAN && sym1->type != S_TRISTATE) + return NULL; + + if ((e1->type == E_SYMBOL && e2->type == E_EQUAL && e2->right.sym == &symbol_yes) || + (e2->type == E_SYMBOL && e1->type == E_EQUAL && e1->right.sym == &symbol_yes)) + // (a) && (a='y') -> (a='y') + return expr_alloc_comp(E_EQUAL, sym1, &symbol_yes); + + if ((e1->type == E_SYMBOL && e2->type == E_UNEQUAL && e2->right.sym == &symbol_no) || + (e2->type == E_SYMBOL && e1->type == E_UNEQUAL && e1->right.sym == &symbol_no)) + // (a) && (a!='n') -> (a) + return expr_alloc_symbol(sym1); + + if ((e1->type == E_SYMBOL && e2->type == E_UNEQUAL && e2->right.sym == &symbol_mod) || + (e2->type == E_SYMBOL && e1->type == E_UNEQUAL && e1->right.sym == &symbol_mod)) + // (a) && (a!='m') -> (a='y') + return expr_alloc_comp(E_EQUAL, sym1, &symbol_yes); + + if (sym1->type == S_TRISTATE) { + if (e1->type == E_EQUAL && e2->type == E_UNEQUAL) { + // (a='b') && (a!='c') -> 'b'='c' ? 'n' : a='b' + sym2 = e1->right.sym; + if ((e2->right.sym->flags & SYMBOL_CONST) && (sym2->flags & SYMBOL_CONST)) + return sym2 != e2->right.sym ? expr_alloc_comp(E_EQUAL, sym1, sym2) + : expr_alloc_symbol(&symbol_no); + } + if (e1->type == E_UNEQUAL && e2->type == E_EQUAL) { + // (a='b') && (a!='c') -> 'b'='c' ? 'n' : a='b' + sym2 = e2->right.sym; + if ((e1->right.sym->flags & SYMBOL_CONST) && (sym2->flags & SYMBOL_CONST)) + return sym2 != e1->right.sym ? expr_alloc_comp(E_EQUAL, sym1, sym2) + : expr_alloc_symbol(&symbol_no); + } + if (e1->type == E_UNEQUAL && e2->type == E_UNEQUAL && + ((e1->right.sym == &symbol_yes && e2->right.sym == &symbol_no) || + (e1->right.sym == &symbol_no && e2->right.sym == &symbol_yes))) + // (a!='y') && (a!='n') -> (a='m') + return expr_alloc_comp(E_EQUAL, sym1, &symbol_mod); + + if (e1->type == E_UNEQUAL && e2->type == E_UNEQUAL && + ((e1->right.sym == &symbol_yes && e2->right.sym == &symbol_mod) || + (e1->right.sym == &symbol_mod && e2->right.sym == &symbol_yes))) + // (a!='y') && (a!='m') -> (a='n') + return expr_alloc_comp(E_EQUAL, sym1, &symbol_no); + + if (e1->type == E_UNEQUAL && e2->type == E_UNEQUAL && + ((e1->right.sym == &symbol_mod && e2->right.sym == &symbol_no) || + (e1->right.sym == &symbol_no && e2->right.sym == &symbol_mod))) + // (a!='m') && (a!='n') -> (a='m') + return expr_alloc_comp(E_EQUAL, sym1, &symbol_yes); + + if ((e1->type == E_SYMBOL && e2->type == E_EQUAL && e2->right.sym == &symbol_mod) || + (e2->type == E_SYMBOL && e1->type == E_EQUAL && e1->right.sym == &symbol_mod) || + (e1->type == E_SYMBOL && e2->type == E_UNEQUAL && e2->right.sym == &symbol_yes) || + (e2->type == E_SYMBOL && e1->type == E_UNEQUAL && e1->right.sym == &symbol_yes)) + return NULL; + } + + if (DEBUG_EXPR) { + printf("optimize ("); + expr_fprint(e1, stdout); + printf(") && ("); + expr_fprint(e2, stdout); + printf(")?\n"); + } + return NULL; +} + +static void expr_eliminate_dups1(enum expr_type type, struct expr **ep1, struct expr **ep2) +{ +#define e1 (*ep1) +#define e2 (*ep2) + struct expr *tmp; + + if (e1->type == type) { + expr_eliminate_dups1(type, &e1->left.expr, &e2); + expr_eliminate_dups1(type, &e1->right.expr, &e2); + return; + } + if (e2->type == type) { + expr_eliminate_dups1(type, &e1, &e2->left.expr); + expr_eliminate_dups1(type, &e1, &e2->right.expr); + return; + } + if (e1 == e2) + return; + + switch (e1->type) { + case E_OR: case E_AND: + expr_eliminate_dups1(e1->type, &e1, &e1); + default: + ; + } + + switch (type) { + case E_OR: + tmp = expr_join_or(e1, e2); + if (tmp) { + expr_free(e1); expr_free(e2); + e1 = expr_alloc_symbol(&symbol_no); + e2 = tmp; + trans_count++; + } + break; + case E_AND: + tmp = expr_join_and(e1, e2); + if (tmp) { + expr_free(e1); expr_free(e2); + e1 = expr_alloc_symbol(&symbol_yes); + e2 = tmp; + trans_count++; + } + break; + default: + ; + } +#undef e1 +#undef e2 +} + +struct expr *expr_eliminate_dups(struct expr *e) +{ + int oldcount; + if (!e) + return e; + + oldcount = trans_count; + while (1) { + trans_count = 0; + switch (e->type) { + case E_OR: case E_AND: + expr_eliminate_dups1(e->type, &e, &e); + default: + ; + } + if (!trans_count) + break; + e = expr_eliminate_yn(e); + } + trans_count = oldcount; + return e; +} + +struct expr *expr_transform(struct expr *e) +{ + struct expr *tmp; + + if (!e) + return NULL; + switch (e->type) { + case E_EQUAL: + case E_GEQ: + case E_GTH: + case E_LEQ: + case E_LTH: + case E_UNEQUAL: + case E_SYMBOL: + case E_LIST: + break; + default: + e->left.expr = expr_transform(e->left.expr); + e->right.expr = expr_transform(e->right.expr); + } + + switch (e->type) { + case E_EQUAL: + if (e->left.sym->type != S_BOOLEAN) + break; + if (e->right.sym == &symbol_no) { + e->type = E_NOT; + e->left.expr = expr_alloc_symbol(e->left.sym); + e->right.sym = NULL; + break; + } + if (e->right.sym == &symbol_mod) { + printf("boolean symbol %s tested for 'm'? test forced to 'n'\n", e->left.sym->name); + e->type = E_SYMBOL; + e->left.sym = &symbol_no; + e->right.sym = NULL; + break; + } + if (e->right.sym == &symbol_yes) { + e->type = E_SYMBOL; + e->right.sym = NULL; + break; + } + break; + case E_UNEQUAL: + if (e->left.sym->type != S_BOOLEAN) + break; + if (e->right.sym == &symbol_no) { + e->type = E_SYMBOL; + e->right.sym = NULL; + break; + } + if (e->right.sym == &symbol_mod) { + printf("boolean symbol %s tested for 'm'? test forced to 'y'\n", e->left.sym->name); + e->type = E_SYMBOL; + e->left.sym = &symbol_yes; + e->right.sym = NULL; + break; + } + if (e->right.sym == &symbol_yes) { + e->type = E_NOT; + e->left.expr = expr_alloc_symbol(e->left.sym); + e->right.sym = NULL; + break; + } + break; + case E_NOT: + switch (e->left.expr->type) { + case E_NOT: + // !!a -> a + tmp = e->left.expr->left.expr; + free(e->left.expr); + free(e); + e = tmp; + e = expr_transform(e); + break; + case E_EQUAL: + case E_UNEQUAL: + // !a='x' -> a!='x' + tmp = e->left.expr; + free(e); + e = tmp; + e->type = e->type == E_EQUAL ? E_UNEQUAL : E_EQUAL; + break; + case E_LEQ: + case E_GEQ: + // !a<='x' -> a>'x' + tmp = e->left.expr; + free(e); + e = tmp; + e->type = e->type == E_LEQ ? E_GTH : E_LTH; + break; + case E_LTH: + case E_GTH: + // !a<'x' -> a>='x' + tmp = e->left.expr; + free(e); + e = tmp; + e->type = e->type == E_LTH ? E_GEQ : E_LEQ; + break; + case E_OR: + // !(a || b) -> !a && !b + tmp = e->left.expr; + e->type = E_AND; + e->right.expr = expr_alloc_one(E_NOT, tmp->right.expr); + tmp->type = E_NOT; + tmp->right.expr = NULL; + e = expr_transform(e); + break; + case E_AND: + // !(a && b) -> !a || !b + tmp = e->left.expr; + e->type = E_OR; + e->right.expr = expr_alloc_one(E_NOT, tmp->right.expr); + tmp->type = E_NOT; + tmp->right.expr = NULL; + e = expr_transform(e); + break; + case E_SYMBOL: + if (e->left.expr->left.sym == &symbol_yes) { + // !'y' -> 'n' + tmp = e->left.expr; + free(e); + e = tmp; + e->type = E_SYMBOL; + e->left.sym = &symbol_no; + break; + } + if (e->left.expr->left.sym == &symbol_mod) { + // !'m' -> 'm' + tmp = e->left.expr; + free(e); + e = tmp; + e->type = E_SYMBOL; + e->left.sym = &symbol_mod; + break; + } + if (e->left.expr->left.sym == &symbol_no) { + // !'n' -> 'y' + tmp = e->left.expr; + free(e); + e = tmp; + e->type = E_SYMBOL; + e->left.sym = &symbol_yes; + break; + } + break; + default: + ; + } + break; + default: + ; + } + return e; +} + +int expr_contains_symbol(struct expr *dep, struct symbol *sym) +{ + if (!dep) + return 0; + + switch (dep->type) { + case E_AND: + case E_OR: + return expr_contains_symbol(dep->left.expr, sym) || + expr_contains_symbol(dep->right.expr, sym); + case E_SYMBOL: + return dep->left.sym == sym; + case E_EQUAL: + case E_GEQ: + case E_GTH: + case E_LEQ: + case E_LTH: + case E_UNEQUAL: + return dep->left.sym == sym || + dep->right.sym == sym; + case E_NOT: + return expr_contains_symbol(dep->left.expr, sym); + default: + ; + } + return 0; +} + +bool expr_depends_symbol(struct expr *dep, struct symbol *sym) +{ + if (!dep) + return false; + + switch (dep->type) { + case E_AND: + return expr_depends_symbol(dep->left.expr, sym) || + expr_depends_symbol(dep->right.expr, sym); + case E_SYMBOL: + return dep->left.sym == sym; + case E_EQUAL: + if (dep->left.sym == sym) { + if (dep->right.sym == &symbol_yes || dep->right.sym == &symbol_mod) + return true; + } + break; + case E_UNEQUAL: + if (dep->left.sym == sym) { + if (dep->right.sym == &symbol_no) + return true; + } + break; + default: + ; + } + return false; +} + +struct expr *expr_trans_compare(struct expr *e, enum expr_type type, struct symbol *sym) +{ + struct expr *e1, *e2; + + if (!e) { + e = expr_alloc_symbol(sym); + if (type == E_UNEQUAL) + e = expr_alloc_one(E_NOT, e); + return e; + } + switch (e->type) { + case E_AND: + e1 = expr_trans_compare(e->left.expr, E_EQUAL, sym); + e2 = expr_trans_compare(e->right.expr, E_EQUAL, sym); + if (sym == &symbol_yes) + e = expr_alloc_two(E_AND, e1, e2); + if (sym == &symbol_no) + e = expr_alloc_two(E_OR, e1, e2); + if (type == E_UNEQUAL) + e = expr_alloc_one(E_NOT, e); + return e; + case E_OR: + e1 = expr_trans_compare(e->left.expr, E_EQUAL, sym); + e2 = expr_trans_compare(e->right.expr, E_EQUAL, sym); + if (sym == &symbol_yes) + e = expr_alloc_two(E_OR, e1, e2); + if (sym == &symbol_no) + e = expr_alloc_two(E_AND, e1, e2); + if (type == E_UNEQUAL) + e = expr_alloc_one(E_NOT, e); + return e; + case E_NOT: + return expr_trans_compare(e->left.expr, type == E_EQUAL ? E_UNEQUAL : E_EQUAL, sym); + case E_UNEQUAL: + case E_LTH: + case E_LEQ: + case E_GTH: + case E_GEQ: + case E_EQUAL: + if (type == E_EQUAL) { + if (sym == &symbol_yes) + return expr_copy(e); + if (sym == &symbol_mod) + return expr_alloc_symbol(&symbol_no); + if (sym == &symbol_no) + return expr_alloc_one(E_NOT, expr_copy(e)); + } else { + if (sym == &symbol_yes) + return expr_alloc_one(E_NOT, expr_copy(e)); + if (sym == &symbol_mod) + return expr_alloc_symbol(&symbol_yes); + if (sym == &symbol_no) + return expr_copy(e); + } + break; + case E_SYMBOL: + return expr_alloc_comp(type, e->left.sym, sym); + case E_LIST: + case E_RANGE: + case E_NONE: + /* panic */; + } + return NULL; +} + +enum string_value_kind { + k_string, + k_signed, + k_unsigned, + k_invalid +}; + +union string_value { + unsigned long long u; + signed long long s; +}; + +static enum string_value_kind expr_parse_string(const char *str, + enum symbol_type type, + union string_value *val) +{ + char *tail; + enum string_value_kind kind; + + errno = 0; + switch (type) { + case S_BOOLEAN: + case S_TRISTATE: + return k_string; + case S_INT: + val->s = strtoll(str, &tail, 10); + kind = k_signed; + break; + case S_HEX: + val->u = strtoull(str, &tail, 16); + kind = k_unsigned; + break; + case S_STRING: + case S_UNKNOWN: + val->s = strtoll(str, &tail, 0); + kind = k_signed; + break; + default: + return k_invalid; + } + return !errno && !*tail && tail > str && isxdigit(tail[-1]) + ? kind : k_string; +} + +tristate expr_calc_value(struct expr *e) +{ + tristate val1, val2; + const char *str1, *str2; + enum string_value_kind k1 = k_string, k2 = k_string; + union string_value lval = {}, rval = {}; + int res; + + if (!e) + return yes; + + switch (e->type) { + case E_SYMBOL: + sym_calc_value(e->left.sym); + return e->left.sym->curr.tri; + case E_AND: + val1 = expr_calc_value(e->left.expr); + val2 = expr_calc_value(e->right.expr); + return EXPR_AND(val1, val2); + case E_OR: + val1 = expr_calc_value(e->left.expr); + val2 = expr_calc_value(e->right.expr); + return EXPR_OR(val1, val2); + case E_NOT: + val1 = expr_calc_value(e->left.expr); + return EXPR_NOT(val1); + case E_EQUAL: + case E_GEQ: + case E_GTH: + case E_LEQ: + case E_LTH: + case E_UNEQUAL: + break; + default: + printf("expr_calc_value: %d?\n", e->type); + return no; + } + + sym_calc_value(e->left.sym); + sym_calc_value(e->right.sym); + str1 = sym_get_string_value(e->left.sym); + str2 = sym_get_string_value(e->right.sym); + + if (e->left.sym->type != S_STRING || e->right.sym->type != S_STRING) { + k1 = expr_parse_string(str1, e->left.sym->type, &lval); + k2 = expr_parse_string(str2, e->right.sym->type, &rval); + } + + if (k1 == k_string || k2 == k_string) + res = strcmp(str1, str2); + else if (k1 == k_invalid || k2 == k_invalid) { + if (e->type != E_EQUAL && e->type != E_UNEQUAL) { + printf("Cannot compare \"%s\" and \"%s\"\n", str1, str2); + return no; + } + res = strcmp(str1, str2); + } else if (k1 == k_unsigned || k2 == k_unsigned) + res = (lval.u > rval.u) - (lval.u < rval.u); + else /* if (k1 == k_signed && k2 == k_signed) */ + res = (lval.s > rval.s) - (lval.s < rval.s); + + switch(e->type) { + case E_EQUAL: + return res ? no : yes; + case E_GEQ: + return res >= 0 ? yes : no; + case E_GTH: + return res > 0 ? yes : no; + case E_LEQ: + return res <= 0 ? yes : no; + case E_LTH: + return res < 0 ? yes : no; + case E_UNEQUAL: + return res ? yes : no; + default: + printf("expr_calc_value: relation %d?\n", e->type); + return no; + } +} + +static int expr_compare_type(enum expr_type t1, enum expr_type t2) +{ + if (t1 == t2) + return 0; + switch (t1) { + case E_LEQ: + case E_LTH: + case E_GEQ: + case E_GTH: + if (t2 == E_EQUAL || t2 == E_UNEQUAL) + return 1; + case E_EQUAL: + case E_UNEQUAL: + if (t2 == E_NOT) + return 1; + case E_NOT: + if (t2 == E_AND) + return 1; + case E_AND: + if (t2 == E_OR) + return 1; + case E_OR: + if (t2 == E_LIST) + return 1; + case E_LIST: + if (t2 == 0) + return 1; + default: + return -1; + } + printf("[%dgt%d?]", t1, t2); + return 0; +} + +static inline struct expr * +expr_get_leftmost_symbol(const struct expr *e) +{ + + if (e == NULL) + return NULL; + + while (e->type != E_SYMBOL) + e = e->left.expr; + + return expr_copy(e); +} + +/* + * Given expression `e1' and `e2', returns the leaf of the longest + * sub-expression of `e1' not containing 'e2. + */ +struct expr *expr_simplify_unmet_dep(struct expr *e1, struct expr *e2) +{ + struct expr *ret; + + switch (e1->type) { + case E_OR: + return expr_alloc_and( + expr_simplify_unmet_dep(e1->left.expr, e2), + expr_simplify_unmet_dep(e1->right.expr, e2)); + case E_AND: { + struct expr *e; + e = expr_alloc_and(expr_copy(e1), expr_copy(e2)); + e = expr_eliminate_dups(e); + ret = (!expr_eq(e, e1)) ? e1 : NULL; + expr_free(e); + break; + } + default: + ret = e1; + break; + } + + return expr_get_leftmost_symbol(ret); +} + +void expr_print(struct expr *e, void (*fn)(void *, struct symbol *, const char *), void *data, int prevtoken) +{ + if (!e) { + fn(data, NULL, "y"); + return; + } + + if (expr_compare_type(prevtoken, e->type) > 0) + fn(data, NULL, "("); + switch (e->type) { + case E_SYMBOL: + if (e->left.sym->name) + fn(data, e->left.sym, e->left.sym->name); + else + fn(data, NULL, ""); + break; + case E_NOT: + fn(data, NULL, "!"); + expr_print(e->left.expr, fn, data, E_NOT); + break; + case E_EQUAL: + if (e->left.sym->name) + fn(data, e->left.sym, e->left.sym->name); + else + fn(data, NULL, ""); + fn(data, NULL, "="); + fn(data, e->right.sym, e->right.sym->name); + break; + case E_LEQ: + case E_LTH: + if (e->left.sym->name) + fn(data, e->left.sym, e->left.sym->name); + else + fn(data, NULL, ""); + fn(data, NULL, e->type == E_LEQ ? "<=" : "<"); + fn(data, e->right.sym, e->right.sym->name); + break; + case E_GEQ: + case E_GTH: + if (e->left.sym->name) + fn(data, e->left.sym, e->left.sym->name); + else + fn(data, NULL, ""); + fn(data, NULL, e->type == E_GEQ ? ">=" : ">"); + fn(data, e->right.sym, e->right.sym->name); + break; + case E_UNEQUAL: + if (e->left.sym->name) + fn(data, e->left.sym, e->left.sym->name); + else + fn(data, NULL, ""); + fn(data, NULL, "!="); + fn(data, e->right.sym, e->right.sym->name); + break; + case E_OR: + expr_print(e->left.expr, fn, data, E_OR); + fn(data, NULL, " || "); + expr_print(e->right.expr, fn, data, E_OR); + break; + case E_AND: + expr_print(e->left.expr, fn, data, E_AND); + fn(data, NULL, " && "); + expr_print(e->right.expr, fn, data, E_AND); + break; + case E_LIST: + fn(data, e->right.sym, e->right.sym->name); + if (e->left.expr) { + fn(data, NULL, " ^ "); + expr_print(e->left.expr, fn, data, E_LIST); + } + break; + case E_RANGE: + fn(data, NULL, "["); + fn(data, e->left.sym, e->left.sym->name); + fn(data, NULL, " "); + fn(data, e->right.sym, e->right.sym->name); + fn(data, NULL, "]"); + break; + default: + { + char buf[32]; + sprintf(buf, "", e->type); + fn(data, NULL, buf); + break; + } + } + if (expr_compare_type(prevtoken, e->type) > 0) + fn(data, NULL, ")"); +} + +static void expr_print_file_helper(void *data, struct symbol *sym, const char *str) +{ + xfwrite(str, strlen(str), 1, data); +} + +void expr_fprint(struct expr *e, FILE *out) +{ + expr_print(e, expr_print_file_helper, out, E_NONE); +} + +static void expr_print_gstr_helper(void *data, struct symbol *sym, const char *str) +{ + struct gstr *gs = (struct gstr*)data; + const char *sym_str = NULL; + + if (sym) + sym_str = sym_get_string_value(sym); + + if (gs->max_width) { + unsigned extra_length = strlen(str); + const char *last_cr = strrchr(gs->s, '\n'); + unsigned last_line_length; + + if (sym_str) + extra_length += 4 + strlen(sym_str); + + if (!last_cr) + last_cr = gs->s; + + last_line_length = strlen(gs->s) - (last_cr - gs->s); + + if ((last_line_length + extra_length) > gs->max_width) + str_append(gs, "\\\n"); + } + + str_append(gs, str); + if (sym && sym->type != S_UNKNOWN) + str_printf(gs, " [=%s]", sym_str); +} + +void expr_gstr_print(struct expr *e, struct gstr *gs) +{ + expr_print(e, expr_print_gstr_helper, gs, E_NONE); +} diff --git a/tools/kconfig/expr.h b/tools/kconfig/expr.h new file mode 100644 index 0000000000..973b6f7333 --- /dev/null +++ b/tools/kconfig/expr.h @@ -0,0 +1,238 @@ +/* + * Copyright (C) 2002 Roman Zippel + * Released under the terms of the GNU GPL v2.0. + */ + +#ifndef EXPR_H +#define EXPR_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include +#include +#include "list.h" +#ifndef __cplusplus +#include +#endif + +struct file { + struct file *next; + struct file *parent; + const char *name; + int lineno; +}; + +typedef enum tristate { + no, mod, yes +} tristate; + +enum expr_type { + E_NONE, E_OR, E_AND, E_NOT, + E_EQUAL, E_UNEQUAL, E_LTH, E_LEQ, E_GTH, E_GEQ, + E_LIST, E_SYMBOL, E_RANGE +}; + +union expr_data { + struct expr *expr; + struct symbol *sym; +}; + +struct expr { + enum expr_type type; + union expr_data left, right; +}; + +#define EXPR_OR(dep1, dep2) (((dep1)>(dep2))?(dep1):(dep2)) +#define EXPR_AND(dep1, dep2) (((dep1)<(dep2))?(dep1):(dep2)) +#define EXPR_NOT(dep) (2-(dep)) + +#define expr_list_for_each_sym(l, e, s) \ + for (e = (l); e && (s = e->right.sym); e = e->left.expr) + +struct expr_value { + struct expr *expr; + tristate tri; +}; + +struct symbol_value { + void *val; + tristate tri; +}; + +enum symbol_type { + S_UNKNOWN, S_BOOLEAN, S_TRISTATE, S_INT, S_HEX, S_STRING, S_OTHER +}; + +/* enum values are used as index to symbol.def[] */ +enum { + S_DEF_USER, /* main user value */ + S_DEF_AUTO, /* values read from auto.conf */ + S_DEF_DEF3, /* Reserved for UI usage */ + S_DEF_DEF4, /* Reserved for UI usage */ + S_DEF_COUNT +}; + +struct symbol { + struct symbol *next; + char *name; + enum symbol_type type; + struct symbol_value curr; + struct symbol_value def[S_DEF_COUNT]; + tristate visible; + int flags; + struct property *prop; + struct expr_value dir_dep; + struct expr_value rev_dep; +}; + +#define for_all_symbols(i, sym) for (i = 0; i < SYMBOL_HASHSIZE; i++) for (sym = symbol_hash[i]; sym; sym = sym->next) if (sym->type != S_OTHER) + +#define SYMBOL_CONST 0x0001 /* symbol is const */ +#define SYMBOL_CHECK 0x0008 /* used during dependency checking */ +#define SYMBOL_CHOICE 0x0010 /* start of a choice block (null name) */ +#define SYMBOL_CHOICEVAL 0x0020 /* used as a value in a choice block */ +#define SYMBOL_VALID 0x0080 /* set when symbol.curr is calculated */ +#define SYMBOL_OPTIONAL 0x0100 /* choice is optional - values can be 'n' */ +#define SYMBOL_WRITE 0x0200 /* write symbol to file (KCONFIG_CONFIG) */ +#define SYMBOL_CHANGED 0x0400 /* ? */ +#define SYMBOL_AUTO 0x1000 /* value from environment variable */ +#define SYMBOL_CHECKED 0x2000 /* used during dependency checking */ +#define SYMBOL_WARNED 0x8000 /* warning has been issued */ + +/* Set when symbol.def[] is used */ +#define SYMBOL_DEF 0x10000 /* First bit of SYMBOL_DEF */ +#define SYMBOL_DEF_USER 0x10000 /* symbol.def[S_DEF_USER] is valid */ +#define SYMBOL_DEF_AUTO 0x20000 /* symbol.def[S_DEF_AUTO] is valid */ +#define SYMBOL_DEF3 0x40000 /* symbol.def[S_DEF_3] is valid */ +#define SYMBOL_DEF4 0x80000 /* symbol.def[S_DEF_4] is valid */ + +/* choice values need to be set before calculating this symbol value */ +#define SYMBOL_NEED_SET_CHOICE_VALUES 0x100000 + +/* Set symbol to y if allnoconfig; used for symbols that hide others */ +#define SYMBOL_ALLNOCONFIG_Y 0x200000 + +#define SYMBOL_MAXLENGTH 256 +#define SYMBOL_HASHSIZE 9973 + +/* A property represent the config options that can be associated + * with a config "symbol". + * Sample: + * config FOO + * default y + * prompt "foo prompt" + * select BAR + * config BAZ + * int "BAZ Value" + * range 1..255 + */ +enum prop_type { + P_UNKNOWN, + P_PROMPT, /* prompt "foo prompt" or "BAZ Value" */ + P_COMMENT, /* text associated with a comment */ + P_MENU, /* prompt associated with a menuconfig option */ + P_DEFAULT, /* default y */ + P_CHOICE, /* choice value */ + P_SELECT, /* select BAR */ + P_RANGE, /* range 7..100 (for a symbol) */ + P_ENV, /* value from environment variable */ + P_SYMBOL, /* where a symbol is defined */ +}; + +struct property { + struct property *next; /* next property - null if last */ + struct symbol *sym; /* the symbol for which the property is associated */ + enum prop_type type; /* type of property */ + const char *text; /* the prompt value - P_PROMPT, P_MENU, P_COMMENT */ + struct expr_value visible; + struct expr *expr; /* the optional conditional part of the property */ + struct menu *menu; /* the menu the property are associated with + * valid for: P_SELECT, P_RANGE, P_CHOICE, + * P_PROMPT, P_DEFAULT, P_MENU, P_COMMENT */ + struct file *file; /* what file was this property defined */ + int lineno; /* what lineno was this property defined */ +}; + +#define for_all_properties(sym, st, tok) \ + for (st = sym->prop; st; st = st->next) \ + if (st->type == (tok)) +#define for_all_defaults(sym, st) for_all_properties(sym, st, P_DEFAULT) +#define for_all_choices(sym, st) for_all_properties(sym, st, P_CHOICE) +#define for_all_prompts(sym, st) \ + for (st = sym->prop; st; st = st->next) \ + if (st->text) + +struct menu { + struct menu *next; + struct menu *parent; + struct menu *list; + struct symbol *sym; + struct property *prompt; + struct expr *visibility; + struct expr *dep; + unsigned int flags; + char *help; + struct file *file; + int lineno; + void *data; +}; + +#define MENU_CHANGED 0x0001 +#define MENU_ROOT 0x0002 + +struct jump_key { + struct list_head entries; + size_t offset; + struct menu *target; + int index; +}; + +#define JUMP_NB 9 + +extern struct file *file_list; +extern struct file *current_file; +struct file *lookup_file(const char *name); + +extern struct symbol symbol_yes, symbol_no, symbol_mod; +extern struct symbol *modules_sym; +extern struct symbol *sym_defconfig_list; +extern int cdebug; +struct expr *expr_alloc_symbol(struct symbol *sym); +struct expr *expr_alloc_one(enum expr_type type, struct expr *ce); +struct expr *expr_alloc_two(enum expr_type type, struct expr *e1, struct expr *e2); +struct expr *expr_alloc_comp(enum expr_type type, struct symbol *s1, struct symbol *s2); +struct expr *expr_alloc_and(struct expr *e1, struct expr *e2); +struct expr *expr_alloc_or(struct expr *e1, struct expr *e2); +struct expr *expr_copy(const struct expr *org); +void expr_free(struct expr *e); +void expr_eliminate_eq(struct expr **ep1, struct expr **ep2); +tristate expr_calc_value(struct expr *e); +struct expr *expr_trans_bool(struct expr *e); +struct expr *expr_eliminate_dups(struct expr *e); +struct expr *expr_transform(struct expr *e); +int expr_contains_symbol(struct expr *dep, struct symbol *sym); +bool expr_depends_symbol(struct expr *dep, struct symbol *sym); +struct expr *expr_trans_compare(struct expr *e, enum expr_type type, struct symbol *sym); +struct expr *expr_simplify_unmet_dep(struct expr *e1, struct expr *e2); + +void expr_fprint(struct expr *e, FILE *out); +struct gstr; /* forward */ +void expr_gstr_print(struct expr *e, struct gstr *gs); + +static inline int expr_is_yes(struct expr *e) +{ + return !e || (e->type == E_SYMBOL && e->left.sym == &symbol_yes); +} + +static inline int expr_is_no(struct expr *e) +{ + return e && (e->type == E_SYMBOL && e->left.sym == &symbol_no); +} + +#ifdef __cplusplus +} +#endif + +#endif /* EXPR_H */ diff --git a/tools/kconfig/gconf.c b/tools/kconfig/gconf.c new file mode 100644 index 0000000000..26d208b435 --- /dev/null +++ b/tools/kconfig/gconf.c @@ -0,0 +1,1521 @@ +/* Hey EMACS -*- linux-c -*- */ +/* + * + * Copyright (C) 2002-2003 Romain Lievin + * Released under the terms of the GNU GPL v2.0. + * + */ + +#ifdef HAVE_CONFIG_H +# include +#endif + +#include +#include "lkc.h" +#include "images.c" + +#include +#include +#include +#include + +#include +#include +#include +#include + +//#define DEBUG + +enum { + SINGLE_VIEW, SPLIT_VIEW, FULL_VIEW +}; + +enum { + OPT_NORMAL, OPT_ALL, OPT_PROMPT +}; + +static gint view_mode = FULL_VIEW; +static gboolean show_name = TRUE; +static gboolean show_range = TRUE; +static gboolean show_value = TRUE; +static gboolean resizeable = FALSE; +static int opt_mode = OPT_NORMAL; + +GtkWidget *main_wnd = NULL; +GtkWidget *tree1_w = NULL; // left frame +GtkWidget *tree2_w = NULL; // right frame +GtkWidget *text_w = NULL; +GtkWidget *hpaned = NULL; +GtkWidget *vpaned = NULL; +GtkWidget *back_btn = NULL; +GtkWidget *save_btn = NULL; +GtkWidget *save_menu_item = NULL; + +GtkTextTag *tag1, *tag2; +GdkColor color; + +GtkTreeStore *tree1, *tree2, *tree; +GtkTreeModel *model1, *model2; +static GtkTreeIter *parents[256]; +static gint indent; + +static struct menu *current; // current node for SINGLE view +static struct menu *browsed; // browsed node for SPLIT view + +enum { + COL_OPTION, COL_NAME, COL_NO, COL_MOD, COL_YES, COL_VALUE, + COL_MENU, COL_COLOR, COL_EDIT, COL_PIXBUF, + COL_PIXVIS, COL_BTNVIS, COL_BTNACT, COL_BTNINC, COL_BTNRAD, + COL_NUMBER +}; + +static void display_list(void); +static void display_tree(struct menu *menu); +static void display_tree_part(void); +static void update_tree(struct menu *src, GtkTreeIter * dst); +static void set_node(GtkTreeIter * node, struct menu *menu, gchar ** row); +static gchar **fill_row(struct menu *menu); +static void conf_changed(void); + +/* Helping/Debugging Functions */ + +const char *dbg_sym_flags(int val) +{ + static char buf[256]; + + bzero(buf, 256); + + if (val & SYMBOL_CONST) + strcat(buf, "const/"); + if (val & SYMBOL_CHECK) + strcat(buf, "check/"); + if (val & SYMBOL_CHOICE) + strcat(buf, "choice/"); + if (val & SYMBOL_CHOICEVAL) + strcat(buf, "choiceval/"); + if (val & SYMBOL_VALID) + strcat(buf, "valid/"); + if (val & SYMBOL_OPTIONAL) + strcat(buf, "optional/"); + if (val & SYMBOL_WRITE) + strcat(buf, "write/"); + if (val & SYMBOL_CHANGED) + strcat(buf, "changed/"); + if (val & SYMBOL_AUTO) + strcat(buf, "auto/"); + + buf[strlen(buf) - 1] = '\0'; + + return buf; +} + +void replace_button_icon(GladeXML * xml, GdkDrawable * window, + GtkStyle * style, gchar * btn_name, gchar ** xpm) +{ + GdkPixmap *pixmap; + GdkBitmap *mask; + GtkToolButton *button; + GtkWidget *image; + + pixmap = gdk_pixmap_create_from_xpm_d(window, &mask, + &style->bg[GTK_STATE_NORMAL], + xpm); + + button = GTK_TOOL_BUTTON(glade_xml_get_widget(xml, btn_name)); + image = gtk_image_new_from_pixmap(pixmap, mask); + gtk_widget_show(image); + gtk_tool_button_set_icon_widget(button, image); +} + +/* Main Window Initialization */ +void init_main_window(const gchar * glade_file) +{ + GladeXML *xml; + GtkWidget *widget; + GtkTextBuffer *txtbuf; + GtkStyle *style; + + xml = glade_xml_new(glade_file, "window1", NULL); + if (!xml) + g_error(_("GUI loading failed !\n")); + glade_xml_signal_autoconnect(xml); + + main_wnd = glade_xml_get_widget(xml, "window1"); + hpaned = glade_xml_get_widget(xml, "hpaned1"); + vpaned = glade_xml_get_widget(xml, "vpaned1"); + tree1_w = glade_xml_get_widget(xml, "treeview1"); + tree2_w = glade_xml_get_widget(xml, "treeview2"); + text_w = glade_xml_get_widget(xml, "textview3"); + + back_btn = glade_xml_get_widget(xml, "button1"); + gtk_widget_set_sensitive(back_btn, FALSE); + + widget = glade_xml_get_widget(xml, "show_name1"); + gtk_check_menu_item_set_active((GtkCheckMenuItem *) widget, + show_name); + + widget = glade_xml_get_widget(xml, "show_range1"); + gtk_check_menu_item_set_active((GtkCheckMenuItem *) widget, + show_range); + + widget = glade_xml_get_widget(xml, "show_data1"); + gtk_check_menu_item_set_active((GtkCheckMenuItem *) widget, + show_value); + + save_btn = glade_xml_get_widget(xml, "button3"); + save_menu_item = glade_xml_get_widget(xml, "save1"); + conf_set_changed_callback(conf_changed); + + style = gtk_widget_get_style(main_wnd); + widget = glade_xml_get_widget(xml, "toolbar1"); + + replace_button_icon(xml, main_wnd->window, style, + "button4", (gchar **) xpm_single_view); + replace_button_icon(xml, main_wnd->window, style, + "button5", (gchar **) xpm_split_view); + replace_button_icon(xml, main_wnd->window, style, + "button6", (gchar **) xpm_tree_view); + + txtbuf = gtk_text_view_get_buffer(GTK_TEXT_VIEW(text_w)); + tag1 = gtk_text_buffer_create_tag(txtbuf, "mytag1", + "foreground", "red", + "weight", PANGO_WEIGHT_BOLD, + NULL); + tag2 = gtk_text_buffer_create_tag(txtbuf, "mytag2", + /*"style", PANGO_STYLE_OBLIQUE, */ + NULL); + + gtk_window_set_title(GTK_WINDOW(main_wnd), rootmenu.prompt->text); + + gtk_widget_show(main_wnd); +} + +void init_tree_model(void) +{ + gint i; + + tree = tree2 = gtk_tree_store_new(COL_NUMBER, + G_TYPE_STRING, G_TYPE_STRING, + G_TYPE_STRING, G_TYPE_STRING, + G_TYPE_STRING, G_TYPE_STRING, + G_TYPE_POINTER, GDK_TYPE_COLOR, + G_TYPE_BOOLEAN, GDK_TYPE_PIXBUF, + G_TYPE_BOOLEAN, G_TYPE_BOOLEAN, + G_TYPE_BOOLEAN, G_TYPE_BOOLEAN, + G_TYPE_BOOLEAN); + model2 = GTK_TREE_MODEL(tree2); + + for (parents[0] = NULL, i = 1; i < 256; i++) + parents[i] = (GtkTreeIter *) g_malloc(sizeof(GtkTreeIter)); + + tree1 = gtk_tree_store_new(COL_NUMBER, + G_TYPE_STRING, G_TYPE_STRING, + G_TYPE_STRING, G_TYPE_STRING, + G_TYPE_STRING, G_TYPE_STRING, + G_TYPE_POINTER, GDK_TYPE_COLOR, + G_TYPE_BOOLEAN, GDK_TYPE_PIXBUF, + G_TYPE_BOOLEAN, G_TYPE_BOOLEAN, + G_TYPE_BOOLEAN, G_TYPE_BOOLEAN, + G_TYPE_BOOLEAN); + model1 = GTK_TREE_MODEL(tree1); +} + +void init_left_tree(void) +{ + GtkTreeView *view = GTK_TREE_VIEW(tree1_w); + GtkCellRenderer *renderer; + GtkTreeSelection *sel; + GtkTreeViewColumn *column; + + gtk_tree_view_set_model(view, model1); + gtk_tree_view_set_headers_visible(view, TRUE); + gtk_tree_view_set_rules_hint(view, TRUE); + + column = gtk_tree_view_column_new(); + gtk_tree_view_append_column(view, column); + gtk_tree_view_column_set_title(column, _("Options")); + + renderer = gtk_cell_renderer_toggle_new(); + gtk_tree_view_column_pack_start(GTK_TREE_VIEW_COLUMN(column), + renderer, FALSE); + gtk_tree_view_column_set_attributes(GTK_TREE_VIEW_COLUMN(column), + renderer, + "active", COL_BTNACT, + "inconsistent", COL_BTNINC, + "visible", COL_BTNVIS, + "radio", COL_BTNRAD, NULL); + renderer = gtk_cell_renderer_text_new(); + gtk_tree_view_column_pack_start(GTK_TREE_VIEW_COLUMN(column), + renderer, FALSE); + gtk_tree_view_column_set_attributes(GTK_TREE_VIEW_COLUMN(column), + renderer, + "text", COL_OPTION, + "foreground-gdk", + COL_COLOR, NULL); + + sel = gtk_tree_view_get_selection(view); + gtk_tree_selection_set_mode(sel, GTK_SELECTION_SINGLE); + gtk_widget_realize(tree1_w); +} + +static void renderer_edited(GtkCellRendererText * cell, + const gchar * path_string, + const gchar * new_text, gpointer user_data); + +void init_right_tree(void) +{ + GtkTreeView *view = GTK_TREE_VIEW(tree2_w); + GtkCellRenderer *renderer; + GtkTreeSelection *sel; + GtkTreeViewColumn *column; + gint i; + + gtk_tree_view_set_model(view, model2); + gtk_tree_view_set_headers_visible(view, TRUE); + gtk_tree_view_set_rules_hint(view, TRUE); + + column = gtk_tree_view_column_new(); + gtk_tree_view_append_column(view, column); + gtk_tree_view_column_set_title(column, _("Options")); + + renderer = gtk_cell_renderer_pixbuf_new(); + gtk_tree_view_column_pack_start(GTK_TREE_VIEW_COLUMN(column), + renderer, FALSE); + gtk_tree_view_column_set_attributes(GTK_TREE_VIEW_COLUMN(column), + renderer, + "pixbuf", COL_PIXBUF, + "visible", COL_PIXVIS, NULL); + renderer = gtk_cell_renderer_toggle_new(); + gtk_tree_view_column_pack_start(GTK_TREE_VIEW_COLUMN(column), + renderer, FALSE); + gtk_tree_view_column_set_attributes(GTK_TREE_VIEW_COLUMN(column), + renderer, + "active", COL_BTNACT, + "inconsistent", COL_BTNINC, + "visible", COL_BTNVIS, + "radio", COL_BTNRAD, NULL); + renderer = gtk_cell_renderer_text_new(); + gtk_tree_view_column_pack_start(GTK_TREE_VIEW_COLUMN(column), + renderer, FALSE); + gtk_tree_view_column_set_attributes(GTK_TREE_VIEW_COLUMN(column), + renderer, + "text", COL_OPTION, + "foreground-gdk", + COL_COLOR, NULL); + + renderer = gtk_cell_renderer_text_new(); + gtk_tree_view_insert_column_with_attributes(view, -1, + _("Name"), renderer, + "text", COL_NAME, + "foreground-gdk", + COL_COLOR, NULL); + renderer = gtk_cell_renderer_text_new(); + gtk_tree_view_insert_column_with_attributes(view, -1, + "N", renderer, + "text", COL_NO, + "foreground-gdk", + COL_COLOR, NULL); + renderer = gtk_cell_renderer_text_new(); + gtk_tree_view_insert_column_with_attributes(view, -1, + "M", renderer, + "text", COL_MOD, + "foreground-gdk", + COL_COLOR, NULL); + renderer = gtk_cell_renderer_text_new(); + gtk_tree_view_insert_column_with_attributes(view, -1, + "Y", renderer, + "text", COL_YES, + "foreground-gdk", + COL_COLOR, NULL); + renderer = gtk_cell_renderer_text_new(); + gtk_tree_view_insert_column_with_attributes(view, -1, + _("Value"), renderer, + "text", COL_VALUE, + "editable", + COL_EDIT, + "foreground-gdk", + COL_COLOR, NULL); + g_signal_connect(G_OBJECT(renderer), "edited", + G_CALLBACK(renderer_edited), NULL); + + column = gtk_tree_view_get_column(view, COL_NAME); + gtk_tree_view_column_set_visible(column, show_name); + column = gtk_tree_view_get_column(view, COL_NO); + gtk_tree_view_column_set_visible(column, show_range); + column = gtk_tree_view_get_column(view, COL_MOD); + gtk_tree_view_column_set_visible(column, show_range); + column = gtk_tree_view_get_column(view, COL_YES); + gtk_tree_view_column_set_visible(column, show_range); + column = gtk_tree_view_get_column(view, COL_VALUE); + gtk_tree_view_column_set_visible(column, show_value); + + if (resizeable) { + for (i = 0; i < COL_VALUE; i++) { + column = gtk_tree_view_get_column(view, i); + gtk_tree_view_column_set_resizable(column, TRUE); + } + } + + sel = gtk_tree_view_get_selection(view); + gtk_tree_selection_set_mode(sel, GTK_SELECTION_SINGLE); +} + + +/* Utility Functions */ + + +static void text_insert_help(struct menu *menu) +{ + GtkTextBuffer *buffer; + GtkTextIter start, end; + const char *prompt = _(menu_get_prompt(menu)); + struct gstr help = str_new(); + + menu_get_ext_help(menu, &help); + + buffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(text_w)); + gtk_text_buffer_get_bounds(buffer, &start, &end); + gtk_text_buffer_delete(buffer, &start, &end); + gtk_text_view_set_left_margin(GTK_TEXT_VIEW(text_w), 15); + + gtk_text_buffer_get_end_iter(buffer, &end); + gtk_text_buffer_insert_with_tags(buffer, &end, prompt, -1, tag1, + NULL); + gtk_text_buffer_insert_at_cursor(buffer, "\n\n", 2); + gtk_text_buffer_get_end_iter(buffer, &end); + gtk_text_buffer_insert_with_tags(buffer, &end, str_get(&help), -1, tag2, + NULL); + str_free(&help); +} + + +static void text_insert_msg(const char *title, const char *message) +{ + GtkTextBuffer *buffer; + GtkTextIter start, end; + const char *msg = message; + + buffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(text_w)); + gtk_text_buffer_get_bounds(buffer, &start, &end); + gtk_text_buffer_delete(buffer, &start, &end); + gtk_text_view_set_left_margin(GTK_TEXT_VIEW(text_w), 15); + + gtk_text_buffer_get_end_iter(buffer, &end); + gtk_text_buffer_insert_with_tags(buffer, &end, title, -1, tag1, + NULL); + gtk_text_buffer_insert_at_cursor(buffer, "\n\n", 2); + gtk_text_buffer_get_end_iter(buffer, &end); + gtk_text_buffer_insert_with_tags(buffer, &end, msg, -1, tag2, + NULL); +} + + +/* Main Windows Callbacks */ + +void on_save_activate(GtkMenuItem * menuitem, gpointer user_data); +gboolean on_window1_delete_event(GtkWidget * widget, GdkEvent * event, + gpointer user_data) +{ + GtkWidget *dialog, *label; + gint result; + + if (!conf_get_changed()) + return FALSE; + + dialog = gtk_dialog_new_with_buttons(_("Warning !"), + GTK_WINDOW(main_wnd), + (GtkDialogFlags) + (GTK_DIALOG_MODAL | + GTK_DIALOG_DESTROY_WITH_PARENT), + GTK_STOCK_OK, + GTK_RESPONSE_YES, + GTK_STOCK_NO, + GTK_RESPONSE_NO, + GTK_STOCK_CANCEL, + GTK_RESPONSE_CANCEL, NULL); + gtk_dialog_set_default_response(GTK_DIALOG(dialog), + GTK_RESPONSE_CANCEL); + + label = gtk_label_new(_("\nSave configuration ?\n")); + gtk_container_add(GTK_CONTAINER(GTK_DIALOG(dialog)->vbox), label); + gtk_widget_show(label); + + result = gtk_dialog_run(GTK_DIALOG(dialog)); + switch (result) { + case GTK_RESPONSE_YES: + on_save_activate(NULL, NULL); + return FALSE; + case GTK_RESPONSE_NO: + return FALSE; + case GTK_RESPONSE_CANCEL: + case GTK_RESPONSE_DELETE_EVENT: + default: + gtk_widget_destroy(dialog); + return TRUE; + } + + return FALSE; +} + + +void on_window1_destroy(GtkObject * object, gpointer user_data) +{ + gtk_main_quit(); +} + + +void +on_window1_size_request(GtkWidget * widget, + GtkRequisition * requisition, gpointer user_data) +{ + static gint old_h; + gint w, h; + + if (widget->window == NULL) + gtk_window_get_default_size(GTK_WINDOW(main_wnd), &w, &h); + else + gdk_window_get_size(widget->window, &w, &h); + + if (h == old_h) + return; + old_h = h; + + gtk_paned_set_position(GTK_PANED(vpaned), 2 * h / 3); +} + + +/* Menu & Toolbar Callbacks */ + + +static void +load_filename(GtkFileSelection * file_selector, gpointer user_data) +{ + const gchar *fn; + + fn = gtk_file_selection_get_filename(GTK_FILE_SELECTION + (user_data)); + + if (conf_read(fn)) + text_insert_msg(_("Error"), _("Unable to load configuration !")); + else + display_tree(&rootmenu); +} + +void on_load1_activate(GtkMenuItem * menuitem, gpointer user_data) +{ + GtkWidget *fs; + + fs = gtk_file_selection_new(_("Load file...")); + g_signal_connect(GTK_OBJECT(GTK_FILE_SELECTION(fs)->ok_button), + "clicked", + G_CALLBACK(load_filename), (gpointer) fs); + g_signal_connect_swapped(GTK_OBJECT + (GTK_FILE_SELECTION(fs)->ok_button), + "clicked", G_CALLBACK(gtk_widget_destroy), + (gpointer) fs); + g_signal_connect_swapped(GTK_OBJECT + (GTK_FILE_SELECTION(fs)->cancel_button), + "clicked", G_CALLBACK(gtk_widget_destroy), + (gpointer) fs); + gtk_widget_show(fs); +} + + +void on_save_activate(GtkMenuItem * menuitem, gpointer user_data) +{ + if (conf_write(NULL)) + text_insert_msg(_("Error"), _("Unable to save configuration !")); +} + + +static void +store_filename(GtkFileSelection * file_selector, gpointer user_data) +{ + const gchar *fn; + + fn = gtk_file_selection_get_filename(GTK_FILE_SELECTION + (user_data)); + + if (conf_write(fn)) + text_insert_msg(_("Error"), _("Unable to save configuration !")); + + gtk_widget_destroy(GTK_WIDGET(user_data)); +} + +void on_save_as1_activate(GtkMenuItem * menuitem, gpointer user_data) +{ + GtkWidget *fs; + + fs = gtk_file_selection_new(_("Save file as...")); + g_signal_connect(GTK_OBJECT(GTK_FILE_SELECTION(fs)->ok_button), + "clicked", + G_CALLBACK(store_filename), (gpointer) fs); + g_signal_connect_swapped(GTK_OBJECT + (GTK_FILE_SELECTION(fs)->ok_button), + "clicked", G_CALLBACK(gtk_widget_destroy), + (gpointer) fs); + g_signal_connect_swapped(GTK_OBJECT + (GTK_FILE_SELECTION(fs)->cancel_button), + "clicked", G_CALLBACK(gtk_widget_destroy), + (gpointer) fs); + gtk_widget_show(fs); +} + + +void on_quit1_activate(GtkMenuItem * menuitem, gpointer user_data) +{ + if (!on_window1_delete_event(NULL, NULL, NULL)) + gtk_widget_destroy(GTK_WIDGET(main_wnd)); +} + + +void on_show_name1_activate(GtkMenuItem * menuitem, gpointer user_data) +{ + GtkTreeViewColumn *col; + + show_name = GTK_CHECK_MENU_ITEM(menuitem)->active; + col = gtk_tree_view_get_column(GTK_TREE_VIEW(tree2_w), COL_NAME); + if (col) + gtk_tree_view_column_set_visible(col, show_name); +} + + +void on_show_range1_activate(GtkMenuItem * menuitem, gpointer user_data) +{ + GtkTreeViewColumn *col; + + show_range = GTK_CHECK_MENU_ITEM(menuitem)->active; + col = gtk_tree_view_get_column(GTK_TREE_VIEW(tree2_w), COL_NO); + if (col) + gtk_tree_view_column_set_visible(col, show_range); + col = gtk_tree_view_get_column(GTK_TREE_VIEW(tree2_w), COL_MOD); + if (col) + gtk_tree_view_column_set_visible(col, show_range); + col = gtk_tree_view_get_column(GTK_TREE_VIEW(tree2_w), COL_YES); + if (col) + gtk_tree_view_column_set_visible(col, show_range); + +} + + +void on_show_data1_activate(GtkMenuItem * menuitem, gpointer user_data) +{ + GtkTreeViewColumn *col; + + show_value = GTK_CHECK_MENU_ITEM(menuitem)->active; + col = gtk_tree_view_get_column(GTK_TREE_VIEW(tree2_w), COL_VALUE); + if (col) + gtk_tree_view_column_set_visible(col, show_value); +} + + +void +on_set_option_mode1_activate(GtkMenuItem *menuitem, gpointer user_data) +{ + opt_mode = OPT_NORMAL; + gtk_tree_store_clear(tree2); + display_tree(&rootmenu); /* instead of update_tree to speed-up */ +} + + +void +on_set_option_mode2_activate(GtkMenuItem *menuitem, gpointer user_data) +{ + opt_mode = OPT_ALL; + gtk_tree_store_clear(tree2); + display_tree(&rootmenu); /* instead of update_tree to speed-up */ +} + + +void +on_set_option_mode3_activate(GtkMenuItem *menuitem, gpointer user_data) +{ + opt_mode = OPT_PROMPT; + gtk_tree_store_clear(tree2); + display_tree(&rootmenu); /* instead of update_tree to speed-up */ +} + + +void on_introduction1_activate(GtkMenuItem * menuitem, gpointer user_data) +{ + GtkWidget *dialog; + const gchar *intro_text = _( + "Welcome to gkc, the GTK+ graphical configuration tool\n" + "For each option, a blank box indicates the feature is disabled, a\n" + "check indicates it is enabled, and a dot indicates that it is to\n" + "be compiled as a module. Clicking on the box will cycle through the three states.\n" + "\n" + "If you do not see an option (e.g., a device driver) that you\n" + "believe should be present, try turning on Show All Options\n" + "under the Options menu.\n" + "Although there is no cross reference yet to help you figure out\n" + "what other options must be enabled to support the option you\n" + "are interested in, you can still view the help of a grayed-out\n" + "option.\n" + "\n" + "Toggling Show Debug Info under the Options menu will show \n" + "the dependencies, which you can then match by examining other options."); + + dialog = gtk_message_dialog_new(GTK_WINDOW(main_wnd), + GTK_DIALOG_DESTROY_WITH_PARENT, + GTK_MESSAGE_INFO, + GTK_BUTTONS_CLOSE, "%s", intro_text); + g_signal_connect_swapped(GTK_OBJECT(dialog), "response", + G_CALLBACK(gtk_widget_destroy), + GTK_OBJECT(dialog)); + gtk_widget_show_all(dialog); +} + + +void on_about1_activate(GtkMenuItem * menuitem, gpointer user_data) +{ + GtkWidget *dialog; + const gchar *about_text = + _("gkc is copyright (c) 2002 Romain Lievin .\n" + "Based on the source code from Roman Zippel.\n"); + + dialog = gtk_message_dialog_new(GTK_WINDOW(main_wnd), + GTK_DIALOG_DESTROY_WITH_PARENT, + GTK_MESSAGE_INFO, + GTK_BUTTONS_CLOSE, "%s", about_text); + g_signal_connect_swapped(GTK_OBJECT(dialog), "response", + G_CALLBACK(gtk_widget_destroy), + GTK_OBJECT(dialog)); + gtk_widget_show_all(dialog); +} + + +void on_license1_activate(GtkMenuItem * menuitem, gpointer user_data) +{ + GtkWidget *dialog; + const gchar *license_text = + _("gkc is released under the terms of the GNU GPL v2.\n" + "For more information, please see the source code or\n" + "visit http://www.fsf.org/licenses/licenses.html\n"); + + dialog = gtk_message_dialog_new(GTK_WINDOW(main_wnd), + GTK_DIALOG_DESTROY_WITH_PARENT, + GTK_MESSAGE_INFO, + GTK_BUTTONS_CLOSE, "%s", license_text); + g_signal_connect_swapped(GTK_OBJECT(dialog), "response", + G_CALLBACK(gtk_widget_destroy), + GTK_OBJECT(dialog)); + gtk_widget_show_all(dialog); +} + + +void on_back_clicked(GtkButton * button, gpointer user_data) +{ + enum prop_type ptype; + + current = current->parent; + ptype = current->prompt ? current->prompt->type : P_UNKNOWN; + if (ptype != P_MENU) + current = current->parent; + display_tree_part(); + + if (current == &rootmenu) + gtk_widget_set_sensitive(back_btn, FALSE); +} + + +void on_load_clicked(GtkButton * button, gpointer user_data) +{ + on_load1_activate(NULL, user_data); +} + + +void on_single_clicked(GtkButton * button, gpointer user_data) +{ + view_mode = SINGLE_VIEW; + gtk_widget_hide(tree1_w); + current = &rootmenu; + display_tree_part(); +} + + +void on_split_clicked(GtkButton * button, gpointer user_data) +{ + gint w, h; + view_mode = SPLIT_VIEW; + gtk_widget_show(tree1_w); + gtk_window_get_default_size(GTK_WINDOW(main_wnd), &w, &h); + gtk_paned_set_position(GTK_PANED(hpaned), w / 2); + if (tree2) + gtk_tree_store_clear(tree2); + display_list(); + + /* Disable back btn, like in full mode. */ + gtk_widget_set_sensitive(back_btn, FALSE); +} + + +void on_full_clicked(GtkButton * button, gpointer user_data) +{ + view_mode = FULL_VIEW; + gtk_widget_hide(tree1_w); + if (tree2) + gtk_tree_store_clear(tree2); + display_tree(&rootmenu); + gtk_widget_set_sensitive(back_btn, FALSE); +} + + +void on_collapse_clicked(GtkButton * button, gpointer user_data) +{ + gtk_tree_view_collapse_all(GTK_TREE_VIEW(tree2_w)); +} + + +void on_expand_clicked(GtkButton * button, gpointer user_data) +{ + gtk_tree_view_expand_all(GTK_TREE_VIEW(tree2_w)); +} + + +/* CTree Callbacks */ + +/* Change hex/int/string value in the cell */ +static void renderer_edited(GtkCellRendererText * cell, + const gchar * path_string, + const gchar * new_text, gpointer user_data) +{ + GtkTreePath *path = gtk_tree_path_new_from_string(path_string); + GtkTreeIter iter; + const char *old_def, *new_def; + struct menu *menu; + struct symbol *sym; + + if (!gtk_tree_model_get_iter(model2, &iter, path)) + return; + + gtk_tree_model_get(model2, &iter, COL_MENU, &menu, -1); + sym = menu->sym; + + gtk_tree_model_get(model2, &iter, COL_VALUE, &old_def, -1); + new_def = new_text; + + sym_set_string_value(sym, new_def); + + update_tree(&rootmenu, NULL); + + gtk_tree_path_free(path); +} + +/* Change the value of a symbol and update the tree */ +static void change_sym_value(struct menu *menu, gint col) +{ + struct symbol *sym = menu->sym; + tristate newval; + + if (!sym) + return; + + if (col == COL_NO) + newval = no; + else if (col == COL_MOD) + newval = mod; + else if (col == COL_YES) + newval = yes; + else + return; + + switch (sym_get_type(sym)) { + case S_BOOLEAN: + case S_TRISTATE: + if (!sym_tristate_within_range(sym, newval)) + newval = yes; + sym_set_tristate_value(sym, newval); + if (view_mode == FULL_VIEW) + update_tree(&rootmenu, NULL); + else if (view_mode == SPLIT_VIEW) { + update_tree(browsed, NULL); + display_list(); + } + else if (view_mode == SINGLE_VIEW) + display_tree_part(); //fixme: keep exp/coll + break; + case S_INT: + case S_HEX: + case S_STRING: + default: + break; + } +} + +static void toggle_sym_value(struct menu *menu) +{ + if (!menu->sym) + return; + + sym_toggle_tristate_value(menu->sym); + if (view_mode == FULL_VIEW) + update_tree(&rootmenu, NULL); + else if (view_mode == SPLIT_VIEW) { + update_tree(browsed, NULL); + display_list(); + } + else if (view_mode == SINGLE_VIEW) + display_tree_part(); //fixme: keep exp/coll +} + +static gint column2index(GtkTreeViewColumn * column) +{ + gint i; + + for (i = 0; i < COL_NUMBER; i++) { + GtkTreeViewColumn *col; + + col = gtk_tree_view_get_column(GTK_TREE_VIEW(tree2_w), i); + if (col == column) + return i; + } + + return -1; +} + + +/* User click: update choice (full) or goes down (single) */ +gboolean +on_treeview2_button_press_event(GtkWidget * widget, + GdkEventButton * event, gpointer user_data) +{ + GtkTreeView *view = GTK_TREE_VIEW(widget); + GtkTreePath *path; + GtkTreeViewColumn *column; + GtkTreeIter iter; + struct menu *menu; + gint col; + +#if GTK_CHECK_VERSION(2,1,4) // bug in ctree with earlier version of GTK + gint tx = (gint) event->x; + gint ty = (gint) event->y; + gint cx, cy; + + gtk_tree_view_get_path_at_pos(view, tx, ty, &path, &column, &cx, + &cy); +#else + gtk_tree_view_get_cursor(view, &path, &column); +#endif + if (path == NULL) + return FALSE; + + if (!gtk_tree_model_get_iter(model2, &iter, path)) + return FALSE; + gtk_tree_model_get(model2, &iter, COL_MENU, &menu, -1); + + col = column2index(column); + if (event->type == GDK_2BUTTON_PRESS) { + enum prop_type ptype; + ptype = menu->prompt ? menu->prompt->type : P_UNKNOWN; + + if (ptype == P_MENU && view_mode != FULL_VIEW && col == COL_OPTION) { + // goes down into menu + current = menu; + display_tree_part(); + gtk_widget_set_sensitive(back_btn, TRUE); + } else if ((col == COL_OPTION)) { + toggle_sym_value(menu); + gtk_tree_view_expand_row(view, path, TRUE); + } + } else { + if (col == COL_VALUE) { + toggle_sym_value(menu); + gtk_tree_view_expand_row(view, path, TRUE); + } else if (col == COL_NO || col == COL_MOD + || col == COL_YES) { + change_sym_value(menu, col); + gtk_tree_view_expand_row(view, path, TRUE); + } + } + + return FALSE; +} + +/* Key pressed: update choice */ +gboolean +on_treeview2_key_press_event(GtkWidget * widget, + GdkEventKey * event, gpointer user_data) +{ + GtkTreeView *view = GTK_TREE_VIEW(widget); + GtkTreePath *path; + GtkTreeViewColumn *column; + GtkTreeIter iter; + struct menu *menu; + gint col; + + gtk_tree_view_get_cursor(view, &path, &column); + if (path == NULL) + return FALSE; + + if (event->keyval == GDK_space) { + if (gtk_tree_view_row_expanded(view, path)) + gtk_tree_view_collapse_row(view, path); + else + gtk_tree_view_expand_row(view, path, FALSE); + return TRUE; + } + if (event->keyval == GDK_KP_Enter) { + } + if (widget == tree1_w) + return FALSE; + + gtk_tree_model_get_iter(model2, &iter, path); + gtk_tree_model_get(model2, &iter, COL_MENU, &menu, -1); + + if (!strcasecmp(event->string, "n")) + col = COL_NO; + else if (!strcasecmp(event->string, "m")) + col = COL_MOD; + else if (!strcasecmp(event->string, "y")) + col = COL_YES; + else + col = -1; + change_sym_value(menu, col); + + return FALSE; +} + + +/* Row selection changed: update help */ +void +on_treeview2_cursor_changed(GtkTreeView * treeview, gpointer user_data) +{ + GtkTreeSelection *selection; + GtkTreeIter iter; + struct menu *menu; + + selection = gtk_tree_view_get_selection(treeview); + if (gtk_tree_selection_get_selected(selection, &model2, &iter)) { + gtk_tree_model_get(model2, &iter, COL_MENU, &menu, -1); + text_insert_help(menu); + } +} + + +/* User click: display sub-tree in the right frame. */ +gboolean +on_treeview1_button_press_event(GtkWidget * widget, + GdkEventButton * event, gpointer user_data) +{ + GtkTreeView *view = GTK_TREE_VIEW(widget); + GtkTreePath *path; + GtkTreeViewColumn *column; + GtkTreeIter iter; + struct menu *menu; + + gint tx = (gint) event->x; + gint ty = (gint) event->y; + gint cx, cy; + + gtk_tree_view_get_path_at_pos(view, tx, ty, &path, &column, &cx, + &cy); + if (path == NULL) + return FALSE; + + gtk_tree_model_get_iter(model1, &iter, path); + gtk_tree_model_get(model1, &iter, COL_MENU, &menu, -1); + + if (event->type == GDK_2BUTTON_PRESS) { + toggle_sym_value(menu); + current = menu; + display_tree_part(); + } else { + browsed = menu; + display_tree_part(); + } + + gtk_widget_realize(tree2_w); + gtk_tree_view_set_cursor(view, path, NULL, FALSE); + gtk_widget_grab_focus(tree2_w); + + return FALSE; +} + + +/* Fill a row of strings */ +static gchar **fill_row(struct menu *menu) +{ + static gchar *row[COL_NUMBER]; + struct symbol *sym = menu->sym; + const char *def; + int stype; + tristate val; + enum prop_type ptype; + int i; + + for (i = COL_OPTION; i <= COL_COLOR; i++) + g_free(row[i]); + bzero(row, sizeof(row)); + + row[COL_OPTION] = + g_strdup_printf("%s %s", _(menu_get_prompt(menu)), + sym && !sym_has_value(sym) ? "(NEW)" : ""); + + if (opt_mode == OPT_ALL && !menu_is_visible(menu)) + row[COL_COLOR] = g_strdup("DarkGray"); + else if (opt_mode == OPT_PROMPT && + menu_has_prompt(menu) && !menu_is_visible(menu)) + row[COL_COLOR] = g_strdup("DarkGray"); + else + row[COL_COLOR] = g_strdup("Black"); + + ptype = menu->prompt ? menu->prompt->type : P_UNKNOWN; + switch (ptype) { + case P_MENU: + row[COL_PIXBUF] = (gchar *) xpm_menu; + if (view_mode == SINGLE_VIEW) + row[COL_PIXVIS] = GINT_TO_POINTER(TRUE); + row[COL_BTNVIS] = GINT_TO_POINTER(FALSE); + break; + case P_COMMENT: + row[COL_PIXBUF] = (gchar *) xpm_void; + row[COL_PIXVIS] = GINT_TO_POINTER(FALSE); + row[COL_BTNVIS] = GINT_TO_POINTER(FALSE); + break; + default: + row[COL_PIXBUF] = (gchar *) xpm_void; + row[COL_PIXVIS] = GINT_TO_POINTER(FALSE); + row[COL_BTNVIS] = GINT_TO_POINTER(TRUE); + break; + } + + if (!sym) + return row; + row[COL_NAME] = g_strdup(sym->name); + + sym_calc_value(sym); + sym->flags &= ~SYMBOL_CHANGED; + + if (sym_is_choice(sym)) { // parse childs for getting final value + struct menu *child; + struct symbol *def_sym = sym_get_choice_value(sym); + struct menu *def_menu = NULL; + + row[COL_BTNVIS] = GINT_TO_POINTER(FALSE); + + for (child = menu->list; child; child = child->next) { + if (menu_is_visible(child) + && child->sym == def_sym) + def_menu = child; + } + + if (def_menu) + row[COL_VALUE] = + g_strdup(_(menu_get_prompt(def_menu))); + } + if (sym->flags & SYMBOL_CHOICEVAL) + row[COL_BTNRAD] = GINT_TO_POINTER(TRUE); + + stype = sym_get_type(sym); + switch (stype) { + case S_BOOLEAN: + if (GPOINTER_TO_INT(row[COL_PIXVIS]) == FALSE) + row[COL_BTNVIS] = GINT_TO_POINTER(TRUE); + if (sym_is_choice(sym)) + break; + /* fall through */ + case S_TRISTATE: + val = sym_get_tristate_value(sym); + switch (val) { + case no: + row[COL_NO] = g_strdup("N"); + row[COL_VALUE] = g_strdup("N"); + row[COL_BTNACT] = GINT_TO_POINTER(FALSE); + row[COL_BTNINC] = GINT_TO_POINTER(FALSE); + break; + case mod: + row[COL_MOD] = g_strdup("M"); + row[COL_VALUE] = g_strdup("M"); + row[COL_BTNINC] = GINT_TO_POINTER(TRUE); + break; + case yes: + row[COL_YES] = g_strdup("Y"); + row[COL_VALUE] = g_strdup("Y"); + row[COL_BTNACT] = GINT_TO_POINTER(TRUE); + row[COL_BTNINC] = GINT_TO_POINTER(FALSE); + break; + } + + if (val != no && sym_tristate_within_range(sym, no)) + row[COL_NO] = g_strdup("_"); + if (val != mod && sym_tristate_within_range(sym, mod)) + row[COL_MOD] = g_strdup("_"); + if (val != yes && sym_tristate_within_range(sym, yes)) + row[COL_YES] = g_strdup("_"); + break; + case S_INT: + case S_HEX: + case S_STRING: + def = sym_get_string_value(sym); + row[COL_VALUE] = g_strdup(def); + row[COL_EDIT] = GINT_TO_POINTER(TRUE); + row[COL_BTNVIS] = GINT_TO_POINTER(FALSE); + break; + } + + return row; +} + + +/* Set the node content with a row of strings */ +static void set_node(GtkTreeIter * node, struct menu *menu, gchar ** row) +{ + GdkColor color; + gboolean success; + GdkPixbuf *pix; + + pix = gdk_pixbuf_new_from_xpm_data((const char **) + row[COL_PIXBUF]); + + gdk_color_parse(row[COL_COLOR], &color); + gdk_colormap_alloc_colors(gdk_colormap_get_system(), &color, 1, + FALSE, FALSE, &success); + + gtk_tree_store_set(tree, node, + COL_OPTION, row[COL_OPTION], + COL_NAME, row[COL_NAME], + COL_NO, row[COL_NO], + COL_MOD, row[COL_MOD], + COL_YES, row[COL_YES], + COL_VALUE, row[COL_VALUE], + COL_MENU, (gpointer) menu, + COL_COLOR, &color, + COL_EDIT, GPOINTER_TO_INT(row[COL_EDIT]), + COL_PIXBUF, pix, + COL_PIXVIS, GPOINTER_TO_INT(row[COL_PIXVIS]), + COL_BTNVIS, GPOINTER_TO_INT(row[COL_BTNVIS]), + COL_BTNACT, GPOINTER_TO_INT(row[COL_BTNACT]), + COL_BTNINC, GPOINTER_TO_INT(row[COL_BTNINC]), + COL_BTNRAD, GPOINTER_TO_INT(row[COL_BTNRAD]), + -1); + + g_object_unref(pix); +} + + +/* Add a node to the tree */ +static void place_node(struct menu *menu, char **row) +{ + GtkTreeIter *parent = parents[indent - 1]; + GtkTreeIter *node = parents[indent]; + + gtk_tree_store_append(tree, node, parent); + set_node(node, menu, row); +} + + +/* Find a node in the GTK+ tree */ +static GtkTreeIter found; + +/* + * Find a menu in the GtkTree starting at parent. + */ +GtkTreeIter *gtktree_iter_find_node(GtkTreeIter * parent, + struct menu *tofind) +{ + GtkTreeIter iter; + GtkTreeIter *child = &iter; + gboolean valid; + GtkTreeIter *ret; + + valid = gtk_tree_model_iter_children(model2, child, parent); + while (valid) { + struct menu *menu; + + gtk_tree_model_get(model2, child, 6, &menu, -1); + + if (menu == tofind) { + memcpy(&found, child, sizeof(GtkTreeIter)); + return &found; + } + + ret = gtktree_iter_find_node(child, tofind); + if (ret) + return ret; + + valid = gtk_tree_model_iter_next(model2, child); + } + + return NULL; +} + + +/* + * Update the tree by adding/removing entries + * Does not change other nodes + */ +static void update_tree(struct menu *src, GtkTreeIter * dst) +{ + struct menu *child1; + GtkTreeIter iter, tmp; + GtkTreeIter *child2 = &iter; + gboolean valid; + GtkTreeIter *sibling; + struct symbol *sym; + struct menu *menu1, *menu2; + + if (src == &rootmenu) + indent = 1; + + valid = gtk_tree_model_iter_children(model2, child2, dst); + for (child1 = src->list; child1; child1 = child1->next) { + + sym = child1->sym; + + reparse: + menu1 = child1; + if (valid) + gtk_tree_model_get(model2, child2, COL_MENU, + &menu2, -1); + else + menu2 = NULL; // force adding of a first child + +#ifdef DEBUG + printf("%*c%s | %s\n", indent, ' ', + menu1 ? menu_get_prompt(menu1) : "nil", + menu2 ? menu_get_prompt(menu2) : "nil"); +#endif + + if ((opt_mode == OPT_NORMAL && !menu_is_visible(child1)) || + (opt_mode == OPT_PROMPT && !menu_has_prompt(child1)) || + (opt_mode == OPT_ALL && !menu_get_prompt(child1))) { + + /* remove node */ + if (gtktree_iter_find_node(dst, menu1) != NULL) { + memcpy(&tmp, child2, sizeof(GtkTreeIter)); + valid = gtk_tree_model_iter_next(model2, + child2); + gtk_tree_store_remove(tree2, &tmp); + if (!valid) + return; /* next parent */ + else + goto reparse; /* next child */ + } else + continue; + } + + if (menu1 != menu2) { + if (gtktree_iter_find_node(dst, menu1) == NULL) { // add node + if (!valid && !menu2) + sibling = NULL; + else + sibling = child2; + gtk_tree_store_insert_before(tree2, + child2, + dst, sibling); + set_node(child2, menu1, fill_row(menu1)); + if (menu2 == NULL) + valid = TRUE; + } else { // remove node + memcpy(&tmp, child2, sizeof(GtkTreeIter)); + valid = gtk_tree_model_iter_next(model2, + child2); + gtk_tree_store_remove(tree2, &tmp); + if (!valid) + return; // next parent + else + goto reparse; // next child + } + } else if (sym && (sym->flags & SYMBOL_CHANGED)) { + set_node(child2, menu1, fill_row(menu1)); + } + + indent++; + update_tree(child1, child2); + indent--; + + valid = gtk_tree_model_iter_next(model2, child2); + } +} + + +/* Display the whole tree (single/split/full view) */ +static void display_tree(struct menu *menu) +{ + struct symbol *sym; + struct property *prop; + struct menu *child; + enum prop_type ptype; + + if (menu == &rootmenu) { + indent = 1; + current = &rootmenu; + } + + for (child = menu->list; child; child = child->next) { + prop = child->prompt; + sym = child->sym; + ptype = prop ? prop->type : P_UNKNOWN; + + if (sym) + sym->flags &= ~SYMBOL_CHANGED; + + if ((view_mode == SPLIT_VIEW) + && !(child->flags & MENU_ROOT) && (tree == tree1)) + continue; + + if ((view_mode == SPLIT_VIEW) && (child->flags & MENU_ROOT) + && (tree == tree2)) + continue; + + if ((opt_mode == OPT_NORMAL && menu_is_visible(child)) || + (opt_mode == OPT_PROMPT && menu_has_prompt(child)) || + (opt_mode == OPT_ALL && menu_get_prompt(child))) + place_node(child, fill_row(child)); +#ifdef DEBUG + printf("%*c%s: ", indent, ' ', menu_get_prompt(child)); + printf("%s", child->flags & MENU_ROOT ? "rootmenu | " : ""); + printf("%s", prop_get_type_name(ptype)); + printf(" | "); + if (sym) { + printf("%s", sym_type_name(sym->type)); + printf(" | "); + printf("%s", dbg_sym_flags(sym->flags)); + printf("\n"); + } else + printf("\n"); +#endif + if ((view_mode != FULL_VIEW) && (ptype == P_MENU) + && (tree == tree2)) + continue; +/* + if (((menu != &rootmenu) && !(menu->flags & MENU_ROOT)) + || (view_mode == FULL_VIEW) + || (view_mode == SPLIT_VIEW))*/ + + /* Change paned position if the view is not in 'split mode' */ + if (view_mode == SINGLE_VIEW || view_mode == FULL_VIEW) { + gtk_paned_set_position(GTK_PANED(hpaned), 0); + } + + if (((view_mode == SINGLE_VIEW) && (menu->flags & MENU_ROOT)) + || (view_mode == FULL_VIEW) + || (view_mode == SPLIT_VIEW)) { + indent++; + display_tree(child); + indent--; + } + } +} + +/* Display a part of the tree starting at current node (single/split view) */ +static void display_tree_part(void) +{ + if (tree2) + gtk_tree_store_clear(tree2); + if (view_mode == SINGLE_VIEW) + display_tree(current); + else if (view_mode == SPLIT_VIEW) + display_tree(browsed); + gtk_tree_view_expand_all(GTK_TREE_VIEW(tree2_w)); +} + +/* Display the list in the left frame (split view) */ +static void display_list(void) +{ + if (tree1) + gtk_tree_store_clear(tree1); + + tree = tree1; + display_tree(&rootmenu); + gtk_tree_view_expand_all(GTK_TREE_VIEW(tree1_w)); + tree = tree2; +} + +void fixup_rootmenu(struct menu *menu) +{ + struct menu *child; + static int menu_cnt = 0; + + menu->flags |= MENU_ROOT; + for (child = menu->list; child; child = child->next) { + if (child->prompt && child->prompt->type == P_MENU) { + menu_cnt++; + fixup_rootmenu(child); + menu_cnt--; + } else if (!menu_cnt) + fixup_rootmenu(child); + } +} + + +/* Main */ +int main(int ac, char *av[]) +{ + const char *name; + char *env; + gchar *glade_file; + + bindtextdomain(PACKAGE, LOCALEDIR); + bind_textdomain_codeset(PACKAGE, "UTF-8"); + textdomain(PACKAGE); + + /* GTK stuffs */ + gtk_set_locale(); + gtk_init(&ac, &av); + glade_init(); + + //add_pixmap_directory (PACKAGE_DATA_DIR "/" PACKAGE "/pixmaps"); + //add_pixmap_directory (PACKAGE_SOURCE_DIR "/pixmaps"); + + /* Determine GUI path */ + env = getenv(SRCTREE); + if (env) + glade_file = g_strconcat(env, "/scripts/kconfig/gconf.glade", NULL); + else if (av[0][0] == '/') + glade_file = g_strconcat(av[0], ".glade", NULL); + else + glade_file = g_strconcat(g_get_current_dir(), "/", av[0], ".glade", NULL); + + /* Conf stuffs */ + if (ac > 1 && av[1][0] == '-') { + switch (av[1][1]) { + case 'a': + //showAll = 1; + break; + case 's': + conf_set_message_callback(NULL); + break; + case 'h': + case '?': + printf("%s [-s] \n", av[0]); + exit(0); + } + name = av[2]; + } else + name = av[1]; + + conf_parse(name); + fixup_rootmenu(&rootmenu); + conf_read(NULL); + + /* Load the interface and connect signals */ + init_main_window(glade_file); + init_tree_model(); + init_left_tree(); + init_right_tree(); + + switch (view_mode) { + case SINGLE_VIEW: + display_tree_part(); + break; + case SPLIT_VIEW: + display_list(); + break; + case FULL_VIEW: + display_tree(&rootmenu); + break; + } + + gtk_main(); + + return 0; +} + +static void conf_changed(void) +{ + bool changed = conf_get_changed(); + gtk_widget_set_sensitive(save_btn, changed); + gtk_widget_set_sensitive(save_menu_item, changed); +} diff --git a/tools/kconfig/gconf.glade b/tools/kconfig/gconf.glade new file mode 100644 index 0000000000..aa483cb327 --- /dev/null +++ b/tools/kconfig/gconf.glade @@ -0,0 +1,661 @@ + + + + + + True + Gtk Kernel Configurator + GTK_WINDOW_TOPLEVEL + GTK_WIN_POS_NONE + False + 640 + 480 + True + False + True + False + False + GDK_WINDOW_TYPE_HINT_NORMAL + GDK_GRAVITY_NORTH_WEST + + + + + + + True + False + 0 + + + + True + + + + True + _File + True + + + + + + + True + Load a config file + _Load + True + + + + + + True + gtk-open + 1 + 0.5 + 0.5 + 0 + 0 + + + + + + + + True + Save the config in .config + _Save + True + + + + + + True + gtk-save + 1 + 0.5 + 0.5 + 0 + 0 + + + + + + + + True + Save the config in a file + Save _as + True + + + + + True + gtk-save-as + 1 + 0.5 + 0.5 + 0 + 0 + + + + + + + + True + + + + + + True + _Quit + True + + + + + + True + gtk-quit + 1 + 0.5 + 0.5 + 0 + 0 + + + + + + + + + + + + True + _Options + True + + + + + + + True + Show name + Show _name + True + False + + + + + + + True + Show range (Y/M/N) + Show _range + True + False + + + + + + + True + Show value of the option + Show _data + True + False + + + + + + + True + + + + + + True + Show normal options + Show normal options + True + True + + + + + + + True + Show all options + Show all _options + True + False + set_option_mode1 + + + + + + + True + Show all options with prompts + Show all prompt options + True + False + set_option_mode1 + + + + + + + + + + + + True + _Help + True + + + + + + + True + _Introduction + True + + + + + + True + gtk-dialog-question + 1 + 0.5 + 0.5 + 0 + 0 + + + + + + + + True + _About + True + + + + + + True + gtk-properties + 1 + 0.5 + 0.5 + 0 + 0 + + + + + + + + True + _License + True + + + + + True + gtk-justify-fill + 1 + 0.5 + 0.5 + 0 + 0 + + + + + + + + + + + 0 + False + False + + + + + + True + GTK_SHADOW_OUT + GTK_POS_LEFT + GTK_POS_TOP + + + + True + GTK_ORIENTATION_HORIZONTAL + GTK_TOOLBAR_BOTH + True + True + + + + True + Goes up of one level (single view) + Back + True + gtk-undo + True + True + False + + + + False + True + + + + + + True + True + True + False + + + + True + + + + + False + False + + + + + + True + Load a config file + Load + True + gtk-open + True + True + False + + + + False + True + + + + + + True + Save a config file + Save + True + gtk-save + True + True + False + + + + False + True + + + + + + True + True + True + False + + + + True + + + + + False + False + + + + + + True + Single view + Single + True + gtk-missing-image + True + True + False + + + + False + True + + + + + + True + Split view + Split + True + gtk-missing-image + True + True + False + + + + False + True + + + + + + True + Full view + Full + True + gtk-missing-image + True + True + False + + + + False + True + + + + + + True + True + True + False + + + + True + + + + + False + False + + + + + + True + Collapse the whole tree in the right frame + Collapse + True + gtk-remove + True + True + False + + + + False + True + + + + + + True + Expand the whole tree in the right frame + Expand + True + gtk-add + True + True + False + + + + False + True + + + + + + + 0 + False + False + + + + + + 1 + True + True + 0 + + + + True + GTK_POLICY_AUTOMATIC + GTK_POLICY_AUTOMATIC + GTK_SHADOW_IN + GTK_CORNER_TOP_LEFT + + + + True + True + True + False + False + False + + + + + + + + True + False + + + + + + True + True + 0 + + + + True + GTK_POLICY_AUTOMATIC + GTK_POLICY_AUTOMATIC + GTK_SHADOW_IN + GTK_CORNER_TOP_LEFT + + + + True + True + True + True + False + False + False + + + + + + + + True + False + + + + + + True + GTK_POLICY_NEVER + GTK_POLICY_AUTOMATIC + GTK_SHADOW_IN + GTK_CORNER_TOP_LEFT + + + + True + True + False + False + True + GTK_JUSTIFY_LEFT + GTK_WRAP_WORD + True + 0 + 0 + 0 + 0 + 0 + 0 + Sorry, no help available for this option yet. + + + + + True + True + + + + + True + True + + + + + 0 + True + True + + + + + + + diff --git a/tools/kconfig/images.c b/tools/kconfig/images.c new file mode 100644 index 0000000000..d4f84bd4a9 --- /dev/null +++ b/tools/kconfig/images.c @@ -0,0 +1,326 @@ +/* + * Copyright (C) 2002 Roman Zippel + * Released under the terms of the GNU GPL v2.0. + */ + +static const char *xpm_load[] = { +"22 22 5 1", +". c None", +"# c #000000", +"c c #838100", +"a c #ffff00", +"b c #ffffff", +"......................", +"......................", +"......................", +"............####....#.", +"...........#....##.##.", +"..................###.", +".................####.", +".####...........#####.", +"#abab##########.......", +"#babababababab#.......", +"#ababababababa#.......", +"#babababababab#.......", +"#ababab###############", +"#babab##cccccccccccc##", +"#abab##cccccccccccc##.", +"#bab##cccccccccccc##..", +"#ab##cccccccccccc##...", +"#b##cccccccccccc##....", +"###cccccccccccc##.....", +"##cccccccccccc##......", +"###############.......", +"......................"}; + +static const char *xpm_save[] = { +"22 22 5 1", +". c None", +"# c #000000", +"a c #838100", +"b c #c5c2c5", +"c c #cdb6d5", +"......................", +".####################.", +".#aa#bbbbbbbbbbbb#bb#.", +".#aa#bbbbbbbbbbbb#bb#.", +".#aa#bbbbbbbbbcbb####.", +".#aa#bbbccbbbbbbb#aa#.", +".#aa#bbbccbbbbbbb#aa#.", +".#aa#bbbbbbbbbbbb#aa#.", +".#aa#bbbbbbbbbbbb#aa#.", +".#aa#bbbbbbbbbbbb#aa#.", +".#aa#bbbbbbbbbbbb#aa#.", +".#aaa############aaa#.", +".#aaaaaaaaaaaaaaaaaa#.", +".#aaaaaaaaaaaaaaaaaa#.", +".#aaa#############aa#.", +".#aaa#########bbb#aa#.", +".#aaa#########bbb#aa#.", +".#aaa#########bbb#aa#.", +".#aaa#########bbb#aa#.", +".#aaa#########bbb#aa#.", +"..##################..", +"......................"}; + +static const char *xpm_back[] = { +"22 22 3 1", +". c None", +"# c #000083", +"a c #838183", +"......................", +"......................", +"......................", +"......................", +"......................", +"...........######a....", +"..#......##########...", +"..##...####......##a..", +"..###.###.........##..", +"..######..........##..", +"..#####...........##..", +"..######..........##..", +"..#######.........##..", +"..########.......##a..", +"...............a###...", +"...............###....", +"......................", +"......................", +"......................", +"......................", +"......................", +"......................"}; + +static const char *xpm_tree_view[] = { +"22 22 2 1", +". c None", +"# c #000000", +"......................", +"......................", +"......#...............", +"......#...............", +"......#...............", +"......#...............", +"......#...............", +"......########........", +"......#...............", +"......#...............", +"......#...............", +"......#...............", +"......#...............", +"......########........", +"......#...............", +"......#...............", +"......#...............", +"......#...............", +"......#...............", +"......########........", +"......................", +"......................"}; + +static const char *xpm_single_view[] = { +"22 22 2 1", +". c None", +"# c #000000", +"......................", +"......................", +"..........#...........", +"..........#...........", +"..........#...........", +"..........#...........", +"..........#...........", +"..........#...........", +"..........#...........", +"..........#...........", +"..........#...........", +"..........#...........", +"..........#...........", +"..........#...........", +"..........#...........", +"..........#...........", +"..........#...........", +"..........#...........", +"..........#...........", +"..........#...........", +"......................", +"......................"}; + +static const char *xpm_split_view[] = { +"22 22 2 1", +". c None", +"# c #000000", +"......................", +"......................", +"......#......#........", +"......#......#........", +"......#......#........", +"......#......#........", +"......#......#........", +"......#......#........", +"......#......#........", +"......#......#........", +"......#......#........", +"......#......#........", +"......#......#........", +"......#......#........", +"......#......#........", +"......#......#........", +"......#......#........", +"......#......#........", +"......#......#........", +"......#......#........", +"......................", +"......................"}; + +static const char *xpm_symbol_no[] = { +"12 12 2 1", +" c white", +". c black", +" ", +" .......... ", +" . . ", +" . . ", +" . . ", +" . . ", +" . . ", +" . . ", +" . . ", +" . . ", +" .......... ", +" "}; + +static const char *xpm_symbol_mod[] = { +"12 12 2 1", +" c white", +". c black", +" ", +" .......... ", +" . . ", +" . . ", +" . .. . ", +" . .... . ", +" . .... . ", +" . .. . ", +" . . ", +" . . ", +" .......... ", +" "}; + +static const char *xpm_symbol_yes[] = { +"12 12 2 1", +" c white", +". c black", +" ", +" .......... ", +" . . ", +" . . ", +" . . . ", +" . .. . ", +" . . .. . ", +" . .... . ", +" . .. . ", +" . . ", +" .......... ", +" "}; + +static const char *xpm_choice_no[] = { +"12 12 2 1", +" c white", +". c black", +" ", +" .... ", +" .. .. ", +" . . ", +" . . ", +" . . ", +" . . ", +" . . ", +" . . ", +" .. .. ", +" .... ", +" "}; + +static const char *xpm_choice_yes[] = { +"12 12 2 1", +" c white", +". c black", +" ", +" .... ", +" .. .. ", +" . . ", +" . .. . ", +" . .... . ", +" . .... . ", +" . .. . ", +" . . ", +" .. .. ", +" .... ", +" "}; + +static const char *xpm_menu[] = { +"12 12 2 1", +" c white", +". c black", +" ", +" .......... ", +" . . ", +" . .. . ", +" . .... . ", +" . ...... . ", +" . ...... . ", +" . .... . ", +" . .. . ", +" . . ", +" .......... ", +" "}; + +static const char *xpm_menu_inv[] = { +"12 12 2 1", +" c white", +". c black", +" ", +" .......... ", +" .......... ", +" .. ...... ", +" .. .... ", +" .. .. ", +" .. .. ", +" .. .... ", +" .. ...... ", +" .......... ", +" .......... ", +" "}; + +static const char *xpm_menuback[] = { +"12 12 2 1", +" c white", +". c black", +" ", +" .......... ", +" . . ", +" . .. . ", +" . .... . ", +" . ...... . ", +" . ...... . ", +" . .... . ", +" . .. . ", +" . . ", +" .......... ", +" "}; + +static const char *xpm_void[] = { +"12 12 2 1", +" c white", +". c black", +" ", +" ", +" ", +" ", +" ", +" ", +" ", +" ", +" ", +" ", +" ", +" "}; diff --git a/tools/kconfig/kconfig-language.txt b/tools/kconfig/kconfig-language.txt new file mode 100644 index 0000000000..c52856da0c --- /dev/null +++ b/tools/kconfig/kconfig-language.txt @@ -0,0 +1,556 @@ +Introduction +------------ + +The configuration database is a collection of configuration options +organized in a tree structure: + + +- Code maturity level options + | +- Prompt for development and/or incomplete code/drivers + +- General setup + | +- Networking support + | +- System V IPC + | +- BSD Process Accounting + | +- Sysctl support + +- Loadable module support + | +- Enable loadable module support + | +- Set version information on all module symbols + | +- Kernel module loader + +- ... + +Every entry has its own dependencies. These dependencies are used +to determine the visibility of an entry. Any child entry is only +visible if its parent entry is also visible. + +Menu entries +------------ + +Most entries define a config option; all other entries help to organize +them. A single configuration option is defined like this: + +config MODVERSIONS + bool "Set version information on all module symbols" + depends on MODULES + help + Usually, modules have to be recompiled whenever you switch to a new + kernel. ... + +Every line starts with a key word and can be followed by multiple +arguments. "config" starts a new config entry. The following lines +define attributes for this config option. Attributes can be the type of +the config option, input prompt, dependencies, help text and default +values. A config option can be defined multiple times with the same +name, but every definition can have only a single input prompt and the +type must not conflict. + +Menu attributes +--------------- + +A menu entry can have a number of attributes. Not all of them are +applicable everywhere (see syntax). + +- type definition: "bool"/"tristate"/"string"/"hex"/"int" + Every config option must have a type. There are only two basic types: + tristate and string; the other types are based on these two. The type + definition optionally accepts an input prompt, so these two examples + are equivalent: + + bool "Networking support" + and + bool + prompt "Networking support" + +- input prompt: "prompt" ["if" ] + Every menu entry can have at most one prompt, which is used to display + to the user. Optionally dependencies only for this prompt can be added + with "if". + +- default value: "default" ["if" ] + A config option can have any number of default values. If multiple + default values are visible, only the first defined one is active. + Default values are not limited to the menu entry where they are + defined. This means the default can be defined somewhere else or be + overridden by an earlier definition. + The default value is only assigned to the config symbol if no other + value was set by the user (via the input prompt above). If an input + prompt is visible the default value is presented to the user and can + be overridden by him. + Optionally, dependencies only for this default value can be added with + "if". + +- type definition + default value: + "def_bool"/"def_tristate" ["if" ] + This is a shorthand notation for a type definition plus a value. + Optionally dependencies for this default value can be added with "if". + +- dependencies: "depends on" + This defines a dependency for this menu entry. If multiple + dependencies are defined, they are connected with '&&'. Dependencies + are applied to all other options within this menu entry (which also + accept an "if" expression), so these two examples are equivalent: + + bool "foo" if BAR + default y if BAR + and + depends on BAR + bool "foo" + default y + +- reverse dependencies: "select" ["if" ] + While normal dependencies reduce the upper limit of a symbol (see + below), reverse dependencies can be used to force a lower limit of + another symbol. The value of the current menu symbol is used as the + minimal value can be set to. If is selected multiple + times, the limit is set to the largest selection. + Reverse dependencies can only be used with boolean or tristate + symbols. + Note: + select should be used with care. select will force + a symbol to a value without visiting the dependencies. + By abusing select you are able to select a symbol FOO even + if FOO depends on BAR that is not set. + In general use select only for non-visible symbols + (no prompts anywhere) and for symbols with no dependencies. + That will limit the usefulness but on the other hand avoid + the illegal configurations all over. + +- limiting menu display: "visible if" + This attribute is only applicable to menu blocks, if the condition is + false, the menu block is not displayed to the user (the symbols + contained there can still be selected by other symbols, though). It is + similar to a conditional "prompt" attribute for individual menu + entries. Default value of "visible" is true. + +- numerical ranges: "range" ["if" ] + This allows to limit the range of possible input values for int + and hex symbols. The user can only input a value which is larger than + or equal to the first symbol and smaller than or equal to the second + symbol. + +- help text: "help" or "---help---" + This defines a help text. The end of the help text is determined by + the indentation level, this means it ends at the first line which has + a smaller indentation than the first line of the help text. + "---help---" and "help" do not differ in behaviour, "---help---" is + used to help visually separate configuration logic from help within + the file as an aid to developers. + +- misc options: "option" [=] + Various less common options can be defined via this option syntax, + which can modify the behaviour of the menu entry and its config + symbol. These options are currently possible: + + - "defconfig_list" + This declares a list of default entries which can be used when + looking for the default configuration (which is used when the main + .config doesn't exists yet.) + + - "modules" + This declares the symbol to be used as the MODULES symbol, which + enables the third modular state for all config symbols. + At most one symbol may have the "modules" option set. + + - "env"= + This imports the environment variable into Kconfig. It behaves like + a default, except that the value comes from the environment, this + also means that the behaviour when mixing it with normal defaults is + undefined at this point. The symbol is currently not exported back + to the build environment (if this is desired, it can be done via + another symbol). + + - "allnoconfig_y" + This declares the symbol as one that should have the value y when + using "allnoconfig". Used for symbols that hide other symbols. + +Menu dependencies +----------------- + +Dependencies define the visibility of a menu entry and can also reduce +the input range of tristate symbols. The tristate logic used in the +expressions uses one more state than normal boolean logic to express the +module state. Dependency expressions have the following syntax: + + ::= (1) + '=' (2) + '!=' (3) + '(' ')' (4) + '!' (5) + '&&' (6) + '||' (7) + +Expressions are listed in decreasing order of precedence. + +(1) Convert the symbol into an expression. Boolean and tristate symbols + are simply converted into the respective expression values. All + other symbol types result in 'n'. +(2) If the values of both symbols are equal, it returns 'y', + otherwise 'n'. +(3) If the values of both symbols are equal, it returns 'n', + otherwise 'y'. +(4) Returns the value of the expression. Used to override precedence. +(5) Returns the result of (2-/expr/). +(6) Returns the result of min(/expr/, /expr/). +(7) Returns the result of max(/expr/, /expr/). + +An expression can have a value of 'n', 'm' or 'y' (or 0, 1, 2 +respectively for calculations). A menu entry becomes visible when its +expression evaluates to 'm' or 'y'. + +There are two types of symbols: constant and non-constant symbols. +Non-constant symbols are the most common ones and are defined with the +'config' statement. Non-constant symbols consist entirely of alphanumeric +characters or underscores. +Constant symbols are only part of expressions. Constant symbols are +always surrounded by single or double quotes. Within the quote, any +other character is allowed and the quotes can be escaped using '\'. + +Menu structure +-------------- + +The position of a menu entry in the tree is determined in two ways. First +it can be specified explicitly: + +menu "Network device support" + depends on NET + +config NETDEVICES + ... + +endmenu + +All entries within the "menu" ... "endmenu" block become a submenu of +"Network device support". All subentries inherit the dependencies from +the menu entry, e.g. this means the dependency "NET" is added to the +dependency list of the config option NETDEVICES. + +The other way to generate the menu structure is done by analyzing the +dependencies. If a menu entry somehow depends on the previous entry, it +can be made a submenu of it. First, the previous (parent) symbol must +be part of the dependency list and then one of these two conditions +must be true: +- the child entry must become invisible, if the parent is set to 'n' +- the child entry must only be visible, if the parent is visible + +config MODULES + bool "Enable loadable module support" + +config MODVERSIONS + bool "Set version information on all module symbols" + depends on MODULES + +comment "module support disabled" + depends on !MODULES + +MODVERSIONS directly depends on MODULES, this means it's only visible if +MODULES is different from 'n'. The comment on the other hand is always +visible when MODULES is visible (the (empty) dependency of MODULES is +also part of the comment dependencies). + + +Kconfig syntax +-------------- + +The configuration file describes a series of menu entries, where every +line starts with a keyword (except help texts). The following keywords +end a menu entry: +- config +- menuconfig +- choice/endchoice +- comment +- menu/endmenu +- if/endif +- source +The first five also start the definition of a menu entry. + +config: + + "config" + + +This defines a config symbol and accepts any of above +attributes as options. + +menuconfig: + "menuconfig" + + +This is similar to the simple config entry above, but it also gives a +hint to front ends, that all suboptions should be displayed as a +separate list of options. + +choices: + + "choice" [symbol] + + + "endchoice" + +This defines a choice group and accepts any of the above attributes as +options. A choice can only be of type bool or tristate, while a boolean +choice only allows a single config entry to be selected, a tristate +choice also allows any number of config entries to be set to 'm'. This +can be used if multiple drivers for a single hardware exists and only a +single driver can be compiled/loaded into the kernel, but all drivers +can be compiled as modules. +A choice accepts another option "optional", which allows to set the +choice to 'n' and no entry needs to be selected. +If no [symbol] is associated with a choice, then you can not have multiple +definitions of that choice. If a [symbol] is associated to the choice, +then you may define the same choice (ie. with the same entries) in another +place. + +comment: + + "comment" + + +This defines a comment which is displayed to the user during the +configuration process and is also echoed to the output files. The only +possible options are dependencies. + +menu: + + "menu" +

      + + "endmenu" + +This defines a menu block, see "Menu structure" above for more +information. The only possible options are dependencies and "visible" +attributes. + +if: + + "if" + + "endif" + +This defines an if block. The dependency expression is appended +to all enclosed menu entries. + +source: + + "source" + +This reads the specified configuration file. This file is always parsed. + +mainmenu: + + "mainmenu" + +This sets the config program's title bar if the config program chooses +to use it. It should be placed at the top of the configuration, before any +other statement. + + +Kconfig hints +------------- +This is a collection of Kconfig tips, most of which aren't obvious at +first glance and most of which have become idioms in several Kconfig +files. + +Adding common features and make the usage configurable +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +It is a common idiom to implement a feature/functionality that are +relevant for some architectures but not all. +The recommended way to do so is to use a config variable named HAVE_* +that is defined in a common Kconfig file and selected by the relevant +architectures. +An example is the generic IOMAP functionality. + +We would in lib/Kconfig see: + +# Generic IOMAP is used to ... +config HAVE_GENERIC_IOMAP + +config GENERIC_IOMAP + depends on HAVE_GENERIC_IOMAP && FOO + +And in lib/Makefile we would see: +obj-$(CONFIG_GENERIC_IOMAP) += iomap.o + +For each architecture using the generic IOMAP functionality we would see: + +config X86 + select ... + select HAVE_GENERIC_IOMAP + select ... + +Note: we use the existing config option and avoid creating a new +config variable to select HAVE_GENERIC_IOMAP. + +Note: the use of the internal config variable HAVE_GENERIC_IOMAP, it is +introduced to overcome the limitation of select which will force a +config option to 'y' no matter the dependencies. +The dependencies are moved to the symbol GENERIC_IOMAP and we avoid the +situation where select forces a symbol equals to 'y'. + +Build as module only +~~~~~~~~~~~~~~~~~~~~ +To restrict a component build to module-only, qualify its config symbol +with "depends on m". E.g.: + +config FOO + depends on BAR && m + +limits FOO to module (=m) or disabled (=n). + +Kconfig recursive dependency limitations +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +If you've hit the Kconfig error: "recursive dependency detected" you've run +into a recursive dependency issue with Kconfig, a recursive dependency can be +summarized as a circular dependency. The kconfig tools need to ensure that +Kconfig files comply with specified configuration requirements. In order to do +that kconfig must determine the values that are possible for all Kconfig +symbols, this is currently not possible if there is a circular relation +between two or more Kconfig symbols. For more details refer to the "Simple +Kconfig recursive issue" subsection below. Kconfig does not do recursive +dependency resolution; this has a few implications for Kconfig file writers. +We'll first explain why this issues exists and then provide an example +technical limitation which this brings upon Kconfig developers. Eager +developers wishing to try to address this limitation should read the next +subsections. + +Simple Kconfig recursive issue +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Read: Documentation/kbuild/Kconfig.recursion-issue-01 + +Test with: + +make KBUILD_KCONFIG=Documentation/kbuild/Kconfig.recursion-issue-01 allnoconfig + +Cumulative Kconfig recursive issue +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Read: Documentation/kbuild/Kconfig.recursion-issue-02 + +Test with: + +make KBUILD_KCONFIG=Documentation/kbuild/Kconfig.recursion-issue-02 allnoconfig + +Practical solutions to kconfig recursive issue +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Developers who run into the recursive Kconfig issue have three options +at their disposal. We document them below and also provide a list of +historical issues resolved through these different solutions. + + a) Remove any superfluous "select FOO" or "depends on FOO" + b) Match dependency semantics: + b1) Swap all "select FOO" to "depends on FOO" or, + b2) Swap all "depends on FOO" to "select FOO" + +The resolution to a) can be tested with the sample Kconfig file +Documentation/kbuild/Kconfig.recursion-issue-01 through the removal +of the "select CORE" from CORE_BELL_A_ADVANCED as that is implicit already +since CORE_BELL_A depends on CORE. At times it may not be possible to remove +some dependency criteria, for such cases you can work with solution b). + +The two different resolutions for b) can be tested in the sample Kconfig file +Documentation/kbuild/Kconfig.recursion-issue-02. + +Below is a list of examples of prior fixes for these types of recursive issues; +all errors appear to involve one or more select's and one or more "depends on". + +commit fix +====== === +06b718c01208 select A -> depends on A +c22eacfe82f9 depends on A -> depends on B +6a91e854442c select A -> depends on A +118c565a8f2e select A -> select B +f004e5594705 select A -> depends on A +c7861f37b4c6 depends on A -> (null) +80c69915e5fb select A -> (null) (1) +c2218e26c0d0 select A -> depends on A (1) +d6ae99d04e1c select A -> depends on A +95ca19cf8cbf select A -> depends on A +8f057d7bca54 depends on A -> (null) +8f057d7bca54 depends on A -> select A +a0701f04846e select A -> depends on A +0c8b92f7f259 depends on A -> (null) +e4e9e0540928 select A -> depends on A (2) +7453ea886e87 depends on A > (null) (1) +7b1fff7e4fdf select A -> depends on A +86c747d2a4f0 select A -> depends on A +d9f9ab51e55e select A -> depends on A +0c51a4d8abd6 depends on A -> select A (3) +e98062ed6dc4 select A -> depends on A (3) +91e5d284a7f1 select A -> (null) + +(1) Partial (or no) quote of error. +(2) That seems to be the gist of that fix. +(3) Same error. + +Future kconfig work +~~~~~~~~~~~~~~~~~~~ + +Work on kconfig is welcomed on both areas of clarifying semantics and on +evaluating the use of a full SAT solver for it. A full SAT solver can be +desirable to enable more complex dependency mappings and / or queries, +for instance on possible use case for a SAT solver could be that of handling +the current known recursive dependency issues. It is not known if this would +address such issues but such evaluation is desirable. If support for a full SAT +solver proves too complex or that it cannot address recursive dependency issues +Kconfig should have at least clear and well defined semantics which also +addresses and documents limitations or requirements such as the ones dealing +with recursive dependencies. + +Further work on both of these areas is welcomed on Kconfig. We elaborate +on both of these in the next two subsections. + +Semantics of Kconfig +~~~~~~~~~~~~~~~~~~~~ + +The use of Kconfig is broad, Linux is now only one of Kconfig's users: +one study has completed a broad analysis of Kconfig use in 12 projects [0]. +Despite its widespread use, and although this document does a reasonable job +in documenting basic Kconfig syntax a more precise definition of Kconfig +semantics is welcomed. One project deduced Kconfig semantics through +the use of the xconfig configurator [1]. Work should be done to confirm if +the deduced semantics matches our intended Kconfig design goals. + +Having well defined semantics can be useful for tools for practical +evaluation of depenencies, for instance one such use known case was work to +express in boolean abstraction of the inferred semantics of Kconfig to +translate Kconfig logic into boolean formulas and run a SAT solver on this to +find dead code / features (always inactive), 114 dead features were found in +Linux using this methodology [1] (Section 8: Threats to validity). + +Confirming this could prove useful as Kconfig stands as one of the the leading +industrial variability modeling languages [1] [2]. Its study would help +evaluate practical uses of such languages, their use was only theoretical +and real world requirements were not well understood. As it stands though +only reverse engineering techniques have been used to deduce semantics from +variability modeling languages such as Kconfig [3]. + +[0] http://www.eng.uwaterloo.ca/~shshe/kconfig_semantics.pdf +[1] http://gsd.uwaterloo.ca/sites/default/files/vm-2013-berger.pdf +[2] http://gsd.uwaterloo.ca/sites/default/files/ase241-berger_0.pdf +[3] http://gsd.uwaterloo.ca/sites/default/files/icse2011.pdf + +Full SAT solver for Kconfig +~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Although SAT solvers [0] haven't yet been used by Kconfig directly, as noted in +the previous subsection, work has been done however to express in boolean +abstraction the inferred semantics of Kconfig to translate Kconfig logic into +boolean formulas and run a SAT solver on it [1]. Another known related project +is CADOS [2] (former VAMOS [3]) and the tools, mainly undertaker [4], which has +been introduced first with [5]. The basic concept of undertaker is to exract +variability models from Kconfig, and put them together with a propositional +formula extracted from CPP #ifdefs and build-rules into a SAT solver in order +to find dead code, dead files, and dead symbols. If using a SAT solver is +desirable on Kconfig one approach would be to evaluate repurposing such efforts +somehow on Kconfig. There is enough interest from mentors of existing projects +to not only help advise how to integrate this work upstream but also help +maintain it long term. Interested developers should visit: + +http://kernelnewbies.org/KernelProjects/kconfig-sat + +[0] http://www.cs.cornell.edu/~sabhar/chapters/SATSolvers-KR-Handbook.pdf +[1] http://gsd.uwaterloo.ca/sites/default/files/vm-2013-berger.pdf +[2] https://cados.cs.fau.de +[3] https://vamos.cs.fau.de +[4] https://undertaker.cs.fau.de +[5] https://www4.cs.fau.de/Publications/2011/tartler_11_eurosys.pdf diff --git a/tools/kconfig/kxgettext.c b/tools/kconfig/kxgettext.c new file mode 100644 index 0000000000..2858738b22 --- /dev/null +++ b/tools/kconfig/kxgettext.c @@ -0,0 +1,235 @@ +/* + * Arnaldo Carvalho de Melo , 2005 + * + * Released under the terms of the GNU GPL v2.0 + */ + +#include +#include + +#include "lkc.h" + +static char *escape(const char* text, char *bf, int len) +{ + char *bfp = bf; + int multiline = strchr(text, '\n') != NULL; + int eol = 0; + int textlen = strlen(text); + + if ((textlen > 0) && (text[textlen-1] == '\n')) + eol = 1; + + *bfp++ = '"'; + --len; + + if (multiline) { + *bfp++ = '"'; + *bfp++ = '\n'; + *bfp++ = '"'; + len -= 3; + } + + while (*text != '\0' && len > 1) { + if (*text == '"') + *bfp++ = '\\'; + else if (*text == '\n') { + *bfp++ = '\\'; + *bfp++ = 'n'; + *bfp++ = '"'; + *bfp++ = '\n'; + *bfp++ = '"'; + len -= 5; + ++text; + goto next; + } + else if (*text == '\\') { + *bfp++ = '\\'; + len--; + } + *bfp++ = *text++; +next: + --len; + } + + if (multiline && eol) + bfp -= 3; + + *bfp++ = '"'; + *bfp = '\0'; + + return bf; +} + +struct file_line { + struct file_line *next; + const char *file; + int lineno; +}; + +static struct file_line *file_line__new(const char *file, int lineno) +{ + struct file_line *self = malloc(sizeof(*self)); + + if (self == NULL) + goto out; + + self->file = file; + self->lineno = lineno; + self->next = NULL; +out: + return self; +} + +struct message { + const char *msg; + const char *option; + struct message *next; + struct file_line *files; +}; + +static struct message *message__list; + +static struct message *message__new(const char *msg, char *option, + const char *file, int lineno) +{ + struct message *self = malloc(sizeof(*self)); + + if (self == NULL) + goto out; + + self->files = file_line__new(file, lineno); + if (self->files == NULL) + goto out_fail; + + self->msg = strdup(msg); + if (self->msg == NULL) + goto out_fail_msg; + + self->option = option; + self->next = NULL; +out: + return self; +out_fail_msg: + free(self->files); +out_fail: + free(self); + self = NULL; + goto out; +} + +static struct message *mesage__find(const char *msg) +{ + struct message *m = message__list; + + while (m != NULL) { + if (strcmp(m->msg, msg) == 0) + break; + m = m->next; + } + + return m; +} + +static int message__add_file_line(struct message *self, const char *file, + int lineno) +{ + int rc = -1; + struct file_line *fl = file_line__new(file, lineno); + + if (fl == NULL) + goto out; + + fl->next = self->files; + self->files = fl; + rc = 0; +out: + return rc; +} + +static int message__add(const char *msg, char *option, const char *file, + int lineno) +{ + int rc = 0; + char bf[16384]; + char *escaped = escape(msg, bf, sizeof(bf)); + struct message *m = mesage__find(escaped); + + if (m != NULL) + rc = message__add_file_line(m, file, lineno); + else { + m = message__new(escaped, option, file, lineno); + + if (m != NULL) { + m->next = message__list; + message__list = m; + } else + rc = -1; + } + return rc; +} + +static void menu_build_message_list(struct menu *menu) +{ + struct menu *child; + + message__add(menu_get_prompt(menu), NULL, + menu->file == NULL ? "Root Menu" : menu->file->name, + menu->lineno); + + if (menu->sym != NULL && menu_has_help(menu)) + message__add(menu_get_help(menu), menu->sym->name, + menu->file == NULL ? "Root Menu" : menu->file->name, + menu->lineno); + + for (child = menu->list; child != NULL; child = child->next) + if (child->prompt != NULL) + menu_build_message_list(child); +} + +static void message__print_file_lineno(struct message *self) +{ + struct file_line *fl = self->files; + + putchar('\n'); + if (self->option != NULL) + printf("# %s:00000\n", self->option); + + printf("#: %s:%d", fl->file, fl->lineno); + fl = fl->next; + + while (fl != NULL) { + printf(", %s:%d", fl->file, fl->lineno); + fl = fl->next; + } + + putchar('\n'); +} + +static void message__print_gettext_msgid_msgstr(struct message *self) +{ + message__print_file_lineno(self); + + printf("msgid %s\n" + "msgstr \"\"\n", self->msg); +} + +static void menu__xgettext(void) +{ + struct message *m = message__list; + + while (m != NULL) { + /* skip empty lines ("") */ + if (strlen(m->msg) > sizeof("\"\"")) + message__print_gettext_msgid_msgstr(m); + m = m->next; + } +} + +int main(int ac, char **av) +{ + conf_parse(av[1]); + + menu_build_message_list(menu_get_root_menu(NULL)); + menu__xgettext(); + return 0; +} diff --git a/tools/kconfig/list.h b/tools/kconfig/list.h new file mode 100644 index 0000000000..2cf23f002d --- /dev/null +++ b/tools/kconfig/list.h @@ -0,0 +1,131 @@ +#ifndef LIST_H +#define LIST_H + +/* + * Copied from include/linux/... + */ + +#undef offsetof +#define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER) + +/** + * container_of - cast a member of a structure out to the containing structure + * @ptr: the pointer to the member. + * @type: the type of the container struct this is embedded in. + * @member: the name of the member within the struct. + * + */ +#define container_of(ptr, type, member) ({ \ + const typeof( ((type *)0)->member ) *__mptr = (ptr); \ + (type *)( (char *)__mptr - offsetof(type,member) );}) + + +struct list_head { + struct list_head *next, *prev; +}; + + +#define LIST_HEAD_INIT(name) { &(name), &(name) } + +#define LIST_HEAD(name) \ + struct list_head name = LIST_HEAD_INIT(name) + +/** + * list_entry - get the struct for this entry + * @ptr: the &struct list_head pointer. + * @type: the type of the struct this is embedded in. + * @member: the name of the list_head within the struct. + */ +#define list_entry(ptr, type, member) \ + container_of(ptr, type, member) + +/** + * list_for_each_entry - iterate over list of given type + * @pos: the type * to use as a loop cursor. + * @head: the head for your list. + * @member: the name of the list_head within the struct. + */ +#define list_for_each_entry(pos, head, member) \ + for (pos = list_entry((head)->next, typeof(*pos), member); \ + &pos->member != (head); \ + pos = list_entry(pos->member.next, typeof(*pos), member)) + +/** + * list_for_each_entry_safe - iterate over list of given type safe against removal of list entry + * @pos: the type * to use as a loop cursor. + * @n: another type * to use as temporary storage + * @head: the head for your list. + * @member: the name of the list_head within the struct. + */ +#define list_for_each_entry_safe(pos, n, head, member) \ + for (pos = list_entry((head)->next, typeof(*pos), member), \ + n = list_entry(pos->member.next, typeof(*pos), member); \ + &pos->member != (head); \ + pos = n, n = list_entry(n->member.next, typeof(*n), member)) + +/** + * list_empty - tests whether a list is empty + * @head: the list to test. + */ +static inline int list_empty(const struct list_head *head) +{ + return head->next == head; +} + +/* + * Insert a new entry between two known consecutive entries. + * + * This is only for internal list manipulation where we know + * the prev/next entries already! + */ +static inline void __list_add(struct list_head *_new, + struct list_head *prev, + struct list_head *next) +{ + next->prev = _new; + _new->next = next; + _new->prev = prev; + prev->next = _new; +} + +/** + * list_add_tail - add a new entry + * @new: new entry to be added + * @head: list head to add it before + * + * Insert a new entry before the specified head. + * This is useful for implementing queues. + */ +static inline void list_add_tail(struct list_head *_new, struct list_head *head) +{ + __list_add(_new, head->prev, head); +} + +/* + * Delete a list entry by making the prev/next entries + * point to each other. + * + * This is only for internal list manipulation where we know + * the prev/next entries already! + */ +static inline void __list_del(struct list_head *prev, struct list_head *next) +{ + next->prev = prev; + prev->next = next; +} + +#define LIST_POISON1 ((void *) 0x00100100) +#define LIST_POISON2 ((void *) 0x00200200) +/** + * list_del - deletes entry from list. + * @entry: the element to delete from the list. + * Note: list_empty() on entry does not return true after this, the entry is + * in an undefined state. + */ +static inline void list_del(struct list_head *entry) +{ + __list_del(entry->prev, entry->next); + entry->next = (struct list_head*)LIST_POISON1; + entry->prev = (struct list_head*)LIST_POISON2; +} +#endif diff --git a/tools/kconfig/lkc.h b/tools/kconfig/lkc.h new file mode 100644 index 0000000000..b1f1cc34a7 --- /dev/null +++ b/tools/kconfig/lkc.h @@ -0,0 +1,187 @@ +/* + * Copyright (C) 2002 Roman Zippel + * Released under the terms of the GNU GPL v2.0. + */ + +#ifndef LKC_H +#define LKC_H + +#include "expr.h" + +#ifndef KBUILD_NO_NLS +# include +#else +static inline const char *gettext(const char *txt) { return txt; } +static inline void textdomain(const char *domainname) {} +static inline void bindtextdomain(const char *name, const char *dir) {} +static inline char *bind_textdomain_codeset(const char *dn, char *c) { return c; } +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +#include "lkc_proto.h" + +#define SRCTREE "srctree" + +#ifndef PACKAGE +#define PACKAGE "linux" +#endif + +#define LOCALEDIR "/usr/share/locale" + +#define _(text) gettext(text) +#define N_(text) (text) + +#ifndef CONFIG_ +#define CONFIG_ "CONFIG_" +#endif +static inline const char *CONFIG_prefix(void) +{ + return getenv( "CONFIG_" ) ?: CONFIG_; +} +#undef CONFIG_ +#define CONFIG_ CONFIG_prefix() + +#define TF_COMMAND 0x0001 +#define TF_PARAM 0x0002 +#define TF_OPTION 0x0004 + +enum conf_def_mode { + def_default, + def_yes, + def_mod, + def_no, + def_random +}; + +#define T_OPT_MODULES 1 +#define T_OPT_DEFCONFIG_LIST 2 +#define T_OPT_ENV 3 +#define T_OPT_ALLNOCONFIG_Y 4 + +struct kconf_id { + int name; + int token; + unsigned int flags; + enum symbol_type stype; +}; + +void zconfdump(FILE *out); +void zconf_starthelp(void); +FILE *zconf_fopen(const char *name); +void zconf_initscan(const char *name); +void zconf_nextfile(const char *name); +void zconf_nextfiles(const char *name); +int zconf_lineno(void); +const char *zconf_curname(void); + +/* confdata.c */ +const char *conf_get_configname(void); +const char *conf_get_autoconfig_name(void); +char *conf_get_default_confname(void); +void sym_set_change_count(int count); +void sym_add_change_count(int count); +bool conf_set_all_new_symbols(enum conf_def_mode mode); +void set_all_choice_values(struct symbol *csym); + +/* confdata.c and expr.c */ +static inline void xfwrite(const void *str, size_t len, size_t count, FILE *out) +{ + assert(len != 0); + + if (fwrite(str, len, count, out) != count) + fprintf(stderr, "Error in writing or end of file.\n"); +} + +/* menu.c */ +void _menu_init(void); +void menu_warn(struct menu *menu, const char *fmt, ...); +struct menu *menu_add_menu(void); +void menu_end_menu(void); +void menu_add_entry(struct symbol *sym); +void menu_end_entry(void); +void menu_add_dep(struct expr *dep); +void menu_add_visibility(struct expr *dep); +struct property *menu_add_prompt(enum prop_type type, char *prompt, struct expr *dep); +void menu_add_expr(enum prop_type type, struct expr *expr, struct expr *dep); +void menu_add_symbol(enum prop_type type, struct symbol *sym, struct expr *dep); +void menu_add_option(int token, char *arg); +void menu_finalize(struct menu *parent); +void menu_set_type(int type); + +/* util.c */ +struct file *file_lookup(const char *name); +int file_write_dep(const char *name); +void *xmalloc(size_t size); +void *xcalloc(size_t nmemb, size_t size); + +struct gstr { + size_t len; + char *s; + /* + * when max_width is not zero long lines in string s (if any) get + * wrapped not to exceed the max_width value + */ + int max_width; +}; +struct gstr str_new(void); +void str_free(struct gstr *gs); +void str_append(struct gstr *gs, const char *s); +void str_printf(struct gstr *gs, const char *fmt, ...); +const char *str_get(struct gstr *gs); + +/* symbol.c */ +extern struct expr *sym_env_list; + +void sym_init(void); +void sym_clear_all_valid(void); +struct symbol *sym_choice_default(struct symbol *sym); +const char *sym_get_string_default(struct symbol *sym); +struct symbol *sym_check_deps(struct symbol *sym); +struct property *prop_alloc(enum prop_type type, struct symbol *sym); +struct symbol *prop_get_symbol(struct property *prop); +struct property *sym_get_env_prop(struct symbol *sym); + +static inline tristate sym_get_tristate_value(struct symbol *sym) +{ + return sym->curr.tri; +} + + +static inline struct symbol *sym_get_choice_value(struct symbol *sym) +{ + return (struct symbol *)sym->curr.val; +} + +static inline bool sym_set_choice_value(struct symbol *ch, struct symbol *chval) +{ + return sym_set_tristate_value(chval, yes); +} + +static inline bool sym_is_choice(struct symbol *sym) +{ + return sym->flags & SYMBOL_CHOICE ? true : false; +} + +static inline bool sym_is_choice_value(struct symbol *sym) +{ + return sym->flags & SYMBOL_CHOICEVAL ? true : false; +} + +static inline bool sym_is_optional(struct symbol *sym) +{ + return sym->flags & SYMBOL_OPTIONAL ? true : false; +} + +static inline bool sym_has_value(struct symbol *sym) +{ + return sym->flags & SYMBOL_DEF_USER ? true : false; +} + +#ifdef __cplusplus +} +#endif + +#endif /* LKC_H */ diff --git a/tools/kconfig/lkc_proto.h b/tools/kconfig/lkc_proto.h new file mode 100644 index 0000000000..d5398718ec --- /dev/null +++ b/tools/kconfig/lkc_proto.h @@ -0,0 +1,52 @@ +#include + +/* confdata.c */ +void conf_parse(const char *name); +int conf_read(const char *name); +int conf_read_simple(const char *name, int); +int conf_write_defconfig(const char *name); +int conf_write(const char *name); +int conf_write_autoconf(void); +bool conf_get_changed(void); +void conf_set_changed_callback(void (*fn)(void)); +void conf_set_message_callback(void (*fn)(const char *fmt, va_list ap)); + +/* menu.c */ +extern struct menu rootmenu; + +bool menu_is_empty(struct menu *menu); +bool menu_is_visible(struct menu *menu); +bool menu_has_prompt(struct menu *menu); +const char * menu_get_prompt(struct menu *menu); +struct menu * menu_get_root_menu(struct menu *menu); +struct menu * menu_get_parent_menu(struct menu *menu); +bool menu_has_help(struct menu *menu); +const char * menu_get_help(struct menu *menu); +struct gstr get_relations_str(struct symbol **sym_arr, struct list_head *head); +void menu_get_ext_help(struct menu *menu, struct gstr *help); + +/* symbol.c */ +extern struct symbol * symbol_hash[SYMBOL_HASHSIZE]; + +struct symbol * sym_lookup(const char *name, int flags); +struct symbol * sym_find(const char *name); +const char * sym_expand_string_value(const char *in); +const char * sym_escape_string_value(const char *in); +struct symbol ** sym_re_search(const char *pattern); +const char * sym_type_name(enum symbol_type type); +void sym_calc_value(struct symbol *sym); +enum symbol_type sym_get_type(struct symbol *sym); +bool sym_tristate_within_range(struct symbol *sym,tristate tri); +bool sym_set_tristate_value(struct symbol *sym,tristate tri); +tristate sym_toggle_tristate_value(struct symbol *sym); +bool sym_string_valid(struct symbol *sym, const char *newval); +bool sym_string_within_range(struct symbol *sym, const char *str); +bool sym_set_string_value(struct symbol *sym, const char *newval); +bool sym_is_changable(struct symbol *sym); +struct property * sym_get_choice_prop(struct symbol *sym); +const char * sym_get_string_value(struct symbol *sym); + +const char * prop_get_type_name(enum prop_type type); + +/* expr.c */ +void expr_print(struct expr *e, void (*fn)(void *, struct symbol *, const char *), void *data, int prevtoken); diff --git a/tools/kconfig/lxdialog/.gitignore b/tools/kconfig/lxdialog/.gitignore new file mode 100644 index 0000000000..90b08ff025 --- /dev/null +++ b/tools/kconfig/lxdialog/.gitignore @@ -0,0 +1,4 @@ +# +# Generated files +# +lxdialog diff --git a/tools/kconfig/lxdialog/BIG.FAT.WARNING b/tools/kconfig/lxdialog/BIG.FAT.WARNING new file mode 100644 index 0000000000..a8999d82bd --- /dev/null +++ b/tools/kconfig/lxdialog/BIG.FAT.WARNING @@ -0,0 +1,4 @@ +This is NOT the official version of dialog. This version has been +significantly modified from the original. It is for use by the Linux +kernel configuration script. Please do not bother Savio Lam with +questions about this program. diff --git a/tools/kconfig/lxdialog/check-lxdialog.sh b/tools/kconfig/lxdialog/check-lxdialog.sh new file mode 100755 index 0000000000..6964d2b0c5 --- /dev/null +++ b/tools/kconfig/lxdialog/check-lxdialog.sh @@ -0,0 +1,95 @@ +#!/bin/bash +# Check ncurses compatibility + +# What library to link +ldflags() +{ + if [ $(uname -s) == "Darwin" ]; then + #OSX seems to need intl too + echo -n "-lintl " + fi + pkg-config --libs ncursesw 2>/dev/null && exit + pkg-config --libs ncurses 2>/dev/null && exit + for ext in so a dll.a dylib ; do + for lib in ncursesw ncurses curses ; do + $cc -print-file-name=lib${lib}.${ext} $extra_libs | grep -q / + if [ $? -eq 0 ]; then + echo "-l${lib}" + exit + fi + done + done + exit 1 +} + +# Where is ncurses.h? +ccflags() +{ + if pkg-config --cflags ncursesw 2>/dev/null; then + echo '-DCURSES_LOC="" -DNCURSES_WIDECHAR=1' + elif pkg-config --cflags ncurses 2>/dev/null; then + echo '-DCURSES_LOC=""' + elif [ -f /usr/include/ncursesw/curses.h ]; then + echo '-I/usr/include/ncursesw -DCURSES_LOC=""' + echo ' -DNCURSES_WIDECHAR=1' + elif [ -f /usr/include/ncurses/ncurses.h ]; then + echo '-I/usr/include/ncurses -DCURSES_LOC=""' + elif [ -f /usr/include/ncurses/curses.h ]; then + echo '-I/usr/include/ncurses -DCURSES_LOC=""' + elif [ -f /usr/include/ncurses.h ]; then + echo '-DCURSES_LOC=""' + else + echo '-DCURSES_LOC=""' + fi +} + +# Temp file, try to clean up after us +tmp=.lxdialog.tmp +trap "rm -f $tmp" 0 1 2 3 15 + +# Check if we can link to ncurses +check() { + $cc -x c - -o $tmp 2>/dev/null <<'EOF' +#include CURSES_LOC +main() {} +EOF + if [ $? != 0 ]; then + echo " *** Unable to find the ncurses libraries or the" 1>&2 + echo " *** required header files." 1>&2 + echo " *** 'make menuconfig' requires the ncurses libraries." 1>&2 + echo " *** " 1>&2 + echo " *** Install ncurses (ncurses-devel) and try again." 1>&2 + echo " *** " 1>&2 + exit 1 + fi +} + +usage() { + printf "Usage: $0 [-check compiler options|-ccflags|-ldflags compiler options]\n" +} + +if [ $# -eq 0 ]; then + usage + exit 1 +fi + +cc="" +case "$1" in + "-check") + shift + cc="$@" + check + ;; + "-ccflags") + ccflags + ;; + "-ldflags") + shift + cc="$@" + ldflags + ;; + "*") + usage + exit 1 + ;; +esac diff --git a/tools/kconfig/lxdialog/checklist.c b/tools/kconfig/lxdialog/checklist.c new file mode 100644 index 0000000000..8d016faa28 --- /dev/null +++ b/tools/kconfig/lxdialog/checklist.c @@ -0,0 +1,332 @@ +/* + * checklist.c -- implements the checklist box + * + * ORIGINAL AUTHOR: Savio Lam (lam836@cs.cuhk.hk) + * Stuart Herbert - S.Herbert@sheffield.ac.uk: radiolist extension + * Alessandro Rubini - rubini@ipvvis.unipv.it: merged the two + * MODIFIED FOR LINUX KERNEL CONFIG BY: William Roadcap (roadcap@cfw.com) + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include "dialog.h" + +static int list_width, check_x, item_x; + +/* + * Print list item + */ +static void print_item(WINDOW * win, int choice, int selected) +{ + int i; + char *list_item = malloc(list_width + 1); + + strncpy(list_item, item_str(), list_width - item_x); + list_item[list_width - item_x] = '\0'; + + /* Clear 'residue' of last item */ + wattrset(win, dlg.menubox.atr); + wmove(win, choice, 0); + for (i = 0; i < list_width; i++) + waddch(win, ' '); + + wmove(win, choice, check_x); + wattrset(win, selected ? dlg.check_selected.atr + : dlg.check.atr); + if (!item_is_tag(':')) + wprintw(win, "(%c)", item_is_tag('X') ? 'X' : ' '); + + wattrset(win, selected ? dlg.tag_selected.atr : dlg.tag.atr); + mvwaddch(win, choice, item_x, list_item[0]); + wattrset(win, selected ? dlg.item_selected.atr : dlg.item.atr); + waddstr(win, list_item + 1); + if (selected) { + wmove(win, choice, check_x + 1); + wrefresh(win); + } + free(list_item); +} + +/* + * Print the scroll indicators. + */ +static void print_arrows(WINDOW * win, int choice, int item_no, int scroll, + int y, int x, int height) +{ + wmove(win, y, x); + + if (scroll > 0) { + wattrset(win, dlg.uarrow.atr); + waddch(win, ACS_UARROW); + waddstr(win, "(-)"); + } else { + wattrset(win, dlg.menubox.atr); + waddch(win, ACS_HLINE); + waddch(win, ACS_HLINE); + waddch(win, ACS_HLINE); + waddch(win, ACS_HLINE); + } + + y = y + height + 1; + wmove(win, y, x); + + if ((height < item_no) && (scroll + choice < item_no - 1)) { + wattrset(win, dlg.darrow.atr); + waddch(win, ACS_DARROW); + waddstr(win, "(+)"); + } else { + wattrset(win, dlg.menubox_border.atr); + waddch(win, ACS_HLINE); + waddch(win, ACS_HLINE); + waddch(win, ACS_HLINE); + waddch(win, ACS_HLINE); + } +} + +/* + * Display the termination buttons + */ +static void print_buttons(WINDOW * dialog, int height, int width, int selected) +{ + int x = width / 2 - 11; + int y = height - 2; + + print_button(dialog, gettext("Select"), y, x, selected == 0); + print_button(dialog, gettext(" Help "), y, x + 14, selected == 1); + + wmove(dialog, y, x + 1 + 14 * selected); + wrefresh(dialog); +} + +/* + * Display a dialog box with a list of options that can be turned on or off + * in the style of radiolist (only one option turned on at a time). + */ +int dialog_checklist(const char *title, const char *prompt, int height, + int width, int list_height) +{ + int i, x, y, box_x, box_y; + int key = 0, button = 0, choice = 0, scroll = 0, max_choice; + WINDOW *dialog, *list; + + /* which item to highlight */ + item_foreach() { + if (item_is_tag('X')) + choice = item_n(); + if (item_is_selected()) { + choice = item_n(); + break; + } + } + +do_resize: + if (getmaxy(stdscr) < (height + CHECKLIST_HEIGTH_MIN)) + return -ERRDISPLAYTOOSMALL; + if (getmaxx(stdscr) < (width + CHECKLIST_WIDTH_MIN)) + return -ERRDISPLAYTOOSMALL; + + max_choice = MIN(list_height, item_count()); + + /* center dialog box on screen */ + x = (getmaxx(stdscr) - width) / 2; + y = (getmaxy(stdscr) - height) / 2; + + draw_shadow(stdscr, y, x, height, width); + + dialog = newwin(height, width, y, x); + keypad(dialog, TRUE); + + draw_box(dialog, 0, 0, height, width, + dlg.dialog.atr, dlg.border.atr); + wattrset(dialog, dlg.border.atr); + mvwaddch(dialog, height - 3, 0, ACS_LTEE); + for (i = 0; i < width - 2; i++) + waddch(dialog, ACS_HLINE); + wattrset(dialog, dlg.dialog.atr); + waddch(dialog, ACS_RTEE); + + print_title(dialog, title, width); + + wattrset(dialog, dlg.dialog.atr); + print_autowrap(dialog, prompt, width - 2, 1, 3); + + list_width = width - 6; + box_y = height - list_height - 5; + box_x = (width - list_width) / 2 - 1; + + /* create new window for the list */ + list = subwin(dialog, list_height, list_width, y + box_y + 1, + x + box_x + 1); + + keypad(list, TRUE); + + /* draw a box around the list items */ + draw_box(dialog, box_y, box_x, list_height + 2, list_width + 2, + dlg.menubox_border.atr, dlg.menubox.atr); + + /* Find length of longest item in order to center checklist */ + check_x = 0; + item_foreach() + check_x = MAX(check_x, strlen(item_str()) + 4); + check_x = MIN(check_x, list_width); + + check_x = (list_width - check_x) / 2; + item_x = check_x + 4; + + if (choice >= list_height) { + scroll = choice - list_height + 1; + choice -= scroll; + } + + /* Print the list */ + for (i = 0; i < max_choice; i++) { + item_set(scroll + i); + print_item(list, i, i == choice); + } + + print_arrows(dialog, choice, item_count(), scroll, + box_y, box_x + check_x + 5, list_height); + + print_buttons(dialog, height, width, 0); + + wnoutrefresh(dialog); + wnoutrefresh(list); + doupdate(); + + while (key != KEY_ESC) { + key = wgetch(dialog); + + for (i = 0; i < max_choice; i++) { + item_set(i + scroll); + if (toupper(key) == toupper(item_str()[0])) + break; + } + + if (i < max_choice || key == KEY_UP || key == KEY_DOWN || + key == '+' || key == '-') { + if (key == KEY_UP || key == '-') { + if (!choice) { + if (!scroll) + continue; + /* Scroll list down */ + if (list_height > 1) { + /* De-highlight current first item */ + item_set(scroll); + print_item(list, 0, FALSE); + scrollok(list, TRUE); + wscrl(list, -1); + scrollok(list, FALSE); + } + scroll--; + item_set(scroll); + print_item(list, 0, TRUE); + print_arrows(dialog, choice, item_count(), + scroll, box_y, box_x + check_x + 5, list_height); + + wnoutrefresh(dialog); + wrefresh(list); + + continue; /* wait for another key press */ + } else + i = choice - 1; + } else if (key == KEY_DOWN || key == '+') { + if (choice == max_choice - 1) { + if (scroll + choice >= item_count() - 1) + continue; + /* Scroll list up */ + if (list_height > 1) { + /* De-highlight current last item before scrolling up */ + item_set(scroll + max_choice - 1); + print_item(list, + max_choice - 1, + FALSE); + scrollok(list, TRUE); + wscrl(list, 1); + scrollok(list, FALSE); + } + scroll++; + item_set(scroll + max_choice - 1); + print_item(list, max_choice - 1, TRUE); + + print_arrows(dialog, choice, item_count(), + scroll, box_y, box_x + check_x + 5, list_height); + + wnoutrefresh(dialog); + wrefresh(list); + + continue; /* wait for another key press */ + } else + i = choice + 1; + } + if (i != choice) { + /* De-highlight current item */ + item_set(scroll + choice); + print_item(list, choice, FALSE); + /* Highlight new item */ + choice = i; + item_set(scroll + choice); + print_item(list, choice, TRUE); + wnoutrefresh(dialog); + wrefresh(list); + } + continue; /* wait for another key press */ + } + switch (key) { + case 'H': + case 'h': + case '?': + button = 1; + /* fall-through */ + case 'S': + case 's': + case ' ': + case '\n': + item_foreach() + item_set_selected(0); + item_set(scroll + choice); + item_set_selected(1); + delwin(list); + delwin(dialog); + return button; + case TAB: + case KEY_LEFT: + case KEY_RIGHT: + button = ((key == KEY_LEFT ? --button : ++button) < 0) + ? 1 : (button > 1 ? 0 : button); + + print_buttons(dialog, height, width, button); + wrefresh(dialog); + break; + case 'X': + case 'x': + key = KEY_ESC; + break; + case KEY_ESC: + key = on_key_esc(dialog); + break; + case KEY_RESIZE: + delwin(list); + delwin(dialog); + on_key_resize(); + goto do_resize; + } + + /* Now, update everything... */ + doupdate(); + } + delwin(list); + delwin(dialog); + return key; /* ESC pressed */ +} diff --git a/tools/kconfig/lxdialog/dialog.h b/tools/kconfig/lxdialog/dialog.h new file mode 100644 index 0000000000..fcffd5b41f --- /dev/null +++ b/tools/kconfig/lxdialog/dialog.h @@ -0,0 +1,257 @@ +/* + * dialog.h -- common declarations for all dialog modules + * + * AUTHOR: Savio Lam (lam836@cs.cuhk.hk) + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include +#include +#include +#include +#include +#include +#include + +#ifndef KBUILD_NO_NLS +# include +#else +# define gettext(Msgid) ((const char *) (Msgid)) +#endif + +#ifdef __sun__ +#define CURS_MACROS +#endif +#include CURSES_LOC + +/* + * Colors in ncurses 1.9.9e do not work properly since foreground and + * background colors are OR'd rather than separately masked. This version + * of dialog was hacked to work with ncurses 1.9.9e, making it incompatible + * with standard curses. The simplest fix (to make this work with standard + * curses) uses the wbkgdset() function, not used in the original hack. + * Turn it off if we're building with 1.9.9e, since it just confuses things. + */ +#if defined(NCURSES_VERSION) && defined(_NEED_WRAP) && !defined(GCC_PRINTFLIKE) +#define OLD_NCURSES 1 +#undef wbkgdset +#define wbkgdset(w,p) /*nothing */ +#else +#define OLD_NCURSES 0 +#endif + +#define TR(params) _tracef params + +#define KEY_ESC 27 +#define TAB 9 +#define MAX_LEN 2048 +#define BUF_SIZE (10*1024) +#define MIN(x,y) (x < y ? x : y) +#define MAX(x,y) (x > y ? x : y) + +#ifndef ACS_ULCORNER +#define ACS_ULCORNER '+' +#endif +#ifndef ACS_LLCORNER +#define ACS_LLCORNER '+' +#endif +#ifndef ACS_URCORNER +#define ACS_URCORNER '+' +#endif +#ifndef ACS_LRCORNER +#define ACS_LRCORNER '+' +#endif +#ifndef ACS_HLINE +#define ACS_HLINE '-' +#endif +#ifndef ACS_VLINE +#define ACS_VLINE '|' +#endif +#ifndef ACS_LTEE +#define ACS_LTEE '+' +#endif +#ifndef ACS_RTEE +#define ACS_RTEE '+' +#endif +#ifndef ACS_UARROW +#define ACS_UARROW '^' +#endif +#ifndef ACS_DARROW +#define ACS_DARROW 'v' +#endif + +/* error return codes */ +#define ERRDISPLAYTOOSMALL (KEY_MAX + 1) + +/* + * Color definitions + */ +struct dialog_color { + chtype atr; /* Color attribute */ + int fg; /* foreground */ + int bg; /* background */ + int hl; /* highlight this item */ +}; + +struct subtitle_list { + struct subtitle_list *next; + const char *text; +}; + +struct dialog_info { + const char *backtitle; + struct subtitle_list *subtitles; + struct dialog_color screen; + struct dialog_color shadow; + struct dialog_color dialog; + struct dialog_color title; + struct dialog_color border; + struct dialog_color button_active; + struct dialog_color button_inactive; + struct dialog_color button_key_active; + struct dialog_color button_key_inactive; + struct dialog_color button_label_active; + struct dialog_color button_label_inactive; + struct dialog_color inputbox; + struct dialog_color inputbox_border; + struct dialog_color searchbox; + struct dialog_color searchbox_title; + struct dialog_color searchbox_border; + struct dialog_color position_indicator; + struct dialog_color menubox; + struct dialog_color menubox_border; + struct dialog_color item; + struct dialog_color item_selected; + struct dialog_color tag; + struct dialog_color tag_selected; + struct dialog_color tag_key; + struct dialog_color tag_key_selected; + struct dialog_color check; + struct dialog_color check_selected; + struct dialog_color uarrow; + struct dialog_color darrow; +}; + +/* + * Global variables + */ +extern struct dialog_info dlg; +extern char dialog_input_result[]; +extern int saved_x, saved_y; /* Needed in signal handler in mconf.c */ + +/* + * Function prototypes + */ + +/* item list as used by checklist and menubox */ +void item_reset(void); +void item_make(const char *fmt, ...); +void item_add_str(const char *fmt, ...); +void item_set_tag(char tag); +void item_set_data(void *p); +void item_set_selected(int val); +int item_activate_selected(void); +void *item_data(void); +char item_tag(void); + +/* item list manipulation for lxdialog use */ +#define MAXITEMSTR 200 +struct dialog_item { + char str[MAXITEMSTR]; /* prompt displayed */ + char tag; + void *data; /* pointer to menu item - used by menubox+checklist */ + int selected; /* Set to 1 by dialog_*() function if selected. */ +}; + +/* list of lialog_items */ +struct dialog_list { + struct dialog_item node; + struct dialog_list *next; +}; + +extern struct dialog_list *item_cur; +extern struct dialog_list item_nil; +extern struct dialog_list *item_head; + +int item_count(void); +void item_set(int n); +int item_n(void); +const char *item_str(void); +int item_is_selected(void); +int item_is_tag(char tag); +#define item_foreach() \ + for (item_cur = item_head ? item_head: item_cur; \ + item_cur && (item_cur != &item_nil); item_cur = item_cur->next) + +/* generic key handlers */ +int on_key_esc(WINDOW *win); +int on_key_resize(void); + +/* minimum (re)size values */ +#define CHECKLIST_HEIGTH_MIN 6 /* For dialog_checklist() */ +#define CHECKLIST_WIDTH_MIN 6 +#define INPUTBOX_HEIGTH_MIN 2 /* For dialog_inputbox() */ +#define INPUTBOX_WIDTH_MIN 2 +#define MENUBOX_HEIGTH_MIN 15 /* For dialog_menu() */ +#define MENUBOX_WIDTH_MIN 65 +#define TEXTBOX_HEIGTH_MIN 8 /* For dialog_textbox() */ +#define TEXTBOX_WIDTH_MIN 8 +#define YESNO_HEIGTH_MIN 4 /* For dialog_yesno() */ +#define YESNO_WIDTH_MIN 4 +#define WINDOW_HEIGTH_MIN 19 /* For init_dialog() */ +#define WINDOW_WIDTH_MIN 80 + +int init_dialog(const char *backtitle); +void set_dialog_backtitle(const char *backtitle); +void set_dialog_subtitles(struct subtitle_list *subtitles); +void end_dialog(int x, int y); +void attr_clear(WINDOW * win, int height, int width, chtype attr); +void dialog_clear(void); +void print_autowrap(WINDOW * win, const char *prompt, int width, int y, int x); +void print_button(WINDOW * win, const char *label, int y, int x, int selected); +void print_title(WINDOW *dialog, const char *title, int width); +void draw_box(WINDOW * win, int y, int x, int height, int width, chtype box, + chtype border); +void draw_shadow(WINDOW * win, int y, int x, int height, int width); + +int first_alpha(const char *string, const char *exempt); +int dialog_yesno(const char *title, const char *prompt, int height, int width); +int dialog_msgbox(const char *title, const char *prompt, int height, + int width, int pause); + + +typedef void (*update_text_fn)(char *buf, size_t start, size_t end, void + *_data); +int dialog_textbox(const char *title, char *tbuf, int initial_height, + int initial_width, int *keys, int *_vscroll, int *_hscroll, + update_text_fn update_text, void *data); +int dialog_menu(const char *title, const char *prompt, + const void *selected, int *s_scroll); +int dialog_checklist(const char *title, const char *prompt, int height, + int width, int list_height); +int dialog_inputbox(const char *title, const char *prompt, int height, + int width, const char *init); + +/* + * This is the base for fictitious keys, which activate + * the buttons. + * + * Mouse-generated keys are the following: + * -- the first 32 are used as numbers, in addition to '0'-'9' + * -- the lowercase are used to signal mouse-enter events (M_EVENT + 'o') + * -- uppercase chars are used to invoke the button (M_EVENT + 'O') + */ +#define M_EVENT (KEY_MAX+1) diff --git a/tools/kconfig/lxdialog/inputbox.c b/tools/kconfig/lxdialog/inputbox.c new file mode 100644 index 0000000000..d58de1dc53 --- /dev/null +++ b/tools/kconfig/lxdialog/inputbox.c @@ -0,0 +1,301 @@ +/* + * inputbox.c -- implements the input box + * + * ORIGINAL AUTHOR: Savio Lam (lam836@cs.cuhk.hk) + * MODIFIED FOR LINUX KERNEL CONFIG BY: William Roadcap (roadcap@cfw.com) + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include "dialog.h" + +char dialog_input_result[MAX_LEN + 1]; + +/* + * Print the termination buttons + */ +static void print_buttons(WINDOW * dialog, int height, int width, int selected) +{ + int x = width / 2 - 11; + int y = height - 2; + + print_button(dialog, gettext(" Ok "), y, x, selected == 0); + print_button(dialog, gettext(" Help "), y, x + 14, selected == 1); + + wmove(dialog, y, x + 1 + 14 * selected); + wrefresh(dialog); +} + +/* + * Display a dialog box for inputing a string + */ +int dialog_inputbox(const char *title, const char *prompt, int height, int width, + const char *init) +{ + int i, x, y, box_y, box_x, box_width; + int input_x = 0, key = 0, button = -1; + int show_x, len, pos; + char *instr = dialog_input_result; + WINDOW *dialog; + + if (!init) + instr[0] = '\0'; + else + strcpy(instr, init); + +do_resize: + if (getmaxy(stdscr) <= (height - INPUTBOX_HEIGTH_MIN)) + return -ERRDISPLAYTOOSMALL; + if (getmaxx(stdscr) <= (width - INPUTBOX_WIDTH_MIN)) + return -ERRDISPLAYTOOSMALL; + + /* center dialog box on screen */ + x = (getmaxx(stdscr) - width) / 2; + y = (getmaxy(stdscr) - height) / 2; + + draw_shadow(stdscr, y, x, height, width); + + dialog = newwin(height, width, y, x); + keypad(dialog, TRUE); + + draw_box(dialog, 0, 0, height, width, + dlg.dialog.atr, dlg.border.atr); + wattrset(dialog, dlg.border.atr); + mvwaddch(dialog, height - 3, 0, ACS_LTEE); + for (i = 0; i < width - 2; i++) + waddch(dialog, ACS_HLINE); + wattrset(dialog, dlg.dialog.atr); + waddch(dialog, ACS_RTEE); + + print_title(dialog, title, width); + + wattrset(dialog, dlg.dialog.atr); + print_autowrap(dialog, prompt, width - 2, 1, 3); + + /* Draw the input field box */ + box_width = width - 6; + getyx(dialog, y, x); + box_y = y + 2; + box_x = (width - box_width) / 2; + draw_box(dialog, y + 1, box_x - 1, 3, box_width + 2, + dlg.dialog.atr, dlg.border.atr); + + print_buttons(dialog, height, width, 0); + + /* Set up the initial value */ + wmove(dialog, box_y, box_x); + wattrset(dialog, dlg.inputbox.atr); + + len = strlen(instr); + pos = len; + + if (len >= box_width) { + show_x = len - box_width + 1; + input_x = box_width - 1; + for (i = 0; i < box_width - 1; i++) + waddch(dialog, instr[show_x + i]); + } else { + show_x = 0; + input_x = len; + waddstr(dialog, instr); + } + + wmove(dialog, box_y, box_x + input_x); + + wrefresh(dialog); + + while (key != KEY_ESC) { + key = wgetch(dialog); + + if (button == -1) { /* Input box selected */ + switch (key) { + case TAB: + case KEY_UP: + case KEY_DOWN: + break; + case KEY_BACKSPACE: + case 127: + if (pos) { + wattrset(dialog, dlg.inputbox.atr); + if (input_x == 0) { + show_x--; + } else + input_x--; + + if (pos < len) { + for (i = pos - 1; i < len; i++) { + instr[i] = instr[i+1]; + } + } + + pos--; + len--; + instr[len] = '\0'; + wmove(dialog, box_y, box_x); + for (i = 0; i < box_width; i++) { + if (!instr[show_x + i]) { + waddch(dialog, ' '); + break; + } + waddch(dialog, instr[show_x + i]); + } + wmove(dialog, box_y, input_x + box_x); + wrefresh(dialog); + } + continue; + case KEY_LEFT: + if (pos > 0) { + if (input_x > 0) { + wmove(dialog, box_y, --input_x + box_x); + } else if (input_x == 0) { + show_x--; + wmove(dialog, box_y, box_x); + for (i = 0; i < box_width; i++) { + if (!instr[show_x + i]) { + waddch(dialog, ' '); + break; + } + waddch(dialog, instr[show_x + i]); + } + wmove(dialog, box_y, box_x); + } + pos--; + } + continue; + case KEY_RIGHT: + if (pos < len) { + if (input_x < box_width - 1) { + wmove(dialog, box_y, ++input_x + box_x); + } else if (input_x == box_width - 1) { + show_x++; + wmove(dialog, box_y, box_x); + for (i = 0; i < box_width; i++) { + if (!instr[show_x + i]) { + waddch(dialog, ' '); + break; + } + waddch(dialog, instr[show_x + i]); + } + wmove(dialog, box_y, input_x + box_x); + } + pos++; + } + continue; + default: + if (key < 0x100 && isprint(key)) { + if (len < MAX_LEN) { + wattrset(dialog, dlg.inputbox.atr); + if (pos < len) { + for (i = len; i > pos; i--) + instr[i] = instr[i-1]; + instr[pos] = key; + } else { + instr[len] = key; + } + pos++; + len++; + instr[len] = '\0'; + + if (input_x == box_width - 1) { + show_x++; + } else { + input_x++; + } + + wmove(dialog, box_y, box_x); + for (i = 0; i < box_width; i++) { + if (!instr[show_x + i]) { + waddch(dialog, ' '); + break; + } + waddch(dialog, instr[show_x + i]); + } + wmove(dialog, box_y, input_x + box_x); + wrefresh(dialog); + } else + flash(); /* Alarm user about overflow */ + continue; + } + } + } + switch (key) { + case 'O': + case 'o': + delwin(dialog); + return 0; + case 'H': + case 'h': + delwin(dialog); + return 1; + case KEY_UP: + case KEY_LEFT: + switch (button) { + case -1: + button = 1; /* Indicates "Help" button is selected */ + print_buttons(dialog, height, width, 1); + break; + case 0: + button = -1; /* Indicates input box is selected */ + print_buttons(dialog, height, width, 0); + wmove(dialog, box_y, box_x + input_x); + wrefresh(dialog); + break; + case 1: + button = 0; /* Indicates "OK" button is selected */ + print_buttons(dialog, height, width, 0); + break; + } + break; + case TAB: + case KEY_DOWN: + case KEY_RIGHT: + switch (button) { + case -1: + button = 0; /* Indicates "OK" button is selected */ + print_buttons(dialog, height, width, 0); + break; + case 0: + button = 1; /* Indicates "Help" button is selected */ + print_buttons(dialog, height, width, 1); + break; + case 1: + button = -1; /* Indicates input box is selected */ + print_buttons(dialog, height, width, 0); + wmove(dialog, box_y, box_x + input_x); + wrefresh(dialog); + break; + } + break; + case ' ': + case '\n': + delwin(dialog); + return (button == -1 ? 0 : button); + case 'X': + case 'x': + key = KEY_ESC; + break; + case KEY_ESC: + key = on_key_esc(dialog); + break; + case KEY_RESIZE: + delwin(dialog); + on_key_resize(); + goto do_resize; + } + } + + delwin(dialog); + return KEY_ESC; /* ESC pressed */ +} diff --git a/tools/kconfig/lxdialog/menubox.c b/tools/kconfig/lxdialog/menubox.c new file mode 100644 index 0000000000..11ae9ad7ac --- /dev/null +++ b/tools/kconfig/lxdialog/menubox.c @@ -0,0 +1,437 @@ +/* + * menubox.c -- implements the menu box + * + * ORIGINAL AUTHOR: Savio Lam (lam836@cs.cuhk.hk) + * MODIFIED FOR LINUX KERNEL CONFIG BY: William Roadcap (roadcapw@cfw.com) + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +/* + * Changes by Clifford Wolf (god@clifford.at) + * + * [ 1998-06-13 ] + * + * *) A bugfix for the Page-Down problem + * + * *) Formerly when I used Page Down and Page Up, the cursor would be set + * to the first position in the menu box. Now lxdialog is a bit + * smarter and works more like other menu systems (just have a look at + * it). + * + * *) Formerly if I selected something my scrolling would be broken because + * lxdialog is re-invoked by the Menuconfig shell script, can't + * remember the last scrolling position, and just sets it so that the + * cursor is at the bottom of the box. Now it writes the temporary file + * lxdialog.scrltmp which contains this information. The file is + * deleted by lxdialog if the user leaves a submenu or enters a new + * one, but it would be nice if Menuconfig could make another "rm -f" + * just to be sure. Just try it out - you will recognise a difference! + * + * [ 1998-06-14 ] + * + * *) Now lxdialog is crash-safe against broken "lxdialog.scrltmp" files + * and menus change their size on the fly. + * + * *) If for some reason the last scrolling position is not saved by + * lxdialog, it sets the scrolling so that the selected item is in the + * middle of the menu box, not at the bottom. + * + * 02 January 1999, Michael Elizabeth Chastain (mec@shout.net) + * Reset 'scroll' to 0 if the value from lxdialog.scrltmp is bogus. + * This fixes a bug in Menuconfig where using ' ' to descend into menus + * would leave mis-synchronized lxdialog.scrltmp files lying around, + * fscanf would read in 'scroll', and eventually that value would get used. + */ + +#include "dialog.h" + +static int menu_width, item_x; + +/* + * Print menu item + */ +static void do_print_item(WINDOW * win, const char *item, int line_y, + int selected, int hotkey) +{ + int j; + char *menu_item = malloc(menu_width + 1); + + strncpy(menu_item, item, menu_width - item_x); + menu_item[menu_width - item_x] = '\0'; + j = first_alpha(menu_item, "YyNnMmHh"); + + /* Clear 'residue' of last item */ + wattrset(win, dlg.menubox.atr); + wmove(win, line_y, 0); +#if OLD_NCURSES + { + int i; + for (i = 0; i < menu_width; i++) + waddch(win, ' '); + } +#else + wclrtoeol(win); +#endif + wattrset(win, selected ? dlg.item_selected.atr : dlg.item.atr); + mvwaddstr(win, line_y, item_x, menu_item); + if (hotkey) { + wattrset(win, selected ? dlg.tag_key_selected.atr + : dlg.tag_key.atr); + mvwaddch(win, line_y, item_x + j, menu_item[j]); + } + if (selected) { + wmove(win, line_y, item_x + 1); + } + free(menu_item); + wrefresh(win); +} + +#define print_item(index, choice, selected) \ +do { \ + item_set(index); \ + do_print_item(menu, item_str(), choice, selected, !item_is_tag(':')); \ +} while (0) + +/* + * Print the scroll indicators. + */ +static void print_arrows(WINDOW * win, int item_no, int scroll, int y, int x, + int height) +{ + int cur_y, cur_x; + + getyx(win, cur_y, cur_x); + + wmove(win, y, x); + + if (scroll > 0) { + wattrset(win, dlg.uarrow.atr); + waddch(win, ACS_UARROW); + waddstr(win, "(-)"); + } else { + wattrset(win, dlg.menubox.atr); + waddch(win, ACS_HLINE); + waddch(win, ACS_HLINE); + waddch(win, ACS_HLINE); + waddch(win, ACS_HLINE); + } + + y = y + height + 1; + wmove(win, y, x); + wrefresh(win); + + if ((height < item_no) && (scroll + height < item_no)) { + wattrset(win, dlg.darrow.atr); + waddch(win, ACS_DARROW); + waddstr(win, "(+)"); + } else { + wattrset(win, dlg.menubox_border.atr); + waddch(win, ACS_HLINE); + waddch(win, ACS_HLINE); + waddch(win, ACS_HLINE); + waddch(win, ACS_HLINE); + } + + wmove(win, cur_y, cur_x); + wrefresh(win); +} + +/* + * Display the termination buttons. + */ +static void print_buttons(WINDOW * win, int height, int width, int selected) +{ + int x = width / 2 - 28; + int y = height - 2; + + print_button(win, gettext("Select"), y, x, selected == 0); + print_button(win, gettext(" Exit "), y, x + 12, selected == 1); + print_button(win, gettext(" Help "), y, x + 24, selected == 2); + print_button(win, gettext(" Save "), y, x + 36, selected == 3); + print_button(win, gettext(" Load "), y, x + 48, selected == 4); + + wmove(win, y, x + 1 + 12 * selected); + wrefresh(win); +} + +/* scroll up n lines (n may be negative) */ +static void do_scroll(WINDOW *win, int *scroll, int n) +{ + /* Scroll menu up */ + scrollok(win, TRUE); + wscrl(win, n); + scrollok(win, FALSE); + *scroll = *scroll + n; + wrefresh(win); +} + +/* + * Display a menu for choosing among a number of options + */ +int dialog_menu(const char *title, const char *prompt, + const void *selected, int *s_scroll) +{ + int i, j, x, y, box_x, box_y; + int height, width, menu_height; + int key = 0, button = 0, scroll = 0, choice = 0; + int first_item = 0, max_choice; + WINDOW *dialog, *menu; + +do_resize: + height = getmaxy(stdscr); + width = getmaxx(stdscr); + if (height < MENUBOX_HEIGTH_MIN || width < MENUBOX_WIDTH_MIN) + return -ERRDISPLAYTOOSMALL; + + height -= 4; + width -= 5; + menu_height = height - 10; + + max_choice = MIN(menu_height, item_count()); + + /* center dialog box on screen */ + x = (getmaxx(stdscr) - width) / 2; + y = (getmaxy(stdscr) - height) / 2; + + draw_shadow(stdscr, y, x, height, width); + + dialog = newwin(height, width, y, x); + keypad(dialog, TRUE); + + draw_box(dialog, 0, 0, height, width, + dlg.dialog.atr, dlg.border.atr); + wattrset(dialog, dlg.border.atr); + mvwaddch(dialog, height - 3, 0, ACS_LTEE); + for (i = 0; i < width - 2; i++) + waddch(dialog, ACS_HLINE); + wattrset(dialog, dlg.dialog.atr); + wbkgdset(dialog, dlg.dialog.atr & A_COLOR); + waddch(dialog, ACS_RTEE); + + print_title(dialog, title, width); + + wattrset(dialog, dlg.dialog.atr); + print_autowrap(dialog, prompt, width - 2, 1, 3); + + menu_width = width - 6; + box_y = height - menu_height - 5; + box_x = (width - menu_width) / 2 - 1; + + /* create new window for the menu */ + menu = subwin(dialog, menu_height, menu_width, + y + box_y + 1, x + box_x + 1); + keypad(menu, TRUE); + + /* draw a box around the menu items */ + draw_box(dialog, box_y, box_x, menu_height + 2, menu_width + 2, + dlg.menubox_border.atr, dlg.menubox.atr); + + if (menu_width >= 80) + item_x = (menu_width - 70) / 2; + else + item_x = 4; + + /* Set choice to default item */ + item_foreach() + if (selected && (selected == item_data())) + choice = item_n(); + /* get the saved scroll info */ + scroll = *s_scroll; + if ((scroll <= choice) && (scroll + max_choice > choice) && + (scroll >= 0) && (scroll + max_choice <= item_count())) { + first_item = scroll; + choice = choice - scroll; + } else { + scroll = 0; + } + if ((choice >= max_choice)) { + if (choice >= item_count() - max_choice / 2) + scroll = first_item = item_count() - max_choice; + else + scroll = first_item = choice - max_choice / 2; + choice = choice - scroll; + } + + /* Print the menu */ + for (i = 0; i < max_choice; i++) { + print_item(first_item + i, i, i == choice); + } + + wnoutrefresh(menu); + + print_arrows(dialog, item_count(), scroll, + box_y, box_x + item_x + 1, menu_height); + + print_buttons(dialog, height, width, 0); + wmove(menu, choice, item_x + 1); + wrefresh(menu); + + while (key != KEY_ESC) { + key = wgetch(menu); + + if (key < 256 && isalpha(key)) + key = tolower(key); + + if (strchr("ynmh", key)) + i = max_choice; + else { + for (i = choice + 1; i < max_choice; i++) { + item_set(scroll + i); + j = first_alpha(item_str(), "YyNnMmHh"); + if (key == tolower(item_str()[j])) + break; + } + if (i == max_choice) + for (i = 0; i < max_choice; i++) { + item_set(scroll + i); + j = first_alpha(item_str(), "YyNnMmHh"); + if (key == tolower(item_str()[j])) + break; + } + } + + if (item_count() != 0 && + (i < max_choice || + key == KEY_UP || key == KEY_DOWN || + key == '-' || key == '+' || + key == KEY_PPAGE || key == KEY_NPAGE)) { + /* Remove highligt of current item */ + print_item(scroll + choice, choice, FALSE); + + if (key == KEY_UP || key == '-') { + if (choice < 2 && scroll) { + /* Scroll menu down */ + do_scroll(menu, &scroll, -1); + + print_item(scroll, 0, FALSE); + } else + choice = MAX(choice - 1, 0); + + } else if (key == KEY_DOWN || key == '+') { + print_item(scroll+choice, choice, FALSE); + + if ((choice > max_choice - 3) && + (scroll + max_choice < item_count())) { + /* Scroll menu up */ + do_scroll(menu, &scroll, 1); + + print_item(scroll+max_choice - 1, + max_choice - 1, FALSE); + } else + choice = MIN(choice + 1, max_choice - 1); + + } else if (key == KEY_PPAGE) { + scrollok(menu, TRUE); + for (i = 0; (i < max_choice); i++) { + if (scroll > 0) { + do_scroll(menu, &scroll, -1); + print_item(scroll, 0, FALSE); + } else { + if (choice > 0) + choice--; + } + } + + } else if (key == KEY_NPAGE) { + for (i = 0; (i < max_choice); i++) { + if (scroll + max_choice < item_count()) { + do_scroll(menu, &scroll, 1); + print_item(scroll+max_choice-1, + max_choice - 1, FALSE); + } else { + if (choice + 1 < max_choice) + choice++; + } + } + } else + choice = i; + + print_item(scroll + choice, choice, TRUE); + + print_arrows(dialog, item_count(), scroll, + box_y, box_x + item_x + 1, menu_height); + + wnoutrefresh(dialog); + wrefresh(menu); + + continue; /* wait for another key press */ + } + + switch (key) { + case KEY_LEFT: + case TAB: + case KEY_RIGHT: + button = ((key == KEY_LEFT ? --button : ++button) < 0) + ? 4 : (button > 4 ? 0 : button); + + print_buttons(dialog, height, width, button); + wrefresh(menu); + break; + case ' ': + case 's': + case 'y': + case 'n': + case 'm': + case '/': + case 'h': + case '?': + case 'z': + case '\n': + /* save scroll info */ + *s_scroll = scroll; + delwin(menu); + delwin(dialog); + item_set(scroll + choice); + item_set_selected(1); + switch (key) { + case 'h': + case '?': + return 2; + case 's': + case 'y': + return 5; + case 'n': + return 6; + case 'm': + return 7; + case ' ': + return 8; + case '/': + return 9; + case 'z': + return 10; + case '\n': + return button; + } + return 0; + case 'e': + case 'x': + key = KEY_ESC; + break; + case KEY_ESC: + key = on_key_esc(menu); + break; + case KEY_RESIZE: + on_key_resize(); + delwin(menu); + delwin(dialog); + goto do_resize; + } + } + delwin(menu); + delwin(dialog); + return key; /* ESC pressed */ +} diff --git a/tools/kconfig/lxdialog/textbox.c b/tools/kconfig/lxdialog/textbox.c new file mode 100644 index 0000000000..1773319b95 --- /dev/null +++ b/tools/kconfig/lxdialog/textbox.c @@ -0,0 +1,408 @@ +/* + * textbox.c -- implements the text box + * + * ORIGINAL AUTHOR: Savio Lam (lam836@cs.cuhk.hk) + * MODIFIED FOR LINUX KERNEL CONFIG BY: William Roadcap (roadcap@cfw.com) + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include "dialog.h" + +static void back_lines(int n); +static void print_page(WINDOW *win, int height, int width, update_text_fn + update_text, void *data); +static void print_line(WINDOW *win, int row, int width); +static char *get_line(void); +static void print_position(WINDOW * win); + +static int hscroll; +static int begin_reached, end_reached, page_length; +static char *buf; +static char *page; + +/* + * refresh window content + */ +static void refresh_text_box(WINDOW *dialog, WINDOW *box, int boxh, int boxw, + int cur_y, int cur_x, update_text_fn update_text, + void *data) +{ + print_page(box, boxh, boxw, update_text, data); + print_position(dialog); + wmove(dialog, cur_y, cur_x); /* Restore cursor position */ + wrefresh(dialog); +} + + +/* + * Display text from a file in a dialog box. + * + * keys is a null-terminated array + * update_text() may not add or remove any '\n' or '\0' in tbuf + */ +int dialog_textbox(const char *title, char *tbuf, int initial_height, + int initial_width, int *keys, int *_vscroll, int *_hscroll, + update_text_fn update_text, void *data) +{ + int i, x, y, cur_x, cur_y, key = 0; + int height, width, boxh, boxw; + WINDOW *dialog, *box; + bool done = false; + + begin_reached = 1; + end_reached = 0; + page_length = 0; + hscroll = 0; + buf = tbuf; + page = buf; /* page is pointer to start of page to be displayed */ + + if (_vscroll && *_vscroll) { + begin_reached = 0; + + for (i = 0; i < *_vscroll; i++) + get_line(); + } + if (_hscroll) + hscroll = *_hscroll; + +do_resize: + getmaxyx(stdscr, height, width); + if (height < TEXTBOX_HEIGTH_MIN || width < TEXTBOX_WIDTH_MIN) + return -ERRDISPLAYTOOSMALL; + if (initial_height != 0) + height = initial_height; + else + if (height > 4) + height -= 4; + else + height = 0; + if (initial_width != 0) + width = initial_width; + else + if (width > 5) + width -= 5; + else + width = 0; + + /* center dialog box on screen */ + x = (getmaxx(stdscr) - width) / 2; + y = (getmaxy(stdscr) - height) / 2; + + draw_shadow(stdscr, y, x, height, width); + + dialog = newwin(height, width, y, x); + keypad(dialog, TRUE); + + /* Create window for box region, used for scrolling text */ + boxh = height - 4; + boxw = width - 2; + box = subwin(dialog, boxh, boxw, y + 1, x + 1); + wattrset(box, dlg.dialog.atr); + wbkgdset(box, dlg.dialog.atr & A_COLOR); + + keypad(box, TRUE); + + /* register the new window, along with its borders */ + draw_box(dialog, 0, 0, height, width, + dlg.dialog.atr, dlg.border.atr); + + wattrset(dialog, dlg.border.atr); + mvwaddch(dialog, height - 3, 0, ACS_LTEE); + for (i = 0; i < width - 2; i++) + waddch(dialog, ACS_HLINE); + wattrset(dialog, dlg.dialog.atr); + wbkgdset(dialog, dlg.dialog.atr & A_COLOR); + waddch(dialog, ACS_RTEE); + + print_title(dialog, title, width); + + print_button(dialog, gettext(" Exit "), height - 2, width / 2 - 4, TRUE); + wnoutrefresh(dialog); + getyx(dialog, cur_y, cur_x); /* Save cursor position */ + + /* Print first page of text */ + attr_clear(box, boxh, boxw, dlg.dialog.atr); + refresh_text_box(dialog, box, boxh, boxw, cur_y, cur_x, update_text, + data); + + while (!done) { + key = wgetch(dialog); + switch (key) { + case 'E': /* Exit */ + case 'e': + case 'X': + case 'x': + case 'q': + case '\n': + done = true; + break; + case 'g': /* First page */ + case KEY_HOME: + if (!begin_reached) { + begin_reached = 1; + page = buf; + refresh_text_box(dialog, box, boxh, boxw, + cur_y, cur_x, update_text, + data); + } + break; + case 'G': /* Last page */ + case KEY_END: + + end_reached = 1; + /* point to last char in buf */ + page = buf + strlen(buf); + back_lines(boxh); + refresh_text_box(dialog, box, boxh, boxw, cur_y, + cur_x, update_text, data); + break; + case 'K': /* Previous line */ + case 'k': + case KEY_UP: + if (begin_reached) + break; + + back_lines(page_length + 1); + refresh_text_box(dialog, box, boxh, boxw, cur_y, + cur_x, update_text, data); + break; + case 'B': /* Previous page */ + case 'b': + case 'u': + case KEY_PPAGE: + if (begin_reached) + break; + back_lines(page_length + boxh); + refresh_text_box(dialog, box, boxh, boxw, cur_y, + cur_x, update_text, data); + break; + case 'J': /* Next line */ + case 'j': + case KEY_DOWN: + if (end_reached) + break; + + back_lines(page_length - 1); + refresh_text_box(dialog, box, boxh, boxw, cur_y, + cur_x, update_text, data); + break; + case KEY_NPAGE: /* Next page */ + case ' ': + case 'd': + if (end_reached) + break; + + begin_reached = 0; + refresh_text_box(dialog, box, boxh, boxw, cur_y, + cur_x, update_text, data); + break; + case '0': /* Beginning of line */ + case 'H': /* Scroll left */ + case 'h': + case KEY_LEFT: + if (hscroll <= 0) + break; + + if (key == '0') + hscroll = 0; + else + hscroll--; + /* Reprint current page to scroll horizontally */ + back_lines(page_length); + refresh_text_box(dialog, box, boxh, boxw, cur_y, + cur_x, update_text, data); + break; + case 'L': /* Scroll right */ + case 'l': + case KEY_RIGHT: + if (hscroll >= MAX_LEN) + break; + hscroll++; + /* Reprint current page to scroll horizontally */ + back_lines(page_length); + refresh_text_box(dialog, box, boxh, boxw, cur_y, + cur_x, update_text, data); + break; + case KEY_ESC: + if (on_key_esc(dialog) == KEY_ESC) + done = true; + break; + case KEY_RESIZE: + back_lines(height); + delwin(box); + delwin(dialog); + on_key_resize(); + goto do_resize; + default: + for (i = 0; keys[i]; i++) { + if (key == keys[i]) { + done = true; + break; + } + } + } + } + delwin(box); + delwin(dialog); + if (_vscroll) { + const char *s; + + s = buf; + *_vscroll = 0; + back_lines(page_length); + while (s < page && (s = strchr(s, '\n'))) { + (*_vscroll)++; + s++; + } + } + if (_hscroll) + *_hscroll = hscroll; + return key; +} + +/* + * Go back 'n' lines in text. Called by dialog_textbox(). + * 'page' will be updated to point to the desired line in 'buf'. + */ +static void back_lines(int n) +{ + int i; + + begin_reached = 0; + /* Go back 'n' lines */ + for (i = 0; i < n; i++) { + if (*page == '\0') { + if (end_reached) { + end_reached = 0; + continue; + } + } + if (page == buf) { + begin_reached = 1; + return; + } + page--; + do { + if (page == buf) { + begin_reached = 1; + return; + } + page--; + } while (*page != '\n'); + page++; + } +} + +/* + * Print a new page of text. + */ +static void print_page(WINDOW *win, int height, int width, update_text_fn + update_text, void *data) +{ + int i, passed_end = 0; + + if (update_text) { + char *end; + + for (i = 0; i < height; i++) + get_line(); + end = page; + back_lines(height); + update_text(buf, page - buf, end - buf, data); + } + + page_length = 0; + for (i = 0; i < height; i++) { + print_line(win, i, width); + if (!passed_end) + page_length++; + if (end_reached && !passed_end) + passed_end = 1; + } + wnoutrefresh(win); +} + +/* + * Print a new line of text. + */ +static void print_line(WINDOW * win, int row, int width) +{ + char *line; + + line = get_line(); + line += MIN(strlen(line), hscroll); /* Scroll horizontally */ + wmove(win, row, 0); /* move cursor to correct line */ + waddch(win, ' '); + waddnstr(win, line, MIN(strlen(line), width - 2)); + + /* Clear 'residue' of previous line */ +#if OLD_NCURSES + { + int x = getcurx(win); + int i; + for (i = 0; i < width - x; i++) + waddch(win, ' '); + } +#else + wclrtoeol(win); +#endif +} + +/* + * Return current line of text. Called by dialog_textbox() and print_line(). + * 'page' should point to start of current line before calling, and will be + * updated to point to start of next line. + */ +static char *get_line(void) +{ + int i = 0; + static char line[MAX_LEN + 1]; + + end_reached = 0; + while (*page != '\n') { + if (*page == '\0') { + end_reached = 1; + break; + } else if (i < MAX_LEN) + line[i++] = *(page++); + else { + /* Truncate lines longer than MAX_LEN characters */ + if (i == MAX_LEN) + line[i++] = '\0'; + page++; + } + } + if (i <= MAX_LEN) + line[i] = '\0'; + if (!end_reached) + page++; /* move past '\n' */ + + return line; +} + +/* + * Print current position + */ +static void print_position(WINDOW * win) +{ + int percent; + + wattrset(win, dlg.position_indicator.atr); + wbkgdset(win, dlg.position_indicator.atr & A_COLOR); + percent = (page - buf) * 100 / strlen(buf); + wmove(win, getmaxy(win) - 3, getmaxx(win) - 9); + wprintw(win, "(%3d%%)", percent); +} diff --git a/tools/kconfig/lxdialog/util.c b/tools/kconfig/lxdialog/util.c new file mode 100644 index 0000000000..f7abdeb92a --- /dev/null +++ b/tools/kconfig/lxdialog/util.c @@ -0,0 +1,713 @@ +/* + * util.c + * + * ORIGINAL AUTHOR: Savio Lam (lam836@cs.cuhk.hk) + * MODIFIED FOR LINUX KERNEL CONFIG BY: William Roadcap (roadcap@cfw.com) + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include + +#include "dialog.h" + +/* Needed in signal handler in mconf.c */ +int saved_x, saved_y; + +struct dialog_info dlg; + +static void set_mono_theme(void) +{ + dlg.screen.atr = A_NORMAL; + dlg.shadow.atr = A_NORMAL; + dlg.dialog.atr = A_NORMAL; + dlg.title.atr = A_BOLD; + dlg.border.atr = A_NORMAL; + dlg.button_active.atr = A_REVERSE; + dlg.button_inactive.atr = A_DIM; + dlg.button_key_active.atr = A_REVERSE; + dlg.button_key_inactive.atr = A_BOLD; + dlg.button_label_active.atr = A_REVERSE; + dlg.button_label_inactive.atr = A_NORMAL; + dlg.inputbox.atr = A_NORMAL; + dlg.inputbox_border.atr = A_NORMAL; + dlg.searchbox.atr = A_NORMAL; + dlg.searchbox_title.atr = A_BOLD; + dlg.searchbox_border.atr = A_NORMAL; + dlg.position_indicator.atr = A_BOLD; + dlg.menubox.atr = A_NORMAL; + dlg.menubox_border.atr = A_NORMAL; + dlg.item.atr = A_NORMAL; + dlg.item_selected.atr = A_REVERSE; + dlg.tag.atr = A_BOLD; + dlg.tag_selected.atr = A_REVERSE; + dlg.tag_key.atr = A_BOLD; + dlg.tag_key_selected.atr = A_REVERSE; + dlg.check.atr = A_BOLD; + dlg.check_selected.atr = A_REVERSE; + dlg.uarrow.atr = A_BOLD; + dlg.darrow.atr = A_BOLD; +} + +#define DLG_COLOR(dialog, f, b, h) \ +do { \ + dlg.dialog.fg = (f); \ + dlg.dialog.bg = (b); \ + dlg.dialog.hl = (h); \ +} while (0) + +static void set_classic_theme(void) +{ + DLG_COLOR(screen, COLOR_CYAN, COLOR_BLUE, true); + DLG_COLOR(shadow, COLOR_BLACK, COLOR_BLACK, true); + DLG_COLOR(dialog, COLOR_BLACK, COLOR_WHITE, false); + DLG_COLOR(title, COLOR_YELLOW, COLOR_WHITE, true); + DLG_COLOR(border, COLOR_WHITE, COLOR_WHITE, true); + DLG_COLOR(button_active, COLOR_WHITE, COLOR_BLUE, true); + DLG_COLOR(button_inactive, COLOR_BLACK, COLOR_WHITE, false); + DLG_COLOR(button_key_active, COLOR_WHITE, COLOR_BLUE, true); + DLG_COLOR(button_key_inactive, COLOR_RED, COLOR_WHITE, false); + DLG_COLOR(button_label_active, COLOR_YELLOW, COLOR_BLUE, true); + DLG_COLOR(button_label_inactive, COLOR_BLACK, COLOR_WHITE, true); + DLG_COLOR(inputbox, COLOR_BLACK, COLOR_WHITE, false); + DLG_COLOR(inputbox_border, COLOR_BLACK, COLOR_WHITE, false); + DLG_COLOR(searchbox, COLOR_BLACK, COLOR_WHITE, false); + DLG_COLOR(searchbox_title, COLOR_YELLOW, COLOR_WHITE, true); + DLG_COLOR(searchbox_border, COLOR_WHITE, COLOR_WHITE, true); + DLG_COLOR(position_indicator, COLOR_YELLOW, COLOR_WHITE, true); + DLG_COLOR(menubox, COLOR_BLACK, COLOR_WHITE, false); + DLG_COLOR(menubox_border, COLOR_WHITE, COLOR_WHITE, true); + DLG_COLOR(item, COLOR_BLACK, COLOR_WHITE, false); + DLG_COLOR(item_selected, COLOR_WHITE, COLOR_BLUE, true); + DLG_COLOR(tag, COLOR_YELLOW, COLOR_WHITE, true); + DLG_COLOR(tag_selected, COLOR_YELLOW, COLOR_BLUE, true); + DLG_COLOR(tag_key, COLOR_YELLOW, COLOR_WHITE, true); + DLG_COLOR(tag_key_selected, COLOR_YELLOW, COLOR_BLUE, true); + DLG_COLOR(check, COLOR_BLACK, COLOR_WHITE, false); + DLG_COLOR(check_selected, COLOR_WHITE, COLOR_BLUE, true); + DLG_COLOR(uarrow, COLOR_GREEN, COLOR_WHITE, true); + DLG_COLOR(darrow, COLOR_GREEN, COLOR_WHITE, true); +} + +static void set_blackbg_theme(void) +{ + DLG_COLOR(screen, COLOR_RED, COLOR_BLACK, true); + DLG_COLOR(shadow, COLOR_BLACK, COLOR_BLACK, false); + DLG_COLOR(dialog, COLOR_WHITE, COLOR_BLACK, false); + DLG_COLOR(title, COLOR_RED, COLOR_BLACK, false); + DLG_COLOR(border, COLOR_BLACK, COLOR_BLACK, true); + + DLG_COLOR(button_active, COLOR_YELLOW, COLOR_RED, false); + DLG_COLOR(button_inactive, COLOR_YELLOW, COLOR_BLACK, false); + DLG_COLOR(button_key_active, COLOR_YELLOW, COLOR_RED, true); + DLG_COLOR(button_key_inactive, COLOR_RED, COLOR_BLACK, false); + DLG_COLOR(button_label_active, COLOR_WHITE, COLOR_RED, false); + DLG_COLOR(button_label_inactive, COLOR_BLACK, COLOR_BLACK, true); + + DLG_COLOR(inputbox, COLOR_YELLOW, COLOR_BLACK, false); + DLG_COLOR(inputbox_border, COLOR_YELLOW, COLOR_BLACK, false); + + DLG_COLOR(searchbox, COLOR_YELLOW, COLOR_BLACK, false); + DLG_COLOR(searchbox_title, COLOR_YELLOW, COLOR_BLACK, true); + DLG_COLOR(searchbox_border, COLOR_BLACK, COLOR_BLACK, true); + + DLG_COLOR(position_indicator, COLOR_RED, COLOR_BLACK, false); + + DLG_COLOR(menubox, COLOR_YELLOW, COLOR_BLACK, false); + DLG_COLOR(menubox_border, COLOR_BLACK, COLOR_BLACK, true); + + DLG_COLOR(item, COLOR_WHITE, COLOR_BLACK, false); + DLG_COLOR(item_selected, COLOR_WHITE, COLOR_RED, false); + + DLG_COLOR(tag, COLOR_RED, COLOR_BLACK, false); + DLG_COLOR(tag_selected, COLOR_YELLOW, COLOR_RED, true); + DLG_COLOR(tag_key, COLOR_RED, COLOR_BLACK, false); + DLG_COLOR(tag_key_selected, COLOR_YELLOW, COLOR_RED, true); + + DLG_COLOR(check, COLOR_YELLOW, COLOR_BLACK, false); + DLG_COLOR(check_selected, COLOR_YELLOW, COLOR_RED, true); + + DLG_COLOR(uarrow, COLOR_RED, COLOR_BLACK, false); + DLG_COLOR(darrow, COLOR_RED, COLOR_BLACK, false); +} + +static void set_bluetitle_theme(void) +{ + set_classic_theme(); + DLG_COLOR(title, COLOR_BLUE, COLOR_WHITE, true); + DLG_COLOR(button_key_active, COLOR_YELLOW, COLOR_BLUE, true); + DLG_COLOR(button_label_active, COLOR_WHITE, COLOR_BLUE, true); + DLG_COLOR(searchbox_title, COLOR_BLUE, COLOR_WHITE, true); + DLG_COLOR(position_indicator, COLOR_BLUE, COLOR_WHITE, true); + DLG_COLOR(tag, COLOR_BLUE, COLOR_WHITE, true); + DLG_COLOR(tag_key, COLOR_BLUE, COLOR_WHITE, true); + +} + +/* + * Select color theme + */ +static int set_theme(const char *theme) +{ + int use_color = 1; + if (!theme) + set_bluetitle_theme(); + else if (strcmp(theme, "classic") == 0) + set_classic_theme(); + else if (strcmp(theme, "bluetitle") == 0) + set_bluetitle_theme(); + else if (strcmp(theme, "blackbg") == 0) + set_blackbg_theme(); + else if (strcmp(theme, "mono") == 0) + use_color = 0; + + return use_color; +} + +static void init_one_color(struct dialog_color *color) +{ + static int pair = 0; + + pair++; + init_pair(pair, color->fg, color->bg); + if (color->hl) + color->atr = A_BOLD | COLOR_PAIR(pair); + else + color->atr = COLOR_PAIR(pair); +} + +static void init_dialog_colors(void) +{ + init_one_color(&dlg.screen); + init_one_color(&dlg.shadow); + init_one_color(&dlg.dialog); + init_one_color(&dlg.title); + init_one_color(&dlg.border); + init_one_color(&dlg.button_active); + init_one_color(&dlg.button_inactive); + init_one_color(&dlg.button_key_active); + init_one_color(&dlg.button_key_inactive); + init_one_color(&dlg.button_label_active); + init_one_color(&dlg.button_label_inactive); + init_one_color(&dlg.inputbox); + init_one_color(&dlg.inputbox_border); + init_one_color(&dlg.searchbox); + init_one_color(&dlg.searchbox_title); + init_one_color(&dlg.searchbox_border); + init_one_color(&dlg.position_indicator); + init_one_color(&dlg.menubox); + init_one_color(&dlg.menubox_border); + init_one_color(&dlg.item); + init_one_color(&dlg.item_selected); + init_one_color(&dlg.tag); + init_one_color(&dlg.tag_selected); + init_one_color(&dlg.tag_key); + init_one_color(&dlg.tag_key_selected); + init_one_color(&dlg.check); + init_one_color(&dlg.check_selected); + init_one_color(&dlg.uarrow); + init_one_color(&dlg.darrow); +} + +/* + * Setup for color display + */ +static void color_setup(const char *theme) +{ + int use_color; + + use_color = set_theme(theme); + if (use_color && has_colors()) { + start_color(); + init_dialog_colors(); + } else + set_mono_theme(); +} + +/* + * Set window to attribute 'attr' + */ +void attr_clear(WINDOW * win, int height, int width, chtype attr) +{ + int i, j; + + wattrset(win, attr); + for (i = 0; i < height; i++) { + wmove(win, i, 0); + for (j = 0; j < width; j++) + waddch(win, ' '); + } + touchwin(win); +} + +void dialog_clear(void) +{ + int lines, columns; + + lines = getmaxy(stdscr); + columns = getmaxx(stdscr); + + attr_clear(stdscr, lines, columns, dlg.screen.atr); + /* Display background title if it exists ... - SLH */ + if (dlg.backtitle != NULL) { + int i, len = 0, skip = 0; + struct subtitle_list *pos; + + wattrset(stdscr, dlg.screen.atr); + mvwaddstr(stdscr, 0, 1, (char *)dlg.backtitle); + + for (pos = dlg.subtitles; pos != NULL; pos = pos->next) { + /* 3 is for the arrow and spaces */ + len += strlen(pos->text) + 3; + } + + wmove(stdscr, 1, 1); + if (len > columns - 2) { + const char *ellipsis = "[...] "; + waddstr(stdscr, ellipsis); + skip = len - (columns - 2 - strlen(ellipsis)); + } + + for (pos = dlg.subtitles; pos != NULL; pos = pos->next) { + if (skip == 0) + waddch(stdscr, ACS_RARROW); + else + skip--; + + if (skip == 0) + waddch(stdscr, ' '); + else + skip--; + + if (skip < strlen(pos->text)) { + waddstr(stdscr, pos->text + skip); + skip = 0; + } else + skip -= strlen(pos->text); + + if (skip == 0) + waddch(stdscr, ' '); + else + skip--; + } + + for (i = len + 1; i < columns - 1; i++) + waddch(stdscr, ACS_HLINE); + } + wnoutrefresh(stdscr); +} + +/* + * Do some initialization for dialog + */ +int init_dialog(const char *backtitle) +{ + int height, width; + + initscr(); /* Init curses */ + + /* Get current cursor position for signal handler in mconf.c */ + getyx(stdscr, saved_y, saved_x); + + getmaxyx(stdscr, height, width); + if (height < WINDOW_HEIGTH_MIN || width < WINDOW_WIDTH_MIN) { + endwin(); + return -ERRDISPLAYTOOSMALL; + } + + dlg.backtitle = backtitle; + color_setup(getenv("MENUCONFIG_COLOR")); + + keypad(stdscr, TRUE); + cbreak(); + noecho(); + dialog_clear(); + + return 0; +} + +void set_dialog_backtitle(const char *backtitle) +{ + dlg.backtitle = backtitle; +} + +void set_dialog_subtitles(struct subtitle_list *subtitles) +{ + dlg.subtitles = subtitles; +} + +/* + * End using dialog functions. + */ +void end_dialog(int x, int y) +{ + /* move cursor back to original position */ + move(y, x); + refresh(); + endwin(); +} + +/* Print the title of the dialog. Center the title and truncate + * tile if wider than dialog (- 2 chars). + **/ +void print_title(WINDOW *dialog, const char *title, int width) +{ + if (title) { + int tlen = MIN(width - 2, strlen(title)); + wattrset(dialog, dlg.title.atr); + mvwaddch(dialog, 0, (width - tlen) / 2 - 1, ' '); + mvwaddnstr(dialog, 0, (width - tlen)/2, title, tlen); + waddch(dialog, ' '); + } +} + +/* + * Print a string of text in a window, automatically wrap around to the + * next line if the string is too long to fit on one line. Newline + * characters '\n' are propperly processed. We start on a new line + * if there is no room for at least 4 nonblanks following a double-space. + */ +void print_autowrap(WINDOW * win, const char *prompt, int width, int y, int x) +{ + int newl, cur_x, cur_y; + int prompt_len, room, wlen; + char tempstr[MAX_LEN + 1], *word, *sp, *sp2, *newline_separator = 0; + + strcpy(tempstr, prompt); + + prompt_len = strlen(tempstr); + + if (prompt_len <= width - x * 2) { /* If prompt is short */ + wmove(win, y, (width - prompt_len) / 2); + waddstr(win, tempstr); + } else { + cur_x = x; + cur_y = y; + newl = 1; + word = tempstr; + while (word && *word) { + sp = strpbrk(word, "\n "); + if (sp && *sp == '\n') + newline_separator = sp; + + if (sp) + *sp++ = 0; + + /* Wrap to next line if either the word does not fit, + or it is the first word of a new sentence, and it is + short, and the next word does not fit. */ + room = width - cur_x; + wlen = strlen(word); + if (wlen > room || + (newl && wlen < 4 && sp + && wlen + 1 + strlen(sp) > room + && (!(sp2 = strpbrk(sp, "\n ")) + || wlen + 1 + (sp2 - sp) > room))) { + cur_y++; + cur_x = x; + } + wmove(win, cur_y, cur_x); + waddstr(win, word); + getyx(win, cur_y, cur_x); + + /* Move to the next line if the word separator was a newline */ + if (newline_separator) { + cur_y++; + cur_x = x; + newline_separator = 0; + } else + cur_x++; + + if (sp && *sp == ' ') { + cur_x++; /* double space */ + while (*++sp == ' ') ; + newl = 1; + } else + newl = 0; + word = sp; + } + } +} + +/* + * Print a button + */ +void print_button(WINDOW * win, const char *label, int y, int x, int selected) +{ + int i, temp; + + wmove(win, y, x); + wattrset(win, selected ? dlg.button_active.atr + : dlg.button_inactive.atr); + waddstr(win, "<"); + temp = strspn(label, " "); + label += temp; + wattrset(win, selected ? dlg.button_label_active.atr + : dlg.button_label_inactive.atr); + for (i = 0; i < temp; i++) + waddch(win, ' '); + wattrset(win, selected ? dlg.button_key_active.atr + : dlg.button_key_inactive.atr); + waddch(win, label[0]); + wattrset(win, selected ? dlg.button_label_active.atr + : dlg.button_label_inactive.atr); + waddstr(win, (char *)label + 1); + wattrset(win, selected ? dlg.button_active.atr + : dlg.button_inactive.atr); + waddstr(win, ">"); + wmove(win, y, x + temp + 1); +} + +/* + * Draw a rectangular box with line drawing characters + */ +void +draw_box(WINDOW * win, int y, int x, int height, int width, + chtype box, chtype border) +{ + int i, j; + + wattrset(win, 0); + for (i = 0; i < height; i++) { + wmove(win, y + i, x); + for (j = 0; j < width; j++) + if (!i && !j) + waddch(win, border | ACS_ULCORNER); + else if (i == height - 1 && !j) + waddch(win, border | ACS_LLCORNER); + else if (!i && j == width - 1) + waddch(win, box | ACS_URCORNER); + else if (i == height - 1 && j == width - 1) + waddch(win, box | ACS_LRCORNER); + else if (!i) + waddch(win, border | ACS_HLINE); + else if (i == height - 1) + waddch(win, box | ACS_HLINE); + else if (!j) + waddch(win, border | ACS_VLINE); + else if (j == width - 1) + waddch(win, box | ACS_VLINE); + else + waddch(win, box | ' '); + } +} + +/* + * Draw shadows along the right and bottom edge to give a more 3D look + * to the boxes + */ +void draw_shadow(WINDOW * win, int y, int x, int height, int width) +{ + int i; + + if (has_colors()) { /* Whether terminal supports color? */ + wattrset(win, dlg.shadow.atr); + wmove(win, y + height, x + 2); + for (i = 0; i < width; i++) + waddch(win, winch(win) & A_CHARTEXT); + for (i = y + 1; i < y + height + 1; i++) { + wmove(win, i, x + width); + waddch(win, winch(win) & A_CHARTEXT); + waddch(win, winch(win) & A_CHARTEXT); + } + wnoutrefresh(win); + } +} + +/* + * Return the position of the first alphabetic character in a string. + */ +int first_alpha(const char *string, const char *exempt) +{ + int i, in_paren = 0, c; + + for (i = 0; i < strlen(string); i++) { + c = tolower(string[i]); + + if (strchr("<[(", c)) + ++in_paren; + if (strchr(">])", c) && in_paren > 0) + --in_paren; + + if ((!in_paren) && isalpha(c) && strchr(exempt, c) == 0) + return i; + } + + return 0; +} + +/* + * ncurses uses ESC to detect escaped char sequences. This resutl in + * a small timeout before ESC is actually delivered to the application. + * lxdialog suggest which is correctly translated to two + * times esc. But then we need to ignore the second esc to avoid stepping + * out one menu too much. Filter away all escaped key sequences since + * keypad(FALSE) turn off ncurses support for escape sequences - and thats + * needed to make notimeout() do as expected. + */ +int on_key_esc(WINDOW *win) +{ + int key; + int key2; + int key3; + + nodelay(win, TRUE); + keypad(win, FALSE); + key = wgetch(win); + key2 = wgetch(win); + do { + key3 = wgetch(win); + } while (key3 != ERR); + nodelay(win, FALSE); + keypad(win, TRUE); + if (key == KEY_ESC && key2 == ERR) + return KEY_ESC; + else if (key != ERR && key != KEY_ESC && key2 == ERR) + ungetch(key); + + return -1; +} + +/* redraw screen in new size */ +int on_key_resize(void) +{ + dialog_clear(); + return KEY_RESIZE; +} + +struct dialog_list *item_cur; +struct dialog_list item_nil; +struct dialog_list *item_head; + +void item_reset(void) +{ + struct dialog_list *p, *next; + + for (p = item_head; p; p = next) { + next = p->next; + free(p); + } + item_head = NULL; + item_cur = &item_nil; +} + +void item_make(const char *fmt, ...) +{ + va_list ap; + struct dialog_list *p = malloc(sizeof(*p)); + + if (item_head) + item_cur->next = p; + else + item_head = p; + item_cur = p; + memset(p, 0, sizeof(*p)); + + va_start(ap, fmt); + vsnprintf(item_cur->node.str, sizeof(item_cur->node.str), fmt, ap); + va_end(ap); +} + +void item_add_str(const char *fmt, ...) +{ + va_list ap; + size_t avail; + + avail = sizeof(item_cur->node.str) - strlen(item_cur->node.str); + + va_start(ap, fmt); + vsnprintf(item_cur->node.str + strlen(item_cur->node.str), + avail, fmt, ap); + item_cur->node.str[sizeof(item_cur->node.str) - 1] = '\0'; + va_end(ap); +} + +void item_set_tag(char tag) +{ + item_cur->node.tag = tag; +} +void item_set_data(void *ptr) +{ + item_cur->node.data = ptr; +} + +void item_set_selected(int val) +{ + item_cur->node.selected = val; +} + +int item_activate_selected(void) +{ + item_foreach() + if (item_is_selected()) + return 1; + return 0; +} + +void *item_data(void) +{ + return item_cur->node.data; +} + +char item_tag(void) +{ + return item_cur->node.tag; +} + +int item_count(void) +{ + int n = 0; + struct dialog_list *p; + + for (p = item_head; p; p = p->next) + n++; + return n; +} + +void item_set(int n) +{ + int i = 0; + item_foreach() + if (i++ == n) + return; +} + +int item_n(void) +{ + int n = 0; + struct dialog_list *p; + + for (p = item_head; p; p = p->next) { + if (p == item_cur) + return n; + n++; + } + return 0; +} + +const char *item_str(void) +{ + return item_cur->node.str; +} + +int item_is_selected(void) +{ + return (item_cur->node.selected != 0); +} + +int item_is_tag(char tag) +{ + return (item_cur->node.tag == tag); +} diff --git a/tools/kconfig/lxdialog/yesno.c b/tools/kconfig/lxdialog/yesno.c new file mode 100644 index 0000000000..676fb2f824 --- /dev/null +++ b/tools/kconfig/lxdialog/yesno.c @@ -0,0 +1,114 @@ +/* + * yesno.c -- implements the yes/no box + * + * ORIGINAL AUTHOR: Savio Lam (lam836@cs.cuhk.hk) + * MODIFIED FOR LINUX KERNEL CONFIG BY: William Roadcap (roadcap@cfw.com) + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include "dialog.h" + +/* + * Display termination buttons + */ +static void print_buttons(WINDOW * dialog, int height, int width, int selected) +{ + int x = width / 2 - 10; + int y = height - 2; + + print_button(dialog, gettext(" Yes "), y, x, selected == 0); + print_button(dialog, gettext(" No "), y, x + 13, selected == 1); + + wmove(dialog, y, x + 1 + 13 * selected); + wrefresh(dialog); +} + +/* + * Display a dialog box with two buttons - Yes and No + */ +int dialog_yesno(const char *title, const char *prompt, int height, int width) +{ + int i, x, y, key = 0, button = 0; + WINDOW *dialog; + +do_resize: + if (getmaxy(stdscr) < (height + YESNO_HEIGTH_MIN)) + return -ERRDISPLAYTOOSMALL; + if (getmaxx(stdscr) < (width + YESNO_WIDTH_MIN)) + return -ERRDISPLAYTOOSMALL; + + /* center dialog box on screen */ + x = (getmaxx(stdscr) - width) / 2; + y = (getmaxy(stdscr) - height) / 2; + + draw_shadow(stdscr, y, x, height, width); + + dialog = newwin(height, width, y, x); + keypad(dialog, TRUE); + + draw_box(dialog, 0, 0, height, width, + dlg.dialog.atr, dlg.border.atr); + wattrset(dialog, dlg.border.atr); + mvwaddch(dialog, height - 3, 0, ACS_LTEE); + for (i = 0; i < width - 2; i++) + waddch(dialog, ACS_HLINE); + wattrset(dialog, dlg.dialog.atr); + waddch(dialog, ACS_RTEE); + + print_title(dialog, title, width); + + wattrset(dialog, dlg.dialog.atr); + print_autowrap(dialog, prompt, width - 2, 1, 3); + + print_buttons(dialog, height, width, 0); + + while (key != KEY_ESC) { + key = wgetch(dialog); + switch (key) { + case 'Y': + case 'y': + delwin(dialog); + return 0; + case 'N': + case 'n': + delwin(dialog); + return 1; + + case TAB: + case KEY_LEFT: + case KEY_RIGHT: + button = ((key == KEY_LEFT ? --button : ++button) < 0) ? 1 : (button > 1 ? 0 : button); + + print_buttons(dialog, height, width, button); + wrefresh(dialog); + break; + case ' ': + case '\n': + delwin(dialog); + return button; + case KEY_ESC: + key = on_key_esc(dialog); + break; + case KEY_RESIZE: + delwin(dialog); + on_key_resize(); + goto do_resize; + } + } + + delwin(dialog); + return key; /* ESC pressed */ +} diff --git a/tools/kconfig/mconf.c b/tools/kconfig/mconf.c new file mode 100644 index 0000000000..315ce2c7cb --- /dev/null +++ b/tools/kconfig/mconf.c @@ -0,0 +1,1047 @@ +/* + * Copyright (C) 2002 Roman Zippel + * Released under the terms of the GNU GPL v2.0. + * + * Introduced single menu mode (show all sub-menus in one large tree). + * 2002-11-06 Petr Baudis + * + * i18n, 2005, Arnaldo Carvalho de Melo + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "lkc.h" +#include "lxdialog/dialog.h" + +static const char mconf_readme[] = N_( +"Overview\n" +"--------\n" +"This interface lets you select features and parameters for the build.\n" +"Features can either be built-in, modularized, or ignored. Parameters\n" +"must be entered in as decimal or hexadecimal numbers or text.\n" +"\n" +"Menu items beginning with following braces represent features that\n" +" [ ] can be built in or removed\n" +" < > can be built in, modularized or removed\n" +" { } can be built in or modularized (selected by other feature)\n" +" - - are selected by other feature,\n" +"while *, M or whitespace inside braces means to build in, build as\n" +"a module or to exclude the feature respectively.\n" +"\n" +"To change any of these features, highlight it with the cursor\n" +"keys and press to build it in, to make it a module or\n" +" to remove it. You may also press the to cycle\n" +"through the available options (i.e. Y->N->M->Y).\n" +"\n" +"Some additional keyboard hints:\n" +"\n" +"Menus\n" +"----------\n" +"o Use the Up/Down arrow keys (cursor keys) to highlight the item you\n" +" wish to change or the submenu you wish to select and press .\n" +" Submenus are designated by \"--->\", empty ones by \"----\".\n" +"\n" +" Shortcut: Press the option's highlighted letter (hotkey).\n" +" Pressing a hotkey more than once will sequence\n" +" through all visible items which use that hotkey.\n" +"\n" +" You may also use the and keys to scroll\n" +" unseen options into view.\n" +"\n" +"o To exit a menu use the cursor keys to highlight the button\n" +" and press .\n" +"\n" +" Shortcut: Press or or if there is no hotkey\n" +" using those letters. You may press a single , but\n" +" there is a delayed response which you may find annoying.\n" +"\n" +" Also, the and cursor keys will cycle between and\n" +" \n" +"\n" +"\n" +"Data Entry\n" +"-----------\n" +"o Enter the requested information and press \n" +" If you are entering hexadecimal values, it is not necessary to\n" +" add the '0x' prefix to the entry.\n" +"\n" +"o For help, use the or cursor keys to highlight the help option\n" +" and press . You can try as well.\n" +"\n" +"\n" +"Text Box (Help Window)\n" +"--------\n" +"o Use the cursor keys to scroll up/down/left/right. The VI editor\n" +" keys h,j,k,l function here as do , , and for\n" +" those who are familiar with less and lynx.\n" +"\n" +"o Press , , , or to exit.\n" +"\n" +"\n" +"Alternate Configuration Files\n" +"-----------------------------\n" +"Menuconfig supports the use of alternate configuration files for\n" +"those who, for various reasons, find it necessary to switch\n" +"between different configurations.\n" +"\n" +"The button will let you save the current configuration to\n" +"a file of your choosing. Use the button to load a previously\n" +"saved alternate configuration.\n" +"\n" +"Even if you don't use alternate configuration files, but you find\n" +"during a Menuconfig session that you have completely messed up your\n" +"settings, you may use the button to restore your previously\n" +"saved settings from \".config\" without restarting Menuconfig.\n" +"\n" +"Other information\n" +"-----------------\n" +"If you use Menuconfig in an XTERM window, make sure you have your\n" +"$TERM variable set to point to an xterm definition which supports\n" +"color. Otherwise, Menuconfig will look rather bad. Menuconfig will\n" +"not display correctly in an RXVT window because rxvt displays only one\n" +"intensity of color, bright.\n" +"\n" +"Menuconfig will display larger menus on screens or xterms which are\n" +"set to display more than the standard 25 row by 80 column geometry.\n" +"In order for this to work, the \"stty size\" command must be able to\n" +"display the screen's current row and column geometry. I STRONGLY\n" +"RECOMMEND that you make sure you do NOT have the shell variables\n" +"LINES and COLUMNS exported into your environment. Some distributions\n" +"export those variables via /etc/profile. Some ncurses programs can\n" +"become confused when those variables (LINES & COLUMNS) don't reflect\n" +"the true screen size.\n" +"\n" +"Optional personality available\n" +"------------------------------\n" +"If you prefer to have all of the options listed in a single menu,\n" +"rather than the default multimenu hierarchy, run the menuconfig with\n" +"MENUCONFIG_MODE environment variable set to single_menu. Example:\n" +"\n" +"make MENUCONFIG_MODE=single_menu menuconfig\n" +"\n" +" will then unroll the appropriate category, or enfold it if it\n" +"is already unrolled.\n" +"\n" +"Note that this mode can eventually be a little more CPU expensive\n" +"(especially with a larger number of unrolled categories) than the\n" +"default mode.\n" +"\n" +"Different color themes available\n" +"--------------------------------\n" +"It is possible to select different color themes using the variable\n" +"MENUCONFIG_COLOR. To select a theme use:\n" +"\n" +"make MENUCONFIG_COLOR= menuconfig\n" +"\n" +"Available themes are\n" +" mono => selects colors suitable for monochrome displays\n" +" blackbg => selects a color scheme with black background\n" +" classic => theme with blue background. The classic look\n" +" bluetitle => an LCD friendly version of classic. (default)\n" +"\n"), +menu_instructions[] = N_( + "Arrow keys navigate the menu. " + " selects submenus ---> (or empty submenus ----). " + "Highlighted letters are hotkeys. " + "Pressing includes, excludes, modularizes features. " + "Press to exit, for Help, for Search. " + "Legend: [*] built-in [ ] excluded module < > module capable"), +radiolist_instructions[] = N_( + "Use the arrow keys to navigate this window or " + "press the hotkey of the item you wish to select " + "followed by the . " + "Press for additional information about this option."), +inputbox_instructions_int[] = N_( + "Please enter a decimal value. " + "Fractions will not be accepted. " + "Use the key to move from the input field to the buttons below it."), +inputbox_instructions_hex[] = N_( + "Please enter a hexadecimal value. " + "Use the key to move from the input field to the buttons below it."), +inputbox_instructions_string[] = N_( + "Please enter a string value. " + "Use the key to move from the input field to the buttons below it."), +setmod_text[] = N_( + "This feature depends on another which has been configured as a module.\n" + "As a result, this feature will be built as a module."), +load_config_text[] = N_( + "Enter the name of the configuration file you wish to load. " + "Accept the name shown to restore the configuration you " + "last retrieved. Leave blank to abort."), +load_config_help[] = N_( + "\n" + "For various reasons, one may wish to keep several different\n" + "configurations available on a single machine.\n" + "\n" + "If you have saved a previous configuration in a file other than the\n" + "default one, entering its name here will allow you to modify that\n" + "configuration.\n" + "\n" + "If you are uncertain, then you have probably never used alternate\n" + "configuration files. You should therefore leave this blank to abort.\n"), +save_config_text[] = N_( + "Enter a filename to which this configuration should be saved " + "as an alternate. Leave blank to abort."), +save_config_help[] = N_( + "\n" + "For various reasons, one may wish to keep different configurations\n" + "available on a single machine.\n" + "\n" + "Entering a file name here will allow you to later retrieve, modify\n" + "and use the current configuration as an alternate to whatever\n" + "configuration options you have selected at that time.\n" + "\n" + "If you are uncertain what all this means then you should probably\n" + "leave this blank.\n"), +search_help[] = N_( + "\n" + "Search for symbols and display their relations.\n" + "Regular expressions are allowed.\n" + "Example: search for \"^FOO\"\n" + "Result:\n" + "-----------------------------------------------------------------\n" + "Symbol: FOO [=m]\n" + "Type : tristate\n" + "Prompt: Foo bus is used to drive the bar HW\n" + " Location:\n" + " -> Bus options (PCI, PCMCIA, EISA, ISA)\n" + " -> PCI support (PCI [=y])\n" + "(1) -> PCI access mode ( [=y])\n" + " Defined at drivers/pci/Kconfig:47\n" + " Depends on: X86_LOCAL_APIC && X86_IO_APIC || IA64\n" + " Selects: LIBCRC32\n" + " Selected by: BAR [=n]\n" + "-----------------------------------------------------------------\n" + "o The line 'Type:' shows the type of the configuration option for\n" + " this symbol (boolean, tristate, string, ...)\n" + "o The line 'Prompt:' shows the text used in the menu structure for\n" + " this symbol\n" + "o The 'Defined at' line tells at what file / line number the symbol\n" + " is defined\n" + "o The 'Depends on:' line tells what symbols need to be defined for\n" + " this symbol to be visible in the menu (selectable)\n" + "o The 'Location:' lines tells where in the menu structure this symbol\n" + " is located\n" + " A location followed by a [=y] indicates that this is a\n" + " selectable menu item - and the current value is displayed inside\n" + " brackets.\n" + " Press the key in the (#) prefix to jump directly to that\n" + " location. You will be returned to the current search results\n" + " after exiting this new menu.\n" + "o The 'Selects:' line tells what symbols will be automatically\n" + " selected if this symbol is selected (y or m)\n" + "o The 'Selected by' line tells what symbol has selected this symbol\n" + "\n" + "Only relevant lines are shown.\n" + "\n\n" + "Search examples:\n" + "Examples: USB => find all symbols containing USB\n" + " ^USB => find all symbols starting with USB\n" + " USB$ => find all symbols ending with USB\n" + "\n"); + +static int indent; +static struct menu *current_menu; +static int child_count; +static int single_menu_mode; +static int show_all_options; +static int save_and_exit; +static int silent; + +static void conf(struct menu *menu, struct menu *active_menu); +static void conf_choice(struct menu *menu); +static void conf_string(struct menu *menu); +static void conf_load(void); +static void conf_save(void); +static int show_textbox_ext(const char *title, char *text, int r, int c, + int *keys, int *vscroll, int *hscroll, + update_text_fn update_text, void *data); +static void show_textbox(const char *title, const char *text, int r, int c); +static void show_helptext(const char *title, const char *text); +static void show_help(struct menu *menu); + +static char filename[PATH_MAX+1]; +static void set_config_filename(const char *config_filename) +{ + static char menu_backtitle[PATH_MAX+128]; + int size; + + size = snprintf(menu_backtitle, sizeof(menu_backtitle), + "%s - %s", config_filename, rootmenu.prompt->text); + if (size >= sizeof(menu_backtitle)) + menu_backtitle[sizeof(menu_backtitle)-1] = '\0'; + set_dialog_backtitle(menu_backtitle); + + size = snprintf(filename, sizeof(filename), "%s", config_filename); + if (size >= sizeof(filename)) + filename[sizeof(filename)-1] = '\0'; +} + +struct subtitle_part { + struct list_head entries; + const char *text; +}; +static LIST_HEAD(trail); + +static struct subtitle_list *subtitles; +static void set_subtitle(void) +{ + struct subtitle_part *sp; + struct subtitle_list *pos, *tmp; + + for (pos = subtitles; pos != NULL; pos = tmp) { + tmp = pos->next; + free(pos); + } + + subtitles = NULL; + list_for_each_entry(sp, &trail, entries) { + if (sp->text) { + if (pos) { + pos->next = xcalloc(1, sizeof(*pos)); + pos = pos->next; + } else { + subtitles = pos = xcalloc(1, sizeof(*pos)); + } + pos->text = sp->text; + } + } + + set_dialog_subtitles(subtitles); +} + +static void reset_subtitle(void) +{ + struct subtitle_list *pos, *tmp; + + for (pos = subtitles; pos != NULL; pos = tmp) { + tmp = pos->next; + free(pos); + } + subtitles = NULL; + set_dialog_subtitles(subtitles); +} + +struct search_data { + struct list_head *head; + struct menu **targets; + int *keys; +}; + +static void update_text(char *buf, size_t start, size_t end, void *_data) +{ + struct search_data *data = _data; + struct jump_key *pos; + int k = 0; + + list_for_each_entry(pos, data->head, entries) { + if (pos->offset >= start && pos->offset < end) { + char header[4]; + + if (k < JUMP_NB) { + int key = '0' + (pos->index % JUMP_NB) + 1; + + sprintf(header, "(%c)", key); + data->keys[k] = key; + data->targets[k] = pos->target; + k++; + } else { + sprintf(header, " "); + } + + memcpy(buf + pos->offset, header, sizeof(header) - 1); + } + } + data->keys[k] = 0; +} + +static void search_conf(void) +{ + struct symbol **sym_arr; + struct gstr res; + struct gstr title; + char *dialog_input; + int dres, vscroll = 0, hscroll = 0; + bool again; + struct gstr sttext; + struct subtitle_part stpart; + + title = str_new(); + str_printf( &title, _("Enter (sub)string or regexp to search for " + "(with or without \"%s\")"), CONFIG_); + +again: + dialog_clear(); + dres = dialog_inputbox(_("Search Configuration Parameter"), + str_get(&title), + 10, 75, ""); + switch (dres) { + case 0: + break; + case 1: + show_helptext(_("Search Configuration"), search_help); + goto again; + default: + str_free(&title); + return; + } + + /* strip the prefix if necessary */ + dialog_input = dialog_input_result; + if (strncasecmp(dialog_input_result, CONFIG_, strlen(CONFIG_)) == 0) + dialog_input += strlen(CONFIG_); + + sttext = str_new(); + str_printf(&sttext, "Search (%s)", dialog_input_result); + stpart.text = str_get(&sttext); + list_add_tail(&stpart.entries, &trail); + + sym_arr = sym_re_search(dialog_input); + do { + LIST_HEAD(head); + struct menu *targets[JUMP_NB]; + int keys[JUMP_NB + 1], i; + struct search_data data = { + .head = &head, + .targets = targets, + .keys = keys, + }; + struct jump_key *pos, *tmp; + + res = get_relations_str(sym_arr, &head); + set_subtitle(); + dres = show_textbox_ext(_("Search Results"), (char *) + str_get(&res), 0, 0, keys, &vscroll, + &hscroll, &update_text, (void *) + &data); + again = false; + for (i = 0; i < JUMP_NB && keys[i]; i++) + if (dres == keys[i]) { + conf(targets[i]->parent, targets[i]); + again = true; + } + str_free(&res); + list_for_each_entry_safe(pos, tmp, &head, entries) + free(pos); + } while (again); + free(sym_arr); + str_free(&title); + list_del(trail.prev); + str_free(&sttext); +} + +static void build_conf(struct menu *menu) +{ + struct symbol *sym; + struct property *prop; + struct menu *child; + int type, tmp, doint = 2; + tristate val; + char ch; + bool visible; + + /* + * note: menu_is_visible() has side effect that it will + * recalc the value of the symbol. + */ + visible = menu_is_visible(menu); + if (show_all_options && !menu_has_prompt(menu)) + return; + else if (!show_all_options && !visible) + return; + + sym = menu->sym; + prop = menu->prompt; + if (!sym) { + if (prop && menu != current_menu) { + const char *prompt = menu_get_prompt(menu); + switch (prop->type) { + case P_MENU: + child_count++; + prompt = _(prompt); + if (single_menu_mode) { + item_make("%s%*c%s", + menu->data ? "-->" : "++>", + indent + 1, ' ', prompt); + } else + item_make(" %*c%s %s", + indent + 1, ' ', prompt, + menu_is_empty(menu) ? "----" : "--->"); + item_set_tag('m'); + item_set_data(menu); + if (single_menu_mode && menu->data) + goto conf_childs; + return; + case P_COMMENT: + if (prompt) { + child_count++; + item_make(" %*c*** %s ***", indent + 1, ' ', _(prompt)); + item_set_tag(':'); + item_set_data(menu); + } + break; + default: + if (prompt) { + child_count++; + item_make("---%*c%s", indent + 1, ' ', _(prompt)); + item_set_tag(':'); + item_set_data(menu); + } + } + } else + doint = 0; + goto conf_childs; + } + + type = sym_get_type(sym); + if (sym_is_choice(sym)) { + struct symbol *def_sym = sym_get_choice_value(sym); + struct menu *def_menu = NULL; + + child_count++; + for (child = menu->list; child; child = child->next) { + if (menu_is_visible(child) && child->sym == def_sym) + def_menu = child; + } + + val = sym_get_tristate_value(sym); + if (sym_is_changable(sym)) { + switch (type) { + case S_BOOLEAN: + item_make("[%c]", val == no ? ' ' : '*'); + break; + case S_TRISTATE: + switch (val) { + case yes: ch = '*'; break; + case mod: ch = 'M'; break; + default: ch = ' '; break; + } + item_make("<%c>", ch); + break; + } + item_set_tag('t'); + item_set_data(menu); + } else { + item_make(" "); + item_set_tag(def_menu ? 't' : ':'); + item_set_data(menu); + } + + item_add_str("%*c%s", indent + 1, ' ', _(menu_get_prompt(menu))); + if (val == yes) { + if (def_menu) { + item_add_str(" (%s)", _(menu_get_prompt(def_menu))); + item_add_str(" --->"); + if (def_menu->list) { + indent += 2; + build_conf(def_menu); + indent -= 2; + } + } + return; + } + } else { + if (menu == current_menu) { + item_make("---%*c%s", indent + 1, ' ', _(menu_get_prompt(menu))); + item_set_tag(':'); + item_set_data(menu); + goto conf_childs; + } + child_count++; + val = sym_get_tristate_value(sym); + if (sym_is_choice_value(sym) && val == yes) { + item_make(" "); + item_set_tag(':'); + item_set_data(menu); + } else { + switch (type) { + case S_BOOLEAN: + if (sym_is_changable(sym)) + item_make("[%c]", val == no ? ' ' : '*'); + else + item_make("-%c-", val == no ? ' ' : '*'); + item_set_tag('t'); + item_set_data(menu); + break; + case S_TRISTATE: + switch (val) { + case yes: ch = '*'; break; + case mod: ch = 'M'; break; + default: ch = ' '; break; + } + if (sym_is_changable(sym)) { + if (sym->rev_dep.tri == mod) + item_make("{%c}", ch); + else + item_make("<%c>", ch); + } else + item_make("-%c-", ch); + item_set_tag('t'); + item_set_data(menu); + break; + default: + tmp = 2 + strlen(sym_get_string_value(sym)); /* () = 2 */ + item_make("(%s)", sym_get_string_value(sym)); + tmp = indent - tmp + 4; + if (tmp < 0) + tmp = 0; + item_add_str("%*c%s%s", tmp, ' ', _(menu_get_prompt(menu)), + (sym_has_value(sym) || !sym_is_changable(sym)) ? + "" : _(" (NEW)")); + item_set_tag('s'); + item_set_data(menu); + goto conf_childs; + } + } + item_add_str("%*c%s%s", indent + 1, ' ', _(menu_get_prompt(menu)), + (sym_has_value(sym) || !sym_is_changable(sym)) ? + "" : _(" (NEW)")); + if (menu->prompt->type == P_MENU) { + item_add_str(" %s", menu_is_empty(menu) ? "----" : "--->"); + return; + } + } + +conf_childs: + indent += doint; + for (child = menu->list; child; child = child->next) + build_conf(child); + indent -= doint; +} + +static void conf(struct menu *menu, struct menu *active_menu) +{ + struct menu *submenu; + const char *prompt = menu_get_prompt(menu); + struct subtitle_part stpart; + struct symbol *sym; + int res; + int s_scroll = 0; + + if (menu != &rootmenu) + stpart.text = menu_get_prompt(menu); + else + stpart.text = NULL; + list_add_tail(&stpart.entries, &trail); + + while (1) { + item_reset(); + current_menu = menu; + build_conf(menu); + if (!child_count) + break; + set_subtitle(); + dialog_clear(); + res = dialog_menu(prompt ? _(prompt) : _("Main Menu"), + _(menu_instructions), + active_menu, &s_scroll); + if (res == 1 || res == KEY_ESC || res == -ERRDISPLAYTOOSMALL) + break; + if (item_count() != 0) { + if (!item_activate_selected()) + continue; + if (!item_tag()) + continue; + } + submenu = item_data(); + active_menu = item_data(); + if (submenu) + sym = submenu->sym; + else + sym = NULL; + + switch (res) { + case 0: + switch (item_tag()) { + case 'm': + if (single_menu_mode) + submenu->data = (void *) (long) !submenu->data; + else + conf(submenu, NULL); + break; + case 't': + if (sym_is_choice(sym) && sym_get_tristate_value(sym) == yes) + conf_choice(submenu); + else if (submenu->prompt->type == P_MENU) + conf(submenu, NULL); + break; + case 's': + conf_string(submenu); + break; + } + break; + case 2: + if (sym) + show_help(submenu); + else { + reset_subtitle(); + show_helptext(_("README"), _(mconf_readme)); + } + break; + case 3: + reset_subtitle(); + conf_save(); + break; + case 4: + reset_subtitle(); + conf_load(); + break; + case 5: + if (item_is_tag('t')) { + if (sym_set_tristate_value(sym, yes)) + break; + if (sym_set_tristate_value(sym, mod)) + show_textbox(NULL, setmod_text, 6, 74); + } + break; + case 6: + if (item_is_tag('t')) + sym_set_tristate_value(sym, no); + break; + case 7: + if (item_is_tag('t')) + sym_set_tristate_value(sym, mod); + break; + case 8: + if (item_is_tag('t')) + sym_toggle_tristate_value(sym); + else if (item_is_tag('m')) + conf(submenu, NULL); + break; + case 9: + search_conf(); + break; + case 10: + show_all_options = !show_all_options; + break; + } + } + + list_del(trail.prev); +} + +static int show_textbox_ext(const char *title, char *text, int r, int c, int + *keys, int *vscroll, int *hscroll, update_text_fn + update_text, void *data) +{ + dialog_clear(); + return dialog_textbox(title, text, r, c, keys, vscroll, hscroll, + update_text, data); +} + +static void show_textbox(const char *title, const char *text, int r, int c) +{ + show_textbox_ext(title, (char *) text, r, c, (int []) {0}, NULL, NULL, + NULL, NULL); +} + +static void show_helptext(const char *title, const char *text) +{ + show_textbox(title, text, 0, 0); +} + +static void conf_message_callback(const char *fmt, va_list ap) +{ + char buf[PATH_MAX+1]; + + vsnprintf(buf, sizeof(buf), fmt, ap); + if (save_and_exit) { + if (!silent) + printf("%s", buf); + } else { + show_textbox(NULL, buf, 6, 60); + } +} + +static void show_help(struct menu *menu) +{ + struct gstr help = str_new(); + + help.max_width = getmaxx(stdscr) - 10; + menu_get_ext_help(menu, &help); + + show_helptext(_(menu_get_prompt(menu)), str_get(&help)); + str_free(&help); +} + +static void conf_choice(struct menu *menu) +{ + const char *prompt = _(menu_get_prompt(menu)); + struct menu *child; + struct symbol *active; + + active = sym_get_choice_value(menu->sym); + while (1) { + int res; + int selected; + item_reset(); + + current_menu = menu; + for (child = menu->list; child; child = child->next) { + if (!menu_is_visible(child)) + continue; + if (child->sym) + item_make("%s", _(menu_get_prompt(child))); + else { + item_make("*** %s ***", _(menu_get_prompt(child))); + item_set_tag(':'); + } + item_set_data(child); + if (child->sym == active) + item_set_selected(1); + if (child->sym == sym_get_choice_value(menu->sym)) + item_set_tag('X'); + } + dialog_clear(); + res = dialog_checklist(prompt ? _(prompt) : _("Main Menu"), + _(radiolist_instructions), + MENUBOX_HEIGTH_MIN, + MENUBOX_WIDTH_MIN, + CHECKLIST_HEIGTH_MIN); + selected = item_activate_selected(); + switch (res) { + case 0: + if (selected) { + child = item_data(); + if (!child->sym) + break; + + sym_set_tristate_value(child->sym, yes); + } + return; + case 1: + if (selected) { + child = item_data(); + show_help(child); + active = child->sym; + } else + show_help(menu); + break; + case KEY_ESC: + return; + case -ERRDISPLAYTOOSMALL: + return; + } + } +} + +static void conf_string(struct menu *menu) +{ + const char *prompt = menu_get_prompt(menu); + + while (1) { + int res; + const char *heading; + + switch (sym_get_type(menu->sym)) { + case S_INT: + heading = _(inputbox_instructions_int); + break; + case S_HEX: + heading = _(inputbox_instructions_hex); + break; + case S_STRING: + heading = _(inputbox_instructions_string); + break; + default: + heading = _("Internal mconf error!"); + } + dialog_clear(); + res = dialog_inputbox(prompt ? _(prompt) : _("Main Menu"), + heading, 10, 75, + sym_get_string_value(menu->sym)); + switch (res) { + case 0: + if (sym_set_string_value(menu->sym, dialog_input_result)) + return; + show_textbox(NULL, _("You have made an invalid entry."), 5, 43); + break; + case 1: + show_help(menu); + break; + case KEY_ESC: + return; + } + } +} + +static void conf_load(void) +{ + + while (1) { + int res; + dialog_clear(); + res = dialog_inputbox(NULL, load_config_text, + 11, 55, filename); + switch(res) { + case 0: + if (!dialog_input_result[0]) + return; + if (!conf_read(dialog_input_result)) { + set_config_filename(dialog_input_result); + sym_set_change_count(1); + return; + } + show_textbox(NULL, _("File does not exist!"), 5, 38); + break; + case 1: + show_helptext(_("Load Alternate Configuration"), load_config_help); + break; + case KEY_ESC: + return; + } + } +} + +static void conf_save(void) +{ + while (1) { + int res; + dialog_clear(); + res = dialog_inputbox(NULL, save_config_text, + 11, 55, filename); + switch(res) { + case 0: + if (!dialog_input_result[0]) + return; + if (!conf_write(dialog_input_result)) { + set_config_filename(dialog_input_result); + return; + } + show_textbox(NULL, _("Can't create file! Probably a nonexistent directory."), 5, 60); + break; + case 1: + show_helptext(_("Save Alternate Configuration"), save_config_help); + break; + case KEY_ESC: + return; + } + } +} + +static int handle_exit(void) +{ + int res; + + save_and_exit = 1; + reset_subtitle(); + dialog_clear(); + if (conf_get_changed()) + res = dialog_yesno(NULL, + _("Do you wish to save your new configuration?\n" + "(Press to continue kernel configuration.)"), + 6, 60); + else + res = -1; + + end_dialog(saved_x, saved_y); + + switch (res) { + case 0: + if (conf_write(filename)) { + fprintf(stderr, _("\n\n" + "Error while writing of the configuration.\n" + "Your configuration changes were NOT saved." + "\n\n")); + return 1; + } + /* fall through */ + case -1: + if (!silent) + printf(_("\n\n" + "*** End of the configuration.\n" + "*** Execute 'make' to start the build or try 'make help'." + "\n\n")); + res = 0; + break; + default: + if (!silent) + fprintf(stderr, _("\n\n" + "Your configuration changes were NOT saved." + "\n\n")); + if (res != KEY_ESC) + res = 0; + } + + return res; +} + +static void sig_handler(int signo) +{ + exit(handle_exit()); +} + +int main(int ac, char **av) +{ + char *mode; + int res; + + setlocale(LC_ALL, ""); + bindtextdomain(PACKAGE, LOCALEDIR); + textdomain(PACKAGE); + + signal(SIGINT, sig_handler); + + if (ac > 1 && strcmp(av[1], "-s") == 0) { + silent = 1; + /* Silence conf_read() until the real callback is set up */ + conf_set_message_callback(NULL); + av++; + } + conf_parse(av[1]); + conf_read(NULL); + + mode = getenv("MENUCONFIG_MODE"); + if (mode) { + if (!strcasecmp(mode, "single_menu")) + single_menu_mode = 1; + } + + if (init_dialog(NULL)) { + fprintf(stderr, N_("Your display is too small to run Menuconfig!\n")); + fprintf(stderr, N_("It must be at least 19 lines by 80 columns.\n")); + return 1; + } + + set_config_filename(conf_get_configname()); + conf_set_message_callback(conf_message_callback); + do { + conf(&rootmenu, NULL); + res = handle_exit(); + } while (res == KEY_ESC); + + return res; +} diff --git a/tools/kconfig/menu.c b/tools/kconfig/menu.c new file mode 100644 index 0000000000..aed678e8a7 --- /dev/null +++ b/tools/kconfig/menu.c @@ -0,0 +1,697 @@ +/* + * Copyright (C) 2002 Roman Zippel + * Released under the terms of the GNU GPL v2.0. + */ + +#include +#include +#include +#include + +#include "lkc.h" + +static const char nohelp_text[] = "There is no help available for this option."; + +struct menu rootmenu; +static struct menu **last_entry_ptr; + +struct file *file_list; +struct file *current_file; + +void menu_warn(struct menu *menu, const char *fmt, ...) +{ + va_list ap; + va_start(ap, fmt); + fprintf(stderr, "%s:%d:warning: ", menu->file->name, menu->lineno); + vfprintf(stderr, fmt, ap); + fprintf(stderr, "\n"); + va_end(ap); +} + +static void prop_warn(struct property *prop, const char *fmt, ...) +{ + va_list ap; + va_start(ap, fmt); + fprintf(stderr, "%s:%d:warning: ", prop->file->name, prop->lineno); + vfprintf(stderr, fmt, ap); + fprintf(stderr, "\n"); + va_end(ap); +} + +void _menu_init(void) +{ + current_entry = current_menu = &rootmenu; + last_entry_ptr = &rootmenu.list; +} + +void menu_add_entry(struct symbol *sym) +{ + struct menu *menu; + + menu = xmalloc(sizeof(*menu)); + memset(menu, 0, sizeof(*menu)); + menu->sym = sym; + menu->parent = current_menu; + menu->file = current_file; + menu->lineno = zconf_lineno(); + + *last_entry_ptr = menu; + last_entry_ptr = &menu->next; + current_entry = menu; + if (sym) + menu_add_symbol(P_SYMBOL, sym, NULL); +} + +void menu_end_entry(void) +{ +} + +struct menu *menu_add_menu(void) +{ + menu_end_entry(); + last_entry_ptr = ¤t_entry->list; + return current_menu = current_entry; +} + +void menu_end_menu(void) +{ + last_entry_ptr = ¤t_menu->next; + current_menu = current_menu->parent; +} + +static struct expr *menu_check_dep(struct expr *e) +{ + if (!e) + return e; + + switch (e->type) { + case E_NOT: + e->left.expr = menu_check_dep(e->left.expr); + break; + case E_OR: + case E_AND: + e->left.expr = menu_check_dep(e->left.expr); + e->right.expr = menu_check_dep(e->right.expr); + break; + case E_SYMBOL: + /* change 'm' into 'm' && MODULES */ + if (e->left.sym == &symbol_mod) + return expr_alloc_and(e, expr_alloc_symbol(modules_sym)); + break; + default: + break; + } + return e; +} + +void menu_add_dep(struct expr *dep) +{ + current_entry->dep = expr_alloc_and(current_entry->dep, menu_check_dep(dep)); +} + +void menu_set_type(int type) +{ + struct symbol *sym = current_entry->sym; + + if (sym->type == type) + return; + if (sym->type == S_UNKNOWN) { + sym->type = type; + return; + } + menu_warn(current_entry, + "ignoring type redefinition of '%s' from '%s' to '%s'", + sym->name ? sym->name : "", + sym_type_name(sym->type), sym_type_name(type)); +} + +static struct property *menu_add_prop(enum prop_type type, char *prompt, struct expr *expr, struct expr *dep) +{ + struct property *prop = prop_alloc(type, current_entry->sym); + + prop->menu = current_entry; + prop->expr = expr; + prop->visible.expr = menu_check_dep(dep); + + if (prompt) { + if (isspace(*prompt)) { + prop_warn(prop, "leading whitespace ignored"); + while (isspace(*prompt)) + prompt++; + } + if (current_entry->prompt && current_entry != &rootmenu) + prop_warn(prop, "prompt redefined"); + + /* Apply all upper menus' visibilities to actual prompts. */ + if(type == P_PROMPT) { + struct menu *menu = current_entry; + + while ((menu = menu->parent) != NULL) { + struct expr *dup_expr; + + if (!menu->visibility) + continue; + /* + * Do not add a reference to the + * menu's visibility expression but + * use a copy of it. Otherwise the + * expression reduction functions + * will modify expressions that have + * multiple references which can + * cause unwanted side effects. + */ + dup_expr = expr_copy(menu->visibility); + + prop->visible.expr + = expr_alloc_and(prop->visible.expr, + dup_expr); + } + } + + current_entry->prompt = prop; + } + prop->text = prompt; + + return prop; +} + +struct property *menu_add_prompt(enum prop_type type, char *prompt, struct expr *dep) +{ + return menu_add_prop(type, prompt, NULL, dep); +} + +void menu_add_visibility(struct expr *expr) +{ + current_entry->visibility = expr_alloc_and(current_entry->visibility, + expr); +} + +void menu_add_expr(enum prop_type type, struct expr *expr, struct expr *dep) +{ + menu_add_prop(type, NULL, expr, dep); +} + +void menu_add_symbol(enum prop_type type, struct symbol *sym, struct expr *dep) +{ + menu_add_prop(type, NULL, expr_alloc_symbol(sym), dep); +} + +void menu_add_option(int token, char *arg) +{ + switch (token) { + case T_OPT_MODULES: + if (modules_sym) + zconf_error("symbol '%s' redefines option 'modules'" + " already defined by symbol '%s'", + current_entry->sym->name, + modules_sym->name + ); + modules_sym = current_entry->sym; + break; + case T_OPT_DEFCONFIG_LIST: + if (!sym_defconfig_list) + sym_defconfig_list = current_entry->sym; + else if (sym_defconfig_list != current_entry->sym) + zconf_error("trying to redefine defconfig symbol"); + break; + case T_OPT_ENV: + prop_add_env(arg); + break; + case T_OPT_ALLNOCONFIG_Y: + current_entry->sym->flags |= SYMBOL_ALLNOCONFIG_Y; + break; + } +} + +static int menu_validate_number(struct symbol *sym, struct symbol *sym2) +{ + return sym2->type == S_INT || sym2->type == S_HEX || + (sym2->type == S_UNKNOWN && sym_string_valid(sym, sym2->name)); +} + +static void sym_check_prop(struct symbol *sym) +{ + struct property *prop; + struct symbol *sym2; + for (prop = sym->prop; prop; prop = prop->next) { + switch (prop->type) { + case P_DEFAULT: + if ((sym->type == S_STRING || sym->type == S_INT || sym->type == S_HEX) && + prop->expr->type != E_SYMBOL) + prop_warn(prop, + "default for config symbol '%s'" + " must be a single symbol", sym->name); + if (prop->expr->type != E_SYMBOL) + break; + sym2 = prop_get_symbol(prop); + if (sym->type == S_HEX || sym->type == S_INT) { + if (!menu_validate_number(sym, sym2)) + prop_warn(prop, + "'%s': number is invalid", + sym->name); + } + break; + case P_SELECT: + sym2 = prop_get_symbol(prop); + if (sym->type != S_BOOLEAN && sym->type != S_TRISTATE) + prop_warn(prop, + "config symbol '%s' uses select, but is " + "not boolean or tristate", sym->name); + else if (sym2->type != S_UNKNOWN && + sym2->type != S_BOOLEAN && + sym2->type != S_TRISTATE) + prop_warn(prop, + "'%s' has wrong type. 'select' only " + "accept arguments of boolean and " + "tristate type", sym2->name); + break; + case P_RANGE: + if (sym->type != S_INT && sym->type != S_HEX) + prop_warn(prop, "range is only allowed " + "for int or hex symbols"); + if (!menu_validate_number(sym, prop->expr->left.sym) || + !menu_validate_number(sym, prop->expr->right.sym)) + prop_warn(prop, "range is invalid"); + break; + default: + ; + } + } +} + +void menu_finalize(struct menu *parent) +{ + struct menu *menu, *last_menu; + struct symbol *sym; + struct property *prop; + struct expr *parentdep, *basedep, *dep, *dep2, **ep; + + sym = parent->sym; + if (parent->list) { + if (sym && sym_is_choice(sym)) { + if (sym->type == S_UNKNOWN) { + /* find the first choice value to find out choice type */ + current_entry = parent; + for (menu = parent->list; menu; menu = menu->next) { + if (menu->sym && menu->sym->type != S_UNKNOWN) { + menu_set_type(menu->sym->type); + break; + } + } + } + /* set the type of the remaining choice values */ + for (menu = parent->list; menu; menu = menu->next) { + current_entry = menu; + if (menu->sym && menu->sym->type == S_UNKNOWN) + menu_set_type(sym->type); + } + parentdep = expr_alloc_symbol(sym); + } else if (parent->prompt) + parentdep = parent->prompt->visible.expr; + else + parentdep = parent->dep; + + for (menu = parent->list; menu; menu = menu->next) { + basedep = expr_transform(menu->dep); + basedep = expr_alloc_and(expr_copy(parentdep), basedep); + basedep = expr_eliminate_dups(basedep); + menu->dep = basedep; + if (menu->sym) + prop = menu->sym->prop; + else + prop = menu->prompt; + for (; prop; prop = prop->next) { + if (prop->menu != menu) + continue; + dep = expr_transform(prop->visible.expr); + dep = expr_alloc_and(expr_copy(basedep), dep); + dep = expr_eliminate_dups(dep); + if (menu->sym && menu->sym->type != S_TRISTATE) + dep = expr_trans_bool(dep); + prop->visible.expr = dep; + if (prop->type == P_SELECT) { + struct symbol *es = prop_get_symbol(prop); + es->rev_dep.expr = expr_alloc_or(es->rev_dep.expr, + expr_alloc_and(expr_alloc_symbol(menu->sym), expr_copy(dep))); + } + } + } + for (menu = parent->list; menu; menu = menu->next) + menu_finalize(menu); + } else if (sym) { + basedep = parent->prompt ? parent->prompt->visible.expr : NULL; + basedep = expr_trans_compare(basedep, E_UNEQUAL, &symbol_no); + basedep = expr_eliminate_dups(expr_transform(basedep)); + last_menu = NULL; + for (menu = parent->next; menu; menu = menu->next) { + dep = menu->prompt ? menu->prompt->visible.expr : menu->dep; + if (!expr_contains_symbol(dep, sym)) + break; + if (expr_depends_symbol(dep, sym)) + goto next; + dep = expr_trans_compare(dep, E_UNEQUAL, &symbol_no); + dep = expr_eliminate_dups(expr_transform(dep)); + dep2 = expr_copy(basedep); + expr_eliminate_eq(&dep, &dep2); + expr_free(dep); + if (!expr_is_yes(dep2)) { + expr_free(dep2); + break; + } + expr_free(dep2); + next: + menu_finalize(menu); + menu->parent = parent; + last_menu = menu; + } + if (last_menu) { + parent->list = parent->next; + parent->next = last_menu->next; + last_menu->next = NULL; + } + + sym->dir_dep.expr = expr_alloc_or(sym->dir_dep.expr, parent->dep); + } + for (menu = parent->list; menu; menu = menu->next) { + if (sym && sym_is_choice(sym) && + menu->sym && !sym_is_choice_value(menu->sym)) { + current_entry = menu; + menu->sym->flags |= SYMBOL_CHOICEVAL; + if (!menu->prompt) + menu_warn(menu, "choice value must have a prompt"); + for (prop = menu->sym->prop; prop; prop = prop->next) { + if (prop->type == P_DEFAULT) + prop_warn(prop, "defaults for choice " + "values not supported"); + if (prop->menu == menu) + continue; + if (prop->type == P_PROMPT && + prop->menu->parent->sym != sym) + prop_warn(prop, "choice value used outside its choice group"); + } + /* Non-tristate choice values of tristate choices must + * depend on the choice being set to Y. The choice + * values' dependencies were propagated to their + * properties above, so the change here must be re- + * propagated. + */ + if (sym->type == S_TRISTATE && menu->sym->type != S_TRISTATE) { + basedep = expr_alloc_comp(E_EQUAL, sym, &symbol_yes); + menu->dep = expr_alloc_and(basedep, menu->dep); + for (prop = menu->sym->prop; prop; prop = prop->next) { + if (prop->menu != menu) + continue; + prop->visible.expr = expr_alloc_and(expr_copy(basedep), + prop->visible.expr); + } + } + menu_add_symbol(P_CHOICE, sym, NULL); + prop = sym_get_choice_prop(sym); + for (ep = &prop->expr; *ep; ep = &(*ep)->left.expr) + ; + *ep = expr_alloc_one(E_LIST, NULL); + (*ep)->right.sym = menu->sym; + } + if (menu->list && (!menu->prompt || !menu->prompt->text)) { + for (last_menu = menu->list; ; last_menu = last_menu->next) { + last_menu->parent = parent; + if (!last_menu->next) + break; + } + last_menu->next = menu->next; + menu->next = menu->list; + menu->list = NULL; + } + } + + if (sym && !(sym->flags & SYMBOL_WARNED)) { + if (sym->type == S_UNKNOWN) + menu_warn(parent, "config symbol defined without type"); + + if (sym_is_choice(sym) && !parent->prompt) + menu_warn(parent, "choice must have a prompt"); + + /* Check properties connected to this symbol */ + sym_check_prop(sym); + sym->flags |= SYMBOL_WARNED; + } + + if (sym && !sym_is_optional(sym) && parent->prompt) { + sym->rev_dep.expr = expr_alloc_or(sym->rev_dep.expr, + expr_alloc_and(parent->prompt->visible.expr, + expr_alloc_symbol(&symbol_mod))); + } +} + +bool menu_has_prompt(struct menu *menu) +{ + if (!menu->prompt) + return false; + return true; +} + +/* + * Determine if a menu is empty. + * A menu is considered empty if it contains no or only + * invisible entries. + */ +bool menu_is_empty(struct menu *menu) +{ + struct menu *child; + + for (child = menu->list; child; child = child->next) { + if (menu_is_visible(child)) + return(false); + } + return(true); +} + +bool menu_is_visible(struct menu *menu) +{ + struct menu *child; + struct symbol *sym; + tristate visible; + + if (!menu->prompt) + return false; + + if (menu->visibility) { + if (expr_calc_value(menu->visibility) == no) + return false; + } + + sym = menu->sym; + if (sym) { + sym_calc_value(sym); + visible = menu->prompt->visible.tri; + } else + visible = menu->prompt->visible.tri = expr_calc_value(menu->prompt->visible.expr); + + if (visible != no) + return true; + + if (!sym || sym_get_tristate_value(menu->sym) == no) + return false; + + for (child = menu->list; child; child = child->next) { + if (menu_is_visible(child)) { + if (sym) + sym->flags |= SYMBOL_DEF_USER; + return true; + } + } + + return false; +} + +const char *menu_get_prompt(struct menu *menu) +{ + if (menu->prompt) + return menu->prompt->text; + else if (menu->sym) + return menu->sym->name; + return NULL; +} + +struct menu *menu_get_root_menu(struct menu *menu) +{ + return &rootmenu; +} + +struct menu *menu_get_parent_menu(struct menu *menu) +{ + enum prop_type type; + + for (; menu != &rootmenu; menu = menu->parent) { + type = menu->prompt ? menu->prompt->type : 0; + if (type == P_MENU) + break; + } + return menu; +} + +bool menu_has_help(struct menu *menu) +{ + return menu->help != NULL; +} + +const char *menu_get_help(struct menu *menu) +{ + if (menu->help) + return menu->help; + else + return ""; +} + +static void get_prompt_str(struct gstr *r, struct property *prop, + struct list_head *head) +{ + int i, j; + struct menu *submenu[8], *menu, *location = NULL; + struct jump_key *jump = NULL; + + str_printf(r, _("Prompt: %s\n"), _(prop->text)); + menu = prop->menu->parent; + for (i = 0; menu != &rootmenu && i < 8; menu = menu->parent) { + bool accessible = menu_is_visible(menu); + + submenu[i++] = menu; + if (location == NULL && accessible) + location = menu; + } + if (head && location) { + jump = xmalloc(sizeof(struct jump_key)); + + if (menu_is_visible(prop->menu)) { + /* + * There is not enough room to put the hint at the + * beginning of the "Prompt" line. Put the hint on the + * last "Location" line even when it would belong on + * the former. + */ + jump->target = prop->menu; + } else + jump->target = location; + + if (list_empty(head)) + jump->index = 0; + else + jump->index = list_entry(head->prev, struct jump_key, + entries)->index + 1; + + list_add_tail(&jump->entries, head); + } + + if (i > 0) { + str_printf(r, _(" Location:\n")); + for (j = 4; --i >= 0; j += 2) { + menu = submenu[i]; + if (jump && menu == location) + jump->offset = strlen(r->s); + str_printf(r, "%*c-> %s", j, ' ', + _(menu_get_prompt(menu))); + if (menu->sym) { + str_printf(r, " (%s [=%s])", menu->sym->name ? + menu->sym->name : _(""), + sym_get_string_value(menu->sym)); + } + str_append(r, "\n"); + } + } +} + +/* + * get property of type P_SYMBOL + */ +static struct property *get_symbol_prop(struct symbol *sym) +{ + struct property *prop = NULL; + + for_all_properties(sym, prop, P_SYMBOL) + break; + return prop; +} + +/* + * head is optional and may be NULL + */ +static void get_symbol_str(struct gstr *r, struct symbol *sym, + struct list_head *head) +{ + bool hit; + struct property *prop; + + if (sym && sym->name) { + str_printf(r, "Symbol: %s [=%s]\n", sym->name, + sym_get_string_value(sym)); + str_printf(r, "Type : %s\n", sym_type_name(sym->type)); + if (sym->type == S_INT || sym->type == S_HEX) { + prop = sym_get_range_prop(sym); + if (prop) { + str_printf(r, "Range : "); + expr_gstr_print(prop->expr, r); + str_append(r, "\n"); + } + } + } + for_all_prompts(sym, prop) + get_prompt_str(r, prop, head); + + prop = get_symbol_prop(sym); + if (prop) { + str_printf(r, _(" Defined at %s:%d\n"), prop->menu->file->name, + prop->menu->lineno); + if (!expr_is_yes(prop->visible.expr)) { + str_append(r, _(" Depends on: ")); + expr_gstr_print(prop->visible.expr, r); + str_append(r, "\n"); + } + } + + hit = false; + for_all_properties(sym, prop, P_SELECT) { + if (!hit) { + str_append(r, " Selects: "); + hit = true; + } else + str_printf(r, " && "); + expr_gstr_print(prop->expr, r); + } + if (hit) + str_append(r, "\n"); + if (sym->rev_dep.expr) { + str_append(r, _(" Selected by: ")); + expr_gstr_print(sym->rev_dep.expr, r); + str_append(r, "\n"); + } + str_append(r, "\n\n"); +} + +struct gstr get_relations_str(struct symbol **sym_arr, struct list_head *head) +{ + struct symbol *sym; + struct gstr res = str_new(); + int i; + + for (i = 0; sym_arr && (sym = sym_arr[i]); i++) + get_symbol_str(&res, sym, head); + if (!i) + str_append(&res, _("No matches found.\n")); + return res; +} + + +void menu_get_ext_help(struct menu *menu, struct gstr *help) +{ + struct symbol *sym = menu->sym; + const char *help_text = nohelp_text; + + if (menu_has_help(menu)) { + if (sym->name) + str_printf(help, "%s%s:\n\n", CONFIG_, sym->name); + help_text = menu_get_help(menu); + } + str_printf(help, "%s\n", _(help_text)); + if (sym) + get_symbol_str(help, sym, NULL); +} diff --git a/tools/kconfig/merge_config.sh b/tools/kconfig/merge_config.sh new file mode 100755 index 0000000000..67d1314476 --- /dev/null +++ b/tools/kconfig/merge_config.sh @@ -0,0 +1,170 @@ +#!/bin/sh +# merge_config.sh - Takes a list of config fragment values, and merges +# them one by one. Provides warnings on overridden values, and specified +# values that did not make it to the resulting .config file (due to missed +# dependencies or config symbol removal). +# +# Portions reused from kconf_check and generate_cfg: +# http://git.yoctoproject.org/cgit/cgit.cgi/yocto-kernel-tools/tree/tools/kconf_check +# http://git.yoctoproject.org/cgit/cgit.cgi/yocto-kernel-tools/tree/tools/generate_cfg +# +# Copyright (c) 2009-2010 Wind River Systems, Inc. +# Copyright 2011 Linaro +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License version 2 as +# published by the Free Software Foundation. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +# See the GNU General Public License for more details. + +clean_up() { + rm -f $TMP_FILE + exit +} +trap clean_up HUP INT TERM + +usage() { + echo "Usage: $0 [OPTIONS] [CONFIG [...]]" + echo " -h display this help text" + echo " -m only merge the fragments, do not execute the make command" + echo " -n use allnoconfig instead of alldefconfig" + echo " -r list redundant entries when merging fragments" + echo " -O dir to put generated output files. Consider setting \$KCONFIG_CONFIG instead." +} + +RUNMAKE=true +ALLTARGET=alldefconfig +WARNREDUN=false +OUTPUT=. + +while true; do + case $1 in + "-n") + ALLTARGET=allnoconfig + shift + continue + ;; + "-m") + RUNMAKE=false + shift + continue + ;; + "-h") + usage + exit + ;; + "-r") + WARNREDUN=true + shift + continue + ;; + "-O") + if [ -d $2 ];then + OUTPUT=$(echo $2 | sed 's/\/*$//') + else + echo "output directory $2 does not exist" 1>&2 + exit 1 + fi + shift 2 + continue + ;; + *) + break + ;; + esac +done + +if [ "$#" -lt 1 ] ; then + usage + exit +fi + +if [ -z "$KCONFIG_CONFIG" ]; then + if [ "$OUTPUT" != . ]; then + KCONFIG_CONFIG=$(readlink -m -- "$OUTPUT/.config") + else + KCONFIG_CONFIG=.config + fi +fi + +INITFILE=$1 +shift; + +if [ ! -r "$INITFILE" ]; then + echo "The base file '$INITFILE' does not exist. Exit." >&2 + exit 1 +fi + +MERGE_LIST=$* +SED_CONFIG_EXP="s/^\(# \)\{0,1\}\(CONFIG_[a-zA-Z0-9_]*\)[= ].*/\2/p" +TMP_FILE=$(mktemp ./.tmp.config.XXXXXXXXXX) + +echo "Using $INITFILE as base" +cat $INITFILE > $TMP_FILE + +# Merge files, printing warnings on overridden values +for MERGE_FILE in $MERGE_LIST ; do + echo "Merging $MERGE_FILE" + if [ ! -r "$MERGE_FILE" ]; then + echo "The merge file '$MERGE_FILE' does not exist. Exit." >&2 + exit 1 + fi + CFG_LIST=$(sed -n "$SED_CONFIG_EXP" $MERGE_FILE) + + for CFG in $CFG_LIST ; do + grep -q -w $CFG $TMP_FILE || continue + PREV_VAL=$(grep -w $CFG $TMP_FILE) + NEW_VAL=$(grep -w $CFG $MERGE_FILE) + if [ "x$PREV_VAL" != "x$NEW_VAL" ] ; then + echo Value of $CFG is redefined by fragment $MERGE_FILE: + echo Previous value: $PREV_VAL + echo New value: $NEW_VAL + echo + elif [ "$WARNREDUN" = "true" ]; then + echo Value of $CFG is redundant by fragment $MERGE_FILE: + fi + sed -i "/$CFG[ =]/d" $TMP_FILE + done + cat $MERGE_FILE >> $TMP_FILE +done + +if [ "$RUNMAKE" = "false" ]; then + cp -T -- "$TMP_FILE" "$KCONFIG_CONFIG" + echo "#" + echo "# merged configuration written to $KCONFIG_CONFIG (needs make)" + echo "#" + clean_up + exit +fi + +# If we have an output dir, setup the O= argument, otherwise leave +# it blank, since O=. will create an unnecessary ./source softlink +OUTPUT_ARG="" +if [ "$OUTPUT" != "." ] ; then + OUTPUT_ARG="O=$OUTPUT" +fi + + +# Use the merged file as the starting point for: +# alldefconfig: Fills in any missing symbols with Kconfig default +# allnoconfig: Fills in any missing symbols with # CONFIG_* is not set +make KCONFIG_ALLCONFIG=$TMP_FILE $OUTPUT_ARG $ALLTARGET + + +# Check all specified config values took (might have missed-dependency issues) +for CFG in $(sed -n "$SED_CONFIG_EXP" $TMP_FILE); do + + REQUESTED_VAL=$(grep -w -e "$CFG" $TMP_FILE) + ACTUAL_VAL=$(grep -w -e "$CFG" "$KCONFIG_CONFIG") + if [ "x$REQUESTED_VAL" != "x$ACTUAL_VAL" ] ; then + echo "Value requested for $CFG not in final .config" + echo "Requested value: $REQUESTED_VAL" + echo "Actual value: $ACTUAL_VAL" + echo "" + fi +done + +clean_up diff --git a/tools/kconfig/nconf.c b/tools/kconfig/nconf.c new file mode 100644 index 0000000000..d42d534a66 --- /dev/null +++ b/tools/kconfig/nconf.c @@ -0,0 +1,1561 @@ +/* + * Copyright (C) 2008 Nir Tzachar +#include + +#include "lkc.h" +#include "nconf.h" +#include + +static const char nconf_global_help[] = N_( +"Help windows\n" +"------------\n" +"o Global help: Unless in a data entry window, pressing will give \n" +" you the global help window, which you are just reading.\n" +"\n" +"o A short version of the global help is available by pressing .\n" +"\n" +"o Local help: To get help related to the current menu entry, use any\n" +" of , or if in a data entry window then press .\n" +"\n" +"\n" +"Menu entries\n" +"------------\n" +"This interface lets you select features and parameters for the kernel\n" +"build. Kernel features can either be built-in, modularized, or removed.\n" +"Parameters must be entered as text or decimal or hexadecimal numbers.\n" +"\n" +"Menu entries beginning with following braces represent features that\n" +" [ ] can be built in or removed\n" +" < > can be built in, modularized or removed\n" +" { } can be built in or modularized, are selected by another feature\n" +" - - are selected by another feature\n" +" XXX cannot be selected. Symbol Info tells you why.\n" +"*, M or whitespace inside braces means to build in, build as a module\n" +"or to exclude the feature respectively.\n" +"\n" +"To change any of these features, highlight it with the movement keys\n" +"listed below and press to build it in, to make it a module or\n" +" to remove it. You may press the key to cycle through the\n" +"available options.\n" +"\n" +"A trailing \"--->\" designates a submenu, a trailing \"----\" an\n" +"empty submenu.\n" +"\n" +"Menu navigation keys\n" +"----------------------------------------------------------------------\n" +"Linewise up \n" +"Linewise down \n" +"Pagewise up \n" +"Pagewise down \n" +"First entry \n" +"Last entry \n" +"Enter a submenu \n" +"Go back to parent menu \n" +"Close a help window \n" +"Close entry window, apply \n" +"Close entry window, forget \n" +"Start incremental, case-insensitive search for STRING in menu entries,\n" +" no regex support, STRING is displayed in upper left corner\n" +" STRING\n" +" Remove last character \n" +" Jump to next hit \n" +" Jump to previous hit \n" +"Exit menu search mode \n" +"Search for configuration variables with or without leading CONFIG_\n" +" RegExpr\n" +"Verbose search help \n" +"----------------------------------------------------------------------\n" +"\n" +"Unless in a data entry window, key <1> may be used instead of ,\n" +"<2> instead of , etc.\n" +"\n" +"\n" +"Radiolist (Choice list)\n" +"-----------------------\n" +"Use the movement keys listed above to select the option you wish to set\n" +"and press .\n" +"\n" +"\n" +"Data entry\n" +"----------\n" +"Enter the requested information and press . Hexadecimal values\n" +"may be entered without the \"0x\" prefix.\n" +"\n" +"\n" +"Text Box (Help Window)\n" +"----------------------\n" +"Use movement keys as listed in table above.\n" +"\n" +"Press any of to exit.\n" +"\n" +"\n" +"Alternate configuration files\n" +"-----------------------------\n" +"nconfig supports switching between different configurations.\n" +"Press to save your current configuration. Press and enter\n" +"a file name to load a previously saved configuration.\n" +"\n" +"\n" +"Terminal configuration\n" +"----------------------\n" +"If you use nconfig in a xterm window, make sure your TERM environment\n" +"variable specifies a terminal configuration which supports at least\n" +"16 colors. Otherwise nconfig will look rather bad.\n" +"\n" +"If the \"stty size\" command reports the current terminalsize correctly,\n" +"nconfig will adapt to sizes larger than the traditional 80x25 \"standard\"\n" +"and display longer menus properly.\n" +"\n" +"\n" +"Single menu mode\n" +"----------------\n" +"If you prefer to have all of the menu entries listed in a single menu,\n" +"rather than the default multimenu hierarchy, run nconfig with\n" +"NCONFIG_MODE environment variable set to single_menu. Example:\n" +"\n" +"make NCONFIG_MODE=single_menu nconfig\n" +"\n" +" will then unfold the appropriate category, or fold it if it\n" +"is already unfolded. Folded menu entries will be designated by a\n" +"leading \"++>\" and unfolded entries by a leading \"-->\".\n" +"\n" +"Note that this mode can eventually be a little more CPU expensive than\n" +"the default mode, especially with a larger number of unfolded submenus.\n" +"\n"), +menu_no_f_instructions[] = N_( +"Legend: [*] built-in [ ] excluded module < > module capable.\n" +"Submenus are designated by a trailing \"--->\", empty ones by \"----\".\n" +"\n" +"Use the following keys to navigate the menus:\n" +"Move up or down with and .\n" +"Enter a submenu with or .\n" +"Exit a submenu to its parent menu with or .\n" +"Pressing includes, excludes, modularizes features.\n" +"Pressing cycles through the available options.\n" +"To search for menu entries press .\n" +" always leaves the current window.\n" +"\n" +"You do not have function keys support.\n" +"Press <1> instead of , <2> instead of , etc.\n" +"For verbose global help use key <1>.\n" +"For help related to the current menu entry press or .\n"), +menu_instructions[] = N_( +"Legend: [*] built-in [ ] excluded module < > module capable.\n" +"Submenus are designated by a trailing \"--->\", empty ones by \"----\".\n" +"\n" +"Use the following keys to navigate the menus:\n" +"Move up or down with or .\n" +"Enter a submenu with or .\n" +"Exit a submenu to its parent menu with or .\n" +"Pressing includes, excludes, modularizes features.\n" +"Pressing cycles through the available options.\n" +"To search for menu entries press .\n" +" always leaves the current window.\n" +"\n" +"Pressing <1> may be used instead of , <2> instead of , etc.\n" +"For verbose global help press .\n" +"For help related to the current menu entry press or .\n"), +radiolist_instructions[] = N_( +"Press , , or to navigate a radiolist, select\n" +"with .\n" +"For help related to the current entry press or .\n" +"For global help press .\n"), +inputbox_instructions_int[] = N_( +"Please enter a decimal value.\n" +"Fractions will not be accepted.\n" +"Press to apply, to cancel."), +inputbox_instructions_hex[] = N_( +"Please enter a hexadecimal value.\n" +"Press to apply, to cancel."), +inputbox_instructions_string[] = N_( +"Please enter a string value.\n" +"Press to apply, to cancel."), +setmod_text[] = N_( +"This feature depends on another feature which has been configured as a\n" +"module. As a result, the current feature will be built as a module too."), +load_config_text[] = N_( +"Enter the name of the configuration file you wish to load.\n" +"Accept the name shown to restore the configuration you last\n" +"retrieved. Leave empty to abort."), +load_config_help[] = N_( +"For various reasons, one may wish to keep several different\n" +"configurations available on a single machine.\n" +"\n" +"If you have saved a previous configuration in a file other than the\n" +"default one, entering its name here will allow you to load and modify\n" +"that configuration.\n" +"\n" +"Leave empty to abort.\n"), +save_config_text[] = N_( +"Enter a filename to which this configuration should be saved\n" +"as an alternate. Leave empty to abort."), +save_config_help[] = N_( +"For various reasons, one may wish to keep several different\n" +"configurations available on a single machine.\n" +"\n" +"Entering a file name here will allow you to later retrieve, modify\n" +"and use the current configuration as an alternate to whatever\n" +"configuration options you have selected at that time.\n" +"\n" +"Leave empty to abort.\n"), +search_help[] = N_( +"Search for symbols (configuration variable names CONFIG_*) and display\n" +"their relations. Regular expressions are supported.\n" +"Example: Search for \"^FOO\".\n" +"Result:\n" +"-----------------------------------------------------------------\n" +"Symbol: FOO [ = m]\n" +"Prompt: Foo bus is used to drive the bar HW\n" +"Defined at drivers/pci/Kconfig:47\n" +"Depends on: X86_LOCAL_APIC && X86_IO_APIC || IA64\n" +"Location:\n" +" -> Bus options (PCI, PCMCIA, EISA, ISA)\n" +" -> PCI support (PCI [ = y])\n" +" -> PCI access mode ( [ = y])\n" +"Selects: LIBCRC32\n" +"Selected by: BAR\n" +"-----------------------------------------------------------------\n" +"o The line 'Prompt:' shows the text displayed for this symbol in\n" +" the menu hierarchy.\n" +"o The 'Defined at' line tells at what file / line number the symbol is\n" +" defined.\n" +"o The 'Depends on:' line lists symbols that need to be defined for\n" +" this symbol to be visible and selectable in the menu.\n" +"o The 'Location:' lines tell, where in the menu structure this symbol\n" +" is located. A location followed by a [ = y] indicates that this is\n" +" a selectable menu item, and the current value is displayed inside\n" +" brackets.\n" +"o The 'Selects:' line tells, what symbol will be automatically selected\n" +" if this symbol is selected (y or m).\n" +"o The 'Selected by' line tells what symbol has selected this symbol.\n" +"\n" +"Only relevant lines are shown.\n" +"\n\n" +"Search examples:\n" +"USB => find all symbols containing USB\n" +"^USB => find all symbols starting with USB\n" +"USB$ => find all symbols ending with USB\n" +"\n"); + +struct mitem { + char str[256]; + char tag; + void *usrptr; + int is_visible; +}; + +#define MAX_MENU_ITEMS 4096 +static int show_all_items; +static int indent; +static struct menu *current_menu; +static int child_count; +static int single_menu_mode; +/* the window in which all information appears */ +static WINDOW *main_window; +/* the largest size of the menu window */ +static int mwin_max_lines; +static int mwin_max_cols; +/* the window in which we show option buttons */ +static MENU *curses_menu; +static ITEM *curses_menu_items[MAX_MENU_ITEMS]; +static struct mitem k_menu_items[MAX_MENU_ITEMS]; +static int items_num; +static int global_exit; +/* the currently selected button */ +const char *current_instructions = menu_instructions; + +static char *dialog_input_result; +static int dialog_input_result_len; + +static void conf(struct menu *menu); +static void conf_choice(struct menu *menu); +static void conf_string(struct menu *menu); +static void conf_load(void); +static void conf_save(void); +static void show_help(struct menu *menu); +static int do_exit(void); +static void setup_windows(void); +static void search_conf(void); + +typedef void (*function_key_handler_t)(int *key, struct menu *menu); +static void handle_f1(int *key, struct menu *current_item); +static void handle_f2(int *key, struct menu *current_item); +static void handle_f3(int *key, struct menu *current_item); +static void handle_f4(int *key, struct menu *current_item); +static void handle_f5(int *key, struct menu *current_item); +static void handle_f6(int *key, struct menu *current_item); +static void handle_f7(int *key, struct menu *current_item); +static void handle_f8(int *key, struct menu *current_item); +static void handle_f9(int *key, struct menu *current_item); + +struct function_keys { + const char *key_str; + const char *func; + function_key key; + function_key_handler_t handler; +}; + +static const int function_keys_num = 9; +struct function_keys function_keys[] = { + { + .key_str = "F1", + .func = "Help", + .key = F_HELP, + .handler = handle_f1, + }, + { + .key_str = "F2", + .func = "SymInfo", + .key = F_SYMBOL, + .handler = handle_f2, + }, + { + .key_str = "F3", + .func = "Help 2", + .key = F_INSTS, + .handler = handle_f3, + }, + { + .key_str = "F4", + .func = "ShowAll", + .key = F_CONF, + .handler = handle_f4, + }, + { + .key_str = "F5", + .func = "Back", + .key = F_BACK, + .handler = handle_f5, + }, + { + .key_str = "F6", + .func = "Save", + .key = F_SAVE, + .handler = handle_f6, + }, + { + .key_str = "F7", + .func = "Load", + .key = F_LOAD, + .handler = handle_f7, + }, + { + .key_str = "F8", + .func = "SymSearch", + .key = F_SEARCH, + .handler = handle_f8, + }, + { + .key_str = "F9", + .func = "Exit", + .key = F_EXIT, + .handler = handle_f9, + }, +}; + +static void print_function_line(void) +{ + int i; + int offset = 1; + const int skip = 1; + int lines = getmaxy(stdscr); + + for (i = 0; i < function_keys_num; i++) { + (void) wattrset(main_window, attributes[FUNCTION_HIGHLIGHT]); + mvwprintw(main_window, lines-3, offset, + "%s", + function_keys[i].key_str); + (void) wattrset(main_window, attributes[FUNCTION_TEXT]); + offset += strlen(function_keys[i].key_str); + mvwprintw(main_window, lines-3, + offset, "%s", + function_keys[i].func); + offset += strlen(function_keys[i].func) + skip; + } + (void) wattrset(main_window, attributes[NORMAL]); +} + +/* help */ +static void handle_f1(int *key, struct menu *current_item) +{ + show_scroll_win(main_window, + _("Global help"), _(nconf_global_help)); + return; +} + +/* symbole help */ +static void handle_f2(int *key, struct menu *current_item) +{ + show_help(current_item); + return; +} + +/* instructions */ +static void handle_f3(int *key, struct menu *current_item) +{ + show_scroll_win(main_window, + _("Short help"), + _(current_instructions)); + return; +} + +/* config */ +static void handle_f4(int *key, struct menu *current_item) +{ + int res = btn_dialog(main_window, + _("Show all symbols?"), + 2, + " ", + ""); + if (res == 0) + show_all_items = 1; + else if (res == 1) + show_all_items = 0; + + return; +} + +/* back */ +static void handle_f5(int *key, struct menu *current_item) +{ + *key = KEY_LEFT; + return; +} + +/* save */ +static void handle_f6(int *key, struct menu *current_item) +{ + conf_save(); + return; +} + +/* load */ +static void handle_f7(int *key, struct menu *current_item) +{ + conf_load(); + return; +} + +/* search */ +static void handle_f8(int *key, struct menu *current_item) +{ + search_conf(); + return; +} + +/* exit */ +static void handle_f9(int *key, struct menu *current_item) +{ + do_exit(); + return; +} + +/* return != 0 to indicate the key was handles */ +static int process_special_keys(int *key, struct menu *menu) +{ + int i; + + if (*key == KEY_RESIZE) { + setup_windows(); + return 1; + } + + for (i = 0; i < function_keys_num; i++) { + if (*key == KEY_F(function_keys[i].key) || + *key == '0' + function_keys[i].key){ + function_keys[i].handler(key, menu); + return 1; + } + } + + return 0; +} + +static void clean_items(void) +{ + int i; + for (i = 0; curses_menu_items[i]; i++) + free_item(curses_menu_items[i]); + bzero(curses_menu_items, sizeof(curses_menu_items)); + bzero(k_menu_items, sizeof(k_menu_items)); + items_num = 0; +} + +typedef enum {MATCH_TINKER_PATTERN_UP, MATCH_TINKER_PATTERN_DOWN, + FIND_NEXT_MATCH_DOWN, FIND_NEXT_MATCH_UP} match_f; + +/* return the index of the matched item, or -1 if no such item exists */ +static int get_mext_match(const char *match_str, match_f flag) +{ + int match_start = item_index(current_item(curses_menu)); + int index; + + if (flag == FIND_NEXT_MATCH_DOWN) + ++match_start; + else if (flag == FIND_NEXT_MATCH_UP) + --match_start; + + index = match_start; + index = (index + items_num) % items_num; + while (true) { + char *str = k_menu_items[index].str; + if (strcasestr(str, match_str) != 0) + return index; + if (flag == FIND_NEXT_MATCH_UP || + flag == MATCH_TINKER_PATTERN_UP) + --index; + else + ++index; + index = (index + items_num) % items_num; + if (index == match_start) + return -1; + } +} + +/* Make a new item. */ +static void item_make(struct menu *menu, char tag, const char *fmt, ...) +{ + va_list ap; + + if (items_num > MAX_MENU_ITEMS-1) + return; + + bzero(&k_menu_items[items_num], sizeof(k_menu_items[0])); + k_menu_items[items_num].tag = tag; + k_menu_items[items_num].usrptr = menu; + if (menu != NULL) + k_menu_items[items_num].is_visible = + menu_is_visible(menu); + else + k_menu_items[items_num].is_visible = 1; + + va_start(ap, fmt); + vsnprintf(k_menu_items[items_num].str, + sizeof(k_menu_items[items_num].str), + fmt, ap); + va_end(ap); + + if (!k_menu_items[items_num].is_visible) + memcpy(k_menu_items[items_num].str, "XXX", 3); + + curses_menu_items[items_num] = new_item( + k_menu_items[items_num].str, + k_menu_items[items_num].str); + set_item_userptr(curses_menu_items[items_num], + &k_menu_items[items_num]); + /* + if (!k_menu_items[items_num].is_visible) + item_opts_off(curses_menu_items[items_num], O_SELECTABLE); + */ + + items_num++; + curses_menu_items[items_num] = NULL; +} + +/* very hackish. adds a string to the last item added */ +static void item_add_str(const char *fmt, ...) +{ + va_list ap; + int index = items_num-1; + char new_str[256]; + char tmp_str[256]; + + if (index < 0) + return; + + va_start(ap, fmt); + vsnprintf(new_str, sizeof(new_str), fmt, ap); + va_end(ap); + snprintf(tmp_str, sizeof(tmp_str), "%s%s", + k_menu_items[index].str, new_str); + strncpy(k_menu_items[index].str, + tmp_str, + sizeof(k_menu_items[index].str)); + + free_item(curses_menu_items[index]); + curses_menu_items[index] = new_item( + k_menu_items[index].str, + k_menu_items[index].str); + set_item_userptr(curses_menu_items[index], + &k_menu_items[index]); +} + +/* get the tag of the currently selected item */ +static char item_tag(void) +{ + ITEM *cur; + struct mitem *mcur; + + cur = current_item(curses_menu); + if (cur == NULL) + return 0; + mcur = (struct mitem *) item_userptr(cur); + return mcur->tag; +} + +static int curses_item_index(void) +{ + return item_index(current_item(curses_menu)); +} + +static void *item_data(void) +{ + ITEM *cur; + struct mitem *mcur; + + cur = current_item(curses_menu); + if (!cur) + return NULL; + mcur = (struct mitem *) item_userptr(cur); + return mcur->usrptr; + +} + +static int item_is_tag(char tag) +{ + return item_tag() == tag; +} + +static char filename[PATH_MAX+1]; +static char menu_backtitle[PATH_MAX+128]; +static const char *set_config_filename(const char *config_filename) +{ + int size; + + size = snprintf(menu_backtitle, sizeof(menu_backtitle), + "%s - %s", config_filename, rootmenu.prompt->text); + if (size >= sizeof(menu_backtitle)) + menu_backtitle[sizeof(menu_backtitle)-1] = '\0'; + + size = snprintf(filename, sizeof(filename), "%s", config_filename); + if (size >= sizeof(filename)) + filename[sizeof(filename)-1] = '\0'; + return menu_backtitle; +} + +/* return = 0 means we are successful. + * -1 means go on doing what you were doing + */ +static int do_exit(void) +{ + int res; + if (!conf_get_changed()) { + global_exit = 1; + return 0; + } + res = btn_dialog(main_window, + _("Do you wish to save your new configuration?\n" + " to cancel and resume nconfig."), + 2, + " ", + ""); + if (res == KEY_EXIT) { + global_exit = 0; + return -1; + } + + /* if we got here, the user really wants to exit */ + switch (res) { + case 0: + res = conf_write(filename); + if (res) + btn_dialog( + main_window, + _("Error during writing of configuration.\n" + "Your configuration changes were NOT saved."), + 1, + ""); + break; + default: + btn_dialog( + main_window, + _("Your configuration changes were NOT saved."), + 1, + ""); + break; + } + global_exit = 1; + return 0; +} + + +static void search_conf(void) +{ + struct symbol **sym_arr; + struct gstr res; + struct gstr title; + char *dialog_input; + int dres; + + title = str_new(); + str_printf( &title, _("Enter (sub)string or regexp to search for " + "(with or without \"%s\")"), CONFIG_); + +again: + dres = dialog_inputbox(main_window, + _("Search Configuration Parameter"), + str_get(&title), + "", &dialog_input_result, &dialog_input_result_len); + switch (dres) { + case 0: + break; + case 1: + show_scroll_win(main_window, + _("Search Configuration"), search_help); + goto again; + default: + str_free(&title); + return; + } + + /* strip the prefix if necessary */ + dialog_input = dialog_input_result; + if (strncasecmp(dialog_input_result, CONFIG_, strlen(CONFIG_)) == 0) + dialog_input += strlen(CONFIG_); + + sym_arr = sym_re_search(dialog_input); + res = get_relations_str(sym_arr, NULL); + free(sym_arr); + show_scroll_win(main_window, + _("Search Results"), str_get(&res)); + str_free(&res); + str_free(&title); +} + + +static void build_conf(struct menu *menu) +{ + struct symbol *sym; + struct property *prop; + struct menu *child; + int type, tmp, doint = 2; + tristate val; + char ch; + + if (!menu || (!show_all_items && !menu_is_visible(menu))) + return; + + sym = menu->sym; + prop = menu->prompt; + if (!sym) { + if (prop && menu != current_menu) { + const char *prompt = menu_get_prompt(menu); + enum prop_type ptype; + ptype = menu->prompt ? menu->prompt->type : P_UNKNOWN; + switch (ptype) { + case P_MENU: + child_count++; + prompt = _(prompt); + if (single_menu_mode) { + item_make(menu, 'm', + "%s%*c%s", + menu->data ? "-->" : "++>", + indent + 1, ' ', prompt); + } else + item_make(menu, 'm', + " %*c%s %s", + indent + 1, ' ', prompt, + menu_is_empty(menu) ? "----" : "--->"); + + if (single_menu_mode && menu->data) + goto conf_childs; + return; + case P_COMMENT: + if (prompt) { + child_count++; + item_make(menu, ':', + " %*c*** %s ***", + indent + 1, ' ', + _(prompt)); + } + break; + default: + if (prompt) { + child_count++; + item_make(menu, ':', "---%*c%s", + indent + 1, ' ', + _(prompt)); + } + } + } else + doint = 0; + goto conf_childs; + } + + type = sym_get_type(sym); + if (sym_is_choice(sym)) { + struct symbol *def_sym = sym_get_choice_value(sym); + struct menu *def_menu = NULL; + + child_count++; + for (child = menu->list; child; child = child->next) { + if (menu_is_visible(child) && child->sym == def_sym) + def_menu = child; + } + + val = sym_get_tristate_value(sym); + if (sym_is_changable(sym)) { + switch (type) { + case S_BOOLEAN: + item_make(menu, 't', "[%c]", + val == no ? ' ' : '*'); + break; + case S_TRISTATE: + switch (val) { + case yes: + ch = '*'; + break; + case mod: + ch = 'M'; + break; + default: + ch = ' '; + break; + } + item_make(menu, 't', "<%c>", ch); + break; + } + } else { + item_make(menu, def_menu ? 't' : ':', " "); + } + + item_add_str("%*c%s", indent + 1, + ' ', _(menu_get_prompt(menu))); + if (val == yes) { + if (def_menu) { + item_add_str(" (%s)", + _(menu_get_prompt(def_menu))); + item_add_str(" --->"); + if (def_menu->list) { + indent += 2; + build_conf(def_menu); + indent -= 2; + } + } + return; + } + } else { + if (menu == current_menu) { + item_make(menu, ':', + "---%*c%s", indent + 1, + ' ', _(menu_get_prompt(menu))); + goto conf_childs; + } + child_count++; + val = sym_get_tristate_value(sym); + if (sym_is_choice_value(sym) && val == yes) { + item_make(menu, ':', " "); + } else { + switch (type) { + case S_BOOLEAN: + if (sym_is_changable(sym)) + item_make(menu, 't', "[%c]", + val == no ? ' ' : '*'); + else + item_make(menu, 't', "-%c-", + val == no ? ' ' : '*'); + break; + case S_TRISTATE: + switch (val) { + case yes: + ch = '*'; + break; + case mod: + ch = 'M'; + break; + default: + ch = ' '; + break; + } + if (sym_is_changable(sym)) { + if (sym->rev_dep.tri == mod) + item_make(menu, + 't', "{%c}", ch); + else + item_make(menu, + 't', "<%c>", ch); + } else + item_make(menu, 't', "-%c-", ch); + break; + default: + tmp = 2 + strlen(sym_get_string_value(sym)); + item_make(menu, 's', " (%s)", + sym_get_string_value(sym)); + tmp = indent - tmp + 4; + if (tmp < 0) + tmp = 0; + item_add_str("%*c%s%s", tmp, ' ', + _(menu_get_prompt(menu)), + (sym_has_value(sym) || + !sym_is_changable(sym)) ? "" : + _(" (NEW)")); + goto conf_childs; + } + } + item_add_str("%*c%s%s", indent + 1, ' ', + _(menu_get_prompt(menu)), + (sym_has_value(sym) || !sym_is_changable(sym)) ? + "" : _(" (NEW)")); + if (menu->prompt && menu->prompt->type == P_MENU) { + item_add_str(" %s", menu_is_empty(menu) ? "----" : "--->"); + return; + } + } + +conf_childs: + indent += doint; + for (child = menu->list; child; child = child->next) + build_conf(child); + indent -= doint; +} + +static void reset_menu(void) +{ + unpost_menu(curses_menu); + clean_items(); +} + +/* adjust the menu to show this item. + * prefer not to scroll the menu if possible*/ +static void center_item(int selected_index, int *last_top_row) +{ + int toprow; + + set_top_row(curses_menu, *last_top_row); + toprow = top_row(curses_menu); + if (selected_index < toprow || + selected_index >= toprow+mwin_max_lines) { + toprow = max(selected_index-mwin_max_lines/2, 0); + if (toprow >= item_count(curses_menu)-mwin_max_lines) + toprow = item_count(curses_menu)-mwin_max_lines; + set_top_row(curses_menu, toprow); + } + set_current_item(curses_menu, + curses_menu_items[selected_index]); + *last_top_row = toprow; + post_menu(curses_menu); + refresh_all_windows(main_window); +} + +/* this function assumes reset_menu has been called before */ +static void show_menu(const char *prompt, const char *instructions, + int selected_index, int *last_top_row) +{ + int maxx, maxy; + WINDOW *menu_window; + + current_instructions = instructions; + + clear(); + (void) wattrset(main_window, attributes[NORMAL]); + print_in_middle(stdscr, 1, 0, getmaxx(stdscr), + menu_backtitle, + attributes[MAIN_HEADING]); + + (void) wattrset(main_window, attributes[MAIN_MENU_BOX]); + box(main_window, 0, 0); + (void) wattrset(main_window, attributes[MAIN_MENU_HEADING]); + mvwprintw(main_window, 0, 3, " %s ", prompt); + (void) wattrset(main_window, attributes[NORMAL]); + + set_menu_items(curses_menu, curses_menu_items); + + /* position the menu at the middle of the screen */ + scale_menu(curses_menu, &maxy, &maxx); + maxx = min(maxx, mwin_max_cols-2); + maxy = mwin_max_lines; + menu_window = derwin(main_window, + maxy, + maxx, + 2, + (mwin_max_cols-maxx)/2); + keypad(menu_window, TRUE); + set_menu_win(curses_menu, menu_window); + set_menu_sub(curses_menu, menu_window); + + /* must reassert this after changing items, otherwise returns to a + * default of 16 + */ + set_menu_format(curses_menu, maxy, 1); + center_item(selected_index, last_top_row); + set_menu_format(curses_menu, maxy, 1); + + print_function_line(); + + /* Post the menu */ + post_menu(curses_menu); + refresh_all_windows(main_window); +} + +static void adj_match_dir(match_f *match_direction) +{ + if (*match_direction == FIND_NEXT_MATCH_DOWN) + *match_direction = + MATCH_TINKER_PATTERN_DOWN; + else if (*match_direction == FIND_NEXT_MATCH_UP) + *match_direction = + MATCH_TINKER_PATTERN_UP; + /* else, do no change.. */ +} + +struct match_state +{ + int in_search; + match_f match_direction; + char pattern[256]; +}; + +/* Return 0 means I have handled the key. In such a case, ans should hold the + * item to center, or -1 otherwise. + * Else return -1 . + */ +static int do_match(int key, struct match_state *state, int *ans) +{ + char c = (char) key; + int terminate_search = 0; + *ans = -1; + if (key == '/' || (state->in_search && key == 27)) { + move(0, 0); + refresh(); + clrtoeol(); + state->in_search = 1-state->in_search; + bzero(state->pattern, sizeof(state->pattern)); + state->match_direction = MATCH_TINKER_PATTERN_DOWN; + return 0; + } else if (!state->in_search) + return 1; + + if (isalnum(c) || isgraph(c) || c == ' ') { + state->pattern[strlen(state->pattern)] = c; + state->pattern[strlen(state->pattern)] = '\0'; + adj_match_dir(&state->match_direction); + *ans = get_mext_match(state->pattern, + state->match_direction); + } else if (key == KEY_DOWN) { + state->match_direction = FIND_NEXT_MATCH_DOWN; + *ans = get_mext_match(state->pattern, + state->match_direction); + } else if (key == KEY_UP) { + state->match_direction = FIND_NEXT_MATCH_UP; + *ans = get_mext_match(state->pattern, + state->match_direction); + } else if (key == KEY_BACKSPACE || key == 127) { + state->pattern[strlen(state->pattern)-1] = '\0'; + adj_match_dir(&state->match_direction); + } else + terminate_search = 1; + + if (terminate_search) { + state->in_search = 0; + bzero(state->pattern, sizeof(state->pattern)); + move(0, 0); + refresh(); + clrtoeol(); + return -1; + } + return 0; +} + +static void conf(struct menu *menu) +{ + struct menu *submenu = 0; + const char *prompt = menu_get_prompt(menu); + struct symbol *sym; + int res; + int current_index = 0; + int last_top_row = 0; + struct match_state match_state = { + .in_search = 0, + .match_direction = MATCH_TINKER_PATTERN_DOWN, + .pattern = "", + }; + + while (!global_exit) { + reset_menu(); + current_menu = menu; + build_conf(menu); + if (!child_count) + break; + + show_menu(prompt ? _(prompt) : _("Main Menu"), + _(menu_instructions), + current_index, &last_top_row); + keypad((menu_win(curses_menu)), TRUE); + while (!global_exit) { + if (match_state.in_search) { + mvprintw(0, 0, + "searching: %s", match_state.pattern); + clrtoeol(); + } + refresh_all_windows(main_window); + res = wgetch(menu_win(curses_menu)); + if (!res) + break; + if (do_match(res, &match_state, ¤t_index) == 0) { + if (current_index != -1) + center_item(current_index, + &last_top_row); + continue; + } + if (process_special_keys(&res, + (struct menu *) item_data())) + break; + switch (res) { + case KEY_DOWN: + menu_driver(curses_menu, REQ_DOWN_ITEM); + break; + case KEY_UP: + menu_driver(curses_menu, REQ_UP_ITEM); + break; + case KEY_NPAGE: + menu_driver(curses_menu, REQ_SCR_DPAGE); + break; + case KEY_PPAGE: + menu_driver(curses_menu, REQ_SCR_UPAGE); + break; + case KEY_HOME: + menu_driver(curses_menu, REQ_FIRST_ITEM); + break; + case KEY_END: + menu_driver(curses_menu, REQ_LAST_ITEM); + break; + case 'h': + case '?': + show_help((struct menu *) item_data()); + break; + } + if (res == 10 || res == 27 || + res == 32 || res == 'n' || res == 'y' || + res == KEY_LEFT || res == KEY_RIGHT || + res == 'm') + break; + refresh_all_windows(main_window); + } + + refresh_all_windows(main_window); + /* if ESC or left*/ + if (res == 27 || (menu != &rootmenu && res == KEY_LEFT)) + break; + + /* remember location in the menu */ + last_top_row = top_row(curses_menu); + current_index = curses_item_index(); + + if (!item_tag()) + continue; + + submenu = (struct menu *) item_data(); + if (!submenu || !menu_is_visible(submenu)) + continue; + sym = submenu->sym; + + switch (res) { + case ' ': + if (item_is_tag('t')) + sym_toggle_tristate_value(sym); + else if (item_is_tag('m')) + conf(submenu); + break; + case KEY_RIGHT: + case 10: /* ENTER WAS PRESSED */ + switch (item_tag()) { + case 'm': + if (single_menu_mode) + submenu->data = + (void *) (long) !submenu->data; + else + conf(submenu); + break; + case 't': + if (sym_is_choice(sym) && + sym_get_tristate_value(sym) == yes) + conf_choice(submenu); + else if (submenu->prompt && + submenu->prompt->type == P_MENU) + conf(submenu); + else if (res == 10) + sym_toggle_tristate_value(sym); + break; + case 's': + conf_string(submenu); + break; + } + break; + case 'y': + if (item_is_tag('t')) { + if (sym_set_tristate_value(sym, yes)) + break; + if (sym_set_tristate_value(sym, mod)) + btn_dialog(main_window, setmod_text, 0); + } + break; + case 'n': + if (item_is_tag('t')) + sym_set_tristate_value(sym, no); + break; + case 'm': + if (item_is_tag('t')) + sym_set_tristate_value(sym, mod); + break; + } + } +} + +static void conf_message_callback(const char *fmt, va_list ap) +{ + char buf[1024]; + + vsnprintf(buf, sizeof(buf), fmt, ap); + btn_dialog(main_window, buf, 1, ""); +} + +static void show_help(struct menu *menu) +{ + struct gstr help; + + if (!menu) + return; + + help = str_new(); + menu_get_ext_help(menu, &help); + show_scroll_win(main_window, _(menu_get_prompt(menu)), str_get(&help)); + str_free(&help); +} + +static void conf_choice(struct menu *menu) +{ + const char *prompt = _(menu_get_prompt(menu)); + struct menu *child = 0; + struct symbol *active; + int selected_index = 0; + int last_top_row = 0; + int res, i = 0; + struct match_state match_state = { + .in_search = 0, + .match_direction = MATCH_TINKER_PATTERN_DOWN, + .pattern = "", + }; + + active = sym_get_choice_value(menu->sym); + /* this is mostly duplicated from the conf() function. */ + while (!global_exit) { + reset_menu(); + + for (i = 0, child = menu->list; child; child = child->next) { + if (!show_all_items && !menu_is_visible(child)) + continue; + + if (child->sym == sym_get_choice_value(menu->sym)) + item_make(child, ':', " %s", + _(menu_get_prompt(child))); + else if (child->sym) + item_make(child, ':', " %s", + _(menu_get_prompt(child))); + else + item_make(child, ':', "*** %s ***", + _(menu_get_prompt(child))); + + if (child->sym == active){ + last_top_row = top_row(curses_menu); + selected_index = i; + } + i++; + } + show_menu(prompt ? _(prompt) : _("Choice Menu"), + _(radiolist_instructions), + selected_index, + &last_top_row); + while (!global_exit) { + if (match_state.in_search) { + mvprintw(0, 0, "searching: %s", + match_state.pattern); + clrtoeol(); + } + refresh_all_windows(main_window); + res = wgetch(menu_win(curses_menu)); + if (!res) + break; + if (do_match(res, &match_state, &selected_index) == 0) { + if (selected_index != -1) + center_item(selected_index, + &last_top_row); + continue; + } + if (process_special_keys( + &res, + (struct menu *) item_data())) + break; + switch (res) { + case KEY_DOWN: + menu_driver(curses_menu, REQ_DOWN_ITEM); + break; + case KEY_UP: + menu_driver(curses_menu, REQ_UP_ITEM); + break; + case KEY_NPAGE: + menu_driver(curses_menu, REQ_SCR_DPAGE); + break; + case KEY_PPAGE: + menu_driver(curses_menu, REQ_SCR_UPAGE); + break; + case KEY_HOME: + menu_driver(curses_menu, REQ_FIRST_ITEM); + break; + case KEY_END: + menu_driver(curses_menu, REQ_LAST_ITEM); + break; + case 'h': + case '?': + show_help((struct menu *) item_data()); + break; + } + if (res == 10 || res == 27 || res == ' ' || + res == KEY_LEFT){ + break; + } + refresh_all_windows(main_window); + } + /* if ESC or left */ + if (res == 27 || res == KEY_LEFT) + break; + + child = item_data(); + if (!child || !menu_is_visible(child) || !child->sym) + continue; + switch (res) { + case ' ': + case 10: + case KEY_RIGHT: + sym_set_tristate_value(child->sym, yes); + return; + case 'h': + case '?': + show_help(child); + active = child->sym; + break; + case KEY_EXIT: + return; + } + } +} + +static void conf_string(struct menu *menu) +{ + const char *prompt = menu_get_prompt(menu); + + while (1) { + int res; + const char *heading; + + switch (sym_get_type(menu->sym)) { + case S_INT: + heading = _(inputbox_instructions_int); + break; + case S_HEX: + heading = _(inputbox_instructions_hex); + break; + case S_STRING: + heading = _(inputbox_instructions_string); + break; + default: + heading = _("Internal nconf error!"); + } + res = dialog_inputbox(main_window, + prompt ? _(prompt) : _("Main Menu"), + heading, + sym_get_string_value(menu->sym), + &dialog_input_result, + &dialog_input_result_len); + switch (res) { + case 0: + if (sym_set_string_value(menu->sym, + dialog_input_result)) + return; + btn_dialog(main_window, + _("You have made an invalid entry."), 0); + break; + case 1: + show_help(menu); + break; + case KEY_EXIT: + return; + } + } +} + +static void conf_load(void) +{ + while (1) { + int res; + res = dialog_inputbox(main_window, + NULL, load_config_text, + filename, + &dialog_input_result, + &dialog_input_result_len); + switch (res) { + case 0: + if (!dialog_input_result[0]) + return; + if (!conf_read(dialog_input_result)) { + set_config_filename(dialog_input_result); + sym_set_change_count(1); + return; + } + btn_dialog(main_window, _("File does not exist!"), 0); + break; + case 1: + show_scroll_win(main_window, + _("Load Alternate Configuration"), + load_config_help); + break; + case KEY_EXIT: + return; + } + } +} + +static void conf_save(void) +{ + while (1) { + int res; + res = dialog_inputbox(main_window, + NULL, save_config_text, + filename, + &dialog_input_result, + &dialog_input_result_len); + switch (res) { + case 0: + if (!dialog_input_result[0]) + return; + res = conf_write(dialog_input_result); + if (!res) { + set_config_filename(dialog_input_result); + return; + } + btn_dialog(main_window, _("Can't create file! " + "Probably a nonexistent directory."), + 1, ""); + break; + case 1: + show_scroll_win(main_window, + _("Save Alternate Configuration"), + save_config_help); + break; + case KEY_EXIT: + return; + } + } +} + +void setup_windows(void) +{ + int lines, columns; + + getmaxyx(stdscr, lines, columns); + + if (main_window != NULL) + delwin(main_window); + + /* set up the menu and menu window */ + main_window = newwin(lines-2, columns-2, 2, 1); + keypad(main_window, TRUE); + mwin_max_lines = lines-7; + mwin_max_cols = columns-6; + + /* panels order is from bottom to top */ + new_panel(main_window); +} + +int main(int ac, char **av) +{ + int lines, columns; + char *mode; + + setlocale(LC_ALL, ""); + bindtextdomain(PACKAGE, LOCALEDIR); + textdomain(PACKAGE); + + if (ac > 1 && strcmp(av[1], "-s") == 0) { + /* Silence conf_read() until the real callback is set up */ + conf_set_message_callback(NULL); + av++; + } + conf_parse(av[1]); + conf_read(NULL); + + mode = getenv("NCONFIG_MODE"); + if (mode) { + if (!strcasecmp(mode, "single_menu")) + single_menu_mode = 1; + } + + /* Initialize curses */ + initscr(); + /* set color theme */ + set_colors(); + + cbreak(); + noecho(); + keypad(stdscr, TRUE); + curs_set(0); + + getmaxyx(stdscr, lines, columns); + if (columns < 75 || lines < 20) { + endwin(); + printf("Your terminal should have at " + "least 20 lines and 75 columns\n"); + return 1; + } + + notimeout(stdscr, FALSE); +#if NCURSES_REENTRANT + set_escdelay(1); +#else + ESCDELAY = 1; +#endif + + /* set btns menu */ + curses_menu = new_menu(curses_menu_items); + menu_opts_off(curses_menu, O_SHOWDESC); + menu_opts_on(curses_menu, O_SHOWMATCH); + menu_opts_on(curses_menu, O_ONEVALUE); + menu_opts_on(curses_menu, O_NONCYCLIC); + menu_opts_on(curses_menu, O_IGNORECASE); + set_menu_mark(curses_menu, " "); + set_menu_fore(curses_menu, attributes[MAIN_MENU_FORE]); + set_menu_back(curses_menu, attributes[MAIN_MENU_BACK]); + set_menu_grey(curses_menu, attributes[MAIN_MENU_GREY]); + + set_config_filename(conf_get_configname()); + setup_windows(); + + /* check for KEY_FUNC(1) */ + if (has_key(KEY_F(1)) == FALSE) { + show_scroll_win(main_window, + _("Instructions"), + _(menu_no_f_instructions)); + } + + conf_set_message_callback(conf_message_callback); + /* do the work */ + while (!global_exit) { + conf(&rootmenu); + if (!global_exit && do_exit() == 0) + break; + } + /* ok, we are done */ + unpost_menu(curses_menu); + free_menu(curses_menu); + delwin(main_window); + clear(); + refresh(); + endwin(); + return 0; +} diff --git a/tools/kconfig/nconf.gui.c b/tools/kconfig/nconf.gui.c new file mode 100644 index 0000000000..8275f0e551 --- /dev/null +++ b/tools/kconfig/nconf.gui.c @@ -0,0 +1,656 @@ +/* + * Copyright (C) 2008 Nir Tzachar 0) + win_rows = msg_lines+4; + else + win_rows = msg_lines+2; + + win = newwin(win_rows, total_width+4, y, x); + keypad(win, TRUE); + menu_win = derwin(win, 1, btns_width, win_rows-2, + 1+(total_width+2-btns_width)/2); + menu = new_menu(btns); + msg_win = derwin(win, win_rows-2, msg_width, 1, + 1+(total_width+2-msg_width)/2); + + set_menu_fore(menu, attributes[DIALOG_MENU_FORE]); + set_menu_back(menu, attributes[DIALOG_MENU_BACK]); + + (void) wattrset(win, attributes[DIALOG_BOX]); + box(win, 0, 0); + + /* print message */ + (void) wattrset(msg_win, attributes[DIALOG_TEXT]); + fill_window(msg_win, msg); + + set_menu_win(menu, win); + set_menu_sub(menu, menu_win); + set_menu_format(menu, 1, btn_num); + menu_opts_off(menu, O_SHOWDESC); + menu_opts_off(menu, O_SHOWMATCH); + menu_opts_on(menu, O_ONEVALUE); + menu_opts_on(menu, O_NONCYCLIC); + set_menu_mark(menu, ""); + post_menu(menu); + + + touchwin(win); + refresh_all_windows(main_window); + while ((res = wgetch(win))) { + switch (res) { + case KEY_LEFT: + menu_driver(menu, REQ_LEFT_ITEM); + break; + case KEY_RIGHT: + menu_driver(menu, REQ_RIGHT_ITEM); + break; + case 10: /* ENTER */ + case 27: /* ESCAPE */ + case ' ': + case KEY_F(F_BACK): + case KEY_F(F_EXIT): + break; + } + touchwin(win); + refresh_all_windows(main_window); + + if (res == 10 || res == ' ') { + res = item_index(current_item(menu)); + break; + } else if (res == 27 || res == KEY_F(F_BACK) || + res == KEY_F(F_EXIT)) { + res = KEY_EXIT; + break; + } + } + + unpost_menu(menu); + free_menu(menu); + for (i = 0; i < btn_num; i++) + free_item(btns[i]); + + delwin(win); + return res; +} + +int dialog_inputbox(WINDOW *main_window, + const char *title, const char *prompt, + const char *init, char **resultp, int *result_len) +{ + int prompt_lines = 0; + int prompt_width = 0; + WINDOW *win; + WINDOW *prompt_win; + WINDOW *form_win; + PANEL *panel; + int i, x, y; + int res = -1; + int cursor_position = strlen(init); + int cursor_form_win; + char *result = *resultp; + + if (strlen(init)+1 > *result_len) { + *result_len = strlen(init)+1; + *resultp = result = realloc(result, *result_len); + } + + /* find the widest line of msg: */ + prompt_lines = get_line_no(prompt); + for (i = 0; i < prompt_lines; i++) { + const char *line = get_line(prompt, i); + int len = get_line_length(line); + prompt_width = max(prompt_width, len); + } + + if (title) + prompt_width = max(prompt_width, strlen(title)); + + /* place dialog in middle of screen */ + y = (getmaxy(stdscr)-(prompt_lines+4))/2; + x = (getmaxx(stdscr)-(prompt_width+4))/2; + + strncpy(result, init, *result_len); + + /* create the windows */ + win = newwin(prompt_lines+6, prompt_width+7, y, x); + prompt_win = derwin(win, prompt_lines+1, prompt_width, 2, 2); + form_win = derwin(win, 1, prompt_width, prompt_lines+3, 2); + keypad(form_win, TRUE); + + (void) wattrset(form_win, attributes[INPUT_FIELD]); + + (void) wattrset(win, attributes[INPUT_BOX]); + box(win, 0, 0); + (void) wattrset(win, attributes[INPUT_HEADING]); + if (title) + mvwprintw(win, 0, 3, "%s", title); + + /* print message */ + (void) wattrset(prompt_win, attributes[INPUT_TEXT]); + fill_window(prompt_win, prompt); + + mvwprintw(form_win, 0, 0, "%*s", prompt_width, " "); + cursor_form_win = min(cursor_position, prompt_width-1); + mvwprintw(form_win, 0, 0, "%s", + result + cursor_position-cursor_form_win); + + /* create panels */ + panel = new_panel(win); + + /* show the cursor */ + curs_set(1); + + touchwin(win); + refresh_all_windows(main_window); + while ((res = wgetch(form_win))) { + int len = strlen(result); + switch (res) { + case 10: /* ENTER */ + case 27: /* ESCAPE */ + case KEY_F(F_HELP): + case KEY_F(F_EXIT): + case KEY_F(F_BACK): + break; + case 127: + case KEY_BACKSPACE: + if (cursor_position > 0) { + memmove(&result[cursor_position-1], + &result[cursor_position], + len-cursor_position+1); + cursor_position--; + cursor_form_win--; + len--; + } + break; + case KEY_DC: + if (cursor_position >= 0 && cursor_position < len) { + memmove(&result[cursor_position], + &result[cursor_position+1], + len-cursor_position+1); + len--; + } + break; + case KEY_UP: + case KEY_RIGHT: + if (cursor_position < len) { + cursor_position++; + cursor_form_win++; + } + break; + case KEY_DOWN: + case KEY_LEFT: + if (cursor_position > 0) { + cursor_position--; + cursor_form_win--; + } + break; + case KEY_HOME: + cursor_position = 0; + cursor_form_win = 0; + break; + case KEY_END: + cursor_position = len; + cursor_form_win = min(cursor_position, prompt_width-1); + break; + default: + if ((isgraph(res) || isspace(res))) { + /* one for new char, one for '\0' */ + if (len+2 > *result_len) { + *result_len = len+2; + *resultp = result = realloc(result, + *result_len); + } + /* insert the char at the proper position */ + memmove(&result[cursor_position+1], + &result[cursor_position], + len-cursor_position+1); + result[cursor_position] = res; + cursor_position++; + cursor_form_win++; + len++; + } else { + mvprintw(0, 0, "unknown key: %d\n", res); + } + break; + } + if (cursor_form_win < 0) + cursor_form_win = 0; + else if (cursor_form_win > prompt_width-1) + cursor_form_win = prompt_width-1; + + wmove(form_win, 0, 0); + wclrtoeol(form_win); + mvwprintw(form_win, 0, 0, "%*s", prompt_width, " "); + mvwprintw(form_win, 0, 0, "%s", + result + cursor_position-cursor_form_win); + wmove(form_win, 0, cursor_form_win); + touchwin(win); + refresh_all_windows(main_window); + + if (res == 10) { + res = 0; + break; + } else if (res == 27 || res == KEY_F(F_BACK) || + res == KEY_F(F_EXIT)) { + res = KEY_EXIT; + break; + } else if (res == KEY_F(F_HELP)) { + res = 1; + break; + } + } + + /* hide the cursor */ + curs_set(0); + del_panel(panel); + delwin(prompt_win); + delwin(form_win); + delwin(win); + return res; +} + +/* refresh all windows in the correct order */ +void refresh_all_windows(WINDOW *main_window) +{ + update_panels(); + touchwin(main_window); + refresh(); +} + +/* layman's scrollable window... */ +void show_scroll_win(WINDOW *main_window, + const char *title, + const char *text) +{ + int res; + int total_lines = get_line_no(text); + int x, y, lines, columns; + int start_x = 0, start_y = 0; + int text_lines = 0, text_cols = 0; + int total_cols = 0; + int win_cols = 0; + int win_lines = 0; + int i = 0; + WINDOW *win; + WINDOW *pad; + PANEL *panel; + + getmaxyx(stdscr, lines, columns); + + /* find the widest line of msg: */ + total_lines = get_line_no(text); + for (i = 0; i < total_lines; i++) { + const char *line = get_line(text, i); + int len = get_line_length(line); + total_cols = max(total_cols, len+2); + } + + /* create the pad */ + pad = newpad(total_lines+10, total_cols+10); + (void) wattrset(pad, attributes[SCROLLWIN_TEXT]); + fill_window(pad, text); + + win_lines = min(total_lines+4, lines-2); + win_cols = min(total_cols+2, columns-2); + text_lines = max(win_lines-4, 0); + text_cols = max(win_cols-2, 0); + + /* place window in middle of screen */ + y = (lines-win_lines)/2; + x = (columns-win_cols)/2; + + win = newwin(win_lines, win_cols, y, x); + keypad(win, TRUE); + /* show the help in the help window, and show the help panel */ + (void) wattrset(win, attributes[SCROLLWIN_BOX]); + box(win, 0, 0); + (void) wattrset(win, attributes[SCROLLWIN_HEADING]); + mvwprintw(win, 0, 3, " %s ", title); + panel = new_panel(win); + + /* handle scrolling */ + do { + + copywin(pad, win, start_y, start_x, 2, 2, text_lines, + text_cols, 0); + print_in_middle(win, + text_lines+2, + 0, + text_cols, + "", + attributes[DIALOG_MENU_FORE]); + wrefresh(win); + + res = wgetch(win); + switch (res) { + case KEY_NPAGE: + case ' ': + case 'd': + start_y += text_lines-2; + break; + case KEY_PPAGE: + case 'u': + start_y -= text_lines+2; + break; + case KEY_HOME: + start_y = 0; + break; + case KEY_END: + start_y = total_lines-text_lines; + break; + case KEY_DOWN: + case 'j': + start_y++; + break; + case KEY_UP: + case 'k': + start_y--; + break; + case KEY_LEFT: + case 'h': + start_x--; + break; + case KEY_RIGHT: + case 'l': + start_x++; + break; + } + if (res == 10 || res == 27 || res == 'q' || + res == KEY_F(F_HELP) || res == KEY_F(F_BACK) || + res == KEY_F(F_EXIT)) + break; + if (start_y < 0) + start_y = 0; + if (start_y >= total_lines-text_lines) + start_y = total_lines-text_lines; + if (start_x < 0) + start_x = 0; + if (start_x >= total_cols-text_cols) + start_x = total_cols-text_cols; + } while (res); + + del_panel(panel); + delwin(win); + refresh_all_windows(main_window); +} diff --git a/tools/kconfig/nconf.h b/tools/kconfig/nconf.h new file mode 100644 index 0000000000..0d5261705e --- /dev/null +++ b/tools/kconfig/nconf.h @@ -0,0 +1,96 @@ +/* + * Copyright (C) 2008 Nir Tzachar +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include "ncurses.h" + +#define max(a, b) ({\ + typeof(a) _a = a;\ + typeof(b) _b = b;\ + _a > _b ? _a : _b; }) + +#define min(a, b) ({\ + typeof(a) _a = a;\ + typeof(b) _b = b;\ + _a < _b ? _a : _b; }) + +typedef enum { + NORMAL = 1, + MAIN_HEADING, + MAIN_MENU_BOX, + MAIN_MENU_FORE, + MAIN_MENU_BACK, + MAIN_MENU_GREY, + MAIN_MENU_HEADING, + SCROLLWIN_TEXT, + SCROLLWIN_HEADING, + SCROLLWIN_BOX, + DIALOG_TEXT, + DIALOG_MENU_FORE, + DIALOG_MENU_BACK, + DIALOG_BOX, + INPUT_BOX, + INPUT_HEADING, + INPUT_TEXT, + INPUT_FIELD, + FUNCTION_TEXT, + FUNCTION_HIGHLIGHT, + ATTR_MAX +} attributes_t; +extern attributes_t attributes[]; + +typedef enum { + F_HELP = 1, + F_SYMBOL = 2, + F_INSTS = 3, + F_CONF = 4, + F_BACK = 5, + F_SAVE = 6, + F_LOAD = 7, + F_SEARCH = 8, + F_EXIT = 9, +} function_key; + +void set_colors(void); + +/* this changes the windows attributes !!! */ +void print_in_middle(WINDOW *win, + int starty, + int startx, + int width, + const char *string, + chtype color); +int get_line_length(const char *line); +int get_line_no(const char *text); +const char *get_line(const char *text, int line_no); +void fill_window(WINDOW *win, const char *text); +int btn_dialog(WINDOW *main_window, const char *msg, int btn_num, ...); +int dialog_inputbox(WINDOW *main_window, + const char *title, const char *prompt, + const char *init, char **resultp, int *result_len); +void refresh_all_windows(WINDOW *main_window); +void show_scroll_win(WINDOW *main_window, + const char *title, + const char *text); diff --git a/tools/kconfig/qconf.cc b/tools/kconfig/qconf.cc new file mode 100644 index 0000000000..fc55559922 --- /dev/null +++ b/tools/kconfig/qconf.cc @@ -0,0 +1,1870 @@ +/* + * Copyright (C) 2002 Roman Zippel + * Copyright (C) 2015 Boris Barbulovski + * Released under the terms of the GNU GPL v2.0. + */ + +#include + +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include "lkc.h" +#include "qconf.h" + +#include "qconf.moc" +#include "images.c" + +#ifdef _ +# undef _ +# define _ qgettext +#endif + +static QApplication *configApp; +static ConfigSettings *configSettings; + +QAction *ConfigMainWindow::saveAction; + +static inline QString qgettext(const char* str) +{ + return QString::fromLocal8Bit(gettext(str)); +} + +static inline QString qgettext(const QString& str) +{ + return QString::fromLocal8Bit(gettext(str.toLatin1())); +} + +ConfigSettings::ConfigSettings() + : QSettings("kernel.org", "qconf") +{ +} + +/** + * Reads a list of integer values from the application settings. + */ +QList ConfigSettings::readSizes(const QString& key, bool *ok) +{ + QList result; + QStringList entryList = value(key).toStringList(); + QStringList::Iterator it; + + for (it = entryList.begin(); it != entryList.end(); ++it) + result.push_back((*it).toInt()); + + return result; +} + +/** + * Writes a list of integer values to the application settings. + */ +bool ConfigSettings::writeSizes(const QString& key, const QList& value) +{ + QStringList stringList; + QList::ConstIterator it; + + for (it = value.begin(); it != value.end(); ++it) + stringList.push_back(QString::number(*it)); + setValue(key, stringList); + + return true; +} + + +/* + * set the new data + * TODO check the value + */ +void ConfigItem::okRename(int col) +{ +} + +/* + * update the displayed of a menu entry + */ +void ConfigItem::updateMenu(void) +{ + ConfigList* list; + struct symbol* sym; + struct property *prop; + QString prompt; + int type; + tristate expr; + + list = listView(); + if (goParent) { + setPixmap(promptColIdx, list->menuBackPix); + prompt = ".."; + goto set_prompt; + } + + sym = menu->sym; + prop = menu->prompt; + prompt = _(menu_get_prompt(menu)); + + if (prop) switch (prop->type) { + case P_MENU: + if (list->mode == singleMode || list->mode == symbolMode) { + /* a menuconfig entry is displayed differently + * depending whether it's at the view root or a child. + */ + if (sym && list->rootEntry == menu) + break; + setPixmap(promptColIdx, list->menuPix); + } else { + if (sym) + break; + setPixmap(promptColIdx, QIcon()); + } + goto set_prompt; + case P_COMMENT: + setPixmap(promptColIdx, QIcon()); + goto set_prompt; + default: + ; + } + if (!sym) + goto set_prompt; + + setText(nameColIdx, QString::fromLocal8Bit(sym->name)); + + type = sym_get_type(sym); + switch (type) { + case S_BOOLEAN: + case S_TRISTATE: + char ch; + + if (!sym_is_changable(sym) && list->optMode == normalOpt) { + setPixmap(promptColIdx, QIcon()); + setText(noColIdx, QString::null); + setText(modColIdx, QString::null); + setText(yesColIdx, QString::null); + break; + } + expr = sym_get_tristate_value(sym); + switch (expr) { + case yes: + if (sym_is_choice_value(sym) && type == S_BOOLEAN) + setPixmap(promptColIdx, list->choiceYesPix); + else + setPixmap(promptColIdx, list->symbolYesPix); + setText(yesColIdx, "Y"); + ch = 'Y'; + break; + case mod: + setPixmap(promptColIdx, list->symbolModPix); + setText(modColIdx, "M"); + ch = 'M'; + break; + default: + if (sym_is_choice_value(sym) && type == S_BOOLEAN) + setPixmap(promptColIdx, list->choiceNoPix); + else + setPixmap(promptColIdx, list->symbolNoPix); + setText(noColIdx, "N"); + ch = 'N'; + break; + } + if (expr != no) + setText(noColIdx, sym_tristate_within_range(sym, no) ? "_" : 0); + if (expr != mod) + setText(modColIdx, sym_tristate_within_range(sym, mod) ? "_" : 0); + if (expr != yes) + setText(yesColIdx, sym_tristate_within_range(sym, yes) ? "_" : 0); + + setText(dataColIdx, QChar(ch)); + break; + case S_INT: + case S_HEX: + case S_STRING: + const char* data; + + data = sym_get_string_value(sym); + + setText(dataColIdx, data); + if (type == S_STRING) + prompt = QString("%1: %2").arg(prompt).arg(data); + else + prompt = QString("(%2) %1").arg(prompt).arg(data); + break; + } + if (!sym_has_value(sym) && visible) + prompt += _(" (NEW)"); +set_prompt: + setText(promptColIdx, prompt); +} + +void ConfigItem::testUpdateMenu(bool v) +{ + ConfigItem* i; + + visible = v; + if (!menu) + return; + + sym_calc_value(menu->sym); + if (menu->flags & MENU_CHANGED) { + /* the menu entry changed, so update all list items */ + menu->flags &= ~MENU_CHANGED; + for (i = (ConfigItem*)menu->data; i; i = i->nextItem) + i->updateMenu(); + } else if (listView()->updateAll) + updateMenu(); +} + + +/* + * construct a menu entry + */ +void ConfigItem::init(void) +{ + if (menu) { + ConfigList* list = listView(); + nextItem = (ConfigItem*)menu->data; + menu->data = this; + + if (list->mode != fullMode) + setExpanded(true); + sym_calc_value(menu->sym); + } + updateMenu(); +} + +/* + * destruct a menu entry + */ +ConfigItem::~ConfigItem(void) +{ + if (menu) { + ConfigItem** ip = (ConfigItem**)&menu->data; + for (; *ip; ip = &(*ip)->nextItem) { + if (*ip == this) { + *ip = nextItem; + break; + } + } + } +} + +ConfigLineEdit::ConfigLineEdit(ConfigView* parent) + : Parent(parent) +{ + connect(this, SIGNAL(editingFinished()), SLOT(hide())); +} + +void ConfigLineEdit::show(ConfigItem* i) +{ + item = i; + if (sym_get_string_value(item->menu->sym)) + setText(QString::fromLocal8Bit(sym_get_string_value(item->menu->sym))); + else + setText(QString::null); + Parent::show(); + setFocus(); +} + +void ConfigLineEdit::keyPressEvent(QKeyEvent* e) +{ + switch (e->key()) { + case Qt::Key_Escape: + break; + case Qt::Key_Return: + case Qt::Key_Enter: + sym_set_string_value(item->menu->sym, text().toLatin1()); + parent()->updateList(item); + break; + default: + Parent::keyPressEvent(e); + return; + } + e->accept(); + parent()->list->setFocus(); + hide(); +} + +ConfigList::ConfigList(ConfigView* p, const char *name) + : Parent(p), + updateAll(false), + symbolYesPix(xpm_symbol_yes), symbolModPix(xpm_symbol_mod), symbolNoPix(xpm_symbol_no), + choiceYesPix(xpm_choice_yes), choiceNoPix(xpm_choice_no), + menuPix(xpm_menu), menuInvPix(xpm_menu_inv), menuBackPix(xpm_menuback), voidPix(xpm_void), + showName(false), showRange(false), showData(false), mode(singleMode), optMode(normalOpt), + rootEntry(0), headerPopup(0) +{ + int i; + + setObjectName(name); + setSortingEnabled(false); + setRootIsDecorated(true); + + setVerticalScrollMode(ScrollPerPixel); + setHorizontalScrollMode(ScrollPerPixel); + + setHeaderLabels(QStringList() << _("Option") << _("Name") << "N" << "M" << "Y" << _("Value")); + + connect(this, SIGNAL(itemSelectionChanged(void)), + SLOT(updateSelection(void))); + + if (name) { + configSettings->beginGroup(name); + showName = configSettings->value("/showName", false).toBool(); + showRange = configSettings->value("/showRange", false).toBool(); + showData = configSettings->value("/showData", false).toBool(); + optMode = (enum optionMode)configSettings->value("/optionMode", 0).toInt(); + configSettings->endGroup(); + connect(configApp, SIGNAL(aboutToQuit()), SLOT(saveSettings())); + } + + addColumn(promptColIdx); + + reinit(); +} + +bool ConfigList::menuSkip(struct menu *menu) +{ + if (optMode == normalOpt && menu_is_visible(menu)) + return false; + if (optMode == promptOpt && menu_has_prompt(menu)) + return false; + if (optMode == allOpt) + return false; + return true; +} + +void ConfigList::reinit(void) +{ + removeColumn(dataColIdx); + removeColumn(yesColIdx); + removeColumn(modColIdx); + removeColumn(noColIdx); + removeColumn(nameColIdx); + + if (showName) + addColumn(nameColIdx); + if (showRange) { + addColumn(noColIdx); + addColumn(modColIdx); + addColumn(yesColIdx); + } + if (showData) + addColumn(dataColIdx); + + updateListAll(); +} + +void ConfigList::saveSettings(void) +{ + if (!objectName().isEmpty()) { + configSettings->beginGroup(objectName()); + configSettings->setValue("/showName", showName); + configSettings->setValue("/showRange", showRange); + configSettings->setValue("/showData", showData); + configSettings->setValue("/optionMode", (int)optMode); + configSettings->endGroup(); + } +} + +ConfigItem* ConfigList::findConfigItem(struct menu *menu) +{ + ConfigItem* item = (ConfigItem*)menu->data; + + for (; item; item = item->nextItem) { + if (this == item->listView()) + break; + } + + return item; +} + +void ConfigList::updateSelection(void) +{ + struct menu *menu; + enum prop_type type; + + if (selectedItems().count() == 0) + return; + + ConfigItem* item = (ConfigItem*)selectedItems().first(); + if (!item) + return; + + menu = item->menu; + emit menuChanged(menu); + if (!menu) + return; + type = menu->prompt ? menu->prompt->type : P_UNKNOWN; + if (mode == menuMode && type == P_MENU) + emit menuSelected(menu); +} + +void ConfigList::updateList(ConfigItem* item) +{ + ConfigItem* last = 0; + + if (!rootEntry) { + if (mode != listMode) + goto update; + QTreeWidgetItemIterator it(this); + ConfigItem* item; + + while (*it) { + item = (ConfigItem*)(*it); + if (!item->menu) + continue; + item->testUpdateMenu(menu_is_visible(item->menu)); + + ++it; + } + return; + } + + if (rootEntry != &rootmenu && (mode == singleMode || + (mode == symbolMode && rootEntry->parent != &rootmenu))) { + item = (ConfigItem *)topLevelItem(0); + if (!item) + item = new ConfigItem(this, 0, true); + last = item; + } + if ((mode == singleMode || (mode == symbolMode && !(rootEntry->flags & MENU_ROOT))) && + rootEntry->sym && rootEntry->prompt) { + item = last ? last->nextSibling() : firstChild(); + if (!item) + item = new ConfigItem(this, last, rootEntry, true); + else + item->testUpdateMenu(true); + + updateMenuList(item, rootEntry); + update(); + resizeColumnToContents(0); + return; + } +update: + updateMenuList(this, rootEntry); + update(); + resizeColumnToContents(0); +} + +void ConfigList::setValue(ConfigItem* item, tristate val) +{ + struct symbol* sym; + int type; + tristate oldval; + + sym = item->menu ? item->menu->sym : 0; + if (!sym) + return; + + type = sym_get_type(sym); + switch (type) { + case S_BOOLEAN: + case S_TRISTATE: + oldval = sym_get_tristate_value(sym); + + if (!sym_set_tristate_value(sym, val)) + return; + if (oldval == no && item->menu->list) + item->setExpanded(true); + parent()->updateList(item); + break; + } +} + +void ConfigList::changeValue(ConfigItem* item) +{ + struct symbol* sym; + struct menu* menu; + int type, oldexpr, newexpr; + + menu = item->menu; + if (!menu) + return; + sym = menu->sym; + if (!sym) { + if (item->menu->list) + item->setExpanded(!item->isExpanded()); + return; + } + + type = sym_get_type(sym); + switch (type) { + case S_BOOLEAN: + case S_TRISTATE: + oldexpr = sym_get_tristate_value(sym); + newexpr = sym_toggle_tristate_value(sym); + if (item->menu->list) { + if (oldexpr == newexpr) + item->setExpanded(!item->isExpanded()); + else if (oldexpr == no) + item->setExpanded(true); + } + if (oldexpr != newexpr) + parent()->updateList(item); + break; + case S_INT: + case S_HEX: + case S_STRING: + parent()->lineEdit->show(item); + break; + } +} + +void ConfigList::setRootMenu(struct menu *menu) +{ + enum prop_type type; + + if (rootEntry == menu) + return; + type = menu && menu->prompt ? menu->prompt->type : P_UNKNOWN; + if (type != P_MENU) + return; + updateMenuList(this, 0); + rootEntry = menu; + updateListAll(); + if (currentItem()) { + currentItem()->setSelected(hasFocus()); + scrollToItem(currentItem()); + } +} + +void ConfigList::setParentMenu(void) +{ + ConfigItem* item; + struct menu *oldroot; + + oldroot = rootEntry; + if (rootEntry == &rootmenu) + return; + setRootMenu(menu_get_parent_menu(rootEntry->parent)); + + QTreeWidgetItemIterator it(this); + while (*it) { + item = (ConfigItem *)(*it); + if (item->menu == oldroot) { + setCurrentItem(item); + scrollToItem(item); + break; + } + + ++it; + } +} + +/* + * update all the children of a menu entry + * removes/adds the entries from the parent widget as necessary + * + * parent: either the menu list widget or a menu entry widget + * menu: entry to be updated + */ +void ConfigList::updateMenuList(ConfigItem *parent, struct menu* menu) +{ + struct menu* child; + ConfigItem* item; + ConfigItem* last; + bool visible; + enum prop_type type; + + if (!menu) { + while (parent->childCount() > 0) + { + delete parent->takeChild(0); + } + + return; + } + + last = parent->firstChild(); + if (last && !last->goParent) + last = 0; + for (child = menu->list; child; child = child->next) { + item = last ? last->nextSibling() : parent->firstChild(); + type = child->prompt ? child->prompt->type : P_UNKNOWN; + + switch (mode) { + case menuMode: + if (!(child->flags & MENU_ROOT)) + goto hide; + break; + case symbolMode: + if (child->flags & MENU_ROOT) + goto hide; + break; + default: + break; + } + + visible = menu_is_visible(child); + if (!menuSkip(child)) { + if (!child->sym && !child->list && !child->prompt) + continue; + if (!item || item->menu != child) + item = new ConfigItem(parent, last, child, visible); + else + item->testUpdateMenu(visible); + + if (mode == fullMode || mode == menuMode || type != P_MENU) + updateMenuList(item, child); + else + updateMenuList(item, 0); + last = item; + continue; + } + hide: + if (item && item->menu == child) { + last = parent->firstChild(); + if (last == item) + last = 0; + else while (last->nextSibling() != item) + last = last->nextSibling(); + delete item; + } + } +} + +void ConfigList::updateMenuList(ConfigList *parent, struct menu* menu) +{ + struct menu* child; + ConfigItem* item; + ConfigItem* last; + bool visible; + enum prop_type type; + + if (!menu) { + while (parent->topLevelItemCount() > 0) + { + delete parent->takeTopLevelItem(0); + } + + return; + } + + last = (ConfigItem*)parent->topLevelItem(0); + if (last && !last->goParent) + last = 0; + for (child = menu->list; child; child = child->next) { + item = last ? last->nextSibling() : (ConfigItem*)parent->topLevelItem(0); + type = child->prompt ? child->prompt->type : P_UNKNOWN; + + switch (mode) { + case menuMode: + if (!(child->flags & MENU_ROOT)) + goto hide; + break; + case symbolMode: + if (child->flags & MENU_ROOT) + goto hide; + break; + default: + break; + } + + visible = menu_is_visible(child); + if (!menuSkip(child)) { + if (!child->sym && !child->list && !child->prompt) + continue; + if (!item || item->menu != child) + item = new ConfigItem(parent, last, child, visible); + else + item->testUpdateMenu(visible); + + if (mode == fullMode || mode == menuMode || type != P_MENU) + updateMenuList(item, child); + else + updateMenuList(item, 0); + last = item; + continue; + } + hide: + if (item && item->menu == child) { + last = (ConfigItem*)parent->topLevelItem(0); + if (last == item) + last = 0; + else while (last->nextSibling() != item) + last = last->nextSibling(); + delete item; + } + } +} + +void ConfigList::keyPressEvent(QKeyEvent* ev) +{ + QTreeWidgetItem* i = currentItem(); + ConfigItem* item; + struct menu *menu; + enum prop_type type; + + if (ev->key() == Qt::Key_Escape && mode != fullMode && mode != listMode) { + emit parentSelected(); + ev->accept(); + return; + } + + if (!i) { + Parent::keyPressEvent(ev); + return; + } + item = (ConfigItem*)i; + + switch (ev->key()) { + case Qt::Key_Return: + case Qt::Key_Enter: + if (item->goParent) { + emit parentSelected(); + break; + } + menu = item->menu; + if (!menu) + break; + type = menu->prompt ? menu->prompt->type : P_UNKNOWN; + if (type == P_MENU && rootEntry != menu && + mode != fullMode && mode != menuMode) { + emit menuSelected(menu); + break; + } + case Qt::Key_Space: + changeValue(item); + break; + case Qt::Key_N: + setValue(item, no); + break; + case Qt::Key_M: + setValue(item, mod); + break; + case Qt::Key_Y: + setValue(item, yes); + break; + default: + Parent::keyPressEvent(ev); + return; + } + ev->accept(); +} + +void ConfigList::mousePressEvent(QMouseEvent* e) +{ + //QPoint p(contentsToViewport(e->pos())); + //printf("contentsMousePressEvent: %d,%d\n", p.x(), p.y()); + Parent::mousePressEvent(e); +} + +void ConfigList::mouseReleaseEvent(QMouseEvent* e) +{ + QPoint p = e->pos(); + ConfigItem* item = (ConfigItem*)itemAt(p); + struct menu *menu; + enum prop_type ptype; + QIcon icon; + int idx, x; + + if (!item) + goto skip; + + menu = item->menu; + x = header()->offset() + p.x(); + idx = header()->logicalIndexAt(x); + switch (idx) { + case promptColIdx: + icon = item->pixmap(promptColIdx); + if (!icon.isNull()) { + int off = header()->sectionPosition(0) + visualRect(indexAt(p)).x() + 4; // 4 is Hardcoded image offset. There might be a way to do it properly. + if (x >= off && x < off + icon.availableSizes().first().width()) { + if (item->goParent) { + emit parentSelected(); + break; + } else if (!menu) + break; + ptype = menu->prompt ? menu->prompt->type : P_UNKNOWN; + if (ptype == P_MENU && rootEntry != menu && + mode != fullMode && mode != menuMode) + emit menuSelected(menu); + else + changeValue(item); + } + } + break; + case noColIdx: + setValue(item, no); + break; + case modColIdx: + setValue(item, mod); + break; + case yesColIdx: + setValue(item, yes); + break; + case dataColIdx: + changeValue(item); + break; + } + +skip: + //printf("contentsMouseReleaseEvent: %d,%d\n", p.x(), p.y()); + Parent::mouseReleaseEvent(e); +} + +void ConfigList::mouseMoveEvent(QMouseEvent* e) +{ + //QPoint p(contentsToViewport(e->pos())); + //printf("contentsMouseMoveEvent: %d,%d\n", p.x(), p.y()); + Parent::mouseMoveEvent(e); +} + +void ConfigList::mouseDoubleClickEvent(QMouseEvent* e) +{ + QPoint p = e->pos(); // TODO: Check if this works(was contentsToViewport). + ConfigItem* item = (ConfigItem*)itemAt(p); + struct menu *menu; + enum prop_type ptype; + + if (!item) + goto skip; + if (item->goParent) { + emit parentSelected(); + goto skip; + } + menu = item->menu; + if (!menu) + goto skip; + ptype = menu->prompt ? menu->prompt->type : P_UNKNOWN; + if (ptype == P_MENU && (mode == singleMode || mode == symbolMode)) + emit menuSelected(menu); + else if (menu->sym) + changeValue(item); + +skip: + //printf("contentsMouseDoubleClickEvent: %d,%d\n", p.x(), p.y()); + Parent::mouseDoubleClickEvent(e); +} + +void ConfigList::focusInEvent(QFocusEvent *e) +{ + struct menu *menu = NULL; + + Parent::focusInEvent(e); + + ConfigItem* item = (ConfigItem *)currentItem(); + if (item) { + item->setSelected(true); + menu = item->menu; + } + emit gotFocus(menu); +} + +void ConfigList::contextMenuEvent(QContextMenuEvent *e) +{ + if (e->y() <= header()->geometry().bottom()) { + if (!headerPopup) { + QAction *action; + + headerPopup = new QMenu(this); + action = new QAction(_("Show Name"), this); + action->setCheckable(true); + connect(action, SIGNAL(toggled(bool)), + parent(), SLOT(setShowName(bool))); + connect(parent(), SIGNAL(showNameChanged(bool)), + action, SLOT(setOn(bool))); + action->setChecked(showName); + headerPopup->addAction(action); + action = new QAction(_("Show Range"), this); + action->setCheckable(true); + connect(action, SIGNAL(toggled(bool)), + parent(), SLOT(setShowRange(bool))); + connect(parent(), SIGNAL(showRangeChanged(bool)), + action, SLOT(setOn(bool))); + action->setChecked(showRange); + headerPopup->addAction(action); + action = new QAction(_("Show Data"), this); + action->setCheckable(true); + connect(action, SIGNAL(toggled(bool)), + parent(), SLOT(setShowData(bool))); + connect(parent(), SIGNAL(showDataChanged(bool)), + action, SLOT(setOn(bool))); + action->setChecked(showData); + headerPopup->addAction(action); + } + headerPopup->exec(e->globalPos()); + e->accept(); + } else + e->ignore(); +} + +ConfigView*ConfigView::viewList; +QAction *ConfigView::showNormalAction; +QAction *ConfigView::showAllAction; +QAction *ConfigView::showPromptAction; + +ConfigView::ConfigView(QWidget* parent, const char *name) + : Parent(parent) +{ + setObjectName(name); + QVBoxLayout *verticalLayout = new QVBoxLayout(this); + verticalLayout->setContentsMargins(0, 0, 0, 0); + + list = new ConfigList(this); + verticalLayout->addWidget(list); + lineEdit = new ConfigLineEdit(this); + lineEdit->hide(); + verticalLayout->addWidget(lineEdit); + + this->nextView = viewList; + viewList = this; +} + +ConfigView::~ConfigView(void) +{ + ConfigView** vp; + + for (vp = &viewList; *vp; vp = &(*vp)->nextView) { + if (*vp == this) { + *vp = nextView; + break; + } + } +} + +void ConfigView::setOptionMode(QAction *act) +{ + if (act == showNormalAction) + list->optMode = normalOpt; + else if (act == showAllAction) + list->optMode = allOpt; + else + list->optMode = promptOpt; + + list->updateListAll(); +} + +void ConfigView::setShowName(bool b) +{ + if (list->showName != b) { + list->showName = b; + list->reinit(); + emit showNameChanged(b); + } +} + +void ConfigView::setShowRange(bool b) +{ + if (list->showRange != b) { + list->showRange = b; + list->reinit(); + emit showRangeChanged(b); + } +} + +void ConfigView::setShowData(bool b) +{ + if (list->showData != b) { + list->showData = b; + list->reinit(); + emit showDataChanged(b); + } +} + +void ConfigList::setAllOpen(bool open) +{ + QTreeWidgetItemIterator it(this); + + while (*it) { + (*it)->setExpanded(open); + + ++it; + } +} + +void ConfigView::updateList(ConfigItem* item) +{ + ConfigView* v; + + for (v = viewList; v; v = v->nextView) + v->list->updateList(item); +} + +void ConfigView::updateListAll(void) +{ + ConfigView* v; + + for (v = viewList; v; v = v->nextView) + v->list->updateListAll(); +} + +ConfigInfoView::ConfigInfoView(QWidget* parent, const char *name) + : Parent(parent), sym(0), _menu(0) +{ + setObjectName(name); + + + if (!objectName().isEmpty()) { + configSettings->beginGroup(objectName()); + _showDebug = configSettings->value("/showDebug", false).toBool(); + configSettings->endGroup(); + connect(configApp, SIGNAL(aboutToQuit()), SLOT(saveSettings())); + } +} + +void ConfigInfoView::saveSettings(void) +{ + if (!objectName().isEmpty()) { + configSettings->beginGroup(objectName()); + configSettings->setValue("/showDebug", showDebug()); + configSettings->endGroup(); + } +} + +void ConfigInfoView::setShowDebug(bool b) +{ + if (_showDebug != b) { + _showDebug = b; + if (_menu) + menuInfo(); + else if (sym) + symbolInfo(); + emit showDebugChanged(b); + } +} + +void ConfigInfoView::setInfo(struct menu *m) +{ + if (_menu == m) + return; + _menu = m; + sym = NULL; + if (!_menu) + clear(); + else + menuInfo(); +} + +void ConfigInfoView::symbolInfo(void) +{ + QString str; + + str += "Symbol: "; + str += print_filter(sym->name); + str += "

      value: "; + str += print_filter(sym_get_string_value(sym)); + str += "
      visibility: "; + str += sym->visible == yes ? "y" : sym->visible == mod ? "m" : "n"; + str += "
      "; + str += debug_info(sym); + + setText(str); +} + +void ConfigInfoView::menuInfo(void) +{ + struct symbol* sym; + QString head, debug, help; + + sym = _menu->sym; + if (sym) { + if (_menu->prompt) { + head += ""; + head += print_filter(_(_menu->prompt->text)); + head += ""; + if (sym->name) { + head += " ("; + if (showDebug()) + head += QString().sprintf("
      ", sym); + head += print_filter(sym->name); + if (showDebug()) + head += ""; + head += ")"; + } + } else if (sym->name) { + head += ""; + if (showDebug()) + head += QString().sprintf("", sym); + head += print_filter(sym->name); + if (showDebug()) + head += ""; + head += ""; + } + head += "

      "; + + if (showDebug()) + debug = debug_info(sym); + + struct gstr help_gstr = str_new(); + menu_get_ext_help(_menu, &help_gstr); + help = print_filter(str_get(&help_gstr)); + str_free(&help_gstr); + } else if (_menu->prompt) { + head += ""; + head += print_filter(_(_menu->prompt->text)); + head += "

      "; + if (showDebug()) { + if (_menu->prompt->visible.expr) { + debug += "  dep: "; + expr_print(_menu->prompt->visible.expr, expr_print_help, &debug, E_NONE); + debug += "

      "; + } + } + } + if (showDebug()) + debug += QString().sprintf("defined at %s:%d

      ", _menu->file->name, _menu->lineno); + + setText(head + debug + help); +} + +QString ConfigInfoView::debug_info(struct symbol *sym) +{ + QString debug; + + debug += "type: "; + debug += print_filter(sym_type_name(sym->type)); + if (sym_is_choice(sym)) + debug += " (choice)"; + debug += "
      "; + if (sym->rev_dep.expr) { + debug += "reverse dep: "; + expr_print(sym->rev_dep.expr, expr_print_help, &debug, E_NONE); + debug += "
      "; + } + for (struct property *prop = sym->prop; prop; prop = prop->next) { + switch (prop->type) { + case P_PROMPT: + case P_MENU: + debug += QString().sprintf("prompt: ", prop->menu); + debug += print_filter(_(prop->text)); + debug += "
      "; + break; + case P_DEFAULT: + case P_SELECT: + case P_RANGE: + case P_ENV: + debug += prop_get_type_name(prop->type); + debug += ": "; + expr_print(prop->expr, expr_print_help, &debug, E_NONE); + debug += "
      "; + break; + case P_CHOICE: + if (sym_is_choice(sym)) { + debug += "choice: "; + expr_print(prop->expr, expr_print_help, &debug, E_NONE); + debug += "
      "; + } + break; + default: + debug += "unknown property: "; + debug += prop_get_type_name(prop->type); + debug += "
      "; + } + if (prop->visible.expr) { + debug += "    dep: "; + expr_print(prop->visible.expr, expr_print_help, &debug, E_NONE); + debug += "
      "; + } + } + debug += "
      "; + + return debug; +} + +QString ConfigInfoView::print_filter(const QString &str) +{ + QRegExp re("[<>&\"\\n]"); + QString res = str; + for (int i = 0; (i = res.indexOf(re, i)) >= 0;) { + switch (res[i].toLatin1()) { + case '<': + res.replace(i, 1, "<"); + i += 4; + break; + case '>': + res.replace(i, 1, ">"); + i += 4; + break; + case '&': + res.replace(i, 1, "&"); + i += 5; + break; + case '"': + res.replace(i, 1, """); + i += 6; + break; + case '\n': + res.replace(i, 1, "
      "); + i += 4; + break; + } + } + return res; +} + +void ConfigInfoView::expr_print_help(void *data, struct symbol *sym, const char *str) +{ + QString* text = reinterpret_cast(data); + QString str2 = print_filter(str); + + if (sym && sym->name && !(sym->flags & SYMBOL_CONST)) { + *text += QString().sprintf("", sym); + *text += str2; + *text += ""; + } else + *text += str2; +} + +QMenu* ConfigInfoView::createStandardContextMenu(const QPoint & pos) +{ + QMenu* popup = Parent::createStandardContextMenu(pos); + QAction* action = new QAction(_("Show Debug Info"), popup); + action->setCheckable(true); + connect(action, SIGNAL(toggled(bool)), SLOT(setShowDebug(bool))); + connect(this, SIGNAL(showDebugChanged(bool)), action, SLOT(setOn(bool))); + action->setChecked(showDebug()); + popup->addSeparator(); + popup->addAction(action); + return popup; +} + +void ConfigInfoView::contextMenuEvent(QContextMenuEvent *e) +{ + Parent::contextMenuEvent(e); +} + +ConfigSearchWindow::ConfigSearchWindow(ConfigMainWindow* parent, const char *name) + : Parent(parent), result(NULL) +{ + setObjectName(name); + setWindowTitle("Search Config"); + + QVBoxLayout* layout1 = new QVBoxLayout(this); + layout1->setContentsMargins(11, 11, 11, 11); + layout1->setSpacing(6); + QHBoxLayout* layout2 = new QHBoxLayout(0); + layout2->setContentsMargins(0, 0, 0, 0); + layout2->setSpacing(6); + layout2->addWidget(new QLabel(_("Find:"), this)); + editField = new QLineEdit(this); + connect(editField, SIGNAL(returnPressed()), SLOT(search())); + layout2->addWidget(editField); + searchButton = new QPushButton(_("Search"), this); + searchButton->setAutoDefault(false); + connect(searchButton, SIGNAL(clicked()), SLOT(search())); + layout2->addWidget(searchButton); + layout1->addLayout(layout2); + + split = new QSplitter(this); + split->setOrientation(Qt::Vertical); + list = new ConfigView(split, name); + list->list->mode = listMode; + info = new ConfigInfoView(split, name); + connect(list->list, SIGNAL(menuChanged(struct menu *)), + info, SLOT(setInfo(struct menu *))); + connect(list->list, SIGNAL(menuChanged(struct menu *)), + parent, SLOT(setMenuLink(struct menu *))); + + layout1->addWidget(split); + + if (name) { + QVariant x, y; + int width, height; + bool ok; + + configSettings->beginGroup(name); + width = configSettings->value("/window width", parent->width() / 2).toInt(); + height = configSettings->value("/window height", parent->height() / 2).toInt(); + resize(width, height); + x = configSettings->value("/window x"); + y = configSettings->value("/window y"); + if ((x.isValid())&&(y.isValid())) + move(x.toInt(), y.toInt()); + QList sizes = configSettings->readSizes("/split", &ok); + if (ok) + split->setSizes(sizes); + configSettings->endGroup(); + connect(configApp, SIGNAL(aboutToQuit()), SLOT(saveSettings())); + } +} + +void ConfigSearchWindow::saveSettings(void) +{ + if (!objectName().isEmpty()) { + configSettings->beginGroup(objectName()); + configSettings->setValue("/window x", pos().x()); + configSettings->setValue("/window y", pos().y()); + configSettings->setValue("/window width", size().width()); + configSettings->setValue("/window height", size().height()); + configSettings->writeSizes("/split", split->sizes()); + configSettings->endGroup(); + } +} + +void ConfigSearchWindow::search(void) +{ + struct symbol **p; + struct property *prop; + ConfigItem *lastItem = NULL; + + free(result); + list->list->clear(); + info->clear(); + + result = sym_re_search(editField->text().toLatin1()); + if (!result) + return; + for (p = result; *p; p++) { + for_all_prompts((*p), prop) + lastItem = new ConfigItem(list->list, lastItem, prop->menu, + menu_is_visible(prop->menu)); + } +} + +/* + * Construct the complete config widget + */ +ConfigMainWindow::ConfigMainWindow(void) + : searchWindow(0) +{ + QMenuBar* menu; + bool ok = true; + QVariant x, y; + int width, height; + char title[256]; + + QDesktopWidget *d = configApp->desktop(); + snprintf(title, sizeof(title), "%s%s", + rootmenu.prompt->text, + "" + ); + setWindowTitle(title); + + width = configSettings->value("/window width", d->width() - 64).toInt(); + height = configSettings->value("/window height", d->height() - 64).toInt(); + resize(width, height); + x = configSettings->value("/window x"); + y = configSettings->value("/window y"); + if ((x.isValid())&&(y.isValid())) + move(x.toInt(), y.toInt()); + + split1 = new QSplitter(this); + split1->setOrientation(Qt::Horizontal); + setCentralWidget(split1); + + menuView = new ConfigView(split1, "menu"); + menuList = menuView->list; + + split2 = new QSplitter(split1); + split2->setOrientation(Qt::Vertical); + + // create config tree + configView = new ConfigView(split2, "config"); + configList = configView->list; + + helpText = new ConfigInfoView(split2, "help"); + + setTabOrder(configList, helpText); + configList->setFocus(); + + menu = menuBar(); + toolBar = new QToolBar("Tools", this); + addToolBar(toolBar); + + backAction = new QAction(QPixmap(xpm_back), _("Back"), this); + connect(backAction, SIGNAL(triggered(bool)), SLOT(goBack())); + backAction->setEnabled(false); + QAction *quitAction = new QAction(_("&Quit"), this); + quitAction->setShortcut(Qt::CTRL + Qt::Key_Q); + connect(quitAction, SIGNAL(triggered(bool)), SLOT(close())); + QAction *loadAction = new QAction(QPixmap(xpm_load), _("&Load"), this); + loadAction->setShortcut(Qt::CTRL + Qt::Key_L); + connect(loadAction, SIGNAL(triggered(bool)), SLOT(loadConfig())); + saveAction = new QAction(QPixmap(xpm_save), _("&Save"), this); + saveAction->setShortcut(Qt::CTRL + Qt::Key_S); + connect(saveAction, SIGNAL(triggered(bool)), SLOT(saveConfig())); + conf_set_changed_callback(conf_changed); + // Set saveAction's initial state + conf_changed(); + QAction *saveAsAction = new QAction(_("Save &As..."), this); + connect(saveAsAction, SIGNAL(triggered(bool)), SLOT(saveConfigAs())); + QAction *searchAction = new QAction(_("&Find"), this); + searchAction->setShortcut(Qt::CTRL + Qt::Key_F); + connect(searchAction, SIGNAL(triggered(bool)), SLOT(searchConfig())); + singleViewAction = new QAction(QPixmap(xpm_single_view), _("Single View"), this); + singleViewAction->setCheckable(true); + connect(singleViewAction, SIGNAL(triggered(bool)), SLOT(showSingleView())); + splitViewAction = new QAction(QPixmap(xpm_split_view), _("Split View"), this); + splitViewAction->setCheckable(true); + connect(splitViewAction, SIGNAL(triggered(bool)), SLOT(showSplitView())); + fullViewAction = new QAction(QPixmap(xpm_tree_view), _("Full View"), this); + fullViewAction->setCheckable(true); + connect(fullViewAction, SIGNAL(triggered(bool)), SLOT(showFullView())); + + QAction *showNameAction = new QAction(_("Show Name"), this); + showNameAction->setCheckable(true); + connect(showNameAction, SIGNAL(toggled(bool)), configView, SLOT(setShowName(bool))); + showNameAction->setChecked(configView->showName()); + QAction *showRangeAction = new QAction(_("Show Range"), this); + showRangeAction->setCheckable(true); + connect(showRangeAction, SIGNAL(toggled(bool)), configView, SLOT(setShowRange(bool))); + QAction *showDataAction = new QAction(_("Show Data"), this); + showDataAction->setCheckable(true); + connect(showDataAction, SIGNAL(toggled(bool)), configView, SLOT(setShowData(bool))); + + QActionGroup *optGroup = new QActionGroup(this); + optGroup->setExclusive(true); + connect(optGroup, SIGNAL(triggered(QAction*)), configView, + SLOT(setOptionMode(QAction *))); + connect(optGroup, SIGNAL(triggered(QAction *)), menuView, + SLOT(setOptionMode(QAction *))); + + configView->showNormalAction = new QAction(_("Show Normal Options"), optGroup); + configView->showAllAction = new QAction(_("Show All Options"), optGroup); + configView->showPromptAction = new QAction(_("Show Prompt Options"), optGroup); + configView->showNormalAction->setCheckable(true); + configView->showAllAction->setCheckable(true); + configView->showPromptAction->setCheckable(true); + + QAction *showDebugAction = new QAction( _("Show Debug Info"), this); + showDebugAction->setCheckable(true); + connect(showDebugAction, SIGNAL(toggled(bool)), helpText, SLOT(setShowDebug(bool))); + showDebugAction->setChecked(helpText->showDebug()); + + QAction *showIntroAction = new QAction( _("Introduction"), this); + connect(showIntroAction, SIGNAL(triggered(bool)), SLOT(showIntro())); + QAction *showAboutAction = new QAction( _("About"), this); + connect(showAboutAction, SIGNAL(triggered(bool)), SLOT(showAbout())); + + // init tool bar + toolBar->addAction(backAction); + toolBar->addSeparator(); + toolBar->addAction(loadAction); + toolBar->addAction(saveAction); + toolBar->addSeparator(); + toolBar->addAction(singleViewAction); + toolBar->addAction(splitViewAction); + toolBar->addAction(fullViewAction); + + // create config menu + QMenu* config = menu->addMenu(_("&File")); + config->addAction(loadAction); + config->addAction(saveAction); + config->addAction(saveAsAction); + config->addSeparator(); + config->addAction(quitAction); + + // create edit menu + QMenu* editMenu = menu->addMenu(_("&Edit")); + editMenu->addAction(searchAction); + + // create options menu + QMenu* optionMenu = menu->addMenu(_("&Option")); + optionMenu->addAction(showNameAction); + optionMenu->addAction(showRangeAction); + optionMenu->addAction(showDataAction); + optionMenu->addSeparator(); + optionMenu->addActions(optGroup->actions()); + optionMenu->addSeparator(); + + // create help menu + menu->addSeparator(); + QMenu* helpMenu = menu->addMenu(_("&Help")); + helpMenu->addAction(showIntroAction); + helpMenu->addAction(showAboutAction); + + connect(configList, SIGNAL(menuChanged(struct menu *)), + helpText, SLOT(setInfo(struct menu *))); + connect(configList, SIGNAL(menuSelected(struct menu *)), + SLOT(changeMenu(struct menu *))); + connect(configList, SIGNAL(parentSelected()), + SLOT(goBack())); + connect(menuList, SIGNAL(menuChanged(struct menu *)), + helpText, SLOT(setInfo(struct menu *))); + connect(menuList, SIGNAL(menuSelected(struct menu *)), + SLOT(changeMenu(struct menu *))); + + connect(configList, SIGNAL(gotFocus(struct menu *)), + helpText, SLOT(setInfo(struct menu *))); + connect(menuList, SIGNAL(gotFocus(struct menu *)), + helpText, SLOT(setInfo(struct menu *))); + connect(menuList, SIGNAL(gotFocus(struct menu *)), + SLOT(listFocusChanged(void))); + connect(helpText, SIGNAL(menuSelected(struct menu *)), + SLOT(setMenuLink(struct menu *))); + + QString listMode = configSettings->value("/listMode", "symbol").toString(); + if (listMode == "single") + showSingleView(); + else if (listMode == "full") + showFullView(); + else /*if (listMode == "split")*/ + showSplitView(); + + // UI setup done, restore splitter positions + QList sizes = configSettings->readSizes("/split1", &ok); + if (ok) + split1->setSizes(sizes); + + sizes = configSettings->readSizes("/split2", &ok); + if (ok) + split2->setSizes(sizes); +} + +void ConfigMainWindow::loadConfig(void) +{ + QString s = QFileDialog::getOpenFileName(this, "", conf_get_configname()); + if (s.isNull()) + return; + if (conf_read(QFile::encodeName(s))) + QMessageBox::information(this, "qconf", _("Unable to load configuration!")); + ConfigView::updateListAll(); +} + +bool ConfigMainWindow::saveConfig(void) +{ + if (conf_write(NULL)) { + QMessageBox::information(this, "qconf", _("Unable to save configuration!")); + return false; + } + return true; +} + +void ConfigMainWindow::saveConfigAs(void) +{ + QString s = QFileDialog::getSaveFileName(this, "", conf_get_configname()); + if (s.isNull()) + return; + saveConfig(); +} + +void ConfigMainWindow::searchConfig(void) +{ + if (!searchWindow) + searchWindow = new ConfigSearchWindow(this, "search"); + searchWindow->show(); +} + +void ConfigMainWindow::changeMenu(struct menu *menu) +{ + configList->setRootMenu(menu); + if (configList->rootEntry->parent == &rootmenu) + backAction->setEnabled(false); + else + backAction->setEnabled(true); +} + +void ConfigMainWindow::setMenuLink(struct menu *menu) +{ + struct menu *parent; + ConfigList* list = NULL; + ConfigItem* item; + + if (configList->menuSkip(menu)) + return; + + switch (configList->mode) { + case singleMode: + list = configList; + parent = menu_get_parent_menu(menu); + if (!parent) + return; + list->setRootMenu(parent); + break; + case symbolMode: + if (menu->flags & MENU_ROOT) { + configList->setRootMenu(menu); + configList->clearSelection(); + list = menuList; + } else { + list = configList; + parent = menu_get_parent_menu(menu->parent); + if (!parent) + return; + item = menuList->findConfigItem(parent); + if (item) { + item->setSelected(true); + menuList->scrollToItem(item); + } + list->setRootMenu(parent); + } + break; + case fullMode: + list = configList; + break; + default: + break; + } + + if (list) { + item = list->findConfigItem(menu); + if (item) { + item->setSelected(true); + list->scrollToItem(item); + list->setFocus(); + } + } +} + +void ConfigMainWindow::listFocusChanged(void) +{ + if (menuList->mode == menuMode) + configList->clearSelection(); +} + +void ConfigMainWindow::goBack(void) +{ + ConfigItem* item, *oldSelection; + + configList->setParentMenu(); + if (configList->rootEntry == &rootmenu) + backAction->setEnabled(false); + + if (menuList->selectedItems().count() == 0) + return; + + item = (ConfigItem*)menuList->selectedItems().first(); + oldSelection = item; + while (item) { + if (item->menu == configList->rootEntry) { + oldSelection->setSelected(false); + item->setSelected(true); + break; + } + item = (ConfigItem*)item->parent(); + } +} + +void ConfigMainWindow::showSingleView(void) +{ + singleViewAction->setEnabled(false); + singleViewAction->setChecked(true); + splitViewAction->setEnabled(true); + splitViewAction->setChecked(false); + fullViewAction->setEnabled(true); + fullViewAction->setChecked(false); + + menuView->hide(); + menuList->setRootMenu(0); + configList->mode = singleMode; + if (configList->rootEntry == &rootmenu) + configList->updateListAll(); + else + configList->setRootMenu(&rootmenu); + configList->setFocus(); +} + +void ConfigMainWindow::showSplitView(void) +{ + singleViewAction->setEnabled(true); + singleViewAction->setChecked(false); + splitViewAction->setEnabled(false); + splitViewAction->setChecked(true); + fullViewAction->setEnabled(true); + fullViewAction->setChecked(false); + + configList->mode = symbolMode; + if (configList->rootEntry == &rootmenu) + configList->updateListAll(); + else + configList->setRootMenu(&rootmenu); + configList->setAllOpen(true); + configApp->processEvents(); + menuList->mode = menuMode; + menuList->setRootMenu(&rootmenu); + menuList->setAllOpen(true); + menuView->show(); + menuList->setFocus(); +} + +void ConfigMainWindow::showFullView(void) +{ + singleViewAction->setEnabled(true); + singleViewAction->setChecked(false); + splitViewAction->setEnabled(true); + splitViewAction->setChecked(false); + fullViewAction->setEnabled(false); + fullViewAction->setChecked(true); + + menuView->hide(); + menuList->setRootMenu(0); + configList->mode = fullMode; + if (configList->rootEntry == &rootmenu) + configList->updateListAll(); + else + configList->setRootMenu(&rootmenu); + configList->setFocus(); +} + +/* + * ask for saving configuration before quitting + * TODO ask only when something changed + */ +void ConfigMainWindow::closeEvent(QCloseEvent* e) +{ + if (!conf_get_changed()) { + e->accept(); + return; + } + QMessageBox mb("qconf", _("Save configuration?"), QMessageBox::Warning, + QMessageBox::Yes | QMessageBox::Default, QMessageBox::No, QMessageBox::Cancel | QMessageBox::Escape); + mb.setButtonText(QMessageBox::Yes, _("&Save Changes")); + mb.setButtonText(QMessageBox::No, _("&Discard Changes")); + mb.setButtonText(QMessageBox::Cancel, _("Cancel Exit")); + switch (mb.exec()) { + case QMessageBox::Yes: + if (saveConfig()) + e->accept(); + else + e->ignore(); + break; + case QMessageBox::No: + e->accept(); + break; + case QMessageBox::Cancel: + e->ignore(); + break; + } +} + +void ConfigMainWindow::showIntro(void) +{ + static const QString str = _("Welcome to the qconf graphical configuration tool.\n\n" + "For each option, a blank box indicates the feature is disabled, a check\n" + "indicates it is enabled, and a dot indicates that it is to be compiled\n" + "as a module. Clicking on the box will cycle through the three states.\n\n" + "If you do not see an option (e.g., a device driver) that you believe\n" + "should be present, try turning on Show All Options under the Options menu.\n" + "Although there is no cross reference yet to help you figure out what other\n" + "options must be enabled to support the option you are interested in, you can\n" + "still view the help of a grayed-out option.\n\n" + "Toggling Show Debug Info under the Options menu will show the dependencies,\n" + "which you can then match by examining other options.\n\n"); + + QMessageBox::information(this, "qconf", str); +} + +void ConfigMainWindow::showAbout(void) +{ + static const QString str = _("qconf is Copyright (C) 2002 Roman Zippel .\n" + "Copyright (C) 2015 Boris Barbulovski .\n\n" + "Bug reports and feature request can also be entered at http://bugzilla.kernel.org/\n"); + + QMessageBox::information(this, "qconf", str); +} + +void ConfigMainWindow::saveSettings(void) +{ + configSettings->setValue("/window x", pos().x()); + configSettings->setValue("/window y", pos().y()); + configSettings->setValue("/window width", size().width()); + configSettings->setValue("/window height", size().height()); + + QString entry; + switch(configList->mode) { + case singleMode : + entry = "single"; + break; + + case symbolMode : + entry = "split"; + break; + + case fullMode : + entry = "full"; + break; + + default: + break; + } + configSettings->setValue("/listMode", entry); + + configSettings->writeSizes("/split1", split1->sizes()); + configSettings->writeSizes("/split2", split2->sizes()); +} + +void ConfigMainWindow::conf_changed(void) +{ + if (saveAction) + saveAction->setEnabled(conf_get_changed()); +} + +void fixup_rootmenu(struct menu *menu) +{ + struct menu *child; + static int menu_cnt = 0; + + menu->flags |= MENU_ROOT; + for (child = menu->list; child; child = child->next) { + if (child->prompt && child->prompt->type == P_MENU) { + menu_cnt++; + fixup_rootmenu(child); + menu_cnt--; + } else if (!menu_cnt) + fixup_rootmenu(child); + } +} + +static const char *progname; + +static void usage(void) +{ + printf(_("%s [-s] \n").toLatin1().constData(), progname); + exit(0); +} + +int main(int ac, char** av) +{ + ConfigMainWindow* v; + const char *name; + + bindtextdomain(PACKAGE, LOCALEDIR); + textdomain(PACKAGE); + + progname = av[0]; + configApp = new QApplication(ac, av); + if (ac > 1 && av[1][0] == '-') { + switch (av[1][1]) { + case 's': + conf_set_message_callback(NULL); + break; + case 'h': + case '?': + usage(); + } + name = av[2]; + } else + name = av[1]; + if (!name) + usage(); + + conf_parse(name); + fixup_rootmenu(&rootmenu); + conf_read(NULL); + //zconfdump(stdout); + + configSettings = new ConfigSettings(); + configSettings->beginGroup("/kconfig/qconf"); + v = new ConfigMainWindow(); + + //zconfdump(stdout); + configApp->connect(configApp, SIGNAL(lastWindowClosed()), SLOT(quit())); + configApp->connect(configApp, SIGNAL(aboutToQuit()), v, SLOT(saveSettings())); + v->show(); + configApp->exec(); + + configSettings->endGroup(); + delete configSettings; + delete v; + delete configApp; + + return 0; +} diff --git a/tools/kconfig/qconf.h b/tools/kconfig/qconf.h new file mode 100644 index 0000000000..a40036d1b0 --- /dev/null +++ b/tools/kconfig/qconf.h @@ -0,0 +1,330 @@ +/* + * Copyright (C) 2002 Roman Zippel + * Released under the terms of the GNU GPL v2.0. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "expr.h" + +class ConfigView; +class ConfigList; +class ConfigItem; +class ConfigLineEdit; +class ConfigMainWindow; + +class ConfigSettings : public QSettings { +public: + ConfigSettings(); + QList readSizes(const QString& key, bool *ok); + bool writeSizes(const QString& key, const QList& value); +}; + +enum colIdx { + promptColIdx, nameColIdx, noColIdx, modColIdx, yesColIdx, dataColIdx, colNr +}; +enum listMode { + singleMode, menuMode, symbolMode, fullMode, listMode +}; +enum optionMode { + normalOpt = 0, allOpt, promptOpt +}; + +class ConfigList : public QTreeWidget { + Q_OBJECT + typedef class QTreeWidget Parent; +public: + ConfigList(ConfigView* p, const char *name = 0); + void reinit(void); + ConfigView* parent(void) const + { + return (ConfigView*)Parent::parent(); + } + ConfigItem* findConfigItem(struct menu *); + +protected: + void keyPressEvent(QKeyEvent *e); + void mousePressEvent(QMouseEvent *e); + void mouseReleaseEvent(QMouseEvent *e); + void mouseMoveEvent(QMouseEvent *e); + void mouseDoubleClickEvent(QMouseEvent *e); + void focusInEvent(QFocusEvent *e); + void contextMenuEvent(QContextMenuEvent *e); + +public slots: + void setRootMenu(struct menu *menu); + + void updateList(ConfigItem *item); + void setValue(ConfigItem* item, tristate val); + void changeValue(ConfigItem* item); + void updateSelection(void); + void saveSettings(void); +signals: + void menuChanged(struct menu *menu); + void menuSelected(struct menu *menu); + void parentSelected(void); + void gotFocus(struct menu *); + +public: + void updateListAll(void) + { + updateAll = true; + updateList(NULL); + updateAll = false; + } + ConfigList* listView() + { + return this; + } + ConfigItem* firstChild() const + { + return (ConfigItem *)children().first(); + } + void addColumn(colIdx idx) + { + showColumn(idx); + } + void removeColumn(colIdx idx) + { + hideColumn(idx); + } + void setAllOpen(bool open); + void setParentMenu(void); + + bool menuSkip(struct menu *); + + void updateMenuList(ConfigItem *parent, struct menu*); + void updateMenuList(ConfigList *parent, struct menu*); + + bool updateAll; + + QPixmap symbolYesPix, symbolModPix, symbolNoPix; + QPixmap choiceYesPix, choiceNoPix; + QPixmap menuPix, menuInvPix, menuBackPix, voidPix; + + bool showName, showRange, showData; + enum listMode mode; + enum optionMode optMode; + struct menu *rootEntry; + QPalette disabledColorGroup; + QPalette inactivedColorGroup; + QMenu* headerPopup; +}; + +class ConfigItem : public QTreeWidgetItem { + typedef class QTreeWidgetItem Parent; +public: + ConfigItem(ConfigList *parent, ConfigItem *after, struct menu *m, bool v) + : Parent(parent, after), nextItem(0), menu(m), visible(v), goParent(false) + { + init(); + } + ConfigItem(ConfigItem *parent, ConfigItem *after, struct menu *m, bool v) + : Parent(parent, after), nextItem(0), menu(m), visible(v), goParent(false) + { + init(); + } + ConfigItem(ConfigList *parent, ConfigItem *after, bool v) + : Parent(parent, after), nextItem(0), menu(0), visible(v), goParent(true) + { + init(); + } + ~ConfigItem(void); + void init(void); + void okRename(int col); + void updateMenu(void); + void testUpdateMenu(bool v); + ConfigList* listView() const + { + return (ConfigList*)Parent::treeWidget(); + } + ConfigItem* firstChild() const + { + return (ConfigItem *)Parent::child(0); + } + ConfigItem* nextSibling() + { + ConfigItem *ret = NULL; + ConfigItem *_parent = (ConfigItem *)parent(); + + if(_parent) { + ret = (ConfigItem *)_parent->child(_parent->indexOfChild(this)+1); + } else { + QTreeWidget *_treeWidget = treeWidget(); + ret = (ConfigItem *)_treeWidget->topLevelItem(_treeWidget->indexOfTopLevelItem(this)+1); + } + + return ret; + } + void setText(colIdx idx, const QString& text) + { + Parent::setText(idx, text); + } + QString text(colIdx idx) const + { + return Parent::text(idx); + } + void setPixmap(colIdx idx, const QIcon &icon) + { + Parent::setIcon(idx, icon); + } + const QIcon pixmap(colIdx idx) const + { + return icon(idx); + } + // TODO: Implement paintCell + + ConfigItem* nextItem; + struct menu *menu; + bool visible; + bool goParent; +}; + +class ConfigLineEdit : public QLineEdit { + Q_OBJECT + typedef class QLineEdit Parent; +public: + ConfigLineEdit(ConfigView* parent); + ConfigView* parent(void) const + { + return (ConfigView*)Parent::parent(); + } + void show(ConfigItem *i); + void keyPressEvent(QKeyEvent *e); + +public: + ConfigItem *item; +}; + +class ConfigView : public QWidget { + Q_OBJECT + typedef class QWidget Parent; +public: + ConfigView(QWidget* parent, const char *name = 0); + ~ConfigView(void); + static void updateList(ConfigItem* item); + static void updateListAll(void); + + bool showName(void) const { return list->showName; } + bool showRange(void) const { return list->showRange; } + bool showData(void) const { return list->showData; } +public slots: + void setShowName(bool); + void setShowRange(bool); + void setShowData(bool); + void setOptionMode(QAction *); +signals: + void showNameChanged(bool); + void showRangeChanged(bool); + void showDataChanged(bool); +public: + ConfigList* list; + ConfigLineEdit* lineEdit; + + static ConfigView* viewList; + ConfigView* nextView; + + static QAction *showNormalAction; + static QAction *showAllAction; + static QAction *showPromptAction; +}; + +class ConfigInfoView : public QTextBrowser { + Q_OBJECT + typedef class QTextBrowser Parent; +public: + ConfigInfoView(QWidget* parent, const char *name = 0); + bool showDebug(void) const { return _showDebug; } + +public slots: + void setInfo(struct menu *menu); + void saveSettings(void); + void setShowDebug(bool); + +signals: + void showDebugChanged(bool); + void menuSelected(struct menu *); + +protected: + void symbolInfo(void); + void menuInfo(void); + QString debug_info(struct symbol *sym); + static QString print_filter(const QString &str); + static void expr_print_help(void *data, struct symbol *sym, const char *str); + QMenu *createStandardContextMenu(const QPoint & pos); + void contextMenuEvent(QContextMenuEvent *e); + + struct symbol *sym; + struct menu *_menu; + bool _showDebug; +}; + +class ConfigSearchWindow : public QDialog { + Q_OBJECT + typedef class QDialog Parent; +public: + ConfigSearchWindow(ConfigMainWindow* parent, const char *name = 0); + +public slots: + void saveSettings(void); + void search(void); + +protected: + QLineEdit* editField; + QPushButton* searchButton; + QSplitter* split; + ConfigView* list; + ConfigInfoView* info; + + struct symbol **result; +}; + +class ConfigMainWindow : public QMainWindow { + Q_OBJECT + + static QAction *saveAction; + static void conf_changed(void); +public: + ConfigMainWindow(void); +public slots: + void changeMenu(struct menu *); + void setMenuLink(struct menu *); + void listFocusChanged(void); + void goBack(void); + void loadConfig(void); + bool saveConfig(void); + void saveConfigAs(void); + void searchConfig(void); + void showSingleView(void); + void showSplitView(void); + void showFullView(void); + void showIntro(void); + void showAbout(void); + void saveSettings(void); + +protected: + void closeEvent(QCloseEvent *e); + + ConfigSearchWindow *searchWindow; + ConfigView *menuView; + ConfigList *menuList; + ConfigView *configView; + ConfigList *configList; + ConfigInfoView *helpText; + QToolBar *toolBar; + QAction *backAction; + QAction *singleViewAction; + QAction *splitViewAction; + QAction *fullViewAction; + QSplitter *split1; + QSplitter *split2; +}; diff --git a/tools/kconfig/streamline_config.pl b/tools/kconfig/streamline_config.pl new file mode 100755 index 0000000000..f3d3fb42b8 --- /dev/null +++ b/tools/kconfig/streamline_config.pl @@ -0,0 +1,647 @@ +#!/usr/bin/perl -w +# +# Copyright 2005-2009 - Steven Rostedt +# Licensed under the terms of the GNU GPL License version 2 +# +# It's simple enough to figure out how this works. +# If not, then you can ask me at stripconfig@goodmis.org +# +# What it does? +# +# If you have installed a Linux kernel from a distribution +# that turns on way too many modules than you need, and +# you only want the modules you use, then this program +# is perfect for you. +# +# It gives you the ability to turn off all the modules that are +# not loaded on your system. +# +# Howto: +# +# 1. Boot up the kernel that you want to stream line the config on. +# 2. Change directory to the directory holding the source of the +# kernel that you just booted. +# 3. Copy the configuraton file to this directory as .config +# 4. Have all your devices that you need modules for connected and +# operational (make sure that their corresponding modules are loaded) +# 5. Run this script redirecting the output to some other file +# like config_strip. +# 6. Back up your old config (if you want too). +# 7. copy the config_strip file to .config +# 8. Run "make oldconfig" +# +# Now your kernel is ready to be built with only the modules that +# are loaded. +# +# Here's what I did with my Debian distribution. +# +# cd /usr/src/linux-2.6.10 +# cp /boot/config-2.6.10-1-686-smp .config +# ~/bin/streamline_config > config_strip +# mv .config config_sav +# mv config_strip .config +# make oldconfig +# +use strict; +use Getopt::Long; + +# set the environment variable LOCALMODCONFIG_DEBUG to get +# debug output. +my $debugprint = 0; +$debugprint = 1 if (defined($ENV{LOCALMODCONFIG_DEBUG})); + +sub dprint { + return if (!$debugprint); + print STDERR @_; +} + +my $config = ".config"; + +my $uname = `uname -r`; +chomp $uname; + +my @searchconfigs = ( + { + "file" => ".config", + "exec" => "cat", + }, + { + "file" => "/proc/config.gz", + "exec" => "zcat", + }, + { + "file" => "/boot/config-$uname", + "exec" => "cat", + }, + { + "file" => "/boot/vmlinuz-$uname", + "exec" => "scripts/extract-ikconfig", + "test" => "scripts/extract-ikconfig", + }, + { + "file" => "vmlinux", + "exec" => "scripts/extract-ikconfig", + "test" => "scripts/extract-ikconfig", + }, + { + "file" => "/lib/modules/$uname/kernel/kernel/configs.ko", + "exec" => "scripts/extract-ikconfig", + "test" => "scripts/extract-ikconfig", + }, + { + "file" => "kernel/configs.ko", + "exec" => "scripts/extract-ikconfig", + "test" => "scripts/extract-ikconfig", + }, + { + "file" => "kernel/configs.o", + "exec" => "scripts/extract-ikconfig", + "test" => "scripts/extract-ikconfig", + }, +); + +sub read_config { + foreach my $conf (@searchconfigs) { + my $file = $conf->{"file"}; + + next if ( ! -f "$file"); + + if (defined($conf->{"test"})) { + `$conf->{"test"} $conf->{"file"} 2>/dev/null`; + next if ($?); + } + + my $exec = $conf->{"exec"}; + + print STDERR "using config: '$file'\n"; + + open(my $infile, '-|', "$exec $file") || die "Failed to run $exec $file"; + my @x = <$infile>; + close $infile; + return @x; + } + die "No config file found"; +} + +my @config_file = read_config; + +# Parse options +my $localmodconfig = 0; +my $localyesconfig = 0; + +GetOptions("localmodconfig" => \$localmodconfig, + "localyesconfig" => \$localyesconfig); + +# Get the build source and top level Kconfig file (passed in) +my $ksource = ($ARGV[0] ? $ARGV[0] : '.'); +my $kconfig = $ARGV[1]; +my $lsmod_file = $ENV{'LSMOD'}; + +my @makefiles = `find $ksource -name Makefile -or -name Kbuild 2>/dev/null`; +chomp @makefiles; + +my %depends; +my %selects; +my %prompts; +my %objects; +my $var; +my $iflevel = 0; +my @ifdeps; + +# prevent recursion +my %read_kconfigs; + +sub read_kconfig { + my ($kconfig) = @_; + + my $state = "NONE"; + my $config; + + my $cont = 0; + my $line; + + my $source = "$ksource/$kconfig"; + my $last_source = ""; + + # Check for any environment variables used + while ($source =~ /\$(\w+)/ && $last_source ne $source) { + my $env = $1; + $last_source = $source; + $source =~ s/\$$env/$ENV{$env}/; + } + + open(my $kinfile, '<', $source) || die "Can't open $kconfig"; + while (<$kinfile>) { + chomp; + + # Make sure that lines ending with \ continue + if ($cont) { + $_ = $line . " " . $_; + } + + if (s/\\$//) { + $cont = 1; + $line = $_; + next; + } + + $cont = 0; + + # collect any Kconfig sources + if (/^source\s*"(.*)"/) { + my $kconfig = $1; + # prevent reading twice. + if (!defined($read_kconfigs{$kconfig})) { + $read_kconfigs{$kconfig} = 1; + read_kconfig($kconfig); + } + next; + } + + # configs found + if (/^\s*(menu)?config\s+(\S+)\s*$/) { + $state = "NEW"; + $config = $2; + + # Add depends for 'if' nesting + for (my $i = 0; $i < $iflevel; $i++) { + if ($i) { + $depends{$config} .= " " . $ifdeps[$i]; + } else { + $depends{$config} = $ifdeps[$i]; + } + $state = "DEP"; + } + + # collect the depends for the config + } elsif ($state eq "NEW" && /^\s*depends\s+on\s+(.*)$/) { + $state = "DEP"; + $depends{$config} = $1; + } elsif ($state eq "DEP" && /^\s*depends\s+on\s+(.*)$/) { + $depends{$config} .= " " . $1; + } elsif ($state eq "DEP" && /^\s*def(_(bool|tristate)|ault)\s+(\S.*)$/) { + my $dep = $3; + if ($dep !~ /^\s*(y|m|n)\s*$/) { + $dep =~ s/.*\sif\s+//; + $depends{$config} .= " " . $dep; + dprint "Added default depends $dep to $config\n"; + } + + # Get the configs that select this config + } elsif ($state ne "NONE" && /^\s*select\s+(\S+)/) { + my $conf = $1; + if (defined($selects{$conf})) { + $selects{$conf} .= " " . $config; + } else { + $selects{$conf} = $config; + } + + # configs without prompts must be selected + } elsif ($state ne "NONE" && /^\s*tristate\s\S/) { + # note if the config has a prompt + $prompts{$config} = 1; + + # Check for if statements + } elsif (/^if\s+(.*\S)\s*$/) { + my $deps = $1; + # remove beginning and ending non text + $deps =~ s/^[^a-zA-Z0-9_]*//; + $deps =~ s/[^a-zA-Z0-9_]*$//; + + my @deps = split /[^a-zA-Z0-9_]+/, $deps; + + $ifdeps[$iflevel++] = join ':', @deps; + + } elsif (/^endif/) { + + $iflevel-- if ($iflevel); + + # stop on "help" + } elsif (/^\s*help\s*$/) { + $state = "NONE"; + } + } + close($kinfile); +} + +if ($kconfig) { + read_kconfig($kconfig); +} + +# Makefiles can use variables to define their dependencies +sub convert_vars { + my ($line, %vars) = @_; + + my $process = ""; + + while ($line =~ s/^(.*?)(\$\((.*?)\))//) { + my $start = $1; + my $variable = $2; + my $var = $3; + + if (defined($vars{$var})) { + $process .= $start . $vars{$var}; + } else { + $process .= $start . $variable; + } + } + + $process .= $line; + + return $process; +} + +# Read all Makefiles to map the configs to the objects +foreach my $makefile (@makefiles) { + + my $line = ""; + my %make_vars; + + open(my $infile, '<', $makefile) || die "Can't open $makefile"; + while (<$infile>) { + # if this line ends with a backslash, continue + chomp; + if (/^(.*)\\$/) { + $line .= $1; + next; + } + + $line .= $_; + $_ = $line; + $line = ""; + + my $objs; + + # Convert variables in a line (could define configs) + $_ = convert_vars($_, %make_vars); + + # collect objects after obj-$(CONFIG_FOO_BAR) + if (/obj-\$\((CONFIG_[^\)]*)\)\s*[+:]?=\s*(.*)/) { + $var = $1; + $objs = $2; + + # check if variables are set + } elsif (/^\s*(\S+)\s*[:]?=\s*(.*\S)/) { + $make_vars{$1} = $2; + } + if (defined($objs)) { + foreach my $obj (split /\s+/,$objs) { + $obj =~ s/-/_/g; + if ($obj =~ /(.*)\.o$/) { + # Objects may be enabled by more than one config. + # Store configs in an array. + my @arr; + + if (defined($objects{$1})) { + @arr = @{$objects{$1}}; + } + + $arr[$#arr+1] = $var; + + # The objects have a hash mapping to a reference + # of an array of configs. + $objects{$1} = \@arr; + } + } + } + } + close($infile); +} + +my %modules; +my $linfile; + +if (defined($lsmod_file)) { + if ( ! -f $lsmod_file) { + if ( -f $ENV{'objtree'}."/".$lsmod_file) { + $lsmod_file = $ENV{'objtree'}."/".$lsmod_file; + } else { + die "$lsmod_file not found"; + } + } + + my $otype = ( -x $lsmod_file) ? '-|' : '<'; + open($linfile, $otype, $lsmod_file); + +} else { + + # see what modules are loaded on this system + my $lsmod; + + foreach my $dir ( ("/sbin", "/bin", "/usr/sbin", "/usr/bin") ) { + if ( -x "$dir/lsmod" ) { + $lsmod = "$dir/lsmod"; + last; + } +} + if (!defined($lsmod)) { + # try just the path + $lsmod = "lsmod"; + } + + open($linfile, '-|', $lsmod) || die "Can not call lsmod with $lsmod"; +} + +while (<$linfile>) { + next if (/^Module/); # Skip the first line. + if (/^(\S+)/) { + $modules{$1} = 1; + } +} +close ($linfile); + +# add to the configs hash all configs that are needed to enable +# a loaded module. This is a direct obj-${CONFIG_FOO} += bar.o +# where we know we need bar.o so we add FOO to the list. +my %configs; +foreach my $module (keys(%modules)) { + if (defined($objects{$module})) { + my @arr = @{$objects{$module}}; + foreach my $conf (@arr) { + $configs{$conf} = $module; + dprint "$conf added by direct ($module)\n"; + if ($debugprint) { + my $c=$conf; + $c =~ s/^CONFIG_//; + if (defined($depends{$c})) { + dprint " deps = $depends{$c}\n"; + } else { + dprint " no deps\n"; + } + } + } + } else { + # Most likely, someone has a custom (binary?) module loaded. + print STDERR "$module config not found!!\n"; + } +} + +# Read the current config, and see what is enabled. We want to +# ignore configs that we would not enable anyway. + +my %orig_configs; +my $valid = "A-Za-z_0-9"; + +foreach my $line (@config_file) { + $_ = $line; + + if (/(CONFIG_[$valid]*)=(m|y)/) { + $orig_configs{$1} = $2; + } +} + +my $repeat = 1; + +my $depconfig; + +# +# Note, we do not care about operands (like: &&, ||, !) we want to add any +# config that is in the depend list of another config. This script does +# not enable configs that are not already enabled. If we come across a +# config A that depends on !B, we can still add B to the list of depends +# to keep on. If A was on in the original config, B would not have been +# and B would not be turned on by this script. +# +sub parse_config_depends +{ + my ($p) = @_; + + while ($p =~ /[$valid]/) { + + if ($p =~ /^[^$valid]*([$valid]+)/) { + my $conf = "CONFIG_" . $1; + + $p =~ s/^[^$valid]*[$valid]+//; + + # We only need to process if the depend config is a module + if (!defined($orig_configs{$conf}) || !$orig_configs{conf} eq "m") { + next; + } + + if (!defined($configs{$conf})) { + # We must make sure that this config has its + # dependencies met. + $repeat = 1; # do again + dprint "$conf selected by depend $depconfig\n"; + $configs{$conf} = 1; + } + } else { + die "this should never happen"; + } + } +} + +# Select is treated a bit differently than depends. We call this +# when a config has no prompt and requires another config to be +# selected. We use to just select all configs that selected this +# config, but found that that can balloon into enabling hundreds +# of configs that we do not care about. +# +# The idea is we look at all the configs that select it. If one +# is already in our list of configs to enable, then there's nothing +# else to do. If there isn't, we pick the first config that was +# enabled in the orignal config and use that. +sub parse_config_selects +{ + my ($config, $p) = @_; + + my $next_config; + + while ($p =~ /[$valid]/) { + + if ($p =~ /^[^$valid]*([$valid]+)/) { + my $conf = "CONFIG_" . $1; + + $p =~ s/^[^$valid]*[$valid]+//; + + # Make sure that this config exists in the current .config file + if (!defined($orig_configs{$conf})) { + dprint "$conf not set for $config select\n"; + next; + } + + # Check if something other than a module selects this config + if (defined($orig_configs{$conf}) && $orig_configs{$conf} ne "m") { + dprint "$conf (non module) selects config, we are good\n"; + # we are good with this + return; + } + if (defined($configs{$conf})) { + dprint "$conf selects $config so we are good\n"; + # A set config selects this config, we are good + return; + } + # Set this config to be selected + if (!defined($next_config)) { + $next_config = $conf; + } + } else { + die "this should never happen"; + } + } + + # If no possible config selected this, then something happened. + if (!defined($next_config)) { + print STDERR "WARNING: $config is required, but nothing in the\n"; + print STDERR " current config selects it.\n"; + return; + } + + # If we are here, then we found no config that is set and + # selects this config. Repeat. + $repeat = 1; + # Make this config need to be selected + $configs{$next_config} = 1; + dprint "$next_config selected by select $config\n"; +} + +my %process_selects; + +# loop through all configs, select their dependencies. +sub loop_depend { + $repeat = 1; + + while ($repeat) { + $repeat = 0; + + forloop: + foreach my $config (keys %configs) { + + # If this config is not a module, we do not need to process it + if (defined($orig_configs{$config}) && $orig_configs{$config} ne "m") { + next forloop; + } + + $config =~ s/^CONFIG_//; + $depconfig = $config; + + if (defined($depends{$config})) { + # This config has dependencies. Make sure they are also included + parse_config_depends $depends{$config}; + } + + # If the config has no prompt, then we need to check if a config + # that is enabled selected it. Or if we need to enable one. + if (!defined($prompts{$config}) && defined($selects{$config})) { + $process_selects{$config} = 1; + } + } + } +} + +sub loop_select { + + foreach my $config (keys %process_selects) { + $config =~ s/^CONFIG_//; + + dprint "Process select $config\n"; + + # config has no prompt and must be selected. + parse_config_selects $config, $selects{$config}; + } +} + +while ($repeat) { + # Get the first set of configs and their dependencies. + loop_depend; + + $repeat = 0; + + # Now we need to see if we have to check selects; + loop_select; +} + +my %setconfigs; + +# Finally, read the .config file and turn off any module enabled that +# we could not find a reason to keep enabled. +foreach my $line (@config_file) { + $_ = $line; + + if (/CONFIG_IKCONFIG/) { + if (/# CONFIG_IKCONFIG is not set/) { + # enable IKCONFIG at least as a module + print "CONFIG_IKCONFIG=m\n"; + # don't ask about PROC + print "# CONFIG_IKCONFIG_PROC is not set\n"; + } else { + print; + } + next; + } + + if (/^(CONFIG.*)=(m|y)/) { + if (defined($configs{$1})) { + if ($localyesconfig) { + $setconfigs{$1} = 'y'; + print "$1=y\n"; + next; + } else { + $setconfigs{$1} = $2; + } + } elsif ($2 eq "m") { + print "# $1 is not set\n"; + next; + } + } + print; +} + +# Integrity check, make sure all modules that we want enabled do +# indeed have their configs set. +loop: +foreach my $module (keys(%modules)) { + if (defined($objects{$module})) { + my @arr = @{$objects{$module}}; + foreach my $conf (@arr) { + if (defined($setconfigs{$conf})) { + next loop; + } + } + print STDERR "module $module did not have configs"; + foreach my $conf (@arr) { + print STDERR " " , $conf; + } + print STDERR "\n"; + } +} diff --git a/tools/kconfig/symbol.c b/tools/kconfig/symbol.c new file mode 100644 index 0000000000..25cf0c2c0c --- /dev/null +++ b/tools/kconfig/symbol.c @@ -0,0 +1,1378 @@ +/* + * Copyright (C) 2002 Roman Zippel + * Released under the terms of the GNU GPL v2.0. + */ + +#include +#include +#include +#include +#include + +#include "lkc.h" + +struct symbol symbol_yes = { + .name = "y", + .curr = { "y", yes }, + .flags = SYMBOL_CONST|SYMBOL_VALID, +}, symbol_mod = { + .name = "m", + .curr = { "m", mod }, + .flags = SYMBOL_CONST|SYMBOL_VALID, +}, symbol_no = { + .name = "n", + .curr = { "n", no }, + .flags = SYMBOL_CONST|SYMBOL_VALID, +}, symbol_empty = { + .name = "", + .curr = { "", no }, + .flags = SYMBOL_VALID, +}; + +struct symbol *sym_defconfig_list; +struct symbol *modules_sym; +tristate modules_val; + +struct expr *sym_env_list; + +static void sym_add_default(struct symbol *sym, const char *def) +{ + struct property *prop = prop_alloc(P_DEFAULT, sym); + + prop->expr = expr_alloc_symbol(sym_lookup(def, SYMBOL_CONST)); +} + +void sym_init(void) +{ + struct symbol *sym; + struct utsname uts; + static bool inited = false; + + if (inited) + return; + inited = true; + + uname(&uts); + + sym = sym_lookup("UNAME_RELEASE", 0); + sym->type = S_STRING; + sym->flags |= SYMBOL_AUTO; + sym_add_default(sym, uts.release); +} + +enum symbol_type sym_get_type(struct symbol *sym) +{ + enum symbol_type type = sym->type; + + if (type == S_TRISTATE) { + if (sym_is_choice_value(sym) && sym->visible == yes) + type = S_BOOLEAN; + else if (modules_val == no) + type = S_BOOLEAN; + } + return type; +} + +const char *sym_type_name(enum symbol_type type) +{ + switch (type) { + case S_BOOLEAN: + return "boolean"; + case S_TRISTATE: + return "tristate"; + case S_INT: + return "integer"; + case S_HEX: + return "hex"; + case S_STRING: + return "string"; + case S_UNKNOWN: + return "unknown"; + case S_OTHER: + break; + } + return "???"; +} + +struct property *sym_get_choice_prop(struct symbol *sym) +{ + struct property *prop; + + for_all_choices(sym, prop) + return prop; + return NULL; +} + +struct property *sym_get_env_prop(struct symbol *sym) +{ + struct property *prop; + + for_all_properties(sym, prop, P_ENV) + return prop; + return NULL; +} + +static struct property *sym_get_default_prop(struct symbol *sym) +{ + struct property *prop; + + for_all_defaults(sym, prop) { + prop->visible.tri = expr_calc_value(prop->visible.expr); + if (prop->visible.tri != no) + return prop; + } + return NULL; +} + +static struct property *sym_get_range_prop(struct symbol *sym) +{ + struct property *prop; + + for_all_properties(sym, prop, P_RANGE) { + prop->visible.tri = expr_calc_value(prop->visible.expr); + if (prop->visible.tri != no) + return prop; + } + return NULL; +} + +static long long sym_get_range_val(struct symbol *sym, int base) +{ + sym_calc_value(sym); + switch (sym->type) { + case S_INT: + base = 10; + break; + case S_HEX: + base = 16; + break; + default: + break; + } + return strtoll(sym->curr.val, NULL, base); +} + +static void sym_validate_range(struct symbol *sym) +{ + struct property *prop; + int base; + long long val, val2; + char str[64]; + + switch (sym->type) { + case S_INT: + base = 10; + break; + case S_HEX: + base = 16; + break; + default: + return; + } + prop = sym_get_range_prop(sym); + if (!prop) + return; + val = strtoll(sym->curr.val, NULL, base); + val2 = sym_get_range_val(prop->expr->left.sym, base); + if (val >= val2) { + val2 = sym_get_range_val(prop->expr->right.sym, base); + if (val <= val2) + return; + } + if (sym->type == S_INT) + sprintf(str, "%lld", val2); + else + sprintf(str, "0x%llx", val2); + sym->curr.val = strdup(str); +} + +static void sym_set_changed(struct symbol *sym) +{ + struct property *prop; + + sym->flags |= SYMBOL_CHANGED; + for (prop = sym->prop; prop; prop = prop->next) { + if (prop->menu) + prop->menu->flags |= MENU_CHANGED; + } +} + +static void sym_set_all_changed(void) +{ + struct symbol *sym; + int i; + + for_all_symbols(i, sym) + sym_set_changed(sym); +} + +static void sym_calc_visibility(struct symbol *sym) +{ + struct property *prop; + tristate tri; + + /* any prompt visible? */ + tri = no; + for_all_prompts(sym, prop) { + prop->visible.tri = expr_calc_value(prop->visible.expr); + tri = EXPR_OR(tri, prop->visible.tri); + } + if (tri == mod && (sym->type != S_TRISTATE || modules_val == no)) + tri = yes; + if (sym->visible != tri) { + sym->visible = tri; + sym_set_changed(sym); + } + if (sym_is_choice_value(sym)) + return; + /* defaulting to "yes" if no explicit "depends on" are given */ + tri = yes; + if (sym->dir_dep.expr) + tri = expr_calc_value(sym->dir_dep.expr); + if (tri == mod) + tri = yes; + if (sym->dir_dep.tri != tri) { + sym->dir_dep.tri = tri; + sym_set_changed(sym); + } + tri = no; + if (sym->rev_dep.expr) + tri = expr_calc_value(sym->rev_dep.expr); + if (tri == mod && sym_get_type(sym) == S_BOOLEAN) + tri = yes; + if (sym->rev_dep.tri != tri) { + sym->rev_dep.tri = tri; + sym_set_changed(sym); + } +} + +/* + * Find the default symbol for a choice. + * First try the default values for the choice symbol + * Next locate the first visible choice value + * Return NULL if none was found + */ +struct symbol *sym_choice_default(struct symbol *sym) +{ + struct symbol *def_sym; + struct property *prop; + struct expr *e; + + /* any of the defaults visible? */ + for_all_defaults(sym, prop) { + prop->visible.tri = expr_calc_value(prop->visible.expr); + if (prop->visible.tri == no) + continue; + def_sym = prop_get_symbol(prop); + if (def_sym->visible != no) + return def_sym; + } + + /* just get the first visible value */ + prop = sym_get_choice_prop(sym); + expr_list_for_each_sym(prop->expr, e, def_sym) + if (def_sym->visible != no) + return def_sym; + + /* failed to locate any defaults */ + return NULL; +} + +static struct symbol *sym_calc_choice(struct symbol *sym) +{ + struct symbol *def_sym; + struct property *prop; + struct expr *e; + int flags; + + /* first calculate all choice values' visibilities */ + flags = sym->flags; + prop = sym_get_choice_prop(sym); + expr_list_for_each_sym(prop->expr, e, def_sym) { + sym_calc_visibility(def_sym); + if (def_sym->visible != no) + flags &= def_sym->flags; + } + + sym->flags &= flags | ~SYMBOL_DEF_USER; + + /* is the user choice visible? */ + def_sym = sym->def[S_DEF_USER].val; + if (def_sym && def_sym->visible != no) + return def_sym; + + def_sym = sym_choice_default(sym); + + if (def_sym == NULL) + /* no choice? reset tristate value */ + sym->curr.tri = no; + + return def_sym; +} + +void sym_calc_value(struct symbol *sym) +{ + struct symbol_value newval, oldval; + struct property *prop; + struct expr *e; + + if (!sym) + return; + + if (sym->flags & SYMBOL_VALID) + return; + + if (sym_is_choice_value(sym) && + sym->flags & SYMBOL_NEED_SET_CHOICE_VALUES) { + sym->flags &= ~SYMBOL_NEED_SET_CHOICE_VALUES; + prop = sym_get_choice_prop(sym); + sym_calc_value(prop_get_symbol(prop)); + } + + sym->flags |= SYMBOL_VALID; + + oldval = sym->curr; + + switch (sym->type) { + case S_INT: + case S_HEX: + case S_STRING: + newval = symbol_empty.curr; + break; + case S_BOOLEAN: + case S_TRISTATE: + newval = symbol_no.curr; + break; + default: + sym->curr.val = sym->name; + sym->curr.tri = no; + return; + } + if (!sym_is_choice_value(sym)) + sym->flags &= ~SYMBOL_WRITE; + + sym_calc_visibility(sym); + + /* set default if recursively called */ + sym->curr = newval; + + switch (sym_get_type(sym)) { + case S_BOOLEAN: + case S_TRISTATE: + if (sym_is_choice_value(sym) && sym->visible == yes) { + prop = sym_get_choice_prop(sym); + newval.tri = (prop_get_symbol(prop)->curr.val == sym) ? yes : no; + } else { + if (sym->visible != no) { + /* if the symbol is visible use the user value + * if available, otherwise try the default value + */ + sym->flags |= SYMBOL_WRITE; + if (sym_has_value(sym)) { + newval.tri = EXPR_AND(sym->def[S_DEF_USER].tri, + sym->visible); + goto calc_newval; + } + } + if (sym->rev_dep.tri != no) + sym->flags |= SYMBOL_WRITE; + if (!sym_is_choice(sym)) { + prop = sym_get_default_prop(sym); + if (prop) { + sym->flags |= SYMBOL_WRITE; + newval.tri = EXPR_AND(expr_calc_value(prop->expr), + prop->visible.tri); + } + } + calc_newval: + if (sym->dir_dep.tri == no && sym->rev_dep.tri != no) { + struct expr *e; + e = expr_simplify_unmet_dep(sym->rev_dep.expr, + sym->dir_dep.expr); + fprintf(stderr, "warning: ("); + expr_fprint(e, stderr); + fprintf(stderr, ") selects %s which has unmet direct dependencies (", + sym->name); + expr_fprint(sym->dir_dep.expr, stderr); + fprintf(stderr, ")\n"); + expr_free(e); + } + newval.tri = EXPR_OR(newval.tri, sym->rev_dep.tri); + } + if (newval.tri == mod && sym_get_type(sym) == S_BOOLEAN) + newval.tri = yes; + break; + case S_STRING: + case S_HEX: + case S_INT: + if (sym->visible != no) { + sym->flags |= SYMBOL_WRITE; + if (sym_has_value(sym)) { + newval.val = sym->def[S_DEF_USER].val; + break; + } + } + prop = sym_get_default_prop(sym); + if (prop) { + struct symbol *ds = prop_get_symbol(prop); + if (ds) { + sym->flags |= SYMBOL_WRITE; + sym_calc_value(ds); + newval.val = ds->curr.val; + } + } + break; + default: + ; + } + + sym->curr = newval; + if (sym_is_choice(sym) && newval.tri == yes) + sym->curr.val = sym_calc_choice(sym); + sym_validate_range(sym); + + if (memcmp(&oldval, &sym->curr, sizeof(oldval))) { + sym_set_changed(sym); + if (modules_sym == sym) { + sym_set_all_changed(); + modules_val = modules_sym->curr.tri; + } + } + + if (sym_is_choice(sym)) { + struct symbol *choice_sym; + + prop = sym_get_choice_prop(sym); + expr_list_for_each_sym(prop->expr, e, choice_sym) { + if ((sym->flags & SYMBOL_WRITE) && + choice_sym->visible != no) + choice_sym->flags |= SYMBOL_WRITE; + if (sym->flags & SYMBOL_CHANGED) + sym_set_changed(choice_sym); + } + } + + if (sym->flags & SYMBOL_AUTO) + sym->flags &= ~SYMBOL_WRITE; + + if (sym->flags & SYMBOL_NEED_SET_CHOICE_VALUES) + set_all_choice_values(sym); +} + +void sym_clear_all_valid(void) +{ + struct symbol *sym; + int i; + + for_all_symbols(i, sym) + sym->flags &= ~SYMBOL_VALID; + sym_add_change_count(1); + sym_calc_value(modules_sym); +} + +bool sym_tristate_within_range(struct symbol *sym, tristate val) +{ + int type = sym_get_type(sym); + + if (sym->visible == no) + return false; + + if (type != S_BOOLEAN && type != S_TRISTATE) + return false; + + if (type == S_BOOLEAN && val == mod) + return false; + if (sym->visible <= sym->rev_dep.tri) + return false; + if (sym_is_choice_value(sym) && sym->visible == yes) + return val == yes; + return val >= sym->rev_dep.tri && val <= sym->visible; +} + +bool sym_set_tristate_value(struct symbol *sym, tristate val) +{ + tristate oldval = sym_get_tristate_value(sym); + + if (oldval != val && !sym_tristate_within_range(sym, val)) + return false; + + if (!(sym->flags & SYMBOL_DEF_USER)) { + sym->flags |= SYMBOL_DEF_USER; + sym_set_changed(sym); + } + /* + * setting a choice value also resets the new flag of the choice + * symbol and all other choice values. + */ + if (sym_is_choice_value(sym) && val == yes) { + struct symbol *cs = prop_get_symbol(sym_get_choice_prop(sym)); + struct property *prop; + struct expr *e; + + cs->def[S_DEF_USER].val = sym; + cs->flags |= SYMBOL_DEF_USER; + prop = sym_get_choice_prop(cs); + for (e = prop->expr; e; e = e->left.expr) { + if (e->right.sym->visible != no) + e->right.sym->flags |= SYMBOL_DEF_USER; + } + } + + sym->def[S_DEF_USER].tri = val; + if (oldval != val) + sym_clear_all_valid(); + + return true; +} + +tristate sym_toggle_tristate_value(struct symbol *sym) +{ + tristate oldval, newval; + + oldval = newval = sym_get_tristate_value(sym); + do { + switch (newval) { + case no: + newval = mod; + break; + case mod: + newval = yes; + break; + case yes: + newval = no; + break; + } + if (sym_set_tristate_value(sym, newval)) + break; + } while (oldval != newval); + return newval; +} + +bool sym_string_valid(struct symbol *sym, const char *str) +{ + signed char ch; + + switch (sym->type) { + case S_STRING: + return true; + case S_INT: + ch = *str++; + if (ch == '-') + ch = *str++; + if (!isdigit(ch)) + return false; + if (ch == '0' && *str != 0) + return false; + while ((ch = *str++)) { + if (!isdigit(ch)) + return false; + } + return true; + case S_HEX: + if (str[0] == '0' && (str[1] == 'x' || str[1] == 'X')) + str += 2; + ch = *str++; + do { + if (!isxdigit(ch)) + return false; + } while ((ch = *str++)); + return true; + case S_BOOLEAN: + case S_TRISTATE: + switch (str[0]) { + case 'y': case 'Y': + case 'm': case 'M': + case 'n': case 'N': + return true; + } + return false; + default: + return false; + } +} + +bool sym_string_within_range(struct symbol *sym, const char *str) +{ + struct property *prop; + long long val; + + switch (sym->type) { + case S_STRING: + return sym_string_valid(sym, str); + case S_INT: + if (!sym_string_valid(sym, str)) + return false; + prop = sym_get_range_prop(sym); + if (!prop) + return true; + val = strtoll(str, NULL, 10); + return val >= sym_get_range_val(prop->expr->left.sym, 10) && + val <= sym_get_range_val(prop->expr->right.sym, 10); + case S_HEX: + if (!sym_string_valid(sym, str)) + return false; + prop = sym_get_range_prop(sym); + if (!prop) + return true; + val = strtoll(str, NULL, 16); + return val >= sym_get_range_val(prop->expr->left.sym, 16) && + val <= sym_get_range_val(prop->expr->right.sym, 16); + case S_BOOLEAN: + case S_TRISTATE: + switch (str[0]) { + case 'y': case 'Y': + return sym_tristate_within_range(sym, yes); + case 'm': case 'M': + return sym_tristate_within_range(sym, mod); + case 'n': case 'N': + return sym_tristate_within_range(sym, no); + } + return false; + default: + return false; + } +} + +bool sym_set_string_value(struct symbol *sym, const char *newval) +{ + const char *oldval; + char *val; + int size; + + switch (sym->type) { + case S_BOOLEAN: + case S_TRISTATE: + switch (newval[0]) { + case 'y': case 'Y': + return sym_set_tristate_value(sym, yes); + case 'm': case 'M': + return sym_set_tristate_value(sym, mod); + case 'n': case 'N': + return sym_set_tristate_value(sym, no); + } + return false; + default: + ; + } + + if (!sym_string_within_range(sym, newval)) + return false; + + if (!(sym->flags & SYMBOL_DEF_USER)) { + sym->flags |= SYMBOL_DEF_USER; + sym_set_changed(sym); + } + + oldval = sym->def[S_DEF_USER].val; + size = strlen(newval) + 1; + if (sym->type == S_HEX && (newval[0] != '0' || (newval[1] != 'x' && newval[1] != 'X'))) { + size += 2; + sym->def[S_DEF_USER].val = val = xmalloc(size); + *val++ = '0'; + *val++ = 'x'; + } else if (!oldval || strcmp(oldval, newval)) + sym->def[S_DEF_USER].val = val = xmalloc(size); + else + return true; + + strcpy(val, newval); + free((void *)oldval); + sym_clear_all_valid(); + + return true; +} + +/* + * Find the default value associated to a symbol. + * For tristate symbol handle the modules=n case + * in which case "m" becomes "y". + * If the symbol does not have any default then fallback + * to the fixed default values. + */ +const char *sym_get_string_default(struct symbol *sym) +{ + struct property *prop; + struct symbol *ds; + const char *str; + tristate val; + + sym_calc_visibility(sym); + sym_calc_value(modules_sym); + val = symbol_no.curr.tri; + str = symbol_empty.curr.val; + + /* If symbol has a default value look it up */ + prop = sym_get_default_prop(sym); + if (prop != NULL) { + switch (sym->type) { + case S_BOOLEAN: + case S_TRISTATE: + /* The visibility may limit the value from yes => mod */ + val = EXPR_AND(expr_calc_value(prop->expr), prop->visible.tri); + break; + default: + /* + * The following fails to handle the situation + * where a default value is further limited by + * the valid range. + */ + ds = prop_get_symbol(prop); + if (ds != NULL) { + sym_calc_value(ds); + str = (const char *)ds->curr.val; + } + } + } + + /* Handle select statements */ + val = EXPR_OR(val, sym->rev_dep.tri); + + /* transpose mod to yes if modules are not enabled */ + if (val == mod) + if (!sym_is_choice_value(sym) && modules_sym->curr.tri == no) + val = yes; + + /* transpose mod to yes if type is bool */ + if (sym->type == S_BOOLEAN && val == mod) + val = yes; + + switch (sym->type) { + case S_BOOLEAN: + case S_TRISTATE: + switch (val) { + case no: return "n"; + case mod: return "m"; + case yes: return "y"; + } + case S_INT: + case S_HEX: + return str; + case S_STRING: + return str; + case S_OTHER: + case S_UNKNOWN: + break; + } + return ""; +} + +const char *sym_get_string_value(struct symbol *sym) +{ + tristate val; + + switch (sym->type) { + case S_BOOLEAN: + case S_TRISTATE: + val = sym_get_tristate_value(sym); + switch (val) { + case no: + return "n"; + case mod: + sym_calc_value(modules_sym); + return (modules_sym->curr.tri == no) ? "n" : "m"; + case yes: + return "y"; + } + break; + default: + ; + } + return (const char *)sym->curr.val; +} + +bool sym_is_changable(struct symbol *sym) +{ + return sym->visible > sym->rev_dep.tri; +} + +static unsigned strhash(const char *s) +{ + /* fnv32 hash */ + unsigned hash = 2166136261U; + for (; *s; s++) + hash = (hash ^ *s) * 0x01000193; + return hash; +} + +struct symbol *sym_lookup(const char *name, int flags) +{ + struct symbol *symbol; + char *new_name; + int hash; + + if (name) { + if (name[0] && !name[1]) { + switch (name[0]) { + case 'y': return &symbol_yes; + case 'm': return &symbol_mod; + case 'n': return &symbol_no; + } + } + hash = strhash(name) % SYMBOL_HASHSIZE; + + for (symbol = symbol_hash[hash]; symbol; symbol = symbol->next) { + if (symbol->name && + !strcmp(symbol->name, name) && + (flags ? symbol->flags & flags + : !(symbol->flags & (SYMBOL_CONST|SYMBOL_CHOICE)))) + return symbol; + } + new_name = strdup(name); + } else { + new_name = NULL; + hash = 0; + } + + symbol = xmalloc(sizeof(*symbol)); + memset(symbol, 0, sizeof(*symbol)); + symbol->name = new_name; + symbol->type = S_UNKNOWN; + symbol->flags |= flags; + + symbol->next = symbol_hash[hash]; + symbol_hash[hash] = symbol; + + return symbol; +} + +struct symbol *sym_find(const char *name) +{ + struct symbol *symbol = NULL; + int hash = 0; + + if (!name) + return NULL; + + if (name[0] && !name[1]) { + switch (name[0]) { + case 'y': return &symbol_yes; + case 'm': return &symbol_mod; + case 'n': return &symbol_no; + } + } + hash = strhash(name) % SYMBOL_HASHSIZE; + + for (symbol = symbol_hash[hash]; symbol; symbol = symbol->next) { + if (symbol->name && + !strcmp(symbol->name, name) && + !(symbol->flags & SYMBOL_CONST)) + break; + } + + return symbol; +} + +/* + * Expand symbol's names embedded in the string given in argument. Symbols' + * name to be expanded shall be prefixed by a '$'. Unknown symbol expands to + * the empty string. + */ +const char *sym_expand_string_value(const char *in) +{ + const char *src; + char *res; + size_t reslen; + + reslen = strlen(in) + 1; + res = xmalloc(reslen); + res[0] = '\0'; + + while ((src = strchr(in, '$'))) { + char *p, name[SYMBOL_MAXLENGTH]; + const char *symval = ""; + struct symbol *sym; + size_t newlen; + + strncat(res, in, src - in); + src++; + + p = name; + while (isalnum(*src) || *src == '_') + *p++ = *src++; + *p = '\0'; + + sym = sym_find(name); + if (sym != NULL) { + sym_calc_value(sym); + symval = sym_get_string_value(sym); + } + + newlen = strlen(res) + strlen(symval) + strlen(src) + 1; + if (newlen > reslen) { + reslen = newlen; + res = realloc(res, reslen); + } + + strcat(res, symval); + in = src; + } + strcat(res, in); + + return res; +} + +const char *sym_escape_string_value(const char *in) +{ + const char *p; + size_t reslen; + char *res; + size_t l; + + reslen = strlen(in) + strlen("\"\"") + 1; + + p = in; + for (;;) { + l = strcspn(p, "\"\\"); + p += l; + + if (p[0] == '\0') + break; + + reslen++; + p++; + } + + res = xmalloc(reslen); + res[0] = '\0'; + + strcat(res, "\""); + + p = in; + for (;;) { + l = strcspn(p, "\"\\"); + strncat(res, p, l); + p += l; + + if (p[0] == '\0') + break; + + strcat(res, "\\"); + strncat(res, p++, 1); + } + + strcat(res, "\""); + return res; +} + +struct sym_match { + struct symbol *sym; + off_t so, eo; +}; + +/* Compare matched symbols as thus: + * - first, symbols that match exactly + * - then, alphabetical sort + */ +static int sym_rel_comp(const void *sym1, const void *sym2) +{ + const struct sym_match *s1 = sym1; + const struct sym_match *s2 = sym2; + int exact1, exact2; + + /* Exact match: + * - if matched length on symbol s1 is the length of that symbol, + * then this symbol should come first; + * - if matched length on symbol s2 is the length of that symbol, + * then this symbol should come first. + * Note: since the search can be a regexp, both symbols may match + * exactly; if this is the case, we can't decide which comes first, + * and we fallback to sorting alphabetically. + */ + exact1 = (s1->eo - s1->so) == strlen(s1->sym->name); + exact2 = (s2->eo - s2->so) == strlen(s2->sym->name); + if (exact1 && !exact2) + return -1; + if (!exact1 && exact2) + return 1; + + /* As a fallback, sort symbols alphabetically */ + return strcmp(s1->sym->name, s2->sym->name); +} + +struct symbol **sym_re_search(const char *pattern) +{ + struct symbol *sym, **sym_arr = NULL; + struct sym_match *sym_match_arr = NULL; + int i, cnt, size; + regex_t re; + regmatch_t match[1]; + + cnt = size = 0; + /* Skip if empty */ + if (strlen(pattern) == 0) + return NULL; + if (regcomp(&re, pattern, REG_EXTENDED|REG_ICASE)) + return NULL; + + for_all_symbols(i, sym) { + if (sym->flags & SYMBOL_CONST || !sym->name) + continue; + if (regexec(&re, sym->name, 1, match, 0)) + continue; + if (cnt >= size) { + void *tmp; + size += 16; + tmp = realloc(sym_match_arr, size * sizeof(struct sym_match)); + if (!tmp) + goto sym_re_search_free; + sym_match_arr = tmp; + } + sym_calc_value(sym); + /* As regexec returned 0, we know we have a match, so + * we can use match[0].rm_[se]o without further checks + */ + sym_match_arr[cnt].so = match[0].rm_so; + sym_match_arr[cnt].eo = match[0].rm_eo; + sym_match_arr[cnt++].sym = sym; + } + if (sym_match_arr) { + qsort(sym_match_arr, cnt, sizeof(struct sym_match), sym_rel_comp); + sym_arr = malloc((cnt+1) * sizeof(struct symbol)); + if (!sym_arr) + goto sym_re_search_free; + for (i = 0; i < cnt; i++) + sym_arr[i] = sym_match_arr[i].sym; + sym_arr[cnt] = NULL; + } +sym_re_search_free: + /* sym_match_arr can be NULL if no match, but free(NULL) is OK */ + free(sym_match_arr); + regfree(&re); + + return sym_arr; +} + +/* + * When we check for recursive dependencies we use a stack to save + * current state so we can print out relevant info to user. + * The entries are located on the call stack so no need to free memory. + * Note insert() remove() must always match to properly clear the stack. + */ +static struct dep_stack { + struct dep_stack *prev, *next; + struct symbol *sym; + struct property *prop; + struct expr *expr; +} *check_top; + +static void dep_stack_insert(struct dep_stack *stack, struct symbol *sym) +{ + memset(stack, 0, sizeof(*stack)); + if (check_top) + check_top->next = stack; + stack->prev = check_top; + stack->sym = sym; + check_top = stack; +} + +static void dep_stack_remove(void) +{ + check_top = check_top->prev; + if (check_top) + check_top->next = NULL; +} + +/* + * Called when we have detected a recursive dependency. + * check_top point to the top of the stact so we use + * the ->prev pointer to locate the bottom of the stack. + */ +static void sym_check_print_recursive(struct symbol *last_sym) +{ + struct dep_stack *stack; + struct symbol *sym, *next_sym; + struct menu *menu = NULL; + struct property *prop; + struct dep_stack cv_stack; + + if (sym_is_choice_value(last_sym)) { + dep_stack_insert(&cv_stack, last_sym); + last_sym = prop_get_symbol(sym_get_choice_prop(last_sym)); + } + + for (stack = check_top; stack != NULL; stack = stack->prev) + if (stack->sym == last_sym) + break; + if (!stack) { + fprintf(stderr, "unexpected recursive dependency error\n"); + return; + } + + for (; stack; stack = stack->next) { + sym = stack->sym; + next_sym = stack->next ? stack->next->sym : last_sym; + prop = stack->prop; + if (prop == NULL) + prop = stack->sym->prop; + + /* for choice values find the menu entry (used below) */ + if (sym_is_choice(sym) || sym_is_choice_value(sym)) { + for (prop = sym->prop; prop; prop = prop->next) { + menu = prop->menu; + if (prop->menu) + break; + } + } + if (stack->sym == last_sym) + fprintf(stderr, "%s:%d:error: recursive dependency detected!\n", + prop->file->name, prop->lineno); + fprintf(stderr, "For a resolution refer to Documentation/kbuild/kconfig-language.txt\n"); + fprintf(stderr, "subsection \"Kconfig recursive dependency limitations\"\n"); + if (stack->expr) { + fprintf(stderr, "%s:%d:\tsymbol %s %s value contains %s\n", + prop->file->name, prop->lineno, + sym->name ? sym->name : "", + prop_get_type_name(prop->type), + next_sym->name ? next_sym->name : ""); + } else if (stack->prop) { + fprintf(stderr, "%s:%d:\tsymbol %s depends on %s\n", + prop->file->name, prop->lineno, + sym->name ? sym->name : "", + next_sym->name ? next_sym->name : ""); + } else if (sym_is_choice(sym)) { + fprintf(stderr, "%s:%d:\tchoice %s contains symbol %s\n", + menu->file->name, menu->lineno, + sym->name ? sym->name : "", + next_sym->name ? next_sym->name : ""); + } else if (sym_is_choice_value(sym)) { + fprintf(stderr, "%s:%d:\tsymbol %s is part of choice %s\n", + menu->file->name, menu->lineno, + sym->name ? sym->name : "", + next_sym->name ? next_sym->name : ""); + } else { + fprintf(stderr, "%s:%d:\tsymbol %s is selected by %s\n", + prop->file->name, prop->lineno, + sym->name ? sym->name : "", + next_sym->name ? next_sym->name : ""); + } + } + + if (check_top == &cv_stack) + dep_stack_remove(); +} + +static struct symbol *sym_check_expr_deps(struct expr *e) +{ + struct symbol *sym; + + if (!e) + return NULL; + switch (e->type) { + case E_OR: + case E_AND: + sym = sym_check_expr_deps(e->left.expr); + if (sym) + return sym; + return sym_check_expr_deps(e->right.expr); + case E_NOT: + return sym_check_expr_deps(e->left.expr); + case E_EQUAL: + case E_GEQ: + case E_GTH: + case E_LEQ: + case E_LTH: + case E_UNEQUAL: + sym = sym_check_deps(e->left.sym); + if (sym) + return sym; + return sym_check_deps(e->right.sym); + case E_SYMBOL: + return sym_check_deps(e->left.sym); + default: + break; + } + printf("Oops! How to check %d?\n", e->type); + return NULL; +} + +/* return NULL when dependencies are OK */ +static struct symbol *sym_check_sym_deps(struct symbol *sym) +{ + struct symbol *sym2; + struct property *prop; + struct dep_stack stack; + + dep_stack_insert(&stack, sym); + + sym2 = sym_check_expr_deps(sym->rev_dep.expr); + if (sym2) + goto out; + + for (prop = sym->prop; prop; prop = prop->next) { + if (prop->type == P_CHOICE || prop->type == P_SELECT) + continue; + stack.prop = prop; + sym2 = sym_check_expr_deps(prop->visible.expr); + if (sym2) + break; + if (prop->type != P_DEFAULT || sym_is_choice(sym)) + continue; + stack.expr = prop->expr; + sym2 = sym_check_expr_deps(prop->expr); + if (sym2) + break; + stack.expr = NULL; + } + +out: + dep_stack_remove(); + + return sym2; +} + +static struct symbol *sym_check_choice_deps(struct symbol *choice) +{ + struct symbol *sym, *sym2; + struct property *prop; + struct expr *e; + struct dep_stack stack; + + dep_stack_insert(&stack, choice); + + prop = sym_get_choice_prop(choice); + expr_list_for_each_sym(prop->expr, e, sym) + sym->flags |= (SYMBOL_CHECK | SYMBOL_CHECKED); + + choice->flags |= (SYMBOL_CHECK | SYMBOL_CHECKED); + sym2 = sym_check_sym_deps(choice); + choice->flags &= ~SYMBOL_CHECK; + if (sym2) + goto out; + + expr_list_for_each_sym(prop->expr, e, sym) { + sym2 = sym_check_sym_deps(sym); + if (sym2) + break; + } +out: + expr_list_for_each_sym(prop->expr, e, sym) + sym->flags &= ~SYMBOL_CHECK; + + if (sym2 && sym_is_choice_value(sym2) && + prop_get_symbol(sym_get_choice_prop(sym2)) == choice) + sym2 = choice; + + dep_stack_remove(); + + return sym2; +} + +struct symbol *sym_check_deps(struct symbol *sym) +{ + struct symbol *sym2; + struct property *prop; + + if (sym->flags & SYMBOL_CHECK) { + sym_check_print_recursive(sym); + return sym; + } + if (sym->flags & SYMBOL_CHECKED) + return NULL; + + if (sym_is_choice_value(sym)) { + struct dep_stack stack; + + /* for choice groups start the check with main choice symbol */ + dep_stack_insert(&stack, sym); + prop = sym_get_choice_prop(sym); + sym2 = sym_check_deps(prop_get_symbol(prop)); + dep_stack_remove(); + } else if (sym_is_choice(sym)) { + sym2 = sym_check_choice_deps(sym); + } else { + sym->flags |= (SYMBOL_CHECK | SYMBOL_CHECKED); + sym2 = sym_check_sym_deps(sym); + sym->flags &= ~SYMBOL_CHECK; + } + + if (sym2 && sym2 == sym) + sym2 = NULL; + + return sym2; +} + +struct property *prop_alloc(enum prop_type type, struct symbol *sym) +{ + struct property *prop; + struct property **propp; + + prop = xmalloc(sizeof(*prop)); + memset(prop, 0, sizeof(*prop)); + prop->type = type; + prop->sym = sym; + prop->file = current_file; + prop->lineno = zconf_lineno(); + + /* append property to the prop list of symbol */ + if (sym) { + for (propp = &sym->prop; *propp; propp = &(*propp)->next) + ; + *propp = prop; + } + + return prop; +} + +struct symbol *prop_get_symbol(struct property *prop) +{ + if (prop->expr && (prop->expr->type == E_SYMBOL || + prop->expr->type == E_LIST)) + return prop->expr->left.sym; + return NULL; +} + +const char *prop_get_type_name(enum prop_type type) +{ + switch (type) { + case P_PROMPT: + return "prompt"; + case P_ENV: + return "env"; + case P_COMMENT: + return "comment"; + case P_MENU: + return "menu"; + case P_DEFAULT: + return "default"; + case P_CHOICE: + return "choice"; + case P_SELECT: + return "select"; + case P_RANGE: + return "range"; + case P_SYMBOL: + return "symbol"; + case P_UNKNOWN: + break; + } + return "unknown"; +} + +static void prop_add_env(const char *env) +{ + struct symbol *sym, *sym2; + struct property *prop; + char *p; + + sym = current_entry->sym; + sym->flags |= SYMBOL_AUTO; + for_all_properties(sym, prop, P_ENV) { + sym2 = prop_get_symbol(prop); + if (strcmp(sym2->name, env)) + menu_warn(current_entry, "redefining environment symbol from %s", + sym2->name); + return; + } + + prop = prop_alloc(P_ENV, sym); + prop->expr = expr_alloc_symbol(sym_lookup(env, SYMBOL_CONST)); + + sym_env_list = expr_alloc_one(E_LIST, sym_env_list); + sym_env_list->right.sym = sym; + + p = getenv(env); + if (p) + sym_add_default(sym, p); + else + menu_warn(current_entry, "environment variable %s undefined", env); +} diff --git a/tools/kconfig/util.c b/tools/kconfig/util.c new file mode 100644 index 0000000000..0e76042473 --- /dev/null +++ b/tools/kconfig/util.c @@ -0,0 +1,147 @@ +/* + * Copyright (C) 2002-2005 Roman Zippel + * Copyright (C) 2002-2005 Sam Ravnborg + * + * Released under the terms of the GNU GPL v2.0. + */ + +#include +#include +#include +#include "lkc.h" + +/* file already present in list? If not add it */ +struct file *file_lookup(const char *name) +{ + struct file *file; + const char *file_name = sym_expand_string_value(name); + + for (file = file_list; file; file = file->next) { + if (!strcmp(name, file->name)) { + free((void *)file_name); + return file; + } + } + + file = xmalloc(sizeof(*file)); + memset(file, 0, sizeof(*file)); + file->name = file_name; + file->next = file_list; + file_list = file; + return file; +} + +/* write a dependency file as used by kbuild to track dependencies */ +int file_write_dep(const char *name) +{ + struct symbol *sym, *env_sym; + struct expr *e; + struct file *file; + FILE *out; + + if (!name) + name = ".kconfig.d"; + out = fopen("..config.tmp", "w"); + if (!out) + return 1; + fprintf(out, "deps_config := \\\n"); + for (file = file_list; file; file = file->next) { + if (file->next) + fprintf(out, "\t%s \\\n", file->name); + else + fprintf(out, "\t%s\n", file->name); + } + fprintf(out, "\n%s: \\\n" + "\t$(deps_config)\n\n", conf_get_autoconfig_name()); + + expr_list_for_each_sym(sym_env_list, e, sym) { + struct property *prop; + const char *value; + + prop = sym_get_env_prop(sym); + env_sym = prop_get_symbol(prop); + if (!env_sym) + continue; + value = getenv(env_sym->name); + if (!value) + value = ""; + fprintf(out, "ifneq \"$(%s)\" \"%s\"\n", env_sym->name, value); + fprintf(out, "%s: FORCE\n", conf_get_autoconfig_name()); + fprintf(out, "endif\n"); + } + + fprintf(out, "\n$(deps_config): ;\n"); + fclose(out); + rename("..config.tmp", name); + return 0; +} + + +/* Allocate initial growable string */ +struct gstr str_new(void) +{ + struct gstr gs; + gs.s = xmalloc(sizeof(char) * 64); + gs.len = 64; + gs.max_width = 0; + strcpy(gs.s, "\0"); + return gs; +} + +/* Free storage for growable string */ +void str_free(struct gstr *gs) +{ + if (gs->s) + free(gs->s); + gs->s = NULL; + gs->len = 0; +} + +/* Append to growable string */ +void str_append(struct gstr *gs, const char *s) +{ + size_t l; + if (s) { + l = strlen(gs->s) + strlen(s) + 1; + if (l > gs->len) { + gs->s = realloc(gs->s, l); + gs->len = l; + } + strcat(gs->s, s); + } +} + +/* Append printf formatted string to growable string */ +void str_printf(struct gstr *gs, const char *fmt, ...) +{ + va_list ap; + char s[10000]; /* big enough... */ + va_start(ap, fmt); + vsnprintf(s, sizeof(s), fmt, ap); + str_append(gs, s); + va_end(ap); +} + +/* Retrieve value of growable string */ +const char *str_get(struct gstr *gs) +{ + return gs->s; +} + +void *xmalloc(size_t size) +{ + void *p = malloc(size); + if (p) + return p; + fprintf(stderr, "Out of memory.\n"); + exit(1); +} + +void *xcalloc(size_t nmemb, size_t size) +{ + void *p = calloc(nmemb, size); + if (p) + return p; + fprintf(stderr, "Out of memory.\n"); + exit(1); +} diff --git a/tools/kconfig/zconf.gperf b/tools/kconfig/zconf.gperf new file mode 100644 index 0000000000..ac498f01b4 --- /dev/null +++ b/tools/kconfig/zconf.gperf @@ -0,0 +1,49 @@ +%language=ANSI-C +%define hash-function-name kconf_id_hash +%define lookup-function-name kconf_id_lookup +%define string-pool-name kconf_id_strings +%compare-strncmp +%enum +%pic +%struct-type + +struct kconf_id; + +static const struct kconf_id *kconf_id_lookup(register const char *str, register unsigned int len); + +%% +mainmenu, T_MAINMENU, TF_COMMAND +menu, T_MENU, TF_COMMAND +endmenu, T_ENDMENU, TF_COMMAND +source, T_SOURCE, TF_COMMAND +choice, T_CHOICE, TF_COMMAND +endchoice, T_ENDCHOICE, TF_COMMAND +comment, T_COMMENT, TF_COMMAND +config, T_CONFIG, TF_COMMAND +menuconfig, T_MENUCONFIG, TF_COMMAND +help, T_HELP, TF_COMMAND +---help---, T_HELP, TF_COMMAND +if, T_IF, TF_COMMAND|TF_PARAM +endif, T_ENDIF, TF_COMMAND +depends, T_DEPENDS, TF_COMMAND +optional, T_OPTIONAL, TF_COMMAND +default, T_DEFAULT, TF_COMMAND, S_UNKNOWN +prompt, T_PROMPT, TF_COMMAND +tristate, T_TYPE, TF_COMMAND, S_TRISTATE +def_tristate, T_DEFAULT, TF_COMMAND, S_TRISTATE +bool, T_TYPE, TF_COMMAND, S_BOOLEAN +boolean, T_TYPE, TF_COMMAND, S_BOOLEAN +def_bool, T_DEFAULT, TF_COMMAND, S_BOOLEAN +int, T_TYPE, TF_COMMAND, S_INT +hex, T_TYPE, TF_COMMAND, S_HEX +string, T_TYPE, TF_COMMAND, S_STRING +select, T_SELECT, TF_COMMAND +range, T_RANGE, TF_COMMAND +visible, T_VISIBLE, TF_COMMAND +option, T_OPTION, TF_COMMAND +on, T_ON, TF_PARAM +modules, T_OPT_MODULES, TF_OPTION +defconfig_list, T_OPT_DEFCONFIG_LIST,TF_OPTION +env, T_OPT_ENV, TF_OPTION +allnoconfig_y, T_OPT_ALLNOCONFIG_Y,TF_OPTION +%% diff --git a/tools/kconfig/zconf.l b/tools/kconfig/zconf.l new file mode 100644 index 0000000000..8c787b5095 --- /dev/null +++ b/tools/kconfig/zconf.l @@ -0,0 +1,390 @@ +%option nostdinit noyywrap never-interactive full ecs +%option 8bit nodefault perf-report perf-report +%option noinput +%x COMMAND HELP STRING PARAM +%{ +/* + * Copyright (C) 2002 Roman Zippel + * Released under the terms of the GNU GPL v2.0. + */ + +#include +#include +#include +#include +#include +#include + +#include "lkc.h" + +#define START_STRSIZE 16 + +static struct { + struct file *file; + int lineno; +} current_pos; + +static char *text; +static int text_size, text_asize; + +struct buffer { + struct buffer *parent; + YY_BUFFER_STATE state; +}; + +struct buffer *current_buf; + +static int last_ts, first_ts; + +static void zconf_endhelp(void); +static void zconf_endfile(void); + +static void new_string(void) +{ + text = xmalloc(START_STRSIZE); + text_asize = START_STRSIZE; + text_size = 0; + *text = 0; +} + +static void append_string(const char *str, int size) +{ + int new_size = text_size + size + 1; + if (new_size > text_asize) { + new_size += START_STRSIZE - 1; + new_size &= -START_STRSIZE; + text = realloc(text, new_size); + text_asize = new_size; + } + memcpy(text + text_size, str, size); + text_size += size; + text[text_size] = 0; +} + +static void alloc_string(const char *str, int size) +{ + text = xmalloc(size + 1); + memcpy(text, str, size); + text[size] = 0; +} + +static void warn_ignored_character(char chr) +{ + fprintf(stderr, + "%s:%d:warning: ignoring unsupported character '%c'\n", + zconf_curname(), zconf_lineno(), chr); +} +%} + +n [A-Za-z0-9_-] + +%% + int str = 0; + int ts, i; + +[ \t]*#.*\n | +[ \t]*\n { + current_file->lineno++; + return T_EOL; +} +[ \t]*#.* + + +[ \t]+ { + BEGIN(COMMAND); +} + +. { + unput(yytext[0]); + BEGIN(COMMAND); +} + + +{ + {n}+ { + const struct kconf_id *id = kconf_id_lookup(yytext, yyleng); + BEGIN(PARAM); + current_pos.file = current_file; + current_pos.lineno = current_file->lineno; + if (id && id->flags & TF_COMMAND) { + zconflval.id = id; + return id->token; + } + alloc_string(yytext, yyleng); + zconflval.string = text; + return T_WORD; + } + . warn_ignored_character(*yytext); + \n { + BEGIN(INITIAL); + current_file->lineno++; + return T_EOL; + } +} + +{ + "&&" return T_AND; + "||" return T_OR; + "(" return T_OPEN_PAREN; + ")" return T_CLOSE_PAREN; + "!" return T_NOT; + "=" return T_EQUAL; + "!=" return T_UNEQUAL; + "<=" return T_LESS_EQUAL; + ">=" return T_GREATER_EQUAL; + "<" return T_LESS; + ">" return T_GREATER; + \"|\' { + str = yytext[0]; + new_string(); + BEGIN(STRING); + } + \n BEGIN(INITIAL); current_file->lineno++; return T_EOL; + ({n}|[/.])+ { + const struct kconf_id *id = kconf_id_lookup(yytext, yyleng); + if (id && id->flags & TF_PARAM) { + zconflval.id = id; + return id->token; + } + alloc_string(yytext, yyleng); + zconflval.string = text; + return T_WORD; + } + #.* /* comment */ + \\\n current_file->lineno++; + [[:blank:]]+ + . warn_ignored_character(*yytext); + <> { + BEGIN(INITIAL); + } +} + +{ + [^'"\\\n]+/\n { + append_string(yytext, yyleng); + zconflval.string = text; + return T_WORD_QUOTE; + } + [^'"\\\n]+ { + append_string(yytext, yyleng); + } + \\.?/\n { + append_string(yytext + 1, yyleng - 1); + zconflval.string = text; + return T_WORD_QUOTE; + } + \\.? { + append_string(yytext + 1, yyleng - 1); + } + \'|\" { + if (str == yytext[0]) { + BEGIN(PARAM); + zconflval.string = text; + return T_WORD_QUOTE; + } else + append_string(yytext, 1); + } + \n { + printf("%s:%d:warning: multi-line strings not supported\n", zconf_curname(), zconf_lineno()); + current_file->lineno++; + BEGIN(INITIAL); + return T_EOL; + } + <> { + BEGIN(INITIAL); + } +} + +{ + [ \t]+ { + ts = 0; + for (i = 0; i < yyleng; i++) { + if (yytext[i] == '\t') + ts = (ts & ~7) + 8; + else + ts++; + } + last_ts = ts; + if (first_ts) { + if (ts < first_ts) { + zconf_endhelp(); + return T_HELPTEXT; + } + ts -= first_ts; + while (ts > 8) { + append_string(" ", 8); + ts -= 8; + } + append_string(" ", ts); + } + } + [ \t]*\n/[^ \t\n] { + current_file->lineno++; + zconf_endhelp(); + return T_HELPTEXT; + } + [ \t]*\n { + current_file->lineno++; + append_string("\n", 1); + } + [^ \t\n].* { + while (yyleng) { + if ((yytext[yyleng-1] != ' ') && (yytext[yyleng-1] != '\t')) + break; + yyleng--; + } + append_string(yytext, yyleng); + if (!first_ts) + first_ts = last_ts; + } + <> { + zconf_endhelp(); + return T_HELPTEXT; + } +} + +<> { + if (current_file) { + zconf_endfile(); + return T_EOL; + } + fclose(yyin); + yyterminate(); +} + +%% +void zconf_starthelp(void) +{ + new_string(); + last_ts = first_ts = 0; + BEGIN(HELP); +} + +static void zconf_endhelp(void) +{ + zconflval.string = text; + BEGIN(INITIAL); +} + + +/* + * Try to open specified file with following names: + * ./name + * $(srctree)/name + * The latter is used when srctree is separate from objtree + * when compiling the kernel. + * Return NULL if file is not found. + */ +FILE *zconf_fopen(const char *name) +{ + char *env, fullname[PATH_MAX+1]; + FILE *f; + + f = fopen(name, "r"); + if (!f && name != NULL && name[0] != '/') { + env = getenv(SRCTREE); + if (env) { + sprintf(fullname, "%s/%s", env, name); + f = fopen(fullname, "r"); + } + } + return f; +} + +void zconf_initscan(const char *name) +{ + yyin = zconf_fopen(name); + if (!yyin) { + printf("can't find file %s\n", name); + exit(1); + } + + current_buf = xmalloc(sizeof(*current_buf)); + memset(current_buf, 0, sizeof(*current_buf)); + + current_file = file_lookup(name); + current_file->lineno = 1; +} + +void zconf_nextfile(const char *name) +{ + struct file *iter; + struct file *file = file_lookup(name); + struct buffer *buf = xmalloc(sizeof(*buf)); + memset(buf, 0, sizeof(*buf)); + + current_buf->state = YY_CURRENT_BUFFER; + yyin = zconf_fopen(file->name); + if (!yyin) { + printf("%s:%d: can't open file \"%s\"\n", + zconf_curname(), zconf_lineno(), file->name); + exit(1); + } + yy_switch_to_buffer(yy_create_buffer(yyin, YY_BUF_SIZE)); + buf->parent = current_buf; + current_buf = buf; + + for (iter = current_file->parent; iter; iter = iter->parent ) { + if (!strcmp(current_file->name,iter->name) ) { + printf("%s:%d: recursive inclusion detected. " + "Inclusion path:\n current file : '%s'\n", + zconf_curname(), zconf_lineno(), + zconf_curname()); + iter = current_file->parent; + while (iter && \ + strcmp(iter->name,current_file->name)) { + printf(" included from: '%s:%d'\n", + iter->name, iter->lineno-1); + iter = iter->parent; + } + if (iter) + printf(" included from: '%s:%d'\n", + iter->name, iter->lineno+1); + exit(1); + } + } + file->lineno = 1; + file->parent = current_file; + current_file = file; +} + +void zconf_nextfiles(const char *wildcard) +{ + wordexp_t p; + char **w; + int i; + + wordexp(wildcard, &p, 0); + w = p.we_wordv; + + for (i = p.we_wordc - 1; i >= 0; i--) + zconf_nextfile(w[i]); + + wordfree(&p); +} + +static void zconf_endfile(void) +{ + struct buffer *parent; + + current_file = current_file->parent; + + parent = current_buf->parent; + if (parent) { + fclose(yyin); + yy_delete_buffer(YY_CURRENT_BUFFER); + yy_switch_to_buffer(parent->state); + } + free(current_buf); + current_buf = parent; +} + +int zconf_lineno(void) +{ + return current_pos.lineno; +} + +const char *zconf_curname(void) +{ + return current_pos.file ? current_pos.file->name : ""; +} diff --git a/tools/kconfig/zconf.y b/tools/kconfig/zconf.y new file mode 100644 index 0000000000..77c7133132 --- /dev/null +++ b/tools/kconfig/zconf.y @@ -0,0 +1,745 @@ +%{ +/* + * Copyright (C) 2002 Roman Zippel + * Released under the terms of the GNU GPL v2.0. + */ + +#include +#include +#include +#include +#include +#include + +#include "lkc.h" + +#define printd(mask, fmt...) if (cdebug & (mask)) printf(fmt) + +#define PRINTD 0x0001 +#define DEBUG_PARSE 0x0002 + +int cdebug = PRINTD; + +extern int zconflex(void); +static void zconfprint(const char *err, ...); +static void zconf_error(const char *err, ...); +static void zconferror(const char *err); +static bool zconf_endtoken(const struct kconf_id *id, int starttoken, int endtoken); + +struct symbol *symbol_hash[SYMBOL_HASHSIZE]; + +static struct menu *current_menu, *current_entry; + +%} +%expect 30 + +%union +{ + char *string; + struct file *file; + struct symbol *symbol; + struct expr *expr; + struct menu *menu; + const struct kconf_id *id; +} + +%token T_MAINMENU +%token T_MENU +%token T_ENDMENU +%token T_SOURCE +%token T_CHOICE +%token T_ENDCHOICE +%token T_COMMENT +%token T_CONFIG +%token T_MENUCONFIG +%token T_HELP +%token T_HELPTEXT +%token T_IF +%token T_ENDIF +%token T_DEPENDS +%token T_OPTIONAL +%token T_PROMPT +%token T_TYPE +%token T_DEFAULT +%token T_SELECT +%token T_RANGE +%token T_VISIBLE +%token T_OPTION +%token T_ON +%token T_WORD +%token T_WORD_QUOTE +%token T_UNEQUAL +%token T_LESS +%token T_LESS_EQUAL +%token T_GREATER +%token T_GREATER_EQUAL +%token T_CLOSE_PAREN +%token T_OPEN_PAREN +%token T_EOL + +%left T_OR +%left T_AND +%left T_EQUAL T_UNEQUAL +%left T_LESS T_LESS_EQUAL T_GREATER T_GREATER_EQUAL +%nonassoc T_NOT + +%type prompt +%type symbol +%type expr +%type if_expr +%type end +%type option_name +%type if_entry menu_entry choice_entry +%type symbol_option_arg word_opt + +%destructor { + fprintf(stderr, "%s:%d: missing end statement for this entry\n", + $$->file->name, $$->lineno); + if (current_menu == $$) + menu_end_menu(); +} if_entry menu_entry choice_entry + +%{ +/* Include zconf.hash.c here so it can see the token constants. */ +#include "zconf.hash.c" +%} + +%% +input: nl start | start; + +start: mainmenu_stmt stmt_list | stmt_list; + +stmt_list: + /* empty */ + | stmt_list common_stmt + | stmt_list choice_stmt + | stmt_list menu_stmt + | stmt_list end { zconf_error("unexpected end statement"); } + | stmt_list T_WORD error T_EOL { zconf_error("unknown statement \"%s\"", $2); } + | stmt_list option_name error T_EOL +{ + zconf_error("unexpected option \"%s\"", kconf_id_strings + $2->name); +} + | stmt_list error T_EOL { zconf_error("invalid statement"); } +; + +option_name: + T_DEPENDS | T_PROMPT | T_TYPE | T_SELECT | T_OPTIONAL | T_RANGE | T_DEFAULT | T_VISIBLE +; + +common_stmt: + T_EOL + | if_stmt + | comment_stmt + | config_stmt + | menuconfig_stmt + | source_stmt +; + +option_error: + T_WORD error T_EOL { zconf_error("unknown option \"%s\"", $1); } + | error T_EOL { zconf_error("invalid option"); } +; + + +/* config/menuconfig entry */ + +config_entry_start: T_CONFIG T_WORD T_EOL +{ + struct symbol *sym = sym_lookup($2, 0); + sym->flags |= SYMBOL_OPTIONAL; + menu_add_entry(sym); + printd(DEBUG_PARSE, "%s:%d:config %s\n", zconf_curname(), zconf_lineno(), $2); +}; + +config_stmt: config_entry_start config_option_list +{ + menu_end_entry(); + printd(DEBUG_PARSE, "%s:%d:endconfig\n", zconf_curname(), zconf_lineno()); +}; + +menuconfig_entry_start: T_MENUCONFIG T_WORD T_EOL +{ + struct symbol *sym = sym_lookup($2, 0); + sym->flags |= SYMBOL_OPTIONAL; + menu_add_entry(sym); + printd(DEBUG_PARSE, "%s:%d:menuconfig %s\n", zconf_curname(), zconf_lineno(), $2); +}; + +menuconfig_stmt: menuconfig_entry_start config_option_list +{ + if (current_entry->prompt) + current_entry->prompt->type = P_MENU; + else + zconfprint("warning: menuconfig statement without prompt"); + menu_end_entry(); + printd(DEBUG_PARSE, "%s:%d:endconfig\n", zconf_curname(), zconf_lineno()); +}; + +config_option_list: + /* empty */ + | config_option_list config_option + | config_option_list symbol_option + | config_option_list depends + | config_option_list help + | config_option_list option_error + | config_option_list T_EOL +; + +config_option: T_TYPE prompt_stmt_opt T_EOL +{ + menu_set_type($1->stype); + printd(DEBUG_PARSE, "%s:%d:type(%u)\n", + zconf_curname(), zconf_lineno(), + $1->stype); +}; + +config_option: T_PROMPT prompt if_expr T_EOL +{ + menu_add_prompt(P_PROMPT, $2, $3); + printd(DEBUG_PARSE, "%s:%d:prompt\n", zconf_curname(), zconf_lineno()); +}; + +config_option: T_DEFAULT expr if_expr T_EOL +{ + menu_add_expr(P_DEFAULT, $2, $3); + if ($1->stype != S_UNKNOWN) + menu_set_type($1->stype); + printd(DEBUG_PARSE, "%s:%d:default(%u)\n", + zconf_curname(), zconf_lineno(), + $1->stype); +}; + +config_option: T_SELECT T_WORD if_expr T_EOL +{ + menu_add_symbol(P_SELECT, sym_lookup($2, 0), $3); + printd(DEBUG_PARSE, "%s:%d:select\n", zconf_curname(), zconf_lineno()); +}; + +config_option: T_RANGE symbol symbol if_expr T_EOL +{ + menu_add_expr(P_RANGE, expr_alloc_comp(E_RANGE,$2, $3), $4); + printd(DEBUG_PARSE, "%s:%d:range\n", zconf_curname(), zconf_lineno()); +}; + +symbol_option: T_OPTION symbol_option_list T_EOL +; + +symbol_option_list: + /* empty */ + | symbol_option_list T_WORD symbol_option_arg +{ + const struct kconf_id *id = kconf_id_lookup($2, strlen($2)); + if (id && id->flags & TF_OPTION) + menu_add_option(id->token, $3); + else + zconfprint("warning: ignoring unknown option %s", $2); + free($2); +}; + +symbol_option_arg: + /* empty */ { $$ = NULL; } + | T_EQUAL prompt { $$ = $2; } +; + +/* choice entry */ + +choice: T_CHOICE word_opt T_EOL +{ + struct symbol *sym = sym_lookup($2, SYMBOL_CHOICE); + sym->flags |= SYMBOL_AUTO; + menu_add_entry(sym); + menu_add_expr(P_CHOICE, NULL, NULL); + printd(DEBUG_PARSE, "%s:%d:choice\n", zconf_curname(), zconf_lineno()); +}; + +choice_entry: choice choice_option_list +{ + $$ = menu_add_menu(); +}; + +choice_end: end +{ + if (zconf_endtoken($1, T_CHOICE, T_ENDCHOICE)) { + menu_end_menu(); + printd(DEBUG_PARSE, "%s:%d:endchoice\n", zconf_curname(), zconf_lineno()); + } +}; + +choice_stmt: choice_entry choice_block choice_end +; + +choice_option_list: + /* empty */ + | choice_option_list choice_option + | choice_option_list depends + | choice_option_list help + | choice_option_list T_EOL + | choice_option_list option_error +; + +choice_option: T_PROMPT prompt if_expr T_EOL +{ + menu_add_prompt(P_PROMPT, $2, $3); + printd(DEBUG_PARSE, "%s:%d:prompt\n", zconf_curname(), zconf_lineno()); +}; + +choice_option: T_TYPE prompt_stmt_opt T_EOL +{ + if ($1->stype == S_BOOLEAN || $1->stype == S_TRISTATE) { + menu_set_type($1->stype); + printd(DEBUG_PARSE, "%s:%d:type(%u)\n", + zconf_curname(), zconf_lineno(), + $1->stype); + } else + YYERROR; +}; + +choice_option: T_OPTIONAL T_EOL +{ + current_entry->sym->flags |= SYMBOL_OPTIONAL; + printd(DEBUG_PARSE, "%s:%d:optional\n", zconf_curname(), zconf_lineno()); +}; + +choice_option: T_DEFAULT T_WORD if_expr T_EOL +{ + if ($1->stype == S_UNKNOWN) { + menu_add_symbol(P_DEFAULT, sym_lookup($2, 0), $3); + printd(DEBUG_PARSE, "%s:%d:default\n", + zconf_curname(), zconf_lineno()); + } else + YYERROR; +}; + +choice_block: + /* empty */ + | choice_block common_stmt +; + +/* if entry */ + +if_entry: T_IF expr nl +{ + printd(DEBUG_PARSE, "%s:%d:if\n", zconf_curname(), zconf_lineno()); + menu_add_entry(NULL); + menu_add_dep($2); + $$ = menu_add_menu(); +}; + +if_end: end +{ + if (zconf_endtoken($1, T_IF, T_ENDIF)) { + menu_end_menu(); + printd(DEBUG_PARSE, "%s:%d:endif\n", zconf_curname(), zconf_lineno()); + } +}; + +if_stmt: if_entry if_block if_end +; + +if_block: + /* empty */ + | if_block common_stmt + | if_block menu_stmt + | if_block choice_stmt +; + +/* mainmenu entry */ + +mainmenu_stmt: T_MAINMENU prompt nl +{ + menu_add_prompt(P_MENU, $2, NULL); +}; + +/* menu entry */ + +menu: T_MENU prompt T_EOL +{ + menu_add_entry(NULL); + menu_add_prompt(P_MENU, $2, NULL); + printd(DEBUG_PARSE, "%s:%d:menu\n", zconf_curname(), zconf_lineno()); +}; + +menu_entry: menu visibility_list depends_list +{ + $$ = menu_add_menu(); +}; + +menu_end: end +{ + if (zconf_endtoken($1, T_MENU, T_ENDMENU)) { + menu_end_menu(); + printd(DEBUG_PARSE, "%s:%d:endmenu\n", zconf_curname(), zconf_lineno()); + } +}; + +menu_stmt: menu_entry menu_block menu_end +; + +menu_block: + /* empty */ + | menu_block common_stmt + | menu_block menu_stmt + | menu_block choice_stmt +; + +source_stmt: T_SOURCE prompt T_EOL +{ + printd(DEBUG_PARSE, "%s:%d:source %s\n", zconf_curname(), zconf_lineno(), $2); + zconf_nextfiles($2); +}; + +/* comment entry */ + +comment: T_COMMENT prompt T_EOL +{ + menu_add_entry(NULL); + menu_add_prompt(P_COMMENT, $2, NULL); + printd(DEBUG_PARSE, "%s:%d:comment\n", zconf_curname(), zconf_lineno()); +}; + +comment_stmt: comment depends_list +{ + menu_end_entry(); +}; + +/* help option */ + +help_start: T_HELP T_EOL +{ + printd(DEBUG_PARSE, "%s:%d:help\n", zconf_curname(), zconf_lineno()); + zconf_starthelp(); +}; + +help: help_start T_HELPTEXT +{ + current_entry->help = $2; +}; + +/* depends option */ + +depends_list: + /* empty */ + | depends_list depends + | depends_list T_EOL + | depends_list option_error +; + +depends: T_DEPENDS T_ON expr T_EOL +{ + menu_add_dep($3); + printd(DEBUG_PARSE, "%s:%d:depends on\n", zconf_curname(), zconf_lineno()); +}; + +/* visibility option */ + +visibility_list: + /* empty */ + | visibility_list visible + | visibility_list T_EOL +; + +visible: T_VISIBLE if_expr +{ + menu_add_visibility($2); +}; + +/* prompt statement */ + +prompt_stmt_opt: + /* empty */ + | prompt if_expr +{ + menu_add_prompt(P_PROMPT, $1, $2); +}; + +prompt: T_WORD + | T_WORD_QUOTE +; + +end: T_ENDMENU T_EOL { $$ = $1; } + | T_ENDCHOICE T_EOL { $$ = $1; } + | T_ENDIF T_EOL { $$ = $1; } +; + +nl: + T_EOL + | nl T_EOL +; + +if_expr: /* empty */ { $$ = NULL; } + | T_IF expr { $$ = $2; } +; + +expr: symbol { $$ = expr_alloc_symbol($1); } + | symbol T_LESS symbol { $$ = expr_alloc_comp(E_LTH, $1, $3); } + | symbol T_LESS_EQUAL symbol { $$ = expr_alloc_comp(E_LEQ, $1, $3); } + | symbol T_GREATER symbol { $$ = expr_alloc_comp(E_GTH, $1, $3); } + | symbol T_GREATER_EQUAL symbol { $$ = expr_alloc_comp(E_GEQ, $1, $3); } + | symbol T_EQUAL symbol { $$ = expr_alloc_comp(E_EQUAL, $1, $3); } + | symbol T_UNEQUAL symbol { $$ = expr_alloc_comp(E_UNEQUAL, $1, $3); } + | T_OPEN_PAREN expr T_CLOSE_PAREN { $$ = $2; } + | T_NOT expr { $$ = expr_alloc_one(E_NOT, $2); } + | expr T_OR expr { $$ = expr_alloc_two(E_OR, $1, $3); } + | expr T_AND expr { $$ = expr_alloc_two(E_AND, $1, $3); } +; + +symbol: T_WORD { $$ = sym_lookup($1, 0); free($1); } + | T_WORD_QUOTE { $$ = sym_lookup($1, SYMBOL_CONST); free($1); } +; + +word_opt: /* empty */ { $$ = NULL; } + | T_WORD + +%% + +void conf_parse(const char *name) +{ + struct symbol *sym; + int i; + + zconf_initscan(name); + + sym_init(); + _menu_init(); + rootmenu.prompt = menu_add_prompt(P_MENU, "Linux Kernel Configuration", NULL); + + if (getenv("ZCONF_DEBUG")) + zconfdebug = 1; + zconfparse(); + if (zconfnerrs) + exit(1); + if (!modules_sym) + modules_sym = sym_find( "n" ); + + rootmenu.prompt->text = _(rootmenu.prompt->text); + rootmenu.prompt->text = sym_expand_string_value(rootmenu.prompt->text); + + menu_finalize(&rootmenu); + for_all_symbols(i, sym) { + if (sym_check_deps(sym)) + zconfnerrs++; + } + if (zconfnerrs) + exit(1); + sym_set_change_count(1); +} + +static const char *zconf_tokenname(int token) +{ + switch (token) { + case T_MENU: return "menu"; + case T_ENDMENU: return "endmenu"; + case T_CHOICE: return "choice"; + case T_ENDCHOICE: return "endchoice"; + case T_IF: return "if"; + case T_ENDIF: return "endif"; + case T_DEPENDS: return "depends"; + case T_VISIBLE: return "visible"; + } + return ""; +} + +static bool zconf_endtoken(const struct kconf_id *id, int starttoken, int endtoken) +{ + if (id->token != endtoken) { + zconf_error("unexpected '%s' within %s block", + kconf_id_strings + id->name, zconf_tokenname(starttoken)); + zconfnerrs++; + return false; + } +#if 0 +//Wildcard breaks this somehow, so disabled for now. -JD + if (current_menu->file != current_file) { + zconf_error("'%s' in different file than '%s'", + kconf_id_strings + id->name, zconf_tokenname(starttoken)); + fprintf(stderr, "%s:%d: location of the '%s'\n", + current_menu->file->name, current_menu->lineno, + zconf_tokenname(starttoken)); + zconfnerrs++; + return false; + } +#endif + return true; +} + +static void zconfprint(const char *err, ...) +{ + va_list ap; + + fprintf(stderr, "%s:%d: ", zconf_curname(), zconf_lineno()); + va_start(ap, err); + vfprintf(stderr, err, ap); + va_end(ap); + fprintf(stderr, "\n"); +} + +static void zconf_error(const char *err, ...) +{ + va_list ap; + + zconfnerrs++; + fprintf(stderr, "%s:%d: ", zconf_curname(), zconf_lineno()); + va_start(ap, err); + vfprintf(stderr, err, ap); + va_end(ap); + fprintf(stderr, "\n"); +} + +static void zconferror(const char *err) +{ + fprintf(stderr, "%s:%d: %s\n", zconf_curname(), zconf_lineno() + 1, err); +} + +static void print_quoted_string(FILE *out, const char *str) +{ + const char *p; + int len; + + putc('"', out); + while ((p = strchr(str, '"'))) { + len = p - str; + if (len) + fprintf(out, "%.*s", len, str); + fputs("\\\"", out); + str = p + 1; + } + fputs(str, out); + putc('"', out); +} + +static void print_symbol(FILE *out, struct menu *menu) +{ + struct symbol *sym = menu->sym; + struct property *prop; + + if (sym_is_choice(sym)) + fprintf(out, "\nchoice\n"); + else + fprintf(out, "\nconfig %s\n", sym->name); + switch (sym->type) { + case S_BOOLEAN: + fputs(" boolean\n", out); + break; + case S_TRISTATE: + fputs(" tristate\n", out); + break; + case S_STRING: + fputs(" string\n", out); + break; + case S_INT: + fputs(" integer\n", out); + break; + case S_HEX: + fputs(" hex\n", out); + break; + default: + fputs(" ???\n", out); + break; + } + for (prop = sym->prop; prop; prop = prop->next) { + if (prop->menu != menu) + continue; + switch (prop->type) { + case P_PROMPT: + fputs(" prompt ", out); + print_quoted_string(out, prop->text); + if (!expr_is_yes(prop->visible.expr)) { + fputs(" if ", out); + expr_fprint(prop->visible.expr, out); + } + fputc('\n', out); + break; + case P_DEFAULT: + fputs( " default ", out); + expr_fprint(prop->expr, out); + if (!expr_is_yes(prop->visible.expr)) { + fputs(" if ", out); + expr_fprint(prop->visible.expr, out); + } + fputc('\n', out); + break; + case P_CHOICE: + fputs(" #choice value\n", out); + break; + case P_SELECT: + fputs( " select ", out); + expr_fprint(prop->expr, out); + fputc('\n', out); + break; + case P_RANGE: + fputs( " range ", out); + expr_fprint(prop->expr, out); + fputc('\n', out); + break; + case P_MENU: + fputs( " menu ", out); + print_quoted_string(out, prop->text); + fputc('\n', out); + break; + default: + fprintf(out, " unknown prop %d!\n", prop->type); + break; + } + } + if (menu->help) { + int len = strlen(menu->help); + while (menu->help[--len] == '\n') + menu->help[len] = 0; + fprintf(out, " help\n%s\n", menu->help); + } +} + +void zconfdump(FILE *out) +{ + struct property *prop; + struct symbol *sym; + struct menu *menu; + + menu = rootmenu.list; + while (menu) { + if ((sym = menu->sym)) + print_symbol(out, menu); + else if ((prop = menu->prompt)) { + switch (prop->type) { + case P_COMMENT: + fputs("\ncomment ", out); + print_quoted_string(out, prop->text); + fputs("\n", out); + break; + case P_MENU: + fputs("\nmenu ", out); + print_quoted_string(out, prop->text); + fputs("\n", out); + break; + default: + ; + } + if (!expr_is_yes(prop->visible.expr)) { + fputs(" depends ", out); + expr_fprint(prop->visible.expr, out); + fputc('\n', out); + } + } + + if (menu->list) + menu = menu->list; + else if (menu->next) + menu = menu->next; + else while ((menu = menu->parent)) { + if (menu->prompt && menu->prompt->type == P_MENU) + fputs("\nendmenu\n", out); + if (menu->next) { + menu = menu->next; + break; + } + } + } +} + +#include "zconf.lex.c" +#include "util.c" +#include "confdata.c" +#include "expr.c" +#include "symbol.c" +#include "menu.c" diff --git a/tools/tests/gen_esp32part_tests.py b/tools/tests/gen_esp32part_tests.py new file mode 100755 index 0000000000..413f1aac91 --- /dev/null +++ b/tools/tests/gen_esp32part_tests.py @@ -0,0 +1,313 @@ +#!/usr/bin/env python +import unittest +import struct +import csv +import sys +import subprocess +import tempfile +import os +sys.path.append("..") +from gen_esp32part import * + +SIMPLE_CSV = """ +# Name,Type,SubType,Offset,Size +factory,0,2,65536,1048576 +""" + +LONGER_BINARY_TABLE = "" +# type 0x00, subtype 0x00, +# offset 64KB, size 1MB +LONGER_BINARY_TABLE += "\xAA\x50\x00\x00" + \ + "\x00\x00\x01\x00" + \ + "\x00\x00\x10\x00" + \ + "factory\0" + ("\0"*8) + \ + "\x00\x00\x00\x00" +# type 0x01, subtype 0x20, +# offset 0x110000, size 128KB +LONGER_BINARY_TABLE += "\xAA\x50\x01\x20" + \ + "\x00\x00\x11\x00" + \ + "\x00\x02\x00\x00" + \ + "data" + ("\0"*12) + \ + "\x00\x00\x00\x00" +# type 0x10, subtype 0x00, +# offset 0x150000, size 1MB +LONGER_BINARY_TABLE += "\xAA\x50\x10\x00" + \ + "\x00\x00\x15\x00" + \ + "\x00\x10\x00\x00" + \ + "second" + ("\0"*10) + \ + "\x00\x00\x00\x00" + + +class CSVParserTests(unittest.TestCase): + + def test_simple_partition(self): + table = PartitionTable.from_csv(SIMPLE_CSV) + self.assertEqual(len(table), 1) + self.assertEqual(table[0].name, "factory") + self.assertEqual(table[0].type, 0) + self.assertEqual(table[0].subtype, 2) + self.assertEqual(table[0].offset, 65536) + self.assertEqual(table[0].size, 1048576) + + + def test_require_type(self): + csv = """ +# Name,Type, SubType,Offset,Size +ihavenotype, +""" + with self.assertRaisesRegexp(InputError, "type"): + PartitionTable.from_csv(csv) + + + def test_type_subtype_names(self): + csv_magicnumbers = """ +# Name, Type, SubType, Offset, Size +myapp, 0, 0,, 0x100000 +myota_0, 0, 0x10,, 0x100000 +myota_1, 0, 0x11,, 0x100000 +myota_15, 0, 0x1f,, 0x100000 +mytest, 0, 0x20,, 0x100000 +myota_status, 1, 0,, 0x100000 + """ + csv_nomagicnumbers = """ +# Name, Type, SubType, Offset, Size +myapp, app, factory,, 0x100000 +myota_0, app, ota_0,, 0x100000 +myota_1, app, ota_1,, 0x100000 +myota_15, app, ota_15,, 0x100000 +mytest, app, test,, 0x100000 +myota_status, data, ota,, 0x100000 +""" + # make two equivalent partition tables, one using + # magic numbers and one using shortcuts. Ensure they match + magic = PartitionTable.from_csv(csv_magicnumbers) + magic.verify() + nomagic = PartitionTable.from_csv(csv_nomagicnumbers) + nomagic.verify() + + self.assertEqual(nomagic["myapp"].type, 0) + self.assertEqual(nomagic["myapp"].subtype, 0) + self.assertEqual(nomagic["myapp"], magic["myapp"]) + self.assertEqual(nomagic["myota_0"].type, 0) + self.assertEqual(nomagic["myota_0"].subtype, 0x10) + self.assertEqual(nomagic["myota_0"], magic["myota_0"]) + self.assertEqual(nomagic["myota_15"], magic["myota_15"]) + self.assertEqual(nomagic["mytest"], magic["mytest"]) + self.assertEqual(nomagic["myota_status"], magic["myota_status"]) + + #self.assertEqual(nomagic.to_binary(), magic.to_binary()) + + def test_unit_suffixes(self): + csv = """ +# Name, Type, Subtype, Offset, Size +one_megabyte, app, factory, 32k, 1M +""" + t = PartitionTable.from_csv(csv) + t.verify() + self.assertEqual(t[0].offset, 32*1024) + self.assertEqual(t[0].size, 1*1024*1024) + + def test_default_offsets(self): + csv = """ +# Name, Type, Subtype, Offset, Size +first, app, factory,, 1M +second, data, 0x15,, 1M +minidata, data, 0x40,, 32K +otherapp, app, factory,, 1M + """ + t = PartitionTable.from_csv(csv) + # 'first' + self.assertEqual(t[0].offset, 0x010000) # 64KB boundary as it's an app image + self.assertEqual(t[0].size, 0x100000) # Size specified in CSV + # 'second' + self.assertEqual(t[1].offset, 0x110000) # prev offset+size + self.assertEqual(t[1].size, 0x100000) # Size specified in CSV + # 'minidata' + self.assertEqual(t[2].offset, 0x210000) + # 'otherapp' + self.assertEqual(t[3].offset, 0x220000) # 64KB boundary as it's an app image + + def test_negative_size_to_offset(self): + csv = """ +# Name, Type, Subtype, Offset, Size +first, app, factory, 0x10000, -2M +second, data, 0x15, , 1M + """ + t = PartitionTable.from_csv(csv) + t.verify() + # 'first' + self.assertEqual(t[0].offset, 0x10000) # in CSV + self.assertEqual(t[0].size, 0x200000 - t[0].offset) # Up to 2M + # 'second' + self.assertEqual(t[1].offset, 0x200000) # prev offset+size + + def test_overlapping_offsets_fail(self): + csv = """ +first, app, factory, 0x100000, 2M +second, app, ota_0, 0x200000, 1M +""" + t = PartitionTable.from_csv(csv) + with self.assertRaisesRegexp(InputError, "overlap"): + t.verify() + +class BinaryOutputTests(unittest.TestCase): + def test_binary_entry(self): + csv = """ +first, 0x30, 0xEE, 0x100400, 0x300000 +""" + t = PartitionTable.from_csv(csv) + tb = t.to_binary() + self.assertEqual(len(tb), 32) + self.assertEqual('\xAA\x50', tb[0:2]) # magic + self.assertEqual('\x30\xee', tb[2:4]) # type, subtype + eo, es = struct.unpack(" /etc/profile.d/esp32_toolchain.sh << EOF +export PATH="$PATH:/opt/xtensa-esp32-elf/bin" +EOF + +# clean up pacman packages to save some disk space +pacman --noconfirm -R unzip +pacman --noconfirm -Scc + +echo "************************************************" +echo "MSYS2 environment is now ready to use ESP32 SDK." +echo "Run 'source /etc/profile' to add the toolchain to" +echo "your path. Execute 'msys_shell.cmd' to launch an" +echo "MSYS terminal." +echo +echo "Once ESP32 SDK is downloaded/checked out, set the" +echo "environment variable SDK_PATH in /etc/profile to" +echo "point to the directory." +echo "************************************************" +echo +

      @!+M=L70H{0wwIxA(a{GdyzU5%<3#yRN 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᤟&Om-k!K=y*{XPg7#fyT$&K@60m3qh-= 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 z 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�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%0AkfU1A`z$926T2kYXG*1_!FzL17OY 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�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ξ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�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 #$b9R_XB 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�uJp$sz~p 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 NTqpz%qVnmI_~E0EY* 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�Cv>gTz5y0?^bRhz)97fz@a* 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 gF)S4Ru|C1 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

  • l)IoF)X&%t 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